Skip to main content
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.

Installation

npm install axios ethers

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('/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('/swap/bytecode', {
  quoteId: quote.quoteId,
  originAddress: walletAddress,
  destinationAddress: walletAddress,
  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...')

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(`/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: 2024-01-24T12:35:00.000Z

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