Monetra Core

07/02/2026 · Zascia Hugo · 7 min read

TypeScriptFinanceOpen SourceCore
On This Page

Monetra Core is the heart of the Monetra ecosystem. It is the stripped-down, high-performance engine designed solely for financial correctness.

While the full Monetra framework provides ledgers, audit trails, and complex financial instruments, Monetra Core does one thing and does it perfectly: safe financial arithmetic.

It exists for developers who need the reliability of precise money handling but want to build their own abstractions on top of it. It is the primitive layer - the "physics engine" for your financial application.

The Mission: Zero Ambiguity

In financial software, ambiguity is a bug. 10 / 3 is not 3.33. It is an operation that yields a quotient and a remainder, and your code must decide what to do with that remainder.

Monetra Core forces these decisions to be explicit. It provides the essential types and operations to ensure that:

  1. Money is never treated as a float.
  2. Currencies are never mixed implicitly.
  3. Rounding is never accidental.

What is Inside "Core"?

Monetra Core is designed to be lightweight and zero-dependency. It includes only the non-negotiable primitives for financial engineering.

1. The Money Type

A pure, immutable representation of monetary value. It stores the amount in minor units (like integer cents) and carries the currency code as part of its type signature.

// It is impossible to mix currencies by accident
const price = new Money(1000, "USD");
const shipping = new Money(500, "EUR");

// This throws a compile-time or runtime error immediately
const total = price.add(shipping); 

2. Precise Arithmetic

Standard math operations (add, subtract, multiply, allocate) that guarantee precision.

  • Allocation: Split a monetary amount into parts without losing a single cent.
  • Scale: Multiply by a factor (like a tax rate) with explicit rounding strategies.

3. Currency Registry

A minimal, extensible registry for currency definitions. It comes with standard ISO 4217 currencies but allows you to define custom tokens, loyalty points, or internal credits.

Why Use Core?

You might choose Monetra Core over the full Monetra framework if:

  • You are building a library: You want to export financial types without forcing a large dependency tree on your users.
  • You have your own persistence layer: You don't need Monetra's ledger or audit history because you are storing data in a specific way (e.g., a custom SQL schema or a blockchain).
  • Bundle size matters: You are running in a serverless function or an edge worker and need the smallest possible footprint.

The "Core" Philosophy

Monetra Core follows the Unix philosophy: do one thing and do it well.

It respects the fact that financial systems are diverse. A crypto exchange, a payroll provider, and an e-commerce checkout have vastly different needs for storage and reporting. But they all share the same need for correct math.

Monetra Core solves the math. The rest is up to you.

Features at a Glance

  • Immutable by Default: Values never change; operations return new instances.
  • Rounding Strategies: Full support for "Round Half Up", "Round Half Even" (Banker's Rounding), and more.
  • Allocation Algorithms: Distribute funds (e.g., splitting a $100 bill 3 ways) while preserving the total value ($33.33, $33.33, $33.34).
  • Type Safety: leveraged TypeScript to catch financial errors at compile time.

Example: The Allocation Problem

The classic test of any financial library is how it handles division.

import { Money, Currency } from "@zugobite/monetra-core";

const bill = new Money(100, Currency.USD); // $1.00
const split = bill.allocate([1, 1, 1]); 

// Result:
// [34 cents, 33 cents, 33 cents]
// Total: 100 cents. Nothing lost.

Monetra Core handles the "remainder distribution" automatically, ensuring the sum of the parts always equals the whole.

Internal Architecture

Monetra Core is organised into focused modules, each handling one aspect of financial correctness:

Money - The Value Type

The Money class is the centre of the library. It stores amounts as BigInt minor units (cents, pennies, satoshis) and carries the currency code as part of its identity. Every arithmetic operation returns a new instance - money values are immutable by design.

Key operations: add, subtract, multiply, divide, abs, negate, clamp, percentage, split.

Comparisons: equals, greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual, compare.

Static helpers: Money.min(), Money.max(), Money.zero(), Money.fromMinor(), Money.fromMajor().

Currency Registry - The Rules

The registry defines how currencies behave. It ships with 60+ ISO 4217 currencies (USD, EUR, GBP, JPY, ZAR, etc.) with correct decimal precision out of the box. For non-standard use cases - crypto tokens, loyalty points, internal credits - defineToken() lets you register custom currencies with up to 18 decimal places.

Built-in crypto presets: ETH (18 decimals), BTC (8), USDC (6), USDT (6).

Allocation - The Splitter

Allocation handles the classic problem of dividing money without losing cents. It accepts any array of ratios and distributes remainders deterministically. The total of the parts always equals the original amount.

Helpers: percentage(), addPercent(), subtractPercent(), split().

Rounding - The Policy Layer

Six explicit rounding modes: HALF_UP, HALF_DOWN, HALF_EVEN (Banker's), FLOOR, CEIL, TRUNCATE. Lossy operations like division require you to specify a rounding mode - the library refuses to guess.

Converter - The Exchange Layer

The Converter class manages exchange rates between currencies, including historical rate support via addHistoricalRate(). MoneyBag provides a safe container for aggregating values across multiple currencies without forcing premature conversion.

Error Handling - The Safety Net

Custom error classes with programmatic error codes: CurrencyMismatchError, InvalidArgumentError, OverflowError, RoundingRequiredError, InsufficientFundsError, InvalidPrecisionError. Errors are specific and actionable - they tell you exactly what went wrong and why.

Design Principles

PrincipleImplementation
ImmutabilityAll operations return new Money instances - values never mutate
ExplicitnessRounding mode is required on lossy operations - no silent precision loss
Type SafetyCurrency mismatch throws at both compile-time (TypeScript) and runtime
Zero DependenciesNo supply chain risks - the entire library is self-contained
Conservation of ValueAllocation algorithms guarantee the sum of parts equals the whole
Fail FastInvalid operations throw immediately with specific, descriptive errors

What I Learned

Building Monetra Core reinforced several important lessons:

  • BigInt changes the game for financial math. Moving from floating-point to integer-based arithmetic eliminates an entire category of precision bugs. The tradeoff is a slightly more verbose API, but the correctness guarantee is worth it.
  • Explicit rounding is uncomfortable but necessary. Developers instinctively want a default rounding mode. Forcing the choice feels annoying at first, but it prevents countless subtle bugs in production - especially when different business contexts require different rounding rules.
  • Zero dependencies is a feature, not a limitation. Every dependency is a potential vulnerability and a version conflict. For a financial library that other systems depend on, the supply chain must be minimal.
  • Allocation is harder than it looks. Splitting $10.00 three ways sounds trivial until you realise $3.33 × 3 = $9.99. The remaining cent must go somewhere, and the decision must be deterministic and fair. This is the kind of edge case that separates toy demos from production libraries.

Where Can I Learn More?

Monetra Core is the bedrock. Build on it with confidence.