Skip to content

Commit

Permalink
Merge branch 'develop' into chore/bump-assets-controller
Browse files Browse the repository at this point in the history
  • Loading branch information
sahar-fehri committed May 7, 2024
2 parents d13aff2 + 4519cac commit e87e242
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 20 deletions.
26 changes: 23 additions & 3 deletions app/scripts/lib/createRPCMethodTrackingMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import {
///: BEGIN:ONLY_INCLUDE_IF(blockaid)
import { SIGNING_METHODS } from '../../../shared/constants/transaction';

import {
REDESIGN_APPROVAL_TYPES,
REDESIGN_TRANSACTION_TYPES,
} from '../../../ui/pages/confirmations/utils/confirm';
import { getBlockaidMetricsProps } from '../../../ui/helpers/utils/metrics';
///: END:ONLY_INCLUDE_IF
import { getSnapAndHardwareInfoForMetrics } from './snap-keyring/metrics';
Expand Down Expand Up @@ -129,6 +133,7 @@ let globalRateLimitCount = 0;
* that should be tracked for methods rate limited by random sample.
* @param {Function} opts.getAccountType
* @param {Function} opts.getDeviceModel
* @param {Function} opts.isConfirmationRedesignEnabled
* @param {RestrictedControllerMessenger} opts.snapAndHardwareMessenger
* @param {AppStateController} opts.appStateController
* @param {number} [opts.globalRateLimitTimeout] - time, in milliseconds, of the sliding
Expand All @@ -148,6 +153,7 @@ export default function createRPCMethodTrackingMiddleware({
globalRateLimitMaxAmount = 10, // max of events in the globalRateLimitTimeout window. pass 0 for no global rate limit
getAccountType,
getDeviceModel,
isConfirmationRedesignEnabled,
snapAndHardwareMessenger,
///: BEGIN:ONLY_INCLUDE_IF(blockaid)
appStateController,
Expand Down Expand Up @@ -252,6 +258,19 @@ export default function createRPCMethodTrackingMiddleware({
}
///: END:ONLY_INCLUDE_IF

const isConfirmationRedesign =
isConfirmationRedesignEnabled() &&
[...REDESIGN_APPROVAL_TYPES, ...REDESIGN_TRANSACTION_TYPES].find(
(type) => type === method,
);

if (isConfirmationRedesign) {
eventProperties.ui_customizations = [
...(eventProperties.ui_customizations || []),
MetaMetricsEventUiCustomization.RedesignedConfirmation,
];
}

const snapAndHardwareInfo = await getSnapAndHardwareInfoForMetrics(
getAccountType,
getDeviceModel,
Expand All @@ -265,9 +284,10 @@ export default function createRPCMethodTrackingMiddleware({
if (method === MESSAGE_TYPE.PERSONAL_SIGN) {
const { isSIWEMessage } = detectSIWE({ data });
if (isSIWEMessage) {
eventProperties.ui_customizations = (
eventProperties.ui_customizations || []
).concat(MetaMetricsEventUiCustomization.Siwe);
eventProperties.ui_customizations = [
...(eventProperties.ui_customizations || []),
MetaMetricsEventUiCustomization.Siwe,
];
}
}
} catch (e) {
Expand Down
75 changes: 67 additions & 8 deletions app/scripts/lib/createRPCMethodTrackingMiddleware.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { errorCodes } from 'eth-rpc-errors';
import { detectSIWE } from '@metamask/controller-utils';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
MetaMetricsEventUiCustomization,
} from '../../../shared/constants/metametrics';
Expand Down Expand Up @@ -43,6 +44,7 @@ const createHandler = (opts) =>
globalRateLimitTimeout: 0,
globalRateLimitMaxAmount: 0,
appStateController,
isConfirmationRedesignEnabled: () => false,
...opts,
});

Expand Down Expand Up @@ -156,7 +158,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
await handler(req, res, next);
expect(trackEvent).toHaveBeenCalledTimes(1);
expect(trackEvent.mock.calls[0][0]).toMatchObject({
category: 'inpage_provider',
category: MetaMetricsEventCategory.InpageProvider,
event: MetaMetricsEventName.SignatureRequested,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN,
Expand Down Expand Up @@ -197,7 +199,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
*
*/
expect(trackEvent.mock.calls[0][0]).toStrictEqual({
category: 'inpage_provider',
category: MetaMetricsEventCategory.InpageProvider,
event: MetaMetricsEventName.SignatureRequested,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN,
Expand Down Expand Up @@ -225,7 +227,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
await executeMiddlewareStack();
expect(trackEvent).toHaveBeenCalledTimes(2);
expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: 'inpage_provider',
category: MetaMetricsEventCategory.InpageProvider,
event: MetaMetricsEventName.SignatureApproved,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4,
Expand All @@ -249,7 +251,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
await executeMiddlewareStack();
expect(trackEvent).toHaveBeenCalledTimes(2);
expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: 'inpage_provider',
category: MetaMetricsEventCategory.InpageProvider,
event: MetaMetricsEventName.SignatureRejected,
properties: {
signature_type: MESSAGE_TYPE.PERSONAL_SIGN,
Expand All @@ -271,7 +273,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
await executeMiddlewareStack();
expect(trackEvent).toHaveBeenCalledTimes(2);
expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: 'inpage_provider',
category: MetaMetricsEventCategory.InpageProvider,
event: MetaMetricsEventName.PermissionsApproved,
properties: { method: MESSAGE_TYPE.ETH_REQUEST_ACCOUNTS },
referrer: { url: 'some.dapp' },
Expand Down Expand Up @@ -416,6 +418,63 @@ describe('createRPCMethodTrackingMiddleware', () => {
});
});

it('should track Confirmation Redesign through ui_customizations prop if enabled', async () => {
const req = {
method: MESSAGE_TYPE.PERSONAL_SIGN,
origin: 'some.dapp',
};
const res = {
error: null,
};
const { next, executeMiddlewareStack } = getNext();
const handler = createHandler({
isConfirmationRedesignEnabled: () => true,
});

await handler(req, res, next);
await executeMiddlewareStack();

expect(trackEvent).toHaveBeenCalledTimes(2);

expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: MetaMetricsEventCategory.InpageProvider,
event: MetaMetricsEventName.SignatureApproved,
properties: {
signature_type: MESSAGE_TYPE.PERSONAL_SIGN,
ui_customizations: [
MetaMetricsEventUiCustomization.RedesignedConfirmation,
],
},
referrer: { url: 'some.dapp' },
});
});

it('should not track Confirmation Redesign through ui_customizations prop if not enabled', async () => {
const req = {
method: MESSAGE_TYPE.PERSONAL_SIGN,
origin: 'some.dapp',
};
const res = {
error: null,
};
const { next, executeMiddlewareStack } = getNext();
const handler = createHandler();

await handler(req, res, next);
await executeMiddlewareStack();

expect(trackEvent).toHaveBeenCalledTimes(2);

expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: MetaMetricsEventCategory.InpageProvider,
event: MetaMetricsEventName.SignatureApproved,
properties: {
signature_type: MESSAGE_TYPE.PERSONAL_SIGN,
},
referrer: { url: 'some.dapp' },
});
});

it('should track Sign-in With Ethereum (SIWE) message if detected', async () => {
const req = {
method: MESSAGE_TYPE.PERSONAL_SIGN,
Expand All @@ -437,7 +496,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent).toHaveBeenCalledTimes(2);

expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: 'inpage_provider',
category: MetaMetricsEventCategory.InpageProvider,
event: MetaMetricsEventName.SignatureApproved,
properties: {
signature_type: MESSAGE_TYPE.PERSONAL_SIGN,
Expand Down Expand Up @@ -466,7 +525,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent).toHaveBeenCalledTimes(2);

expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: 'inpage_provider',
category: MetaMetricsEventCategory.InpageProvider,
event: MetaMetricsEventName.SignatureFailed,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN,
Expand All @@ -493,7 +552,7 @@ describe('createRPCMethodTrackingMiddleware', () => {

expect(trackEvent).toHaveBeenCalledTimes(1);
expect(trackEvent.mock.calls[0][0]).toMatchObject({
category: 'inpage_provider',
category: MetaMetricsEventCategory.InpageProvider,
event: MetaMetricsEventName.SignatureRequested,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN,
Expand Down
9 changes: 9 additions & 0 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4895,6 +4895,14 @@ export default class MetamaskController extends EventEmitter {
);
///: END:ONLY_INCLUDE_IF

const isConfirmationRedesignEnabled = () => {
return (
process.env.ENABLE_CONFIRMATION_REDESIGN &&
this.preferencesController.store.getState().preferences
.redesignedConfirmations
);
};

engine.push(
createRPCMethodTrackingMiddleware({
trackEvent: this.metaMetricsController.trackEvent.bind(
Expand All @@ -4905,6 +4913,7 @@ export default class MetamaskController extends EventEmitter {
),
getAccountType: this.getAccountType.bind(this),
getDeviceModel: this.getDeviceModel.bind(this),
isConfirmationRedesignEnabled,
snapAndHardwareMessenger: this.controllerMessenger.getRestricted({
name: 'SnapAndHardwareMessenger',
allowedActions: [
Expand Down
1 change: 1 addition & 0 deletions shared/constants/metametrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,7 @@ export enum MetaMetricsEventUiCustomization {
FlaggedAsSafetyUnknown = 'flagged_as_safety_unknown',
FlaggedAsWarning = 'flagged_as_warning',
GasEstimationFailed = 'gas_estimation_failed',
RedesignedConfirmation = 'redesigned_confirmation',
SecurityAlertError = 'security_alert_error',
Siwe = 'sign_in_with_ethereum',
}
Expand Down
24 changes: 17 additions & 7 deletions ui/pages/confirmations/hooks/useCurrentConfirmation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ApprovalRequest } from '@metamask/approval-controller';
import { ApprovalType } from '@metamask/controller-utils';
import { TransactionType } from '@metamask/transaction-controller';
import { Json } from '@metamask/utils';
import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
Expand All @@ -11,6 +10,7 @@ import {
pendingConfirmationsSelector,
unconfirmedTransactionsHashSelector,
} from '../../../selectors';
import { REDESIGN_APPROVAL_TYPES, REDESIGN_TRANSACTION_TYPES } from '../utils';

type Approval = ApprovalRequest<Record<string, Json>>;

Expand Down Expand Up @@ -38,7 +38,9 @@ const useCurrentConfirmation = () => {
) {
return;
}

let pendingConfirmation: Approval | undefined;

if (paramsTransactionId) {
if (paramsTransactionId === currentConfirmation?.id) {
return;
Expand All @@ -47,29 +49,37 @@ const useCurrentConfirmation = () => {
({ id: confirmId }) => confirmId === paramsTransactionId,
);
}

if (!pendingConfirmation) {
if (!latestPendingConfirmation) {
setCurrentConfirmation(undefined);
return;
}
pendingConfirmation = latestPendingConfirmation;
}

if (pendingConfirmation.id !== currentConfirmation?.id) {
const unconfirmedTransaction =
unconfirmedTransactions[pendingConfirmation.id];
if (!unconfirmedTransactions) {
setCurrentConfirmation(undefined);
return;
}
if (
pendingConfirmation.type !== ApprovalType.PersonalSign &&
pendingConfirmation.type !== ApprovalType.EthSignTypedData &&
unconfirmedTransaction.type !== TransactionType.contractInteraction
) {

const isConfirmationRedesignType =
REDESIGN_APPROVAL_TYPES.find(
(type) => type === pendingConfirmation?.type,
) ||
REDESIGN_TRANSACTION_TYPES.find(
(type) => type === unconfirmedTransaction?.type,
);

if (!isConfirmationRedesignType) {
setCurrentConfirmation(undefined);
return;
}
if (pendingConfirmation.type === ApprovalType.PersonalSign) {

if (pendingConfirmation?.type === ApprovalType.PersonalSign) {
const { siwe } = unconfirmedTransaction.msgParams;
if (siwe?.isSIWEMessage) {
setCurrentConfirmation(undefined);
Expand Down
15 changes: 13 additions & 2 deletions ui/pages/confirmations/utils/confirm.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import { ApprovalRequest } from '@metamask/approval-controller';
import { ApprovalType } from '@metamask/controller-utils';
import { TransactionType } from '@metamask/transaction-controller';
import { Json } from '@metamask/utils';

const SignatureApprovalTypes = [
export const REDESIGN_APPROVAL_TYPES = [
ApprovalType.EthSignTypedData,
ApprovalType.PersonalSign,
ApprovalType.Transaction,
] as const;

export const REDESIGN_TRANSACTION_TYPES = [
TransactionType.contractInteraction,
] as const;

const SIGNATURE_APPROVAL_TYPES = [
ApprovalType.EthSign,
ApprovalType.PersonalSign,
ApprovalType.EthSignTypedData,
];

export const isSignatureApprovalRequest = (
request: ApprovalRequest<Record<string, Json>>,
) => SignatureApprovalTypes.includes(request.type as ApprovalType);
) => SIGNATURE_APPROVAL_TYPES.includes(request.type as ApprovalType);

0 comments on commit e87e242

Please sign in to comment.