UNPKG

bigblocks

Version:

Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React

174 lines (173 loc) 5.54 kB
// Currency Utilities - Format amounts, convert between currencies import { toBitcoin, toToken, toTokenSat } from "satoshi-token"; /** * Format satoshis as BSV with appropriate decimal places */ export function formatBSV(satoshis, decimals = 8) { // Handle null/undefined/NaN cases if (satoshis == null || Number.isNaN(satoshis)) { return "0"; } const bsv = toBitcoin(satoshis); return Number(bsv) .toFixed(decimals) .replace(/\.?0+$/, ""); } /** * Format satoshis as the specified currency */ export function formatCurrency(value, currency = "USD", exchangeRate) { let amount = value; // If value is in satoshis and we want fiat currency, convert via BSV if (currency !== "BSV" && exchangeRate) { const bsvAmount = typeof value === "number" && value > 1000000 ? toBitcoin(value) : value; amount = bsvAmount * exchangeRate; } const formatters = { BSV: new Intl.NumberFormat("en-US", { minimumFractionDigits: 0, maximumFractionDigits: 8, }), USD: new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", minimumFractionDigits: 2, maximumFractionDigits: 2, }), EUR: new Intl.NumberFormat("en-EU", { style: "currency", currency: "EUR", minimumFractionDigits: 2, maximumFractionDigits: 2, }), GBP: new Intl.NumberFormat("en-GB", { style: "currency", currency: "GBP", minimumFractionDigits: 2, maximumFractionDigits: 2, }), JPY: new Intl.NumberFormat("ja-JP", { style: "currency", currency: "JPY", minimumFractionDigits: 0, maximumFractionDigits: 0, }), }; const formatted = formatters[currency].format(amount); // Add BSV suffix for BSV amounts if (currency === "BSV") { return `${formatted} BSV`; } return formatted; } /** * Format token amounts with proper decimal places */ export function formatTokenAmount(amount, decimals = 0) { const num = typeof amount === "string" ? Number.parseFloat(amount) : amount; if (Number.isNaN(num)) return "0"; // Use satoshi-token library for conversion const displayAmount = decimals > 0 ? toToken(num, decimals) : num; // Format with appropriate decimal places const formatter = new Intl.NumberFormat("en-US", { minimumFractionDigits: 0, maximumFractionDigits: Math.min(decimals, 8), }); return formatter.format(Number(displayAmount)); } /** * Parse token amount from display format to token units */ export function parseTokenAmount(amount, decimals = 0) { const num = Number.parseFloat(amount); if (Number.isNaN(num)) return "0"; // Use satoshi-token library for conversion const tokenAmount = decimals > 0 ? toTokenSat(num, decimals) : num; // Return as string for precise handling return tokenAmount.toString(); } /** * Convert between different currencies */ export function convertCurrency(amount, fromCurrency, toCurrency, exchangeRates) { if (fromCurrency === toCurrency) return amount; // Convert to USD as base currency first let usdAmount = amount; if (fromCurrency !== "USD") { const fromRate = exchangeRates[fromCurrency]; if (!fromRate) throw new Error(`Exchange rate not available for ${fromCurrency}`); usdAmount = fromCurrency === "BSV" ? amount * fromRate : amount / fromRate; } // Convert from USD to target currency if (toCurrency === "USD") return usdAmount; const toRate = exchangeRates[toCurrency]; if (!toRate) throw new Error(`Exchange rate not available for ${toCurrency}`); return toCurrency === "BSV" ? usdAmount / toRate : usdAmount * toRate; } /** * Calculate percentage change */ export function calculatePercentageChange(oldValue, newValue) { if (oldValue === 0) return newValue > 0 ? 100 : 0; return ((newValue - oldValue) / oldValue) * 100; } /** * Format percentage with appropriate color coding */ export function formatPercentage(percentage) { const abs = Math.abs(percentage); const sign = percentage > 0 ? "+" : percentage < 0 ? "-" : ""; return { text: `${sign}${abs.toFixed(2)}%`, color: percentage > 0 ? "green" : percentage < 0 ? "red" : "gray", }; } /** * Abbreviate large numbers (e.g., 1000 -> 1K, 1000000 -> 1M) */ export function abbreviateNumber(num) { // Handle null/undefined/NaN cases if (num == null || Number.isNaN(num)) { return "0"; } const billion = 1000000000; const million = 1000000; const thousand = 1000; if (num >= billion) { return `${(num / billion).toFixed(1)}B`; } if (num >= million) { return `${(num / million).toFixed(1)}M`; } if (num >= thousand) { return `${(num / thousand).toFixed(1)}K`; } return num.toString(); } /** * Validate if a string is a valid numeric amount */ export function isValidAmount(amount) { const num = Number.parseFloat(amount); return !Number.isNaN(num) && num >= 0 && Number.isFinite(num); } /** * Get currency symbol for display */ export function getCurrencySymbol(currency) { const symbols = { BSV: "₿", USD: "$", EUR: "€", GBP: "£", JPY: "¥", }; return symbols[currency]; }