diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 9ec138eac03..c16354f54e9 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -2,6 +2,8 @@
# Each line is a file pattern followed by one or more owners.
* @MetaMask/mobile-devs
-app/component-library/ @MetaMask/design-system-engineers
-app/components/UI/Ramp/ @MetaMask/ramp
-app/reducers/fiatOrders/ @MetaMask/ramp
+app/component-library/ @MetaMask/design-system-engineers @MetaMask/mobile-platform
+patches/ @MetaMask/mobile-platform
+bitrise.yml @MetaMask/mobile-platform
+app/components/UI/Ramp/ @MetaMask/ramp @MetaMask/mobile-platform
+app/reducers/fiatOrders/ @MetaMask/ramp @MetaMask/mobile-platform
diff --git a/app/components/UI/NetworkVerificationInfo/NetworkVerificationInfo.test.tsx b/app/components/UI/NetworkVerificationInfo/NetworkVerificationInfo.test.tsx
index 45b0b9f28dc..937e1d3f9c3 100644
--- a/app/components/UI/NetworkVerificationInfo/NetworkVerificationInfo.test.tsx
+++ b/app/components/UI/NetworkVerificationInfo/NetworkVerificationInfo.test.tsx
@@ -7,7 +7,7 @@ import { useSelector } from 'react-redux';
const mockNetworkInfo = {
chainName: 'Test Chain',
- chainId: '1',
+ chainId: '0xa',
rpcUrl: 'http://test.com',
ticker: 'TEST',
blockExplorerUrl: 'http://explorer.test.com',
@@ -68,4 +68,13 @@ describe('NetworkVerificationInfo', () => {
getByText(strings('add_custom_network.unrecognized_chain_name')),
).toThrow('Unable to find an element with text');
});
+
+ it('should render chainId on decimal', () => {
+ (useSelector as jest.Mock).mockReturnValue(true);
+ const { getByText } = render(
+ ,
+ );
+
+ expect(getByText('10')).toBeTruthy();
+ });
});
diff --git a/app/components/UI/NetworkVerificationInfo/NetworkVerificationInfo.tsx b/app/components/UI/NetworkVerificationInfo/NetworkVerificationInfo.tsx
index 31eb57ecfbc..7db6acaa005 100644
--- a/app/components/UI/NetworkVerificationInfo/NetworkVerificationInfo.tsx
+++ b/app/components/UI/NetworkVerificationInfo/NetworkVerificationInfo.tsx
@@ -34,6 +34,7 @@ import {
} from '../../../util/networks';
import { NetworkApprovalModalSelectorsIDs } from '../../../../e2e/selectors/Modals/NetworkApprovalModal.selectors';
import hideKeyFromUrl from '../../../util/hideKeyFromUrl';
+import { convertHexToDecimal } from '@metamask/controller-utils';
interface Alert {
alertError: string;
@@ -106,7 +107,9 @@ const NetworkVerificationInfo = ({
{strings('add_custom_network.chain_id')}
- {customNetworkInformation.chainId}
+
+ {convertHexToDecimal(customNetworkInformation.chainId)}
+
{strings('add_custom_network.network_url')}
diff --git a/app/components/UI/NetworkVerificationInfo/__snapshots__/NetworkVerificationInfo.test.tsx.snap b/app/components/UI/NetworkVerificationInfo/__snapshots__/NetworkVerificationInfo.test.tsx.snap
index 4591659646d..f892eee35fc 100644
--- a/app/components/UI/NetworkVerificationInfo/__snapshots__/NetworkVerificationInfo.test.tsx.snap
+++ b/app/components/UI/NetworkVerificationInfo/__snapshots__/NetworkVerificationInfo.test.tsx.snap
@@ -93,32 +93,33 @@ exports[`NetworkVerificationInfo renders correctly 1`] = `
-
- T
-
+ testID="network-avatar-image"
+ />
- 1
+ 10
({
useSelector: jest.fn(),
}));
-describe('useNativeTokenFiatAmount', () => {
+describe('useIsOriginalNativeTokenSymbol', () => {
afterEach(() => {
jest.clearAllMocks();
});
diff --git a/app/core/RPCMethods/networkChecker.test.ts b/app/core/RPCMethods/networkChecker.test.ts
index 4478678560c..f98223d5b12 100644
--- a/app/core/RPCMethods/networkChecker.test.ts
+++ b/app/core/RPCMethods/networkChecker.test.ts
@@ -212,4 +212,68 @@ describe('checkSafeNetwork', () => {
);
expect(alerts).toEqual([]);
});
+
+ it('should not return warning name/symbol if it match with popular network', async () => {
+ mockedAxios.get.mockImplementation(() =>
+ Promise.resolve({
+ data: [
+ {
+ chainId: '10',
+ rpc: ['https://optimism-mainnet.infura.io/v3/1234'],
+ name: 'Optimism',
+ nativeCurrency: {
+ symbol: 'ETH',
+ decimals: 18,
+ },
+ },
+ ],
+ }),
+ );
+
+ const alerts = await checkSafeNetwork(
+ '10',
+ 'https://optimism-mainnet.infura.io/v3/1234',
+ 'Optimism',
+ 'ETH',
+ );
+ expect(alerts).toEqual([]);
+ });
+ it('should return warning name/symbol if it doesnt match with popular network and third part provider', async () => {
+ mockedAxios.get.mockImplementation(() =>
+ Promise.resolve({
+ data: [
+ {
+ chainId: '10',
+ rpc: ['https://optimism-mainnet.infura.io/v3/1234'],
+ name: 'Optimism',
+ nativeCurrency: {
+ symbol: 'ETH',
+ decimals: 18,
+ },
+ },
+ ],
+ }),
+ );
+
+ const alerts = await checkSafeNetwork(
+ '10',
+ 'https://optimism-mainnet.infura.io/v3/1234',
+ 'Optimism test',
+ 'OP',
+ );
+ expect(alerts).toEqual([
+ {
+ alertError:
+ "It looks like this network's display name doesn't match its chain ID.",
+ alertSeverity: BannerAlertSeverity.Warning,
+ alertOrigin: 'chain_name',
+ },
+ {
+ alertError:
+ "It looks like this network's symbol doesn't match this chain ID.",
+ alertSeverity: BannerAlertSeverity.Warning,
+ alertOrigin: 'chain_ticker',
+ },
+ ]);
+ });
});
diff --git a/app/core/RPCMethods/networkChecker.util.ts b/app/core/RPCMethods/networkChecker.util.ts
index 8342d0d210a..ad42c919533 100644
--- a/app/core/RPCMethods/networkChecker.util.ts
+++ b/app/core/RPCMethods/networkChecker.util.ts
@@ -2,13 +2,26 @@ import axios from 'axios';
import { BannerAlertSeverity } from '../../component-library/components/Banners/Banner';
import { strings } from '../../../locales/i18n';
import PopularList from '../../util/networks/customNetworks';
+import { toHex } from '@metamask/controller-utils';
-const findPopularNetwork = (rpcUrl: string) =>
+const findPopularNetwork = (rpcUrl: string, chainId: string) =>
PopularList.some((network) => {
const { origin } = new URL(network.rpcUrl);
- return origin === rpcUrl;
+ return origin === rpcUrl && network.chainId === chainId;
});
+const findPopularNetworkName = (name: string, chainId: string) =>
+ PopularList.some(
+ (network) =>
+ network.nickname.toLowerCase() === name.toLowerCase() &&
+ network.chainId === chainId,
+ );
+
+const findPopularNetworkSymbol = (symbol: string, chainId: string) =>
+ PopularList.some(
+ (network) => network.ticker === symbol && network.chainId === chainId,
+ );
+
const checkSafeNetwork = async (
chainIdDecimal: string,
rpcUrl: string,
@@ -31,7 +44,7 @@ const checkSafeNetwork = async (
!matchedChain.rpc
?.map((rpc: string) => new URL(rpc).origin)
.includes(origin) &&
- !findPopularNetwork(origin)
+ !findPopularNetwork(origin, toHex(chainIdDecimal))
) {
alerts.push({
alertError: strings('add_custom_network.invalid_rpc_url'),
@@ -46,14 +59,20 @@ const checkSafeNetwork = async (
alertOrigin: 'decimals',
});
}
- if (matchedChain.name?.toLowerCase() !== nickname?.toLowerCase()) {
+ if (
+ matchedChain.name?.toLowerCase() !== nickname?.toLowerCase() &&
+ !findPopularNetworkName(nickname, toHex(chainIdDecimal))
+ ) {
alerts.push({
alertError: strings('add_custom_network.unrecognized_chain_name'),
alertSeverity: BannerAlertSeverity.Warning,
alertOrigin: 'chain_name',
});
}
- if (matchedChain.nativeCurrency?.symbol !== ticker) {
+ if (
+ matchedChain.nativeCurrency?.symbol !== ticker &&
+ !findPopularNetworkSymbol(ticker, toHex(chainIdDecimal))
+ ) {
alerts.push({
alertError: strings('add_custom_network.unrecognized_chain_ticker'),
alertSeverity: BannerAlertSeverity.Warning,