Skip to main content

Documentation Index

Fetch the complete documentation index at: https://anypay-docs-sdk-0-15-0-updates.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Fund with Trails

Traditional funding flows require users to find an external bridge, swap to the required deposit token, pay multiple gas fees across networks, and navigate complex UIs. Trails handles all of that in a single transaction. Users can deposit from any token they hold on any supported chain — or use a fiat onramp, exchange transfer, or QR code — all in one embedded experience.

Use cases

Funding flows are exact-input by default. The user selects how much to send; the destination receives the resulting amount after routing.
  • Transfer funds into a perpetual exchange
  • Bootstrap liquidity in a lending protocol vault
  • Onboard users to a new chain
  • Top up a prediction market or gaming app account
  • Deposit into staking contracts

Examples

Deposit USDC to Polygon

import { Fund } from '0xtrails/widget'

export const BaseDeposit = () => {
  return (
    <Fund
      apiKey="YOUR_API_KEY"
      to={{
        recipient: "0x...",
        currency: "USDC",
        chain: "polygon",
      }}
      onFundingSuccess={({ sessionId }) => {
        console.log('Deposit completed:', sessionId)
      }}
    />
  )
}

Depositing into a lending protocol

For protocols like Aave that are natively supported, use the lend composable action. This handles approval, the supply call, and dynamic amount resolution without encoding any calldata by hand:
import { useTrailsSendTransaction, lend, erc20Utils } from '0xtrails'

export function AaveLendButton({ recipient }: { recipient: `0x${string}` }) {
  const { sendTransaction, isPending } = useTrailsSendTransaction({
    actions: [
      lend({
        marketId: 'base-usdc-aave-v3-lending',
        amount: '100',
      }),
    ],
  })

  return (
    <button
      disabled={isPending}
      onClick={() =>
        sendTransaction({
          to: recipient,
          tokenAddress: erc20Utils.USDC.addressOn('base'),
          tokenAmount: '100', // human-readable USDC amount
        })
      }
    >
      {isPending ? 'Sending...' : 'Supply 100 USDC to Aave'}
    </button>
  )
}
Use useEarnMarkets to discover available market IDs. See Markets and Providers.

Depositing into a vault

For ERC-4626 and vault-style protocols (Morpho, Yearn, SummerFi), use the deposit composable action:
import { useTrailsSendTransaction, deposit, erc20Utils } from '0xtrails'

export function YearnDepositButton({ recipient }: { recipient: `0x${string}` }) {
  const { sendTransaction, isPending } = useTrailsSendTransaction({
    actions: [
      deposit({
        marketId: 'katana-usdc-yearn-v3-vault',
        amount: '100',
      }),
    ],
  })

  return (
    <button
      disabled={isPending}
      onClick={() =>
        sendTransaction({
          to: recipient,
          tokenAddress: erc20Utils.USDC.addressOn('katana'),
          tokenAmount: '100',
        })
      }
    >
      {isPending ? 'Sending...' : 'Deposit 100 USDC to Yearn'}
    </button>
  )
}

Depositing into a custom contract

For protocols not covered by composable actions, use TRAILS_ROUTER_PLACEHOLDER_AMOUNT in to.calldata:
import { Fund } from '0xtrails/widget'
import { TRAILS_ROUTER_PLACEHOLDER_AMOUNT } from '0xtrails'
import { encodeFunctionData } from 'viem'
import { customVaultABI } from './abi.ts'

export const CustomVaultDeposit = () => {
  const VAULT_CONTRACT = "0x..."

  const depositCalldata = encodeFunctionData({
    abi: customVaultABI,
    functionName: 'deposit',
    args: [
      TRAILS_ROUTER_PLACEHOLDER_AMOUNT, // replaced with actual output at execution
      "0x...",                          // receiver address
    ],
  })

  return (
    <Fund
      apiKey="YOUR_API_KEY"
      to={{
        recipient: VAULT_CONTRACT,
        currency: "USDC",
        chain: "katana",
        calldata: depositCalldata,
      }}
      onFundingSuccess={({ sessionId }) => {
        console.log('Vault deposit completed:', sessionId)
      }}
    />
  )
}

Trustless deposit address via API (quote → commit → execute)

Create a deposit address flow server-side using the Trails API directly:
const quoteResponse = await fetch('https://trails-api.sequence.app/rpc/Trails/QuoteIntent', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Access-Key': 'YOUR_ACCESS_KEY',
  },
  body: JSON.stringify({
    ownerAddress: userWallet,
    originChainId: 137,
    originTokenAddress: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
    destinationChainId: 8453,
    destinationTokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
    destinationToAddress: appCreditAddress,
    destinationTokenAmount: '50000000', // 50 USDC (6 decimals)
    tradeType: 'EXACT_OUTPUT',
  }),
})

const { intent } = await quoteResponse.json()
const intentAddress = intent.depositTransaction.toAddress

const commitResponse = await fetch('https://trails-api.sequence.app/rpc/Trails/CommitIntent', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Access-Key': 'YOUR_ACCESS_KEY',
  },
  body: JSON.stringify({ intent }),
})

const { intentId } = await commitResponse.json()

// Ask the user to deposit to the intent address, then execute
const executeResponse = await fetch('https://trails-api.sequence.app/rpc/Trails/ExecuteIntent', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Access-Key': 'YOUR_ACCESS_KEY',
  },
  body: JSON.stringify({
    intentId,
    depositTransactionHash: userDepositTxHash,
  }),
})
Quotes expire after 10 minutes.

Next steps