@anywalletkit/wallet-btc

中文文档
0.4.1发布于 2026/11/03Apache-2.0TypeScriptESM + CJS构建来源已验证近 30 天下载 2304

Bitcoin wallet for Any Wallet Kit on @scure/btc-signer: BIP-84 p2wpkh and BIP-86 taproot accounts, own coin selection, RBF, Blockbook/Esplora transports.

原始使用文档
文档目录6 节
  1. Install
  2. What a spend is
  3. Safety checks
  4. Message signing
  5. Transports
  6. Activity history

@anywalletkit/wallet-btc

npm

Bitcoin accounts on @scure/btc-signer (audited by Cure53; pure Uint8Array, no Buffer, no Node shims):

Install

npm install @anywalletkit/wallet-btc
# or: pnpm add @anywalletkit/wallet-btc  ·  yarn add @anywalletkit/wallet-btc

On npm: @anywalletkit/wallet-btc, published from the release workflow with provenance.

addressTypePathAddressStandard
p2wpkh (default)m/84'/0'/0'/0/ibc1q…BIP-84 native segwit
p2trm/86'/0'/0'/0/ibc1p…BIP-86 key-path taproot

Test networks use coin type 1' (tb1… / bcrt1…). Both paths are pinned by the official BIP-84 / BIP-86 test vectors.

import WalletManagerBtc from '@anywalletkit/wallet-btc'

const wallet = new WalletManagerBtc(seedPhrase, {
  network: 'bitcoin',
  addressType: 'p2wpkh',                       // or 'p2tr'
  client: [
    { type: 'blockbook-http', clientConfig: { url: 'https://btc1.trezor.io' } },
    { type: 'esplora-http', clientConfig: { url: 'https://mempool.space/api' } }, // fails over in order
  ],
  maxFeeRate: 200,                             // sat/vB ceiling (default 500)
})
const account = await wallet.getAccount(0)

const preview = await account.describeTransaction({ to: 'bc1q…', value: 50_000n })
//   { kind: 'btc-transfer', inputs, outputs: [{ role: 'recipient' | 'change' }], fee, feeRate, vsize, rbf, lockTime, warnings }

await account.transfer({ recipient: 'bc1q…', amount: 50_000n })             // sats
await account.sendTransaction({ to: 'bc1q…', value: 50_000n, feeRate: 12n }) // explicit sat/vB
const hex = await account.signTransaction({ to: 'bc1q…', value: 50_000n })   // sign only
const max = await account.getMaxSpendable()                                  // sweep amount after fee
wallet.dispose()

What a spend is

Coin selection is our own (selectCoins, coinselect.ts): effective-value accumulation, largest first; inputs that cannot pay for themselves are skipped; change below dust (294 sat p2wpkh / 330 sat p2tr) is folded into the fee; at most maxInputs (200) inputs. Fees are feeRate × vsize with the standard segwit weights, estimated with 72-byte signatures so the quote is never below the fee actually paid.

Transactions signal replace-by-fee (rbf, default on) and set nLockTime to the current tip (antiFeeSniping, default on when the transport can report the height).

Safety checks

A broadcast with no definitive answer (fetch threw, a timeout, a 5xx or 408, an unreadable body) throws BroadcastUnknownError (maybeSent, hash = the txid computed before sending): the transaction may be in the mempool, so do not build another spend. A node's refusal (4xx with a reason, an error body) stays an error marked answered (isAnsweredRefusal); with several clients it is a refusal only when every one refused. "Already in the mempool / block chain" returns the txid. A custom BtcClient should mark refusals answered: true. Outputs are matched to recipient and change by script.

Before signing and before broadcasting — also for caller-supplied raw hex — every transaction is resolved into a BtcTxDescription and must pass:

  • fee rate ≤ maxFeeRate (UnsafeTransactionError('fee-rate-too-high'));
  • exactly one output equals the requested recipient + amount, every other output is our own change ('unexpected-output', 'recipient-mismatch', 'change-not-ours');
  • transactionMaxFee / transferMaxFee absolute caps.

Warnings that do not block: high-fee-rate, fee-over-10pct-of-amount, dust-output, no-change.

Message signing

sign() / verify() are BIP-137 for p2wpkh accounts (header 39 + recovery, base64 — the Electrum / Bitcoin Core encoding). Taproot accounts have no BIP-137 form; sign() throws UnsupportedAddressTypeError (BIP-322 is not implemented).

