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

# Withdrawals

# Withdrawals

This guide covers withdrawing tokens from the privacy pool back to a public wallet using the Privacy Boost React SDK.

## Basic Withdrawal

```tsx theme={null}
import { useVault } from '@sunnyside-io/privacy-boost-react';

function UnshieldButton() {
  const { unshield } = useVault();

  const handleUnshield = async () => {
    const result = await unshield({
      tokenAddress: '0x...token-address',
      amount: '1.0',
    });

    console.log('Withdrawal request:', result.requestId);
  };

  return <button onClick={handleUnshield}>Withdraw</button>;
}
```

## Withdrawal Parameters

| Parameter          | Type               | Required | Description                                       |
| ------------------ | ------------------ | -------- | ------------------------------------------------- |
| `tokenAddress`     | `Hex`              | Yes      | Token contract address                            |
| `amount`           | `string \| bigint` | Yes      | Amount (human-readable string or wei)             |
| `recipientAddress` | `Hex`              | No       | Destination wallet (defaults to connected wallet) |
| `onProgress`       | `OnProgress`       | No       | Progress callback                                 |

## Progress Tracking

```tsx theme={null}
function WithdrawWithProgress() {
  const { unshield } = useVault();
  const [step, setStep] = useState<string | null>(null);

  const handleUnshield = async () => {
    await unshield({
      tokenAddress: '0x...token-address',
      amount: '1.0',
      onProgress: ({ message }) => setStep(message),
    });
    setStep(null);
  };

  return (
    <div>
      <button onClick={handleUnshield}>Withdraw</button>
      {step && <p>{step}</p>}
    </div>
  );
}
```

<Warning>
  Proof generation can take several seconds. Always show progress feedback to users during withdrawals.
</Warning>

## Complete Example

```tsx theme={null}
import { useState } from 'react';
import { useVault, useBalances, useAuth } from '@sunnyside-io/privacy-boost-react';

function UnshieldForm({ tokenAddress }: { tokenAddress: string }) {
  const { unshield } = useVault();
  const { refresh } = useBalances();
  const { address } = useAuth();
  const [amount, setAmount] = useState('');
  const [recipient, setRecipient] = useState('');
  const [loading, setLoading] = useState(false);
  const [step, setStep] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const handleUnshield = async () => {
    setLoading(true);
    setError(null);

    try {
      await unshield({
        tokenAddress,
        amount,
        recipientAddress: recipient || undefined,
        onProgress: ({ message }) => setStep(message),
      });
      setAmount('');
      await refresh();
    } catch (err: any) {
      if (err.code !== 'TRANSACTION_REJECTED') {
        setError(err.message);
      }
    } finally {
      setLoading(false);
      setStep(null);
    }
  };

  return (
    <div>
      <input
        type="text"
        value={amount}
        onChange={(e) => setAmount(e.target.value)}
        placeholder="Amount"
        disabled={loading}
      />
      <input
        type="text"
        value={recipient}
        onChange={(e) => setRecipient(e.target.value)}
        placeholder={`Recipient (default: ${address})`}
        disabled={loading}
      />
      {error && <p style={{ color: 'red' }}>{error}</p>}
      {step && <p>{step}</p>}
      <button onClick={handleUnshield} disabled={loading || !amount}>
        {loading ? 'Withdrawing...' : 'Withdraw'}
      </button>
    </div>
  );
}
```

## Error Handling

```tsx theme={null}
try {
  await unshield({ tokenAddress, amount });
} catch (error: any) {
  switch (error.code) {
    case 'TRANSACTION_REJECTED':
      return;
    case 'INSUFFICIENT_BALANCE':
      setError('Not enough shielded balance');
      break;
    case 'PROOF_GENERATION_FAILED':
      setError('Failed to generate proof. Please try again.');
      break;
    default:
      setError(error.message);
  }
}
```

## Best Practices

### 1. Show Proof Generation Time

Always show a progress indicator during proof generation.

### 2. Refresh Balances After Withdrawal

```tsx theme={null}
await unshield({ tokenAddress, amount });
await refresh();
```

## Next Steps

* [Deposits Guide](./deposits)
* [Transfers Guide](./transfers)
* [Error Handling](./error-handling)
