@anywalletkit/wallet-btc 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -336,4 +336,4 @@ export {
336
336
  btcExplorerTxUrl,
337
337
  createBtcHistory
338
338
  };
339
- //# sourceMappingURL=chunk-TZNOUBSP.js.map
339
+ //# sourceMappingURL=chunk-SIR2SRK2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/blockbook.ts","../src/http.ts","../src/types.ts","../src/history.ts"],"sourcesContent":["import { NetworkError } from '@anywalletkit/core'\nimport { DEFAULT_TIMEOUT_MS, fetchWithTimeout, isIntString, isRecord, refusal, refusedStatus } from './http.js'\nimport type { BlockbookTx, BtcClient, Utxo } from './types.js'\n\nconst MEMPOOL_SPACE_URL = 'https://mempool.space'\n\nexport interface BlockbookVin { txid?: string; vout?: number; n?: number; isAddress?: boolean; isOwn?: boolean; addresses?: string[]; value?: string }\nexport interface BlockbookVout { n: number; isAddress?: boolean; isOwn?: boolean; addresses?: string[]; value?: string; spent?: boolean }\nexport interface BlockbookAddressTx { txid: string; blockHeight: number; vin?: BlockbookVin[]; vout?: BlockbookVout[] }\n/** A Blockbook transaction with its inputs and outputs (`/api/v2/tx/{txid}`, or one row of `?details=txs`). */\nexport interface BlockbookTxDetails extends BlockbookTx {\n vin?: BlockbookVin[]\n vout?: BlockbookVout[]\n value?: string\n valueIn?: string\n}\n/** One `/api/v2/address/{a}?details=txs` page. */\nexport interface BlockbookAddressPage {\n page?: number\n totalPages?: number\n itemsOnPage?: number\n address?: string\n balance?: string\n unconfirmedBalance?: string\n txs?: number\n transactions?: BlockbookTxDetails[]\n}\n\n/**\n * Pending outgoing value the way Bitcoin Core's wallet counts it: a pending tx\n * is trusted only if every input is ours and confirmed or chained from another\n * trusted tx; only then its change counts back.\n */\nexport function unconfirmedOutgoing(transactions: BlockbookAddressTx[] | undefined, address: string): bigint {\n const pending = (transactions ?? []).filter((tx) => tx.blockHeight === -1)\n const pendingIds = new Set(pending.map((t) => t.txid))\n const byId = new Map(pending.map((t) => [t.txid, t]))\n const trusted = new Map<string, boolean>()\n const owned = (entries: Array<BlockbookVin | BlockbookVout> | undefined) =>\n (entries ?? []).filter((e) => e.isAddress && e.addresses?.includes(address)).reduce((s, e) => s + BigInt(e.value ?? 0), 0n)\n const isTrusted = (tx: BlockbookAddressTx): boolean => {\n if (trusted.has(tx.txid)) return trusted.get(tx.txid)!\n trusted.set(tx.txid, false)\n const vins = tx.vin ?? []\n const ours = vins.filter((v) => v.isAddress && v.addresses?.includes(address))\n const ok = vins.length > 0 && ours.length === vins.length && ours.every((v) => !v.txid || !pendingIds.has(v.txid) || isTrusted(byId.get(v.txid)!))\n trusted.set(tx.txid, ok)\n return ok\n }\n const consumed = new Set<string>()\n for (const tx of pending) for (const v of tx.vin ?? []) if (v.txid && pendingIds.has(v.txid)) consumed.add(`${v.txid}:${v.vout}`)\n return pending.reduce((total, tx) => {\n const spent = owned((tx.vin ?? []).filter((v) => !v.txid || !pendingIds.has(v.txid)))\n const change = isTrusted(tx) ? owned((tx.vout ?? []).filter((o) => !consumed.has(`${tx.txid}:${o.n}`))) : 0n\n return total + (spent - change)\n }, 0n)\n}\n\n/** Blockbook REST transport (Trezor's indexer; QuickNode's Blockbook add-on speaks the same API). */\nexport class BlockbookClient implements BtcClient {\n private readonly base: string\n private readonly fetchFn: typeof fetch\n private readonly timeoutMs: number\n\n constructor(config: { url: string }, fetchFn: typeof fetch = globalThis.fetch, timeoutMs = DEFAULT_TIMEOUT_MS) {\n this.base = config.url.replace(/\\/+$/, '').replace(/\\/api$/, '')\n this.fetchFn = fetchFn\n this.timeoutMs = timeoutMs\n }\n\n async connect(): Promise<void> {}\n async close(): Promise<void> {}\n\n private async get<T>(path: string, check: (v: unknown) => v is T): Promise<T> {\n const url = `${this.base}/api${path}`\n const res = await fetchWithTimeout(this.fetchFn, url, undefined, this.timeoutMs, this.base)\n if (!res.ok) {\n // A 4xx (not 408) is the server refusing: nothing was taken. A 5xx may have been forwarded (round 3, M12).\n const reason = refusedStatus(res.status) ? (await res.text().catch(() => '')).slice(0, 200) : ''\n const err = new NetworkError(`Blockbook request failed: ${res.status} ${res.statusText} (${url})${reason ? `: ${reason}` : ''}`, { provider: this.base })\n throw refusedStatus(res.status) ? refusal(err) : err\n }\n let body: unknown\n try { body = await res.json() } catch (e) { throw new NetworkError(`Blockbook returned non-JSON for ${url}`, { provider: this.base, cause: e }) }\n if (!check(body)) throw new NetworkError(`Blockbook returned an unexpected shape for ${url}`, { provider: this.base })\n return body\n }\n\n async getBalance(address: string) {\n const data = await this.get(`/v2/address/${address}?details=txs`, (v): v is { balance: string; unconfirmedBalance: string; transactions?: BlockbookAddressTx[] } =>\n isRecord(v) && isIntString(v.balance) && isIntString(v.unconfirmedBalance) && (v.transactions === undefined || Array.isArray(v.transactions)))\n return { confirmed: BigInt(data.balance), unconfirmed: BigInt(data.unconfirmedBalance), unconfirmedOutgoing: unconfirmedOutgoing(data.transactions, address) }\n }\n\n async listUnspent(address: string): Promise<Utxo[]> {\n const data = await this.get(`/v2/utxo/${address}`, (v): v is Array<{ txid: string; vout: number; value: string; height?: number }> =>\n Array.isArray(v) && v.every((u) => isRecord(u) && typeof u.txid === 'string' && typeof u.vout === 'number' && isIntString(u.value)))\n return data.map((u) => ({ txid: u.txid, vout: u.vout, value: BigInt(u.value), height: u.height ?? -1 }))\n }\n\n async getHistory(address: string) {\n const items: Array<{ txid: string; height: number }> = []\n for (let page = 1; ; page++) {\n const data = await this.get(`/v2/address/${address}?details=txslight&pageSize=1000&page=${page}`, (v): v is { transactions?: Array<{ txid: string; blockHeight: number }>; totalPages?: number } =>\n isRecord(v) && (v.transactions === undefined || Array.isArray(v.transactions)))\n for (const tx of data.transactions ?? []) items.push({ txid: tx.txid, height: tx.blockHeight })\n if (page >= (data.totalPages ?? 1)) break\n }\n return items\n }\n\n /** One page of the address's transactions, newest first, with inputs / outputs (what the activity history reads). */\n async getAddressPage(address: string, page = 1, pageSize = 25): Promise<BlockbookAddressPage> {\n const data = await this.get(`/v2/address/${address}?details=txs&page=${page}&pageSize=${pageSize}`, (v): v is BlockbookAddressPage =>\n isRecord(v) && (v.transactions === undefined || (Array.isArray(v.transactions) && v.transactions.every(BlockbookClient.isTx))))\n const out: BlockbookAddressPage = { ...data }\n for (const tx of out.transactions ?? []) delete (tx as { hex?: string }).hex\n return out\n }\n\n /** A transaction with its inputs / outputs; undefined when Blockbook does not know it. */\n async getTransactionDetails(txid: string): Promise<BlockbookTxDetails | undefined> {\n try {\n const tx = await this.get(`/v2/tx/${txid}`, (v): v is BlockbookTxDetails => BlockbookClient.isTx(v))\n const out: BlockbookTxDetails = { ...tx }\n delete (out as { hex?: string }).hex\n return out\n } catch (e) {\n if (e instanceof NetworkError && /\\b(400|404)\\b/.test(e.message)) return undefined\n throw e\n }\n }\n\n private static isTx(v: unknown): v is BlockbookTx {\n return isRecord(v) && typeof v.txid === 'string' && typeof v.blockHeight === 'number' && typeof v.confirmations === 'number'\n }\n\n async getTransactionInfo(txid: string): Promise<BlockbookTx | undefined> {\n try { return await this.get(`/v2/tx/${txid}`, BlockbookClient.isTx) } catch (e) {\n if (e instanceof NetworkError && /\\b(400|404)\\b/.test(e.message)) return undefined\n throw e\n }\n }\n\n async getTransaction(txid: string): Promise<string> {\n const data = await this.get(`/v2/tx/${txid}`, BlockbookClient.isTx)\n if (typeof data.hex !== 'string' || !data.hex) throw new NetworkError(`Transaction ${txid} has no hex data`, { provider: this.base })\n return data.hex\n }\n\n async broadcast(rawTx: string): Promise<string> {\n const data = await this.get(`/v2/sendtx/${rawTx}`, (v): v is { result?: string; error?: { message?: string } | string } => isRecord(v))\n if (data.error) throw refusal(new Error(typeof data.error === 'string' ? data.error : data.error.message ?? 'broadcast failed'))\n if (!data.result) throw new NetworkError('Blockbook returned no txid', { provider: this.base })\n return data.result\n }\n\n /** sat/vB. Blockbook reports BTC/kB (×1e5 → sat/vB); falls back to mempool.space when it has no estimate. */\n async estimateFee(blocks: number): Promise<number> {\n try {\n const data = await this.get(`/v1/estimatefee/${blocks}`, (v): v is { result?: string } | string => typeof v === 'string' || isRecord(v))\n const rate = Number(typeof data === 'string' ? data : data.result)\n if (rate > 0) return Math.max(rate * 100_000, 1)\n } catch { /* fall through */ }\n const res = await fetchWithTimeout(this.fetchFn, `${MEMPOOL_SPACE_URL}/api/v1/fees/recommended`, undefined, this.timeoutMs, MEMPOOL_SPACE_URL)\n if (!res.ok) throw new NetworkError('Fee estimation request failed', { provider: MEMPOOL_SPACE_URL })\n const d = (await res.json()) as { fastestFee: number; halfHourFee: number; hourFee: number; economyFee: number }\n const satPerVb = blocks <= 1 ? d.fastestFee : blocks <= 3 ? d.halfHourFee : blocks <= 6 ? d.hourFee : d.economyFee\n if (!satPerVb || satPerVb <= 0) throw new NetworkError('Fee estimation is unavailable', { provider: MEMPOOL_SPACE_URL })\n return satPerVb\n }\n\n async getBlockHeight(): Promise<number> {\n const data = await this.get('/v2', (v): v is { blockbook?: { bestHeight?: number } } => isRecord(v))\n const h = data.blockbook?.bestHeight\n if (typeof h !== 'number' || h <= 0) throw new NetworkError('Blockbook did not report a block height', { provider: this.base })\n return h\n }\n}\n","import { NetworkError } from '@anywalletkit/core'\n\nexport const DEFAULT_TIMEOUT_MS = 15_000\n\n/** fetch with a per-request timeout when the runtime has `AbortSignal.timeout` (Hermes needs runtime-hermes for it). */\nexport async function fetchWithTimeout(fetchFn: typeof fetch, url: string, init: RequestInit | undefined, timeoutMs: number, provider: string): Promise<Response> {\n const signal = typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function' ? AbortSignal.timeout(timeoutMs) : undefined\n try {\n return await fetchFn(url, { ...init, ...(signal ? { signal } : {}) })\n } catch (e) {\n throw new NetworkError(`Request failed: ${url}`, { provider, cause: e })\n }\n}\n\n/** An HTTP status that is the server refusing the request itself: 4xx, but not 408 (request timeout). */\nexport const refusedStatus = (status: number): boolean => status >= 400 && status < 500 && status !== 408\n\n/** Mark an error as a node's answer refusing the request: nothing was taken (round 3, M12). */\nexport function refusal<E extends Error>(e: E): E {\n return Object.assign(e, { answered: true })\n}\n\n/**\n * An endpoint answered with a refusal (HTTP 4xx other than 408, or an error body): nothing was\n * taken. A thrown fetch, a timeout, a 5xx or a body that cannot be read may have been.\n */\nexport function isAnsweredRefusal(e: unknown): boolean {\n return (e as { answered?: unknown } | null)?.answered === true\n}\n\n/** The node says it already holds the transaction (an earlier attempt delivered it): it is out, not refused. */\nexport function isAlreadyKnown(e: unknown): boolean {\n for (let x: unknown = e, depth = 0; x instanceof Error && depth < 5; x = x.cause, depth++) {\n if (/txn-already-(in-mempool|known)|already (known|in (the )?(mempool|block ?chain))/i.test(x.message)) return true\n }\n return false\n}\n\nexport const isRecord = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v)\nexport const isHex64 = (v: unknown): v is string => typeof v === 'string' && /^[0-9a-fA-F]{64}$/.test(v)\nexport const isIntString = (v: unknown): v is string => typeof v === 'string' && /^-?\\d+$/.test(v)\n","/** Bitcoin mainnet, testnet or regtest. */\nexport type BtcNetwork = 'bitcoin' | 'testnet' | 'regtest'\n\n/** Address / script type the account spends from. BIP-84 p2wpkh (bc1q…) or BIP-86 p2tr (bc1p…). */\nexport type BtcAddressType = 'p2wpkh' | 'p2tr'\n\n/** Minimal chain-data client every transport implements. Values in satoshis, fee rates in sat/vB. */\nexport interface BtcClient {\n connect(): Promise<void>\n close(): Promise<void>\n getBalance(address: string): Promise<{ confirmed: bigint; unconfirmed: bigint; unconfirmedOutgoing?: bigint }>\n listUnspent(address: string): Promise<Utxo[]>\n getHistory(address: string): Promise<Array<{ txid: string; height: number }>>\n /** Raw transaction hex. */\n getTransaction(txid: string): Promise<string>\n /** Full tx record (used for receipts). */\n getTransactionInfo?(txid: string): Promise<BlockbookTx | undefined>\n /** Broadcast raw hex; returns the txid. */\n broadcast(rawTx: string): Promise<string>\n /** Fee rate in sat/vB for confirmation within `blocks`. */\n estimateFee(blocks: number): Promise<number>\n /** Current chain tip height (anti-fee-sniping locktime). Optional. */\n getBlockHeight?(): Promise<number>\n}\n\n/** An unspent output the account can spend. */\nexport interface Utxo {\n txid: string\n vout: number\n /** Satoshis. */\n value: bigint\n /** Block height; 0 or -1 while unconfirmed. */\n height: number\n}\n\n/** One transport to a Bitcoin indexer: Blockbook or Esplora over HTTP. */\nexport type BtcClientConfig =\n /** Trezor Blockbook REST (`https://btc1.trezor.io`, QuickNode's Blockbook add-on, …). */\n | { type: 'blockbook-http'; clientConfig: { url: string } }\n /** Esplora REST (`https://mempool.space/api`, `https://blockstream.info/api`). */\n | { type: 'esplora-http'; clientConfig: { url: string } }\n\n/**\n * Options for a Bitcoin wallet manager or account: transports, network, address type and fee\n * limits.\n */\nexport interface BtcConfig {\n /** One or more transports (config objects or ready `BtcClient`s). A list fails over in order. Omit for an offline (sign-only) wallet. */\n client?: BtcClientConfig | BtcClient | Array<BtcClientConfig | BtcClient>\n /** Network; default `bitcoin` (mainnet). */\n network?: BtcNetwork\n /** p2wpkh (BIP-84, default) or p2tr (BIP-86 taproot). Changes the derivation path and the address. */\n addressType?: BtcAddressType\n /** Extra attempts across the client list after the first failure (default 3). */\n retries?: number\n /** Per-request timeout in ms (default 15000). */\n timeoutMs?: number\n /** Max fee (sats) for `transfer`. */\n transferMaxFee?: bigint | number\n /** Max fee (sats) for `sendTransaction` / `signTransaction`. */\n transactionMaxFee?: bigint | number\n /** Fee-rate ceiling in sat/vB (default 500). Anything above is refused before signing or broadcast. */\n maxFeeRate?: number\n /** Coin-selection input cap (default 200). */\n maxInputs?: number\n /** Opt-in to replace-by-fee signalling (default true). */\n rbf?: boolean\n /** Set nLockTime to the current height so the tx cannot be mined into a reorg (default true; skipped when the transport has no `getBlockHeight`). */\n antiFeeSniping?: boolean\n /** Injectable fetch (tests, custom agents). Defaults to globalThis.fetch. */\n fetch?: typeof fetch\n}\n\n/** A spend. `value` in satoshis; `feeRate` in sat/vB (estimated for `confirmationTarget` blocks when omitted). */\nexport interface BtcSpend {\n to: string\n value: bigint | number | string\n feeRate?: bigint | number\n confirmationTarget?: number\n /** Override the account-level `rbf` default for this spend. */\n rbf?: boolean\n}\n\n/** `sendTransaction` accepts a spend or an already signed raw transaction hex. */\nexport type BtcTransaction = BtcSpend | string\n\n/** A Bitcoin transfer. Amount in satoshis. */\nexport interface BtcTransferOptions {\n /** Not supported on Bitcoin; present for the shared account interface. */\n token?: string\n recipient: string\n amount: bigint | number | string\n}\n\n/** A mined Bitcoin transaction. */\nexport interface BtcReceipt {\n hash: string\n /** Always 1 once mined — a Bitcoin transaction cannot fail after inclusion. */\n status: 1\n blockNumber: bigint\n confirmations: number\n /** Total fee in sats (when the transport reports it). */\n fee?: bigint\n hex?: string\n}\n\n/** Transport-neutral tx record (Blockbook's /api/v2/tx shape; Esplora is mapped onto it). */\nexport interface BlockbookTx {\n txid: string\n blockHeight: number\n confirmations: number\n fees?: string\n hex?: string\n blockTime?: number\n}\n\n/** The most one transaction can send (a sweep of every UTXO), after the fee. */\nexport interface BtcMaxSpendableResult {\n /** Max sats one transaction can send after the fee. 0n when nothing is spendable. */\n amount: bigint\n fee: bigint\n /** Always 0n: a sweep leaves no change. */\n changeValue: bigint\n /** Inputs the sweep would consume. */\n inputs: number\n feeRate: bigint\n}\n\n/** Problems a described transaction is flagged with. */\nexport type BtcWarning =\n /** Fee rate above `maxFeeRate` (also a hard error before signing/broadcast). */\n | 'high-fee-rate'\n /** Fee exceeds 10 % of the amount sent. */\n | 'fee-over-10pct-of-amount'\n /** An output is below its dust threshold. */\n | 'dust-output'\n /** Change was below dust and folded into the fee. */\n | 'no-change'\n\n/** One input of a described transaction: the UTXO it spends. */\nexport interface BtcTxInputDescription {\n txid: string\n vout: number\n value: bigint\n}\n\n/** One output of a described transaction, tagged as the recipient, our change, or unknown. */\nexport interface BtcTxOutputDescription {\n /** Undefined for scripts without an address form. */\n address: string | undefined\n value: bigint\n role: 'recipient' | 'change' | 'unknown'\n}\n\n/** \"What you sign\": the fully resolved transaction before (or after) signing. */\nexport interface BtcTxDescription {\n kind: 'btc-transfer'\n inputs: BtcTxInputDescription[]\n outputs: BtcTxOutputDescription[]\n /** Sats sent to non-change outputs. */\n amount: bigint\n fee: bigint\n /** sat/vB, rounded to 2 decimals. */\n feeRate: number\n vsize: number\n rbf: boolean\n lockTime: number\n /** Present once the transaction is signed. */\n txid?: string\n warnings: BtcWarning[]\n}\n\n/** CAIP-2 ids of the Bitcoin networks, by name. */\nexport const CAIP2_GENESIS: Record<BtcNetwork, string> = {\n bitcoin: 'bip122:000000000019d6689c085ae165831e93',\n testnet: 'bip122:000000000933ea01ad0ee984209779ba',\n regtest: 'bip122:0f9188f13cb7b2c71f2a335e3a4fc328',\n}\n","/**\n * Activity history for Bitcoin: a `HistorySource` over Blockbook's\n * `/api/v2/address/{a}?details=txs` pages (Trezor's indexer, QuickNode's\n * Blockbook add-on, any self-hosted instance), reusing the package's\n * `BlockbookClient` and failing over across several instances.\n *\n * One transaction = one native transfer in the owner's direction: a send is\n * what left to non-own outputs (fee separate), a receive is what landed on the\n * address. The cursor is the Blockbook page number. Explorer: mempool.space.\n */\nimport type { ChainTransfer, ChainTx, HistoryPage, HistoryQuery, HistorySource } from '@anywalletkit/core'\nimport { BlockbookClient, type BlockbookAddressPage, type BlockbookTxDetails } from './blockbook.js'\nimport { DEFAULT_TIMEOUT_MS } from './http.js'\nimport { CAIP2_GENESIS, type BtcNetwork } from './types.js'\n\n// ── Public types ─────────────────────────────────────────────────────────────\n\n/** Options for {@link createBtcHistory}. */\nexport interface BtcHistoryOptions {\n /** One Blockbook root (`https://btc1.trezor.io`). */\n blockbookUrl?: string\n /** Several roots, tried in order (failover). */\n blockbookUrls?: string[]\n /** `bitcoin` (default), `testnet`, `regtest`. */\n network?: BtcNetwork\n fetch?: typeof fetch\n /** Per request, ms. Default 15 000. */\n timeoutMs?: number\n /** Rows per Blockbook page (its max is 1000). Default: the query limit, capped at 100. */\n pageSize?: number\n}\n\n/** What a Bitcoin `ChainTx` was built from, and the address's own totals. */\nexport interface BtcHistoryRaw {\n /** The Blockbook transaction (vin / vout with addresses and values; `hex` dropped). */\n tx: BlockbookTxDetails\n /** Sum of inputs spent by the address, sats. */\n ownIn: bigint\n /** Sum of outputs paid to the address, sats. */\n ownOut: bigint\n}\n\n/** A `ChainTx` with the Blockbook transaction it was built from. */\nexport interface BtcChainTx extends ChainTx {\n raw: BtcHistoryRaw\n}\n\n/** One page of Bitcoin history. */\nexport interface BtcHistoryPage extends HistoryPage {\n items: BtcChainTx[]\n /** Blockbook page served / total pages. */\n page?: number\n totalPages?: number\n}\n\n/** Bitcoin history from a Blockbook instance. Build it with {@link createBtcHistory}. */\nexport interface BtcHistorySource extends HistorySource {\n listActivity(address: string, query?: HistoryQuery): Promise<BtcHistoryPage>\n getTransaction(hash: string, address: string): Promise<BtcChainTx | undefined>\n}\n\n/** Every configured Blockbook endpoint failed (or none was configured). */\nexport class HistoryUnavailableError extends Error {\n readonly chain: string\n readonly reason: string\n readonly attempts: readonly string[]\n constructor(chain: string, reason: string, attempts: readonly string[] = []) {\n super(`History unavailable for ${chain}: ${reason}`)\n this.name = 'HistoryUnavailableError'\n this.chain = chain\n this.reason = reason\n this.attempts = attempts\n }\n}\n\nconst DEFAULT_LIMIT = 25\nconst MAX_PAGE_SIZE = 100\n\n// ── Cursor: the next Blockbook page, base64 JSON ─────────────────────────────\n\n/** @internal Decoded form of a Bitcoin history cursor. */\nexport interface BtcHistoryCursor {\n v: 1\n /** Next page (1-based). */\n p: number\n /** Page size the pagination started with (changing it mid-way would skip or repeat rows). */\n s: number\n}\n\nconst B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n\nfunction b64encode(s: string): string {\n let out = ''\n for (let i = 0; i < s.length; i += 3) {\n const c = [s.charCodeAt(i), s.charCodeAt(i + 1), s.charCodeAt(i + 2)]\n const n = (c[0]! << 16) | ((c[1]! || 0) << 8) | (c[2]! || 0)\n out += B64[(n >> 18) & 63]! + B64[(n >> 12) & 63]! + (Number.isNaN(c[1]) ? '=' : B64[(n >> 6) & 63]!) + (Number.isNaN(c[2]) ? '=' : B64[n & 63]!)\n }\n return out\n}\n\nfunction b64decode(s: string): string {\n const clean = s.replace(/[^A-Za-z0-9+/]/g, '')\n let out = ''\n for (let i = 0; i < clean.length; i += 4) {\n const c = [0, 1, 2, 3].map((k) => (i + k < clean.length ? B64.indexOf(clean[i + k]!) : -1))\n if (c[0]! < 0 || c[1]! < 0) throw new Error('bad base64')\n const n = (c[0]! << 18) | (c[1]! << 12) | ((c[2]! < 0 ? 0 : c[2]!) << 6) | (c[3]! < 0 ? 0 : c[3]!)\n out += String.fromCharCode((n >> 16) & 0xff)\n if (c[2]! >= 0) out += String.fromCharCode((n >> 8) & 0xff)\n if (c[3]! >= 0) out += String.fromCharCode(n & 0xff)\n }\n return out\n}\n\nexport function encodeCursor(c: BtcHistoryCursor): string {\n return b64encode(JSON.stringify(c))\n}\n\nexport function decodeCursor(s: string): BtcHistoryCursor {\n let parsed: unknown\n try {\n parsed = JSON.parse(b64decode(s))\n } catch {\n throw new Error('@anywalletkit/wallet-btc: malformed history cursor')\n }\n const c = parsed as Partial<BtcHistoryCursor> | null\n if (!c || c.v !== 1 || !Number.isInteger(c.p) || (c.p as number) < 1 || !Number.isInteger(c.s) || (c.s as number) < 1) throw new Error('@anywalletkit/wallet-btc: malformed history cursor')\n return { v: 1, p: c.p as number, s: c.s as number }\n}\n\n// ── Mapping ──────────────────────────────────────────────────────────────────\n\nconst big = (v: unknown): bigint => (typeof v === 'string' && /^-?\\d+$/.test(v) ? BigInt(v) : typeof v === 'number' ? BigInt(Math.trunc(v)) : 0n)\n\nexport function mapBlockbookTx(chain: string, address: string, tx: BlockbookTxDetails): BtcChainTx {\n const owns = (e: { isAddress?: boolean; addresses?: string[] }) => e.isAddress !== false && (e.addresses ?? []).includes(address)\n let ownIn = 0n, ownOut = 0n, sentToOthers = 0n\n for (const vin of tx.vin ?? []) if (owns(vin)) ownIn += big(vin.value)\n for (const vout of tx.vout ?? []) {\n if (owns(vout)) ownOut += big(vout.value)\n else sentToOthers += big(vout.value)\n }\n const firstInput = (tx.vin ?? []).find((v) => v.isAddress !== false && v.addresses?.[0])?.addresses?.[0]\n const firstOtherOutput = (tx.vout ?? []).find((v) => v.isAddress !== false && !owns(v) && v.addresses?.[0])?.addresses?.[0]\n const transfers: ChainTransfer[] = []\n let from: string, to: string | null, nativeValue: bigint\n if (ownIn > 0n) {\n // We spent inputs: a send (or a consolidation when every output is ours).\n from = address\n to = firstOtherOutput ?? address\n nativeValue = firstOtherOutput ? sentToOthers : ownOut\n if (nativeValue > 0n) transfers.push({ token: null, from: address, to, amount: nativeValue })\n } else {\n // Only outputs are ours: a receive (coinbase has no input address).\n from = firstInput ?? 'coinbase'\n to = address\n nativeValue = ownOut\n if (nativeValue > 0n) transfers.push({ token: null, from, to: address, amount: nativeValue })\n }\n const confirmed = tx.confirmations > 0 && tx.blockHeight > 0\n const out: BtcChainTx = {\n chain, hash: tx.txid, time: tx.blockTime ?? 0, status: confirmed ? 'confirmed' : 'pending', address, from, to, nativeValue, transfers,\n raw: { tx, ownIn, ownOut },\n }\n if (tx.fees !== undefined) out.fee = big(tx.fees)\n if (confirmed) out.block = BigInt(tx.blockHeight)\n return out\n}\n\n// ── Source ───────────────────────────────────────────────────────────────────\n\n/** mempool.space link for a transaction. */\nexport function btcExplorerTxUrl(hash: string, network: BtcNetwork = 'bitcoin'): string {\n return `https://mempool.space/${network === 'testnet' ? 'testnet/' : ''}tx/${hash}`\n}\n\n/**\n * A history source for Bitcoin addresses backed by Blockbook (Trezor's public instances,\n * QuickNode's add-on, or your own).\n *\n * @throws Error when no Blockbook URL is given.\n */\nexport function createBtcHistory(options: BtcHistoryOptions = {}): BtcHistorySource {\n const network = options.network ?? 'bitcoin'\n const chain = CAIP2_GENESIS[network]\n const urls = [...(options.blockbookUrls ?? []), ...(options.blockbookUrl ? [options.blockbookUrl] : [])]\n if (urls.length === 0) throw new Error('@anywalletkit/wallet-btc: createBtcHistory needs blockbookUrl or blockbookUrls')\n const fetchFn = options.fetch ?? globalThis.fetch\n if (typeof fetchFn !== 'function') throw new Error('@anywalletkit/wallet-btc: no global fetch; pass `fetch` in the options')\n const clients = urls.map((url) => ({ url, client: new BlockbookClient({ url }, fetchFn, options.timeoutMs ?? DEFAULT_TIMEOUT_MS) }))\n\n async function failover<T>(run: (client: BlockbookClient) => Promise<T>): Promise<T> {\n const attempts: string[] = []\n for (const { url, client } of clients) {\n try {\n return await run(client)\n } catch (e) {\n attempts.push(`${url}: ${e instanceof Error ? e.message : String(e)}`)\n }\n }\n throw new HistoryUnavailableError(chain, attempts[attempts.length - 1] ?? 'every Blockbook failed', attempts)\n }\n\n return {\n chain,\n\n async listActivity(address: string, query: HistoryQuery = {}): Promise<BtcHistoryPage> {\n const cursor = query.cursor ? decodeCursor(query.cursor) : undefined\n const pageSize = cursor?.s ?? Math.min(MAX_PAGE_SIZE, Math.max(1, Math.floor(options.pageSize ?? query.limit ?? DEFAULT_LIMIT)))\n const pageNo = cursor?.p ?? 1\n const data: BlockbookAddressPage = await failover((c) => c.getAddressPage(address, pageNo, pageSize))\n let items = (data.transactions ?? []).map((tx) => mapBlockbookTx(chain, address, tx))\n items.sort((a, b) => (b.block === undefined ? 1 : a.block === undefined ? -1 : (b.block > a.block ? 1 : b.block < a.block ? -1 : 0)) || b.time - a.time)\n const totalPages = data.totalPages ?? 1\n let more = pageNo < totalPages\n if (query.since !== undefined) {\n const since = query.since\n if (items.some((t) => t.status === 'confirmed' && t.time < since)) more = false\n items = items.filter((t) => t.status !== 'confirmed' || t.time >= since)\n }\n const page: BtcHistoryPage = { items, page: pageNo, totalPages }\n if (more) page.cursor = encodeCursor({ v: 1, p: pageNo + 1, s: pageSize })\n return page\n },\n\n async getTransaction(hash: string, address: string): Promise<BtcChainTx | undefined> {\n const tx = await failover((c) => c.getTransactionDetails(hash))\n return tx ? mapBlockbookTx(chain, address, tx) : undefined\n },\n\n explorerTxUrl(hash: string): string {\n return btcExplorerTxUrl(hash, network)\n },\n }\n}\n\n"],"mappings":";AAAA,SAAS,gBAAAA,qBAAoB;;;ACA7B,SAAS,oBAAoB;AAEtB,IAAM,qBAAqB;AAGlC,eAAsB,iBAAiB,SAAuB,KAAa,MAA+B,WAAmB,UAAqC;AAChK,QAAM,SAAS,OAAO,gBAAgB,eAAe,OAAO,YAAY,YAAY,aAAa,YAAY,QAAQ,SAAS,IAAI;AAClI,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK,EAAE,GAAG,MAAM,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC;AAAA,EACtE,SAAS,GAAG;AACV,UAAM,IAAI,aAAa,mBAAmB,GAAG,IAAI,EAAE,UAAU,OAAO,EAAE,CAAC;AAAA,EACzE;AACF;AAGO,IAAM,gBAAgB,CAAC,WAA4B,UAAU,OAAO,SAAS,OAAO,WAAW;AAG/F,SAAS,QAAyB,GAAS;AAChD,SAAO,OAAO,OAAO,GAAG,EAAE,UAAU,KAAK,CAAC;AAC5C;AAMO,SAAS,kBAAkB,GAAqB;AACrD,SAAQ,GAAqC,aAAa;AAC5D;AAGO,SAAS,eAAe,GAAqB;AAClD,WAAS,IAAa,GAAG,QAAQ,GAAG,aAAa,SAAS,QAAQ,GAAG,IAAI,EAAE,OAAO,SAAS;AACzF,QAAI,mFAAmF,KAAK,EAAE,OAAO,EAAG,QAAO;AAAA,EACjH;AACA,SAAO;AACT;AAEO,IAAM,WAAW,CAAC,MAA6C,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AACtH,IAAM,UAAU,CAAC,MAA4B,OAAO,MAAM,YAAY,oBAAoB,KAAK,CAAC;AAChG,IAAM,cAAc,CAAC,MAA4B,OAAO,MAAM,YAAY,UAAU,KAAK,CAAC;;;ADpCjG,IAAM,oBAAoB;AA6BnB,SAAS,oBAAoB,cAAgD,SAAyB;AAC3G,QAAM,WAAW,gBAAgB,CAAC,GAAG,OAAO,CAAC,OAAO,GAAG,gBAAgB,EAAE;AACzE,QAAM,aAAa,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACrD,QAAM,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACpD,QAAM,UAAU,oBAAI,IAAqB;AACzC,QAAM,QAAQ,CAAC,aACZ,WAAW,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,SAAS,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,MAAM,IAAI,OAAO,EAAE,SAAS,CAAC,GAAG,EAAE;AAC5H,QAAM,YAAY,CAAC,OAAoC;AACrD,QAAI,QAAQ,IAAI,GAAG,IAAI,EAAG,QAAO,QAAQ,IAAI,GAAG,IAAI;AACpD,YAAQ,IAAI,GAAG,MAAM,KAAK;AAC1B,UAAM,OAAO,GAAG,OAAO,CAAC;AACxB,UAAM,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,SAAS,OAAO,CAAC;AAC7E,UAAM,KAAK,KAAK,SAAS,KAAK,KAAK,WAAW,KAAK,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,WAAW,IAAI,EAAE,IAAI,KAAK,UAAU,KAAK,IAAI,EAAE,IAAI,CAAE,CAAC;AACjJ,YAAQ,IAAI,GAAG,MAAM,EAAE;AACvB,WAAO;AAAA,EACT;AACA,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,MAAM,QAAS,YAAW,KAAK,GAAG,OAAO,CAAC,EAAG,KAAI,EAAE,QAAQ,WAAW,IAAI,EAAE,IAAI,EAAG,UAAS,IAAI,GAAG,EAAE,IAAI,IAAI,EAAE,IAAI,EAAE;AAChI,SAAO,QAAQ,OAAO,CAAC,OAAO,OAAO;AACnC,UAAM,QAAQ,OAAO,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,WAAW,IAAI,EAAE,IAAI,CAAC,CAAC;AACpF,UAAM,SAAS,UAAU,EAAE,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI;AAC1G,WAAO,SAAS,QAAQ;AAAA,EAC1B,GAAG,EAAE;AACP;AAGO,IAAM,kBAAN,MAAM,iBAAqC;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAAyB,UAAwB,WAAW,OAAO,YAAY,oBAAoB;AAC7G,SAAK,OAAO,OAAO,IAAI,QAAQ,QAAQ,EAAE,EAAE,QAAQ,UAAU,EAAE;AAC/D,SAAK,UAAU;AACf,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAM,UAAyB;AAAA,EAAC;AAAA,EAChC,MAAM,QAAuB;AAAA,EAAC;AAAA,EAE9B,MAAc,IAAO,MAAc,OAA2C;AAC5E,UAAM,MAAM,GAAG,KAAK,IAAI,OAAO,IAAI;AACnC,UAAM,MAAM,MAAM,iBAAiB,KAAK,SAAS,KAAK,QAAW,KAAK,WAAW,KAAK,IAAI;AAC1F,QAAI,CAAC,IAAI,IAAI;AAEX,YAAM,SAAS,cAAc,IAAI,MAAM,KAAK,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE,GAAG,MAAM,GAAG,GAAG,IAAI;AAC9F,YAAM,MAAM,IAAIC,cAAa,6BAA6B,IAAI,MAAM,IAAI,IAAI,UAAU,KAAK,GAAG,IAAI,SAAS,KAAK,MAAM,KAAK,EAAE,IAAI,EAAE,UAAU,KAAK,KAAK,CAAC;AACxJ,YAAM,cAAc,IAAI,MAAM,IAAI,QAAQ,GAAG,IAAI;AAAA,IACnD;AACA,QAAI;AACJ,QAAI;AAAE,aAAO,MAAM,IAAI,KAAK;AAAA,IAAE,SAAS,GAAG;AAAE,YAAM,IAAIA,cAAa,mCAAmC,GAAG,IAAI,EAAE,UAAU,KAAK,MAAM,OAAO,EAAE,CAAC;AAAA,IAAE;AAChJ,QAAI,CAAC,MAAM,IAAI,EAAG,OAAM,IAAIA,cAAa,8CAA8C,GAAG,IAAI,EAAE,UAAU,KAAK,KAAK,CAAC;AACrH,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,SAAiB;AAChC,UAAM,OAAO,MAAM,KAAK,IAAI,eAAe,OAAO,gBAAgB,CAAC,MACjE,SAAS,CAAC,KAAK,YAAY,EAAE,OAAO,KAAK,YAAY,EAAE,kBAAkB,MAAM,EAAE,iBAAiB,UAAa,MAAM,QAAQ,EAAE,YAAY,EAAE;AAC/I,WAAO,EAAE,WAAW,OAAO,KAAK,OAAO,GAAG,aAAa,OAAO,KAAK,kBAAkB,GAAG,qBAAqB,oBAAoB,KAAK,cAAc,OAAO,EAAE;AAAA,EAC/J;AAAA,EAEA,MAAM,YAAY,SAAkC;AAClD,UAAM,OAAO,MAAM,KAAK,IAAI,YAAY,OAAO,IAAI,CAAC,MAClD,MAAM,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,SAAS,CAAC,KAAK,OAAO,EAAE,SAAS,YAAY,OAAO,EAAE,SAAS,YAAY,YAAY,EAAE,KAAK,CAAC,CAAC;AACrI,WAAO,KAAK,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,OAAO,OAAO,EAAE,KAAK,GAAG,QAAQ,EAAE,UAAU,GAAG,EAAE;AAAA,EACzG;AAAA,EAEA,MAAM,WAAW,SAAiB;AAChC,UAAM,QAAiD,CAAC;AACxD,aAAS,OAAO,KAAK,QAAQ;AAC3B,YAAM,OAAO,MAAM,KAAK,IAAI,eAAe,OAAO,wCAAwC,IAAI,IAAI,CAAC,MACjG,SAAS,CAAC,MAAM,EAAE,iBAAiB,UAAa,MAAM,QAAQ,EAAE,YAAY,EAAE;AAChF,iBAAW,MAAM,KAAK,gBAAgB,CAAC,EAAG,OAAM,KAAK,EAAE,MAAM,GAAG,MAAM,QAAQ,GAAG,YAAY,CAAC;AAC9F,UAAI,SAAS,KAAK,cAAc,GAAI;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,eAAe,SAAiB,OAAO,GAAG,WAAW,IAAmC;AAC5F,UAAM,OAAO,MAAM,KAAK,IAAI,eAAe,OAAO,qBAAqB,IAAI,aAAa,QAAQ,IAAI,CAAC,MACnG,SAAS,CAAC,MAAM,EAAE,iBAAiB,UAAc,MAAM,QAAQ,EAAE,YAAY,KAAK,EAAE,aAAa,MAAM,iBAAgB,IAAI,EAAG;AAChI,UAAM,MAA4B,EAAE,GAAG,KAAK;AAC5C,eAAW,MAAM,IAAI,gBAAgB,CAAC,EAAG,QAAQ,GAAwB;AACzE,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,sBAAsB,MAAuD;AACjF,QAAI;AACF,YAAM,KAAK,MAAM,KAAK,IAAI,UAAU,IAAI,IAAI,CAAC,MAA+B,iBAAgB,KAAK,CAAC,CAAC;AACnG,YAAM,MAA0B,EAAE,GAAG,GAAG;AACxC,aAAQ,IAAyB;AACjC,aAAO;AAAA,IACT,SAAS,GAAG;AACV,UAAI,aAAaA,iBAAgB,gBAAgB,KAAK,EAAE,OAAO,EAAG,QAAO;AACzE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,OAAe,KAAK,GAA8B;AAChD,WAAO,SAAS,CAAC,KAAK,OAAO,EAAE,SAAS,YAAY,OAAO,EAAE,gBAAgB,YAAY,OAAO,EAAE,kBAAkB;AAAA,EACtH;AAAA,EAEA,MAAM,mBAAmB,MAAgD;AACvE,QAAI;AAAE,aAAO,MAAM,KAAK,IAAI,UAAU,IAAI,IAAI,iBAAgB,IAAI;AAAA,IAAE,SAAS,GAAG;AAC9E,UAAI,aAAaA,iBAAgB,gBAAgB,KAAK,EAAE,OAAO,EAAG,QAAO;AACzE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,MAA+B;AAClD,UAAM,OAAO,MAAM,KAAK,IAAI,UAAU,IAAI,IAAI,iBAAgB,IAAI;AAClE,QAAI,OAAO,KAAK,QAAQ,YAAY,CAAC,KAAK,IAAK,OAAM,IAAIA,cAAa,eAAe,IAAI,oBAAoB,EAAE,UAAU,KAAK,KAAK,CAAC;AACpI,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAU,OAAgC;AAC9C,UAAM,OAAO,MAAM,KAAK,IAAI,cAAc,KAAK,IAAI,CAAC,MAAuE,SAAS,CAAC,CAAC;AACtI,QAAI,KAAK,MAAO,OAAM,QAAQ,IAAI,MAAM,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAK,MAAM,WAAW,kBAAkB,CAAC;AAC/H,QAAI,CAAC,KAAK,OAAQ,OAAM,IAAIA,cAAa,8BAA8B,EAAE,UAAU,KAAK,KAAK,CAAC;AAC9F,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,YAAY,QAAiC;AACjD,QAAI;AACF,YAAM,OAAO,MAAM,KAAK,IAAI,mBAAmB,MAAM,IAAI,CAAC,MAAyC,OAAO,MAAM,YAAY,SAAS,CAAC,CAAC;AACvI,YAAM,OAAO,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK,MAAM;AACjE,UAAI,OAAO,EAAG,QAAO,KAAK,IAAI,OAAO,KAAS,CAAC;AAAA,IACjD,QAAQ;AAAA,IAAqB;AAC7B,UAAM,MAAM,MAAM,iBAAiB,KAAK,SAAS,GAAG,iBAAiB,4BAA4B,QAAW,KAAK,WAAW,iBAAiB;AAC7I,QAAI,CAAC,IAAI,GAAI,OAAM,IAAIA,cAAa,iCAAiC,EAAE,UAAU,kBAAkB,CAAC;AACpG,UAAM,IAAK,MAAM,IAAI,KAAK;AAC1B,UAAM,WAAW,UAAU,IAAI,EAAE,aAAa,UAAU,IAAI,EAAE,cAAc,UAAU,IAAI,EAAE,UAAU,EAAE;AACxG,QAAI,CAAC,YAAY,YAAY,EAAG,OAAM,IAAIA,cAAa,iCAAiC,EAAE,UAAU,kBAAkB,CAAC;AACvH,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,iBAAkC;AACtC,UAAM,OAAO,MAAM,KAAK,IAAI,OAAO,CAAC,MAAoD,SAAS,CAAC,CAAC;AACnG,UAAM,IAAI,KAAK,WAAW;AAC1B,QAAI,OAAO,MAAM,YAAY,KAAK,EAAG,OAAM,IAAIA,cAAa,2CAA2C,EAAE,UAAU,KAAK,KAAK,CAAC;AAC9H,WAAO;AAAA,EACT;AACF;;;AELO,IAAM,gBAA4C;AAAA,EACvD,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AACX;;;ACnHO,IAAM,0BAAN,cAAsC,MAAM;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACT,YAAY,OAAe,QAAgB,WAA8B,CAAC,GAAG;AAC3E,UAAM,2BAA2B,KAAK,KAAK,MAAM,EAAE;AACnD,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,SAAS;AACd,SAAK,WAAW;AAAA,EAClB;AACF;AAEA,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AAatB,IAAM,MAAM;AAEZ,SAAS,UAAU,GAAmB;AACpC,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK,GAAG;AACpC,UAAM,IAAI,CAAC,EAAE,WAAW,CAAC,GAAG,EAAE,WAAW,IAAI,CAAC,GAAG,EAAE,WAAW,IAAI,CAAC,CAAC;AACpE,UAAM,IAAK,EAAE,CAAC,KAAM,MAAQ,EAAE,CAAC,KAAM,MAAM,KAAM,EAAE,CAAC,KAAM;AAC1D,WAAO,IAAK,KAAK,KAAM,EAAE,IAAK,IAAK,KAAK,KAAM,EAAE,KAAM,OAAO,MAAM,EAAE,CAAC,CAAC,IAAI,MAAM,IAAK,KAAK,IAAK,EAAE,MAAO,OAAO,MAAM,EAAE,CAAC,CAAC,IAAI,MAAM,IAAI,IAAI,EAAE;AAAA,EAChJ;AACA,SAAO;AACT;AAEA,SAAS,UAAU,GAAmB;AACpC,QAAM,QAAQ,EAAE,QAAQ,mBAAmB,EAAE;AAC7C,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACxC,UAAM,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,MAAO,IAAI,IAAI,MAAM,SAAS,IAAI,QAAQ,MAAM,IAAI,CAAC,CAAE,IAAI,EAAG;AAC1F,QAAI,EAAE,CAAC,IAAK,KAAK,EAAE,CAAC,IAAK,EAAG,OAAM,IAAI,MAAM,YAAY;AACxD,UAAM,IAAK,EAAE,CAAC,KAAM,KAAO,EAAE,CAAC,KAAM,MAAQ,EAAE,CAAC,IAAK,IAAI,IAAI,EAAE,CAAC,MAAO,KAAM,EAAE,CAAC,IAAK,IAAI,IAAI,EAAE,CAAC;AAC/F,WAAO,OAAO,aAAc,KAAK,KAAM,GAAI;AAC3C,QAAI,EAAE,CAAC,KAAM,EAAG,QAAO,OAAO,aAAc,KAAK,IAAK,GAAI;AAC1D,QAAI,EAAE,CAAC,KAAM,EAAG,QAAO,OAAO,aAAa,IAAI,GAAI;AAAA,EACrD;AACA,SAAO;AACT;AAEO,SAAS,aAAa,GAA6B;AACxD,SAAO,UAAU,KAAK,UAAU,CAAC,CAAC;AACpC;AAEO,SAAS,aAAa,GAA6B;AACxD,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,UAAU,CAAC,CAAC;AAAA,EAClC,QAAQ;AACN,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AACA,QAAM,IAAI;AACV,MAAI,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,OAAO,UAAU,EAAE,CAAC,KAAM,EAAE,IAAe,KAAK,CAAC,OAAO,UAAU,EAAE,CAAC,KAAM,EAAE,IAAe,EAAG,OAAM,IAAI,MAAM,oDAAoD;AAC3L,SAAO,EAAE,GAAG,GAAG,GAAG,EAAE,GAAa,GAAG,EAAE,EAAY;AACpD;AAIA,IAAM,MAAM,CAAC,MAAwB,OAAO,MAAM,YAAY,UAAU,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,OAAO,MAAM,WAAW,OAAO,KAAK,MAAM,CAAC,CAAC,IAAI;AAEvI,SAAS,eAAe,OAAe,SAAiB,IAAoC;AACjG,QAAM,OAAO,CAAC,MAAqD,EAAE,cAAc,UAAU,EAAE,aAAa,CAAC,GAAG,SAAS,OAAO;AAChI,MAAI,QAAQ,IAAI,SAAS,IAAI,eAAe;AAC5C,aAAW,OAAO,GAAG,OAAO,CAAC,EAAG,KAAI,KAAK,GAAG,EAAG,UAAS,IAAI,IAAI,KAAK;AACrE,aAAW,QAAQ,GAAG,QAAQ,CAAC,GAAG;AAChC,QAAI,KAAK,IAAI,EAAG,WAAU,IAAI,KAAK,KAAK;AAAA,QACnC,iBAAgB,IAAI,KAAK,KAAK;AAAA,EACrC;AACA,QAAM,cAAc,GAAG,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS,EAAE,YAAY,CAAC,CAAC,GAAG,YAAY,CAAC;AACvG,QAAM,oBAAoB,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,GAAG,YAAY,CAAC;AAC1H,QAAM,YAA6B,CAAC;AACpC,MAAI,MAAc,IAAmB;AACrC,MAAI,QAAQ,IAAI;AAEd,WAAO;AACP,SAAK,oBAAoB;AACzB,kBAAc,mBAAmB,eAAe;AAChD,QAAI,cAAc,GAAI,WAAU,KAAK,EAAE,OAAO,MAAM,MAAM,SAAS,IAAI,QAAQ,YAAY,CAAC;AAAA,EAC9F,OAAO;AAEL,WAAO,cAAc;AACrB,SAAK;AACL,kBAAc;AACd,QAAI,cAAc,GAAI,WAAU,KAAK,EAAE,OAAO,MAAM,MAAM,IAAI,SAAS,QAAQ,YAAY,CAAC;AAAA,EAC9F;AACA,QAAM,YAAY,GAAG,gBAAgB,KAAK,GAAG,cAAc;AAC3D,QAAM,MAAkB;AAAA,IACtB;AAAA,IAAO,MAAM,GAAG;AAAA,IAAM,MAAM,GAAG,aAAa;AAAA,IAAG,QAAQ,YAAY,cAAc;AAAA,IAAW;AAAA,IAAS;AAAA,IAAM;AAAA,IAAI;AAAA,IAAa;AAAA,IAC5H,KAAK,EAAE,IAAI,OAAO,OAAO;AAAA,EAC3B;AACA,MAAI,GAAG,SAAS,OAAW,KAAI,MAAM,IAAI,GAAG,IAAI;AAChD,MAAI,UAAW,KAAI,QAAQ,OAAO,GAAG,WAAW;AAChD,SAAO;AACT;AAKO,SAAS,iBAAiB,MAAc,UAAsB,WAAmB;AACtF,SAAO,yBAAyB,YAAY,YAAY,aAAa,EAAE,MAAM,IAAI;AACnF;AAQO,SAAS,iBAAiB,UAA6B,CAAC,GAAqB;AAClF,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,QAAQ,cAAc,OAAO;AACnC,QAAM,OAAO,CAAC,GAAI,QAAQ,iBAAiB,CAAC,GAAI,GAAI,QAAQ,eAAe,CAAC,QAAQ,YAAY,IAAI,CAAC,CAAE;AACvG,MAAI,KAAK,WAAW,EAAG,OAAM,IAAI,MAAM,gFAAgF;AACvH,QAAM,UAAU,QAAQ,SAAS,WAAW;AAC5C,MAAI,OAAO,YAAY,WAAY,OAAM,IAAI,MAAM,wEAAwE;AAC3H,QAAM,UAAU,KAAK,IAAI,CAAC,SAAS,EAAE,KAAK,QAAQ,IAAI,gBAAgB,EAAE,IAAI,GAAG,SAAS,QAAQ,aAAa,kBAAkB,EAAE,EAAE;AAEnI,iBAAe,SAAY,KAA0D;AACnF,UAAM,WAAqB,CAAC;AAC5B,eAAW,EAAE,KAAK,OAAO,KAAK,SAAS;AACrC,UAAI;AACF,eAAO,MAAM,IAAI,MAAM;AAAA,MACzB,SAAS,GAAG;AACV,iBAAS,KAAK,GAAG,GAAG,KAAK,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC,EAAE;AAAA,MACvE;AAAA,IACF;AACA,UAAM,IAAI,wBAAwB,OAAO,SAAS,SAAS,SAAS,CAAC,KAAK,0BAA0B,QAAQ;AAAA,EAC9G;AAEA,SAAO;AAAA,IACL;AAAA,IAEA,MAAM,aAAa,SAAiB,QAAsB,CAAC,GAA4B;AACrF,YAAM,SAAS,MAAM,SAAS,aAAa,MAAM,MAAM,IAAI;AAC3D,YAAM,WAAW,QAAQ,KAAK,KAAK,IAAI,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,YAAY,MAAM,SAAS,aAAa,CAAC,CAAC;AAC/H,YAAM,SAAS,QAAQ,KAAK;AAC5B,YAAM,OAA6B,MAAM,SAAS,CAAC,MAAM,EAAE,eAAe,SAAS,QAAQ,QAAQ,CAAC;AACpG,UAAI,SAAS,KAAK,gBAAgB,CAAC,GAAG,IAAI,CAAC,OAAO,eAAe,OAAO,SAAS,EAAE,CAAC;AACpF,YAAM,KAAK,CAAC,GAAG,OAAO,EAAE,UAAU,SAAY,IAAI,EAAE,UAAU,SAAY,KAAM,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,QAAQ,EAAE,QAAQ,KAAK,MAAO,EAAE,OAAO,EAAE,IAAI;AACvJ,YAAM,aAAa,KAAK,cAAc;AACtC,UAAI,OAAO,SAAS;AACpB,UAAI,MAAM,UAAU,QAAW;AAC7B,cAAM,QAAQ,MAAM;AACpB,YAAI,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,eAAe,EAAE,OAAO,KAAK,EAAG,QAAO;AAC1E,gBAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,eAAe,EAAE,QAAQ,KAAK;AAAA,MACzE;AACA,YAAM,OAAuB,EAAE,OAAO,MAAM,QAAQ,WAAW;AAC/D,UAAI,KAAM,MAAK,SAAS,aAAa,EAAE,GAAG,GAAG,GAAG,SAAS,GAAG,GAAG,SAAS,CAAC;AACzE,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,eAAe,MAAc,SAAkD;AACnF,YAAM,KAAK,MAAM,SAAS,CAAC,MAAM,EAAE,sBAAsB,IAAI,CAAC;AAC9D,aAAO,KAAK,eAAe,OAAO,SAAS,EAAE,IAAI;AAAA,IACnD;AAAA,IAEA,cAAc,MAAsB;AAClC,aAAO,iBAAiB,MAAM,OAAO;AAAA,IACvC;AAAA,EACF;AACF;","names":["NetworkError","NetworkError"]}
@@ -335,4 +335,4 @@ declare function btcExplorerTxUrl(hash: string, network?: BtcNetwork): string;
335
335
  */
