UNPKG

@shogun-sdk/money-legos

Version:

Shogun Money Legos: clients and types for quotes, memes, prices, balances, fees, validations, etc.

237 lines 9.07 kB
export const formatNetworkName = (network) => { return network.charAt(0).toUpperCase() + network.slice(1); }; export const toUpperCase = (stringInput) => { return stringInput.toUpperCase(); }; export const formatNumber = (number, decPlaces = 1) => { const units = ['K', 'M', 'B', 'T']; // Thousand, Million, Billion, Trillion const isNegative = number < 0; const absNumber = Math.abs(number); // Handle numbers less than 1, showing 4 decimal places if (absNumber < 1) { return `${isNegative ? '-' : ''}${absNumber.toFixed(4)}`; } // Handle numbers between 1 and 999, displaying with two decimal places if (absNumber < 1000) { return `${isNegative ? '-' : ''}${formatNumberWithThreeDecimalPlaces(absNumber)}`; } // Handle numbers >= 1000 and < 1 million (abbreviating as 'K') if (absNumber >= 1000 && absNumber < 1e6) { const rounded = Math.floor(absNumber / 100) / 10; // Round to nearest 100 return `${isNegative ? '-' : ''}${rounded}${units[0]}`; } // Handle numbers >= 1 million and < 1 billion (abbreviating as 'M') if (absNumber >= 1e6 && absNumber < 1e9) { const rounded = Math.floor(absNumber / 1e4) / 100; // Round to nearest 10,000 return `${isNegative ? '-' : ''}${rounded}${units[1]}`; } // Handle numbers >= 1 billion and < 1 trillion (abbreviating as 'B') if (absNumber >= 1e9 && absNumber < 1e12) { const rounded = Math.floor(absNumber / 1e7) / 100; // Round to nearest 10,000,000 return `${isNegative ? '-' : ''}${rounded}${units[2]}`; } // Handle numbers >= 1 trillion (abbreviating as 'T') if (absNumber >= 1e12) { const rounded = Math.floor(absNumber / 1e10) / 100; // Round to nearest 10,000,000,000 return `${isNegative ? '-' : ''}${rounded}${units[3]}`; } // Default to showing number with decimals (if larger than trillion) return `${isNegative ? '-' : ''}${absNumber.toFixed(decPlaces)}`; }; /** * Capitalizes specific chain names or returns the original name * @param name - The chain name to process (e.g. 'Bsc' becomes 'BSC') * @returns The processed chain name */ const formatBlockchainName = (chainName) => { if (!chainName) { return ''; } const normalizedChainName = chainName.toLowerCase(); if (['bsc'].includes(normalizedChainName)) { return chainName.toUpperCase(); } return chainName; }; export const capitalizeFirstLetter = (str) => { return formatBlockchainName(str.charAt(0).toUpperCase() + str.slice(1)); }; export const formatEthUiBalance = (balance, symbol) => { return `${Number(balance) === 0 ? '0' : Number(balance).toFixed(4)} ${symbol ? symbol : 'ETH'}`; }; export const formatPriceInEth = (price) => { // Handle zero or empty input if (!price || Number(price) === 0) { return '0'; } const priceFormatted = Number(price).toFixed(30); const [integerPart, decimalPart] = priceFormatted.split('.'); // Get the integer and decimal parts const leadingZerosCount = decimalPart?.match(/^0*/)?.[0]?.length || 0; // Count leading zeros let formattedPrice = integerPart; const significantPart = decimalPart?.substring(leadingZerosCount); // Get the significant part after leading zeros // Build the formatted price string if (leadingZerosCount <= 2) { formattedPrice += `.${`0`.repeat(leadingZerosCount)}${significantPart?.substring(0, 4)}`; } else { formattedPrice += `.0${subscriptDigit(leadingZerosCount)}${significantPart?.substring(0, 4)}`; } return formattedPrice ?? '0'; }; export const formatMaxBuyNativeAmount = (amount) => { const amountFormatted = amount.toFixed(30); const [integerPart, decimalPart] = amountFormatted.split('.'); // Get the integer and decimal parts const leadingZerosCount = decimalPart?.match(/^0*/)?.[0]?.length || 0; // Count leading zeros let formattedPrice = integerPart; const significantPart = decimalPart?.substring(leadingZerosCount); // Get the significant part after leading zeros formattedPrice += `.${`0`.repeat(leadingZerosCount)}${significantPart?.substring(0, 2)}`; return formattedPrice ?? '0'; }; export function formatNumberWithThreeDecimalPlaces(num) { if (Math.abs(num) < 0.0001) { return '0'; } return num.toFixed(4).replace(/\.?0*$/, ''); } export const subscriptDigit = (digit) => { const subscriptMap = { 0: '₀', 1: '₁', 2: '₂', 3: '₃', 4: '₄', 5: '₅', 6: '₆', 7: '₇', 8: '₈', 9: '₉', 10: '₁₀', 11: '₁₁', 12: '₁₂', 13: '₁₃', 14: '₁₄', 15: '₁₅', 16: '₁₆', 17: '₁₇', 18: '₁₈', 19: '₁₉', }; return subscriptMap[digit] || digit.toString(); }; export const formatSupplyPercentageOwned = (tokenSupplyOwned) => { if (tokenSupplyOwned === 0) { return '0%'; } if (tokenSupplyOwned < 0.01) { return '&lt; 0.01 %'; } return `${tokenSupplyOwned.toFixed(2)}%`; }; export const convertNumbThousand = (x) => { if (!x) { return '0'; } return x.toLocaleString('en-US'); }; export function lowercase(input) { return String(input).toLowerCase(); } export const formatPnl = (pnl) => { if (pnl === 'N/A') return `PNL: N/A`; let pnlFormatted = formatNumberWithThreeDecimalPlaces(Number(pnl)); if (pnlFormatted === '0') pnlFormatted = '0.00'; return `PNL: ${Number(pnlFormatted) >= 0 ? '🟢' : '🔴'} <b>${pnlFormatted}%</b>`; }; export const formatChangeXH = (change, h) => { let changeFormatted = change.toFixed(3); if (changeFormatted === '0') changeFormatted = '0.00'; return `${h}h: ${Number(changeFormatted) >= 0 ? '🟢' : '🔴'} <b>${changeFormatted}%</b>`; }; export const formatAvgEntry = (avgEntry) => { if (avgEntry === 'N/A') return avgEntry; const avgEntryFormatted = formatPriceInEth(Number(avgEntry).toFixed(30)); return `$${avgEntryFormatted}`; }; export const formatTimeAgo = (timestamp) => { const now = Date.now(); const diff = now - timestamp * 1000; const minutes = Math.floor(diff / 60000); const hours = Math.floor(diff / 3600000); const days = Math.floor(diff / 86400000); const weeks = Math.floor(days / 7); const months = Math.floor(days / 30); const years = Math.floor(days / 365); if (years > 0) return `${years} ${years === 1 ? 'year' : 'years'} ago`; if (months > 0) return `${months} ${months === 1 ? 'month' : 'months'} ago`; if (weeks > 0) return `${weeks} ${weeks === 1 ? 'week' : 'weeks'} ago`; if (days > 0) return `${days} ${days === 1 ? 'day' : 'days'} ago`; if (hours > 0) return `${hours} ${hours === 1 ? 'hour' : 'hours'} ago`; if (minutes > 0) return `${minutes} ${minutes === 1 ? 'minute' : 'minutes'} ago`; return 'less than a minute ago'; }; /** * Normalizes a decimal number string by limiting the number of decimal places. * This helper prevents numeric overflow/underflow errors when dealing with high-precision decimals. * * @param value - The decimal number as a string (e.g., "0.15947712418300652") * @returns A string with the normalized decimal number * * Examples: * normalizeDecimals("0.15947712418300652") => "0.15947712" * normalizeDecimals("1.23", 4) => "1.23" * normalizeDecimals("123") => "123" * normalizeDecimals("0.1234", 2) => "0.12" * */ export function normalizeDecimals(value, decimals = 18) { if (!value.includes('.')) return value; const [whole, fraction] = value.split('.'); return `${whole}.${fraction?.slice(0, decimals) ?? ''}`; } export function bigIntReplacer(_key, value) { return typeof value === 'bigint' ? value.toString() : value; } export function getFormattedObject(object) { return JSON.stringify(object, bigIntReplacer, 2); } export function formatUSD(amount) { // Convert to number and handle potential parsing errors const numAmount = typeof amount === 'string' ? parseFloat(amount.replace(/[^0-9.-]/g, '')) : amount; // Check for invalid input if (isNaN(numAmount)) { return '0'; } return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 2, minimumFractionDigits: 0, }).format(numAmount); } export function getUserIdLog(userId) { return `[${userId}]`; } export function getFormattedCurrentMethod(userId, methodName, instance) { return `${getUserIdLog(userId)} >> ${instance?.constructor?.name ? instance?.constructor?.name + '.' : ''}${methodName}`; } // replace last 9 digits with 0s export function formatTokenAmount(amount) { const strAmount = amount.toString(); if (strAmount.length <= 9) { return strAmount; } return strAmount.slice(0, -9) + '0'.repeat(9); } //# sourceMappingURL=formatter.js.map