Skip to main content

Configuration Options

Trails is easy to get started, however we have deep configuration options to address most use cases.

Core Props

PropTypeRequiredDescription
apiKeystringYesYour project access key provided by Trails
mode"pay" | "fund" | "earn" | "swap"YesWidget operation mode
toAddressstringNoDestination address for payments
toAmountstringNoExact amount for payments (used in pay mode)
toChainIdnumber | stringNoDestination chain ID
toTokenstringNoDestination token symbol or contract address
toCalldatastringNoCustom calldata for contract interactions

UI & Rendering Options

PropTypeRequiredDescription
renderInlinebooleanNoRender widget inline instead of as a modal (default: false)
childrenReact.ReactNodeNoCustom button content (when not renderInline)
buttonTextstringNoCustom text for the trigger button (auto-generated if not provided)
theme"light" | "dark" | "auto"NoColor theme; auto follows system preference (default: "auto")
customCssstring | Record<string, string>NoCustom CSS styles to apply to the component
disableCssbooleanNoDisable default CSS injection (for custom styling)
toastbooleanNoShow toast notifications for transaction updates
hideDisconnectbooleanNoHide the disconnect button in the widget
payMessagestringNoCustom message to display during payment flow

Wallet & Connection Options

PropTypeRequiredDescription
walletConnectProjectIdstringNoWalletConnect project ID for WalletConnect integration
walletOptionsstring[]NoArray of wallet connector IDs to show (e.g., ["metamask", "walletconnect"])
isSmartWalletbooleanNoIndicate if the connected wallet is a smart wallet (for ERC-4337 support)
decoupleWagmibooleanNoDecouple from wagmi provider (use external wagmi config)
wagmiConnectorsConnector[]NoCustom wagmi connectors to use

Transaction Options

PropTypeRequiredDescription
paymasterUrlsArray<{ chainId: number; url: string }>NoConfigure per-chain paymaster endpoints for gasless transactions
swapProviderRouteProviderNoPreferred swap provider: "AUTO", "LIFI", "RELAY", "SUSHI", "ZEROX", or "CCTP". Default: "AUTO" automatically selects best provider
bridgeProviderRouteProviderNoPreferred bridge provider: "AUTO", "LIFI", "RELAY", "CCTP". Default: "AUTO" automatically selects best provider for cross-chain transfers
slippageTolerancenumber | stringNoSlippage tolerance for swaps (e.g., 0.005 for 0.5%)
priceImpactWarningThresholdBpsnumberNoPrice impact threshold in basis points before showing a warning (e.g., 500 for 5%)
priceImpactWarningMessagestringNoCustom message to display when price impact exceeds threshold
priceImpactFallbackBridgeUrlstringNoURL to redirect users when price impact is too high

App Metadata (for WalletConnect)

PropTypeRequiredDescription
appNamestringNoYour app’s name (shown in wallet connect dialogs)
appUrlstringNoYour app’s URL
appImageUrlstringNoYour app’s logo URL
appDescriptionstringNoShort description of your app

Onramp Integration

PropTypeRequiredDescription
onrampOnrampFactoryNoOnramp factory function from @0xtrails/onramp for fiat-to-crypto funding
import { trailsOnramp } from "@0xtrails/onramp"

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="fund"
  onramp={trailsOnramp({ 
    config: { 
      exchanges: ['coinbase', 'moonpay'] 
    } 
  })}
/>

Event Handlers

PropTypeRequiredDescription
onOriginConfirmation(data: { txHash: string; chainId: number; sessionId: string }) => voidNoCalled when origin transaction is confirmed
onDestinationConfirmation(data: { txHash: string; chainId: number; sessionId: string }) => voidNoCalled when destination transaction is confirmed
onCheckoutStart(data: { sessionId: string }) => voidNoCalled when checkout process starts
onCheckoutQuote(data: { sessionId: string; quote: any }) => voidNoCalled when quote is received
onCheckoutSignatureRequest(data: { sessionId: string }) => voidNoCalled when signature is requested from wallet
onCheckoutSignatureConfirmed(data: { sessionId: string }) => voidNoCalled when user confirms signature
onCheckoutSignatureRejected(data: { sessionId: string; error: unknown }) => voidNoCalled when user rejects signature
onCheckoutComplete(data: { sessionId: string }) => voidNoCalled when checkout completes successfully
onCheckoutError(data: { sessionId: string; error: unknown }) => voidNoCalled when checkout encounters an error (including user rejection)
onCheckoutStatusUpdate(data: { sessionId: string; transactionStates: TransactionState[] }) => voidNoCalled when transaction status updates
onCheckoutApprovalRequest(data: { sessionId: string }) => voidNoCalled when token approval is requested
onCheckoutApprovalConfirmed(data: { sessionId: string; transactionHash: string }) => voidNoCalled when token approval is confirmed
onCheckoutApprovalRejected(data: { sessionId: string; error: unknown }) => voidNoCalled when token approval is rejected
onOpen() => voidNoCalled when the widget modal opens
onClose() => voidNoCalled when the widget modal closes

Smart Contract Interactions

Execute custom contract calls with payments:
import { encodeFunctionData } from 'viem'

const calldata = encodeFunctionData({
  abi: contractABI,
  functionName: 'mintNFT',
  args: [recipient, tokenId]
})

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="pay"
  toAddress="0x..." // Contract address
  toAmount="0.1"
  toChainId={1}
  toToken="ETH"
  toCalldata={calldata}
  onCheckoutComplete={(result) => {
    console.log('NFT minted:', result)
  }}
/>

Event Handling Examples

Complete Event Handling

import { getIsUserRejectionError } from '0xtrails'

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="pay"
  toAddress="0x..."
  toAmount="1"
  toChainId={8453}
  toToken="USDC"
  onOriginConfirmation={({ txHash, chainId, sessionId }) => {
    console.log('Origin tx confirmed:', { txHash, chainId, sessionId })
  }}
  onDestinationConfirmation={({ txHash, chainId, sessionId }) => {
    console.log('Destination tx confirmed:', { txHash, chainId, sessionId })
  }}
  onCheckoutStatusUpdate={({ sessionId, transactionStates }) => {
    transactionStates.forEach((state, index) => {
      console.log(`Step ${index + 1}: ${state.label} - ${state.state}`)
      if (state.state === 'confirmed') {
        console.log('Transaction confirmed:', state.transactionHash)
      }
    })
  }}
  onCheckoutComplete={({ sessionId }) => {
    console.log('Transaction completed successfully:', sessionId)
  }}
  onCheckoutError={({ sessionId, error }) => {
    console.error('Transaction failed:', sessionId, error)
    
    // Check if user rejected the transaction
    if (getIsUserRejectionError(error)) {
      console.log('User rejected the transaction')
      // Handle user rejection (e.g., show "Transaction cancelled" message)
    } else {
      // Handle other errors (show error notification, retry logic, etc.)
    }
  }}
/>

Handling User Rejection

User rejection occurs when a user declines to sign a transaction in their wallet. This is handled through the onCheckoutError callback:
import { getIsUserRejectionError, TrailsWidget } from '0xtrails'

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="pay"
  toAddress="0x..."
  onCheckoutError={({ sessionId, error }) => {
    if (getIsUserRejectionError(error)) {
      // User cancelled the transaction
      showNotification('Transaction cancelled by user')
    } else {
      // Other error occurred
      showNotification('Transaction failed: ' + error)
    }
  }}
/>