安装
pnpm add @bigmi/core
配置
客户端配置
客户端是 Bigmi 的核心。以下是配置方法:import { createClient, bitcoin, blockchair, ankr, fallback } from '@bigmi/core'
const client = createClient({
chain: bitcoin,
transport: fallback([
blockchair(),
ankr({apiKey: 'YOUR_ANKR_API_KEY'})
]),
// Additional parameters
})
参数
| 参数 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|
chain | 否 | - | 此客户端将在其上执行操作的链/网络。该库导出了 bitcoin 和 signet 网络,也可以使用 defineChain 工具函数创建自定义链。 |
transport | 是 | - | 这是一个通过 HTTP 访问的 JSON-RPC 服务,用于与区块链通信。 |
account | 否 | - | 供客户端执行操作的账户或地址。 |
pollingInterval | 否 | 4,000ms | 轮询操作或事件的频率。 |
cacheTime | 否 | pollingInterval | 4,000ms | 客户端缓存响应的时长。 |
key | 否 | ’base’ | 客户端的键。 |
name | 否 | ’Base Client’ | 客户端的名称。 |
type | 否 | ’base’ | 客户端的类型。 |
rpcSchema | 否 | - | 客户端的类型化 JSON-RPC schema。 |
传输配置
Bigmi 支持通过 HTTP 使用的 JSON-RPC 端点。 Bigmi 还包含封装了 Blockchair、Blockcypher、Ankr 和 Mempool API 的传输,用于区块链读取操作。 这些传输大多可免费使用,但有 API 调用限制。对于生产环境场景,可以使用apiKey 和 baseUrl 进行配置。
建议使用封装了多个传输的 fallback 传输,以获得更好的可靠性。
import { createClient, bitcoin, blockchair, ankr, fallback, mempool, http } from '@bigmi/core'
const client = createClient({
chain: bitcoin,
transport: fallback([
blockchair(),
ankr({apiKey: 'YOUR_ANKR_API_KEY'}),
mempool(),
http() // It defaults to the chain's public RPC URL.
]),
})
UTXO-API 传输参数
这些包括基于 API 的传输blockchair、ankr、mempool 和 blockcypher。
由于这些是对 HTTP 传输的封装,它们也可以使用任意 HTTP 传输配置参数进行配置。
| 参数 | 是否必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
apiKey | 否 | string | - | 服务的 API 密钥。 |
baseUrl | 否 | string | - | API 的基础 URL。 |
HTTP 传输配置参数
| 参数 | 是否必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
key | 否 | string | ’http’ | 传输的键。 |
name | 否 | string | ’HTTP’ | 传输的名称。 |
rank | 否 | boolean | RankOptions | false | 如果为 true,传输将按延迟排序。可提供选项来自定义排序行为。 |
retryCount | 否 | number | 3 | 放弃前重试请求的次数。 |
retryDelay | 否 | number | 150 | 重试之间的延迟(毫秒)。 |
timeout | 否 | number | 10,000ms | 等待响应的最长时间。 |
raw | 否 | boolean | false | 如果为 true,JSON-RPC 错误将作为响应的一部分返回,而不是被抛出。 |
onFetchRequest | 否 | function | - | 用于拦截 fetch 请求的回调函数。 |
onFetchResponse | 否 | function | - | 用于拦截 fetch 响应的回调函数。 |
fetchOptions | 否 | object | - | 传递给请求的 fetch 选项。 |
methods | 否 | {include?: method[], exclude?: method[]} | - | 在此传输中包含或排除的方法。 |
Fallback 传输配置参数
| 参数 | 是否必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
key | 否 | string | ’fallback’ | 传输的键。 |
name | 否 | string | ’Fallback’ | 传输的名称。 |
rank | 否 | boolean | RankOptions | false | 如果为 true,传输将按延迟排序。可提供选项来自定义排序行为。 |
retryCount | 否 | number | 3 | 放弃前重试请求的次数。 |
retryDelay | 否 | number | 150 | 在回退到下一个传输之前,重试之间的延迟(毫秒)。 |
shouldThrow | 否 | function | - | 当某个传输抛出错误时,此谓词决定是回退到下一个传输还是结束执行。 |
链配置
Bigmi 内置了主网和 signet 链定义。import { createClient, bitcoin, signet, http, mempool, fallback } from '@bigmi/core'
const mainnetClient = createClient({
chain: bitcoin,
transport: fallback([
mempool(),
http()
])
})
const testnetClient = createClient({
chain: signet,
transport: fallback([
mempool({baseUrl: 'https://mempool.space/signet/api'}),
http()
])
})
自定义链
可以使用defineChain 工具函数创建自定义链。
import { defineChain, createClient, ChainId, ankr, mempool, http, fallback } from '@bigmi/core'
const testnet4 = defineChain({
id: ChainId.Testnet4,
name: 'Bitcoin Testnet4',
nativeCurrency: { name: 'Bitcoin', symbol: 'BTC', decimals: 8 },
rpcUrls: {
default: {
http: ['https://bitcoin-testnet-rpc.publicnode.com'],
},
},
blockExplorers: {
default: {
name: 'Mempool',
url: 'https://mempool.space/testnet4/',
},
},
testnet: true
})
const testnet4Client = createClient({
chain: testnet4,
transport: fallback([
ankr({apiKey: 'YOUR_ANKR_API_KEY'}),
mempool({ baseUrl: 'https://mempool.space/testnet4/api' }),
http()
]),
})
Actions
Bigmi 包含许多称为 action 的函数,可用于执行各种区块链操作。读取区块链数据
import { getBalance, getTransaction, getBlockCount } from '@bigmi/core'
import { client } from './client.ts'
// check address balance
const address = 'some_address'
const balance = await getBalance(client, { address })
console.log('Balance:', balance)
// get transaction
const txId = 'some_tx'
const tx = await getTransaction(client, { txId })
console.log('Transaction:', tx)
// get the latest block
const blockCount = await getBlockCount(client)
console.log('Current block:', blockCount)
import { createClient, bitcoin, http, fallback, mempool } from '@bigmi/core'
export const client = createClient({
chain: bitcoin,
transport: fallback([
mempool(),
http()
])
})
创建并发送 Bitcoin 交易
import { sendBitcoin } from './sendBitcoin.ts'
import { client } from './client.ts'
const privateKey = Buffer.from('0xgf.....', 'hex')
const fromAddress = 'b1qc....'
const toAddress = 'b1qer..'
const amount = 10000 // in sats, equivalent to 0.0001 BTC
// send bitcoin to another address
const { txId, confirmed, fee } = await sendBitcoin(client, fromAddress, toAddress, amount, privateKey)
console.log({
txId,
confirmed,
fee
})
import { createClient, bitcoin, http, fallback, mempool } from '@bigmi/core'
export const client = createClient({
chain: bitcoin,
transport: fallback([
mempool(),
http()
])
})
import * as bitcoin from 'bitcoinjs-lib';
import * as ecc from '@bitcoinerlab/secp256k1'
import { createClient, getBalance, getUTXOs, sendUTXOTransaction, waitForTransaction, estimateFee, type Client } from '@bigmi/core';
export async function sendBitcoin(
client: Client,
fromAddress: string,
toAddress: string,
amount: number,
privateKey: Buffer
) {
try {
// Check balance
const balance = await getBalance(client, { address: fromAddress });
// Add a 1000 sats buffer for transaction fees
if (balance < amount + 1000) {
throw new Error('Insufficient balance');
}
// Get UTXOs
const utxos = await getUTXOs(client, {
address: fromAddress,
// Add a 1000 sats buffer for transaction fees
minValue: amount + 1000,
});
if (utxos.length === 0) {
throw new Error('No UTXOs available');
}
//init ECC lib
bitcoin.initEccLib(ecc)
// Create transaction
const psbt = new bitcoin.Psbt();
let totalInput = 0;
for (const utxo of utxos) {
psbt.addInput({
hash: utxo.txId,
index: utxo.vout,
witnessUtxo: {
script: Buffer.from(utxo.scriptHex, 'hex'),
value: utxo.value,
},
});
totalInput += utxo.value;
}
// Add outputs
psbt.addOutput({
address: toAddress,
value: amount,
});
// Calculate fee and change
const fee = await estimateFee(client, utxos.length, 2);
const change = totalInput - amount - fee;
if (change < 0) {
throw new Error('Insufficient funds for fee');
}
if (change > 546) { // Dust threshold
psbt.addOutput({
address: fromAddress,
value: change,
});
}
// Sign and finalize
const keyPair = bitcoin.ECPair.fromPrivateKey(privateKey);
psbt.signAllInputs(keyPair);
psbt.finalizeAllInputs();
// Get transaction hex
const txHex = psbt.extractTransaction().toHex();
// Broadcast with Bigmi
const txId = await sendUTXOTransaction(client, { hex: txHex });
// Wait for confirmation
const confirmed = await waitForTransaction(client, {
txId,
txHex,
senderAddress: fromAddress,
confirmations: 1,
});
return {
txId,
fee,
confirmed,
};
} catch (error) {
console.error('Transaction failed:', error);
throw error;
}
}

