Squashed commit of the following:

commit a9488404b028aaeef5b7ab867a2392a969834fb0
Author: c4605 <bolasblack@gmail.com>
Date:   Mon May 12 23:36:07 2025 +0800

    docs: optimize deps

commit a50d05dca2
Author: sofinico <nicolettisofia1@gmail.com>
Date:   Wed May 7 16:50:43 2025 +0200

    chore: address bro-sdk team review

commit 47fcf33525
Merge: d13a68d 2188881
Author: Sofía <36451685+sofinico@users.noreply.github.com>
Date:   Tue May 6 17:36:14 2025 +0200

    Merge branch 'snapshots/v0.5' into feat/update-v0.5-readme

commit d13a68d4f8
Author: sofinico <nicolettisofia1@gmail.com>
Date:   Tue May 6 17:18:15 2025 +0200

    fix: add temporal patch to prevent `pnpm docs:watch` from failing

commit fef755490f
Author: sofinico <nicolettisofia1@gmail.com>
Date:   Tue May 6 17:15:20 2025 +0200

    chore(docs): fix lint errors and remove unsed packages

commit f8739f7f17
Author: Facundo Lerena <faculerena@gmail.com>
Date:   Wed Apr 30 16:17:59 2025 -0300

    docs: Update dev-instructions file.

commit 78de614697
Author: Facundo Lerena <faculerena@gmail.com>
Date:   Wed Apr 30 16:06:12 2025 -0300

    docs: Update Readme to address example location

commit 4592f31a85
Author: Facundo Lerena <faculerena@gmail.com>
Date:   Wed Apr 30 16:05:45 2025 -0300

    docs: Update `Bitcoin.ts` mock

commit 355bec1a9b
Merge: a3f0e9a 4fe7500
Author: Facundo Lerena <faculerena@gmail.com>
Date:   Wed Apr 30 15:56:15 2025 -0300

    Merge branch 'snapshots/v0.5' of github.com:Brotocol-xyz/bro-sdk into feat/update-v0.5-readme

commit a3f0e9ab41
Author: Facundo Lerena <faculerena@gmail.com>
Date:   Tue Apr 29 16:10:23 2025 -0300

    docs: Remove `docs/readmeCodeSnippets.ts`

commit 23f725bfa9
Author: Facundo Lerena <faculerena@gmail.com>
Date:   Tue Apr 29 16:08:55 2025 -0300

    docs: Moved exampels into code-snippets, adressed comments in #20

commit f44e4382b7
Merge: 9809076 52d6e8c
Author: Facundo Lerena <faculerena@gmail.com>
Date:   Tue Apr 29 11:48:05 2025 -0300

    Merged snapshot

commit 9809076820
Merge: f531587 57f8b37
Author: Sofía <36451685+sofinico@users.noreply.github.com>
Date:   Mon Apr 28 14:47:40 2025 +0200

    Merge pull request #2 from CoinFabrik/feat/update-v0.5-readme-runes-brc20

    Docs: Add code snippets for Runes and BRC20

commit 57f8b3790f
Author: Facundo Lerena <faculerena@gmail.com>
Date:   Fri Apr 25 15:29:48 2025 -0300

    Docs: Update code snippets

    Added Runes and BRC20 bridging examples

commit f5315877ee
Author: sofinico <nicolettisofia1@gmail.com>
Date:   Fri Apr 25 17:47:04 2025 +0200

    docs: address peer-review [wip]

commit 12d8f150e9
Author: sofinico <nicolettisofia1@gmail.com>
Date:   Tue Apr 22 14:07:26 2025 +0200

    docs: update readme basic operations and add table of contents

commit c52e9b834a
Author: sofinico <nicolettisofia1@gmail.com>
Date:   Tue Apr 22 12:28:42 2025 +0200

    docs: update code snippets

    * Replace `getSupportedRoutes` with `getPossibleRoutes`
    * Ajust readmeCodeSnippets.ts to rebrand where applicable
    * Add note explaining `functionArgs` serialization design for bridge from Stacks
    * Add @types/node dev dependency for readmeCodeSnippets.ts

commit fcddf91a43
Author: sofinico <nicolettisofia1@gmail.com>
Date:   Tue Apr 22 11:17:49 2025 +0200

    docs: update readme

    Changes include:

    * Removed static token support table and replaced it with SDK methods that dynamically retrieve supported tokens.
    * Replaced the supported chains table with a  bullet-point list for improved readability.
    * Added a "Basic Operations" section to introcude general usage patterns of the SDK.
    * Improved code snippets, with correspondace to the docs/readmeCodeSnippets.ts file for consistency.

commit 029c19922d
Author: sofinico <nicolettisofia1@gmail.com>
Date:   Tue Apr 22 11:05:19 2025 +0200

    chore: add branded literal type doc

commit 13090aa374
Author: sofinico <nicolettisofia1@gmail.com>
Date:   Tue Apr 22 11:04:53 2025 +0200

    docs: create readme code snippets and dev instructions files

done #20
This commit is contained in:
c4605
2025-05-12 23:36:51 +08:00
parent d17514e8f5
commit f5b572eebd
13 changed files with 1714 additions and 229 deletions

408
README.md
View File