336
336
  declare function createBtcHistory(options?: BtcHistoryOptions): BtcHistorySource;
337
337
 
338
- export { createBtcHistory as A, type BtcClient as B, CAIP2_GENESIS as C, decodeCursor as D, encodeCursor as E, mapBlockbookTx as F, unconfirmedOutgoing as G, HistoryUnavailableError as H, type Utxo as U, type BlockbookTx as a, type BtcConfig as b, type BtcTxDescription as c, type BtcAddressType as d, type BtcNetwork as e, type BtcSpend as f, type BtcTransferOptions as g, type BtcMaxSpendableResult as h, type BtcReceipt as i, type BtcTransaction as j, type BlockbookAddressPage as k, BlockbookClient as l, type BlockbookTxDetails as m, type BlockbookVin as n, type BlockbookVout as o, type BtcChainTx as p, type BtcClientConfig as q, type BtcHistoryCursor as r, type BtcHistoryOptions as s, type BtcHistoryPage as t, type BtcHistoryRaw as u, type BtcHistorySource as v, type BtcTxInputDescription as w, type BtcTxOutputDescription as x, type BtcWarning as y, btcExplorerTxUrl as z };
338
+ export { btcExplorerTxUrl as A, type BtcClient as B, CAIP2_GENESIS as C, createBtcHistory as D, decodeCursor as E, encodeCursor as F, mapBlockbookTx as G, HistoryUnavailableError as H, unconfirmedOutgoing as I, type Utxo as U, type BlockbookTx as a, type BtcConfig as b, type BtcTxDescription as c, type BtcAddressType as d, type BtcNetwork as e, type BtcSpend as f, type BtcTransferOptions as g, type BtcMaxSpendableResult as h, type BtcReceipt as i, type BtcTransaction as j, type BlockbookAddressPage as k, type BlockbookAddressTx as l, BlockbookClient as m, type BlockbookTxDetails as n, type BlockbookVin as o, type BlockbookVout as p, type BtcChainTx as q, type BtcClientConfig as r, type BtcHistoryCursor as s, type BtcHistoryOptions as t, type BtcHistoryPage as u, type BtcHistoryRaw as v, type BtcHistorySource as w, type BtcTxInputDescription as x, type BtcTxOutputDescription as y, type BtcWarning as z };
@@ -335,4 +335,4 @@ declare function btcExplorerTxUrl(hash: string, network?: BtcNetwork): string;
335
335
  */
