import BN from "bn.js"; import { WAD } from "../constants.js"; /** * Conversion Utilities Module * * Safe BN ↔ number conversions and common transformations */ const WAD_BN = new BN(WAD.toString()); /** * Safely convert BN to number, throws if exceeds MAX_SAFE_INTEGER */ export function safeToNumber(bn: BN, context?: string): number { const MAX_SAFE = new BN(Number.MAX_SAFE_INTEGER.toString()); if (bn.abs().gt(MAX_SAFE)) { throw new Error( `Value exceeds MAX_SAFE_INTEGER${context ? ` in ${context}` : ""}: ${bn.toString()}` ); } return bn.toNumber(); } /** * Convert lamports to SOL (safe conversion) */ export function lamportsToSol(lamports: BN): number { const wholeSol = lamports.div(new BN(1_000_000_000)); const remainder = lamports.mod(new BN(1_000_000_000)); const whole = safeToNumber(wholeSol, "lamportsToSol:whole"); const fractional = safeToNumber(remainder, "lamportsToSol:remainder") / 1_000_000_000; return whole + fractional; } /** * Convert cents to dollars */ export function centsToDollars(cents: BN): number { return safeToNumber(cents, "centsToDollars") / 100; } /** * Convert timestamp BN to Date */ export function timestampToDate(timestamp: BN): Date { const seconds = safeToNumber(timestamp, "timestampToDate"); return new Date(seconds * 1000); } /** * Check if timestamp has passed */ export function isTimestampPassed(timestamp: BN): boolean { const now = new BN(Math.floor(Date.now() / 1000)); return now.gt(timestamp); } /** * Convert WAD to float for display */ export function wadToFloat(wad: BN): number { const wholePart = wad.div(WAD_BN); const remainder = wad.mod(WAD_BN); const whole = parseFloat(wholePart.toString()); const fractional = parseFloat(remainder.toString()) / Number(WAD); return whole + fractional; }