# 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-` 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.