Functional Weave
Code in Rust

money.convert@1.0.0

impl/typescript.ts

1,398 bytes · the TypeScript implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

import { multiplyRational, rational, rationalToInteger } from "./math_rational.ts";  ← from math.rational ^1.0.0 · built alongside by fune
import { type RoundingMode } from "./math_round_div.ts";  ← from math.round-div ^1.0.0 · built alongside by fune
import { type Money, money } from "./money_amount.ts";  ← from money.amount ^1.0.0 · built alongside by fune
import { currencyDigits } from "./money_currency_digits.ts";  ← from money.currency-digits ^1.0.0 · built alongside by fune
import { type ExchangeRate } from "./money_convert_types.ts";

/**
 * Convert `amount` into the rate's quote currency.
 *
 * Exact up to one final rounding into the quote currency's minor unit; the
 * rate is a fraction in major units and each currency's decimal places are
 * looked up rather than assumed to be two.
 */
export function convertMoney(amount: Money, rate: ExchangeRate, mode: RoundingMode): Money {
  if (amount.currency !== rate.base) {
    throw new RangeError(`exchange rate converts ${rate.base} to ${rate.quote}, not ${amount.currency}`);
  }
  const r = rational(rate.rate.numerator, rate.rate.denominator);
  if (r.numerator <= 0) {
    throw new RangeError("exchange rate must be positive");
  }
  const fromDigits = currencyDigits(rate.base);
  const toDigits = currencyDigits(rate.quote);

  // minor units of quote per minor unit of base: rate x 10^toDigits / 10^fromDigits
  const scale = rational(10 ** toDigits, 10 ** fromDigits);
  const perMinor = multiplyRational(r, scale);
  const exact = multiplyRational(rational(amount.minor, 1), perMinor);
  return money(rationalToInteger(exact, mode), rate.quote);
}