base / base/ui

formatAmount in app/vibenet/library/format.ts produces malformed output for negative values

Open Beginner friendly
#157 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
2
Forks
12
Avg merge
1d 4h
Merged PRs (30d)
76

Description

# `formatAmount` in `app/vibenet/library/format.ts` produces malformed output for negative values

## Summary

`formatAmount` uses `value % divisor` to extract the fractional part. JavaScript's `BigInt %` preserves the sign of the dividend, so for negative `value` the remainder is negative. Its `.toString()` includes a leading `"-"` which corrupts the subsequent `.padStart` / `.slice` chain and produces strings like `"-1.-5"` instead of `"-1.5"`.

`value / divisor` (integer division toward zero) also drops the sign when the absolute value is less than the divisor `BigInt("-500000000000000000") / 10n**18n === 0n` so the whole part loses its sign too.

## Root cause

```ts
// app/vibenet/library/format.ts
const frac = (value % divisor) // negative when value < 0
.toString() // "-500000000000000000"
.padStart(decimals, '0') // still starts with "-"
.slice(0, maxFractionDigits) // "-500" ← sign consumed by slice
.replace(/0+$/, ''); // "-5"
return frac ? `${whole}.${frac}` : whole; // → "-1.-5"
```

## Observable inconsistency

| `raw` | `decimals` | `maxFractionDigits` | Result | Expected |
|---|---|---|---|---|
| `"-1500000000000000000"` | 18 | 4 | `"-1.-5"` | `"-1.5"` |
| `"-500000000000000000"` | 18 | 4 | `"0.-5"` | `"-0.5"` |
| `"1500000000000000000"` | 18 | 4 | `"1.5"` ✓ | `"1.5"` |

Reproduces in a Node REPL with the function copy-pasted as-is.

## Suggested fix

Take `abs` before the modulo; the whole part already carries the sign via `toLocaleString`:

```ts
export function formatAmount(raw: string, decimals: number, maxFractionDigits = 4): string {
try {
const value = BigInt(raw);
if (value === 0n) return '0';
const divisor = 10n ** BigInt(decimals);
const abs = value < 0n ? -value : value;
const whole = (value / divisor).toLocaleString();
const frac = (abs % divisor)
.toString()
.padStart(decimals, '0')
.slice(0, maxFractionDigits)
.replace(/0+$/, '');
return frac ? `${whole}.${frac}` : whole;
} catch {
return raw;
}
}
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in app/vibenet/library/format.ts and reproduce the issue in a Node REPL using the negative values from the report. Check the behavior for values above and below the divisor, then verify that the listed negative cases produce "-1.5" and "-0.5" without changing the existing positive behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.