npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@asylia/blockchain-data-btc

v1.0.0

Published

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.

Readme

@asylia/blockchain-data-btc

Normalized Bitcoin chain-data and market-data SDK for the Asylia self-custody platform. One BlockchainDataService fronts multiple upstream providers and returns stable TypeScript shapes for balances, UTXOs, transactions, raw funding transactions, fiat rates, block height, and broadcast results.

The package is runtime-light and framework-agnostic. It is designed to run in browsers, Deno/Supabase Edge Functions, and Node 18+ using Web fetch APIs.

Keywords: Bitcoin chain data, Mempool.space, Blockstream, Esplora, Blockchain.com, Blockcypher, UTXO API, Bitcoin broadcast, fiat rates, rate limiting, failover, request deduplication, TypeScript wallet SDK.

Maintainer And Support

@asylia/blockchain-data-btc is maintained by Asylian21.

Support Asylia Bitcoin tooling

If this work helps your wallet, audit, integration, or research, you can support ongoing development with a Bitcoin donation: bc1qrdchup8497xz0972v35q4nr0fx5egghf0z23c3

Status

1.0.0. The package ships the stable Asylia chain-data provider stack for the Bitcoin wallet toolkit.

Installation

npm install @asylia/blockchain-data-btc

Why This Package Exists

Wallet code should not care which upstream answered a chain-data request. It needs a deterministic API that:

  • returns the same response shape across providers,
  • survives outages and rate limits by rotating through a priority list,
  • cools down providers that return 429/403 responses,
  • coalesces identical concurrent requests,
  • avoids duplicate provider spend during manual refreshes,
  • can be reused from the browser, server-side fallbacks, tests, and future mobile tooling.

Provider Architecture

The Asylia wallet can read chain data directly from the browser and escalate to a caller-owned edge fallback only when needed:

BlockchainDataService
├─ MempoolSpaceProvider          read, raw tx, broadcast
├─ BlockstreamInfoProvider       read, raw tx, broadcast
├─ EsploraMirrorProvider         read, raw tx, broadcast
├─ BlockchainDotComProvider      balance, UTXO, broadcast
├─ BlockcypherProvider           balance, UTXO, txs, tip, broadcast
├─ CoinbaseProvider              fiat BTC rates
├─ CoinGeckoProvider             fiat BTC rates
├─ KrakenProvider                fiat BTC rates
└─ EdgeFallbackProvider          caller-supplied server/edge escape hatch

EdgeFallbackProvider accepts an invoke({ op, args }) callback. That keeps the SDK free of Supabase, Vercel, HTTP route, or RPC assumptions while still letting the wallet call a server-side endpoint that owns paid provider credentials.

Privacy Note

When used directly in a browser, the upstream provider that answers a request can see the user's IP address and the queried addresses. Asylia accepts this for the default web wallet because it improves latency, keeps the app static, and lets several public providers absorb normal load. Operators with stricter address-set privacy requirements should run their own Esplora endpoint behind a privacy gateway and register it through EsploraMirrorProvider or an edge fallback.

Quick Start

import {
  BlockchainDataService,
  BlockcypherProvider,
  BlockchainDotComProvider,
  BlockstreamInfoProvider,
  EdgeFallbackProvider,
  EsploraMirrorProvider,
  MempoolSpaceProvider,
  ProviderId,
} from '@asylia/blockchain-data-btc';

const chainData = new BlockchainDataService({
  providers: {
    [ProviderId.MEMPOOL_SPACE]: new MempoolSpaceProvider(),
    [ProviderId.BLOCKSTREAM_INFO]: new BlockstreamInfoProvider(),
    [ProviderId.MEMPOOL_EMZY]: new EsploraMirrorProvider({
      baseUrl: 'https://mempool.emzy.de/api',
      displayName: 'MEMPOOL_EMZY',
    }),
    [ProviderId.BLOCKCHAIN_DOT_COM]: new BlockchainDotComProvider(),
    [ProviderId.BLOCKCYPHER]: new BlockcypherProvider(),
    [ProviderId.EDGE_FALLBACK]: new EdgeFallbackProvider({
      invoke: (payload) => callMyServerSideFallback(payload),
    }),
  },
  devMode: true,
});

