Need a crash course on Bitcoin layers?
→ READ OUR FREE GUIDE
Need a crash course on Bitcoin layers?
→ READ OUR FREE GUIDE
Need a crash course on Bitcoin layers?
→ READ OUR FREE GUIDE
Need a crash course on Bitcoin layers?
→ READ OUR FREE GUIDE
Need a crash course on Bitcoin layers?
→ READ OUR FREE GUIDE

How to Integrate sBTC Into Your Application

With the launch of sBTC, you may be wondering how to integrate this new 1:1 Bitcoin-backed asset into your app. In this guide, we’ll walk you through it.

Type
Tutorial
Topic(s)
Stacks
Published
December 19, 2024
Author(s)
Developer Advocate
A graphic of sBTC
Contents

Earlier this week, sBTC launched on Stacks. sBTC is a new 1:1 Bitcoin-backed asset designed to unlock Bitcoin DeFi. It’s secured by Bitcoin’s hash power and backed by 100% Bitcoin finality, and its bridge is maintained by 15 trusted institutions, with plans to decentralize over time into an open, rotating signer set.

This is a major milestone for Stacks and something that core devs have been working on for 2 years. And in just 48 hours since launch, over 717 BTC has been bridged into Stacks via sBTC.

As a developer, you may want to tap into that influx of liquidity and enable users to transact with sBTC in your app. The good news? It’s easy.

sBTC Is an Implicit SIP-010 Token

sBTC is a somewhat unique token in the Stacks ecosystem in that it is an “implicit” SIP-010 token. SIP-010 tokens are the fungible token standard in Stacks that use <code-rich-text>impl-trait<code-rich-text> functions to define standards for basic functions like token transfers, fetching the name and supply of a particular token, etc.

In the case of sBTC, it doesn’t use the <code-rich-text>impl-trait<code-rich-text> function and instead actually implements the necessary functions in order to be compliant with the SIP-010 standard. The reason that sBTC uses an implicit implementation is that it leaves the door open in the future to make the sBTC contract one of the boot contracts at the protocol level.

But functionally, sBTC behaves just like a SIP-010 token. For example, an sBTC transfer function looks like this:


(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34))))
	(begin
		(asserts! (or (is-eq tx-sender sender) (is-eq contract-caller sender)) ERR_NOT_OWNER)
		(try! (ft-transfer? sbtc-token amount sender recipient))
		(match memo to-print (print to-print) 0x)
		(ok true)
	)
)

In short, enabling your users to transact with sBTC is just as easy as letting them transact with any other fungible token on Stacks.

Creating sBTC Transactions

If your app already enables SIP-010 token interactions, it’s trivial to add sBTC to your application. You’re going to use the same code that you use to enable users to create a transaction and simply specify the token as sBTC.

If you’re using Stacks.js v7, the code looks like this:


import { STACKS_MAINNET } from "@stacks/network";
import {
  AnchorMode,
  broadcastTransaction,
  Cl,
  makeContractCall,
  PostConditionMode,
} from "@stacks/transactions";

const txOptions = {
  contractAddress: "SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4",
  contractName: "sbtc-token",
  functionName: "transfer",
  functionArgs: [
    Cl.uint(1000), // amount to transfer
    Cl.principal(""), // sender address
    Cl.principal(""), // recipient address
    Cl.none(), // optional memo - passing none
  ],
  senderKey: "",
  validateWithAbi: true,
  network: STACKS_MAINNET,
  postConditions: [],
  postConditionMode: PostConditionMode.Deny,
  anchorMode: AnchorMode.Any,
};

const transaction = await makeContractCall(txOptions);

For more guidance on creating transactions, reference Stacks.js documentation as well as Stacks documentation.

Broadcasting sBTC Transactions

Once you’ve created a sBTC transaction for your app user, you then need to broadcast that transaction on their behalf to the network. To do so, you would use the following snippet:


