Skip to main content
All hooks and utilities are available from the 0xtrails package unless stated otherwise.

Chains

import { getSupportedChains, useSupportedChains } from '0xtrails'
  • getSupportedChains(): Promise<Chain[]>
  • useSupportedChains(): { supportedChains: Chain[], isLoadingChains: boolean }
Chain data structure:
type Chain = {
  id: number
  name: string
  chainId: number
  rpcUrls: string[]
  nativeCurrency: {
    name: string
    symbol: string
    decimals: number
  }
  blockExplorerUrls?: string[]
  imageUrl?: string
}
Utility:
import { getChainInfo } from '0xtrails'
const chain = getChainInfo(8453) // Base chain info

Tokens

import { getSupportedTokens, useSupportedTokens, useTokenList } from '0xtrails'
  • useTokenList(): { tokens: SupportedToken[] | undefined, isLoadingTokens: boolean }
  • useSupportedTokens({ chainId?: number }): { supportedTokens: SupportedToken[], isLoadingTokens: boolean }
  • getSupportedTokens(): Promise<SupportedToken[]>
Token data structure:
type SupportedToken = {
  id: string
  symbol: string
  name: string
  contractAddress: string
  decimals: number
  chainId: number
  chainName: string
  imageUrl: string
}
Additional helpers:
import { useTokenInfo, useTokenAddress } from '0xtrails'

// Returns basic info for an ERC-20 by address and chainId
const { tokenInfo, isLoading, error } = useTokenInfo({
  address: '0x...',
  chainId: 8453
})

// Get token address by symbol and chain
const tokenAddress = useTokenAddress({
  chainId: 8453,
  tokenSymbol: 'USDC'
})

Balances

import {
  useTokenBalances,
  getAccountTotalBalanceUsd,
  useAccountTotalBalanceUsd,
  getHasSufficientBalanceToken,
  useHasSufficientBalanceToken,
  getHasSufficientBalanceUsd,
  useHasSufficientBalanceUsd,
} from '0xtrails'
Balance hooks and utilities:
  • useTokenBalances(address): Returns sorted token balances enriched with USD price
  • useAccountTotalBalanceUsd(address): Returns total USD balance across tokens
  • useHasSufficientBalanceUsd(address, targetUsd): Check if account has sufficient USD balance
  • useHasSufficientBalanceToken(address, tokenAddress, tokenAmount, chainId): Check token balance
Balance data structures:
type TokenBalance = {
  contractAddress: string
  accountAddress: string
  tokenID: string
  balance: string
  chainId: number
  contractType: string
  blockHash: string
  blockNumber: number
  updateID: number
  contractInfo: {
    chainId: number
    contractAddress: string
    contractType: string
    decimals: number
    logoURI: string
    name: string
    symbol: string
    extensions?: {
      link?: string
      description?: string
      ogImage?: string
    }
  }
}
Example usage:
import { useTokenBalances, useAccountTotalBalanceUsd } from '0xtrails'

const WalletBalance = ({ address }: { address: string }) => {
  const { tokenBalances, isLoading } = useTokenBalances(address)
  const { totalBalanceUsd } = useAccountTotalBalanceUsd(address)

  if (isLoading) return <div>Loading balances...</div>

  return (
    <div>
      <h3>Total Balance: ${totalBalanceUsd}</h3>
      {tokenBalances?.map((token) => (
        <div key={`${token.chainId}-${token.contractAddress}`}>
          {token.contractInfo.symbol}: {token.balance}
        </div>
      ))}
    </div>
  )
}

Quotes and Swapping

import { 
  useQuote, 
  TradeType,
  type UseQuoteReturn,
  type UseQuoteProps,
  type SwapReturn,
  type Quote
} from '0xtrails'

useQuote Hook

The useQuote hook provides real-time quotes for token swaps and cross-chain transfers:
type UseQuoteProps = {
  walletClient?: WalletClient
  fromTokenAddress?: string | null
  fromChainId?: number | null
  toTokenAddress?: string | null
  toChainId?: number | null
  swapAmount?: string | bigint
  toRecipient?: string | null
  tradeType?: TradeType | null
  slippageTolerance?: string | number | null
  onStatusUpdate?: (txs: TransactionState[]) => void | null
}

type UseQuoteReturn = {
  quote: Quote | null
  swap: (() => Promise<SwapReturn | null>) | null
  isLoadingQuote: boolean
  quoteError: unknown
  refetchQuote: (() => Promise<void>) | null
}

Trade Types

