UNPKG

@thorwallet/xchain-util

Version:
384 lines 15.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatBaseAsAssetAmount = exports.formatAssetAmountCurrency = exports.currencySymbolByAsset = exports.AssetCurrencySymbol = exports.assetToString = exports.assetFromString = exports.isValidAsset = exports.AssetRuneERC20Testnet = exports.AssetRuneERC20 = exports.AssetRuneNative = exports.AssetRuneB1A = exports.AssetRune67C = exports.RUNE_TICKER = exports.AssetETH = exports.AssetLTC = exports.AssetBCH = exports.AssetBTC = exports.AssetBNB = exports.formatBaseAmount = exports.formatAssetAmount = exports.isBaseAmount = exports.isAssetAmount = exports.assetToBase = exports.baseToAsset = exports.baseAmount = exports.assetAmount = exports.isBigNumberValue = void 0; const tslib_1 = require("tslib"); const bignumber_js_1 = tslib_1.__importDefault(require("bignumber.js")); const bn_1 = require("./bn"); const string_1 = require("./string"); const chain_const_1 = require("./chain.const"); const chain_1 = require("./chain"); const types_1 = require("./types"); /** * Guard whichs checks 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_js_1.default; exports.isBigNumberValue = isBigNumberValue; /** * Default number of asset decimals * For history reason and by starting the project on Binance chain assets, it's 8 decimal. * * For example: * ``` * RUNE has a maximum of 8 digits of decimal * 0.00000001 RUNE == 1 ð (tor) * ``` * */ const ASSET_DECIMAL = 8; /** * 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 = bn_1.fixedBN(value, decimal); return { type: types_1.Denomination.ASSET, amount: () => amount, plus: (v, d = decimal) => exports.assetAmount(amount.plus(exports.isBigNumberValue(v) ? v : v.amount()), d), minus: (v, d = decimal) => exports.assetAmount(amount.minus(exports.isBigNumberValue(v) ? v : v.amount()), d), times: (v, d = decimal) => exports.assetAmount(amount.times(exports.isBigNumberValue(v) ? v : v.amount()), d), div: (v, d = decimal) => exports.assetAmount(amount.div(exports.isBigNumberValue(v) ? v : v.amount()), d), lt: (v) => amount.lt(exports.isBigNumberValue(v) ? v : v.amount()), lte: (v) => amount.lte(exports.isBigNumberValue(v) ? v : v.amount()), gt: (v) => amount.gt(exports.isBigNumberValue(v) ? v : v.amount()), gte: (v) => amount.gte(exports.isBigNumberValue(v) ? v : v.amount()), eq: (v) => amount.eq(exports.isBigNumberValue(v) ? v : v.amount()), decimal, }; }; exports.assetAmount = assetAmount; /** * 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 = bn_1.fixedBN(value, 0); return { type: types_1.Denomination.BASE, amount: () => amount, plus: (v, d = decimal) => exports.baseAmount(amount.plus(exports.isBigNumberValue(v) ? v : v.amount()), d), minus: (v, d = decimal) => exports.baseAmount(amount.minus(exports.isBigNumberValue(v) ? v : v.amount()), d), times: (v, d = decimal) => exports.baseAmount(amount.times(exports.isBigNumberValue(v) ? v : v.amount()), d), div: (v, d = decimal) => exports.baseAmount(amount.div(exports.isBigNumberValue(v) ? v : v.amount()).decimalPlaces(0, bignumber_js_1.default.ROUND_DOWN), d), lt: (v) => amount.lt(exports.isBigNumberValue(v) ? v : v.amount()), lte: (v) => amount.lte(exports.isBigNumberValue(v) ? v : v.amount()), gt: (v) => amount.gt(exports.isBigNumberValue(v) ? v : v.amount()), gte: (v) => amount.gte(exports.isBigNumberValue(v) ? v : v.amount()), eq: (v) => amount.eq(exports.isBigNumberValue(v) ? v : v.amount()), decimal, }; }; exports.baseAmount = baseAmount; /** * 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 exports.assetAmount(value, decimal); }; exports.baseToAsset = baseToAsset; /** * 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 exports.baseAmount(value, asset.decimal); }; exports.assetToBase = assetToBase; /** * Guard to check whether value is an amount of asset or not * * @param {BaseAmount|AssetAmount} v * @returns {boolean} `true` or `false`. * */ const isAssetAmount = (v) => v.type === types_1.Denomination.ASSET; exports.isAssetAmount = isAssetAmount; /** * Guard to check whether value is an amount of a base value or not * * @param {BaseAmount|AssetAmount} v * @returns {boolean} `true` or `false`. * */ const isBaseAmount = (v) => v.type === types_1.Denomination.BASE; exports.isBaseAmount = isBaseAmount; /** * 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 = false, }) => { // strict check for `undefined` value as negate of 0 will return true and passed decimal value will be ignored const formatted = bn_1.formatBN(amount.amount(), decimal === undefined ? amount.decimal : decimal); // Note: `trimZeros` wins over `decimal` return trimZeros ? string_1.trimZeros(formatted) : formatted; }; exports.formatAssetAmount = formatAssetAmount; /** * 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) => bn_1.formatBN(amount.amount(), 0); exports.formatBaseAmount = formatBaseAmount; /** * Base "chain" asset of Binance chain. * * Based on definition in Thorchain `common` * @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24 */ exports.AssetBNB = { chain: chain_const_1.BNBChain, symbol: 'BNB', ticker: 'BNB' }; /** * 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 */ exports.AssetBTC = { chain: chain_const_1.BTCChain, symbol: 'BTC', ticker: 'BTC' }; /** * Base "chain" asset on bitcoin cash main net. * * Based on definition in Thorchain `common` * @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24 */ exports.AssetBCH = { chain: chain_const_1.BCHChain, symbol: 'BCH', ticker: 'BCH' }; /** * Base "chain" asset on litecoin main net. * * Based on definition in Thorchain `common` * @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24 */ exports.AssetLTC = { chain: chain_const_1.LTCChain, symbol: 'LTC', ticker: 'LTC' }; /** * 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 */ exports.AssetETH = { chain: chain_const_1.ETHChain, symbol: 'ETH', ticker: 'ETH' }; exports.RUNE_TICKER = 'RUNE'; /** * Base "chain" asset for RUNE-67C on Binance test net. * * Based on definition in Thorchain `common` * @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24 */ exports.AssetRune67C = { chain: chain_const_1.BNBChain, symbol: 'RUNE-67C', ticker: exports.RUNE_TICKER }; /** * Base "chain" asset for RUNE-B1A on Binance main net. * * Based on definition in Thorchain `common` * @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24 */ exports.AssetRuneB1A = { chain: chain_const_1.BNBChain, symbol: 'RUNE-B1A', ticker: exports.RUNE_TICKER }; /** * Base "chain" asset on thorchain main net. * * Based on definition in Thorchain `common` * @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24 */ exports.AssetRuneNative = { chain: chain_const_1.THORChain, symbol: exports.RUNE_TICKER, ticker: exports.RUNE_TICKER }; /** * Base "chain" asset for RUNE on ethereum main net. * * Based on definition in Thorchain `common` * @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24 */ exports.AssetRuneERC20 = { chain: chain_const_1.ETHChain, symbol: `${exports.RUNE_TICKER}-0x3155ba85d5f96b2d030a4966af206230e46849cb`, ticker: exports.RUNE_TICKER, }; /** * Base "chain" asset for RUNE on ethereum main net. * * Based on definition in Thorchain `common` * @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24 */ exports.AssetRuneERC20Testnet = { chain: chain_const_1.ETHChain, symbol: `${exports.RUNE_TICKER}-0xd601c6A3a36721320573885A8d8420746dA3d7A0`, ticker: exports.RUNE_TICKER, }; /** * Helper to check whether asset is valid * * @param {Asset} asset * @returns {boolean} `true` or `false` */ const isValidAsset = (asset) => !!asset.chain && !!asset.ticker && !!asset.symbol; exports.isValidAsset = isValidAsset; /** * 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 assetFromString = (s) => { var _a; const data = s.split('.'); if (data.length <= 1 || ((_a = data[1]) === null || _a === void 0 ? void 0 : _a.length) < 1) { return null; } const chain = data[0]; // filter out not supported string of chains if (!chain || !chain_1.isChain(chain)) return null; const symbol = data[1]; const ticker = symbol.split('-')[0]; return { chain, symbol, ticker }; }; exports.assetFromString = assetFromString; /** * 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) * * @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 }) => `${chain}.${symbol .split('-') .map((x, i) => { if (i === 0) { return x; } return x.toLowerCase(); }) .join('-')}`; exports.assetToString = assetToString; /** * Currency symbols currently supported */ var AssetCurrencySymbol; (function (AssetCurrencySymbol) { AssetCurrencySymbol["RUNE"] = "\u16B1"; AssetCurrencySymbol["BTC"] = "\u20BF"; AssetCurrencySymbol["SATOSHI"] = "\u26A1"; AssetCurrencySymbol["ETH"] = "\u039E"; AssetCurrencySymbol["USD"] = "$"; })(AssetCurrencySymbol = exports.AssetCurrencySymbol || (exports.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 === exports.RUNE_TICKER: return AssetCurrencySymbol.RUNE; case ticker === exports.AssetBTC.ticker: return AssetCurrencySymbol.BTC; case ticker === exports.AssetETH.ticker: return AssetCurrencySymbol.ETH; case ticker.includes('USD'): return AssetCurrencySymbol.USD; default: return ticker; } }; exports.currencySymbolByAsset = currencySymbolByAsset; /** * 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 = exports.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 let regex = new RegExp(`${exports.AssetRune67C.ticker}|${exports.AssetRuneB1A.ticker}|${exports.AssetRuneNative.ticker}`, 'i'); if (ticker.match(regex)) return `${AssetCurrencySymbol.RUNE} ${amountFormatted}`; // BTC regex = new RegExp(exports.AssetBTC.ticker, 'i'); if (ticker.match(new RegExp(exports.AssetBTC.ticker, 'i'))) { const base = exports.assetToBase(amount); // format all < ₿ 0.01 in statoshi if (base.amount().isLessThanOrEqualTo('1000000')) { return `${AssetCurrencySymbol.SATOSHI} ${exports.formatBaseAmount(base)}`; } return `${AssetCurrencySymbol.BTC} ${amountFormatted}`; } // ETH regex = new RegExp(exports.AssetETH.ticker, 'i'); if (ticker.match(regex)) return `${AssetCurrencySymbol.ETH} ${amountFormatted}`; // USD regex = new RegExp('USD', 'i'); if (ticker.match('USD')) return `${AssetCurrencySymbol.USD} ${amountFormatted}`; return `${amountFormatted} ${ticker}`; } return `$ ${amountFormatted}`; }; exports.formatAssetAmountCurrency = formatAssetAmountCurrency; /** * 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, }) => exports.formatAssetAmount({ amount: exports.baseToAsset(amount), decimal, trimZeros }); exports.formatBaseAsAssetAmount = formatBaseAsAssetAmount; //# sourceMappingURL=asset.js.map