All hooks and utilities are available from the 0xtrails package unless stated otherwise.
TrailsProvider
Required for Hooks: The TrailsProvider must wrap your application when using any Trails hooks. This provider configures the necessary context for all hook functionality.
import { TrailsProvider } from '0xtrails'
<TrailsProvider
config={{
trailsApiKey: "...",
trailsApiUrl: "...", // optional
sequenceIndexerUrl: "...", // optional
sequenceNodeGatewayUrl: "..." // optional
}}
>
<App />
</TrailsProvider>
Configuration Options
trailsApiKey (required): Your Trails API key. Join the Trails Telegram group to request access.
trailsApiUrl (optional): Custom API endpoint URL if using a self-hosted instance.
sequenceIndexerUrl (optional): Custom Sequence indexer URL.
sequenceNodeGatewayUrl (optional): Custom Sequence node gateway URL.
Chains
import { getSupportedChains, useSupportedChains } from '0xtrails'
getSupportedChains(): Promise<Chain[]>
useSupportedChains(): { supportedChains: Chain[], isLoadingChains: boolean }
Chain Type
type Chain = {
id: number
name: string
chainId: number
rpcUrls: string[]
nativeCurrency: {
name: string
symbol: string
decimals: number
}
blockExplorerUrls?: string[]
imageUrl?: string
}
Utility Functions
import { getChainInfo, getAllChains } from '0xtrails'
// Get info for specific chain
const chain = getChainInfo(8453) // Base chain info
// Get all chains (including unsupported)
const allChains = getAllChains()
Tokens
import { getSupportedTokens, useSupportedTokens, useTokenList } from '0xtrails'
useTokenList(): { tokens: SupportedToken[] | undefined, isLoadingTokens: boolean }
useSupportedTokens({ chainId?: number }): { supportedTokens: SupportedToken[], isLoadingTokens: boolean }
getSupportedTokens(): Promise<SupportedToken[]>
SupportedToken Type
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
TokenBalance Type
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 {
prepareSend,
useQuote,
TradeType,
type UseQuoteReturn,
type UseQuoteProps,
type SwapReturn,
type Quote
} from '0xtrails'
prepareSend
Prepares a send transaction with optimal routing. This is a lower-level function for advanced use cases.
Signature:
function prepareSend(params: {
fromTokenAddress: string
fromChainId: number
toTokenAddress: string
toChainId: number
amount: string | bigint
tradeType: TradeType
toRecipient?: string
slippageTolerance?: string | number
}): Promise<PrepareSendResult>
Usage:
const result = await prepareSend({
fromTokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
fromChainId: 1,
toTokenAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
toChainId: 8453,
amount: '1000000',
tradeType: TradeType.EXACT_INPUT,
})
useQuote Hook
The useQuote hook provides real-time quotes for token swaps and cross-chain transfers.
Types
type UseQuoteProps = {
walletClient?: any
fromTokenAddress?: string | null
fromChainId?: number | null
toTokenAddress?: string | null
toChainId?: number | null
toCalldata?: string | null
swapAmount?: string | bigint
toRecipient?: string | null
tradeType?: TradeType | null
slippageTolerance?: string | number | null
onStatusUpdate?: ((transactionStates: TransactionState[]) => void) | null
quoteProvider?: string | null
checkoutOnHandlers?: Partial<CheckoutOnHandlers>
paymasterUrl?: string
selectedFeeToken?: {
tokenAddress: string
tokenSymbol?: string
} | null
abortSignal?: AbortSignal
apiKey?: string | null
}
type UseQuoteReturn = {
quote: Quote | null
swap: (() => Promise<SwapReturn | null>) | null
isLoadingQuote: boolean
quoteError: unknown
refetchQuote: (() => Promise<void>) | null
}
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)
},
checkoutOnHandlers: {
triggerCheckoutStart: () => {
console.log("Checkout started")
},
triggerCheckoutSignatureConfirmed: () => {
console.log("Signature confirmed")
},
triggerCheckoutSignatureRequest: () => {
console.log("Signature request")
},
triggerCheckoutComplete: (
txStatus: "success" | "fail",
accountAddress?: string,
) => {
console.log(`Checkout complete for account ${accountAddress}: ${txStatus}`)
},
triggerCheckoutStatusUpdate: (transactionStates: TransactionState[]) => {
console.log("Transaction states updated:", transactionStates)
},
triggerCheckoutQuote: (quote: any) => {
console.log("Quote received:", quote)
},
triggerCheckoutSignatureRejected: (error: any) => {
console.log("Signature rejected:", error)
},
}
})
// 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
apiKey="YOUR_API_KEY"
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.
Transaction History
import {
getIntentTransactionHistory,
getAccountTransactionHistory,
useAccountTransactionHistory,
useIntentTransactionHistory,
getTxTimeDiff,
} from '0xtrails'
getIntentTransactionHistory
Gets transaction history for a specific intent address.
Signature:
function getIntentTransactionHistory(params: {
intentAddress: string
pageSize?: number
page?: number
}): Promise<IntentTransactionHistoryResponse>
Usage:
const history = await getIntentTransactionHistory({
intentAddress: '0x...',
pageSize: 10,
page: 0,
})
getAccountTransactionHistory
Gets transaction history for a wallet address interacting with Trails.
Signature:
function getAccountTransactionHistory(params: {
chainId: number
accountAddress: string
pageSize?: number
includeMetadata?: boolean
page?: number
}): Promise<TransactionHistoryResponse>
Usage:
const history = await getAccountTransactionHistory({
chainId: 1,
accountAddress: '0x...',
pageSize: 10,
})
useAccountTransactionHistory
React hook for account transaction history with pagination.
Usage:
const { transactions, isLoading, error, hasMore, loadMore } =
useAccountTransactionHistory({
chainId: 1,
accountAddress: address,
})
useIntentTransactionHistory
React hook for intent transaction history.
Usage:
const { transactions, isLoading, error } = useIntentTransactionHistory({
intentAddress: '0x...',
})
getTxTimeDiff
Gets the time difference for a transaction in human-readable format.
Signature: (timestamp: string | number) => string
Usage:
const timeDiff = getTxTimeDiff(transaction.timestamp)
console.log(timeDiff) // "5 minutes ago"
useGetTransactionHistory
Hook for fetching transaction history from a user’s wallet address for a specific chain.
import { useGetTransactionHistory } from '0xtrails'
Types
type TransactionHistoryItemFromAPI = {
txnHash: string
blockNumber: number
blockHash: string
chainId: number
metaTxnID: string | null
transfers: Transfer[]
timestamp: string
}
type TransactionHistoryItem = TransactionHistoryItemFromAPI & {
explorerUrl?: string
chainName?: string
}
type TransactionHistoryResponse = {
page: {
column: string
pageSize: number
more: boolean
}
transactions: TransactionHistoryItem[]
}
type GetAccountTransactionHistoryParams = {
chainId: number
accountAddress: string
pageSize?: number
includeMetadata?: boolean
page?: number
}
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>
)
}
Encoders
import { getERC20TransferData } from '0xtrails'
getERC20TransferData
Encodes ERC20 transfer calldata for token transfers.
Signature: (to: string, amount: bigint) => string
Usage:
const transferData = getERC20TransferData(
'0x1234567890123456789012345678901234567890',
1000000n // 1 USDC (6 decimals)
)
Error Handling
import {
InsufficientBalanceError,
UserRejectionError,
getIsUserRejectionError,
} from '0xtrails'
InsufficientBalanceError
Error thrown when a user has insufficient balance to complete a transaction.
Usage:
try {
await swap()
} catch (error) {
if (error instanceof InsufficientBalanceError) {
console.error('Insufficient balance for this transaction')
}
}
UserRejectionError
Error thrown when a user rejects a transaction in their wallet.
Usage:
try {
await swap()
} catch (error) {
if (error instanceof UserRejectionError) {
console.log('User rejected the transaction')
}
}
getIsUserRejectionError
Utility function to check if an error is a user rejection error.
Signature: (error: unknown) => boolean
Usage:
try {
await swap()
} catch (error) {
if (getIsUserRejectionError(error)) {
console.log('User rejected the transaction')
}
}
Advanced: Intent Functions
These are advanced functions for direct intent management. Most developers should use the TrailsWidget or useQuote hook instead.
import {
calculateIntentAddress,
calculateOriginAndDestinationIntentAddresses,
commitIntent,
getIntent,
sendOriginTransaction,
} from '0xtrails'
Types
type OriginCallParams = {
to: string
value: bigint
data: string
chainId: number
}
type QuoteProvider = 'lifi' | 'relay' | 'cctp' | 'auto'
type TrailsFee = {
amount: bigint
amountUsd: number
token: SupportedToken
}
calculateIntentAddress
Calculates the intent contract address for a given set of parameters.
Signature: (params: IntentParams) => Promise<string>
Usage:
const intentAddress = await calculateIntentAddress({
fromChainId: 1,
toChainId: 8453,
// ... other params
})
calculateOriginAndDestinationIntentAddresses
Calculates both origin and destination intent addresses.
Signature:
function calculateOriginAndDestinationIntentAddresses(
params: IntentParams
): Promise<{ originAddress: string; destinationAddress: string }>
Usage:
const { originAddress, destinationAddress } =
await calculateOriginAndDestinationIntentAddresses(params)
commitIntent
Commits an intent to the blockchain.
Signature: (params: CommitIntentParams) => Promise<CommitIntentResult>
Usage:
const result = await commitIntent({
walletClient,
fromChainId: 1,
toChainId: 8453,
// ... other params
})
getIntent
Retrieves an existing intent from the blockchain.
Signature: (intentAddress: string) => Promise<Intent>
Usage:
const intent = await getIntent('0x...')
sendOriginTransaction
Sends the origin transaction for an intent.
Signature: (params: SendOriginTxParams) => Promise<string>
Usage:
const txHash = await sendOriginTransaction({
walletClient,
intentAddress: '0x...',
// ... other params
})