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

# prepareWithdrawalAuthorization

> Determine if account share approval is needed for withdrawal and prepare the authorization

Determine whether account share approval is needed for a withdrawal operation and prepare the appropriate authorization.

This is the recommended entry point for the withdrawal flow. It automatically:

* Checks existing account share allowance
* Detects smart contract wallets (Safe, EIP-4337, EIP-7702)
* Returns the appropriate authorization result

## Import

```typescript theme={null}
import {
  prepareWithdrawalAuthorization,
  isWithdrawApprovalAuth,
  isWithdrawAlreadyApprovedAuth,
  WithdrawAuthMethod,
} from '@paxoslabs/amplify-sdk'
```

## Usage

```typescript theme={null}
// First discover the vault
const [vault] = await getVaultsByConfig({
  yieldType: 'CORE',
  chainId: 1,
})

const auth = await prepareWithdrawalAuthorization({
  vaultName: vault.name,
  wantAsset: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
  withdrawAmount: '1.0',
  userAddress: '0x1234...',
  chainId: 1,
})

if (isWithdrawApprovalAuth(auth)) {
  // Execute approval transaction
  await walletClient.writeContract(auth.txData)
} else {
  // Already approved, proceed to withdrawal
  console.log(`Allowance: ${auth.allowance}`)
}
```

***

## Parameters

| Parameter        | Type                              | Required | Description                                                             |
| ---------------- | --------------------------------- | -------- | ----------------------------------------------------------------------- |
| `vaultName`      | `string`                          | Yes      | Account name from `AmplifyVault.name` (e.g. from `getVaultsByConfig()`) |
| `wantAsset`      | `Address`                         | Yes      | Token address to receive upon withdrawal                                |
| `withdrawAmount` | `string`                          | Yes      | Account shares to withdraw (decimal string)                             |
| `userAddress`    | `Address`                         | Yes      | Owner of account shares                                                 |
| `chainId`        | `number`                          | Yes      | Blockchain network ID                                                   |
| `forceMethod`    | `"approval" \| "allowance_check"` | No       | Override auto routing behavior                                          |

***

## Return Type

Returns a discriminated union `WithdrawAuthorizationResult`:

### WithdrawAuthMethod.APPROVAL

Returned when approval is needed (insufficient allowance, smart wallet detected in auto mode, or `forceMethod: "approval"`).

```typescript theme={null}
interface WithdrawApprovalAuthorizationResult {
  method: 'approval'
  txData: ApproveWithdrawOrderTxData // Ready-to-use approval tx
}
```

### WithdrawAuthMethod.ALREADY\_APPROVED

Returned when existing allowance is sufficient.

```typescript theme={null}
interface WithdrawAlreadyApprovedAuthorizationResult {
  method: 'already_approved'
  allowance: string
  allowanceAsBigInt: string
}
```

***

## Type Guards

Use type guards for type-safe handling:

```typescript theme={null}
import {
  isWithdrawApprovalAuth,
  isWithdrawAlreadyApprovedAuth,
} from "@paxoslabs/amplify-sdk";

const auth = await prepareWithdrawalAuthorization({ ... });

if (isWithdrawApprovalAuth(auth)) {
  // TypeScript knows auth.txData exists
  await walletClient.writeContract(auth.txData);
}

if (isWithdrawAlreadyApprovedAuth(auth)) {
  // TypeScript knows auth.allowance exists
  console.log(auth.allowance);
}
```

Or use a switch statement:

```typescript theme={null}
switch (auth.method) {
  case WithdrawAuthMethod.APPROVAL:
    await walletClient.writeContract(auth.txData)
    break
  case WithdrawAuthMethod.ALREADY_APPROVED:
    console.log(`Approved: ${auth.allowance}`)
    break
}
```

***

## Smart Wallet Behavior

In auto mode, smart contract wallets (Safe, EIP-4337, EIP-7702) are routed to `APPROVAL` with approve tx data so they can batch approve + withdraw atomically.

