Skip to content

Commit

Permalink
feat: only poll popular networks (#29071)
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.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/29071?quickstart=1)

## **Related issues**

Fixes: #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**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/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-extension/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.

---------

Co-authored-by: Nicholas Gambino <[email protected]>
  • Loading branch information
bergeron and gambinish authored Dec 11, 2024
1 parent 5f8af0e commit 07d4265
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 35 deletions.
11 changes: 6 additions & 5 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions shared/constants/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,11 @@ export const FEATURED_RPCS: AddNetworkFields[] = [
},
];

export const FEATURED_NETWORK_CHAIN_IDS = [
CHAIN_IDS.MAINNET,
...FEATURED_RPCS.map((rpc) => rpc.chainId),
];

export const infuraChainIdsTestNets: string[] = [
CHAIN_IDS.SEPOLIA,
CHAIN_IDS.HOLESKY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,6 @@
"tokenSortConfig": "object",
"shouldShowAggregatedBalancePopover": "boolean",
"tokenNetworkFilter": {
"0x1": "boolean",
"0xaa36a7": "boolean",
"0xe705": "boolean",
"0xe708": "boolean",
"0x539": "boolean"
},
"redesignedConfirmationsEnabled": true,
Expand Down Expand Up @@ -334,8 +330,6 @@
"TokenListController": {
"tokenList": "object",
"tokensChainsCache": {
"0x1": "object",
"0xe708": "object",
"0x539": "object"
},
"preventPollingOnNetworkRestart": false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@
"tokenSortConfig": "object",
"shouldShowAggregatedBalancePopover": "boolean",
"tokenNetworkFilter": {
"0x1": "boolean",
"0xaa36a7": "boolean",
"0xe705": "boolean",
"0xe708": "boolean",
"0x539": "boolean"
},
"redesignedConfirmationsEnabled": true,
Expand Down Expand Up @@ -180,8 +176,6 @@
"nonRPCGasFeeApisDisabled": "boolean",
"tokenList": "object",
"tokensChainsCache": {
"0x1": "object",
"0xe708": "object",
"0x539": "object"
},
"preventPollingOnNetworkRestart": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState, useContext, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
getCurrentNetwork,
getIsTokenNetworkFilterEqualCurrentNetwork,
getTokenNetworkFilter,
} from '../../../../../selectors';
import { getNetworkConfigurationsByChainId } from '../../../../../../shared/modules/selectors/networks';
Expand All @@ -26,7 +27,10 @@ import {
import ImportControl from '../import-control';
import { useI18nContext } from '../../../../../hooks/useI18nContext';
import { MetaMetricsContext } from '../../../../../contexts/metametrics';
import { TEST_CHAINS } from '../../../../../../shared/constants/network';
import {
FEATURED_NETWORK_CHAIN_IDS,
TEST_CHAINS,
} from '../../../../../../shared/constants/network';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
Expand Down Expand Up @@ -57,6 +61,9 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => {
const popoverRef = useRef<HTMLDivElement>(null);
const currentNetwork = useSelector(getCurrentNetwork);
const allNetworks = useSelector(getNetworkConfigurationsByChainId);
const isTokenNetworkFilterEqualCurrentNetwork = useSelector(
getIsTokenNetworkFilterEqualCurrentNetwork,
);

const tokenNetworkFilter = useSelector(getTokenNetworkFilter);
const [isTokenSortPopoverOpen, setIsTokenSortPopoverOpen] = useState(false);
Expand All @@ -74,10 +81,6 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => {
allOpts[chainId] = true;
});

const allNetworksFilterShown =
Object.keys(tokenNetworkFilter).length !==
Object.keys(allOpts || {}).length;

useEffect(() => {
if (isTestNetwork) {
const testnetFilter = { [currentNetwork.chainId]: true };
Expand Down Expand Up @@ -175,7 +178,10 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => {
className="asset-list-control-bar__button asset-list-control-bar__network_control"
onClick={toggleNetworkFilterPopover}
size={ButtonBaseSize.Sm}
disabled={isTestNetwork}
disabled={
isTestNetwork ||
!FEATURED_NETWORK_CHAIN_IDS.includes(currentNetwork.chainId)
}
endIconName={IconName.ArrowDown}
backgroundColor={
isNetworkFilterPopoverOpen
Expand All @@ -186,9 +192,9 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => {
marginRight={isFullScreen ? 2 : null}
ellipsis
>
{allNetworksFilterShown
{isTokenNetworkFilterEqualCurrentNetwork
? currentNetwork?.nickname ?? t('currentNetwork')
: t('allNetworks')}
: t('popularNetworks')}
</ButtonBase>
)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => {
variant={TextVariant.bodyMdMedium}
color={TextColor.textDefault}
>
{t('allNetworks')}
{t('popularNetworks')}
</Text>
<Text
variant={TextVariant.bodySmMedium}
Expand Down
6 changes: 5 additions & 1 deletion ui/components/app/assets/token-list/token-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import TokenCell from '../token-cell';
import { TEST_CHAINS } from '../../../../../shared/constants/network';
import { sortAssets } from '../util/sort';
import {
getChainIdsToPoll,
getCurrencyRates,
getCurrentNetwork,
getIsTestnet,
Expand Down Expand Up @@ -93,6 +94,7 @@ export default function TokenList({
const tokenNetworkFilter = useSelector(getTokenNetworkFilter);
const selectedAccount = useSelector(getSelectedAccount);
const conversionRate = useSelector(getConversionRate);
const chainIdsToPoll = useSelector(getChainIdsToPoll);
const contractExchangeRates = useSelector(
getTokenExchangeRates,
shallowEqual,
Expand All @@ -103,7 +105,9 @@ export default function TokenList({
getIsTokenNetworkFilterEqualCurrentNetwork,
);

const { tokenBalances } = useTokenBalances();
const { tokenBalances } = useTokenBalances({
chainIds: chainIdsToPoll as Hex[],
});
const selectedAccountTokenBalancesAcrossChains =
tokenBalances[selectedAccount.address];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import {
getAllDomains,
getPermittedChainsForSelectedTab,
getPermittedAccountsForSelectedTab,
getTokenNetworkFilter,
getPreferences,
} from '../../../selectors';
import ToggleButton from '../../ui/toggle-button';
import {
Expand Down Expand Up @@ -116,7 +116,7 @@ export const NetworkListMenu = ({ onClose }: { onClose: () => void }) => {
const dispatch = useDispatch();
const trackEvent = useContext(MetaMetricsContext);

const tokenNetworkFilter = useSelector(getTokenNetworkFilter);
const { tokenNetworkFilter } = useSelector(getPreferences);
const showTestNetworks = useSelector(getShowTestNetworks);
const currentChainId = useSelector(getCurrentChainId);
const selectedTabOrigin = useSelector(getOriginOfCurrentTab);
Expand Down Expand Up @@ -294,7 +294,7 @@ export const NetworkListMenu = ({ onClose }: { onClose: () => void }) => {

// as a user, I don't want my network selection to force update my filter when I have "All Networks" toggled on
// however, if I am already filtered on "Current Network", we'll want to filter by the selected network when the network changes
if (Object.keys(tokenNetworkFilter).length <= 1) {
if (Object.keys(tokenNetworkFilter || {}).length <= 1) {
dispatch(setTokenNetworkFilter({ [network.chainId]: true }));
} else if (process.env.PORTFOLIO_VIEW) {
dispatch(setTokenNetworkFilter(allOpts));
Expand Down
2 changes: 1 addition & 1 deletion ui/pages/asset/components/asset-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ const AssetPage = ({
getSelectedAccountNativeTokenCachedBalanceByChainId,
) as Record<Hex, Hex>;

const { tokenBalances } = useTokenBalances();
const { tokenBalances } = useTokenBalances({ chainIds: [chainId] });
const selectedAccountTokenBalancesAcrossChains =
tokenBalances[selectedAccount.address];

Expand Down
42 changes: 38 additions & 4 deletions ui/selectors/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
MOONBEAM_DISPLAY_NAME,
MOONRIVER_DISPLAY_NAME,
TEST_NETWORK_IDS,
FEATURED_NETWORK_CHAIN_IDS,
} from '../../shared/constants/network';
import {
WebHIDConnectedStatuses,
Expand Down Expand Up @@ -1086,9 +1087,35 @@ export function getIsTokenNetworkFilterEqualCurrentNetwork(state) {
return false;
}

/**
* Returns an object indicating which networks
* tokens should be shown on in the portfolio view.
*
* @param {*} state
* @returns {Record<Hex, boolean>}
*/
export function getTokenNetworkFilter(state) {
const currentChainId = getCurrentChainId(state);
const { tokenNetworkFilter } = getPreferences(state);
return tokenNetworkFilter || {};

// Portfolio view not enabled outside popular networks
if (
!process.env.PORTFOLIO_VIEW ||
!FEATURED_NETWORK_CHAIN_IDS.includes(currentChainId)
) {
return { [currentChainId]: true };
}

// Portfolio view only enabled on featured networks
return Object.entries(tokenNetworkFilter || {}).reduce(
(acc, [chainId, value]) => {
if (FEATURED_NETWORK_CHAIN_IDS.includes(chainId)) {
acc[chainId] = value;
}
return acc;
},
{},
);
}

export function getUseTransactionSimulations(state) {
Expand Down Expand Up @@ -2364,7 +2391,9 @@ export const getAllChainsToPoll = createDeepEqualSelector(
}

return Object.keys(networkConfigurations).filter(
(chainId) => chainId === currentChainId || !TEST_CHAINS.includes(chainId),
(chainId) =>
chainId === currentChainId ||
FEATURED_NETWORK_CHAIN_IDS.includes(chainId),
);
},
);
Expand All @@ -2386,7 +2415,9 @@ export const getChainIdsToPoll = createDeepEqualSelector(
}

return Object.keys(networkConfigurations).filter(
(chainId) => chainId === currentChainId || !TEST_CHAINS.includes(chainId),
(chainId) =>
chainId === currentChainId ||
FEATURED_NETWORK_CHAIN_IDS.includes(chainId),
);
},
);
Expand Down Expand Up @@ -2414,7 +2445,10 @@ export const getNetworkClientIdsToPoll = createDeepEqualSelector(

return Object.entries(networkConfigurations).reduce(
(acc, [chainId, network]) => {
if (chainId === currentChainId || !TEST_CHAINS.includes(chainId)) {
if (
chainId === currentChainId ||
FEATURED_NETWORK_CHAIN_IDS.includes(chainId)
) {
acc.push(
network.rpcEndpoints[network.defaultRpcEndpointIndex]
.networkClientId,
Expand Down

0 comments on commit 07d4265

Please sign in to comment.