> ## 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.

# Token Transfer Form

> Build a complete, validated transfer UI using Sorokit hooks.

This guide demonstrates how to combine the validation power of `useSorobanForm` with the execution logic of `useContractSend`. We will build a form that captures a recipient address and an amount.

#### Implementation Pattern

The most efficient way to build this is to use two hooks side-by-side. Both hooks point to the same contract and method, which means they share a single network request for the contract specification.

* `useSorobanForm`: Handles input validation as the user types.
* `useContractSend`: Handles the blockchain transaction after the user clicks Submit.

#### The Complete Form

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

export function TransferForm({ contractId }) {
  const { register, handleSubmit, formState } = useSorobanForm({
    contractId,
    method: "transfer",
  });

  const { sendAsync, status } = useContractSend({
    contractId,
    method: "transfer",
  });

  const onSubmit = async (values) => {
    await sendAsync(values);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label>Recipient</label>
      <input {...register("to")} placeholder="G..." />
      {formState.errors.to && <span>{String(formState.errors.to.message)}</span>}

      <label>Amount (BigInt)</label>
      <input
        type="text"
        {...register("amount", {
          setValueAs: (v) => (v === "" ? undefined : BigInt(v)),
        })}
      />
      {formState.errors.amount && <span>{String(formState.errors.amount.message)}</span>}

      <button disabled={status === "SUBMITTING"}>{status === "IDLE" ? "Send" : status}</button>
    </form>
  );
}
```

#### Important Considerations

* BigInt Conversion: Smart contracts use high-precision numbers. By using `setValueAs`, you ensure the string from the HTML input is converted to a `bigint` before it reaches the Zod validator.
* Error Mapping: Notice how `formState.errors.to` works automatically. Sorokit has already derived the validation rules from the contract's WASM file.
* Loading States: Using the `status` string from `useContractSend` is better than a simple boolean because you can show the user exactly where they are in the process (e.g., "SIMULATING").
