Initial Commit
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
# 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 <key>` 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 <baseUrl>/pricemulti?fsyms=<targets>&tsyms=<base>` via the shared
|
||||
`httpRequest()` helper from `@suaveplan/currency-providers`. The
|
||||
`authorization: Apikey <key>` 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 <key>`) | 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.
|
||||
Reference in New Issue
Block a user