← All @molecule/* packages · App templates
@molecule/api-fx-ratesCore interface · fx-rates · API (Node) · v1.0.1 · Apache-2.0
Foreign exchange rates core interface
npm install @molecule/api-fx-rates@molecule/api-fx-rates is the fx-rates core interface on the API (Node) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 2 providers: @molecule/api-fx-rates-ecb, @molecule/api-fx-rates-openexchange.
import { setProvider, getRate, convert } from '@molecule/api-fx-rates'
import { provider as ecb } from '@molecule/api-fx-rates-ecb'
setProvider(ecb)
const eurUsd = await getRate('EUR', 'USD')
const usdCents = await convert(10_000, 'EUR', 'USD') // 10000 EUR cents -> USD centsProviders (2): @molecule/api-fx-rates-ecb, @molecule/api-fx-rates-openexchange
Works with: @molecule/api-bond, @molecule/api-i18n
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Provider-agnostic foreign-exchange rates interface for molecule.dev.
Defines the FxRatesProvider interface for currency conversion and daily
reference-rate lookups. Bond packages (ECB, OpenExchange, etc.) implement
this interface. Application code uses the convenience functions
(getRate, getDailyRates, convert, listSupportedCurrencies) which
delegate to the bonded provider.
Rates are normalized as plain number ratios: 1 unit of FROM = rate units of TO.
Currency codes are ISO 4217 three-letter strings (e.g. 'USD', 'EUR', 'JPY').
Amounts are integer minor units (cents) to avoid floating-point drift.
import { setProvider, getRate, convert } from '@molecule/api-fx-rates'
import { provider as ecb } from '@molecule/api-fx-rates-ecb'
setProvider(ecb)
const eurUsd = await getRate('EUR', 'USD')
const usdCents = await convert(10_000, 'EUR', 'USD') // 10000 EUR cents -> USD cents
core
npm install @molecule/api-fx-rates @molecule/api-bond @molecule/api-i18n
FxDailyRatesA daily snapshot of reference rates, all expressed against a common pivot.
interface FxDailyRates {
/**
* The pivot currency the snapshot is quoted against
* (e.g. `'EUR'` for ECB, `'USD'` for most paid feeds).
*/
pivot: CurrencyCode
/**
* Date of the daily snapshot.
*/
asOf: Date
/**
* Map from currency code to rate: `1 unit of pivot = rates[code] units of code`.
* The pivot itself is conventionally included with rate `1`.
*/
rates: Record<CurrencyCode, number>
}
FxRateA single FX rate quote: 1 unit of {@link from} = rate units of {@link to},
as observed at {@link asOf}.
interface FxRate {
/**
* Source currency (ISO 4217).
*/
from: CurrencyCode
/**
* Target currency (ISO 4217).
*/
to: CurrencyCode
/**
* Conversion ratio: `1 unit of {from} = rate units of {to}`.
*/
rate: number
/**
* Timestamp the rate was observed/published.
*/
asOf: Date
}
FxRatesOptionsOptions accepted by all FX-rates provider methods.
interface FxRatesOptions {
/**
* Date the rate should be observed at. Defaults to "latest"
* if omitted. Implementations that do not support historical
* lookups MAY throw if a non-latest date is requested.
*/
asOf?: Date
}
FxRatesProviderForeign-exchange rates provider interface.
All FX-rate providers (ECB, OpenExchange, fixtures, etc.) implement this interface. The interface is deliberately minimal so providers with very different upstream APIs can satisfy it identically.
interface FxRatesProvider {
/**
* Looks up the conversion rate `1 unit of from = rate units of to`.
*
* Implementations SHOULD compute cross-rates through their pivot when
* neither side equals the pivot.
*
* @param from - Source currency (ISO 4217).
* @param to - Target currency (ISO 4217).
* @param options - Optional asOf date for historical rates.
* @returns The conversion ratio as a plain number.
*/
getRate(from: CurrencyCode, to: CurrencyCode, options?: FxRatesOptions): Promise<number>
/**
* Returns all reference rates the provider publishes for the given day,
* normalized against the provider's pivot currency.
*
* @param options - Optional asOf date for the daily snapshot.
* @returns The full daily snapshot.
*/
getDailyRates(options?: FxRatesOptions): Promise<FxDailyRates>
/**
* Converts an integer minor-unit amount (e.g. cents) from one currency
* to another, returning an integer minor-unit amount in the target.
*
* Implementations are expected to handle currencies with non-cent minor
* units (e.g. JPY has 0 decimals) consistently with the inputs.
*
* @param amountMinor - Amount in minor units of {@link from} (e.g. cents).
* @param from - Source currency (ISO 4217).
* @param to - Target currency (ISO 4217).
* @param options - Optional asOf date for historical rates.
* @returns Converted amount in minor units of {@link to}.
*/
convert(
amountMinor: number,
from: CurrencyCode,
to: CurrencyCode,
options?: FxRatesOptions,
): Promise<number>
/**
* Lists every currency the provider currently supports.
*
* @returns Array of ISO 4217 currency codes the provider can quote.
*/
listSupportedCurrencies(): Promise<CurrencyCode[]>
}
CurrencyCodeISO 4217 three-letter currency code (e.g. 'USD', 'EUR', 'JPY').
Kept as a plain string alias rather than a string-literal union so
providers can support whatever set of currencies they expose. Use
{@link FxRatesProvider.listSupportedCurrencies} to discover what a given
provider supports at runtime.
type CurrencyCode = string
convert(amountMinor, from, to, options)Converts an integer minor-unit amount (e.g. cents) from one currency to another using the bonded provider.
function convert(
amountMinor: number,
from: string,
to: string,
options?: FxRatesOptions,
): Promise<number>
amountMinor — Amount in minor units of {@link from} (e.g. cents).from — Source currency (ISO 4217).to — Target currency (ISO 4217).options — Optional asOf date for historical rates.Returns: Converted amount in minor units of {@link to}.
getDailyRates(options)Returns all reference rates the bonded provider publishes for the given day, normalized against the provider's pivot currency.
function getDailyRates(options?: FxRatesOptions): Promise<FxDailyRates>
options — Optional asOf date for the daily snapshot.Returns: The full daily snapshot.
getProvider()Retrieves the bonded FX-rates provider, throwing if none is configured.
function getProvider(): FxRatesProvider
Returns: The bonded FX-rates provider.
getRate(from, to, options)Looks up the conversion rate 1 unit of from = rate units of to.
function getRate(from: string, to: string, options?: FxRatesOptions): Promise<number>
from — Source currency (ISO 4217).to — Target currency (ISO 4217).options — Optional asOf date for historical rates.Returns: The conversion ratio as a plain number.
hasProvider()Checks whether an FX-rates provider is currently bonded.
function hasProvider(): boolean
Returns: true if an FX-rates provider is bonded.
listSupportedCurrencies()Lists every currency the bonded provider currently supports.
function listSupportedCurrencies(): Promise<string[]>
Returns: Array of ISO 4217 currency codes.
setProvider(provider)Registers an FX-rates provider as the active singleton. Called by bond
packages (e.g. @molecule/api-fx-rates-ecb) during application startup.
function setProvider(provider: FxRatesProvider): void
provider — The FX-rates provider implementation to bond.| Provider | Package |
|---|---|
| ECB FX Rates | @molecule/api-fx-rates-ecb |
| OpenExchangeRates | @molecule/api-fx-rates-openexchange |
Peer dependencies:
@molecule/api-bond ^1.0.1@molecule/api-i18n ^1.0.1@molecule/api-bond@molecule/api-i18nIntegration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual currency/pricing screens, and check every box off one by one. This is money: a wrong rate silently corrupts every price, so verify the NUMBERS the app computes, not just that a value rendered. A box you can't check is an integration bug to fix — not a skip:
getRate('USD', 'EUR') yields a
real ratio (roughly 0.8-1.0 for USD->EUR), never 0, null, NaN, negative, or
an absurd value like 1e9 — and the UI shows it as an actual number.convert does the CORRECT MATH: converting 100 USD (amountMinor
10_000 cents) USD->EUR returns approximately 10_000 * rate in the
target's minor units, rounded sensibly for that currency (integer cents;
JPY has 0 decimals), and the UI shows that converted amount — not the
untouched original.getRate('EUR', 'USD') is approximately 1 / getRate('USD', 'EUR') — and
same-currency is identity: getRate('USD', 'USD') is exactly 1 and
convert(x, 'USD', 'USD') returns x unchanged.'ZZZ', absent from
listSupportedCurrencies()) surfaces a clear error in the UI — NEVER a
silent rate of 0 (which zeroes the price) or a pass-through of 1.options.asOf), a past date returns
that day's rate (different from latest for a volatile pair), not today's.