Files
2026-05-27 23:29:53 +01:00

5.2 KiB

Add @suaveplan/currency-provider-coinmarketcap sibling provider

Package: @suaveplan/currency-provider-coinmarketcap Status: PROPOSED Type: new package (sibling of slimmed @suaveplan/currency-providers)

  • Spec delta: ./specs/currency-provider-coinmarketcap/spec.md

Why

The 2026-05-17 slim-currency-providers refactor moved the nine concrete provider classes out of @suaveplan/currency-providers and committed each one to its own publishable sibling package. This change lands the CoinMarketCap sibling — a crypto rate source backed by the pro-api.coinmarketcap.com REST API and authenticated through the X-CMC_PRO_API_KEY HTTP header.

Consumers that already register sibling providers via CurrencyProviderRegistry (or instantiate them directly into CurrencyConverter) gain a CoinMarketCap option without installing eight other provider packages they do not wire in.

What changes

ADDED

  • @suaveplan/currency-provider-coinmarketcap package at packages/finance/currency-provider-coinmarketcap/, version 0.1.0, universal-tier (sideEffects: false).
  • CoinMarketCapProvider class implementing CurrencyProvider from @suaveplan/currency. Constructed from ApiKeyConfig (apiKey, optional baseUrl, optional injectable FetchLike from @suaveplan/types).
  • supportsCrypto: true, supportsFiat: false, no supportsVirtual. CoinMarketCap is a crypto-rates source — fiat rates are out of scope for this sibling (consumers wanting fiat install currency-provider-ecb / currency-provider-fixer / currency-provider-open-exchange-rates).
  • fetchRates(options?) calls GET <baseUrl>/cryptocurrency/quotes/latest?symbol=<targets>&convert=<base> via the shared httpRequest() helper from @suaveplan/currency-providers. The X-CMC_PRO_API_KEY header carries config.apiKey; the Accept header is application/json.
  • Constructor raises CurrencyProviderError(MISSING_CONFIG) when config.apiKey is empty or whitespace-only (consistent with the ApiKeyConfig contract documented in the slim core).
  • Response parsing raises CurrencyProviderError(PARSE_ERROR) when the payload is not valid JSON or the data map is missing / wrong shape.
  • Response parsing raises CurrencyProviderError(UPSTREAM_ERROR) when the upstream payload contains a non-null status.error_code field.
  • fetchRates() raises CurrencyProviderError(UNKNOWN_CURRENCY) when none of the requested target symbols resolve to a quote in the configured base currency.
  • Non-2xx HTTP responses surface as CurrencyProviderError(HTTP_ERROR) (raised by the shared httpRequest() helper, with status populated).
  • README, sibling .md per implementation file, and subpath exports for ./coinmarketcap/coinmarketcap.

KEPT (from slim core, consumed unchanged)

  • CurrencyProviderError + CURRENCY_PROVIDER_CODES registry (HTTP_ERROR, PARSE_ERROR, UPSTREAM_ERROR, MISSING_CONFIG, UNKNOWN_CURRENCY).
  • ApiKeyConfig shared config type.
  • httpRequest() shared HTTP helper.
  • FetchLike from @suaveplan/types.

Source mapping

Module Source
CoinMarketCapProvider ../suaveplan/packages/finance/currency-providers/src/crypto/coinmarketcap.ts L1-L61 (upstream class)
Error mapping (MISSING_CONFIG / PARSE_ERROR / UPSTREAM_ERROR / UNKNOWN_CURRENCY) genesis-original — upstream threw raw Error; the slim core's typed CurrencyProviderError registry replaces that
httpRequest / composeAbortSignal plumbing @suaveplan/currency-providers/src/http/http.ts (slim core, genesis-original)
Symbol-based crypto query shape upstream behaviour preserved (symbol=<csv>&convert=<base> against /v1/cryptocurrency/quotes/latest)

Impact

Affected dependents

Run bunx turbo ls --filter=...@suaveplan/currency-provider-coinmarketcap to enumerate.

  • No current dependents (new sibling package; verified by bunx turbo ls --filter=...@suaveplan/currency-provider-coinmarketcap).

The package's only upstream dependencies are @suaveplan/currency-providers (slim core, registry / factory / HTTP helper / error registry / configs), @suaveplan/currency (the CurrencyProvider contract), @suaveplan/types (FetchLike), @suaveplan/error (transitive), and tslib. None of those packages need to be touched by this change — the sibling consumes their public surfaces unchanged.

Out of scope

  • Fiat conversion endpoints. CoinMarketCap exposes /v1/fiat/map and /v2/tools/price-conversion but this sibling stays scoped to the crypto quotes endpoint (supportsFiat: false). A fiat follow-up can land separately if a real consumer needs it.
  • Historical-rate endpoints, OHLCV, WebSocket streams. Same deferral as every other sibling provider — interface extension lands once @suaveplan/currency's CurrencyProvider contract grows the slots.
  • Rate-limit and retry orchestration. Deferred to @suaveplan/rate-limiter and @suaveplan/retry integrations once those wrappers land — every sibling provider gains them uniformly through a single composition.
  • CoinMarketCap-specific helper utilities (rank, market-cap weighting, metadata). Out of scope for a rates provider; a future @suaveplan/coinmarketcap package can expose those if needed.