0.3.2 • Published 4 months ago

sbtc v0.3.2

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

sbtc 0.3.x (mainnet-pre-release)

A helper package for interacting with sBTC from JavaScript/TypeScript.

Installation

npm install sbtc

Overview

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:

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:

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.

VersionPurposeFunctionality
0.1.xDeveloper release (hackathon)
0.2.xRegtest/Testnet releaseDeposit only
0.3.xMainnet pre-releaseDeposit 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

ParameterDescriptionTypeDefault
signersPublicKeySigners public key (aggregated schnorr)string 32 byte hex
amountSatsBitcoin amount denominated in sats (* 10^8)number, bigint
stacksAddressThe deposit recipient Stacks addressstring
bitcoinChangeAddressBitcoin change addressstring
feeRateFee rate in sat/vbytenumber
utxosUTXOs to "fund" the transactionUtxoWithTx[]
reclaimPublicKeyPublic key (schnorr, x-only) for reclaiming failed depositsstring
reclaimLockTimeOptional reclaim lock timenumber950
maxSignerFeeOptional maximum fee to pay to signers for the sBTC mintnumber80_000
networkOptional Bitcoin networkBitcoinNetworkMAINNET
utxoToSpendableOptional function to convert p2wpk and p2sh utxos to spendable inputsFunctionBest effort default implementation to make utxos spendable
paymentPublicKeyOptional payment public key (currently only used for default utxoToSpendable.sh implementation)string hex

SbtcApiClientMainnet / SbtcApiClientTestnet / SbtcApiClientDevenv

ParameterDescriptionTypeDefault
sbtcContractThe multisig address of the initial sBTC contractstringMainnet: SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4
Testnet: SNGWPN3XDAQE673MXYXF81016M50NHF5X5PWWM70
Devenv: SN3R84XZYA63QS28932XQF3G1J8R9PC3W76P9CSQS
sbtcApiUrlThe base URL of the sBTC API (Emily)stringMainnet: https://sbtc-emily.com
Testnet: https://beta.sbtc-emily.com
Devenv: http://localhost:3031
btcApiUrlThe base URL of the Bitcoin mempool/electrs APIstringMainnet: https://mempool.space/api
Testnet: https://beta.sbtc-mempool.tech/api/proxy
Devenv: http://localhost:3010/api/proxy
stxApiUrlThe base URL of the Stacks APIstringMainnet: https://api.hiro.so
Testnet: https://api.testnet.hiro.so
Devenv: http://localhost:3999
0.3.0

7 months ago

0.2.1

7 months ago

0.2.0

7 months ago

0.2.6

7 months ago

0.3.2

4 months ago

0.2.3

7 months ago

0.3.1

6 months ago

0.2.2

7 months ago

0.2.5

7 months ago

0.2.4

7 months ago

0.1.8

2 years ago

0.1.9

2 years ago

0.1.0

2 years ago

0.1.2

2 years ago

0.1.1

2 years ago

0.1.7

2 years ago

0.1.3

2 years ago

0.1.6

2 years ago

0.1.5

2 years ago

0.0.1

2 years ago