### Api/Conversions/Convert --- title: convert description: Create a Dinero object converter. returns: Dinero --- # 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](/guides/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` | The Dinero object to convert. | Yes | | `newCurrency` | `DineroCurrency` | The currency to convert into. | Yes | | `rates` | `DineroRates` | 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[] --- # 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[]` | 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 --- # 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](#pass-a-custom-divide-function). For convenience, Dinero.js provides the following divide functions: `up`, `down`, `halfUp`, `halfDown`, `halfOdd`, `halfEven` ([bankers rounding](https://wiki.c2.com/?BankersRounding)), `halfTowardsZero`, and `halfAwayFromZero`. ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `dineroObject` | `Dinero` | 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 --- # trimScale Trim a Dinero object's scale as much as possible, down to the currency exponent. ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `dineroObject` | `Dinero` | 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](/guides/currency-type-safety). ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `dineroObject` | `Dinero` | The first Dinero object to compare. | Yes | | `comparator` | `Dinero` | 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`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/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` | The first Dinero object to compare. | Yes | | `comparator` | `Dinero` | 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](/guides/currency-type-safety). ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `dineroObject` | `Dinero` | The first Dinero object to compare. | Yes | | `comparator` | `Dinero` | 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](/guides/currency-type-safety). ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `dineroObject` | `Dinero` | The first Dinero object to compare. | Yes | | `comparator` | `Dinero` | 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` | 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[]` | 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[]` | 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` | 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` | 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` | 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](/guides/currency-type-safety). ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `dineroObject` | `Dinero` | The first Dinero object to compare. | Yes | | `comparator` | `Dinero` | 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](/guides/currency-type-safety). ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `dineroObject` | `Dinero` | The first Dinero object to compare. | Yes | | `comparator` | `Dinero` | 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 --- # 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](/guides/currency-type-safety). ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `dineroObjects` | `Dinero[]` | 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 --- # 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](/guides/currency-type-safety). ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `dineroObjects` | `Dinero[]` | 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`](/core-concepts/scale) of your object—or, when unspecified, the [`exponent`](/core-concepts/currency#currency-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` | The Dinero object to format. | Yes | | `transformer` | `DineroTransformer` | 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 --- # toSnapshot Get a snapshot of a Dinero object. Snapshots are plain JavaScript objects, suited for [transport and storage](/guides/transporting-and-restoring). They're also useful when you need to retrieve raw data from a Dinero object. ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `dineroObject` | `Dinero` | 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` | The Dinero object to format. | Yes | | `transformer` | `DineroTransformer` | 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 --- # 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](/guides/currency-type-safety). ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `augend` | `Dinero` | The Dinero object to add to. | Yes | | `addend` | `Dinero` | 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[] --- # 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` | The Dinero object to allocate from. | Yes | | `ratios` | `Array \| 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 --- # 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` | The Dinero object to multiply. | Yes | | `multiplier` | `DineroScaledAmount \| 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 --- # 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](/guides/currency-type-safety). ## Parameters | Name | Type | Description | Required | |------|------|-------------|----------| | `minuend` | `Dinero` | The Dinero object to subtract from. | Yes | | `subtrahend` | `Dinero` | 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`](/api/conversions/transform-scale). ## Usage Pass this function as the last argument to [`multiply`](/api/mutations/multiply), [`allocate`](/api/mutations/allocate), or [`transformScale`](/api/conversions/transform-scale) 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`](/api/mutations/multiply), [`allocate`](/api/mutations/allocate), or [`transformScale`](/api/conversions/transform-scale) 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`](/api/rounding/half-up). 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`](/api/mutations/multiply), [`allocate`](/api/mutations/allocate), or [`transformScale`](/api/conversions/transform-scale) 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](https://wiki.c2.com/?BankersRounding). 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`](/api/mutations/multiply), [`allocate`](/api/mutations/allocate), or [`transformScale`](/api/conversions/transform-scale) 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`](/api/rounding/half-up). 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`](/api/mutations/multiply), [`allocate`](/api/mutations/allocate), or [`transformScale`](/api/conversions/transform-scale) 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`](/api/mutations/multiply), [`allocate`](/api/mutations/allocate), or [`transformScale`](/api/conversions/transform-scale) 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`](/api/mutations/multiply), [`allocate`](/api/mutations/allocate), or [`transformScale`](/api/conversions/transform-scale) 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`](/api/mutations/multiply), [`allocate`](/api/mutations/allocate), or [`transformScale`](/api/conversions/transform-scale) 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](https://en.wikipedia.org/wiki/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](/guides/precision-and-large-numbers#using-dinero-with-bigint), import from `dinero.js/bigint/currencies` instead. ::: info Need a currency that isn't listed here? You can [create custom currency objects](/core-concepts/currency#creating-custom-currencies). For cryptocurrencies, see the [cryptocurrency guide](/guides/cryptocurrencies). ::: ::: 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](/core-concepts/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 --- # dinero Create a Dinero object that represents a monetary value. You specify the amount in [minor currency units](/core-concepts/amount) (e.g., cents for the US dollar) and pass a [currency](/core-concepts/currency). The [scale](/core-concepts/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` | 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) implementation, but the library is generic. This means you can use it with any data type you want: [bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt), third-parties like [big.js](https://github.com/MikeMcl/big.js), etc. To do so, check the advanced guide on [precision and large numbers](/guides/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](/core-concepts/currency#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](/core-concepts/currency#currency-exponent) to `1`. **See also:** [Formatting non-decimal currencies](/guides/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 ( {products.map(({ name, price }) => ( ))}
Name Price
{name} {isZero(price) ? 'Complimentary' : format(price)}
); } ``` --- ### 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](https://en.wikipedia.org/wiki/ISO_4217) currencies, the first two letters of the code are the two letters of the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/Mauritanian_ouguiya) and the [Malagasy ariary](https://en.wikipedia.org/wiki/Malagasy_ariary). ```js // Mauritanian ouguiya const MRU = { code: 'MRU', base: 5, // ... }; ``` Some currencies have multiple subdivisions. For example, before [decimalization](https://en.wikipedia.org/wiki/Decimalisation), 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](/core-concepts/amount) in major currency units. ```js // Japanese yen const JPY = { code: 'JPY', base: 10, exponent: 0, }; ``` When you pass a [scale](/core-concepts/scale) to a Dinero object, it overrides the exponent. This has an impact on how you should specify the [amount](/core-concepts/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](/getting-started/quick-start#install-the-library), 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](/guides/precision-and-large-numbers#using-dinero-with-bigint), 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](https://www.six-group.com/en/products-services/financial-information/data-standards.html) 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](#creating-custom-currencies) 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](/faq/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 = { code: 'FRF', base: 10, exponent: 2, }; ``` To opt into [compile-time currency safety](/guides/currency-type-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; ``` 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](/guides/currency-type-safety), [Precision and large numbers](/guides/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`](/api/formatting/to-decimal) 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](/api/formatting/to-decimal) - [To units](/api/formatting/to-units) - [Formatting in a multilingual site](/guides/formatting-in-a-multilingual-site) - [Formatting non-decimal currencies](/guides/formatting-non-decimal-currencies) ## Retrieving raw data One of the most convenient formatting functions in Dinero.js is [`toSnapshot`](/api/formatting/to-snapshot). 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`](/api/formatting/to-snapshot) 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`](/api/formatting/to-snapshot) is transport and storage. To do so, check the advanced guide on [transporting and restoring](/guides/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](/core-concepts/currency#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](/guides/storing-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](https://en.wikipedia.org/wiki/IEEE_754). 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`](/api/conversions/trim-scale) 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`](/api/mutations/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](/guides/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](/core-concepts/currency#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](/guides/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`](/api/formatting/to-decimal) 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`](/api/formatting/to-decimal) to get the numeric value, then format with [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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`](/api/formatting/to-decimal). See the [Multilingual support](/guides/formatting-in-a-multilingual-site) 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](https://nodejs.org/about/releases/) 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`](/api/mutations/add), [`subtract`](/api/mutations/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](https://webpack.js.org/guides/tree-shaking/) - [Scope Hoisting](https://v2.parceljs.org/features/scope-hoisting/) - [Building for Production](https://vitejs.dev/guide/build.html) ## 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](https://www.jsdelivr.com/) or [cdnjs](https://cdnjs.com/), 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](https://www.cloudflare.com/cdn) or [Cloudfront](https://aws.amazon.com/cloudfront/). **Resources:** - [Content delivery network](https://wikipedia.org/wiki/Content_delivery_network) - [Gzip](https://gnu.org/software/gzip/) - [Brotli](https://github.com/google/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 ``` ## 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](/core-concepts/formatting) 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](/agent-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](https://eslint.org/docs/rules/new-cap). ```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](/core-concepts/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](/core-concepts/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](#replace-getamount-getcurrency-and-getprecision-with-tosnapshot). | | `d1.getCurrency()` | Dropped, [see replacement](#replace-getamount-getcurrency-and-getprecision-with-tosnapshot). | | `d1.getPrecision()` | Dropped, [see replacement](#replace-getamount-getcurrency-and-getprecision-with-tosnapshot). | | `d1.getLocale()` | [Dropped](#dropped-support-for-locale). | #### Mutations | Dinero v1.x | Dinero v2 | |--------------------------|----------------------------------------------------------------------------------------------------| | `d1.add(d2)` | [`add(d1, d2)`](/api/mutations/add) | | `d1.subtract(d2)` | [`subtract(d1, d2)`](/api/mutations/subtract) | | `d1.multiply(...args)` | [`multiply(d1, ...args)`](/api/mutations/multiply) | | `d1.allocate(...args)` | [`allocate(d1, ...args)`](/api/mutations/allocate) | | `d1.divide(...args)` | Dropped, [see replacement](#replace-divide-with-allocate). | | `d1.percentage(...args)` | Dropped, [see replacement](#replace-percentage-with-a-custom-solution-using-allocate-or-multiply). | | `d1.setLocale(...args)` | [Dropped](#dropped-support-for-locale). | #### Conversions | Dinero v1.x | Dinero v2 | |---------------------------------------|------------------------------------------------------------------------| | `d1.convert(...args)` | [`convert(d1, ...args)`](/api/conversions/convert) | | `Dinero.normalizePrecision([d1, d2])` | [`normalizeScale([d1, d2])`](/api/conversions/normalize-scale) | | `d1.convertPrecision(...args)` | [`transformScale(d1, ...args)`](/api/conversions/transform-scale) | #### Comparisons | Dinero v1.x | Dinero v2 | |-----------------------------|-----------------------------------------------------------------------------| | `d1.equalsTo(d2)` | [`equal(d1, d2)`](/api/comparisons/equal) | | `d1.greaterThan(d2)` | [`greaterThan(d1, d2)`](/api/comparisons/greater-than) | | `d1.greaterThanOrEqual(d2)` | [`greaterThanOrEqual(d1, d2)`](/api/comparisons/greater-than-or-equal) | | `d1.lessThan(d2)` | [`lessThan(d1, d2)`](/api/comparisons/less-than) | | `d1.lessThanOrEqual(d2)` | [`lessThanOrEqual(d1, d2)`](/api/comparisons/less-than-or-equal) | | `Dinero.minimum([d1, d2])` | [`minimum([d1, d2])`](/api/comparisons/minimum) | | `Dinero.maximum([d1, d2])` | [`maximum([d1, d2])`](/api/comparisons/maximum) | | `d1.isZero()` | [`isZero(d1)`](/api/comparisons/is-zero) | | `d1.isPositive()` | [`isPositive(d1)`](/api/comparisons/is-positive) | | `d1.isNegative()` | [`isNegative(d1)`](/api/comparisons/is-negative) | | `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)`](/api/comparisons/has-sub-units) | #### Formatting | Dinero v1.x | Dinero v2 | |-----------------------------|----------------------------------------------------------------------------------------| | `d1.toFormat(format)` | Dropped, [see replacement](#replace-tounit-and-toroundedunit-with-tounits-or-todecimal) | | `d1.toObject()` | [`toSnapshot(d1)`](/api/formatting/to-snapshot) | | `d1.toUnit(...args)` | Dropped, [see replacement](#replace-tounit-and-toroundedunit-with-tounits-or-todecimal) | | `d1.toRoundedUnit(...args)` | Dropped, [see replacement](#replace-tounit-and-toroundedunit-with-tounits-or-todecimal) | ### Replace floats with scaled amounts In v1.x, methods like [`convert`](/api/conversions/convert), [`multiply`](/api/mutations/multiply), or [`allocate`](/api/mutations/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](/api/conversions/convert) - [Multiply](/api/mutations/multiply) - [Allocate](/api/mutations/allocate) ### Replace getAmount, getCurrency and getPrecision with toSnapshot The `getAmount`, `getCurrency`, and `getPrecision` methods have been replaced with [`toSnapshot`](/api/formatting/to-snapshot), 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](/api/formatting/to-snapshot) ### Replace divide with allocate Dinero.js v2 no longer has a built-in `divide` function. Use [`allocate`](/api/mutations/allocate) instead. **See also:** [Allocate](/api/mutations/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`](/api/mutations/allocate) or [`multiply`](/api/mutations/multiply). **See also:** [How do I calculate a percentage?](/guides/calculating-percentages) ### Replace toUnit and toRoundedUnit with toUnits or toDecimal Dinero.js v2 no longer has a built-in `toUnit` and `toRoundedUnit` functions. Use [`toUnits`](/api/formatting/to-units) or [`toDecimal`](/api/formatting/to-decimal) instead. **See also:** - [To units](/api/formatting/to-units) - [To decimal](/api/formatting/to-decimal) ### Dropped support for locale In v1.x, object formatting relied upon the [Internationalization API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl). 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](/api/formatting/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`](/api/mutations/allocate) or [`multiply`](/api/mutations/multiply). For example, if you need to calculate 15% of a Dinero object, you can split it with [`allocate`](/api/mutations/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`](/api/mutations/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](http://mikemcl.github.io/big.js/). Cryptos usually have high exponents, making them likely to exceed the range of safe JavaScript integers. **See also:** [Precision and large numbers](/guides/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`. 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 const d2 = dinero({ amount: 100, currency: USD }); // Dinero const d3 = dinero({ amount: 100, currency: EUR }); // Dinero 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 add(doubled, price); // OK add(doubled, dinero({ amount: 100, currency: EUR })); // Type error const [half1, half2] = allocate(price, [50, 50]); // Dinero[] 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 const rates = { EUR: { amount: 89, scale: 2 } }; const converted = convert(d, EUR, rates); // Dinero 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; ``` 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 — 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](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl) (`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`](/api/formatting/to-decimal). ```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](https://nodejs.org/api/intl.html#intl_options_for_building_node_js). ::: ## 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 ( <>

