Skip to main content

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.

This guide demonstrates complete deposit flows using the unified deposit API, which automatically detects the optimal authorization method (permit vs approval).
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.
The unified deposit API handles three authorization paths automatically:
MethodDescription
PermitGas-efficient off-chain signature (EIP-2612). Single transaction — no separate approval needed.
ApprovalStandard ERC-20 approve transaction followed by the deposit transaction.
Already ApprovedDirect deposit when sufficient allowance already exists.

Prerequisites

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

Installation

pnpm add @paxoslabs/amplify-sdk @privy-io/react-auth viem @tanstack/react-query

Imports

// 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";

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

useDeposit Hook

// src/hooks/useDeposit.ts
import { ,  } from "react";
import {  } from "viem";
import {  } from "viem/chains";
import {
  ,
  ,
  ,
  ,
  ,
  ,
  ,
} from "@paxoslabs/amplify-sdk";

declare const : () => { : (: any) => <string> };
declare const : () => { : <{ : string; : () => <any> }> };

interface DepositParams {
  : string;
  : `0x${string}`;
  : string;
}

export function () {
  const {  } = ();
  const {  } = ();
  const [, ] = <string>("");
  const [, ] = (false);

  const  = (
    async ({ , ,  }: DepositParams) => {
      const  = [0];
      if (!) {
        throw new ("Connect a wallet first");
      }

      (true);
      const  = . as `0x${string}`;

      try {
        const  = {
          ,
          ,
          : ,
          ,
          : .id,
        };

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

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

          ("Submitting deposit...");
          const  = await ({
            ...,
            ,
            : .permitData.message.deadline,
          });

          await ({
            : .txData.chainId,
            : .txData.address,
            : ({
              : .txData.abi,
              : .txData.functionName,
              : .txData.args,
            }),
          });
        } else if (()) {
          ("Approving token spend...");
          await ({
            : .id,
            : .txData.address,
            : ({
              : .txData.abi,
              : .txData.functionName,
              : .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().

          ("Submitting deposit...");
          const  = await ();
          await ({
            : .txData.chainId,
            : .txData.address,
            : ({
              : .txData.abi,
              : .txData.functionName,
              : .txData.args,
            }),
          });
        } else if (()) {
          ("Submitting deposit...");
          const  = await ();
          await ({
            : .txData.chainId,
            : .txData.address,
            : ({
              : .txData.abi,
              : .txData.functionName,
              : .txData.args,
            }),
          });
        }

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

  return { , ,  };
}

Deposit Component

// 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>
  );
}

Customization

Custom Slippage

const  = await ({
  ...,
  : 100, // 1% instead of default 0.5%
})

Distributor Code

const  = await ({
  ...,
  : 'your_distributor_code',
})

Force Approval Flow

const  = await ({
  ...,
  : 'approval', // Skip permit detection
})

Troubleshooting

IssueSolution
”SDK not initialized”Call initAmplifySDK() before using hooks
”Connect a wallet first”Ensure user has connected wallet
Permit signature failsToken may not support EIP-2612, falls back to approval
Transaction revertsCheck token balance and allowance
For more details on the deposit API, see Deposit Workflow.