const NANO = 1_000_000_000n; export type ProtoDecimal = { units?: string | number; nano?: string | number }; export type Decimal = { value: bigint; scale: number }; export function decimal(value: ProtoDecimal): Decimal { return { value: BigInt(value.units ?? 0) * NANO + BigInt(value.nano ?? 0), scale: 9, }; } export function add(left: Decimal, right: Decimal): Decimal { const scale = Math.max(left.scale, right.scale); return { value: left.value * 10n ** BigInt(scale - left.scale) + right.value * 10n ** BigInt(scale - right.scale), scale, }; } export function subtract(left: Decimal, right: Decimal): Decimal { return add(left, { value: -right.value, scale: right.scale }); } export function multiply(left: Decimal, right: Decimal): Decimal { return { value: left.value * right.value, scale: left.scale + right.scale }; } export function isZero(value: Decimal): boolean { return value.value === 0n; } export function formatDecimal({ value, scale }: Decimal): string { if (value === 0n) return '0'; const sign = value < 0n ? '-' : ''; const digits = (value < 0n ? -value : value) .toString() .padStart(scale + 1, '0'); const whole = digits.slice(0, -scale) || '0'; const fraction = digits.slice(-scale).replace(/0+$/, ''); return `${sign}${whole}${fraction ? `.${fraction}` : ''}`; }