Skip to content

Commit

Permalink
fix: poll only popular network (#12658)
Browse files Browse the repository at this point in the history
<!--
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**
To reduce the impact of showing assets across all networks, which can be
unbounded, this PR scopes the portfolio view to the 9 popular networks
built into metamask.

<!--
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?
-->

## **Related issues**

Fixes: MetaMask/metamask-extension#29055

## **Manual testing steps**

1. On popular networks:
- The token filter should allow switching between popular networks and
current network
  - The filter should work as described
  - RPC requests in the background should only hit the popular networks

2. On other networks
- The token filter should become disabled and scoped to the current
network
  - RPC requests in the background should only hit the current network

## **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/a65afd42-b67e-401e-b33c-b46fad3dd812



https://github.com/user-attachments/assets/e2179b4c-c3da-43d1-86d3-50fc066f0899



<!-- [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.
  • Loading branch information
salimtb authored Dec 16, 2024
1 parent 529dc1b commit a597568
Show file tree
Hide file tree
Showing 22 changed files with 768 additions and 88 deletions.
8 changes: 7 additions & 1 deletion app/components/UI/Tokens/TokenList/TokenListFooter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
import {
selectChainId,
selectIsAllNetworks,
selectIsPopularNetwork,
} from '../../../../../selectors/networkController';
import { TokenI } from '../../types';
import { selectUseTokenDetection } from '../../../../../selectors/preferencesController';
Expand All @@ -48,12 +49,15 @@ const getDetectedTokensCount = (
isAllNetworksSelected: boolean,
allTokens: TokenI[],
filteredTokens: TokenI[] | undefined,
isPopularNetworks: boolean,
): number => {
if (!isPortfolioEnabled) {
return filteredTokens?.length ?? 0;
}

return isAllNetworksSelected ? allTokens.length : filteredTokens?.length ?? 0;
return isAllNetworksSelected && isPopularNetworks
? allTokens.length
: filteredTokens?.length ?? 0;
};

export const TokenListFooter = ({
Expand All @@ -75,6 +79,7 @@ export const TokenListFooter = ({
const isTokenDetectionEnabled = useSelector(selectUseTokenDetection);
const chainId = useSelector(selectChainId);
const isAllNetworks = useSelector(selectIsAllNetworks);
const isPopularNetworks = useSelector(selectIsPopularNetwork);

const styles = createStyles(colors);

Expand Down Expand Up @@ -103,6 +108,7 @@ export const TokenListFooter = ({
isAllNetworks,
allDetectedTokens,
detectedTokens,
isPopularNetworks,
);

const areTokensDetected = tokenCount > 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TokenFilterBottomSheet } from './TokenFilterBottomSheet';
import { useSelector } from 'react-redux';
import Engine from '../../../../core/Engine';
import {
selectAllPopularNetworkConfigurations,
selectChainId,
selectNetworkConfigurations,
} from '../../../../selectors/networkController';
Expand Down Expand Up @@ -102,6 +103,8 @@ describe('TokenFilterBottomSheet', () => {
return {}; // default to show all networks
} else if (selector === selectNetworkConfigurations) {
return mockNetworks; // default to show all networks
} else if (selector === selectAllPopularNetworkConfigurations) {
return mockNetworks; // default to show all networks
}
return null;
});
Expand All @@ -114,14 +117,14 @@ describe('TokenFilterBottomSheet', () => {
it('renders correctly with the default option (All Networks) selected', () => {
const { queryByText } = render(<TokenFilterBottomSheet />);

expect(queryByText('All Networks')).toBeTruthy();
expect(queryByText('Popular networks')).toBeTruthy();
expect(queryByText('Current Network')).toBeTruthy();
});

it('sets filter to All Networks and closes bottom sheet when first option is pressed', async () => {
const { queryByText } = render(<TokenFilterBottomSheet />);

fireEvent.press(queryByText('All Networks'));
fireEvent.press(queryByText('Popular networks'));

await waitFor(() => {
expect(
Expand Down Expand Up @@ -152,6 +155,8 @@ describe('TokenFilterBottomSheet', () => {
return { '0x1': true }; // filter by current network
} else if (selector === selectNetworkConfigurations) {
return mockNetworks;
} else if (selector === selectAllPopularNetworkConfigurations) {
return mockNetworks;
}
return null;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React, { useRef, useMemo } from 'react';
import { useSelector } from 'react-redux';
import {
selectChainId,
selectNetworkConfigurations,
selectIsAllNetworks,
selectAllPopularNetworkConfigurations,
} from '../../../../selectors/networkController';
import { selectTokenNetworkFilter } from '../../../../selectors/preferencesController';
import BottomSheet, {
Expand All @@ -29,7 +29,7 @@ enum FilterOption {

const TokenFilterBottomSheet = () => {
const sheetRef = useRef<BottomSheetRef>(null);
const allNetworks = useSelector(selectNetworkConfigurations);
const allNetworks = useSelector(selectAllPopularNetworkConfigurations);
const { colors } = useTheme();
const styles = createStyles(colors);

Expand Down Expand Up @@ -79,7 +79,9 @@ const TokenFilterBottomSheet = () => {
verticalAlignment={VerticalAlignment.Center}
>
<Text style={styles.bottomSheetText}>
{strings('wallet.all_networks')}
{`${strings('app_settings.popular')} ${strings(
'app_settings.networks',
)}`}
</Text>
</ListItemSelect>
<ListItemSelect
Expand Down
2 changes: 1 addition & 1 deletion app/components/UI/Tokens/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ exports[`Tokens Portfolio View should match the snapshot when portfolio view is
}
}
>
All Networks
Ethereum Main Network
</Text>
<SvgMock
color="#141618"
Expand Down
32 changes: 16 additions & 16 deletions app/components/UI/Tokens/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef, useState, LegacyRef, useMemo, useEffect } from 'react';
import React, { useRef, useState, LegacyRef, useMemo } from 'react';
import { Hex } from '@metamask/utils';
import { View, Text } from 'react-native';
import ActionSheet from '@metamask/react-native-actionsheet';
Expand All @@ -15,6 +15,7 @@ import Logger from '../../../util/Logger';
import {
selectChainId,
selectIsAllNetworks,
selectIsPopularNetwork,
selectNetworkConfigurations,
} from '../../../selectors/networkController';
import {
Expand Down Expand Up @@ -138,10 +139,15 @@ const Tokens: React.FC<TokensI> = ({ tokens }) => {
const multiChainMarketData = useSelector(selectTokenMarketData);
const multiChainTokenBalance = useSelector(selectTokensBalances);
const multiChainCurrencyRates = useSelector(selectCurrencyRates);
const isPopularNetwork = useSelector(selectIsPopularNetwork);

const styles = createStyles(colors);

const tokensList = useMemo((): TokenI[] => {
// if it is not popular network, display tokens only for current network
const filteredAssetsParam = isPopularNetwork
? tokenNetworkFilter
: { [currentChainId]: true };
if (isPortfolioViewEnabled()) {
// MultiChain implementation
const allTokens = Object.values(
Expand Down Expand Up @@ -183,7 +189,7 @@ const Tokens: React.FC<TokensI> = ({ tokens }) => {
const filteredAssets = filterAssets(tokensToDisplay, [
{
key: 'chainId',
opts: tokenNetworkFilter,
opts: filteredAssetsParam,
filterCallback: 'inclusive',
},
]);
Expand Down Expand Up @@ -289,6 +295,7 @@ const Tokens: React.FC<TokensI> = ({ tokens }) => {
tokens,
// Dependencies for multichain implementation
selectedAccountTokensChains,
isPopularNetwork,
tokenNetworkFilter,
currentChainId,
multiChainCurrencyRates,
Expand Down Expand Up @@ -404,15 +411,6 @@ const Tokens: React.FC<TokensI> = ({ tokens }) => {
const onActionSheetPress = (index: number) =>
index === 0 ? removeToken() : null;

useEffect(() => {
const { PreferencesController } = Engine.context;
if (isTestNet(currentChainId)) {
PreferencesController.setTokenNetworkFilter({
[currentChainId]: true,
});
}
}, [currentChainId]);

return (
<View
style={styles.wrapper}
Expand All @@ -425,20 +423,22 @@ const Tokens: React.FC<TokensI> = ({ tokens }) => {
testID={WalletViewSelectorsIDs.TOKEN_NETWORK_FILTER}
label={
<Text style={styles.controlButtonText} numberOfLines={1}>
{isAllNetworks
? strings('wallet.all_networks')
{isAllNetworks && isPopularNetwork
? `${strings('app_settings.popular')} ${strings(
'app_settings.networks',
)}`
: networkName ?? strings('wallet.current_network')}
</Text>
}
isDisabled={isTestNet(currentChainId)}
isDisabled={isTestNet(currentChainId) || !isPopularNetwork}
onPress={showFilterControls}
endIconName={IconName.ArrowDown}
style={
isTestNet(currentChainId)
isTestNet(currentChainId) || !isPopularNetwork
? styles.controlButtonDisabled
: styles.controlButton
}
disabled={isTestNet(currentChainId)}
disabled={isTestNet(currentChainId) || !isPopularNetwork}
/>
<View style={styles.controlButtonInnerWrapper}>
<ButtonIcon
Expand Down
4 changes: 3 additions & 1 deletion app/components/Views/DetectedTokens/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
import {
selectChainId,
selectIsAllNetworks,
selectIsPopularNetwork,
selectNetworkClientId,
selectNetworkConfigurations,
} from '../../../selectors/networkController';
Expand Down Expand Up @@ -98,6 +99,7 @@ const DetectedTokens = () => {
) as TokenI[];
const allNetworks = useSelector(selectNetworkConfigurations);
const chainId = useSelector(selectChainId);
const isPopularNetworks = useSelector(selectIsPopularNetwork);
const selectedNetworkClientId = useSelector(selectNetworkClientId);
const [ignoredTokens, setIgnoredTokens] = useState<IgnoredTokensByAddress>(
{},
Expand All @@ -108,7 +110,7 @@ const DetectedTokens = () => {
const styles = createStyles(colors);

const currentDetectedTokens =
isPortfolioViewEnabled() && isAllNetworks
isPortfolioViewEnabled() && isAllNetworks && isPopularNetworks
? allDetectedTokens
: detectedTokens;

Expand Down
13 changes: 9 additions & 4 deletions app/components/Views/NetworkSelector/NetworkSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import BottomSheet, {
import { IconName } from '../../../component-library/components/Icons/Icon';
import { useSelector } from 'react-redux';
import {
selectNetworkConfigurations,
selectIsAllNetworks,
selectNetworkConfigurations,
} from '../../../selectors/networkController';
import { selectShowTestNetworks } from '../../../selectors/preferencesController';
import Networks, {
Expand Down Expand Up @@ -126,7 +126,7 @@ const NetworkSelector = () => {
const styles = createStyles(colors);
const sheetRef = useRef<BottomSheetRef>(null);
const showTestNetworks = useSelector(selectShowTestNetworks);
const isAllNetworks = useSelector(selectIsAllNetworks);
const isAllNetwork = useSelector(selectIsAllNetworks);

const networkConfigurations = useSelector(selectNetworkConfigurations);

Expand Down Expand Up @@ -179,14 +179,19 @@ const NetworkSelector = () => {

const setTokenNetworkFilter = useCallback(
(chainId: string) => {
const isPopularNetwork =
chainId === CHAIN_IDS.MAINNET ||
chainId === CHAIN_IDS.LINEA_MAINNET ||
PopularList.some((network) => network.chainId === chainId);

const { PreferencesController } = Engine.context;
if (!isAllNetworks) {
if (!isAllNetwork && isPopularNetwork) {
PreferencesController.setTokenNetworkFilter({
[chainId]: true,
});
}
},
[isAllNetworks],
[isAllNetwork],
);

const onRpcSelect = useCallback(
Expand Down
3 changes: 2 additions & 1 deletion app/components/Views/Wallet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import {
selectTokens,
selectTokensByChainIdAndAddress,
} from '../../../selectors/tokensController';
import { selectTokenNetworkFilter } from '../../../selectors/preferencesController';
import {
NavigationProp,
ParamListBase,
Expand Down Expand Up @@ -93,6 +92,7 @@ import { PortfolioBalance } from '../../UI/Tokens/TokenList/PortfolioBalance';
import useCheckNftAutoDetectionModal from '../../hooks/useCheckNftAutoDetectionModal';
import useCheckMultiRpcModal from '../../hooks/useCheckMultiRpcModal';
import { selectContractBalances } from '../../../selectors/tokenBalancesController';
import { selectTokenNetworkFilter } from '../../../selectors/preferencesController';

const createStyles = ({ colors, typography }: Theme) =>
StyleSheet.create({
Expand Down Expand Up @@ -310,6 +310,7 @@ const Wallet = ({

const networkImageSource = useSelector(selectNetworkImageSource);
const tokenNetworkFilter = useSelector(selectTokenNetworkFilter);

/**
* Shows Nft auto detect modal if the user is on mainnet, never saw the modal and have nft detection off
*/
Expand Down
Loading

0 comments on commit a597568

Please sign in to comment.