WDK logoWDK documentation

Bitcoin Routes with BOB Gateway

Use Bitcoin source or destination routes and distinguish quoting, signing, broadcasting and settlement.

Community modules are developed and maintained independently by third-party contributors.

Tether and the WDK Team do not endorse or assume responsibility for their code, security, or maintenance. Use your own judgment and proceed at your own risk.

Use BOB Gateway to send native BTC into a provider route, or send a supported token to a Bitcoin recipient. Read installation availability, then discover a route for your pair and amount. The BTC export identifies native Bitcoin; use it only when the corresponding chain is bitcoin.

Choose the sending account

DirectionSource account and amountsDestination and refund
BTC to a tokenBitcoin mainnet account exposing getAddress() and signTransaction(). Input is satoshis.recipient belongs to the destination chain; refundAddress is a Bitcoin address.
Token to BTCSend-capable EVM or TRON account, plus any required token approval. Input uses the source token's base units.Set toToken: BTC, toChain: 'bitcoin' and a Bitcoin recipient. The refund address belongs to the source EVM/TRON chain. Output minimum is satoshis.

The Bitcoin source adapter validates standard mainnet deposit addresses; do not configure this flow with a Bitcoin testnet account. An acceptable deposit-address format does not independently verify who controls the address returned by the gateway.

Send BTC into a route

Supply an already initialized Bitcoin mainnet account owned by your application. Choose the destination token and chain from discovery and verify the intended recipient there. The following application function does not create or dispose the account.

confirmOperation({ intent, quote }) is an application callback that displays the source amount, destination token and chain, recipient, refund address, minimum output and fee entries, and resolves to a boolean. recordSubmission({ id, hash, transactions }) durably retains the submitted order and source transaction. Both callbacks must be implemented by the caller.

Submit A Bitcoin Source Route
import { GatewaySwidge, BTC } from '@gobob/wdk-protocol-swidge-gateway'

async function sendBitcoinRoute({
  bitcoinAccount, destinationChain, destinationToken, amountSats,
  recipientAddress, refundAddress, minAmountOut,
  confirmOperation, recordSubmission,
}) {
  const gateway = new GatewaySwidge(bitcoinAccount, { fromChain: 'bitcoin' })
  const intent = Object.freeze({
    fromToken: BTC,
    toToken: destinationToken,
    toChain: destinationChain,
    fromTokenAmount: amountSats,
    recipient: recipientAddress,
    refundAddress,
    minAmountOut,
  })
  const quote = await gateway.quoteSwidge(intent)
  if (!await confirmOperation({ intent, quote })) return null

  const result = await gateway.swidge(intent)
  await recordSubmission({ id: result.id, hash: result.hash, transactions: result.transactions })
  return result
}

Use bigint amounts: amountSats is the BTC input, while minAmountOut is in the destination token's base units. Include enough BTC for the input and the Bitcoin network fee. Set the protocol's optional feeRate in sat/vB when your application chooses the rate; otherwise the account estimates it.

Execution obtains a fresh quote and checks that its BTC input equals the requested input. It creates an order, validates the returned deposit address, and asks the account to sign a transaction. The module sends the signed hex to the gateway's register-tx endpoint, which broadcasts it; it does not call the wallet's Bitcoin broadcaster.

The returned id is the gateway order ID, and hash is the signed source transaction's txid. Preserve both. A successful registration is not Bitcoin confirmation or destination settlement. If recording the result fails, retain the submission details inside the callback; the broadcast is not undone.

Inspect a Bitcoin simulation

simulateSwidge() creates a real, unfunded gateway order and signs a Bitcoin transaction. It is not a quote-only operation. Use quoteSwidge() when you only need an indicative price.

For an existing Bitcoin-bound instance and the same intent shape, inspect only the fields the API returns:

Inspect A Bitcoin Simulation
async function inspectBitcoinSimulation(gateway, intent) {
  const simulation = await gateway.simulateSwidge(intent)
  if (!('onramp' in simulation)) throw new Error('Expected a Bitcoin source route')
  return {
    orderId: simulation.orderId,
    broadcast: simulation.broadcast,
    txid: simulation.onramp.txid,
    valid: simulation.onramp.valid,
    paidToDeposit: simulation.onramp.paidToDeposit,
  }
}

broadcast is false. valid means the signed transaction pays exactly the quoted satoshi amount to the order's deposit address. The raw signed transaction is not returned. The later swidge() call creates its own order and transaction; it does not reuse the simulation's order or txid.

Receive BTC from an EVM or TRON account

Use the source token's contract address as fromToken, BTC as toToken, and bitcoin as toChain. Supply your intended Bitcoin address as recipient and a refund address controlled on the source chain. Follow Execute a Swidge for approval and source submission.

The source account pays its chain's gas or resource costs. A Bitcoin payout is tracked as a destination transaction, separately from the EVM/TRON source hash. Do not interpret the source hash as a Bitcoin transaction hash.

Recover from uncertain registration

An error from register-tx can occur after the gateway has broadcast the signed transaction. The module's registration error identifies the order and signed txid when that registration call fails. Retain those identifiers and check the Bitcoin chain and gateway order before sending again.

Do not infer that the transaction was unsent from an HTTP timeout, missing response or absent local record. Reconcile wallet submissions and spendable outputs when a crash or network failure leaves the outcome unknown. See Track Settlement.

Next Steps


Need Help?

On this page