Skip to content

Commit cabe1a2

Browse files
authored
chore: remove tokensChainsCache from assets selectors, transactions utils, and test fixtures (#28925)
<!-- 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** Removes all usages of the deprecated `tokensChainsCache` field from `TokenListController` across the codebase. This includes: - Deleting `app/selectors/tokenListController.ts` which exposed `selectTokenList`, `selectERC20TokensByChain`, and `selectERC20TokensByChainInternal` — all deprecated selectors that read from `tokensChainsCache` - Refactoring `selectAsset` and `assetToToken` in `assets-list.ts` to source `aggregators` directly from the token stored in `allTokens` (via `TokensController`) instead of looking it up in `tokensChainsCache` - Removing the early-return shortcut in `isSmartContractAddress` that checked `tokensChainsCache` before querying the network - Removing the `TokenListController.tokensChainsCache` mask from the Sentry state filter - Cleaning up all test fixtures and mocks that referenced `tokensChainsCache` <!-- 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 tokensChainsCache from assets selectors, transactions utils, and test fixtures ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3058 ## **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. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **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** > Touches asset-to-token mapping and contract-address detection behavior; mistakes could cause missing token metadata (e.g., `aggregators`) or extra network calls/perf regressions from removing the cache short-circuit. > > **Overview** > Removes the deprecated `TokenListController` selectors (`selectTokenList`, `selectERC20TokensByChain`) and updates callers/tests to no longer mock or depend on them. > > Updates `selectAsset` in `assets-list` to stop reading `TokenListController.tokensChainsCache`; `aggregators` (and `rwaData`) are now sourced from `TokensController.allTokens`, and related state fixtures/tests are adjusted accordingly. > > Simplifies `isSmartContractAddress` in `util/transactions` by dropping the mainnet token-cache short-circuit, and cleans up Sentry state masking to no longer reference `TokenListController.tokensChainsCache`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 016a367. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 47ee978 commit cabe1a2

9 files changed

Lines changed: 6 additions & 131 deletions

File tree

app/components/UI/AssetOverview/TokenDetails/TokenDetails.test.tsx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
selectEvmTicker,
1010
selectProviderConfig,
1111
} from '../../../../selectors/networkController';
12-
import { selectTokenList } from '../../../../selectors/tokenListController';
1312
import { selectContractExchangeRates } from '../../../../selectors/tokenRatesController';
1413
import { backgroundState } from '../../../../util/test/initial-root-state';
1514
import renderWithProvider from '../../../../util/test/renderWithProvider';
@@ -80,9 +79,6 @@ const mockDAI = {
8079
hasBalanceError: false,
8180
chainId: '0x1',
8281
};
83-
const mockAssets = {
84-
'0x6b175474e89094c44da98b954eedeac495271d0f': mockDAI,
85-
};
8682
const mockExchangeRate = 2712.15;
8783
const mockCurrentCurrency = 'usd';
8884
const mockContractExchangeRates = {
@@ -172,8 +168,6 @@ describe('TokenDetails', () => {
172168
}
173169

174170
switch (selectorOrCallback) {
175-
case selectTokenList:
176-
return mockAssets;
177171
case selectContractExchangeRates:
178172
return {};
179173
case selectConversionRate:
@@ -249,8 +243,6 @@ describe('TokenDetails', () => {
249243
}
250244

251245
switch (selectorOrCallback) {
252-
case selectTokenList:
253-
return mockAssets;
254246
case selectContractExchangeRates:
255247
return {};
256248
case selectConversionRate:

app/components/Views/TradeWalletActions/TradeWalletActions.test.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,6 @@ jest.mock('../../../core/redux/slices/bridge', () => ({
147147
selectEnabledSourceChains: jest.fn().mockReturnValue([]),
148148
}));
149149

150-
jest.mock('../../../selectors/tokenListController', () => ({
151-
selectTokenList: jest.fn().mockReturnValue([]),
152-
}));
153-
154150
jest.mock('../../UI/Stake/hooks/useStakingEligibility', () => ({
155151
__esModule: true,
156152
default: jest.fn(),

app/components/Views/WalletActions/WalletActions.test.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,6 @@ jest.mock('../../../core/redux/slices/bridge', () => ({
132132
selectIsSwapsEnabled: jest.fn().mockReturnValue(true),
133133
}));
134134

135-
jest.mock('../../../selectors/tokenListController', () => ({
136-
selectTokenList: jest.fn().mockReturnValue([]),
137-
}));
138-
139135
jest.mock('../../UI/Stake/hooks/useStakingEligibility', () => ({
140136
__esModule: true,
141137
default: jest.fn(),

app/selectors/assets/assets-list.test.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ const mockState = ({
151151
decimals: 18,
152152
symbol: 'stETH',
153153
name: 'Lido Staked Ether',
154+
aggregators: ['UniswapLabs', 'Metamask', 'Aave'],
154155
image:
155156
'https://static.cx.metamask.io/api/v1/tokenIcons/10/0xae7ab96520de3a18e5e111b5eaab095312d7fe84.png',
156157
},
@@ -227,19 +228,6 @@ const mockState = ({
227228
},
228229
},
229230
},
230-
TokenListController: {
231-
tokensChainsCache: {
232-
'0x1': {
233-
data: {
234-
'0xae7ab96520de3a18e5e111b5eaab095312d7fe84': {
235-
address: '0xae7ab96520de3a18e5e111b5eaab095312d7fe84',
236-
symbol: 'stETH',
237-
aggregators: ['UniswapLabs', 'Metamask', 'Aave'],
238-
},
239-
},
240-
},
241-
},
242-
},
243231
MultichainAssetsController: {
244232
accountsAssets: {
245233
'2d89e6a0-b4e6-45a8-a707-f10cef143b42': [

app/selectors/assets/assets-list.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -496,8 +496,6 @@ export const selectAsset = createSelector(
496496
[
497497
selectAssetsBySelectedAccountGroup,
498498
selectStakedAssets,
499-
(state: RootState) =>
500-
state.engine.backgroundState.TokenListController.tokensChainsCache,
501499
selectAllTokens,
502500
selectSelectedInternalAccountAddress,
503501
selectSelectedInternalAccountByScope,
@@ -517,7 +515,6 @@ export const selectAsset = createSelector(
517515
(
518516
assets,
519517
stakedAssets,
520-
tokensChainsCache,
521518
allTokens,
522519
selectedAddress,
523520
getAccountByScope,
@@ -549,16 +546,17 @@ export const selectAsset = createSelector(
549546
);
550547
});
551548

552-
// Look up rwaData from the original token in allTokens
549+
// Look up aggregators and rwaData from the original token in allTokens
553550
const originalToken = selectedAddress
554551
? allTokens?.[chainId as Hex]?.[selectedAddress]?.find(
555552
(token) => token.address.toLowerCase() === address.toLowerCase(),
556553
)
557554
: undefined;
558555

556+
const aggregators = originalToken?.aggregators;
559557
const rwaData = (originalToken as TokenI | undefined)?.rwaData;
560558

561-
return asset ? assetToToken(asset, tokensChainsCache, rwaData) : undefined;
559+
return asset ? assetToToken(asset, aggregators, rwaData) : undefined;
562560
},
563561
);
564562

@@ -568,15 +566,12 @@ const oneHundredths = 0.01;
568566
// BIP44 MAINTENANCE: Review what fields are really needed
569567
function assetToToken(
570568
asset: Asset & { isStaked?: boolean },
571-
tokensChainsCache: TokenListState['tokensChainsCache'],
569+
aggregators?: string[],
572570
rwaData?: TokenI['rwaData'],
573571
): TokenI {
574572
return {
575573
address: asset.assetId,
576-
aggregators:
577-
('address' in asset &&
578-
tokensChainsCache[asset.chainId]?.data[asset.address]?.aggregators) ||
579-
[],
574+
aggregators: aggregators ?? [],
580575
decimals: asset.decimals,
581576
image: asset.image,
582577
name: asset.name,

app/selectors/tokenListController.ts

Lines changed: 0 additions & 36 deletions
This file was deleted.

app/util/sentry/utils.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,6 @@ export const sentryStateMask = {
160160
SubjectMetadataController: {
161161
[AllProperties]: false,
162162
},
163-
TokenListController: {
164-
tokensChainsCache: {
165-
[AllProperties]: false,
166-
},
167-
},
168163
TokenRatesController: {
169164
[AllProperties]: false,
170165
},

app/util/transactions/index.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {
3434
toTokenMinimalUnit,
3535
} from '../number';
3636
import AppConstants from '../../core/AppConstants';
37-
import { isMainnetByChainId } from '../networks';
3837
import FIRST_PARTY_CONTRACT_NAMES from '../../constants/first-party-contracts';
3938
import {
4039
UINT256_BN_MAX_VALUE,
@@ -512,15 +511,6 @@ export async function isSmartContractAddress(
512511

513512
address = toChecksumAddress(address);
514513

515-
// If in contract map we don't need to cache it
516-
if (
517-
isMainnetByChainId(chainId) &&
518-
Engine.context.TokenListController.state.tokensChainsCache?.[chainId]
519-
?.data?.[address]
520-
) {
521-
return Promise.resolve(true);
522-
}
523-
524514
const { NetworkController } = Engine.context;
525515
const finalNetworkClientId =
526516
networkClientId ?? NetworkController.findNetworkClientIdByChainId(chainId);

app/util/transactions/index.test.ts

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,6 @@ ENGINE_MOCK.context = {
175175
provider: {} as Provider,
176176
}),
177177
},
178-
TokenListController: {
179-
state: {
180-
tokensChainsCache: {
181-
'0x1': {
182-
data: [],
183-
},
184-
},
185-
},
186-
},
187178
};
188179

189180
const spyOnQueryMethod = (returnValue: string | undefined) =>
@@ -2638,31 +2629,9 @@ describe('Transactions utils :: isSmartContractAddress', () => {
26382629
expect(result).toBe(false);
26392630
});
26402631

2641-
it('returns true when address is in token cache for mainnet', async () => {
2642-
const address = '0x1234567890123456789012345678901234567890';
2643-
2644-
// Mock the Engine context for mainnet with cached token
2645-
ENGINE_MOCK.context.TokenListController.state.tokensChainsCache = {
2646-
'0x1': {
2647-
data: {
2648-
[address]: { symbol: 'TEST' },
2649-
},
2650-
},
2651-
};
2652-
2653-
const result = await isSmartContractAddress(address, '0x1');
2654-
expect(result).toBe(true);
2655-
});
2656-
26572632
it('returns true when contract code is found', async () => {
26582633
const address = '0x1234567890123456789012345678901234567890';
26592634

2660-
// Clear token cache
2661-
ENGINE_MOCK.context.TokenListController.state.tokensChainsCache = {
2662-
'0x5': { data: {} },
2663-
};
2664-
2665-
// Mock contract code
26662635
spyOnQueryMethod('0x608060405234801561001057600080fd5b50');
26672636

26682637
const result = await isSmartContractAddress(address, '0x5');
@@ -2672,12 +2641,6 @@ describe('Transactions utils :: isSmartContractAddress', () => {
26722641
it('returns false when no contract code is found', async () => {
26732642
const address = '0x1234567890123456789012345678901234567890';
26742643

2675-
// Clear token cache
2676-
ENGINE_MOCK.context.TokenListController.state.tokensChainsCache = {
2677-
'0x5': { data: {} },
2678-
};
2679-
2680-
// Mock empty contract code
26812644
spyOnQueryMethod('0x');
26822645

26832646
const result = await isSmartContractAddress(address, '0x5');
@@ -2688,10 +2651,6 @@ describe('Transactions utils :: isSmartContractAddress', () => {
26882651
const address = '0x1234567890123456789012345678901234567890';
26892652
const customNetworkClientId = 'custom-network';
26902653

2691-
ENGINE_MOCK.context.TokenListController.state.tokensChainsCache = {
2692-
'0x5': { data: {} },
2693-
};
2694-
26952654
spyOnQueryMethod('0x608060405234801561001057600080fd5b50');
26962655

26972656
const result = await isSmartContractAddress(

0 commit comments

Comments
 (0)