sbtc
A JS/TS helper package for interacting with sBTC.
Installation
$npm install sbtc
Architecture
The sBTC protocol operates across multiple layers:
-
Bitcoin: The original funds are sourced from Bitcoin. A depositor sends these funds to a group of signers, which manage a (rotating) multisignature address formatted for sBTC transactions.
-
sBTC API (Emily): This API is responsible for tracking deposits and notifying the signers about pending deposits.
-
Stacks: The network where sBTC is minted. Once the deposit is confirmed, the signers mint the corresponding amount of sBTC to the depositor's specified address on the Stacks network.
Deposit Flow
-
Create Deposit (Bitcoin) Transaction:
- Structure a Bitcoin transaction to send funds to the group of signers.
- Use a specialized format that includes:
- Deposit Script: Identifies which Stacks address the sBTC will be minted to and what the maximum fee (in satoshis) the signers may take in exchange for minting.
- Reclaim Script: Allows the sender to reclaim their funds if the transaction is not processed by the signers.
-
Sign and Broadcast the Transaction:
- Sign the transaction with the sender's private key.
- Broadcast the transaction to the Bitcoin network (Bitcoin Regtest for Stacks Testnet).
-
Notify the sBTC API (Emily):
- Inform the API about the transaction by submitting its details. This step ensures that the signers are aware of the deposit and can track it.
-
Processing by Signers: (no action required)
- The signers retrieve and verify the deposit transaction from the Bitcoin blockchain.
- Once verified, the signers mint the equivalent amount of sBTC on the Stacks network.
-
Receive sBTC (Stacks): (no action required)
- The minted sBTC is sent to the depositor's designated Stacks address, completing the deposit process.
- sBTC is SIP-010 compatible and will show up in Stacks wallets and explorers.
Withdrawal Flow
Coming soon
sBTC Package Functions
The sBTC package exports high-level functions for building addresses and transactions for deposits.
Examples
buildSbtcDepositAddress
Build a deposit address and metadata using buildSbtcDepositAddress
with a wallet provider using sendTransfer
.
import { buildSbtcDepositAddress, SbtcApiClientTestnet } from 'sbtc';const client = new SbtcApiClientTestnet();// 1. BUILD THE DEPOSIT ADDRESS AND METADATAconst deposit = buildSbtcDepositAddress({stacksAddress: TARGET_STX_ADDRESS,signersPublicKey: await client.fetchSignersPublicKey(),// OPTIONAL DEFAULTS// maxSignerFee: 80_000, // optional: fee to pay for the deposit transaction (taken from the signers from the sats)// reclaimLockTime: 6_000, // optional: lock time for the reclaim script// network: REGTEST, // optional: which bitcoin network to use});// `deposit.address` is the deposit address (send funds here, aka the deposit address as an output)// 2. DEPOSIT USING YOUR FAVORITE WALLET (TYPICALLY ALSO BROADCASTED BY THE WALLET)const txid = await WalletProvider.sendTransfer({recipient: deposit.address,amount: 100_000, // the amount to deposit; <=maxSignerFee is taken from this amount});// 3. NOTIFY THE SIGNERSawait client.notifySbtc({ txid, ...deposit });
buildSbtcDepositTx
The buildSbtcDepositTx
function is similar to buildSbtcDepositAddress
, but instead of returning just a deposit address, it constructs a complete Bitcoin transaction for depositing sBTC.
import { buildSbtcDepositTx } from 'sbtc';// 1. BUILD THE DEPOSIT TRANSACTION AND METADATAconst deposit = buildSbtcDepositTx({amountSats: DEPOSIT_AMOUNT, // the amount in sats/sBTC to deposit; <=maxSignerFee is taken from this amount// same options as `buildSbtcDepositAddress`network,stacksAddress,signersPublicKey,maxSignerFee,reclaimLockTime,});// `deposit.transaction` has one output, which is the combined taproot of the deposit and reclaim scripts// 2. SIGN THE TRANSACTIONdeposit.transaction.sign(YOUR_BTC_PRIVATE_KEY);deposit.transaction.finalize();// 2. OR SIGN VIA EXTERNAL WALLETconst psbtBytes = deposit.transaction.toPSBT();// 3. BROADCAST THE TRANSACTIONconst txid = await client.broadcastTx(deposit.transaction);// 4. NOTIFY THE SIGNERSawait client.notifySbtc(deposit);
sbtcDepositHelper
Create a fully-formed deposit transaction (assuming an address with spendable bitcoin UTXOs)
import { sbtcDepositHelper, SbtcApiClientTestnet } from 'sbtc';const client = new SbtcApiClientTestnet();// 1. BUILD THE DEPOSIT TRANSACTION AND METADATA (GIVEN UTXOS FOR AN ADDRESS)const deposit = await sbtcDepositHelper({stacksAddress: TARGET_STX_ADDRESS, // where to send/mint the sBTCamountSats: 5_000_000, // (maximum) amount of sBTC to depositsignersPublicKey: pub, // the aggregated public key of the signersfeeRate: await client.fetchFeeRate('medium'),utxos: await client.fetchUtxos(YOUR_BTC_ADDRESS),bitcoinChangeAddress: YOUR_BTC_ADDRESS,});// 2. SIGN THE TRANSACTIONdeposit.transaction.sign(YOUR_BTC_PRIVATE_KEY);deposit.transaction.finalize();// 2. OR SIGN VIA EXTERNAL WALLETconst psbtBytes = deposit.transaction.toPSBT();// 3. BROADCAST TRANSACTIONconst txid = await client.broadcastTx(deposit.transaction);console.log('txid', txid);// 4. NOTIFY THE SIGNERSconst res = await client.notifySbtc(deposit);console.log('res', res.status, res.statusMessage);
HTTP Clients
Additionally, there are two API helpers, which make it easier to get all the data needed to create the above transactions:
- SbtcApiClientMainnet — a client for communicating with the different pieces of the sBTC deployment
- SbtcApiClientTestnet — a client for communicating with the different pieces of the sBTC deployment on Testnet
- SbtcApiClientDevenv — a client for developing against a local deployment of sBTC
While the final adjustments are still being made in the pre-release phase, this package may change default URLs and contract addresses on every minor release.
Version | Purpose | Functionality |
---|---|---|
0.1.x | Developer release (hackathon) | |
0.2.x | Regtest/Testnet release | Deposit only |
0.3.x | Mainnet pre-release | Deposit only |
Examples
import { SbtcApiClientMainnet, SbtcApiClientTestnet, SbtcApiClientDevenv } from 'sbtc';const client = new SbtcApiClientMainnet();// const client = new SbtcApiClientTestnet();// const client = new SbtcApiClientDevenv();const pub = await client.fetchSignersPublicKey(); // fetches the aggregated public key of the signersconst address = await client.fetchSignersAddress(); // fetches the p2tr address of the aggregated public key of the signersconst feeRate = await client.fetchFeeRate('low'); // or 'medium', 'high'const unspents = await client.fetchUtxos(BTC_ADDRESS);const hex = await client.fetchTxHex(TXID);await client.broadcastTx(DEPOSIT_BTC_TX); // broadcast a deposit BTC transactionawait client.notifySbtc(DEPOSIT_BTC_TX); // notify the sBTC API about the deposit (otherwise it won't be processed)const sbtcBalance = await client.fetchSbtcBalance(STX_ADDRESS); // fetch the sBTC balance of an Stacks address
API Reference
sbtcDepositHelper
Parameter | Description | Type | Default |
---|---|---|---|
signersPublicKey | Signers public key (aggregated schnorr) | string 32 byte hex | — |
amountSats | Bitcoin amount denominated in sats (* 10^8) | number, bigint | — |
stacksAddress | The deposit recipient Stacks address | string | — |
bitcoinChangeAddress | Bitcoin change address | string | — |
feeRate | Fee rate in sat/vbyte | number | — |
utxos | UTXOs to "fund" the transaction | UtxoWithTx[] | — |
reclaimPublicKey | Public key (schnorr, x-only) for reclaiming failed deposits | string | — |
reclaimLockTime | Optional reclaim lock time | number | 144 |
maxSignerFee | Optional maximum fee to pay to signers for the sBTC mint | number | 80_000 |
network | Optional Bitcoin network | BitcoinNetwork | MAINNET |
utxoToSpendable | Optional function to convert p2wpk and p2sh utxos to spendable inputs | Function | Best effort default implementation to make utxos spendable |
paymentPublicKey | Optional payment public key (currently only used for default utxoToSpendable.sh implementation) | string hex | — |
SbtcApiClient Configuration
Parameter | Description | Type |
---|---|---|
sbtcContract | The multisig address of the initial sBTC contract | string |
sbtcApiUrl | The base URL of the sBTC API (Emily) | string |
btcApiUrl | The base URL of the Bitcoin mempool/electrs API | string |
stxApiUrl | The base URL of the Stacks API | string |