## Relay Bitcoin Integration Guide

Relay supports deposits to and withdrawals from Bitcoin across any supported chain. This guide covers the Bitcoin-specific parameters, PSBT signing, balance calculation, and API/SDK usage required for integration.

## Required Information

Bitcoin transactions differ from EVM chains in several ways. The sections below highlight the Bitcoin-specific parameters and requirements for your integration.

Bitcoin addresses are case-sensitive.

### SDK Properties

| Action                | Parameter     | Input                      | Description                             |
|-----------------------|---------------|----------------------------|-----------------------------------------|
| Deposit to Bitcoin    | `toChainId`   | `8253038`                  | Chain ID assigned to Bitcoin in Relay. |
|                       | `recipient`    | User’s Bitcoin Address      | Valid Bitcoin address.                   |
|                       | `toCurrency`   | `bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8` | Native BTC identifier.                 |
| Withdraw from Bitcoin | `chainId`     | `8253038`                  | Chain ID assigned to Bitcoin in Relay. |
|                       | `currency`     | `bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8` | Native BTC identifier.                 |

### Bitcoin Currency

| Token | Currency Address                           | Symbol | Decimals |
|-------|-------------------------------------------|--------|----------|
| BTC   | `bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8` | BTC    | 8        |

## PSBT Signing

Bitcoin transactions use **Partially Signed Bitcoin Transactions (PSBT)** for signing. When withdrawing from Bitcoin, the quote response returns a PSBT instead of standard EVM calldata. The 
[Bitcoin wallet adapter](https://docs.relay.link/references/relay-kit/sdk/adapters#what-adapters-are-available-out-of-the-box) handles PSBT parsing, finalization, and broadcasting. Provide a `signPsbt` callback that signs the PSBT and returns the signed result in base64 format.

## UTXOs and Bitcoin Balance

Unlike EVM chains that track account balances directly, Bitcoin uses a **UTXO** **(Unspent Transaction Output)** model. Each address balance equals the sum of unspent outputs it has received minus outputs it has spent. To calculate a Bitcoin address balance, query the 
[mempool.space API](https://mempool.space/docs/api/rest#get-address) and compute the difference between funded and spent transaction outputs:

```javascript
async function getBitcoinBalance(address: string) {
    const response = await fetch(
        `https://mempool.space/api/address/${address}`
    );
    const data = await response.json();

const fundedTxo = data.chain_stats.funded_txo_sum;
    const spentTxo = data.chain_stats.spent_txo_sum;
    const pendingSpent = data.mempool_stats.spent_txo_sum;

// Balance in satoshis
    const balance =
        BigInt(fundedTxo) - BigInt(spentTxo) - BigInt(pendingSpent);

return {
        balance, // Confirmed balance in satoshis
        pendingBalance: BigInt(pendingSpent), // Pending outgoing
    };
}
```

Balance values are returned in **satoshis** (1 BTC = 100,000,000 satoshis).

## API

### Params

| Action                | Parameter     | Input                      | Description                             |
|-----------------------|---------------|----------------------------|-----------------------------------------|
| Deposit to Bitcoin    | `recipient`    | User’s Bitcoin Address      | Valid Bitcoin address.                   |
|                       | `destinationChainId` | `8253038`                            | Chain ID assigned to Bitcoin in Relay. |
|                       | `destinationCurrency` | `bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8` | Native BTC identifier.                 |
| Withdraw from Bitcoin | `user`        | User’s Bitcoin Address      | Valid Bitcoin address.                   |
|                       | `originChainId`  | `8253038`                          | Chain ID assigned to Bitcoin in Relay. |
|                       | `originCurrency` | `bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8` | Native BTC identifier.                 |

### Execution

Bitcoin uses the standard Relay API flow. Review the [execution steps](https://docs.relay.link/references/api/api_core_concepts/step-execution) documentation, then use the [Get Quote](https://docs.relay.link/references/api/get-quote-v2) endpoint.

For Bitcoin origin deposits, the request transitions to `pending` as soon as the deposit appears in the Bitcoin mempool — earlier than the equivalent transition on EVM origins. Block-confirmation policy still governs the move to `submitted`/`success`.

### Example: Withdraw from Bitcoin to Base

Request:

```bash
curl -X POST "https://api.relay.link/quote/v2" \
  -H "Content-Type: application/json" \
  -d '{\
    "user": "bc1q4vxn43l44h30nkluqfxd9eckf45vr2awz38lwa",\
    "originChainId": 8253038,\
    "originCurrency": "bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8",\
    "destinationChainId": 8453,\
    "destinationCurrency": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",\
    "recipient": "0x03508bb71268bba25ecacc8f620e01866650532c",\
    "tradeType": "EXACT_INPUT",\
    "amount": "100000"\
  }'\
