Repository Public
1// Exact integer money arithmetic. No floating point anywhere.2const MAX = (1n << 256n) - 1n;34export function parseUnits(input: string, decimals: number): bigint {5 if (!Number.isInteger(decimals) || decimals < 0 || decimals > 36) throw new Error('bad decimals');6 const s = input.trim().replace(',', '.');7 if (!/^\d{1,60}(\.\d{0,60})?$/.test(s)) throw new Error('invalid amount');8 const [int = '0', frac = ''] = s.split('.');9 if (frac.length > decimals && /[1-9]/.test(frac.slice(decimals))) throw new Error('too many decimals');10 const v = BigInt(int) * 10n ** BigInt(decimals) + BigInt((frac.slice(0, decimals) || '').padEnd(decimals, '0') || '0');11 if (v > MAX) throw new Error('amount overflow');12 return v;13}1415export function formatUnits(value: bigint, decimals: number): string {16 if (value < 0n) throw new Error('negative amount');17 const base = 10n ** BigInt(decimals);18 const int = value / base;19 const frac = (value % base).toString().padStart(decimals, '0').replace(/0+$/, '');20 return frac ? `${int}.${frac}` : int.toString();21}2223/** Parse a canonical base-unit string ("0" or no leading zero, digits only). */24export function baseUnits(s: string): bigint {25 if (!/^(0|[1-9]\d{0,77})$/.test(s)) throw new Error('invalid base-unit integer');26 return BigInt(s);27}28