dinero.js

GitHub

Create, calculate, and format money in JavaScript and TypeScript

RAW Doc

Api/Conversions/Convert

---
title: convert
description: Create a Dinero object converter.
returns: Dinero<TAmount, TNewCurrency>
---

convert

Convert a Dinero object from a currency to another.

If you need to use fractional rates, you shouldn't use floats, but scaled amounts instead. For example, instead of passing 0.89, you should pass { amount: 89, scale: 2 }. When using scaled amounts, the function converts the returned object to the safest scale.

In TypeScript, the returned Dinero object carries the type of the new currency. See Currency type safety.

::: warning
Both currencies must share the same base. Converting between currencies with different bases (e.g., USD base 10 and MGA base 5) will throw.
:::

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The Dinero object to convert. | Yes |
| newCurrency | DineroCurrency<TAmount, TNewCurrency> | The currency to convert into. | Yes |
| rates | DineroRates<TAmount> | The rates to convert with. | Yes |

Code examples

Convert to another currency

js
import { dinero, convert } from 'dinero.js';
import { USD, EUR } from 'dinero.js/currencies';

const rates = { EUR: { amount: 89, scale: 2 } };
const d = dinero({ amount: 500, currency: USD });

convert(d, EUR, rates); // a Dinero object with amount 44500 and scale 4

Convert to a currency with a different scale

js
import { dinero, convert } from 'dinero.js';
import { USD, IQD } from 'dinero.js/currencies';

const rates = { IQD: 1199 };
const d = dinero({ amount: 500, currency: USD });

convert(d, IQD, rates); // a Dinero object with amount 5995000 and scale 3

Build a reusable converter

If you're converting many objects, you might want to reuse the same rates without having to pass them every time. To do so, you can wrap convert in a converter function that accepts a Dinero object and a new currency, and returns it formatted using a predefined converter.

js
import { dinero, convert } from 'dinero.js';
import { USD, EUR } from 'dinero.js/currencies';

const rates = { EUR: { amount: 89, scale: 2 } };

function converter(dineroObject, newCurrency) {
return convert(dineroObject, newCurrency, rates);
}

const d = dinero({ amount: 500, currency: USD });

converter(d, EUR); // a Dinero object with amount 44500 and scale 4

You can even build your own reusable higher-order function to build converters.

js
// ...

function createConverter(rates) {
return function converter(dineroObject, newCurrency) {
return convert(dineroObject, newCurrency, rates);
};
}

---

Api/Conversions/Normalize Scale

---
title: normalizeScale
description: Normalize a set of Dinero objects to the highest scale of the set.
returns: Dinero<TAmount, TCurrency>[]
---

normalizeScale

Normalize a set of Dinero objects to the highest scale of the set.

Normalizing to a higher scale means that the internal amount value increases by orders of magnitude. If you're using the default Dinero.js implementation (with the number calculator), be careful not to exceed the minimum and maximum safe integers.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObjects | Dinero<TAmount, TCurrency>[] | The Dinero objects to normalize. | Yes |

Code examples

Normalize objects to the same scale

js
import { dinero, normalizeScale } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 100, currency: USD, scale: 2 });
const d2 = dinero({ amount: 2000, currency: USD, scale: 3 });

const [one, two] = normalizeScale([d1, d2]);

one; // a Dinero object with amount 1000 and scale 3
two; // a Dinero object with amount 2000 and scale 3

---

Api/Conversions/Transform Scale

---
title: transformScale
description: Transform a Dinero object to a new scale.
returns: Dinero<TAmount, TCurrency>
---

transformScale

Transform a Dinero object to a new scale.

When transforming to a higher scale, the internal amount value increases by orders of magnitude. If you're using the default Dinero.js implementation (with the number calculator), be careful not to exceed the minimum and maximum safe integers.

When transforming to a smaller scale, the amount loses precision. By default, the function rounds down the amount. You can specify how to round by passing a custom divide function.

For convenience, Dinero.js provides the following divide functions: up, down, halfUp, halfDown, halfOdd, halfEven (bankers rounding), halfTowardsZero, and halfAwayFromZero.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The Dinero object to transform. | Yes |
| newScale | TAmount | The new scale. | Yes |
| divide | DivideOperation | A custom divide function. | No |

Code examples

Transform an object to a new scale

js
import { dinero, transformScale } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 500, currency: USD, scale: 2 });

transformScale(d, 4); // a Dinero object with amount 50000 and scale 4

Pass a custom divide function

js
import { dinero, transformScale, up } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 10455, currency: USD, scale: 3 });

transformScale(d, 2, up); // a Dinero object with amount 1046 and scale 2

---

Api/Conversions/Trim Scale

---
title: trimScale
description: Trim a Dinero object's scale as much as possible, down to the currency exponent.
returns: Dinero<TAmount, TCurrency>
---

trimScale

Trim a Dinero object's scale as much as possible, down to the currency exponent.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The Dinero object to trim. | Yes |

Code examples

Trim an object down to its currency exponent's scale

js
import { dinero, trimScale } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 500000, currency: USD, scale: 5 });

trimScale(d); // a Dinero object with amount 500 and scale 2

Trim an object down to the safest possible scale

js
import { dinero, trimScale } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 99950, currency: USD, scale: 4 });

trimScale(d); // a Dinero object with amount 9995 and scale 3

---

Api/Comparisons/Compare

---
title: compare
description: Compare the value of a Dinero object relative to another.
returns: number
---

compare

Compare the value of a Dinero object relative to another. This is useful for sorting Dinero objects.

Possible return values are:
- -1 if the first Dinero object is less than the other
- 1 if the first Dinero object is greater than the other
- 0 if both objects are equal

You can only compare objects that share the same currency. The function also normalizes objects to the same scale (the highest) before comparing them.

In TypeScript, this is enforced at compile time when using typed currencies.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The first Dinero object to compare. | Yes |
| comparator | Dinero<TAmount, TCurrency> | The second Dinero object to compare. | Yes |

Code examples

Compare two objects

js
import { dinero, compare } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 800, currency: USD });
const d2 = dinero({ amount: 500, currency: USD });

compare(d1, d2); // 1

Compare two objects after normalization

js
import { dinero, compare } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 5000, currency: USD, scale: 3 });
const d2 = dinero({ amount: 800, currency: USD });

compare(d1, d2); // -1

const d3 = dinero({ amount: 5000, currency: USD, scale: 3 });
const d4 = dinero({ amount: 500, currency: USD });

compare(d3, d4); // 0

Sort arrays of objects

One of the main use cases of the compare function is to sort Dinero objects. For example, you can use it with Array.prototype.sort.

js
import { dinero, compare } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 900, currency: USD });
const d2 = dinero({ amount: 500, currency: USD });
const d3 = dinero({ amount: 800, currency: USD });

const lowToHigh = [d1, d2, d3].sort(compare);
const highToLow = [d1, d2, d3].sort((a, b) => compare(b, a));

---

Api/Comparisons/Equal

---
title: equal
description: Check whether the value of a Dinero object is equal to another.
returns: boolean
---

equal

Check whether the value of a Dinero object is equal to another.

This function does same-value equality, determining whether two Dinero objects are functionally equivalent. It also normalizes objects to the same scale (the highest) before comparing them.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The first Dinero object to compare. | Yes |
| comparator | Dinero<TAmount, TCurrency> | The second Dinero object to compare. | Yes |

Code examples

Compare two identical objects

js
import { dinero, equal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 500, currency: USD });

equal(d1, d2); // true

Compare two objects with different amounts

js
import { dinero, equal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 800, currency: USD });

equal(d1, d2); // false

Compare two identical objects after normalization

js
import { dinero, equal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 5000, currency: USD, scale: 3 });

equal(d1, d2); // true

Compare two objects with different currencies

js
import { dinero, equal } from 'dinero.js';
import { USD, EUR } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 500, currency: EUR });

equal(d1, d2); // false

---

Api/Comparisons/Greater Than

---
title: greaterThan
description: Check whether the value of a Dinero object is greater than another.
returns: boolean
---

greaterThan

Check whether the value of a Dinero object is greater than another.

You can only compare objects that share the same currency. The function also normalizes objects to the same scale (the highest) before comparing them.

In TypeScript, this is enforced at compile time when using typed currencies.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The first Dinero object to compare. | Yes |
| comparator | Dinero<TAmount, TCurrency> | The second Dinero object to compare. | Yes |

Code examples

Compare two objects

js
import { dinero, greaterThan } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 800, currency: USD });

greaterThan(d1, d2); // false

Compare two objects after normalization

js
import { dinero, greaterThan } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 800, currency: USD });
const d2 = dinero({ amount: 5000, currency: USD, scale: 3 });

greaterThan(d1, d2); // true

---

Api/Comparisons/Greater Than Or Equal

---
title: greaterThanOrEqual
description: Check whether the value of a Dinero object is greater than or equal another.
returns: boolean
---

greaterThanOrEqual

Check whether the value of a Dinero object is greater than or equal another.

You can only compare objects that share the same currency. The function also normalizes objects to the same scale (the highest) before comparing them.

In TypeScript, this is enforced at compile time when using typed currencies.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The first Dinero object to compare. | Yes |
| comparator | Dinero<TAmount, TCurrency> | The second Dinero object to compare. | Yes |

Code examples

Compare two objects

js
import { dinero, greaterThanOrEqual } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 800, currency: USD });

greaterThanOrEqual(d1, d2); // false

Compare two identical objects

js
import { dinero, greaterThanOrEqual } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 500, currency: USD });

greaterThanOrEqual(d1, d2); // true

Compare two objects after normalization

js
import { dinero, greaterThanOrEqual } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 800, currency: USD });
const d2 = dinero({ amount: 5000, currency: USD, scale: 3 });

greaterThanOrEqual(d1, d2); // true

---

Api/Comparisons/Has Sub Units

---
title: hasSubUnits
description: Check whether a Dinero object has minor currency units.
returns: boolean
---

hasSubUnits

Check whether a Dinero object has minor currency units.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount> | The Dinero object to check. | Yes |

Code examples

Check an object with sub-units

js
import { dinero, hasSubUnits } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1150, currency: USD });

hasSubUnits(d); // true

Check an object without sub-units

js
import { dinero, hasSubUnits } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1100, currency: USD });

hasSubUnits(d); // false

Check an object with sub-units based on the scale

js
import { dinero, hasSubUnits } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1100, currency: USD, scale: 3 });

hasSubUnits(d); // true

---

Api/Comparisons/Have Same Amount

---
title: haveSameAmount
description: Check whether a set of Dinero objects have the same amount.
returns: boolean
---

haveSameAmount

Check whether a set of Dinero objects have the same amount.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObjects | Dinero<TAmount, TCurrency>[] | The Dinero object to check. | Yes |

Code examples

Compare two objects with the same amount

js
import { dinero, haveSameAmount } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 1000, currency: USD });
const d2 = dinero({ amount: 1000, currency: USD });

haveSameAmount([d1, d2]); // true

Compare two objects with different amount

js
import { dinero, haveSameAmount } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 1000, currency: USD });
const d2 = dinero({ amount: 2000, currency: USD });

haveSameAmount([d1, d2]); // false

Compare two objects with the same amount once normalized

js
import { dinero, haveSameAmount } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 1000, currency: USD });
const d2 = dinero({ amount: 10000, currency: USD, scale: 3 });

haveSameAmount([d1, d2]); // true

---

Api/Comparisons/Have Same Currency

---
title: haveSameCurrency
description: Check whether a set of Dinero objects have the same currency.
returns: boolean
---

haveSameCurrency

Check whether a set of Dinero objects have the same currency.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObjects | Dinero<TAmount>[] | The Dinero object to check. | Yes |

Code examples

Compare two objects with the same currency

js
import { dinero, haveSameCurrency } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 2000, currency: USD });
const d2 = dinero({ amount: 1000, currency: USD });

haveSameCurrency([d1, d2]); // true

Compare two objects with different currencies

js
import { dinero, haveSameAmount } from 'dinero.js';
import { USD, EUR } from 'dinero.js/currencies';

const d1 = dinero({ amount: 1000, currency: USD });
const d2 = dinero({ amount: 1000, currency: EUR });

haveSameAmount([d1, d2]); // false

---

Api/Comparisons/Is Negative

---
title: isNegative
description: Check whether a Dinero object is negative.
returns: boolean
---

isNegative

Check whether a Dinero object is negative.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount> | The Dinero object to check. | Yes |

Code examples

Check a positive object

js
import { dinero, isNegative } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 100, currency: USD });

isNegative(d); // false

Check a negative object

js
import { dinero, isNegative } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: -100, currency: USD });

isNegative(d); // true

Check a zero object

js
import { dinero, isNegative } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 0, currency: USD });

isNegative(d); // false

---

Api/Comparisons/Is Positive

---
title: isPositive
description: Check whether a Dinero object is positive.
returns: boolean
---

isPositive

Check whether a Dinero object is positive.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount> | The Dinero object to check. | Yes |

Code examples

Check a positive object

js
import { dinero, isPositive } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 100, currency: USD });

isPositive(d); // true

Check a negative object

js
import { dinero, isPositive } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: -100, currency: USD });

isPositive(d); // false

Check a zero object

js
import { dinero, isPositive } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 0, currency: USD });

isPositive(d); // false

---

Api/Comparisons/Is Zero

---
title: isZero
description: Check whether the value of a Dinero object is zero.
returns: boolean
---

isZero

Check whether the value of a Dinero object is zero.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount> | The Dinero object to check. | Yes |

Code examples

Check a zero object

js
import { dinero, isZero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 0, currency: USD });

isZero(d); // true

Check a non-zero object

js
import { dinero, isZero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 100, currency: USD });

isZero(d); // false

---

Api/Comparisons/Less Than

---
title: lessThan
description: Check whether the value of a Dinero object is lesser than another.
returns: boolean
---

lessThan

Check whether the value of a Dinero object is lesser than another.

You can only compare objects that share the same currency. The function also normalizes objects to the same scale (the highest) before comparing them.

In TypeScript, this is enforced at compile time when using typed currencies.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The first Dinero object to compare. | Yes |
| comparator | Dinero<TAmount, TCurrency> | The second Dinero object to compare. | Yes |

Code examples

Compare two objects

js
import { dinero, lessThan } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 800, currency: USD });
const d2 = dinero({ amount: 500, currency: USD });

