The unified deposit API simplifies deposits by automatically detecting the optimal authorization method. Use prepareDepositAuthorization() to determine the method, then prepareDeposit() to execute.
Import
import {
prepareDepositAuthorization,
prepareDeposit,
isPermitAuth,
isApprovalAuth,
isAlreadyApprovedAuth,
} 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 {
/** Yield strategy type (e.g., YieldType.CORE) */
yieldType: YieldType;
/** 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: ChainId;
/** Optional deadline for permit signature (defaults to 1 hour from now) */
deadline?: bigint;
/** Force specific authorization method (bypasses automatic detection) */
forceMethod?: "permit" | "approval";
}
| Parameter | Type | Required | Description |
|---|
yieldType | YieldType | Yes | Yield strategy type (e.g., YieldType.CORE) |
depositAsset | Address | Yes | Token contract address to deposit |
depositAmount | string | Yes | Amount as decimal string (e.g., “100.25”) |
to | Address | Yes | Recipient address for vault shares |
chainId | number | Yes | Blockchain network ID |
deadline | bigint | No | Permit deadline (defaults to 1 hour) |
forceMethod | "permit" | "approval" | No | Override automatic detection |
Return Type (Discriminated Union)
Type Definition
Permit Result
Approval Result
Already Approved Result
type DepositAuthorizationResult =
| PermitAuthorizationResult
| ApprovalAuthorizationResult
| AlreadyApprovedAuthorizationResult;
/** Returned when token supports EIP-2612 permit */
interface PermitAuthorizationResult {
method: "permit";
/** EIP-712 typed data ready for wallet signing */
permitData: PermitSignatureData;
}
/** Returned when an ERC20 approval transaction is needed */
interface ApprovalAuthorizationResult {
method: "approval";
/** Transaction data for ERC20 approve() call */
txData: ApproveDepositTokenTxData;
}
/** Returned when existing allowance is sufficient */
interface AlreadyApprovedAuthorizationResult {
method: "already_approved";
/** Current allowance (human-readable) */
allowance: string;
/** Current allowance as BigInt string */
allowanceAsBigInt: string;
}
Decision Logic
The function follows this priority order:
- Check
forceMethod — If specified, use that method directly
- Detect smart wallet — If the address has deployed bytecode (Safe, EIP-4337, EIP-7702), route to
APPROVAL so callers can batch approve + deposit atomically
- Check permit support — If the token supports EIP-2612, return permit signature data
- Check existing allowance — If sufficient, return
ALREADY_APPROVED
- 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).
| Token | Authorization Method | Notes |
|---|
| USDC | Permit (EIP-2612) | Single-transaction gasless signature |
| USDG | Permit (EIP-2612) | Single-transaction gasless signature |
| pyUSD | Permit (EIP-2612) | Single-transaction gasless signature |
| USD₮0 | Permit (EIP-2612) | Single-transaction gasless signature |
| USDT | Approval (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 {
/** Yield strategy type (e.g., YieldType.CORE) */
yieldType: YieldType;
/** 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: ChainId;
/** 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 {
prepareDepositAuthorization,
prepareDeposit,
isPermitAuth,
isApprovalAuth,
isAlreadyApprovedAuth,
YieldType,
} from "@paxoslabs/amplify-sdk";
const params = {
yieldType: YieldType.CORE,
depositAsset: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as `0x${string}`, // 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 Pattern | Description | Resolution |
|---|
"SDK not initialized" | SDK used before init | Call initAmplifySDK() first |
"No vault found for token..." | No vault matches params | Verify yieldType, token, chainId |
"does not support EIP-2612 permit" | Token doesn’t support permits | Use approval flow instead |
"requires both signature and deadline" | Missing permit params | Provide signature and deadline for permit deposits |