UNPKG

9.15 kBMarkdownView Raw
1# Cashify 💸
2
3> Lightweight currency conversion library, successor of money.js
4
5[![Build Status](https://github.com/xxczaki/cashify/workflows/CI/badge.svg)](https://github.com/xxczaki/cashify/actions?query=workflow%3ACI)
6[![Coverage Status](https://coveralls.io/repos/github/xxczaki/cashify/badge.svg?branch=master)](https://coveralls.io/github/xxczaki/cashify?branch=master)
7[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo)
8[![install size](https://packagephobia.now.sh/badge?p=cashify)](https://packagephobia.now.sh/result?p=cashify)
9![minified size](https://img.shields.io/bundlephobia/minzip/cashify)
10[![Mentioned in Awesome Node.js](https://awesome.re/mentioned-badge.svg)](https://github.com/sindresorhus/awesome-nodejs)
11
12- [Motivation](#motivation)
13- [Highlights](#highlights)
14- [Install](#install)
15- [Usage](#usage)
16 - [With constructor](#with-constructor)
17 - [Without constructor](#without-constructor)
18 - [Parsing](#parsing)
19 - [Integration with big.js](#integration-bigjs)
20 - [Integration with currency.js](#integration-currencyjs)
21- [API](#api)
22 - [Cashify({base, rates})](#cashifybase-rates)
23 - [base](#base)
24 - [rates](#rates)
25 - [BigJs](#bigjs)
26 - [convert(amount, {from, to, base, rates})](#convertamount-from-to-base-rates-with-and-without-constructor)
27 - [amount](#amount)
28 - [from](#from)
29 - [to](#to)
30 - [base](#base-1)
31 - [rates](#rates-1)
32 - [BigJs](#bigjs-1)
33 - [parse(expression)](#parseexpression)
34 - [expression](#expression)
35- [Migrating from money.js](#migrating-from-moneyjs)
36- [Floating point issues](#floating-point-issues)
37- [Related projects](#related-projects)
38- [License](#license)
39
40---
41
42## Motivation
43
44This package was created, because the popular [money.js](http://openexchangerates.github.io/money.js/) library:
45* is not maintained (last commit was ~5 years ago)
46* has over 20 open issues
47* does not support TypeScript
48* has implicit globals
49* does not have any unit tests
50* [has floating point issues](#floating-point-issues)
51
52## Highlights
53
54- Simple API
55- 0 dependencies
56- Actively maintained
57- Well tested and documented
58- [Easy migration from money.js](#migrating-from-moneyjs)
59- Written in TypeScript
60- ESM-only
61
62## Install
63
64```
65$ npm install cashify
66```
67
68**Please note that starting with version `3.0.0` this package is ESM-only and thus requires Node.js v14 or higher.**
69
70## Usage
71
72### With constructor
73
74```js
75import {Cashify} from 'cashify';
76
77const rates = {
78 GBP: 0.92,
79 EUR: 1.00,
80 USD: 1.12
81};
82
83const cashify = new Cashify({base: 'EUR', rates});
84
85const result = cashify.convert(10, {from: 'EUR', to: 'GBP'});
86
87console.log(result); //=> 9.2
88```
89
90### Without constructor
91
92Using the `Cashify` constructor is not required. Instead, you can just use the `convert` function:
93
94```js
95import {convert} from 'cashify';
96
97const rates = {
98 GBP: 0.92,
99 EUR: 1.00,
100 USD: 1.12
101};
102
103const result = convert(10, {from: 'EUR', to: 'GBP', base: 'EUR', rates});
104
105console.log(result); //=> 9.2
106```
107
108### Parsing
109
110Cashify supports parsing, so you can pass a `string` to the `amount` argument and the `from` and/or `to` currency will be automatically detected:
111
112```js
113import {Cashify} from 'cashify';
114
115const rates = {
116 GBP: 0.92,
117 EUR: 1.00,
118 USD: 1.12
119};
120
121const cashify = new Cashify({base: 'EUR', rates});
122
123// Basic parsing
124cashify.convert('€10 EUR', {to: 'GBP'});
125
126// Full parsing
127cashify.convert('10 EUR to GBP');
128```
129
130Alternatively, if you just want to parse a `string` without conversion you can use the [`parse`](#parseexpression) function which returns an `object` with parsing results:
131
132```js
133import {parse} from 'cashify';
134
135parse('10 EUR to GBP'); //=> {amount: 10, from: 'EUR', to: 'GBP'}
136```
137
138**Note:** If you want to use full parsing, you need to pass a `string` in a specific format:
139
140```
14110 usd to pln
14212.5 GBP in EUR
1433.1415 eur as chf
144```
145
146You can use `to`, `in` or `as` to separate the expression (case insensitive). Used currencies name case doesn't matter, as cashify will automatically convert them to upper case.
147
148<a id="integration-bigjs"></a>
149
150### Integration with [big.js](https://github.com/MikeMcl/big.js/)
151
152[big.js](https://github.com/scurker/currency.js/) is a small JavaScript library for arbitrary-precision decimal arithmetic. You can use it with cashify to make sure you won't run into floating point issues:
153
154```js
155import {Cashify} from 'cashify';
156import Big from 'big.js';
157
158const rates = {
159 EUR: 0.8235,
160 USD: 1
161};
162
163const cashify = new Cashify({base: 'USD', rates});
164
165const result = cashify.convert(1, {
166 from: 'USD',
167 to: 'EUR',
168 BigJs: Big
169});
170
171console.log(result); //=> 8.235 (without big.js you would get something like 0.8234999999999999)
172```
173
174<a id="integration-currencyjs"></a>
175
176### Integration with [currency.js](https://github.com/scurker/currency.js/)
177
178[currency.js](https://github.com/scurker/currency.js/) is a small and lightweight library for working with currency values. It integrates well with cashify. In the following example we are using it to format the conversion result:
179
180```js
181import {Cashify} from 'cashify';
182import currency from 'currency.js';
183
184const rates = {
185 GBP: 0.92,
186 EUR: 1.00,
187 USD: 1.12
188};
189
190const cashify = new Cashify({base: 'EUR', rates});
191
192const converted = cashify.convert(8635619, {from: 'EUR', to: 'GBP'}); // => 7944769.48
193
194// Format the conversion result
195currency(converted, {symbol: '€', formatWithSymbol: true}).format(); // => €7,944,769.48
196```
197
198## API
199
200### Cashify({base, rates, BigJs})
201
202Constructor.
203
204##### base
205
206Type: `string`
207
208The base currency.
209
210##### rates
211
212Type: `object`
213
214An object containing currency rates (for example from an API, such as Open Exchange Rates).
215
216##### BigJs
217
218Type: [big.js](https://github.com/MikeMcl/big.js/) constructor
219
220See [integration with big.js](#integration-bigjs).
221
222### convert(amount, {from, to, base, rates}) *`with and without constructor`*
223
224Returns conversion result (`number`).
225
226##### amount
227
228Type: `number` or `string`
229
230Amount of money you want to convert. You can either use a `number` or a `string`. If you choose the second option, you can take advantage of [parsing](#parsing) and not specify `from` and/or `to` argument(s).
231
232##### from
233
234Type: `string`
235
236Currency from which you want to convert. You might not need to specify it if you are using [parsing](#parsing).
237
238##### to
239
240Type: `string`
241
242Currency to which you want to convert. You might not need to specify it if you are using [parsing](#parsing).
243
244##### base
245
246Type: `string`
247
248The base currency.
249
250##### rates
251
252Type: `object`
253
254An object containing currency rates (for example from an API, such as Open Exchange Rates).
255
256##### BigJs
257
258Type: [big.js](https://github.com/MikeMcl/big.js/) constructor
259
260See [integration with big.js](#integration-bigjs).
261
262### parse(expression)
263
264Returns an `object`, which contains parsing results:
265
266```
267{
268 amount: number;
269 from: string | undefined;
270 to: string | undefined;
271}
272```
273
274##### expression
275
276Type: `string`
277
278Expression you want to parse, ex. `10 usd to pln` or `€1.23 eur`
279
280## Migrating from money.js
281
282With `Cashify` constructor:
283
284```diff
285- import fx from 'money';
286+ import {Cashify} from 'cashify';
287
288- fx.base = 'EUR';
289- fx.rates = {
290- GBP: 0.92,
291- EUR: 1.00,
292- USD: 1.12
293- };
294
295+ const rates = {
296+ GBP: 0.92,
297+ EUR: 1.00,
298+ USD: 1.12
299+ };
300
301+ const cashify = new Cashify({base: 'EUR', rates});
302
303- fx.convert(10, {from: 'GBP', to: 'EUR'});
304+ cashify.convert(10, {from: 'GBP', to: 'EUR'});
305```
306
307With `convert` function:
308
309```diff
310- import fx from 'money';
311+ import {convert} from 'cashify';
312
313- fx.base = 'EUR';
314- fx.rates = {
315- GBP: 0.92,
316- EUR: 1.00,
317- USD: 1.12
318- };
319
320+ const rates = {
321+ GBP: 0.92,
322+ EUR: 1.00,
323+ USD: 1.12
324+ };
325
326- fx.convert(10, {from: 'GBP', to: 'EUR'});
327+ convert(10, {from: 'GBP', to: 'EUR', base: 'EUR', rates});
328```
329
330## Floating point issues
331
332When working with currencies, decimals only need to be precise up to the smallest cent value while avoiding common floating point errors when performing basic arithmetic.
333
334Let's take a look at the following example:
335
336```js
337import fx from 'money';
338import {Cashify} from 'cashify';
339
340const rates = {
341 GBP: 0.92,
342 USD: 1.12
343};
344
345fx.rates = rates;
346fx.base = 'EUR';
347
348const cashify = new Cashify({base: 'EUR', rates});
349
350fx.convert(10, {from: 'EUR', to: 'GBP'}); //=> 9.200000000000001
351cashify.convert(10, {from: 'EUR', to: 'GBP'}); //=> 9.2
352```
353
354As you can see, money.js doesn't handle currencies correctly and therefore a floating point issues are occuring. Even though there's just a minor discrepancy between the results, if you're converting large amounts, that can add up.
355
356Cashify solves this problem the same way as [currency.js](https://github.com/scurker/currency.js/) - by working with integers behind the scenes. **This should be okay for most reasonable values of currencies**; if you want to avoid all floating point issues, see [integration with big.js]().
357
358## Related projects
359
360* [nestjs-cashify](https://github.com/vahidvdn/nestjs-cashify) - Node.js Cashify module for Nest.js.
361* [cashify-rs](https://github.com/xxczaki/cashify-rs) - Cashify port for Rust.
362
363## License
364
365MIT © [Antoni Kępiński](https://www.kepinski.ch)