import bigDecimal from "js-big-decimal"; import type { MarketData } from "../types/wallet.types"; interface MarketDataResponse { id: string; circulating_supply?: number | null; current_price?: number | null; fully_diluted_valuation?: number | null; image?: string; last_updated?: string; market_cap?: number | null; market_cap_change_24h?: number | null; market_cap_change_percentage_24h?: number | null; max_supply?: number | null; name?: string; price_change_24h?: number | null; price_change_percentage_24h?: number | null; symbol?: string; total_supply?: number | null; total_volume?: number | null; } export const CURRENCIES = [ { code: 'usd', symbol: '$', name: 'US Dollar' }, { code: 'eur', symbol: '€', name: 'Euro' }, { code: 'gbp', symbol: '£', name: 'British Pound' }, { code: 'aud', symbol: 'A$', name: 'Australian Dollar' }, { code: 'cad', symbol: 'C$', name: 'Canadian Dollar' }, { code: 'chf', symbol: 'Fr', name: 'Swiss Franc' }, { code: 'inr', symbol: '₹', name: 'Indian Rupee' }, { code: 'cny', symbol: '¥', name: 'Chinese Yuan' }, { code: 'jpy', symbol: '¥', name: 'Japanese Yen' }, ] as const; export type CurrencyCode = typeof CURRENCIES[number]['code']; export type CurrencySymbol = typeof CURRENCIES[number]['symbol']; export const currencySymbols = Object.fromEntries( CURRENCIES.map(c => [c.code, c.symbol]) ) as Record; export const currencyCodes = CURRENCIES.map(c => c.code); export const SUPPORTED_TOKENS: Record = { nexacoin: 'nexa' }; export async function getMarketData(currency: CurrencyCode): Promise> { const ids = Object.keys(SUPPORTED_TOKENS).join(","); const res = await fetch(`https://api.coingecko.com/api/v3/coins/markets?ids=${ids}&vs_currency=${currency}`); if (!res.ok) { throw new Error("Failed to fetch market data"); } const payload: MarketDataResponse[] = await res.json(); const data: Record = {}; payload.forEach(entry => { data[SUPPORTED_TOKENS[entry.id]] = { id: entry.id, name: entry.name ?? '', symbol: entry.symbol ?? '', image: entry.image ?? '', price: entry.current_price ?? 0, priceChange: entry.price_change_24h, priceChangePercentage: entry.price_change_percentage_24h, marketCap: entry.market_cap, fdv: entry.fully_diluted_valuation, circSupply: entry.circulating_supply, totalSupply: entry.total_supply, maxSupply: entry.max_supply, totalVolume: entry.total_volume } }); return data; } export function getCurrencySymbol(currency: CurrencyCode): string { return currencySymbols[currency] || currency; } export function calculateFiatValue(amount: string | number, price: number, currency?: CurrencyCode): string { const value = bigDecimal.multiply(amount, price); const rounded = bigDecimal.round(value, 2, bigDecimal.RoundingModes.HALF_DOWN); return currency ? formatMoney(rounded, currency) : rounded; } export function formatMoney(value: string | number, currency: CurrencyCode, locale = 'en-US'): string { return new Intl.NumberFormat(locale, { style: 'currency', currency, maximumFractionDigits: 2, minimumFractionDigits: 2 }).format(Number(value)); }