Transports

blockbook-http (Trezor Blockbook REST, QuickNode's add-on) and esplora-http (mempool.space, blockstream.info). Requests time out after timeoutMs (15 s) and responses are shape-checked (NetworkError otherwise). Pass your own object implementing BtcClient for anything else.

Activity history

createBtcHistory is the chain's HistorySource (@anywalletkit/core) over Blockbook, reusing BlockbookClient (getAddressPage, getTransactionDetails).

import { createBtcHistory } from '@anywalletkit/wallet-btc/history'

const history = createBtcHistory({ blockbookUrls: ['https://btc1.trezor.io', 'https://bitcoin.atomicwallet.io'] })
const page = await history.listActivity('bc1q3x8yszvcvjjxqragsh0l6j8rxnhk7pay9hnj5h', { limit: 25 })
const older = await history.listActivity(address, { cursor: page.cursor })
const one = await history.getTransaction(page.items[0].hash, address)
history.explorerTxUrl(one.hash) // https://mempool.space/tx/…
optiondefaultnotes
blockbookUrl / blockbookUrls—Blockbook roots, tried in order (Cloudflare 403, 5xx, network → next). The Trezor instances (btc1…5.trezor.io) sit behind a Cloudflare challenge that blocks non-browser user agents; bitcoin.atomicwallet.io and blockbook.btc.zelcore.io answered on 2026-10-14. QuickNode's Blockbook add-on speaks the same API.
networkbitcointestnet / regtest CAIP-2 ids; mempool.space testnet links.
pageSizethe query limit, ≤ 100Rows per Blockbook page (its max is 1000).
fetch, timeoutMsglobal, 15 000

Endpoint. GET /api/v2/address/{a}?details=txs&page=&pageSize= — Blockbook returns transactions newest first with inputs and outputs (hex is dropped). The cursor is base64 JSON { v: 1, p, s }: the next page and the page size the pagination started with (Blockbook clamps out-of-range pages to the last one, so paging stops at totalPages). since is applied client-side; unconfirmed rows are always kept.

Mapping. Inputs the address spent (ownIn) and outputs it received (ownOut) are summed. Spent inputs → a send: from = address, to = the first output that is not ours, nativeValue = what left to non-own outputs (change ignored, fee separate); every output ours → a consolidation to itself. No spent inputs → a receive: from = the first input address (coinbase when none), nativeValue = ownOut. transfers is that one native leg, fee = fees, status = confirmed once confirmations ≥ 1 (else pending, no block), block = blockHeight, raw = the Blockbook transaction plus ownIn / ownOut.

Fixtures in test/fixtures/history/ were captured on 2026-10-14 from bitcoin.atomicwallet.io for the test address (its 4 transactions: two receives, two sends with change) and GET /api/v2/tx/{txid} of one send. No protocol module recognizes Bitcoin transactions, so there is no recognizer cross-check.

版本与发布记录

@anywalletkit/wallet-btc 共发布 12 个版本,首次发布于 2026/10/25;过去 12 个月发布了 12 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.4.1latest2026/11/035 天前
0.4.02026/10/309 天前
0.3.22026/10/2810 天前
0.3.12026/10/2811 天前
0.3.02026/10/2712 天前
0.2.52026/10/2612 天前

关于 @anywalletkit/wallet-btc 的常见问题

@anywalletkit/wallet-btc 是什么?

Bitcoin wallet for Any Wallet Kit on @scure/btc-signer: BIP-84 p2wpkh and BIP-86 taproot accounts, own coin selection, RBF, Blockbook/Esplora transports.

如何安装 @anywalletkit/wallet-btc?

在项目目录运行 npm install @anywalletkit/wallet-btc,或使用 pnpm add / yarn add / bun add。

@anywalletkit/wallet-btc 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@anywalletkit/wallet-btc 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@anywalletkit/wallet-btc 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@anywalletkit/wallet-btc 可以商用吗?

@anywalletkit/wallet-btc 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@anywalletkit/wallet-btc 的下载量有多少?

根据 npm 官方下载统计,@anywalletkit/wallet-btc 在 2026/10/06 – 2026/11/04 这 30 天内被下载 2,304 次,日均约 77 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@anywalletkit/wallet-btc 还在维护吗?

最新版本 0.4.1 发布于 2026/11/03(5 天前);至今共发布 12 个版本,其中过去 12 个月发布了 12 个;首次发布于 2026/10/25。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。