diff --git a/ui/pages/import-token/token-list/token-list.container.js b/ui/pages/import-token/token-list/token-list.container.js
index 565bd4262..7b6b0147b 100644
--- a/ui/pages/import-token/token-list/token-list.container.js
+++ b/ui/pages/import-token/token-list/token-list.container.js
@@ -1,11 +1,10 @@
import { connect } from 'react-redux';
import TokenList from './token-list.component';
-const mapStateToProps = ({ metamask }) => {
- const { tokens, useTokenDetection } = metamask;
+const mapStateToProps = (state) => {
+ const { tokens } = state.metamask;
return {
tokens,
- useTokenDetection,
};
};
diff --git a/ui/pages/settings/advanced-tab/advanced-tab.component.js b/ui/pages/settings/advanced-tab/advanced-tab.component.js
index a03d6a25a..072d8be80 100644
--- a/ui/pages/settings/advanced-tab/advanced-tab.component.js
+++ b/ui/pages/settings/advanced-tab/advanced-tab.component.js
@@ -791,10 +791,6 @@ export default class AdvancedTab extends PureComponent {
}
renderTokenDetectionToggle() {
- if (!process.env.TOKEN_DETECTION_V2) {
- return null;
- }
-
const { t } = this.context;
const { useTokenDetection, setUseTokenDetection } = this.props;
@@ -807,7 +803,7 @@ export default class AdvancedTab extends PureComponent {
{t('tokenDetection')}
- {t('tokenDetectionToggleDescription')}
+ {t('tokenDetectionDescription')}
diff --git a/ui/pages/settings/advanced-tab/advanced-tab.component.test.js b/ui/pages/settings/advanced-tab/advanced-tab.component.test.js
index 744ef2f80..0aad2d496 100644
--- a/ui/pages/settings/advanced-tab/advanced-tab.component.test.js
+++ b/ui/pages/settings/advanced-tab/advanced-tab.component.test.js
@@ -43,23 +43,23 @@ describe('AdvancedTab Component', () => {
});
it('should render correctly when threeBoxFeatureFlag', () => {
- expect(component.find('.settings-page__content-row')).toHaveLength(15);
+ expect(component.find('.settings-page__content-row')).toHaveLength(16);
});
it('should render backup button', () => {
- expect(component.find('.settings-page__content-row')).toHaveLength(15);
+ expect(component.find('.settings-page__content-row')).toHaveLength(16);
expect(
component
.find('.settings-page__content-row')
- .at(9)
+ .at(10)
.find('.settings-page__content-item'),
).toHaveLength(2);
expect(
component
.find('.settings-page__content-row')
- .at(9)
+ .at(10)
.find('.settings-page__content-item')
.at(0)
.find('.settings-page__content-description')
@@ -69,7 +69,7 @@ describe('AdvancedTab Component', () => {
expect(
component
.find('.settings-page__content-row')
- .at(9)
+ .at(10)
.find('.settings-page__content-item')
.at(1)
.find('Button')
@@ -78,19 +78,19 @@ describe('AdvancedTab Component', () => {
});
it('should render restore button', () => {
- expect(component.find('.settings-page__content-row')).toHaveLength(15);
+ expect(component.find('.settings-page__content-row')).toHaveLength(16);
expect(
component
.find('.settings-page__content-row')
- .at(10)
+ .at(11)
.find('.settings-page__content-item'),
).toHaveLength(2);
expect(
component
.find('.settings-page__content-row')
- .at(10)
+ .at(11)
.find('.settings-page__content-item')
.at(0)
.find('.settings-page__content-description')
@@ -100,7 +100,7 @@ describe('AdvancedTab Component', () => {
expect(
component
.find('.settings-page__content-row')
- .at(10)
+ .at(11)
.find('.settings-page__content-item')
.at(1)
.find('label')
@@ -137,7 +137,7 @@ describe('AdvancedTab Component', () => {
},
);
- const autoTimeout = component.find('.settings-page__content-row').at(8);
+ const autoTimeout = component.find('.settings-page__content-row').at(9);
const textField = autoTimeout.find(TextField);
textField.props().onChange({ target: { value: 1440 } });
@@ -148,14 +148,13 @@ describe('AdvancedTab Component', () => {
});
it('should toggle show test networks', () => {
- const testNetworks = component.find('.settings-page__content-row').at(6);
+ const testNetworks = component.find('.settings-page__content-row').at(7);
const toggleButton = testNetworks.find(ToggleButton);
toggleButton.first().simulate('toggle');
expect(toggleTestnet.calledOnce).toStrictEqual(true);
});
it('should toggle token detection', () => {
- process.env.TOKEN_DETECTION_V2 = true;
component = shallow(
-
-
{t('useTokenDetection')}
-
- {t('useTokenDetectionDescription')}
-
-
-
-
- {
- this.context.trackEvent({
- category: EVENT.CATEGORIES.SETTINGS,
- event: 'Token Detection',
- properties: {
- action: 'Token Detection',
- legacy_event: true,
- },
- });
- setUseTokenDetection(!value);
- }}
- offLabel={t('off')}
- onLabel={t('on')}
- />
-
-
-
- );
- }
-
renderCollectibleDetectionToggle() {
if (!process.env.COLLECTIBLES_V1) {
return null;
@@ -326,10 +288,6 @@ export default class ExperimentalTab extends PureComponent {
render() {
return (
- {/* TODO: Remove during TOKEN_DETECTION_V2 feature flag clean up */}
- {process.env.TOKEN_DETECTION_V2
- ? null
- : this.renderTokenDetectionToggle()}
{this.renderOpenSeaEnabledToggle()}
{this.renderCollectibleDetectionToggle()}
{this.renderEIP1559V2EnabledToggle()}
diff --git a/ui/pages/settings/experimental-tab/experimental-tab.component.test.js b/ui/pages/settings/experimental-tab/experimental-tab.component.test.js
deleted file mode 100644
index f7a06e076..000000000
--- a/ui/pages/settings/experimental-tab/experimental-tab.component.test.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react';
-import sinon from 'sinon';
-import { mount } from 'enzyme';
-import ExperimentalTab from './experimental-tab.container';
-
-describe('Experimental Tab', () => {
- let wrapper;
-
- const props = {
- useTokenDetection: true,
- setUseTokenDetection: sinon.spy(),
- };
-
- it('toggles Use token detection', () => {
- wrapper = mount(, {
- context: {
- t: (str) => str,
- trackEvent: () => undefined,
- },
- });
- const useTokenDetection = wrapper.find({ type: 'checkbox' }).at(0);
- useTokenDetection.simulate('click');
- expect(props.setUseTokenDetection.calledOnce).toStrictEqual(true);
- });
-
- /** TODO: Remove during TOKEN_DETECTION_V2 feature flag clean up */
- it('should not show use token detection toggle', () => {
- process.env.TOKEN_DETECTION_V2 = true;
- wrapper = mount(, {
- context: {
- t: (str) => str,
- trackEvent: () => undefined,
- },
- });
- const useTokenDetectionText = wrapper.find({ text: 'Use token detection' });
- expect(useTokenDetectionText).toHaveLength(0);
- });
-});
diff --git a/ui/pages/settings/experimental-tab/experimental-tab.container.js b/ui/pages/settings/experimental-tab/experimental-tab.container.js
index 354bb714b..d27f7e572 100644
--- a/ui/pages/settings/experimental-tab/experimental-tab.container.js
+++ b/ui/pages/settings/experimental-tab/experimental-tab.container.js
@@ -2,7 +2,6 @@ import { compose } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import {
- setUseTokenDetection,
setUseCollectibleDetection,
setOpenSeaEnabled,
setEIP1559V2Enabled,
@@ -10,7 +9,6 @@ import {
setCustomNetworkListEnabled,
} from '../../../store/actions';
import {
- getUseTokenDetection,
getUseCollectibleDetection,
getOpenSeaEnabled,
getEIP1559V2Enabled,
@@ -21,10 +19,6 @@ import ExperimentalTab from './experimental-tab.component';
const mapStateToProps = (state) => {
return {
- useTokenDetection:
- getUseTokenDetection(
- state,
- ) /** TODO: Remove during TOKEN_DETECTION_V2 feature flag clean up */,
useCollectibleDetection: getUseCollectibleDetection(state),
openSeaEnabled: getOpenSeaEnabled(state),
eip1559V2Enabled: getEIP1559V2Enabled(state),
@@ -35,10 +29,6 @@ const mapStateToProps = (state) => {
const mapDispatchToProps = (dispatch) => {
return {
- setUseTokenDetection: (val) =>
- dispatch(
- setUseTokenDetection(val),
- ) /** TODO: Remove during TOKEN_DETECTION_V2 feature flag clean up */,
setUseCollectibleDetection: (val) =>
dispatch(setUseCollectibleDetection(val)),
setOpenSeaEnabled: (val) => dispatch(setOpenSeaEnabled(val)),
diff --git a/ui/pages/settings/settings-tab/settings-tab.component.js b/ui/pages/settings/settings-tab/settings-tab.component.js
index ff163d228..53d8d6d63 100644
--- a/ui/pages/settings/settings-tab/settings-tab.component.js
+++ b/ui/pages/settings/settings-tab/settings-tab.component.js
@@ -54,7 +54,6 @@ export default class SettingsTab extends PureComponent {
setHideZeroBalanceTokens: PropTypes.func,
lastFetchedConversionDate: PropTypes.number,
selectedAddress: PropTypes.string,
- useTokenDetection: PropTypes.bool,
tokenList: PropTypes.object,
};
@@ -168,13 +167,8 @@ export default class SettingsTab extends PureComponent {
renderBlockieOptIn() {
const { t } = this.context;
- const {
- useBlockie,
- setUseBlockie,
- selectedAddress,
- useTokenDetection,
- tokenList,
- } = this.props;
+ const { useBlockie, setUseBlockie, selectedAddress, tokenList } =
+ this.props;
const getIconStyles = () => ({
display: 'block',
@@ -215,7 +209,6 @@ export default class SettingsTab extends PureComponent {
id="jazzicon"
address={selectedAddress}
diameter={32}
- useTokenDetection={useTokenDetection}
tokenList={tokenList}
style={getIconStyles()}
/>
diff --git a/ui/pages/settings/settings-tab/settings-tab.container.js b/ui/pages/settings/settings-tab/settings-tab.container.js
index 15dbc51dd..18bae977e 100644
--- a/ui/pages/settings/settings-tab/settings-tab.container.js
+++ b/ui/pages/settings/settings-tab/settings-tab.container.js
@@ -7,7 +7,7 @@ import {
setHideZeroBalanceTokens,
setParticipateInMetaMetrics,
} from '../../../store/actions';
-import { getPreferences } from '../../../selectors';
+import { getTokenList, getPreferences } from '../../../selectors';
import SettingsTab from './settings-tab.component';
const mapStateToProps = (state, ownProps) => {
@@ -21,13 +21,12 @@ const mapStateToProps = (state, ownProps) => {
useBlockie,
currentLocale,
selectedAddress,
- useTokenDetection,
- tokenList,
} = metamask;
const { useNativeCurrencyAsPrimaryCurrency, hideZeroBalanceTokens } =
getPreferences(state);
const { lastFetchedConversionDate } = ownProps;
+ const tokenList = getTokenList(state);
return {
warning,
@@ -39,7 +38,6 @@ const mapStateToProps = (state, ownProps) => {
hideZeroBalanceTokens,
lastFetchedConversionDate,
selectedAddress,
- useTokenDetection,
tokenList,
};
};
diff --git a/ui/pages/swaps/build-quote/build-quote.js b/ui/pages/swaps/build-quote/build-quote.js
index 010a0f6c8..6bbac7e08 100644
--- a/ui/pages/swaps/build-quote/build-quote.js
+++ b/ui/pages/swaps/build-quote/build-quote.js
@@ -67,7 +67,6 @@ import {
getCurrentChainId,
getRpcPrefsForCurrentProvider,
getUseTokenDetection,
- getTokenList,
isHardwareWallet,
getHardwareWalletType,
} from '../../../selectors';
@@ -151,7 +150,6 @@ export default function BuildQuote({
const defaultSwapsToken = useSelector(getSwapsDefaultToken, isEqual);
const chainId = useSelector(getCurrentChainId);
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider, shallowEqual);
- const tokenList = useSelector(getTokenList, isEqual);
const useTokenDetection = useSelector(getUseTokenDetection);
const quotes = useSelector(getQuotes, isEqual);
const areQuotesPresent = Object.keys(quotes).length > 0;
@@ -214,7 +212,7 @@ export default function BuildQuote({
conversionRate,
currentCurrency,
chainId,
- tokenList,
+ shuffledTokensList,
useTokenDetection,
);
diff --git a/ui/pages/swaps/index.js b/ui/pages/swaps/index.js
index 128ae7474..ea1ef45ae 100644
--- a/ui/pages/swaps/index.js
+++ b/ui/pages/swaps/index.js
@@ -136,8 +136,8 @@ export default function Swap() {
checkNetworkAndAccountSupports1559,
);
const defaultSwapsToken = useSelector(getSwapsDefaultToken, isEqual);
- const tokenList = useSelector(getTokenList, isEqual);
- const listTokenValues = shuffle(Object.values(tokenList));
+ const tokenList = useSelector(getTokenList);
+ const shuffledTokensList = shuffle(Object.entries(tokenList));
const reviewSwapClickedTimestamp = useSelector(getReviewSwapClickedTimestamp);
const pendingSmartTransactions = useSelector(getPendingSmartTransactions);
const reviewSwapClicked = Boolean(reviewSwapClickedTimestamp);
@@ -474,7 +474,7 @@ export default function Swap() {
);
}}
diff --git a/ui/pages/token-details/token-details-page.js b/ui/pages/token-details/token-details-page.js
index fc7ce15f4..b34f35f59 100644
--- a/ui/pages/token-details/token-details-page.js
+++ b/ui/pages/token-details/token-details-page.js
@@ -34,12 +34,8 @@ export default function TokenDetailsPage() {
const tokenList = useSelector(getTokenList);
const { address: tokenAddress } = useParams();
- const tokenMetadata = Object.values(tokenList).find((token) =>
- isEqualCaseInsensitive(token.address, tokenAddress),
- );
+ const tokenMetadata = tokenList[tokenAddress.toLowerCase()];
const aggregators = tokenMetadata?.aggregators?.join(', ');
- const fileName = tokenMetadata?.iconUrl;
- const imagePath = fileName;
const token = tokens.find(({ address }) =>
isEqualCaseInsensitive(address, tokenAddress),
@@ -99,7 +95,7 @@ export default function TokenDetailsPage() {
@@ -183,7 +179,7 @@ export default function TokenDetailsPage() {
? networkNickname ?? t('privateNetwork')
: t(networkType)}
- {process.env.TOKEN_DETECTION_V2 && aggregators && (
+ {aggregators && (
<>
{
});
it('should render token list title in token details page', () => {
- process.env.TOKEN_DETECTION_V2 = true;
const store = configureMockStore()(state);
const { getByText } = renderWithProvider(, store);
expect(getByText('Token lists:')).toBeInTheDocument();
- process.env.TOKEN_DETECTION_V2 = false;
});
it('should render token list for the token in token details page', () => {
- process.env.TOKEN_DETECTION_V2 = true;
const store = configureMockStore()(state);
const { getByText } = renderWithProvider(, store);
expect(
@@ -334,7 +331,6 @@ describe('TokenDetailsPage', () => {
'Aave, Bancor, CMC, Crypto.com, CoinGecko, 1inch, Paraswap, PMM, Synthetix, Zapper, Zerion, 0x.',
),
).toBeInTheDocument();
- process.env.TOKEN_DETECTION_V2 = false;
});
it('should call hide token button when button is clicked in token details page', () => {
diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js
index fd26227a2..e45693fdb 100644
--- a/ui/selectors/selectors.js
+++ b/ui/selectors/selectors.js
@@ -53,7 +53,7 @@ import {
} from '../helpers/utils/conversions.util';
import { TEMPLATED_CONFIRMATION_MESSAGE_TYPES } from '../pages/confirmation/templates';
-
+import { STATIC_MAINNET_TOKEN_LIST } from '../../shared/constants/tokens';
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
import { DAY } from '../../shared/constants/time';
import {
@@ -828,8 +828,8 @@ function getAllowedAnnouncementIds(state) {
7: false,
8: supportsWebHid && currentKeyringIsLedger && currentlyUsingLedgerLive,
9: false,
- 10: Boolean(process.env.TOKEN_DETECTION_V2) && !process.env.IN_TEST,
- 11: Boolean(process.env.TOKEN_DETECTION_V2) && !process.env.IN_TEST,
+ 10: true,
+ 11: true,
12: false,
13: true,
};
@@ -919,13 +919,19 @@ export function getTheme(state) {
}
/**
- * To retrieve the tokenList produced by TokenListcontroller
+ * To retrieve the token list for use throughout the UI. Will return the remotely fetched list
+ * from the tokens controller if token detection is enabled, or the static list if not.
*
* @param {*} state
* @returns {object}
*/
export function getTokenList(state) {
- return state.metamask.tokenList;
+ const isTokenDetectionInactiveOnMainnet =
+ getIsTokenDetectionInactiveOnMainnet(state);
+ const caseInSensitiveTokenList = isTokenDetectionInactiveOnMainnet
+ ? STATIC_MAINNET_TOKEN_LIST
+ : state.metamask.tokenList;
+ return caseInSensitiveTokenList;
}
export function doesAddressRequireLedgerHidConnection(state, address) {
@@ -1014,6 +1020,8 @@ export function getIsAdvancedGasFeeDefault(state) {
}
/**
+ * To get the name of the network that support token detection based in chainId.
+ *
* @param state
* @returns string e.g. ethereum, bsc or polygon
*/
@@ -1033,13 +1041,13 @@ export const getTokenDetectionSupportNetworkByChainId = (state) => {
}
};
/**
- * To check for the chainId that supports token detection ,
+ * To check if teh chainId supports token detection ,
* currently it returns true for Ethereum Mainnet, Polygon, BSC and Avalanche
*
* @param {*} state
* @returns Boolean
*/
-export function getIsTokenDetectionSupported(state) {
+export function getIsDynamicTokenListAvailable(state) {
const chainId = getCurrentChainId(state);
return [
MAINNET_CHAIN_ID,
@@ -1069,6 +1077,50 @@ export function getNewTokensImported(state) {
return state.appState.newTokensImported;
}
+/**
+ * To check if the token detection is OFF and the network is Mainnet
+ * so that the user can skip third party token api fetch
+ * and use the static tokenlist from contract-metadata
+ *
+ * @param {*} state
+ * @returns Boolean
+ */
+export function getIsTokenDetectionInactiveOnMainnet(state) {
+ const isMainnet = getIsMainnet(state);
+ const useTokenDetection = getUseTokenDetection(state);
+
+ return !useTokenDetection && isMainnet;
+}
+
+/**
+ * To check for the chainId that supports token detection ,
+ * currently it returns true for Ethereum Mainnet, Polygon, BSC and Avalanche
+ *
+ * @param {*} state
+ * @returns Boolean
+ */
+export function getIsTokenDetectionSupported(state) {
+ const useTokenDetection = getUseTokenDetection(state);
+ const isDynamicTokenListAvailable = getIsDynamicTokenListAvailable(state);
+
+ return useTokenDetection && isDynamicTokenListAvailable;
+}
+
+/**
+ * To check if the token detection is OFF for the token detection supported networks
+ * and the network is not Mainnet
+ *
+ * @param {*} state
+ * @returns Boolean
+ */
+export function getIstokenDetectionInactiveOnNonMainnetSupportedNetwork(state) {
+ const useTokenDetection = getUseTokenDetection(state);
+ const isMainnet = getIsMainnet(state);
+ const isDynamicTokenListAvailable = getIsDynamicTokenListAvailable(state);
+
+ return isDynamicTokenListAvailable && !useTokenDetection && !isMainnet;
+}
+
/**
* To get the `customNetworkListEnabled` value which determines whether we use the custom network list
*
diff --git a/yarn.lock b/yarn.lock
index 91de10061..3460200b3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2867,10 +2867,10 @@
resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.35.0.tgz#2bf2b8f2b6fdbd5132f0bcfa594b6c02dc71c42e"
integrity sha512-zfZKwLFOVrQS8vTFoeoNCG9JhqmK4oyembGiGVVpUAYD9BHVZnd9WpicGoUC07ROXLEyQuAK9AJZNBtqwwzfEQ==
-"@metamask/controllers@^30.0.0", "@metamask/controllers@^30.0.2":
- version "30.0.2"
- resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-30.0.2.tgz#0a5512598d2997e34d3542889cae7088fe1fa4b8"
- integrity sha512-nIUQaaGPzy9whcAvzwHCRsMtw3YWdBv6mUiN9EA2CKdYUesnVj4bpXSSMEso1oEhsNRa2/XTZSb6i+Odo/raJw==
+"@metamask/controllers@^30.0.0", "@metamask/controllers@^30.1.0":
+ version "30.1.0"
+ resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-30.1.0.tgz#157d0afca156f1f37a89fbb864c4ee5c64d23af0"
+ integrity sha512-480mQafsYKbl0q7YgV820mrPCUtWgLLVH/s8ozNT6/ZVX3sBU0FBhNKeCalewhn0HRfMRnLe8pvHCKIH30k/0w==
dependencies:
"@ethereumjs/common" "^2.3.1"
"@ethereumjs/tx" "^3.2.1"