Skip to content

Commit f6bfc9c

Browse files
committed
implement token formatting
1 parent e29a4a6 commit f6bfc9c

1 file changed

Lines changed: 53 additions & 0 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import Big from "big.js";
2+
3+
/**
4+
* Formats raw token amount (bigint or string) to human-readable decimal string.
5+
*
6+
* - Handles arbitrarily large amounts safely (no Number conversion)
7+
* - Divides raw / 10^decimals using Big.js for precision
8+
* - Uses Intl.NumberFormat for locale-aware formatting
9+
* - Trims insignificant trailing zeros (except for amounts <1)
10+
* - Edge cases: 0, max safe integer * 10^decimals, overflow
11+
*
12+
* @param raw - Raw minor units (e.g. 1000000n for 1 USDC)
13+
* @param decimals - Token decimals (e.g. 6 for USDC, 7 for XLM/stroops)
14+
* @param locale - Optional locale (defaults to 'en-US')
15+
* @returns Formatted display string (e.g. '1.00', '0.00', '1,234.56')
16+
*/
17+
export function formatTokenAmount(
18+
raw: bigint | string | number,
19+
decimals: number,
20+
locale: string = "en-US"
21+
): string {
22+
if (raw === 0n || raw === "0" || raw === 0) return "0.00";
23+
24+
// Convert to BigInt safely
25+
const bigRaw = BigInt(raw.toString());
26+
27+
// Safe division using Big.js
28+
const divisor = 10n ** BigInt(decimals);
29+
const bigIntValue = Big(bigRaw.toString()).div(Big(divisor.toString()));
30+
31+
// Get fixed decimal representation
32+
const fixed = bigIntValue.toFixed(decimals).replace(/\.?0+$/, "");
33+
34+
// Use Intl.NumberFormat for locale formatting
35+
return new Intl.NumberFormat(locale, {
36+
minimumFractionDigits: 0,
37+
maximumFractionDigits: decimals,
38+
}).format(parseFloat(fixed));
39+
}
40+
41+
// Convenience for XLM/stroops (7 decimals)
42+
export function formatXlm(
43+
raw: bigint | string | number,
44+
locale?: string
45+
): string {
46+
return formatTokenAmount(raw, 7, locale ?? "en-US");
47+
}
48+
49+
// Export types for use in components
50+
export type TokenFormatOptions = {
51+
decimals: number;
52+
locale?: string;
53+
};

0 commit comments

Comments
 (0)