Skip to content

Commit ab46059

Browse files
authored
chore: remove token list item v2 flag (#27731)
<!-- 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** Remove token list item V2 FF and token list item V1 <!-- 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: remove token list item V2 FF and token list item V1 ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2951 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] 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). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] 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] > **Medium Risk** > Medium risk because it removes an A/B-gated codepath and replaces the token row implementation and related analytics attribution, which can affect wallet token list rendering, navigation, and metrics across networks (EVM + non-EVM). > > **Overview** > Removes the `tokenListItemV2AbtestVersioned` feature flag and all V2 token list item codepaths, making token lists (`TokenList`, `TokensSection`) always render `TokenListItem`. > > `TokenListItem` is updated to absorb the former V2 layout: it replaces `AssetElement` with a custom row UI, adds fiat token-price display (EVM via market data + FX rates; non‑EVM via multichain rates), handles testnet/"loading" fiat states, and refines secondary-balance behavior for mUSD conversion and Merkl claim bonus (including claim/CTA tracking). > > Token details analytics attribution is simplified by dropping token-list-layout A/B test properties from `TOKEN_DETAILS_OPENED`, and unit tests/feature-flag registry entries are updated accordingly. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0b37022. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent fbfbf17 commit ab46059

12 files changed

Lines changed: 711 additions & 2913 deletions

File tree

app/components/UI/TokenDetails/Views/TokenDetails.tsx

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
22
import { View, StyleSheet, ActivityIndicator } from 'react-native';
33
import { useSelector } from 'react-redux';
4-
import { selectTokenListLayoutV2Enabled } from '../../../../selectors/featureFlagController/tokenListLayout';
54
import { useAnalytics } from '../../../hooks/useAnalytics/useAnalytics';
65
import { MetaMetricsEvents } from '../../../../core/Analytics';
76
import { SupportedCaipChainId } from '@metamask/multichain-network-controller';
@@ -317,7 +316,6 @@ const TokenDetails: React.FC<{
317316
const useTokenDetailsOpenedTracking = (params: TokenDetailsRouteParams) => {
318317
const { trackEvent, createEventBuilder } = useAnalytics();
319318
const { variantName, isTestActive } = useTokenDetailsABTest();
320-
const isTokenListV2 = useSelector(selectTokenListLayoutV2Enabled);
321319
const lastTrackedTokenKeyRef = useRef<string | null>(null);
322320

323321
return useCallback(
@@ -356,16 +354,9 @@ const useTokenDetailsOpenedTracking = (params: TokenDetailsRouteParams) => {
356354
market_insights_displayed: isMarketInsightsDisplayed,
357355
severity,
358356
// A/B test attribution — each experiment is independent
359-
...((isTestActive || isFromTokenList) && {
357+
...(isTestActive && {
360358
ab_tests: {
361-
...(isTestActive && {
362-
assetsASSETS2493AbtestTokenDetailsLayout: variantName,
363-
}),
364-
...(isFromTokenList && {
365-
assetsASSETS2621AbtestTokenListLayout: isTokenListV2
366-
? 'v2'
367-
: 'v1',
368-
}),
359+
assetsASSETS2493AbtestTokenDetailsLayout: variantName,
369360
},
370361
}),
371362
};
@@ -378,7 +369,6 @@ const useTokenDetailsOpenedTracking = (params: TokenDetailsRouteParams) => {
378369
[
379370
createEventBuilder,
380371
isTestActive,
381-
isTokenListV2,
382372
params.address,
383373
params.balance,
384374
params.chainId,

app/components/UI/Tokens/TokenList/TokenList.test.tsx

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,25 +77,6 @@ jest.mock('./TokenListItem/TokenListItem', () => ({
7777
},
7878
}));
7979

80-
jest.mock('./TokenListItemV2/TokenListItemV2', () => ({
81-
TokenListItemV2: ({ assetKey }: { assetKey: { address: string } }) => {
82-
const React = jest.requireActual('react');
83-
const { View, Text } = jest.requireActual('react-native');
84-
return React.createElement(
85-
View,
86-
{ testID: `token-item-v2-${assetKey.address}` },
87-
React.createElement(Text, null, `Token V2: ${assetKey.address}`),
88-
);
89-
},
90-
}));
91-
92-
jest.mock(
93-
'../../../../selectors/featureFlagController/tokenListLayout',
94-
() => ({
95-
selectTokenListLayoutV2Enabled: jest.fn(() => false),
96-
}),
97-
);
98-
9980
// Mock design system components
10081
jest.mock('@metamask/design-system-react-native', () => ({
10182
Box: ({

app/components/UI/Tokens/TokenList/TokenList.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
import { TokenI } from '../types';
1818
import { strings } from '../../../../../locales/i18n';
1919
import { TokenListItem } from './TokenListItem/TokenListItem';
20-
import { TokenListItemV2 } from './TokenListItemV2/TokenListItemV2';
2120
import { WalletViewSelectorsIDs } from '../../../Views/Wallet/WalletView.testIds';
2221
import { useNavigation } from '@react-navigation/native';
2322
import Routes from '../../../../constants/navigation/Routes';
@@ -31,7 +30,6 @@ import { useTailwind } from '@metamask/design-system-twrnc-preset';
3130
import { MetaMetricsEvents } from '../../../../core/Analytics';
3231
import { useAnalytics } from '../../../hooks/useAnalytics/useAnalytics';
3332
import { SCROLL_TO_TOKEN_EVENT } from '../constants';
34-
import { selectTokenListLayoutV2Enabled } from '../../../../selectors/featureFlagController/tokenListLayout';
3533
import { useMusdCtaVisibility } from '../../Earn/hooks/useMusdCtaVisibility';
3634

3735
export interface FlashListAssetKey {
@@ -74,10 +72,6 @@ const TokenListComponent = ({
7472
// Declaring this here and passing it down to avoid O(n) API calls to on-ramp
7573
const { shouldShowTokenListItemCta } = useMusdCtaVisibility();
7674

77-
// A/B test: Token list item layout (V1 vs V2)
78-
const isTokenListV2 = useSelector(selectTokenListLayoutV2Enabled);
79-
const ListItemComponent = isTokenListV2 ? TokenListItemV2 : TokenListItem;
80-
8175
const listRef = useRef<FlashListRef<FlashListAssetKey>>(null);
8276

8377
const navigation = useNavigation();
@@ -166,7 +160,7 @@ const TokenListComponent = ({
166160

167161
const renderTokenListItem = useCallback(
168162
({ item }: { item: FlashListAssetKey }) => (
169-
<ListItemComponent
163+
<TokenListItem
170164
assetKey={item}
171165
showRemoveMenu={showRemoveMenu}
172166
setShowScamWarningModal={setShowScamWarningModal}
@@ -178,7 +172,6 @@ const TokenListComponent = ({
178172
/>
179173
),
180174
[
181-
ListItemComponent,
182175
showRemoveMenu,
183176
setShowScamWarningModal,
184177
privacyMode,
@@ -197,7 +190,7 @@ const TokenListComponent = ({
197190
testID={WalletViewSelectorsIDs.TOKENS_CONTAINER_LIST}
198191
>
199192
{displayTokenKeys.map((item, index) => (
200-
<ListItemComponent
193+
<TokenListItem
201194
key={`${getTokenKey(item)}-${index}`}
202195
assetKey={item}
203196
showRemoveMenu={showRemoveMenu}

0 commit comments

Comments
 (0)