# @suaveplan/currency - Universal currency conversion engine — pluggable CurrencyProvider interface, TTL-bounded RateCache with direct / inverse / triangulated lookup, primary + fallback chain with AbortSignal cancellation, Zod-validated public boundary, typed CurrencyError hierarchy with stable CURRENCY.* code registry, virtual-currency seeding with post-construction setVirtualRate / updateVirtualRate mutators, enriched ConversionResult carrying providerName and triangulatedThrough diagnostics. Built on @suaveplan/money minor-unit bigint arithmetic. Universal currency conversion engine — pluggable `CurrencyProvider` interface, TTL-bounded `RateCache` with direct / inverse / triangulated lookup, primary + fallback chain with `AbortSignal` cancellation, Zod-validated public boundary, typed `CurrencyError` hierarchy with stable `CURRENCY.*` code registry, virtual-currency seeding with post-construction `setVirtualRate` / `updateVirtualRate` mutators, and enriched `ConversionResult` carrying `providerName` and `triangulatedThrough` diagnostics. Built on `@suaveplan/money` minor-unit `bigint` arithmetic. ## Documentation tree - [converter](./src/converter/converter.md) — `CurrencyConverter` is the orchestration heart of `@suaveplan/currency`. It combines a pluggable `CurrencyProvider` (pl… - [converter](./src/converter/converter.md) — `CurrencyConverter` is the orchestration heart of `@suaveplan/currency`. It combines a pluggable `CurrencyProvider` (pl… - [error-codes](./src/error-codes/error-codes.md) — `@suaveplan/currency` raises only typed errors. This module owns the stable `CURRENCY_CODES` registry (built with `defi… - [error-codes](./src/error-codes/error-codes.md) — `@suaveplan/currency` raises only typed errors. This module owns the stable `CURRENCY_CODES` registry (built with `defi… - [provider](./src/provider/provider.md) — The provider module ships two reference implementations of the `CurrencyProvider` contract: a mutable `InMemoryProvider… - [provider](./src/provider/provider.md) — The provider module ships two reference implementations of the `CurrencyProvider` contract: a mutable `InMemoryProvider… - [rate-cache](./src/rate-cache/rate-cache.md) — `RateCache` is the converter's in-memory rate store. It folds every successful `fetchRates` answer into a single map ke… - [rate-cache](./src/rate-cache/rate-cache.md) — `RateCache` is the converter's in-memory rate store. It folds every successful `fetchRates` answer into a single map ke… - [schemas](./src/schemas/schemas.md) — The schemas module is the package's input-validation boundary. Every public options bundle that crosses into a `Currenc… - [schemas](./src/schemas/schemas.md) — The schemas module is the package's input-validation boundary. Every public options bundle that crosses into a `Currenc… - [types](./src/types/common.md) — Single home for every shared type the `@suaveplan/currency` public surface exposes. The module defines the `CurrencyPro… - [common](./src/types/common.md) — Single home for every shared type the `@suaveplan/currency` public surface exposes. The module defines the `CurrencyPro… ## Install ```bash bun add @suaveplan/currency @suaveplan/money ``` ## Quick start ```ts import { CurrencyConverter, InMemoryProvider } from "@suaveplan/currency"; import { Money } from "@suaveplan/money"; const provider = new InMemoryProvider(); provider.setRates("USD", { EUR: 0.92, GBP: 0.79, JPY: 149.5 }); const converter = new CurrencyConverter({ provider }); const usd = Money.fromMajor("100", "USD"); const result = await converter.convert(usd, "EUR"); // result.amount === 9200n // result.rate === 0.92 // result.providerName === "in-memory" // result.triangulatedThrough === null const eur = await converter.convertAmount(250, "USD", "EUR"); // eur === 230 (250 * 0.92) ``` ## Features - **Pluggable `CurrencyProvider` interface** for any exchange-rate source. - **In-memory `RateCache`** with configurable TTL eviction. - **Cross-rate triangulation** via cached intermediate base (single-hop). - **Inverse rate calculation** from cached data when only one direction is known. - **Provider fallback chain** for resilience — tries providers in order. - **`AbortSignal` cancellation** on `convert` / `convertAmount` / `getRate`, honoured between fallback attempts. - **Zod-validated boundary** on every public option bundle. - **Typed `CurrencyError` hierarchy** with stable `CURRENCY.*` codes (`INVALID_CONFIG`, `INVALID_OPTIONS`, `PROVIDER_UNAVAILABLE`, `UNSUPPORTED_CURRENCY`, `RATE_UNAVAILABLE`, `TRIANGULATION_IMPOSSIBLE`, `ABORTED`). - **Virtual-currency seeding** for game currencies, with `setVirtualRate` / `updateVirtualRate` post-construction mutation. - **Enriched `ConversionResult`** — `providerName` (`""` / `""` / `""` / actual provider name) plus `triangulatedThrough` (chain of intermediate currencies for triangulated rates). - **Built-in `InMemoryProvider` + `createStaticProvider` factory** for tests and fixed-rate apps. - **Tree-shakeable subpath exports** per public module. ## Modules - [`src/converter/converter.md`](./src/converter/converter.md) — `CurrencyConverter` orchestrator (provider chain, cache, triangulation, virtual currency, AbortSignal). - [`src/rate-cache/rate-cache.md`](./src/rate-cache/rate-cache.md) — TTL-bounded `RateCache` with direct / inverse / triangulated lookup. - [`src/provider/provider.md`](./src/provider/provider.md) — `InMemoryProvider` + `createStaticProvider` reference implementations. - [`src/error-codes/error-codes.md`](./src/error-codes/error-codes.md) — `CURRENCY_CODES` registry + `CurrencyError` discriminated class. - [`src/schemas/schemas.md`](./src/schemas/schemas.md) — Zod schemas + parse helpers for every public option bundle. - [`src/types/common.md`](./src/types/common.md) — public type surface (`CurrencyProvider`, `ConversionResult`, `ConverterConfig`, …). ## Status `0.1.0` (pre-graduation). Migrated from `../suaveplan/packages/finance/currency/` with feature parity plus typed errors, Zod boundary, `AbortSignal` support, and enriched `ConversionResult`. See the design proposal for the migration record and the deferred-feature list.