110 lines
5.5 KiB
Markdown
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.
|