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