lessThan(d1, d2); // false

Compare two objects after normalization

js
import { dinero, lessThan } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 5000, currency: USD, scale: 3 });
const d2 = dinero({ amount: 800, currency: USD });

lessThan(d1, d2); // true

---

Api/Comparisons/Less Than Or Equal

---
title: lessThanOrEqual
description: Check whether the value of a Dinero object is lesser than or equal to another.
returns: boolean
---

lessThanOrEqual

Check whether the value of a Dinero object is lesser than or equal to another.

You can only compare objects that share the same currency. The function also normalizes objects to the same scale (the highest) before comparing them.

In TypeScript, this is enforced at compile time when using typed currencies.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The first Dinero object to compare. | Yes |
| comparator | Dinero<TAmount, TCurrency> | The second Dinero object to compare. | Yes |

Code examples

Compare two objects

js
import { dinero, lessThanOrEqual } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 800, currency: USD });
const d2 = dinero({ amount: 500, currency: USD });

lessThanOrEqual(d1, d2); // false

Compare two identical objects

js
import { dinero, lessThanOrEqual } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 500, currency: USD });

lessThanOrEqual(d1, d2); // true

Compare two objects after normalization

js
import { dinero, lessThanOrEqual } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 5000, currency: USD, scale: 3 });
const d2 = dinero({ amount: 800, currency: USD });

lessThanOrEqual(d1, d2); // true

---

Api/Comparisons/Maximum

---
title: maximum
description: Get the greatest of the passed Dinero objects.
returns: Dinero<TAmount, TCurrency>
---

maximum

Get the greatest of the passed Dinero objects.

You can only compare objects that share the same currency. The function also normalizes objects to the same scale (the highest) before comparing them.

In TypeScript, this is enforced at compile time when using typed currencies.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObjects | Dinero<TAmount, TCurrency>[] | The Dinero objects to maximum. | Yes |

Code examples

Get the greatest object from a set

js
import { dinero, maximum } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 150, currency: USD });
const d2 = dinero({ amount: 50, currency: USD });

maximum([d1, d2]); // a Dinero object with amount 150

Get the greatest object from a set after normalization

js
import { dinero, maximum } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 1000, currency: USD, scale: 3 });

maximum([d1, d2]); // a Dinero object with amount 5000 and scale 3

---

Api/Comparisons/Minimum

---
title: minimum
description: Get the lowest of the passed Dinero objects.
returns: Dinero<TAmount, TCurrency>
---

minimum

Get the lowest of the passed Dinero objects.

You can only compare objects that share the same currency. The function also normalizes objects to the same scale (the highest) before comparing them.

In TypeScript, this is enforced at compile time when using typed currencies.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObjects | Dinero<TAmount, TCurrency>[] | The Dinero objects to minimum. | Yes |

Code examples

Get the lowest object from a set

js
import { dinero, minimum } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 150, currency: USD });
const d2 = dinero({ amount: 50, currency: USD });

minimum([d1, d2]); // a Dinero object with amount 50

Get the lowest object from a set after normalization

js
import { dinero, minimum } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 1000, currency: USD, scale: 3 });

minimum([d1, d2]); // a Dinero object with amount 1000 and scale 3

---

Api/Formatting/To Decimal

---
title: toDecimal
description: Get the amount of a Dinero object in decimal format.
returns: TOutput = string
---

toDecimal

Get the amount of a Dinero object in a stringified decimal representation.

The number of decimal places depends on the scale of your object—or, when unspecified, the exponent of its currency.

::: info
You can only use this function with Dinero objects that are single-based and use a decimal currency.
:::

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The Dinero object to format. | Yes |
| transformer | DineroTransformer<TAmount, TOutput, TCurrency> | An optional transformer function. | No |

Code examples

Format an object in decimal format

js
import { dinero, toDecimal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 1050, currency: USD });
const d2 = dinero({ amount: 10545, currency: USD, scale: 3 });

toDecimal(d1); // "10.50"
toDecimal(d2); // "10.545"

Use a custom transformer

If you need to further transform the value before returning it, you can pass a custom function.

js
import { dinero, toDecimal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1050, currency: USD });

toDecimal(d, ({ value, currency }) => ${currency.code} ${value}); // "USD 10.50"

---

Api/Formatting/To Snapshot

---
title: toSnapshot
description: Get a snapshot of a Dinero object.
returns: DineroSnapshot<TAmount, TCurrency>
---

toSnapshot

Get a snapshot of a Dinero object.

Snapshots are plain JavaScript objects, suited for transport and storage. They're also useful when you need to retrieve raw data from a Dinero object.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The Dinero object to snapshot. | Yes |

Code examples

Get a snapshot of an object

js
import { dinero, toSnapshot } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 500, currency: USD });

toSnapshot(d);

// {
// amount: 500,
// currency: {
// code: 'USD',
// base: 10,
// exponent: 2,
// },
// scale: 2,
// }

---

Api/Formatting/To Units

---
title: toUnits
description: Get the amount of a Dinero object in units.
returns: TOutput = TAmount[]
---

toUnits

Get the amount of a Dinero object in units.

This function returns the total amount divided into each unit and sub-unit, as an array. For example, an object representing $10.45 expressed as 1045 (with currency USD and no custom scale) would return [10, 45] for 10 dollars and 45 cents.

When specifying multiple bases, the function returns as many units as necessary.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The Dinero object to format. | Yes |
| transformer | DineroTransformer<TAmount, TOutput, TCurrency> | An optional transformer function. | No |

Code examples

Format an object in units

js
import { dinero, toUnits } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 1050, currency: USD });
const d2 = dinero({ amount: 10545, currency: USD, scale: 3 });

toUnits(d1); // [10, 50]
toUnits(d2); // [10, 545]

Format a non-decimal object

js
import { dinero, toUnits } from 'dinero.js';

const GRD = { code: 'GRD', base: 6, exponent: 1 };
const d = dinero({ amount: 9, currency: GRD });

toUnits(d); // [1, 3]

Format an object with multiple subdivisions

js
import { dinero, toUnits } from 'dinero.js';

const GBP = { code: 'GBP', base: [20, 12], exponent: 1 };
const d = dinero({ amount: 267, currency: GBP });

toUnits(d); // [1, 2, 3]

Use a custom transformer

If you need to further transform the value before returning it, you can pass a custom function.

js
import { dinero, toUnits } from 'dinero.js';

const GBP = { code: 'GBP', base: [20, 12], exponent: 1 };
const d = dinero({ amount: 267, currency: GBP });

const labels = ['pounds', 'shillings', 'pence'];

toUnits(d, ({ value }) =>
value
.filter((amount) => amount > 0)
.map((amount, index) => ${amount} ${labels[index]})
.join(', ')
);

---

Api/Mutations/Add

---
title: add
description: Adding up two Dinero objects.
returns: Dinero<TAmount, TCurrency>
---

add

Add up two Dinero objects.

You can only add objects that share the same currency. The function also normalizes objects to the same scale (the highest) before adding them up.

In TypeScript, this is enforced at compile time when using typed currencies.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| augend | Dinero<TAmount, TCurrency> | The Dinero object to add to. | Yes |
| addend | Dinero<TAmount, TCurrency> | The Dinero object to add. | Yes |

Code examples

Add objects

js
import { dinero, add } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 100, currency: USD });

add(d1, d2); // a Dinero object with amount 600

Add objects with a different scale

js
import { dinero, add } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 400, currency: USD });
const d2 = dinero({ amount: 104545, currency: USD, scale: 4 });

add(d1, d2); // a Dinero object with amount 144545 and scale 4

Add more than two objects

To retrieve the sum of multiple objects, you can call the add function multiple times.

js
import { dinero, add } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 300, currency: USD });
const d2 = dinero({ amount: 200, currency: USD });
const d3 = dinero({ amount: 100, currency: USD });

const addMany = (addends) => addends.reduce(add);

addMany([d1, d2, d3]); // a Dinero object with amount 600

---

Api/Mutations/Allocate

---
title: allocate
description: Distribute the amount of a Dinero object across a list of ratios.
returns: Dinero<TAmount, TCurrency>[]
---

allocate

Distribute the amount of a Dinero object across a list of ratios.

Monetary values have indivisible units, meaning you can't always exactly split them. With allocate, you can split a monetary amount then distribute the remainder as evenly as possible.

You can use percentage or ratio style for ratios: [25, 75] and [1, 3] do the same thing. You can also pass zero ratios (such as [0, 50, 50]). If there's a remainder to distribute, zero ratios are skipped and return a Dinero object with amount zero.

If you need to use fractional ratios, you shouldn't use floats, but scaled amounts instead. For example, instead of passing [50.5, 49.5], you should pass [{ amount: 505, scale: 1 }, { amount: 495, scale: 1 }]. When using scaled amounts, the function converts the returned objects to the safest scale.

All ratios must be positive, and you can't only pass zero ratios.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| dineroObject | Dinero<TAmount, TCurrency> | The Dinero object to allocate from. | Yes |
| ratios | Array<DineroScaledAmount<TAmount> \| TAmount> | The ratios to allocate the amount to. | Yes |

Code examples

Allocate to percentages

js
import { dinero, allocate } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 500, currency: USD });

const [d1, d2] = allocate(d, [50, 50]);

d1; // a Dinero object with amount 250
d2; // a Dinero object with amount 250

Allocate to ratios

js
import { dinero, allocate } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 100, currency: USD });

const [d1, d2] = allocate(d, [1, 3]);

d1; // a Dinero object with amount 25
d2; // a Dinero object with amount 75

Distribute as fairly as possible

js
import { dinero, allocate } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1003, currency: USD });

const [d1, d2] = allocate(d, [50, 50]);

d1; // a Dinero object with amount 502
d2; // a Dinero object with amount 501

Ignore zero ratios

js
import { dinero, allocate } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1003, currency: USD });

const [d1, d2, d3] = allocate(d, [0, 50, 50]);

d1; // a Dinero object with amount 0
d2; // a Dinero object with amount 502
d3; // a Dinero object with amount 501

Use scaled ratios and convert to the safest scale

js
import { dinero, allocate } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const ratios = [
{ amount: 505, scale: 1 },
{ amount: 495, scale: 1 },
]; // translates to ratios 50.5 and 49.5
const d = dinero({ amount: 100, currency: USD });

const [d1, d2] = allocate(d, ratios);

d1; // a Dinero object with amount 505 and scale 3
d2; // a Dinero object with amount 495 and scale 3

---

Api/Mutations/Multiply

---
title: multiply
description: Multiply a Dinero object.
returns: Dinero<TAmount, TCurrency>
---

multiply

Multiply a Dinero object.

If you need to multiply by a fractional multiplier, you shouldn't use floats, but scaled amounts instead. For example, instead of passing 2.1, you should pass { amount: 21, scale: 1 }. When using scaled amounts, the function converts the returned objects to the safest scale.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| multiplicand | Dinero<TAmount, TCurrency> | The Dinero object to multiply. | Yes |
| multiplier | DineroScaledAmount<TAmount> \| TAmount | The number to multiply with. | Yes |

Code examples

Multiply by an integer

js
import { dinero, multiply } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 400, currency: USD });

multiply(d, 4); // a Dinero object with amount 1600

Multiply by a scaled multiplier

js
import { dinero, multiply } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 401, currency: USD });

multiply(d, { amount: 2001, scale: 3 }); // a Dinero object with amount 802401 and scale 5

---

Api/Mutations/Subtract

---
title: subtract
description: Subtracting two Dinero objects.
returns: Dinero<TAmount, TCurrency>
---

subtract

Subtract two Dinero objects.

You can only subtract objects that share the same currency. The function also normalizes objects to the same scale (the highest) before subtracting them.

In TypeScript, this is enforced at compile time when using typed currencies.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| minuend | Dinero<TAmount, TCurrency> | The Dinero object to subtract from. | Yes |
| subtrahend | Dinero<TAmount, TCurrency> | The Dinero object to subtract. | Yes |

Code examples

Subtract objects

js
import { dinero, subtract } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 100, currency: USD });

subtract(d1, d2); // a Dinero object with amount 400

Subtract objects with a different scale

js
import { dinero, subtract } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 1000, currency: USD, scale: 3 });

subtract(d1, d2); // a Dinero object with amount 4000 and scale 3

Subtract more than two objects

js
import { dinero, subtract } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 400, currency: USD });
const d2 = dinero({ amount: 200, currency: USD });
const d3 = dinero({ amount: 100, currency: USD });

const subtractMany = (subtrahends) => subtrahends.reduce(subtract);

subtractMany([d1, d2, d3]); // a Dinero object with amount 100

---

Api/Rounding/Down

---
title: down
description: Divide and round towards negative infinity.
---

down

Divide and round towards negative infinity.

This rounding mode always rounds down, regardless of the fractional part. For positive numbers, it truncates the decimal (e.g., 1.1 becomes 1, 1.9 becomes 1). For negative numbers, it rounds away from zero (e.g., -1.1 becomes -2).

This is the default rounding mode used by transformScale.

Usage

Pass this function as the last argument to multiply, allocate, or transformScale to control how remainders are handled.

Code examples

Use with multiply

js
import { dinero, multiply, down } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 401, currency: USD });

multiply(d, { amount: 21, scale: 1 }, down); // a Dinero object with amount 8421 and scale 3

Use with transformScale

js
import { dinero, transformScale, down } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 10455, currency: USD, scale: 3 });

transformScale(d, 2, down); // a Dinero object with amount 1045 and scale 2

---

Api/Rounding/Half Away From Zero

---
title: halfAwayFromZero
description: Divide and round half away from zero.
---

halfAwayFromZero

Divide and round towards the nearest neighbor, rounding away from zero when exactly halfway.

This rounding mode rounds to the nearest integer. When the value is exactly halfway between two integers, it rounds away from zero. Positive halfway values round up (e.g., 1.5 becomes 2), and negative halfway values round down (e.g., -1.5 becomes -2).

This is sometimes referred to as "commercial rounding" or "arithmetic rounding."

Usage

Pass this function as the last argument to multiply, allocate, or transformScale to control how remainders are handled.

Code examples

Use with multiply

js
import { dinero, multiply, halfAwayFromZero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 305, currency: USD });

