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

# Cross-Chain Transfer

> Bridge tokens across different blockchains

# Cross-Chain Transfer Guide

This guide covers integrating the Zet Cross-Chain Transfer API to move tokens between different blockchains.

## Overview

Cross-chain transfers use Zet's multi-chain routing infrastructure but are designed specifically for moving tokens from one chain to another, optionally converting to a different token on the destination chain.

```
Your App                    Zet API                   Bridge Protocol
   │                           │                          │
   ├── GET /transfer/chains ──►│                          │
   │◄── Chain + token list ────┤                          │
   │                           │                          │
   ├── POST /transfer/quote ──►│── Find route ───────────►│
   │◄── Quote + bridge info ───┤◄── Best bridge ──────────┤
   │                           │                          │
   ├── POST /transfer/execute ►│                          │
   │                           │── Approve + bridge ──► Source Chain
   │                           │                    Bridge relay ──► Dest Chain
   │                           │── Poll status ──────────►│
   │                           │                          │
   │◄── Webhook: transfer.completed ◄─────────────────────┤
   │                           │                          │
```

## Supported chains

### Source chains (send from)

| Chain    | Chain ID | Tokens                 |
| -------- | -------- | ---------------------- |
| **Base** | 8453     | ETH, USDC, CNGN, cbBTC |
| **BSC**  | 56       | BNB, USDC, USDT, CNGN  |

### Destination chains (send to)

| Chain         | Chain ID         |
| ------------- | ---------------- |
| **Base**      | 8453             |
| **BSC**       | 56               |
| **Ethereum**  | 1                |
| **Polygon**   | 137              |
| **Arbitrum**  | 42161            |
| **Avalanche** | 43114            |
| **Solana**    | 1151111081099710 |

<Info>
  You can also query supported chains dynamically via `GET /transfer/chains`.
</Info>

## Step 1: Get a transfer quote

Transfer 100 USDC from Base to Ethereum:

```javascript theme={null}
const quote = await fetch('https://api.zet.money/v1/transfer/quote', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': process.env.ZET_API_KEY,
  },
  body: JSON.stringify({
    fromChain: 'base',
    toChain: 'ethereum',
    token: 'USDC',
    toToken: 'USDC',              // Same token on destination
    amount: '100',
    destinationAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f5bA16',
  }),
}).then(r => r.json());
```

### Bridge + swap

Transfer USDC from Base and receive ETH on Ethereum:

```javascript theme={null}
const quote = await fetch('https://api.zet.money/v1/transfer/quote', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': process.env.ZET_API_KEY,
  },
  body: JSON.stringify({
    fromChain: 'base',
    toChain: 'ethereum',
    token: 'USDC',
    toToken: 'ETH',              // Different token on destination
    amount: '100',
    destinationAddress: '0x742d35Cc...',
  }),
}).then(r => r.json());
```

### Quote response

```json theme={null}
{
  "success": true,
  "data": {
    "quoteId": "qt_01H8X6abc",
    "fromChain": "base",
    "toChain": "ethereum",
    "fromToken": "USDC",
    "toToken": "USDC",
    "fromAmount": "100",
    "toAmount": "99.85",
    "fees": {
      "platformFee": "0.032",
      "platformFeeFiat": "50",
      "bridgeFee": "0.15",
      "totalFee": "0.182"
    },
    "route": {
      "steps": 2,
      "estimatedTime": "2-5 minutes",
      "bridge": "Bridge Protocol"
    },
    "expiresAt": "2026-03-02T10:05:00Z"
  }
}
```

### Fee breakdown

| Fee          | Amount                   | Description                |
| ------------ | ------------------------ | -------------------------- |
| Platform fee | 50 NGN (in source token) | Zet cross-chain fee        |
| Bridge fee   | Variable                 | Set by the bridge protocol |

## Step 2: Execute the transfer

### Custodial

```javascript theme={null}
const transfer = await fetch('https://api.zet.money/v1/transfer/execute', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': process.env.ZET_API_KEY,
  },
  body: JSON.stringify({
    quoteId: quote.data.quoteId,
    walletId: 'wal_01H8X3abc',
    reference: `transfer_${transferId}`,
  }),
}).then(r => r.json());
```

### Non-custodial

```javascript theme={null}
const transfer = await fetch('https://api.zet.money/v1/transfer/execute', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': process.env.ZET_API_KEY,
  },
  body: JSON.stringify({
    quoteId: quote.data.quoteId,
    sourceAddress: '0x742d35Cc...',
    reference: `transfer_${transferId}`,
  }),
}).then(r => r.json());

// User signs approval + bridge transaction
if (transfer.data.approvalData) {
  await userWallet.sendTransaction(transfer.data.approvalData);
}
await userWallet.sendTransaction(transfer.data.transactionData);
```

## Step 3: Monitor completion

Cross-chain transfers take longer than same-chain operations because they involve bridge relay confirmation on the destination chain.

| Bridge           | Estimated Time |
| ---------------- | -------------- |
| Fast bridges     | 1-5 minutes    |
| Standard bridges | 2-10 minutes   |
| Slow bridges     | 5-20 minutes   |

Listen for the `transfer.completed` webhook:

```javascript theme={null}
app.post('/webhooks/zet', (req, res) => {
  const { event, data } = req.body;

  if (event === 'transfer.completed') {
    console.log(`Transfer complete on ${data.chain}`);
    console.log(`TX: ${data.transactionHash}`);
  }

  if (event === 'transfer.failed') {
    // Funds typically remain on the source chain
    console.log(`Transfer failed: ${data.errorMessage}`);
  }

  res.status(200).send('OK');
});
```

## Common patterns

### Portfolio rebalancing

Move tokens between chains to rebalance a user's portfolio:

```javascript theme={null}
// Move 50 USDC from Base to BSC
const quote = await getTransferQuote({
  fromChain: 'base',
  toChain: 'bsc',
  token: 'USDC',
  toToken: 'USDC',
  amount: '50',
  destinationAddress: walletAddress, // Same address, different chain
});
```

### Multi-chain withdrawals

Let users withdraw to any supported chain:

```javascript theme={null}
// User wants to withdraw 100 USDC to Polygon
const quote = await getTransferQuote({
  fromChain: 'base',
  toChain: 'polygon',
  token: 'USDC',
  toToken: 'USDC',
  amount: '100',
  destinationAddress: userPolygonAddress,
});
```

## Best practices

1. **Show estimated time** — cross-chain transfers are slower than same-chain; manage user expectations
2. **Display the bridge protocol** — users benefit from knowing which bridge is being used
3. **Handle stuck transactions** — bridges can occasionally slow down; implement timeout alerts
4. **Prefer same-chain when possible** — if both source and destination are on the same chain, use the Swap API instead
5. **Verify destination address format** — ensure the address is valid for the destination chain (especially for Solana)
6. **Show fee breakdown** — bridge fees vary significantly; transparency builds trust
