diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d1f88c2542a..d976967c2033 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -369,8 +369,6 @@ jobs: - name: Generate iOS bundle run: yarn gen-bundle:ios - env: - NODE_OPTIONS: --max_old_space_size=12288 - name: Check bundle size run: ./scripts/js-bundle-stats.sh ios/main.jsbundle 52 @@ -557,13 +555,13 @@ jobs: echo "Android E2E tests failed (result: $ANDROID_RESULT)" exit 1 fi - + IOS_RESULT="${{ needs.e2e-smoke-tests-ios.result }}" if [[ "$IOS_RESULT" == "failure" ]] || [[ "$IOS_RESULT" == "cancelled" ]]; then echo "iOS E2E tests failed (result: $IOS_RESULT)" exit 1 fi - + FLASK_RESULT="${{ needs.e2e-smoke-tests-android-flask.result }}" if [[ "$FLASK_RESULT" == "failure" ]] || [[ "$FLASK_RESULT" == "cancelled" ]]; then echo "Android Flask E2E tests failed (result: $FLASK_RESULT)" diff --git a/.github/workflows/release-pr-approval.yml b/.github/workflows/release-pr-approval.yml index 4ffaa35af8f1..771b93ddbd5a 100644 --- a/.github/workflows/release-pr-approval.yml +++ b/.github/workflows/release-pr-approval.yml @@ -1,7 +1,6 @@ name: Release PR Approval on: - pull_request: pull_request_review: types: [submitted] diff --git a/.yarn/patches/@metamask-react-native-webview-npm-14.5.0-b34fed6d50.patch b/.yarn/patches/@metamask-react-native-webview-npm-14.5.0-b34fed6d50.patch index f6f965cf2478..edb394837512 100644 --- a/.yarn/patches/@metamask-react-native-webview-npm-14.5.0-b34fed6d50.patch +++ b/.yarn/patches/@metamask-react-native-webview-npm-14.5.0-b34fed6d50.patch @@ -152,3 +152,29 @@ index d1459423fe85502017d2b424f61718ce1ae082b1..7fda7cf056af3e7e8904a0e2aa3391dc } if (!pendingPermissions.isEmpty()) { +diff --git a/apple/RNCWebViewImpl.m b/apple/RNCWebViewImpl.m +index c3bb7cc41097a39964b56386dbde321f7d52b35a..ebbb771d6bba6182e03f3c96ae8c9ab6514bd4f9 100644 +--- a/apple/RNCWebViewImpl.m ++++ b/apple/RNCWebViewImpl.m +@@ -973,11 +973,20 @@ -(void)setKeyboardDisplayRequiresUserAction:(BOOL)keyboardDisplayRequiresUserAct + } + + - (void)downloadBase64File:(NSString *)base64String { ++ // Infer file extension from the data: URL before doing any heavy work. ++ // For generic application/octet-stream payloads we suppress the download ++ // entirely (no "Do you want to download File.bin?" alert), since these ++ // are typically iframe-driven noise rather than user‑initiated downloads. ++ NSString *fileExtension = [self fileExtensionFromBase64String:base64String]; ++ if ([[fileExtension lowercaseString] isEqualToString:@"bin"]) { ++ NSLog(@"RNCWebViewImpl: Ignoring generic binary download (File.bin) from data: URL"); ++ return; ++ } ++ + NSArray *components = [base64String componentsSeparatedByString:@","]; + NSString *base64ContentPart = components.lastObject; + + NSData *fileData = [[NSData alloc] initWithBase64EncodedString:base64ContentPart options:NSDataBase64DecodingIgnoreUnknownCharacters]; +- NSString *fileExtension = [self fileExtensionFromBase64String:base64String]; + [self showDownloadAlert:fileExtension invokeDownload:^{ + NSString *tempFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"File.%@", fileExtension]]; + [fileData writeToFile:tempFilePath atomically:YES]; diff --git a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx index 7d31aa888456..daef84999913 100644 --- a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx +++ b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx @@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react'; import { Pressable, View } from 'react-native'; import { strings } from '../../../../locales/i18n'; -import InfoModal from '../../../components/UI/Swaps/components/InfoModal'; +import InfoModal from '../../../components/Base/InfoModal'; import { TOKEN_APPROVAL_SPENDING_CAP } from '../../../constants/urls'; import formatNumber from '../../../util/formatNumber'; import { isNumber } from '../../../util/number'; diff --git a/app/components/Base/InfoModal.test.tsx b/app/components/Base/InfoModal.test.tsx new file mode 100644 index 000000000000..54f41d11c2c1 --- /dev/null +++ b/app/components/Base/InfoModal.test.tsx @@ -0,0 +1,210 @@ +import React from 'react'; +import { render, fireEvent } from '@testing-library/react-native'; +import InfoModal from './InfoModal'; + +// Mock IonicIcon +jest.mock('react-native-vector-icons/Ionicons', () => 'Icon'); + +// Mock react-native-modal +jest.mock('react-native-modal', () => { + const MockedModal = ({ + isVisible, + children, + }: { + isVisible?: boolean; + children?: React.ReactNode; + [key: string]: unknown; + }) => { + if (!isVisible) return null; + return <>{children}; + }; + return MockedModal; +}); + +// Mock Base/Text component +jest.mock('./Text', () => { + /* eslint-disable @typescript-eslint/no-shadow */ + const React = jest.requireActual('react'); + const { Text: RNText } = jest.requireActual('react-native'); + /* eslint-enable @typescript-eslint/no-shadow */ + return { + __esModule: true, + default: (props: { children?: React.ReactNode; [key: string]: unknown }) => + React.createElement(RNText, props, props.children), + }; +}); + +// Mock Base/Title component +jest.mock('./Title', () => { + /* eslint-disable @typescript-eslint/no-shadow */ + const React = jest.requireActual('react'); + const { Text: RNText } = jest.requireActual('react-native'); + /* eslint-enable @typescript-eslint/no-shadow */ + return { + __esModule: true, + default: (props: { children?: React.ReactNode; [key: string]: unknown }) => + React.createElement(RNText, props, props.children), + }; +}); + +// Mock useTheme hook +jest.mock('../../util/theme', () => ({ + useTheme: jest.fn(() => ({ + colors: { + background: { default: '#FFFFFF' }, + text: { default: '#000000' }, + overlay: { default: '#00000099' }, + }, + shadows: { + size: { + sm: { + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.1, + shadowRadius: 4, + }, + }, + }, + })), +})); + +describe('InfoModal', () => { + const mockToggleModal = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('Rendering', () => { + it('renders content when visible', () => { + const { queryByText } = render( + , + ); + + expect(queryByText('Test Title')).toBeOnTheScreen(); + }); + + it('hides content when not visible', () => { + const { queryByText } = render( + , + ); + + expect(queryByText('Test Title')).toBeNull(); + }); + + it('renders title as string', () => { + const { getByText } = render( + , + ); + + expect(getByText('String Title')).toBeOnTheScreen(); + }); + + it('renders title as ReactNode', () => { + const { getByText } = render( + ReactNode Title} + toggleModal={mockToggleModal} + />, + ); + + expect(getByText('ReactNode Title')).toBeOnTheScreen(); + }); + + it('renders body as ReactNode', () => { + const { Text: RNText } = jest.requireActual('react-native'); + + const { getByText } = render( + Body Content} + toggleModal={mockToggleModal} + />, + ); + + expect(getByText('Body Content')).toBeOnTheScreen(); + }); + + it('renders message text', () => { + const { getByText } = render( + , + ); + + expect(getByText('Test message')).toBeOnTheScreen(); + }); + + it('renders urlText link when provided with message', () => { + const { getByText } = render( + , + ); + + expect(getByText('Learn more')).toBeOnTheScreen(); + }); + + it('renders complete modal with all props', () => { + const mockUrlCallback = jest.fn(); + const { Text: RNText } = jest.requireActual('react-native'); + + const { getByText } = render( + Full Body} + message="Full Message" + urlText="Full Link" + url={mockUrlCallback} + toggleModal={mockToggleModal} + propagateSwipe + testID="full-modal" + />, + ); + + expect(getByText('Full Title')).toBeOnTheScreen(); + expect(getByText('Full Body')).toBeOnTheScreen(); + expect(getByText('Full Message')).toBeOnTheScreen(); + expect(getByText('Full Link')).toBeOnTheScreen(); + }); + }); + + describe('Interactions', () => { + it('calls url callback when link is pressed', () => { + const mockUrlCallback = jest.fn(); + + const { getByText } = render( + , + ); + + fireEvent.press(getByText('Click here')); + + expect(mockUrlCallback).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/app/components/UI/Swaps/components/InfoModal.tsx b/app/components/Base/InfoModal.tsx similarity index 96% rename from app/components/UI/Swaps/components/InfoModal.tsx rename to app/components/Base/InfoModal.tsx index 649df653a1d6..d57df3aff2f9 100644 --- a/app/components/UI/Swaps/components/InfoModal.tsx +++ b/app/components/Base/InfoModal.tsx @@ -2,9 +2,9 @@ import React from 'react'; import { StyleSheet, View, TouchableOpacity, SafeAreaView } from 'react-native'; import Modal from 'react-native-modal'; import IonicIcon from 'react-native-vector-icons/Ionicons'; -import Text from '../../../Base/Text'; -import Title from '../../../Base/Title'; -import { useTheme } from '../../../../util/theme'; +import Text from './Text'; +import Title from './Title'; +import { useTheme } from '../../util/theme'; import { Theme } from '@metamask/design-tokens'; const createStyles = (colors: Theme['colors'], shadows: Theme['shadows']) => diff --git a/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.tsx b/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.tsx index 40cea9dd2d94..a48cb51e3c01 100644 --- a/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.tsx +++ b/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.tsx @@ -13,7 +13,7 @@ import { decodeTransferData } from '../../../util/transactions'; import { doENSReverseLookup } from '../../../util/ENSUtils'; import { areAddressesEqual, toFormattedAddress } from '../../../util/address'; import { useTheme } from '../../../util/theme'; -import InfoModal from '../Swaps/components/InfoModal'; +import InfoModal from '../../Base/InfoModal'; import useExistingAddress from '../../hooks/useExistingAddress'; import { AddressTo } from '../AddressInputs'; import createStyles from './AccountFromToInfoCard.styles'; diff --git a/app/components/UI/EditGasFee1559/index.js b/app/components/UI/EditGasFee1559/index.js index dace7a839c79..797caeab3582 100644 --- a/app/components/UI/EditGasFee1559/index.js +++ b/app/components/UI/EditGasFee1559/index.js @@ -11,7 +11,7 @@ import Text from '../../Base/Text'; import StyledButton from '../StyledButton'; import RangeInput from '../../Base/RangeInput'; import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons'; -import InfoModal from '../Swaps/components/InfoModal'; +import InfoModal from '../../Base/InfoModal'; import Icon from 'react-native-vector-icons/Ionicons'; import { strings } from '../../../../locales/i18n'; import Alert, { AlertType } from '../../Base/Alert'; diff --git a/app/components/UI/EditGasFeeLegacy/index.js b/app/components/UI/EditGasFeeLegacy/index.js index b26d0a25e308..f4920d400b4b 100644 --- a/app/components/UI/EditGasFeeLegacy/index.js +++ b/app/components/UI/EditGasFeeLegacy/index.js @@ -14,7 +14,7 @@ import Text from '../../Base/Text'; import StyledButton from '../StyledButton'; import RangeInput from '../../Base/RangeInput'; import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons'; -import InfoModal from '../Swaps/components/InfoModal'; +import InfoModal from '../../Base/InfoModal'; import Icon from 'react-native-vector-icons/Ionicons'; import { strings } from '../../../../locales/i18n'; import Alert, { AlertType } from '../../Base/Alert'; diff --git a/app/components/UI/Swaps/QuotesView.js b/app/components/UI/Swaps/QuotesView.js index 8be464b4648e..625de4d74325 100644 --- a/app/components/UI/Swaps/QuotesView.js +++ b/app/components/UI/Swaps/QuotesView.js @@ -67,7 +67,7 @@ import Ratio from './components/Ratio'; import ActionAlert from './components/ActionAlert'; import ApprovalTransactionEditionModal from './components/ApprovalTransactionEditionModal'; import GasEditModal from './components/GasEditModal'; -import InfoModal from './components/InfoModal'; +import InfoModal from '../../Base/InfoModal'; import useModalHandler from '../../Base/hooks/useModalHandler'; import useBalance from './utils/useBalance'; import { decodeApproveData, getTicker } from '../../../util/transactions'; diff --git a/app/components/UI/Swaps/components/AssetSwapButton.js b/app/components/UI/Swaps/components/AssetSwapButton.js index 591865658abb..91681814fd57 100644 --- a/app/components/UI/Swaps/components/AssetSwapButton.js +++ b/app/components/UI/Swaps/components/AssetSwapButton.js @@ -4,7 +4,7 @@ import { StyleSheet, View } from 'react-native'; import Text from '../../../Base/Text'; import AssetActionButton from '../../AssetOverview/AssetActionButton'; -import InfoModal from './InfoModal'; +import InfoModal from '../../../Base/InfoModal'; import useModalHandler from '../../../Base/hooks/useModalHandler'; import { strings } from '../../../../../locales/i18n'; diff --git a/app/components/UI/Swaps/components/GasEditModal.js b/app/components/UI/Swaps/components/GasEditModal.js index 2e0a48aaf951..8de1d13e3504 100644 --- a/app/components/UI/Swaps/components/GasEditModal.js +++ b/app/components/UI/Swaps/components/GasEditModal.js @@ -8,7 +8,7 @@ import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIc import { connect } from 'react-redux'; import Text from '../../../Base/Text'; -import InfoModal from './InfoModal'; +import InfoModal from '../../../Base/InfoModal'; import EditGasFeeLegacy from '../../EditGasFeeLegacy'; import EditGasFee1559 from '../../EditGasFee1559'; import { diff --git a/app/components/UI/Swaps/index.js b/app/components/UI/Swaps/index.js index 0cdcf84ab720..bb6e7c71af1a 100644 --- a/app/components/UI/Swaps/index.js +++ b/app/components/UI/Swaps/index.js @@ -62,7 +62,7 @@ import TokenSelectModal from './components/TokenSelectModal'; import SlippageModal from './components/SlippageModal'; import useBalance from './utils/useBalance'; import useBlockExplorer from './utils/useBlockExplorer'; -import InfoModal from './components/InfoModal'; +import InfoModal from '../../Base/InfoModal'; import { AlertType } from '../../Base/Alert'; import { isZero, gte } from '../../../util/lodash'; import { useTheme } from '../../../util/theme'; diff --git a/app/components/UI/TimeEstimateInfoModal/index.js b/app/components/UI/TimeEstimateInfoModal/index.js index 08fe89800d36..69d69b2651c0 100644 --- a/app/components/UI/TimeEstimateInfoModal/index.js +++ b/app/components/UI/TimeEstimateInfoModal/index.js @@ -1,7 +1,7 @@ import React from 'react'; import { View } from 'react-native'; import Text from '../../Base/Text'; -import InfoModal from '../Swaps/components/InfoModal'; +import InfoModal from '../../Base/InfoModal'; import PropTypes from 'prop-types'; import { strings } from '../../../../locales/i18n'; import AppConstants from '../../../core/AppConstants'; diff --git a/app/components/Views/NetworkSelector/NetworkSelector.tsx b/app/components/Views/NetworkSelector/NetworkSelector.tsx index 8e654132c180..21a14941ada6 100644 --- a/app/components/Views/NetworkSelector/NetworkSelector.tsx +++ b/app/components/Views/NetworkSelector/NetworkSelector.tsx @@ -60,7 +60,7 @@ import { // Internal dependencies import createStyles from './NetworkSelector.styles'; import { InfuraNetworkType } from '@metamask/controller-utils'; -import InfoModal from '../../../../app/components/UI/Swaps/components/InfoModal'; +import InfoModal from '../../Base/InfoModal'; import hideKeyFromUrl from '../../../util/hideKeyFromUrl'; import CustomNetwork from '../Settings/NetworksSettings/NetworkSettings/CustomNetworkView/CustomNetwork'; import { NetworksSelectorSelectorsIDs } from '../../../../e2e/selectors/Settings/NetworksView.selectors'; diff --git a/app/components/Views/NetworkSelector/__snapshots__/NetworkSelector.test.tsx.snap b/app/components/Views/NetworkSelector/__snapshots__/NetworkSelector.test.tsx.snap index 0cc0cf38c055..6935c6352b99 100644 --- a/app/components/Views/NetworkSelector/__snapshots__/NetworkSelector.test.tsx.snap +++ b/app/components/Views/NetworkSelector/__snapshots__/NetworkSelector.test.tsx.snap @@ -4791,6 +4791,133 @@ exports[`Network Selector renders correctly when network UI redesign is enabled + + + + + + + + + + MegaEth + + + + + + Add + + + { + const switchNativeCurrencyDisplayOptions = (nativeValue, fiatValue) => { if (nativeCurrencySelected) return nativeValue; return fiatValue; }; const valueToWatch = `${renderableGasFeeMinNative}${renderableGasFeeMaxNative}`; - const LeftLabelComponent = ({ - value, - infoValue, - }) => ( + const LeftLabelComponent = ({ value, infoValue }) => ( {strings(value)} @@ -383,10 +380,7 @@ const EditGasFee1559Update = ({ ); - const TextComponent = ({ - title, - value, - }) => ( + const TextComponent = ({ title, value }) => ( <> {strings(title)} @@ -717,12 +711,12 @@ const EditGasFee1559Update = ({ modalInfo.value === 'gas_limit' ? strings('edit_gas_fee_eip1559.gas_limit') : modalInfo.value === 'max_priority_fee' - ? strings('edit_gas_fee_eip1559.max_priority_fee') - : modalInfo.value === 'max_fee' - ? strings('edit_gas_fee_eip1559.max_fee') - : modalInfo.value === 'new_gas_fee' - ? strings('edit_gas_fee_eip1559.new_gas_fee') - : null + ? strings('edit_gas_fee_eip1559.max_priority_fee') + : modalInfo.value === 'max_fee' + ? strings('edit_gas_fee_eip1559.max_fee') + : modalInfo.value === 'new_gas_fee' + ? strings('edit_gas_fee_eip1559.new_gas_fee') + : null } toggleModal={() => updateModalInfo({ ...modalInfo, isVisible: false }) diff --git a/app/components/Views/confirmations/legacy/components/EditGasFeeLegacyUpdate/index.jsx b/app/components/Views/confirmations/legacy/components/EditGasFeeLegacyUpdate/index.jsx index 4a5948a9e223..9accc36dd6c6 100644 --- a/app/components/Views/confirmations/legacy/components/EditGasFeeLegacyUpdate/index.jsx +++ b/app/components/Views/confirmations/legacy/components/EditGasFeeLegacyUpdate/index.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ /* eslint-disable react/display-name */ import { GAS_ESTIMATE_TYPES } from '@metamask/gas-fee-controller'; import BigNumber from 'bignumber.js'; @@ -38,7 +39,7 @@ import RangeInput from '../../../../../Base/RangeInput'; import { useMetrics } from '../../../../../hooks/useMetrics'; import FadeAnimationView from '../../../../../UI/FadeAnimationView'; import StyledButton from '../../../../../UI/StyledButton'; -import InfoModal from '../../../../../UI/Swaps/components/InfoModal'; +import InfoModal from '../../../../../Base/InfoModal'; import createStyles from './styles'; const EditGasFeeLegacy = ({ @@ -231,8 +232,7 @@ const EditGasFeeLegacy = ({ const isMainnet = isMainnetByChainId(chainId); const nativeCurrencySelected = primaryCurrency === 'ETH' || !isMainnet; - let gasFeePrimary, - gasFeeSecondary; + let gasFeePrimary, gasFeeSecondary; if (nativeCurrencySelected) { gasFeePrimary = transactionFee; gasFeeSecondary = transactionFeeFiat; @@ -393,8 +393,8 @@ const EditGasFeeLegacy = ({ infoText === 'gas_limit' ? strings('edit_gas_fee_eip1559.gas_limit') : infoText === 'gas_price' - ? strings('edit_gas_fee_eip1559.gas_price') - : null + ? strings('edit_gas_fee_eip1559.gas_price') + : null } toggleModal={() => setShowRangeInfoModal(false)} body={ diff --git a/app/components/Views/confirmations/legacy/components/TransactionReview/TransactionReviewEIP1559/index.js b/app/components/Views/confirmations/legacy/components/TransactionReview/TransactionReviewEIP1559/index.js index ad6da0ef31e5..707d959df17e 100644 --- a/app/components/Views/confirmations/legacy/components/TransactionReview/TransactionReviewEIP1559/index.js +++ b/app/components/Views/confirmations/legacy/components/TransactionReview/TransactionReviewEIP1559/index.js @@ -8,7 +8,7 @@ import { isTestNet, } from '../../../../../../../util/networks'; import PropTypes from 'prop-types'; -import InfoModal from '../../../../../../UI/Swaps/components/InfoModal'; +import InfoModal from '../../../../../../Base/InfoModal'; import FadeAnimationView from '../../../../../../UI/FadeAnimationView'; import SkeletonPlaceholder from 'react-native-skeleton-placeholder'; import { strings } from '../../../../../../../../locales/i18n'; diff --git a/app/components/Views/confirmations/legacy/components/TransactionReview/TransactionReviewEIP1559Update/index.jsx b/app/components/Views/confirmations/legacy/components/TransactionReview/TransactionReviewEIP1559Update/index.jsx index 24d6b8ab93ab..159150af9461 100644 --- a/app/components/Views/confirmations/legacy/components/TransactionReview/TransactionReviewEIP1559Update/index.jsx +++ b/app/components/Views/confirmations/legacy/components/TransactionReview/TransactionReviewEIP1559Update/index.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { useCallback, useEffect, useState } from 'react'; import { Linking, TouchableOpacity, View } from 'react-native'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; @@ -15,7 +16,7 @@ import useModalHandler from '../../../../../../Base/hooks/useModalHandler'; import Summary from '../../../../../../Base/Summary'; import Text from '../../../../../../Base/Text'; import FadeAnimationView from '../../../../../../UI/FadeAnimationView'; -import InfoModal from '../../../../../../UI/Swaps/components/InfoModal'; +import InfoModal from '../../../../../../Base/InfoModal'; import TimeEstimateInfoModal from '../../../../../../UI/TimeEstimateInfoModal'; import SkeletonComponent from './skeletonComponent'; import createStyles from './styles'; diff --git a/app/images/megaeth-mainnet-logo.png b/app/images/megaeth-mainnet-logo.png index d89c1d851469..2abc2a3f9f4d 100644 Binary files a/app/images/megaeth-mainnet-logo.png and b/app/images/megaeth-mainnet-logo.png differ diff --git a/app/util/networks/customNetworks.test.ts b/app/util/networks/customNetworks.test.ts index 3b001ce8ca3a..6db27dfc0dee 100644 --- a/app/util/networks/customNetworks.test.ts +++ b/app/util/networks/customNetworks.test.ts @@ -21,6 +21,7 @@ describe('popularNetwork', () => { Sei: toHex('1329'), Monad: toHex('143'), HyperEVM: toHex('999'), + MegaEth: toHex('4326'), }; PopularList.forEach((rpc) => { diff --git a/app/util/networks/customNetworks.tsx b/app/util/networks/customNetworks.tsx index 08deef6f1d1e..d10619a36656 100644 --- a/app/util/networks/customNetworks.tsx +++ b/app/util/networks/customNetworks.tsx @@ -175,6 +175,19 @@ export const PopularList = [ imageSource: require('../../images/monad-mainnet-logo.png'), }, }, + { + chainId: toHex('4326'), + nickname: 'MegaEth', + rpcUrl: `https://mainnet.megaeth.com/rpc`, + failoverRpcUrls: [], + ticker: 'ETH', + warning: true, + rpcPrefs: { + blockExplorerUrl: 'https://explorer.megaeth.com', + imageUrl: 'MEGAETH', + imageSource: require('../../images/megaeth-mainnet-logo.png'), + }, + }, ]; /** diff --git a/app/util/networks/index.js b/app/util/networks/index.js index a945a16910f7..7a9ca789b5a9 100644 --- a/app/util/networks/index.js +++ b/app/util/networks/index.js @@ -680,15 +680,18 @@ export const WHILELIST_NETWORK_NAME = { [ChainId['monad-testnet']]: 'Monad Testnet', [NETWORKS_CHAIN_ID.SEI]: 'Sei Mainnet', [NETWORKS_CHAIN_ID.HYPER_EVM]: 'HyperEVM', + [NETWORKS_CHAIN_ID.MEGAETH_MAINNET]: 'MegaEth', }; // Whitelisted symbols for specific chain IDs to prevent showing warnings on Network Settings. export const WHITELIST_SYMBOL = { [NETWORKS_CHAIN_ID.HYPER_EVM]: 'HYPE', + [NETWORKS_CHAIN_ID.MEGAETH_MAINNET]: 'ETH', }; export const WHITELIST_NETWORK_RPC_URL = { [NETWORKS_CHAIN_ID.HYPER_EVM]: 'https://rpc.hyperliquid.xyz', + [NETWORKS_CHAIN_ID.MEGAETH_MAINNET]: 'https://mainnet.megaeth.com/rpc', }; /** diff --git a/metro.config.js b/metro.config.js index c583c375b4f1..201ac39f9cbb 100644 --- a/metro.config.js +++ b/metro.config.js @@ -49,9 +49,14 @@ module.exports = function (baseConfig) { // For less powerful machines, leave room to do other tasks. For instance, // if you have 10 cores but only 16GB, only 3 workers would get used. + // Also forces maxWorkers value to be no less than 2, ensuring + // worker code runs concurrently and not on the main Metro process const maxWorkers = Math.ceil( - os.availableParallelism() * - Math.min(1, os.totalmem() / (64 * 1024 * 1024 * 1024)), + Math.max( + 2, + os.availableParallelism() * + Math.min(1, os.totalmem() / (64 * 1024 * 1024 * 1024)), + ), ); return wrapWithReanimatedMetroConfig( diff --git a/yarn.lock b/yarn.lock index 7146d5fddf94..58723da5ac5f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9357,14 +9357,14 @@ __metadata: "@metamask/react-native-webview@patch:@metamask/react-native-webview@npm%3A14.5.0#~/.yarn/patches/@metamask-react-native-webview-npm-14.5.0-b34fed6d50.patch": version: 14.5.0 - resolution: "@metamask/react-native-webview@patch:@metamask/react-native-webview@npm%3A14.5.0#~/.yarn/patches/@metamask-react-native-webview-npm-14.5.0-b34fed6d50.patch::version=14.5.0&hash=c64f43" + resolution: "@metamask/react-native-webview@patch:@metamask/react-native-webview@npm%3A14.5.0#~/.yarn/patches/@metamask-react-native-webview-npm-14.5.0-b34fed6d50.patch::version=14.5.0&hash=c6e87d" dependencies: escape-string-regexp: "npm:^4.0.0" invariant: "npm:2.2.4" peerDependencies: react: "*" react-native: "*" - checksum: 10/ea801ba7e33c39df045bbe6dd882792b96b89f32b391c7a46c1a2878a5987f275549682b308c7014fba46fc07d1c5605b0499c0425d21076c98f65bb4bb56b05 + checksum: 10/f22bae5e15763e77ec0e21f34b31d97a48fadb35590a5e75341c93b269cbdb702fcafb4bd7d4b9041977ca525b03b49b558a3800126faadf08e64b8787fb1cb3 languageName: node linkType: hard