@moneolabs/core
Shared primitives for the Moneo SDKs: exact money arithmetic, assets, durations, clocks, and price
sources.
npm install @moneolabs/core
You do not usually install this directly. It comes in with @moneolabs/wallet, @moneolabs/guard, or
@moneolabs/trading. It is published on its own because the money type is useful without them.
Money
Amounts are integer counts of minor units in a bigint. There is no float anywhere in the
arithmetic. A budget that drifts by a fraction of a cent every time it is checked is a budget that
eventually lets something through.
import { parseMoney, addMoney, formatMoney, splitMoney } from "@moneolabs/core";
parseMoney("$1,234.56");
parseMoney("421.10 USDG");
parseMoney(250, "USD");
formatMoney(addMoney(parseMoney("$0.10"), parseMoney("$0.20")));
splitMoney(parseMoney("$100.00"), 3);
Precision you did not ask to lose is an error, not a rounding:
parseMoney("$0.001");
parseMoney("$0.1000");
Scaling takes a rational, so percentages stay exact:
scaleMoney(parseMoney("$1,500.00"), 0.003);
scaleMoney(parseMoney("$1,500.00"), 1n, 3n);
Assets
USD, EUR, GBP, USDG, USDC, and ETH are built in with their real precision.
Tokenized equities are not, because the list keeps changing, so register the ones
you trade:
registerAsset({ symbol: "AAPL", decimals: 18 });
parseMoney("10.5 AAPL");
Clocks
Time is injected everywhere it matters, so tests do not wait for real windows.
const clock = manualClock(0);
clock.sleep(1000).then(() => console.log("woke"));
await clock.advance("2s");
advance() drains repeatedly rather than once. A woken task usually schedules another sleep, and
with a big enough jump that new sleep can already be due.
Prices
Limits are in dollars, agents hold other things.
await valueInUsd(parseMoney("2 AAPL"), fixedPrices({ AAPL: 309.92 }));
await valueInUsd(parseMoney("100 USDG"), peggedPrices);
await valueInUsd(parseMoney("1 AAPL"), peggedPrices);
Refusing to guess is deliberate. A price silently assumed to be 1 is how a limit stops meaning
anything.
Also here
parseDuration and formatDuration for windows like "1h30m". id() for prefixed, URL safe ids.
fingerprint() and stableStringify() for content-addressing a config regardless of key order.
MoneoError and friends, each carrying a stable code so agents act on codes rather than on
message text.
License
MIT