Skip to content

VoirDev/moneta

Repository files navigation

Moneta — Immutable money value object (Kotlin Multiplatform)

Moneta is a compact, immutable value object representing a monetary amount together with its currency metadata.


Features

  • Stores amount + currency code + decimals in one object
  • Decimal-based using high-precision Decimal (no floating artifacts)
  • Supports fiat & crypto (e.g., USD 2 decimals, BTC 8 decimals, ERC‑20 tokens)
  • Exact atomic conversions (cents, satoshis, wei)

Why Moneta?

When money is represented only as a decimal value (BigDecimal, Decimal, etc.), the caller must also track currency code & decimals. This leads to risk:

val amount = BigDecimal("1.23") // but what currency? what scale?

With Moneta, a monetary value carries its own currency metadata:

val usd = Currency(code = "USD", decimals = 2)
val m = Moneta.fromDecimalString("1.235", currency = usd)
// m = 1.24 USD (HALF_UP rounding default)

No need to pass around a separate Currency object.


Quick Start

Installation

Add the following dependency to your project:

dependencies {
    implementation("dev.voir:moneta:1.0.1")
}

Constructing values

val usdCurrency = Currency(code = "USD", decimals = 2)
val btcCurrency = Currency(code = "BTC", decimals = 8)

// Whole-unit constructors
val usd = Moneta.fromInt(10, currency = usdCurrency)    // 10.00 USD
val btc = Moneta.fromLong(1, currency = btcCurrency)    // 1.00000000 BTC

// Precise decimal input (avoid Float/Double artifacts)
val exact = Moneta.fromDecimalString("0.1", currency = usdCurrency) // 0.10 USD

// From atomic smallest units (cents, satoshis, wei)
val sats = Moneta.fromAtomicLong(150000000, currency = btcCurrency)

Arithmetic

Arithmetic operations preserve the left operand's currency metadata and operate on the underlying decimal values. Constructors normalize input to absolute amounts, but arithmetic results can be negative.

val usd = Currency(code = "USD", decimals = 2)
val a = Moneta.fromDecimalString("1.50", currency = usd)
val b = Moneta.fromDecimalString("2.00", currency = usd)

val c = a.plus(b)   // -> 3.50 USD
val d = b.minus(a)  // -> 0.50 USD
val e = a.times(3)  // -> 4.50 USD

Atomic conversion (for persistence)

val m = Moneta.fromDecimalString("1.235", currency = Currency(code = "USD", decimals = 2))
val atomic = m.toAtomicString() // "124"

License

This project is licensed under the Apache License, Version 2.0.

See the full license in LICENSE.

About

Moneta is a compact, immutable value object representing a monetary amount together with its currency metadata.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages