DEV Community

Andrey Frolov
Andrey Frolov

Posted on

Introducing Easymoney 💵

Hi everyone! Today I'm excited to announce 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 from "Patterns of Enterprise Application Architecture".

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

Highlights

First-class Typescript support
Support all standard math operations
Custom currencies support
Support big number values
Support crypto
Support formatting

Principles that we put in our library

As small as possible bundle size
Nearly 100 per cent coverage, proofing reliability
Clear communications and transparency within the community

In-depth

First-class Typescript support

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

Support all standard math operations

Addition


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

Enter fullscreen mode Exit fullscreen mode

Multiplication


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

Enter fullscreen mode Exit fullscreen mode

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

Custom currencies support


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

Enter fullscreen mode Exit fullscreen mode

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.

Support big number values

We also support numbers bigger than Number.MAX_SAFE_INTEGER

Support custom and crypto currencies


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

Enter fullscreen mode Exit fullscreen mode

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.

Support formatting

Formatting ISO currencies with Intl.NumberFormat


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"


Enter fullscreen mode Exit fullscreen mode

Formatting cryptocurrencies



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


Enter fullscreen mode Exit fullscreen mode

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.

Reliability



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 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, to make sure the coverage doesn't decrease between releases.

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, where you can track the process of future features that you can suggest in 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.
  • We will keep detailed releases so you can always track changes in the library.
  • We are going to use templates for issues 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 and I will try to find some work for you and say thank you very much for your help.

Get Started

Repository
Docs

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, 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. Alternatively, you can always ask me on Twitter.

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

Discussion (1)

Collapse
thisdotmedia_staff profile image
This Dot Media

So exciting! Congrats on your launch Andrey 😁 Also, great introduction. Seems like a useful library!