Skip to content

Latest commit

 

History

History
524 lines (375 loc) · 17.5 KB

README.md

File metadata and controls

524 lines (375 loc) · 17.5 KB

Crypto Utils

Crypto utilities for formatting tokens and fractions.

NPM Version CircleCI codecov Discord Twitter Follow



Check out the other Uniswap and crypto libraries, that depend on this library:

💰 @thanpolas/univ3prices for calculating Uniswap V3 Prices.
☎️ @thanpolas/uniswap-chain-queries for fetching on-chain data for ERC20 tokens, Uniswap V2 (and clones) and Uniswap V3.



Features

Install

Install the module using NPM:

npm install @thanpolas/crypto-utils --save

Quick Start

const { tokenToAuto } = require('@thanpolas/crypto-utils');

const tokenQuantity = '2083278970151697065687';
const decimals = 18;

const value = tokenToAuto(tokenQuantity, decimals);

console.log(value);
// "2083.27897"

Liquidity Pool Tokens Ratio

poolTokensToAuto(poolFraction, decimalFraction, optOptions)

Calculates the ratio between the reserves of two tokens in a liquidity pool.

  • poolFraction {Array<string|bigint>} The tuple fraction, an Array with two items representing the liquidity pool token reserves.
  • decimalFraction {Array<string|number>} An Array tuple with two items representing the decimal places of token0 and token1 as defined in the "poolFraction" argument.
  • optOptions {Object=} An object with calculation options, read more about available options here.
  • Returns {string} Formatted token.
const { poolTokensToAuto } = require('@thanpolas/crypto-utils');


// 3236.0404424781496715 - Reversed: 0.00030901962375791667205
const dai_weth_pool_str = [
  '124393780771528474299654469',
  '38440119331842498607318',
];

const dai_weth_decimals_str = ['18', '18'];

const value = poolTokensToAuto(dai_weth_pool_str, dai_weth_decimals_str);
console.log(value);
// "3236.04044"

const opts {
    reverse: true;
}
const value = poolTokensToAuto(dai_weth_pool_str, dai_weth_decimals_str, opts);
console.log(value);
// "0.00030902"

Token Formatting

tokenToSignificant(tokenQuantity, tokenDecimals, optOptions)

Calculates the value of token quantity to significant digits, default of significant digits is 5.

tokenToSignificant() is better suited for values that are bellow 1.

  • tokenQuantity {number|string|bigint} The quantity of tokens to be formatted.
  • tokenDecimals {number|string} How many decimals this token has.
  • optOptions {Object=} An object with calculation options, read more about available options here.
  • Returns {string} Formatted token.
const { tokenToSignificant } = require('@thanpolas/crypto-utils');

const tokenQuantity = '2083278970151697065687';
const decimals = 18;

const value = tokenToSignificant(tokenQuantity, decimals);
console.log(value);
// "2083.3"

const opts = { decimalPlaces: 7 };
const value = tokenToSignificant(tokenQuantity, decimals, opts);
console.log(value);
// "2083.279"

tokenToFixed(tokenQuantity, tokenDecimals, optOptions)

Calculates the value of token quantity with fixed decimal digits, default of decimal digits is 5.

tokenToFixed() is better suited for values that are above 1.

  • tokenQuantity {number|string|bigint} The quantity of tokens to be formatted.
  • tokenDecimals {number|string} How many decimals this token has.
  • optOptions {Object=} An object with calculation options, read more about available options here.
  • Returns {string} Formatted token.
const { tokenToFixed } = require('@thanpolas/crypto-utils');

const tokenQuantity = '2083278970151697065687';
const decimals = 18;

const value = tokenToFixed(tokenQuantity, decimals);
console.log(value);
// "2083.27897"

const opts = { decimalPlaces: 7 };
const value = tokenToFixed(tokenQuantity, decimals, opts);
console.log(value);
// "2083.2789702"

tokenToAuto(tokenQuantity, tokenDecimals, optOptions)

Will automatically use toFixed() if the value is above 1 or use toSignificant() if the value is bellow 1.

  • tokenQuantity {number|string|bigint} The quantity of tokens to be formatted.
  • tokenDecimals {number|string} How many decimals this token has.
  • optOptions {Object=} An object with calculation options, read more about available options here.
  • Returns {string} Formatted token.
const { tokenToAuto } = require('@thanpolas/crypto-utils');

const tokenQuantity = '2083278970151697065687';
const decimals = 18;

const value = tokenToAuto(tokenQuantity, decimals);
console.log(value);
// "2083.27897"

