Skip to content

Commit 09ce116

Browse files
nickewansmithgambinishabretonc7sdylanbutler1
authored
fix: cp-7.59.0 remove dex prefix for hip3 asset display (MetaMask#22461)
<!-- 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** Added support for proper display of hip3 and other DEX assets by stripping prefixes from asset symbols throughout the Perps UI. - Added `getPerpsDisplaySymbol()` in `marketUtils.ts` - Strips DEX prefixes (e.g., `hip3:`, `xyz:`) from asset symbols - Returns clean symbol for display (e.g., `hip3:BTC` → `BTC`) **Utils:** - `transactionTransforms.ts` - Strip prefixes in transaction subtitles (fills, orders, funding) **Hooks:** - `usePerpsToasts.tsx` - Clean asset names in toast notifications **Components:** - `PerpsAmountDisplay.tsx` - Display token symbols without prefixes - `PerpsOrderHeader.tsx` - Show clean asset names in order titles - `PerpsOpenOrderCard.tsx` - Format symbols in order cards - `PerpsRecentActivityList.tsx` - Display clean symbols in activity list - Hip3 assets now display as `BTC` instead of `hip3:BTC` - Stock/commodity assets show as `TSLA` instead of `xyz:TSLA` - Consistent, clean asset naming across entire Perps UI - Regular assets (BTC, ETH, SOL) remain unchanged <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2043 Fixes: MetaMask#22439 ## **Manual testing steps** ```gherkin Feature: Hip3 Asset Name Display Background: Given the system uses getPerpsDisplaySymbol() to format asset names Scenario: Strip DEX prefix from hip3 assets Given a hip3 asset with symbol "hip3:BTC" When displaying the asset name Then show "BTC" Scenario: Keep regular asset names unchanged Given a regular asset with symbol "BTC" When displaying the asset name Then show "BTC" ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** https://github.com/user-attachments/assets/c6c73f1c-2640-4dac-9311-eaae8393e235 <!-- [screenshots/recordings] --> ## **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] > Standardizes Perps asset symbols by stripping DEX prefixes (e.g., hip3:, xyz:) via getPerpsDisplaySymbol across UI, toasts, and transaction transforms, with comprehensive tests. > > - **Utils**: > - Add `getPerpsDisplaySymbol` in `marketUtils` to strip DEX prefixes from symbols for display. > - Apply in `transactionTransforms` to clean `subtitle` for fills, orders, and funding items. > - **Hooks**: > - Update `usePerpsToasts` to use cleaned symbols in all toast subtitles and errors. > - **Components**: > - `PerpsOrderHeader`, `PerpsAmountDisplay`, `PerpsOpenOrderCard`, `PerpsRecentActivityList`, `PerpsClosePositionView`, `PerpsOrderView`: replace raw symbols with `getPerpsDisplaySymbol` in titles, labels, and amounts. > - **Tests**: > - Add/expand coverage to assert prefix stripping (HIP-3/DEX) and unchanged regular symbols across the updated components, hooks, and utils. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit f7c4f2d. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Nicholas Gambino <nicholas.gambino@consensys.net> Co-authored-by: Nick Gambino <35090461+gambinish@users.noreply.github.com> Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com> Co-authored-by: Arthur Breton <arthur.breton@consensys.net> Co-authored-by: dylanbutler1 <99672693+dylanbutler1@users.noreply.github.com>
1 parent b10575a commit 09ce116

16 files changed

Lines changed: 629 additions & 31 deletions

File tree

app/components/UI/Perps/Views/PerpsClosePositionView/PerpsClosePositionView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import PerpsAmountDisplay from '../../components/PerpsAmountDisplay';
7575
import PerpsLimitPriceBottomSheet from '../../components/PerpsLimitPriceBottomSheet';
7676
import PerpsSlider from '../../components/PerpsSlider/PerpsSlider';
7777
import PerpsCloseSummary from '../../components/PerpsCloseSummary';
78+
import { getPerpsDisplaySymbol } from '../../utils/marketUtils';
7879

7980
const PerpsClosePositionView: React.FC = () => {
8081
const theme = useTheme();
@@ -557,7 +558,7 @@ const PerpsClosePositionView: React.FC = () => {
557558
{/* Toggle Button for USD/Token Display */}
558559
<View style={styles.toggleContainer}>
559560
<Text variant={TextVariant.BodySM} color={TextColor.Alternative}>
560-
{`${formatPositionSize(closeAmount, marketData?.szDecimals)} ${position.coin}`}
561+
{`${formatPositionSize(closeAmount, marketData?.szDecimals)} ${getPerpsDisplaySymbol(position.coin)}`}
561562
</Text>
562563
</View>
563564

app/components/UI/Perps/Views/PerpsHeroCardView/PerpsHeroCardView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import {
6060
getPerpsHeroCardViewSelector,
6161
} from '../../../../../../e2e/selectors/Perps/Perps.selectors';
6262
import { useReferralDetails } from '../../../Rewards/hooks/useReferralDetails';
63+
import { getPerpsDisplaySymbol } from '../../utils/marketUtils';
6364

6465
// To add a new card, add the image to the array.
6566
const CARD_IMAGES: { image: ImageSourcePropType; id: number; name: string }[] =
@@ -185,7 +186,7 @@ const PerpsHeroCardView: React.FC = () => {
185186
style={styles.assetName}
186187
testID={getPerpsHeroCardViewSelector.assetSymbol(index)}
187188
>
188-
{data.asset}
189+
{getPerpsDisplaySymbol(data.asset)}
189190
</Text>
190191
<View
191192
style={styles.directionBadge}

app/components/UI/Perps/Views/PerpsOrderView/PerpsOrderView.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,9 @@ const PerpsOrderViewContentBase: React.FC = () => {
864864
!isLoadingAccount && amountTimesLeverage < minimumOrderAmount;
865865
const placeOrderLabel = isInsufficientFunds
866866
? strings('perps.order.validation.insufficient_funds')
867-
: strings(orderButtonKey, { asset: orderForm.asset });
867+
: strings(orderButtonKey, {
868+
asset: getPerpsDisplaySymbol(orderForm.asset),
869+
});
868870

869871
const doesStopLossRiskLiquidation = Boolean(
870872
orderForm.stopLossPrice &&

app/components/UI/Perps/components/PerpsAmountDisplay/PerpsAmountDisplay.test.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,68 @@ describe('PerpsAmountDisplay', () => {
249249
// No token amount should be displayed
250250
expect(screen.queryByText(/BTC|ETH|SOL/)).toBeNull();
251251
});
252+
253+
it('strips hip3 prefix from token symbol when showing token amount', () => {
254+
// Arrange
255+
const tokenAmount = '1.5';
256+
const tokenSymbol = 'hip3:BTC';
257+
const amount = '50000';
258+
259+
// Act
260+
render(
261+
<PerpsAmountDisplay
262+
amount={amount}
263+
showTokenAmount
264+
tokenAmount={tokenAmount}
265+
tokenSymbol={tokenSymbol}
266+
/>,
267+
);
268+
269+
// Assert
270+
const tokenElements = screen.getAllByText('1.5 BTC');
271+
expect(tokenElements.length).toBe(2); // Main display and token amount section
272+
});
273+
274+
it('strips DEX prefix from token symbol when showing max amount', () => {
275+
// Arrange
276+
const amount = '10000';
277+
const tokenAmount = '100';
278+
const tokenSymbol = 'xyz:TSLA';
279+
280+
// Act
281+
const { getByText } = render(
282+
<PerpsAmountDisplay
283+
amount={amount}
284+
showMaxAmount
285+
tokenAmount={tokenAmount}
286+
tokenSymbol={tokenSymbol}
287+
/>,
288+
);
289+
290+
// Assert
291+
expect(getByText('100 TSLA')).toBeTruthy();
292+
});
293+
294+
it('keeps regular token symbols unchanged', () => {
295+
// Arrange
296+
const amount = '5000';
297+
const tokenAmount = '2.5';
298+
const tokenSymbol = 'SOL';
299+
300+
// Act
301+
render(
302+
<PerpsAmountDisplay
303+
amount={amount}
304+
showTokenAmount
305+
tokenAmount={tokenAmount}
306+
tokenSymbol={tokenSymbol}
307+
/>,
308+
);
309+
310+
// Assert
311+
const tokenElements = screen.getAllByText('2.5 SOL');
312+
expect(tokenElements.length).toBe(2);
313+
});
252314
});
253315

254316
describe('Formatting', () => {

app/components/UI/Perps/components/PerpsAmountDisplay/PerpsAmountDisplay.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
} from '../../utils/formatUtils';
1616
import { PERPS_CONSTANTS } from '../../constants/perpsConfig';
1717
import createStyles from './PerpsAmountDisplay.styles';
18+
import { getPerpsDisplaySymbol } from '../../utils/marketUtils';
1819

1920
interface PerpsAmountDisplayProps {
2021
amount: string;
@@ -52,7 +53,7 @@ const PerpsAmountDisplay: React.FC<PerpsAmountDisplayProps> = ({
5253
// Calculate display value - extracted from nested ternary for clarity
5354
const displayValue = (() => {
5455
if (showTokenAmount && tokenAmount && tokenSymbol) {
55-
return `${formatPositionSize(tokenAmount)} ${tokenSymbol}`;
56+
return `${formatPositionSize(tokenAmount)} ${getPerpsDisplaySymbol(tokenSymbol)}`;
5657
}
5758
if (amount) {
5859
return formatPerpsFiat(amount, { ranges: PRICE_RANGES_MINIMAL_VIEW });
@@ -137,7 +138,7 @@ const PerpsAmountDisplay: React.FC<PerpsAmountDisplayProps> = ({
137138
style={styles.maxAmount}
138139
testID={PerpsAmountDisplaySelectorsIDs.MAX_LABEL}
139140
>
140-
{formatPositionSize(tokenAmount)} {tokenSymbol}
141+
{formatPositionSize(tokenAmount)} {getPerpsDisplaySymbol(tokenSymbol)}
141142
</Text>
142143
)}
143144
{showWarning && (

app/components/UI/Perps/components/PerpsOpenOrderCard/PerpsOpenOrderCard.test.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,48 @@ describe('PerpsOpenOrderCard', () => {
402402
expect(screen.getByText(/0\.1\s+BTC/)).toBeOnTheScreen();
403403
});
404404

405+
it('strips hip3 prefix from asset symbol', () => {
406+
const hip3Order = {
407+
...mockOrder,
408+
symbol: 'hip3:BTC',
409+
size: '1.5',
410+
originalSize: '1.5',
411+
};
412+
413+
render(<PerpsOpenOrderCard order={hip3Order} />);
414+
415+
// Should display "BTC" without the hip3 prefix
416+
expect(screen.getByText(/1\.5\s+BTC/)).toBeOnTheScreen();
417+
});
418+
419+
it('strips DEX prefix from asset symbol', () => {
420+
const dexOrder = {
421+
...mockOrder,
422+
symbol: 'xyz:TSLA',
423+
size: '100',
424+
originalSize: '100',
425+
};
426+
427+
render(<PerpsOpenOrderCard order={dexOrder} />);
428+
429+
// Should display "TSLA" without the xyz prefix
430+
expect(screen.getByText(/100\s+TSLA/)).toBeOnTheScreen();
431+
});
432+
433+
it('keeps regular asset symbols unchanged', () => {
434+
const solOrder = {
435+
...mockOrder,
436+
symbol: 'SOL',
437+
size: '50',
438+
originalSize: '50',
439+
};
440+
441+
render(<PerpsOpenOrderCard order={solOrder} />);
442+
443+
// Should display "SOL" as is
444+
expect(screen.getByText(/50\s+SOL/)).toBeOnTheScreen();
445+
});
446+
405447
it('handles market orders', () => {
406448
const marketOrder = {
407449
...mockOrder,

app/components/UI/Perps/components/PerpsOpenOrderCard/PerpsOpenOrderCard.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import PerpsTokenLogo from '../PerpsTokenLogo';
3535
import PerpsBottomSheetTooltip from '../PerpsBottomSheetTooltip/PerpsBottomSheetTooltip';
3636
import { useSelector } from 'react-redux';
3737
import { selectPerpsEligibility } from '../../selectors/perpsController';
38+
import { getPerpsDisplaySymbol } from '../../utils/marketUtils';
3839

3940
/**
4041
* PerpsOpenOrderCard Component
@@ -247,7 +248,8 @@ const PerpsOpenOrderCard: React.FC<PerpsOpenOrderCardProps> = ({
247248
</Text>
248249
</View>
249250
<Text variant={TextVariant.BodySM} color={TextColor.Alternative}>
250-
{formatPositionSize(order.originalSize)} {order.symbol}
251+
{formatPositionSize(order.originalSize)}{' '}
252+
{getPerpsDisplaySymbol(order.symbol)}
251253
</Text>
252254
</View>
253255

app/components/UI/Perps/components/PerpsOrderHeader/PerpsOrderHeader.test.tsx

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,57 @@ describe('PerpsOrderHeader', () => {
193193
const orderTypeButton = getByTestId('perps-order-header-order-type-button');
194194
expect(orderTypeButton.props.disabled).toBe(true);
195195
});
196+
197+
describe('HIP3 Asset Symbol Handling', () => {
198+
it('should strip hip3 prefix from asset symbol in long direction', () => {
199+
const { getByText } = render(
200+
<PerpsOrderHeader
201+
{...defaultProps}
202+
asset="hip3:BTC"
203+
direction="long"
204+
/>,
205+
);
206+
expect(getByText('Long BTC')).toBeTruthy();
207+
});
208+
209+
it('should strip hip3 prefix from asset symbol in short direction', () => {
210+
const { getByText } = render(
211+
<PerpsOrderHeader
212+
{...defaultProps}
213+
asset="hip3:ETH"
214+
direction="short"
215+
/>,
216+
);
217+
expect(getByText('Short ETH')).toBeTruthy();
218+
});
219+
220+
it('should strip DEX prefix from asset symbol', () => {
221+
const { getByText } = render(
222+
<PerpsOrderHeader
223+
{...defaultProps}
224+
asset="xyz:TSLA"
225+
direction="long"
226+
/>,
227+
);
228+
expect(getByText('Long TSLA')).toBeTruthy();
229+
});
230+
231+
it('should keep regular asset symbols unchanged', () => {
232+
const { getByText } = render(
233+
<PerpsOrderHeader {...defaultProps} asset="SOL" direction="short" />,
234+
);
235+
expect(getByText('Short SOL')).toBeTruthy();
236+
});
237+
238+
it('should strip prefix even with custom title not provided', () => {
239+
const { getByText } = render(
240+
<PerpsOrderHeader
241+
{...defaultProps}
242+
asset="abc:AAPL"
243+
direction="long"
244+
/>,
245+
);
246+
expect(getByText('Long AAPL')).toBeTruthy();
247+
});
248+
});
196249
});

app/components/UI/Perps/components/PerpsOrderHeader/PerpsOrderHeader.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
} from '../../utils/formatUtils';
2525
import { createStyles } from './PerpsOrderHeader.styles';
2626
import { strings } from '../../../../../../locales/i18n';
27+
import { getPerpsDisplaySymbol } from '../../utils/marketUtils';
2728

2829
interface PerpsOrderHeaderProps {
2930
asset: string;
@@ -112,7 +113,7 @@ const PerpsOrderHeader: React.FC<PerpsOrderHeaderProps> = ({
112113
direction === 'long'
113114
? strings('perps.market.long')
114115
: strings('perps.market.short')
115-
} ${asset}`}
116+
} ${getPerpsDisplaySymbol(asset)}`}
116117
</Text>
117118
<View style={styles.priceRow}>
118119
<Text variant={TextVariant.BodyMD} color={TextColor.Default}>

app/components/UI/Perps/components/PerpsRecentActivityList/PerpsRecentActivityList.test.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,48 @@ describe('PerpsRecentActivityList', () => {
236236
expect(screen.getByText('2.0 ETH')).toBeOnTheScreen();
237237
});
238238

239+
it('strips hip3 prefix from transaction subtitle', () => {
240+
const hip3Transactions = [
241+
{
242+
...mockTransactions[0],
243+
subtitle: 'hip3:BTC',
244+
asset: 'hip3:BTC',
245+
},
246+
];
247+
248+
render(<PerpsRecentActivityList transactions={hip3Transactions} />);
249+
250+
expect(screen.getByText('BTC')).toBeOnTheScreen();
251+
});
252+
253+
it('strips DEX prefix from transaction subtitle', () => {
254+
const dexTransactions = [
255+
{
256+
...mockTransactions[0],
257+
subtitle: 'xyz:TSLA',
258+
asset: 'xyz:TSLA',
259+
},
260+
];
261+
262+
render(<PerpsRecentActivityList transactions={dexTransactions} />);
263+
264+
expect(screen.getByText('TSLA')).toBeOnTheScreen();
265+
});
266+
267+
it('keeps regular symbols unchanged in subtitle', () => {
268+
const solTransactions = [
269+
{
270+
...mockTransactions[0],
271+
subtitle: 'SOL',
272+
asset: 'SOL',
273+
},
274+
];
275+
276+
render(<PerpsRecentActivityList transactions={solTransactions} />);
277+
278+
expect(screen.getByText('SOL')).toBeOnTheScreen();
279+
});
280+
239281
it('renders token logos for each transaction', () => {
240282
render(<PerpsRecentActivityList transactions={mockTransactions} />);
241283

0 commit comments

Comments
 (0)