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

416
README.md
View File

@@ -1,19 +1,39 @@
# BroSDK # 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** 🐙 🐙 **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 ## Installation
### Prerequisites With [pnpm](https://pnpm.io/):
- [Node.js](https://nodejs.org/en)
- [pnpm](https://pnpm.io/)
### Install
```bash ```bash
pnpm install @brotocol-xyz/bro-sdk pnpm install @brotocol-xyz/bro-sdk
@@ -21,261 +41,203 @@ pnpm install @brotocol-xyz/bro-sdk
## Usage ## 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" import { BroSDK } from "@brotocol-xyz/bro-sdk"
const sdk = new BroSDK() 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). 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 | | Namespace | Mainnet | Testnet |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | | :---------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------: |
| Bitcoin | `Mainnet` | `Testnet` | | Bitcoin | `Mainnet` | `Testnet` |
| Runes | `Mainnet` | `Testnet` | | Runes | `Mainnet` | `Testnet` |
| BRC20 | `Mainnet` | `Testnet` | | BRC20 | `Mainnet` | `Testnet` |
| Stacks | `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 | 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.
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| 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` |
### 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 // For Runes provide the runes ID
import { BroSDK } from "@brotocol-xyz/bro-sdk" const runesToken = await sdk.runesIdToRunesToken(
const broSdk = new BroSDK() KnownChainId.Runes.Mainnet,
``` "500:20",
)
#### Bridge from Stacks // For Stacks provide the contract address
const stacksToken = await sdk.stacksAddressToStacksToken(
Use case showcasing a transfer of 100 `sUSDT` from Stacks to `USDT` on Ethereum using BroSDK. KnownChainId.Stacks.Mainnet,
```typescript
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);
```
#### Bridge from EVM
Use case showcasing a transfer of 100 `USDT` from Ethereum to `UsSDT` on Stacks using BroSDK.
```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 */ deployerAddress: "SP2XD7417HGPRTREMKF748VNEQPDRR0RMANB7X1NK",
to: EVMAddress /* Bridge Endpoint address */ contractName: "token-abtc",
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 // For EVM tokens provide the contract address
const result = await broSdk.bridgeFromEVM(bridgeFromEVMInput); const evmToken = await sdk.evmAddressToEVMToken(
console.log("Transaction ID:", result.txHash); KnownChainId.EVM.Ethereum,
"0x31761a152F1e96F966C041291644129144233b0B",
)
``` ```
#### Bridge from Bitcoin If a token is **unsupported**, these functions return `Promise<undefined>`.
Use case showcasing a transfer of 1 `BTC` from Bitcoin to `WBTC` 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 > [!WARNING]
import { >
BridgeFromBitcoinInput, > `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.
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 ### Available Routes
const bridgeInfo = await broSdk.bridgeInfoFromBitcoin({
fromChain: KnownChainId.Bitcoin.Mainnet, ```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, toChain: KnownChainId.EVM.Ethereum,
fromToken: KnownTokenId.Bitcoin.BTC, })
toToken: KnownTokenId.EVM.WBTC,
amount: toSDKNumberOrUndefined(1),
});
console.log("Bridge Info:", bridgeInfo) // Check if a specific token pair is supported for at least one route
const isSupported = await sdk.isSupportedRoute({
const bridgeFromBitcoinInput: BridgeFromBitcoinInput = { fromChain: KnownChainId.BRC20.Mainnet,
fromChain: KnownChainId.Bitcoin.Mainnet,
fromToken: KnownTokenId.Bitcoin.BTC,
toChain: KnownChainId.EVM.Ethereum, toChain: KnownChainId.EVM.Ethereum,
toToken: KnownTokenId.EVM.WBTC, fromToken: brc20Token as KnownTokenId.BRC20Token,
fromAddress: /* Sender Bitcoin address */, toToken: evmToken as KnownTokenId.EVMToken,
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 // If the token pair is supported, get available routes for that pair
const result = await broSdk.bridgeFromBitcoin(bridgeFromBitcoinInput); if (isSupported) {
console.log("Transaction ID:", result.txid); 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: stacksToken as KnownTokenId.StacksToken,
toToken: evmToken as KnownTokenId.EVMToken,
amount: toSDKNumberOrUndefined(100_000_000), // Assume 6 decimals
})
```
#### `estimateBridgeTransactionFrom` methods
Estimate the transaction fee and virtual size (vbytes) for bridging from Bitcoin-based networks (Bitcoin, Runes, BRC20). Fees are calculated as:
```any
fee = virtualSize [vbytes] × networkFeeRate [sat/vbyte]
```
`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.
**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.
See the [`examples/bridgeFrom/Bitcoin.ts`](https://github.com/Brotocol-xyz/bro-sdk/tree/master/examples/bridgeFrom/Bitcoin.ts) file for usage example.
#### `bridgeFrom` methods
Once the route is validated, the cross-chain transfer can be initiated. These methods **construct and submit** the transaction on the source chain.
> [!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.
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 ## 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 ## Visualize Typedoc Documentation
@@ -10,9 +10,19 @@ pnpm run docs:watch
In a new terminal window, run: In a new terminal window, run:
```bash
pnpx http-server generated/docs
```
or
```bash ```bash
cd generated/docs cd generated/docs
python -m http.server 8080 python -m http.server 8080
``` ```
Open `http://localhost:8080` in your browser to view the documentation. 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: asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
axios@1.8.3: axios@1.9.0:
resolution: {integrity: sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==} resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==}
balanced-match@1.0.2: balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@@ -2373,7 +2373,7 @@ snapshots:
asynckit@0.4.0: {} asynckit@0.4.0: {}
axios@1.8.3: axios@1.9.0:
dependencies: dependencies:
follow-redirects: 1.15.9 follow-redirects: 1.15.9
form-data: 4.0.2 form-data: 4.0.2
@@ -2443,7 +2443,7 @@ snapshots:
'@stacks/common': 7.0.2 '@stacks/common': 7.0.2
'@stacks/stacks-blockchain-api-types': 7.14.1 '@stacks/stacks-blockchain-api-types': 7.14.1
'@stacks/transactions': 7.0.5 '@stacks/transactions': 7.0.5
axios: 1.8.3 axios: 1.9.0
lodash: 4.17.21 lodash: 4.17.21
yargs: 17.7.2 yargs: 17.7.2
yqueue: 1.0.1 yqueue: 1.0.1

View File

@@ -4,6 +4,14 @@ import { EVMEndpointContract } from "../evmUtils/evmContractAddresses"
import { BigNumber } from "../utils/BigNumber" import { BigNumber } from "../utils/BigNumber"
import { InvalidMethodParametersError } from "../utils/errors" 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 SDKBrandedLiteral<
Type extends string, Type extends string,
T extends string | number, T extends string | number,

View File

@@ -1,6 +1,11 @@
{ {
"$schema": "https://json.schemastore.org/tsconfig.json", "$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": { "compilerOptions": {
"module": "esnext", "module": "esnext",
"target": "esnext", "target": "esnext",