Repository: MetaMask/metamask-mobile
Pull request #13740: fix: fix balance display in account info signature request
Author: login: sahar-fehri
Labels: name: QA Passed
description: QA testing has been completed and passed
name: team-assets
name: needs-assets-ux-review
description: A shared label between the Assets and UX team to flag PRs ready for consolidated team review.
name: skip-sonar-cloud
description: Only used for bypassing sonar cloud when failures are not relevant to the changes.
name: release-7.43.0
description: Issue or pull request that will be included in release 7.43.0
Created: 2025-02-26T18:12:30Z | Merged: 2025-03-03T15:27:49Z

## **Description**

PR to fix balance display in signature confirmation component.
It also fixes the balance display when the network is being switched within a dapp.

## **Related issues**

Fixes: https://github.com/MetaMask/metamask-mobile/issues/13730
Fixes: https://github.com/MetaMask/metamask-mobile/issues/13727

## **Manual testing steps**

Description of manual testing steps are included in reported issues
1. Go to this page...
2.
3.

## **Screenshots/Recordings**



<!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->
[Screen Recording 2025-02-26 at 19.09.10](https://github.com/user-attachments/assets/a4fd0edc-e81d-4284-a2b9-44dbe5b90a49)


https://github.com/user-attachments/assets/13e39779-588d-43ba-a41b-dea9e1ce5b48




## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.



Diff:
diff --git a/android/.project b/android/.project
index 3cf8618bf4c1..7c65af890832 100644
--- a/android/.project
+++ b/android/.project
@@ -14,4 +14,15 @@
 	<natures>
 		<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
 	</natures>
+	<filteredResources>
+		<filter>
+			<id>1741006795407</id>
+			<name></name>
+			<type>30</type>
+			<matcher>
+				<id>org.eclipse.core.resources.regexFilterMatcher</id>
+				<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
+			</matcher>
+		</filter>
+	</filteredResources>
 </projectDescription>
diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs
index e8895216fd3c..948553877cf0 100644
--- a/android/.settings/org.eclipse.buildship.core.prefs
+++ b/android/.settings/org.eclipse.buildship.core.prefs
@@ -1,2 +1,13 @@
+arguments=--init-script /var/folders/j9/20w1vr5s10v1y55vbf73rbx40000gn/T/db3b08fc4a9ef609cb16b96b200fa13e563f396e9bb1ed0905fdab7bc3bc513b.gradle --init-script /var/folders/j9/20w1vr5s10v1y55vbf73rbx40000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
+auto.sync=false
+build.scans.enabled=false
+connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
 connection.project.dir=
 eclipse.preferences.version=1
+gradle.user.home=
+java.home=/Users/salim/Library/Java/JavaVirtualMachines/azul-16.0.2/Contents/Home
+jvm.arguments=
+offline.mode=false
+override.workspace.settings=true
+show.console.view=true
+show.executions.view=true
diff --git a/app/components/Nav/Main/index.js b/app/components/Nav/Main/index.js
index 7ce6c9742ccd..7ae2f675494b 100644
--- a/app/components/Nav/Main/index.js
+++ b/app/components/Nav/Main/index.js
@@ -58,6 +58,7 @@ import { useMinimumVersions } from '../../hooks/MinimumVersions';
 import navigateTermsOfUse from '../../../util/termsOfUse/termsOfUse';
 import {
   selectChainId,
+  selectIsAllNetworks,
   selectNetworkClientId,
   selectNetworkConfigurations,
   selectProviderConfig,
@@ -67,7 +68,10 @@ import {
   selectNetworkName,
   selectNetworkImageSource,
 } from '../../../selectors/networkInfos';
-import { selectShowIncomingTransactionNetworks } from '../../../selectors/preferencesController';
+import {
+  selectShowIncomingTransactionNetworks,
+  selectTokenNetworkFilter,
+} from '../../../selectors/preferencesController';
 
 import useNotificationHandler from '../../../util/notifications/hooks';
 import {
@@ -86,6 +90,7 @@ import { useConnectionHandler } from '../../../util/navigation/useConnectionHand
 import { AssetPollingProvider } from '../../hooks/AssetPolling/AssetPollingProvider';
 import { getGlobalEthQuery } from '../../../util/networks/global-network';
 import { selectIsEvmNetworkSelected } from '../../../selectors/multichainNetworkController';
+import { isPortfolioViewEnabled } from '../../../util/networks';
 
 const Stack = createStackNavigator();
 
@@ -232,6 +237,9 @@ const Main = (props) => {
   const { toastRef } = useContext(ToastContext);
   const networkImage = useSelector(selectNetworkImageSource);
 
+  const isAllNetworks = useSelector(selectIsAllNetworks);
+  const tokenNetworkFilter = useSelector(selectTokenNetworkFilter);
+
   const hasNetworkChanged = useCallback(
     (chainId, previousConfig, isEvmSelected) => {
       if (!previousConfig) return false;
@@ -249,6 +257,14 @@ const Main = (props) => {
     if (
       hasNetworkChanged(chainId, previousProviderConfig.current, isEvmSelected)
     ) {
+      //set here token network filter if portfolio view is enabled
+      if (isPortfolioViewEnabled()) {
+        const { PreferencesController } = Engine.context;
+        PreferencesController.setTokenNetworkFilter({
+          ...(isAllNetworks ? tokenNetworkFilter : {}),
+          [chainId]: true,
+        });
+      }
       toastRef?.current?.showToast({
         variant: ToastVariants.Network,
         labelOptions: [
@@ -272,6 +288,8 @@ const Main = (props) => {
     chainId,
     isEvmSelected,
     hasNetworkChanged,
+    isAllNetworks,
+    tokenNetworkFilter,
   ]);
 
   // Show add network confirmation.
diff --git a/app/components/UI/DrawerView/__snapshots__/index.test.tsx.snap b/app/components/UI/DrawerView/__snapshots__/index.test.tsx.snap
index 9e9f02bb66cb..68bdcd7423a4 100644
--- a/app/components/UI/DrawerView/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/DrawerView/__snapshots__/index.test.tsx.snap
@@ -1,6 +1,6 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`DrawerView should render correctly 1`] = `
+exports[`DrawerView - Extended Coverage renders correctly (snapshot) 1`] = `
 <View
   style={
     {
diff --git a/app/components/UI/DrawerView/index.js b/app/components/UI/DrawerView/index.js
index e662c454f305..11b3dbf5c469 100644
--- a/app/components/UI/DrawerView/index.js
+++ b/app/components/UI/DrawerView/index.js
@@ -87,6 +87,7 @@ import { createAccountSelectorNavDetails } from '../../Views/AccountSelector';
 import NetworkInfo from '../NetworkInfo';
 import { withMetricsAwareness } from '../../../components/hooks/useMetrics';
 import { toChecksumHexAddress } from '@metamask/controller-utils';
+import safePromiseHandler from './utils';
 
 const createStyles = (colors) =>
   StyleSheet.create({
@@ -981,9 +982,12 @@ class DrawerView extends PureComponent {
       networkSwitched,
       toggleInfoNetworkModal,
     } = this.props;
+
     onboardNetworkAction(chainId);
     networkSwitched({ networkUrl: '', networkStatus: false });
-    toggleInfoNetworkModal();
+
+    // Wrap the toggle call in a setTimeout to avoid awaiting a non-promise function.
+    safePromiseHandler(toggleInfoNetworkModal(), 100);
   };
 
   renderProtectModal = () => {
diff --git a/app/components/UI/DrawerView/index.test.tsx b/app/components/UI/DrawerView/index.test.tsx
index 11a92223e2a7..db98d215af73 100644
--- a/app/components/UI/DrawerView/index.test.tsx
+++ b/app/components/UI/DrawerView/index.test.tsx
@@ -5,6 +5,16 @@ import DrawerView from './';
 import { backgroundState } from '../../../util/test/initial-root-state';
 import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils';
 
+import { fireEvent } from '@testing-library/react-native';
+
+jest.mock('react-native-share', () => ({
+  open: jest.fn(() => Promise.resolve()),
+}));
+
+jest.mock('../../../core/ClipboardManager', () => ({
+  setString: jest.fn(() => Promise.resolve()),
+}));
+
 const mockInitialState = {
   engine: {
     backgroundState: {
@@ -33,8 +43,62 @@ jest.mock('../../../core/Engine', () => {
   };
 });
 
-describe('DrawerView', () => {
-  it('should render correctly', () => {
+describe('DrawerView - Extended Coverage', () => {
+  const navigationMock = {
+    navigate: jest.fn(),
+    goBack: jest.fn(),
+    replace: jest.fn(),
+    dangerouslyGetState: jest.fn(() => ({ routes: [{ name: 'Home' }] })),
+  };
+  const metricsMock = {
+    trackEvent: jest.fn(),
+    createEventBuilder: jest.fn(() => ({
+      addProperties: jest.fn(() => ({
+        build: jest.fn(() => ({})),
+      })),
+      build: jest.fn(() => ({})),
+    })),
+  };
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  const props = {
+    navigation: navigationMock,
+    providerConfig: {
+      type: 'mainnet',
+      ticker: 'ETH',
+      rpcUrl: 'https://rpc.example.com',
+    },
+    accounts: {},
+    selectedInternalAccount: {
+      address: '0x123',
+      metadata: { name: 'Account 1' },
+    },
+    currentCurrency: 'USD',
+    keyrings: [],
+    toggleNetworkModal: jest.fn(),
+    showAlert: jest.fn(),
+    networkModalVisible: false,
+    newAssetTransaction: jest.fn(),
+    passwordSet: true,
+    wizard: {},
+    ticker: 'ETH',
+    networkConfigurations: {},
+    tokens: [],
+    tokenBalances: {},
+    collectibles: [],
+    seedphraseBackedUp: true,
+    currentRoute: 'Home',
+    switchedNetwork: {},
+    protectWalletModalVisible: jest.fn(),
+    onboardNetworkAction: jest.fn(),
+    networkSwitched: jest.fn(),
+    infoNetworkModalVisible: false,
+    toggleInfoNetworkModal: jest.fn(),
+    onCloseDrawer: jest.fn(),
+    metrics: metricsMock,
+    chainId: '1',
+  };
+
+  it('renders correctly (snapshot)', () => {
     const { toJSON } = renderWithProvider(
       <DrawerView navigation={{ goBack: () => null }} />,
       {
@@ -43,4 +107,34 @@ describe('DrawerView', () => {
     );
     expect(toJSON()).toMatchSnapshot();
   });
+
+  it('handles onSend correctly', async () => {
+    const { getByTestId } = renderWithProvider(<DrawerView {...props} />, {
+      state: mockInitialState,
+    });
+    const sendButton = getByTestId('drawer-send-button');
+    fireEvent.press(sendButton);
+    expect(navigationMock.navigate).toHaveBeenCalledWith('SendFlowView');
+  });
+
+  it('calls openAccountSelector and tracks the event', () => {
+    const { getByTestId } = renderWithProvider(<DrawerView {...props} />, {
+      state: mockInitialState,
+    });
+    const identicon = getByTestId('navbar-account-identicon');
+    fireEvent.press(identicon);
+    expect(navigationMock.navigate).toHaveBeenCalled();
+  });
+
+  it('handles onReceive correctly', () => {
+    const { getByTestId } = renderWithProvider(<DrawerView {...props} />, {
+      state: mockInitialState,
+    });
+    const receiveButton = getByTestId('drawer-receive-button');
+    fireEvent.press(receiveButton);
+    expect(navigationMock.navigate).toHaveBeenCalledWith('QRTabSwitcher', {
+      disableTabber: true,
+      initialScreen: 1,
+    });
+  });
 });
diff --git a/app/components/UI/DrawerView/util.test.ts b/app/components/UI/DrawerView/util.test.ts
new file mode 100644
index 000000000000..1656b128632a
--- /dev/null
+++ b/app/components/UI/DrawerView/util.test.ts
@@ -0,0 +1,53 @@
+import safePromiseHandler from './utils';
+
+describe('safePromiseHandler', () => {
+  beforeEach(() => {
+    jest.useFakeTimers();
+  });
+
+  afterEach(() => {
+    jest.runOnlyPendingTimers();
+    jest.useRealTimers();
+    jest.clearAllMocks();
+  });
+
+  it('should return a function', () => {
+    const toggleFunction = jest.fn();
+    const handler = safePromiseHandler(toggleFunction);
+    expect(typeof handler).toBe('function');
+  });
+
+  it('should call toggleFunction after the default delay (100ms)', () => {
+    const toggleFunction = jest.fn();
+    const handler = safePromiseHandler(toggleFunction);
+    handler();
+    // Initially, the toggleFunction should not have been called.
+    expect(toggleFunction).not.toHaveBeenCalled();
+    // Advance time by 100ms
+    jest.advanceTimersByTime(100);
+    expect(toggleFunction).toHaveBeenCalledTimes(1);
+  });
+
+  it('should call toggleFunction after a custom delay', () => {
+    const customDelay = 250;
+    const toggleFunction = jest.fn();
+    const handler = safePromiseHandler(toggleFunction, customDelay);
+    handler();
+    // Advance time by less than customDelay; function should not have been called yet.
+    jest.advanceTimersByTime(customDelay - 1);
+    expect(toggleFunction).not.toHaveBeenCalled();
+    // Advance by the remaining time.
+    jest.advanceTimersByTime(1);
+    expect(toggleFunction).toHaveBeenCalledTimes(1);
+  });
+
+  it('should call toggleFunction for each invocation of the handler', () => {
+    const toggleFunction = jest.fn();
+    const handler = safePromiseHandler(toggleFunction);
+    // Call the returned function twice.
+    handler();
+    handler();
+    jest.advanceTimersByTime(100);
+    expect(toggleFunction).toHaveBeenCalledTimes(2);
+  });
+});
diff --git a/app/components/UI/DrawerView/utils.ts b/app/components/UI/DrawerView/utils.ts
new file mode 100644
index 000000000000..0a82f8c9f40d
--- /dev/null
+++ b/app/components/UI/DrawerView/utils.ts
@@ -0,0 +1,13 @@
+/**
+ * Delays the execution of a function by a specified amount of time.
+ *
+ * @param toggleFunction - The function to execute after the delay.
+ * @param delay - The delay in milliseconds (default: 100ms).
+ * @returns A function that, when called, will execute the provided function after the delay.
+ */
+const safePromiseHandler =
+  (toggleFunction: () => void, delay: number = 100): (() => void) =>
+  () =>
+    setTimeout(toggleFunction, delay);
+
+export default safePromiseHandler;
diff --git a/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx b/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
index c11146d23186..744ef1b045c4 100644
--- a/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
+++ b/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
@@ -1,21 +1,52 @@
 import React from 'react';
-
 import renderWithProvider from '../../../../../../../util/test/renderWithProvider';
 import { personalSignatureConfirmationState } from '../../../../../../../util/test/confirm-data-helpers';
 import AccountNetworkInfoExpanded from './AccountNetworkInfoExpanded';
+import { isPortfolioViewEnabled } from '../../../../../../../util/networks';
+
+jest.mock('../../../../../../../util/networks', () => ({
+  ...jest.requireActual('../../../../../../../util/networks'),
+  isPortfolioViewEnabled: jest.fn(),
+}));
 
 jest.mock('../../../../../../../core/Engine', () => ({
   getTotalFiatAccountBalance: () => ({ tokenFiat: 10 }),
 }));
 
 describe('AccountNetworkInfoExpanded', () => {
-  it('should render correctly', async () => {
+  const mockIsPortfolioViewEnabled = jest.mocked(isPortfolioViewEnabled);
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    mockIsPortfolioViewEnabled.mockReturnValue(false);
+  });
+
+  it('should match snapshot when isPortfolioVieEnabled is true', () => {
+    mockIsPortfolioViewEnabled.mockReturnValue(true);
+    const { toJSON, getByText } = renderWithProvider(
+      <AccountNetworkInfoExpanded />,
+      {
+        state: personalSignatureConfirmationState,
+      },
+    );
+
+    expect(toJSON()).toMatchSnapshot();
+    expect(getByText('Account')).toBeDefined();
+    expect(getByText('Balance')).toBeDefined();
+    expect(getByText('Balance')).toBeDefined();
+    expect(getByText('$0')).toBeDefined();
+    expect(getByText('Network')).toBeDefined();
+    expect(getByText('Ethereum Mainnet')).toBeDefined();
+  });
+
+  it('should render correctly when isPortfolioVieEnabled is false', async () => {
     const { getByText } = renderWithProvider(<AccountNetworkInfoExpanded />, {
       state: personalSignatureConfirmationState,
     });
+
+    expect(getByText('$10')).toBeDefined();
     expect(getByText('Account')).toBeDefined();
     expect(getByText('Balance')).toBeDefined();
-    expect(getByText('$10')).toBeDefined();
     expect(getByText('Network')).toBeDefined();
     expect(getByText('Ethereum Mainnet')).toBeDefined();
   });
diff --git a/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.tsx b/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.tsx
index dd93e73e057c..a3818ff9ecda 100644
--- a/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.tsx
+++ b/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.tsx
@@ -9,6 +9,7 @@ import Network from '../../../UI/InfoRow/InfoValue/Network';
 import { useSignatureRequest } from '../../../../hooks/useSignatureRequest';
 import { Hex } from '@metamask/utils';
 import { renderShortAddress } from '../../../../../../../util/address';
+import { useMultichainBalances } from '../../../../../../hooks/useMultichainBalances';
 
 const AccountNetworkInfoExpanded = () => {
   const signatureRequest = useSignatureRequest();
@@ -16,6 +17,10 @@ const AccountNetworkInfoExpanded = () => {
 
   const fromAddress = signatureRequest?.messageParams?.from as string;
   const { accountAddress, accountFiatBalance } = useAccountInfo(fromAddress);
+  const { multichainBalances } = useMultichainBalances();
+  const balanceToDisplay = multichainBalances.isPortfolioVieEnabled
+    ? multichainBalances.displayBalance
+    : accountFiatBalance;
 
   return (
     <View>
@@ -24,7 +29,7 @@ const AccountNetworkInfoExpanded = () => {
           {renderShortAddress(accountAddress, 5)}
         </InfoRow>
         <InfoRow label={strings('confirm.label.balance')}>
-          {accountFiatBalance}
+          {balanceToDisplay}
         </InfoRow>
       </InfoSection>
       <InfoSection>
diff --git a/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/__snapshots__/AccountNetworkInfoExpanded.test.tsx.snap b/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/__snapshots__/AccountNetworkInfoExpanded.test.tsx.snap
new file mode 100644
index 000000000000..4a7211429ab0
--- /dev/null
+++ b/app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/__snapshots__/AccountNetworkInfoExpanded.test.tsx.snap
@@ -0,0 +1,259 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AccountNetworkInfoExpanded should match snapshot when isPortfolioVieEnabled is true 1`] = `
+<View>
+  <View
+    style={
+      {
+        "backgroundColor": "#ffffff",
+        "borderRadius": 8,
+        "marginBottom": 8,
+        "paddingBottom": 8,
+        "paddingHorizontal": 8,
+        "paddingTop": 12,
+      }
+    }
+    testID="info-section"
+  >
+    <View
+      style={
+        {
+          "alignItems": "center",
+          "display": "flex",
+          "flexDirection": "row",
+          "flexWrap": "wrap",
+          "justifyContent": "space-between",
+          "paddingBottom": 8,
+          "paddingHorizontal": 8,
+        }
+      }
+      testID="info-row"
+    >
+      <View
+        style={
+          {
+            "alignItems": "center",
+            "alignSelf": "flex-start",
+            "display": "flex",
+            "flexDirection": "row",
+            "minHeight": 38,
+            "paddingEnd": 4,
+          }
+        }
+      >
+        <Text
+          accessibilityRole="text"
+          style={
+            {
+              "alignItems": "center",
+              "color": "#141618",
+              "fontFamily": "EuclidCircularB-Bold",
+              "fontSize": 14,
+              "fontWeight": "500",
+              "justifyContent": "center",
+              "letterSpacing": 0,
+              "lineHeight": 22,
+            }
+          }
+        >
+          Account
+        </Text>
+      </View>
+      <Text
+        accessibilityRole="text"
+        style={
+          {
+            "color": "#141618",
+            "fontFamily": "EuclidCircularB-Regular",
+            "fontSize": 14,
+            "fontWeight": "400",
+            "letterSpacing": 0,
+            "lineHeight": 22,
+          }
+        }
+      >
+        0x935E7...05477
+      </Text>
+    </View>
+    <View
+      style={
+        {
+          "alignItems": "center",
+          "display": "flex",
+          "flexDirection": "row",
+          "flexWrap": "wrap",
+          "justifyContent": "space-between",
+          "paddingBottom": 8,
+          "paddingHorizontal": 8,
+        }
+      }
+      testID="info-row"
+    >
+      <View
+        style={
+          {
+            "alignItems": "center",
+            "alignSelf": "flex-start",
+            "display": "flex",
+            "flexDirection": "row",
+            "minHeight": 38,
+            "paddingEnd": 4,
+          }
+        }
+      >
+        <Text
+          accessibilityRole="text"
+          style={
+            {
+              "alignItems": "center",
+              "color": "#141618",
+              "fontFamily": "EuclidCircularB-Bold",
+              "fontSize": 14,
+              "fontWeight": "500",
+              "justifyContent": "center",
+              "letterSpacing": 0,
+              "lineHeight": 22,
+            }
+          }
+        >
+          Balance
+        </Text>
+      </View>
+      <Text
+        accessibilityRole="text"
+        style={
+          {
+            "color": "#141618",
+            "fontFamily": "EuclidCircularB-Regular",
+            "fontSize": 14,
+            "fontWeight": "400",
+            "letterSpacing": 0,
+            "lineHeight": 22,
+          }
+        }
+      >
+        $0
+      </Text>
+    </View>
+  </View>
+  <View
+    style={
+      {
+        "backgroundColor": "#ffffff",
+        "borderRadius": 8,
+        "marginBottom": 8,
+        "paddingBottom": 8,
+        "paddingHorizontal": 8,
+        "paddingTop": 12,
+      }
+    }
+    testID="info-section"
+  >
+    <View
+      style={
+        {
+          "alignItems": "center",
+          "display": "flex",
+          "flexDirection": "row",
+          "flexWrap": "wrap",
+          "justifyContent": "space-between",
+          "paddingBottom": 8,
+          "paddingHorizontal": 8,
+        }
+      }
+      testID="info-row"
+    >
+      <View
+        style={
+          {
+            "alignItems": "center",
+            "alignSelf": "flex-start",
+            "display": "flex",
+            "flexDirection": "row",
+            "minHeight": 38,
+            "paddingEnd": 4,
+          }
+        }
+      >
+        <Text
+          accessibilityRole="text"
+          style={
+            {
+              "alignItems": "center",
+              "color": "#141618",
+              "fontFamily": "EuclidCircularB-Bold",
+              "fontSize": 14,
+              "fontWeight": "500",
+              "justifyContent": "center",
+              "letterSpacing": 0,
+              "lineHeight": 22,
+            }
+          }
+        >
+          Network
+        </Text>
+      </View>
+      <View
+        style={
+          {
+            "marginLeft": "auto",
+          }
+        }
+      >
+        <View
+          style={
+            {
+              "alignItems": "center",
+              "display": "flex",
+              "flexDirection": "row",
+            }
+          }
+        >
+          <View
+            style={
+              {
+                "alignItems": "center",
+                "backgroundColor": "#ffffff",
+                "borderRadius": 8,
+                "height": 16,
+                "justifyContent": "center",
+                "overflow": "hidden",
+                "width": 16,
+              }
+            }
+          >
+            <Image
+              onError={[Function]}
+              resizeMode="contain"
+              source={1}
+              style={
+                {
+                  "height": 16,
+                  "width": 16,
+                }
+              }
+              testID="network-avatar-image"
+            />
+          </View>
+          <Text
+            accessibilityRole="text"
+            style={
+              {
+                "color": "#141618",
+                "fontFamily": "EuclidCircularB-Regular",
+                "fontSize": 14,
+                "fontWeight": "400",
+                "letterSpacing": 0,
+                "lineHeight": 22,
+                "marginLeft": 8,
+              }
+            }
+          >
+            Ethereum Mainnet
+          </Text>
+        </View>
+      </View>
+    </View>
+  </View>
+</View>
+`;
diff --git a/app/selectors/multichain/multichain.test.ts b/app/selectors/multichain/multichain.test.ts
index 425630ec7484..eddb7524ba98 100644
--- a/app/selectors/multichain/multichain.test.ts
+++ b/app/selectors/multichain/multichain.test.ts
@@ -9,6 +9,9 @@ import {
   selectMultichainShouldShowFiat,
   selectMultichainConversionRate,
   MultichainNativeAssets,
+  selectMultichainCoinRates,
+  selectMultichainBalances,
+  NETWORK_ASSETS_MAP,
 } from './multichain';
 import { InternalAccount } from '@metamask/keyring-internal-api';
 import { CHAIN_IDS } from '@metamask/transaction-controller';
@@ -450,4 +453,49 @@ describe('MultichainNonEvm Selectors', () => {
       expect(selectMultichainConversionRate(state)).toBe(mockSolConversionRate);
     });
   });
+
+  describe('selectMultichainBalances and selectMultichainCoinRates', () => {
+    it('selectMultichainBalances returns balances from the MultichainBalancesController state', () => {
+      const state = getEvmState();
+      const mockBalances = {
+        'account-1': {
+          [MultichainNativeAssets.Bitcoin]: { amount: '10', unit: 'BTC' },
+        },
+      };
+      state.engine.backgroundState.MultichainBalancesController.balances =
+        mockBalances;
+      expect(selectMultichainBalances(state)).toEqual(mockBalances);
+    });
+
+    it('selectMultichainCoinRates returns rates from the RatesController state', () => {
+      const state = getEvmState();
+      const mockRates = {
+        eth: {
+          conversionRate: 2000,
+          conversionDate: Date.now(),
+          usdConversionRate: 2000,
+        },
+      };
+      state.engine.backgroundState.RatesController.rates = mockRates;
+      expect(selectMultichainCoinRates(state)).toEqual(mockRates);
+    });
+
+    it('NETWORK_ASSETS_MAP has correct mappings', () => {
+      expect(NETWORK_ASSETS_MAP[SolScope.Mainnet]).toEqual([
+        MultichainNativeAssets.Solana,
+      ]);
+      expect(NETWORK_ASSETS_MAP[SolScope.Testnet]).toEqual([
+        MultichainNativeAssets.SolanaTestnet,
+      ]);
+      expect(NETWORK_ASSETS_MAP[SolScope.Devnet]).toEqual([
+        MultichainNativeAssets.SolanaDevnet,
+      ]);
+      expect(NETWORK_ASSETS_MAP[BtcScope.Mainnet]).toEqual([
+        MultichainNativeAssets.Bitcoin,
+      ]);
+      expect(NETWORK_ASSETS_MAP[BtcScope.Testnet]).toEqual([
+        MultichainNativeAssets.BitcoinTestnet,
+      ]);
+    });
+  });
 });


Reviews:
user: login: Prithpal-Sooriya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-26T19:20:22Z
user: login: sahar-fehri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-27T08:45:40Z
user: login: salimtb
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-02-28T13:27:13Z
user: login: OGPoyraz
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-03-03T08:41:55Z
user: login: OGPoyraz
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T08:52:48Z
user: login: OGPoyraz
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T10:53:48Z
user: login: OGPoyraz
body: Confirmation changes LGTM
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-03T15:08:59Z
user: login: salimtb
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:11:23Z

Review comments:
diff_hunk: @@ -8,14 +8,23 @@ jest.mock('../../../../../../../core/Engine', () => ({
   getTotalFiatAccountBalance: () => ({ tokenFiat: 10 }),
 }));
 
+jest.mock('../../../../../../hooks/useMultichainBalances', () => ({
+  useMultichainBalances: () => ({
+    multichainBalances: {
+      isPortfolioVieEnabled: true,
+      displayBalance: '$100',
+    },
+  }),
path: app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
user: login: Prithpal-Sooriya
body: It would've been nice to test using pure state (and let the hooks correctly fire), but this hook is really complex!
created_at: 2025-02-26T19:20:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -249,6 +257,14 @@ const Main = (props) => {
     if (
       hasNetworkChanged(chainId, previousProviderConfig.current, isEvmSelected)
     ) {
+      //set here token network filter if portfolio view is enabled
+      if (isPortfolioViewEnabled()) {
path: app/components/Nav/Main/index.js
user: login: sahar-fehri
body: When a network is being switched within a dapp we need to set the correct tokenNetworkFilter so that the portfolio components returns the right aggregated balance.

created_at: 2025-02-27T08:45:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,21 +1,73 @@
 import React from 'react';
-
 import renderWithProvider from '../../../../../../../util/test/renderWithProvider';
 import { personalSignatureConfirmationState } from '../../../../../../../util/test/confirm-data-helpers';
 import AccountNetworkInfoExpanded from './AccountNetworkInfoExpanded';
+import { useMultichainBalances } from '../../../../../../hooks/useMultichainBalances';
 
 jest.mock('../../../../../../../core/Engine', () => ({
   getTotalFiatAccountBalance: () => ({ tokenFiat: 10 }),
 }));
 
+jest.mock('../../../../../../hooks/useMultichainBalances', () => ({
+  useMultichainBalances: jest.fn(),
+}));
+
+const mockedUseMultichainBalances = useMultichainBalances as jest.Mock;
+
 describe('AccountNetworkInfoExpanded', () => {
-  it('should render correctly', async () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('should match snapshot when isPortfolioVieEnabled is true', () => {
+    mockedUseMultichainBalances.mockReturnValue({
+      multichainBalances: {
+        isPortfolioVieEnabled: true,
+        displayBalance: '$100',
+      },
+    });
+    const { toJSON } = renderWithProvider(<AccountNetworkInfoExpanded />, {
+      state: personalSignatureConfirmationState,
+    });
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('should render correctly when isPortfolioVieEnabled is true', async () => {
+    mockedUseMultichainBalances.mockReturnValue({
+      multichainBalances: {
+        isPortfolioVieEnabled: true,
+        displayBalance: '$100',
+      },
+    });
     const { getByText } = renderWithProvider(<AccountNetworkInfoExpanded />, {
       state: personalSignatureConfirmationState,
     });
     expect(getByText('Account')).toBeDefined();
     expect(getByText('Balance')).toBeDefined();
-    expect(getByText('$10')).toBeDefined();
+    expect(getByText('$100')).toBeDefined();
+    expect(getByText('Network')).toBeDefined();
+    expect(getByText('Ethereum Mainnet')).toBeDefined();
+  });
path: app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
user: login: OGPoyraz
body: Does it make sense to merge these tests if they are using same state? We can have snapshot matcher and assertions in the same test. 
created_at: 2025-03-03T08:25:32Z
author_association: MEMBER
diff_hunk: @@ -1,21 +1,73 @@
 import React from 'react';
-
 import renderWithProvider from '../../../../../../../util/test/renderWithProvider';
 import { personalSignatureConfirmationState } from '../../../../../../../util/test/confirm-data-helpers';
 import AccountNetworkInfoExpanded from './AccountNetworkInfoExpanded';
+import { useMultichainBalances } from '../../../../../../hooks/useMultichainBalances';
 
 jest.mock('../../../../../../../core/Engine', () => ({
   getTotalFiatAccountBalance: () => ({ tokenFiat: 10 }),
 }));
 
+jest.mock('../../../../../../hooks/useMultichainBalances', () => ({
+  useMultichainBalances: jest.fn(),
+}));
+
+const mockedUseMultichainBalances = useMultichainBalances as jest.Mock;
+
 describe('AccountNetworkInfoExpanded', () => {
-  it('should render correctly', async () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('should match snapshot when isPortfolioVieEnabled is true', () => {
+    mockedUseMultichainBalances.mockReturnValue({
+      multichainBalances: {
+        isPortfolioVieEnabled: true,
+        displayBalance: '$100',
+      },
+    });
+    const { toJSON } = renderWithProvider(<AccountNetworkInfoExpanded />, {
+      state: personalSignatureConfirmationState,
+    });
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('should render correctly when isPortfolioVieEnabled is true', async () => {
+    mockedUseMultichainBalances.mockReturnValue({
+      multichainBalances: {
+        isPortfolioVieEnabled: true,
+        displayBalance: '$100',
+      },
+    });
     const { getByText } = renderWithProvider(<AccountNetworkInfoExpanded />, {
       state: personalSignatureConfirmationState,
     });
     expect(getByText('Account')).toBeDefined();
     expect(getByText('Balance')).toBeDefined();
-    expect(getByText('$10')).toBeDefined();
+    expect(getByText('$100')).toBeDefined();
+    expect(getByText('Network')).toBeDefined();
+    expect(getByText('Ethereum Mainnet')).toBeDefined();
+  });
+
+  it('should render correctly when isPortfolioVieEnabled is false', async () => {
+    mockedUseMultichainBalances.mockReturnValue({
+      multichainBalances: {
+        isPortfolioVieEnabled: false,
+        displayBalance: '$100',
+      },
+    });
+    const { queryByText, getByText } = renderWithProvider(
+      <AccountNetworkInfoExpanded />,
+      {
+        state: personalSignatureConfirmationState,
+      },
+    );
+    // Depending on your component's behavior when the portfolio view is disabled,
+    // adjust the assertion accordingly. Here we assume '$100' is not rendered.
+    expect(queryByText('$100')).toBeNull();
path: app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
user: login: OGPoyraz
body: I think even if `$100` is rendered, `expect(getByText('$10')).toBeDefined();` will throw. 
So it doesn't hurt to have null assertion here but we can also add `expect(getByText('$10')).toBeDefined();` with ease.
created_at: 2025-03-03T08:30:01Z
author_association: MEMBER
diff_hunk: @@ -1,21 +1,73 @@
 import React from 'react';
-
 import renderWithProvider from '../../../../../../../util/test/renderWithProvider';
 import { personalSignatureConfirmationState } from '../../../../../../../util/test/confirm-data-helpers';
 import AccountNetworkInfoExpanded from './AccountNetworkInfoExpanded';
+import { useMultichainBalances } from '../../../../../../hooks/useMultichainBalances';
 
 jest.mock('../../../../../../../core/Engine', () => ({
   getTotalFiatAccountBalance: () => ({ tokenFiat: 10 }),
 }));
 
+jest.mock('../../../../../../hooks/useMultichainBalances', () => ({
+  useMultichainBalances: jest.fn(),
path: app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
user: login: OGPoyraz
body: Can we avoid mocking this hook in the tests? I know it's a big hook that collects bunch of different state pieces. But mocking here assuming changes will work properly on upcoming iterations - which we (Confirmations as codeowners) cannot follow what's being updated. 

From exact same reasons - we are using `personalSignatureConfirmationState`, so any updates on selectors or other hooks will break this test meaning that guarantees the flow. 
created_at: 2025-03-03T08:41:37Z
author_association: MEMBER
diff_hunk: @@ -8,14 +8,23 @@ jest.mock('../../../../../../../core/Engine', () => ({
   getTotalFiatAccountBalance: () => ({ tokenFiat: 10 }),
 }));
 
+jest.mock('../../../../../../hooks/useMultichainBalances', () => ({
+  useMultichainBalances: () => ({
+    multichainBalances: {
+      isPortfolioVieEnabled: true,
+      displayBalance: '$100',
+    },
+  }),
path: app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
user: login: OGPoyraz
body: I think we must encourage devs to do that. I can feel the pain - but it's not hard to collect those data. One can add a state logger then eliminate unneeded state. Once you have those data helpers on your hand (like https://github.com/MetaMask/metamask-mobile/blob/main/app/util/test/confirm-data-helpers.ts#L46) it guarantees you that your code will work as expected - or fail as expected on dependency changes. 
created_at: 2025-03-03T08:52:47Z
author_association: MEMBER
diff_hunk: @@ -1,21 +1,44 @@
 import React from 'react';
-
 import renderWithProvider from '../../../../../../../util/test/renderWithProvider';
 import { personalSignatureConfirmationState } from '../../../../../../../util/test/confirm-data-helpers';
 import AccountNetworkInfoExpanded from './AccountNetworkInfoExpanded';
+// eslint-disable-next-line import/no-namespace
+import * as networks from '../../../../../../../util/networks';
 
 jest.mock('../../../../../../../core/Engine', () => ({
   getTotalFiatAccountBalance: () => ({ tokenFiat: 10 }),
 }));
 
 describe('AccountNetworkInfoExpanded', () => {
-  it('should render correctly', async () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('should match snapshot when isPortfolioVieEnabled is true', () => {
+    jest.spyOn(networks, 'isPortfolioViewEnabled').mockReturnValue(true);
+    const { toJSON, getByText } = renderWithProvider(
+      <AccountNetworkInfoExpanded />,
+      {
+        state: personalSignatureConfirmationState,
+      },
+    );
+    expect(toJSON()).toMatchSnapshot();
+    expect(getByText('Account')).toBeDefined();
+    expect(getByText('Balance')).toBeDefined();
+    expect(getByText('$0')).toBeDefined();
+    expect(getByText('Network')).toBeDefined();
+    expect(getByText('Ethereum Mainnet')).toBeDefined();
+  });
+
+  it('should render correctly when isPortfolioVieEnabled is false', async () => {
+    jest.spyOn(networks, 'isPortfolioViewEnabled').mockReturnValue(false);
     const { getByText } = renderWithProvider(<AccountNetworkInfoExpanded />, {
       state: personalSignatureConfirmationState,
     });
+
+    // The rest of the UI should still render.
path: app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
user: login: OGPoyraz
body: Can we remove unnecessary additions here?
created_at: 2025-03-03T10:43:33Z
author_association: MEMBER
diff_hunk: @@ -1,21 +1,44 @@
 import React from 'react';
-
 import renderWithProvider from '../../../../../../../util/test/renderWithProvider';
 import { personalSignatureConfirmationState } from '../../../../../../../util/test/confirm-data-helpers';
 import AccountNetworkInfoExpanded from './AccountNetworkInfoExpanded';
+// eslint-disable-next-line import/no-namespace
+import * as networks from '../../../../../../../util/networks';
 
 jest.mock('../../../../../../../core/Engine', () => ({
   getTotalFiatAccountBalance: () => ({ tokenFiat: 10 }),
 }));
 
 describe('AccountNetworkInfoExpanded', () => {
-  it('should render correctly', async () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('should match snapshot when isPortfolioVieEnabled is true', () => {
+    jest.spyOn(networks, 'isPortfolioViewEnabled').mockReturnValue(true);
+    const { toJSON, getByText } = renderWithProvider(
+      <AccountNetworkInfoExpanded />,
+      {
+        state: personalSignatureConfirmationState,
+      },
+    );
+    expect(toJSON()).toMatchSnapshot();
+    expect(getByText('Account')).toBeDefined();
+    expect(getByText('Balance')).toBeDefined();
+    expect(getByText('$0')).toBeDefined();
+    expect(getByText('Network')).toBeDefined();
+    expect(getByText('Ethereum Mainnet')).toBeDefined();
+  });
+
+  it('should render correctly when isPortfolioVieEnabled is false', async () => {
+    jest.spyOn(networks, 'isPortfolioViewEnabled').mockReturnValue(false);
     const { getByText } = renderWithProvider(<AccountNetworkInfoExpanded />, {
       state: personalSignatureConfirmationState,
     });
+
+    // The rest of the UI should still render.
     expect(getByText('Account')).toBeDefined();
     expect(getByText('Balance')).toBeDefined();
-    expect(getByText('$10')).toBeDefined();
path: app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
user: login: OGPoyraz
body: Can we put back this assertion?
created_at: 2025-03-03T10:44:00Z
author_association: MEMBER
diff_hunk: @@ -1,21 +1,44 @@
 import React from 'react';
-
 import renderWithProvider from '../../../../../../../util/test/renderWithProvider';
 import { personalSignatureConfirmationState } from '../../../../../../../util/test/confirm-data-helpers';
 import AccountNetworkInfoExpanded from './AccountNetworkInfoExpanded';
+// eslint-disable-next-line import/no-namespace
+import * as networks from '../../../../../../../util/networks';
path: app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx
user: login: OGPoyraz
body: Can we remove this eslint-disabler and mock necessary piece here?
I can't suggest with Github tool because of the removed line but here is the final suggestion.

```js
import React from 'react';
import renderWithProvider from '../../../../../../../util/test/renderWithProvider';
import { personalSignatureConfirmationState } from '../../../../../../../util/test/confirm-data-helpers';
import AccountNetworkInfoExpanded from './AccountNetworkInfoExpanded';
import { isPortfolioViewEnabled } from '../../../../../../../util/networks';

jest.mock('../../../../../../../util/networks', () => ({
  ...jest.requireActual('../../../../../../../util/networks'),
  isPortfolioViewEnabled: jest.fn(),
}));

jest.mock('../../../../../../../core/Engine', () => ({
  getTotalFiatAccountBalance: () => ({ tokenFiat: 10 }),
}));

describe('AccountNetworkInfoExpanded', () => {
  const mockIsPortfolioViewEnabled = jest.mocked(isPortfolioViewEnabled);

  beforeEach(() => {
    jest.clearAllMocks();
    mockIsPortfolioViewEnabled.mockReturnValue(false);
  });

  it('should match snapshot when isPortfolioVieEnabled is true', () => {
    mockIsPortfolioViewEnabled.mockReturnValue(true);
    const { toJSON, getByText } = renderWithProvider(
      <AccountNetworkInfoExpanded />,
      {
        state: personalSignatureConfirmationState,
      },
    );
    expect(toJSON()).toMatchSnapshot();
    expect(getByText('Account')).toBeDefined();
    expect(getByText('Balance')).toBeDefined();
    expect(getByText('$0')).toBeDefined();
    expect(getByText('Network')).toBeDefined();
    expect(getByText('Ethereum Mainnet')).toBeDefined();
  });

  it('should render correctly when isPortfolioVieEnabled is false', async () => {
    const { getByText } = renderWithProvider(<AccountNetworkInfoExpanded />, {
      state: personalSignatureConfirmationState,
    });

    expect(getByText('$10')).toBeDefined();
    expect(getByText('Account')).toBeDefined();
    expect(getByText('Balance')).toBeDefined();
    expect(getByText('Network')).toBeDefined();
    expect(getByText('Ethereum Mainnet')).toBeDefined();
  });
});
```
created_at: 2025-03-03T10:53:31Z
author_association: MEMBER

PR comments:
user: login: github-actions[bot]
created_at: 2025-02-26T18:12:41Z
body: **CLA Signature Action:** All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-02-26T18:14:04Z
body: ## [<img alt="https://bitrise.io/" src="https://assets-global.website-files.com/5db35de024bb983af1b4e151/5e6f9ccc3e129dfd8a205e4e_Bitrise%20Logo%20-%20Eggplant%20Bg.png" height="20">](https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/37320427-7103-4055-80aa-743634ecbcb8) **Bitrise**

❌❌❌ `pr_smoke_e2e_pipeline` failed on Bitrise! ❌❌❌

Commit hash: d5750465b3369c946b961e7f423b86e84551227d
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/37320427-7103-4055-80aa-743634ecbcb8

>[!NOTE]
>- You can kick off another `pr_smoke_e2e_pipeline` on Bitrise by removing and re-applying the `Run Smoke E2E` label on the pull request

> [!TIP]
>- Check the [documentation](https://www.notion.so/metamask-consensys/Bitrise-Pipeline-Overview-43159500c43748a389556f0593e8834b#26052f2ea6e24f8c9cfdb57a7522dc1f) if you have any doubts on how to understand the failure on bitrise

<!-- BITRISE_TAG -->
<!-- BITRISE_FAIL_TAG -->

<!-- d5750465b3369c946b961e7f423b86e84551227d -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-02-26T22:42:16Z
body: ## [<img alt="https://bitrise.io/" src="https://assets-global.website-files.com/5db35de024bb983af1b4e151/5e6f9ccc3e129dfd8a205e4e_Bitrise%20Logo%20-%20Eggplant%20Bg.png" height="20">](https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/bb4bc0df-76ce-4481-bdb0-585eb88cd879) **Bitrise**

❌❌❌ `pr_smoke_e2e_pipeline` failed on Bitrise! ❌❌❌

Commit hash: ab5960a47f59e77be6c15f042f611e95602923f4
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/bb4bc0df-76ce-4481-bdb0-585eb88cd879

>[!NOTE]
>- You can kick off another `pr_smoke_e2e_pipeline` on Bitrise by removing and re-applying the `Run Smoke E2E` label on the pull request

> [!TIP]
>- Check the [documentation](https://www.notion.so/metamask-consensys/Bitrise-Pipeline-Overview-43159500c43748a389556f0593e8834b#26052f2ea6e24f8c9cfdb57a7522dc1f) if you have any doubts on how to understand the failure on bitrise

<!-- BITRISE_TAG -->
<!-- BITRISE_FAIL_TAG -->

<!-- ab5960a47f59e77be6c15f042f611e95602923f4 -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-02-26T23:54:44Z
body: ## [<img alt="https://bitrise.io/" src="https://assets-global.website-files.com/5db35de024bb983af1b4e151/5e6f9ccc3e129dfd8a205e4e_Bitrise%20Logo%20-%20Eggplant%20Bg.png" height="20">](https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/62a945c4-b0d7-46ef-88ae-ede53e0c9e0a) **Bitrise**

❌❌❌ `pr_smoke_e2e_pipeline` failed on Bitrise! ❌❌❌

Commit hash: bb03cd08d3f03a03302f4188e9f63d330c217d59
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/62a945c4-b0d7-46ef-88ae-ede53e0c9e0a

>[!NOTE]
>- You can kick off another `pr_smoke_e2e_pipeline` on Bitrise by removing and re-applying the `Run Smoke E2E` label on the pull request

> [!TIP]
>- Check the [documentation](https://www.notion.so/metamask-consensys/Bitrise-Pipeline-Overview-43159500c43748a389556f0593e8834b#26052f2ea6e24f8c9cfdb57a7522dc1f) if you have any doubts on how to understand the failure on bitrise

<!-- BITRISE_TAG -->
<!-- BITRISE_FAIL_TAG -->

<!-- bb03cd08d3f03a03302f4188e9f63d330c217d59 -->
author_association: CONTRIBUTOR
user: login: sleepytanya
created_at: 2025-02-27T17:29:34Z
body: @sahar-fehri @salimtb 

Fixed!

Android prod build: https://app.bitrise.io/build/2823e9a0-0af9-4606-a2b4-3b3988dcd15c?tab=artifacts


https://github.com/user-attachments/assets/d6fd145b-50fd-4944-9845-08bbb2589eab

<img width="1363" alt="Screenshot 2025-02-27 at 12 28 30" src="https://github.com/user-attachments/assets/3ad05fed-896b-427d-8e98-7315b5357b9f" />


author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-02-27T23:06:04Z
body: ## [<img alt="https://bitrise.io/" src="https://assets-global.website-files.com/5db35de024bb983af1b4e151/5e6f9ccc3e129dfd8a205e4e_Bitrise%20Logo%20-%20Eggplant%20Bg.png" height="20">](https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/6b8c609d-0c65-4dda-9c82-29cf62fa6f57) **Bitrise**

❌❌❌ `pr_smoke_e2e_pipeline` failed on Bitrise! ❌❌❌

Commit hash: 507eb2dadb3ec776a4afd6630b5ef4891abce8ce
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/6b8c609d-0c65-4dda-9c82-29cf62fa6f57

>[!NOTE]
>- You can kick off another `pr_smoke_e2e_pipeline` on Bitrise by removing and re-applying the `Run Smoke E2E` label on the pull request

> [!TIP]
>- Check the [documentation](https://www.notion.so/metamask-consensys/Bitrise-Pipeline-Overview-43159500c43748a389556f0593e8834b#26052f2ea6e24f8c9cfdb57a7522dc1f) if you have any doubts on how to understand the failure on bitrise

<!-- BITRISE_TAG -->
<!-- BITRISE_FAIL_TAG -->

<!-- 507eb2dadb3ec776a4afd6630b5ef4891abce8ce -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-02-28T13:25:35Z
body: ## [<img alt="https://bitrise.io/" src="https://assets-global.website-files.com/5db35de024bb983af1b4e151/5e6f9ccc3e129dfd8a205e4e_Bitrise%20Logo%20-%20Eggplant%20Bg.png" height="20">](https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/62821681-0951-4908-9c63-9fe7be7a92f2) **Bitrise**

❌❌❌ `pr_smoke_e2e_pipeline` failed on Bitrise! ❌❌❌

Commit hash: aaf1ee89715738166c0e9ae27545941be27545bc
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/62821681-0951-4908-9c63-9fe7be7a92f2

>[!NOTE]
>- You can kick off another `pr_smoke_e2e_pipeline` on Bitrise by removing and re-applying the `Run Smoke E2E` label on the pull request

> [!TIP]
>- Check the [documentation](https://www.notion.so/metamask-consensys/Bitrise-Pipeline-Overview-43159500c43748a389556f0593e8834b#26052f2ea6e24f8c9cfdb57a7522dc1f) if you have any doubts on how to understand the failure on bitrise

<!-- BITRISE_TAG -->
<!-- BITRISE_FAIL_TAG -->

<!-- aaf1ee89715738166c0e9ae27545941be27545bc -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-02-28T14:05:48Z
body: ## [<img alt="https://bitrise.io/" src="https://assets-global.website-files.com/5db35de024bb983af1b4e151/5e6f9ccc3e129dfd8a205e4e_Bitrise%20Logo%20-%20Eggplant%20Bg.png" height="20">](https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/e1d3c93e-7f72-4e5d-beb8-3251c9001186) **Bitrise**

❌❌❌ `pr_smoke_e2e_pipeline` failed on Bitrise! ❌❌❌

Commit hash: cdcd7ebeff6286f9204b9bc7a15593919d143395
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/e1d3c93e-7f72-4e5d-beb8-3251c9001186

>[!NOTE]
>- You can kick off another `pr_smoke_e2e_pipeline` on Bitrise by removing and re-applying the `Run Smoke E2E` label on the pull request

> [!TIP]
>- Check the [documentation](https://www.notion.so/metamask-consensys/Bitrise-Pipeline-Overview-43159500c43748a389556f0593e8834b#26052f2ea6e24f8c9cfdb57a7522dc1f) if you have any doubts on how to understand the failure on bitrise

<!-- BITRISE_TAG -->
<!-- BITRISE_FAIL_TAG -->

<!-- cdcd7ebeff6286f9204b9bc7a15593919d143395 -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-03T10:19:03Z
body: ## [<img alt="https://bitrise.io/" src="https://assets-global.website-files.com/5db35de024bb983af1b4e151/5e6f9ccc3e129dfd8a205e4e_Bitrise%20Logo%20-%20Eggplant%20Bg.png" height="20">](https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/979eb483-a798-4aa9-ac59-6298a66887bb) **Bitrise**

❌❌❌ `pr_smoke_e2e_pipeline` failed on Bitrise! ❌❌❌

Commit hash: 986f1476ed55863893b79c95037b87cccdd6277b
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/979eb483-a798-4aa9-ac59-6298a66887bb

>[!NOTE]
>- You can kick off another `pr_smoke_e2e_pipeline` on Bitrise by removing and re-applying the `Run Smoke E2E` label on the pull request

> [!TIP]
>- Check the [documentation](https://www.notion.so/metamask-consensys/Bitrise-Pipeline-Overview-43159500c43748a389556f0593e8834b#26052f2ea6e24f8c9cfdb57a7522dc1f) if you have any doubts on how to understand the failure on bitrise

<!-- BITRISE_TAG -->
<!-- BITRISE_FAIL_TAG -->

<!-- 986f1476ed55863893b79c95037b87cccdd6277b -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-03T13:08:58Z
body: ## [<img alt="https://bitrise.io/" src="https://assets-global.website-files.com/5db35de024bb983af1b4e151/5e6f9ccc3e129dfd8a205e4e_Bitrise%20Logo%20-%20Eggplant%20Bg.png" height="20">](https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/e4e5edeb-6089-48f0-8763-61523a5aff03) **Bitrise**

✅✅✅ `pr_smoke_e2e_pipeline` passed on Bitrise! ✅✅✅

Commit hash: 3cd0a2924b7e607a18170c2333bb1d232eb234d5
Build link: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/e4e5edeb-6089-48f0-8763-61523a5aff03

>[!NOTE]
>- You can kick off another `pr_smoke_e2e_pipeline` on Bitrise by removing and re-applying the `Run Smoke E2E` label on the pull request

<!-- BITRISE_TAG -->
<!-- BITRISE_SUCCESS_TAG -->

<!-- 3cd0a2924b7e607a18170c2333bb1d232eb234d5 -->
author_association: CONTRIBUTOR
user: login: sonarqubecloud[bot]
created_at: 2025-03-03T13:18:19Z
body: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=metamask-mobile&pullRequest=13740) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [42.1% Coverage on New Code](https://sonarcloud.io/component_measures?id=metamask-mobile&pullRequest=13740&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=metamask-mobile&pullRequest=13740)


author_association: NONE