multiply(d, { amount: 21, scale: 1 }, halfAwayFromZero); // a Dinero object with amount 6405 and scale 3

Use with transformScale

js
import { dinero, transformScale, halfAwayFromZero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1055, currency: USD, scale: 3 });

transformScale(d, 2, halfAwayFromZero); // a Dinero object with amount 106 and scale 2

---

Api/Rounding/Half Down

---
title: halfDown
description: Divide and round half towards negative infinity.
---

halfDown

Divide and round towards the nearest neighbor, rounding down when exactly halfway.

This rounding mode rounds to the nearest integer. When the value is exactly halfway between two integers (e.g., 1.5), it rounds down (towards negative infinity). For non-halfway values, it behaves the same as halfUp.

For example, 1.5 rounds to 1, 2.5 rounds to 2, and -1.5 rounds to -2.

Usage

Pass this function as the last argument to multiply, allocate, or transformScale to control how remainders are handled.

Code examples

Use with multiply

js
import { dinero, multiply, halfDown } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 305, currency: USD });

multiply(d, { amount: 21, scale: 1 }, halfDown); // a Dinero object with amount 6405 and scale 3

Use with transformScale

js
import { dinero, transformScale, halfDown } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1055, currency: USD, scale: 3 });

transformScale(d, 2, halfDown); // a Dinero object with amount 105 and scale 2

---

Api/Rounding/Half Even

---
title: halfEven
description: Divide and round half to the nearest even integer.
---

halfEven

Divide and round towards the nearest neighbor, rounding to the nearest even integer when exactly halfway.

This rounding mode is also known as bankers rounding. It rounds to the nearest integer, and when the value is exactly halfway between two integers, it picks the even one. This reduces cumulative rounding bias in financial calculations.

For example, 1.5 rounds to 2, 2.5 rounds to 2, 3.5 rounds to 4, and -2.5 rounds to -2.

Usage

Pass this function as the last argument to multiply, allocate, or transformScale to control how remainders are handled.

Code examples

Use with multiply

js
import { dinero, multiply, halfEven } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 305, currency: USD });

multiply(d, { amount: 21, scale: 1 }, halfEven); // a Dinero object with amount 6405 and scale 3

Use with transformScale

js
import { dinero, transformScale, halfEven } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1050, currency: USD, scale: 3 });

transformScale(d, 2, halfEven); // a Dinero object with amount 104 and scale 2

---

Api/Rounding/Half Odd

---
title: halfOdd
description: Divide and round half to the nearest odd integer.
---

halfOdd

Divide and round towards the nearest neighbor, rounding to the nearest odd integer when exactly halfway.

This rounding mode rounds to the nearest integer. When the value is exactly halfway between two integers, it picks the odd one. For non-halfway values, it behaves the same as halfUp.

For example, 1.5 rounds to 1, 2.5 rounds to 3, 3.5 rounds to 3, and -2.5 rounds to -3.

Usage

Pass this function as the last argument to multiply, allocate, or transformScale to control how remainders are handled.

Code examples

Use with multiply

js
import { dinero, multiply, halfOdd } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 305, currency: USD });

multiply(d, { amount: 21, scale: 1 }, halfOdd); // a Dinero object with amount 6405 and scale 3

Use with transformScale

js
import { dinero, transformScale, halfOdd } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1050, currency: USD, scale: 3 });

transformScale(d, 2, halfOdd); // a Dinero object with amount 105 and scale 2

---

Api/Rounding/Half Towards Zero

---
title: halfTowardsZero
description: Divide and round half towards zero.
---

halfTowardsZero

Divide and round towards the nearest neighbor, rounding towards zero when exactly halfway.

This rounding mode rounds to the nearest integer. When the value is exactly halfway between two integers, it rounds towards zero. Positive halfway values round down (e.g., 1.5 becomes 1), and negative halfway values round up (e.g., -1.5 becomes -1).

Usage

Pass this function as the last argument to multiply, allocate, or transformScale to control how remainders are handled.

Code examples

Use with multiply

js
import { dinero, multiply, halfTowardsZero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 305, currency: USD });

multiply(d, { amount: 21, scale: 1 }, halfTowardsZero); // a Dinero object with amount 6405 and scale 3

Use with transformScale

js
import { dinero, transformScale, halfTowardsZero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1055, currency: USD, scale: 3 });

transformScale(d, 2, halfTowardsZero); // a Dinero object with amount 105 and scale 2

---

Api/Rounding/Half Up

---
title: halfUp
description: Divide and round half towards positive infinity.
---

halfUp

Divide and round towards the nearest neighbor, rounding up when exactly halfway.

This rounding mode rounds to the nearest integer. When the value is exactly halfway between two integers (e.g., 1.5), it rounds up (towards positive infinity). This is the most commonly taught rounding method.

For example, 1.5 rounds to 2, 2.5 rounds to 3, and -1.5 rounds to -1.

Usage

Pass this function as the last argument to multiply, allocate, or transformScale to control how remainders are handled.

Code examples

Use with multiply

js
import { dinero, multiply, halfUp } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 305, currency: USD });

multiply(d, { amount: 21, scale: 1 }, halfUp); // a Dinero object with amount 6405 and scale 3

Use with transformScale

js
import { dinero, transformScale, halfUp } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1055, currency: USD, scale: 3 });

transformScale(d, 2, halfUp); // a Dinero object with amount 106 and scale 2

---

Api/Rounding/Up

---
title: up
description: Divide and round towards positive infinity.
---

up

Divide and round towards positive infinity.

This rounding mode always rounds up, regardless of the fractional part. For positive numbers, any fractional value causes the result to increase (e.g., 1.1 becomes 2, 1.9 becomes 2). For negative numbers, it rounds towards zero (e.g., -1.9 becomes -1).

Usage

Pass this function as the last argument to multiply, allocate, or transformScale to control how remainders are handled.

Code examples

Use with multiply

js
import { dinero, multiply, up } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 401, currency: USD });

multiply(d, { amount: 21, scale: 1 }, up); // a Dinero object with amount 8422 and scale 3

Use with transformScale

js
import { dinero, transformScale, up } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 10455, currency: USD, scale: 3 });

transformScale(d, 2, up); // a Dinero object with amount 1046 and scale 2

---

Api/Currencies

---
title: Currencies
description: ISO 4217 currency objects available in dinero.js/currencies.
---

Currencies

Dinero.js ships with all ISO 4217 currencies out of the box.

js
import { dinero } from 'dinero.js';
import { USD, EUR, JPY } from 'dinero.js/currencies';

const d = dinero({ amount: 1000, currency: USD });

If you're using the bigint variant, import from dinero.js/bigint/currencies instead.

::: info
Need a currency that isn't listed here? You can create custom currency objects. For cryptocurrencies, see the cryptocurrency guide.
:::

::: warning
Currency data tracks the ISO 4217 standard and may change between Dinero.js versions. If you need stability, pin your package version or define your own currency objects.
:::

Properties

| Property | Type | Description |
|----------|------|-------------|
| code | string | The ISO 4217 currency code. |
| base | number | The number base (radix). Most currencies use 10; non-decimal currencies like MGA and MRU use 5. |
| exponent | number | The number of decimal places. Determines how the amount maps to major and minor units. |

Available currencies

| Code | Currency | Base | Exponent |
|------|----------|------|----------|
| AED | United Arab Emirates dirham | 10 | 2 |
| AFN | Afghan afghani | 10 | 2 |
| ALL | Albanian lek | 10 | 2 |
| AMD | Armenian dram | 10 | 2 |
| AOA | Angolan kwanza | 10 | 2 |
| ARS | Argentine peso | 10 | 2 |
| AUD | Australian dollar | 10 | 2 |
| AWG | Aruban florin | 10 | 2 |
| AZN | Azerbaijani manat | 10 | 2 |
| BAM | Bosnia and Herzegovina convertible mark | 10 | 2 |
| BBD | Barbados dollar | 10 | 2 |
| BDT | Bangladeshi taka | 10 | 2 |
| BGN | Bulgarian lev | 10 | 2 |
| BHD | Bahraini dinar | 10 | 3 |
| BIF | Burundian franc | 10 | 0 |
| BMD | Bermudian dollar | 10 | 2 |
| BND | Brunei dollar | 10 | 2 |
| BOB | Bolivian boliviano | 10 | 2 |
| BOV | Bolivian Mvdol | 10 | 2 |
| BRL | Brazilian real | 10 | 2 |
| BSD | Bahamian dollar | 10 | 2 |
| BTN | Bhutanese ngultrum | 10 | 2 |
| BWP | Botswana pula | 10 | 2 |
| BYN | Belarusian ruble | 10 | 2 |
| BZD | Belize dollar | 10 | 2 |
| CAD | Canadian dollar | 10 | 2 |
| CDF | Congolese franc | 10 | 2 |
| CHE | WIR Euro | 10 | 2 |
| CHF | Swiss franc | 10 | 2 |
| CHW | WIR Franc | 10 | 2 |
| CLF | Unidad de Fomento | 10 | 4 |
| CLP | Chilean peso | 10 | 0 |
| CNY | Renminbi (Chinese) yuan | 10 | 2 |
| COP | Colombian peso | 10 | 2 |
| COU | Unidad de Valor Real | 10 | 2 |
| CRC | Costa Rican colón | 10 | 2 |
| CUP | Cuban peso | 10 | 2 |
| CVE | Cape Verdean escudo | 10 | 2 |
| CZK | Czech koruna | 10 | 2 |
| DJF | Djiboutian franc | 10 | 0 |
| DKK | Danish krone | 10 | 2 |
| DOP | Dominican peso | 10 | 2 |
| DZD | Algerian dinar | 10 | 2 |
| EGP | Egyptian pound | 10 | 2 |
| ERN | Eritrean nakfa | 10 | 2 |
| ETB | Ethiopian birr | 10 | 2 |
| EUR | Euro | 10 | 2 |
| FJD | Fiji dollar | 10 | 2 |
| FKP | Falkland Islands pound | 10 | 2 |
| GBP | Pound sterling | 10 | 2 |
| GEL | Georgian lari | 10 | 2 |
| GHS | Ghanaian cedi | 10 | 2 |
| GIP | Gibraltar pound | 10 | 2 |
| GMD | Gambian dalasi | 10 | 2 |
| GNF | Guinean franc | 10 | 0 |
| GTQ | Guatemalan quetzal | 10 | 2 |
| GYD | Guyanese dollar | 10 | 2 |
| HKD | Hong Kong dollar | 10 | 2 |
| HNL | Honduran lempira | 10 | 2 |
| HTG | Haitian gourde | 10 | 2 |
| HUF | Hungarian forint | 10 | 2 |
| IDR | Indonesian rupiah | 10 | 2 |
| ILS | Israeli new shekel | 10 | 2 |
| INR | Indian rupee | 10 | 2 |
| IQD | Iraqi dinar | 10 | 3 |
| IRR | Iranian rial | 10 | 2 |
| ISK | Icelandic króna | 10 | 0 |
| JMD | Jamaican dollar | 10 | 2 |
| JOD | Jordanian dinar | 10 | 3 |
| JPY | Japanese yen | 10 | 0 |
| KES | Kenyan shilling | 10 | 2 |
| KGS | Kyrgyzstani som | 10 | 2 |
| KHR | Cambodian riel | 10 | 2 |
| KMF | Comoro franc | 10 | 0 |
| KPW | North Korean won | 10 | 2 |
| KRW | South Korean won | 10 | 0 |
| KWD | Kuwaiti dinar | 10 | 3 |
| KYD | Cayman Islands dollar | 10 | 2 |
| KZT | Kazakhstani tenge | 10 | 2 |
| LAK | Lao kip | 10 | 2 |
| LBP | Lebanese pound | 10 | 2 |
| LKR | Sri Lankan rupee | 10 | 2 |
| LRD | Liberian dollar | 10 | 2 |
| LSL | Lesotho loti | 10 | 2 |
| LYD | Libyan dinar | 10 | 3 |
| MAD | Moroccan dirham | 10 | 2 |
| MDL | Moldovan leu | 10 | 2 |
| MGA | Malagasy ariary | 5 | 1 |
| MKD | Macedonian denar | 10 | 2 |
| MMK | Myanmar kyat | 10 | 2 |
| MNT | Mongolian tögrög | 10 | 2 |
| MOP | Macanese pataca | 10 | 2 |
| MRU | Mauritanian ouguiya | 5 | 1 |
| MUR | Mauritian rupee | 10 | 2 |
| MVR | Maldivian rufiyaa | 10 | 2 |
| MWK | Malawian kwacha | 10 | 2 |
| MXN | Mexican peso | 10 | 2 |
| MXV | Mexican Unidad de Inversion | 10 | 2 |
| MYR | Malaysian ringgit | 10 | 2 |
| MZN | Mozambican metical | 10 | 2 |
| NAD | Namibian dollar | 10 | 2 |
| NGN | Nigerian naira | 10 | 2 |
| NIO | Nicaraguan córdoba | 10 | 2 |
| NOK | Norwegian krone | 10 | 2 |
| NPR | Nepalese rupee | 10 | 2 |
| NZD | New Zealand dollar | 10 | 2 |
| OMR | Omani rial | 10 | 3 |
| PAB | Panamanian balboa | 10 | 2 |
| PEN | Peruvian sol | 10 | 2 |
| PGK | Papua New Guinean kina | 10 | 2 |
| PHP | Philippine peso | 10 | 2 |
| PKR | Pakistani rupee | 10 | 2 |
| PLN | Polish złoty | 10 | 2 |
| PYG | Paraguayan guaraní | 10 | 0 |
| QAR | Qatari riyal | 10 | 2 |
| RON | Romanian leu | 10 | 2 |
| RSD | Serbian dinar | 10 | 2 |
| RUB | Russian ruble | 10 | 2 |
| RWF | Rwandan franc | 10 | 0 |
| SAR | Saudi riyal | 10 | 2 |
| SBD | Solomon Islands dollar | 10 | 2 |
| SCR | Seychelles rupee | 10 | 2 |
| SDG | Sudanese pound | 10 | 2 |
| SEK | Swedish krona | 10 | 2 |
| SGD | Singapore dollar | 10 | 2 |
| SHP | Saint Helena pound | 10 | 2 |
| SLE | Sierra Leonean leone | 10 | 2 |
| SOS | Somali shilling | 10 | 2 |
| SRD | Surinamese dollar | 10 | 2 |
| SSP | South Sudanese pound | 10 | 2 |
| STN | São Tomé and Príncipe dobra | 10 | 2 |
| SVC | Salvadoran colón | 10 | 2 |
| SYP | Syrian pound | 10 | 2 |
| SZL | Swazi lilangeni | 10 | 2 |
| THB | Thai baht | 10 | 2 |
| TJS | Tajikistani somoni | 10 | 2 |
| TMT | Turkmenistan manat | 10 | 2 |
| TND | Tunisian dinar | 10 | 3 |
| TOP | Tongan paʻanga | 10 | 2 |
| TRY | Turkish lira | 10 | 2 |
| TTD | Trinidad and Tobago dollar | 10 | 2 |
| TWD | New Taiwan dollar | 10 | 2 |
| TZS | Tanzanian shilling | 10 | 2 |
| UAH | Ukrainian hryvnia | 10 | 2 |
| UGX | Ugandan shilling | 10 | 0 |
| USD | United States dollar | 10 | 2 |
| USN | United States dollar (next day) | 10 | 2 |
| UYI | Uruguay Peso en Unidades Indexadas | 10 | 0 |
| UYU | Uruguayan peso | 10 | 2 |
| UYW | Unidad previsional | 10 | 4 |
| UZS | Uzbekistani soʻm | 10 | 2 |
| VED | Venezuelan digital bolívar | 10 | 2 |
| VES | Venezuelan bolívar | 10 | 2 |
| VND | Vietnamese đồng | 10 | 0 |
| VUV | Vanuatu vatu | 10 | 0 |
| WST | Samoan tālā | 10 | 2 |
| XAD | Arab Accounting Dinar | 10 | 2 |
| XAF | Central African CFA franc | 10 | 0 |
| XCD | East Caribbean dollar | 10 | 2 |
| XCG | Caribbean guilder | 10 | 2 |
| XOF | West African CFA franc | 10 | 0 |
| XPF | CFP franc | 10 | 0 |
| YER | Yemeni rial | 10 | 2 |
| ZAR | South African rand | 10 | 2 |
| ZMW | Zambian kwacha | 10 | 2 |
| ZWG | Zimbabwe Gold | 10 | 2 |

