Documentation Index
Fetch the complete documentation index at: https://anypay-trails-api-docs.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Swap with Trails
Trails enables seamless token swapping across multiple blockchain networks in 1-click, allowing users to exchange tokens without manually bridging assets or dealing with multiple DEXs available via an integrated widget or API.
Enhanced Swapping Experience
Traditional cross-chain swapping requires users to:
- Approve any ERC20 tokens
- Bridge tokens to the target chain
- Find and interact with DEXs on multiple networks
- Pay gas fees on each chain
- Wait for bridge confirmations
We optimize the UX flow from any wallet to enable swaps across multiple liquidity sources & chains. All interactions are executed in a single confirmation for the user. Notably, this works across any wallet or application, ERC-7702 or 4337 is not required for batching transactions.
Use Cases
Ideal for a variety of token exchange scenarios:
- Cross-chain token swaps (e.g., ETH on Mainnet → USDC on Base)
- Same-chain token exchanges with optimal routing
- Portfolio rebalancing across chains
- Converting between stablecoins with minimal slippage
Examples
Simple Cross-Chain Token Swap
Basic cross-chain swap implementation using the Trails widget with callbacks:
import { TrailsWidget } from '0xtrails/widget'
export const BasicSwap = () => {
return (
<TrailsWidget
apiKey="YOUR_API_KEY"
mode="swap"
onCheckoutComplete={({ sessionId }) => {
console.log('Swap completed:', sessionId)
}}
onCheckoutError={({ sessionId, error }) => {
console.error('Swap failed:', sessionId, error)
}}
>
<button className="swap-button">
Swap Tokens
</button>
</TrailsWidget>
)
}
Swap with Custom Theme
Customize the appearance to match your brand:
import { TrailsWidget } from '0xtrails/widget'
export const ThemedSwap = () => {
return (
<TrailsWidget
apiKey="YOUR_API_KEY"
mode="swap"
theme="dark"
onCheckoutComplete={({ sessionId }) => {
console.log('Themed swap completed:', sessionId)
}}
>
<div className="custom-swap-trigger">
<span>🔄</span>
<span>Swap Tokens</span>
</div>
</TrailsWidget>
)
}
Advanced Swap with Custom Quote Provider
While Trails automatically optimizes the selected route by the user, you may opt to specify a quote or bridge provider to optimize for your use case. For example, using Circle’s CCTP V2 for bridging:
import { TrailsWidget } from '0xtrails/widget'
export const AdvancedSwap = () => {
return (
<TrailsWidget
apiKey="YOUR_API_KEY"
mode="swap"
bridgeProvider="CCTP"
onCheckoutComplete={({ sessionId }) => {
console.log('Advanced swap completed:', sessionId)
// Handle post-swap logic
}}
onCheckoutError={({ sessionId, error }) => {
console.error('Swap error:', sessionId, error)
// Handle error state
}}
>
<button className="advanced-swap-button">
Swap with a Custom Provider
</button>
</TrailsWidget>
)
}
Using the useQuote Hook
For more control over the swap process for headless implementations, use the useQuote hook directly:
import { useQuote, TradeType } from '0xtrails'
import { useWalletClient, useAccount } from 'wagmi'
import { useState } from 'react'
export const CustomSwapComponent = () => {
const { data: walletClient } = useWalletClient()
const { address } = useAccount()
const [fromToken, setFromToken] = useState('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') // USDC on Ethereum
const [toToken, setToToken] = useState('0x833589fcd6edb6e08f4c7c32d4f71b54bda02913') // USDC on Base
const [amount, setAmount] = useState('1000000') // 1 USDC
const { quote, swap, isLoadingQuote, quoteError } = useQuote({
walletClient,
fromTokenAddress: fromToken,
fromChainId: 1, // Ethereum
toTokenAddress: toToken,
toChainId: 8453, // Base
swapAmount: amount,
tradeType: TradeType.EXACT_INPUT,
toAddress: address,
slippageTolerance: '0.005', // 0.5%
onStatusUpdate: (states) => {
console.log('Swap progress:', states)
},
})
const handleSwap = async () => {
if (!swap) return
try {
const result = await swap()
console.log('Swap result:', result)
} catch (error) {
console.error('Swap failed:', error)
}
}
if (isLoadingQuote) {
return <div>Loading quote...</div>
}
if (quoteError) {
return <div>Error getting quote: {String(quoteError)}</div>
}
if (!quote) {
return <div>No quote available</div>
}
return (
<div className="swap-component">
<div className="quote-info">
<h3>Swap Quote</h3>
<p>From: {quote.originAmountFormatted} {quote.originToken.symbol} on {quote.originChain.name}</p>
<p>To: {quote.destinationAmountFormatted} {quote.destinationToken.symbol} on {quote.destinationChain.name}</p>
<p>Fee: {quote.totalFeeAmountUsdDisplay}</p>
<p>Estimated time: {quote.completionEstimateSeconds}s</p>
</div>
<button onClick={handleSwap} className="execute-swap-button">
Execute Swap
</button>
</div>
)
}
Why Swap with Trails?
- Unified Liquidity: Access tokens from the user’s wallet across all supported chains in one transaction
- High Performance Balance Retrieval: A high-performant indexer is natively integrated to query the entirety of a user’s balance for smooth UX and price retrieval
- Reduced Complexity: Eliminate manual bridging and multi-step swaps (Approval and Transfer)
- Customized Branding: Brand or theme the widget however you’d like to be native to your protocol or application
- Seamless UX: Automatic routing finds optimal swap paths for low slippage for improved UX
- Gasless & Alt-fee token options: Support for gasless or alternative gas tokens like USDC for transactions to reduce friction
- Real-time Quotes: Live pricing and route optimization
- Chain Abstraction: Built from the ground up to support multichain environments and abstract underlying chains.
Next Steps
Learn more about customizing and configuring swap functionality: