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

# Deposits

> Unified deposit API with automatic permit/approval detection

The Unified Deposit API simplifies deposits by automatically detecting the optimal authorization method. Use `prepareDepositAuthorization()` to determine the method, then `prepareDepositTxData()` or `prepareDepositWithPermitTxData()` to execute.

## DepositAuthMethod

```ts theme={null}
export const DepositAuthMethod = {
  PERMIT: "permit",           // EIP-2612 off-chain signature (gas efficient)
  APPROVAL: "approval",       // Traditional ERC20 approval (two transactions)
  ALREADY_APPROVED: "already_approved", // Existing allowance sufficient
} as const;

export type DepositAuthMethod =
  (typeof DepositAuthMethod)[keyof typeof DepositAuthMethod];
```

## prepareDepositAuthorization()

Determines the optimal authorization method for a deposit operation.

### Function Signature

```ts theme={null}
export async function prepareDepositAuthorization(
  params: PrepareDepositAuthorizationParams
): Promise<DepositAuthorizationResult>;
```

### Parameters

```ts theme={null}
export interface PrepareDepositAuthorizationParams {
  /** Yield strategy type (e.g., YieldType.CORE) */
  yieldType: YieldType;

  /** Token contract address to deposit */
  depositToken: Address;

  /** Amount of assets to deposit as decimal string (e.g., "100.25") */
  depositAmount: string;

  /** User's wallet address (permit owner / approval sender) */
  recipientAddress: Address;

  /** Blockchain network ID */
  chainId: ChainId;

  /** Optional deadline for permit signature (defaults to 1 hour from now) */
  deadline?: bigint;

  /** Force specific authorization method (bypasses automatic detection) */
  forceMethod?: "permit" | "approval";
}
```

### Return Type (Discriminated Union)

```ts theme={null}
export type DepositAuthorizationResult =
  | PermitAuthorizationResult
  | ApprovalAuthorizationResult
  | AlreadyApprovedAuthorizationResult;

/** Returned when token supports EIP-2612 permit */
export interface PermitAuthorizationResult {
  method: DepositAuthMethod.PERMIT;
  /** EIP-712 typed data ready for wallet signing */
  permitData: PermitSignatureData;
}

/** Returned when an ERC20 approval transaction is needed */
export interface ApprovalAuthorizationResult {
  method: DepositAuthMethod.APPROVAL;
  /** Transaction data for ERC20 approve() call */
  txData: ApproveDepositTokenTxData;
  /** Current allowance (human-readable) */
  currentAllowance: string;
  /** Current allowance as BigInt string */
  currentAllowanceAsBigInt: string;
}

/** Returned when existing allowance is sufficient */
export interface AlreadyApprovedAuthorizationResult {
  method: DepositAuthMethod.ALREADY_APPROVED;
  /** Current allowance (human-readable) */
  allowance: string;
  /** Current allowance as BigInt string */
  allowanceAsBigInt: string;
}
```

### Decision Logic

The function follows this priority order:

1. **Check `forceMethod`** - If specified, use that method
2. **Check permit support** - If token is in permit allowlist, return permit data
3. **Check existing allowance** - If sufficient, return `ALREADY_APPROVED`
4. **Default to approval** - Return approval transaction data

## prepareDepositTxData()

Prepares transaction data for a standard deposit (after approval).

### Function Signature

```ts theme={null}
export async function prepareDepositTxData(
  params: PrepareDepositParams
): Promise<DepositTxData>;
```

### Parameters

```ts theme={null}
export interface PrepareDepositParams {
  /** Yield strategy type (e.g., YieldType.PRIME) */
  yieldType: YieldType;

  /** Token contract address to deposit */
  depositToken: Address;

  /** Amount of assets to deposit as decimal string (e.g., "100.25") */
  depositAmount: string;

  /** Recipient address for vault shares */
  recipientAddress: Address;

  /** Blockchain network ID */
  chainId: ChainId;

  /** Optional slippage in basis points (default: 50 = 0.5%) */
  slippage?: number;

  /** Optional partner code for fee attribution */
  partnerCode?: string;
}
```

### Return Type

```ts theme={null}
export interface DepositTxData {
  abi: Abi;
  address: Address;
  functionName: string;
  args: unknown[];
  chainId: number;
}
```

## prepareDepositWithPermitTxData()

Prepares transaction data for a permit-based deposit (single transaction).

### Function Signature

```ts theme={null}
export async function prepareDepositWithPermitTxData(
  params: PrepareDepositWithPermitParams
): Promise<PermitDepositTxData>;
```

### Parameters

