Skip to main content
Most ERC-20 tokens require an allowance before the Boring Vault contract can pull funds. prepareApproveDepositToken and prepareDepositTransactionData combine into the standard two-transaction flow.

Sequence Overview

const approval = await prepareApproveDepositToken({
  yieldType, // e.g. YieldType.CORE
  depositToken, // token users spend
  depositAmount, // optional decimal string, defaults to max approval
  chainId,
});

const deposit = await prepareDepositTxData({
  yieldType,
  recipientAddress, // receives vault shares
  depositToken,
  depositAmount, // decimal string
  chainId,
  slippage, // optional bps, defaults to 100
});
  • approval returns { abi, address, functionName: 'approve', args }. args[0] is the vault spender.
  • deposit returns { abi, address, functionName: 'deposit', args, chainId }.
  • Skip the approval if the allowance is already ≥ deposit.args[1].

React with Privy

import { encodeFunctionData, erc20Abi, createPublicClient, custom } from "viem";
import { mainnet } from "viem/chains";
import {
  prepareApproveDepositToken,
  prepareDepositTxData,
  YieldType,
} from "@paxoslabs/amplify-sdk";
import { usePrivy, useWallets } from "@privy-io/react-auth";

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 client = createPublicClient({
  chain: mainnet,
  transport: custom(await wallet.getEthereumProvider()),
});

const approval = await prepareApproveDepositToken({
  yieldType: YieldType.CORE,
  depositToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
  depositAmount: "1000",
  chainId: mainnet.id,
});

const allowance = await client.readContract({
  abi: erc20Abi,
  address: approval.address,
  functionName: "allowance",
  args: [owner, approval.args[0]],
});

if (allowance < approval.args[1]) {
  await sendTransaction({
    chainId: mainnet.id,
    to: approval.address,
    data: encodeFunctionData({
      abi: approval.abi,
      functionName: approval.functionName,
      args: approval.args,
    }),
  });
}

const deposit = await prepareDepositTxData({
  yieldType: YieldType.CORE,
  recipientAddress: owner,
  depositToken: approval.address,
  depositAmount: "1000",
  chainId: mainnet.id,
});

await sendTransaction({
  chainId: deposit.chainId,
  to: deposit.address,
  data: encodeFunctionData({
    abi: deposit.abi,
    functionName: deposit.functionName,
    args: deposit.args,
  }),
});

React with wagmi

import {
  prepareApproveDepositToken,
  prepareDepositTxData,
  YieldType,
} from "@paxoslabs/amplify-sdk";
import { useAccount, useWriteContract } from "wagmi";

const { address, chainId } = useAccount();
const { writeContractAsync } = useWriteContract();
if (!address || !chainId) {
  throw new Error("Connect a wallet before preparing transactions.");
}

const approval = await prepareApproveDepositToken({
  yieldType: YieldType.CORE,
  depositToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
  depositAmount: "1000",
  chainId,
});

await writeContractAsync({ ...approval, account: address });

const { chainId: _ignored, ...deposit } = await prepareDepositTxData({
  yieldType: YieldType.CORE,
  recipientAddress: address,
  depositToken: approval.address,
  depositAmount: "1000",
  chainId,
});

await writeContractAsync({ ...deposit, account: address });

React with viem

import { createWalletClient, custom } from "viem";
import { mainnet } from "viem/chains";
import {
  prepareApproveDepositToken,
  prepareDepositTxData,
  YieldType,
} from "@paxoslabs/amplify-sdk";

// ethereum is window.ethereum from an injected wallet.
const [account] = (await ethereum.request({
  method: "eth_requestAccounts",
})) as `0x${string}`[];

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

const approval = await prepareApproveDepositToken({
  yieldType: YieldType.CORE,
  depositToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
  depositAmount: "1000",
  chainId: mainnet.id,
});

await client.writeContract({ ...approval, account });

const { chainId: _ignored, ...deposit } = await prepareDepositTxData({
  yieldType: YieldType.CORE,
  recipientAddress: account,
  depositToken: approval.address,
  depositAmount: "1000",
  chainId: mainnet.id,
});

await client.writeContract({ ...deposit, account });
Prefer a permit flow to skip approvals? Jump to Deposit with Permit.***