> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pods.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Cross-Chain Swap

> Complete example of executing a cross-chain token swap with bridge integration

This example demonstrates how to swap tokens across different blockchain networks using the Pods 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+
* Pods API key
* Wallet with tokens on the origin chain
* Basic understanding of async/await

## Choose Your Library

<Tabs>
  <Tab title="ethers.js">
    Using ethers.js v6 for blockchain interactions - the most popular Ethereum library.
  </Tab>

  <Tab title="viem">
    Using viem for blockchain interactions - a modern, TypeScript-first alternative with better performance.
  </Tab>
</Tabs>

## Installation

<Tabs>
  <Tab title="ethers.js">
    ```bash theme={null}
    npm install axios ethers
    ```
  </Tab>

  <Tab title="viem">
    ```bash theme={null}
    npm install axios viem
    ```
  </Tab>
</Tabs>

## Environment Variables

Create a `.env` file:

```bash theme={null}
PODS_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
```

<Warning>
  Never commit your `.env` file to version control. Add it to `.gitignore`.
</Warning>

## Step-by-Step Walkthrough

### 1. Initialize API Client

```javascript theme={null}
import axios from 'axios'

const pods = axios.create({
  baseURL: 'https://api.pods.finance',
  headers: {
    'x-api-key': process.env.PODS_API_KEY,
    'Content-Type': 'application/json'
  }
})
```

### 2. Get Cross-Chain Quote

```javascript theme={null}
const { data } = await pods.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)
```

<Info>
  Cross-chain swaps use bridge providers like TeleSwap or Mayan and may take several minutes to complete.
</Info>

### 3. Generate Bytecode

```javascript theme={null}
const { data: bytecode } = await pods.post('/v2/swap/bytecode', {
  quoteId: quote.quoteId,
  originAddress: walletAddress,
  destinationAddress: walletAddress,
  ...(quote.rawQuote && { rawQuote: quote.rawQuote })
})

console.log('Chain ID:', bytecode.chainId)
console.log('ID:', bytecode.id)
console.log('Transactions to execute:', bytecode.transactionData.length)
```

### 4. Execute Origin Transactions (atomic batch)

<Warning>
  All origin-chain legs must go in **one atomic transaction**. See
  [Executing Bytecode](/getting-started/executing-bytecode) and
  [`cross-chain-swap.js`](/examples/javascript/cross-chain-swap.js).
</Warning>

```javascript theme={null}
import { http, createWalletClient, publicActions } from 'viem'
import { mainnet } from 'viem/chains'
import { privateKeyToAccount } from 'viem/accounts'
import { executeLegsViaEip7702 } from './eip7702-batch.js'

const account = privateKeyToAccount(process.env.PRIVATE_KEY)
const walletClient = createWalletClient({
  account,
  chain: mainnet,
  transport: http(process.env.ORIGIN_RPC_URL)
}).extend(publicActions)

const receipt = await executeLegsViaEip7702(walletClient, bytecode.transactionData)
console.log('✅ Origin batch confirmed in block', receipt.blockNumber)
console.log('⏳ Waiting for bridge to process...')
```

### 5. Monitor Status

Use the quote ID for quote status. The bytecode response also returns an `id`; use it with `GET /actions/{id}` when you need the execution record.

```javascript theme={null}
// Poll for status updates
const swapId = quote.quoteId

let status = 'pending'
while (!['fulfilled', 'failed', 'refunded', 'expired'].includes(status)) {
  await new Promise(resolve => setTimeout(resolve, 10000)) // Wait 10s

  const { data: statusData } = await pods.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 === 'fulfilled') {
  console.log('Cross-chain swap completed successfully!')
} else {
  console.error('Swap did not complete:', status)
}
```

## Webhook Alternative

Instead of polling, you can configure webhooks to receive status updates:

```javascript theme={null}
// Configure webhook in your Pods dashboard
// Webhook payload will include:
{
  "swapId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "fulfilled",
  "originTxHash": "0x123...",
  "destinationTxHash": "0x456...",
  "timestamp": "2024-01-24T12:35:00.000Z"
}
```

## Error Handling

```javascript theme={null}
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

```bash theme={null}
# 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)
   ID: 65f1a2b3c4d5e6f789012345
   Transactions: 2

3️⃣  Executing atomic EIP-7702 batch on origin...
   ✅ Confirmed in block 12345678

✅ Origin transaction completed!
⏳ Waiting for bridge to process...

4️⃣  Monitoring status...
   Status: confirmed
   Origin TX: 0x456...

   Status: processing
   Origin TX: 0x456...
   Destination TX: 0x789...

   Status: fulfilled
   Origin TX: 0x456...
   Destination TX: 0x789...

🎉 Cross-chain swap completed successfully!
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Same-Chain Swap" icon="arrows-rotate" href="/examples/javascript/same-chain-swap">
    Execute same-chain token swaps
  </Card>

  <Card title="Strategy Deposit" icon="arrow-up-right-dots" href="/examples/javascript/strategy-deposit">
    Deposit into yield strategies
  </Card>

  <Card title="Swap Guide" icon="book" href="/guides/swaps/get-quote">
    Learn more about swaps
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference">
    View complete API documentation
  </Card>
</CardGroup>
