Skip to content

BigInt utility functions truncate sub-unit amounts to zero and have no consistent formatting across the UI #2

Description

@benfoster-dev

The percentage() function in shared/utils.ts truncates BigInt values before dividing:

const percentage = (value: BigInt, divider: BigInt, decimals = 7): number => {
  return (Number(value.valueOf() / (10n ** BigInt(decimals))) /
      Number(divider.valueOf() / (10n ** BigInt(decimals)))
    ) * 100
}

BigInt division truncates to integer. For values under 1 whole token (less than 10^7 stroops), the division produces 0n. A balance of 1.5 XLM (15000000n stroops) works, but 0.5 XLM (5000000n stroops) divided by 10000000n gives 0n. The percentage shows 0% instead of 50% for a half-filled escrow.

But this is part of a broader problem with how BigInt amounts are handled across the UI:

  1. percentage() loses all sub-unit precision as described above. The EscrowPanel progress bar is wrong for any fractional amount.

  2. There is no shared formatting function for displaying token amounts. Different components format amounts differently — some divide by 10^7, some don't, some use toFixed(2), some show raw stroops.

  3. The conversion between stroops and display amounts is not centralized. The magic number 10^7 (or 10n ** 7n) appears in multiple places with no named constant.

  4. The BigInt type annotations use the constructor BigInt (capital B) in some places and the primitive bigint (lowercase) in others. TypeScript treats these differently — BigInt is the wrapper object, bigint is the primitive. Mixing them causes type errors under strict mode.

This is high severity. The fix requires: rewriting percentage() to preserve precision (scale numerator before dividing, or convert to Number at the right point), creating a shared token formatting utility with a named STROOPS constant, standardizing all amount displays across EscrowPanel, StreamCard, AmountInput, and WalletData, and fixing the BigInt/bigint type inconsistency.

This touches shared/utils.ts, and every component that displays or computes with token amounts.

Before submitting your PR, make sure all checks pass locally and the build succeeds. Each issue will be thoroughly reviewed and only merged if it fully meets the requirements. In your PR, specify the issue number and title. You can optionally provide a screenshot showing the fix working. On the issue, comment tagging the author to let them know you're working on it. On the PR, tag the maintainer to notify that review is ready.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdifficulty:hardHard difficultyhelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions