UNPKG

@xchainjs/xchain-util

Version:
796 lines (779 loc) 30 kB
import BigNumber from 'bignumber.js'; /** * Helper to delay anything within an `async` function * * @param ms delay in milliseconds * * @example * * ``` * const anyAsyncFunc = async () => { * // do something * console.log('before delay') * // wait for 200ms * await delay(200) * // and do other things * console.log('after delay') * } * ``` */ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); /** * Shortcut to create a BigNumber * * @param {string | number | BigNumber.Instance} value * @returns {BigNumber} The BigNumber interface from the given value. */ const bn = (value) => new BigNumber(value); /** * Helper to check whether a BigNumber is valid or not * * @param {BigNumber} value * @returns {boolean} `true` or `false`. * */ const isValidBN = (value) => !value.isNaN(); /** * Helper to create a big number from string or number * If it fails to create a big number, a big number with value 0 will be returned instead * * @param {string|number|undefined} value * @returns {BigNumber} The BigNumber interface from the given value. If invalid one is provided, will return `0`. * */ const bnOrZero = (value) => { const b = value ? bn(value) : bn(0); return isValidBN(b) ? b : bn(0); }; /** * Helper to validate a possible BigNumber * If the given value is invalid or undefined, 0 is returned as a BigNumber * * @param {BigNumber|undefined} value * @returns {boolean} `true` or `false`. */ const validBNOrZero = (value) => (value && isValidBN(value) ? value : bn(0)); /** * Format a BaseNumber to a string depending on given decimal places * * @param {BigNumber} value * @param {number} decimal The decimal place. (optional) * @returns {string} The formatted string from the given BigNumber and decimal place. * */ const formatBN = (value, decimal = 2) => value.toFormat(decimal); /** * The enumuration for symbol position. * `before` or `after` */ var SymbolPosition; (function (SymbolPosition) { SymbolPosition["BEFORE"] = "before"; SymbolPosition["AFTER"] = "after"; })(SymbolPosition || (SymbolPosition = {})); /** * Formats a big number value by prefixing it with `$` * * @param {BigNumber} n * @param {number} decimalPlaces The decimal place. (optional) * @param {string} symbol The currency symbol. (optional) * @param {position} position The symbol position. (optional) * @returns {string} The formatted string from the given BigNumber, decimal places, symbol and position. */ const formatBNCurrency = (n, decimalPlaces = 2, symbol = '$', position = SymbolPosition.BEFORE) => { const value = formatBN(n, decimalPlaces); if (position === SymbolPosition.BEFORE) { return `${symbol}${value}`; } return `${value}${symbol}`; }; /** * Helper to get a fixed `BigNumber` * Returns zero `BigNumber` if `value` is invalid * * @param {number|string|BigNumber|undefined} value * @param {number} decimalPlaces The decimal place. (optional) * @returns {BigNumber} The BigNumber interface from the given value and decimal. * */ const fixedBN = (value, decimalPlaces = 2) => { const n = bn(value || 0); const fixedBN = isValidBN(n) ? n.toFixed(decimalPlaces) : bn(0).toFixed(decimalPlaces); return bn(fixedBN); }; /** * Removes leading / trailing zeros from a string of numbers * (1) Regex to remove trailing zeros https://stackoverflow.com/a/53397618/2032698 * (2) Regex to remove leading zeros https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch06s06.html * * @param {string} value * @returns {string} The result after removing trailing zeros. */ const trimZeros = (value) => value // (1) remove trailing zeros .replace(/(\.[0-9]*[1-9])0+$|\.0*$/, '$1') // (2) remove leading zeros .replace(/\b0*([1-9][0-9]*|0)\b/, '$1'); var Denomination; (function (Denomination) { /** * values for asset amounts in base units (no decimal) */ Denomination["Base"] = "BASE"; /** * values of asset amounts (w/ decimal) */ Denomination["Asset"] = "ASSET"; })(Denomination || (Denomination = {})); /** * Asset type */ var AssetType; (function (AssetType) { AssetType[AssetType["NATIVE"] = 0] = "NATIVE"; AssetType[AssetType["TOKEN"] = 1] = "TOKEN"; AssetType[AssetType["SYNTH"] = 2] = "SYNTH"; AssetType[AssetType["TRADE"] = 3] = "TRADE"; AssetType[AssetType["SECURED"] = 4] = "SECURED"; })(AssetType || (AssetType = {})); /** * Guard to check whether value is a BigNumber.Value or not * * @param {unknown} v * @returns {boolean} `true` or `false`. * */ const isBigNumberValue = (v) => typeof v === 'string' || typeof v === 'number' || v instanceof BigNumber; /** * Default number of asset decimals * For history reason and by starting the project on Binance chain assets, it's 8 decimal.F * * For example: * ``` * RUNE has a maximum of 8 digits of decimal * 0.00000001 RUNE == 1 ð (tor) * ``` * */ const ASSET_DECIMAL = 8; /** * Native asset delimiter */ const NATIVE_ASSET_DELIMITER = '.'; /** * Token asset delimiter */ const TOKEN_ASSET_DELIMITER = '.'; /** * Synth asset delimiter */ const SYNTH_ASSET_DELIMITER = '/'; /** * Trade asset delimiter */ const TRADE_ASSET_DELIMITER = '~'; /** * Secured asset delimiter */ const SECURED_ASSET_DELIMITER = '-'; /** * Factory to create values of assets (e.g. RUNE) * * @param {string|number|BigNumber|undefined} value - The asset amount, If the value is undefined, AssetAmount with value `0` will be returned. * @param {number} decimal The decimal places. (optional) * @returns {AssetAmount} The asset amount from the given value and decimal. * **/ const assetAmount = (value, decimal = ASSET_DECIMAL) => { const amount = fixedBN(value, decimal); return { type: Denomination.Asset, amount: () => amount, plus: (v, d = decimal) => assetAmount(amount.plus(isBigNumberValue(v) ? v : v.amount()), d), minus: (v, d = decimal) => assetAmount(amount.minus(isBigNumberValue(v) ? v : v.amount()), d), times: (v, d = decimal) => assetAmount(amount.times(isBigNumberValue(v) ? v : v.amount()), d), div: (v, d = decimal) => assetAmount(amount.div(isBigNumberValue(v) ? v : v.amount()), d), lt: (v) => amount.lt(isBigNumberValue(v) ? v : v.amount()), lte: (v) => amount.lte(isBigNumberValue(v) ? v : v.amount()), gt: (v) => amount.gt(isBigNumberValue(v) ? v : v.amount()), gte: (v) => amount.gte(isBigNumberValue(v) ? v : v.amount()), eq: (v) => amount.eq(isBigNumberValue(v) ? v : v.amount()), decimal, }; }; /** * Factory to create base amounts (e.g. tor) * * @param {string|number|BigNumber|undefined} value - The base amount, If the value is undefined, BaseAmount with value `0` will be returned. * @param {number} decimal The decimal places of its associated AssetAmount. (optional) * @returns {BaseAmount} The base amount from the given value and decimal. **/ const baseAmount = (value, decimal = ASSET_DECIMAL) => { const amount = fixedBN(value, 0); return { type: Denomination.Base, amount: () => amount, plus: (v, d = decimal) => baseAmount(amount.plus(isBigNumberValue(v) ? v : v.amount()), d), minus: (v, d = decimal) => baseAmount(amount.minus(isBigNumberValue(v) ? v : v.amount()), d), times: (v, d = decimal) => baseAmount(amount.times(isBigNumberValue(v) ? v : v.amount()), d), div: (v, d = decimal) => baseAmount(amount.div(isBigNumberValue(v) ? v : v.amount()).decimalPlaces(0, BigNumber.ROUND_DOWN), d), lt: (v) => amount.lt(isBigNumberValue(v) ? v : v.amount()), lte: (v) => amount.lte(isBigNumberValue(v) ? v : v.amount()), gt: (v) => amount.gt(isBigNumberValue(v) ? v : v.amount()), gte: (v) => amount.gte(isBigNumberValue(v) ? v : v.amount()), eq: (v) => amount.eq(isBigNumberValue(v) ? v : v.amount()), decimal, }; }; /** * Helper to convert values for a asset from base values (e.g. RUNE from tor) * * @param {BaseAmount} base * @returns {AssetAmount} The asset amount from the given base amount. * */ const baseToAsset = (base) => { const decimal = base.decimal; const value = base .amount() .div(Math.pow(10, decimal)) .decimalPlaces(decimal); return assetAmount(value, decimal); }; /** * Helper to convert asset to base values (e.g. tor -> RUNE) * * @param {AssetAmount} asset * @returns {BaseAmount} The base amount from the given AssetAmount. * */ const assetToBase = (asset) => { const value = asset .amount() .multipliedBy(Math.pow(10, asset.decimal)) .integerValue(); return baseAmount(value, asset.decimal); }; /** * Guard to check whether value is an amount of asset or not * * @param {Amount<Denomination>} v * @returns {boolean} `true` or `false`. * */ const isAssetAmount = (v) => v.type === Denomination.Asset; /** * Guard to check whether value is an amount of a base value or not * * @param {Amount<Denomination>} v * @returns {boolean} `true` or `false`. * */ const isBaseAmount = (v) => v.type === Denomination.Base; /** * Formats an `AssetAmount` into `string` based on decimal places * * If `decimal` is not set, `amount.decimal` is used * Note: `trimZeros` wins over `decimal` * * @param {Params} param The asset amount format options. * @returns {string} The formatted asset amount string from the given options. */ const formatAssetAmount = ({ amount, decimal, trimZeros: trimZeros$1 = false, }) => { // strict check for `undefined` value as negate of 0 will return true and passed decimal value will be ignored const formatted = formatBN(amount.amount(), decimal === undefined ? amount.decimal : decimal); // Note: `trimZeros` wins over `decimal` return trimZeros$1 ? trimZeros(formatted) : formatted; }; /** * Formats a `BaseAmount` value into a `string` * * @param {BaseAmount} amount * @returns {string} The formatted base amount string from the given base amount. */ const formatBaseAmount = (amount) => formatBN(amount.amount(), 0); /** * Base "chain" asset on bitcoin main net. * * Based on definition in Thorchain `common` * @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24 */ const AssetBTC = { chain: 'BTC', symbol: 'BTC', ticker: 'BTC', type: AssetType.NATIVE }; /** * Base "chain" asset on ethereum main net. * * Based on definition in Thorchain `common` * @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24 */ const AssetETH = { chain: 'ETH', symbol: 'ETH', ticker: 'ETH', type: AssetType.NATIVE }; /** * Helper to check whether asset is valid * * @param {Asset} asset * @returns {boolean} `true` or `false` */ const isValidAsset = (asset) => !!asset.chain && !!asset.ticker && !!asset.symbol; /** * Helper to check whether an asset is synth asset * * @param {Asset} asset * @returns {boolean} `true` or `false` */ const isSynthAsset = (asset) => asset.type === AssetType.SYNTH; /** * Helper to check whether an asset is trade asset * * @param {AnyAsset} asset * @returns {boolean} `true` or `false` */ const isTradeAsset = (asset) => asset.type === AssetType.TRADE; /** * Helper to check whether an asset is secured asset * * @param {AnyAsset} asset * @returns {boolean} `true` or `false` */ const isSecuredAsset = (asset) => asset.type === AssetType.SECURED; /** * * @param {AnyAsset} asset * @returns {boolean} `true` or `false` */ const isTokenAsset = (asset) => asset.type === AssetType.TOKEN; /** * Creates an `Asset` by a given string * * This helper function expects a string with following naming convention: * `AAA.BBB-CCC` * where * chain: `AAA` * ticker (optional): `BBB` * symbol: `BBB-CCC` or `CCC` (if no ticker available) * * @see https://docs.thorchain.org/developers/transaction-memos#asset-notation * * If the naming convention fails, it returns null * * @param {string} s The given string. * @returns {Asset|null} The asset from the given string. */ const assetConfigs = new Map([ ['KUJI.USK', { chain: 'KUJI', symbol: 'USK', ticker: 'USK', type: AssetType.TOKEN }], ['MAYA.MAYA', { chain: 'MAYA', symbol: 'MAYA', ticker: 'MAYA', type: AssetType.TOKEN }], ['RUNE', { chain: 'THOR', symbol: 'RUNE', ticker: 'RUNE', type: AssetType.NATIVE }], ['X/RUJI', { chain: 'THOR', symbol: 'RUJI', ticker: 'RUJI', type: AssetType.NATIVE }], ]); // Helper function to create an asset from its components const createAsset = (chain, symbol, ticker, type) => { return { chain, symbol, ticker, type }; }; const assetFromString = (s) => { if (!s || s.trim() === '') return null; // Handle empty strings // Check if the asset is directly in the assetConfigs const directAsset = assetConfigs.get(s); if (directAsset) return directAsset; // Define asset delimiters for the first delimiter const assetDelimiters = { '.': AssetType.NATIVE, '/': AssetType.SYNTH, '~': AssetType.TRADE, '-': AssetType.SECURED, }; // Identify the first delimiter in the string const firstDelimiter = Object.keys(assetDelimiters).find((delim) => s.includes(delim)); if (!firstDelimiter) return null; // Split the string into chain and symbol part based on the first delimiter const [chain, ...restParts] = s.split(firstDelimiter); if (!chain || restParts.length === 0) return null; // Invalid format or empty parts // Handle secured and trade assets which may have further splits const symbol = restParts.join(firstDelimiter); let ticker = symbol.split('-')[0]; // For secured and trade assets, handle contract address as part of the symbol const type = assetDelimiters[firstDelimiter]; // Check if symbol is empty (e.g., BNB. or AVAX~ cases) if (symbol === '') return null; // Handle trade and secured assets if (firstDelimiter === '~' || firstDelimiter === '-' || firstDelimiter === '/') { return createAsset(chain.trim(), symbol.trim(), ticker.trim(), type); } // Handle token assets: if the symbol has more than one part (split by `-`) if (symbol.includes('-')) { const [primaryTicker] = symbol.split('-'); ticker = primaryTicker; // For token assets, use the contract address return createAsset(chain.trim(), symbol.trim(), ticker.trim(), AssetType.TOKEN); } // For native, synth, or other types of assets return createAsset(chain.trim(), symbol.trim(), ticker.trim(), type); }; /** * Similar to an `assetFromString`, but throws an exception for invalid asset strings */ const assetFromStringEx = (s) => { const asset = assetFromString(s); if (!asset) throw Error('asset string not correct'); return asset; }; /** * Returns an `Asset` as a string using following naming convention: * * `AAA.BBB-CCC` * where * chain: `AAA` * ticker (optional): `BBB` * symbol: `BBB-CCC` or `CCC` (if no ticker available) * symbol (synth): `BBB/CCC` or `CCC` (if no ticker available) * * @see https://docs.thorchain.org/developers/transaction-memos#asset-notation * * @param {Asset} asset The given asset. * @returns {string} The string from the given asset. */ const assetToString = ({ chain, symbol, type }) => { switch (type) { case AssetType.SYNTH: return `${chain}${SYNTH_ASSET_DELIMITER}${symbol}`; case AssetType.TOKEN: return `${chain}${TOKEN_ASSET_DELIMITER}${symbol}`; case AssetType.TRADE: return `${chain}${TRADE_ASSET_DELIMITER}${symbol}`; case AssetType.SECURED: return `${chain}${SECURED_ASSET_DELIMITER}${symbol}`; default: return `${chain}${NATIVE_ASSET_DELIMITER}${symbol}`; } }; /** * Currency symbols currently supported */ var AssetCurrencySymbol; (function (AssetCurrencySymbol) { AssetCurrencySymbol["RUNE"] = "\u16B1"; AssetCurrencySymbol["BTC"] = "\u20BF"; AssetCurrencySymbol["SATOSHI"] = "\u26A1"; AssetCurrencySymbol["ETH"] = "\u039E"; AssetCurrencySymbol["USD"] = "$"; AssetCurrencySymbol["DASH"] = "\u0110"; AssetCurrencySymbol["LTC"] = "\u0141"; AssetCurrencySymbol["DOGE"] = "\u00D0"; AssetCurrencySymbol["CACAO"] = "\uD800\uDF02"; })(AssetCurrencySymbol || (AssetCurrencySymbol = {})); /** * Returns currency symbols by given `Asset` * * @param {Asset} asset The given asset. * @returns {string} The currency symbol from the given asset. */ const currencySymbolByAsset = ({ ticker }) => { switch (true) { case ticker === 'RUNE': return AssetCurrencySymbol.RUNE; case ticker === AssetBTC.ticker: return AssetCurrencySymbol.BTC; case ticker === AssetETH.ticker: return AssetCurrencySymbol.ETH; case ticker === 'DASH': return AssetCurrencySymbol.DASH; case ticker === 'LTC': return AssetCurrencySymbol.LTC; case ticker === 'DOGE': return AssetCurrencySymbol.DOGE; case ticker.includes('USD'): return AssetCurrencySymbol.USD; default: return ticker; } }; /** * Formats an asset amount using its currency symbol * * If `decimal` is not set, `amount.decimal` is used * If `asset` is not set, `$` will be used as currency symbol by default * `trimZeros` is `false` by default * Note: `trimZeros` wins over `decimal` * * @param {Params} params The asset amount currency format options. * @return {string} The formatted asset amount string using its currency format. */ const formatAssetAmountCurrency = ({ amount, asset, decimal, trimZeros: shouldTrimZeros = false, }) => { var _a; const amountFormatted = formatAssetAmount({ amount, // strict check for `undefined` value as negate of 0 will return true and passed decimal value will be ignored decimal: decimal === undefined ? amount.decimal : decimal, trimZeros: shouldTrimZeros, }); const ticker = (_a = asset === null || asset === void 0 ? void 0 : asset.ticker) !== null && _a !== void 0 ? _a : ''; if (ticker) { // RUNE if (ticker === 'RUNE') return `${AssetCurrencySymbol.RUNE} ${amountFormatted}`; // BTC let regex = new RegExp(AssetBTC.ticker, 'i'); if (ticker.match(regex)) { const base = assetToBase(amount); // format all < ₿ 0.01 in statoshi if (base.amount().isLessThanOrEqualTo('1000000')) { return `${AssetCurrencySymbol.SATOSHI} ${formatBaseAmount(base)}`; } return `${AssetCurrencySymbol.BTC} ${amountFormatted}`; } // ETH regex = new RegExp(AssetETH.ticker, 'i'); if (ticker.match(regex)) return `${AssetCurrencySymbol.ETH} ${amountFormatted}`; // LTC regex = new RegExp('LTC', 'i'); if (ticker.match(regex)) return `${AssetCurrencySymbol.LTC} ${amountFormatted}`; // DASH regex = new RegExp('DASH', 'i'); if (ticker.match(regex)) return `${AssetCurrencySymbol.DASH} ${amountFormatted}`; // DOGE regex = new RegExp('DOGE', 'i'); if (ticker.match(regex)) return `${AssetCurrencySymbol.DOGE} ${amountFormatted}`; // USD regex = new RegExp('USD', 'i'); if (ticker.match('USD')) return `${AssetCurrencySymbol.USD} ${amountFormatted}`; return `${amountFormatted} ${ticker}`; } return `$ ${amountFormatted}`; }; /** * Formats a `BaseAmount` into a string of an `AssetAmount` * * If `decimal` is not set, `amount.decimal` is used * Note: `trimZeros` wins over `decimal` * * @param {Params} params The base amount currency format options. * @return {string} The formatted base amount string using its currency format. */ const formatBaseAsAssetAmount = ({ amount, decimal, trimZeros = false, }) => formatAssetAmount({ amount: baseToAsset(amount), decimal, trimZeros }); /** * Checks equality of two `Assets` * @param {Asset} a Asset one * @param {Asset} b Asset two * @return {boolean} Result of equality check */ const eqAsset = (a, b) => a.chain === b.chain && a.symbol === b.symbol && a.ticker === b.ticker && a.type === b.type; /** * Removes `0x` or `0X` from address */ const strip0x = (addr) => addr.replace(/^0(x|X)/, ''); const getContractAddressFromAsset = (asset) => { const assetAddress = asset.symbol.slice(asset.ticker.length + 1); return strip0x(assetAddress); }; const XCHAINJS_IDENTIFIER = 'xchainjs-client'; const NINE_REALMS_CLIENT_HEADER = 'x-client-id'; /** * Middleware to add custom header to requests (9R endpoints only) * * @param request RequestArgs (rxjs/ajax) | AxiosRequestConfig (axios) * @returns RequestArgs (rxjs/ajax) | AxiosRequestConfig (axios) */ const add9Rheader = (request) => { var _a, _b; try { // URL throws an `TypeError` if `url` is not available and 'unknown-url' is set // [TypeError: Invalid URL] input: 'unknown-url', code: 'ERR_INVALID_URL' } const url = new URL((_a = request === null || request === void 0 ? void 0 : request.url) !== null && _a !== void 0 ? _a : 'unknown-url'); const headerAlreadyExists = request.headers && 'x-client-id' in request.headers; if (url.host.includes('ninerealms') && !headerAlreadyExists) { const headers = (_b = request === null || request === void 0 ? void 0 : request.headers) !== null && _b !== void 0 ? _b : {}; // Add custom header to request before returning it const newRequest = Object.assign(Object.assign({}, request), { headers: Object.assign(Object.assign({}, headers), { [`${NINE_REALMS_CLIENT_HEADER}`]: `${XCHAINJS_IDENTIFIER}` }) }); // console.log(` Request ${newRequest.url} ${JSON.stringify(newRequest.headers)}`) return newRequest; } } catch (error) { console.error(`Failed to add custom ${NINE_REALMS_CLIENT_HEADER} header`, error); } // If it errors, just return same request and keep it untouched (no change) // console.log(` Request ${request.url} ${JSON.stringify(request.headers)}`) return request; }; /** * Adds custom header to axios requests (9R endpoints only) */ // eslint-disable-next-line @typescript-eslint/no-explicit-any const register9Rheader = (axios) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any axios.interceptors.request.use(add9Rheader, (error) => Promise.reject(error)); }; /** * Utility Class to combine an amount (asset/base) with the Asset * */ class BaseCryptoAmount { constructor(amount, asset) { this.asset = asset; this.baseAmount = amount; } plus(v) { this.check(v); const assetAmountResult = assetToBase(this.assetAmount.plus(v.assetAmount)); return new BaseCryptoAmount(assetAmountResult, this.asset); } minus(v) { this.check(v); const assetAmountResult = assetToBase(this.assetAmount.minus(v.assetAmount)); return new BaseCryptoAmount(assetAmountResult, this.asset); } times(v) { this.check(v); if (v instanceof BaseCryptoAmount) { const assetAmountResult = assetToBase(this.assetAmount.times(v.assetAmount)); return new BaseCryptoAmount(assetAmountResult, this.asset); } else { const assetAmountResult = assetToBase(this.assetAmount.times(v)); return new BaseCryptoAmount(assetAmountResult, this.asset); } } div(v) { this.check(v); if (v instanceof BaseCryptoAmount) { const assetAmountResult = assetToBase(this.assetAmount.div(v.assetAmount)); return new BaseCryptoAmount(assetAmountResult, this.asset); } else { const assetAmountResult = assetToBase(this.assetAmount.div(v)); return new BaseCryptoAmount(assetAmountResult, this.asset); } } lt(v) { this.check(v); return this.assetAmount.lt(v.assetAmount); } lte(v) { this.check(v); return this.assetAmount.lte(v.assetAmount); } gt(v) { this.check(v); return this.assetAmount.gt(v.assetAmount); } gte(v) { this.check(v); return this.assetAmount.gte(v.assetAmount); } eq(v) { this.check(v); return this.assetAmount.eq(v.assetAmount); } formatedAssetString() { return formatAssetAmountCurrency({ amount: this.assetAmount, asset: this.asset, trimZeros: true, }); } assetAmountFixedString() { return this.assetAmount.amount().toFixed(); } get assetAmount() { return baseToAsset(this.baseAmount); } /** * This guard protects against trying to perform math with different assets * * Example. * const x = new CryptoAmount(assetAmount(1),AssetBTC) * const y = new CryptoAmount(assetAmount(1),AssetETH) * * x.plus(y) <- will throw error "cannot perform math on 2 diff assets BTC.BTC ETH.ETH * * @param v - CryptoNumeric */ check(v) { if (v instanceof BaseCryptoAmount) { if (!eqAsset(this.asset, v.asset)) { throw Error(`cannot perform math on 2 diff assets ${assetToString(this.asset)} ${assetToString(v.asset)}`); } } } } class CryptoAmount extends BaseCryptoAmount { } class AssetCryptoAmount extends BaseCryptoAmount { } class TokenCryptoAmount extends BaseCryptoAmount { } class SynthCryptoAmount extends BaseCryptoAmount { } class TradeCryptoAmount extends BaseCryptoAmount { } class SecuredCryptoAmount extends BaseCryptoAmount { } /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. 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. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; /* eslint-disable @typescript-eslint/no-explicit-any */ /** * Utility class for caching stable data */ class CachedValue { /** * @constructor * @param refreshData function that refresh and return the data * @param {number|undefined} cacheMaxAge time in millisecond to expire cache */ constructor(refreshData, cacheMaxAge) { this.refreshPromise = null; this.cacheMaxAge = cacheMaxAge || Infinity; this.refreshData = refreshData; } /** * @private * Validates if internal cache is valid or expired */ isCacheValid() { return Boolean(this.cacheTimestamp && new Date().getTime() - this.cacheTimestamp.getTime() < this.cacheMaxAge); } /** * Returns cached data if valid or request fresh data if cache is invalid * @param params use this params to request data if cache is expired */ getValue(params) { return __awaiter(this, void 0, void 0, function* () { if (this.isCacheValid()) { return this.cachedValue; } if (this.refreshPromise) { this.cachedValue = yield this.refreshPromise; } else { this.refreshPromise = this.refreshData(params); this.cachedValue = yield this.refreshPromise; this.cacheTimestamp = new Date(); this.refreshPromise = null; } return this.cachedValue; }); } } export { AssetCryptoAmount, AssetCurrencySymbol, AssetType, CachedValue, CryptoAmount, Denomination, NATIVE_ASSET_DELIMITER, NINE_REALMS_CLIENT_HEADER, SECURED_ASSET_DELIMITER, SYNTH_ASSET_DELIMITER, SecuredCryptoAmount, SynthCryptoAmount, TOKEN_ASSET_DELIMITER, TRADE_ASSET_DELIMITER, TokenCryptoAmount, TradeCryptoAmount, XCHAINJS_IDENTIFIER, add9Rheader, assetAmount, assetFromString, assetFromStringEx, assetToBase, assetToString, baseAmount, baseToAsset, bn, bnOrZero, currencySymbolByAsset, delay, eqAsset, fixedBN, formatAssetAmount, formatAssetAmountCurrency, formatBN, formatBNCurrency, formatBaseAmount, formatBaseAsAssetAmount, getContractAddressFromAsset, isAssetAmount, isBaseAmount, isBigNumberValue, isSecuredAsset, isSynthAsset, isTokenAsset, isTradeAsset, isValidAsset, isValidBN, register9Rheader, strip0x, trimZeros, validBNOrZero };