@@ -1,19 +1,39 @@
# BroSDK
`@brotocol-xyz/bro-sdk` is a TypeScript SDK designed to integrate with Brotocol's on-chain and off-chain infrastructure. It is web3 library-agnostic, meaning you can use your preferred library to send and broadcast transactions while the SDK handles the rest.
🐙 **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.
## Table of Contents
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.
- [BroSDK](#brosdk)
- [Table of Contents](#table-of-contents)
- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [Supported Chains](#supported-chains)
- [Mainnet Chains](#mainnet-chains)
- [Testnet Chains](#testnet-chains)
- [Helpers](#helpers)
- [Supported Tokens](#supported-tokens)
- [Retrieve a `TokenId`](#retrieve-a-tokenid)
- [Available Routes](#available-routes)
- [Basic Operations](#basic-operations)
- [`bridgeInfoFrom` methods](#bridgeinfofrom-methods)
- [`estimateBridgeTransactionFrom` methods](#estimatebridgetransactionfrom-methods)
- [`bridgeFrom` methods](#bridgefrom-methods)
- [License](#license)
## Features
- Asset transfers between Bitcoin, Stacks, and EVM-compatible blockchains
- Support for Runes and BRC20 metaprotocols
- Cross-chain swaps and DEX aggregator integrations
- Flexible design, allowing integration with any Bitcoin and web3 library
## Installation
### Prerequisites
- [Node.js](https://nodejs.org/en)
- [pnpm](https://pnpm.io/)
### Install
With [pnpm](https://pnpm.io/):
```bash
pnpm install @brotocol-xyz/bro-sdk
@@ -21,261 +41,203 @@ pnpm install @brotocol-xyz/bro-sdk
## Usage
The [`BroSDK`](./src/BroSDK.ts) class provides the core functions of the library. To create an instance:
The [`BroSDK`](https://releases-latest.xlink-sdk.pages.dev/classes/index.BroSDK) class provides the core functions of the library. To create an instance:
```typescript
```ts
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](https://releases-latest.xlink-sdk.pages.dev).
### Supported Blockchains and Tokens
### Supported Chains
#### [`KnownChainId`](https://releases-latest.xlink-sdk.pages.dev/modules/index.KnownChainId)
#### Mainnet Chains
Defines types and utility functions for supported networks, ensuring only valid chain IDs are used within the SDK.
- **Bitcoin**, **Runes** & **BRC20**
- **Stacks**
- **EVM**: Ethereum, BSC, CoreDAO, Bsquared, BOB, Bitlayer, Lorenzo, Merlin, AILayer, Mode, XLayer, Arbitrum, Aurora, Manta, Linea, Base
#### Testnet Chains
- **Bitcoin**, **Runes** & **BRC20**
- **Stacks**
- **EVM**: Sepolia, BSC Testnet, CoreDAO Testnet, Blife Testnet, Bitboy Testnet, Bera Testnet
#### Helpers
The [`KnownChainId`](https://releases-latest.xlink-sdk.pages.dev/modules/index.KnownChainId) namespace defines types and utility functions for all supported mainnet and testnet networks.
Usage example:
```ts
import { KnownChainId } from "@brotocol-xyz/bro-sdk"
// Bitcoin
const bitcoinChainId = KnownChainId.Bitcoin.Mainnet
const bitcoinTestnetChainId = KnownChainId.Bitcoin.Testnet
// EVM
const ethereumChainId = KnownChainId.EVM.Ethereum
const ethereumTestnetChainId = KnownChainId.EVM.Sepolia
// Utility function usage example
KnownChainId.isEVMTestnetChain(KnownChainId.EVM.Sepolia) // Returns true
KnownChainId.isEVMMainnetChain(KnownChainId.EVM.Sepolia) // Returns false
```
> [!NOTE]
> Runes and BRC20 metaprotocols are treated as distinct chains within the SDK, even though they share Bitcoin as the underlying blockchain.
<!--
Decided to remove the table as it seemed a little bulky for the README. But left it here for future reference.
#### Available chains
| 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` |
| EVM | `Ethereum`, `BSC`, `CoreDAO`, `Bsquared`, `BOB`, `Bitlayer`, `Lorenzo`, `Merlin`, `AILayer`, `Mode`, `XLayer`, `Arbitrum`, `Aurora`, `Manta`, `Linea`, `Base` | `Sepolia`, `BSCTestnet`, `CoreDAOTestnet`, `BlifeTestnet`, `BitboyTestnet`, `BeraTestnet` | -->
#### [`KnownTokenId`](https://releases-latest.xlink-sdk.pages.dev/modules/index.KnownTokenId)
### Supported Tokens
Defines types, utility functions, and supported tokens within the SDK.
Token support is **dynamic**, meaning new tokens can be added without requiring SDK updates. Instead of relying on a static list, the SDK provides methods to fetch supported tokens at runtime. Tokens are represented using the `TokenId` type — this is how the library internally handles and identifies tokens.
| 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` |
Also, check the [`KnownTokenId`](https://releases-latest.xlink-sdk.pages.dev/modules/index.KnownTokenId) namespace to see types and utility functions for all supported tokens.
### Use Cases
#### Retrieve a `TokenId`
Create an instance of the SDK with default options:
```ts
// For BRC20 provide the tick symbol
const brc20Token = await sdk.brc20TickToBRC20Token(
KnownChainId.BRC20.Mainnet,
"alex$",
)
```typescript
import { BroSDK } from "@brotocol-xyz/bro-sdk"
const broSdk = new BroSDK()
// For Runes provide the runes ID
const runesToken = await sdk.runesIdToRunesToken(
KnownChainId.Runes.Mainnet,
"500:20",
)
// For Stacks provide the contract address
const stacksToken = await sdk.stacksAddressToStacksToken(
KnownChainId.Stacks.Mainnet,
{
deployerAddress: "SP2XD7417HGPRTREMKF748VNEQPDRR0RMANB7X1NK",
contractName: "token-abtc",
},
)
// For EVM tokens provide the contract address
const evmToken = await sdk.evmAddressToEVMToken(
KnownChainId.EVM.Ethereum,
"0x31761a152F1e96F966C041291644129144233b0B",
)
```
#### Bridge from Stacks
If a token is **unsupported**, these functions return `Promise<undefined>`.
Use case showcasing a transfer of 100 `sUSDT` from Stacks to `USDT` on Ethereum using BroSDK.
> [!NOTE]
> Some Stacks and EVM tokens are still statically defined in `KnownTokenId.Stacks` and `KnownTokenId.EVM` for backward compatibility, but future additions will also be dynamically handled.
```typescript
import {
BridgeFromStacksInput,
KnownChainId,
KnownTokenId,
toSDKNumberOrUndefined,
} from '@brotocol-xyz/bro-sdk';
import { serializeCVBytes, makeContractCall, broadcastTransaction } from '@stacks/transactions';
> [!WARNING]
>
> `TokenId` values **might change in future updates** (no backward compatibility guaranteed). To ensure validity, always get fresh `TokenId`s at runtime using SDK methods—never cache them or construct them manually.
// Retrieve bridge information
const bridgeInfo = await broSdk.bridgeInfoFromStacks({
### Available Routes
```ts
// Get all Brotocol available routes
const allRoutes = await sdk.getPossibleRoutes()
// Get routes filtered by source chain
const routesBySourceChain = await sdk.getPossibleRoutes({
fromChain: KnownChainId.BRC20.Mainnet,
})
// Get routes filtered by source and target chain
const routesBySourceAndTargetChain = await sdk.getPossibleRoutes({
fromChain: KnownChainId.BRC20.Mainnet,
toChain: KnownChainId.EVM.Ethereum,
})
// Check if a specific token pair is supported for at least one route
const isSupported = await sdk.isSupportedRoute({
fromChain: KnownChainId.BRC20.Mainnet,
toChain: KnownChainId.EVM.Ethereum,
fromToken: brc20Token as KnownTokenId.BRC20Token,
toToken: evmToken as KnownTokenId.EVMToken,
})
// If the token pair is supported, get available routes for that pair
if (isSupported) {
const routesByPair = await sdk.getPossibleRoutes({
fromChain: KnownChainId.BRC20.Mainnet,
toChain: KnownChainId.EVM.Ethereum,
fromToken: brc20Token as KnownTokenId.BRC20Token,
toToken: evmToken as KnownTokenId.EVMToken,
})
}
```
### Basic Operations
The SDK provides three main methods for handling cross-chain asset transfers.
- [`bridgeInfoFrom<Chain>`](#bridgeinfofrom-methods)
- [`estimateBridgeTransactionFrom<Chain>`](#estimatebridgetransactionfrom-methods)
- [`bridgeFrom<Chain>`](#bridgefrom-methods)
#### `bridgeInfoFrom` methods
Retrieve data to perform a cross-chain transfer:
- Validate whether the route is supported (throws an error if not).
- Retrieve Brotocol fee values and the exact amount that will arrive on destination chain.
> [!NOTE]
> These methods do not check the bridge's min/max amount limits. These checks are enforced on-chain, and the transaction will revert if the amount conditions are not met.
```ts
import { toSDKNumberOrUndefined } from "@brotocol-xyz/bro-sdk"
// Retrieve bridge info to perform a transfer from Stacks to EVM
const bridgeInfo = await sdk.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);
fromToken: stacksToken as KnownTokenId.StacksToken,
toToken: evmToken as KnownTokenId.EVMToken,
amount: toSDKNumberOrUndefined(100_000_000), // Assume 6 decimals
})
```
#### Bridge from EVM
#### `estimateBridgeTransactionFrom` methods
Use case showcasing a transfer of 100 `USDT` from Ethereum to `UsSDT` on Stacks using BroSDK.
Estimate the transaction fee and virtual size (vbytes) for bridging from Bitcoin-based networks (Bitcoin, Runes, BRC20). Fees are calculated as:
```typescript
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);
```any
fee = virtualSize [vbytes] × networkFeeRate [sat/vbyte]
```
#### Bridge from Bitcoin
`networkFeeRate` is provided by dev. Typical fee rates range from 1100 sat/vbyte, depending on network congestion and desired confirmation speed. See this [reference](https://learnmeabitcoin.com/technical/transaction/size/) for more on transaction size.
Use case showcasing a transfer of 1 `BTC` from Bitcoin to `WBTC` on Ethereum using BroSDK.
**Why is this important?** Miners prioritize transactions with higher fees per vbyte. Accurately estimating the transaction virtual size allows to set an appropriate fee, so the transaction is confirmed in a timely manner.
```typescript
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";
See the [`examples/bridgeFrom/Bitcoin.ts`](https://github.com/Brotocol-xyz/bro-sdk/tree/master/examples/bridgeFrom/Bitcoin.ts) file for usage example.
// 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),
});
#### `bridgeFrom` methods
console.log("Bridge Info:", bridgeInfo)
Once the route is validated, the cross-chain transfer can be initiated. These methods **construct and submit** the transaction on the source chain.
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 };
},
};
> [!IMPORTANT]
> The SDK does **not always** broadcast transactions—it provides the data required to sign and send them. The `sendTransaction` function parameter must be implemented by the developer using their preferred web3 library. The SDK provides the necessary arguments, including contract addresses, function to call and call data.
// Perform the bridge operation
const result = await broSdk.bridgeFromBitcoin(bridgeFromBitcoinInput);
console.log("Transaction ID:", result.txid);
```
Examples on how to use the `bridgeFrom` methods can be found in the [examples folder](https://github.com/Brotocol-xyz/bro-sdk/tree/master/examples/bridgeFrom/).
## License
This project is licensed under the terms of the [MIT license](LICENSE).
This project is licensed under the terms of the [MIT license](LICENSE).

View File

@@ -1,4 +1,4 @@
# Test Instructions
# Dev Instructions
## Visualize Typedoc Documentation
@@ -10,9 +10,19 @@ pnpm run docs:watch
In a new terminal window, run:
```bash
pnpx http-server generated/docs
```
or
```bash
cd generated/docs
python -m http.server 8080
```
Open `http://localhost:8080` in your browser to view the documentation.
## README Examples
Version history of the README examples is tracked at [`../examples/bridgeFrom`](../examples/bridgeFrom).

View File

@@ -0,0 +1,161 @@
// Bridge From BRC20
import {
GetConfirmedSpendableUTXOFn,
reselectSpendableUTXOsFactory,
UTXOBasic,
} from "../../../src/bitcoinHelpers"
import {
BroSDK,
KnownTokenId,
KnownChainId,
BridgeFromBRC20Input,
} from "../../../src/index"
import { Psbt, payments, networks } from "bitcoinjs-lib"
import axios from "axios"
const sdk = new BroSDK()
// For BRC20 provide the tick symbol
const brc20Token: KnownTokenId.BRC20Token = (await sdk.brc20TickToBRC20Token(
KnownChainId.BRC20.Mainnet,
"alex$",
))!
// For EVM tokens provide the contract address
const evmToken: KnownTokenId.EVMToken = (await sdk.evmAddressToEVMToken(
KnownChainId.EVM.Ethereum,
"0x31761a152F1e96F966C041291644129144233b0B",
))!
// Mock functions for key management
const getPublicKey = async (): Promise<string> => {
// This is a mock implementation
// In a real implementation, this would return the user's public key
return "02a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7"
}
const signTx = async (hex: string): Promise<string> => {
// This is a mock implementation
// In a real implementation, this would sign the transaction with the user's private key
return "mock_signature"
}
const publicKey = await getPublicKey()
const { address: senderAddress, output: scriptPubKey } = payments.p2wpkh({
pubkey: Buffer.from(publicKey, "hex"),
network: networks.bitcoin,
})
// Select UTXOs to spend
const reselectSpendableNetworkFeeUTXOs: BridgeFromBRC20Input["reselectSpendableNetworkFeeUTXOs"] =
async (satsToSend, lastTimeSelectedUTXOs) => {
// Example of available UTXOs from a Bitcoin node or API
const availableUTXOs: UTXOBasic[] = [
{
txId: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
index: 0,
amount: 5000n,
},
{
txId: "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
index: 1,
amount: 3000n,
},
{
txId: "7890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456",
index: 2,
amount: 2000n,
},
]
const getUTXOSpendable: GetConfirmedSpendableUTXOFn = async (
utxo: UTXOBasic,
) => {
// For this example, we'll create a simple UTXOSpendable object
return {
...utxo,
scriptPubKey: scriptPubKey!,
addressType: "p2wpkh",
blockHeight: 800000n, // Example block height
}
}
// Create the reselect function with factory helper
const reselectFn = reselectSpendableUTXOsFactory(
availableUTXOs,
getUTXOSpendable,
)
return reselectFn(satsToSend, lastTimeSelectedUTXOs)
}
const sendTransaction: BridgeFromBRC20Input["sendTransaction"] = async tx => {
/**
* Implementation example for broadcasting a Bitcoin transaction with Axios
*/
const response = await axios.post("https://blockstream.info/api/tx", tx.hex, {
headers: { "Content-Type": "text/plain" },
})
return { txid: response.data }
}
const bridgeFromBRC20Input: BridgeFromBRC20Input = {
fromChain: KnownChainId.BRC20.Mainnet,
fromToken: brc20Token,
toChain: KnownChainId.EVM.Ethereum,
toToken: evmToken,
fromAddress: senderAddress!,
fromAddressScriptPubKey: scriptPubKey!,
toAddress: "0x31751a152F1e95F966C041291644129144233b0B",
inputInscriptionUTXO: {
txId: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
index: 0,
amount: 1000n,
scriptPubKey: scriptPubKey!,
addressType: "p2wpkh",
},
networkFeeRate: 10n,
reselectSpendableNetworkFeeUTXOs,
networkFeeChangeAddress: senderAddress!,
networkFeeChangeAddressScriptPubKey: scriptPubKey!,
signPsbt: async tx => {
const psbt = Psbt.fromBuffer(Buffer.from(tx.psbt))
for (const index of tx.signBitcoinInputs) {
const signature = await signTx(psbt.toHex())
// Add the signature to the PSBT
psbt.updateInput(index, {
partialSig: [
{
pubkey: Buffer.from(await getPublicKey(), "hex"),
signature: Buffer.from(signature, "hex"),
},
],
})
}
for (const index of tx.signInscriptionInputs) {
const signature = await signTx(psbt.toHex())
// Add the signature to the PSBT
psbt.updateInput(index, {
partialSig: [
{
pubkey: Buffer.from(await getPublicKey(), "hex"),
signature: Buffer.from(signature, "hex"),
},
],
})
}
psbt.finalizeAllInputs()
return { psbt: psbt.toBuffer() }
},
sendTransaction,
}
const result = await sdk.bridgeFromBRC20(bridgeFromBRC20Input)
console.log("Bitcoin Transaction ID:", result.txid)

View File

@@ -0,0 +1,167 @@
// Bridge From BTC
import {
GetConfirmedSpendableUTXOFn,
reselectSpendableUTXOsFactory,
UTXOBasic,
} from "@brotocol-xyz/bro-sdk/bitcoinHelpers"
import {
BroSDK,
KnownTokenId,
KnownChainId,
toSDKNumberOrUndefined,
BridgeFromBitcoinInput,
} from "@brotocol-xyz/bro-sdk"
import { Psbt, payments, networks } from "bitcoinjs-lib"
import axios from "axios"
const sdk = new BroSDK()
// For EVM tokens provide the contract address
const evmToken = await sdk.evmAddressToEVMToken(
KnownChainId.EVM.Ethereum,
"0x31761a152F1e96F966C041291644129144233b0B",
)
// Mock functions for key management
// In a real implementation, these would be provided by the user's environment
const getPublicKey = async (): Promise<string> => {
// This is a mock implementation
// In a real implementation, this would return the user's public key
return "02a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7"
}
const signTx = async (hex: string): Promise<string> => {
// This is a mock implementation
// In a real implementation, this would sign the transaction with the user's private key
return "mock_signature"
}
// Get address and scriptPubKey
const publicKey = await getPublicKey()
const { address: senderAddress, output: scriptPubKey } = payments.p2wpkh({
pubkey: Buffer.from(publicKey, "hex"),
network: networks.bitcoin,
})
// Select UTXOs to spend
const reselectSpendableUTXOs: BridgeFromBitcoinInput["reselectSpendableUTXOs"] =
async (satsToSend, lastTimeSelectedUTXOs) => {
// Example of available UTXOs from a Bitcoin node or API
const availableUTXOs: UTXOBasic[] = [
{
txId: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
index: 0,
amount: 5000n,
},
{
txId: "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
index: 1,
amount: 3000n,
},
{
txId: "7890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456",
index: 2,
amount: 2000n,
},
]
// Function to convert basic UTXOs to spendable UTXOs with scriptPubKey
const getUTXOSpendable: GetConfirmedSpendableUTXOFn = async (
utxo: UTXOBasic,
) => {
// For this example, we'll create a simple UTXOSpendable object
return {
...utxo,
scriptPubKey: scriptPubKey!,
addressType: "p2wpkh",
blockHeight: 800000n, // Example block height
}
}
// Create the reselect function with factory helper
const reselectFn = reselectSpendableUTXOsFactory(
availableUTXOs,
getUTXOSpendable,
)
return reselectFn(satsToSend, lastTimeSelectedUTXOs)
}
// Sign a Bitcoin PSBT
const signPsbt: BridgeFromBitcoinInput["signPsbt"] = async tx => {
/**
* Implementation example for signing a Bitcoin PSBT (Partially Signed Bitcoin Transaction)
*/
const psbt = Psbt.fromBuffer(Buffer.from(tx.psbt))
// For each input that needs to be signed
for (const index of tx.signInputs) {
// Get the input's sighash
const input = psbt.data.inputs[index]
// @ts-ignore
const sighash = input.sighashType
// Sign the transaction using the mocked signTx function
const signature = await signTx(psbt.toHex())
// Add the signature to the PSBT
psbt.updateInput(index, {
partialSig: [
{
pubkey: Buffer.from(await getPublicKey(), "hex"),
signature: Buffer.from(signature, "hex"),
},
],
})
}
psbt.finalizeAllInputs()
return { psbt: psbt.toBuffer() }
}
// Broadcast the signed transaction
const sendTransaction: BridgeFromBitcoinInput["sendTransaction"] = async tx => {
/**
* Implementation example for broadcasting a Bitcoin transaction with Axios
*/
const response = await axios.post("https://blockstream.info/api/tx", tx.hex, {
headers: { "Content-Type": "text/plain" },
})
return { txid: response.data }
}
// Estimate transaction fee and virtual size before performing the bridge operation
const estimateTransaction = await sdk.estimateBridgeTransactionFromBitcoin({
fromChain: KnownChainId.Bitcoin.Mainnet,
fromToken: KnownTokenId.Bitcoin.BTC,
toChain: KnownChainId.EVM.Ethereum,
toToken: evmToken as KnownTokenId.EVMToken,
fromAddressScriptPubKey: scriptPubKey!,
fromAddress: senderAddress!,
toAddress: "0x31751a152F1e95F966C041291644129144233b0B",
amount: toSDKNumberOrUndefined(1),
networkFeeRate: 10n,
reselectSpendableUTXOs: reselectSpendableUTXOs,
})
console.log("Estimated Transaction: ", estimateTransaction)
const bridgeFromBitcoinInput: BridgeFromBitcoinInput = {
fromChain: KnownChainId.Bitcoin.Mainnet,
fromToken: KnownTokenId.Bitcoin.BTC,
toChain: KnownChainId.EVM.Ethereum,
toToken: evmToken as KnownTokenId.EVMToken,
fromAddressScriptPubKey: scriptPubKey!,
fromAddress: senderAddress!,
toAddress: "0x31751a152F1e95F966C041291644129144233b0B",
amount: toSDKNumberOrUndefined(1),
networkFeeRate: 10n, // Expressed in satoshis per virtual byte (sat/vbyte).
reselectSpendableUTXOs,
signPsbt,
sendTransaction,
}
// Perform the bridge operation
const result = await sdk.bridgeFromBitcoin(bridgeFromBitcoinInput)
console.log("Bitcoin Transaction ID:", result.txid)

View File

@@ -0,0 +1,79 @@
// Bridge From EVM
import {
BroSDK,
KnownTokenId,
KnownChainId,
toSDKNumberOrUndefined,
BridgeFromEVMInput,
EVMAddress,
SDKNumber,
formatSDKNumber,
} from "@brotocol-xyz/bro-sdk"
// Choose your preferred web3 lib here
import { ethers } from "ethers"
const sdk = new BroSDK()
// For Stacks provide the contract address
const stacksToken: KnownTokenId.StacksToken =
(await sdk.stacksAddressToStacksToken(KnownChainId.Stacks.Mainnet, {
deployerAddress: "SP2XD7417HGPRTREMKF748VNEQPDRR0RMANB7X1NK",
contractName: "token-abtc",
}))!
// For EVM tokens provide the contract address
const evmToken: KnownTokenId.EVMToken = (await sdk.evmAddressToEVMToken(
KnownChainId.EVM.Ethereum,
"0x31761a152F1e96F966C041291644129144233b0B",
))!
// Example signer setup using ethers.js
const provider = new ethers.JsonRpcProvider(
"https://mainnet.someprovider.io/YOUR_PROJECT_ID",
)
const signer = new ethers.Wallet(
"000000000000000000000000000000000000000000000000000000000000002d",
provider,
)
const signerAddress = signer.address as `0x${string}`
const bridgeFromEVMInput: BridgeFromEVMInput = {
fromChain: KnownChainId.EVM.Ethereum,
toChain: KnownChainId.Stacks.Mainnet,
fromToken: evmToken,
toToken: stacksToken,
// Sender Ethereum address
fromAddress: signerAddress,
// Receiver Stacks principal
toAddress: "SP2ZD731ANQZT6J4K3F5N8A40ZXWXC1XFXHVVQFKE",
amount: toSDKNumberOrUndefined(100),
sendTransaction: async (tx: {
from: EVMAddress // Sender Ethereum address
to: EVMAddress // Bridge Endpoint address
data: Uint8Array
recommendedGasLimit: SDKNumber
value?: SDKNumber
}): Promise<{ txHash: string }> => {
/**
* Implementation for sending transaction on Ethereum mainnet
* See https://docs.ethers.org/v6/api/contract/ for reference
*/
const txRequest = {
from: tx.from,
to: tx.to,
data: ethers.hexlify(tx.data),
gasLimit: formatSDKNumber(tx.recommendedGasLimit),
}
const sentTx = await signer.sendTransaction(txRequest)
const receipt = await sentTx.wait()
if (receipt === null) throw new Error("Transaction receipt is null")
return { txHash: receipt.hash }
},
}
// Perform the bridge operation
const result = await sdk.bridgeFromEVM(bridgeFromEVMInput)
console.log("Transaction ID:", result.txHash)

View File

@@ -0,0 +1,189 @@
// Bridge From Runes
import {
GetConfirmedSpendableUTXOFn,
reselectSpendableUTXOsFactory,
UTXOBasic,
} from "@brotocol-xyz/bro-sdk/bitcoinHelpers"
import {
BroSDK,
KnownTokenId,
KnownChainId,
toSDKNumberOrUndefined,
BridgeFromRunesInput,
RunesUTXOSpendable,
} from "@brotocol-xyz/bro-sdk"
import { Psbt, payments, networks } from "bitcoinjs-lib"
import axios from "axios"
const sdk = new BroSDK()
// For Runes provide the runes ID
const runesToken: KnownTokenId.RunesToken = (await sdk.runesIdToRunesToken(
KnownChainId.Runes.Mainnet,
"500:20",
))!
// For EVM tokens provide the contract address
const evmToken: KnownTokenId.EVMToken = (await sdk.evmAddressToEVMToken(
KnownChainId.EVM.Ethereum,
"0x31761a152F1e96F966C041291644129144233b0B",
))!
// Mock functions for key management
// In a real implementation, these would be provided by the user's environment
const getPublicKey = async (): Promise<string> => {
// This is a mock implementation
// In a real implementation, this would return the user's public key
return "02a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7"
}
const signTx = async (hex: string): Promise<string> => {
// This is a mock implementation
// In a real implementation, this would sign the transaction with the user's private key
return "mock_signature"
}
// Get address and scriptPubKey
const publicKey = await getPublicKey()
const { address: senderAddress, output: scriptPubKey } = payments.p2wpkh({
pubkey: Buffer.from(publicKey, "hex"),
network: networks.bitcoin,
})
// Select UTXOs to spend for network fees
const reselectSpendableNetworkFeeUTXOsForRunes: BridgeFromRunesInput["reselectSpendableNetworkFeeUTXOs"] =
async (satsToSend, lastTimeSelectedUTXOs) => {
// Example of available UTXOs from a Bitcoin node or API
const availableUTXOs: UTXOBasic[] = [
{
txId: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
index: 0,
amount: 5000n,
},
{
txId: "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
index: 1,
amount: 3000n,
},
{
txId: "7890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456",
index: 2,
amount: 2000n,
},
]
// Function to convert basic UTXOs to spendable UTXOs with scriptPubKey
const getUTXOSpendable: GetConfirmedSpendableUTXOFn = async (
utxo: UTXOBasic,
) => {
// For this example, we'll create a simple UTXOSpendable object
return {
...utxo,
scriptPubKey: scriptPubKey!,
addressType: "p2wpkh",
blockHeight: 800000n, // Example block height
}
}
// Create the reselect function with factory helper
const reselectFn = reselectSpendableUTXOsFactory(
availableUTXOs,
getUTXOSpendable,
)
return reselectFn(satsToSend, lastTimeSelectedUTXOs)
}
// Example Runes UTXOs
const runesUTXOs: RunesUTXOSpendable[] = [
{
txId: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
index: 0,
amount: 1000n,
scriptPubKey: scriptPubKey!,
addressType: "p2wpkh",
runes: [
{
runeId: "500:20",
runeDivisibility: 8,
runeAmount: 100000000n, // 1.0 rune
},
],
},
]
// Sign a Bitcoin PSBT for Runes
const signPsbtForRunes: BridgeFromRunesInput["signPsbt"] = async tx => {
const psbt = Psbt.fromBuffer(Buffer.from(tx.psbt))
// For each Bitcoin input that needs to be signed
for (const index of tx.signBitcoinInputs) {
// Sign the transaction using the mocked signTx function
const signature = await signTx(psbt.toHex())
// Add the signature to the PSBT
psbt.updateInput(index, {
partialSig: [
{
pubkey: Buffer.from(await getPublicKey(), "hex"),
signature: Buffer.from(signature, "hex"),
},
],
})
}
// For each Runes input that needs to be signed
for (const index of tx.signRunesInputs) {
// Sign the transaction using the mocked signTx function
const signature = await signTx(psbt.toHex())
// Add the signature to the PSBT
psbt.updateInput(index, {
partialSig: [
{
pubkey: Buffer.from(await getPublicKey(), "hex"),
signature: Buffer.from(signature, "hex"),
},
],
})
}
psbt.finalizeAllInputs()
return { psbt: psbt.toBuffer() }
}
// Broadcast the signed transaction
const sendTransactionForRunes: BridgeFromRunesInput["sendTransaction"] =
async tx => {
const response = await axios.post(
"https://blockstream.info/api/tx",
tx.hex,
{
headers: { "Content-Type": "text/plain" },
},
)
return { txid: response.data }
}
// Create the bridge input
const bridgeFromRunesInput: BridgeFromRunesInput = {
fromChain: KnownChainId.Runes.Mainnet,
fromToken: runesToken,
toChain: KnownChainId.EVM.Ethereum,
toToken: evmToken,
fromAddress: senderAddress!,
fromAddressScriptPubKey: scriptPubKey!,
toAddress: "0x31751a152F1e95F966C041291644129144233b0B",
amount: toSDKNumberOrUndefined(1), // 1.0 rune
inputRuneUTXOs: runesUTXOs,
networkFeeRate: 10n,
reselectSpendableNetworkFeeUTXOs: reselectSpendableNetworkFeeUTXOsForRunes,
networkFeeChangeAddress: senderAddress!,
networkFeeChangeAddressScriptPubKey: scriptPubKey!,
signPsbt: signPsbtForRunes,
sendTransaction: sendTransactionForRunes,
}
// Perform the bridge operation
const result = await sdk.bridgeFromRunes(bridgeFromRunesInput)
console.log("Bitcoin Transaction ID:", result.txid)

View File

@@ -0,0 +1,80 @@
// Bridge From Stacks
import {
BroSDK,
KnownTokenId,
KnownChainId,
BridgeFromStacksInput,
toSDKNumberOrUndefined,
BridgeFromStacksInput_ContractCallOptions as ContractCallOptions,
} from "@brotocol-xyz/bro-sdk"
import {
makeContractCall,
broadcastTransaction,
deserializeCV,
} from "@stacks/transactions"
const sdk = new BroSDK()
// For Stacks provide the contract address
const stacksToken: KnownTokenId.StacksToken =
(await sdk.stacksAddressToStacksToken(KnownChainId.Stacks.Mainnet, {
deployerAddress: "SP2XD7417HGPRTREMKF748VNEQPDRR0RMANB7X1NK",
contractName: "token-abtc",
}))!
// For EVM tokens provide the contract address
const evmToken: KnownTokenId.EVMToken = (await sdk.evmAddressToEVMToken(
KnownChainId.EVM.Ethereum,
"0x31761a152F1e96F966C041291644129144233b0B",
))!
const bridgeInfo = await sdk.bridgeInfoFromStacks({
fromChain: KnownChainId.Stacks.Mainnet,
toChain: KnownChainId.EVM.Ethereum,
fromToken: stacksToken,
toToken: evmToken,
amount: toSDKNumberOrUndefined(100_000_000),
})
console.log("Bridge Info:", bridgeInfo)
const bridgeFromStacksInput: BridgeFromStacksInput = {
fromChain: KnownChainId.Stacks.Mainnet,
toChain: KnownChainId.EVM.Ethereum,
fromToken: stacksToken,
toToken: evmToken,
fromAddress: "SP2ZD731ANQZT6J4K3F5N8A40ZXWXC1XFXHVVQFKE",
// Receiver EVM address
toAddress: "0x31751a152F1e95F966C041291644129144233b0B",
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
* - https://stacks.js.org/functions/_stacks_transactions.makeContractCall
* - https://stacks.js.org/functions/_stacks_transactions.broadcastTransaction
*/
const transaction = await makeContractCall({
contractAddress: tx.contractAddress,
contractName: tx.contractName,
functionName: tx.functionName,
// Deserialize each element of functionArgs and convert it into ClarityValue[]
functionArgs: tx.functionArgs.map(arg => deserializeCV(arg)),
postConditions: [] /* Add post conditions */,
validateWithAbi: true,
senderKey:
"b244296d5907de9864c0b0d51f98a13c52890be0404e83f273144cd5b9960eed01",
network: "mainnet",
})
const broadcastResponse = await broadcastTransaction({
transaction,
network: "mainnet",
})
return { txid: broadcastResponse.txid }
},
}
const result = await sdk.bridgeFromStacks(bridgeFromStacksInput)
console.log("Transaction ID:", result.txid)

View File

@@ -0,0 +1,20 @@
{
"name": "bro-sdk-bridgeFrom-example",
"version": "1.0.0",
"description": "",
"private": true,
"main": null,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@brotocol-xyz/bro-sdk": "file:../..",
"@types/node": "^22.15.17",
"axios": "^1.9.0",
"bitcoinjs-lib": "^6.1.7",
"ethers": "^6.14.0"
}
}

791
examples/bridgeFrom/pnpm-lock.yaml generated Normal file
View File

@@ -0,0 +1,791 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@brotocol-xyz/bro-sdk':
specifier: file:../..
version: file:../..(@stacks/common@7.0.2)
'@types/node':
specifier: ^22.15.17
version: 22.15.17
axios:
specifier: ^1.9.0
version: 1.9.0
bitcoinjs-lib:
specifier: ^6.1.7
version: 6.1.7
ethers:
specifier: ^6.14.0
version: 6.14.0
packages:
'@adraffy/ens-normalize@1.10.1':
resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==}
'@brotocol-xyz/bro-sdk@file:../..':
resolution: {directory: ../.., type: directory}
'@c4/btc-utils@0.3.1':
resolution: {integrity: sha512-mhJ43BhjJP7KspiWZVNnvCy3VTmN8EksBiV+d49jVPBDwrj8dBGuhbv3aM+AVnIfq4Z0Ds6k6q2wkl/lKeNcOA==}
'@noble/curves@1.2.0':
resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==}
'@noble/curves@1.8.2':
resolution: {integrity: sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==}
engines: {node: ^14.21.3 || >=16}
'@noble/curves@1.9.0':
resolution: {integrity: sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==}
engines: {node: ^14.21.3 || >=16}
'@noble/hashes@1.1.5':
resolution: {integrity: sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==}
'@noble/hashes@1.3.2':
resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==}
engines: {node: '>= 16'}
'@noble/hashes@1.7.2':
resolution: {integrity: sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==}
engines: {node: ^14.21.3 || >=16}
'@noble/hashes@1.8.0':
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
engines: {node: ^14.21.3 || >=16}
'@noble/secp256k1@1.7.1':
resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==}
'@scure/base@1.2.5':
resolution: {integrity: sha512-9rE6EOVeIQzt5TSu4v+K523F8u6DhBsoZWPGKlnCshhlDhy0kJzUX4V+tr2dWmzF1GdekvThABoEQBGBQI7xZw==}
'@scure/bip32@1.6.2':
resolution: {integrity: sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==}
'@scure/bip39@1.5.4':
resolution: {integrity: sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==}
'@scure/btc-signer@1.8.0':
resolution: {integrity: sha512-lzf9ugp2hZwP84bdRQuxdX2iib3wyUs7+8+Ph/hanVaXWGOZfSfgEZFaOyocj/Qh0Igt1WHkZh6hdh4KloynNQ==}
'@stacks/common@7.0.2':
resolution: {integrity: sha512-+RSecHdkxOtswmE4tDDoZlYEuULpnTQVeDIG5eZ32opK8cFxf4EugAcK9CsIsHx/Se1yTEaQ21WGATmJGK84lQ==}
'@stacks/network@7.0.2':
resolution: {integrity: sha512-XzHnoWqku/jRrTgMXhmh3c+I0O9vDH24KlhzGDZtBu+8CGGyHNPAZzGwvoUShonMXrXjEnfO9IYQwV5aJhfv6g==}
'@stacks/stacks-blockchain-api-types@7.14.1':
resolution: {integrity: sha512-65hvhXxC+EUqHJAQsqlBCqXB+zwfxZICSKYJugdg6BCp9I9qniyfz5XyQeC4RMVo0tgEoRdS/b5ZCFo5kLWmxA==}
'@stacks/transactions@7.0.6':
resolution: {integrity: sha512-qRGo4tNwOh+avUv/u4JGqqUWQ8xW/iUWtJV0o3BxpMyRxqDXmj+m+yeAEVYf9jRDouOo+NaWmwtRmWc0URZPdw==}
'@types/node@22.15.17':
resolution: {integrity: sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==}
'@types/node@22.7.5':
resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==}
abitype@1.0.8:
resolution: {integrity: sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==}
peerDependencies:
typescript: '>=5.0.4'
zod: ^3 >=3.22.0
peerDependenciesMeta:
typescript:
optional: true
zod:
optional: true
aes-js@4.0.0-beta.5:
resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==}
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
axios@1.9.0:
resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==}
base-x@4.0.1:
resolution: {integrity: sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw==}
bech32@2.0.0:
resolution: {integrity: sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==}
big.js@6.2.2:
resolution: {integrity: sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==}
bip174@2.1.1:
resolution: {integrity: sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==}
engines: {node: '>=8.0.0'}
bitcoinjs-lib@6.1.7:
resolution: {integrity: sha512-tlf/r2DGMbF7ky1MgUqXHzypYHakkEnm0SZP23CJKIqNY/5uNAnMbFhMJdhjrL/7anfb/U8+AlpdjPWjPnAalg==}
engines: {node: '>=8.0.0'}
bs58@5.0.0:
resolution: {integrity: sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==}
bs58check@3.0.1:
resolution: {integrity: sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==}
c32check@2.0.0:
resolution: {integrity: sha512-rpwfAcS/CMqo0oCqDf3r9eeLgScRE3l/xHDCXhM3UyrfvIn7PrLq63uHh7yYbv8NzaZn5MVsVhIRpQ+5GZ5HyA==}
engines: {node: '>=8'}
call-bind-apply-helpers@1.0.2:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'}
clarity-codegen@1.1.3:
resolution: {integrity: sha512-/EXXaq5J8e9ldrQjsNPQwr2QOoIMBvLHFab5nahFwdfG18ZiyXSx9SvxHUbzMHBLUzsvgnlmopAlIj+R+2rwmw==}
hasBin: true
peerDependencies:
'@stacks/common': ^7.0.2
'@stacks/transactions': ^7.0.2
cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
cross-fetch@3.2.0:
resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==}
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
es-define-property@1.0.1:
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
engines: {node: '>= 0.4'}
es-errors@1.3.0:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
es-object-atoms@1.1.1:
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
engines: {node: '>= 0.4'}
es-set-tostringtag@2.1.0:
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
ethers@6.14.0:
resolution: {integrity: sha512-KgHwltNSMdbrGWEyKkM0Rt2s+u1nDH/5BVDQakLinzGEJi4bWindBzZSCC4gKsbZjwDTI6ex/8suR9Ihbmz4IQ==}
engines: {node: '>=14.0.0'}
eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
follow-redirects@1.15.9:
resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
form-data@4.0.2:
resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==}
engines: {node: '>= 6'}
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
get-intrinsic@1.3.0:
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'}
get-proto@1.0.1:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
has-symbols@1.1.0:
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
engines: {node: '>= 0.4'}
has-tostringtag@1.0.2:
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
engines: {node: '>= 0.4'}
hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
isows@1.0.6:
resolution: {integrity: sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==}
peerDependencies:
ws: '*'
lodash.clonedeep@4.5.0:
resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==}
lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
micro-packed@0.7.3:
resolution: {integrity: sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg==}
mime-db@1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
node-fetch@2.7.0:
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
engines: {node: 4.x || >=6.0.0}
peerDependencies:
encoding: ^0.1.0
peerDependenciesMeta:
encoding:
optional: true
ox@0.6.9:
resolution: {integrity: sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==}
peerDependencies:
typescript: '>=5.4.0'
peerDependenciesMeta:
typescript:
optional: true
proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
tslib@2.7.0:
resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
typeforce@1.18.0:
resolution: {integrity: sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==}
undici-types@6.19.8:
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
varuint-bitcoin@1.1.2:
resolution: {integrity: sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==}
viem@2.29.2:
resolution: {integrity: sha512-cukRxab90jvQ+TDD84sU3qB3UmejYqgCw4cX8SfWzvh7JPfZXI3kAMUaT5OSR2As1Mgvx1EJawccwPjGqkSSwA==}
peerDependencies:
typescript: '>=5.0.4'
peerDependenciesMeta:
typescript:
optional: true
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
ws@8.17.1:
resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
ws@8.18.1:
resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
yargs@17.7.2:
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
engines: {node: '>=12'}
yqueue@1.0.1:
resolution: {integrity: sha512-DBxJZBRafFLA/tCc5uO8ZTGFr+sQgn1FRJkZ4cVrIQIk6bv2bInraE3mbpLAJw9z93JGrLkqDoyTLrrZaCNq5w==}
snapshots:
'@adraffy/ens-normalize@1.10.1': {}
'@brotocol-xyz/bro-sdk@file:../..(@stacks/common@7.0.2)':
dependencies:
'@c4/btc-utils': 0.3.1
'@scure/btc-signer': 1.8.0
'@stacks/network': 7.0.2
'@stacks/transactions': 7.0.6
big.js: 6.2.2
c32check: 2.0.0
clarity-codegen: 1.1.3(@stacks/common@7.0.2)(@stacks/transactions@7.0.6)
viem: 2.29.2
transitivePeerDependencies:
- '@stacks/common'
- bufferutil
- debug
- encoding
- typescript
- utf-8-validate
- zod
'@c4/btc-utils@0.3.1':
optionalDependencies:
'@scure/btc-signer': 1.8.0
'@noble/curves@1.2.0':
dependencies:
'@noble/hashes': 1.3.2
'@noble/curves@1.8.2':
dependencies:
'@noble/hashes': 1.7.2
'@noble/curves@1.9.0':
dependencies:
'@noble/hashes': 1.8.0
'@noble/hashes@1.1.5': {}
'@noble/hashes@1.3.2': {}
'@noble/hashes@1.7.2': {}
'@noble/hashes@1.8.0': {}
'@noble/secp256k1@1.7.1': {}
'@scure/base@1.2.5': {}
'@scure/bip32@1.6.2':
dependencies:
'@noble/curves': 1.8.2
'@noble/hashes': 1.7.2
'@scure/base': 1.2.5
'@scure/bip39@1.5.4':
dependencies:
'@noble/hashes': 1.7.2
'@scure/base': 1.2.5
'@scure/btc-signer@1.8.0':
dependencies:
'@noble/curves': 1.9.0
'@noble/hashes': 1.8.0
'@scure/base': 1.2.5
micro-packed: 0.7.3
'@stacks/common@7.0.2': {}
'@stacks/network@7.0.2':
dependencies:
'@stacks/common': 7.0.2
cross-fetch: 3.2.0
transitivePeerDependencies:
- encoding
'@stacks/stacks-blockchain-api-types@7.14.1': {}
'@stacks/transactions@7.0.6':
dependencies:
'@noble/hashes': 1.1.5
'@noble/secp256k1': 1.7.1
'@stacks/common': 7.0.2
'@stacks/network': 7.0.2
c32check: 2.0.0
lodash.clonedeep: 4.5.0
transitivePeerDependencies:
- encoding
'@types/node@22.15.17':
dependencies:
undici-types: 6.21.0
'@types/node@22.7.5':
dependencies:
undici-types: 6.19.8
abitype@1.0.8: {}
aes-js@4.0.0-beta.5: {}
ansi-regex@5.0.1: {}
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
asynckit@0.4.0: {}
axios@1.9.0:
dependencies:
follow-redirects: 1.15.9
form-data: 4.0.2
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
base-x@4.0.1: {}
bech32@2.0.0: {}
big.js@6.2.2: {}
bip174@2.1.1: {}
bitcoinjs-lib@6.1.7:
dependencies:
'@noble/hashes': 1.8.0
bech32: 2.0.0
bip174: 2.1.1
bs58check: 3.0.1
typeforce: 1.18.0
varuint-bitcoin: 1.1.2
bs58@5.0.0:
dependencies:
base-x: 4.0.1
bs58check@3.0.1:
dependencies:
'@noble/hashes': 1.8.0
bs58: 5.0.0
c32check@2.0.0:
dependencies:
'@noble/hashes': 1.8.0
base-x: 4.0.1
call-bind-apply-helpers@1.0.2:
dependencies:
es-errors: 1.3.0
function-bind: 1.1.2
clarity-codegen@1.1.3(@stacks/common@7.0.2)(@stacks/transactions@7.0.6):
dependencies:
'@stacks/common': 7.0.2
'@stacks/stacks-blockchain-api-types': 7.14.1
'@stacks/transactions': 7.0.6
axios: 1.9.0
lodash: 4.17.21
yargs: 17.7.2
yqueue: 1.0.1
transitivePeerDependencies:
- debug
cliui@8.0.1:
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 7.0.0
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
color-name@1.1.4: {}
combined-stream@1.0.8:
dependencies:
delayed-stream: 1.0.0
cross-fetch@3.2.0:
dependencies:
node-fetch: 2.7.0
transitivePeerDependencies:
- encoding
delayed-stream@1.0.0: {}
dunder-proto@1.0.1:
dependencies:
call-bind-apply-helpers: 1.0.2
es-errors: 1.3.0
gopd: 1.2.0
emoji-regex@8.0.0: {}
es-define-property@1.0.1: {}
es-errors@1.3.0: {}
es-object-atoms@1.1.1:
dependencies:
es-errors: 1.3.0
es-set-tostringtag@2.1.0:
dependencies:
es-errors: 1.3.0
get-intrinsic: 1.3.0
has-tostringtag: 1.0.2
hasown: 2.0.2
escalade@3.2.0: {}
ethers@6.14.0:
dependencies:
'@adraffy/ens-normalize': 1.10.1
'@noble/curves': 1.2.0
'@noble/hashes': 1.3.2
'@types/node': 22.7.5
aes-js: 4.0.0-beta.5
tslib: 2.7.0
ws: 8.17.1
transitivePeerDependencies:
- bufferutil
- utf-8-validate
eventemitter3@5.0.1: {}
follow-redirects@1.15.9: {}
form-data@4.0.2:
dependencies:
asynckit: 0.4.0
combined-stream: 1.0.8
es-set-tostringtag: 2.1.0
mime-types: 2.1.35
function-bind@1.1.2: {}
get-caller-file@2.0.5: {}
get-intrinsic@1.3.0:
dependencies:
call-bind-apply-helpers: 1.0.2
es-define-property: 1.0.1
es-errors: 1.3.0
es-object-atoms: 1.1.1
function-bind: 1.1.2
get-proto: 1.0.1
gopd: 1.2.0
has-symbols: 1.1.0
hasown: 2.0.2
math-intrinsics: 1.1.0
get-proto@1.0.1:
dependencies:
dunder-proto: 1.0.1
es-object-atoms: 1.1.1
gopd@1.2.0: {}
has-symbols@1.1.0: {}
has-tostringtag@1.0.2:
dependencies:
has-symbols: 1.1.0
hasown@2.0.2:
dependencies:
function-bind: 1.1.2
is-fullwidth-code-point@3.0.0: {}
isows@1.0.6(ws@8.18.1):
dependencies:
ws: 8.18.1
lodash.clonedeep@4.5.0: {}
lodash@4.17.21: {}
math-intrinsics@1.1.0: {}
micro-packed@0.7.3:
dependencies:
'@scure/base': 1.2.5
mime-db@1.52.0: {}
mime-types@2.1.35:
dependencies:
mime-db: 1.52.0
node-fetch@2.7.0:
dependencies:
whatwg-url: 5.0.0
ox@0.6.9:
dependencies:
'@adraffy/ens-normalize': 1.10.1
'@noble/curves': 1.8.2
'@noble/hashes': 1.8.0
'@scure/bip32': 1.6.2
'@scure/bip39': 1.5.4
abitype: 1.0.8
eventemitter3: 5.0.1
transitivePeerDependencies:
- zod
proxy-from-env@1.1.0: {}
require-directory@2.1.1: {}
safe-buffer@5.2.1: {}
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
tr46@0.0.3: {}
tslib@2.7.0: {}
typeforce@1.18.0: {}
undici-types@6.19.8: {}
undici-types@6.21.0: {}
varuint-bitcoin@1.1.2:
dependencies:
safe-buffer: 5.2.1
viem@2.29.2:
dependencies:
'@noble/curves': 1.8.2
'@noble/hashes': 1.7.2
'@scure/bip32': 1.6.2
'@scure/bip39': 1.5.4
abitype: 1.0.8
isows: 1.0.6(ws@8.18.1)
ox: 0.6.9
ws: 8.18.1
transitivePeerDependencies:
- bufferutil
- utf-8-validate
- zod
webidl-conversions@3.0.1: {}
whatwg-url@5.0.0:
dependencies:
tr46: 0.0.3
webidl-conversions: 3.0.1
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
ws@8.17.1: {}
ws@8.18.1: {}
y18n@5.0.8: {}
yargs-parser@21.1.1: {}
yargs@17.7.2:
dependencies:
cliui: 8.0.1
escalade: 3.2.0
get-caller-file: 2.0.5
require-directory: 2.1.1
string-width: 4.2.3
y18n: 5.0.8
yargs-parser: 21.1.1
yqueue@1.0.1: {}

View File

@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ESNext",
"lib": ["ESNext"],
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
}
}

8
pnpm-lock.yaml generated
View File

@@ -791,8 +791,8 @@ packages:
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
axios@1.8.3:
resolution: {integrity: sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==}
axios@1.9.0:
resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==}
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@@ -2373,7 +2373,7 @@ snapshots:
asynckit@0.4.0: {}
axios@1.8.3:
axios@1.9.0:
dependencies:
follow-redirects: 1.15.9
form-data: 4.0.2
@@ -2443,7 +2443,7 @@ snapshots:
'@stacks/common': 7.0.2
'@stacks/stacks-blockchain-api-types': 7.14.1
'@stacks/transactions': 7.0.5
axios: 1.8.3
axios: 1.9.0
lodash: 4.17.21
yargs: 17.7.2
yqueue: 1.0.1

View File

@@ -4,6 +4,14 @@ import { EVMEndpointContract } from "../evmUtils/evmContractAddresses"
import { BigNumber } from "../utils/BigNumber"
import { InvalidMethodParametersError } from "../utils/errors"
/**
* A branded literal type used for SDK-specific types `ChainId`, `TokenId` and `SDKNumber`.
*
* For example:
* - `"bitcoin-mainnet (BroSDK ChainId)"` represents a valid `ChainId`
* - `"brc20-something (BroSDK TokenId)"` represents a valid `TokenId`
* - `"10 (BroSDK number)"` represents a valid `SDKNumber`
*/
type SDKBrandedLiteral<
Type extends string,
T extends string | number,

View File

@@ -1,6 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig.json",
"exclude": ["node_modules", "lib", "examples/cross-chain-swap"],
"exclude": [
"node_modules",
"lib",
"examples/cross-chain-swap",
"examples/bridgeFrom"
],
"compilerOptions": {
"module": "esnext",
"target": "esnext",