const broadcastResponse = await broadcastTransaction({
  transaction,
  network: STACKS_MAINNET,
});
const txId = broadcastResponse.txid;
console.log({ txId });

That code will return the <code-rich-text>txid<code-rich-text>, the transaction id, and you can then go to the Stacks Explorer to view it by going to the url:

https://explorer.hiro.so/txid/<insert-your-tx-id>

sBTC Post-Conditions

Stacks also offers a powerful feature called post-conditions that bring additional security to transactions. Post-conditions enable you to specify conditions that must be met in order for a transaction to be processed. For example, an sBTC post-condition could look like “no more than <code-rich-text>n<code-rich-text> sBTC will be transferred from the user’s address or else the transaction will abort.”

Post-conditions bring human-readable conditions to transactions on Stacks and help users understand exactly what transactions they’re signing. In the context of an sBTC transaction, there are a few post-conditions you can construct inside your application.

Here is what that code looks like:


import { STACKS_MAINNET } from "@stacks/network";
import {
  AnchorMode,
  broadcastTransaction,
  Cl,
  makeContractCall,
  Pc, // add this `Pc` helper to your imports
  PostConditionMode,
} from "@stacks/transactions";

// Define the sBTC token address and the post condition for your transfer
const sbtcTokenAddress = "SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token";
const postConditions = Pc.principal(sbtcTokenAddress)
  .willSendEq(1000)
  .ft(sbtcTokenAddress, "sbtc-token");

const txOptions = {
  contractAddress: "SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4",
  contractName: "sbtc-token",
  functionName: "transfer",
  functionArgs: [
    Cl.uint(1000), // amount to transfer
    Cl.principal(""), // sender address
    Cl.principal(""), // recipient address
    Cl.none(), // optional memo - passing none
  ],
  senderKey: "",
  validateWithAbi: true,
  network: STACKS_MAINNET,
  postConditions: [postConditions], // now add your post conditions here
  postConditionMode: PostConditionMode.Deny, // update your post condition mode here to rollback the transaction unless the post condition is met
  anchorMode: AnchorMode.Any,
};

const transaction = await makeContractCall(txOptions);

const broadcastResponse = await broadcastTransaction({
  transaction,
  network: STACKS_MAINNET,
});
const txId = broadcastResponse.txid;
console.log({ txId });

In the above snippet, we are using the <code-rich-text>Pc<code-rich-text> helper from the <code-rich-text>@stacks/transactions<code-rich-text> library to help build out our specific post-condition, and a couple different things are happening in the code.

First, we define the <code-rich-text>Pc.principal<code-rich-text> as the sBTC contract. Then we build out a <code-rich-text>ft<code-rich-text> post-condition for the <code-rich-text>sbtc-token<code-rich-text> contract that states we will send <code-rich-text>willSendEq<code-rich-text> exactly the amount of sBTC that we intend to transfer in the transaction that we built.

An <code-rich-text>ft<code-rich-text> post condition is a specific post-condition type for handling fungible token assets.

Next, we update the <code-rich-text>txOptions<code-rich-text> code, which defines the properties of our transaction. By adding the post-condition we just created to our transaction and setting the post-condition mode to <code-rich-text>deny<code-rich-text>, this now says that if the following "rule" that we set to transfer exactly <code-rich-text>100000000<code-rich-text> amount of sBTC (or 1 BTC) does not happen, then roll the transaction back.

To learn more about post-conditions, visit Stacks.js documentation as well as Stacks docs.

Conclusion

That’s it! With just a few steps, your users are now transacting with sBTC in your app. If you need more guidance, be sure to check out Stacks and Hiro documentation, and you can always find us in the Hiro Developer Tools channels on Discord.

Product updates & dev resources straight to your inbox
Your Email is in an invalid format
Checkbox is required.
Thanks for
subscribing.
Oops! Something went wrong while submitting the form.
Copy link
Mailbox
Hiro news & product updates straight to your inbox
Only relevant communications. We promise we won’t spam.

Related stories