Price: {intlFormat(price, language.locale)}

); } ``` --- ### 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`](/api/formatting/to-units). ```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](https://stripe.com/) 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](https://stripe.com/) payment platform provides APIs to process payments and manage orders. Like many other platforms, it expects [money representations](https://stripe.com/docs/currencies#zero-decimal) 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](https://stripe.com/docs/api/charges/create?lang=node#create_charge-currency). ```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](https://www.paypal.com/) 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`](/api/formatting/to-decimal) 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](https://www.adyen.com/) payment platform provides APIs to process payments and manage orders. Like many other platforms, it expects [money representations](https://developer.squareup.com/reference/square/objects/Money) 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](https://squareup.com/) digital payment platform provides APIs to process payments and manage orders. Like many other platforms, it expects [money representations](https://docs.adyen.com/development-resources/currency-codes) 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`](https://github.com/square/square-nodejs-sdk/blob/master/src/models/money.ts). 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER) and [smallest](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER) 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) primitive or third-parties like [big.js](https://github.com/MikeMcl/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](https://github.com/MikeMcl/big.js). ```ts import Big from 'big.js'; import { DineroCalculator, DineroComparisonOperator } from 'dinero.js'; const calculator: DineroCalculator = { 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](https://github.com/MikeMcl/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 = { 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`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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](https://wikipedia.org/wiki/IEEE_754). 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 `number`s 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](https://wikipedia.org/wiki/Floating-point_unit) - Full browser and Node.js compatibility (requires [some polyfills](/getting-started/compatibility#browser-support) 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`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) calculator, allowing you to [use the library with native `bigint`s](#using-dinero-with-bigint). 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, `bigint`s are much slower than `number`s, and not available in all environments. They're also [impossible to polyfill and hard to transpile](https://v8.dev/features/bigint#polyfilling-transpiling) 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](https://v8.dev/features/bigint#use-cases)) #### Drawbacks - Significantly slower than `number`s, [implemented in software](https://v8.dev/blog/bigint) - Impossible to polyfill directly or to efficiently transpile down to ES5 - No native [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) and [`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) support, requires a custom [replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#the_replacer_parameter) and [reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#using_the_reviver_parameter) ### When to use libraries If you need to support arbitrarily large integers in browsers that don't support `bigint`s, you can [write a custom calculator](#implementing-a-custom-calculator) to use Dinero.js with libraries like [big.js](https://github.com/MikeMcl/big.js) or [JSBI](https://github.com/GoogleChromeLabs/jsbi). Contrary to the `bigint` type which relies on operators, libraries expose APIs to safely manipulate arbitrarily large integers. Such solutions usually rely on `string`s or arrays of `number`s, 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 `bigint`s](#when-to-use-bigint) but cannot because you need to support environments that don't implement them.** #### Benefits - Better browser and Node.js support than `bigint`s, transpilable and polyfillable #### Drawbacks - Significantly slower than `number`s and `bigint`s - 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](/core-concepts/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](/guides/precision-and-large-numbers#using-dinero-with-bigint), 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`](/api/formatting/to-snapshot) 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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](/guides/precision-and-large-numbers#using-dinero-with-bigint) or a [custom library](/guides/precision-and-large-numbers#implementing-a-custom-calculator), 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`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) directly with `bigint`s.** When serializing, make sure to pass a [custom replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#the_replacer_parameter) 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; }), }); ``` ---