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

> Complete deposit integration examples for Privy, Wagmi, and Viem

This guide demonstrates complete deposit flows using the unified deposit API, which automatically detects the optimal authorization method (permit vs approval).

<Warning>
  **Breaking change in v0.5.0**: Transaction functions now use `vaultName`
  instead of `yieldType`. Discover account names with `getVaultsByConfig()` before
  making deposit calls. See the [migration
  guide](/v0.5.2/intro/products/earn/developers/changelog#migration-guide).
</Warning>

The unified deposit API handles three authorization paths automatically:

| Method               | Description                                                                                     |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| **Permit**           | Gas-efficient off-chain signature (EIP-2612). Single transaction — no separate approval needed. |
| **Approval**         | Standard ERC-20 `approve` transaction followed by the deposit transaction.                      |
| **Already Approved** | Direct deposit when sufficient allowance already exists.                                        |

## Prerequisites

* Node.js 22+
* Amplify API key from Paxos Labs
* SDK initialized with `initAmplifySDK()`

## Installation

<Tabs>
  <Tab title="Privy" icon="wallet">
    ```bash theme={null}
    pnpm add @paxoslabs/amplify-sdk @privy-io/react-auth viem @tanstack/react-query
    ```
  </Tab>

  <Tab title="Wagmi" icon="react">
    ```bash theme={null}
    pnpm add @paxoslabs/amplify-sdk wagmi viem @tanstack/react-query
    ```
  </Tab>

  <Tab title="Viem" icon="code">
    ```bash theme={null}
    pnpm add @paxoslabs/amplify-sdk viem
    ```
  </Tab>
</Tabs>

## Imports

<Tabs>
  <Tab title="Privy" icon="wallet">
    ```ts theme={null}
    // SDK imports
    import {
      getVaultsByConfig,
      prepareDepositAuthorization,
      prepareDeposit,
      isPermitAuth,
      isApprovalAuth,
      isAlreadyApprovedAuth,
      toEthSignTypedDataV4,
      YieldType,
    } from "@paxoslabs/amplify-sdk";

    // Privy imports
    import { usePrivy, useWallets } from "@privy-io/react-auth";

    // Viem imports
    import { encodeFunctionData } from "viem";
    import { mainnet } from "viem/chains";
    ```
  </Tab>

  <Tab title="Wagmi" icon="react">
    ```ts theme={null}
    // SDK imports
    import {
      getVaultsByConfig,
      prepareDepositAuthorization,
      prepareDeposit,
      isPermitAuth,
      isApprovalAuth,
      isAlreadyApprovedAuth,
      YieldType,
    } from "@paxoslabs/amplify-sdk";

    // Wagmi imports
    import { useAccount, useWriteContract, useSignTypedData } from "wagmi";
    ```
  </Tab>

  <Tab title="Viem" icon="code">
    ```ts theme={null}
    // SDK imports
    import {
      initAmplifySDK,
      getVaultsByConfig,
      prepareDepositAuthorization,
      prepareDeposit,
      isPermitAuth,
      isApprovalAuth,
      isAlreadyApprovedAuth,
      YieldType,
    } from "@paxoslabs/amplify-sdk";

    // Viem imports
    import { createWalletClient, createPublicClient, custom, http } from "viem";
    import { mainnet } from "viem/chains";
    ```
  </Tab>
</Tabs>

## Step 0: Fetch Available Accounts

Retrieve all accounts accessible with your API key. This is the data you need to build an account selector for your users.

```ts theme={null}
import { getVaultsByConfig, YieldType } from '@paxoslabs/amplify-sdk'

const vaults = await getVaultsByConfig()

for (const vault of vaults) {
  console.log(`${vault.name} — ${vault.yieldType} on chain ${vault.chainId}`)
  for (const asset of vault.supportedAssets) {
    console.log(`  ${asset.symbol}: deposit=${asset.depositable}, withdraw=${asset.withdrawable}`)
  }
}
```

You can also narrow the list with filters:

```ts theme={null}
const coreVaults = await getVaultsByConfig({ yieldType: YieldType.CORE })
const ethVaults = await getVaultsByConfig({ chainId: 1 })
const usdcVaults = await getVaultsByConfig({ depositAssetAddress: USDC_ADDRESS })
```

## Step 1: Select an Account

Once the user picks an account from your UI, record its `vault.name` — all subsequent transaction calls require it.

```ts theme={null}
const selectedVault = vaults[0] // or from user selection

const vaultName = selectedVault.name
const depositAsset = selectedVault.vault.baseTokenAddress
const chainId = selectedVault.chainId
```

## Step 2: Check Authorization

Determine the optimal authorization method for this deposit. The SDK auto-detects permit support.

```ts theme={null}
import {
  prepareDepositAuthorization,
  isPermitAuth,
  isApprovalAuth,
  isAlreadyApprovedAuth,
} from '@paxoslabs/amplify-sdk'

const auth = await prepareDepositAuthorization({
  vaultName,
  depositAsset,
  depositAmount: '1000',
  to: userAddress,
  chainId,
})

if (isPermitAuth(auth)) {
  // Sign EIP-712 typed data off-chain (gasless)
} else if (isApprovalAuth(auth)) {
  // Send an ERC-20 approve transaction first
} else if (isAlreadyApprovedAuth(auth)) {
  // Sufficient allowance exists — skip straight to deposit
}
```

## Step 3: Execute Deposit

After authorization, prepare and submit the deposit transaction.

```ts theme={null}
import { prepareDeposit } from '@paxoslabs/amplify-sdk'

const prepared = await prepareDeposit({
  vaultName,
  depositAsset,
  depositAmount: '1000',
  to: userAddress,
  chainId,
  // For permit path, also pass: signature, deadline
})

// Submit prepared.txData via your wallet provider
```

## Complete Examples

<Tabs>
  <Tab title="Privy" icon="wallet">
    ### useDeposit Hook

    ```tsx twoslash expandable {51,54,71-75,87,105,115,117} theme={null}
    // src/hooks/useDeposit.ts
    import { useState, useCallback } from "react";
    import { encodeFunctionData } from "viem";
    import { mainnet } from "viem/chains";
    import {
      prepareDepositAuthorization,
      prepareDeposit,
      isPermitAuth,
      isApprovalAuth,
      isAlreadyApprovedAuth,
      toEthSignTypedDataV4,
      YieldType,
    } from "@paxoslabs/amplify-sdk";

    // @noErrors
    declare const usePrivy: () => { sendTransaction: (tx: any) => Promise<string> };
    declare const useWallets: () => { wallets: Array<{ address: string; getEthereumProvider: () => Promise<any> }> };

    interface DepositParams {
      amount: string;
      depositAsset: `0x${string}`;
      vaultName: string;
    }

    export function useDeposit() {
      const { sendTransaction } = usePrivy();
      const { wallets } = useWallets();
      const [status, setStatus] = useState<string>("");
      const [isLoading, setIsLoading] = useState(false);

      const deposit = useCallback(
        async ({ amount, depositAsset, vaultName }: DepositParams) => {
          const wallet = wallets[0];
          if (!wallet) {
            throw new Error("Connect a wallet first");
          }

          setIsLoading(true);
          const to = wallet.address as `0x${string}`;

          try {
            const params = {
              vaultName,
              depositAsset,
              depositAmount: amount,
              to,
              chainId: mainnet.id,
            };

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

            // Step 2: Handle based on method using type guards
            if (isPermitAuth(auth)) {
              setStatus("Please sign permit in your wallet...");
              const provider = await wallet.getEthereumProvider();
              const signature = (await provider.request({
                method: "eth_signTypedData_v4",
                params: [to, toEthSignTypedDataV4(auth.permitData)],
              })) as `0x${string}`;

              setStatus("Submitting deposit...");
              const prepared = await prepareDeposit({
                ...params,
                signature,
                deadline: auth.permitData.message.deadline,
              });

              await sendTransaction({
                chainId: prepared.txData.chainId,
                to: prepared.txData.address,
                data: encodeFunctionData({
                  abi: prepared.txData.abi,
                  functionName: prepared.txData.functionName,
                  args: prepared.txData.args,
                }),
              });
            } else if (isApprovalAuth(auth)) {
              setStatus("Approving token spend...");
              await sendTransaction({
                chainId: mainnet.id,
                to: auth.txData.address,
                data: encodeFunctionData({
                  abi: auth.txData.abi,
                  functionName: auth.txData.functionName,
                  args: auth.txData.args,
                }),
              });

              // Important: In production, wait for the approval transaction
              // to be confirmed before proceeding with the deposit.
              // See the Node.js example for the full pattern using
              // publicClient.waitForTransactionReceipt().

              setStatus("Submitting deposit...");
              const prepared = await prepareDeposit(params);
              await sendTransaction({
                chainId: prepared.txData.chainId,
                to: prepared.txData.address,
                data: encodeFunctionData({
                  abi: prepared.txData.abi,
                  functionName: prepared.txData.functionName,
                  args: prepared.txData.args,
                }),
              });
            } else if (isAlreadyApprovedAuth(auth)) {
              setStatus("Submitting deposit...");
              const prepared = await prepareDeposit(params);
              await sendTransaction({
                chainId: prepared.txData.chainId,
                to: prepared.txData.address,
                data: encodeFunctionData({
                  abi: prepared.txData.abi,
                  functionName: prepared.txData.functionName,
                  args: prepared.txData.args,
                }),
              });
            }

            setStatus("Deposit successful!");
          } catch (error) {
            setStatus(`Error: ${error instanceof Error ? error.message : "Unknown"}`);
            throw error;
          } finally {
            setIsLoading(false);
          }
        },
        [wallets, sendTransaction]
      );

      return { deposit, status, isLoading };
    }
    ```

    ### Deposit Component

    ```tsx {4,14} theme={null}
    // src/components/DepositForm.tsx
    import { useState } from "react";
    import { useQuery } from "@tanstack/react-query";
    import { getVaultsByConfig, YieldType } from "@paxoslabs/amplify-sdk";
    import { useDeposit } from "../hooks/useDeposit";
    import { mainnet } from "viem/chains";

    export function DepositForm() {
      const [amount, setAmount] = useState("100");
      const { deposit, status, isLoading } = useDeposit();

      const { data: vaults } = useQuery({
        queryKey: ["vaults", YieldType.CORE, mainnet.id],
        queryFn: () => getVaultsByConfig({ yieldType: YieldType.CORE, chainId: mainnet.id }),
      });

      const vault = vaults?.[0];

      const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        if (!vault) return;
        await deposit({
          amount,
          depositAsset: vault.vault.baseTokenAddress as `0x${string}`,
          vaultName: vault.name,
        });
      };

      return (
        <form onSubmit={handleSubmit}>
          <label>
            Amount (USDC):
            <input
              type="number"
              value={amount}
              onChange={(e) => setAmount(e.target.value)}
              disabled={isLoading}
              min="0"
              step="0.01"
            />
          </label>
          <button type="submit" disabled={isLoading}>
            {isLoading ? "Processing..." : "Deposit"}
          </button>
          {status && <p>{status}</p>}
        </form>
      );
    }
    ```
  </Tab>

  <Tab title="Wagmi" icon="react">
    ### useDeposit Hook

    ```tsx twoslash expandable {44,47,52,66,79,87,89} theme={null}
    // src/hooks/useDeposit.ts
    import { useState, useCallback } from "react";
    import { useAccount, useWriteContract, useSignTypedData } from "wagmi";
    import {
      prepareDepositAuthorization,
      prepareDeposit,
      isPermitAuth,
      isApprovalAuth,
      isAlreadyApprovedAuth,
    } from "@paxoslabs/amplify-sdk";

    interface DepositParams {
      amount: string;
      depositAsset: `0x${string}`;
      vaultName: string;
    }

    export function useDeposit() {
      const { address, chainId } = useAccount();
      const { writeContractAsync } = useWriteContract();
      const { signTypedDataAsync } = useSignTypedData();
      const [status, setStatus] = useState<string>("");
      const [isLoading, setIsLoading] = useState(false);

      const deposit = useCallback(
        async ({ amount, depositAsset, vaultName }: DepositParams) => {
          if (!address || !chainId) {
            throw new Error("Connect a wallet first");
          }

          setIsLoading(true);

          try {
            const params = {
              vaultName,
              depositAsset,
              depositAmount: amount,
              to: address,
              chainId,
            };

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

            // Step 2: Handle based on method using type guards
            if (isPermitAuth(auth)) {
              setStatus("Please sign permit in your wallet...");
              const signature = await signTypedDataAsync(auth.permitData);

              setStatus("Submitting deposit...");
              const prepared = await prepareDeposit({
                ...params,
                signature,
                deadline: auth.permitData.message.deadline,
              });

              await writeContractAsync({
                ...prepared.txData,
                account: address,
              });
            } else if (isApprovalAuth(auth)) {
              setStatus("Approving token spend...");
              await writeContractAsync({
                ...auth.txData,
                account: address,
              });

              // Important: In production, wait for the approval transaction
              // to be confirmed before proceeding with the deposit.
              // See the Node.js example for the full pattern using
              // publicClient.waitForTransactionReceipt().

              setStatus("Submitting deposit...");
              const prepared = await prepareDeposit(params);
              await writeContractAsync({
                address: prepared.txData.address,
                abi: prepared.txData.abi,
                functionName: prepared.txData.functionName,
                args: prepared.txData.args,
                account: address,
              });
            } else if (isAlreadyApprovedAuth(auth)) {
              setStatus("Submitting deposit...");
              const prepared = await prepareDeposit(params);
              await writeContractAsync({
                address: prepared.txData.address,
                abi: prepared.txData.abi,
                functionName: prepared.txData.functionName,
                args: prepared.txData.args,
                account: address,
              });
            }

            setStatus("Deposit successful!");
          } catch (error) {
            setStatus(`Error: ${error instanceof Error ? error.message : "Unknown"}`);
            throw error;
          } finally {
            setIsLoading(false);
          }
        },
        [address, chainId, writeContractAsync, signTypedDataAsync]
      );

      return { deposit, status, isLoading };
    }
    ```

    ### Deposit Component

    ```tsx {4,18} theme={null}
    // src/components/DepositForm.tsx
    import { useState } from "react";
    import { useAccount } from "wagmi";
    import { getVaultsByConfig, YieldType } from "@paxoslabs/amplify-sdk";
    import { useDeposit } from "../hooks/useDeposit";
    import { useQuery } from "@tanstack/react-query";

    const USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as const;

    export function DepositForm() {
      const { isConnected, chainId } = useAccount();
      const [amount, setAmount] = useState("100");
      const { deposit, status, isLoading } = useDeposit();

      const { data: vault } = useQuery({
        queryKey: ["vault", chainId],
        queryFn: async () => {
          const [v] = await getVaultsByConfig({
            yieldType: YieldType.CORE,
            chainId,
            depositAssetAddress: USDC_ADDRESS,
          });
          return v;
        },
        enabled: !!chainId,
      });

      if (!isConnected) {
        return <p>Please connect your wallet</p>;
      }

      const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        if (!vault) return;
        await deposit({
          amount,
          depositAsset: USDC_ADDRESS,
          vaultName: vault.name,
        });
      };

      return (
        <form onSubmit={handleSubmit}>
          <label>
            Amount (USDC):
            <input
              type="number"
              value={amount}
              onChange={(e) => setAmount(e.target.value)}
              disabled={isLoading}
              min="0"
              step="0.01"
            />
          </label>
          <button type="submit" disabled={isLoading}>
            {isLoading ? "Processing..." : "Deposit"}
          </button>
          {status && <p>{status}</p>}
        </form>
      );
    }
    ```
  </Tab>

  <Tab title="Viem" icon="code">
    ### Complete Script

    This example uses pure viem without React, suitable for Node.js scripts or vanilla TypeScript applications.

    ```ts twoslash expandable {29,54,70,73,85,103,117,130,135} theme={null}
    // deposit.ts
    import { createWalletClient, createPublicClient, custom, http } from "viem";
    import { mainnet } from "viem/chains";
    import {
      initAmplifySDK,
      getVaultsByConfig,
      prepareDepositAuthorization,
      prepareDeposit,
      isPermitAuth,
      isApprovalAuth,
      isAlreadyApprovedAuth,
      YieldType,
    } from "@paxoslabs/amplify-sdk";

    // @noErrors
    declare const window: { ethereum: any };
    declare const process: { env: { AMPLIFY_API_KEY: string } };

    // Configuration
    const CONFIG = {
      apiKey: process.env.AMPLIFY_API_KEY!,
      depositAsset: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as `0x${string}`, // USDC
      depositAmount: "1000",
    };

    async function main() {
      // Step 1: Initialize SDK
      console.log("Initializing SDK...");
      await initAmplifySDK(CONFIG.apiKey);

      // Step 2: Connect wallet
      console.log("Connecting wallet...");
      const ethereum = window.ethereum;
      if (!ethereum) {
        throw new Error("No wallet found");
      }

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

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

      const publicClient = createPublicClient({
        chain: mainnet,
        transport: http(),
      });

      // Step 3: Discover vault and prepare deposit parameters
      const [vault] = await getVaultsByConfig({
        yieldType: YieldType.CORE,
        chainId: mainnet.id,
        depositAssetAddress: CONFIG.depositAsset,
      });

      const params = {
        vaultName: vault.name,
        depositAsset: CONFIG.depositAsset,
        depositAmount: CONFIG.depositAmount,
        to: account,
        chainId: mainnet.id,
      };

      // Step 4: Get authorization method
      console.log("Checking authorization method...");
      const auth = await prepareDepositAuthorization(params);

      // Step 5: Handle based on method using type guards
      if (isPermitAuth(auth)) {
        console.log("Authorization method: permit");
        console.log("Signing permit...");
        const signature = await walletClient.signTypedData({
          account,
          domain: auth.permitData.domain,
          types: auth.permitData.types,
          primaryType: auth.permitData.primaryType,
          message: auth.permitData.message,
        });

        console.log("Submitting deposit with permit...");
        const prepared = await prepareDeposit({
          ...params,
          signature,
          deadline: auth.permitData.message.deadline,
        });

        const permitHash = await walletClient.writeContract({
          ...prepared.txData,
          account,
        });

        console.log(`Deposit submitted: ${permitHash}`);
        await publicClient.waitForTransactionReceipt({ hash: permitHash });
        console.log("Deposit confirmed!");
      } else if (isApprovalAuth(auth)) {
        console.log("Authorization method: approval");
        console.log("Sending approval transaction...");

        const approvalHash = await walletClient.writeContract({
          ...auth.txData,
          account,
        });

        console.log(`Approval submitted: ${approvalHash}`);
        await publicClient.waitForTransactionReceipt({ hash: approvalHash });
        console.log("Approval confirmed!");

        console.log("Submitting deposit...");
        const prepared = await prepareDeposit(params);

        const depositHash = await walletClient.writeContract({
          address: prepared.txData.address,
          abi: prepared.txData.abi,
          functionName: prepared.txData.functionName,
          args: prepared.txData.args,
          account,
        });

        console.log(`Deposit submitted: ${depositHash}`);
        await publicClient.waitForTransactionReceipt({ hash: depositHash });
        console.log("Deposit confirmed!");
      } else if (isAlreadyApprovedAuth(auth)) {
        console.log("Authorization method: already_approved");
        console.log(`Existing allowance: ${auth.allowance}`);
        console.log("Submitting deposit directly...");

        const prepared = await prepareDeposit(params);

        const directHash = await walletClient.writeContract({
          address: prepared.txData.address,
          abi: prepared.txData.abi,
          functionName: prepared.txData.functionName,
          args: prepared.txData.args,
          account,
        });

        console.log(`Deposit submitted: ${directHash}`);
        await publicClient.waitForTransactionReceipt({ hash: directHash });
        console.log("Deposit confirmed!");
      }
    }

    main().catch(console.error);
    ```

    ### Running the Script

    ```bash theme={null}
    # Set environment variable
    export AMPLIFY_API_KEY=pxl_your_api_key

    # Run with tsx or ts-node
    npx tsx deposit.ts
    ```

    ### Expected Output

    ```
    Initializing SDK...
    Connecting wallet...
    Checking authorization method...
    Authorization method: permit
    Signing permit...
    Submitting deposit with permit...
    Deposit submitted: 0x1234...
    Deposit confirmed!
    ```
  </Tab>
</Tabs>

## Customization

### Custom Slippage

```ts twoslash {3} theme={null}
// @noErrors
declare const params: any
declare function prepareDeposit(params: any): Promise<any>
// ---cut---
const prepared = await prepareDeposit({
  ...params,
  slippage: 100, // 1% instead of default 0.5%
})
```

### Distributor Code

```ts twoslash {3} theme={null}
// @noErrors
declare const params: any
declare function prepareDeposit(params: any): Promise<any>
// ---cut---
const prepared = await prepareDeposit({
  ...params,
  distributorCode: 'your_distributor_code',
})
```

### Force Approval Flow

```ts twoslash {3} theme={null}
// @noErrors
declare const params: any
declare function prepareDepositAuthorization(params: any): Promise<any>
// ---cut---
const auth = await prepareDepositAuthorization({
  ...params,
  forceMethod: 'approval', // Skip permit detection
})
```

## Troubleshooting

| Issue                    | Solution                                               |
| ------------------------ | ------------------------------------------------------ |
| "SDK not initialized"    | Call `initAmplifySDK()` before using hooks             |
| "Connect a wallet first" | Ensure user has connected wallet                       |
| Permit signature fails   | Token may not support EIP-2612, falls back to approval |
| Transaction reverts      | Check token balance and allowance                      |

For more details on the deposit API, see [Deposit Workflow](/v0.5.2/intro/products/earn/developers/api/deposit-workflow).