```typescript theme={null}
// Smart wallet detected automatically
const [vault] = await getVaultsByConfig({ yieldType: 'CORE', chainId: 1 })

const auth = await prepareWithdrawalAuthorization({
  vaultName: vault.name,
  wantAsset: USDC_ADDRESS,
  withdrawAmount: '1.0',
  userAddress: safeAddress, // Smart contract wallet
  chainId: 1,
})

// Returns APPROVAL in auto mode for smart wallets
// auth.method === WithdrawAuthMethod.APPROVAL
```

The SDK detects smart wallets by checking for deployed bytecode at the address using `getCode`. This covers:

* **Safe (Gnosis Safe)** multi-sig wallets
* **EIP-4337** smart accounts (e.g., Biconomy, ZeroDev, Alchemy)
* **EIP-7702** delegated EOAs
* **Privy embedded wallets** (when using smart wallets)

***

## Force Method Overrides

Use `forceMethod` for deterministic behavior:

```typescript theme={null}
const [vault] = await getVaultsByConfig({ yieldType: 'CORE', chainId: 1 })

// Always return approval tx data (skip checks)
const forceApproval = await prepareWithdrawalAuthorization({
  vaultName: vault.name,
  wantAsset: USDC_ADDRESS,
  withdrawAmount: '1.0',
  userAddress,
  chainId: 1,
  forceMethod: 'approval',
})

// Always run allowance check (skip smart-wallet heuristic)
const forceAllowanceCheck = await prepareWithdrawalAuthorization({
  vaultName: vault.name,
  wantAsset: USDC_ADDRESS,
  withdrawAmount: '1.0',
  userAddress,
  chainId: 1,
  forceMethod: 'allowance_check',
})
```

***

## Examples

<Tabs>
  <Tab title="Complete Viem Flow">
    ```typescript theme={null}
    import {
      getVaultsByConfig,
      prepareWithdrawalAuthorization,
      isWithdrawApprovalAuth,
      prepareWithdrawal,
      YieldType,
    } from "@paxoslabs/amplify-sdk";

    async function withdraw(
      walletClient: WalletClient,
      publicClient: PublicClient,
      userAddress: `0x${string}`,
    ) {
      const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
      const withdrawAmount = "1.0";

      // Discover vault
      const [vault] = await getVaultsByConfig({
        yieldType: YieldType.CORE,
        chainId: 1,
      });

      // Step 1: Authorize
      const auth = await prepareWithdrawalAuthorization({
        vaultName: vault.name,
        wantAsset: USDC,
        withdrawAmount,
        userAddress,
        chainId: 1,
      });

      if (isWithdrawApprovalAuth(auth)) {
        const approveHash = await walletClient.writeContract(auth.txData);
        await publicClient.waitForTransactionReceipt({ hash: approveHash });
      }

      // Step 2: Submit withdrawal order
      const withdrawTx = await prepareWithdrawal({
        vaultName: vault.name,
        wantAsset: USDC,
        userAddress,
        chainId: 1,
        withdrawAmount,
      });

      const hash = await walletClient.writeContract(withdrawTx);
      return hash;
    }
    ```
  </Tab>

  <Tab title="Smart Wallet Batching">
    ```typescript theme={null}
    import {
      getVaultsByConfig,
      prepareWithdrawalAuthorization,
      isWithdrawApprovalAuth,
      prepareWithdrawal,
      YieldType,
    } from "@paxoslabs/amplify-sdk";
    import { encodeFunctionData } from "viem";

    async function batchedWithdraw(safeAddress: `0x${string}`) {
      const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
      const withdrawAmount = "1.0";

      const [vault] = await getVaultsByConfig({
        yieldType: YieldType.CORE,
        chainId: 1,
      });

      // Get authorization (default: APPROVAL for smart wallets)
      const auth = await prepareWithdrawalAuthorization({
        vaultName: vault.name,
        wantAsset: USDC,
        withdrawAmount,
        userAddress: safeAddress,
        chainId: 1,
      });

      const calls = [];

      // Add approval call
      if (isWithdrawApprovalAuth(auth)) {
        calls.push({
          to: auth.txData.address,
          data: encodeFunctionData({
            abi: auth.txData.abi,
            functionName: auth.txData.functionName,
            args: auth.txData.args,
          }),
          value: 0n,
        });
      }

      // Add withdrawal call
      const withdrawTx = await prepareWithdrawal({
        vaultName: vault.name,
        wantAsset: USDC,
        userAddress: safeAddress,
        chainId: 1,
        withdrawAmount,
      });

      calls.push({
        to: withdrawTx.address,
        data: encodeFunctionData({
          abi: withdrawTx.abi,
          functionName: withdrawTx.functionName,
          args: withdrawTx.args,
        }),
        value: 0n,
      });

      // Execute both atomically via smart wallet
      return calls;
    }
    ```
  </Tab>
