From 5f144eca1db9f1ce9e3b38548dd8d442c3898e83 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Thu, 21 Nov 2024 11:44:44 -0700 Subject: [PATCH 01/16] Upgrade `@metamask/swaps-controller` to 12.0.0 This version updates SwapsController so that it is less reliant on the global network. Specifically: - The `setChainId` and `setProvider` methods have been removed from SwapsController. - The `fetchGasFeeEstimates` and `fetchEstimatedMultiLayerL1Fee` SwapsController constructor options are now expected to take a `networkClientId`. - The SwapsController constructor no longer takes a `chainId` option. - `startFetchAndSetQuotes`, `fetchTokenWithCache`, `fetchTopAssetsWithCache`, and `fetchAggregatorMetadataWithCache` now take a `networkClientId`. - The `fetchParamsMetaData` SwapsController state property now includes a `networkClientId`. - The chain cache in SwapsController state will now automatically be updated whenever the network has changed. At the moment, the global network client ID is still passed into SwapsController whenever it is used, but now that can be changed to use a dapp-level network client ID without needing to update SwapsController. --- .../UI/AssetOverview/AssetOverview.tsx | 13 +- app/components/UI/Swaps/QuotesView.js | 14 +- app/components/UI/Swaps/QuotesView.test.ts | 10 +- .../__snapshots__/QuotesView.test.ts.snap | 6 +- .../Swaps/__snapshots__/index.test.tsx.snap | 1687 ++++++++++++++++ .../__snapshots__/index.test.tsx.snap | 1719 +++++++++++++++++ .../components/LoadingAnimation/index.js | 12 +- .../LoadingAnimation/index.test.tsx | 24 + app/components/UI/Swaps/index.js | 35 +- app/components/UI/Swaps/index.test.tsx | 37 + app/components/UI/Swaps/utils/index.js | 3 + app/core/Engine/Engine.ts | 15 +- app/reducers/swaps/index.js | 24 +- app/util/test/initial-background-state.json | 3 +- package.json | 3 +- patches/@react-navigation+native+5.9.4.patch | 13 + patches/react-native-modal+12.1.0.patch | 22 +- yarn.lock | 13 +- 18 files changed, 3587 insertions(+), 66 deletions(-) create mode 100644 app/components/UI/Swaps/__snapshots__/index.test.tsx.snap create mode 100644 app/components/UI/Swaps/components/LoadingAnimation/__snapshots__/index.test.tsx.snap create mode 100644 app/components/UI/Swaps/components/LoadingAnimation/index.test.tsx create mode 100644 app/components/UI/Swaps/index.test.tsx create mode 100644 patches/@react-navigation+native+5.9.4.patch diff --git a/app/components/UI/AssetOverview/AssetOverview.tsx b/app/components/UI/AssetOverview/AssetOverview.tsx index 55ce2b8f222..b09fc68912f 100644 --- a/app/components/UI/AssetOverview/AssetOverview.tsx +++ b/app/components/UI/AssetOverview/AssetOverview.tsx @@ -10,6 +10,7 @@ import AppConstants from '../../../core/AppConstants'; import Engine from '../../../core/Engine'; import { selectChainId, + selectNetworkClientId, selectTicker, } from '../../../selectors/networkController'; import { @@ -46,7 +47,6 @@ import Routes from '../../../constants/navigation/Routes'; import TokenDetails from './TokenDetails'; import { RootState } from '../../../reducers'; import useGoToBridge from '../Bridge/utils/useGoToBridge'; -import SwapsController from '@metamask/swaps-controller'; import { MetaMetricsEvents } from '../../../core/Analytics'; import { getDecimalChainId } from '../../../util/networks'; import { useMetrics } from '../../../components/hooks/useMetrics'; @@ -82,6 +82,7 @@ const AssetOverview: React.FC = ({ const tokenBalances = useSelector(selectContractBalances); const chainId = useSelector((state: RootState) => selectChainId(state)); const ticker = useSelector((state: RootState) => selectTicker(state)); + const selectedNetworkClientId = useSelector(selectNetworkClientId); const { data: prices = [], isLoading } = useTokenHistoricalPrices({ address: asset.isETH ? zeroAddress() : asset.address, @@ -94,12 +95,12 @@ const AssetOverview: React.FC = ({ const dispatch = useDispatch(); useEffect(() => { - const { SwapsController: SwapsControllerFromEngine } = Engine.context as { - SwapsController: SwapsController; - }; + const { SwapsController } = Engine.context; const fetchTokenWithCache = async () => { try { - await SwapsControllerFromEngine.fetchTokenWithCache(); + await SwapsController.fetchTokenWithCache({ + networkClientId: selectedNetworkClientId, + }); // TODO: Replace "any" with type // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { @@ -110,7 +111,7 @@ const AssetOverview: React.FC = ({ } }; fetchTokenWithCache(); - }, []); + }, [selectedNetworkClientId]); const onReceive = () => { navigation.navigate(Routes.QR_TAB_SWITCHER, { diff --git a/app/components/UI/Swaps/QuotesView.js b/app/components/UI/Swaps/QuotesView.js index 494216449fd..b983796c39b 100644 --- a/app/components/UI/Swaps/QuotesView.js +++ b/app/components/UI/Swaps/QuotesView.js @@ -8,7 +8,7 @@ import { TouchableOpacity, Linking, } from 'react-native'; -import { connect } from 'react-redux'; +import { connect, useSelector } from 'react-redux'; import IonicIcon from 'react-native-vector-icons/Ionicons'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; import BigNumber from 'bignumber.js'; @@ -96,7 +96,7 @@ import { import { selectChainId, selectIsEIP1559Network, - selectNetworkClientId, + selectSelectedNetworkClientId, selectTicker, } from '../../../selectors/networkController'; import { @@ -304,6 +304,7 @@ async function resetAndStartPolling({ destinationToken, sourceAmount, walletAddress, + networkClientId, }) { if (!sourceToken || !destinationToken) { return; @@ -316,6 +317,7 @@ async function resetAndStartPolling({ destinationToken, sourceAmount, walletAddress, + networkClientId, }); await SwapsController.stopPollingAndResetState(); await SwapsController.startFetchAndSetQuotes( @@ -762,6 +764,8 @@ function SwapsQuotesView({ } }, [error, navigation]); + const selectedNetworkClientId = useSelector(selectSelectedNetworkClientId); + const handleRetryFetchQuotes = useCallback(() => { if (error?.key === swapsUtils.SwapsError.QUOTES_EXPIRED_ERROR) { navigation.setParams({ leftAction: strings('navigation.back') }); @@ -776,6 +780,7 @@ function SwapsQuotesView({ destinationToken, sourceAmount, walletAddress: selectedAddress, + networkClientId: selectedNetworkClientId, }); } else { navigation.pop(); @@ -788,6 +793,7 @@ function SwapsQuotesView({ sourceAmount, selectedAddress, navigation, + selectedNetworkClientId, ]); const updateSwapsTransactions = useCallback( @@ -1396,6 +1402,7 @@ function SwapsQuotesView({ destinationToken, sourceAmount, walletAddress: selectedAddress, + networkClientId: selectedNetworkClientId, }); return () => { @@ -1409,6 +1416,7 @@ function SwapsQuotesView({ slippage, sourceAmount, sourceToken.address, + selectedNetworkClientId, ]); /** selectedQuote alert effect */ @@ -2384,7 +2392,7 @@ SwapsQuotesView.propTypes = { const mapStateToProps = (state) => ({ accounts: selectAccounts(state), chainId: selectChainId(state), - networkClientId: selectNetworkClientId(state), + networkClientId: selectSelectedNetworkClientId(state), ticker: selectTicker(state), balances: selectContractBalances(state), selectedAddress: selectSelectedInternalAccountFormattedAddress(state), diff --git a/app/components/UI/Swaps/QuotesView.test.ts b/app/components/UI/Swaps/QuotesView.test.ts index eafafb20e98..eac7a44da30 100644 --- a/app/components/UI/Swaps/QuotesView.test.ts +++ b/app/components/UI/Swaps/QuotesView.test.ts @@ -17,6 +17,7 @@ import { } from '../../../util/test/accountsControllerTestUtils'; import { SwapsViewSelectors } from '../../../../e2e/selectors/swaps/SwapsView.selectors'; import Engine from '../../../core/Engine'; +import { RpcEndpointType } from '@metamask/network-controller'; jest.mock('../../../core/Engine', () => ({ context: { @@ -203,7 +204,14 @@ const mockInitialState: DeepPartial = { defaultRpcEndpointIndex: 0, name: 'Ethereum Mainnet', nativeCurrency: 'ETH', - rpcEndpoints: [], + rpcEndpoints: [ + { + name: 'Ethereum Mainnet', + networkClientId: 'mainnet', + type: RpcEndpointType.Infura, + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + }, + ], }, }, }, diff --git a/app/components/UI/Swaps/__snapshots__/QuotesView.test.ts.snap b/app/components/UI/Swaps/__snapshots__/QuotesView.test.ts.snap index 0bd67e23b11..f69db814fbc 100644 --- a/app/components/UI/Swaps/__snapshots__/QuotesView.test.ts.snap +++ b/app/components/UI/Swaps/__snapshots__/QuotesView.test.ts.snap @@ -194,9 +194,7 @@ exports[`QuotesView should render quote screen 1`] = ` "width": 5, }, { - "backgroundColor": "transparent", - "borderColor": "#bbc0c5", - "borderWidth": 1, + "backgroundColor": "#3cc29e", }, ] } @@ -215,7 +213,7 @@ exports[`QuotesView should render quote screen 1`] = ` } } > - Private Network + Ethereum Main Network diff --git a/app/components/UI/Swaps/__snapshots__/index.test.tsx.snap b/app/components/UI/Swaps/__snapshots__/index.test.tsx.snap new file mode 100644 index 00000000000..548df17bfd0 --- /dev/null +++ b/app/components/UI/Swaps/__snapshots__/index.test.tsx.snap @@ -0,0 +1,1687 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SwapsAmountView renders 1`] = ` + + + + + + + + + Account is loading... + + +  + + + + + + + + + + + + Select a token + + +  + + + + + + + + + 0 + + + + + + + + + + +  + + + + + + + + + + + + Select a token + + +  + + + + + + + + + + + + + + + + + + 1 + + + + + 2 + + + + + 3 + + + + + + + 4 + + + + + 5 + + + + + 6 + + + + + + + 7 + + + + + 8 + + + + + 9 + + + + + + + . + + + + + 0 + + + + +  + + + + + + + + + + Max slippage 2% + + + + + + + + Get quotes + + + + + + + + + + + +`; diff --git a/app/components/UI/Swaps/components/LoadingAnimation/__snapshots__/index.test.tsx.snap b/app/components/UI/Swaps/components/LoadingAnimation/__snapshots__/index.test.tsx.snap new file mode 100644 index 00000000000..76d124104e2 --- /dev/null +++ b/app/components/UI/Swaps/components/LoadingAnimation/__snapshots__/index.test.tsx.snap @@ -0,0 +1,1719 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LoadingAnimation renders 1`] = ` + + + + + Starting... + + + + + + + + + + + + --- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ", + } + } + style={ + [ + { + "backgroundColor": "#ffffff", + "flex": 1, + }, + undefined, + ] + } + /> + + + +`; diff --git a/app/components/UI/Swaps/components/LoadingAnimation/index.js b/app/components/UI/Swaps/components/LoadingAnimation/index.js index ec6a1363364..9b282d42517 100644 --- a/app/components/UI/Swaps/components/LoadingAnimation/index.js +++ b/app/components/UI/Swaps/components/LoadingAnimation/index.js @@ -5,8 +5,10 @@ import React, { useRef, useState, } from 'react'; +import { useSelector } from 'react-redux'; import { Animated, View, StyleSheet, Image } from 'react-native'; import PropTypes from 'prop-types'; +import { selectSelectedNetworkClientId } from '../../../../../selectors/networkController'; import Engine from '../../../../../core/Engine'; import Logger from '../../../../../util/Logger'; import Device from '../../../../../util/device'; @@ -129,6 +131,8 @@ function LoadingAnimation({ const [renderLogos, setRenderLogos] = useState(false); const [currentQuoteIndex, setCurrentQuoteIndex] = useState(0); + const selectedNetworkClientId = useSelector(selectSelectedNetworkClientId); + /* References */ const foxRef = useRef(); const foxHeadPan = useRef(new Animated.ValueXY(0, 0)).current; @@ -317,9 +321,11 @@ function LoadingAnimation({ return; } if (!aggregatorMetadata) { + const { SwapsController } = Engine.context; try { - const { SwapsController } = Engine.context; - await SwapsController.fetchAggregatorMetadataWithCache(); + await SwapsController.fetchAggregatorMetadataWithCache({ + networkClientId: selectedNetworkClientId, + }); } catch (error) { Logger.error( error, @@ -337,7 +343,7 @@ function LoadingAnimation({ setShouldStart(true); } })(); - }, [aggregatorMetadata, hasStarted]); + }, [aggregatorMetadata, hasStarted, selectedNetworkClientId]); /* Delay the logos rendering to avoid navigation transition lag */ useEffect(() => { diff --git a/app/components/UI/Swaps/components/LoadingAnimation/index.test.tsx b/app/components/UI/Swaps/components/LoadingAnimation/index.test.tsx new file mode 100644 index 00000000000..d0f72eb0ad1 --- /dev/null +++ b/app/components/UI/Swaps/components/LoadingAnimation/index.test.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import renderWithProvider, { + DeepPartial, +} from '../../../../../util/test/renderWithProvider'; +import LoadingAnimation from './'; +import { backgroundState } from '../../../../../util/test/initial-root-state'; +import { RootState } from '../../../../../reducers'; + +const mockInitialState: DeepPartial = { + engine: { + backgroundState: { + ...backgroundState, + }, + }, +}; + +describe('LoadingAnimation', () => { + it('renders', () => { + const wrapper = renderWithProvider(, { + state: mockInitialState, + }); + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/app/components/UI/Swaps/index.js b/app/components/UI/Swaps/index.js index 5b1710f43c0..fb08e469161 100644 --- a/app/components/UI/Swaps/index.js +++ b/app/components/UI/Swaps/index.js @@ -13,7 +13,7 @@ import { TouchableOpacity, InteractionManager, } from 'react-native'; -import { connect } from 'react-redux'; +import { connect, useSelector } from 'react-redux'; import { useNavigation, useRoute } from '@react-navigation/native'; import { View as AnimatableView } from 'react-native-animatable'; import IonicIcon from 'react-native-vector-icons/Ionicons'; @@ -70,6 +70,7 @@ import { selectChainId, selectNetworkConfigurations, selectProviderConfig, + selectSelectedNetworkClientId, } from '../../../selectors/networkController'; import { selectConversionRate, @@ -184,6 +185,7 @@ function SwapsAmountView({ accounts, selectedAddress, chainId, + selectedNetworkClientId, providerConfig, networkConfigurations, balances, @@ -252,6 +254,8 @@ function SwapsAmountView({ }, [navigation, route, colors]); useEffect(() => { + let isStopped = false; + (async () => { try { const featureFlags = await swapsUtils.fetchSwapsFeatureFlags( @@ -259,6 +263,10 @@ function SwapsAmountView({ AppConstants.SWAPS.CLIENT_ID, ); + if (isStopped) { + return; + } + const liveness = getSwapsLiveness(featureFlags, chainId); setLiveness(chainId, featureFlags); @@ -288,6 +296,10 @@ function SwapsAmountView({ navigation.pop(); } })(); + + return () => { + isStopped = true; + }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [initialSource, chainId, navigation, setLiveness]); @@ -297,8 +309,12 @@ function SwapsAmountView({ (async () => { const { SwapsController } = Engine.context; try { - await SwapsController.fetchAggregatorMetadataWithCache(); - await SwapsController.fetchTopAssetsWithCache(); + await SwapsController.fetchAggregatorMetadataWithCache({ + networkClientId: selectedNetworkClientId, + }); + await SwapsController.fetchTopAssetsWithCache({ + networkClientId: selectedNetworkClientId, + }); } catch (error) { Logger.error( error, @@ -306,7 +322,7 @@ function SwapsAmountView({ ); } })(); - }, []); + }, [selectedNetworkClientId]); useEffect(() => { (async () => { @@ -320,7 +336,9 @@ function SwapsAmountView({ setInitialLoadingTokens(true); } setLoadingTokens(true); - await SwapsController.fetchTokenWithCache(); + await SwapsController.fetchTokenWithCache({ + networkClientId: selectedNetworkClientId, + }); setLoadingTokens(false); setInitialLoadingTokens(false); } catch (error) { @@ -333,7 +351,7 @@ function SwapsAmountView({ setInitialLoadingTokens(false); } })(); - }, [swapsControllerTokens, swapsTokens]); + }, [swapsControllerTokens, swapsTokens, selectedNetworkClientId]); const canSetAnInitialSourceToken = !isSourceSet && @@ -986,6 +1004,10 @@ SwapsAmountView.propTypes = { * Chain Id */ chainId: PropTypes.string, + /** + * Selected network client ID + */ + selectedNetworkClientId: PropTypes.string, /** * Network configurations */ @@ -1008,6 +1030,7 @@ const mapStateToProps = (state) => ({ providerConfig: selectProviderConfig(state), networkConfigurations: selectNetworkConfigurations(state), chainId: selectChainId(state), + selectedNetworkClientId: selectSelectedNetworkClientId(state), tokensWithBalance: swapsTokensWithBalanceSelector(state), tokensTopAssets: swapsTopAssetsSelector(state), }); diff --git a/app/components/UI/Swaps/index.test.tsx b/app/components/UI/Swaps/index.test.tsx new file mode 100644 index 00000000000..e11bf8e9cd8 --- /dev/null +++ b/app/components/UI/Swaps/index.test.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import renderWithProvider, { + DeepPartial, +} from '../../../util/test/renderWithProvider'; +import SwapsAmountView from './'; +import { backgroundState } from '../../../util/test/initial-root-state'; +import { RootState } from '../../../reducers'; + +jest.mock('@react-navigation/native', () => { + const actualNav = jest.requireActual('@react-navigation/native'); + return { + ...actualNav, + useNavigation: () => ({ + setOptions: jest.fn(), + pop: jest.fn(), + navigate: jest.fn(), + }), + useRoute: () => ({}), + }; +}); + +const mockInitialState: DeepPartial = { + engine: { + backgroundState: { + ...backgroundState, + }, + }, +}; + +describe('SwapsAmountView', () => { + it('renders', async () => { + const wrapper = renderWithProvider(, { + state: mockInitialState, + }); + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/app/components/UI/Swaps/utils/index.js b/app/components/UI/Swaps/utils/index.js index 665562c3f55..d9d41edd236 100644 --- a/app/components/UI/Swaps/utils/index.js +++ b/app/components/UI/Swaps/utils/index.js @@ -118,6 +118,7 @@ export function getQuotesNavigationsParams(route) { * @param {object} options.destinationToken destinationToken object from tokens API * @param {string} sourceAmount Amount in minimal token units of sourceToken to be swapped * @param {string} fromAddress Current address attempting to swap + * @param {string} networkClientId Current network client ID */ export function getFetchParams({ slippage = 1, @@ -125,6 +126,7 @@ export function getFetchParams({ destinationToken, sourceAmount, walletAddress, + networkClientId, }) { return { slippage, @@ -135,6 +137,7 @@ export function getFetchParams({ metaData: { sourceTokenInfo: sourceToken, destinationTokenInfo: destinationToken, + networkClientId, }, }; } diff --git a/app/core/Engine/Engine.ts b/app/core/Engine/Engine.ts index 294baf2b96f..472cdbe8e7a 100644 --- a/app/core/Engine/Engine.ts +++ b/app/core/Engine/Engine.ts @@ -1399,17 +1399,15 @@ export class Engine { // allowedActions: [ // 'GasFeeController:getEIP1559GasFeeEstimates', // ], - allowedActions: [ - 'NetworkController:findNetworkClientIdByChainId', - 'NetworkController:getNetworkClientById', - ], - allowedEvents: [], + allowedActions: ['NetworkController:getNetworkClientById'], + allowedEvents: ['NetworkController:networkDidChange'], }), pollCountLimit: AppConstants.SWAPS.POLL_COUNT_LIMIT, // TODO: Remove once GasFeeController exports this action type fetchGasFeeEstimates: () => gasFeeController.fetchGasFeeEstimates(), // @ts-expect-error TODO: Resolve mismatch between gas fee and swaps controller types fetchEstimatedMultiLayerL1Fee, + pollCountLimit: AppConstants.SWAPS.POLL_COUNT_LIMIT, }), GasFeeController: gasFeeController, ApprovalController: approvalController, @@ -1668,8 +1666,7 @@ export class Engine { } configureControllersOnNetworkChange() { - const { AccountTrackerController, NetworkController, SwapsController } = - this.context; + const { AccountTrackerController, NetworkController } = this.context; const { provider } = NetworkController.getProviderAndBlockTracker(); // Skip configuration if this is called before the provider is initialized @@ -1678,10 +1675,6 @@ export class Engine { } provider.sendAsync = provider.sendAsync.bind(provider); - SwapsController.setProvider(provider, { - chainId: getGlobalChainId(NetworkController), - pollCountLimit: AppConstants.SWAPS.POLL_COUNT_LIMIT, - }); AccountTrackerController.refresh(); } diff --git a/app/reducers/swaps/index.js b/app/reducers/swaps/index.js index 84674aee8ca..384e8983d90 100644 --- a/app/reducers/swaps/index.js +++ b/app/reducers/swaps/index.js @@ -2,10 +2,10 @@ import { createSelector } from 'reselect'; import { isMainnetByChainId } from '../../util/networks'; import { safeToChecksumAddress } from '../../util/address'; import { toLowerCaseEquals } from '../../util/general'; -import Engine from '../../core/Engine'; import { lte } from '../../util/lodash'; import { selectChainId } from '../../selectors/networkController'; import { selectTokens } from '../../selectors/tokensController'; +import { selectTokenList } from '../../selectors/tokenListController'; import { selectContractBalances } from '../../selectors/tokenBalancesController'; import { getChainFeatureFlags, getSwapsLiveness } from './utils'; import { allowedTestnetChainIds } from '../../components/UI/Swaps/utils'; @@ -35,15 +35,12 @@ export const setSwapsHasOnboarded = (hasOnboarded) => ({ // * Functions -function addMetadata(chainId, tokens) { +function addMetadata(chainId, tokens, tokenList) { if (!isMainnetByChainId(chainId)) { return tokens; } return tokens.map((token) => { - const tokenMetadata = - Engine.context.TokenListController.state.tokenList[ - safeToChecksumAddress(token.address) - ]; + const tokenMetadata = tokenList[safeToChecksumAddress(token.address)]; if (tokenMetadata) { return { ...token, name: tokenMetadata.name }; } @@ -193,12 +190,13 @@ const swapsControllerAndUserTokens = createSelector( export const swapsTokensSelector = createSelector( chainIdSelector, swapsControllerAndUserTokens, - (chainId, tokens) => { + selectTokenList, + (chainId, tokens, tokenList) => { if (!tokens) { return []; } - return addMetadata(chainId, tokens); + return addMetadata(chainId, tokens, tokenList); }, ); @@ -227,8 +225,9 @@ export const swapsTokensObjectSelector = createSelector( export const swapsTokensWithBalanceSelector = createSelector( chainIdSelector, swapsControllerAndUserTokens, + selectTokenList, selectContractBalances, - (chainId, tokens, balances) => { + (chainId, tokens, tokenList, balances) => { if (!tokens) { return []; } @@ -260,7 +259,7 @@ export const swapsTokensWithBalanceSelector = createSelector( 0, Math.max(tokensWithBalance.length, MAX_TOKENS_WITH_BALANCE), ); - return addMetadata(chainId, result); + return addMetadata(chainId, result, tokenList); }, ); @@ -271,8 +270,9 @@ export const swapsTokensWithBalanceSelector = createSelector( export const swapsTopAssetsSelector = createSelector( chainIdSelector, swapsControllerAndUserTokens, + selectTokenList, topAssets, - (chainId, tokens, topAssets) => { + (chainId, tokens, tokenList, topAssets) => { if (!topAssets || !tokens) { return []; } @@ -281,7 +281,7 @@ export const swapsTopAssetsSelector = createSelector( tokens?.find((token) => toLowerCaseEquals(token.address, address)), ) .filter(Boolean); - return addMetadata(chainId, result); + return addMetadata(chainId, result, tokenList); }, ); diff --git a/app/util/test/initial-background-state.json b/app/util/test/initial-background-state.json index 0191af34f02..b55fbd59d02 100644 --- a/app/util/test/initial-background-state.json +++ b/app/util/test/initial-background-state.json @@ -270,7 +270,8 @@ "decimals": 0, "address": "", "symbol": "" - } + }, + "networkClientId": "mainnet" }, "topAggSavings": null, "aggregatorMetadata": null, diff --git a/package.json b/package.json index f27eefc20d4..37e56d46f8f 100644 --- a/package.json +++ b/package.json @@ -203,7 +203,7 @@ "@metamask/snaps-utils": "^8.6.1", "@metamask/stake-sdk": "^0.3.0", "@metamask/swappable-obj-proxy": "^2.1.0", - "@metamask/swaps-controller": "^11.0.0", + "@metamask/swaps-controller": "^12.0.0", "@metamask/transaction-controller": "^41.0.0", "@metamask/utils": "^10.0.1", "@ngraveio/bc-ur": "^1.1.6", @@ -481,6 +481,7 @@ "metro-react-native-babel-transformer": "~0.76.9", "multiple-cucumber-html-reporter": "^3.0.1", "nock": "^13.3.1", + "node-addon-api": "^8.3.0", "nyc": "^15.1.0", "octonode": "0.10.2", "patch-package": "^6.2.2", diff --git a/patches/@react-navigation+native+5.9.4.patch b/patches/@react-navigation+native+5.9.4.patch new file mode 100644 index 00000000000..6761d4ff873 --- /dev/null +++ b/patches/@react-navigation+native+5.9.4.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js b/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js +index 5e4f8a4..39c29eb 100644 +--- a/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js ++++ b/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js +@@ -39,7 +39,7 @@ function useLinking(ref, { + // https://github.com/facebook/react-native/commit/6d1aca806cee86ad76de771ed3a1cc62982ebcd7 + if (subscription !== null && subscription !== void 0 && subscription.remove) { + subscription.remove(); +- } else { ++ } else if ('removeEventListener' in _reactNative.Linking) { + _reactNative.Linking.removeEventListener('url', callback); + } + }; diff --git a/patches/react-native-modal+12.1.0.patch b/patches/react-native-modal+12.1.0.patch index 100b619e238..853cca2564d 100644 --- a/patches/react-native-modal+12.1.0.patch +++ b/patches/react-native-modal+12.1.0.patch @@ -1,30 +1,24 @@ diff --git a/node_modules/react-native-modal/dist/modal.js b/node_modules/react-native-modal/dist/modal.js -index ec3cc0b..bed08a4 100644 +index ec3cc0b..6471cfb 100644 --- a/node_modules/react-native-modal/dist/modal.js +++ b/node_modules/react-native-modal/dist/modal.js -@@ -52,6 +52,7 @@ export class ReactNativeModal extends React.Component { - // isVisible prop to false. - // We store in the state the device width and height so that we can update the modal on - // device rotation. -+ this.dimensionsUpdateListener = null; - this.state = { - showContent: true, - isVisible: false, -@@ -448,7 +449,7 @@ export class ReactNativeModal extends React.Component { +@@ -448,15 +448,15 @@ export class ReactNativeModal extends React.Component { if (this.props.onSwipe) { console.warn('`` is deprecated and will be removed starting from 13.0.0. Use `` instead.'); } - DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); -+ this.dimensionsUpdateListener = DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); ++ this._didUpdateDimensionsSubscription = DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); if (this.state.isVisible) { this.open(); } -@@ -456,7 +457,7 @@ export class ReactNativeModal extends React.Component { +- BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress); ++ this._hardwareBackPressSubscription = BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress); } componentWillUnmount() { - BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPress); +- BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPress); - DeviceEventEmitter.removeListener('didUpdateDimensions', this.handleDimensionsUpdate); -+ this.dimensionsUpdateListener?.remove?.(); ++ this._didUpdateDimensionsSubscription.remove(); ++ this._hardwareBackPressSubscription.remove(); if (this.interactionHandle) { InteractionManager.clearInteractionHandle(this.interactionHandle); this.interactionHandle = null; diff --git a/yarn.lock b/yarn.lock index aa0795670d9..57e10f88a28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5424,10 +5424,10 @@ resolved "https://registry.yarnpkg.com/@metamask/swappable-obj-proxy/-/swappable-obj-proxy-2.2.0.tgz#31b8e0ce57e28bf9847b3b24b214996f7748cc99" integrity sha512-0OjVwQtrrPFRGipw64yDUQA0CUXCK161LWCv2KlTTDZD8BKeWSNb0gbnpDI7HvhsJ0gki5gScZj1hF3ShDnBzA== -"@metamask/swaps-controller@^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@metamask/swaps-controller/-/swaps-controller-11.0.0.tgz#7f77e4c65addb5f03bcad8c651ca6a5d74f94fd5" - integrity sha512-SdFEIiHWRZcHrkWkyhNUO5/Cr1GjOYv7RFS3D0jaCVhgCz/0yvHlgKAq5iOgS87DVHh1Iv/uFrFswwJyRin6gQ== +"@metamask/swaps-controller@^12.0.0": + version "12.0.0" + resolved "https://registry.yarnpkg.com/@metamask/swaps-controller/-/swaps-controller-12.0.0.tgz#60f256c10906f417225ebc7c99b587cafe6808a6" + integrity sha512-sjpN1iZnKu4BzWeIi7wUiZAa+rX+EA+SCLAmkrBcACrJQhjsKqBA4Wtrw8gI8uZrwwSfTIRFeMB6ksSiHFPzhQ== dependencies: "@ethersproject/contracts" "^5.7.0" "@ethersproject/providers" "^5.7.0" @@ -22581,6 +22581,11 @@ node-addon-api@^7.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.0.0.tgz#8136add2f510997b3b94814f4af1cce0b0e3962e" integrity sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA== +node-addon-api@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.3.0.tgz#ec3763f18befc1cdf66d11e157ce44d5eddc0603" + integrity sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg== + node-dir@^0.1.17: version "0.1.17" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" From e29501dc735081c5a61b4beab3cd7ac5d440c23e Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Mon, 9 Dec 2024 12:20:30 -0700 Subject: [PATCH 02/16] Try disabling sharp everywhere to see if CI will pass --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 37e56d46f8f..b66914ad52f 100644 --- a/package.json +++ b/package.json @@ -564,7 +564,7 @@ "@storybook/addon-knobs>@storybook/components>react-syntax-highlighter>highlight.js": false, "@storybook/addon-knobs>core-js": false, "@wdio/cucumber-framework>@cucumber/cucumber>duration>es5-ext": false, - "appium-adb>@appium/support>sharp": true, + "appium-adb>@appium/support>sharp": false, "appium>appium-android-driver>appium-chromedriver": false, "appium>appium-base-driver>webdriverio>@types/puppeteer-core>@types/puppeteer>puppeteer": false, "appium>appium-flutter-driver>rpc-websockets>bufferutil": false, @@ -586,7 +586,7 @@ "ganache>utf-8-validate": false, "husky": false, "react-native-inappbrowser-reborn": false, - "react-native-svg-asset-plugin>sharp": true, + "react-native-svg-asset-plugin>sharp": false, "@storybook/builder-webpack5>@swc/core": false, "@metamask/sdk-communication-layer>bufferutil": false, "@metamask/sdk-communication-layer>utf-8-validate": false, From 642155c6e3b2c7aa7191fd345d1c3bd851d33a91 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Mon, 9 Dec 2024 12:22:11 -0700 Subject: [PATCH 03/16] Remove duplicate pollCountLimit option --- app/core/Engine/Engine.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/core/Engine/Engine.ts b/app/core/Engine/Engine.ts index 472cdbe8e7a..8816123ddc4 100644 --- a/app/core/Engine/Engine.ts +++ b/app/core/Engine/Engine.ts @@ -1407,7 +1407,6 @@ export class Engine { fetchGasFeeEstimates: () => gasFeeController.fetchGasFeeEstimates(), // @ts-expect-error TODO: Resolve mismatch between gas fee and swaps controller types fetchEstimatedMultiLayerL1Fee, - pollCountLimit: AppConstants.SWAPS.POLL_COUNT_LIMIT, }), GasFeeController: gasFeeController, ApprovalController: approvalController, From 657e5a990e3a1b2a863e7e45923eeaa6b4c1d68a Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Mon, 9 Dec 2024 12:33:43 -0700 Subject: [PATCH 04/16] Remove node-addon-api --- package.json | 1 - yarn.lock | 5 ----- 2 files changed, 6 deletions(-) diff --git a/package.json b/package.json index b66914ad52f..41bd762df7c 100644 --- a/package.json +++ b/package.json @@ -481,7 +481,6 @@ "metro-react-native-babel-transformer": "~0.76.9", "multiple-cucumber-html-reporter": "^3.0.1", "nock": "^13.3.1", - "node-addon-api": "^8.3.0", "nyc": "^15.1.0", "octonode": "0.10.2", "patch-package": "^6.2.2", diff --git a/yarn.lock b/yarn.lock index 57e10f88a28..a2e6684fa1d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22581,11 +22581,6 @@ node-addon-api@^7.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.0.0.tgz#8136add2f510997b3b94814f4af1cce0b0e3962e" integrity sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA== -node-addon-api@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.3.0.tgz#ec3763f18befc1cdf66d11e157ce44d5eddc0603" - integrity sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg== - node-dir@^0.1.17: version "0.1.17" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" From 0028c5ec6fe87a8d15350c530e3fec3c7f18b203 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Tue, 10 Dec 2024 09:27:02 -0700 Subject: [PATCH 05/16] Attempt to delete these patches and see what happens --- patches/@react-navigation+native+5.9.4.patch | 13 ----------- patches/react-native-modal+12.1.0.patch | 24 -------------------- 2 files changed, 37 deletions(-) delete mode 100644 patches/@react-navigation+native+5.9.4.patch delete mode 100644 patches/react-native-modal+12.1.0.patch diff --git a/patches/@react-navigation+native+5.9.4.patch b/patches/@react-navigation+native+5.9.4.patch deleted file mode 100644 index 6761d4ff873..00000000000 --- a/patches/@react-navigation+native+5.9.4.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js b/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js -index 5e4f8a4..39c29eb 100644 ---- a/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js -+++ b/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js -@@ -39,7 +39,7 @@ function useLinking(ref, { - // https://github.com/facebook/react-native/commit/6d1aca806cee86ad76de771ed3a1cc62982ebcd7 - if (subscription !== null && subscription !== void 0 && subscription.remove) { - subscription.remove(); -- } else { -+ } else if ('removeEventListener' in _reactNative.Linking) { - _reactNative.Linking.removeEventListener('url', callback); - } - }; diff --git a/patches/react-native-modal+12.1.0.patch b/patches/react-native-modal+12.1.0.patch deleted file mode 100644 index 853cca2564d..00000000000 --- a/patches/react-native-modal+12.1.0.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/node_modules/react-native-modal/dist/modal.js b/node_modules/react-native-modal/dist/modal.js -index ec3cc0b..6471cfb 100644 ---- a/node_modules/react-native-modal/dist/modal.js -+++ b/node_modules/react-native-modal/dist/modal.js -@@ -448,15 +448,15 @@ export class ReactNativeModal extends React.Component { - if (this.props.onSwipe) { - console.warn('`` is deprecated and will be removed starting from 13.0.0. Use `` instead.'); - } -- DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); -+ this._didUpdateDimensionsSubscription = DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); - if (this.state.isVisible) { - this.open(); - } -- BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress); -+ this._hardwareBackPressSubscription = BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress); - } - componentWillUnmount() { -- BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPress); -- DeviceEventEmitter.removeListener('didUpdateDimensions', this.handleDimensionsUpdate); -+ this._didUpdateDimensionsSubscription.remove(); -+ this._hardwareBackPressSubscription.remove(); - if (this.interactionHandle) { - InteractionManager.clearInteractionHandle(this.interactionHandle); - this.interactionHandle = null; From cee60bb731b3941597e3e0a73c615dda0d80503c Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Tue, 10 Dec 2024 09:27:20 -0700 Subject: [PATCH 06/16] It should not be necessary to disable sharp --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 443c2fc4bc1..aa12746130d 100644 --- a/package.json +++ b/package.json @@ -564,7 +564,7 @@ "@storybook/addon-knobs>@storybook/components>react-syntax-highlighter>highlight.js": false, "@storybook/addon-knobs>core-js": false, "@wdio/cucumber-framework>@cucumber/cucumber>duration>es5-ext": false, - "appium-adb>@appium/support>sharp": false, + "appium-adb>@appium/support>sharp": true, "appium>appium-android-driver>appium-chromedriver": false, "appium>appium-base-driver>webdriverio>@types/puppeteer-core>@types/puppeteer>puppeteer": false, "appium>appium-flutter-driver>rpc-websockets>bufferutil": false, @@ -586,7 +586,7 @@ "ganache>utf-8-validate": false, "husky": false, "react-native-inappbrowser-reborn": false, - "react-native-svg-asset-plugin>sharp": false, + "react-native-svg-asset-plugin>sharp": true, "@storybook/builder-webpack5>@swc/core": false, "@metamask/sdk-communication-layer>bufferutil": false, "@metamask/sdk-communication-layer>utf-8-validate": false, From 6408c0635ad08f9408d51618cd18ab49f5898256 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Tue, 10 Dec 2024 09:57:51 -0700 Subject: [PATCH 07/16] Revert "Attempt to delete these patches and see what happens" This reverts commit 0028c5ec6fe87a8d15350c530e3fec3c7f18b203. --- patches/@react-navigation+native+5.9.4.patch | 13 +++++++++++ patches/react-native-modal+12.1.0.patch | 24 ++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 patches/@react-navigation+native+5.9.4.patch create mode 100644 patches/react-native-modal+12.1.0.patch diff --git a/patches/@react-navigation+native+5.9.4.patch b/patches/@react-navigation+native+5.9.4.patch new file mode 100644 index 00000000000..6761d4ff873 --- /dev/null +++ b/patches/@react-navigation+native+5.9.4.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js b/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js +index 5e4f8a4..39c29eb 100644 +--- a/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js ++++ b/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js +@@ -39,7 +39,7 @@ function useLinking(ref, { + // https://github.com/facebook/react-native/commit/6d1aca806cee86ad76de771ed3a1cc62982ebcd7 + if (subscription !== null && subscription !== void 0 && subscription.remove) { + subscription.remove(); +- } else { ++ } else if ('removeEventListener' in _reactNative.Linking) { + _reactNative.Linking.removeEventListener('url', callback); + } + }; diff --git a/patches/react-native-modal+12.1.0.patch b/patches/react-native-modal+12.1.0.patch new file mode 100644 index 00000000000..853cca2564d --- /dev/null +++ b/patches/react-native-modal+12.1.0.patch @@ -0,0 +1,24 @@ +diff --git a/node_modules/react-native-modal/dist/modal.js b/node_modules/react-native-modal/dist/modal.js +index ec3cc0b..6471cfb 100644 +--- a/node_modules/react-native-modal/dist/modal.js ++++ b/node_modules/react-native-modal/dist/modal.js +@@ -448,15 +448,15 @@ export class ReactNativeModal extends React.Component { + if (this.props.onSwipe) { + console.warn('`` is deprecated and will be removed starting from 13.0.0. Use `` instead.'); + } +- DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); ++ this._didUpdateDimensionsSubscription = DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); + if (this.state.isVisible) { + this.open(); + } +- BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress); ++ this._hardwareBackPressSubscription = BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress); + } + componentWillUnmount() { +- BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPress); +- DeviceEventEmitter.removeListener('didUpdateDimensions', this.handleDimensionsUpdate); ++ this._didUpdateDimensionsSubscription.remove(); ++ this._hardwareBackPressSubscription.remove(); + if (this.interactionHandle) { + InteractionManager.clearInteractionHandle(this.interactionHandle); + this.interactionHandle = null; From 1d5554f5205de105fc01f1474a580bd2c45cf918 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Tue, 10 Dec 2024 10:12:01 -0700 Subject: [PATCH 08/16] Reapply "Attempt to delete these patches and see what happens" This reverts commit 6408c0635ad08f9408d51618cd18ab49f5898256. --- patches/@react-navigation+native+5.9.4.patch | 13 ----------- patches/react-native-modal+12.1.0.patch | 24 -------------------- 2 files changed, 37 deletions(-) delete mode 100644 patches/@react-navigation+native+5.9.4.patch delete mode 100644 patches/react-native-modal+12.1.0.patch diff --git a/patches/@react-navigation+native+5.9.4.patch b/patches/@react-navigation+native+5.9.4.patch deleted file mode 100644 index 6761d4ff873..00000000000 --- a/patches/@react-navigation+native+5.9.4.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js b/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js -index 5e4f8a4..39c29eb 100644 ---- a/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js -+++ b/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js -@@ -39,7 +39,7 @@ function useLinking(ref, { - // https://github.com/facebook/react-native/commit/6d1aca806cee86ad76de771ed3a1cc62982ebcd7 - if (subscription !== null && subscription !== void 0 && subscription.remove) { - subscription.remove(); -- } else { -+ } else if ('removeEventListener' in _reactNative.Linking) { - _reactNative.Linking.removeEventListener('url', callback); - } - }; diff --git a/patches/react-native-modal+12.1.0.patch b/patches/react-native-modal+12.1.0.patch deleted file mode 100644 index 853cca2564d..00000000000 --- a/patches/react-native-modal+12.1.0.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/node_modules/react-native-modal/dist/modal.js b/node_modules/react-native-modal/dist/modal.js -index ec3cc0b..6471cfb 100644 ---- a/node_modules/react-native-modal/dist/modal.js -+++ b/node_modules/react-native-modal/dist/modal.js -@@ -448,15 +448,15 @@ export class ReactNativeModal extends React.Component { - if (this.props.onSwipe) { - console.warn('`` is deprecated and will be removed starting from 13.0.0. Use `` instead.'); - } -- DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); -+ this._didUpdateDimensionsSubscription = DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); - if (this.state.isVisible) { - this.open(); - } -- BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress); -+ this._hardwareBackPressSubscription = BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress); - } - componentWillUnmount() { -- BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPress); -- DeviceEventEmitter.removeListener('didUpdateDimensions', this.handleDimensionsUpdate); -+ this._didUpdateDimensionsSubscription.remove(); -+ this._hardwareBackPressSubscription.remove(); - if (this.interactionHandle) { - InteractionManager.clearInteractionHandle(this.interactionHandle); - this.interactionHandle = null; From b9bcce0c6e2defc4b69b8068820ccc8f7b0d9f07 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Tue, 10 Dec 2024 10:16:01 -0700 Subject: [PATCH 09/16] Bring this patch back --- patches/react-native-modal+12.1.0.patch | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 patches/react-native-modal+12.1.0.patch diff --git a/patches/react-native-modal+12.1.0.patch b/patches/react-native-modal+12.1.0.patch new file mode 100644 index 00000000000..100b619e238 --- /dev/null +++ b/patches/react-native-modal+12.1.0.patch @@ -0,0 +1,30 @@ +diff --git a/node_modules/react-native-modal/dist/modal.js b/node_modules/react-native-modal/dist/modal.js +index ec3cc0b..bed08a4 100644 +--- a/node_modules/react-native-modal/dist/modal.js ++++ b/node_modules/react-native-modal/dist/modal.js +@@ -52,6 +52,7 @@ export class ReactNativeModal extends React.Component { + // isVisible prop to false. + // We store in the state the device width and height so that we can update the modal on + // device rotation. ++ this.dimensionsUpdateListener = null; + this.state = { + showContent: true, + isVisible: false, +@@ -448,7 +449,7 @@ export class ReactNativeModal extends React.Component { + if (this.props.onSwipe) { + console.warn('`` is deprecated and will be removed starting from 13.0.0. Use `` instead.'); + } +- DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); ++ this.dimensionsUpdateListener = DeviceEventEmitter.addListener('didUpdateDimensions', this.handleDimensionsUpdate); + if (this.state.isVisible) { + this.open(); + } +@@ -456,7 +457,7 @@ export class ReactNativeModal extends React.Component { + } + componentWillUnmount() { + BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPress); +- DeviceEventEmitter.removeListener('didUpdateDimensions', this.handleDimensionsUpdate); ++ this.dimensionsUpdateListener?.remove?.(); + if (this.interactionHandle) { + InteractionManager.clearInteractionHandle(this.interactionHandle); + this.interactionHandle = null; From 1c2a362834d2efee8c146be82a949b4e2223b3e0 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Tue, 10 Dec 2024 17:14:43 -0700 Subject: [PATCH 10/16] Revert this code and see what happens --- app/components/UI/Swaps/index.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/components/UI/Swaps/index.js b/app/components/UI/Swaps/index.js index fb08e469161..d11639c137f 100644 --- a/app/components/UI/Swaps/index.js +++ b/app/components/UI/Swaps/index.js @@ -254,8 +254,6 @@ function SwapsAmountView({ }, [navigation, route, colors]); useEffect(() => { - let isStopped = false; - (async () => { try { const featureFlags = await swapsUtils.fetchSwapsFeatureFlags( @@ -263,10 +261,6 @@ function SwapsAmountView({ AppConstants.SWAPS.CLIENT_ID, ); - if (isStopped) { - return; - } - const liveness = getSwapsLiveness(featureFlags, chainId); setLiveness(chainId, featureFlags); @@ -296,10 +290,6 @@ function SwapsAmountView({ navigation.pop(); } })(); - - return () => { - isStopped = true; - }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [initialSource, chainId, navigation, setLiveness]); From 7c32a0ef2eef7e168b08cbfb45f37ce34c9d4c9c Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Thu, 12 Dec 2024 13:57:15 -0700 Subject: [PATCH 11/16] Fix fetching quotes on Optimism --- app/util/networks/engineNetworkUtils.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/util/networks/engineNetworkUtils.ts b/app/util/networks/engineNetworkUtils.ts index e093fd80e5a..e6e9e29c28c 100644 --- a/app/util/networks/engineNetworkUtils.ts +++ b/app/util/networks/engineNetworkUtils.ts @@ -1,6 +1,7 @@ import Engine from '../../core/Engine'; import { convertHexToDecimal } from '@metamask/controller-utils'; -import { TransactionMeta } from '@metamask/transaction-controller'; +import { NetworkClientId } from '@metamask/network-controller'; +import { TransactionMeta, TransactionParams } from '@metamask/transaction-controller'; import { isStrictHexString } from '@metamask/utils'; /** @@ -42,14 +43,15 @@ export function toggleUseSafeChainsListValidation(value: boolean): void { */ export const fetchEstimatedMultiLayerL1Fee = async ( _: unknown, - txMeta: TransactionMeta, + { txParams, networkClientId }: { + txParams: TransactionParams, + networkClientId: NetworkClientId, + } ) => { - const chainId = txMeta.chainId; - const layer1GasFee = await Engine.context.TransactionController.getLayer1GasFee({ - transactionParams: txMeta.txParams, - chainId, + transactionParams: txParams, + networkClientId, }); const layer1GasFeeNoPrefix = layer1GasFee?.startsWith('0x') From 3ed887b48cd73ba8930ff18bb825431e511ed344 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Thu, 12 Dec 2024 13:58:12 -0700 Subject: [PATCH 12/16] Fix lint violation --- app/util/networks/engineNetworkUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/util/networks/engineNetworkUtils.ts b/app/util/networks/engineNetworkUtils.ts index e6e9e29c28c..65391429710 100644 --- a/app/util/networks/engineNetworkUtils.ts +++ b/app/util/networks/engineNetworkUtils.ts @@ -1,7 +1,7 @@ import Engine from '../../core/Engine'; import { convertHexToDecimal } from '@metamask/controller-utils'; import { NetworkClientId } from '@metamask/network-controller'; -import { TransactionMeta, TransactionParams } from '@metamask/transaction-controller'; +import { TransactionParams } from '@metamask/transaction-controller'; import { isStrictHexString } from '@metamask/utils'; /** From 3b9fc3d337dd098bd1e7cffbb38a40c8404f7ce1 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Thu, 12 Dec 2024 13:58:50 -0700 Subject: [PATCH 13/16] Fix another lint violation --- app/core/Engine/Engine.ts | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/app/core/Engine/Engine.ts b/app/core/Engine/Engine.ts index 3adcbbb853b..44874c783c0 100644 --- a/app/core/Engine/Engine.ts +++ b/app/core/Engine/Engine.ts @@ -317,6 +317,12 @@ export class Engine { }, }); + // eslint-disable-next-line no-console + console.log( + 'initial network controller state', + initialState.NetworkController, + ); + const networkControllerOpts = { infuraProjectId: process.env.MM_INFURA_PROJECT_ID || NON_EMPTY, state: initialState.NetworkController, @@ -971,8 +977,8 @@ export class Engine { disableSnaps: !isBasicFunctionalityToggleEnabled(), }), clientCryptography: { - pbkdf2Sha512: pbkdf2 - } + pbkdf2Sha512: pbkdf2, + }, }); const authenticationController = new AuthenticationController.Controller({ @@ -1302,7 +1308,9 @@ export class Engine { .addProperties({ token_standard: 'ERC20', asset_type: 'token', - chain_id: getDecimalChainId(getGlobalChainId(networkController)), + chain_id: getDecimalChainId( + getGlobalChainId(networkController), + ), }) .build(), ), @@ -1410,7 +1418,6 @@ export class Engine { pollCountLimit: AppConstants.SWAPS.POLL_COUNT_LIMIT, // TODO: Remove once GasFeeController exports this action type fetchGasFeeEstimates: () => gasFeeController.fetchGasFeeEstimates(), - // @ts-expect-error TODO: Resolve mismatch between gas fee and swaps controller types fetchEstimatedMultiLayerL1Fee, }), GasFeeController: gasFeeController, @@ -1515,7 +1522,7 @@ export class Engine { if ( state.networksMetadata[state.selectedNetworkClientId].status === NetworkStatus.Available && - getGlobalChainId(networkController) !== currentChainId + getGlobalChainId(networkController) !== currentChainId ) { // We should add a state or event emitter saying the provider changed setTimeout(() => { @@ -1535,7 +1542,9 @@ export class Engine { } catch (error) { console.error( error, - `Network ID not changed, current chainId: ${getGlobalChainId(networkController)}`, + `Network ID not changed, current chainId: ${getGlobalChainId( + networkController, + )}`, ); } }, From 24e1a95ff3fdd65d173d3a5122c82af5c5e39e87 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Thu, 12 Dec 2024 14:14:34 -0700 Subject: [PATCH 14/16] TEMP - Remove Goerli and Linea Goerli from state to prevent bad requests --- app/core/Engine/Engine.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/app/core/Engine/Engine.ts b/app/core/Engine/Engine.ts index 44874c783c0..33a9a09a8dd 100644 --- a/app/core/Engine/Engine.ts +++ b/app/core/Engine/Engine.ts @@ -159,7 +159,7 @@ import { AccountsControllerMessenger } from '@metamask/accounts-controller'; import { createAccountsController } from './controllers/AccountsController/utils'; import { createRemoteFeatureFlagController } from './controllers/RemoteFeatureFlagController'; import { captureException } from '@sentry/react-native'; -import { lowerCase } from 'lodash'; +import { lowerCase, omit } from 'lodash'; import { networkIdUpdated, networkIdWillUpdate, @@ -317,15 +317,23 @@ export class Engine { }, }); + // Remove Goerli and Linea Goerli from NetworkController state to prevent + // repeated failure messages from the block tracker + const initialNetworkControllerState = initialState.NetworkController + ? { + ...initialState.NetworkController, + networkConfigurationsByChainId: omit( + initialState.NetworkController.networkConfigurationsByChainId, + ['0x5', '0xe704'], + ), + } + : undefined; // eslint-disable-next-line no-console - console.log( - 'initial network controller state', - initialState.NetworkController, - ); + console.dir(initialNetworkControllerState); const networkControllerOpts = { infuraProjectId: process.env.MM_INFURA_PROJECT_ID || NON_EMPTY, - state: initialState.NetworkController, + state: initialNetworkControllerState, messenger: this.controllerMessenger.getRestricted({ name: 'NetworkController', allowedEvents: [], From e7c3256c072897aeb3a59388cc02c7a49d02bc83 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Thu, 12 Dec 2024 14:27:15 -0700 Subject: [PATCH 15/16] fixup! 24e1a95ff3fdd65d173d3a5122c82af5c5e39e87 --- app/core/Engine/Engine.test.ts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/app/core/Engine/Engine.test.ts b/app/core/Engine/Engine.test.ts index 5af5d8965c8..cf91440cd62 100644 --- a/app/core/Engine/Engine.test.ts +++ b/app/core/Engine/Engine.test.ts @@ -132,18 +132,12 @@ describe('Engine', () => { [selectedAddress]: { balance: (ethBalance * 1e18).toString() }, }, }, - NetworkController: { - state: { - ...mockNetworkState({ - chainId: '0x1', - id: '0x1', - nickname: 'mainnet', - ticker: 'ETH', - }), - }, - // TODO(dbrans): Investigate why the shape of the NetworkController state in this - // test is {state: NetworkState} instead of just NetworkState. - } as unknown as NetworkState, + NetworkController: mockNetworkState({ + chainId: '0x1', + id: '0x1', + nickname: 'mainnet', + ticker: 'ETH', + }), CurrencyRateController: { currencyRates: { [ticker]: { From d235bd1f3606b4a2074c909ad0d6ee03ba614d32 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Thu, 12 Dec 2024 14:33:28 -0700 Subject: [PATCH 16/16] fixup! 24e1a95ff3fdd65d173d3a5122c82af5c5e39e87 --- app/core/Engine/Engine.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/core/Engine/Engine.test.ts b/app/core/Engine/Engine.test.ts index cf91440cd62..a261e484232 100644 --- a/app/core/Engine/Engine.test.ts +++ b/app/core/Engine/Engine.test.ts @@ -8,7 +8,6 @@ import { mockNetworkState } from '../../util/test/network'; import MetaMetrics from '../Analytics/MetaMetrics'; import { store } from '../../store'; import { MetaMetricsEvents } from '../Analytics'; -import { NetworkState } from '@metamask/network-controller'; import { Hex } from '@metamask/utils'; import { TransactionMeta } from '@metamask/transaction-controller'; import { RootState } from '../../reducers';