Skip to content

fix: preserve sign in formatCurrency, ensure consistency with StatCard - #100

Open
rindicomfort wants to merge 2 commits into
MergeFi:mainfrom
rindicomfort:fix/formatcurrency-preserve-sign
Open

fix: preserve sign in formatCurrency, ensure consistency with StatCard#100
rindicomfort wants to merge 2 commits into
MergeFi:mainfrom
rindicomfort:fix/formatcurrency-preserve-sign

Conversation

@rindicomfort

Copy link
Copy Markdown

Closes #90

Problem

formatCurrency unconditionally applied Math.abs(), silently discarding negative signs on financial figures. This created an inconsistency with StatCard's internal currency formatter, which correctly preserves signs.

The same negative amount would render as:

  • -50 USDC in StatCard (correct)
  • 50 USDC in formatCurrency (sign lost)

This is a real, live landmine for any future feature that needs to display negative values such as:

  • Net-negative sponsor balances (refunds exceeding deposits)
  • Accounting corrections or adjustments
  • Budget deltas (e.g., remaining budget after overspending)

Solution

Removed Math.abs() from formatCurrency to preserve negative signs naturally
Added comprehensive JSDoc explaining the sign-preservation behavior and legitimate use cases
Reconciled with StatCard – both formatters now handle negative values identically
Added extensive test coverage to prevent regression

Changes

  • src/lib/utils.ts: Removed Math.abs(), added detailed documentation explaining why sign preservation is correct
  • src/lib/utils.test.ts: New comprehensive test suite with 36 tests covering sign preservation, locale formatting, edge cases, and all utility functions
  • src/components/ui/StatCard.test.tsx: Added 5 new tests confirming negative value handling and consistency with formatCurrency

Testing

All 52 tests pass, including:

  • ✅ Sign preservation for negative amounts: formatCurrency(-50, 'USDC')'-50 USDC'
  • ✅ Negative and positive are distinguishable: formatCurrency(-50) !== formatCurrency(50)
  • ✅ StatCard and formatCurrency produce identical output for negative values
  • ✅ No regressions to existing positive/zero cases across all call sites
  • ✅ Edge cases: NaN, Infinity, very large/small negative values
  • ✅ Locale formatting preserved: thousand separators, 2 decimal places

Verification

npm test
# All 52 tests pass (36 in utils.test.ts + 16 in StatCard.test.tsx)

Impact

  • Consistency: formatCurrency and StatCard now agree on sign-handling – no more contradictory behavior
  • Correctness: Financial figures can display negative values correctly throughout the app
  • Future-proof: Negative amounts (refunds, corrections, net-negative balances) will render properly when they occur
  • Zero regression: All existing positive/zero value use cases continue to work identically

Call Sites Verified

All 15+ call sites across the app continue to work correctly:

  • Landing page stats, leaderboard earnings, activity feed
  • Dashboard pages (contributor, maintainer, sponsor)
  • Bounty cards, milestone pages, reputation pages
  • Issue detail pages

No call site currently passes negative values (all mock data is non-negative), so this change is invisible in production today but fixes a latent bug that would surface the moment real negative data appears.


Ready for merge
All acceptance criteria from issue #90 met, fully tested, zero regressions.

Resolves MergeFi#90

## Problem
formatCurrency unconditionally applied Math.abs(), silently discarding
negative signs on financial figures. This created an inconsistency with
StatCard's internal currency formatter, which correctly preserves signs.

The same negative amount would render as:
- '-50 USDC' in StatCard (correct)
- '50 USDC' in formatCurrency (sign lost)

## Solution
- Removed Math.abs() from formatCurrency to preserve negative signs
- Added comprehensive JSDoc explaining the sign-preservation behavior
- Documented legitimate use cases for negative amounts (refunds,
  corrections, net-negative balances)
- Added extensive test coverage for sign preservation
- Added tests confirming formatCurrency and StatCard now agree

## Changes
- src/lib/utils.ts: Remove Math.abs(), add documentation
- src/lib/utils.test.ts: New comprehensive test suite (36 tests)
- src/components/ui/StatCard.test.tsx: Add negative value tests (5 tests)

## Testing
All 52 tests pass, including:
- Sign preservation for negative amounts
- formatCurrency(-50) !== formatCurrency(50)
- StatCard and formatCurrency produce identical output for negatives
- No regressions to existing positive/zero cases

## Impact
Financial figures can now display negative values correctly throughout
the app, matching standard accounting practices and user expectations.
@vercel

vercel Bot commented Aug 16, 2026

Copy link
Copy Markdown

@rindicomfort is attempting to deploy a commit to the chonilius' projects Team on Vercel.

A member of the Team first needs to authorize it.

- Consolidated two validateTeamSplits implementations into one
- Kept the more flexible version that handles both string and number types
- Updated empty array handling to return valid=false (splits must sum to 100%)
- All tests still pass (52 passing)
@rindicomfort
rindicomfort force-pushed the fix/formatcurrency-preserve-sign branch from e854b97 to 75fea94 Compare August 16, 2026 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

formatCurrency unconditionally applies Math.abs(), silently hiding the sign on negative financial figures

1 participant