diff --git a/development/build/index.js b/development/build/index.js index 73a2d2d21b27..304a621233bb 100755 --- a/development/build/index.js +++ b/development/build/index.js @@ -73,7 +73,6 @@ async function defineAndRunBuildTasks() { version, } = await parseArgv(); - // build lavamoat runtime file // build lavamoat runtime file await lavapack.buildRuntime({ scuttleGlobalThis: true, diff --git a/shared/modules/conversion.utils.js b/shared/modules/conversion.utils.js deleted file mode 100644 index d413ed013e97..000000000000 --- a/shared/modules/conversion.utils.js +++ /dev/null @@ -1,452 +0,0 @@ -/** - * Currency Conversion Utility - * This utility function can be used for converting currency related values within metamask. - * The caller should be able to pass it a value, along with information about the value's - * numeric base, denomination and currency, and the desired numeric base, denomination and - * currency. It should return a single value. - * - * @param {(number | string | BN)} value - The value to convert. - * @param {object} [options] - Options to specify details of the conversion - * @param {string} [options.fromCurrency = 'ETH' | 'USD'] - The currency of the passed value - * @param {string} [options.toCurrency = 'ETH' | 'USD'] - The desired currency of the result - * @param {string} [options.fromNumericBase = 'hex' | 'dec' | 'BN'] - The numeric basic of the passed value. - * @param {string} [options.toNumericBase = 'hex' | 'dec' | 'BN'] - The desired numeric basic of the result. - * @param {string} [options.fromDenomination = 'WEI'] - The denomination of the passed value - * @param {string} [options.numberOfDecimals] - The desired number of decimals in the result - * @param {string} [options.roundDown] - The desired number of decimals to round down to - * @param {number} [options.conversionRate] - The rate to use to make the fromCurrency -> toCurrency conversion - * @returns {(number | string | BN)} - * - * The utility passes value along with the options as a single object to the `converter` function. - * `converter` conditional modifies the supplied `value` property, depending - * on the accompanying options. - */ - -import BigNumber from 'bignumber.js'; - -import { addHexPrefix, BN } from 'ethereumjs-util'; -import { ETH, WEI } from '../../ui/helpers/constants/common'; - -import { stripHexPrefix } from './hexstring-utils'; - -// Big Number Constants -const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber('1000000000000000000'); -const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber('1000000000'); -const BIG_NUMBER_ETH_MULTIPLIER = new BigNumber('1'); - -// Setter Maps -const toBigNumber = { - hex: (n) => new BigNumber(stripHexPrefix(n), 16), - dec: (n) => new BigNumber(String(n), 10), - BN: (n) => new BigNumber(n.toString(16), 16), -}; -const toNormalizedDenomination = { - WEI: (bigNumber) => bigNumber.div(BIG_NUMBER_WEI_MULTIPLIER), - GWEI: (bigNumber) => bigNumber.div(BIG_NUMBER_GWEI_MULTIPLIER), - ETH: (bigNumber) => bigNumber.div(BIG_NUMBER_ETH_MULTIPLIER), -}; -const toSpecifiedDenomination = { - WEI: (bigNumber) => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).round(), - GWEI: (bigNumber) => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).round(9), - ETH: (bigNumber) => bigNumber.times(BIG_NUMBER_ETH_MULTIPLIER).round(9), -}; -const baseChange = { - hex: (n) => n.toString(16), - dec: (n) => new BigNumber(n).toString(10), - BN: (n) => new BN(n.toString(16)), -}; - -// Utility function for checking base types -const isValidBase = (base) => { - return Number.isInteger(base) && base > 1; -}; - -/** - * Defines the base type of numeric value - * - * @typedef {('hex' | 'dec' | 'BN')} NumericBase - */ - -/** - * Defines which type of denomination a value is in - * - * @typedef {('WEI' | 'GWEI' | 'ETH')} EthDenomination - */ - -/** - * Utility method to convert a value between denominations, formats and currencies. - * - * @param {object} input - * @param {string | BigNumber} input.value - * @param {NumericBase} input.fromNumericBase - * @param {EthDenomination} [input.fromDenomination] - * @param {string} [input.fromCurrency] - * @param {NumericBase} input.toNumericBase - * @param {EthDenomination} [input.toDenomination] - * @param {string} [input.toCurrency] - * @param {number} [input.numberOfDecimals] - * @param {number} [input.conversionRate] - * @param {boolean} [input.invertConversionRate] - * @param {string} [input.roundDown] - */ -const converter = ({ - value, - fromNumericBase, - fromDenomination, - fromCurrency, - toNumericBase, - toDenomination, - toCurrency, - numberOfDecimals, - conversionRate, - invertConversionRate, - roundDown, -}) => { - let convertedValue = fromNumericBase - ? toBigNumber[fromNumericBase](value) - : value; - - if (fromDenomination) { - convertedValue = toNormalizedDenomination[fromDenomination](convertedValue); - } - - if (fromCurrency !== toCurrency) { - if (conversionRate === null || conversionRate === undefined) { - throw new Error( - `Converting from ${fromCurrency} to ${toCurrency} requires a conversionRate, but one was not provided`, - ); - } - let rate = toBigNumber.dec(conversionRate); - if (invertConversionRate) { - rate = new BigNumber(1.0).div(conversionRate); - } - convertedValue = convertedValue.times(rate); - } - - if (toDenomination) { - convertedValue = toSpecifiedDenomination[toDenomination](convertedValue); - } - - if (numberOfDecimals !== undefined && numberOfDecimals !== null) { - convertedValue = convertedValue.round( - numberOfDecimals, - BigNumber.ROUND_HALF_DOWN, - ); - } - - if (roundDown) { - convertedValue = convertedValue.round(roundDown, BigNumber.ROUND_DOWN); - } - - if (toNumericBase) { - convertedValue = baseChange[toNumericBase](convertedValue); - } - return convertedValue; -}; - -const conversionUtil = ( - value, - { - fromCurrency = null, - toCurrency = fromCurrency, - fromNumericBase, - toNumericBase, - fromDenomination, - toDenomination, - numberOfDecimals, - conversionRate, - invertConversionRate, - }, -) => { - if (fromCurrency !== toCurrency && !conversionRate) { - return 0; - } - return converter({ - fromCurrency, - toCurrency, - fromNumericBase, - toNumericBase, - fromDenomination, - toDenomination, - numberOfDecimals, - conversionRate, - invertConversionRate, - value: value || '0', - }); -}; - -const getBigNumber = (value, base) => { - if (!isValidBase(base)) { - throw new Error('Must specify valid base'); - } - - // We don't include 'number' here, because BigNumber will throw if passed - // a number primitive it considers unsafe. - if (typeof value === 'string' || value instanceof BigNumber) { - return new BigNumber(value, base); - } - - return new BigNumber(String(value), base); -}; - -const addCurrencies = (a, b, options = {}) => { - const { aBase, bBase, ...conversionOptions } = options; - - if (!isValidBase(aBase) || !isValidBase(bBase)) { - throw new Error('Must specify valid aBase and bBase'); - } - - const value = getBigNumber(a, aBase).add(getBigNumber(b, bBase)); - - return converter({ - value, - ...conversionOptions, - }); -}; - -const subtractCurrencies = (a, b, options = {}) => { - const { aBase, bBase, ...conversionOptions } = options; - - if (!isValidBase(aBase) || !isValidBase(bBase)) { - throw new Error('Must specify valid aBase and bBase'); - } - - const value = getBigNumber(a, aBase).minus(getBigNumber(b, bBase)); - - return converter({ - value, - ...conversionOptions, - }); -}; - -const multiplyCurrencies = (a, b, options = {}) => { - const { multiplicandBase, multiplierBase, ...conversionOptions } = options; - - if (!isValidBase(multiplicandBase) || !isValidBase(multiplierBase)) { - throw new Error('Must specify valid multiplicandBase and multiplierBase'); - } - - const value = getBigNumber(a, multiplicandBase).times( - getBigNumber(b, multiplierBase), - ); - - return converter({ - value, - ...conversionOptions, - }); -}; - -const divideCurrencies = (a, b, options = {}) => { - const { dividendBase, divisorBase, ...conversionOptions } = options; - - if (!isValidBase(dividendBase) || !isValidBase(divisorBase)) { - throw new Error('Must specify valid dividendBase and divisorBase'); - } - - const value = getBigNumber(a, dividendBase).div(getBigNumber(b, divisorBase)); - - return converter({ - value, - ...conversionOptions, - }); -}; - -const conversionGreaterThan = ({ ...firstProps }, { ...secondProps }) => { - const firstValue = converter({ ...firstProps }); - const secondValue = converter({ ...secondProps }); - - return firstValue.gt(secondValue); -}; - -const conversionLessThan = ({ ...firstProps }, { ...secondProps }) => { - const firstValue = converter({ ...firstProps }); - const secondValue = converter({ ...secondProps }); - - return firstValue.lt(secondValue); -}; - -const conversionMax = ({ ...firstProps }, { ...secondProps }) => { - const firstIsGreater = conversionGreaterThan( - { ...firstProps }, - { ...secondProps }, - ); - - return firstIsGreater ? firstProps.value : secondProps.value; -}; - -const conversionGTE = ({ ...firstProps }, { ...secondProps }) => { - const firstValue = converter({ ...firstProps }); - const secondValue = converter({ ...secondProps }); - return firstValue.greaterThanOrEqualTo(secondValue); -}; - -const conversionLTE = ({ ...firstProps }, { ...secondProps }) => { - const firstValue = converter({ ...firstProps }); - const secondValue = converter({ ...secondProps }); - return firstValue.lessThanOrEqualTo(secondValue); -}; - -const toNegative = (n, options = {}) => { - return multiplyCurrencies(n, -1, options); -}; - -function decGWEIToHexWEI(decGWEI) { - return conversionUtil(decGWEI, { - fromNumericBase: 'dec', - toNumericBase: 'hex', - fromDenomination: 'GWEI', - toDenomination: 'WEI', - }); -} - -export function subtractHexes(aHexWEI, bHexWEI) { - return subtractCurrencies(aHexWEI, bHexWEI, { - aBase: 16, - bBase: 16, - toNumericBase: 'hex', - numberOfDecimals: 6, - }); -} - -export function addHexes(aHexWEI, bHexWEI) { - return addCurrencies(aHexWEI, bHexWEI, { - aBase: 16, - bBase: 16, - toNumericBase: 'hex', - numberOfDecimals: 6, - }); -} - -export function decWEIToDecETH(hexWEI) { - return conversionUtil(hexWEI, { - fromNumericBase: 'dec', - toNumericBase: 'dec', - fromDenomination: 'WEI', - toDenomination: 'ETH', - }); -} - -export function hexWEIToDecETH(hexWEI) { - return conversionUtil(hexWEI, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromDenomination: 'WEI', - toDenomination: 'ETH', - }); -} - -export function decEthToConvertedCurrency( - ethTotal, - convertedCurrency, - conversionRate, -) { - return conversionUtil(ethTotal, { - fromNumericBase: 'dec', - toNumericBase: 'dec', - fromCurrency: 'ETH', - toCurrency: convertedCurrency, - numberOfDecimals: 2, - conversionRate, - }); -} - -export function getWeiHexFromDecimalValue({ - value, - fromCurrency, - conversionRate, - fromDenomination, - invertConversionRate, -}) { - return conversionUtil(value, { - fromNumericBase: 'dec', - toNumericBase: 'hex', - toCurrency: ETH, - fromCurrency, - conversionRate, - invertConversionRate, - fromDenomination, - toDenomination: WEI, - }); -} - -/** - * Converts a BN object to a hex string with a '0x' prefix - * - * @param {BN} inputBn - The BN to convert to a hex string - * @returns {string} A '0x' prefixed hex string - */ -export function bnToHex(inputBn) { - return addHexPrefix(inputBn.toString(16)); -} - -export function getValueFromWeiHex({ - value, - fromCurrency = ETH, - toCurrency, - conversionRate, - numberOfDecimals, - toDenomination, -}) { - return conversionUtil(value, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromCurrency, - toCurrency, - numberOfDecimals, - fromDenomination: WEI, - toDenomination, - conversionRate, - }); -} - -export function sumHexes(...args) { - const total = args.reduce((acc, hexAmount) => { - return addCurrencies(acc, hexAmount, { - toNumericBase: 'hex', - aBase: 16, - bBase: 16, - }); - }); - - return addHexPrefix(total); -} - -export function hexWEIToDecGWEI(decGWEI) { - return conversionUtil(decGWEI, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromDenomination: 'WEI', - toDenomination: 'GWEI', - }); -} - -export function decimalToHex(decimal) { - return conversionUtil(decimal, { - fromNumericBase: 'dec', - toNumericBase: 'hex', - }); -} - -export function hexToDecimal(hexValue) { - return conversionUtil(hexValue, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - }); -} - -export { - conversionUtil, - addCurrencies, - multiplyCurrencies, - conversionGreaterThan, - conversionLessThan, - conversionGTE, - conversionLTE, - conversionMax, - toNegative, - subtractCurrencies, - decGWEIToHexWEI, - toBigNumber, - toNormalizedDenomination, - divideCurrencies, -}; diff --git a/shared/modules/conversion.utils.test.js b/shared/modules/conversion.utils.test.js index c6b064a94f8e..c3f2b6a92bad 100644 --- a/shared/modules/conversion.utils.test.js +++ b/shared/modules/conversion.utils.test.js @@ -1,212 +1,11 @@ -import BigNumber from 'bignumber.js'; -import { ETH } from '../../ui/helpers/constants/common'; +import { EtherDenomination } from '../constants/common'; import { - addCurrencies, - conversionUtil, decWEIToDecETH, - divideCurrencies, getValueFromWeiHex, getWeiHexFromDecimalValue, } from './conversion.utils'; describe('conversion utils', () => { - describe('addCurrencies()', () => { - it('add whole numbers', () => { - const result = addCurrencies(3, 9, { - aBase: 10, - bBase: 10, - }); - expect(result.toNumber()).toStrictEqual(12); - }); - - it('add decimals', () => { - const result = addCurrencies(1.3, 1.9, { - aBase: 10, - bBase: 10, - }); - expect(result.toNumber()).toStrictEqual(3.2); - }); - - it('add repeating decimals', () => { - const result = addCurrencies(1 / 3, 1 / 9, { - aBase: 10, - bBase: 10, - }); - expect(result.toNumber()).toStrictEqual(0.4444444444444444); - }); - }); - - describe('conversionUtil', () => { - it('returns expected types', () => { - const conv1 = conversionUtil(1000000000000000000, { - fromNumericBase: 'dec', - toNumericBase: 'hex', - }); - const conv2 = conversionUtil(1, { - fromNumericBase: 'dec', - fromDenomination: 'ETH', - toDenomination: 'WEI', - }); - expect(typeof conv1 === 'string').toStrictEqual(true); - expect(conv2 instanceof BigNumber).toStrictEqual(true); - }); - it('converts from dec to hex', () => { - expect( - conversionUtil('1000000000000000000', { - fromNumericBase: 'dec', - toNumericBase: 'hex', - }), - ).toStrictEqual('de0b6b3a7640000'); - expect( - conversionUtil('1500000000000000000', { - fromNumericBase: 'dec', - toNumericBase: 'hex', - }), - ).toStrictEqual('14d1120d7b160000'); - }); - it('converts hex formatted numbers to dec', () => { - expect( - conversionUtil('0xde0b6b3a7640000', { - fromNumericBase: 'hex', - toNumericBase: 'dec', - }), - ).toStrictEqual('1000000000000000000'); - expect( - conversionUtil('0x14d1120d7b160000', { - fromNumericBase: 'hex', - toNumericBase: 'dec', - }), - ).toStrictEqual('1500000000000000000'); - }); - it('converts WEI to ETH', () => { - expect( - conversionUtil('0xde0b6b3a7640000', { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromDenomination: 'WEI', - toDenomination: 'ETH', - }), - ).toStrictEqual('1'); - expect( - conversionUtil('0x14d1120d7b160000', { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromDenomination: 'WEI', - toDenomination: 'ETH', - }), - ).toStrictEqual('1.5'); - }); - it('converts ETH to WEI', () => { - expect( - conversionUtil('1', { - fromNumericBase: 'dec', - fromDenomination: 'ETH', - toDenomination: 'WEI', - }).toNumber(), - ).toStrictEqual(1000000000000000000); - expect( - conversionUtil('1.5', { - fromNumericBase: 'dec', - fromDenomination: 'ETH', - toDenomination: 'WEI', - }).toNumber(), - ).toStrictEqual(1500000000000000000); - }); - it('converts ETH to GWEI', () => { - expect( - conversionUtil('1', { - fromNumericBase: 'dec', - fromDenomination: 'ETH', - toDenomination: 'GWEI', - }).toNumber(), - ).toStrictEqual(1000000000); - expect( - conversionUtil('1.5', { - fromNumericBase: 'dec', - fromDenomination: 'ETH', - toDenomination: 'GWEI', - }).toNumber(), - ).toStrictEqual(1500000000); - }); - it('converts ETH to USD', () => { - expect( - conversionUtil('1', { - fromNumericBase: 'dec', - toNumericBase: 'dec', - toCurrency: 'usd', - conversionRate: 468.58, - numberOfDecimals: 2, - }), - ).toStrictEqual('468.58'); - expect( - conversionUtil('1.5', { - fromNumericBase: 'dec', - toNumericBase: 'dec', - toCurrency: 'usd', - conversionRate: 468.58, - numberOfDecimals: 2, - }), - ).toStrictEqual('702.87'); - }); - it('converts USD to ETH', () => { - expect( - conversionUtil('468.58', { - fromNumericBase: 'dec', - toNumericBase: 'dec', - toCurrency: 'usd', - conversionRate: 468.58, - numberOfDecimals: 2, - invertConversionRate: true, - }), - ).toStrictEqual('1'); - expect( - conversionUtil('702.87', { - fromNumericBase: 'dec', - toNumericBase: 'dec', - toCurrency: 'usd', - conversionRate: 468.58, - numberOfDecimals: 2, - invertConversionRate: true, - }), - ).toStrictEqual('1.5'); - }); - }); - - describe('divideCurrencies()', () => { - it('should correctly divide decimal values', () => { - const result = divideCurrencies(9, 3, { - dividendBase: 10, - divisorBase: 10, - }); - expect(result.toNumber()).toStrictEqual(3); - }); - - it('should correctly divide hexadecimal values', () => { - const result = divideCurrencies(1000, 0xa, { - dividendBase: 16, - divisorBase: 16, - }); - expect(result.toNumber()).toStrictEqual(0x100); - }); - - it('should correctly divide hexadecimal value from decimal value', () => { - const result = divideCurrencies(0x3e8, 0xa, { - dividendBase: 16, - divisorBase: 16, - }); - expect(result.toNumber()).toStrictEqual(0x100); - }); - - it('should throw error for wrong base value', () => { - expect(() => { - divideCurrencies(0x3e8, 0xa, { - dividendBase: 10.5, - divisorBase: 7, - }); - }).toThrow('Must specify valid dividendBase and divisorBase'); - }); - }); - describe('decWEIToDecETH', () => { it('converts 10000000000000 WEI to ETH', () => { const ethDec = decWEIToDecETH('10000000000000'); @@ -223,11 +22,18 @@ describe('conversion utils', () => { it('should correctly convert 0 in ETH', () => { const weiValue = getWeiHexFromDecimalValue({ value: '0', - fromCurrency: ETH, - fromDenomination: ETH, + fromDenomination: EtherDenomination.ETH, }); expect(weiValue).toStrictEqual('0'); }); + + it('should correctly convert 10 in ETH to 8ac7230489e80000 (10000000000000000000) wei', () => { + const weiValue = getWeiHexFromDecimalValue({ + value: '10', + fromDenomination: EtherDenomination.ETH, + }); + expect(weiValue).toStrictEqual('8ac7230489e80000'); + }); }); describe('getValueFromWeiHex', () => { @@ -235,7 +41,6 @@ describe('conversion utils', () => { const ethTransactionAmount = getValueFromWeiHex({ value: '0xde0b6b3a7640000', toCurrency: 'ETH', - conversionRate: 468.58, numberOfDecimals: 6, }); diff --git a/shared/modules/conversion.utils.ts b/shared/modules/conversion.utils.ts new file mode 100644 index 000000000000..e2466bcabb1a --- /dev/null +++ b/shared/modules/conversion.utils.ts @@ -0,0 +1,172 @@ +import { BigNumber } from 'bignumber.js'; + +import { addHexPrefix, BN } from 'ethereumjs-util'; +import { EtherDenomination } from '../constants/common'; +import { Numeric, NumericValue } from './Numeric'; + +export function decGWEIToHexWEI(decGWEI: number) { + return new Numeric(decGWEI, 10, EtherDenomination.GWEI) + .toBase(16) + .toDenomination(EtherDenomination.WEI) + .toString(); +} + +export function subtractHexes(aHexWEI: string, bHexWEI: string) { + return new Numeric(aHexWEI, 16) + .minus(new Numeric(bHexWEI, 16)) + .round(6, BigNumber.ROUND_HALF_DOWN) + .toString(); +} + +export function addHexes(aHexWEI: string, bHexWEI: string) { + return new Numeric(aHexWEI, 16) + .add(new Numeric(bHexWEI, 16)) + .round(6, BigNumber.ROUND_HALF_DOWN) + .toString(); +} + +export function decWEIToDecETH(decWEI: string) { + return new Numeric(decWEI, 10, EtherDenomination.WEI) + .toDenomination(EtherDenomination.ETH) + .toString(); +} + +export function hexWEIToDecETH(hexWEI: string) { + return new Numeric(hexWEI, 16, EtherDenomination.WEI) + .toDenomination(EtherDenomination.ETH) + .toBase(10) + .toString(); +} + +export function decEthToConvertedCurrency( + ethTotal: NumericValue, + convertedCurrency?: string, + conversionRate?: number, +) { + let numeric = new Numeric(ethTotal, 10, EtherDenomination.ETH); + + if (convertedCurrency !== EtherDenomination.ETH) { + numeric = numeric.applyConversionRate(conversionRate); + } + + return numeric.round(2); +} + +export function getWeiHexFromDecimalValue({ + value, + conversionRate = 1, + fromDenomination, + fromCurrency, + invertConversionRate = false, +}: { + value: NumericValue; + conversionRate?: number; + fromDenomination?: EtherDenomination; + fromCurrency?: string; + invertConversionRate?: boolean; +}) { + let numeric = new Numeric(value, 10, fromDenomination); + if (fromCurrency !== EtherDenomination.ETH) { + numeric = numeric.applyConversionRate(conversionRate, invertConversionRate); + } + return numeric.toBase(16).toDenomination(EtherDenomination.WEI).toString(); +} + +/** + * Converts a BN object to a hex string with a '0x' prefix + * + * @param inputBn - The BN to convert to a hex string + * @returns A '0x' prefixed hex string + */ +export function bnToHex(inputBn: BN) { + return addHexPrefix(inputBn.toString(16)); +} + +export function getEthConversionFromWeiHex({ + value, + fromCurrency = EtherDenomination.ETH, + conversionRate, + numberOfDecimals = 6, +}: { + value: NumericValue; + conversionRate?: number; + fromCurrency?: EtherDenomination | string; + numberOfDecimals?: number; +}) { + const denominations = [ + EtherDenomination.ETH, + EtherDenomination.GWEI, + EtherDenomination.WEI, + ]; + + let nonZeroDenomination; + + for (let i = 0; i < denominations.length; i++) { + const convertedValue = getValueFromWeiHex({ + value, + conversionRate, + fromCurrency, + toCurrency: fromCurrency, + numberOfDecimals, + toDenomination: denominations[i], + }); + + if (convertedValue !== '0' || i === denominations.length - 1) { + nonZeroDenomination = `${convertedValue} ${denominations[i]}`; + break; + } + } + + return nonZeroDenomination; +} + +export function getValueFromWeiHex({ + value, + fromCurrency = EtherDenomination.ETH, + toCurrency, + conversionRate, + numberOfDecimals, + toDenomination = EtherDenomination.ETH, +}: { + value: NumericValue; + fromCurrency?: EtherDenomination | string; + toCurrency?: EtherDenomination | string; + conversionRate?: number; + numberOfDecimals?: number; + toDenomination?: EtherDenomination; +}) { + let numeric = new Numeric(value, 16, EtherDenomination.WEI); + if (fromCurrency !== toCurrency) { + numeric = numeric.applyConversionRate(conversionRate); + } + return numeric + .toBase(10) + .toDenomination(toDenomination) + .round(numberOfDecimals, BigNumber.ROUND_HALF_DOWN) + .toString(); +} + +export function sumHexes(first: string, ...args: string[]) { + const firstValue = new Numeric(first, 16); + const total = args.reduce( + (acc, hexAmount) => acc.add(new Numeric(hexAmount, 16)), + firstValue, + ); + + return total.toPrefixedHexString(); +} + +export function hexWEIToDecGWEI(value: number | string | BigNumber | BN) { + return new Numeric(value, 16, EtherDenomination.WEI) + .toBase(10) + .toDenomination(EtherDenomination.GWEI) + .toString(); +} + +export function decimalToHex(decimal: number | string | BigNumber | BN) { + return new Numeric(decimal, 10).toBase(16).toString(); +} + +export function hexToDecimal(hexValue: number | string | BigNumber | BN) { + return new Numeric(hexValue, 16).toBase(10).toString(); +}