Package Exports
- sbtc
- sbtc/dist/esm/index.js
- sbtc/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (sbtc) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
sbtc 0.3.x (mainnet-pre-release)
A helper package for interacting with sBTC from JavaScript/TypeScript.
Installation
npm install sbtcOverview
sBTC
Architecture
- 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.
Withdraw Flow
Coming soon
sbtc Package
The package exports high-level functions for building addresses and transactions.
With wallets:
buildSbtcDepositAddress— build a deposit address and metadata (enough for most use-cases)buildSbtcDepositTx— build a deposit transaction and metadata
Without wallets:
sbtcDepositHelper— create a fully-formed deposit transaction (assuming an address with spendable bitcoin UTXOs)
HTTP Clients:
Additionally, there are three API helpers, which make it easier to get all the data needed to create the above transactions:
SbtcApiClientMainnet— a client for communicating with the sBTC deployment on MainnetSbtcApiClientTestnet— a client for communicating with the sBTC deployment on TestnetSbtcApiClientDevenv— 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
buildSbtcDepositAddress
Build a deposit address and metadata to be used with any wallet.
import { buildSbtcDepositAddress, SbtcApiClientTestnet } from 'sbtc';
const client = new SbtcApiClientTestnet();
// 1. BUILD THE DEPOSIT ADDRESS AND METADATA
const deposit = buildSbtcDepositAddress({
stacksAddress: TARGET_STX_ADDRESS, // the address to send/mint the sBTC to
signersPublicKey: await client.fetchSignersPublicKey(), // the aggregated public key of the signers
reclaimPublicKey: YOUR_RECLAIM_PUBLIC_KEY, // public key for reclaiming failed deposits
// OPTIONAL DEFAULTS
// maxSignerFee: 80_000, // optional: fee to pay for the deposit transaction (taken from the signers from the sats)
// reclaimLockTime: 950, // optional: lock time for the reclaim script
// network: MAINNET, // 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 by the signers as a fee
});
const transaction = await client.fetchTxHex(txid);
// 3. NOTIFY THE SIGNERS
await client.notifySbtc({ transaction, ...deposit });buildSbtcDepositTx
Like buildSbtcDepositAddress, but also builds a deposit transaction.
Note: This function ONLY builds the basic format of the deposit transaction. You still need to add inputs (and potential change outputs) yourself.
import { buildSbtcDepositTx } from 'sbtc';
// 1. BUILD THE DEPOSIT TRANSACTION AND METADATA
const deposit = buildSbtcDepositTx({
amountSats: DEPOSIT_AMOUNT, // the amount in sats/sBTC to deposit; <=maxSignerFee is taken from this amount
stacksAddress: TARGET_STX_ADDRESS, // the address to send/mint the sBTC to
signersPublicKey: await client.fetchSignersPublicKey(), // the aggregated public key of the signers
reclaimPublicKey: YOUR_RECLAIM_PUBLIC_KEY, // public key for reclaiming failed deposits
// OPTIONAL DEFAULTS
// maxSignerFee: 80_000, // optional: fee to pay for the deposit transaction (taken from the signers from the sats)
// reclaimLockTime: 950, // optional: lock time for the reclaim script
// network: MAINNET, // optional: which bitcoin network to use
});
// `deposit.transaction` has one output, which is the combined taproot of the deposit and reclaim scripts
// 2. SIGN THE TRANSACTION
deposit.transaction.sign(YOUR_BTC_PRIVATE_KEY);
deposit.transaction.finalize();
// 2. OR SIGN VIA EXTERNAL WALLET
const psbtBytes = deposit.transaction.toPSBT();
// 3. BROADCAST THE TRANSACTION
const txid = await client.broadcastTx(deposit.transaction);
// 4. NOTIFY THE SIGNERS
await client.notifySbtc(deposit);sbtcDepositHelper
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 sBTC
amountSats: 5_000_000, // (maximum) amount of sBTC to deposit
bitcoinChangeAddress: YOUR_BTC_ADDRESS, // where to send change
reclaimPublicKey: YOUR_RECLAIM_PUBLIC_KEY, // public key for reclaiming failed deposits
signersPublicKey: await client.fetchSignersPublicKey(), // the aggregated public key of the signers
feeRate: await client.fetchFeeRate('medium'),
utxos: await client.fetchUtxos(YOUR_BTC_ADDRESS),
// OPTIONAL DEFAULTS
// network: MAINNET,
// maxSignerFee: 80_000,
// reclaimLockTime: 950,
// paymentPublicKey: YOUR_PAYMENT_PUBLIC_KEY, // only used for default utxoToSpendable.sh implementation
});
// 2. SIGN THE TRANSACTION
deposit.transaction.sign(YOUR_BTC_PRIVATE_KEY);
deposit.transaction.finalize();
// 2. OR SIGN VIA EXTERNAL WALLET
const psbtBytes = deposit.transaction.toPSBT();
// 3. BROADCAST TRANSACTION
const txid = await client.broadcastTx(deposit.transaction);
console.log('txid', txid);
// 4. NOTIFY THE SIGNERS
const res = await client.notifySbtc(deposit);
console.log('res', res.status, res.statusMessage);SbtcApiClientMainnet / SbtcApiClientTestnet / SbtcApiClientDevenv
import { SbtcApiClientMainnet, SbtcApiClientTestnet, SbtcApiClientDevenv } from 'sbtc';
const client = new SbtcApiClientMainnet();
// const client = new SbtcApiClientTestnet();
// const client = new SbtcApiClientDevenv();
// Bitcoin-related methods
const pub = await client.fetchSignersPublicKey(); // fetches the aggregated public key of the signers
const address = await client.fetchSignersAddress(); // fetches the p2tr address of the aggregated public key of the signers
const feeRate = await client.fetchFeeRate('low'); // or 'medium', 'high'
const unspents = await client.fetchUtxos(BTC_ADDRESS);
const hex = await client.fetchTxHex(TXID);
const btcBalance = await client.fetchBalance(BTC_ADDRESS); // in satoshis
// Transaction-related methods
await client.broadcastTx(DEPOSIT_BTC_TX); // broadcast a deposit BTC transaction
await client.notifySbtc(DEPOSIT_BTC_TX); // notify the sBTC API about the deposit
const deposit = await client.fetchDeposit(TXID); // fetch deposit status by txid
const deposit2 = await client.fetchDeposit({ txid: TXID, vout: 0 }); // fetch deposit status by txid and output index
// Stacks-related methods
const sbtcBalance = await client.fetchSbtcBalance(STX_ADDRESS); // fetch the sBTC balance of a Stacks address
const result = await client.fetchCallReadOnly({
contractAddress: CONTRACT_ADDRESS,
functionName: FUNCTION_NAME,
args: [], // optional clarity values
sender: SENDER_ADDRESS, // optional, defaults to zero address
});API
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 |
950 |
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 |
— |
SbtcApiClientMainnet / SbtcApiClientTestnet / SbtcApiClientDevenv
| Parameter | Description | Type | Default |
|---|---|---|---|
sbtcContract |
The multisig address of the initial sBTC contract | string |
Mainnet: SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4 |
Testnet: SNGWPN3XDAQE673MXYXF81016M50NHF5X5PWWM70 |
|||
Devenv: SN3R84XZYA63QS28932XQF3G1J8R9PC3W76P9CSQS |
|||
sbtcApiUrl |
The base URL of the sBTC API (Emily) | string |
Mainnet: https://sbtc-emily.com |
Testnet: https://beta.sbtc-emily.com |
|||
Devenv: http://localhost:3031 |
|||
btcApiUrl |
The base URL of the Bitcoin mempool/electrs API | string |
Mainnet: https://mempool.space/api |
Testnet: https://beta.sbtc-mempool.tech/api/proxy |
|||
Devenv: http://localhost:3010/api/proxy |
|||
stxApiUrl |
The base URL of the Stacks API | string |
Mainnet: https://api.hiro.so |
Testnet: https://api.testnet.hiro.so |
|||
Devenv: http://localhost:3999 |