const balance = await chainData.getSingle('bc1q...');
const multi = await chainData.getMulti(['bc1q...', 'bc1q...']);
const utxos = await chainData.getUtxos(['bc1q...']);
const transactions = await chainData.getTransactions(['bc1q...']);
const rawFundingTx = await chainData.getRawTransaction('f'.repeat(64));
const tip = await chainData.getTipHeight();
const broadcast = await chainData.broadcastTransaction(rawTxHex, expectedTxid);

balance_sats is confirmed balance. pending_sats is net unconfirmed inflow clamped at zero when the provider can expose it cleanly.

Public API

| Export | Purpose | | --- | --- | | BlockchainDataService | Main facade. Construct once per tab/process. | | ProviderId | Stable provider identifiers used in config, logging, and dev info. | | ProviderRole | Capability tags such as read balance, UTXO, raw tx, broadcast, fiat, or tip. | | ProviderRateLimitError | Marker error used to trip provider cooldowns. | | NormalizedAddressBalance, NormalizedUtxo, NormalizedTransaction | Canonical chain-data shapes returned across providers. | | SingleAddressResponse, MultiAddressResponse, MultiAddressUtxosResponse, MultiAddressTransactionsResponse, RawTransactionResponse, BroadcastTransactionResponse, FiatRatesSnapshot | Service response contracts. | | defaultProviderConfig, getProviderRateLimit | Defaults and rate-limit helpers. | | RateLimiterService, RequestCache | Lower-level primitives exposed for tests and custom runtimes. | | MempoolSpaceProvider, BlockstreamInfoProvider, EsploraMirrorProvider, BlockchainDotComProvider, BlockcypherProvider, CoinbaseProvider, CoinGeckoProvider, KrakenProvider, EdgeFallbackProvider | Built-in provider implementations. | | Provider | Interface for custom upstream integrations. |

Failover Behavior

For every service call, the SDK walks the configured provider priority order:

  1. Skip providers that do not support the requested role.
  2. Skip providers whose sliding-window budget is exhausted.
  3. Skip providers in an explicit cooldown window.
  4. Call the next eligible provider.
  5. Return the normalized response on success.
  6. On a ProviderRateLimitError, honor Retry-After when available and try the next provider.
  7. On ordinary upstream failure, record the attempt and continue.
  8. Throw NO_PROVIDER_AVAILABLE only after every eligible provider fails.

When devMode: true, responses include dev_info.data_providers_used so operators can see which upstreams were attempted.

Request Deduplication

Identical concurrent requests share one in-flight Promise:

const first = chainData.getSingle('bc1q...');
const second = chainData.getSingle('bc1q...');
const [a, b] = await Promise.all([first, second]);
// One provider request, two callers.

Settled results are cached for short method-specific TTL windows. Passing { force: true } bypasses the settled TTL entry but still joins an already running request for the same key, so manual refreshes cannot double-spend provider budget.

Multi-address methods are order-safe: calls with the same address set share one provider request even when callers pass addresses in different orders, and the result is realigned to each caller's original order.

Serverless Rate-Limit Caveat

The bundled RateLimiterService is in-memory. In stateless serverless environments each cold invocation starts with a clean budget, so the limiter protects only bursts within one warm container. Pair it with a durable debounce, lease, or last_synced_at row when correctness must span invocations.

In the Asylia wallet, the limiter lives for the user's tab session and is paired with Supabase sync-state rows so multiple tabs do not all refresh the same vault at once.

Testing

Inject a provider stub to make tests deterministic:

import { ProviderId, type Provider } from '@asylia/blockchain-data-btc';

const stub: Provider = {
  fetchSingle: async (address) => ({
    address,
    balance_sats: 100_000,
    pending_sats: 0,
    total_received_sats: 100_000,
    tx_count: 1,
  }),
};

chainData.setProvider(ProviderId.BLOCKSTREAM_INFO, stub);
yarn workspace @asylia/blockchain-data-btc type-check
yarn workspace @asylia/blockchain-data-btc test

Related Packages

License

MIT - see LICENSE.