Skip to content

Commit

Permalink
Merge branch 'main' into fix/12728_getAnalyticsParams_anon_prop
Browse files Browse the repository at this point in the history
  • Loading branch information
NicolasMassart authored Jan 31, 2025
2 parents adaf236 + 411bad5 commit 57316a3
Show file tree
Hide file tree
Showing 113 changed files with 6,323 additions and 738 deletions.
10 changes: 4 additions & 6 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,10 @@ app/components/UI/Swaps @MetaMask/swaps-engineers
# Notifications Team
app/components/Views/Notifications @MetaMask/notifications
app/components/Views/Settings/NotificationsSettings @MetaMask/notifications
app/components/UI/Notifications @MetaMask/notifications
app/reducers/notification @MetaMask/notifications
app/actions/notification @MetaMask/notifications
app/selectors/notification @MetaMask/notifications
app/util/notifications @MetaMask/notifications
app/store/util/notifications @MetaMask/notifications
**/Notifications/** @MetaMask/notifications
**/Notification/** @MetaMask/notifications
**/notifications/** @MetaMask/notifications
**/notification/** @MetaMask/notifications

# Identity Team
app/actions/identity @MetaMask/identity
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/create-release-pr-v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Create Release Pull Request V2

on:
workflow_dispatch:
inputs:
base-branch:
description: 'The base branch, tag, or SHA for git operations and the pull request.'
required: true
semver-version:
description: 'A semantic version. eg: x.x.x'
required: true
previous-version-tag:
description: 'Previous release version tag. eg: v7.7.0'
required: true
jobs:
generate-build-version:
uses: MetaMask/metamask-mobile-build-version/.github/workflows/[email protected]
permissions:
id-token: write

create-release-pr:
needs: generate-build-version
uses: MetaMask/github-tools/.github/workflows/[email protected]
with:
platform: mobile
base-branch: ${{ inputs.base-branch }}
semver-version: ${{ inputs.semver-version }}
previous-version-tag: ${{ inputs.previous-version-tag }}
mobile-build-version: ${{ needs.generate-build-version.outputs.build-version }}
secrets:
# This token needs read permissions to metamask-planning & write permissions to metamask-mobile
github-token: ${{ secrets.PR_TOKEN }}
permissions:
contents: write
pull-requests: write
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,6 @@ android/app/src/main/assets/modules.json
.expo
dist/
web-build/

# CICD
github-tools/
5 changes: 5 additions & 0 deletions .js.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,8 @@ export MM_PERMISSIONS_SETTINGS_V1_ENABLED=""

# Feature flag for Stablecoin Lending UI
export MM_STABLECOIN_LENDING_UI_ENABLED="true"

# Activates remote feature flag override mode.
# Remote feature flag values won't be updated,
# and selectors should return their fallback values
export OVERRIDE_REMOTE_FEATURE_FLAGS="false"
1,081 changes: 705 additions & 376 deletions CHANGELOG.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ android {
applicationId "io.metamask"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionName "7.38.0"
versionCode 1528
versionName "7.38.1"
versionCode 1533
testBuildType System.getProperty('testBuildType', 'debug')
missingDimensionStrategy 'react-native-camera', 'general'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Expand Down
13 changes: 9 additions & 4 deletions app/components/UI/AssetOverview/Balance/Balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { useStyles } from '../../../../component-library/hooks';
import styleSheet from './Balance.styles';
import AssetElement from '../../AssetElement';
import { useSelector } from 'react-redux';
import { selectNetworkName } from '../../../../selectors/networkInfos';
import { selectChainId } from '../../../../selectors/networkController';
import {
selectChainId,
selectNetworkConfigurationByChainId,
} from '../../../../selectors/networkController';
import {
getTestNetImageByChainId,
getDefaultNetworkByChainId,
Expand Down Expand Up @@ -35,6 +37,7 @@ import {
UnpopularNetworkList,
CustomNetworkImgMapping,
} from '../../../../util/networks/customNetworks';
import { RootState } from '../../../../reducers';

interface BalanceProps {
asset: TokenI;
Expand Down Expand Up @@ -91,7 +94,9 @@ export const NetworkBadgeSource = (chainId: Hex, ticker: string) => {
const Balance = ({ asset, mainBalance, secondaryBalance }: BalanceProps) => {
const { styles } = useStyles(styleSheet, {});
const navigation = useNavigation();
const networkName = useSelector(selectNetworkName);
const networkConfigurationByChainId = useSelector((state: RootState) =>
selectNetworkConfigurationByChainId(state, asset.chainId as Hex),
);
const chainId = useSelector(selectChainId);

const tokenChainId = isPortfolioViewEnabled() ? asset.chainId : chainId;
Expand Down Expand Up @@ -156,7 +161,7 @@ const Balance = ({ asset, mainBalance, secondaryBalance }: BalanceProps) => {
<Badge
variant={BadgeVariant.Network}
imageSource={NetworkBadgeSource(tokenChainId as Hex, ticker)}
name={networkName || ''}
name={networkConfigurationByChainId?.name}
/>
}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const MISSMATCH_RPC_URL_TEST_ID =
'networks.rpc-url-missmatch-review-and-compare';
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* This separate test file was created to test the component with isMultichainVersion1Enabled=true.
* Due to the way feature flags are imported and used, it's cleaner to mock them in a separate file.
* When the feature flag is removed, these tests should be merged into the main NetworkVerificationInfo.test.tsx file.
*/
import React from 'react';
import NetworkVerificationInfo from './NetworkVerificationInfo';
import { BannerAlertSeverity } from '../../../component-library/components/Banners/Banner';
import { strings } from '../../../../locales/i18n';
import { useSelector } from 'react-redux';
import renderWithProvider from '../../../util/test/renderWithProvider';
import { PopularList } from '../../../util/networks/customNetworks';
import { MISSMATCH_RPC_URL_TEST_ID } from './NetworkVerificationInfo.constants';

jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useSelector: jest.fn(),
}));

// Mock feature flags
jest.mock('../../../util/networks/index.js', () => ({
...jest.requireActual('../../../util/networks/index.js'),
isMultichainVersion1Enabled: true,
isChainPermissionsFeatureEnabled: true,
}));

const mockNetworkInfo = {
chainName: 'Test Chain',
chainId: '0xa',
rpcUrl: 'http://test.com',
ticker: 'TEST',
blockExplorerUrl: 'http://explorer.test.com',
alerts: [
{
alertError: strings('add_custom_network.unrecognized_chain_name'),
alertSeverity: BannerAlertSeverity.Warning,
alertOrigin: 'chain_name',
},
],
icon: 'test-icon',
};

describe('NetworkVerificationInfo with Feature Flag ON', () => {
// Setup and cleanup for PopularList mock
const originalPopularList = [PopularList];

beforeEach(() => {
(useSelector as jest.Mock).mockClear();
});

afterEach(() => {
// Restore original PopularList after each test
PopularList.length = 0;
PopularList.push(...originalPopularList[0]);
});

describe('RPC URL Mismatch Detection', () => {
const createMockPopularNetwork = (rpcUrl: string) => ({
chainId: '0xa' as `0x${string}`,
rpcUrl,
rpcPrefs: {
imageSource: 'test-image',
blockExplorerUrl: 'https://test-explorer.com',
imageUrl: 'https://test-image.com',
},
nickname: 'Test Network',
ticker: 'TEST',
warning: false,
});

const createNetworkWithPageMeta = (url: string) => ({
...mockNetworkInfo,
pageMeta: { url },
});

it('hides RPC mismatch UI for non-dapp requests', () => {
const { queryByTestId } = renderWithProvider(
<NetworkVerificationInfo
customNetworkInformation={mockNetworkInfo}
onReject={() => undefined}
onConfirm={() => undefined}
isCustomNetwork={false}
/>,
);

expect(queryByTestId(MISSMATCH_RPC_URL_TEST_ID)).toBeNull();
});

it('displays RPC mismatch UI when URLs differ', () => {
const mockPopularNetwork = createMockPopularNetwork(
'https://different.rpc.url',
);
PopularList.length = 0;
PopularList.push(mockPopularNetwork);

const networkInfoWithPageMeta = createNetworkWithPageMeta(
'https://app.uniswap.org',
);

const { queryByTestId } = renderWithProvider(
<NetworkVerificationInfo
customNetworkInformation={networkInfoWithPageMeta}
onReject={() => undefined}
onConfirm={() => undefined}
isCustomNetwork={false}
/>,
);

expect(queryByTestId(MISSMATCH_RPC_URL_TEST_ID)).toBeDefined();
});

it('hides RPC mismatch UI when URLs match', () => {
const mockPopularNetwork = createMockPopularNetwork('http://test.com');
PopularList.length = 0;
PopularList.push(mockPopularNetwork);

const networkInfoWithPageMeta = createNetworkWithPageMeta(
'https://app.uniswap.org',
);

const { queryByTestId } = renderWithProvider(
<NetworkVerificationInfo
customNetworkInformation={networkInfoWithPageMeta}
onReject={() => undefined}
onConfirm={() => undefined}
isCustomNetwork={false}
/>,
);

expect(queryByTestId(MISSMATCH_RPC_URL_TEST_ID)).toBeNull();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import { NetworkApprovalBottomSheetSelectorsIDs } from '../../../../e2e/selector
import hideKeyFromUrl from '../../../util/hideKeyFromUrl';
import { convertHexToDecimal } from '@metamask/controller-utils';
import { isValidASCIIURL, toPunycodeURL } from '../../../util/url';
import { PopularList } from '../../../util/networks/customNetworks';
import { MISSMATCH_RPC_URL_TEST_ID } from './NetworkVerificationInfo.constants';

interface Alert {
alertError: string;
Expand All @@ -59,13 +61,11 @@ const NetworkVerificationInfo = ({
onReject,
onConfirm,
isCustomNetwork = false,
isMissmatchingRPCUrl = false,
}: {
customNetworkInformation: CustomNetworkInformation;
onReject: () => void;
onConfirm: () => void;
isCustomNetwork?: boolean;
isMissmatchingRPCUrl?: boolean;
}) => {
const [networkInfoMaxHeight, setNetworkInfoMaxHeight] = useState<
number | null
Expand All @@ -86,6 +86,24 @@ const NetworkVerificationInfo = ({

const customRpcUrl = customNetworkInformation.rpcUrl;

const isDappRequest = useMemo(
// @ts-expect-error - The CustomNetworkInformation type is missing the pageMeta property
() => Boolean(customNetworkInformation.pageMeta?.url),
[customNetworkInformation],
);

const matchingPopularNetwork = useMemo(() => {
if (!isDappRequest) return null;
return PopularList.find(
(network) => network.chainId === customNetworkInformation.chainId,
);
}, [isDappRequest, customNetworkInformation.chainId]);

const hasRpcMismatch = useMemo(() => {
if (!matchingPopularNetwork) return false;
return matchingPopularNetwork.rpcUrl !== customNetworkInformation.rpcUrl;
}, [matchingPopularNetwork, customNetworkInformation.rpcUrl]);

const goToLearnMore = () => {
Linking.openURL(
'https://support.metamask.io/networks-and-sidechains/managing-networks/verifying-custom-network-information/',
Expand Down Expand Up @@ -169,19 +187,19 @@ const NetworkVerificationInfo = ({
const renderNetworkRpcUrlLabel = () => (
<View style={styles.networkUrlLabelRow}>
<Text
color={isMissmatchingRPCUrl ? TextColor.Primary : TextColor.Default}
color={hasRpcMismatch ? TextColor.Primary : TextColor.Default}
variant={TextVariant.BodyMDMedium}
>
{strings('networks.network_rpc_url_label')}
</Text>
{isMissmatchingRPCUrl && (
{hasRpcMismatch && (
<TouchableOpacity
onPress={() => {
showReviewDefaultRpcUrlChangesModal();
}}
>
<TagColored style={styles.tag} color={TagColor.Info}>
<View style={styles.tagContent}>
<View style={styles.tagContent} testID={MISSMATCH_RPC_URL_TEST_ID}>
<Icon
size={IconSize.Sm}
name={IconName.Info}
Expand Down Expand Up @@ -353,13 +371,13 @@ const NetworkVerificationInfo = ({
<Text variant={TextVariant.BodyMDBold}>
{strings('networks.current_label')}
</Text>
<Text style={styles.textSection}>{customRpcUrl}</Text>
<Text style={styles.textSection}>
{hideKeyFromUrl(matchingPopularNetwork?.rpcUrl)}
</Text>
<Text variant={TextVariant.BodyMDBold}>
{strings('networks.new_label')}
</Text>
<Text style={styles.textSection}>
{'https://flashbots.polygon-mainnet.com'}
</Text>
<Text style={styles.textSection}>{hideKeyFromUrl(customRpcUrl)}</Text>
</View>
</View>
</View>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Theme } from '../../../../../util/theme/models';
import { StyleSheet } from 'react-native';

const stylesSheet = (params: { theme: Theme }) => {
const { theme } = params;
const { colors } = theme;

return StyleSheet.create({
mainContainer: {
flexGrow: 1,
paddingTop: 8,
paddingHorizontal: 16,
backgroundColor: colors.background.default,
justifyContent: 'space-between',
},
});
};

export default stylesSheet;
Loading

0 comments on commit 57316a3

Please sign in to comment.