Skip to content
TokenFlight SDK

Swap Widget

The Swap widget provides a cross-chain token swap interface. Users select source and destination tokens, enter an amount, and execute the swap.

Swap Widget
import { TokenFlightSwap } from '@tokenflight/swap';
const swap = new TokenFlightSwap({
container: '#swap-widget',
config: {
theme: 'dark',
locale: 'en-US',
slippage: 50,
},
callbacks: {
onSwapSuccess: (data) => console.log('Success:', data),
onSwapError: (data) => console.log('Error:', data),
onQuoteReceived: (data) => console.log('Quote:', data),
onAmountChanged: (data) => console.log('Amount:', data),
},
});
swap.initialize();
<tokenflight-swap
theme="dark"
locale="en-US"
default-slippage="50"
from-token="eip155:1:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
to-token="eip155:8453:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
></tokenflight-swap>
AttributeDefaultDescription
theme'light''light', 'dark', or 'auto'
locale'en-US'Display locale
default-slippage'50'Slippage tolerance in basis points (50 = 0.5%)
from-tokenSource token in CAIP-10 format (e.g. eip155:1:0x...)
to-tokenDestination token in CAIP-10 format
recipientCustom recipient address for cross-chain swaps (optional)
api-endpointCustom API endpoint URL
csp-nonceNonce for CSP-restricted environments
PropertyTypeDefaultDescription
theme'dark' | 'light' | 'auto''light'Widget color theme
localestring'en-US'Display locale
slippagenumber50Slippage tolerance in basis points (50 = 0.5%)
fromTokenTokenIdentifierSource token ({ chainId, address } or CAIP-10 string)
toTokenTokenIdentifierDestination token
recipientstringCustom recipient address for cross-chain swaps (optional)
apiEndpointstringCustom API endpoint URL
customColorsRecord<string, string>CSS color variable overrides

The Swap widget supports cross-chain swaps between EVM chains and Solana. When swapping to a different chain type than your connected wallet, you must provide a recipient address:

ScenarioConnected WalletTarget ChainRecipient Required
EVM → EVMMetaMaskBase, Arbitrum, etc.Optional (defaults to connected address)
EVM → SolanaMetaMaskSolanaRequired
Solana → EVMPhantomEthereum, Base, etc.Required
Solana → SolanaPhantomSolanaOptional (defaults to connected address)

Why recipient is required for cross-chain swaps:

When you’re connected with an EVM wallet (e.g., MetaMask) and swapping to Solana, the widget cannot access your Solana address. Therefore, you must manually enter a Solana recipient address. The same applies when swapping from Solana to EVM with a Solana wallet connected.

Example: EVM → Solana

import { TokenFlightSwap } from '@tokenflight/swap';
const swap = new TokenFlightSwap({
container: '#swap-widget',
config: {
theme: 'dark',
// From: Ethereum USDC
fromToken: 'eip155:1:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
// To: Solana USDC (use solana namespace for Solana tokens)
toToken: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
// Required when swapping to a different chain type
// (e.g., EVM wallet → Solana, or Solana wallet → EVM)
recipient: 'HN7cABqLq46Es1jh92dQQisAq662SmxELLLsHHe4YWrH',
},
callbacks: {
onWalletConnected: ({ address, chainType }) => {
console.log(`Connected: ${address} (${chainType})`);
// chainType is 'evm' or 'solana'
},
},
});
swap.initialize();

HTML usage:

<tokenflight-swap
theme="dark"
from-token="eip155:1:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
to-token="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
recipient="HN7cABqLq46Es1jh92dQQisAq662SmxELLLsHHe4YWrH"
></tokenflight-swap>

Programmatically Detecting Cross-Chain Requirements

Section titled “Programmatically Detecting Cross-Chain Requirements”

You can use the exported utilities to detect if a swap will require a recipient address:

import { getChainType, isCrossChainSwap, SOLANA_CHAIN_ID } from '@tokenflight/swap';
const fromChainId = 1; // Ethereum
const toChainId = SOLANA_CHAIN_ID; // Solana
// Check if chains are different types
const isCrossChain = isCrossChainSwap(fromChainId, toChainId);
console.log('Cross-chain swap:', isCrossChain); // true
// Get chain types
console.log('From chain type:', getChainType(fromChainId)); // 'evm'
console.log('To chain type:', getChainType(toChainId)); // 'solana'

When a cross-chain recipient is required, the widget will:

  1. Display a “Recipient” input field below the “You receive” panel
  2. Show a “Required” label to indicate the field must be filled
  3. Prevent the swap from proceeding until a valid address is entered
  4. Validate the address format based on the target chain
CallbackPayloadDescription
onSwapSuccessSwapSuccessDataFired after a successful swap transaction
onSwapErrorSwapErrorDataFired when a swap fails
onQuoteReceivedQuoteResponseFired when a new price quote is fetched
onAmountChangedAmountChangedDataFired when the user changes the input amount
onWalletConnectedWalletConnectedDataFired when a wallet connects
// Update theme without re-initialization
swap.setTheme('light'); // 'light' | 'dark' | 'auto'
// Apply custom color overrides
swap.setCustomColors({ primary: '#ff6600', background: '#1a1a2e' });
// Clean up the widget
swap.destroy();