{"_id":"@asylia/blockchain-data-btc","_rev":"3-4531148a5028d3e376e0354532202407","name":"@asylia/blockchain-data-btc","dist-tags":{"latest":"1.0.1"},"versions":{"0.1.0":{"name":"@asylia/blockchain-data-btc","version":"0.1.0","keywords":["bitcoin","blockchain","blockchain-data","btc","address-balance","utxo","broadcast","raw-transaction","blockstream","mempool","esplora","blockchain.com","blockcypher","coinbase","coingecko","kraken","fiat-rates","failover","rate-limiting","request-deduplication","wallet-sdk","typescript","self-custody","asylia"],"author":{"name":"Asylia"},"license":"MIT","_id":"@asylia/blockchain-data-btc@0.1.0","maintainers":[{"name":"asylion21","email":"infodavidzita@gmail.com"}],"homepage":"https://github.com/Asylia/bitcoin-toolkit/tree/main/packages/blockchain-data-btc#readme","bugs":{"url":"https://github.com/Asylia/bitcoin-toolkit/issues"},"dist":{"shasum":"e57bb1447309ca517d8721b1cc45cde28b82dc2c","tarball":"https://registry.npmjs.org/@asylia/blockchain-data-btc/-/blockchain-data-btc-0.1.0.tgz","fileCount":6,"integrity":"sha512-Me0QtiFwDo8zP1xEYP80mGqHU8SP48V8SUtU7jtt9G608EcuKJQykEUXj+j8vYZ29ge/XxXCYoaTkWYtfMHw7Q==","signatures":[{"sig":"MEYCIQDiXkjI09fg1pn8pPzVk1ALoo7uscZf3Qd3gk8wUlxttQIhAOjEWotWvwDkS8vo/DYK6/BE9Rq1Tf9eGUjLr9op0x+s","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":379809},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup src/index.ts --format esm --dts --sourcemap --clean --out-dir dist --tsconfig tsconfig.build.json","clean":"rimraf dist .turbo node_modules/.tmp","type-check":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"asylion21","email":"infodavidzita@gmail.com"},"repository":{"url":"git+https://github.com/Asylia/bitcoin-toolkit.git","type":"git","directory":"packages/blockchain-data-btc"},"_npmVersion":"10.9.2","description":"Auditable Bitcoin chain-data TypeScript SDK with normalized balances, UTXOs, transactions, raw tx lookup, broadcast, fiat rates, provider failover, cooldowns, rate limiting, and request deduplication.","directories":{},"_nodeVersion":"22.14.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","rimraf":"^6.1.3","vitest":"^4.1.5","typescript":"^6.0.3","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/blockchain-data-btc_0.1.0_1777723332094_0.9466902500401027","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@asylia/blockchain-data-btc","version":"1.0.0","keywords":["bitcoin","blockchain","blockchain-data","btc","address-balance","utxo","broadcast","raw-transaction","blockstream","mempool","esplora","blockchain.com","blockcypher","coinbase","coingecko","kraken","fiat-rates","failover","rate-limiting","request-deduplication","wallet-sdk","typescript","self-custody","asylia"],"author":{"name":"Asylia"},"license":"MIT","_id":"@asylia/blockchain-data-btc@1.0.0","maintainers":[{"name":"asylion21","email":"infodavidzita@gmail.com"}],"homepage":"https://github.com/Asylia/bitcoin-toolkit/tree/main/packages/blockchain-data-btc#readme","bugs":{"url":"https://github.com/Asylia/bitcoin-toolkit/issues"},"dist":{"shasum":"2081501f44c52d95b53820425bd58694a6c34f2d","tarball":"https://registry.npmjs.org/@asylia/blockchain-data-btc/-/blockchain-data-btc-1.0.0.tgz","fileCount":7,"integrity":"sha512-jCUE3fhUcADop6YuspRNVzPRSix6rw44wsrXDBw72g2Lc2IFUdpkH81QrXkt2BRf2dIg6uAf1GhVqgNHLzjorw==","signatures":[{"sig":"MEUCIQDrS+8725qCT8l+EZA9urWGS37gclWWbrzwzIEzq0KnLQIgQZUwDvecpYBB4bIsAJXS6sF02o+UZmLkQruemYIG4TE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":380527},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"9472028259c7ecd4e1becd42fd837267dfdd7fca","scripts":{"lint":"eslint .","test":"vitest run","build":"tsup src/index.ts --format esm --dts --sourcemap --clean --out-dir dist --tsconfig tsconfig.build.json","clean":"rimraf dist .turbo node_modules/.tmp","type-check":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"asylion21","email":"infodavidzita@gmail.com"},"repository":{"url":"git+https://github.com/Asylia/bitcoin-toolkit.git","type":"git","directory":"packages/blockchain-data-btc"},"_npmVersion":"10.9.2","description":"Auditable Bitcoin chain-data TypeScript SDK with normalized balances, UTXOs, transactions, raw tx lookup, broadcast, fiat rates, provider failover, cooldowns, rate limiting, and request deduplication.","directories":{},"_nodeVersion":"22.14.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","rimraf":"^6.1.3","vitest":"^4.1.5","typescript":"^6.0.3","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/blockchain-data-btc_1.0.0_1777891160701_0.15399680749339306","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@asylia/blockchain-data-btc","version":"1.0.1","type":"module","description":"Auditable Bitcoin chain-data TypeScript SDK with normalized balances, UTXOs, transactions, raw tx lookup, broadcast, fiat rates, provider failover, cooldowns, rate limiting, and request deduplication.","license":"MIT","author":{"name":"Asylia"},"repository":{"type":"git","url":"git+https://github.com/Asylia/bitcoin-toolkit.git","directory":"packages/blockchain-data-btc"},"homepage":"https://github.com/Asylia/bitcoin-toolkit/tree/main/packages/blockchain-data-btc#readme","bugs":{"url":"https://github.com/Asylia/bitcoin-toolkit/issues"},"keywords":["bitcoin","blockchain","blockchain-data","btc","address-balance","utxo","broadcast","raw-transaction","blockstream","mempool","esplora","blockchain.com","blockcypher","coinbase","coingecko","kraken","fiat-rates","failover","rate-limiting","request-deduplication","wallet-sdk","typescript","self-custody","asylia"],"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsup src/index.ts --format esm --dts --sourcemap --clean --out-dir dist --tsconfig tsconfig.build.json","type-check":"tsc --noEmit","lint":"eslint .","test":"vitest run","test:coverage":"vitest run --coverage","clean":"rimraf dist .turbo node_modules/.tmp"},"devDependencies":{"@vitest/coverage-v8":"^4.1.6","rimraf":"^6.1.3","tsup":"^8.5.1","typescript":"^6.0.3","vitest":"^4.1.6"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_id":"@asylia/blockchain-data-btc@1.0.1","gitHead":"d269e09a317e911fc1438e068c02a209abc5dac4","_nodeVersion":"21.7.3","_npmVersion":"10.7.0","dist":{"integrity":"sha512-GV1k0vdgJnFAywb8DlL3KrJjJFgkJY+vqiwgnzeENVqfcJDupFrNo1LSinpP3wcn08X2H9MoRqtdSZeHnEqV6A==","shasum":"f938996b30b098e1925c7734d11f89a089282368","tarball":"https://registry.npmjs.org/@asylia/blockchain-data-btc/-/blockchain-data-btc-1.0.1.tgz","fileCount":7,"unpackedSize":414600,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDJSOcWTQ/tpDOSc/DF8GVKprVFp1OEsT7sqAa5v6/nvAiAihole2vMdVQv9jtqrJ+9wuC2b54iGTHH+JQ6WPUHHcw=="}]},"_npmUser":{"name":"asylion21","email":"infodavidzita@gmail.com"},"directories":{},"maintainers":[{"name":"asylion21","email":"infodavidzita@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/blockchain-data-btc_1.0.1_1778785887545_0.8042708544494115"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-02T12:02:11.801Z","modified":"2026-05-14T19:11:27.873Z","0.1.0":"2026-05-02T12:02:12.253Z","1.0.0":"2026-05-04T10:39:20.863Z","1.0.1":"2026-05-14T19:11:27.717Z"},"bugs":{"url":"https://github.com/Asylia/bitcoin-toolkit/issues"},"author":{"name":"Asylia"},"license":"MIT","homepage":"https://github.com/Asylia/bitcoin-toolkit/tree/main/packages/blockchain-data-btc#readme","keywords":["bitcoin","blockchain","blockchain-data","btc","address-balance","utxo","broadcast","raw-transaction","blockstream","mempool","esplora","blockchain.com","blockcypher","coinbase","coingecko","kraken","fiat-rates","failover","rate-limiting","request-deduplication","wallet-sdk","typescript","self-custody","asylia"],"repository":{"type":"git","url":"git+https://github.com/Asylia/bitcoin-toolkit.git","directory":"packages/blockchain-data-btc"},"description":"Auditable Bitcoin chain-data TypeScript SDK with normalized balances, UTXOs, transactions, raw tx lookup, broadcast, fiat rates, provider failover, cooldowns, rate limiting, and request deduplication.","maintainers":[{"name":"asylion21","email":"infodavidzita@gmail.com"}],"readme":"<p align=\"center\">\n  <img src=\"../../apps/wallet/resources/logo.svg\" alt=\"Asylia\" width=\"96\" />\n</p>\n\n# @asylia/blockchain-data-btc\n\nNormalized Bitcoin chain-data and market-data SDK for the Asylia self-custody\nplatform. One `BlockchainDataService` fronts multiple upstream providers and\nreturns stable TypeScript shapes for balances, UTXOs, transactions, raw funding\ntransactions, fiat rates, block height, and broadcast results.\n\nThe package is runtime-light and framework-agnostic. It is designed to run in\nbrowsers, Deno/Supabase Edge Functions, and Node 18+ using Web `fetch` APIs.\n\nKeywords: Bitcoin chain data, Mempool.space, Blockstream, Esplora, Blockchain.com,\nBlockcypher, UTXO API, Bitcoin broadcast, fiat rates, rate limiting, failover,\nrequest deduplication, TypeScript wallet SDK.\n\n## Maintainer And Support\n\n`@asylia/blockchain-data-btc` is maintained by\n[Asylian21](https://github.com/Asylian21).\n\n> **Support Asylia Bitcoin tooling**\n>\n> If this work helps your wallet, audit, integration, or research, you can\n> support ongoing development with a Bitcoin donation:\n> `bc1qrdchup8497xz0972v35q4nr0fx5egghf0z23c3`\n\n## Status\n\n`1.0.0`. The package ships the stable Asylia chain-data provider stack for the\nBitcoin wallet toolkit.\n\n## Installation\n\n```bash\nnpm install @asylia/blockchain-data-btc\n```\n\n## Why This Package Exists\n\nWallet code should not care which upstream answered a chain-data request. It\nneeds a deterministic API that:\n\n- returns the same response shape across providers,\n- survives outages and rate limits by rotating through a priority list,\n- cools down providers that return 429/403 responses,\n- coalesces identical concurrent requests,\n- avoids duplicate provider spend during manual refreshes,\n- can be reused from the browser, server-side fallbacks, tests, and future\n  mobile tooling.\n\n## Provider Architecture\n\nThe Asylia wallet can read chain data directly from the browser and escalate to\na caller-owned edge fallback only when needed:\n\n```text\nBlockchainDataService\n├─ MempoolSpaceProvider          read, raw tx, broadcast\n├─ BlockstreamInfoProvider       read, raw tx, broadcast\n├─ EsploraMirrorProvider         read, raw tx, broadcast\n├─ BlockchainDotComProvider      balance, UTXO, broadcast\n├─ BlockcypherProvider           balance, UTXO, txs, tip, broadcast\n├─ CoinbaseProvider              fiat BTC rates\n├─ CoinGeckoProvider             fiat BTC rates\n├─ KrakenProvider                fiat BTC rates\n└─ EdgeFallbackProvider          caller-supplied server/edge escape hatch\n```\n\n`EdgeFallbackProvider` accepts an `invoke({ op, args })` callback. That keeps the\nSDK free of Supabase, Vercel, HTTP route, or RPC assumptions while still letting\nthe wallet call a server-side endpoint that owns paid provider credentials.\n\n## Privacy Note\n\nWhen used directly in a browser, the upstream provider that answers a request\ncan see the user's IP address and the queried addresses. Asylia accepts this for\nthe default web wallet because it improves latency, keeps the app static, and\nlets several public providers absorb normal load. Operators with stricter\naddress-set privacy requirements should run their own Esplora endpoint behind a\nprivacy gateway and register it through `EsploraMirrorProvider` or an edge\nfallback.\n\n## Quick Start\n\n```ts\nimport {\n  BlockchainDataService,\n  BlockcypherProvider,\n  BlockchainDotComProvider,\n  BlockstreamInfoProvider,\n  EdgeFallbackProvider,\n  EsploraMirrorProvider,\n  MempoolSpaceProvider,\n  ProviderId,\n} from '@asylia/blockchain-data-btc';\n\nconst chainData = new BlockchainDataService({\n  providers: {\n    [ProviderId.MEMPOOL_SPACE]: new MempoolSpaceProvider(),\n    [ProviderId.BLOCKSTREAM_INFO]: new BlockstreamInfoProvider(),\n    [ProviderId.MEMPOOL_EMZY]: new EsploraMirrorProvider({\n      baseUrl: 'https://mempool.emzy.de/api',\n      displayName: 'MEMPOOL_EMZY',\n    }),\n    [ProviderId.BLOCKCHAIN_DOT_COM]: new BlockchainDotComProvider(),\n    [ProviderId.BLOCKCYPHER]: new BlockcypherProvider(),\n    [ProviderId.EDGE_FALLBACK]: new EdgeFallbackProvider({\n      invoke: (payload) => callMyServerSideFallback(payload),\n    }),\n  },\n  devMode: true,\n});\n\nconst balance = await chainData.getSingle('bc1q...');\nconst multi = await chainData.getMulti(['bc1q...', 'bc1q...']);\nconst utxos = await chainData.getUtxos(['bc1q...']);\nconst transactions = await chainData.getTransactions(['bc1q...']);\nconst rawFundingTx = await chainData.getRawTransaction('f'.repeat(64));\nconst tip = await chainData.getTipHeight();\nconst broadcast = await chainData.broadcastTransaction(rawTxHex, expectedTxid);\n```\n\n`balance_sats` is confirmed balance. `pending_sats` is the signed net\nunconfirmed mempool delta when the provider can expose it cleanly.\n\n## Public API\n\n| Export | Purpose |\n| --- | --- |\n| `BlockchainDataService` | Main facade. Construct once per tab/process. |\n| `ProviderId` | Stable provider identifiers used in config, logging, and dev info. |\n| `ProviderRole` | Capability tags such as read balance, UTXO, raw tx, broadcast, fiat, or tip. |\n| `ProviderRateLimitError` | Marker error used to trip provider cooldowns. |\n| `NormalizedAddressBalance`, `NormalizedUtxo`, `NormalizedTransaction` | Canonical chain-data shapes returned across providers. |\n| `SingleAddressResponse`, `MultiAddressResponse`, `MultiAddressUtxosResponse`, `MultiAddressTransactionsResponse`, `RawTransactionResponse`, `BroadcastTransactionResponse`, `FiatRatesSnapshot` | Service response contracts. |\n| `defaultProviderConfig`, `getProviderRateLimit` | Defaults and rate-limit helpers. |\n| `RateLimiterService`, `RequestCache` | Lower-level primitives exposed for tests and custom runtimes. |\n| `MempoolSpaceProvider`, `BlockstreamInfoProvider`, `EsploraMirrorProvider`, `BlockchainDotComProvider`, `BlockcypherProvider`, `CoinbaseProvider`, `CoinGeckoProvider`, `KrakenProvider`, `EdgeFallbackProvider` | Built-in provider implementations. |\n| `Provider` | Interface for custom upstream integrations. |\n\n## Failover Behavior\n\nFor every service call, the SDK walks the configured provider priority order:\n\n1. Skip providers that do not support the requested role.\n2. Skip providers whose sliding-window budget is exhausted.\n3. Skip providers in an explicit cooldown window.\n4. Call the next eligible provider.\n5. Return the normalized response on success.\n6. On a `ProviderRateLimitError`, honor `Retry-After` when available and try the\n   next provider.\n7. On ordinary upstream failure, record the attempt and continue.\n8. Throw `NO_PROVIDER_AVAILABLE` only after every eligible provider fails.\n\nWhen `devMode: true`, responses include `dev_info.data_providers_used` so\noperators can see which upstreams were attempted.\n\n## Request Deduplication\n\nIdentical concurrent requests share one in-flight Promise:\n\n```ts\nconst first = chainData.getSingle('bc1q...');\nconst second = chainData.getSingle('bc1q...');\nconst [a, b] = await Promise.all([first, second]);\n// One provider request, two callers.\n```\n\nSettled results are cached for short method-specific TTL windows. Passing\n`{ force: true }` bypasses the settled TTL entry but still joins an already\nrunning request for the same key, so manual refreshes cannot double-spend\nprovider budget.\n\nMulti-address methods are order-safe: calls with the same address set share one\nprovider request even when callers pass addresses in different orders, and the\nresult is realigned to each caller's original order.\n\n## Serverless Rate-Limit Caveat\n\nThe bundled `RateLimiterService` is in-memory. In stateless serverless\nenvironments each cold invocation starts with a clean budget, so the limiter\nprotects only bursts within one warm container. Pair it with a durable debounce,\nlease, or `last_synced_at` row when correctness must span invocations.\n\nIn the Asylia wallet, the limiter lives for the user's tab session and is paired\nwith Supabase sync-state rows so multiple tabs do not all refresh the same vault\nat once.\n\n## Testing\n\nInject a provider stub to make tests deterministic:\n\n```ts\nimport { ProviderId, type Provider } from '@asylia/blockchain-data-btc';\n\nconst stub: Provider = {\n  fetchSingle: async (address) => ({\n    address,\n    balance_sats: 100_000,\n    pending_sats: 0,\n    total_received_sats: 100_000,\n    tx_count: 1,\n  }),\n};\n\nchainData.setProvider(ProviderId.BLOCKSTREAM_INFO, stub);\n```\n\n```bash\nyarn workspace @asylia/blockchain-data-btc type-check\nyarn workspace @asylia/blockchain-data-btc test\n```\n\n## Related Packages\n\n- [`@asylia/btc-core`](../btc-core) - descriptors, address derivation, PSBTs,\n  signatures, and coin selection.\n- [`@asylia/hw-trezor`](../hw-trezor) - Trezor adapter.\n- [`@asylia/hw-ledger`](../hw-ledger) - Ledger adapter.\n\n## License\n\nMIT - see [`LICENSE`](./LICENSE).\n","readmeFilename":"README.md"}