npm package: @nand.computer/okane
Description: Minimalist, type-safe money library
Author: Yazalde Filimone
Latest version: 0.3.0

# okane

`okane` provides immutable money objects using `bigint` in minor units, ensuring exact
financial calculations without floating-point errors. Each Money object combines an
`amount` and a `currency` type, enabling type-safe arithmetic and preventing mixing of
currencies.

### Installation

```sh
bun add @nand.computer/okane
```

### Quick example

```ts
import { okane, USD, EUR, fixedFx } from "okane";

// create and operate
const total = okane(9999n, USD).add(okane(9999n, USD).mul(0.23)).sub(okane(9999n, USD).mul(0.1));
console.log(total.format("en-US")); // "$111.87"

// allocate
const [a, b, c] = okane(10000n, USD).allocate([1, 1, 1]);
console.log(a.format(), b.format(), c.format()); // "$33.34 $33.33 $33.33"

// FX
const eurTotal = total.convert(EUR, fixedFx({ USD_EUR: 0.92 }));
console.log(eurTotal.format("de-DE")); // "102,64 €"

// compile-time safety
const eur = okane(1000n, EUR);
// total.add(eur); // TS error
```

### Getting Started

Create a Money instance using minor units:

```ts
import { okane, USD } from "okane";
const price = okane(9999n, USD); // $99.99
```

Arithmetic operations preserve immutability and type safety. Addition or subtraction
requires the same currency:

```ts
const tax = okane(2500n, USD);
const total = price.add(tax); // $124.99
// price.add(okane(100n, EUR)) // compile-time error
```

Multiplication and division accept numbers or `bigint` with optional rounding modes
(`half-up`, `half-down`, `floor`, `ceil`, `banker`). Decimal factors use scaled
integer arithmetic to maintain precision:

```ts
price.mul(1.08); // apply 8% tax
price.div(3); // split in 3 parts
```

Money can be split proportionally using `allocate`, guaranteeing no loss due to
rounding:

```ts
okane(100n, USD).allocate([1, 1, 1]); // [$0.33, $0.33, $0.34]
```

Currency conversion uses explicit exchange rates. Differences in decimal precision
between currencies are handled automatically:

```ts
import { EUR, convertWith, fixedFx } from "okane";
const fx = fixedFx({ USD: { EUR: 0.85 } });
const eur = convertWith(price, EUR, fx); // $99.99 → €84.99
```

Parsing from strings or numbers provides exact results. `fromDecimal` converts decimal
strings, `fromMajor` rounds floating-point numbers, and `fromMinor` accepts minor units:

```ts
import { fromDecimal } from "okane";
const amount = fromDecimal("12.34", USD); // 1234n
```

Money objects support comparisons (`eq`, `lt`, `gt`, `isZero`, `isPos`, `isNeg`) and
formatting (`fmt`, `decimal`, `json`). All methods return new immutable instances,
enabling chaining:

```ts
const final = price.add(tax).mul(1.08).sub(okane(500n, USD));
console.log(final.fmt()); // '$135.74'
```

`okane` separates core operations from parsing, formatting, and validation. Validation
returns a Result type, allowing safe handling of untrusted data without exceptions:

```ts
import { parseMoney, unwrap } from "okane";
const m = unwrap(parseMoney({ amount: "9999", currency: { code: "USD", decimals: 2 } }));
```

Predefined currencies cover common fiat and crypto assets, and custom currencies can
be created with `currency(code, decimals, symbol)`. Minor unit multipliers are
accessible via `minorUnits(currency)`.

By representing money as `bigint` in minor units and enforcing type safety at
compile-time, `okane` delivers reliable financial calculations with explicit pipelines,
immutable values, precise allocation, and clear rounding behavior, while remaining
simple to integrate in JavaScript or TypeScript projects.

### Todo

- [ ] lazy evaluate for chained operations
- [ ] Streaming sum for very large arrays
- [ ] Rounding Strategies Plugin