> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sorokit.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# useContractSend

> Build, simulate, sign, and send a state-changing contract method call

Builds, simulates, signs, and sends a state-changing contract method call, exposing the full lifecycle as a `status` field rather than a single boolean. Requires a connected wallet.

```ts theme={null}
import { useContractSend } from "@sorokit/contract";

function useContractSend<TResult = unknown>(
  options: UseContractSendOptions,
): UseContractSendResult<TResult>;
```

## Parameters

| Name         | Type             | Required | Description                                               |
| ------------ | ---------------- | -------- | --------------------------------------------------------- |
| `contractId` | `string`         | Yes      | The deployed contract's address (`C...`).                 |
| `method`     | `string`         | Yes      | The state-changing method to call.                        |
| `network`    | `SorokitNetwork` | No       | Overrides the network from the nearest `SorokitProvider`. |

## Return value

| Field       | Type                                                                                             | Description                                                                |
| ----------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
| `status`    | `"idle" \| "queued" \| "simulating" \| "needsSignature" \| "submitting" \| "success" \| "error"` | The current phase.                                                         |
| `data`      | `TResult \| undefined`                                                                           | The decoded result, once `status` is `"success"`.                          |
| `error`     | `SorokitError \| undefined`                                                                      | A normalized error, once `status` is `"error"`.                            |
| `hash`      | `string \| undefined`                                                                            | The transaction hash, from the moment the network accepts it.              |
| `sendAsync` | `(args?: Record<string, unknown>) => Promise<TResult>`                                           | Validates args, simulates, signs, and sends.                               |
| `reset`     | `() => void`                                                                                     | Resets `status`, `data`, `error`, and `hash` back to their initial values. |

## Example

```tsx theme={null}
import { useContractSend } from "@sorokit/contract";

function TransferButton({ contractId, to }: { contractId: string; to: string }) {
  const { status, sendAsync, error } = useContractSend<boolean>({
    contractId,
    method: "transfer",
  });

  return (
    <div>
      <button
        disabled={status === "simulating" || status === "submitting"}
        onClick={() => sendAsync({ to, amount: 100n })}
      >
        {status === "idle" || status === "success" ? "Transfer" : status}
      </button>
      {error && <p>{error.message}</p>}
    </div>
  );
}
```

## Concurrent sends

Two sends from the same wallet fired at once (a double-clicked button, two components each triggering one) are automatically queued so they don't claim the same account sequence number and fail. A send waiting its turn reports `status: "queued"`. If one call's args or authorization depend on what a previous call wrote, `await` the first `sendAsync` before starting the second.

## Surviving a page reload

If the page reloads while a send is `"submitting"`, [`SorokitProvider`](/wallets/setup) picks it back up on mount and polls for its outcome. Nothing needs to be wired up for this.

## Caching and invalidation

On success, every [`useContractCall`](/hooks/use-contract-call) query for the same `contractId` is invalidated automatically, so reads reflect the new state without a manual refetch.