---

Api/Dinero

---
title: dinero
description: Create a Dinero object.
returns: Dinero<TAmount, TCurrency>
---

dinero

Create a Dinero object that represents a monetary value.

You specify the amount in minor currency units (e.g., cents for the US dollar) and pass a currency. The scale defaults to the currency's exponent but can be set manually for additional precision.

Parameters

| Name | Type | Description | Required |
|------|------|-------------|----------|
| amount | TAmount | The amount in minor currency units. Must be an integer. | Yes |
| currency | DineroCurrency<TAmount> | The currency object. | Yes |
| scale | TAmount | The number of decimal places to represent. Defaults to the currency exponent. | No |

Code examples

Create a Dinero object

js
import { dinero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

// This represents $5.00
const d = dinero({ amount: 500, currency: USD });

Create with a custom scale

When you need more precision than the currency exponent provides, you can specify a custom scale.

js
import { dinero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

// This represents $0.035 (e.g., the price of a single screw)
const d = dinero({ amount: 35, currency: USD, scale: 3 });

Create with bigint

If you need to work with large amounts that exceed the safe range for number, use the bigint variant.

js
import { dinero } from 'dinero.js/bigint';
import { USD } from 'dinero.js/bigint/currencies';

const d = dinero({ amount: 5000n, currency: USD });

Create with a non-decimal currency

You can use custom currency objects for non-decimal currencies.

js
import { dinero } from 'dinero.js';

const GBP = {
code: 'GBP',
base: [20, 12],
exponent: 1,
};

// This represents 50 pre-decimal Great Britain pounds
const d = dinero({ amount: 12000, currency: GBP });

---

Core Concepts/Amount

---
title: Amount
description: Passing an amount to a new Dinero object.
---

Amount

The amount is one of the three pieces of domain data necessary to create a Dinero object. It's expressed in the smallest subdivision of the currency, as an integer.

For example, 50 US dollars equals 5,000 cents.

js
import { dinero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 5000, currency: USD });

You should always pass integers. The library throws whenever you try to pass a float or any non-integer value.

Dinero.js comes with a number implementation, but the library is generic. This means you can use it with any data type you want: bigint, third-parties like big.js, etc. To do so, check the advanced guide on precision and large numbers.

No minor units

When using a currency with no minor units, you should express the amount in major units.

js
import { dinero } from 'dinero.js';
import { JPY } from 'dinero.js/currencies';

// This represents 5,000 Japanese yens
const d = dinero({ amount: 5000, currency: JPY });

When working with currencies with no minor units, you need to set the currency exponent to 0.

Non-decimal currencies

When using a non-decimal currency, you should express the amount in the smallest subdivision. If the currency has multiple subdivisions (such as the pre-decimal British pound sterling), you can specify them with an array.

js
import { dinero } from 'dinero.js';

// Ancient Greek drachma
const GRD = {
code: 'GRD',
base: 6,
exponent: 1,
};

// This represents 1 ancient Greek drachma
// or 6 obols
const d1 = dinero({ amount: 6, currency: GRD });

// Pre-decimal Great Britain pound sterling
// 20 shillings in a pound
// 12 pence in a shilling
const GBP = {
code: 'GBP',
base: [20, 12],
exponent: 1,
};

// This represents 50 pre-decimal Great Britain pounds
// or 1,000 shillings, or 12,000 pence
const d2 = dinero({ amount: 12000, currency: GBP });

When working with non-decimal currencies, you need to set the currency exponent to 1.

See also: Formatting non-decimal currencies

---

Core Concepts/Comparisons

---
title: Comparisons
description: Comparing Dinero objects for amount, currency, equality, sign, and more.
---

Comparisons

Within the control flow of your application, you'll inevitably need to write conditional expressions to make decisions. The Dinero.js API provides functions to compare objects.

js
import { dinero, lessThan } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 800, currency: USD });

lessThan(d1, d2);

Comparing Dinero objects

For example, if you're building a shopping cart checkout page, you'll probably need to see if an amount is greater or lesser than another.

js
import { dinero, greaterThanOrEqual } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const total = dinero({ amount: 25000, currency: USD });
const freeShippingThreshold = dinero({ amount: 10000, currency: USD });

const hasFreeShipping = greaterThanOrEqual(total, freeShippingThreshold);

You can also use comparison functions to control your user interface logic.

js
import React, { useState } from 'react';
import { dinero, isZero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

import { format } from './utils';

function Cart() {
const [products] = useState([
{
name: 'Apple AirPods Pro',
price: dinero({ amount: 17495, currency: USD }),
},
{
name: 'Apple Stickers',
price: dinero({ amount: 0, currency: USD }),
},
]);

return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{products.map(({ name, price }) => (
<tr key={name}>
<td>{name}</td>
<td>{isZero(price) ? 'Complimentary' : format(price)}</td>
</tr>
))}
</tbody>
</table>
);
}

---

Core Concepts/Currency

---
title: Currency
description: Passing a currency to a new Dinero object.
---

Currency

The currency is one of the three pieces of domain data necessary to create a Dinero object.

A Dinero currency is composed of:

- A unique code.
- A base, or radix.
- An exponent.

Currency code

The currency code is a unique identifier for the currency. By convention, they're usually a three-letter or number. For example, in the case of national ISO 4217 currencies, the first two letters of the code are the two letters of the ISO 3166-1 alpha-2 country code, and the third is usually the initial of the currency itself.

js
// United States dollar
const USD = {
code: 'USD',
// ...
};

When they don't refer to a specific country (e.g., euro) or aren't a traditional currency (e.g., cryptocurrencies), the code can vary into a less standard but more mnemonic scheme. Ultimately, the code is your choice and needs to make sense in your application. The only requirement is for it to be unique.

Currency base

The currency base (or radix) is the number of unique digits used to represent a currency's minor unit. Most currencies in circulation are decimal, meaning their base is 10.

js
const USD = {
code: 'USD',
base: 10,
// ...
};

There are still non-decimal currencies in circulation, such as the Mauritanian ouguiya and the Malagasy ariary.

js
// Mauritanian ouguiya
const MRU = {
code: 'MRU',
base: 5,
// ...
};

Some currencies have multiple subdivisions. For example, before decimalization, the British pound sterling was divided into 20 shillings, and each shilling into 12 pence. You also have examples in fiction, like Harry Potter, where one Galleon is divided into 17 Sickles, and each Sickle into 29 Knuts.

To represent these currencies, you can specify each subdivision with an array.

js
// Pre-decimal Great Britain pound sterling
const GBP = {
code: 'GBP',
base: [20, 12],
exponent: 1,
};

// Great Britain wizarding currency (Harry Potter universe)
const GBW = {
code: 'GBW',
base: [17, 29],
exponent: 1,
};

::: info
When working with non-decimal currencies, you should set the exponent to 1.
:::

Currency exponent

The currency exponent expresses the decimal relationship between the currency and its minor unit. For example, there are 100 cents in a US dollar, being 10 to the power of 2, so the exponent for the US dollar is 2.

js
const USD = {
code: 'USD',
base: 10,
exponent: 2,
};

An easier way to think about it is as the number of digits after the decimal separator.

When a currency doesn't have minor currency units (e.g., the Japanese yen), the exponent should be 0. In this case, you can express the amount in major currency units.

js
// Japanese yen
const JPY = {
code: 'JPY',
base: 10,
exponent: 0,
};

When you pass a scale to a Dinero object, it overrides the exponent. This has an impact on how you should specify the amount.

Using built-in currencies

Dinero.js provides ISO 4217 currency objects out of the box via the dinero.js/currencies subpath export.

Once you've installed Dinero.js, you can import currencies:

js
import { dinero } from 'dinero.js';
import { USD, EUR } from 'dinero.js/currencies';

const d1 = dinero({ amount: 1000, currency: USD });
const d2 = dinero({ amount: 1000, currency: EUR });

If you're using the bigint variant, import currencies from dinero.js/bigint/currencies instead:

js
import { dinero } from 'dinero.js/bigint';
import { USD, EUR } from 'dinero.js/bigint/currencies';

const d1 = dinero({ amount: 1000n, currency: USD });
const d2 = dinero({ amount: 1000n, currency: EUR });

Dinero.js tracks the ISO 4217 standard and updates currencies when amendments are published. This means currencies can be added, removed, or have their properties changed (e.g., exponent, code) when you upgrade Dinero.js.

::: warning
Currency data may change between Dinero.js versions. If you need stability, pin your Dinero.js version in your package manager. You can also define your own currency objects for full control. If you look up currencies by code at runtime, always validate that the code exists. See How to look up a currency by code.
:::

Creating custom currencies

You can build your own currency object if it isn't available in dinero.js/currencies.

js
const FRF = {
code: 'FRF',
base: 10,
exponent: 2,
};

If you're a TypeScript user, you can implement the DineroCurrency type. It takes a generic parameter TAmount which represents the type you're using for numeric values (number by default).

ts
import type { DineroCurrency } from 'dinero.js';

const FRF: DineroCurrency<number> = {
code: 'FRF',
base: 10,
exponent: 2,
};

To opt into compile-time currency safety, use as const satisfies to preserve the literal type of the currency code:

ts
import type { DineroCurrency } from 'dinero.js';

const FRF = {
code: 'FRF',
base: 10,
exponent: 2,
} as const satisfies DineroCurrency<number, 'FRF'>;

This lets TypeScript catch currency mismatches (e.g., adding USD and EUR) at compile time. The built-in ISO 4217 currencies are already typed this way.

See also: Currency type safety, Precision and large numbers

---

Core Concepts/Formatting

---
title: Formatting
description: Formatting Dinero objects into rounded numbers or string representation.
---

Formatting

When working with money on the front end, there comes a time when you need to display amounts on the user interface. The Dinero.js API provides functions to format Dinero objects.

js
import { dinero, toUnits, down } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1055, currency: USD });

toUnits(d); // [10, 55]

Displaying an object

The toDecimal function exposes a pre-formatted amount in decimal format and the object's currency. It lets you display objects the way you want using a transformer function.

js
import { dinero, toDecimal, toUnits } from 'dinero.js';
import { USD, MGA } from 'dinero.js/currencies';

const d1 = dinero({ amount: 5000, currency: USD });
const d2 = dinero({ amount: 13, currency: MGA });

toDecimal(d1, ({ value, currency }) => ${currency.code} ${value}); // "USD 50.00"
toUnits(d1, ({ value }) => ${value[0]} dollars, ${value[1]} cents); // "50 dollars, 0 cents"

toUnits(d2, ({ value }) => ${value[0]} ariary, ${value[1]} iraimbilanja); // "2 ariary, 3 iraimbilanja"

Dinero.js uses the object's scale to determine how many decimal places to represent. You can adjust it in the transformer.

js
import { dinero, toDecimal, up } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const transformer = ({ value, currency }) => {
return ${currency.code} ${Number(value).toFixed(1)};
};

const d = dinero({ amount: 4545, currency: USD });

toDecimal(d, transformer); // "USD 45.5"

If you're formatting many objects, you might want to reuse the same transformer without having to pass it every time. To do so, you can write your own higher-order function to build formatters.

js
import { dinero, toDecimal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

// This function lets you pass a transformer and rounding options.
// It returns a function that takes a Dinero object and applies
// the closured transformer.
function createFormatter(transformer) {
return function formatter(dineroObject) {
return toDecimal(dineroObject, transformer);
};
}

// This function is reusable to format any Dinero object
// with the same transformer.
const format = createFormatter(
({ value, currency }) => ${currency.code} ${value}
);

const d = dinero({ amount: 5000, currency: USD });

format(d); // "USD 50.00"

See also:
- To decimal
- To units
- Formatting in a multilingual site
- Formatting non-decimal currencies

Retrieving raw data

One of the most convenient formatting functions in Dinero.js is toSnapshot. Its primary usage isn't the front end but to take snapshots of Dinero objects to inspect them.

Whenever you need to access a Dinero object's raw data, toSnapshot is the go-to function.

js
import { dinero, toSnapshot } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 5000, currency: USD });

toSnapshot(d);