</Tabs>

***

## Comparison with Deposit Authorization

`prepareWithdrawalAuthorization()` mirrors the deposit flow's `prepareDepositAuthorization()`:

| Feature                  | Deposit Auth                          | Withdrawal Auth                                |
| ------------------------ | ------------------------------------- | ---------------------------------------------- |
| Methods                  | PERMIT, APPROVAL, ALREADY\_APPROVED   | APPROVAL, ALREADY\_APPROVED                    |
| Permit Support           | Yes (EIP-2612)                        | No                                             |
| Smart Wallet Auto-Detect | Yes                                   | Yes                                            |
| Force Method             | `forceMethod: "permit" \| "approval"` | `forceMethod: "approval" \| "allowance_check"` |

Withdrawals don't support EIP-2612 permits since the approval is on account shares (BoringVault ERC20), not the deposit token.

***

## Error Handling

| Error                                 | Description               | Resolution                                    |
| ------------------------------------- | ------------------------- | --------------------------------------------- |
| `Vault not found`                     | Invalid account name      | Verify account name via `getVaultsByConfig()` |
| `Failed to check withdrawal approval` | On-chain multicall failed | Check RPC connectivity and retry              |

```typescript theme={null}
import {
  getVaultsByConfig,
  prepareWithdrawalAuthorization,
  APIError,
} from '@paxoslabs/amplify-sdk'

const [vault] = await getVaultsByConfig({ yieldType: 'CORE', chainId: 1 })

try {
  const auth = await prepareWithdrawalAuthorization({
    vaultName: vault.name,
    wantAsset: USDC_ADDRESS,
    withdrawAmount: '1.0',
    userAddress: '0x...',
    chainId: 1,
  })
} catch (error) {
  if (error instanceof APIError) {
    console.error('SDK Error:', error.message)
  }
}
```

***

## Related

* [getVaultsByConfig](/v0.5.2/intro/products/earn/developers/api/getVaultsByConfig) - Discover account names
* [prepareDepositAuthorization](/v0.5.2/intro/products/earn/developers/api/deposit-workflow) - Deposit authorization (equivalent for deposits)
* [prepareWithdrawal](/v0.5.2/intro/products/earn/developers/api/prepareWithdrawal) - Unified withdrawal wrapper
* [prepareWithdrawOrderTxData](/v0.5.2/intro/products/earn/developers/api/prepareWithdrawOrderTxData) - Low-level withdrawal tx builder
* [prepareApproveWithdrawOrderTxData](/v0.5.2/intro/products/earn/developers/api/prepareApproveWithdrawOrderTxData) - Manual account share approval
* [Withdrawals Guide](/v0.5.2/intro/products/earn/developers/guides/withdrawals) - Complete withdrawal integration guide
* [Smart Wallets Guide](/v0.5.2/intro/products/earn/developers/guides/smart-wallets) - Smart wallet integration patterns
