From 15ad0b21c75e3b363d300a70541776718afa95e9 Mon Sep 17 00:00:00 2001
From: Ariella Vu <20778143+digiwand@users.noreply.github.com>
Date: Fri, 19 Apr 2024 20:40:01 +0400
Subject: [PATCH] feat: add Signature Redesign "Account Details Opened" event
(#24095)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Adds "Account Details Opened" event when Account Info Icon in
Confirmation Redesign is clicked
Internal Thread
https://consensys.slack.com/archives/C03ETQA9EPK/p1710437328642929
Event Description
https://www.notion.so/Account-Details-Opened-3deec398d4784bcea00b012cdf1cde03?pvs=4
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/24095?quickstart=1)
## **Related issues**
Fixes: https://github.com/MetaMask/metamask-extension/issues/23555
## **Manual testing steps**
1. set `
ENABLE_CONFIRMATION_REDESIGN=true` in .metamaskrc
2. Turn on MetaMetrics in settings
3. Use test-dapp to test feature in a signature confirmation
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [ ] I’ve followed [MetaMask Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.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-extension/blob/develop/.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.
---
shared/constants/metametrics.ts | 3 +-
.../menu-items/account-details-menu-item.js | 2 +-
.../confirm/header/header-info.test.tsx | 77 ++++++++++++-------
.../components/confirm/header/header-info.tsx | 34 +++++++-
4 files changed, 85 insertions(+), 31 deletions(-)
diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts
index 9017381f7419..f4a012cf0127 100644
--- a/shared/constants/metametrics.ts
+++ b/shared/constants/metametrics.ts
@@ -499,6 +499,7 @@ export enum MetaMetricsEventName {
AccountAdded = 'Account Added',
AccountAddSelected = 'Account Add Selected',
AccountAddFailed = 'Account Add Failed',
+ AccountDetailsOpened = 'Account Details Opened',
AccountPasswordCreated = 'Account Password Created',
AccountReset = 'Account Reset',
AccountRenamed = 'Account Renamed',
@@ -539,7 +540,6 @@ export enum MetaMetricsEventName {
MetricsOptIn = 'Metrics Opt In',
MetricsOptOut = 'Metrics Opt Out',
NavAccountMenuOpened = 'Account Menu Opened',
- NavAccountDetailsOpened = 'Account Details Opened',
NavConnectedSitesOpened = 'Connected Sites Opened',
NavMainMenuOpened = 'Main Menu Opened',
NavPermissionsOpened = 'Permissions Opened',
@@ -784,6 +784,7 @@ export enum MetaMetricsTransactionEventSource {
}
export enum MetaMetricsEventLocation {
+ SignatureConfirmation = 'signature_confirmation',
TokenDetails = 'token_details',
TokenDetection = 'token_detection',
TokenMenu = 'token_menu',
diff --git a/ui/components/multichain/menu-items/account-details-menu-item.js b/ui/components/multichain/menu-items/account-details-menu-item.js
index 3a2af09d1536..4cd0ae165c9c 100644
--- a/ui/components/multichain/menu-items/account-details-menu-item.js
+++ b/ui/components/multichain/menu-items/account-details-menu-item.js
@@ -30,7 +30,7 @@ export const AccountDetailsMenuItem = ({
onClick={() => {
dispatch(setAccountDetailsAddress(address));
trackEvent({
- event: MetaMetricsEventName.NavAccountDetailsOpened,
+ event: MetaMetricsEventName.AccountDetailsOpened,
category: MetaMetricsEventCategory.Navigation,
properties: {
location: metricsLocation,
diff --git a/ui/pages/confirmations/components/confirm/header/header-info.test.tsx b/ui/pages/confirmations/components/confirm/header/header-info.test.tsx
index d88d298c66bc..ef43b98c69a0 100644
--- a/ui/pages/confirmations/components/confirm/header/header-info.test.tsx
+++ b/ui/pages/confirmations/components/confirm/header/header-info.test.tsx
@@ -3,24 +3,33 @@ import React from 'react';
import { fireEvent, waitFor } from '@testing-library/react';
import mockState from '../../../../../../test/data/mock-state.json';
import { renderWithProvider } from '../../../../../../test/jest';
+import { MetaMetricsContext } from '../../../../../contexts/metametrics';
import configureStore from '../../../../../store/store';
+import {
+ MetaMetricsEventCategory,
+ MetaMetricsEventLocation,
+ MetaMetricsEventName,
+} from '../../../../../../shared/constants/metametrics';
+
import HeaderInfo from './header-info';
-const render = () => {
- const store = configureStore({
- metamask: {
- ...mockState.metamask,
- },
- confirm: {
- currentConfirmation: {
- msgParams: {
- from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
- },
+const mockStore = {
+ metamask: {
+ ...mockState.metamask,
+ },
+ confirm: {
+ currentConfirmation: {
+ msgParams: {
+ from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
},
+ type: 'eth_signTypedData_v4',
},
- });
+ },
+};
+const render = () => {
+ const store = configureStore(mockStore);
return renderWithProvider(, store);
};
@@ -33,22 +42,38 @@ describe('Header', () => {
const { getByLabelText } = render();
expect(getByLabelText('Account details')).toBeInTheDocument();
});
- it('shows modal when account info icon is clicked', async () => {
- const { getByLabelText, queryByTestId } = render();
- expect(queryByTestId('account-details-modal')).not.toBeInTheDocument();
- const accountInfoIcon = getByLabelText('Account details');
- fireEvent.click(accountInfoIcon);
- await waitFor(() => {
- expect(queryByTestId('account-details-modal')).toBeInTheDocument();
+
+ describe('when account info icon is clicked', () => {
+ it('shows account info modal with address', async () => {
+ const { getByLabelText, getByText, queryByTestId } = render();
+ const accountInfoIcon = getByLabelText('Account details');
+ fireEvent.click(accountInfoIcon);
+ await waitFor(() => {
+ expect(queryByTestId('account-details-modal')).toBeInTheDocument();
+ expect(getByText('0x0DCD5...3E7bc')).toBeInTheDocument();
+ });
});
- });
- it('shows account info modal with address', async () => {
- const { getByLabelText, getByText, queryByTestId } = render();
- const accountInfoIcon = getByLabelText('Account details');
- fireEvent.click(accountInfoIcon);
- await waitFor(() => {
- expect(queryByTestId('account-details-modal')).toBeInTheDocument();
- expect(getByText('0x0DCD5...3E7bc')).toBeInTheDocument();
+
+ it(`sends "${MetaMetricsEventName.AccountDetailsOpened}" metametric`, () => {
+ const mockTrackEvent = jest.fn();
+ const { getByLabelText } = renderWithProvider(
+
+
+ ,
+ configureStore(mockStore),
+ );
+ const accountInfoIcon = getByLabelText('Account details');
+ fireEvent.click(accountInfoIcon);
+
+ expect(mockTrackEvent).toHaveBeenNthCalledWith(1, {
+ category: MetaMetricsEventCategory.Transactions,
+ event: MetaMetricsEventName.AccountDetailsOpened,
+ properties: {
+ action: 'Confirm Screen',
+ location: MetaMetricsEventLocation.SignatureConfirmation,
+ signature_type: 'eth_signTypedData_v4',
+ },
+ });
});
});
});
diff --git a/ui/pages/confirmations/components/confirm/header/header-info.tsx b/ui/pages/confirmations/components/confirm/header/header-info.tsx
index 3b8fba52e01f..67a6867a0089 100644
--- a/ui/pages/confirmations/components/confirm/header/header-info.tsx
+++ b/ui/pages/confirmations/components/confirm/header/header-info.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useContext } from 'react';
import { useSelector } from 'react-redux';
import {
AvatarAccount,
@@ -27,20 +27,45 @@ import { AddressCopyButton } from '../../../../../components/multichain';
import Tooltip from '../../../../../components/ui/tooltip/tooltip';
import { useI18nContext } from '../../../../../hooks/useI18nContext';
import useConfirmationRecipientInfo from '../../../hooks/useConfirmationRecipientInfo';
-import { getUseBlockie } from '../../../../../selectors';
+
+import {
+ currentConfirmationSelector,
+ getUseBlockie,
+} from '../../../../../selectors';
+import {
+ MetaMetricsEventCategory,
+ MetaMetricsEventLocation,
+ MetaMetricsEventName,
+} from '../../../../../../shared/constants/metametrics';
+import { MetaMetricsContext } from '../../../../../contexts/metametrics';
import { ConfirmInfoRowCurrency } from '../../../../../components/app/confirm/info/row/currency';
import { useBalance } from '../../../hooks/useBalance';
const HeaderInfo = () => {
const useBlockie = useSelector(getUseBlockie);
const [showAccountInfo, setShowAccountInfo] = React.useState(false);
+
+ const currentConfirmation = useSelector(currentConfirmationSelector);
const { recipientAddress: fromAddress, recipientName: fromName } =
useConfirmationRecipientInfo();
const t = useI18nContext();
+ const trackEvent = useContext(MetaMetricsContext);
const { balance: balanceToUse } = useBalance(fromAddress);
+ function trackAccountModalOpened() {
+ trackEvent({
+ category: MetaMetricsEventCategory.Transactions,
+ event: MetaMetricsEventName.AccountDetailsOpened,
+ properties: {
+ action: 'Confirm Screen',
+ location: MetaMetricsEventLocation.SignatureConfirmation,
+ signature_type: currentConfirmation?.type,
+ },
+ });
+ }
+
return (
<>
{
ariaLabel={t('accountDetails')}
iconName={IconName.Info}
size={ButtonIconSize.Md}
- onClick={() => setShowAccountInfo(true)}
+ onClick={() => {
+ trackAccountModalOpened();
+ setShowAccountInfo(true);
+ }}
/>