UNPKG

@aeternity/aepp-sdk

Version:
127 lines (113 loc) 4.44 kB
/* * ISC License (ISC) * Copyright (c) 2018 aeternity developers * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /** * Amount Formatter * @module @aeternity/aepp-sdk/es/utils/amount-formatter * @example import { AmountFormatter } from '@aeternity/aepp-sdk' */ import BigNumber from 'bignumber.js' import { isBigNumber } from './bignumber' /** * AE amount formats */ export const AE_AMOUNT_FORMATS = { AE: 'ae', MILI_AE: 'miliAE', MICRO_AE: 'microAE', NANO_AE: 'nanoAE', PICO_AE: 'picoAE', FEMTO_AE: 'femtoAE', AETTOS: 'aettos' } /** * DENOMINATION_MAGNITUDE */ export const DENOMINATION_MAGNITUDE = { [AE_AMOUNT_FORMATS.AE]: 0, [AE_AMOUNT_FORMATS.MILI_AE]: -3, [AE_AMOUNT_FORMATS.MICRO_AE]: -6, [AE_AMOUNT_FORMATS.NANO_AE]: -9, [AE_AMOUNT_FORMATS.PICO_AE]: -12, [AE_AMOUNT_FORMATS.FEMTO_AE]: -15, [AE_AMOUNT_FORMATS.AETTOS]: -18 } /** * Convert amount to AE * @param {String|Number|BigNumber} value amount to convert * @param {Object} [options={}] options * @param {String} [options.denomination='aettos'] denomination of amount, can be ['ae', 'aettos'] * @return {String} */ export const toAe = ( value: string | number | BigNumber, { denomination = AE_AMOUNT_FORMATS.AETTOS } = {} ): string => formatAmount(value, { denomination, targetDenomination: AE_AMOUNT_FORMATS.AE }) /** * Convert amount to aettos * @param {String|Number|BigNumber} value amount to convert * @param {Object} [options={}] options * @param {String} [options.denomination='ae'] denomination of amount, can be ['ae', 'aettos'] * @return {String} */ export const toAettos = ( value: string | number | BigNumber, { denomination = AE_AMOUNT_FORMATS.AE } = {} ): string => formatAmount(value, { denomination }) /** * Convert amount from one to other denomination * @param {String|Number|BigNumber} value amount to convert * @param {Object} [options={}] options * @param {String} [options.denomination='aettos'] denomination of amount, can be ['ae', 'aettos'] * @param {String} [options.targetDenomination='aettos'] target denomination, can be ['ae', 'aettos'] * @return {String} */ export const formatAmount = ( value: string | number | BigNumber, { denomination = AE_AMOUNT_FORMATS.AETTOS, targetDenomination = AE_AMOUNT_FORMATS.AETTOS } = {} ): string => { const denominations = Object.values(AE_AMOUNT_FORMATS) if (!denominations.includes(denomination)) throw new Error(`Invalid denomination: ${denomination}`) if (!denominations.includes(targetDenomination)) throw new Error(`Invalid target denomination: ${targetDenomination}`) if (!isBigNumber(value)) throw new Error(`Value ${value.toString()} is not type of number`) return new BigNumber(value) .shiftedBy(DENOMINATION_MAGNITUDE[denomination] - DENOMINATION_MAGNITUDE[targetDenomination]) .toFixed() } interface Prefix { name: string magnitude: number } const prefixes: Prefix[] = [ { name: 'exa', magnitude: 18 }, { name: 'giga', magnitude: 9 }, { name: '', magnitude: 0 }, { name: 'pico', magnitude: -12 } ] const getNearestPrefix = (exponent: number): Prefix => prefixes.reduce((p, n) => ( Math.abs(n.magnitude - exponent) < Math.abs(p.magnitude - exponent) ? n : p)) const getLowerBoundPrefix = (exponent: number): Prefix => prefixes .find(p => p.magnitude <= exponent) ?? prefixes[prefixes.length - 1] export default (rawValue: string | number | BigNumber): string => { const value: BigNumber = new BigNumber(rawValue) const exp = value.e ?? 0 const { name, magnitude } = (exp < 0 ? getNearestPrefix : getLowerBoundPrefix)(exp) const v = value .shiftedBy(-magnitude) .precision(9 + Math.min(exp - magnitude, 0)) .toFixed() return `${v}${name !== '' ? ' ' : ''}${name}` }