Skip to main content
The unified deposit API simplifies deposits by automatically detecting the optimal authorization method. Use prepareDepositAuthorization() to determine the method, then prepareDeposit() to execute.
Breaking change in v0.5.0: All transaction functions identify vaults by vaultName: string instead of yieldType. Use getVaultsByConfig() or findVaultByConfig() to discover vault names first. See the migration guide.

Import

import {
  prepareDepositAuthorization,
  prepareDeposit,
  getVaultsByConfig,
  isPermitAuth,
  isApprovalAuth,
  isAlreadyApprovedAuth,
  YieldType,
} from '@paxoslabs/amplify-sdk'

prepareDepositAuthorization()

Determines the optimal authorization method for a deposit operation.

Function Signature

async function prepareDepositAuthorization(
  params: PrepareDepositAuthorizationParams
): Promise<DepositAuthorizationResult>

Parameters

interface PrepareDepositAuthorizationParams {
  /** Human-readable vault name (from AmplifyVault.name) */
  vaultName: string

  /** Token contract address to deposit */
  depositAsset: Address

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

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

  /** Blockchain network ID */
  chainId: number

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

  /** Force specific authorization method (bypasses automatic detection) */
  forceMethod?: 'permit' | 'approval'
}
ParameterTypeRequiredDescription
vaultNamestringYesVault name from AmplifyVault.name (e.g. from getVaultsByConfig())
depositAssetAddressYesToken contract address to deposit
depositAmountstringYesAmount as decimal string (e.g., “100.25”)
toAddressYesRecipient address for vault shares
chainIdnumberYesBlockchain network ID
deadlinebigintNoPermit deadline (defaults to 1 hour)
forceMethod"permit" | "approval"NoOverride automatic detection

Return Type (Discriminated Union)

type DepositAuthorizationResult =
  | PermitAuthorizationResult
  | ApprovalAuthorizationResult
  | AlreadyApprovedAuthorizationResult;

Decision Logic

The function follows this priority order:
  1. Check forceMethod — If specified, use that method directly
  2. Detect smart wallet — If the address has deployed bytecode (Safe, EIP-4337, EIP-7702), route to APPROVAL so callers can batch approve + deposit atomically
  3. Check permit support — If the token supports EIP-2612, return permit signature data
  4. Check existing allowance — If sufficient, return ALREADY_APPROVED
  5. Default to approval — Return approval transaction data

Token Permit Support

The following table shows which supported tokens use the gas-efficient EIP-2612 permit path versus the standard ERC-20 approval path. The SDK detects this automatically — use forceMethod: "approval" to override when needed (e.g., smart contract wallets).
TokenAuthorization MethodNotes
USDCPermit (EIP-2612)Single-transaction gasless signature
USDGPermit (EIP-2612)Single-transaction gasless signature
pyUSDPermit (EIP-2612)Single-transaction gasless signature
USD₮0Permit (EIP-2612)Single-transaction gasless signature
USDTApproval (ERC-20)Requires separate approval transaction. Also requires resetting allowance to 0 before setting a new value when a non-zero allowance already exists.

prepareDeposit()

Prepares transaction data for a deposit, automatically using the correct method based on provided parameters.

Function Signature

async function prepareDeposit(
  params: PrepareDepositParams
): Promise<PrepareDepositResult>

Parameters

interface PrepareDepositParams {
  /** Human-readable vault name (from AmplifyVault.name) */
  vaultName: string

  /** Token contract address to deposit */
  depositAsset: Address

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

  /** Recipient address for vault shares */
  to: Address

  /** Blockchain network ID */
  chainId: number

  /** Permit signature (required for permit flow) */
  signature?: Hex

  /** Permit deadline (required for permit flow) */
  deadline?: bigint

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

  /** Optional distributor code for fee attribution */
  distributorCode?: string

  /** Force deposit method (bypasses automatic routing) */
  forceMethod?: 'permit' | 'approval'
}

Return Type

Returns a discriminated union based on which deposit method is used:
/** Standard deposit (after approval or when already approved) */
interface StandardDepositResult {
  method: 'approval'
  txData: DepositTxData // flat: { abi, address, functionName, args, chainId }
}

/** Permit deposit (with signature) */
interface PermitDepositResult {
  method: 'permit'
  txData: UnencodedDepositWithPermitData // nested: { address, chainId, data: { abi, functionName, args } }
}

type PrepareDepositResult = StandardDepositResult | PermitDepositResult
The two result variants have different txData shapes. Standard deposits use a flat structure (txData.abi), while permit deposits use a nested structure (txData.data.abi). Use result.method to determine which shape you’re working with.

Complete Flow Example

import { mainnet } from 'viem/chains'
import {
  getVaultsByConfig,
  prepareDepositAuthorization,
  prepareDeposit,
  isPermitAuth,
  isApprovalAuth,
  isAlreadyApprovedAuth,
  YieldType,
} from '@paxoslabs/amplify-sdk'

const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' as `0x${string}`

// Step 0: Discover the vault to get its name
const [vault] = await getVaultsByConfig({
  yieldType: YieldType.CORE,
  chainId: mainnet.id,
  depositAssetAddress: USDC,
})

const params = {
  vaultName: vault.name,
  depositAsset: USDC,
  depositAmount: '1000',
  to: userAddress,
  chainId: mainnet.id,
}

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

// Step 2: Handle based on method using type guards
if (isPermitAuth(auth)) {
  // Sign permit off-chain
  const signature = await walletClient.signTypedData({
    account: userAddress,
    ...auth.permitData,
  })

  // Prepare and execute deposit with permit
  const prepared = await prepareDeposit({
    ...params,
    signature,
    deadline: auth.permitData.message.deadline,
  })

  // Permit path: txData has nested .data structure
  await walletClient.writeContract({
    address: prepared.txData.address,
    abi: prepared.txData.data.abi,
    functionName: prepared.txData.data.functionName,
    args: prepared.txData.data.args,
    account: userAddress,
  })
} else if (isApprovalAuth(auth)) {
  // Execute approval first
  const approvalHash = await walletClient.writeContract(auth.txData)
  await publicClient.waitForTransactionReceipt({ hash: approvalHash })

  // Then deposit (standard path: txData is flat)
  const prepared = await prepareDeposit(params)
  await walletClient.writeContract(prepared.txData)
} else if (isAlreadyApprovedAuth(auth)) {
  // Deposit directly (standard path: txData is flat)
  const prepared = await prepareDeposit(params)
  await walletClient.writeContract(prepared.txData)
}

Force Specific Method

Override automatic detection when needed:
// Force permit even if automatic detection would choose approval
const authForcePermit = await prepareDepositAuthorization({
  ...params,
  forceMethod: 'permit',
})

// Force approval even for permit-supporting tokens (useful for smart wallets)
const authForceApproval = await prepareDepositAuthorization({
  ...params,
  forceMethod: 'approval',
})

Slippage Configuration

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

Error Handling

Error Message PatternDescriptionResolution
"SDK not initialized"SDK used before initCall initAmplifySDK() first
"Vault not found"No vault matches vaultNameVerify vault name via getVaultsByConfig()
"does not support EIP-2612 permit"Token doesn’t support permitsUse approval flow instead
"requires both signature and deadline"Missing permit paramsProvide signature and deadline for permit deposits