const opts = { decimalPlaces: 7 };
const value = tokenToAuto(tokenQuantity, decimals, opts;
console.log(value);
// "2083.2789701"

//
// Use a quantity that's bellow 1
//
const tokenSmallQuantity = '278970151697065687';

const value = tokenToAuto(tokenSmallQuantity, decimals);
console.log(value);
// "0.27897"

const opts = { decimalPlaces: 7 };
const value = tokenToAuto(tokenSmallQuantity, decimals, opts);
console.log(value);
// "0.2789702"

Fraction Formatting

toSignificant(fraction, optOptions)

Underlying function that calculates to significant digits of a fraction.

  • fraction {Array<number|string|bigint>} The tuple fraction, an Array with two items representing the numerator and denominator.
  • optOptions {Object=} An object with calculation options, read more about available options here.
  • Returns {string} Formatted token.
const { toSignificant } = require('@thanpolas/crypto-utils');

const fraction = [1000000, 21]; // 47619.047619047619

console.log(toSignificant(fraction));
// "47619"

const opts = { decimalPlaces: 7 };
console.log(toSignificant(fraction, opts));
// "47619.05"

const opts = { decimalPlaces: 7, format: true };
console.log(toSignificant(fraction, opts));
// "47,619.05"

toFixed(fraction, optOptions)

Underlying function that calculates to fixed decimals of a fraction.

  • fraction {Array<number|string|bigint>} The tuple fraction, an Array with two items representing the numerator and denominator.
  • optOptions {Object=} An object with calculation options, read more about available options here.
  • Returns {string} Formatted token.
const { toFixed } = require('@thanpolas/crypto-utils');

const fraction = [1000000, 21]; // 47619.047619047619

console.log(toFixed(fraction));
// "47619.04762"

const opts = { decimalPlaces: 7 };
console.log(toFixed(fraction, opts));
// "47619.0476190"

const opts = { decimalPlaces: 7, format: true };
console.log(toFixed(fraction, opts));
// "47,619.0476190"

toAuto(fraction, optOptions)

Underlying function that does automatic decimal calculation and applies appropriate function. If result is above 1 then toFixed() is applied, if under 1 then toSignificant() is applied.

Tuple array items can be of type string, number or bigint.

  • fraction {Array<number|string|bigint>} The tuple fraction, an Array with two items representing the numerator and denominator.
  • optOptions {Object=} An object with calculation options, read more about available options here.
  • Returns {string} Formatted token.
const { toAuto } = require('@thanpolas/crypto-utils');

// A fraction that has a result of above 1.
const fractionAbove1 = [1000000, 21]; // 47619.047619047619

console.log(toAuto(fractionAbove1));
// "47619.05"

const opts = { decimalPlaces: 7 };
console.log(toAuto(fractionAbove1, opts));
// "47619.0476190"

const opts = { format: true };
console.log(toAuto(fractionAbove1, opts));
// "47,619.04762"

//
// A fraction that has a result of below 1.
//
const fractionBelow1 = [21, 49]; // 0.428571428571429

const value = toAuto(fractionBelow1, decimals);
console.log(value);
// "0.42857"

const opts = { decimalPlaces: 7 };
const value = toAuto(fractionBelow1, decimals, opts);
console.log(value);
// "0.4285714"

Calculation and Formatting Options

The following options are available on all functions:

  • decimalPlaces {string|number} Define how many decimal places you want the result to be. When the calculation function is "toSignificant()" then this parameter gets translated to how many significant digits should be returned.
  • reverse {boolean} Set to true to reverse the fraction before the calculation.
  • format {boolean|Array} Format the output, see next section about formatting.
  • rounding {number} Value for rounding function, default Rounding.ROUND_HALF_UP, see Roudning.

Rounding

Rounding is an enumeration of constants from Decimal.js:

Property Value Description
ROUND_UP 0 Rounds away from zero
ROUND_DOWN 1 Rounds towards zero
ROUND_CEIL 2 Rounds towards Infinity
ROUND_FLOOR 3 Rounds towards -Infinity
ROUND_HALF_UP 4 Rounds towards nearest neighbour. If equidistant, rounds away from zero
ROUND_HALF_DOWN 5 Rounds towards nearest neighbour. If equidistant, rounds towards zero
ROUND_HALF_EVEN 6 Rounds towards nearest neighbour. If equidistant, rounds towards even neighbour
ROUND_HALF_CEIL 7 Rounds towards nearest neighbour. If equidistant, rounds towards Infinity
ROUND_HALF_FLOOR 8 Rounds towards nearest neighbour. If equidistant, rounds towards -Infinity

Rounding Example

const { toFixed } = require('@thanpolas/crypto-utils');

const fraction = [21, 49]; // 0.428571428571429

//
// Default Rounding
//
const opts = {
    decimalPlaces: 3,
};
toFixed(fraction, opts);
// 0.429 - Default rounding is ROUND_HALF_UP

//
// ROUND_FLOOR Rounding
//
const opts = {
    decimalPlaces: 3,
    rounding: Rounding.ROUND_FLOOR,
};

toFixed(fraction, opts);
// 0.428 - Override rounding to ROUND_FLOOR

Formatting

The Crypto Utilities package uses the Intl.NumberFormat function to format the output when desired. By default, no formatting will be applied. Let's have a look at the formatting argument one more time:

  • optFormatting {boolean|Array=} Number formatting, read more on Formatting.

Boolean True Formatting

When a boolean true is used, the default formatting is applied:

  • Locale: en-US.
  • Options: Either maximumSignificantDigits when toSignificant() function is used, or maximumFractionDigits when toFixed() function is used. The value passed to this option is the decimal parts.
const { toFixed } = require('@thanpolas/crypto-utils');

const fraction = [1000000, 21]; // 47619.047619047619

const opts = { decimalPlaces: 7, format: true };
console.log(toFixed(fraction, opts));
// '47,619.0476190'

Array Custom Formatting

When an array is used, then you can provide one or both arguments of the Intl.NumberFormat function.

Note: Custom formatting options will override the decimal places argument.

const { toFixed } = require('@thanpolas/crypto-utils');

const fraction = [1000000, 21]; // 47619.047619047619

const opts = { decimalPlaces: 7, format: ['en-US'] };
console.log(toFixed(fraction, opts));
// '47,619.048' -- decimal places (7) gets overriden by Intl.NumberFormat!

const opts = {
    decimalPlaces: 7,
    format: ['en-US', { style: 'currency', currency: 'USD' }],
};
console.log(toFixed(fraction, opts));
// '$47,619.05' -- decimal places (7) gets overriden by Intl.NumberFormat!

const opts = {
    decimalPlaces: 7,
    format: [
        'en-US',
        { style: 'currency', currency: 'USD', maximumFractionDigits: 3 },
    ],
};
console.log(toFixed(fraction, opts));
// '$47,619.048' -- decimal places (7) gets overriden by Intl.NumberFormat!

Percentage

Percentage functions use native BigInt type.

percentage(biNum, basisPoints, optPrecision)

Calculates the percentage of a bigint number (i.e. for 100 and 5% returns 5).

  • biNum {bigint} The big integer number to calculate the percentage for.
  • basisPoints {number|string} Percent expressed with a precision of 10000 (i.e. 1% = 100).
  • optPrecision {number|string=} The precision of the percentage, default 10000.
  • Returns {bigint} The percentage number.
const { percentage } = require('@thanpolas/crypto-utils');

const biNum = BigInt(100);

const percentageRes = percentage(biNum, 500);
console.log(value);
// 5n

const percentageRes = percentage(biNum, 50);
console.log(value); // Bigints have no decimals
// 0n

percentRemainder(biNum, basisPoints, optPrecision)

Calculates the percent remainder of a bigint number (i.e. for 100 and 5% returns 95).

  • biNum {bigint} The big integer number to calculate the percentage for.
  • basisPoints {number|string} Percent expressed with a precision of 10000 (i.e. 1% = 100).
  • optPrecision {number|string=} The precision of the percentage, default 10000.
  • Returns {bigint} The percentage number.
const { percentRemainder } = require('@thanpolas/crypto-utils');

const biNum = BigInt(100);

const percentRemainderRes = percentRemainder(biNum, 500);
console.log(value);
// 95n

const percentRemainderRes = percentRemainder(biNum, 50);
console.log(value); // Bigints have no decimals
// 100n

Available Utility Functions

The crypto-utils exposes a few utility functions for more low-level calculations:

  • expDecs(decimals) Will return the exponent of the given decimals number.
  • biConv(value) Will safely convert any value to JSBI and not touch values that are of JSBI type.

Maintenance & Development

Update Node Version

When a new node version is available you need to updated it in the following:

  • /package.json
  • /.nvmrc
  • /.circleci/config.yml

Releasing

  1. Update the changelog bellow ("Release History").
  2. Ensure you are on master and your repository is clean.
  3. Type: npm run release for patch version jump.
    • npm run release:minor for minor version jump.
    • npm run release:major for major major jump.

Release History

  • v0.4.1, 20 Oct 2021
    • Fixed typo of percentRemainder() function (was "percentRemainter"), thanks vfat.
  • v0.4.0, 20 Oct 2021
  • v0.3.1, 22 Aug 2021
  • v0.3.0, 21 Aug 2021
    • Implemented the new poolTokensToAuto() to calculate pooled tokens ratios.
    • Breaking Moved all options in an object argument.
    • Introduced the reverse option to reverse numerator and denominator in fractions before division.
    • Forgot to add documentation for toAuto(), now done.
    • Changed default decimal places on auto functions to 5 for both toFixed and toSignificant calls.
  • v0.2.0, 18 Aug 2021
    • Breaking renamed tokenAuto to tokenToAuto.
    • Added formatting argument on all methods.
    • Created toAuto() function for fractions.
    • More tests, especially for fractions.
    • More lax node engine setting (set to >=12).
  • v0.1.1, 17 Aug 2021
    • Fixed and tweaked README badges.
  • v0.1.0, 17 Aug 2021
    • Big Bang

Acknowledgements & Credits

This library was inspired from Uniswap SDK core.

License

Copyright © Thanos Polychronakis and Authors, Licensed under ISC.