Skip to content

Commit 44ac101

Browse files
fix(perps): normalize price formatting in order and position views (MetaMask#22931)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR refactors the fee and price formatting logic in the Perps feature to improve code clarity and consistency. ## **Changelog** CHANGELOG entry: Fixed a bug that caused too many decimals being displayed in the order detail view ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TAT-1970 ## **Manual testing steps** ```gherkin Feature: Perps transaction fee and price display Scenario: user views order transaction details Given user has completed a perps order transaction When user navigates to the order transaction details view Then all fees and prices should display with maximum 2 decimals Scenario: user views position transaction details Given user has an open or closed perps position When user navigates to the position transaction details view Then entry price, size, and fees should display with maximum 2 decimals ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/271fe44a-97ce-422b-ba00-f164055643e0 ### **After** <!-- [screenshots/recordings] --> <img width="1170" height="2532" alt="Simulator Screenshot - iPhone 16e - 2025-11-19 at 13 12 40" src="https://github.com/user-attachments/assets/7215ec22-4fcf-426b-9ea1-88c62b647bd0" /> ## **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. ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Introduce formatPositiveFiat and use it for limit price, fees, entry price, and size in Perps transaction views; update tests accordingly. > > - **Utils**: > - Replace `formatFee` with `formatPositiveFiat` in `utils/formatUtils.ts` (same semantics: `$0`, `< $0.01`, else fiat formatting). > - Keep `formatPerpsFiat` as general formatter; introduce/retain `PRICE_RANGES_UNIVERSAL`/`MINIMAL_VIEW` exports. > - **Perps UI**: > - `PerpsOrderTransactionView.tsx`: use `formatPositiveFiat` for `order.limitPrice` and fee rows (`metamask_fee`, `hyperliquid_fee`, `total_fee`). > - `PerpsPositionTransactionView.tsx`: use `formatPositiveFiat` for position `size`, `entry/close_price`, and `fees`; remove `PRICE_RANGES_UNIVERSAL` usage here. > - **Tests**: > - Update `formatUtils.test.ts` to import and validate `formatPositiveFiat` behavior (thresholds, rounding, stripping) and adjust related expectations; keep comprehensive tests for `formatPerpsFiat` and price ranges. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit bd8ed7d. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 2d39ddc commit 44ac101

4 files changed

Lines changed: 27 additions & 31 deletions

File tree

app/components/UI/Perps/Views/PerpsTransactionsView/PerpsOrderTransactionView.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import { usePerpsBlockExplorerUrl, usePerpsOrderFees } from '../../hooks';
2727
import { PerpsNavigationParamList } from '../../types/navigation';
2828
import { PerpsOrderTransactionRouteProp } from '../../types/transactionHistory';
2929
import {
30-
formatFee,
3130
formatPerpsFiat,
31+
formatPositiveFiat,
3232
formatTransactionDate,
3333
} from '../../utils/formatUtils';
3434
import { styleSheet } from './PerpsOrderTransactionView.styles';
@@ -94,7 +94,7 @@ const PerpsOrderTransactionView: React.FC = () => {
9494
},
9595
{
9696
label: strings('perps.transactions.order.limit_price'),
97-
value: formatPerpsFiat(transaction.order?.limitPrice ?? 0),
97+
value: formatPositiveFiat(transaction.order?.limitPrice ?? 0),
9898
},
9999
{
100100
label: strings('perps.transactions.order.filled'),
@@ -109,15 +109,15 @@ const PerpsOrderTransactionView: React.FC = () => {
109109
const feeRows = [
110110
{
111111
label: strings('perps.transactions.order.metamask_fee'),
112-
value: formatFee(isFilled ? metamaskFee : 0),
112+
value: formatPositiveFiat(isFilled ? metamaskFee : 0),
113113
},
114114
{
115115
label: strings('perps.transactions.order.hyperliquid_fee'),
116-
value: formatFee(isFilled ? protocolFee : 0),
116+
value: formatPositiveFiat(isFilled ? protocolFee : 0),
117117
},
118118
{
119119
label: strings('perps.transactions.order.total_fee'),
120-
value: formatFee(isFilled ? totalFee : 0),
120+
value: formatPositiveFiat(isFilled ? totalFee : 0),
121121
},
122122
];
123123

app/components/UI/Perps/Views/PerpsTransactionsView/PerpsPositionTransactionView.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ import {
3030
PerpsTransaction,
3131
} from '../../types/transactionHistory';
3232
import {
33-
formatFee,
34-
formatPerpsFiat,
33+
formatPositiveFiat,
3534
formatTransactionDate,
36-
PRICE_RANGES_UNIVERSAL,
3735
} from '../../utils/formatUtils';
3836
import { styleSheet } from './PerpsPositionTransactionView.styles';
3937

@@ -91,7 +89,7 @@ const PerpsPositionTransactionView: React.FC = () => {
9189
},
9290
transaction.fill?.amount && {
9391
label: strings('perps.transactions.position.size'),
94-
value: `${formatPerpsFiat(
92+
value: `${formatPositiveFiat(
9593
Math.abs(
9694
BigNumber(transaction.fill?.size || '0')
9795
.times(transaction.fill?.entryPrice || '0')
@@ -105,9 +103,7 @@ const PerpsPositionTransactionView: React.FC = () => {
105103
transaction.fill?.action === 'Closed'
106104
? strings('perps.transactions.position.close_price')
107105
: strings('perps.transactions.position.entry_price'),
108-
value: formatPerpsFiat(transaction.fill.entryPrice, {
109-
ranges: PRICE_RANGES_UNIVERSAL,
110-
}),
106+
value: formatPositiveFiat(transaction.fill.entryPrice),
111107
},
112108
].filter(Boolean);
113109

@@ -116,7 +112,7 @@ const PerpsPositionTransactionView: React.FC = () => {
116112
transaction.fill?.fee !== undefined &&
117113
transaction.fill?.fee !== null && {
118114
label: strings('perps.transactions.position.fees'),
119-
value: formatFee(transaction.fill.fee),
115+
value: formatPositiveFiat(transaction.fill.fee),
120116
textColor: TextColor.Default,
121117
},
122118
].filter(Boolean);

app/components/UI/Perps/utils/formatUtils.test.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ import {
1515
formatTransactionDate,
1616
formatDateSection,
1717
formatFundingRate,
18-
formatFee,
1918
PRICE_RANGES_UNIVERSAL,
2019
PRICE_RANGES_MINIMAL_VIEW,
20+
formatPositiveFiat,
2121
} from './formatUtils';
2222
import { FUNDING_RATE_CONFIG } from '../constants/perpsConfig';
2323

@@ -195,13 +195,13 @@ describe('formatUtils', () => {
195195
});
196196
});
197197

198-
describe('formatFee', () => {
198+
describe('formatPositiveFiat', () => {
199199
it('returns "$0" when fee is exactly zero', () => {
200200
// Given a fee of exactly zero
201201
const fee = 0;
202202

203203
// When formatting the fee
204-
const result = formatFee(fee);
204+
const result = formatPositiveFiat(fee);
205205

206206
// Then it returns "$0"
207207
expect(result).toBe('$0');
@@ -212,7 +212,7 @@ describe('formatUtils', () => {
212212
const fee = 0.005;
213213

214214
// When formatting the fee
215-
const result = formatFee(fee);
215+
const result = formatPositiveFiat(fee);
216216

217217
// Then it returns "< $0.01"
218218
expect(result).toBe('< $0.01');
@@ -223,7 +223,7 @@ describe('formatUtils', () => {
223223
const fee = 0.01;
224224

225225
// When formatting the fee
226-
const result = formatFee(fee);
226+
const result = formatPositiveFiat(fee);
227227

228228
// Then it formats normally
229229
expect(result).toBe('$0.01');
@@ -234,7 +234,7 @@ describe('formatUtils', () => {
234234
const fee = 1.5;
235235

236236
// When formatting the fee
237-
const result = formatFee(fee);
237+
const result = formatPositiveFiat(fee);
238238

239239
// Then it formats normally
240240
expect(result).toBe('$1.50');
@@ -245,7 +245,7 @@ describe('formatUtils', () => {
245245
const fee = 0.0001;
246246

247247
// When formatting the fee
248-
const result = formatFee(fee);
248+
const result = formatPositiveFiat(fee);
249249

250250
// Then it returns "< $0.01"
251251
expect(result).toBe('< $0.01');
@@ -256,7 +256,7 @@ describe('formatUtils', () => {
256256
const fee = 0.0099;
257257

258258
// When formatting the fee
259-
const result = formatFee(fee);
259+
const result = formatPositiveFiat(fee);
260260

261261
// Then it returns "< $0.01"
262262
expect(result).toBe('< $0.01');
@@ -267,7 +267,7 @@ describe('formatUtils', () => {
267267
const fee = 0.0101;
268268

269269
// When formatting the fee
270-
const result = formatFee(fee);
270+
const result = formatPositiveFiat(fee);
271271

272272
// Then it formats normally (rounded to $0.01)
273273
expect(result).toBe('$0.01');
@@ -278,7 +278,7 @@ describe('formatUtils', () => {
278278
const fee = 123.45;
279279

280280
// When formatting the fee
281-
const result = formatFee(fee);
281+
const result = formatPositiveFiat(fee);
282282

283283
// Then it formats with proper decimals
284284
expect(result).toBe('$123.45');
@@ -289,7 +289,7 @@ describe('formatUtils', () => {
289289
const fee = 100;
290290

291291
// When formatting the fee
292-
const result = formatFee(fee);
292+
const result = formatPositiveFiat(fee);
293293

294294
// Then trailing zeros are stripped
295295
expect(result).toBe('$100');
@@ -300,7 +300,7 @@ describe('formatUtils', () => {
300300
const fee = 1.23456789;
301301

302302
// When formatting the fee
303-
const result = formatFee(fee);
303+
const result = formatPositiveFiat(fee);
304304

305305
// Then it rounds appropriately
306306
expect(result).toBe('$1.23');
@@ -311,7 +311,7 @@ describe('formatUtils', () => {
311311
const fee = -0;
312312

313313
// When formatting the fee
314-
const result = formatFee(fee);
314+
const result = formatPositiveFiat(fee);
315315

316316
// Then it returns "$0"
317317
expect(result).toBe('$0');
@@ -322,7 +322,7 @@ describe('formatUtils', () => {
322322
const fee = 0.00000001;
323323

324324
// When formatting the fee
325-
const result = formatFee(fee);
325+
const result = formatPositiveFiat(fee);
326326

327327
// Then it returns "< $0.01"
328328
expect(result).toBe('< $0.01');

app/components/UI/Perps/utils/formatUtils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,11 +346,11 @@ export const formatPerpsFiat = (
346346
* Formats a fee value as USD currency with appropriate decimal places
347347
* @param fee - Raw numeric or string fee value (e.g., 1234.56, not token minimal denomination)
348348
* @returns Formatted currency string with variable decimals based on configured ranges
349-
* @example formatFee(1234.56) => "$1,234.56"
350-
* @example formatFee(0.005) => "< $0.01"
351-
* @example formatFee(0) => "$0"
349+
* @example formatPositiveFiat(1234.56) => "$1,234.56"
350+
* @example formatPositiveFiat(0.005) => "< $0.01"
351+
* @example formatPositiveFiat(0) => "$0"
352352
*/
353-
export const formatFee = (fee: number | string): string => {
353+
export const formatPositiveFiat = (fee: number | string): string => {
354354
const smallFeeThreshold = 0.01;
355355

356356
if (BigNumber(fee).isEqualTo(0)) {

0 commit comments

Comments
 (0)