Live Demo Try the Trails widget live. Configure, preview, and copy code.
React Starter Kit Minimal template for Trails with Earn, Swap, Pay, and Fund modes integrated.
NextJS Starter Kit Minimal NextJS template for Trails with Earn, Swap, Pay, and Fund modes integrated.
Prerequisites
React 18+ (18.0 or newer)
To install in your own application:
Install the SDK and dependencies
Import and Use the Widget
Add the widget to your React application. Here are examples for different modes: Pay Mode (Exact Output) Send exactly 1 USDC to a recipient on Base: import { TrailsWidget } from '0xtrails/widget'
export const PaymentExample = () => {
return (
< TrailsWidget
apiKey = "YOUR_API_KEY"
mode = "pay"
toAddress = "0x97c4A952b46bEcaD0663f76357d3776ba11566E1" // recipient address
toAmount = "1"
toChainId = { 8453 }
toToken = "USDC"
onCheckoutComplete = { ( result ) => {
console . log ( 'Payment completed:' , result )
} }
>
< button className = "pay-button" >
Pay 1 USDC
</ button >
</ TrailsWidget >
)
}
Swap Mode Enable cross-chain token swapping: import { TrailsWidget } from '0xtrails/widget'
export const SwapExample = () => {
return (
< TrailsWidget
apiKey = "YOUR_API_KEY"
mode = "swap"
onCheckoutComplete = { ( result ) => {
console . log ( 'Swap completed:' , result )
} }
>
< button className = "swap-button" >
Swap Tokens
</ button >
</ TrailsWidget >
)
}
Fund Mode Let users choose how much to deposit: import { TrailsWidget } from '0xtrails/widget'
export const FundExample = () => {
return (
< TrailsWidget
apiKey = "YOUR_API_KEY"
mode = "fund"
toAddress = "0x97c4A952b46bEcaD0663f76357d3776ba11566E1"
toChainId = { 8453 }
toToken = "USDC"
onCheckoutComplete = { ( result ) => {
console . log ( 'Funding completed:' , result )
} }
>
< button className = "fund-button" >
Add Funds
</ button >
</ TrailsWidget >
)
}
Handle Events (Optional)
Listen to various events during the transaction flow: import { TrailsWidget } from '0xtrails/widget'
export const AdvancedExample = () => {
return (
< TrailsWidget
apiKey = "YOUR_API_KEY"
mode = "pay"
toAddress = "0x97c4A952b46bEcaD0663f76357d3776ba11566E1"
toAmount = "1"
toChainId = { 8453 }
toToken = "USDC"
onCheckoutStatusUpdate = { ({ sessionId , transactionStates }) => {
console . log ( 'Transaction states updated:' , sessionId , transactionStates )
} }
onCheckoutError = { ({ sessionId , error }) => {
console . error ( 'Transaction error:' , sessionId , error )
} }
onCheckoutComplete = { ({ sessionId }) => {
console . log ( 'Transaction completed:' , sessionId )
} }
>
< button className = "advanced-button" >
Send Payment
</ button >
</ TrailsWidget >
)
}
Trails has a wallet connection flow integrated into the widget so users can connect via the widget or utilize another connector such as RainbowKit, Privy, etc. Using Hooks? If you plan to use Trails hooks (like useQuote, useTokenBalances, etc.), wrap your app with TrailsProvider. See the Hooks documentation for setup details.
Available Modes
The widget supports several modes for different use cases:
Pay - Exact output amount (user pays exactly what’s specified)
Fund - Deposit/top-up (user chooses amount to send)
Swap - Cross-chain token swapping
Earn - Integrated yield farming with various protocols
Withdraw - Withdraw assets with a guided, fee-aware flow
Script Import
While we recommend using the React component, you can also embed via a script tag in a non-React site.
You can load the Trails widget from various CDNs:
< div id = "trails" ></ div >
< script src = "https://cdn.jsdelivr.net/npm/0xtrails@latest/dist/umd/trails.min.js" ></ script >
< script >
TrailsWidget . render ( document . getElementById ( 'trails' ), {
apiKey: 'YOUR_API_KEY' ,
toAddress: '0x97c4A952b46bEcaD0663f76357d3776ba11566E1' ,
toAmount: '0.1' ,
toChainId: 8453 ,
toToken: 'USDC' ,
mode: 'pay'
})
</ script >
CDN Recommendations
unpkg : https://unpkg.com/0xtrails@latest/dist/umd/trails.min.js
jsDelivr : https://cdn.jsdelivr.net/npm/0xtrails@latest/dist/umd/trails.min.js
Specific Version : Replace @latest with @1.0.0 (or your desired version) for production use
For production applications, we recommend pinning to a specific version rather than using @latest to ensure consistent behavior.