```

Response:

```json
{
  "steps": [
    {
      "id": "deposit",
      "action": "Confirm transaction in your wallet",
      "description": "Depositing funds to the relayer to execute the swap for USDC",
      "kind": "transaction",
      "requestId": "0x90399ed9112ee951b6312fae28196e02384f6fd26c5d40a3d51bf2b0fbb1ae80",
      "depositAddress": "",
      "items": [
        {
          "status": "incomplete",
          "data": {
            "psbt": "70736274ff0100fdb4010200000007d5..."
          },
          "check": {
            "endpoint": "/intents/status/v3?requestId=0x90399ed9112ee951b6312fae28196e02384f6fd26c5d40a3d51bf2b0fbb1ae80",
            "method": "GET"
          }
        }
      ]
    }
  ],
  "fees": {
    "gas": {
      "currency": {
        "chainId": 8253038,
        "address": "bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8",
        "symbol": "BTC",
        "name": "Bitcoin",
        "decimals": 8,
        "metadata": {
          "logoURI": "https://assets.relay.link/icons/currencies/btc.png",
          "verified": true
        }
      },
      "amount": "3639",
      "amountFormatted": "0.00003639",
      "amountUsd": "2.654085",
      "minimumAmount": "3639"
    },
    "relayer": {
      "currency": {
        "chainId": 8253038,
        "address": "bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8",
        "symbol": "BTC",
        "name": "Bitcoin",
        "decimals": 8,
        "metadata": {
          "logoURI": "https://assets.relay.link/icons/currencies/btc.png",
          "verified": true
        }
      },
      "amount": "660",
      "amountFormatted": "0.0000066",
      "amountUsd": "0.481367",
      "minimumAmount": "660"
    }
  },
  "details": {
    "operation": "swap",
    "sender": "bc1q4vxn43l44h30nkluqfxd9eckf45vr2awz38lwa",
    "recipient": "0x03508bb71268bba25ecacc8f620e01866650532c",
    "currencyIn": {
      "currency": {
        "chainId": 8253038,
        "address": "bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8",
        "symbol": "BTC",
        "name": "Bitcoin",
        "decimals": 8,
        "metadata": {
          "logoURI": "https://assets.relay.link/icons/currencies/btc.png",
          "verified": true
        }
      },
      "amount": "100000",
      "amountFormatted": "0.001",
      "amountUsd": "72.934456",
      "minimumAmount": "100000"
    },
    "currencyOut": {
      "currency": {
        "chainId": 8453,
        "address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
        "symbol": "USDC",
        "name": "USD Coin",
        "decimals": 6,
        "metadata": {
          "logoURI": "https://coin-images.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
          "verified": true
        }
      },
      "amount": "72469395",
      "amountFormatted": "72.469395",
      "amountUsd": "72.446929",
      "minimumAmount": "71020007"
    },
    "timeEstimate": 4
  }
}
```

### Example: Deposit to Bitcoin from Base

Request:

```bash
curl -X POST "https://api.relay.link/quote/v2" \
  -H "Content-Type: application/json" \
  -d '{\
    "user": "0x03508bb71268bba25ecacc8f620e01866650532c",\
    "originChainId": 8453,\
    "originCurrency": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",\
    "destinationChainId": 8253038,\
    "destinationCurrency": "bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8",\
    "recipient": "bc1q4vxn43l44h30nkluqfxd9eckf45vr2awz38lwa",\
    "tradeType": "EXACT_INPUT",\
    "amount": "10000000"\
  }'\
