Introducing Easymoney 💵
Tags: money, javascript, typescript, webdev
Published: 2020-05-18 12:41:06

Hi everyone! Today I'm excited to announce [easymoney](https://github.com/frolovdev/easymoney): opensource library for operating with monetary values in **JavaScript** and **Typescript**.

We publish the first stable release v1.0.0. In this post, we try to explain some sort of motivation and briefly describe what is ready today and what to expect from our future plans and roadmap.

## About the library

easymoney is a library for operating with monetary values in **JavaScript** and **Typescript**. It's an implementation of a pattern [Martin Fowler's Money Type](https://martinfowler.com/eaaCatalog/money.html) from ["Patterns of Enterprise Application Architecture"](https://www.amazon.ca/gp/product/0321127420/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=evertpot-20&creative=330641&linkCode=as2&creativeASIN=0321127420&linkId=3e43f20d3b2dd7e325a3feecdd2eaecd).

It's an old and widely used pattern that is implemented in many other languages e.g.:

- Java [Moneta](https://github.com/JavaMoney/jsr354-ri)
- PHP [moneyphp](https://github.com/moneyphp/money)
- Go [go-money](https://github.com/Rhymond/go-money)

## Highlights

[First-class Typescript support](#Typescript)
[Support all standard math operations](#Mathoperations)
[Custom currencies support](#Customcurrencies)
[Support big number values](#Bignumber)
[Support crypto](#Crypto)
[Support formatting](#Formatting)

## Principles that we put in our library

[As small as possible bundle size](#Modular)
[Nearly 100 per cent coverage, proofing reliability](#Tests)
[Clear communications and transparency within the community](#Transparency)


## In-depth

### <a name="Typescript"></a> First-class Typescript support

<img width="60000px" height="auto" src="https://media.giphy.com/media/SwfmMMP5SqgLjzhWrQ/giphy.gif" />

The library is written in Typescript. We really like Typescript and try to achieve flexibility between reliability and simplicity in its usage.

### <a name="Mathoperations"></a> Support all standard math operations

**Addition** 

```js

import { createMoney } from '@easymoney/money';

const money1 = createMoney({ amount: 100, currency: 'USD' });

const money2 = createMoney({ amount: 106, currency: 'USD' });

const money3 = money1.add(money2).getAmount();
// => 206

```

**Multiplication**

```js

import { createMoney } from '@easymoney/money';

const money1 = createMoney({ amount: 100, currency: 'USD' });

const money2 = createMoney({ amount: 2, currency: 'USD' });

const money3 = money1.multiply(money2).getAmount();
// => 200

```

Supports all standard math operations. Subtraction, multiplication, division, and so on.

### <a name="Customcurrencies"></a> Custom currencies support

```js

import { createCurrencyList } from "@easymoney/currencies";

const currencies = [{ minorUnit: 2, code: "XBT" },
              { minorUnit: 5, code: "DXBT" }];

const list = createCurrencyList(currencies);


list.contains("USD")
// => false

list.contains("XBT")
// => true

```

Depending on the application, the user may want the list of currencies used by the application to contain other fields, such as the view field to display the symbol (e.g., ₿), or may want to operate with other currencies that are not on the ISO list at all (e.g., various cryptocurrencies). For this reason, we thought it's important to give users the flexibility to customize, if they wish, how they will present currencies in their application.

### <a name="Bignumber"></a> Support big number values

We also support numbers bigger than [Number.MAX_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)

### <a name="Crypto"></a> Support custom and crypto currencies

```js

import { createMoneyCryptoFormatter } from "@easymoney/crypto-formatter";
import { createMoney } from "@easymoney/money";

const BTC = { code: "BTC", minorUnit: 8 };

const money = createMoney({ amount: 6, currency: BTC });

money.getCurrency();
// => { code: "BTC", minorUnit: 8 }

const formattedValue = createMoneyCryptoFormatter().format(money);
// 0.00000005BTC

```

We understand that the use of cryptocurrencies is on the rise, so we consider it necessary to give our users who work in this area a convenient API for their daily tasks. Now, out of the box we support only LTC, ETH, BTC, but we can expand this list in future releases.

### <a name="Formatting"></a> Support formatting

**Formatting ISO currencies with Intl.NumberFormat**

```js

import { createMoneyIntlFormatter } from "@easymoney/formatter"
import { createMoney } from '@easymoney/money';

const money = createMoney({ amount: 5, currency: "USD" });
const money1 = createMoney({ amount: 50, currency: "USD" });

const formatted = createMoneyIntlFormatter().format(money);
// => "$0.05"

const formatted1 = createMoneyIntlFormatter()
                    .format(money,
                            "en-US", 
                            {minimumFractionDigits: 1, maximumFractionDigits: 1});
// => "$0.5"


```

**Formatting cryptocurrencies**

```js


import { createMoneyCryptoFormatter } from "@easymoney/crypto-formatter"
import { createMoney } from '@easymoney/money';
import { cryptoCurrenciesMap } from "@easymoney/currencies"

const money = createMoney({ amount: 5, currency: "LTC" });

const formatted = createMoneyCryptoFormatter().format(money);
// => "0.00000005LTC"

const money1 = createMoney({ amount: 50, currency: cryptoCurrenciesMap.ETH });

const formatted1 = createMoneyCryptoFormatter().format(money);
// => "0.000000000000000005ETH"

const money = { amount: 5, currency: "ETH" };

const formattedValue = createFormatter().format(createMoney(money), {
        currencyPosition: -1
});

// => ETH0.000000000000000005


```

### <a name="Modular"></a> Modular api

Our library is divided into different packages. For example:

**@easymoney/crypto-formatter** –– crypto currency formatting;
**@easymoney/formatter** –– formatting ISO currencies using Intl.NumberFormat;
**@easymoney/money** –– work with monetary values with numbers that fit into Number.MAX_SAFE_INTEGER;
**@easymoney/bignumber.js** –– works with monetary values of any range, integrated with the library bignumber.js;
**@easymoney/currencies** –– works with any range of values integrated with bignumber.js library.

We tried to build the architecture so that the functionality of the library was available as much as possible by domain. This allows for maximum flexibility in the construction of third-party modules (about this below), as well as to have the smallest possible final bundle size so that you need only download the part of the functions that you require.

### <a name="Tests"></a> Reliability 

<a href="https://codecov.io/gh/frolovdev/easymoney">
  <img src="https://codecov.io/gh/frolovdev/easymoney/branch/master/graph/badge.svg" />
</a>

We believe that good software is a reliable software. Therefore, in addition to types, there should be testing behind the guarantee of reliability. With this in mind, we pay a great deal of attention to testing. Most of the code is covered by unit tests, but we also use prop-based testing and a [fast-check](https://github.com/dubzzz/fast-check) tool to brush up on possible unrecorded branches that are not always visible with conventional unit tests. We think that modern javascript has all the tools needed to ensure the reliability of the software being developed.  

Also, we use [codecov](https://codecov.io/), to make sure the coverage doesn't decrease between releases.

### <a name="Transparency"></a> Transparency 

It's an opensource product, so the community must stay in the first place. So keeping this in mind, we want this product to be transparent with the community, so everyone can get quick feedback or find what they need. That's why we are going to pay a lot of attention to the documentation and to the quickest possible resolution of user problems.

For this we have taken the following steps:

- We have an open [roadmap](https://github.com/frolovdev/easymoney/projects/2), where you can track the process of future features that you can suggest in [issues](https://github.com/frolovdev/easymoney/issues).
- We try to explain all motivations in starting guides and a future series of articles will describe all possible functionality and problems. The first one is already [written](https://dev.to/frolovdev/why-rounding-is-more-important-than-you-think-134j).	
- We will keep detailed [releases](https://github.com/frolovdev/easymoney/releases) so you can always track changes in the library.
- We are going to use templates for [issues](https://github.com/frolovdev/easymoney/issues/new/choose) so that you can find similar problems in the issue tracker without much effort.

We realize that there is still a lot of work ahead of us on documentation and on adding the necessary functionality for users. Now we are actively working on documentation and adding guides on how to use our library. In parallel, we will try to implement new features as far as possible. If you want to help, you always can ask to help on [my Twitter](https://twitter.com/frolovdev) and I will try to find some work for you and say thank you very much for your help.

## Get Started

[Repository](https://github.com/frolovdev/easymoney)
[Docs](https://easymoney.now.sh/docs/introduction/getting-started)

## Thank you

Thanks for reading the post and for your time. Big thanks to people who helped me to finish this project, especially [Jan Janucewicz](https://www.linkedin.com/in/jan-janucewicz/), who helped with integrating bignumber.js and made a great effort to tests and documentation.

If you find bugs, please report them on our [Github issues](https://github.com/frolovdev/easymoney/issues). Alternatively, you can always ask me on [Twitter](https://twitter.com/frolovdev/easymoney).

Feel free to ask questions, to express any opinion, and discuss this from your point of view. Make code, not war. ❤️