Skip to main content
This guide walks you through a complete swap flow from Bitcoin (BTC) to Ethereum USDC using the LeoKit API. We’ll cover all five steps: getting a quote, generating a deposit transaction, signing and broadcasting, saving the transaction hash, and tracking the swap status.

Overview

The complete swap flow consists of 5 steps:
  1. Get Quote - Request swap rates from multiple protocols
  2. Generate Deposit - Create an unsigned transaction
  3. Sign & Broadcast - Sign with wallet and broadcast to blockchain
  4. Save Transaction - Register the transaction hash with LeoKit
  5. Track Status - Monitor swap progress until completion

Example: BTC → ETH USDC

Let’s swap 1 BTC (100,000,000 satoshis) to USDC on Ethereum.

Step 1: Get Quote

Request quotes from all supported protocols to find the best rate.
curl -X GET 'https://api.leodex.io/leokit/quote?from_asset=BTC.BTC&to_asset=ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&amount=100000000&destination=0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb&origin=bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh&slippage_bps=150' \
  -H 'Api-Key: your_api_key_here'
Response:
{
  "quotes": [
    {
      "protocol": "thorchain",
      "data": {
        "expected_amount_out": "9850000000",
        "total_swap_seconds": 180,
        "fees": [...],
        "route": ["BTC.BTC", "THOR.RUNE", "ETH.USDC-0xA0b86991..."],
        "flags": ["OPTIMAL", "CHEAPEST"]
      }
    }
  ],
  "timestamp": "2026-01-15T12:34:56.789Z",
  "quote_id": "01936b4a-7c8e-7890-abcd-ef1234567890"
}
Save the quote_id - you’ll need it for all subsequent steps. Quote IDs expire after 15 minutes.

Step 2: Generate Deposit Transaction

Create an unsigned transaction using the quote ID and your selected protocol.
curl -X POST 'https://api.leodex.io/leokit/deposit' \
  -H 'Api-Key: your_api_key_here' \
  -H 'Content-Type: application/json' \
  -d '{
    "quote_id": "01936b4a-7c8e-7890-abcd-ef1234567890",
    "selected_protocol": "thorchain"
  }'
Response:
{
  "type": "UTXO",
  "protocol": "thorchain",
  "quote_id": "01936b4a-7c8e-7890-abcd-ef1234567890",
  "details": {
    "from_address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
    "to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "from_asset": "BTC.BTC",
    "to_asset": "ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    "amount": "100000000",
    "decimals": 8,
    "memo": "=:ETH.USDC-0xA0b86991:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb:985000000"
  },
  "unsigned_transaction": {
    "psbt_hex": "cHNidP8BAH0CAAAAAR...",
    "selected_utxos": [...],
    "chain": "BTC"
  }
}
For Bitcoin transactions, LeoKit returns a PSBT (Partially Signed Bitcoin Transaction) that you’ll sign in the next step.

Step 3: Sign & Broadcast (Client-Side)

Sign the transaction with your wallet and broadcast it to the Bitcoin network.
// Using bitcoinjs-lib
import * as bitcoin from "bitcoinjs-lib";

const psbt = bitcoin.Psbt.fromHex(depositData.unsigned_transaction.psbt_hex);

// Sign with wallet (example with private key)
psbt.signAllInputs(keyPair);
psbt.finalizeAllInputs();

const txHex = psbt.extractTransaction().toHex();

// Broadcast to Bitcoin network
const txHash = await broadcastBitcoinTransaction(txHex);
Never expose your private keys. This example is for educational purposes. Use secure wallet libraries in production.

Step 4: Save Transaction Hash

Register the transaction hash with LeoKit to enable status tracking.
curl -X POST 'https://api.leodex.io/leokit/save-transaction' \
  -H 'Api-Key: your_api_key_here' \
  -H 'Content-Type: application/json' \
  -d '{
    "quote_id": "01936b4a-7c8e-7890-abcd-ef1234567890",
    "tx_hash": "a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234567890"
  }'

Step 5: Track Status

Poll the status endpoint to monitor your swap progress.
curl -X POST 'https://api.leodex.io/leokit/status' \
  -H 'Api-Key: your_api_key_here' \
  -H 'Content-Type: application/json' \
  -d '{
    "quote_id": "01936b4a-7c8e-7890-abcd-ef1234567890"
  }'

Status Values

StatusDescription
pendingTransaction broadcasted, waiting for confirmation
observedTransaction confirmed on source chain
inbound_observedProtocol detected the deposit
swap_in_progressCross-chain swap executing
outbound_observedTokens being sent to destination
completedSwap successful, tokens received
failedSwap failed (reverted or error)

Best Practices

Use appropriate polling intervals - Poll every 10-15 seconds. Faster polling won’t speed up the swap.
Save quote_id persistently - Store it in your database to track swaps even after page refreshes.
Handle timeouts gracefully - Cross-chain swaps can take 5-10 minutes. Show progress indicators to users.
Test with small amounts first - Always test new integrations with minimal amounts on testnet/mainnet.

Next Steps