129 lines
4.3 KiB
Markdown
129 lines
4.3 KiB
Markdown
# OpenSpec Change: enterprise-currency-providers
|
|
|
|
- **Change ID**: enterprise-currency-providers
|
|
- **Package**: `@suaveplan/currency-providers`
|
|
- **Category**: finance
|
|
- **Target path**: `finance/currency/currency-providers`
|
|
- **Status**: PROPOSED
|
|
- **Date**: 2026-04-24
|
|
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/currency-providers.md`
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
Deliver `@suaveplan/currency-providers` on the genesis branch from scratch at enterprise quality. The package implements concrete `CurrencyProvider` implementations (from `@suaveplan/currency`) for eight real exchange-rate APIs: three fiat providers (ECB XML feed, Open Exchange Rates, Fixer) and five crypto providers (CoinGecko, CoinMarketCap, Binance, Kraken, CryptoCompare), plus a `VirtualCurrencyProvider`. All HTTP calls go through a shared `fetch` wrapper with timeout, retry via `@suaveplan/retry`, rate-limit header parsing, and in-flight request coalescing. Typed error hierarchy (`AuthError`, `RateLimitError`, `NetworkError`, `ParseError`). Optional `RateLimitedProvider` decorator.
|
|
|
|
---
|
|
|
|
## Current-state audit (genesis)
|
|
|
|
Does not exist on genesis — fresh build.
|
|
|
|
---
|
|
|
|
## Available workspace deps on genesis
|
|
|
|
| Package | Role |
|
|
|---|---|
|
|
| `@suaveplan/error` (`workspace:^`) | Typed `CURRENCY_PROVIDER.*` error codes |
|
|
| `@suaveplan/types` (`workspace:^`) | `LoggerLike` |
|
|
| `@suaveplan/currency` (`workspace:^`) | `CurrencyProvider` interface |
|
|
| `@suaveplan/retry` (`workspace:^`) | HTTP retry + backoff |
|
|
| `@suaveplan/logger` (`workspace:^`) | Structured logs |
|
|
| `zod` (`catalog:forms`) | Response parsing schemas |
|
|
| `@opentelemetry/api` (`catalog:observability`) | Spans + counters + histograms |
|
|
| `tslib` (`catalog:build`) | Runtime helpers |
|
|
|
|
---
|
|
|
|
## Public API surface
|
|
|
|
```ts
|
|
// Fiat providers
|
|
class EcbProvider implements CurrencyProvider { ... }
|
|
class FixerProvider implements CurrencyProvider { constructor(config: ApiKeyConfig) }
|
|
class OpenExchangeRatesProvider implements CurrencyProvider { constructor(config: ApiKeyConfig) }
|
|
|
|
// Crypto providers
|
|
class BinanceProvider implements CurrencyProvider { ... }
|
|
class CoinGeckoProvider implements CurrencyProvider { ... }
|
|
class CoinMarketCapProvider implements CurrencyProvider { constructor(config: ApiKeyConfig) }
|
|
class CryptoCompareProvider implements CurrencyProvider { ... }
|
|
class KrakenProvider implements CurrencyProvider { ... }
|
|
|
|
// Virtual
|
|
class VirtualCurrencyProvider implements CurrencyProvider { ... }
|
|
|
|
// Wrapper
|
|
class RateLimitedProvider implements CurrencyProvider {
|
|
constructor(provider: CurrencyProvider, options: RateLimitOptions)
|
|
}
|
|
|
|
// Errors
|
|
class ProviderError extends SuaveplanError { ... }
|
|
class AuthError extends ProviderError { ... }
|
|
class RateLimitError extends ProviderError { retryAfterMs?: number }
|
|
class NetworkError extends ProviderError { ... }
|
|
class ParseError extends ProviderError { ... }
|
|
|
|
// HTTP utilities
|
|
function createFetchWrapper(options: FetchWrapperOptions): FetchWrapper
|
|
function coalesce<T>(key: string, fn: () => Promise<T>): Promise<T>
|
|
```
|
|
|
|
---
|
|
|
|
## File layout
|
|
|
|
```text
|
|
finance/currency/currency-providers/
|
|
package.json
|
|
tsconfig.json
|
|
vitest.config.ts
|
|
src/
|
|
index.ts
|
|
error-codes.ts
|
|
types/
|
|
provider.types.ts
|
|
provider.types.md
|
|
http/
|
|
fetch-wrapper/
|
|
fetch-wrapper.ts
|
|
fetch-wrapper.md
|
|
fetch-wrapper.test.ts
|
|
index.ts
|
|
coalesce/
|
|
coalesce.ts
|
|
coalesce.md
|
|
coalesce.test.ts
|
|
index.ts
|
|
fiat/
|
|
ecb-provider/
|
|
ecb-provider.ts / .md / .test.ts / index.ts
|
|
fixer-provider/
|
|
fixer-provider.ts / .md / .test.ts / index.ts
|
|
open-exchange-rates-provider/
|
|
open-exchange-rates-provider.ts / .md / .test.ts / index.ts
|
|
crypto/
|
|
binance-provider/ ...
|
|
coingecko-provider/ ...
|
|
coinmarketcap-provider/ ...
|
|
cryptocompare-provider/ ...
|
|
kraken-provider/ ...
|
|
virtual/
|
|
virtual-currency-provider/ ...
|
|
wrappers/
|
|
rate-limited-provider/ ...
|
|
tests/
|
|
integration.test.ts
|
|
```
|
|
|
|
---
|
|
|
|
## Impact
|
|
|
|
Requires `@suaveplan/currency` to be published first (implements its `CurrencyProvider` interface). Downstream: `@suaveplan/currency` consumers via the fallback chain.
|
|
|
|
**Prerequisites on Verdaccio**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/currency`, `@suaveplan/retry`, `@suaveplan/logger`.
|