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

# useTransfer

> Transfers tokens from the user wallet to another address. Uses Avnus gasless to cover gas fees.

## Usage

```typescript theme={null}
const {
  transfer,
  transferAsync,
  data,
  isLoading,
  isError,
  error,
  isSuccess,
  reset,
} = useTransfer();
```

### Parameters

* `transfer` / `transferAsync` both accept an object with:
  * `params` (`TransferHookInput`):
    * `encryptKey` (string): PIN used to decrypt the private key.
    * `wallet` (`WalletData`): the wallet object. **Pass the full object from `createWallet` / `useGetWallet`** — `publicKey`, `encryptedPrivateKey`, **`walletType`**, and **`signerKind`**. `walletType` is routing-critical: SHHH wallets execute through a different path, and omitting it defaults to `"READY"`, which **reverts** on a SHHH account. `signerKind` is SHHH-only (defaults to `"STARK"`).
    * `token` (`ChainToken`): Token identifier (e.g. `ChainToken.USDC`).
    * `usePasskey` (boolean, optional): When `true`, the hook authenticates with passkey internally (requires `externalUserId`). Do not use with external `setupPasskey`/`authenticate` calls.
    * `otherToken` (optional): Custom token configuration with:
      * `contractAddress` (string): ERC-20 token contract address.
      * `decimals` (number): Token decimals.
    * `recipient` (string): Destination wallet address.
    * `amount` (number): Transfer amount (will be converted to a string internally).
  * `bearerToken` (string): Bearer token for authentication (e.g. from your auth provider).

### Return Value

Returns an object containing:

* `transfer`: Function to trigger the transfer (fire-and-forget style).
* `transferAsync`: Promise-based function that resolves with the transaction hash.
* `data`: Transaction hash of the transfer (string | undefined).
* `isLoading`: Boolean indicating if the operation is in progress.
* `isError`: Boolean indicating if an error occurred.
* `error`: Error instance when `isError` is true, otherwise `null`.
* `isSuccess`: Boolean indicating if the transfer completed successfully.
* `reset`: Function to reset the mutation state.

## Example Implementation

```typescript theme={null}
import { useState } from "react";
import { useAuth } from "@clerk/nextjs";
import { useTransfer, ChainToken } from "@chipi-stack/chipi-react";

export function TransferForm() {
  const { getToken } = useAuth();
  const { transferAsync, data, isLoading, isError, error } = useTransfer();
  const [form, setForm] = useState({
    pin: '',
    recipient: '',
    amount: ''
  });

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const bearerToken = await getToken();

    if (!bearerToken) {
      console.error('No bearer token available');
      return;
    }

    try {
      await transferAsync({
        params: {
          amount: Number(form.amount),
          encryptKey: form.pin,
          // Use the wallet you got from createWallet / useGetWallet, with its
          // walletType + signerKind. These route the transfer correctly —
          // omitting walletType defaults to "READY" and a SHHH wallet reverts.
          wallet: {
            publicKey: wallet.publicKey,
            encryptedPrivateKey: wallet.encryptedPrivateKey,
            walletType: wallet.walletType,   // "SHHH" | "CHIPI" | "READY"
            signerKind: wallet.signerKind,   // SHHH only; defaults to "STARK"
          },
          token: ChainToken.USDC,
          recipient: form.recipient
        },
        bearerToken,
      });
    } catch (err) {
      console.error('Transfer failed:', err);
    }
  };

  return (
    <div className="bg-white rounded-xl shadow-lg p-6">
      <h2 className="text-2xl font-bold mb-4">Transfer Tokens</h2>
      
      <form onSubmit={handleSubmit} className="space-y-4">
        <div>
          <label className="block text-sm font-medium mb-1">Security PIN</label>
          <input
            type="password"
            value={form.pin}
            onChange={(e) => setForm({...form, pin: e.target.value})}
            className="w-full p-2 border rounded-md"
            required
          />
        </div>

        <div>
          <label className="block text-sm font-medium mb-1">Recipient Address</label>
          <input
            type="text"
            value={form.recipient}
            onChange={(e) => setForm({...form, recipient: e.target.value})}
            className="w-full p-2 border rounded-md"
            required
          />
        </div>

        <div>
          <label className="block text-sm font-medium mb-1">Amount</label>
          <input
            type="number"
            step="0.000001"
            value={form.amount}
            onChange={(e) => setForm({...form, amount: e.target.value})}
            className="w-full p-2 border rounded-md"
            required
          />
        </div>

        <button 
          type="submit" 
          disabled={isLoading}
          className="w-full bg-green-600 text-white py-2 px-4 rounded-md hover:bg-green-700 disabled:bg-gray-400"
        >
          {isLoading ? 'Processing...' : 'Transfer'}
        </button>
      </form>

      {data && (
        <div className="mt-4 p-3 bg-gray-50 rounded-md">
          <p className="text-sm font-mono break-all">
            TX Hash: {data}
          </p>
        </div>
      )}

      {isError && error && (
        <div className="mt-4 p-3 bg-red-50 text-red-700 rounded-md">
          Error: {error.message}
        </div>
      )}
    </div>
  );
}
```

## Security Considerations

* Always verify recipient addresses
* Use encrypted private keys
* Implement proper PIN validation
* Monitor transaction status

## Error Handling

* Handle insufficient token balance
* Validate wallet addresses
* Monitor gas fees
* Implement retry logic for failed transactions

<Danger>
  Always verify recipient addresses. Transfers on StarkNet are irreversible.
</Danger>

## Related Hooks

* **useApprove** - Required before transferring new token types
* **useCallAnyContract** - For custom contract interactions
