Files
skills/docs/money/finance/money/README.md
2026-05-29 08:20:56 +01:00

6.5 KiB

@suaveplan/money - Universal precise currency/money arithmetic using integer minor-unit (bigint) representation: immutable Money class with full arithmetic + comparison + conversion surface, locale-aware Intl-backed formatting (formatMoney, formatMoneyCompact), fair allocators preserving the input total (allocateEvenly, allocateByRatios, allocateByPercentages), aggregators (sumMoney, minMoney, maxMoney), 30 ISO 4217 fiat + 5 cryptocurrency built-ins, custom and virtual currency registration, lossless JSON round-trip, typed MoneyError hierarchy with stable MONEY.* code registry.

Universal precise currency and money arithmetic using integer minor-unit representation. All operations use bigint so consumers never hit floating-point rounding drift; cross-currency mistakes raise typed errors; allocations preserve the input total to the minor unit.

Documentation tree

  • allocator — The allocator module solves two related problems: splitting a Money amount across N recipients (or N weights or N per…
    • allocator — The allocator module solves two related problems: splitting a Money amount across N recipients (or N weights or N per…
  • currencies — This module owns the currency-metadata registry that every other part of @suaveplan/money consults to compute minor-u…
    • currencies — This module owns the currency-metadata registry that every other part of @suaveplan/money consults to compute minor-u…
  • error-codes — @suaveplan/money raises only typed errors. This module owns the stable MONEY_CODES registry (built with `defineCode…
    • error-codes — @suaveplan/money raises only typed errors. This module owns the stable MONEY_CODES registry (built with `defineCode…
  • formatter — The formatter renders MoneyLike values to human-readable strings using Intl.NumberFormat(locale)-derived separators…
    • formatter — The formatter renders MoneyLike values to human-readable strings using Intl.NumberFormat(locale)-derived separators…
  • money — Money is the cornerstone of the package: an immutable value object that stores monetary amounts as bigint minor uni…
    • money — Money is the cornerstone of the package: an immutable value object that stores monetary amounts as bigint minor uni…
  • types — @suaveplan/money exposes a small, stable set of types that downstream packages (@suaveplan/currency, `@suaveplan/pa…
    • common — @suaveplan/money exposes a small, stable set of types that downstream packages (@suaveplan/currency, `@suaveplan/pa…

Install

bun add @suaveplan/money

Quick start

import { Money, formatMoney, allocateEvenly } from "@suaveplan/money";

const price = Money.fromMajor(29.99, "USD");
const tax = price.multiply(0.08);
const total = price.add(tax);

console.log(formatMoney(total));      // "$32.39"
console.log(total.toDecimalString()); // "32.39"

// Split a $32.39 bill among 3 — no penny lost
const { shares } = allocateEvenly(total, 3);
console.log(shares.map((s) => formatMoney(s))); // ["$10.80", "$10.80", "$10.79"]

Features

  • Immutable Money class with full arithmetic (add, subtract, multiply, divide, abs, negate), comparison (compareTo, equals, greaterThan, ...), and conversion (toMajor, toDecimalString, toJSON, toString).
  • 30 ISO 4217 fiat currencies (USD, EUR, GBP, JPY, ...) plus 5 cryptocurrencies (BTC, ETH, SOL, USDT, USDC) with accurate exponents.
  • Custom and virtual currency registration via registerCurrency(info) with virtual / issuerId flags for game-currency use cases.
  • Locale-aware formatting through Intl.NumberFormat-derived separators; decimalSeparator / thousandsSeparator overrides for locked output.
  • Compact notation (formatMoneyCompact) with K / M / B suffixes.
  • Fair allocators (allocateEvenly, allocateByRatios, allocateByPercentages) that always preserve the input total.
  • Aggregators (sumMoney, minMoney, maxMoney) with typed empty-input and cross-currency guards.
  • Lossless JSON round-trip via Money.toJSON() / Money.fromJSON() (bigint encoded as decimal string).
  • Typed MoneyError hierarchy extending SuaveplanError<MoneyErrorCode> with stable MONEY.* code registry and currency / otherCurrency discriminants.
  • Subpath exports for every public module so consumers can tree-shake.
  • Universal — no node:*, bun:*, DOM, or fs imports; runs unchanged on Node ≥ 18, Bun, browsers, and Web Workers.

Modules

Subpath exports

import { Money }            from "@suaveplan/money/money/money";
import { formatMoney }      from "@suaveplan/money/formatter/formatter";
import { allocateEvenly }   from "@suaveplan/money/allocator/allocator";
import { registerCurrency } from "@suaveplan/money/currencies/currencies";
import { MoneyError }       from "@suaveplan/money/error-codes/error-codes";
import type { MoneyLike }   from "@suaveplan/money/types/common";

Error handling

Every failure path raises a typed MoneyError carrying a stable MONEY.* code. Six codes are declared: CURRENCY_MISMATCH, UNKNOWN_CURRENCY, DIVISION_BY_ZERO, INVALID_ALLOCATION, EMPTY_INPUT, PARSE_ERROR.

import { Money, MoneyError, MONEY_CODES } from "@suaveplan/money";

try {
    Money.fromMinor(100n, "USD").add(Money.fromMinor(50n, "EUR"));
} catch (err) {
    if (err instanceof MoneyError && err.code === MONEY_CODES.CURRENCY_MISMATCH) {
        console.error(`mismatch: ${err.currency} vs ${err.otherCurrency}`);
    }
}

License

MIT — © Suaveplan Team