Skip to main content
Trails Fund mode consolidates every funding path into a single integration. Users can deposit from their existing crypto balance, from a wallet on another chain, or via fiat onramp — credit card, debit card, or bank account — without leaving your app. You add one widget; Trails handles routing, bridging, gas, and onramp compliance automatically.

What users can fund from

  • Crypto wallet: any token on any supported chain — Polygon, Ethereum, Base, Arbitrum, and more
  • Another app or exchange: funds held in Coinbase, Binance, or any other wallet the user connects
  • Credit or debit card: card payments convert to USDC and land in your destination address in one flow
  • Bank account: ACH and bank transfer onramp, built in
All three paths appear automatically in the widget. No separate onramp integration required.

Drop-in widget

The fastest integration. Wrap any button or UI element with TrailsWidget in fund mode:
import { TrailsWidget } from "0xtrails/widget";

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="fund"
  toAddress="0xYourDepositAddress"
  toChainId={137}
  toToken="USDC"
  onCheckoutComplete={({ sessionId }) => {
    // verify server-side and update the user's balance
    console.log("Funded:", sessionId);
  }}
>
  <button>Add funds</button>
</TrailsWidget>
The widget surfaces crypto funding, cross-chain options, and card/bank onramp in a single UI. Users pick their preferred source; Trails routes from there.

Pre-set an amount

Pass toAmount to pre-populate the deposit value. Users can adjust it before confirming:
<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="fund"
  toAddress="0xYourDepositAddress"
  toChainId={137}
  toToken="USDC"
  toAmount="100"
  onCheckoutComplete={({ sessionId }) => updateBalance(sessionId)}
>
  <button>Add $100</button>
</TrailsWidget>

Default to fiat onramp

Set defaultInputMode="fiat" to open the widget on the card/bank tab by default. Useful for apps where most users are funding from fiat rather than existing crypto:
<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="fund"
  toAddress="0xYourDepositAddress"
  toChainId={137}
  toToken="USDC"
  defaultInputMode="fiat"
  onCheckoutComplete={({ sessionId }) => updateBalance(sessionId)}
>
  <button>Add funds</button>
</TrailsWidget>

Fund a smart contract

To deposit directly into a protocol, vault, or exchange contract on arrival, pass toCalldata with the encoded function call. Trails executes the calldata on the destination chain after routing funds:
import { encodeFunctionData } from "viem";
import { TRAILS_ROUTER_PLACEHOLDER_AMOUNT } from "0xtrails";

// Example: deposit into an ERC-4626 yield vault
const calldata = encodeFunctionData({
  abi: [{
    type: "function",
    name: "deposit",
    inputs: [
      { name: "assets", type: "uint256" },
      { name: "receiver", type: "address" },
    ],
    outputs: [{ name: "shares", type: "uint256" }],
  }],
  functionName: "deposit",
  args: [TRAILS_ROUTER_PLACEHOLDER_AMOUNT, "0xUserAddress"],
});

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="fund"
  toAddress="0xVaultContractAddress"
  toChainId={137}
  toToken="USDC"
  toCalldata={calldata}
  onCheckoutComplete={({ sessionId }) => updateVaultBalance(sessionId)}
>
  <button>Deposit to vault</button>
</TrailsWidget>
TRAILS_ROUTER_PLACEHOLDER_AMOUNT is replaced with the exact routed amount at execution time, so the vault receives the correct figure regardless of bridging or swap slippage.

Widget props

PropTypeDescription
apiKeystringYour Trails API key
mode"fund"Fund mode
toAddressstringDestination wallet or contract address
toChainIdnumberDestination chain ID
toTokenstringDestination token symbol or address
toAmountstringPre-set deposit amount (user can adjust)
toCalldatastringEncoded contract call to execute on arrival
defaultInputMode"fiat" | "token"Which tab opens by default
onCheckoutStartfunctionCalled when deposit is initiated
onCheckoutComplete({ sessionId }) => voidCalled on successful deposit
onCheckoutErrorfunctionCalled on failure

Headless SDK

For custom UI, use useQuote from the headless SDK. You control the presentation; Trails handles execution:
import { useQuote } from "0xtrails";

const { quote, fund } = useQuote({
  toAddress: "0xYourDepositAddress",
  toChainId: 137,
  toTokenAddress: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", // USDC on Polygon
  toAmount: "100000000", // 100 USDC in base units
  tradeType: "EXACT_INPUT",
  onStatusUpdate: (status) => console.log("Fund status:", status),
});

// Show quote.fees, quote.estimatedTime in your UI, then:
await fund();

Supported chains and tokens

Trails supports all major EVM chains. Users can fund from any supported chain regardless of where your destination address lives.
// Query tokens available on a specific chain
const { tokens } = await trails.getTokenList({ chainId: 137 });
See Supported Chains for the full network list.

Next steps

Cross-chain movement

Move tokens between wallets and chains without protocol interaction.

Yield accounts

Route funded USDC directly into a Morpho yield vault on arrival.

Smart Sessions

Automate recurring deposits without per-transaction prompts.

Trails API reference

Full endpoint reference, SDK docs, and widget customization options.