Skip to main content

Overview

Fund mode implements input-driven deposit flows where users select the amount they want to send. The widget automatically routes funds from any supported chain/token to the destination. Trade Type: EXACT_INPUT - User specifies input amount, variable output amount after fees.

Configuration

Required Props

PropTypeDescription
mode"fund"Sets the widget to fund mode

Optional Props

PropTypeDescription
toAmountstringPre-set deposit amount (user can still modify)
toAddressstringDestination address or contract
toChainIdnumberDestination chain ID
toTokenstringDestination token symbol or address
toCalldatastringCalldata to execute on destination
slippageTolerancestring | numberSlippage tolerance (default: 0.5%)
quoteProviderQuoteProviderSpecific quote provider

Implementation

Basic Chain Funding

Simple deposit to a chain:
import { TrailsWidget } from '0xtrails/widget'

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="fund"
  toAddress="0x97c4A952b46bEcaD0663f76357d3776ba11566E1"
  toChainId={8453} // Base
  toToken="USDC"
  onCheckoutComplete={({ sessionId }) => {
    console.log('Deposit completed:', sessionId)
  }}
>
  <button>Deposit to Base</button>
</TrailsWidget>

Fixed Amount Deposit

Pre-populate a specific amount:
<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="fund"
  toAddress="0x..."
  toAmount="100" // Pre-filled, user can change
  toChainId={8453}
  toToken="USDC"
>
  <button>Deposit 100 USDC</button>
</TrailsWidget>

Protocol Deposit with Static Calldata

Deposit into a DeFi protocol with predefined parameters:
import { TrailsWidget } from '0xtrails/widget'
import { encodeFunctionData } from 'viem'

const aaveDepositCalldata = encodeFunctionData({
  abi: [{
    name: 'depositETH',
    type: 'function',
    stateMutability: 'payable',
    inputs: [
      { name: 'pool', type: 'address' },
      { name: 'onBehalfOf', type: 'address' },
      { name: 'referralCode', type: 'uint16' },
    ],
    outputs: [],
  }],
  functionName: 'depositETH',
  args: [
    '0xA238Dd80C259a72e81d7e4664a9801593F98d1c5', // Aave pool
    '0x97c4A952b46bEcaD0663f76357d3776ba11566E1', // User address
    0, // No referral code
  ],
})

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="fund"
  toAddress="0xa0d9C1E9E48Ca30c8d8C3B5D69FF5dc1f6DFfC24" // Aave Pool on Base
  toAmount="100"
  toChainId={8453}
  toToken="USDC"
  toCalldata={aaveDepositCalldata}
/>

Dynamic Amount Protocol Deposit

Use placeholder amount for user-selected deposit amounts in calldata:
import { TrailsWidget, TRAILS_CONTRACT_PLACEHOLDER_AMOUNT } from '0xtrails'
import { encodeFunctionData } from 'viem'

// Encode vault deposit with placeholder that gets replaced at execution
const vaultDepositCalldata = encodeFunctionData({
  abi: [{
    name: 'deposit',
    type: 'function',
    stateMutability: 'nonpayable',
    inputs: [
      { name: 'amount', type: 'uint256' },
      { name: 'receiver', type: 'address' },
    ],
    outputs: [{ name: 'shares', type: 'uint256' }],
  }],
  functionName: 'deposit',
  args: [
    TRAILS_CONTRACT_PLACEHOLDER_AMOUNT, // Replaced with actual bridged amount
    '0x97c4A952b46bEcaD0663f76357d3776ba11566E1', // Receiver
  ],
})

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="fund"
  toAddress="0x80c34BD3A3569E126e7055831036aa7b212cB159" // Yearn Vault
  toChainId={747474} // Katana
  toToken="USDC"
  toCalldata={vaultDepositCalldata}
>
  <button>Deposit to Yearn Vault</button>
</TrailsWidget>

Dynamic Calldata Pattern

When the deposit amount is part of the calldata and user-selected, use TRAILS_CONTRACT_PLACEHOLDER_AMOUNT: Why it’s needed: In fund mode, the final output amount after swaps/bridging isn’t known until execution. The placeholder gets replaced with the actual output amount. When to use:
  • ERC-4626 vault deposits with dynamic amounts
  • Staking contracts that require amount parameter
  • Any function where amount is a parameter and user-selectable
When not needed:
  • Simple transfers to addresses
  • Static calldata where amount isn’t a parameter
  • Functions that read balance directly (e.g., depositAll())

Event Handlers

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="fund"
  toAddress="0x..."
  toChainId={8453}
  toToken="USDC"
  onCheckoutStart={({ sessionId }) => {
    console.log('Deposit started:', sessionId)
  }}
  onCheckoutComplete={({ sessionId }) => {
    console.log('Deposit completed:', sessionId)
    // Update TVL, refresh balances, etc.
  }}
  onCheckoutError={({ sessionId, error }) => {
    console.error('Deposit failed:', error)
    // Handle error appropriately
  }}
/>

Use Cases

  • Chain Onboarding: Help users get started on new chains
  • Protocol Deposits: Deposit into lending protocols (Aave, Compound, Morpho)
  • Vault Deposits: Fund yield aggregators and vaults
  • Perp Exchange Funding: Deposit into perpetual exchanges
  • Liquidity Provision: Add liquidity to AMMs and pools
  • Staking: Fund staking contracts

See Also