Token Swap
The swap flow lets your users exchange one token for another -- either on the same chain or across different chains (bridged swap). The ONE SDK (@one_deploy/sdk v1.1.0) provides a full-featured widget for web and API methods for all platforms.
Widget Usage (Web)
OneSwapWidget
The primary swap widget handles token pair selection, amount input, route display, slippage configuration, and transaction execution.
import { OneSwapWidget } from '@one_deploy/sdk';
function SwapPage() {
return (
<OneSwapWidget
defaultFromToken={{ symbol: 'ETH', chainId: 1 }}
defaultToToken={{ symbol: 'USDC', chainId: 1 }}
defaultAmount="1.0"
walletAddress="0xYourUserWalletAddress"
slippageTolerance={0.5}
allowedChains={[1, 137, 42161]}
onSuccess={(result) => {
console.log('Swap complete:', result.txHash);
}}
onError={(error) => {
console.error('Swap failed:', error.message);
}}
onClose={() => {
console.log('Widget closed');
}}
theme="light"
/>
);
}
OneSwapWidgetProps
interface OneSwapWidgetProps {
/** Default source token */
defaultFromToken?: SwapToken;
/** Default destination token */
defaultToToken?: SwapToken;
/** Pre-filled swap amount (in source token units) */
defaultAmount?: string;
/** Connected wallet address */
walletAddress: string;
/** Slippage tolerance as a percentage (e.g. 0.5 = 0.5%) */
slippageTolerance?: number;
/** Restrict swaps to these chain IDs */
allowedChains?: number[];
/** Restrict selectable tokens */
allowedTokens?: SwapToken[];
/** Enable cross-chain swaps (default: true) */
enableCrossChain?: boolean;
/** Called when swap completes */
onSuccess?: (result: SwapResult) => void;
/** Called when swap fails */
onError?: (error: { code: string; message: string }) => void;
/** Called when user closes widget */
onClose?: () => void;
/** Widget color theme */
theme?: 'light' | 'dark' | 'auto';
/** Override CSS class name */
className?: string;
}
Preset Widgets
import { OneSameChainSwap, OneCrossChainSwap } from '@one_deploy/sdk';
function SwapPresets() {
return (
<>
{/* Same-chain swap only -- cross-chain toggle is hidden */}
<OneSameChainSwap
walletAddress="0xAbc..."
defaultFromToken={{ symbol: 'ETH', chainId: 1 }}
defaultToToken={{ symbol: 'USDC', chainId: 1 }}
onSuccess={(result) => console.log('Same-chain swap done', result)}
/>
{/* Cross-chain swap -- source and dest chains differ */}
<OneCrossChainSwap
walletAddress="0xAbc..."
defaultFromToken={{ symbol: 'ETH', chainId: 1 }}
defaultToToken={{ symbol: 'USDC', chainId: 137 }}
onSuccess={(result) => console.log('Cross-chain swap done', result)}
/>
</>
);
}
API Methods (All Platforms)
getSwapQuote
Fetch a swap quote including the optimal route, estimated output, and fee breakdown.
import { OneEngineClient } from '@one_deploy/sdk';
const engine = new OneEngineClient({
apiKey: 'YOUR_API_KEY',
projectId: 'YOUR_PROJECT_ID',
});
// Same-chain swap: ETH -> USDC on Ethereum
const quote: SwapQuote = await engine.getSwapQuote({
fromToken: 'ETH',
fromChainId: 1,
toToken: 'USDC',
toChainId: 1,
amount: '1.0',
slippage: 0.5,
senderAddress: '0xAbc...',
});
console.log(quote);
// {
// quoteId: 'sq_abc123',
// fromToken: { symbol: 'ETH', chainId: 1, address: '0x...', decimals: 18 },
// toToken: { symbol: 'USDC', chainId: 1, address: '0xA0b...', decimals: 6 },
// fromAmount: '1.0',
// toAmount: '2634.52',
// route: { steps: [...], estimatedGas: '150000', priceImpact: 0.03 },
// fee: { amount: '0.003', token: 'ETH' },
// expiresAt: '2026-02-02T12:05:00Z',
// }
// Cross-chain swap: ETH (Ethereum) -> USDC (Polygon)
const crossChainQuote: SwapQuote = await engine.getSwapQuote({
fromToken: 'ETH',
fromChainId: 1,
toToken: 'USDC',
toChainId: 137,
amount: '0.5',
slippage: 1.0,
senderAddress: '0xAbc...',
});
console.log('Cross-chain route steps:', crossChainQuote.route.steps.length);
// Typically: swap ETH->USDC on Ethereum, bridge USDC to Polygon
executeSwap
Execute a swap using a previously obtained quote.
const result: SwapResult = await engine.executeSwap({
quoteId: quote.quoteId,
senderAddress: '0xAbc...',
receiverAddress: '0xAbc...', // usually same as sender
});
console.log(result);
// {
// swapId: 'sw_xyz789',
// status: 'processing',
// txHash: '0x1234...',
// fromAmount: '1.0',
// toAmount: '2634.52',
// route: { ... },
// }
getSwapStatus
Check the current status of a swap, especially useful for cross-chain swaps that take longer.
const status: SwapResult = await engine.getSwapStatus('sw_xyz789');
console.log(status.status); // 'processing' | 'completed' | 'failed'
console.log(status.txHash); // source chain tx hash
console.log(status.destinationTxHash); // dest chain tx hash (cross-chain only)
getSupportedSwapTokens
List all tokens available for swapping, optionally filtered by chain.
// All tokens across all chains
const allTokens: SwapToken[] = await engine.getSupportedSwapTokens();
// Tokens on Polygon only
const polygonTokens: SwapToken[] = await engine.getSupportedSwapTokens(137);
getSupportedSwapChains
List all chains that support swaps.
const chains = await engine.getSupportedSwapChains();
// [
// { chainId: 1, name: 'Ethereum', type: 'evm' },
// { chainId: 137, name: 'Polygon', type: 'evm' },
// { chainId: 42161, name: 'Arbitrum', type: 'evm' },
// ...
// ]
Types
interface SwapToken {
/** Token ticker symbol */
symbol: string;
/** Chain ID the token lives on */
chainId: number;
/** Contract address (undefined for native tokens like ETH) */
address?: string;
/** Token decimals */
decimals?: number;
/** Display name */
name?: string;
/** Token logo URL */
logoUrl?: string;
}
interface SwapQuoteRequest {
/** Source token symbol */
fromToken: string;
/** Source chain ID */
fromChainId: number;
/** Destination token symbol */
toToken: string;
/** Destination chain ID */
toChainId: number;
/** Amount of source token to swap (human-readable) */
amount: string;
/** Slippage tolerance as a percentage (e.g. 0.5) */
slippage?: number;
/** Address initiating the swap */
senderAddress: string;
}
interface SwapQuote {
/** Server-generated quote identifier */
quoteId: string;
/** Source token details */
fromToken: SwapToken;
/** Destination token details */
toToken: SwapToken;
/** Input amount (human-readable) */
fromAmount: string;
/** Estimated output amount (human-readable) */
toAmount: string;
/** Optimal route for the swap */
route: SwapRoute;
/** Fee breakdown */
fee: {
amount: string;
token: string;
};
/** ISO 8601 expiry */
expiresAt: string;
}
interface SwapRoute {
/** Ordered steps in the swap route */
steps: SwapStep[];
/** Estimated gas in wei */
estimatedGas: string;
/** Price impact as a percentage (e.g. 0.03 = 0.03%) */
priceImpact: number;
/** Estimated execution time in seconds */
estimatedTime?: number;
}
interface SwapStep {
/** Step type */
type: 'swap' | 'bridge' | 'approve';
/** Protocol or DEX used for this step */
protocol: string;
/** Source token for this step */
fromToken: SwapToken;
/** Destination token for this step */
toToken: SwapToken;
/** Input amount for this step */
fromAmount: string;
/** Expected output for this step */
toAmount: string;
/** Chain ID where this step executes */
chainId: number;
}
interface SwapExecuteRequest {
/** Quote ID from getSwapQuote */
quoteId: string;
/** Address executing the swap */
senderAddress: string;
/** Address to receive output tokens (defaults to sender) */
receiverAddress?: string;
}
interface SwapResult {
/** Unique swap identifier */
swapId: string;
/** Current status */
status: 'pending' | 'processing' | 'completed' | 'failed';
/** Source chain transaction hash */
txHash?: string;
/** Destination chain tx hash (cross-chain only) */
destinationTxHash?: string;
/** Actual input amount */
fromAmount: string;
/** Actual (or estimated) output amount */
toAmount: string;
/** Route that was executed */
route: SwapRoute;
/** Source token */
fromToken: SwapToken;
/** Destination token */
toToken: SwapToken;
/** ISO 8601 creation timestamp */
createdAt: string;
/** ISO 8601 last-updated timestamp */
updatedAt: string;
}
Full Example: Same-chain Swap
import { OneEngineClient } from '@one_deploy/sdk';
const engine = new OneEngineClient({
apiKey: process.env.ONE_API_KEY!,
projectId: process.env.ONE_PROJECT_ID!,
});
async function swapETHtoUSDC(wallet: string) {
// 1. Get a quote
const quote = await engine.getSwapQuote({
fromToken: 'ETH',
fromChainId: 1,
toToken: 'USDC',
toChainId: 1,
amount: '0.5',
slippage: 0.5,
senderAddress: wallet,
});
console.log(`Swap 0.5 ETH -> ~${quote.toAmount} USDC`);
console.log(`Route: ${quote.route.steps.map((s) => s.protocol).join(' -> ')}`);
console.log(`Price impact: ${quote.route.priceImpact}%`);
// 2. Execute the swap
const result = await engine.executeSwap({
quoteId: quote.quoteId,
senderAddress: wallet,
});
// 3. Wait for completion
let status = await engine.getSwapStatus(result.swapId);
while (status.status === 'pending' || status.status === 'processing') {
await new Promise((r) => setTimeout(r, 3000));
status = await engine.getSwapStatus(result.swapId);
}
console.log(`Swap ${status.status}: received ${status.toAmount} USDC`);
console.log(`Tx: ${status.txHash}`);
}
Full Example: Cross-chain Swap
async function crossChainSwap(wallet: string) {
// ETH on Ethereum -> USDC on Polygon
const quote = await engine.getSwapQuote({
fromToken: 'ETH',
fromChainId: 1,
toToken: 'USDC',
toChainId: 137,
amount: '1.0',
slippage: 1.0,
senderAddress: wallet,
});
console.log(`Cross-chain: 1 ETH (Ethereum) -> ~${quote.toAmount} USDC (Polygon)`);
console.log(`Steps: ${quote.route.steps.length}`);
quote.route.steps.forEach((step, i) => {
console.log(
` Step ${i + 1}: ${step.type} via ${step.protocol} -- ` +
`${step.fromAmount} ${step.fromToken.symbol} -> ${step.toAmount} ${step.toToken.symbol}`
);
});
console.log(`Estimated time: ${quote.route.estimatedTime}s`);
// Execute
const result = await engine.executeSwap({
quoteId: quote.quoteId,
senderAddress: wallet,
receiverAddress: wallet,
});
// Poll -- cross-chain swaps may take longer
let status = await engine.getSwapStatus(result.swapId);
while (status.status === 'pending' || status.status === 'processing') {
await new Promise((r) => setTimeout(r, 10000));
status = await engine.getSwapStatus(result.swapId);
console.log(`Status: ${status.status}`);
}
console.log(`Done: ${status.toAmount} USDC on Polygon`);
console.log(`Source tx: ${status.txHash}`);
console.log(`Destination tx: ${status.destinationTxHash}`);
}