Skip to main content
Send Bitcoin to any on-chain Bitcoin address.
Withdraw to L1

Withdrawal Flow

The complete process for sending Bitcoin to an on-chain Bitcoin address:
1

Get Fee Quote

Request a fee quote for your withdrawal with different speed options.
const feeQuote = await wallet.getWithdrawalFeeQuote({
  amountSats: 50000,
  withdrawalAddress: "bc1p..." // Your Bitcoin address
});
console.log("Fee quote:", feeQuote);
2

Initiate Withdrawal

Start the withdrawal process using the fee quote.
// Calculate fee based on exit speed
import { ExitSpeed } from "@buildonspark/spark-sdk";

if (!feeQuote) throw new Error("No fee quote available");

const exitSpeed = ExitSpeed.FAST; // or ExitSpeed.MEDIUM, ExitSpeed.SLOW
let feeAmountSats: number;
switch (exitSpeed) {
  case ExitSpeed.FAST:
    feeAmountSats = (feeQuote.l1BroadcastFeeFast?.originalValue || 0) +
                    (feeQuote.userFeeFast?.originalValue || 0);
    break;
  case ExitSpeed.MEDIUM:
    feeAmountSats = (feeQuote.l1BroadcastFeeMedium?.originalValue || 0) +
                    (feeQuote.userFeeMedium?.originalValue || 0);
    break;
  case ExitSpeed.SLOW:
    feeAmountSats = (feeQuote.l1BroadcastFeeSlow?.originalValue || 0) +
                    (feeQuote.userFeeSlow?.originalValue || 0);
    break;
}

const withdrawal = await wallet.withdraw({
  onchainAddress: "bc1p...", // Your Bitcoin address
  exitSpeed,
  amountSats: 50000,
  feeQuoteId: feeQuote.id,
  feeAmountSats: feeAmountSats,
  deductFeeFromWithdrawalAmount: false
});
console.log("Withdrawal initiated:", withdrawal);
3

Monitor Status

Track the withdrawal status until completion.
const exitRequest = await wallet.getCoopExitRequest(withdrawal.id);
console.log("Withdrawal status:", exitRequest.status);
console.log("Transaction ID:", exitRequest.coopExitTxid);
If you have custom L1 requirements like fee control, transaction chaining, or specific broadcast behavior, talk to our team. We can expose lower-level controls to fit your infrastructure needs.

Get Withdrawal Fee Quote

Request fee quotes for different withdrawal speeds before initiating a withdrawal. getWithdrawalFeeQuote(params) Gets a fee quote for a cooperative exit (on-chain withdrawal). The quote includes options for different speeds and an expiry time and must be passed to withdraw before it expires.
const feeQuote = await wallet.getWithdrawalFeeQuote({
  amountSats: 100000,
  withdrawalAddress: "bc1p5d7rjq7g6rdk2yhzks9smtbqtedr4dekq08ge8ztwac72sfr9rusxg3297"
});

console.log("Fee quote:", feeQuote);
if (!feeQuote) throw new Error("No fee quote available");
console.log("Fast total fee (sats):", feeQuote.userFeeFast.originalValue + feeQuote.l1BroadcastFeeFast.originalValue);
console.log("Medium total fee (sats):", feeQuote.userFeeMedium.originalValue + feeQuote.l1BroadcastFeeMedium.originalValue);
console.log("Slow total fee (sats):", feeQuote.userFeeSlow.originalValue + feeQuote.l1BroadcastFeeSlow.originalValue);

Initiate Withdrawal

Start the withdrawal process using a fee quote. withdraw(params) Initiates a cooperative exit to withdraw Bitcoin from Spark to Layer 1.
// Calculate fee based on exit speed
import { ExitSpeed } from "@buildonspark/spark-sdk";

if (!feeQuote) throw new Error("No fee quote available");

const exitSpeed = ExitSpeed.FAST; // ExitSpeed.FAST, ExitSpeed.MEDIUM, or ExitSpeed.SLOW
let feeAmountSats: number;
switch (exitSpeed) {
  case ExitSpeed.FAST:
    feeAmountSats = (feeQuote.l1BroadcastFeeFast?.originalValue || 0) +
                    (feeQuote.userFeeFast?.originalValue || 0);
    break;
  case ExitSpeed.MEDIUM:
    feeAmountSats = (feeQuote.l1BroadcastFeeMedium?.originalValue || 0) +
                    (feeQuote.userFeeMedium?.originalValue || 0);
    break;
  case ExitSpeed.SLOW:
    feeAmountSats = (feeQuote.l1BroadcastFeeSlow?.originalValue || 0) +
                    (feeQuote.userFeeSlow?.originalValue || 0);
    break;
}

const withdrawal = await wallet.withdraw({
  onchainAddress: "bc1p5d7rjq7g6rdk2yhzks9smtbqtedr4dekq08ge8ztwac72sfr9rusxg3297",
  exitSpeed,
  amountSats: 100000,
  feeQuoteId: feeQuote.id,
  feeAmountSats: feeAmountSats,
  deductFeeFromWithdrawalAmount: false
});

if (!withdrawal) throw new Error("Withdrawal failed");

console.log("Withdrawal ID:", withdrawal.id);
console.log("Status:", withdrawal.status);

Monitor Withdrawal Status

Track the status of your withdrawal request. getCoopExitRequest(id) Gets a cooperative exit request by ID to check withdrawal status.
const exitRequest = await wallet.getCoopExitRequest(withdrawalId);
console.log("Withdrawal status:", exitRequest.status);
console.log("Transaction ID:", exitRequest.coopExitTxid);
console.log("Fee:", exitRequest.fee.originalValue, exitRequest.fee.originalUnit);

// Check if withdrawal is complete
if (exitRequest.status === "SUCCEEDED") {
  console.log("Withdrawal completed successfully!");
}

Real-time Withdrawal Monitoring

Monitor withdrawal status by polling getCoopExitRequest().
Withdrawals don’t emit events. Poll the status using getCoopExitRequest() with the withdrawal ID returned from withdraw().
// Check withdrawal status periodically
const checkWithdrawalStatus = async (withdrawalId) => {
  const exitRequest = await wallet.getCoopExitRequest(withdrawalId);
  
  switch (exitRequest.status) {
    case "SUCCEEDED":
      console.log("Withdrawal completed!");
      console.log("On-chain txid:", exitRequest.coopExitTxid);
      return true;
    case "FAILED":
      console.log("Withdrawal failed");
      return false;
    default:
      console.log("Withdrawal pending...");
      setTimeout(() => checkWithdrawalStatus(withdrawalId), 30000); // Check again in 30 seconds
      return false;
  }
};