// {
// amount: 5000,
// currency: {
// code: 'USD',
// base: 10,
// exponent: 2,
// },
// scale: 2,
// }

Another useful usage of toSnapshot is transport and storage. To do so, check the advanced guide on transporting and restoring.

---

Core Concepts/Mutations

---
title: Mutations
description: Mutating Dinero objects through mathematical operations.
---

Mutations

At the core of manipulating money are mutations. The Dinero.js API provides functions to manipulate objects. Most of them are arithmetic-based: adding, multiplying, etc.

js
import { dinero, add } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 800, currency: USD });

add(d1, d2);

Calculating new amounts

Any application that handles money needs to manipulate them. A classic example is a checkout page where you need to calculate the total, add shipping, subtract discounts, etc.

js
import { dinero, add, allocate, subtract } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const products = [
{
name: 'Apple iPhone 12',
price: dinero({ amount: 89900, currency: USD }),
},
{
name: 'Apple AirPods Pro',
price: dinero({ amount: 17495, currency: USD }),
},
];

const subtotal = products.reduce(
(acc, { price }) => add(acc, price),
dinero({ amount: 0, currency: USD })
);

const [discount] = allocate(subtotal, [20, 80]);
const discounted = subtract(subtotal, discount);

const shipping = dinero({ amount: 1000, currency: USD });

const total = add(discounted, shipping);

Dinero objects are immutable

Even though such functions can be categorized as "mutations", Dinero objects are immutable. When you're using a mutation function, the existing objects remain intact.

js
import { dinero, add, toSnapshot } from 'dinero.js';

// ...

toSnapshot(add(d1, d2));

// {
// amount: 1300,
// currency: {
// code: 'USD',
// base: 10,
// exponent: 2,
// },
// scale: 2,
// }

toSnapshot(d1);

// {
// amount: 500,
// currency: {
// code: 'USD',
// base: 10,
// exponent: 2,
// },
// scale: 2,
// }

toSnapshot(d2);

// {
// amount: 800,
// currency: {
// code: 'USD',
// base: 10,
// exponent: 2,
// },
// scale: 2,
// }

---

Core Concepts/Scale

---
title: Scale
description: Passing a scale to a new Dinero object.
---

Scale

The scale is one of the three pieces of domain data necessary to create a Dinero object. It's conceptually close to the currency exponent but serves the purpose of expressing precision as accurately as possible.

Most of the time, you don't need to specify the scale. It defaults to the currency exponent.

js
import { dinero, toSnapshot } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 5000, currency: USD });

const { exponent } = USD; // exponent is 2
const { scale } = toSnapshot(d); // scale is 2 (picked up USD.exponent)

This looks redundant. Why do we need a scale when we have the currency exponent?

While you may think of money as its value in major or minor currency units—value that one can actually pay—it often needs a more precise representation. A good example is when you factor in tax rates, which are often fractional values. For example, let's say you have an item that costs EUR 19.95 with a VAT rate of 5.5%: you end up with a final price of EUR 21.04725. This gets rounded when it's time to pay, but it's crucial to preserve the precision until the end of calculations, especially if you're performing many of them.

The scale is essential to accurately represent monetary values without losing precision. It automatically adapts as needed to ensure you always retain accurate amounts.

Here's what the 5.5% VAT rate calculation looks like with Dinero.js:

js
import { dinero, add, multiply, toSnapshot } from 'dinero.js';
import { EUR } from 'dinero.js/currencies';

const price = dinero({ amount: 1995, currency: EUR });
const tax = multiply(price, { amount: 55, scale: 3 });
const total = add(price, tax);

toSnapshot(total);

// {
// amount: 2104725,
// currency: {
// code: 'EUR',
// base: 10,
// exponent: 2,
// },
// scale: 5,
// }

The final Dinero object total has transparently adjusted to a scale of 5 to satisfy the need for extra precision. The amount of 2104725 can be interpreted as 21.04725 based on that scale instead of 21047.25 based on the currency exponent.

Note the usage of a scale when specifying the number by which to multiply. We want to calculate 5.5% of the price, or multiply it by 0.055 (5.5 / 100). We don't want to use floats, so instead, we're passing 55 with a scale of 3 (55 / 10^3 = 0.055).

When to specify a scale manually

Most of the time, you don't need to specify the scale. You can let Dinero.js pick it up from the currency exponent. However, there are times when you need to specify more precise amounts.

For example, imagine you're in the hardware business. You're likely not selling screws one by one but by kits instead. Let's say you sell kits of 250 for $8.75; you still might need to represent the price of a single screw for admin purposes. In this case, a screw costs $0.035, which can't be accurately represented with two digits, so you can manually pass a larger scale.

js
import { dinero, toSnapshot } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const price = dinero({ amount: 35, currency: USD, scale: 3 });

toSnapshot(price);

// {
// amount: 35,
// currency: {
// code: 'USD',
// base: 10,
// exponent: 2,
// },
// scale: 3,
// }

::: tip
When storing Dinero objects in a database, you typically only need to store the currency exponent. If you're working with custom scales, make sure to store the scale as well so you can accurately restore the object later.
:::

Calculate objects of different scales

When calculating Dinero objects, you don't have to care about their scale. Dinero.js automatically converts objects to the safest scale so you don't lose precision.

js
import { dinero, add, subtract, allocate } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 400, currency: USD });
const d2 = dinero({ amount: 104545, currency: USD, scale: 4 });

add(d1, d2); // a Dinero object with amount 144545 and scale 4

subtract(d2, d1); // a Dinero object with amount 64545 and scale 4

You might also need to use fractional values. For example, you may need to calculate 19.6% of a total cart, or convert a Dinero object to another currency with a 0.82 conversion rate.

In such cases, you shouldn't use floats, but scaled multipliers. For example, instead of 0.82, you should pass 82 and a scale of 2.

js
import { dinero, multiply, allocate } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 400, currency: USD });

multiply(d, { amount: 82, scale: 2 }); // a Dinero object with amount 32800 and scale 4

const [d1, d2] = allocate(d1, [505, 495], { scale: 1 }); // translates to ratios 50.5 and 49.5

d1; // a Dinero object with amount 2020 and scale 3
d2; // a Dinero object with amount 1980 and scale 3

Trimming scale

When calculating Dinero objects of different scales, Dinero.js goes for the safest one to avoid losing precision. This means you can end up with a higher scale than necessary.

In the previous example, both output objects have a trailing zero, meaning they could be adjusted to one order of magnitude down with a smaller scale. While using high scales isn't a problem per se, it does take more space, and can end up reaching the minimum or maximum safe IEEE 754 integer.

In such cases, you can trim down Dinero objects to drop useless precision.

js
import { dinero, add, trimScale } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 100, currency: USD });
const d2 = dinero({ amount: 2000000, currency: USD, scale: 6 });

const d3 = add(d1, d2); // a Dinero object with amount 3000000 and scale 6

trimScale(d3); // a Dinero object with amount 300 and scale 2

::: info
The trimScale function trims Dinero objects down to the smallest, safest possible scale, down to the currency exponent at most.
:::

---

Faq/Can I Multiply By A Decimal

---
title: Can I multiply by a decimal?
description: How to multiply Dinero objects by decimal values like 0.5 using scaled amounts.
---

Can I multiply by a decimal?

You can pass a decimal like 0.5 to multiply, but it will throw an error if the result isn't an integer.

js
import { dinero, multiply } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 1000, currency: USD }); // $10.00
multiply(d1, 0.5); // Works (1000 * 0.5 = 500)

const d2 = dinero({ amount: 1001, currency: USD }); // $10.01
multiply(d2, 0.5); // Throws (1001 * 0.5 = 500.5)

Dinero.js uses integer arithmetic to avoid floating-point precision issues. When you multiply by a decimal and the result isn't an integer, validation fails.

Using scaled amounts

The safe way to multiply by non-integers is to use a scaled amount. Instead of 0.5, pass { amount: 5, scale: 1 } (5 at scale 1 = 5/10 = 0.5):

js
import { dinero, multiply, toSnapshot } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1001, currency: USD }); // $10.01

const result = multiply(d, { amount: 5, scale: 1 }); // $5.005

toSnapshot(result); // { amount: 5005, currency: USD, scale: 3 }

The result's scale increases to preserve precision. This keeps all values as integers throughout the calculation.

::: tip
For percentages, the pattern is the same. To calculate 15% of an amount:

js
multiply(d, { amount: 15, scale: 2 }); // 15 at scale 2 = 0.15

:::

See the Calculating percentages guide for more examples.

---

Faq/How To Look Up A Currency By Code

---
title: How to look up a currency by code
description: How to retrieve a currency object from a string code like "USD".
---

How to look up a currency by code

If you receive currency codes as strings (e.g., from an API or database), you can look up the corresponding currency object using a namespace import.

ts
import * as currencies from 'dinero.js/currencies';

function getCurrency(code: string) {
if (!(code in currencies)) {
throw new Error(Unknown currency code: ${code});
}

return currencies[code as keyof typeof currencies];
}

Since Dinero.js tracks the latest ISO 4217 standard, currency codes can be added or removed between versions. Always validate codes at runtime, especially if they come from stored data. See Using built-in currencies for more details.

ts
import { dinero } from 'dinero.js';

const code = 'USD';
const currency = getCurrency(code);
const price = dinero({ amount: 5000, currency });

This also works with bigint currencies:

ts
import * as currencies from 'dinero.js/bigint/currencies';

function getCurrency(code: string) {
if (!(code in currencies)) {
throw new Error(Unknown currency code: ${code});
}

return currencies[code as keyof typeof currencies];
}

---

Faq/Why Cant I Use Currencies With Bigint

---
title: Why can't I use currencies with bigint?
description: Why currencies from dinero.js/currencies don't work with bigint and how to use dinero.js/bigint/currencies instead.
---

Why can't I use currencies with bigint?

Currencies from dinero.js/currencies have number values for base and exponent:

js
// From dinero.js/currencies
const USD = { code: 'USD', base: 10, exponent: 2 };

When using dinero.js/bigint, all arithmetic operations use bigint math. JavaScript doesn't allow mixing number and bigint in operations—it throws a TypeError:

js
10n + 2  // TypeError: can't convert BigInt to number

This is a JavaScript language constraint. To use the bigint variant, import currencies from dinero.js/bigint/currencies instead:

js
import { dinero } from 'dinero.js/bigint';
import { USD } from 'dinero.js/bigint/currencies';

const d = dinero({ amount: 500n, currency: USD });

These currencies have bigint values for base and exponent:

js
// From dinero.js/bigint/currencies
const USD = { code: 'USD', base: 10n, exponent: 2n };

See the Precision and large numbers guide for more on when to use bigint.

---

Faq/Why Functions Instead Of Methods

---
title: Why functions instead of methods?
description: Why Dinero.js uses standalone functions instead of chainable methods.
---

Why functions instead of methods?

Dinero.js uses standalone functions:

js
add(d1, d2);

Instead of chainable methods:

js
d1.add(d2);

The primary reason is modularity. With standalone functions, bundlers can eliminate unused code. With methods, every Dinero object would carry every operation on its prototype, including the ones you never use.

Composition

Standalone functions compose well with functional utilities:

js
import { pipe } from 'ramda';

pipe(
(d) => multiply(d, 2),
(d) => add(d, fee),
(d) => toDecimal(d),
)(price);

Custom chaining

Nesting can get verbose and hard to understand when inlining:

js
// Multiplies, then adds, but looks like the opposite
add(multiply(d1, 2), d2);

If you prefer chaining, you can create your own wrapper:

js
function chain(d) {
return {
multiply: (n) => chain(multiply(d, n)),
add: (other) => chain(add(d, other)),
};
}

chain(d1).multiply(2).add(d2);

For most use cases, the functional style works well and keeps your bundle small.

---

Faq/Why No Currency Formatting

---
title: Why doesn't Dinero format with currency symbols?
description: Why Dinero.js doesn't format amounts with currency symbols and how to do it yourself.
---

Why doesn't Dinero format with currency symbols?

The toDecimal function returns a plain decimal string like "10.50", not "$10.50" or "10,50 €". Dinero.js delegates locale-aware formatting to you because there's no universal default that works for everyone.

Currency formatting varies significantly across locales:

- en-US: $10.50
- fr-FR: 10,50 $US
- fr-CA: 10,50 $ US
- de-DE: 10,50 $

Even within the same locale, preferences vary: some users prefer USD 10.50 over $10.50, some applications need 10.50 USD for data exports. The library can't make these decisions for you.

Formatting with Intl.NumberFormat

Use toDecimal to get the numeric value, then format with Intl.NumberFormat:

ts
import { dinero, toDecimal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1050, currency: USD });

toDecimal(d, ({ value, currency }) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency.code,
}).format(value);
}); // "$10.50"

This lets you choose the locale and currency display style. For more control, you can build your own formatting logic on top of toDecimal.

See the Multilingual support guide for reusable formatting patterns.

---

Getting Started/Compatibility

---
title: Compatibility
description: Understand which browsers and Node.js versions Dinero.js supports and how to manage polyfills.
---

Compatibility

Browser support

Dinero.js supports all modern browsers (Chrome, Edge, Firefox, and Safari).

::: info
Internet Explorer is no longer supported. Microsoft ended IE11 support in June 2022.
:::

Node.js

Dinero.js runs on any active or maintenance LTS version of Node.js.

---

Getting Started/Optimizing For Production

---
title: Optimizing for production
description: Tips for reducing bundle size and improving performance.
---

Optimizing for production

Tree-shake your code

Tree-shaking lets you bundle only the code you're using and eliminate the rest. For example, if you're only using Dinero.js to add and subtract monetary values, only dinero, add, subtract, and their dependencies should be in your final bundle.

Dinero.js is a pure library, meaning it doesn't produce side-effects. If you're using a modern build system, you can tree-shake it. To do so, make sure to import only the functions you need, and enable tree-shaking in your bundler configuration if necessary.

js
import { dinero, add, subtract } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

// Only these functions end up in your bundle

Resources:
- Tree Shaking
- Scope Hoisting
- Building for Production

Compress your assets

If you're using the UMD build without a bundler, make sure to compress it before you serve it in production.

If you're importing Dinero.js via a CDN such as jsDelivr or cdnjs, you should get Gzip or Brotli compression out of the box. If you're hosting your own, make sure to use the production build and to compress it either manually or using an edge server like Cloudflare or Cloudfront.