336
336
  declare function createBtcHistory(options?: BtcHistoryOptions): BtcHistorySource;
337
337
 
338
- export { createBtcHistory as A, type BtcClient as B, CAIP2_GENESIS as C, decodeCursor as D, encodeCursor as E, mapBlockbookTx as F, unconfirmedOutgoing as G, HistoryUnavailableError as H, type Utxo as U, type BlockbookTx as a, type BtcConfig as b, type BtcTxDescription as c, type BtcAddressType as d, type BtcNetwork as e, type BtcSpend as f, type BtcTransferOptions as g, type BtcMaxSpendableResult as h, type BtcReceipt as i, type BtcTransaction as j, type BlockbookAddressPage as k, BlockbookClient as l, type BlockbookTxDetails as m, type BlockbookVin as n, type BlockbookVout as o, type BtcChainTx as p, type BtcClientConfig as q, type BtcHistoryCursor as r, type BtcHistoryOptions as s, type BtcHistoryPage as t, type BtcHistoryRaw as u, type BtcHistorySource as v, type BtcTxInputDescription as w, type BtcTxOutputDescription as x, type BtcWarning as y, btcExplorerTxUrl as z };
338
+ export { btcExplorerTxUrl as A, type BtcClient as B, CAIP2_GENESIS as C, createBtcHistory as D, decodeCursor as E, encodeCursor as F, mapBlockbookTx as G, HistoryUnavailableError as H, unconfirmedOutgoing as I, type Utxo as U, type BlockbookTx as a, type BtcConfig as b, type BtcTxDescription as c, type BtcAddressType as d, type BtcNetwork as e, type BtcSpend as f, type BtcTransferOptions as g, type BtcMaxSpendableResult as h, type BtcReceipt as i, type BtcTransaction as j, type BlockbookAddressPage as k, type BlockbookAddressTx as l, BlockbookClient as m, type BlockbookTxDetails as n, type BlockbookVin as o, type BlockbookVout as p, type BtcChainTx as q, type BtcClientConfig as r, type BtcHistoryCursor as s, type BtcHistoryOptions as t, type BtcHistoryPage as u, type BtcHistoryRaw as v, type BtcHistorySource as w, type BtcTxInputDescription as x, type BtcTxOutputDescription as y, type BtcWarning as z };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/history.ts","../src/blockbook.ts","../src/http.ts","../src/types.ts"],"sourcesContent":["/**\n * Activity history for Bitcoin: a `HistorySource` over Blockbook's\n * `/api/v2/address/{a}?details=txs` pages (Trezor's indexer, QuickNode's\n * Blockbook add-on, any self-hosted instance), reusing the package's\n * `BlockbookClient` and failing over across several instances.\n *\n * One transaction = one native transfer in the owner's direction: a send is\n * what left to non-own outputs (fee separate), a receive is what landed on the\n * address. The cursor is the Blockbook page number. Explorer: mempool.space.\n */\nimport type { ChainTransfer, ChainTx, HistoryPage, HistoryQuery, HistorySource } from '@anywalletkit/core'\nimport { BlockbookClient, type BlockbookAddressPage, type BlockbookTxDetails } from './blockbook.js'\nimport { DEFAULT_TIMEOUT_MS } from './http.js'\nimport { CAIP2_GENESIS, type BtcNetwork } from './types.js'\n\n// ── Public types ─────────────────────────────────────────────────────────────\n\n/** Options for {@link createBtcHistory}. */\nexport interface BtcHistoryOptions {\n /** One Blockbook root (`https://btc1.trezor.io`). */\n blockbookUrl?: string\n /** Several roots, tried in order (failover). */\n blockbookUrls?: string[]\n /** `bitcoin` (default), `testnet`, `regtest`. */\n network?: BtcNetwork\n fetch?: typeof fetch\n /** Per request, ms. Default 15 000. */\n timeoutMs?: number\n /** Rows per Blockbook page (its max is 1000). Default: the query limit, capped at 100. */\n pageSize?: number\n}\n\n/** What a Bitcoin `ChainTx` was built from, and the address's own totals. */\nexport interface BtcHistoryRaw {\n /** The Blockbook transaction (vin / vout with addresses and values; `hex` dropped). */\n tx: BlockbookTxDetails\n /** Sum of inputs spent by the address, sats. */\n ownIn: bigint\n /** Sum of outputs paid to the address, sats. */\n ownOut: bigint\n}\n\n/** A `ChainTx` with the Blockbook transaction it was built from. */\nexport interface BtcChainTx extends ChainTx {\n raw: BtcHistoryRaw\n}\n\n/** One page of Bitcoin history. */\nexport interface BtcHistoryPage extends HistoryPage {\n items: BtcChainTx[]\n /** Blockbook page served / total pages. */\n page?: number\n totalPages?: number\n}\n\n/** Bitcoin history from a Blockbook instance. Build it with {@link createBtcHistory}. */\nexport interface BtcHistorySource extends HistorySource {\n listActivity(address: string, query?: HistoryQuery): Promise<BtcHistoryPage>\n getTransaction(hash: string, address: string): Promise<BtcChainTx | undefined>\n}\n\n/** Every configured Blockbook endpoint failed (or none was configured). */\nexport class HistoryUnavailableError extends Error {\n readonly chain: string\n readonly reason: string\n readonly attempts: readonly string[]\n constructor(chain: string, reason: string, attempts: readonly string[] = []) {\n super(`History unavailable for ${chain}: ${reason}`)\n this.name = 'HistoryUnavailableError'\n this.chain = chain\n this.reason = reason\n this.attempts = attempts\n }\n}\n\nconst DEFAULT_LIMIT = 25\nconst MAX_PAGE_SIZE = 100\n\n// ── Cursor: the next Blockbook page, base64 JSON ─────────────────────────────\n\n/** @internal Decoded form of a Bitcoin history cursor. */\nexport interface BtcHistoryCursor {\n v: 1\n /** Next page (1-based). */\n p: number\n /** Page size the pagination started with (changing it mid-way would skip or repeat rows). */\n s: number\n}\n\nconst B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n\nfunction b64encode(s: string): string {\n let out = ''\n for (let i = 0; i < s.length; i += 3) {\n const c = [s.charCodeAt(i), s.charCodeAt(i + 1), s.charCodeAt(i + 2)]\n const n = (c[0]! << 16) | ((c[1]! || 0) << 8) | (c[2]! || 0)\n out += B64[(n >> 18) & 63]! + B64[(n >> 12) & 63]! + (Number.isNaN(c[1]) ? '=' : B64[(n >> 6) & 63]!) + (Number.isNaN(c[2]) ? '=' : B64[n & 63]!)\n }\n return out\n}\n\nfunction b64decode(s: string): string {\n const clean = s.replace(/[^A-Za-z0-9+/]/g, '')\n let out = ''\n for (let i = 0; i < clean.length; i += 4) {\n const c = [0, 1, 2, 3].map((k) => (i + k < clean.length ? B64.indexOf(clean[i + k]!) : -1))\n if (c[0]! < 0 || c[1]! < 0) throw new Error('bad base64')\n const n = (c[0]! << 18) | (c[1]! << 12) | ((c[2]! < 0 ? 0 : c[2]!) << 6) | (c[3]! < 0 ? 0 : c[3]!)\n out += String.fromCharCode((n >> 16) & 0xff)\n if (c[2]! >= 0) out += String.fromCharCode((n >> 8) & 0xff)\n if (c[3]! >= 0) out += String.fromCharCode(n & 0xff)\n }\n return out\n}\n\nexport function encodeCursor(c: BtcHistoryCursor): string {\n return b64encode(JSON.stringify(c))\n}\n\nexport function decodeCursor(s: string): BtcHistoryCursor {\n let parsed: unknown\n try {\n parsed = JSON.parse(b64decode(s))\n } catch {\n throw new Error('@anywalletkit/wallet-btc: malformed history cursor')\n }\n const c = parsed as Partial<BtcHistoryCursor> | null\n if (!c || c.v !== 1 || !Number.isInteger(c.p) || (c.p as number) < 1 || !Number.isInteger(c.s) || (c.s as number) < 1) throw new Error('@anywalletkit/wallet-btc: malformed history cursor')\n return { v: 1, p: c.p as number, s: c.s as number }\n}\n\n// ── Mapping ──────────────────────────────────────────────────────────────────\n\nconst big = (v: unknown): bigint => (typeof v === 'string' && /^-?\\d+$/.test(v) ? BigInt(v) : typeof v === 'number' ? BigInt(Math.trunc(v)) : 0n)\n\nexport function mapBlockbookTx(chain: string, address: string, tx: BlockbookTxDetails): BtcChainTx {\n const owns = (e: { isAddress?: boolean; addresses?: string[] }) => e.isAddress !== false && (e.addresses ?? []).includes(address)\n let ownIn = 0n, ownOut = 0n, sentToOthers = 0n\n for (const vin of tx.vin ?? []) if (owns(vin)) ownIn += big(vin.value)\n for (const vout of tx.vout ?? []) {\n if (owns(vout)) ownOut += big(vout.value)\n else sentToOthers += big(vout.value)\n }\n const firstInput = (tx.vin ?? []).find((v) => v.isAddress !== false && v.addresses?.[0])?.addresses?.[0]\n const firstOtherOutput = (tx.vout ?? []).find((v) => v.isAddress !== false && !owns(v) && v.addresses?.[0])?.addresses?.[0]\n const transfers: ChainTransfer[] = []\n let from: string, to: string | null, nativeValue: bigint\n if (ownIn > 0n) {\n // We spent inputs: a send (or a consolidation when every output is ours).\n from = address\n to = firstOtherOutput ?? address\n nativeValue = firstOtherOutput ? sentToOthers : ownOut\n if (nativeValue > 0n) transfers.push({ token: null, from: address, to, amount: nativeValue })\n } else {\n // Only outputs are ours: a receive (coinbase has no input address).\n from = firstInput ?? 'coinbase'\n to = address\n nativeValue = ownOut\n if (nativeValue > 0n) transfers.push({ token: null, from, to: address, amount: nativeValue })\n }\n const confirmed = tx.confirmations > 0 && tx.blockHeight > 0\n const out: BtcChainTx = {\n chain, hash: tx.txid, time: tx.blockTime ?? 0, status: confirmed ? 'confirmed' : 'pending', address, from, to, nativeValue, transfers,\n raw: { tx, ownIn, ownOut },\n }\n if (tx.fees !== undefined) out.fee = big(tx.fees)\n if (confirmed) out.block = BigInt(tx.blockHeight)\n return out\n}\n\n// ── Source ───────────────────────────────────────────────────────────────────\n\n/** mempool.space link for a transaction. */\nexport function btcExplorerTxUrl(hash: string, network: BtcNetwork = 'bitcoin'): string {\n return `https://mempool.space/${network === 'testnet' ? 'testnet/' : ''}tx/${hash}`\n}\n\n/**\n * A history source for Bitcoin addresses backed by Blockbook (Trezor's public instances,\n * QuickNode's add-on, or your own).\n *\n * @throws Error when no Blockbook URL is given.\n */\nexport function createBtcHistory(options: BtcHistoryOptions = {}): BtcHistorySource {\n const network = options.network ?? 'bitcoin'\n const chain = CAIP2_GENESIS[network]\n const urls = [...(options.blockbookUrls ?? []), ...(options.blockbookUrl ? [options.blockbookUrl] : [])]\n if (urls.length === 0) throw new Error('@anywalletkit/wallet-btc: createBtcHistory needs blockbookUrl or blockbookUrls')\n const fetchFn = options.fetch ?? globalThis.fetch\n if (typeof fetchFn !== 'function') throw new Error('@anywalletkit/wallet-btc: no global fetch; pass `fetch` in the options')\n const clients = urls.map((url) => ({ url, client: new BlockbookClient({ url }, fetchFn, options.timeoutMs ?? DEFAULT_TIMEOUT_MS) }))\n\n async function failover<T>(run: (client: BlockbookClient) => Promise<T>): Promise<T> {\n const attempts: string[] = []\n for (const { url, client } of clients) {\n try {\n return await run(client)\n } catch (e) {\n attempts.push(`${url}: ${e instanceof Error ? e.message : String(e)}`)\n }\n }\n throw new HistoryUnavailableError(chain, attempts[attempts.length - 1] ?? 'every Blockbook failed', attempts)\n }\n\n return {\n chain,\n\n async listActivity(address: string, query: HistoryQuery = {}): Promise<BtcHistoryPage> {\n const cursor = query.cursor ? decodeCursor(query.cursor) : undefined\n const pageSize = cursor?.s ?? Math.min(MAX_PAGE_SIZE, Math.max(1, Math.floor(options.pageSize ?? query.limit ?? DEFAULT_LIMIT)))\n const pageNo = cursor?.p ?? 1\n const data: BlockbookAddressPage = await failover((c) => c.getAddressPage(address, pageNo, pageSize))\n let items = (data.transactions ?? []).map((tx) => mapBlockbookTx(chain, address, tx))\n items.sort((a, b) => (b.block === undefined ? 1 : a.block === undefined ? -1 : (b.block > a.block ? 1 : b.block < a.block ? -1 : 0)) || b.time - a.time)\n const totalPages = data.totalPages ?? 1\n let more = pageNo < totalPages\n if (query.since !== undefined) {\n const since = query.since\n if (items.some((t) => t.status === 'confirmed' && t.time < since)) more = false\n items = items.filter((t) => t.status !== 'confirmed' || t.time >= since)\n }\n const page: BtcHistoryPage = { items, page: pageNo, totalPages }\n if (more) page.cursor = encodeCursor({ v: 1, p: pageNo + 1, s: pageSize })\n return page\n },\n\n async getTransaction(hash: string, address: string): Promise<BtcChainTx | undefined> {\n const tx = await failover((c) => c.getTransactionDetails(hash))\n return tx ? mapBlockbookTx(chain, address, tx) : undefined\n },\n\n explorerTxUrl(hash: string): string {\n return btcExplorerTxUrl(hash, network)\n },\n }\n}\n\n","import { NetworkError } from '@anywalletkit/core'\nimport { DEFAULT_TIMEOUT_MS, fetchWithTimeout, isIntString, isRecord, refusal, refusedStatus } from './http.js'\nimport type { BlockbookTx, BtcClient, Utxo } from './types.js'\n\nconst MEMPOOL_SPACE_URL = 'https://mempool.space'\n\nexport interface BlockbookVin { txid?: string; vout?: number; n?: number; isAddress?: boolean; isOwn?: boolean; addresses?: string[]; value?: string }\nexport interface BlockbookVout { n: number; isAddress?: boolean; isOwn?: boolean; addresses?: string[]; value?: string; spent?: boolean }\ninterface BlockbookAddressTx { txid: string; blockHeight: number; vin?: BlockbookVin[]; vout?: BlockbookVout[] }\n/** A Blockbook transaction with its inputs and outputs (`/api/v2/tx/{txid}`, or one row of `?details=txs`). */\nexport interface BlockbookTxDetails extends BlockbookTx {\n vin?: BlockbookVin[]\n vout?: BlockbookVout[]\n value?: string\n valueIn?: string\n}\n/** One `/api/v2/address/{a}?details=txs` page. */\nexport interface BlockbookAddressPage {\n page?: number\n totalPages?: number\n itemsOnPage?: number\n address?: string\n balance?: string\n unconfirmedBalance?: string\n txs?: number\n transactions?: BlockbookTxDetails[]\n}\n\n/**\n * Pending outgoing value the way Bitcoin Core's wallet counts it: a pending tx\n * is trusted only if every input is ours and confirmed or chained from another\n * trusted tx; only then its change counts back.\n */\nexport function unconfirmedOutgoing(transactions: BlockbookAddressTx[] | undefined, address: string): bigint {\n const pending = (transactions ?? []).filter((tx) => tx.blockHeight === -1)\n const pendingIds = new Set(pending.map((t) => t.txid))\n const byId = new Map(pending.map((t) => [t.txid, t]))\n const trusted = new Map<string, boolean>()\n const owned = (entries: Array<BlockbookVin | BlockbookVout> | undefined) =>\n (entries ?? []).filter((e) => e.isAddress && e.addresses?.includes(address)).reduce((s, e) => s + BigInt(e.value ?? 0), 0n)\n const isTrusted = (tx: BlockbookAddressTx): boolean => {\n if (trusted.has(tx.txid)) return trusted.get(tx.txid)!\n trusted.set(tx.txid, false)\n const vins = tx.vin ?? []\n const ours = vins.filter((v) => v.isAddress && v.addresses?.includes(address))\n const ok = vins.length > 0 && ours.length === vins.length && ours.every((v) => !v.txid || !pendingIds.has(v.txid) || isTrusted(byId.get(v.txid)!))\n trusted.set(tx.txid, ok)\n return ok\n }\n const consumed = new Set<string>()\n for (const tx of pending) for (const v of tx.vin ?? []) if (v.txid && pendingIds.has(v.txid)) consumed.add(`${v.txid}:${v.vout}`)\n return pending.reduce((total, tx) => {\n const spent = owned((tx.vin ?? []).filter((v) => !v.txid || !pendingIds.has(v.txid)))\n const change = isTrusted(tx) ? owned((tx.vout ?? []).filter((o) => !consumed.has(`${tx.txid}:${o.n}`))) : 0n\n return total + (spent - change)\n }, 0n)\n}\n\n/** Blockbook REST transport (Trezor's indexer; QuickNode's Blockbook add-on speaks the same API). */\nexport class BlockbookClient implements BtcClient {\n private readonly base: string\n private readonly fetchFn: typeof fetch\n private readonly timeoutMs: number\n\n constructor(config: { url: string }, fetchFn: typeof fetch = globalThis.fetch, timeoutMs = DEFAULT_TIMEOUT_MS) {\n this.base = config.url.replace(/\\/+$/, '').replace(/\\/api$/, '')\n this.fetchFn = fetchFn\n this.timeoutMs = timeoutMs\n }\n\n async connect(): Promise<void> {}\n async close(): Promise<void> {}\n\n private async get<T>(path: string, check: (v: unknown) => v is T): Promise<T> {\n const url = `${this.base}/api${path}`\n const res = await fetchWithTimeout(this.fetchFn, url, undefined, this.timeoutMs, this.base)\n if (!res.ok) {\n // A 4xx (not 408) is the server refusing: nothing was taken. A 5xx may have been forwarded (round 3, M12).\n const reason = refusedStatus(res.status) ? (await res.text().catch(() => '')).slice(0, 200) : ''\n const err = new NetworkError(`Blockbook request failed: ${res.status} ${res.statusText} (${url})${reason ? `: ${reason}` : ''}`, { provider: this.base })\n throw refusedStatus(res.status) ? refusal(err) : err\n }\n let body: unknown\n try { body = await res.json() } catch (e) { throw new NetworkError(`Blockbook returned non-JSON for ${url}`, { provider: this.base, cause: e }) }\n if (!check(body)) throw new NetworkError(`Blockbook returned an unexpected shape for ${url}`, { provider: this.base })\n return body\n }\n\n async getBalance(address: string) {\n const data = await this.get(`/v2/address/${address}?details=txs`, (v): v is { balance: string; unconfirmedBalance: string; transactions?: BlockbookAddressTx[] } =>\n isRecord(v) && isIntString(v.balance) && isIntString(v.unconfirmedBalance) && (v.transactions === undefined || Array.isArray(v.transactions)))\n return { confirmed: BigInt(data.balance), unconfirmed: BigInt(data.unconfirmedBalance), unconfirmedOutgoing: unconfirmedOutgoing(data.transactions, address) }\n }\n\n async listUnspent(address: string): Promise<Utxo[]> {\n const data = await this.get(`/v2/utxo/${address}`, (v): v is Array<{ txid: string; vout: number; value: string; height?: number }> =>\n Array.isArray(v) && v.every((u) => isRecord(u) && typeof u.txid === 'string' && typeof u.vout === 'number' && isIntString(u.value)))\n return data.map((u) => ({ txid: u.txid, vout: u.vout, value: BigInt(u.value), height: u.height ?? -1 }))\n }\n\n async getHistory(address: string) {\n const items: Array<{ txid: string; height: number }> = []\n for (let page = 1; ; page++) {\n const data = await this.get(`/v2/address/${address}?details=txslight&pageSize=1000&page=${page}`, (v): v is { transactions?: Array<{ txid: string; blockHeight: number }>; totalPages?: number } =>\n isRecord(v) && (v.transactions === undefined || Array.isArray(v.transactions)))\n for (const tx of data.transactions ?? []) items.push({ txid: tx.txid, height: tx.blockHeight })\n if (page >= (data.totalPages ?? 1)) break\n }\n return items\n }\n\n /** One page of the address's transactions, newest first, with inputs / outputs (what the activity history reads). */\n async getAddressPage(address: string, page = 1, pageSize = 25): Promise<BlockbookAddressPage> {\n const data = await this.get(`/v2/address/${address}?details=txs&page=${page}&pageSize=${pageSize}`, (v): v is BlockbookAddressPage =>\n isRecord(v) && (v.transactions === undefined || (Array.isArray(v.transactions) && v.transactions.every(BlockbookClient.isTx))))\n const out: BlockbookAddressPage = { ...data }\n for (const tx of out.transactions ?? []) delete (tx as { hex?: string }).hex\n return out\n }\n\n /** A transaction with its inputs / outputs; undefined when Blockbook does not know it. */\n async getTransactionDetails(txid: string): Promise<BlockbookTxDetails | undefined> {\n try {\n const tx = await this.get(`/v2/tx/${txid}`, (v): v is BlockbookTxDetails => BlockbookClient.isTx(v))\n const out: BlockbookTxDetails = { ...tx }\n delete (out as { hex?: string }).hex\n return out\n } catch (e) {\n if (e instanceof NetworkError && /\\b(400|404)\\b/.test(e.message)) return undefined\n throw e\n }\n }\n\n private static isTx(v: unknown): v is BlockbookTx {\n return isRecord(v) && typeof v.txid === 'string' && typeof v.blockHeight === 'number' && typeof v.confirmations === 'number'\n }\n\n async getTransactionInfo(txid: string): Promise<BlockbookTx | undefined> {\n try { return await this.get(`/v2/tx/${txid}`, BlockbookClient.isTx) } catch (e) {\n if (e instanceof NetworkError && /\\b(400|404)\\b/.test(e.message)) return undefined\n throw e\n }\n }\n\n async getTransaction(txid: string): Promise<string> {\n const data = await this.get(`/v2/tx/${txid}`, BlockbookClient.isTx)\n if (typeof data.hex !== 'string' || !data.hex) throw new NetworkError(`Transaction ${txid} has no hex data`, { provider: this.base })\n return data.hex\n }\n\n async broadcast(rawTx: string): Promise<string> {\n const data = await this.get(`/v2/sendtx/${rawTx}`, (v): v is { result?: string; error?: { message?: string } | string } => isRecord(v))\n if (data.error) throw refusal(new Error(typeof data.error === 'string' ? data.error : data.error.message ?? 'broadcast failed'))\n if (!data.result) throw new NetworkError('Blockbook returned no txid', { provider: this.base })\n return data.result\n }\n\n /** sat/vB. Blockbook reports BTC/kB (×1e5 → sat/vB); falls back to mempool.space when it has no estimate. */\n async estimateFee(blocks: number): Promise<number> {\n try {\n const data = await this.get(`/v1/estimatefee/${blocks}`, (v): v is { result?: string } | string => typeof v === 'string' || isRecord(v))\n const rate = Number(typeof data === 'string' ? data : data.result)\n if (rate > 0) return Math.max(rate * 100_000, 1)\n } catch { /* fall through */ }\n const res = await fetchWithTimeout(this.fetchFn, `${MEMPOOL_SPACE_URL}/api/v1/fees/recommended`, undefined, this.timeoutMs, MEMPOOL_SPACE_URL)\n if (!res.ok) throw new NetworkError('Fee estimation request failed', { provider: MEMPOOL_SPACE_URL })\n const d = (await res.json()) as { fastestFee: number; halfHourFee: number; hourFee: number; economyFee: number }\n const satPerVb = blocks <= 1 ? d.fastestFee : blocks <= 3 ? d.halfHourFee : blocks <= 6 ? d.hourFee : d.economyFee\n if (!satPerVb || satPerVb <= 0) throw new NetworkError('Fee estimation is unavailable', { provider: MEMPOOL_SPACE_URL })\n return satPerVb\n }\n\n async getBlockHeight(): Promise<number> {\n const data = await this.get('/v2', (v): v is { blockbook?: { bestHeight?: number } } => isRecord(v))\n const h = data.blockbook?.bestHeight\n if (typeof h !== 'number' || h <= 0) throw new NetworkError('Blockbook did not report a block height', { provider: this.base })\n return h\n }\n}\n","import { NetworkError } from '@anywalletkit/core'\n\nexport const DEFAULT_TIMEOUT_MS = 15_000\n\n/** fetch with a per-request timeout when the runtime has `AbortSignal.timeout` (Hermes needs runtime-hermes for it). */\nexport async function fetchWithTimeout(fetchFn: typeof fetch, url: string, init: RequestInit | undefined, timeoutMs: number, provider: string): Promise<Response> {\n const signal = typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function' ? AbortSignal.timeout(timeoutMs) : undefined\n try {\n return await fetchFn(url, { ...init, ...(signal ? { signal } : {}) })\n } catch (e) {\n throw new NetworkError(`Request failed: ${url}`, { provider, cause: e })\n }\n}\n\n/** An HTTP status that is the server refusing the request itself: 4xx, but not 408 (request timeout). */\nexport const refusedStatus = (status: number): boolean => status >= 400 && status < 500 && status !== 408\n\n/** Mark an error as a node's answer refusing the request: nothing was taken (round 3, M12). */\nexport function refusal<E extends Error>(e: E): E {\n return Object.assign(e, { answered: true })\n}\n\n/**\n * An endpoint answered with a refusal (HTTP 4xx other than 408, or an error body): nothing was\n * taken. A thrown fetch, a timeout, a 5xx or a body that cannot be read may have been.\n */\nexport function isAnsweredRefusal(e: unknown): boolean {\n return (e as { answered?: unknown } | null)?.answered === true\n}\n\n/** The node says it already holds the transaction (an earlier attempt delivered it): it is out, not refused. */\nexport function isAlreadyKnown(e: unknown): boolean {\n for (let x: unknown = e, depth = 0; x instanceof Error && depth < 5; x = x.cause, depth++) {\n if (/txn-already-(in-mempool|known)|already (known|in (the )?(mempool|block ?chain))/i.test(x.message)) return true\n }\n return false\n}\n\nexport const isRecord = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v)\nexport const isHex64 = (v: unknown): v is string => typeof v === 'string' && /^[0-9a-fA-F]{64}$/.test(v)\nexport const isIntString = (v: unknown): v is string => typeof v === 'string' && /^-?\\d+$/.test(v)\n","/** Bitcoin mainnet, testnet or regtest. */\nexport type BtcNetwork = 'bitcoin' | 'testnet' | 'regtest'\n\n/** Address / script type the account spends from. BIP-84 p2wpkh (bc1q…) or BIP-86 p2tr (bc1p…). */\nexport type BtcAddressType = 'p2wpkh' | 'p2tr'\n\n/** Minimal chain-data client every transport implements. Values in satoshis, fee rates in sat/vB. */\nexport interface BtcClient {\n connect(): Promise<void>\n close(): Promise<void>\n getBalance(address: string): Promise<{ confirmed: bigint; unconfirmed: bigint; unconfirmedOutgoing?: bigint }>\n listUnspent(address: string): Promise<Utxo[]>\n getHistory(address: string): Promise<Array<{ txid: string; height: number }>>\n /** Raw transaction hex. */\n getTransaction(txid: string): Promise<string>\n /** Full tx record (used for receipts). */\n getTransactionInfo?(txid: string): Promise<BlockbookTx | undefined>\n /** Broadcast raw hex; returns the txid. */\n broadcast(rawTx: string): Promise<string>\n /** Fee rate in sat/vB for confirmation within `blocks`. */\n estimateFee(blocks: number): Promise<number>\n /** Current chain tip height (anti-fee-sniping locktime). Optional. */\n getBlockHeight?(): Promise<number>\n}\n\n/** An unspent output the account can spend. */\nexport interface Utxo {\n txid: string\n vout: number\n /** Satoshis. */\n value: bigint\n /** Block height; 0 or -1 while unconfirmed. */\n height: number\n}\n\n/** One transport to a Bitcoin indexer: Blockbook or Esplora over HTTP. */\nexport type BtcClientConfig =\n /** Trezor Blockbook REST (`https://btc1.trezor.io`, QuickNode's Blockbook add-on, …). */\n | { type: 'blockbook-http'; clientConfig: { url: string } }\n /** Esplora REST (`https://mempool.space/api`, `https://blockstream.info/api`). */\n | { type: 'esplora-http'; clientConfig: { url: string } }\n\n/**\n * Options for a Bitcoin wallet manager or account: transports, network, address type and fee\n * limits.\n */\nexport interface BtcConfig {\n /** One or more transports (config objects or ready `BtcClient`s). A list fails over in order. Omit for an offline (sign-only) wallet. */\n client?: BtcClientConfig | BtcClient | Array<BtcClientConfig | BtcClient>\n /** Network; default `bitcoin` (mainnet). */\n network?: BtcNetwork\n /** p2wpkh (BIP-84, default) or p2tr (BIP-86 taproot). Changes the derivation path and the address. */\n addressType?: BtcAddressType\n /** Extra attempts across the client list after the first failure (default 3). */\n retries?: number\n /** Per-request timeout in ms (default 15000). */\n timeoutMs?: number\n /** Max fee (sats) for `transfer`. */\n transferMaxFee?: bigint | number\n /** Max fee (sats) for `sendTransaction` / `signTransaction`. */\n transactionMaxFee?: bigint | number\n /** Fee-rate ceiling in sat/vB (default 500). Anything above is refused before signing or broadcast. */\n maxFeeRate?: number\n /** Coin-selection input cap (default 200). */\n maxInputs?: number\n /** Opt-in to replace-by-fee signalling (default true). */\n rbf?: boolean\n /** Set nLockTime to the current height so the tx cannot be mined into a reorg (default true; skipped when the transport has no `getBlockHeight`). */\n antiFeeSniping?: boolean\n /** Injectable fetch (tests, custom agents). Defaults to globalThis.fetch. */\n fetch?: typeof fetch\n}\n\n/** A spend. `value` in satoshis; `feeRate` in sat/vB (estimated for `confirmationTarget` blocks when omitted). */\nexport interface BtcSpend {\n to: string\n value: bigint | number | string\n feeRate?: bigint | number\n confirmationTarget?: number\n /** Override the account-level `rbf` default for this spend. */\n rbf?: boolean\n}\n\n/** `sendTransaction` accepts a spend or an already signed raw transaction hex. */\nexport type BtcTransaction = BtcSpend | string\n\n/** A Bitcoin transfer. Amount in satoshis. */\nexport interface BtcTransferOptions {\n /** Not supported on Bitcoin; present for the shared account interface. */\n token?: string\n recipient: string\n amount: bigint | number | string\n}\n\n/** A mined Bitcoin transaction. */\nexport interface BtcReceipt {\n hash: string\n /** Always 1 once mined — a Bitcoin transaction cannot fail after inclusion. */\n status: 1\n blockNumber: bigint\n confirmations: number\n /** Total fee in sats (when the transport reports it). */\n fee?: bigint\n hex?: string\n}\n\n/** Transport-neutral tx record (Blockbook's /api/v2/tx shape; Esplora is mapped onto it). */\nexport interface BlockbookTx {\n txid: string\n blockHeight: number\n confirmations: number\n fees?: string\n hex?: string\n blockTime?: number\n}\n\n/** The most one transaction can send (a sweep of every UTXO), after the fee. */\nexport interface BtcMaxSpendableResult {\n /** Max sats one transaction can send after the fee. 0n when nothing is spendable. */\n amount: bigint\n fee: bigint\n /** Always 0n: a sweep leaves no change. */\n changeValue: bigint\n /** Inputs the sweep would consume. */\n inputs: number\n feeRate: bigint\n}\n\n/** Problems a described transaction is flagged with. */\nexport type BtcWarning =\n /** Fee rate above `maxFeeRate` (also a hard error before signing/broadcast). */\n | 'high-fee-rate'\n /** Fee exceeds 10 % of the amount sent. */\n | 'fee-over-10pct-of-amount'\n /** An output is below its dust threshold. */\n | 'dust-output'\n /** Change was below dust and folded into the fee. */\n | 'no-change'\n\n/** One input of a described transaction: the UTXO it spends. */\nexport interface BtcTxInputDescription {\n txid: string\n vout: number\n value: bigint\n}\n\n/** One output of a described transaction, tagged as the recipient, our change, or unknown. */\nexport interface BtcTxOutputDescription {\n /** Undefined for scripts without an address form. */\n address: string | undefined\n value: bigint\n role: 'recipient' | 'change' | 'unknown'\n}\n\n/** \"What you sign\": the fully resolved transaction before (or after) signing. */\nexport interface BtcTxDescription {\n kind: 'btc-transfer'\n inputs: BtcTxInputDescription[]\n outputs: BtcTxOutputDescription[]\n /** Sats sent to non-change outputs. */\n amount: bigint\n fee: bigint\n /** sat/vB, rounded to 2 decimals. */\n feeRate: number\n vsize: number\n rbf: boolean\n lockTime: number\n /** Present once the transaction is signed. */\n txid?: string\n warnings: BtcWarning[]\n}\n\n/** CAIP-2 ids of the Bitcoin networks, by name. */\nexport const CAIP2_GENESIS: Record<BtcNetwork, string> = {\n bitcoin: 'bip122:000000000019d6689c085ae165831e93',\n testnet: 'bip122:000000000933ea01ad0ee984209779ba',\n regtest: 'bip122:0f9188f13cb7b2c71f2a335e3a4fc328',\n}\n"],"mappings":"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","names":["import_core"]}
1
+ {"version":3,"sources":["../src/history.ts","../src/blockbook.ts","../src/http.ts","../src/types.ts"],"sourcesContent":["/**\n * Activity history for Bitcoin: a `HistorySource` over Blockbook's\n * `/api/v2/address/{a}?details=txs` pages (Trezor's indexer, QuickNode's\n * Blockbook add-on, any self-hosted instance), reusing the package's\n * `BlockbookClient` and failing over across several instances.\n *\n * One transaction = one native transfer in the owner's direction: a send is\n * what left to non-own outputs (fee separate), a receive is what landed on the\n * address. The cursor is the Blockbook page number. Explorer: mempool.space.\n */\nimport type { ChainTransfer, ChainTx, HistoryPage, HistoryQuery, HistorySource } from '@anywalletkit/core'\nimport { BlockbookClient, type BlockbookAddressPage, type BlockbookTxDetails } from './blockbook.js'\nimport { DEFAULT_TIMEOUT_MS } from './http.js'\nimport { CAIP2_GENESIS, type BtcNetwork } from './types.js'\n\n// ── Public types ─────────────────────────────────────────────────────────────\n\n/** Options for {@link createBtcHistory}. */\nexport interface BtcHistoryOptions {\n /** One Blockbook root (`https://btc1.trezor.io`). */\n blockbookUrl?: string\n /** Several roots, tried in order (failover). */\n blockbookUrls?: string[]\n /** `bitcoin` (default), `testnet`, `regtest`. */\n network?: BtcNetwork\n fetch?: typeof fetch\n /** Per request, ms. Default 15 000. */\n timeoutMs?: number\n /** Rows per Blockbook page (its max is 1000). Default: the query limit, capped at 100. */\n pageSize?: number\n}\n\n/** What a Bitcoin `ChainTx` was built from, and the address's own totals. */\nexport interface BtcHistoryRaw {\n /** The Blockbook transaction (vin / vout with addresses and values; `hex` dropped). */\n tx: BlockbookTxDetails\n /** Sum of inputs spent by the address, sats. */\n ownIn: bigint\n /** Sum of outputs paid to the address, sats. */\n ownOut: bigint\n}\n\n/** A `ChainTx` with the Blockbook transaction it was built from. */\nexport interface BtcChainTx extends ChainTx {\n raw: BtcHistoryRaw\n}\n\n/** One page of Bitcoin history. */\nexport interface BtcHistoryPage extends HistoryPage {\n items: BtcChainTx[]\n /** Blockbook page served / total pages. */\n page?: number\n totalPages?: number\n}\n\n/** Bitcoin history from a Blockbook instance. Build it with {@link createBtcHistory}. */\nexport interface BtcHistorySource extends HistorySource {\n listActivity(address: string, query?: HistoryQuery): Promise<BtcHistoryPage>\n getTransaction(hash: string, address: string): Promise<BtcChainTx | undefined>\n}\n\n/** Every configured Blockbook endpoint failed (or none was configured). */\nexport class HistoryUnavailableError extends Error {\n readonly chain: string\n readonly reason: string\n readonly attempts: readonly string[]\n constructor(chain: string, reason: string, attempts: readonly string[] = []) {\n super(`History unavailable for ${chain}: ${reason}`)\n this.name = 'HistoryUnavailableError'\n this.chain = chain\n this.reason = reason\n this.attempts = attempts\n }\n}\n\nconst DEFAULT_LIMIT = 25\nconst MAX_PAGE_SIZE = 100\n\n// ── Cursor: the next Blockbook page, base64 JSON ─────────────────────────────\n\n/** @internal Decoded form of a Bitcoin history cursor. */\nexport interface BtcHistoryCursor {\n v: 1\n /** Next page (1-based). */\n p: number\n /** Page size the pagination started with (changing it mid-way would skip or repeat rows). */\n s: number\n}\n\nconst B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n\nfunction b64encode(s: string): string {\n let out = ''\n for (let i = 0; i < s.length; i += 3) {\n const c = [s.charCodeAt(i), s.charCodeAt(i + 1), s.charCodeAt(i + 2)]\n const n = (c[0]! << 16) | ((c[1]! || 0) << 8) | (c[2]! || 0)\n out += B64[(n >> 18) & 63]! + B64[(n >> 12) & 63]! + (Number.isNaN(c[1]) ? '=' : B64[(n >> 6) & 63]!) + (Number.isNaN(c[2]) ? '=' : B64[n & 63]!)\n }\n return out\n}\n\nfunction b64decode(s: string): string {\n const clean = s.replace(/[^A-Za-z0-9+/]/g, '')\n let out = ''\n for (let i = 0; i < clean.length; i += 4) {\n const c = [0, 1, 2, 3].map((k) => (i + k < clean.length ? B64.indexOf(clean[i + k]!) : -1))\n if (c[0]! < 0 || c[1]! < 0) throw new Error('bad base64')\n const n = (c[0]! << 18) | (c[1]! << 12) | ((c[2]! < 0 ? 0 : c[2]!) << 6) | (c[3]! < 0 ? 0 : c[3]!)\n out += String.fromCharCode((n >> 16) & 0xff)\n if (c[2]! >= 0) out += String.fromCharCode((n >> 8) & 0xff)\n if (c[3]! >= 0) out += String.fromCharCode(n & 0xff)\n }\n return out\n}\n\nexport function encodeCursor(c: BtcHistoryCursor): string {\n return b64encode(JSON.stringify(c))\n}\n\nexport function decodeCursor(s: string): BtcHistoryCursor {\n let parsed: unknown\n try {\n parsed = JSON.parse(b64decode(s))\n } catch {\n throw new Error('@anywalletkit/wallet-btc: malformed history cursor')\n }\n const c = parsed as Partial<BtcHistoryCursor> | null\n if (!c || c.v !== 1 || !Number.isInteger(c.p) || (c.p as number) < 1 || !Number.isInteger(c.s) || (c.s as number) < 1) throw new Error('@anywalletkit/wallet-btc: malformed history cursor')\n return { v: 1, p: c.p as number, s: c.s as number }\n}\n\n// ── Mapping ──────────────────────────────────────────────────────────────────\n\nconst big = (v: unknown): bigint => (typeof v === 'string' && /^-?\\d+$/.test(v) ? BigInt(v) : typeof v === 'number' ? BigInt(Math.trunc(v)) : 0n)\n\nexport function mapBlockbookTx(chain: string, address: string, tx: BlockbookTxDetails): BtcChainTx {\n const owns = (e: { isAddress?: boolean; addresses?: string[] }) => e.isAddress !== false && (e.addresses ?? []).includes(address)\n let ownIn = 0n, ownOut = 0n, sentToOthers = 0n\n for (const vin of tx.vin ?? []) if (owns(vin)) ownIn += big(vin.value)\n for (const vout of tx.vout ?? []) {\n if (owns(vout)) ownOut += big(vout.value)\n else sentToOthers += big(vout.value)\n }\n const firstInput = (tx.vin ?? []).find((v) => v.isAddress !== false && v.addresses?.[0])?.addresses?.[0]\n const firstOtherOutput = (tx.vout ?? []).find((v) => v.isAddress !== false && !owns(v) && v.addresses?.[0])?.addresses?.[0]\n const transfers: ChainTransfer[] = []\n let from: string, to: string | null, nativeValue: bigint\n if (ownIn > 0n) {\n // We spent inputs: a send (or a consolidation when every output is ours).\n from = address\n to = firstOtherOutput ?? address\n nativeValue = firstOtherOutput ? sentToOthers : ownOut\n if (nativeValue > 0n) transfers.push({ token: null, from: address, to, amount: nativeValue })\n } else {\n // Only outputs are ours: a receive (coinbase has no input address).\n from = firstInput ?? 'coinbase'\n to = address\n nativeValue = ownOut\n if (nativeValue > 0n) transfers.push({ token: null, from, to: address, amount: nativeValue })\n }\n const confirmed = tx.confirmations > 0 && tx.blockHeight > 0\n const out: BtcChainTx = {\n chain, hash: tx.txid, time: tx.blockTime ?? 0, status: confirmed ? 'confirmed' : 'pending', address, from, to, nativeValue, transfers,\n raw: { tx, ownIn, ownOut },\n }\n if (tx.fees !== undefined) out.fee = big(tx.fees)\n if (confirmed) out.block = BigInt(tx.blockHeight)\n return out\n}\n\n// ── Source ───────────────────────────────────────────────────────────────────\n\n/** mempool.space link for a transaction. */\nexport function btcExplorerTxUrl(hash: string, network: BtcNetwork = 'bitcoin'): string {\n return `https://mempool.space/${network === 'testnet' ? 'testnet/' : ''}tx/${hash}`\n}\n\n/**\n * A history source for Bitcoin addresses backed by Blockbook (Trezor's public instances,\n * QuickNode's add-on, or your own).\n *\n * @throws Error when no Blockbook URL is given.\n */\nexport function createBtcHistory(options: BtcHistoryOptions = {}): BtcHistorySource {\n const network = options.network ?? 'bitcoin'\n const chain = CAIP2_GENESIS[network]\n const urls = [...(options.blockbookUrls ?? []), ...(options.blockbookUrl ? [options.blockbookUrl] : [])]\n if (urls.length === 0) throw new Error('@anywalletkit/wallet-btc: createBtcHistory needs blockbookUrl or blockbookUrls')\n const fetchFn = options.fetch ?? globalThis.fetch\n if (typeof fetchFn !== 'function') throw new Error('@anywalletkit/wallet-btc: no global fetch; pass `fetch` in the options')\n const clients = urls.map((url) => ({ url, client: new BlockbookClient({ url }, fetchFn, options.timeoutMs ?? DEFAULT_TIMEOUT_MS) }))\n\n async function failover<T>(run: (client: BlockbookClient) => Promise<T>): Promise<T> {\n const attempts: string[] = []\n for (const { url, client } of clients) {\n try {\n return await run(client)\n } catch (e) {\n attempts.push(`${url}: ${e instanceof Error ? e.message : String(e)}`)\n }\n }\n throw new HistoryUnavailableError(chain, attempts[attempts.length - 1] ?? 'every Blockbook failed', attempts)\n }\n\n return {\n chain,\n\n async listActivity(address: string, query: HistoryQuery = {}): Promise<BtcHistoryPage> {\n const cursor = query.cursor ? decodeCursor(query.cursor) : undefined\n const pageSize = cursor?.s ?? Math.min(MAX_PAGE_SIZE, Math.max(1, Math.floor(options.pageSize ?? query.limit ?? DEFAULT_LIMIT)))\n const pageNo = cursor?.p ?? 1\n const data: BlockbookAddressPage = await failover((c) => c.getAddressPage(address, pageNo, pageSize))\n let items = (data.transactions ?? []).map((tx) => mapBlockbookTx(chain, address, tx))\n items.sort((a, b) => (b.block === undefined ? 1 : a.block === undefined ? -1 : (b.block > a.block ? 1 : b.block < a.block ? -1 : 0)) || b.time - a.time)\n const totalPages = data.totalPages ?? 1\n let more = pageNo < totalPages\n if (query.since !== undefined) {\n const since = query.since\n if (items.some((t) => t.status === 'confirmed' && t.time < since)) more = false\n items = items.filter((t) => t.status !== 'confirmed' || t.time >= since)\n }\n const page: BtcHistoryPage = { items, page: pageNo, totalPages }\n if (more) page.cursor = encodeCursor({ v: 1, p: pageNo + 1, s: pageSize })\n return page\n },\n\n async getTransaction(hash: string, address: string): Promise<BtcChainTx | undefined> {\n const tx = await failover((c) => c.getTransactionDetails(hash))\n return tx ? mapBlockbookTx(chain, address, tx) : undefined\n },\n\n explorerTxUrl(hash: string): string {\n return btcExplorerTxUrl(hash, network)\n },\n }\n}\n\n","import { NetworkError } from '@anywalletkit/core'\nimport { DEFAULT_TIMEOUT_MS, fetchWithTimeout, isIntString, isRecord, refusal, refusedStatus } from './http.js'\nimport type { BlockbookTx, BtcClient, Utxo } from './types.js'\n\nconst MEMPOOL_SPACE_URL = 'https://mempool.space'\n\nexport interface BlockbookVin { txid?: string; vout?: number; n?: number; isAddress?: boolean; isOwn?: boolean; addresses?: string[]; value?: string }\nexport interface BlockbookVout { n: number; isAddress?: boolean; isOwn?: boolean; addresses?: string[]; value?: string; spent?: boolean }\nexport interface BlockbookAddressTx { txid: string; blockHeight: number; vin?: BlockbookVin[]; vout?: BlockbookVout[] }\n/** A Blockbook transaction with its inputs and outputs (`/api/v2/tx/{txid}`, or one row of `?details=txs`). */\nexport interface BlockbookTxDetails extends BlockbookTx {\n vin?: BlockbookVin[]\n vout?: BlockbookVout[]\n value?: string\n valueIn?: string\n}\n/** One `/api/v2/address/{a}?details=txs` page. */\nexport interface BlockbookAddressPage {\n page?: number\n totalPages?: number\n itemsOnPage?: number\n address?: string\n balance?: string\n unconfirmedBalance?: string\n txs?: number\n transactions?: BlockbookTxDetails[]\n}\n\n/**\n * Pending outgoing value the way Bitcoin Core's wallet counts it: a pending tx\n * is trusted only if every input is ours and confirmed or chained from another\n * trusted tx; only then its change counts back.\n */\nexport function unconfirmedOutgoing(transactions: BlockbookAddressTx[] | undefined, address: string): bigint {\n const pending = (transactions ?? []).filter((tx) => tx.blockHeight === -1)\n const pendingIds = new Set(pending.map((t) => t.txid))\n const byId = new Map(pending.map((t) => [t.txid, t]))\n const trusted = new Map<string, boolean>()\n const owned = (entries: Array<BlockbookVin | BlockbookVout> | undefined) =>\n (entries ?? []).filter((e) => e.isAddress && e.addresses?.includes(address)).reduce((s, e) => s + BigInt(e.value ?? 0), 0n)\n const isTrusted = (tx: BlockbookAddressTx): boolean => {\n if (trusted.has(tx.txid)) return trusted.get(tx.txid)!\n trusted.set(tx.txid, false)\n const vins = tx.vin ?? []\n const ours = vins.filter((v) => v.isAddress && v.addresses?.includes(address))\n const ok = vins.length > 0 && ours.length === vins.length && ours.every((v) => !v.txid || !pendingIds.has(v.txid) || isTrusted(byId.get(v.txid)!))\n trusted.set(tx.txid, ok)\n return ok\n }\n const consumed = new Set<string>()\n for (const tx of pending) for (const v of tx.vin ?? []) if (v.txid && pendingIds.has(v.txid)) consumed.add(`${v.txid}:${v.vout}`)\n return pending.reduce((total, tx) => {\n const spent = owned((tx.vin ?? []).filter((v) => !v.txid || !pendingIds.has(v.txid)))\n const change = isTrusted(tx) ? owned((tx.vout ?? []).filter((o) => !consumed.has(`${tx.txid}:${o.n}`))) : 0n\n return total + (spent - change)\n }, 0n)\n}\n\n/** Blockbook REST transport (Trezor's indexer; QuickNode's Blockbook add-on speaks the same API). */\nexport class BlockbookClient implements BtcClient {\n private readonly base: string\n private readonly fetchFn: typeof fetch\n private readonly timeoutMs: number\n\n constructor(config: { url: string }, fetchFn: typeof fetch = globalThis.fetch, timeoutMs = DEFAULT_TIMEOUT_MS) {\n this.base = config.url.replace(/\\/+$/, '').replace(/\\/api$/, '')\n this.fetchFn = fetchFn\n this.timeoutMs = timeoutMs\n }\n\n async connect(): Promise<void> {}\n async close(): Promise<void> {}\n\n private async get<T>(path: string, check: (v: unknown) => v is T): Promise<T> {\n const url = `${this.base}/api${path}`\n const res = await fetchWithTimeout(this.fetchFn, url, undefined, this.timeoutMs, this.base)\n if (!res.ok) {\n // A 4xx (not 408) is the server refusing: nothing was taken. A 5xx may have been forwarded (round 3, M12).\n const reason = refusedStatus(res.status) ? (await res.text().catch(() => '')).slice(0, 200) : ''\n const err = new NetworkError(`Blockbook request failed: ${res.status} ${res.statusText} (${url})${reason ? `: ${reason}` : ''}`, { provider: this.base })\n throw refusedStatus(res.status) ? refusal(err) : err\n }\n let body: unknown\n try { body = await res.json() } catch (e) { throw new NetworkError(`Blockbook returned non-JSON for ${url}`, { provider: this.base, cause: e }) }\n if (!check(body)) throw new NetworkError(`Blockbook returned an unexpected shape for ${url}`, { provider: this.base })\n return body\n }\n\n async getBalance(address: string) {\n const data = await this.get(`/v2/address/${address}?details=txs`, (v): v is { balance: string; unconfirmedBalance: string; transactions?: BlockbookAddressTx[] } =>\n isRecord(v) && isIntString(v.balance) && isIntString(v.unconfirmedBalance) && (v.transactions === undefined || Array.isArray(v.transactions)))\n return { confirmed: BigInt(data.balance), unconfirmed: BigInt(data.unconfirmedBalance), unconfirmedOutgoing: unconfirmedOutgoing(data.transactions, address) }\n }\n\n async listUnspent(address: string): Promise<Utxo[]> {\n const data = await this.get(`/v2/utxo/${address}`, (v): v is Array<{ txid: string; vout: number; value: string; height?: number }> =>\n Array.isArray(v) && v.every((u) => isRecord(u) && typeof u.txid === 'string' && typeof u.vout === 'number' && isIntString(u.value)))\n return data.map((u) => ({ txid: u.txid, vout: u.vout, value: BigInt(u.value), height: u.height ?? -1 }))\n }\n\n async getHistory(address: string) {\n const items: Array<{ txid: string; height: number }> = []\n for (let page = 1; ; page++) {\n const data = await this.get(`/v2/address/${address}?details=txslight&pageSize=1000&page=${page}`, (v): v is { transactions?: Array<{ txid: string; blockHeight: number }>; totalPages?: number } =>\n isRecord(v) && (v.transactions === undefined || Array.isArray(v.transactions)))\n for (const tx of data.transactions ?? []) items.push({ txid: tx.txid, height: tx.blockHeight })\n if (page >= (data.totalPages ?? 1)) break\n }\n return items\n }\n\n /** One page of the address's transactions, newest first, with inputs / outputs (what the activity history reads). */\n async getAddressPage(address: string, page = 1, pageSize = 25): Promise<BlockbookAddressPage> {\n const data = await this.get(`/v2/address/${address}?details=txs&page=${page}&pageSize=${pageSize}`, (v): v is BlockbookAddressPage =>\n isRecord(v) && (v.transactions === undefined || (Array.isArray(v.transactions) && v.transactions.every(BlockbookClient.isTx))))\n const out: BlockbookAddressPage = { ...data }\n for (const tx of out.transactions ?? []) delete (tx as { hex?: string }).hex\n return out\n }\n\n /** A transaction with its inputs / outputs; undefined when Blockbook does not know it. */\n async getTransactionDetails(txid: string): Promise<BlockbookTxDetails | undefined> {\n try {\n const tx = await this.get(`/v2/tx/${txid}`, (v): v is BlockbookTxDetails => BlockbookClient.isTx(v))\n const out: BlockbookTxDetails = { ...tx }\n delete (out as { hex?: string }).hex\n return out\n } catch (e) {\n if (e instanceof NetworkError && /\\b(400|404)\\b/.test(e.message)) return undefined\n throw e\n }\n }\n\n private static isTx(v: unknown): v is BlockbookTx {\n return isRecord(v) && typeof v.txid === 'string' && typeof v.blockHeight === 'number' && typeof v.confirmations === 'number'\n }\n\n async getTransactionInfo(txid: string): Promise<BlockbookTx | undefined> {\n try { return await this.get(`/v2/tx/${txid}`, BlockbookClient.isTx) } catch (e) {\n if (e instanceof NetworkError && /\\b(400|404)\\b/.test(e.message)) return undefined\n throw e\n }\n }\n\n async getTransaction(txid: string): Promise<string> {\n const data = await this.get(`/v2/tx/${txid}`, BlockbookClient.isTx)\n if (typeof data.hex !== 'string' || !data.hex) throw new NetworkError(`Transaction ${txid} has no hex data`, { provider: this.base })\n return data.hex\n }\n\n async broadcast(rawTx: string): Promise<string> {\n const data = await this.get(`/v2/sendtx/${rawTx}`, (v): v is { result?: string; error?: { message?: string } | string } => isRecord(v))\n if (data.error) throw refusal(new Error(typeof data.error === 'string' ? data.error : data.error.message ?? 'broadcast failed'))\n if (!data.result) throw new NetworkError('Blockbook returned no txid', { provider: this.base })\n return data.result\n }\n\n /** sat/vB. Blockbook reports BTC/kB (×1e5 → sat/vB); falls back to mempool.space when it has no estimate. */\n async estimateFee(blocks: number): Promise<number> {\n try {\n const data = await this.get(`/v1/estimatefee/${blocks}`, (v): v is { result?: string } | string => typeof v === 'string' || isRecord(v))\n const rate = Number(typeof data === 'string' ? data : data.result)\n if (rate > 0) return Math.max(rate * 100_000, 1)\n } catch { /* fall through */ }\n const res = await fetchWithTimeout(this.fetchFn, `${MEMPOOL_SPACE_URL}/api/v1/fees/recommended`, undefined, this.timeoutMs, MEMPOOL_SPACE_URL)\n if (!res.ok) throw new NetworkError('Fee estimation request failed', { provider: MEMPOOL_SPACE_URL })\n const d = (await res.json()) as { fastestFee: number; halfHourFee: number; hourFee: number; economyFee: number }\n const satPerVb = blocks <= 1 ? d.fastestFee : blocks <= 3 ? d.halfHourFee : blocks <= 6 ? d.hourFee : d.economyFee\n if (!satPerVb || satPerVb <= 0) throw new NetworkError('Fee estimation is unavailable', { provider: MEMPOOL_SPACE_URL })\n return satPerVb\n }\n\n async getBlockHeight(): Promise<number> {\n const data = await this.get('/v2', (v): v is { blockbook?: { bestHeight?: number } } => isRecord(v))\n const h = data.blockbook?.bestHeight\n if (typeof h !== 'number' || h <= 0) throw new NetworkError('Blockbook did not report a block height', { provider: this.base })\n return h\n }\n}\n","import { NetworkError } from '@anywalletkit/core'\n\nexport const DEFAULT_TIMEOUT_MS = 15_000\n\n/** fetch with a per-request timeout when the runtime has `AbortSignal.timeout` (Hermes needs runtime-hermes for it). */\nexport async function fetchWithTimeout(fetchFn: typeof fetch, url: string, init: RequestInit | undefined, timeoutMs: number, provider: string): Promise<Response> {\n const signal = typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function' ? AbortSignal.timeout(timeoutMs) : undefined\n try {\n return await fetchFn(url, { ...init, ...(signal ? { signal } : {}) })\n } catch (e) {\n throw new NetworkError(`Request failed: ${url}`, { provider, cause: e })\n }\n}\n\n/** An HTTP status that is the server refusing the request itself: 4xx, but not 408 (request timeout). */\nexport const refusedStatus = (status: number): boolean => status >= 400 && status < 500 && status !== 408\n\n/** Mark an error as a node's answer refusing the request: nothing was taken (round 3, M12). */\nexport function refusal<E extends Error>(e: E): E {\n return Object.assign(e, { answered: true })\n}\n\n/**\n * An endpoint answered with a refusal (HTTP 4xx other than 408, or an error body): nothing was\n * taken. A thrown fetch, a timeout, a 5xx or a body that cannot be read may have been.\n */\nexport function isAnsweredRefusal(e: unknown): boolean {\n return (e as { answered?: unknown } | null)?.answered === true\n}\n\n/** The node says it already holds the transaction (an earlier attempt delivered it): it is out, not refused. */\nexport function isAlreadyKnown(e: unknown): boolean {\n for (let x: unknown = e, depth = 0; x instanceof Error && depth < 5; x = x.cause, depth++) {\n if (/txn-already-(in-mempool|known)|already (known|in (the )?(mempool|block ?chain))/i.test(x.message)) return true\n }\n return false\n}\n\nexport const isRecord = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v)\nexport const isHex64 = (v: unknown): v is string => typeof v === 'string' && /^[0-9a-fA-F]{64}$/.test(v)\nexport const isIntString = (v: unknown): v is string => typeof v === 'string' && /^-?\\d+$/.test(v)\n","/** Bitcoin mainnet, testnet or regtest. */\nexport type BtcNetwork = 'bitcoin' | 'testnet' | 'regtest'\n\n/** Address / script type the account spends from. BIP-84 p2wpkh (bc1q…) or BIP-86 p2tr (bc1p…). */\nexport type BtcAddressType = 'p2wpkh' | 'p2tr'\n\n/** Minimal chain-data client every transport implements. Values in satoshis, fee rates in sat/vB. */\nexport interface BtcClient {\n connect(): Promise<void>\n close(): Promise<void>\n getBalance(address: string): Promise<{ confirmed: bigint; unconfirmed: bigint; unconfirmedOutgoing?: bigint }>\n listUnspent(address: string): Promise<Utxo[]>\n getHistory(address: string): Promise<Array<{ txid: string; height: number }>>\n /** Raw transaction hex. */\n getTransaction(txid: string): Promise<string>\n /** Full tx record (used for receipts). */\n getTransactionInfo?(txid: string): Promise<BlockbookTx | undefined>\n /** Broadcast raw hex; returns the txid. */\n broadcast(rawTx: string): Promise<string>\n /** Fee rate in sat/vB for confirmation within `blocks`. */\n estimateFee(blocks: number): Promise<number>\n /** Current chain tip height (anti-fee-sniping locktime). Optional. */\n getBlockHeight?(): Promise<number>\n}\n\n/** An unspent output the account can spend. */\nexport interface Utxo {\n txid: string\n vout: number\n /** Satoshis. */\n value: bigint\n /** Block height; 0 or -1 while unconfirmed. */\n height: number\n}\n\n/** One transport to a Bitcoin indexer: Blockbook or Esplora over HTTP. */\nexport type BtcClientConfig =\n /** Trezor Blockbook REST (`https://btc1.trezor.io`, QuickNode's Blockbook add-on, …). */\n | { type: 'blockbook-http'; clientConfig: { url: string } }\n /** Esplora REST (`https://mempool.space/api`, `https://blockstream.info/api`). */\n | { type: 'esplora-http'; clientConfig: { url: string } }\n\n/**\n * Options for a Bitcoin wallet manager or account: transports, network, address type and fee\n * limits.\n */\nexport interface BtcConfig {\n /** One or more transports (config objects or ready `BtcClient`s). A list fails over in order. Omit for an offline (sign-only) wallet. */\n client?: BtcClientConfig | BtcClient | Array<BtcClientConfig | BtcClient>\n /** Network; default `bitcoin` (mainnet). */\n network?: BtcNetwork\n /** p2wpkh (BIP-84, default) or p2tr (BIP-86 taproot). Changes the derivation path and the address. */\n addressType?: BtcAddressType\n /** Extra attempts across the client list after the first failure (default 3). */\n retries?: number\n /** Per-request timeout in ms (default 15000). */\n timeoutMs?: number\n /** Max fee (sats) for `transfer`. */\n transferMaxFee?: bigint | number\n /** Max fee (sats) for `sendTransaction` / `signTransaction`. */\n transactionMaxFee?: bigint | number\n /** Fee-rate ceiling in sat/vB (default 500). Anything above is refused before signing or broadcast. */\n maxFeeRate?: number\n /** Coin-selection input cap (default 200). */\n maxInputs?: number\n /** Opt-in to replace-by-fee signalling (default true). */\n rbf?: boolean\n /** Set nLockTime to the current height so the tx cannot be mined into a reorg (default true; skipped when the transport has no `getBlockHeight`). */\n antiFeeSniping?: boolean\n /** Injectable fetch (tests, custom agents). Defaults to globalThis.fetch. */\n fetch?: typeof fetch\n}\n\n/** A spend. `value` in satoshis; `feeRate` in sat/vB (estimated for `confirmationTarget` blocks when omitted). */\nexport interface BtcSpend {\n to: string\n value: bigint | number | string\n feeRate?: bigint | number\n confirmationTarget?: number\n /** Override the account-level `rbf` default for this spend. */\n rbf?: boolean\n}\n\n/** `sendTransaction` accepts a spend or an already signed raw transaction hex. */\nexport type BtcTransaction = BtcSpend | string\n\n/** A Bitcoin transfer. Amount in satoshis. */\nexport interface BtcTransferOptions {\n /** Not supported on Bitcoin; present for the shared account interface. */\n token?: string\n recipient: string\n amount: bigint | number | string\n}\n\n/** A mined Bitcoin transaction. */\nexport interface BtcReceipt {\n hash: string\n /** Always 1 once mined — a Bitcoin transaction cannot fail after inclusion. */\n status: 1\n blockNumber: bigint\n confirmations: number\n /** Total fee in sats (when the transport reports it). */\n fee?: bigint\n hex?: string\n}\n\n/** Transport-neutral tx record (Blockbook's /api/v2/tx shape; Esplora is mapped onto it). */\nexport interface BlockbookTx {\n txid: string\n blockHeight: number\n confirmations: number\n fees?: string\n hex?: string\n blockTime?: number\n}\n\n/** The most one transaction can send (a sweep of every UTXO), after the fee. */\nexport interface BtcMaxSpendableResult {\n /** Max sats one transaction can send after the fee. 0n when nothing is spendable. */\n amount: bigint\n fee: bigint\n /** Always 0n: a sweep leaves no change. */\n changeValue: bigint\n /** Inputs the sweep would consume. */\n inputs: number\n feeRate: bigint\n}\n\n/** Problems a described transaction is flagged with. */\nexport type BtcWarning =\n /** Fee rate above `maxFeeRate` (also a hard error before signing/broadcast). */\n | 'high-fee-rate'\n /** Fee exceeds 10 % of the amount sent. */\n | 'fee-over-10pct-of-amount'\n /** An output is below its dust threshold. */\n | 'dust-output'\n /** Change was below dust and folded into the fee. */\n | 'no-change'\n\n/** One input of a described transaction: the UTXO it spends. */\nexport interface BtcTxInputDescription {\n txid: string\n vout: number\n value: bigint\n}\n\n/** One output of a described transaction, tagged as the recipient, our change, or unknown. */\nexport interface BtcTxOutputDescription {\n /** Undefined for scripts without an address form. */\n address: string | undefined\n value: bigint\n role: 'recipient' | 'change' | 'unknown'\n}\n\n/** \"What you sign\": the fully resolved transaction before (or after) signing. */\nexport interface BtcTxDescription {\n kind: 'btc-transfer'\n inputs: BtcTxInputDescription[]\n outputs: BtcTxOutputDescription[]\n /** Sats sent to non-change outputs. */\n amount: bigint\n fee: bigint\n /** sat/vB, rounded to 2 decimals. */\n feeRate: number\n vsize: number\n rbf: boolean\n lockTime: number\n /** Present once the transaction is signed. */\n txid?: string\n warnings: BtcWarning[]\n}\n\n/** CAIP-2 ids of the Bitcoin networks, by name. */\nexport const CAIP2_GENESIS: Record<BtcNetwork, string> = {\n bitcoin: 'bip122:000000000019d6689c085ae165831e93',\n testnet: 'bip122:000000000933ea01ad0ee984209779ba',\n regtest: 'bip122:0f9188f13cb7b2c71f2a335e3a4fc328',\n}\n"],"mappings":"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","names":["import_core"]}
@@ -1,2 +1,2 @@
1
1
  import '@anywalletkit/core';
