Skip to content

Commit 3655a92

Browse files
authored
fix(perps): preserve integer trailing zeros when szDecimals=0 (#29016)
## **Description** `formatPositionSize` in `app/controllers/perps/utils/perpsFormatters.ts` uses ```ts value.toFixed(szDecimals).replace(/\.?0+$/u, '') ``` to strip trailing zeros. Because the decimal point is optional in the regex, the pattern also matches trailing zeros on pure integer strings — so whenever `szDecimals = 0`, valid zeros are eaten: - `formatPositionSize(100, 0)` → `"1"` (expected `"100"`) - `formatPositionSize(20, 0)` → `"2"` (expected `"20"`) - `formatPositionSize(1000, 0)` → `"1"` (expected `"1000"`) This affects every HyperLiquid asset with `szDecimals = 0` (whole-unit assets). The magnitude-based fallback path below is unaffected — it always calls `toFixed(2/4/6)`, so a decimal point is guaranteed. ### Fix Only strip trailing zeros when `toFixed` actually produced a decimal point: ```ts const fixed = value.toFixed(szDecimals); return fixed.includes('.') ? fixed.replace(/\.?0+$/u, '') : fixed; ``` ### Cross-reference Same bug was caught by Cursor Bugbot on the extension copy and fixed in [metamask-extension#41920](MetaMask/metamask-extension#41920) (commit `ed9de1f1`). The extension currently mirrors this file verbatim, so mobile needs the same fix to stay authoritative. ## **Changelog** CHANGELOG entry: Fixed a perps position size formatting bug that stripped valid trailing zeros on whole-unit assets (szDecimals=0), e.g. displaying "1" instead of "100". ## **Related issues** Fixes: [TAT-2992](https://consensyssoftware.atlassian.net/browse/TAT-2992) ## **Manual testing steps** ```gherkin Feature: Position size formatting for whole-unit assets Scenario: user views a position on a HyperLiquid asset with szDecimals=0 Given the asset has szDecimals=0 in HyperLiquid metadata And the user holds a position of 100 units When the position size is rendered in the perps UI Then the displayed size is "100" (not "1") ``` Unit tests cover the regression directly (see new cases added to `perpsFormatters.test.ts`). ## **Screenshots/Recordings** ### **Before** n/a — unit-test-only fix; reproduced via `formatPositionSize(100, 0) === "1"`. ### **After** n/a — `formatPositionSize(100, 0) === "100"` (new test cases). ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) Not applicable — pure string-formatting fix with no perf impact. - [ ] I've tested on Android - [ ] I've tested with a power user scenario - [ ] I've instrumented key operations with Sentry traces for production performance metrics ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [TAT-2992]: https://consensyssoftware.atlassian.net/browse/TAT-2992?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk, isolated change to position-size string formatting that only affects the `szDecimals` path (especially `szDecimals=0`) and is covered by a targeted regression test. > > **Overview** > Fixes `formatPositionSize` so whole-unit assets with `szDecimals=0` no longer lose significant trailing zeros (e.g., `"100"` incorrectly becoming `"1"`). The formatter now only strips trailing zeros when `toFixed(szDecimals)` produces a decimal point, and adds a regression test suite covering integer and rounding behavior for `szDecimals=0`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e732c53. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent e1a97df commit 3655a92

2 files changed

Lines changed: 13 additions & 1 deletion

File tree

app/controllers/perps/utils/perpsFormatters.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@ describe('formatPositionSize', () => {
178178
expect(formatPositionSize(44.0, 2)).toBe('44');
179179
});
180180

181+
it('preserves integer trailing zeros when szDecimals=0 (whole-unit assets)', () => {
182+
expect(formatPositionSize(100, 0)).toBe('100');
183+
expect(formatPositionSize(20, 0)).toBe('20');
184+
expect(formatPositionSize(1000, 0)).toBe('1000');
185+
expect(formatPositionSize(1, 0)).toBe('1');
186+
expect(formatPositionSize(1.7, 0)).toBe('2');
187+
});
188+
181189
it('uses magnitude logic for very small values (< 0.01) without szDecimals', () => {
182190
const result = formatPositionSize(0.00009);
183191
expect(result).toBe('0.00009');

app/controllers/perps/utils/perpsFormatters.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,11 @@ export const formatPositionSize = (
522522

523523
// Use asset-specific decimals if provided (Hyperliquid metadata)
524524
if (szDecimals !== undefined) {
525-
return value.toFixed(szDecimals).replace(/\.?0+$/u, '');
525+
const fixed = value.toFixed(szDecimals);
526+
// Only strip trailing zeros when a decimal point is present; toFixed(0)
527+
// returns an integer string and the regex would otherwise eat valid zeros
528+
// on whole-unit assets (szDecimals=0), e.g. "100" -> "1".
529+
return fixed.includes('.') ? fixed.replace(/\.?0+$/u, '') : fixed;
526530
}
527531

528532
// Fallback: magnitude-based decimal logic for backwards compatibility

0 commit comments

Comments
 (0)