diff --git a/app/scripts/lib/createRPCMethodTrackingMiddleware.js b/app/scripts/lib/createRPCMethodTrackingMiddleware.js index 9073a26c3ae5..e1376ae1e785 100644 --- a/app/scripts/lib/createRPCMethodTrackingMiddleware.js +++ b/app/scripts/lib/createRPCMethodTrackingMiddleware.js @@ -1,3 +1,4 @@ +import { errorCodes } from 'eth-rpc-errors'; import { MESSAGE_TYPE, ORIGIN_METAMASK } from '../../../shared/constants/app'; import { SECOND } from '../../../shared/constants/time'; import { detectSIWE } from '../../../shared/modules/siwe'; @@ -46,6 +47,7 @@ const RATE_LIMIT_MAP = { const EVENT_NAME_MAP = { [MESSAGE_TYPE.ETH_SIGN]: { APPROVED: EVENT_NAMES.SIGNATURE_APPROVED, + FAILED: EVENT_NAMES.SIGNATURE_FAILED, REJECTED: EVENT_NAMES.SIGNATURE_REJECTED, REQUESTED: EVENT_NAMES.SIGNATURE_REQUESTED, }, @@ -195,13 +197,25 @@ export default function createRPCMethodTrackingMiddleware({ return callback(); } - // An error code of 4001 means the user rejected the request, which we - // can use here to determine which event to track. - const event = - res.error?.code === 4001 ? eventType.REJECTED : eventType.APPROVED; - const properties = {}; + // The rpc error methodNotFound implies that 'eth_sign' is disabled in Advanced Settings + const isDisabledEthSignAdvancedSetting = + method === MESSAGE_TYPE.ETH_SIGN && + res.error?.code === errorCodes.rpc.methodNotFound; + + const isDisabledRPCMethod = isDisabledEthSignAdvancedSetting; + + let event; + if (isDisabledRPCMethod) { + event = eventType.FAILED; + properties.error = res.error; + } else if (res.error?.code === 4001) { + event = eventType.REJECTED; + } else { + event = eventType.APPROVED; + } + if (eventType.REQUESTED === EVENT_NAMES.SIGNATURE_REQUESTED) { properties.signature_type = method; } else { @@ -226,6 +240,7 @@ export default function createRPCMethodTrackingMiddleware({ }, properties, }); + return callback(); }); }; diff --git a/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js b/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js index ffa953fa0f75..9a9f72157703 100644 --- a/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js +++ b/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js @@ -1,3 +1,4 @@ +import { errorCodes } from 'eth-rpc-errors'; import { MESSAGE_TYPE } from '../../../shared/constants/app'; import { EVENT_NAMES } from '../../../shared/constants/metametrics'; import { SECOND } from '../../../shared/constants/time'; @@ -213,5 +214,34 @@ describe('createRPCMethodTrackingMiddleware', () => { expect(trackEvent.mock.calls[0][0].properties.method).toBe('eth_chainId'); expect(trackEvent.mock.calls[1][0].properties.method).toBe('eth_chainId'); }); + + describe(`when '${MESSAGE_TYPE.ETH_SIGN}' is disabled in advanced settings`, () => { + it(`should track ${EVENT_NAMES.SIGNATURE_FAILED} and include error property`, async () => { + const mockError = { code: errorCodes.rpc.methodNotFound }; + const req = { + method: MESSAGE_TYPE.ETH_SIGN, + origin: 'some.dapp', + }; + const res = { + error: mockError, + }; + const { next, executeMiddlewareStack } = getNext(); + + handler(req, res, next); + await executeMiddlewareStack(); + + expect(trackEvent).toHaveBeenCalledTimes(2); + + expect(trackEvent.mock.calls[1][0]).toMatchObject({ + category: 'inpage_provider', + event: EVENT_NAMES.SIGNATURE_FAILED, + properties: { + signature_type: MESSAGE_TYPE.ETH_SIGN, + error: mockError, + }, + referrer: { url: 'some.dapp' }, + }); + }); + }); }); }); diff --git a/shared/constants/metametrics.js b/shared/constants/metametrics.js index 62423b94fc35..b6facb12ba9d 100644 --- a/shared/constants/metametrics.js +++ b/shared/constants/metametrics.js @@ -342,6 +342,7 @@ export const EVENT_NAMES = { PUBLIC_ADDRESS_COPIED: 'Public Address Copied', PROVIDER_METHOD_CALLED: 'Provider Method Called', SIGNATURE_APPROVED: 'Signature Approved', + SIGNATURE_FAILED: 'Signature Failed', SIGNATURE_REJECTED: 'Signature Rejected', SIGNATURE_REQUESTED: 'Signature Requested', TOKEN_IMPORT_BUTTON_CLICKED: 'Import Token Button Clicked',