npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@molecule/api-fx-rates

v1.0.1

Published

Foreign exchange rates core interface for molecule.dev

Downloads

491

Readme

@molecule/api-fx-rates

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.ts JSDoc, 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.

Quick Start

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

Type

core

Installation

npm install @molecule/api-fx-rates @molecule/api-bond @molecule/api-i18n

API

Interfaces

FxDailyRates

A 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>
}

FxRate

A 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
}

FxRatesOptions

Options 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
}

FxRatesProvider

Foreign-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[]>
}

Types

CurrencyCode

ISO 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

Functions

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.

Available Providers

| Provider | Package | | ----------------- | ------------------------------------- | | ECB FX Rates | @molecule/api-fx-rates-ecb | | OpenExchangeRates | @molecule/api-fx-rates-openexchange |

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-bond ^1.0.1
  • @molecule/api-i18n ^1.0.1

Runtime Dependencies

  • @molecule/api-bond
  • @molecule/api-i18n

E2E Tests

Integration 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:

  • [ ] A known pair returns a PLAUSIBLE rate: 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.
  • [ ] Round-trip consistency: the inverse pair is reciprocal — 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.
  • [ ] Changing the selected pair changes the displayed result (USD->EUR vs USD->JPY give visibly different converted amounts) — the screen is not pinned to one hardcoded rate.
  • [ ] An unknown/unsupported code (e.g. '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.
  • [ ] If a historical lookup is exposed (options.asOf), a past date returns that day's rate (different from latest for a volatile pair), not today's.
  • [ ] A provider/network failure surfaces gracefully (a visible error or retry) and the amount is left unconverted — the app NEVER falls back to converting at rate 0 or 1, which would corrupt the price shown or charged.
  • [ ] The provider API key stays server-side — fx-rates is server-only; the key never appears in the browser bundle, the network tab, or any client response.