Skip to content
18 changes: 14 additions & 4 deletions app/scripts/lib/createRPCMethodTrackingMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,12 +530,22 @@ export default function createRPCMethodTrackingMiddleware({
stage = STAGE.APPROVED;
}

if (!event) {
return callback();
}

CUSTOM_PROPERTIES_MAP[invokedMethod]?.(req, res, stage, eventProperties);

if (eventType.REQUESTED === MetaMetricsEventName.SignatureRequested) {
// get the snap and hardware info again in case we were not able to during the initial request
// because the KeyringController was locked
const snapAndHardwareInfo = await getSnapAndHardwareInfoForMetrics(
getAccountType,
getDeviceModel,
getHardwareTypeForMetric,
snapAndHardwareMessenger,
);

// merge the snapAndHardwareInfo into eventProperties
Object.assign(eventProperties, snapAndHardwareInfo);
}

let blockaidMetricProps = {};
if (SIGNING_METHODS.includes(invokedMethod)) {
const securityAlertResponse =
Expand Down
76 changes: 76 additions & 0 deletions app/scripts/lib/createRPCMethodTrackingMiddleware.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ import {
import { getDefaultPreferencesControllerState } from '../controllers/preferences-controller';
import { createSegmentMock } from './segment';
import createRPCMethodTrackingMiddleware from './createRPCMethodTrackingMiddleware';
import * as snapKeyringMetrics from './snap-keyring/metrics';

jest.mock('./snap-keyring/metrics', () => {
return {
getSnapAndHardwareInfoForMetrics: jest.fn().mockResolvedValue({}),
};
});
const MockSnapKeyringMetrics = jest.mocked(snapKeyringMetrics);

const MOCK_ID = '123';
const expectedUniqueIdentifier = `signature-${MOCK_ID}`;
Expand Down Expand Up @@ -250,6 +258,31 @@ describe('createRPCMethodTrackingMiddleware', () => {
});
});

it(`should attempt to resolve snaps and hardware info for the ${MetaMetricsEventName.SignatureRequested} event`, async () => {
const req = {
id: MOCK_ID,
method: MESSAGE_TYPE.PERSONAL_SIGN,
origin: 'some.dapp',
securityAlertResponse: {
result_type: BlockaidResultType.Malicious,
reason: BlockaidReason.maliciousDomain,
securityAlertId: 1,
description: 'some_description',
},
};

const res = {
error: null,
};
const { next } = getNext();
const handler = createHandler();
await handler(req, res, next);

expect(
MockSnapKeyringMetrics.getSnapAndHardwareInfoForMetrics,
).toHaveBeenCalledTimes(1);
});

it(`should track a ${MetaMetricsEventName.SignatureRequested} event for personal sign`, async () => {
const req = {
id: MOCK_ID,
Expand Down Expand Up @@ -455,6 +488,49 @@ describe('createRPCMethodTrackingMiddleware', () => {
});
});

it(`should attempt to resolve snaps and hardware info for the ${MetaMetricsEventName.SignatureRejected} event`, async () => {
const req = {
id: MOCK_ID,
method: MESSAGE_TYPE.PERSONAL_SIGN,
origin: 'some.dapp',
};

const res = {
error: {
code: errorCodes.provider.userRejectedRequest,
data: { location: 'some_location' },
},
};
const { next, executeMiddlewareStack } = getNext();
const handler = createHandler();
await handler(req, res, next);
await executeMiddlewareStack();

// Called once for the initial request and once for the rejected request
expect(
MockSnapKeyringMetrics.getSnapAndHardwareInfoForMetrics,
).toHaveBeenCalledTimes(2);
});

it(`should attempt to resolve snaps and hardware info for the ${MetaMetricsEventName.SignatureApproved} event`, async () => {
const req = {
id: MOCK_ID,
method: MESSAGE_TYPE.PERSONAL_SIGN,
origin: 'some.dapp',
};

const res = {};
const { next, executeMiddlewareStack } = getNext();
const handler = createHandler();
await handler(req, res, next);
await executeMiddlewareStack();

// Called once for the initial request and once for the approved request
expect(
MockSnapKeyringMetrics.getSnapAndHardwareInfoForMetrics,
).toHaveBeenCalledTimes(2);
});

it(`should never track blocked methods such as ${MESSAGE_TYPE.GET_PROVIDER_STATE}`, () => {
const req = {
id: MOCK_ID,
Expand Down
Loading
Loading