Resources:
- Content delivery network
- Gzip
- Brotli

---

Getting Started/Quick Start

---
title: Quick start
description: Learn how to get Dinero.js up and running in your project.
---

Quick start

Install the library

To get started, you need to install the dinero.js package.

sh
npm install dinero.js

or

yarn add dinero.js

Then import it in your project:

js
import { dinero, add } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

If you don't use a package manager, you can use the HTML script element:

html
<script src="https://cdn.jsdelivr.net/npm/dinero.js/dist/umd/index.production.js"></script>
<script>
const { dinero, add, USD } = window.dinerojs;
</script>

First steps

Dinero.js lets you express monetary values in JavaScript. You can perform mutations, conversions, comparisons, format them extensively, and overall make money manipulation in your application easier and safer.

To get started, you need to create a new Dinero object. Amounts are specified in minor currency units (like "cents" for the dollar) and currencies in DineroCurrency objects.

This represents $50:

js
const price = dinero({ amount: 5000, currency: USD });

You can add or subtract any amount you want, by passing it another Dinero object:

js
import { dinero, add, subtract } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const price = dinero({ amount: 5000, currency: USD });

// returns a Dinero object with amount 6000
add(price, dinero({ amount: 1000, currency: USD }));

// returns a Dinero object with amount 4000
subtract(price, dinero({ amount: 1000, currency: USD }));

Dinero objects are immutable, meaning you always get a new Dinero object when performing transformations. Your original objects remain untouched.

js
price; // still returns a Dinero object with amount 5000

You can ask all kinds of questions to your Dinero objects.

js
import { dinero, equal, isZero, hasSubUnits } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 500, currency: USD });
equal(d1, d2); // returns true

const d3 = dinero({ amount: 100, currency: USD });
isZero(d3); // returns false

const d4 = dinero({ amount: 1150, currency: USD });
hasSubUnits(d4); // returns true

Dinero.js provides formatting functions that expose a pre-formatted amount. You can use them as-is, or pass a custom transformer function to further customize the output.

js
import { dinero, toDecimal, toUnits } from 'dinero.js';
import { USD, MGA } from 'dinero.js/currencies';

const d1 = dinero({ amount: 5000, currency: USD });
const d2 = dinero({ amount: 13, currency: MGA });

toDecimal(d1); // "50.00"
toDecimal(d1, ({ value, currency }) => ${currency.code} ${value}); // "USD 50.00"
toUnits(d2, ({ value }) => ${value[0]} ariary, ${value[1]} iraimbilanja); // "2 ariary, 3 iraimbilanja"

Dinero objects pick up their scale from their currency exponent. If you want to represent amounts differently, you can specify a scale manually.

This represents $5:

js
const price = dinero({ amount: 5000, currency: USD, scale: 3 });

This is only a preview of what you can do. Dinero.js provides extensive documentation with examples and guides.

Available exports

Dinero.js provides four entry points:

| Import path | Description |
|-------------|-------------|
| dinero.js | Core functions with number amounts (default) |
| dinero.js/currencies | ISO 4217 currency definitions for number |
| dinero.js/bigint/currencies | ISO 4217 currency definitions for bigint |
| dinero.js/bigint | Core functions with bigint amounts |

js
// Standard usage
import { dinero, add, subtract } from 'dinero.js';
import { USD, EUR } from 'dinero.js/currencies';

// For large amounts (bigint)
import { dinero } from 'dinero.js/bigint';
import { USD, EUR } from 'dinero.js/bigint/currencies';

::: info
Dinero.js requires Node.js 14+ with ES modules. Use import, not require().
:::

Agent skills

If you use an AI coding agent (Claude Code, Cursor, GitHub Copilot, etc.), you can install the Dinero.js skills to teach it best practices and common pitfalls.

sh
npx skills add dinerojs/skills

---

Getting Started/Upgrade Guide

---
title: Upgrade guide
description: Upgrading from Dinero.js v1.x to v2.0.
---

Upgrade guide

Migrating from v2 alpha

If you're using Dinero.js v2 alpha with the separate @dinero.js/* packages, you need to update your imports to use the new consolidated package structure.

Update currency imports

diff
- import { USD, EUR } from '@dinero.js/currencies';
+ import { USD, EUR } from 'dinero.js/currencies';

Update bigint imports

diff
- import { calculator } from '@dinero.js/calculator-bigint';
- import { createDinero } from '@dinero.js/core';
+ import { calculator, createDinero } from 'dinero.js/bigint';

Or simply use the pre-configured dinero function:

js
import { dinero } from 'dinero.js/bigint';

const d = dinero({ amount: 1000n, currency: USD });

Remove deprecated packages

You can remove the separate packages from your dependencies:

diff
"dependencies": {
- "@dinero.js/core": "...",
- "@dinero.js/currencies": "...",
- "@dinero.js/calculator-number": "...",
- "@dinero.js/calculator-bigint": "...",
"dinero.js": "..."
}

The dinero.js package now includes everything.

Upgrading from v1.x

The Dinero function is now lowercase

The Dinero function is not a constructor, so by convention, it shouldn't be capitalized. The function is now dinero so there's no confusion on whether you should call it with new or not (you shouldn't). No longer need to disable ESLint's new-cap rule.

diff
- import Dinero from 'dinero.js';
+ import { dinero } from 'dinero.js';

Currency is now an object

The currency is now expressed as a currency object and no longer as a string. v2 provides ISO 4217 currency objects out of the box via the dinero.js/currencies subpath.

diff
- Dinero({ amount: 500, currency: 'USD' });
+ import { USD } from 'dinero.js/currencies';
+ dinero({ amount: 500, currency: USD });

See also: Currency

Precision is now scale

The concept of precision from v1.x is now called scale. It works the same as before.

diff
- Dinero({ amount: 5000, currency: 'USD', precision: 3 });
+ dinero({ amount: 5000, currency: USD, scale: 3 });

See also: Scale

Replace chainable methods with standalone functions

Methods are no longer chainable, allowing you to get rid of unused code with tree-shaking. Instead of calling methods on Dinero objects, you can import individual functions and pass Dinero objects to it.

Former methods and new functions don't all have the same signature. Refer to the correlation tables below and the API reference for each function.

#### Access

| Dinero v1.x | Dinero v2 |
|---------------------|----------------------------------------------------------------------------------------------|
| d1.getAmount() | Dropped, see replacement. |
| d1.getCurrency() | Dropped, see replacement. |
| d1.getPrecision() | Dropped, see replacement. |
| d1.getLocale() | Dropped. |

#### Mutations

| Dinero v1.x | Dinero v2 |
|--------------------------|----------------------------------------------------------------------------------------------------|
| d1.add(d2) | add(d1, d2) |
| d1.subtract(d2) | subtract(d1, d2) |
| d1.multiply(...args) | multiply(d1, ...args) |
| d1.allocate(...args) | allocate(d1, ...args) |
| d1.divide(...args) | Dropped, see replacement. |
| d1.percentage(...args) | Dropped, see replacement. |
| d1.setLocale(...args) | Dropped. |

#### Conversions

| Dinero v1.x | Dinero v2 |
|---------------------------------------|------------------------------------------------------------------------|
| d1.convert(...args) | convert(d1, ...args) |
| Dinero.normalizePrecision([d1, d2]) | [normalizeScale([d1, d2])](/api/conversions/normalize-scale) |
| d1.convertPrecision(...args) | transformScale(d1, ...args) |

#### Comparisons

| Dinero v1.x | Dinero v2 |
|-----------------------------|-----------------------------------------------------------------------------|
| d1.equalsTo(d2) | equal(d1, d2) |
| d1.greaterThan(d2) | greaterThan(d1, d2) |
| d1.greaterThanOrEqual(d2) | greaterThanOrEqual(d1, d2) |
| d1.lessThan(d2) | lessThan(d1, d2) |
| d1.lessThanOrEqual(d2) | lessThanOrEqual(d1, d2) |
| Dinero.minimum([d1, d2]) | [minimum([d1, d2])](/api/comparisons/minimum) |
| Dinero.maximum([d1, d2]) | [maximum([d1, d2])](/api/comparisons/maximum) |
| d1.isZero() | isZero(d1) |
| d1.isPositive() | isPositive(d1) |
| d1.isNegative() | isNegative(d1) |
| d1.hasSameAmount(d2) | [haveSameAmount([d1, d2])](/api/comparisons/have-same-amount) |
| d1.hasSameCurrency(d2) | [haveSameCurrency([d1, d2])](/api/comparisons/have-same-currency) |
| d1.hasSubUnits() | hasSubUnits(d1) |

#### Formatting

| Dinero v1.x | Dinero v2 |
|-----------------------------|----------------------------------------------------------------------------------------|
| d1.toFormat(format) | Dropped, see replacement |
| d1.toObject() | toSnapshot(d1) |
| d1.toUnit(...args) | Dropped, see replacement |
| d1.toRoundedUnit(...args) | Dropped, see replacement |

Replace floats with scaled amounts

In v1.x, methods like convert, multiply, or allocate used to accept floats for rates, factors or ratios. It then rounded the result before creating new objects, resulting is precision loss.

In v2, you should use scaled amounts instead. Scaled amounts represent a numeric value using an integer, and a scale that represents the position of the decimal point. For example, instead of passing 0.89, you would pass 89 with a scale of 2.

js
const scaled = { amount: 89, scale: 2 };

To use fractional values, pass scaled amounts instead of integers.

#### Convert

js
import { dinero, convert } from 'dinero.js';
import { USD, EUR } from 'dinero.js/currencies';

const rates = { EUR: { amount: 89, scale: 2 } }; // 0.89
const d = dinero({ amount: 500, currency: USD });

convert(d, EUR, { rates });

#### Multiply

js
import { dinero, multiply } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const multiplier = { amount: 2001, scale: 3 }; // 2.001
const d = dinero({ amount: 401, currency: USD });

multiply(d, multiplier);

#### Allocate

js
import { dinero, allocate } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const ratios = [
{ amount: 505, scale: 1 }, // 50.5
{ amount: 495, scale: 1 }, // 49.5
];
const d = dinero({ amount: 100, currency: USD });

allocate(d, ratios);

See also:
- Convert
- Multiply
- Allocate

Replace getAmount, getCurrency and getPrecision with toSnapshot

The getAmount, getCurrency, and getPrecision methods have been replaced with toSnapshot, which returns a plain object with the amount, currency and scale (formerly known as precision).

diff
- const amount = Dinero({ amount: 500, currency: 'USD' }).getAmount();
- const currency = Dinero({ amount: 500, currency: 'USD' }).getCurrency();
- const scale = Dinero({ amount: 500, currency: 'USD' }).getPrecision();
+ const { amount, scale, currency } = toSnapshot(
+ dinero({ amount: 500, currency: USD })
+ );

See also: To snapshot

Replace divide with allocate

Dinero.js v2 no longer has a built-in divide function. Use allocate instead.

See also: Allocate

Replace percentage with allocate or multiply

Dinero.js v2 no longer has a built-in percentage function. You can build your own using either allocate or multiply.

See also: How do I calculate a percentage?

Replace toUnit and toRoundedUnit with toUnits or toDecimal

Dinero.js v2 no longer has a built-in toUnit and toRoundedUnit functions. Use toUnits or toDecimal instead.

See also:
- To units
- To decimal

Dropped support for locale

In v1.x, object formatting relied upon the Internationalization API. You could pass a locale to each Dinero object to control how to format it. In v2, formatting is dependency-free and provides you full control. You no longer need to rely on a locale, therefore this concept is gone.

To replicate the same formatting you had in v1.x, you can create a formatter that wraps around the Internationalization API.

js
import { toDecimal } from 'dinero.js';

function createIntlFormatter(locale, options = {}) {
function transformer({ value, currency }) {
return Number(value).toLocaleString(locale, {
...options,
style: 'currency',
currency: currency.code,
});
}

return function formatter(dineroObject) {
return toDecimal(dineroObject, transformer);
};
}

export const intlFormat = createIntlFormatter('en-US');

You can then pass any Dinero object to the returned function.

js
import { dinero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 500, currency: USD });

intlFormat(d); // "$5.00"

See also: To decimal

Dropped support for globals

Dinero.js v2 no longer supports global default and settings. The entire library is side-effects free, and every object needs explicit parameters.

If you need defaults to create objects faster, you can create your own higher-order functions to partially apply Dinero objects. For example, you can write a function to creates US dollar Dinero objects.

js
import { dinero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

function dineroUSD(amount) {
return dinero({ amount, currency: USD });
}

Then, you can create objects by just passing the amount.

js
const d = dineroUSD(500);

---

Guides/Calculating Percentages

---
title: Calculating percentages
description: How to create a Dinero object that represents a percentage of another.
---

Calculating percentages

There are two ways to calculate a percentage with Dinero.js: using allocate or multiply.

For example, if you need to calculate 15% of a Dinero object, you can split it with allocate.

js
import { dinero, allocate } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const price = dinero({ amount: 5000, currency: USD });

const [tax] = allocate(price, [15, 85]);

You can do the same with multiply.

js
import { dinero, multiply } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const price = dinero({ amount: 5000, currency: USD });

const tax = multiply(price, { amount: 15, scale: 2 });

If you need this often, you can abstract it into your own percentage function.

js
function percentage(dineroObject, share, scale = 0) {
const power = scale + 1;
const rest = 100 power - share;
const [chunk] = allocate(dineroObject, [share, rest], { scale });

return chunk;
}

---

Guides/Creating From Floats

---
title: Creating from floats
description: How to instantiate Dinero objects with float inputs using your own factory.
---

Creating from floats

Dinero objects must be instantiated with integers, in minor currency units. For example, to create an object for $19.99, you should write the following code:

js
import { dinero, add, subtract } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1999, currency: USD });

If you have amounts as floats (in this case, 19.99) and you want to abstract object creation, you can write your own helper.

js
function dineroFromFloat({ amount: float, currency, scale }) {
const factor = currency.base (scale ?? currency.exponent);
const amount = Math.round(float * factor);

return dinero({ amount, currency, scale });
}

::: info
This code isn't tested and not guaranteed to cover edge cases. Use it as a starter and make sure it works for you by testing it in your application.
:::

---

Guides/Cryptocurrencies