2
- export { p as BtcChainTx, r as BtcHistoryCursor, s as BtcHistoryOptions, t as BtcHistoryPage, u as BtcHistoryRaw, v as BtcHistorySource, H as HistoryUnavailableError, z as btcExplorerTxUrl, A as createBtcHistory, D as decodeCursor, E as encodeCursor, F as mapBlockbookTx } from './history-B5fmsCjZ.cjs';
2
+ export { q as BtcChainTx, s as BtcHistoryCursor, t as BtcHistoryOptions, u as BtcHistoryPage, v as BtcHistoryRaw, w as BtcHistorySource, H as HistoryUnavailableError, A as btcExplorerTxUrl, D as createBtcHistory, E as decodeCursor, F as encodeCursor, G as mapBlockbookTx } from './history-CasPAf7l.cjs';
package/dist/history.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  import '@anywalletkit/core';
2
- export { p as BtcChainTx, r as BtcHistoryCursor, s as BtcHistoryOptions, t as BtcHistoryPage, u as BtcHistoryRaw, v as BtcHistorySource, H as HistoryUnavailableError, z as btcExplorerTxUrl, A as createBtcHistory, D as decodeCursor, E as encodeCursor, F as mapBlockbookTx } from './history-B5fmsCjZ.js';
2
+ export { q as BtcChainTx, s as BtcHistoryCursor, t as BtcHistoryOptions, u as BtcHistoryPage, v as BtcHistoryRaw, w as BtcHistorySource, H as HistoryUnavailableError, A as btcExplorerTxUrl, D as createBtcHistory, E as decodeCursor, F as encodeCursor, G as mapBlockbookTx } from './history-CasPAf7l.js';
package/dist/history.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  decodeCursor,
6
6
  encodeCursor,
