# Add @suaveplan/currency-provider-cryptocompare sibling provider **Package**: `@suaveplan/currency-provider-cryptocompare` **Status**: ARCHIVED **Type**: new package (sibling of slimmed `@suaveplan/currency-providers`) - **Spec delta**: ./specs/currency-provider-cryptocompare/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 `CryptoCompare` sibling — a crypto rate source backed by the `min-api.cryptocompare.com/data/pricemulti` REST endpoint. CryptoCompare distinguishes itself from the keyed siblings (Fixer, OXR, CoinMarketCap) by being usable **fully keyless** — the free tier covers ~100,000 calls per month without any auth. Callers that want the higher rate limit can supply an `apiKey` in the constructor config; the provider attaches it on every request via the `authorization: Apikey ` header per CryptoCompare's documented Apikey scheme. ## What changes ### ADDED - `@suaveplan/currency-provider-cryptocompare` package at `packages/finance/currency-provider-cryptocompare/`, version `0.1.0`, universal-tier (`sideEffects: false`). - `CryptoCompareProvider` class implementing `CurrencyProvider` from `@suaveplan/currency`. Constructed from `CryptoCompareConfig` (extends `NoKeyConfig`: `apiKey?` + `baseUrl?` + injectable `FetchLike?`). - `supportsCrypto: true`, `supportsFiat: false`, no `supportsVirtual`. CryptoCompare 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 /pricemulti?fsyms=&tsyms=` via the shared `httpRequest()` helper from `@suaveplan/currency-providers`. The `authorization: Apikey ` header is attached **only when** `config.apiKey` is provided and non-whitespace. - 15 default crypto symbols (BTC, ETH, SOL, USDT, USDC, BNB, XRP, ADA, DOGE, DOT, AVAX, LINK, UNI, ATOM, LTC) when callers omit `targets` or pass an empty array. Default base currency: `"USD"`. - Response parsing raises `CurrencyProviderError(PARSE_ERROR)` when the payload is not valid JSON or is not a JSON object. - Response parsing raises `CurrencyProviderError(UPSTREAM_ERROR)` when the payload carries `Response: "Error"`. The `Message` field (or `"unknown upstream error"` when absent) is copied to `error.upstreamMessage`. - `fetchRates()` raises `CurrencyProviderError(UNKNOWN_CURRENCY)` when no requested symbol produces a finite positive 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 export for `./cryptocompare/cryptocompare`. ### KEPT (from slim core, consumed unchanged) - `CurrencyProviderError` + `CURRENCY_PROVIDER_CODES` registry (`HTTP_ERROR`, `PARSE_ERROR`, `UPSTREAM_ERROR`, `UNKNOWN_CURRENCY`). - `NoKeyConfig` shared config type (extended with the optional `apiKey`). - `httpRequest()` shared HTTP helper. - `FetchLike` from `@suaveplan/types`. ## Source mapping | Module | Source | |---|---| | `CryptoCompareProvider` | `../suaveplan/packages/finance/currency-providers/src/crypto/cryptocompare.ts` L1-L69 (upstream class) | | Error mapping (`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) | | Optional API-key header (`authorization: Apikey `) | CryptoCompare public documentation — Apikey auth scheme; not present in the upstream class (which ignored the key entirely) | | Inverted-price + zero-skip semantics | upstream behaviour preserved (`rates[symbol] = 1 / prices[base]` when `prices[base] > 0`) | ## Impact ### Affected dependents Run `bunx turbo ls --filter=...@suaveplan/currency-provider-cryptocompare` to enumerate. - No current dependents (new sibling package; verified by `bunx turbo ls --filter=...@suaveplan/currency-provider-cryptocompare`). The package's only upstream dependencies are `@suaveplan/currency-providers` (slim core, `httpRequest` / error registry / `NoKeyConfig`), `@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 - Historical-rate endpoints (`/v2/histoday`, `/v2/histohour`, `/v2/histominute`), OHLCV, WebSocket streaming. 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. - Multi-tsym ("multi-base") queries. `pricemulti` accepts a CSV `tsyms` list but the `CurrencyProvider` contract returns a single-base map; multi-base aggregation belongs in a future wrapper. - CryptoCompare-specific metadata endpoints (`coin/general`, social, news). Out of scope for a rates provider; a future `@suaveplan/cryptocompare` package can expose those if needed. - Fiat rates. CryptoCompare supports fiat tsyms but the sibling stays scoped to crypto (`supportsFiat: false`) per the slim-core sibling pattern; consumers needing fiat install one of the dedicated fiat siblings.