---
title: Cryptocurrency support
description: How to create Dinero objects for cryptocurrencies like Bitcoin, Ethereum, and others.
---

Cryptocurrency support

Dinero.js works with cryptocurrencies like any other currency, as long as they implement the DineroCurrency type.

When working with these, you should use bigint or a third-party library like big.js. Cryptos usually have high exponents, making them likely to exceed the range of safe JavaScript integers.

See also: Precision and large numbers

The dinero.js/currencies subpath doesn't provide ready-made implementations for cryptocurrencies due to their non-normative and unstable nature. Maintaining such a list would be too demanding, so it makes more sense to keep them in userland. If you want to write a Dinero.js-compatible cryptocurrency, you can implement the DineroCurrency type.

::: warning
Be careful how you name your files. Crypto mining scripts often use the unofficial ISO 4217 code of the currency they're mining, like xbt.js or xmr.js. Adblockers then flag these scripts by name, causing them not to load. Make sure not to use suspicious file names, especially if you don't bundle your code, or they might not load for users with adblockers.
:::

---

Guides/Currency Type Safety

---
title: Currency type safety
description: Catch currency mismatches at compile time with TypeScript.
---

Currency type safety

If you're using TypeScript, Dinero.js can catch currency mismatches at compile time. When you use the built-in ISO 4217 currencies, operations like add, subtract, or equal will reject Dinero objects of different currencies before your code even runs.

How it works

Every Dinero object carries a TCurrency type parameter that represents its currency code as a string literal type. When you use a built-in currency like USD, the Dinero object is typed as Dinero<number, 'USD'>. Operations that require the same currency enforce this at the type level.

ts
import { dinero, add } from 'dinero.js';
import { USD, EUR } from 'dinero.js/currencies';

const d1 = dinero({ amount: 500, currency: USD }); // Dinero<number, 'USD'>
const d2 = dinero({ amount: 100, currency: USD }); // Dinero<number, 'USD'>
const d3 = dinero({ amount: 100, currency: EUR }); // Dinero<number, 'EUR'>

add(d1, d2); // OK
add(d1, d3); // Type error: 'EUR' is not assignable to 'USD'

This applies to all operations that expect the same currency: add, subtract, equal, compare, greaterThan, greaterThanOrEqual, lessThan, lessThanOrEqual, minimum, maximum, haveSameAmount, and normalizeScale.

Preserved through operations

The currency type is preserved through unary operations. When you multiply, allocate, trimScale, or transformScale a Dinero object, the result keeps the same currency type.

ts
import { dinero, add, multiply, allocate } from 'dinero.js';
import { USD, EUR } from 'dinero.js/currencies';

const price = dinero({ amount: 1000, currency: USD });

const doubled = multiply(price, 2); // Dinero<number, 'USD'>
add(doubled, price); // OK
add(doubled, dinero({ amount: 100, currency: EUR })); // Type error

const [half1, half2] = allocate(price, [50, 50]); // Dinero<number, 'USD'>[]
add(half1, price); // OK

Currency conversion

When you convert a Dinero object, the result takes the type of the target currency.

ts
import { dinero, add, convert } from 'dinero.js';
import { USD, EUR } from 'dinero.js/currencies';

const d = dinero({ amount: 500, currency: USD }); // Dinero<number, 'USD'>

const rates = { EUR: { amount: 89, scale: 2 } };
const converted = convert(d, EUR, rates); // Dinero<number, 'EUR'>

add(converted, dinero({ amount: 100, currency: EUR })); // OK
add(converted, d); // Type error: 'USD' is not assignable to 'EUR'

Typed snapshots and formatters

The currency type flows through to snapshots and formatter callbacks.

ts
import { dinero, toSnapshot, toDecimal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const d = dinero({ amount: 1050, currency: USD });

const snapshot = toSnapshot(d);
snapshot.currency.code; // type is 'USD', not string

toDecimal(d, ({ currency }) => {
currency.code; // type is 'USD', not string
return ${currency.code} ...;
});

Custom currencies

If you define custom currencies, you can opt into currency type safety by using as const satisfies:

ts
import type { DineroCurrency } from 'dinero.js';

const BTC = {
code: 'BTC',
base: 10,
exponent: 8,
} as const satisfies DineroCurrency<number, 'BTC'>;

The as const gives the code field the literal type 'BTC' instead of string, and satisfies validates the object conforms to the DineroCurrency shape.

Without as const, the currency code is inferred as string, and Dinero objects using it won't enforce currency matching. This is intentional: it keeps Dinero.js backward compatible and lets you opt into stricter checking only when you want it.

Backward compatibility

The TCurrency type parameter defaults to string. Existing code that doesn't use typed currencies continues to work without changes.

ts
// These are both Dinero<number, string> — no type enforcement
const currency = { code: 'USD', base: 10, exponent: 2 };
const d1 = dinero({ amount: 500, currency });
const d2 = dinero({ amount: 100, currency });
add(d1, d2); // OK — both are string-typed

Runtime currency checks (haveSameCurrency assertions) remain active regardless of typing, so JavaScript users and defensive programming patterns still work.

---

Guides/Formatting In A Multilingual Site

---
title: Formatting in a multilingual site
description: Displaying currencies in a site or application that supports several languages.
---

Formatting in a multilingual site

Different languages and locations can have radically different formatting styles when it comes to money. For example, ten U.S. dollars in American English should be written down "$10.00". However, in Canadian French, the same amount would be "10,00 $ US".

Dinero.js provides formatting functions that give you full control over how to format a Dinero object.

Building a custom Internationalization formatter

ECMAScript provides an Internationalization API (Intl) that lets you natively format monetary values into a given language by passing a locale. You can create your own Intl formatter by wrapping toDecimal.

js
import { dinero, toDecimal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

function intlFormat(dineroObject, locale, options = {}) {
function transformer({ value, currency }) {
return Number(value).toLocaleString(locale, {
...options,
style: 'currency',
currency: currency.code,
});
}

return toDecimal(dineroObject, transformer);
};

const d = dinero({ amount: 1000, currency: USD });

intlFormat(d, 'en-US'); // "$10.00"
intlFormat(d, 'fr-CA'); // "10,00 $ US"

::: info
The Internationalization API is well-supported in modern browsers and Node.js. For full locale data in Node.js, make sure to use a build with full ICU support.
:::

Using the custom formatter

You can use the formatter to display monetary values differently according to the current language of your site or app. For example, a React implementation could look like the following.

jsx
import React from 'react';
import { dinero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

import { intlFormat } from './intlFormat';

const languages = [
{
label: 'English (U.S.)',
locale: 'en-US',
},
{
label: 'Français (Canada)',
locale: 'fr-CA',
},
];

function App() {
const [defaultLanguage] = languages;
const [language, setLanguage] = React.useState(defaultLanguage);

const price = dinero({ amount: 1000, currency: USD });

return (
<>
<select
value={language.locale}
onChange={(event) =>
setLanguage(languages.find(({ locale }) => locale === event.target.value))
}
>
{languages.map(({ label, locale }) => (
<option key={locale} value={locale}>
{label}
</option>
))}
</select>
<p>Price: {intlFormat(price, language.locale)}</p>
</>
);
}

---

Guides/Formatting Non Decimal Currencies

---
title: Formatting non-decimal currencies
description: Displaying non-decimal currencies and currencies with multiple subdivisions.
---

Formatting non-decimal currencies

The great majority of circulating currencies are decimal. If you're working with those, the Dinero.js formatting utility should cover most of your use cases.

However, you might also work with non-decimal currencies. Typical use cases are ancient currencies such as the ancient Greek drachma, or fictional currencies like the wizarding currencies in the Harry Potter universe. If you're building a numismatic site or a game with its own currency, you might have advanced formatting needs.

Handling currencies with a single subdivision

Out of the box, you can format any non-decimal Dinero object using toUnits.

js
import { dinero, toUnits } from 'dinero.js';
import pluralize from 'pluralize';

const labels = ['drachma', 'obol'];

function transformer({ value, currency }) {
return value
.filter((amount) => amount > 0)
.map((amount, index) => ${amount} ${pluralize(labels[index], amount)})
.join(', ');
}

const d = dinero({
amount: 9,
currency: {
code: 'GRD',
base: 6,
exponent: 1,
},
});

toUnits(d, transformer); // "1 drachma, 3 obols"

Handling currencies with multiple subdivisions

While most circulating currencies have a single minor currency unit, many ancient currencies have multiple subdivisions. That's the case for most pre-decimalization European currencies such as the livre tournois in the French Old Regime or the pound sterling in Great Britain before 1971. That's also the case of some fictional currencies.

When working with such currencies, you can specify each subdivision with an array.

For example, let's say you're building a Candy Crush clone where users can buy bonuses with an in-game currency: donuts, cookies, and lollipops. In your game, a donut equals 30 cookies, and a cookie equals 16 lollipops. If a bonus costs 720 lollipops, you might want to format it as "1 donut and 15 cookies".

js
import { dinero, toUnits } from 'dinero.js';

const POP = {
code: 'POP',
base: [30, 16],
exponent: 1,
};

const labels = ['donut', 'cookie', 'lollipop'];

function transformer({ value }) {
return value
.filter((amount) => amount > 0)
.map((amount, index) => ${amount} ${amount > 1 ? ${labels[index]}s : labels[index]})
.join(' and ');
}

const d = dinero({ amount: 720, currency: POP });

toUnits(d, transformer); // "1 donut and 15 cookies"

---

Guides/Integrating With Payment Services

---
title: Integrating with payment services
description: How to integrate Dinero.js with payment services like Stripe, Adyen, or Square.
---

Integrating with payment services

One of the most common use cases when manipulating money is payment. Many services such as Stripe helps you process orders and payments programmatically.

Such solutions integrate well with Dinero.js. If you're building an application that manipulates and charges money, you can use Dinero objects to represent prices and write small connectors for your payment service. Most payment services represent money in minor units, making it straightforward to turn a Dinero object into a payment.

::: info
The following code is purely illustrative. Make sure to test it out in your application.
:::

Integrating with Stripe

The Stripe payment platform provides APIs to process payments and manage orders. Like many other platforms, it expects money representations with an amount in minor currency units, and a currency as an ISO 4217 currency code.

When using Stripe's Node.js client, the currency must be in lowercase.

js
import stripe from 'stripe';
import { dinero, toSnapshot } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

function toStripeMoney(dineroObject) {
const { amount, currency } = toSnapshot(dineroObject);

return { amount, currency: currency.code.toLowerCase() };
}

// ... Stripe client setup

const price = dinero({ amount: 2000, currency: USD });

const response = await client.charges.create({
// ...
...toStripeMoney(price),
});

Integrating with Paypal

The Paypal payment platform provides APIs to process payments and manage orders. Unlike most platforms, it expects a string representation with an amount in major currency units. You can use toDecimal to format the object and pass this value to Paypal.

js
const paypal = require('@paypal/checkout-server-sdk');
const { dinero, toSnapshot, toDecimal } = require('dinero.js');
const { USD } = require('dinero.js/currencies');

function toPaypalMoney(dineroObject) {
const { currency, scale } = toSnapshot(dineroObject);

return {
value: toDecimal(dineroObject),
currency_code: currency.code,
};
}

const price = dinero({ amount: 2000, currency: USD });

let request = new paypal.orders.OrdersCreateRequest();
request.requestBody({
// ...
purchase_units: [
{
amount: toPaypalMoney(price),
},
],
});

Integrating with Adyen

The Adyen payment platform provides APIs to process payments and manage orders. Like many other platforms, it expects money representations with an amount in minor currency units and a currency as an ISO 4217 currency code.

js
import { Client, Config, CheckoutAPI } from '@adyen/api-library';
import { dinero, toSnapshot } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

function toAdyenMoney(dineroObject) {
const { amount, currency } = toSnapshot(dineroObject);

return { value: amount, currency: currency.code };
};

// ... Adyen client setup

const price = dinero({ amount: 2000, currency: USD });

const response = await checkout.paymentMethods({
// ...
amount: toAdyenMoney(price),
});

Integrating with Square

The Square digital payment platform provides APIs to process payments and manage orders. Like many other platforms, it expects money representations with an amount in minor currency units and a currency as an ISO 4217 currency code.

When using Square's Node.js client, the amount must be of type bigint. If you're using Dinero.js with the number calculator (default behavior), you can cast the amount into a bigint when transforming your Dinero object into a Square Money object. Otherwise, if you're using Dinero with the bigint calculator, you can pass the amount directly.

js
import { Client } from 'square';
import { dinero, toSnapshot } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

function toSquareMoney(dineroObject) {
const { amount, currency } = toSnapshot(dineroObject);

return { amount: BigInt(amount), currency: currency.code };
}

// ... Square client setup

const price = dinero({ amount: 2000, currency: USD });

const response = await client.paymentsApi.createPayment({
// ...
amountMoney: toSquareMoney(price),
});

---

Guides/Precision And Large Numbers

---
title: Precision and large numbers
description: Using Dinero.js with bigint or third-party arbitrary-precision libraries for large amounts or high-precision currencies.
---

Precision and large numbers

Dinero expects amounts as number by default. In most cases, this is more than enough, but there are times when you might hit the limitations of the biggest and smallest numbers you can safely represent.

A typical use case is when you need to represent colossal amounts of money. Take the world debt, which reached $258 trillion in 2020. In JavaScript, the biggest number you can accurately represent is 9007199254740991 (9 quadrillions and some spare change). Still, since Dinero requires you to pass amounts in minor currency units, you actually "lose" two orders of magnitude, and can only represent around $90 trillion.

js
import { dinero } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

// Don't do this!
// 25800000000000000 is too big for accurate representation
// in IEEE 754 numbers.
const price = dinero({ amount: 25800000000000000, currency: USD });

Another example is when you need to represent cryptocurrencies, which typically have high exponents. In 2021, the Ether can be subdivided down to 18 fraction digits, meaning you can't even represent 1 ETH with the number type.

js
import { dinero } from 'dinero.js';

const ETH = {
code: 'ETH',
base: 10,
exponent: 18,
};

// Don't do this!
// 1000000000000000000 is too big for accurate representation
// in IEEE 754 numbers.
const price = dinero({ amount: 1000000000000000000, currency: ETH });

In such cases, you need to rely on safer alternatives, such as the bigint primitive or third-parties like big.js.

Using Dinero with bigint

Dinero provides a ready-to-use dinero function for bigints via the dinero.js/bigint subpath. Bigint-compatible currencies are available from dinero.js/bigint/currencies:

js
import { dinero, add } from 'dinero.js/bigint';
import { USD } from 'dinero.js/bigint/currencies';

const d1 = dinero({ amount: 500n, currency: USD });
const d2 = dinero({ amount: 100n, currency: USD });

add(d1, d2); // a Dinero object with amount 600n

::: warning
You cannot use currencies from dinero.js/currencies with bigint. Those have number values for base and exponent. Always import from dinero.js/bigint/currencies when using the bigint variant.
:::

Using Dinero with a custom amount type

Dinero.js delegates all calculations to a type-specific calculator object. The calculator fully determines what amount type you can pass to Dinero objects. Therefore, by changing the calculator with one of a different type, you can create Dinero objects of this type.

You can implement your own if you want to use a third-party library.

Implementing a custom calculator

Dinero.js delegates all calculations to a type-specific calculator object. You can implement a custom calculator for a given type and pass it to Dinero to use the library with amounts of this type.

A calculator implements the DineroCalculator interface. For example, here's what it can look like with big.js.

ts
import Big from 'big.js';
import { DineroCalculator, DineroComparisonOperator } from 'dinero.js';

const calculator: DineroCalculator<Big> = {
add: (a, b) => a.plus(b),
compare: (a, b) => a.cmp(b) as unknown as DineroComparisonOperator,
decrement: (v) => v.minus(new Big(1)),
increment: (v) => v.plus(new Big(1)),
integerDivide: (a, b) => a.div(b).round(0, Big.roundDown),
modulo: (a, b) => a.mod(b),
multiply: (a, b) => a.times(b),
power: (a, b) => a.pow(Number(b)),
subtract: (a, b) => a.minus(b),
zero: () => new Big(0),
};

Once you have your calculator, you can build a custom dinero function.

js
import { createDinero } from 'dinero.js';

// ...

const bigDinero = createDinero({ calculator });

You might notice that you're passing the full calculator, meaning you're shipping calculator methods you might not use. This is unlikely to represent a bottleneck, especially if you're using Dinero with a third-party library like big.js because you're only referencing methods that already exist on every Big object you create.

Providing a custom formatter

When using a custom amount type, you also need a custom formatter so that functions like toDecimal can correctly convert your amounts to strings. The default formatter uses JavaScript's String constructor, which produces scientific notation for large values (e.g., "1e+22" instead of "10000000000000000000000"). This breaks formatting when working with high-precision amounts.

ts
import Big from 'big.js';
import { DineroFormatter } from 'dinero.js';

const formatter: DineroFormatter<Big> = {
toNumber: (value) => value.toNumber(),
toString: (value) => value.toFixed(),
};

Pass it alongside the calculator when creating your custom dinero function:

js
const bigDinero = createDinero({ calculator, formatter });

Picking the right amount type

Depending on what you use Dinero.js for, you might want to choose a different amount type better suited to your needs. Knowing what to pick depends on your constraints, use case, and what compromises you can to make.

With amount types, the main trade-off is between precision and performance. Safe arbitrary precision comes at the cost of speed, so you need to properly assess your needs before deciding.

When to use number

By default, Dinero.js uses the number type. It's ideal when you need to express monetary values that will never exceed what the type can safely represent.

The number primitive type lets you create double-precision floats (or "doubles") using the IEEE 754 standard. It works well for many use cases and provides excellent performance. However, doubles can only represent a limited range of numbers (from -(2^53 - 1) to 2^53 - 1). Anything below or above gets truncated when converted to binary and stored in memory, resulting in imprecisions.

Using Dinero.js with numbers works well when you know and control the numbers to represent. It works for many use cases including dynamic pricing pages, ecommerce sites, or money management applications, as long as you're confident you'll never exceed the type limitations.

#### Benefits

- Great performance, implemented in hardware
- Full browser and Node.js compatibility (requires some polyfills for some static and Math functions)

#### Drawbacks

- Limited range of numbers that can be accurately represented

When to use bigint

Dinero.js provides a bigint calculator, allowing you to use the library with native bigints. It's ideal when you need to represent monetary values with large amounts, beyond what the number type safely supports.

The bigint primitive type lets you create arbitrarily large integers and ensures arithmetic precision. However, bigints are much slower than numbers, and not available in all environments. They're also impossible to polyfill and hard to transpile without incurring significant performance costs.

Using Dinero.js with the bigint type is recommended when you need to use numbers that exceed the number limitations. It can also act as a safeguard when you don't control the monetary amounts in your app, and you have reasons to believe you might exceed the limits. This applies to use cases such as cryptocurrency or stock trading applications.

#### Benefits

- Arbitrary-precision integer support
- Faster than any userland arbitrary-precision library (see Chrome benchmark)

#### Drawbacks

- Significantly slower than numbers, implemented in software
- Impossible to polyfill directly or to efficiently transpile down to ES5
- No native JSON.stringify and JSON.parse support, requires a custom replacer and reviver

When to use libraries

If you need to support arbitrarily large integers in browsers that don't support bigints, you can write a custom calculator to use Dinero.js with libraries like big.js or JSBI.

Contrary to the bigint type which relies on operators, libraries expose APIs to safely manipulate arbitrarily large integers. Such solutions usually rely on strings or arrays of numbers, making them more widely supported across browsers. However, this has a significant impact on performance because of the extra runtime logic, algorithmic complexity, and increase in bundle size.

Using Dinero.js with arbitrary precision arithmetic libraries makes sense when you wish you could use bigints but cannot because you need to support environments that don't implement them.

#### Benefits

- Better browser and Node.js support than bigints, transpilable and polyfillable

#### Drawbacks

- Significantly slower than numbers and bigints
- Increase in bundle size, impacting download and parse time

::: info
Dinero.js doesn't endorse any specific arbitrary precision library, or guarantees they work correctly. If you need to use a library, make sure to verify it works as expected.
:::

---

Guides/Storing In A Database

---
title: Storing in a database
description: How to persist Dinero objects in SQL and NoSQL databases.
---

Storing in a database

When building applications that handle money, you typically need to persist Dinero objects to a database. The way you store them depends on your database system and your application's requirements.

The safest and most portable approach is to store the amount as an integer in minor units, along with the currency code and exponent. This works with any database and gives you full control over how data is stored and retrieved.

Storing amount and currency separately

This approach stores each component of a Dinero object in its own column. It's the most flexible because it doesn't depend on any database-specific features.

sql
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price_amount BIGINT NOT NULL,
price_currency VARCHAR(3) NOT NULL,
price_exponent INTEGER NOT NULL DEFAULT 2
);

INSERT INTO products (name, price_amount, price_currency, price_exponent)
VALUES ('Mass Effect: Legendary Edition', 6999, 'EUR', 2);

When restoring from the database, you can reconstruct a Dinero object by passing the stored values to the dinero function.

js
import { dinero } from 'dinero.js';

// After fetching from database
const row = {
name: 'Mass Effect: Legendary Edition',
price_amount: 6999,
price_currency: 'EUR',
price_exponent: 2,
};

const product = {
name: row.name,
price: dinero({
amount: row.price_amount,
currency: { code: row.price_currency, base: 10, exponent: row.price_exponent },
}),
};

::: tip
If you're working with amounts that have a custom scale different from the currency's exponent, you'll need to store the scale as well and pass it when restoring.
:::

Storing as JSON

If your database supports JSON columns (PostgreSQL with JSONB, MySQL 5.7+, SQLite with JSON1), you can store the entire snapshot as a single value. This simplifies your schema but ties you to databases with JSON support.

sql
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price JSONB NOT NULL
);

You can store a snapshot directly and restore it with minimal transformation.

js
import { dinero, toSnapshot } from 'dinero.js';
import { EUR } from 'dinero.js/currencies';

const price = dinero({ amount: 6999, currency: EUR });

// Insert
await db.query(
'INSERT INTO products (name, price) VALUES ($1, $2)',
['Mass Effect: Legendary Edition', JSON.stringify(toSnapshot(price))]
);

// Restore
const { rows } = await db.query('SELECT * FROM products WHERE id = $1', [1]);

const product = {
...rows[0],
price: dinero(rows[0].price),
};

MongoDB with Decimal128

MongoDB's BSON format includes a Decimal128 type specifically designed for monetary data. It avoids floating-point precision issues that can occur with regular JavaScript numbers.

For typical use cases where amounts fit within JavaScript's safe integer range, you can store the snapshot directly as an embedded document.

js
import { dinero, toSnapshot } from 'dinero.js';
import { EUR } from 'dinero.js/currencies';

const price = dinero({ amount: 6999, currency: EUR });

// Insert snapshot as-is
await collection.insertOne({
name: 'Mass Effect: Legendary Edition',
price: toSnapshot(price),
});

// Restore
const document = await collection.findOne({ name: 'Mass Effect: Legendary Edition' });
const product = {
...document,
price: dinero(document.price),
};

When working with very large amounts or using the bigint calculator, you should use Decimal128 for the amount to ensure precision.

js
import { calculator } from 'dinero.js/bigint';
import { createDinero, toSnapshot } from 'dinero.js';
import { Decimal128 } from 'mongodb';

const dinero = createDinero({ calculator });

const ETH = {
code: 'ETH',
base: 10n,
exponent: 18n,
};

// 1 ETH in wei (10^18)
const balance = dinero({ amount: 1000000000000000000n, currency: ETH });
const snapshot = toSnapshot(balance);

// Insert with Decimal128 for precise amount storage
await collection.insertOne({
name: 'Wallet balance',
balance: {
amount: Decimal128.fromString(String(snapshot.amount)),
currency: snapshot.currency,
scale: snapshot.scale,
},
});

// Restore
const doc = await collection.findOne({ name: 'Wallet balance' });
const wallet = {
...doc,
balance: dinero({
amount: BigInt(doc.balance.amount.toString()),
currency: doc.balance.currency,
scale: doc.balance.scale,
}),
};

PostgreSQL's money type

PostgreSQL has a built-in money type, but it comes with significant limitations that make it unsuitable for most applications:

- No currency information: it only stores the amount, not which currency it represents.
- Locale-dependent: formatting depends on the lc_monetary setting, which can cause issues when moving data between systems.
- Fixed precision: always uses 2 decimal places, which doesn't work for currencies like JPY (0 decimals) or BHD (3 decimals).

If you still want to use it for single-currency applications where these limitations don't apply, you can convert Dinero objects to decimal strings for storage.

sql
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price MONEY NOT NULL
);