```ts theme={null}
export interface PrepareDepositWithPermitParams {
  /** Yield strategy type (e.g., YieldType.PRIME) */
  yieldType: YieldType;

  /** Token contract address to deposit */
  depositToken: Address;

  /** Amount of assets to deposit as decimal string (e.g., "100.25") */
  depositAmount: string;

  /** Recipient address for vault shares */
  recipientAddress: Address;

  /** Blockchain network ID */
  chainId: ChainId;

  /** Permit signature (hex string from wallet signing) */
  signature: Hex;

  /** Permit deadline (must match signature deadline) */
  deadline: bigint;

  /** Optional slippage in basis points (default: 50 = 0.5%) */
  slippage?: number;

  /** Optional partner code for fee attribution */
  partnerCode?: string;
}
```

### Return Type

```ts theme={null}
export interface PermitDepositTxData {
  address: Address;
  chainId: number;
  data: {
    abi: Abi;
    functionName: string;
    args: unknown[];
  };
}
```

## Complete Flow Examples

### React with Privy

```tsx theme={null}
import { encodeFunctionData } from "viem";
import { mainnet } from "viem/chains";
import {
  initAmplifySDK,
  prepareDepositAuthorization,
  prepareDepositTxData,
  prepareDepositWithPermitTxData,
  DepositAuthMethod,
  YieldType,
} from "@paxoslabs/amplify-sdk";
import { usePrivy, useWallets } from "@privy-io/react-auth";

// Initialize SDK (call once at app startup)
await initAmplifySDK("pxl_your_api_key");

const { sendTransaction } = usePrivy();
const { wallets } = useWallets();
const wallet = wallets[0];
if (!wallet) {
  throw new Error("Connect a wallet before preparing transactions.");
}

const owner = wallet.address as `0x${string}`;

const params = {
  yieldType: YieldType.PRIME,
  depositToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as `0x${string}`, // USDC
  depositAmount: "1000",
  recipientAddress: owner,
  chainId: mainnet.id,
};

// Step 1: Get authorization method
const auth = await prepareDepositAuthorization(params);

// Step 2: Handle based on method
switch (auth.method) {
  case DepositAuthMethod.PERMIT: {
    // Sign permit off-chain
    const provider = await wallet.getEthereumProvider();
    const signature = (await provider.request({
      method: "eth_signTypedData_v4",
      params: [
        owner,
        JSON.stringify({
          domain: auth.permitData.domain,
          types: auth.permitData.types,
          primaryType: auth.permitData.primaryType,
          message: auth.permitData.message,
        }),
      ],
    })) as `0x${string}`;

    // Deposit with permit (single transaction)
    const permitTx = await prepareDepositWithPermitTxData({
      ...params,
      signature,
      deadline: BigInt(auth.permitData.message.deadline),
    });

    const { abi: permitAbi, functionName: permitFn, args: permitArgs } = permitTx.data;
    await sendTransaction({
      chainId: permitTx.chainId,
      to: permitTx.address,
      data: encodeFunctionData({
        abi: permitAbi,
        functionName: permitFn,
        args: permitArgs,
      }),
    });
    break;
  }

  case DepositAuthMethod.APPROVAL: {
    // Send approval transaction first
    const { abi: approvalAbi, functionName: approvalFn, args: approvalArgs } = auth.txData;
    await sendTransaction({
      chainId: mainnet.id,
      to: auth.txData.address,
      data: encodeFunctionData({
        abi: approvalAbi,
        functionName: approvalFn,
        args: approvalArgs,
      }),
    });

    // Then deposit
    const depositTx = await prepareDepositTxData(params);
    const { abi: depositAbi, functionName: depositFn, args: depositArgs } = depositTx;
    await sendTransaction({
      chainId: depositTx.chainId,
      to: depositTx.address,
      data: encodeFunctionData({
        abi: depositAbi,
        functionName: depositFn,
        args: depositArgs,
      }),
    });
    break;
  }

  case DepositAuthMethod.ALREADY_APPROVED: {
    // Deposit directly
    const directTx = await prepareDepositTxData(params);
    const { abi, functionName, args } = directTx;
    await sendTransaction({
      chainId: directTx.chainId,
      to: directTx.address,
      data: encodeFunctionData({ abi, functionName, args }),
    });
    break;
  }
}
```

### React with wagmi

