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

110 lines
5.5 KiB
Markdown

# Add @suaveplan/currency-provider-kraken sibling package
**Package**: `@suaveplan/currency-provider-kraken`
**Status**: PROPOSED
**Type**: new package (genesis-original sibling of `@suaveplan/currency-providers`)
- **Design**: ./design.md
- **Spec delta**: ./specs/currency-provider-kraken/spec.md
## Why
The slim refactor archived at
`openspec/archive/2026-05-17-slim-currency-providers/` moved every concrete
provider out of `@suaveplan/currency-providers` and committed to landing each
one as its own `@suaveplan/currency-provider-<name>` sibling. Kraken is one of
the nine siblings the slim core's `proposal.md ## Affected dependents` block
explicitly enumerates — this change ships it.
Kraken is a free public-ticker provider (no API key) with a regulated-exchange
real-time trading price. Wiring it through the slim core's `httpRequest` +
`defineCurrencyProvider` factory gives consumers a granular install (only pay
for Kraken when they want Kraken) and lets the provider iterate on its own
version cadence — exactly the foundation-with-sibling-plugins shape established
by `@suaveplan/network-plugin-*` and `@suaveplan/drive-plugin-*`.
## What changes
### ADDED
- New package `@suaveplan/currency-provider-kraken` at
`packages/finance/currency-provider-kraken/` (universal-tier, `0.1.0`,
`sideEffects: false`).
- `KrakenProvider` class implementing the `CurrencyProvider` contract from
`@suaveplan/currency`. Constructor accepts an optional `NoKeyConfig` from
`@suaveplan/currency-providers` (`baseUrl` override + injectable `FetchLike`).
- `KRAKEN_SYMBOL_MAP` — the canonical mapping from Suaveplan symbol
(`BTC`, `ETH`, `SOL`, `USDT`, `DOT`, `ADA`, `LINK`, `AVAX`, `ATOM`, `LTC`,
`DOGE`, `XRP`) to Kraken pair (`XXBTZUSD`, `XETHZUSD`, …) — exported so
callers can probe / extend.
- `DEFAULT_KRAKEN_BASE_URL = "https://api.kraken.com/0/public"` exported
constant.
- Uses the shared `httpRequest()` helper from
`@suaveplan/currency-providers/http/http` for the GET — non-2xx responses
raise `CurrencyProviderError(HTTP_ERROR)` with `providerName: "kraken"` and
the HTTP status populated.
- Maps the Kraken-specific `data.error: string[]` array to
`CurrencyProviderError(UPSTREAM_ERROR)` with the first message carried on
`upstreamMessage`.
- Raises `CurrencyProviderError(PARSE_ERROR)` when the response body fails to
JSON-parse, when the `result` map is missing / not an object, or when a
ticker's `c[0]` price cannot be parsed to a positive finite number.
- Raises `CurrencyProviderError(UNKNOWN_CURRENCY)` when every requested
`options.targets` symbol resolves to an unknown / unmapped Kraken pair, so
callers don't silently receive an empty rate set.
## Source mapping
Upstream reference for parity (the legacy 9-provider bundle):
| Capability | Upstream source |
|---|---|
| `KrakenProvider` class | `../suaveplan/packages/finance/currency-providers/src/crypto/kraken.ts` L1-L91 |
| Kraken symbol → pair table | `../suaveplan/packages/finance/currency-providers/src/crypto/kraken.ts` L11-L24 |
| `c[0]` last-trade-closed price + reciprocal-to-USD rate calc | `../suaveplan/packages/finance/currency-providers/src/crypto/kraken.ts` L67-L77 |
| Kraken `error: string[]` upstream-failure detection | `../suaveplan/packages/finance/currency-providers/src/crypto/kraken.ts` L58-L60 |
| HTTP-error path | `../suaveplan/packages/finance/currency-providers/src/crypto/kraken.ts` L46-L51 (now delegated to `httpRequest`) |
Genesis-native deltas vs. upstream:
| Capability | Upstream | Migrated | Notes |
|---|---|---|---|
| Plain `Error` HTTP failure | ✅ | ⬆️ | Now `CurrencyProviderError(HTTP_ERROR)` via shared `httpRequest`. |
| Plain `Error` Kraken-error array | ✅ | ⬆️ | Now `CurrencyProviderError(UPSTREAM_ERROR)` with `upstreamMessage`. |
| Hardcoded `globalThis.fetch` | ✅ | ⬆️ | Injectable `FetchLike` via `NoKeyConfig.fetch`. |
| Silent empty rate set on unknown target | ✅ | ⬆️ | Now `CurrencyProviderError(UNKNOWN_CURRENCY)` when every requested target is unmapped. |
| `BTC`/`ETH`/`SOL`/`USDT`/`DOT`/`ADA`/`LINK`/`AVAX`/`ATOM`/`LTC`/`DOGE`/`XRP` symbol map | ✅ | ✅ | Preserved verbatim. |
| Reciprocal-of-USD-price rate model | ✅ | ✅ | Preserved verbatim. |
No upstream enterprise audit exists for `currency-providers` (the slim core's
design notes were the genesis-native source).
## Impact
### Affected dependents
Run `bunx turbo ls --filter=...@suaveplan/currency-provider-kraken` to
enumerate. The package is brand-new so there are no current dependents:
- No current dependents (verified by
`bunx turbo ls --filter=...@suaveplan/currency-provider-kraken`).
This package consumes `@suaveplan/currency-providers` (the slim core) for the
`httpRequest` helper, the `CurrencyProviderError` + `CURRENCY_PROVIDER_CODES`
registry, and the `NoKeyConfig` shape. It consumes `@suaveplan/currency` for
the `CurrencyProvider` / `RateFetchOptions` / `RateFetchResult` contracts and
`@suaveplan/types` for the `FetchLike` shape. None of those packages need
re-testing — they are all unchanged.
## Out of scope
- Authenticated Kraken endpoints (private balance / order endpoints) — this
provider wraps only the public ticker, matching the slim core's "free, no
API key" classification.
- WebSocket / streaming ticker — same deferral as the slim core's
`## Out of scope`.
- Historical-rate / OHLC endpoints — same deferral.
- A `KrakenProvider` built via `defineCurrencyProvider` (object-literal
idiom) — the class form is the canonical surface; the factory remains
available for callers who prefer it.