From 4f92eddff0e283c1aacc5b0744bbe12c138edf0f Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 22 Jun 2023 18:07:20 -0230 Subject: [PATCH] refactor: Use Redux network controller state Various UI components have been updated to use Redux network controller state (via selectors) rather than directly accessing the controller state using the `Engine` global. Relates to MetaMask/mobile-planning#1016 --- app/components/UI/AddCustomToken/index.js | 10 +++++---- .../UI/ApproveTransactionReview/index.js | 5 ++--- app/components/UI/MessageSign/index.js | 7 +++++-- app/components/UI/MessageSign/index.test.tsx | 1 + .../UI/PersonalSign/PersonalSign.tsx | 8 ++++--- .../UI/SignatureRequest/Root/Root.tsx | 5 +++++ app/components/UI/TypedSign/index.js | 8 ++++--- app/components/UI/WatchAssetRequest/index.js | 6 +++--- app/components/Views/AddAsset/index.js | 1 + app/components/Views/Asset/index.js | 19 ++++++++++------- app/components/Views/AssetDetails/index.tsx | 12 ++++++----- app/components/Views/DetectedTokens/index.tsx | 21 ++++++------------- 12 files changed, 58 insertions(+), 45 deletions(-) diff --git a/app/components/UI/AddCustomToken/index.js b/app/components/UI/AddCustomToken/index.js index 1bedb38f0586..7f65c60607cc 100644 --- a/app/components/UI/AddCustomToken/index.js +++ b/app/components/UI/AddCustomToken/index.js @@ -84,6 +84,10 @@ export default class AddCustomToken extends PureComponent { }; static propTypes = { + /** + * The chain ID for the current selected network + */ + chainId: PropTypes.string, /** /* navigation object required to push new views */ @@ -96,8 +100,7 @@ export default class AddCustomToken extends PureComponent { getAnalyticsParams = () => { try { - const { NetworkController } = Engine.context; - const { chainId } = NetworkController?.state?.providerConfig || {}; + const { chainId } = this.props; const { address, symbol } = this.state; return { token_address: address, @@ -184,8 +187,7 @@ export default class AddCustomToken extends PureComponent { let validated = true; const address = this.state.address; const isValidTokenAddress = isValidAddress(address); - const { NetworkController } = Engine.context; - const { chainId } = NetworkController?.state?.providerConfig || {}; + const { chainId } = this.props; const toSmartContract = isValidTokenAddress && (await isSmartContractAddress(address, chainId)); const addressWithoutSpaces = address.replace(/\s/g, ''); diff --git a/app/components/UI/ApproveTransactionReview/index.js b/app/components/UI/ApproveTransactionReview/index.js index e482f3bdb968..4a488c9440ac 100644 --- a/app/components/UI/ApproveTransactionReview/index.js +++ b/app/components/UI/ApproveTransactionReview/index.js @@ -503,14 +503,13 @@ class ApproveTransactionReview extends PureComponent { getAnalyticsParams = () => { try { - const { activeTabUrl, transaction, onSetAnalyticsParams } = this.props; + const { activeTabUrl, chainId, transaction, onSetAnalyticsParams } = + this.props; const { token: { tokenSymbol }, originalApproveAmount, encodedAmount, } = this.state; - const { NetworkController } = Engine.context; - const { chainId } = NetworkController?.state?.providerConfig || {}; const isDapp = !Object.values(AppConstants.DEEPLINKS).includes( transaction?.origin, ); diff --git a/app/components/UI/MessageSign/index.js b/app/components/UI/MessageSign/index.js index 2f36d2ea993e..523d4aa2fe21 100644 --- a/app/components/UI/MessageSign/index.js +++ b/app/components/UI/MessageSign/index.js @@ -38,6 +38,10 @@ const createStyles = (colors) => */ class MessageSign extends PureComponent { static propTypes = { + /** + * The chain ID of the current selected network + */ + chainId: PropTypes.string, /** * react-navigation object used for switching between screens */ @@ -75,11 +79,10 @@ class MessageSign extends PureComponent { getAnalyticsParams = () => { try { const { + chainId, currentPageInformation, messageParams: { from }, } = this.props; - const { NetworkController } = Engine.context; - const { chainId } = NetworkController?.state?.providerConfig || {}; const url = new URL(currentPageInformation?.url); return { account_type: getAddressAccountType(from), diff --git a/app/components/UI/MessageSign/index.test.tsx b/app/components/UI/MessageSign/index.test.tsx index 64d2f5fa3ab1..c7454abd498f 100644 --- a/app/components/UI/MessageSign/index.test.tsx +++ b/app/components/UI/MessageSign/index.test.tsx @@ -50,6 +50,7 @@ function createWrapper({ origin = messageParamsMock.origin } = {}) { return shallow( undefined} diff --git a/app/components/UI/PersonalSign/PersonalSign.tsx b/app/components/UI/PersonalSign/PersonalSign.tsx index 3b2ae7b15fe8..f080fce92240 100644 --- a/app/components/UI/PersonalSign/PersonalSign.tsx +++ b/app/components/UI/PersonalSign/PersonalSign.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect, useCallback } from 'react'; import { View, Text, InteractionManager } from 'react-native'; +import { useSelector } from 'react-redux'; import Engine from '../../../core/Engine'; import SignatureRequest from '../SignatureRequest'; import ExpandedMessage from '../SignatureRequest/ExpandedMessage'; @@ -17,6 +18,7 @@ import { PersonalSignProps } from './types'; import { useNavigation } from '@react-navigation/native'; import createStyles from './styles'; import AppConstants from '../../../core/AppConstants'; +import { selectChainId } from '../../../selectors/networkController'; /** * Component that supports personal_sign @@ -32,6 +34,8 @@ const PersonalSign = ({ const navigation = useNavigation(); const [truncateMessage, setTruncateMessage] = useState(false); + const chainId = useSelector(selectChainId); + const { colors }: any = useTheme(); const styles = createStyles(colors); @@ -46,8 +50,6 @@ const PersonalSign = ({ const getAnalyticsParams = useCallback((): AnalyticsParams => { try { - const { NetworkController }: any = Engine.context; - const { chainId } = NetworkController?.state?.providerConfig || {}; const url = new URL(currentPageInformation?.url); return { @@ -61,7 +63,7 @@ const PersonalSign = ({ } catch (error) { return {}; } - }, [currentPageInformation, messageParams]); + }, [chainId, currentPageInformation, messageParams]); useEffect(() => { AnalyticsV2.trackEvent( diff --git a/app/components/UI/SignatureRequest/Root/Root.tsx b/app/components/UI/SignatureRequest/Root/Root.tsx index a9833ea28519..647144e7da70 100644 --- a/app/components/UI/SignatureRequest/Root/Root.tsx +++ b/app/components/UI/SignatureRequest/Root/Root.tsx @@ -1,6 +1,7 @@ import Modal from 'react-native-modal'; import React, { useState } from 'react'; import { StyleSheet } from 'react-native'; +import { useSelector } from 'react-redux'; import { useNavigation } from '@react-navigation/native'; import { useTheme } from '../../../../util/theme'; import MessageSign from '../../../UI/MessageSign'; @@ -8,6 +9,7 @@ import PersonalSign from '../../../UI/PersonalSign'; import TypedSign from '../../../UI/TypedSign'; import { MessageParams } from '../types'; import { ApprovalTypes } from '../../../../core/RPCMethods/RPCMethodMiddleware'; +import { selectChainId } from '../../../../selectors/networkController'; interface RootProps { messageParams?: MessageParams; @@ -26,6 +28,7 @@ const Root = ({ messageParams, approvalType, onSign }: RootProps) => { const navigation = useNavigation(); const { colors } = useTheme(); const [showExpandedMessage, setShowExpandedMessage] = useState(false); + const chainId = useSelector(selectChainId); const toggleExpandedMessage = () => setShowExpandedMessage(!showExpandedMessage); @@ -64,6 +67,7 @@ const Root = ({ messageParams, approvalType, onSign }: RootProps) => { )} {approvalType === ApprovalTypes.ETH_SIGN_TYPED_DATA && ( { )} {approvalType === ApprovalTypes.ETH_SIGN && ( */ class TypedSign extends PureComponent { static propTypes = { + /** + * The chain ID of the current selected network + */ + chainId: PropTypes.string, /** * react-navigation object used for switching between screens */ @@ -85,9 +89,7 @@ class TypedSign extends PureComponent { getAnalyticsParams = () => { try { - const { currentPageInformation, messageParams } = this.props; - const { NetworkController } = Engine.context; - const { chainId } = NetworkController?.state?.providerConfig || {}; + const { chainId, currentPageInformation, messageParams } = this.props; const url = new URL(currentPageInformation?.url); return { account_type: getAddressAccountType(messageParams.from), diff --git a/app/components/UI/WatchAssetRequest/index.js b/app/components/UI/WatchAssetRequest/index.js index 9a08c1628294..fab444bb7066 100644 --- a/app/components/UI/WatchAssetRequest/index.js +++ b/app/components/UI/WatchAssetRequest/index.js @@ -2,19 +2,20 @@ import React from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, View, Text, InteractionManager } from 'react-native'; import URL from 'url-parse'; +import { useSelector } from 'react-redux'; import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import ActionView from '../ActionView'; import { renderFromTokenMinimalUnit } from '../../../util/number'; import TokenImage from '../../UI/TokenImage'; import Device from '../../../util/device'; -import Engine from '../../../core/Engine'; import { MetaMetricsEvents } from '../../../core/Analytics'; import AnalyticsV2 from '../../../util/analyticsV2'; import useTokenBalance from '../../hooks/useTokenBalance'; import { useTheme } from '../../../util/theme'; import NotificationManager from '../../../core/NotificationManager'; +import { selectChainId } from '../../../selectors/networkController'; const createStyles = (colors) => StyleSheet.create({ @@ -97,14 +98,13 @@ const WatchAssetRequest = ({ const { colors } = useTheme(); const styles = createStyles(colors); const [balance, , error] = useTokenBalance(asset.address, interactingAddress); + const chainId = useSelector(selectChainId); const balanceWithSymbol = error ? strings('transaction.failed') : `${renderFromTokenMinimalUnit(balance, asset.decimals)} ${asset.symbol}`; const getAnalyticsParams = () => { try { - const { NetworkController } = Engine.context; - const { chainId } = NetworkController?.state?.providerConfig || {}; const url = new URL(currentPageInformation?.url); return { diff --git a/app/components/Views/AddAsset/index.js b/app/components/Views/AddAsset/index.js index 6b95f0bbefc1..ff14a11a1b32 100644 --- a/app/components/Views/AddAsset/index.js +++ b/app/components/Views/AddAsset/index.js @@ -166,6 +166,7 @@ class AddAsset extends PureComponent { /> )} { - const { selectedAddress, chainId } = this.props; + const { selectedAddress, chainId, networkId } = this.props; const { transaction: { from, to }, isTransfer, transferInformation, } = tx; - const network = Engine.context.NetworkController.state.network; if ( (safeToChecksumAddress(from) === selectedAddress || safeToChecksumAddress(to) === selectedAddress) && - (chainId === tx.chainId || (!tx.chainId && network === tx.networkID)) && + (chainId === tx.chainId || (!tx.chainId && networkId === tx.networkID)) && tx.status !== 'unapproved' ) { if (isTransfer) @@ -281,17 +285,17 @@ class Asset extends PureComponent { }; noEthFilter = (tx) => { - const { chainId, swapsTransactions, selectedAddress } = this.props; + const { chainId, networkId, swapsTransactions, selectedAddress } = + this.props; const { transaction: { to, from }, isTransfer, transferInformation, } = tx; - const network = Engine.context.NetworkController.state.network; if ( (safeToChecksumAddress(from) === selectedAddress || safeToChecksumAddress(to) === selectedAddress) && - (chainId === tx.chainId || (!tx.chainId && network === tx.networkID)) && + (chainId === tx.chainId || (!tx.chainId && networkId === tx.networkID)) && tx.status !== 'unapproved' ) { if (to?.toLowerCase() === this.navAddress) return true; @@ -566,6 +570,7 @@ const mapStateToProps = (state) => ({ state.engine.backgroundState.PreferencesController.selectedAddress, identities: state.engine.backgroundState.PreferencesController.identities, chainId: selectChainId(state), + networkId: selectNetwork(state), tokens: state.engine.backgroundState.TokensController.tokens, transactions: state.engine.backgroundState.TransactionController.transactions, thirdPartyApiMode: state.privacy.thirdPartyApiMode, diff --git a/app/components/Views/AssetDetails/index.tsx b/app/components/Views/AssetDetails/index.tsx index 548be8e839cc..7762dbe4c1c6 100644 --- a/app/components/Views/AssetDetails/index.tsx +++ b/app/components/Views/AssetDetails/index.tsx @@ -32,7 +32,10 @@ import { useTheme } from '../../../util/theme'; import { MetaMetricsEvents } from '../../../core/Analytics'; import AnalyticsV2 from '../../../util/analyticsV2'; import Routes from '../../../constants/navigation/Routes'; -import { selectProviderConfig } from '../../../selectors/networkController'; +import { + selectChainId, + selectProviderConfig, +} from '../../../selectors/networkController'; const createStyles = (colors: any) => StyleSheet.create({ @@ -98,6 +101,7 @@ const AssetDetails = (props: Props) => { const navigation = useNavigation(); const dispatch = useDispatch(); const providerConfig = useSelector(selectProviderConfig); + const chainId = useSelector(selectChainId); const tokens = useSelector( (state: any) => state.engine.backgroundState.TokensController.tokens as TokenType[], @@ -165,7 +169,7 @@ const AssetDetails = (props: Props) => { }; const triggerHideToken = () => { - const { TokensController, NetworkController } = Engine.context as any; + const { TokensController } = Engine.context as any; navigation.navigate(Routes.MODAL.ROOT_MODAL_FLOW, { screen: 'AssetHideConfirmation', params: { @@ -187,9 +191,7 @@ const AssetDetails = (props: Props) => { token_standard: 'ERC20', asset_type: 'token', tokens: [`${symbol} - ${address}`], - chain_id: getDecimalChainId( - NetworkController?.state?.providerConfig?.chainId, - ), + chain_id: getDecimalChainId(chainId), }); } catch (err) { Logger.log(err, 'AssetDetails: Failed to hide token!'); diff --git a/app/components/Views/DetectedTokens/index.tsx b/app/components/Views/DetectedTokens/index.tsx index 64377efdbeb5..5535fe7cb122 100644 --- a/app/components/Views/DetectedTokens/index.tsx +++ b/app/components/Views/DetectedTokens/index.tsx @@ -20,6 +20,7 @@ import { getDecimalChainId } from '../../../util/networks'; import { FlatList } from 'react-native-gesture-handler'; import { createNavigationDetails } from '../../../util/navigation/navUtils'; import Routes from '../../../constants/navigation/Routes'; +import { selectChainId } from 'app/selectors/networkController'; const createStyles = (colors: any) => StyleSheet.create({ @@ -71,6 +72,7 @@ const DetectedTokens = () => { state.engine.backgroundState.TokensController .detectedTokens as TokenType[], ); + const chainId = useSelector(selectChainId); const [ignoredTokens, setIgnoredTokens] = useState( {}, ); @@ -118,8 +120,6 @@ const DetectedTokens = () => { } modalRef.current?.dismissModal(async () => { - const { NetworkController } = Engine.context as any; - try { tokensToIgnore.length > 0 && (await TokensController.ignoreTokens(tokensToIgnore)); @@ -130,9 +130,7 @@ const DetectedTokens = () => { AnalyticsV2.trackEvent(MetaMetricsEvents.TOKEN_ADDED, { token_address: address, token_symbol: symbol, - chain_id: getDecimalChainId( - NetworkController?.state?.providerConfig?.chainId, - ), + chain_id: getDecimalChainId(chainId), source: 'detected', }), ), @@ -149,12 +147,10 @@ const DetectedTokens = () => { } }); }, - [detectedTokens, ignoredTokens], + [chainId, detectedTokens, ignoredTokens], ); const triggerIgnoreAllTokens = () => { - const { NetworkController } = Engine.context as any; - navigation.navigate('DetectedTokensConfirmation', { onConfirm: () => dismissModalAndTriggerAction(true), isHidingAll: true, @@ -165,9 +161,7 @@ const DetectedTokens = () => { token_standard: 'ERC20', asset_type: 'token', tokens: detectedTokensForAnalytics, - chain_id: getDecimalChainId( - NetworkController?.state?.providerConfig?.chainId, - ), + chain_id: getDecimalChainId(chainId), }), ); }; @@ -256,16 +250,13 @@ const DetectedTokens = () => { }; const trackCancelWithoutAction = (hasPendingAction: boolean) => { - const { NetworkController } = Engine.context as any; if (hasPendingAction) { return; } AnalyticsV2.trackEvent(MetaMetricsEvents.TOKEN_IMPORT_CANCELED, { source: 'detected', tokens: detectedTokensForAnalytics, - chain_id: getDecimalChainId( - NetworkController?.state?.providerConfig?.chainId, - ), + chain_id: getDecimalChainId(chainId), }); };