@anywalletkit/wallet-btc 0.3.0 → 0.3.1

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.
@@ -1 +0,0 @@
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 }\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","/**\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":"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","names":["NetworkError","NetworkError"]}