@hyperlane-xyz/utils
Version:
General utilities and types for the Hyperlane network
143 lines • 5.8 kB
JavaScript
import { formatUnits, parseUnits } from '@ethersproject/units';
import { BigNumber } from 'bignumber.js';
const DEFAULT_DISPLAY_DECIMALS = 4;
const DEFAULT_TOKEN_DECIMALS = 18;
/**
* Convert the given Wei value to Ether value
* @param value The value to convert.
* @returns Converted value in string type.
*/
export function fromWei(value, decimals = DEFAULT_TOKEN_DECIMALS) {
if (!value)
return (0).toString();
const valueString = value.toString(10).trim();
const flooredValue = BigNumber(valueString).toFixed(0, BigNumber.ROUND_FLOOR);
return parseFloat(formatUnits(flooredValue, decimals)).toString();
}
/**
* Convert the given Wei value to Ether value,
* round to set number of decimals with a minimum floor, configured per token
* @param value The value to convert.
* @param decimals
* @returns Converted value in string type.
*/
export function fromWeiRounded(value, decimals = DEFAULT_TOKEN_DECIMALS, displayDecimals) {
if (!value)
return '0';
const flooredValue = BigNumber(value).toFixed(0, BigNumber.ROUND_FLOOR);
const amount = BigNumber(formatUnits(flooredValue, decimals));
if (amount.isZero())
return '0';
displayDecimals ??= amount.gte(10000) ? 2 : DEFAULT_DISPLAY_DECIMALS;
return amount.toFixed(displayDecimals, BigNumber.ROUND_FLOOR);
}
/**
* Convert the given value to Wei value
* @param value The value to convert.
* @returns Converted value in string type.
*/
export function toWei(value, decimals = DEFAULT_TOKEN_DECIMALS) {
if (!value)
return BigNumber(0).toString();
// First convert to a BigNumber, and then call `toString` with the
// explicit radix 10 such that the result is formatted as a base-10 string
// and not in scientific notation.
const valueBN = BigNumber(value);
const valueString = valueBN.toString(10).trim();
const components = valueString.split('.');
if (components.length === 1) {
return parseUnits(valueString, decimals).toString();
}
else if (components.length === 2) {
const trimmedFraction = components[1].substring(0, decimals);
return parseUnits(`${components[0]}.${trimmedFraction}`, decimals).toString();
}
else {
throw new Error(`Cannot convert ${valueString} to wei`);
}
}
/**
* Try to parse the given value into BigNumber.js BigNumber
* @param value The value to parse.
* @returns Parsed value in BigNumber.js BigNumber type.
*/
export function tryParseAmount(value) {
try {
if (!value)
return null;
const parsed = BigNumber(value);
if (!parsed || parsed.isNaN() || !parsed.isFinite())
return null;
else
return parsed;
}
catch {
return null;
}
}
/**
* Checks if an amount is equal of nearly equal to balance within a small margin of error
* Necessary because amounts in the UI are often rounded
* @param amount1 The amount to compare.
* @param amount2 The amount to compare.
* @returns true/false.
*/
export function eqAmountApproximate(amount1, amount2, maxDifference) {
// Is difference btwn amounts less than maxDifference
return BigNumber(amount1).minus(amount2).abs().lte(maxDifference);
}
/**
* Converts a value with `fromDecimals` decimals to a value with `toDecimals` decimals.
* Incurs a loss of precision when `fromDecimals` > `toDecimals`.
* @param fromDecimals The number of decimals `value` has.
* @param toDecimals The number of decimals to convert `value` to.
* @param value The value to convert.
* @returns `value` represented with `toDecimals` decimals in string type.
*/
export function convertDecimalsToIntegerString(fromDecimals, toDecimals, value) {
const converted = convertDecimals(fromDecimals, toDecimals, value);
return converted.integerValue(BigNumber.ROUND_FLOOR).toString(10);
}
export function convertDecimals(fromDecimals, toDecimals, value) {
const amount = BigNumber(value);
if (fromDecimals === toDecimals)
return amount;
else if (fromDecimals > toDecimals) {
const difference = fromDecimals - toDecimals;
return amount.div(BigNumber(10).pow(difference));
}
// fromDecimals < toDecimals
else {
const difference = toDecimals - fromDecimals;
return amount.times(BigNumber(10).pow(difference));
}
}
// Default gas limit buffer percentage
const DEFAULT_GAS_LIMIT_BUFFER_PERCENT = 10;
/**
* Calculates the gas limit with a buffer added to the estimated gas.
* @param estimatedGas The estimated gas for the transaction.
* @param bufferPercent The percentage to add as a buffer (default: 10%).
* @returns The calculated gas limit with the buffer added.
*/
export function addBufferToGasLimit(estimatedGas, bufferPercent = DEFAULT_GAS_LIMIT_BUFFER_PERCENT) {
const bufferMultiplier = 100 + bufferPercent;
return estimatedGas.mul(bufferMultiplier).div(100);
}
/**
* Calculates the amount from the origin chain scaled to the destination chain
* This calculation is in line with the FungibleTokenRouter contract _outboundAmount
* and _inboundAmount functions
* @param fromScale The origin scale number.
* @param toScale The destination scale number.
* @param amount The number to scale.
* @param precisionFactor Number used to get accurate conversion for smaller numbers.
* Take into account the resulting amount will be have this precision factor multiplied into it.
*/
export function convertToScaledAmount({ amount, fromScale, toScale, precisionFactor, }) {
if (!fromScale || !toScale || fromScale === toScale)
return amount * BigInt(Math.floor(precisionFactor));
const scaledAmount = amount * BigInt(Math.floor((fromScale * precisionFactor) / toScale));
return scaledAmount;
}
//# sourceMappingURL=amount.js.map