This example demonstrates how to swap tokens across different blockchain networks using the Deframe API with JavaScript/TypeScript.
Overview
This example covers:
Getting a cross-chain swap quote
Generating transaction bytecode
Executing the swap transaction
Monitoring transaction status across chains
Prerequisites
Node.js 18+
Deframe API key
Wallet with tokens on the origin chain
Basic understanding of async/await
Choose Your Library
Using ethers.js v6 for blockchain interactions - the most popular Ethereum library.
Using viem for blockchain interactions - a modern, TypeScript-first alternative with better performance.
Installation
Environment Variables
Create a .env file:
DEFRAME_API_KEY = your-api-key
WALLET_ADDRESS = 0x...
PRIVATE_KEY = 0x...
ORIGIN_RPC_URL = https://eth-mainnet.g.alchemy.com/v2/your-key
DESTINATION_RPC_URL = https://polygon-mainnet.g.alchemy.com/v2/your-key
Never commit your .env file to version control. Add it to .gitignore.
Step-by-Step Walkthrough
1. Initialize API Client
import axios from 'axios'
const deframe = axios . create ({
baseURL: 'https://api.deframe.io' ,
headers: {
'x-api-key' : process . env . DEFRAME_API_KEY ,
'Content-Type' : 'application/json'
}
})
2. Get Cross-Chain Quote
const { data } = await deframe . get ( '/v2/swap/quote' , {
params: {
originChain: 'ethereum' ,
destinationChain: 'polygon' ,
tokenIn: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' , // USDC on Ethereum
tokenOut: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174' , // USDC on Polygon
amountIn: '1000000000' // 1000 USDC (6 decimals)
}
})
const quote = data . quote
console . log ( 'Quote ID:' , quote . quoteId )
console . log ( 'Origin Chain:' , quote . originChain )
console . log ( 'Destination Chain:' , quote . destinationChain )
console . log ( 'Expected output:' , quote . tokenOut . amount )
console . log ( 'Provider:' , quote . provider )
console . log ( 'Deadline:' , quote . deadline )
Cross-chain swaps use bridge providers like TeleSwap or Mayan and may take several minutes to complete.
3. Generate Bytecode
const { data : bytecode } = await deframe . post ( '/v2/swap/bytecode' , {
quoteId: quote . quoteId ,
originAddress: walletAddress ,
destinationAddress: walletAddress ,
... ( quote . rawQuote && { rawQuote: quote . rawQuote })
})
console . log ( 'Chain ID:' , bytecode . chainId )
console . log ( 'Transactions to execute:' , bytecode . transactionData . length )
4. Execute Transactions
import { ethers } from 'ethers'
// Connect to origin chain
const provider = new ethers . JsonRpcProvider ( process . env . ORIGIN_RPC_URL )
const wallet = new ethers . Wallet ( process . env . PRIVATE_KEY , provider )
for ( const tx of bytecode . transactionData ) {
const transaction = await wallet . sendTransaction ({
to: tx . to ,
data: tx . data ,
value: tx . value ,
chainId: tx . chainId
})
console . log ( 'Transaction sent:' , transaction . hash )
const receipt = await transaction . wait ()
console . log ( 'Confirmed in block:' , receipt . blockNumber )
}
console . log ( '✅ Origin transaction completed!' )
console . log ( '⏳ Waiting for bridge to process...' )
import { createWalletClient , http } from 'viem'
import { mainnet } from 'viem/chains'
import { privateKeyToAccount } from 'viem/accounts'
const account = privateKeyToAccount ( process . env . PRIVATE_KEY )
const client = createWalletClient ({
account ,
chain: mainnet ,
transport: http ( process . env . ORIGIN_RPC_URL )
})
for ( const tx of bytecode . transactionData ) {
const hash = await client . sendTransaction ({
to: tx . to ,
data: tx . data ,
value: BigInt ( tx . value ),
chain: mainnet
})
console . log ( 'Transaction sent:' , hash )
const receipt = await client . waitForTransactionReceipt ({ hash })
console . log ( 'Confirmed in block:' , receipt . blockNumber )
}
console . log ( '✅ Origin transaction completed!' )
console . log ( '⏳ Waiting for bridge to process...' )
5. Monitor Status
Transaction status tracking is available in an upcoming release.
For now, monitor your transaction directly on-chain using the
transaction hash returned after execution.
// Poll for status updates
const swapId = quote . quoteId
let status = 'pending'
while ( status !== 'success' && status !== 'failed' ) {
await new Promise ( resolve => setTimeout ( resolve , 10000 )) // Wait 10s
const { data : statusData } = await deframe . get ( `/v2/swap/status/ ${ swapId } ` )
status = statusData . status
console . log ( 'Status:' , status )
if ( statusData . originTxHash ) {
console . log ( 'Origin TX:' , statusData . originTxHash )
}
if ( statusData . destinationTxHash ) {
console . log ( 'Destination TX:' , statusData . destinationTxHash )
}
}
if ( status === 'success' ) {
console . log ( '🎉 Cross-chain swap completed successfully!' )
} else {
console . error ( '❌ Swap failed' )
}
Webhook Alternative
Instead of polling, you can configure webhooks to receive status updates:
// Configure webhook in your Deframe dashboard
// Webhook payload will include:
{
"swapId" : "550e8400-e29b-41d4-a716-446655440000" ,
"status" : "success" ,
"originTxHash" : "0x123..." ,
"destinationTxHash" : "0x456..." ,
"timestamp" : "2024-01-24T12:35:00.000Z"
}
Error Handling
try {
// Your code here
} catch ( error ) {
if ( error . response ?. data ?. error ) {
const apiError = error . response . data . error
console . error ( 'API Error:' , apiError . code )
console . error ( 'Message:' , apiError . message )
if ( apiError . code === 'QUOTE_EXPIRED' ) {
console . log ( 'Quote expired, please request a new one' )
} else if ( apiError . code === 'NO_ROUTE_FOUND' ) {
console . log ( 'No cross-chain route available' )
}
} else {
console . error ( 'Unexpected error:' , error . message )
}
}
Running the Example
# Install dependencies
npm install
# Set environment variables
cp .env.example .env
# Edit .env with your values
# Run the example
node cross-chain-swap.js
Expected Output
1️⃣ Getting cross-chain quote...
✅ Quote received:
Quote ID: 550e8400-e29b-41d4-a716-446655440000
Origin: ethereum
Destination: polygon
Provider: TeleSwap
Amount in: 1000 USDC
Expected out: 998.5 USDC
Deadline: 1706098500
2️⃣ Generating bytecode...
✅ Bytecode generated:
Chain ID: 1 (ethereum)
Transactions: 2
3️⃣ Executing origin transactions...
Transaction 1/2 (Approve)...
Transaction sent: 0x123...
✅ Confirmed in block 12345678
Transaction 2/2 (Bridge)...
Transaction sent: 0x456...
✅ Confirmed in block 12345679
✅ Origin transaction completed!
⏳ Waiting for bridge to process...
4️⃣ Monitoring status...
Status: crossing
Origin TX: 0x456...
Status: propagated
Origin TX: 0x456...
Destination TX: 0x789...
Status: success
Origin TX: 0x456...
Destination TX: 0x789...
🎉 Cross-chain swap completed successfully!
Next Steps
Same-Chain Swap Execute same-chain token swaps
Strategy Deposit Deposit into yield strategies
Swap Guide Learn more about swaps
API Reference View complete API documentation