enum TradeType {
  EXACT_INPUT = 'EXACT_INPUT',  // User specifies exact input amount
  EXACT_OUTPUT = 'EXACT_OUTPUT' // User specifies exact output amount
}
Usage example:
import { useQuote, TradeType } from '0xtrails'
import { useWalletClient, useAccount } from 'wagmi'

const SwapComponent = () => {
  const { data: walletClient } = useWalletClient()
  const { address } = useAccount()

  const { quote, swap, isLoadingQuote, quoteError, refetchQuote } = useQuote({
    walletClient,
    fromTokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
    fromChainId: 1, // Ethereum
    toTokenAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', // USDC
    toChainId: 8453, // Base
    swapAmount: '1000000', // 1 USDC
    tradeType: TradeType.EXACT_INPUT,
    toRecipient: address,
    slippageTolerance: '0.005', // 0.5%
    onStatusUpdate: (states) => {
      console.log('Transaction states:', states)
    },
  })

  // Quotes can become stale; refetch every ~30 seconds
  useEffect(() => {
    const id = setInterval(() => {
      refetchQuote?.()
    }, 30000)
    return () => clearInterval(id)
  }, [refetchQuote])

  const handleSwap = async () => {
    if (!swap) return
    
    try {
      const result = await swap()
      console.log('Swap completed:', result)
    } catch (error) {
      console.error('Swap failed:', error)
    }
  }

  if (isLoadingQuote) return <div>Getting quote...</div>
  if (quoteError) return <div>Error: {String(quoteError)}</div>
  if (!quote) return <div>No quote available</div>

  return (
    <div>
      <div>
        From: {quote.originAmountFormatted} {quote.originToken.symbol}
      </div>
      <div>
        To: {quote.destinationAmountFormatted} {quote.destinationToken.symbol}
      </div>
      <div>
        Fee: {quote.totalFeeAmountUsdDisplay}
      </div>
      <button onClick={handleSwap}>
        Execute Swap
      </button>
    </div>
  )
}

Constants

import { TRAILS_CONTRACT_PLACEHOLDER_AMOUNT } from '0xtrails'

TRAILS_CONTRACT_PLACEHOLDER_AMOUNT

This constant provides a placeholder value for amounts when encoding calldata in fund mode. It’s used to replace dynamic output amounts during contract execution. Use Case: When creating calldata for fund mode transactions where the final amount isn’t known until execution time, use this placeholder in your encoded function calls. The Trails system will replace it with the actual dynamic amount during contract execution. Example:
import { encodeFunctionData } from 'viem'
import { TRAILS_CONTRACT_PLACEHOLDER_AMOUNT } from '0xtrails'

// Encode calldata with placeholder amount
const calldata = encodeFunctionData({
  abi: stakingABI,
  functionName: 'stake',
  args: [TRAILS_CONTRACT_PLACEHOLDER_AMOUNT] // Will be replaced with actual amount
})

// Use in fund mode widget
<TrailsWidget
  mode="fund"
  toAddress="0x..." // Staking contract
  toCalldata={calldata}
  toChainId={1}
  toToken="ETH"
>
  <button>Stake ETH</button>
</TrailsWidget>
This pattern is essential for fund mode transactions where users choose their input amount, but the contract needs to receive the exact output amount after any swaps or bridging operations.

useGetTransactionHistory

Hook for fetching transaction history from a user’s wallet address for a specific chain.
import { useGetTransactionHistory } from '0xtrails'
Usage:
import { useGetTransactionHistory } from '0xtrails'

function TransactionList() {
  const { data, isLoading, error } = useGetTransactionHistory({
    chainId: 1,
    accountAddress: '0x123...',
    // Optional:
    // pageSize: 10,
    // includeMetadata: true,
    // page: 0,
  })

  if (isLoading) return <div>Loading...</div>
  if (error) return <div>Error: {String(error)}</div>

  return (
    <div>
      {data?.transactions?.map(tx => (
        <div key={tx.txnHash}>
          Transaction: {tx.txnHash} | Block: {tx.blockNumber} | Time: {tx.timestamp}
        </div>
      ))}
    </div>
  )
}
Types:
export type TransactionHistoryItemFromAPI = {
  txnHash: string
  blockNumber: number
  blockHash: string
  chainId: number
  metaTxnID: string | null
  transfers: Transfer[]
  timestamp: string
}

export type TransactionHistoryItem = TransactionHistoryItemFromAPI & {
  explorerUrl?: string
  chainName?: string
}

export type TransactionHistoryResponse = {
  page: {
    column: string
    pageSize: number
    more: boolean
  }
  transactions: TransactionHistoryItem[]
}

export type GetAccountTransactionHistoryParams = {
  chainId: number
  accountAddress: string
  pageSize?: number
  includeMetadata?: boolean
  page?: number
}