7
7
  mapBlockbookTx
8
- } from "./chunk-TZNOUBSP.js";
8
+ } from "./chunk-SIR2SRK2.js";
9
9
  export {
10
10
  HistoryUnavailableError,
11
11
  btcExplorerTxUrl,
package/dist/index.cjs CHANGED
@@ -928,7 +928,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
928
928
  * p2wpkh → `partialSig` (DER + SIGHASH_ALL), p2tr → `tapKeySig` (64 bytes, DEFAULT).
929
929
  * btc-signer only computes the sighash and assembles the witness; it never sees a key.
930
930
  */
931
- async signInputs(tx, values) {
931
+ async #signInputs(tx, values) {
932
932
  if (this.addressType === "p2tr") {
933
933
  const { tweak } = this.taprootKeys();
934
934
  const scripts = Array.from({ length: tx.inputsLength }, () => this.scriptPubKey);
@@ -953,7 +953,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
953
953
  ctx(intended) {
954
954
  return { network: this._network, ownAddress: this.address, intended, maxFeeRate: this.maxFeeRate };
955
955
  }
956
- async signPlan(plan, to, recipientValue, change, lockTime, rbf) {
956
+ async #signPlan(plan, to, recipientValue, change, lockTime, rbf) {
957
957
  const spend = spendInfo(this.publicKey, this._network, this.addressType);
958
958
  const tx = new import_btc_signer4.Transaction({ lockTime });
959
959
  const sequence = rbf ? RBF_SEQUENCE : FINAL_SEQUENCE;
@@ -962,7 +962,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
962
962
  }
963
963
  tx.addOutputAddress(to, recipientValue, this._network);
964
964
  if (change > 0n) tx.addOutputAddress(this.address, change, this._network);
965
- await this.signInputs(tx, plan.utxos.map((u) => u.value));
965
+ await this.#signInputs(tx, plan.utxos.map((u) => u.value));
966
966
  tx.finalize();
967
967
  return tx;
968
968
  }
@@ -971,7 +971,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
971
971
  * signed vsize somehow needs more, the difference comes out of change (never the
972
972
  * recipient) and the tx is re-signed once.
973
973
  */
974
- async signSpend(spend) {
974
+ async #signSpend(spend) {
975
975
  this.live();
976
976
  const plan = await this.planSpend(spend);
977
977
  await this.verifyPrevouts(plan.utxos);
@@ -979,7 +979,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
979
979
  const rbf = spend.rbf ?? this._config.rbf ?? true;
980
980
  let change = plan.change;
981
981
  let fee = plan.fee;
982
- let tx = await this.signPlan(plan, spend.to, plan.amount, change, lockTime, rbf);
982
+ let tx = await this.#signPlan(plan, spend.to, plan.amount, change, lockTime, rbf);
983
983
  const required = BigInt(tx.vsize) * plan.feeRate;
984
984
  if (required > fee) {
985
985
  const delta = required - fee;
@@ -992,7 +992,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
992
992
  fee = plan.fee + plan.change;
993
993
  change = 0n;
994
994
  } else fee = required;
995
- tx = await this.signPlan(plan, spend.to, plan.amount, change, lockTime, rbf);
995
+ tx = await this.#signPlan(plan, spend.to, plan.amount, change, lockTime, rbf);
996
996
  if (BigInt(tx.vsize) * plan.feeRate > fee) throw new Error("Fee shortfall after output rebalance.");
997
997
  }
998
998
  const ctx = this.ctx({ to: spend.to, value: plan.amount });
@@ -1063,7 +1063,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
1063
1063
  /** "What you sign": the fully resolved spend (signed, NOT broadcast) or a caller's raw hex. */
1064
1064
  async describeTransaction(tx) {
1065
1065
  if (typeof tx === "string") return (await this.describeRaw(tx)).desc;
1066
- return (await this.signSpend(tx)).desc;
1066
+ return (await this.#signSpend(tx)).desc;
1067
1067
  }
1068
1068
  /** Sign without broadcasting. Returns the raw transaction hex. Raw hex input gets the checks `sendTransaction` runs (prevouts through the client) and is returned unchanged, never re-signed. */
1069
1069
  async signTransaction(tx, options = {}) {
@@ -1073,7 +1073,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
1073
1073
  this.checkMax(desc.fee, (0, import_core9.feeLimit)(this._config.transactionMaxFee, options), "transaction");
1074
1074
  return tx;
1075
1075
  }
1076
- const { tx: built, fee } = await this.signSpend(tx);
1076
+ const { tx: built, fee } = await this.#signSpend(tx);
1077
1077
  this.checkMax(fee, (0, import_core9.feeLimit)(this._config.transactionMaxFee, options), "transaction");
1078
1078
  return built.hex;
1079
1079
  }
@@ -1091,7 +1091,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
1091
1091
  hash = parsed.id;
1092
1092
  fee = desc.fee;
1093
1093
  } else {
1094
- const built = await this.signSpend(tx);
1094
+ const built = await this.#signSpend(tx);
1095
1095
  rawHex = built.tx.hex;
1096
1096
  hash = built.tx.id;
1097
1097
  fee = built.fee;
@@ -1104,7 +1104,7 @@ var WalletAccountBtc = class _WalletAccountBtc extends WalletAccountReadOnlyBtc
1104
1104
  if (o.token) throw new Error("Tokens are not supported on the bitcoin blockchain.");
1105
1105
  this.live();
1106
1106
  const client = this.requireClient("transfer");
1107
- const built = await this.signSpend({ to: o.recipient, value: o.amount });
1107
+ const built = await this.#signSpend({ to: o.recipient, value: o.amount });
1108
1108
  this.checkMax(built.fee, (0, import_core9.feeLimit)(this._config.transferMaxFee, writeOptions), "transfer");
1109
1109
  return { hash: await this.broadcast(client, built.tx.hex, built.tx.id), fee: built.fee };
1110
1110
  }