In src/shared/utils.ts lines 40-55, both formatTokenUnits and formatCreditBalance produce malformed strings when given negative bigint inputs.
JavaScript BigInt division truncates toward zero and the remainder carries the sign of the dividend:
formatTokenUnits(-5n, 6)
// whole = 0n, fractional = -5n
// (-5n).toString() = "-5", padStart(6, "0") = "0000-5"
// Result: "0.0000-5"
formatTokenUnits(-1234567n, 6)
// whole = -1n, fractional = -234567n
// Result: "-1.-234567"
Current callers pass non-negative values (clamped via deposit > spent ? deposit - spent : 0n), so this is not triggered at runtime today, but the function signature accepts any bigint a trap for future callers.
Note: sibling function formatMicroUnits (line 31) is safe because its regex guard /^\d+$/ rejects negative strings.
Suggested fix:
export function formatTokenUnits(value: bigint, decimals: number) {
const negative = value < 0n;
const abs = negative ? -value : value;
const divisor = 10n ** BigInt(decimals);
const whole = abs / divisor;
const fractional = abs % divisor;
const formatted = decimals === 0
? whole.toString()
: `${whole}.${fractional.toString().padStart(decimals, "0")}`;
return negative ? `-${formatted}` : formatted;
}
Apply the same pattern to formatCreditBalance.
In
src/shared/utils.tslines 40-55, bothformatTokenUnitsandformatCreditBalanceproduce malformed strings when given negativebigintinputs.JavaScript BigInt division truncates toward zero and the remainder carries the sign of the dividend:
Current callers pass non-negative values (clamped via
deposit > spent ? deposit - spent : 0n), so this is not triggered at runtime today, but the function signature accepts anybiginta trap for future callers.Note: sibling function
formatMicroUnits(line 31) is safe because its regex guard/^\d+$/rejects negative strings.Suggested fix:
Apply the same pattern to
formatCreditBalance.