-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #812 from hirosystems/feat/sbtc
add sbtc package docs
- Loading branch information
Showing
1 changed file
with
232 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
--- | ||
title: sbtc | ||
description: A JS/TS helper package for interacting with sBTC. | ||
--- | ||
|
||
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion'; | ||
import { Badge } from '@/components/ui/badge'; | ||
|
||
import { InlineCode } from '@/components/inline-code'; | ||
import { Callout } from "@/components/callout"; | ||
|
||
|
||
## Installation | ||
|
||
```package-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`. | ||
|
||
```ts | ||
import { buildSbtcDepositAddress, SbtcApiClientTestnet } from 'sbtc'; | ||
|
||
const client = new SbtcApiClientTestnet(); | ||
|
||
// 1. BUILD THE DEPOSIT ADDRESS AND METADATA | ||
const 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 SIGNERS | ||
await 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. | ||
|
||
```ts | ||
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 | ||
|
||
// 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 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 | ||
Create a fully-formed deposit transaction (assuming an address with spendable bitcoin UTXOs) | ||
|
||
<Callout>Use this helper function if you are not using a wallet provider</Callout> | ||
|
||
```ts | ||
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 | ||
|
||
signersPublicKey: pub, // the aggregated public key of the signers | ||
|
||
feeRate: await client.fetchFeeRate('medium'), | ||
utxos: await client.fetchUtxos(YOUR_BTC_ADDRESS), | ||
|
||
bitcoinChangeAddress: YOUR_BTC_ADDRESS, | ||
}); | ||
|
||
// 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); | ||
``` | ||
|
||
|
||
## 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 | ||
|
||
```ts | ||
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 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); | ||
|
||
await client.broadcastTx(DEPOSIT_BTC_TX); // broadcast a deposit BTC transaction | ||
await 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 | |