```

Response:

```json
{
  "steps": [
    {
      "id": "approve",
      "action": "Confirm transaction in your wallet",
      "description": "Sign an approval for USDC",
      "kind": "transaction",
      "requestId": "0xd24628d1b4707b389e0298ecf86733c9f524599a2e28bdb1458f27f58cc4d6ca",
      "items": [
        {
          "status": "incomplete",
          "data": {
            "from": "0x03508bb71268bba25ecacc8f620e01866650532c",
            "to": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
            "chainId": 8453
          }
        }
      ]
    },
    {
      "id": "deposit",
      "action": "Confirm transaction in your wallet",
      "description": "Depositing funds to the relayer to execute the swap for BTC",
      "kind": "transaction",
      "requestId": "0xd24628d1b4707b389e0298ecf86733c9f524599a2e28bdb1458f27f58cc4d6ca",
      "depositAddress": "",
      "items": [
        {
          "status": "incomplete",
          "data": {
            "from": "0x03508bb71268bba25ecacc8f620e01866650532c",
            "to": "0x4cd00e387622c35bddb9b4c962c136462338bc31",
            "chainId": 8453
          },
          "check": {
            "endpoint": "/intents/status/v3?requestId=0xd24628d1b4707b389e0298ecf86733c9f524599a2e28bdb1458f27f58cc4d6ca",
            "method": "GET"
          }
        }
      ]
    }
  ],
  "fees": {
    "gas": {
      "currency": {
        "chainId": 8453,
        "address": "0x0000000000000000000000000000000000000000",
        "symbol": "ETH",
        "name": "Ether",
        "decimals": 18,
        "metadata": {
          "logoURI": "https://assets.relay.link/icons/1/light.png",
          "verified": true
        }
      },
      "amount": "238331268682",
      "amountFormatted": "0.000000238331268682",
      "amountUsd": "0.000510",
      "minimumAmount": "238331268682"
    },
    "relayer": {
      "currency": {
        "chainId": 8453,
        "address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
        "symbol": "USDC",
        "name": "USD Coin",
        "decimals": 6,
        "metadata": {
          "logoURI": "https://coin-images.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
          "verified": true
        }
      },
      "amount": "678569",
      "amountFormatted": "0.678569",
      "amountUsd": "0.678359",
      "minimumAmount": "678569"
    }
  },
  "details": {
    "operation": "swap",
    "sender": "0x03508bb71268bba25ecacc8f620e01866650532c",
    "recipient": "bc1q4vxn43l44h30nkluqfxd9eckf45vr2awz38lwa",
    "currencyIn": {
      "currency": {
        "chainId": 8453,
        "address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
        "symbol": "USDC",
        "name": "USD Coin",
        "decimals": 6,
        "metadata": {
          "logoURI": "https://coin-images.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
          "verified": true
        }
      },
      "amount": "10000000",
      "amountFormatted": "10.0",
      "amountUsd": "9.996900",
      "minimumAmount": "10000000"
    },
    "currencyOut": {
      "currency": {
        "chainId": 8253038,
        "address": "bc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqmql8k8",
        "symbol": "BTC",
        "name": "Bitcoin",
        "decimals": 8,
        "metadata": {
          "logoURI": "https://assets.relay.link/icons/currencies/btc.png",
          "verified": true
        }
      },
      "amount": "12759",
      "amountFormatted": "0.00012759",
      "amountUsd": "9.305707",
      "minimumAmount": "12504"
    },
    "timeEstimate": 158
  }
}
```

### SDK

To use the SDK with Bitcoin, install and configure the [Bitcoin wallet adapter](https://docs.relay.link/references/relay-kit/sdk/adapters#what-adapters-are-available-out-of-the-box). The adapter handles PSBT signing and transaction broadcasting.

```bash
npm install @relayprotocol/relay-bitcoin-wallet-adapter
```

For implementation details and code samples, see the [Adapters documentation](https://docs.relay.link/references/relay-kit/sdk/adapters).

### Deposit Addresses (Optional)

Relay also supports the [deposit address flow](https://docs.relay.link/features/deposit-addresses), which allows bridging without wallet connection or PSBT signing. When using deposit addresses, there are additional considerations:

### Block Confirmations

When using deposit addresses, Relay waits for **1 block confirmation** before processing in the typical case. For high-value deposits — those whose origin amount exceeds a per-currency threshold — Relay waits for **2 block confirmations** instead, to reduce the risk of a reorg invalidating the fill. Bitcoin’s block time averages ~10 minutes but varies significantly; blocks can arrive within minutes of each other or take 30-50 minutes. The `timeEstimate` field on the quote response reflects whichever rule applies — expect roughly one block of wait time for standard deposits and roughly two for high-value ones.

When polling for deposit address transactions, allow for at least 2-3 blocks worth of time (3-4 for high-value deposits) before considering a transaction stalled. You can monitor block times at [mempool.space](https://mempool.space/).

### Manually Reindexing a Bitcoin Deposit

If a Bitcoin deposit is not picked up by automatic indexing, you can trigger a manual reindex by calling [`POST /transactions/index`](https://docs.relay.link/references/api/transactions-index) with `chainId: 8253038` and the Bitcoin `txHash`. Relay verifies the transaction is included in a block before reindexing — calls for transactions that have not yet been confirmed in a block return `404`. See the [Transaction Indexing guide](https://docs.relay.link/references/api/api_guides/transaction-indexing) for the full request shape.

### Quote Requirements for Deposit Addresses

When using `useDepositAddress: true` with Bitcoin as origin:

- The `user` address must be a valid Bitcoin address
- The `user` address balance must exceed the quoted amount (otherwise returns `INSUFFICIENT_FUNDS`)
- For indicative quotes, use a known high-balance address (“whale address”). The actual deposit can originate from any address.