js
import { dinero, toDecimal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const price = dinero({ amount: 6999, currency: USD });

// Insert (convert to decimal string)
await db.query(
'INSERT INTO products (name, price) VALUES ($1, $2::money)',
['Mass Effect: Legendary Edition', toDecimal(price)]
);

// Restore (PostgreSQL returns money as a string like "$69.99")
const { rows } = await db.query('SELECT * FROM products WHERE id = $1', [1]);
const amountString = rows[0].price.replace(/[^0-9.-]/g, ''); // Remove currency symbol
const product = {
...rows[0],
price: dinero({
amount: Math.round(parseFloat(amountString) * 100),
currency: USD,
}),
};

::: warning
For most applications, we recommend storing amount and currency separately rather than using the money type. This gives you full control over precision and currency handling.
:::

---

Guides/Transporting And Restoring

---
title: Serialization
description: How to serialize Dinero objects for transport over the network and restore them in your application.
---

Serialization

If you want to send a Dinero object over the network, you need to serialize it first. Conversely, when retrieving a serialized object, you need to restore it as an actual Dinero object before using it in your application and manipulating it with Dinero functions.

Dinero lets you turn objects into snapshots. Snapshots are plain JavaScript objects, suited for transport and storage. To create a snapshot, you can use the toSnapshot function.

js
import { dinero, toSnapshot } from 'dinero.js';
import { USD } from 'dinero.js/currencies';

const price = dinero({ amount: 500, currency: USD });

const snapshot = toSnapshot(price);

/
* {
* amount: 500,
* currency: {
* code: 'USD',
* base: 10,
* exponent: 2,
* },
* scale: 2,
* }
*/

You can use snapshots with any API that accepts serializable data types.

js
import { dinero, toSnapshot } from 'dinero.js';
import { EUR } from 'dinero.js/currencies';
import axios from 'axios';

const price = dinero({ amount: 6999, currency: EUR });

axios.post('http://example.org/api/products', {
name: 'Mass Effect: Legendary Edition',
platform: 'Xbox One',
price: toSnapshot(price),
});

Serializing to JSON

If you want to serialize a Dinero object into JSON, you can directly call JSON.stringify on it, without turning them into a snapshot first.

js
import { dinero } from 'dinero.js';
import { EUR } from 'dinero.js/currencies';

const product = {
name: 'Mass Effect: Legendary Edition',
platform: 'Xbox One',
price: dinero({ amount: 6999, currency: EUR }),
};

fetch('http://example.org/api/products', {
method: 'POST',
body: JSON.stringify(product),
});

Restoring an object

When retrieving a snapshot, you can restore it into an actual Dinero object for usage in your application. To do so, you can pass the snapshot to the dinero function.

js
import { dinero } from 'dinero.js';
import axios from 'axios';

axios.get('http://example.org/api/products', {
params: {
id: '69e89575-fe87-4eb2-8b1d-b445bbe41a47',
},
})
.then(({ data }) => {
const product = {
...data,
price: dinero(data.price),
};
});

Handling arbitrary precision amounts

If you're using Dinero.js with the bigint calculator or a custom library, you need to cast the amount to a string for serialization, so you can retain precision and safely restore it later.

While many arbitrary precision libraries support this out of the box, you can't use JSON.stringify directly with bigints.

When serializing, make sure to pass a custom replacer to coerce every bigint into a string.

js
import { dinero } from 'dinero.js/bigint';
import { EUR } from 'dinero.js/bigint/currencies';

const product = {
name: 'Mass Effect: Legendary Edition',
platform: 'Xbox One',
price: dinero({ amount: 6999n, currency: EUR }),
};

fetch('http://example.org/api/products', {
method: 'POST',
body: JSON.stringify(product, (key, value) => {
if (typeof value === 'bigint') {
return String(value);
}

return value;
}),
});

---