```tsx theme={null}
import {
  useAccount,
  useWriteContract,
  useSignTypedData,
} from "wagmi";
import { encodeFunctionData } from "viem";
import {
  initAmplifySDK,
  prepareDepositAuthorization,
  prepareDepositTxData,
  prepareDepositWithPermitTxData,
  DepositAuthMethod,
  YieldType,
} from "@paxoslabs/amplify-sdk";

// Initialize SDK
await initAmplifySDK("pxl_your_api_key");

const { address, chainId } = useAccount();
const { writeContractAsync } = useWriteContract();
const { signTypedDataAsync } = useSignTypedData();

if (!address || !chainId) {
  throw new Error("Connect a wallet before preparing transactions.");
}

const params = {
  yieldType: YieldType.PRIME,
  depositToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as `0x${string}`,
  depositAmount: "1000",
  recipientAddress: address,
  chainId,
};

const auth = await prepareDepositAuthorization(params);

switch (auth.method) {
  case DepositAuthMethod.PERMIT: {
    const signature = await signTypedDataAsync(auth.permitData);
    const permitTx = await prepareDepositWithPermitTxData({
      ...params,
      signature,
      deadline: BigInt(auth.permitData.message.deadline),
    });
    await writeContractAsync({
      address: permitTx.address,
      abi: permitTx.data.abi,
      functionName: permitTx.data.functionName,
      args: permitTx.data.args,
      account: address,
    });
    break;
  }

  case DepositAuthMethod.APPROVAL: {
    await writeContractAsync({ ...auth.txData, account: address });
    const depositTx = await prepareDepositTxData(params);
    await writeContractAsync({ ...depositTx, account: address });
    break;
  }

  case DepositAuthMethod.ALREADY_APPROVED: {
    const directTx = await prepareDepositTxData(params);
    await writeContractAsync({ ...directTx, account: address });
    break;
  }
}
```

### React with viem

```tsx theme={null}
import { createWalletClient, custom } from "viem";
import { mainnet } from "viem/chains";
import {
  initAmplifySDK,
  prepareDepositAuthorization,
  prepareDepositTxData,
  prepareDepositWithPermitTxData,
  DepositAuthMethod,
  YieldType,
} from "@paxoslabs/amplify-sdk";

// Initialize SDK
await initAmplifySDK("pxl_your_api_key");

const [account] = (await ethereum.request({
  method: "eth_requestAccounts",
})) as `0x${string}`[];

const client = createWalletClient({
  account,
  chain: mainnet,
  transport: custom(ethereum),
});

const params = {
  yieldType: YieldType.PRIME,
  depositToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as `0x${string}`,
  depositAmount: "1000",
  recipientAddress: account,
  chainId: mainnet.id,
};

const auth = await prepareDepositAuthorization(params);

switch (auth.method) {
  case DepositAuthMethod.PERMIT: {
    const signature = await client.signTypedData({
      account,
      ...auth.permitData,
    });
    const permitTx = await prepareDepositWithPermitTxData({
      ...params,
      signature,
      deadline: BigInt(auth.permitData.message.deadline),
    });
    await client.writeContract({
      address: permitTx.address,
      abi: permitTx.data.abi,
      functionName: permitTx.data.functionName,
      args: permitTx.data.args,
      account,
    });
    break;
  }

  case DepositAuthMethod.APPROVAL: {
    await client.writeContract({ ...auth.txData, account });
    const depositTx = await prepareDepositTxData(params);
    await client.writeContract({ ...depositTx, account });
    break;
  }

  case DepositAuthMethod.ALREADY_APPROVED: {
    const directTx = await prepareDepositTxData(params);
    await client.writeContract({ ...directTx, account });
    break;
  }
}
```

## Force Specific Method

Override automatic detection when needed:

```ts theme={null}
// Force permit even if automatic detection would choose approval
const authForcePermit = await prepareDepositAuthorization({
  ...params,
  forceMethod: "permit",
});
// Always returns DepositAuthMethod.PERMIT

// Force approval even for permit-supporting tokens
const authForceApproval = await prepareDepositAuthorization({
  ...params,
  forceMethod: "approval",
});
// Returns APPROVAL or ALREADY_APPROVED
```

## Slippage Configuration

The default slippage is 50 basis points (0.5%). Override when needed:

```ts theme={null}
const depositResult = await prepareDeposit({
  ...params,
  slippage: 100, // 1% slippage
});
```

## Error Handling

Both helpers throw `APIError` with actionable metadata:

```ts theme={null}
try {
  const auth = await prepareDepositAuthorization(params);
} catch (error) {
  if (error.code === "VAULT_NOT_FOUND") {
    console.error("No vault matches parameters");
  }
  if (error.code === "PERMIT_NOT_SUPPORTED") {
    // Fall back to approval flow
  }
}
```

| Error Code               | Description                    | Resolution                       |
| ------------------------ | ------------------------------ | -------------------------------- |
| `SDK_NOT_INITIALIZED`    | SDK used before init           | Call `initAmplifySDK()` first    |
| `VAULT_NOT_FOUND`        | No vault matches params        | Verify yieldType, token, chainId |
| `PERMIT_NOT_SUPPORTED`   | Token doesn't support EIP-2612 | Use approval flow instead        |
| `INSUFFICIENT_ALLOWANCE` | Approval amount too low        | Increase approval or use permit  |

For withdrawal operations, see [Withdraw](./withdraw).
