Skip to main content
The SDK accepts card, bank transfer, exchange, and wallet funding and normalizes them into a single payment flow. It handles UI, source selection, and execution.

Available funding sources

SourceDescription
Bank transfer / ACHDirect debit from a US bank account via ACH, or wire for international transfers
Debit or credit cardVisa and Mastercard; globally supported
Apple PayOne-tap funding from the Apple Pay sheet on supported browsers and devices
Exchange accountFund from a Coinbase, Binance, or Kraken balance directly
Crypto walletAny EVM-compatible wallet; any supported token on any supported network
Install the package and drop the component in:
npm install 0xtrails
import { Fund } from "0xtrails";

function FundButton() {
  return (
    <Fund
      apiKey="YOUR_API_KEY"
      to={{
        recipient: "0xYOUR_PRODUCT_WALLET",
        token: "USDC",
        chain: "polygon",
      }}
      onFundingSuccess={(result) => console.log("Funded:", result)}
    />
  );
}

Default to card or bank funding

Set paymentMethod to open the widget on the fiat tab:
<Fund
  apiKey="YOUR_API_KEY"
  paymentMethod="CREDIT_DEBIT_CARD"
  to={{
    recipient: "0xYOUR_PRODUCT_WALLET",
    token: "USDC",
    chain: "polygon",
  }}
/>

Fund an exact output amount

By default, Fund treats the user’s input as EXACT_INPUT: the customer spends a specific amount and receives whatever that converts to. To guarantee a specific delivered amount instead, set tradeType to EXACT_OUTPUT:
<Fund
  apiKey="YOUR_API_KEY"
  tradeType="EXACT_OUTPUT"
  to={{
    recipient: "0xYOUR_PRODUCT_WALLET",
    token: "USDC",
    chain: "polygon",
    amount: "100",
  }}
/>

Fund directly into a product account

Pass to.calldata to encode a destination action that executes automatically when funds arrive. Use dynamic() wherever the arrived amount should appear in the encoded arguments:
import { Fund, dynamic } from "0xtrails";
import { encodeFunctionData } from "viem";

const calldata = encodeFunctionData({
  abi: VAULT_ABI,
  functionName: "deposit",
  args: [dynamic(), "0xCUSTOMER_ADDRESS"],
});

<Fund
  apiKey="YOUR_API_KEY"
  to={{
    recipient: "0xYOUR_VAULT_CONTRACT",
    token: "USDC",
    chain: "polygon",
    calldata,
  }}
/>
See Dynamic values for details on dynamic() and related placeholders.

Fund component props

PropTypeRequiredDescription
apiKeystringYesYour API key
tradeType"EXACT_INPUT" | "EXACT_OUTPUT"NoEXACT_INPUT (default) fixes what the user spends; EXACT_OUTPUT fixes what they receive
to.recipientstringNoWallet or contract address to receive funds
to.tokenstringNoERC20 symbol or contract address to deliver
to.chainstring | numberNoDestination chain name or ID
to.amountstringRequired for EXACT_OUTPUTExact amount to deliver, in token units
to.calldatastringNoABI-encoded calldata for a destination action
paymentMethodstringNoPre-select funding tab: "CONNECTED_WALLET", "CRYPTO_TRANSFER", "CREDIT_DEBIT_CARD", "EXCHANGE"
onFundingStartfunctionNoCalled when the user begins the flow
onFundingSuccessfunctionNoCalled on completion
onFundingErrorfunctionNoCalled on failure
For theming and appearance options, see SDK configuration.

Non-React sites

For pages without React, load the widget via CDN:
<div id="trails-widget"></div>
<script src="https://cdn.trails.build/widget.js"></script>
<script>
  TrailsWidget.init({
    containerId: "trails-widget",
    accessKey: "YOUR_ACCESS_KEY",
    mode: "fund",
    destinationChainId: 137,
    destinationTokenAddress: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
    destinationToAddress: "0xYOUR_PRODUCT_WALLET",
  });
</script>

Direct API

For server-side integrations with no frontend component, use the API directly.
import { TrailsApi } from "@0xtrails/api";

const trails = new TrailsApi({
  baseUrl: "https://trails-api.sequence.app/rpc/Trails/",
  accessKey: "YOUR_ACCESS_KEY",
});

// Step 1: get a quote
const { intent, feeOptions } = await trails.quoteIntent({
  ownerAddress: "0xCUSTOMER_WALLET",
  originChainId: 1,
  originTokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  destinationChainId: 137,
  destinationTokenAddress: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
  destinationToAddress: "0xYOUR_PRODUCT_WALLET",
  tradeType: "EXACT_INPUT",
  originTokenAmount: "1000000",
});

// Step 2: lock the quote
const { intentId } = await trails.commitIntent({ intent });

// Step 3: execute
await trails.executeIntent({
  intentId,
  depositTransactionHash: "0xTRANSACTION_HASH",
});
For the full intent lifecycle and all endpoints, see the API reference.