🐙 Brotocol isn't just a bridge—it's the liquidity layer for Bitcoin and the essential connector for Bitcoin DeFi 🐙
BroSDK enables seamless asset transfers between Bitcoin, Stacks, and EVM-compatible blockchains. It supports cross-chain swaps, Runes & BRC20 metaprotocols, and DEX aggregator integrations.
The SDK allows users to interact with Brotocol smart contracts from backend environments, browsers, and mobile apps. It securely handles cross-chain transfers, fee estimation, route planning, and transaction size calculations by using Brotocol's on-chain and off-chain infrastructure.
pnpm install @brotocol-xyz/bro-sdk
The BroSDK
class provides the core functions of the library. To create an instance:
import { BroSDK } from "@brotocol-xyz/bro-sdk"
const sdk = new BroSDK()
For the full API reference, including a full list of available methods and their usage, visit the SDK Documentation.
KnownChainId
Defines types and utility functions for supported networks, ensuring only valid chain IDs are used within the SDK.
Namespace | Mainnet | Testnet |
---|---|---|
Bitcoin | Mainnet |
Testnet |
Runes | Mainnet |
Testnet |
BRC20 | Mainnet |
Testnet |
Stacks | Mainnet |
Testnet |
EVM | Ethereum , BSC , CoreDAO , Bsquared , BOB , Bitlayer , Lorenzo , Merlin , AILayer , Mode , XLayer , Arbitrum , Aurora , Manta , Linea , Base |
Sepolia , BSCTestnet , CoreDAOTestnet , BlifeTestnet , BitboyTestnet , BeraTestnet |
KnownTokenId
Defines types, utility functions, and supported tokens within the SDK.
Namespace | Tokens |
---|---|
Bitcoin | BTC |
Runes | To be confirmed |
BRC20 | To be confirmed |
Stacks | sUSDT , sLUNR , aBTC , ALEX , sSKO , vLiSTX , vLiALEX , vLiaBTC ,uBTC , DB20 , DOG , STX , TRUMP |
EVM | USDT , sUSDT , USDC , aBTC , WTCB , BTCB , cbBTC , uBTC , wuBTC , STX , vLiSTX , ALEX , vLiALEX , LUNR , SKO , DB20 , DOG , TRUMP |
Create an instance of the SDK with default options:
import { BroSDK } from "@brotocol-xyz/bro-sdk"
const broSdk = new BroSDK()
Use case showcasing a transfer of 100 sUSDT
from Stacks to USDT
on Ethereum using BroSDK.
import {
BridgeFromStacksInput,
KnownChainId,
KnownTokenId,
toSDKNumberOrUndefined,
} from '@brotocol-xyz/bro-sdk';
import { serializeCVBytes, makeContractCall, broadcastTransaction } from '@stacks/transactions';
// Retrieve bridge information
const bridgeInfo = await broSdk.bridgeInfoFromStacks({
fromChain: KnownChainId.Stacks.Mainnet,
toChain: KnownChainId.EVM.Ethereum,
fromToken: KnownTokenId.Stacks.sUSDT,
toToken: KnownTokenId.EVM.USDT,
amount: toSDKNumberOrUndefined(100),
});
console.log("Bridge Info:", bridgeInfo);
// Define bridge operation input
const bridgeFromStacksInput: BridgeFromStacksInput = {
fromChain: KnownChainId.Stacks.Mainnet,
toChain: KnownChainId.EVM.Ethereum,
fromToken: KnownTokenId.Stacks.sUSDT,
toToken: KnownTokenId.EVM.USDT,
fromAddress: /* Sender Stacks principal */,
toAddress: /* Receiver EVM address */,
amount: toSDKNumberOrUndefined(100),
sendTransaction: async (tx: ContractCallOptions) => {
/**
* Implementation for sending transaction on Stacks mainnet.
* Refer to: https://github.com/hirosystems/stacks.js/tree/main/packages/transactions#smart-contract-function-call
*/
const transaction = await makeContractCall({
contractAddress: tx.contractAddress,
contractName: tx.contractName,
functionName: tx.functionName,
functionArgs: tx.functionArgs,
postConditions: /* Add post conditions if necessary */,
validateWithAbi: true,
senderKey: /* Sender private key */,
network: "mainnet",
});
const broadcastResponse = await broadcastTransaction(transaction, "mainnet");
return { txid: broadcastResponse.txid };
},
};
// Example of how a `sendTransaction` argument would look like
const contractCallOptionsExample: ContractCallOptions = {
contractAddress: "SP2XD7417HGPRTREMKF748VNEQPDRR0RMANB7X1NK",
contractName: "cross-peg-out-endpoint-v2-01",
functionName: "transfer-to-unwrap",
functionArgs: [].map(arg => serializeCVBytes(arg)), // Array elements must be Clarity values
};
// Perform the bridge operation
const result = await broSdk.bridgeFromStacks(bridgeFromStacksInput);
console.log("Transaction ID:", result.txid);
Use case showcasing a transfer of 100 USDT
from Ethereum to UsSDT
on Stacks using BroSDK.
import {
BridgeFromEVMInput,
KnownChainId,
KnownTokenId,
toSDKNumberOrUndefined,
} from "@brotocol-xyz/bro-sdk"
import { ethers } from "ethers";
// Retrieve bridge information
const bridgeInfo = await broSdk.bridgeInfoFromEVM({
fromChain: KnownChainId.EVM.Ethereum,
toChain: KnownChainId.Stacks.Mainnet,
fromToken: KnownTokenId.EVM.USDT,
toToken: KnownTokenId.Stacks.sUSDT,
amount: toSDKNumberOrUndefined(100),
});
console.log("Bridge Info:", bridgeInfo);
// Example signer setup using ethers.js
const provider = new ethers.providers.JsonRpcProvider("https://mainnet.someprovider.io/YOUR_PROJECT_ID");
const signer = new ethers.Wallet("SENDER_PRIVATE_KEY", provider);
const bridgeFromEVMInput: BridgeFromEVMInput = {
fromChain: KnownChainId.EVM.Ethereum,
toChain: KnownChainId.Stacks.Mainnet,
fromToken: KnownTokenId.EVM.USDT,
toToken: KnownTokenId.Stacks.sUSDT,
fromAddress: /* Sender EVM address */,
toAddress: /* Receiver Stacks principal */,
amount: toSDKNumberOrUndefined(100),
sendTransaction: async (tx:
{
from: EVMAddress /* Sender EVM address */
to: EVMAddress /* Bridge Endpoint address */
data: Uint8Array /* Transaction data */
recommendedGasLimit: SDKNumber /* Recommended gas limit */
value?: SDKNumber /* Transaction value */
}
): Promise<{ txHash: string }> => {
/**
* Implementation for sending transaction on Ethereum mainnet
* See https://docs.ethers.org/v5/api/contract/contract/ for reference
*/
const txRequest = {
from: tx.from,
to: tx.to,
data: ethers.utils.hexlify(tx.data),
gasLimit: ethers.BigNumber.from(tx.recommendedGasLimit.split(" ")[0]), // Convert string to BigNumber
};
const sentTx = await signer.sendTransaction(txRequest);
const receipt = await sentTx.wait();
return { txHash: receipt.transactionHash };
},
};
// Perform the bridge operation
const result = await broSdk.bridgeFromEVM(bridgeFromEVMInput);
console.log("Transaction ID:", result.txHash);
Use case showcasing a transfer of 1 BTC
from Bitcoin to WBTC
on Ethereum using BroSDK.
import {
BridgeFromBitcoinInput,
KnownChainId,
KnownTokenId,
toSDKNumberOrUndefined,
} from "@brotocol-xyz/bro-sdk"
/* Use your preferred Bitcoin libs here */
import { Psbt, networks, Transaction, script } from "bitcoinjs-lib";
import { ECPairFactory } from "ecpair";
import * as tinysecp from "tiny-secp256k1";
import axios from "axios";
// Retrieve bridge information
const bridgeInfo = await broSdk.bridgeInfoFromBitcoin({
fromChain: KnownChainId.Bitcoin.Mainnet,
toChain: KnownChainId.EVM.Ethereum,
fromToken: KnownTokenId.Bitcoin.BTC,
toToken: KnownTokenId.EVM.WBTC,
amount: toSDKNumberOrUndefined(1),
});
console.log("Bridge Info:", bridgeInfo)
const bridgeFromBitcoinInput: BridgeFromBitcoinInput = {
fromChain: KnownChainId.Bitcoin.Mainnet,
fromToken: KnownTokenId.Bitcoin.BTC,
toChain: KnownChainId.EVM.Ethereum,
toToken: KnownTokenId.EVM.WBTC,
fromAddress: /* Sender Bitcoin address */,
toAddress: /* Receiver EVM address */,
amount: toSDKNumberOrUndefined(1),
networkFeeRate: 10n,
reselectSpendableUTXOs: async (
satsToSend: bigint,
pinnedUTXOs: UTXOSpendable[],
lastTimeSelectedUTXOs: UTXOSpendable[]
): Promise<UTXOSpendable[]> => {
/**
* Implementation for selecting spendable UTXOs from the wallet
* This should fetch available UTXOs from a Bitcoin node or explorer API
*/
return [];
},
signPsbt: async (tx: { psbt: Uint8Array; signInputs: number[] }): Promise<{ psbt: Uint8Array }> => {
/**
* Implementation for signing a Bitcoin PSBT (Partially Signed Bitcoin Transaction)
* See https://github.com/bitcoinjs/bitcoinjs-lib for reference
*/
let psbt = Psbt.fromBuffer(tx.psbt);
tx.signInputs.forEach((index) => {
psbt.signInput(index, keyPair);
});
psbt.finalizeAllInputs();
return { psbt: psbt.toBuffer() };
},
sendTransaction: async (tx: { hex: string }): Promise<{ txid: string }> => {
/**
* Implementation for broadcasting a Bitcoin transaction with Axios
* Using a Bitcoin node or explorer API (e.g., Blockstream API)
*/
const response = await axios.post("https://some-mempool/api/tx", tx.hex, {
headers: { "Content-Type": "text/plain" },
});
return { txid: response.data };
},
};
// Perform the bridge operation
const result = await broSdk.bridgeFromBitcoin(bridgeFromBitcoinInput);
console.log("Transaction ID:", result.txid);