mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
OpenSea security provider metrics (#17688)
* Added metrics for the OpenSea security provider * Fixed tests * Fixed a test * Fixed metrics * Code refactor * Lint fixed * Removed unnecessary code * Fix build * Fix e2e * Cleanup * Fix e2e * Code refactor * Removed unnecessary code * rpc middleware: catch securityProviderCheck errors to not block dapp rpc requests * Fixed an issue * Added aditional test * Applied some changes * Fixed a test * Fixed a test * Code refactor * Covered more code with tests * Updated a test * Fixed an issue --------- Co-authored-by: Jyoti Puri <jyotipuri@gmail.com> Co-authored-by: digiwand <20778143+digiwand@users.noreply.github.com> Co-authored-by: Brad Decker <bhdecker84@gmail.com>
This commit is contained in:
parent
196b8408d0
commit
0351309227
@ -721,6 +721,9 @@ export default class MetaMetricsController {
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
[TRAITS.DESKTOP_ENABLED]: metamaskState.desktopEnabled || false,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
[TRAITS.SECURITY_PROVIDERS]: metamaskState.transactionSecurityCheckEnabled
|
||||
? ['opensea']
|
||||
: [],
|
||||
};
|
||||
|
||||
if (!previousUserTraits) {
|
||||
|
@ -952,6 +952,7 @@ describe('MetaMetricsController', function () {
|
||||
theme: 'default',
|
||||
useTokenDetection: true,
|
||||
desktopEnabled: false,
|
||||
security_providers: [],
|
||||
});
|
||||
|
||||
assert.deepEqual(traits, {
|
||||
@ -970,6 +971,7 @@ describe('MetaMetricsController', function () {
|
||||
[TRAITS.THEME]: 'default',
|
||||
[TRAITS.TOKEN_DETECTION_ENABLED]: true,
|
||||
[TRAITS.DESKTOP_ENABLED]: false,
|
||||
[TRAITS.SECURITY_PROVIDERS]: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -2147,6 +2147,7 @@ export default class TransactionController extends EventEmitter {
|
||||
originalApprovalAmount,
|
||||
finalApprovalAmount,
|
||||
contractMethodName,
|
||||
securityProviderResponse,
|
||||
} = txMeta;
|
||||
|
||||
const source = referrer === ORIGIN_METAMASK ? 'user' : 'dapp';
|
||||
@ -2298,6 +2299,16 @@ export default class TransactionController extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
let uiCustomizations;
|
||||
|
||||
if (securityProviderResponse?.flagAsDangerous === 1) {
|
||||
uiCustomizations = ['flagged_as_malicious'];
|
||||
} else if (securityProviderResponse?.flagAsDangerous === 2) {
|
||||
uiCustomizations = ['flagged_as_safety_unknown'];
|
||||
} else {
|
||||
uiCustomizations = null;
|
||||
}
|
||||
|
||||
let properties = {
|
||||
chain_id: chainId,
|
||||
referrer,
|
||||
@ -2312,6 +2323,7 @@ export default class TransactionController extends EventEmitter {
|
||||
token_standard: tokenStandard,
|
||||
transaction_type: transactionType,
|
||||
transaction_speed_up: type === TransactionType.retry,
|
||||
ui_customizations: uiCustomizations,
|
||||
};
|
||||
|
||||
if (transactionContractMethod === contractMethodNames.APPROVE) {
|
||||
|
@ -1740,6 +1740,9 @@ describe('Transaction Controller', function () {
|
||||
gas: '0x7b0d',
|
||||
gasPrice: '0x77359400',
|
||||
},
|
||||
securityProviderResponse: {
|
||||
flagAsDangerous: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@ -1766,6 +1769,7 @@ describe('Transaction Controller', function () {
|
||||
token_standard: TokenStandard.none,
|
||||
device_model: 'N/A',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
},
|
||||
sensitiveProperties: {
|
||||
default_gas: '0.000031501',
|
||||
@ -1852,6 +1856,7 @@ describe('Transaction Controller', function () {
|
||||
token_standard: TokenStandard.none,
|
||||
device_model: 'N/A',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
},
|
||||
sensitiveProperties: {
|
||||
default_gas: '0.000031501',
|
||||
@ -1921,6 +1926,9 @@ describe('Transaction Controller', function () {
|
||||
gas: '0x7b0d',
|
||||
gasPrice: '0x77359400',
|
||||
},
|
||||
securityProviderResponse: {
|
||||
flagAsDangerous: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@ -1947,6 +1955,7 @@ describe('Transaction Controller', function () {
|
||||
token_standard: TokenStandard.none,
|
||||
device_model: 'N/A',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
},
|
||||
sensitiveProperties: {
|
||||
default_gas: '0.000031501',
|
||||
@ -2035,6 +2044,7 @@ describe('Transaction Controller', function () {
|
||||
token_standard: TokenStandard.none,
|
||||
device_model: 'N/A',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
},
|
||||
sensitiveProperties: {
|
||||
default_gas: '0.000031501',
|
||||
@ -2099,6 +2109,9 @@ describe('Transaction Controller', function () {
|
||||
chainId: currentChainId,
|
||||
time: 1624408066355,
|
||||
metamaskNetworkId: currentNetworkId,
|
||||
securityProviderResponse: {
|
||||
flagAsDangerous: 0,
|
||||
},
|
||||
};
|
||||
|
||||
const expectedPayload = {
|
||||
@ -2122,6 +2135,7 @@ describe('Transaction Controller', function () {
|
||||
token_standard: TokenStandard.none,
|
||||
device_model: 'N/A',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
},
|
||||
sensitiveProperties: {
|
||||
gas_price: '2',
|
||||
@ -2167,6 +2181,9 @@ describe('Transaction Controller', function () {
|
||||
chainId: currentChainId,
|
||||
time: 1624408066355,
|
||||
metamaskNetworkId: currentNetworkId,
|
||||
securityProviderResponse: {
|
||||
flagAsDangerous: 0,
|
||||
},
|
||||
};
|
||||
const expectedPayload = {
|
||||
actionId,
|
||||
@ -2190,6 +2207,155 @@ describe('Transaction Controller', function () {
|
||||
token_standard: TokenStandard.none,
|
||||
device_model: 'N/A',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
},
|
||||
sensitiveProperties: {
|
||||
baz: 3.0,
|
||||
foo: 'bar',
|
||||
gas_price: '2',
|
||||
gas_limit: '0x7b0d',
|
||||
transaction_contract_method: undefined,
|
||||
transaction_replaced: undefined,
|
||||
first_seen: 1624408066355,
|
||||
transaction_envelope_type: TRANSACTION_ENVELOPE_TYPE_NAMES.LEGACY,
|
||||
status: 'unapproved',
|
||||
},
|
||||
};
|
||||
|
||||
await txController._trackTransactionMetricsEvent(
|
||||
txMeta,
|
||||
TransactionMetaMetricsEvent.added,
|
||||
actionId,
|
||||
{
|
||||
baz: 3.0,
|
||||
foo: 'bar',
|
||||
},
|
||||
);
|
||||
assert.equal(createEventFragmentSpy.callCount, 1);
|
||||
assert.equal(finalizeEventFragmentSpy.callCount, 0);
|
||||
assert.deepEqual(
|
||||
createEventFragmentSpy.getCall(0).args[0],
|
||||
expectedPayload,
|
||||
);
|
||||
});
|
||||
|
||||
it('should call _trackMetaMetricsEvent with the correct payload (extra params) when flagAsDangerous is malicious', async function () {
|
||||
const txMeta = {
|
||||
id: 1,
|
||||
status: TransactionStatus.unapproved,
|
||||
txParams: {
|
||||
from: fromAccount.address,
|
||||
to: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
||||
gasPrice: '0x77359400',
|
||||
gas: '0x7b0d',
|
||||
nonce: '0x4b',
|
||||
},
|
||||
type: TransactionType.simpleSend,
|
||||
origin: 'other',
|
||||
chainId: currentChainId,
|
||||
time: 1624408066355,
|
||||
metamaskNetworkId: currentNetworkId,
|
||||
securityProviderResponse: {
|
||||
flagAsDangerous: 1,
|
||||
},
|
||||
};
|
||||
const expectedPayload = {
|
||||
actionId,
|
||||
initialEvent: 'Transaction Added',
|
||||
successEvent: 'Transaction Approved',
|
||||
failureEvent: 'Transaction Rejected',
|
||||
uniqueIdentifier: 'transaction-added-1',
|
||||
persist: true,
|
||||
category: EVENT.CATEGORIES.TRANSACTIONS,
|
||||
properties: {
|
||||
network: '5',
|
||||
referrer: 'other',
|
||||
source: EVENT.SOURCE.TRANSACTION.DAPP,
|
||||
transaction_type: TransactionType.simpleSend,
|
||||
chain_id: '0x5',
|
||||
eip_1559_version: '0',
|
||||
gas_edit_attempted: 'none',
|
||||
gas_edit_type: 'none',
|
||||
account_type: 'MetaMask',
|
||||
asset_type: AssetType.native,
|
||||
token_standard: TokenStandard.none,
|
||||
device_model: 'N/A',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: ['flagged_as_malicious'],
|
||||
},
|
||||
sensitiveProperties: {
|
||||
baz: 3.0,
|
||||
foo: 'bar',
|
||||
gas_price: '2',
|
||||
gas_limit: '0x7b0d',
|
||||
transaction_contract_method: undefined,
|
||||
transaction_replaced: undefined,
|
||||
first_seen: 1624408066355,
|
||||
transaction_envelope_type: TRANSACTION_ENVELOPE_TYPE_NAMES.LEGACY,
|
||||
status: 'unapproved',
|
||||
},
|
||||
};
|
||||
|
||||
await txController._trackTransactionMetricsEvent(
|
||||
txMeta,
|
||||
TransactionMetaMetricsEvent.added,
|
||||
actionId,
|
||||
{
|
||||
baz: 3.0,
|
||||
foo: 'bar',
|
||||
},
|
||||
);
|
||||
assert.equal(createEventFragmentSpy.callCount, 1);
|
||||
assert.equal(finalizeEventFragmentSpy.callCount, 0);
|
||||
assert.deepEqual(
|
||||
createEventFragmentSpy.getCall(0).args[0],
|
||||
expectedPayload,
|
||||
);
|
||||
});
|
||||
|
||||
it('should call _trackMetaMetricsEvent with the correct payload (extra params) when flagAsDangerous is unknown', async function () {
|
||||
const txMeta = {
|
||||
id: 1,
|
||||
status: TransactionStatus.unapproved,
|
||||
txParams: {
|
||||
from: fromAccount.address,
|
||||
to: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
||||
gasPrice: '0x77359400',
|
||||
gas: '0x7b0d',
|
||||
nonce: '0x4b',
|
||||
},
|
||||
type: TransactionType.simpleSend,
|
||||
origin: 'other',
|
||||
chainId: currentChainId,
|
||||
time: 1624408066355,
|
||||
metamaskNetworkId: currentNetworkId,
|
||||
securityProviderResponse: {
|
||||
flagAsDangerous: 2,
|
||||
},
|
||||
};
|
||||
const expectedPayload = {
|
||||
actionId,
|
||||
initialEvent: 'Transaction Added',
|
||||
successEvent: 'Transaction Approved',
|
||||
failureEvent: 'Transaction Rejected',
|
||||
uniqueIdentifier: 'transaction-added-1',
|
||||
persist: true,
|
||||
category: EVENT.CATEGORIES.TRANSACTIONS,
|
||||
properties: {
|
||||
network: '5',
|
||||
referrer: 'other',
|
||||
source: EVENT.SOURCE.TRANSACTION.DAPP,
|
||||
transaction_type: TransactionType.simpleSend,
|
||||
chain_id: '0x5',
|
||||
eip_1559_version: '0',
|
||||
gas_edit_attempted: 'none',
|
||||
gas_edit_type: 'none',
|
||||
account_type: 'MetaMask',
|
||||
asset_type: AssetType.native,
|
||||
token_standard: TokenStandard.none,
|
||||
device_model: 'N/A',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: ['flagged_as_safety_unknown'],
|
||||
},
|
||||
sensitiveProperties: {
|
||||
baz: 3.0,
|
||||
@ -2245,6 +2411,9 @@ describe('Transaction Controller', function () {
|
||||
maxFeePerGas: '0x77359400',
|
||||
maxPriorityFeePerGas: '0x77359400',
|
||||
},
|
||||
securityProviderResponse: {
|
||||
flagAsDangerous: 0,
|
||||
},
|
||||
};
|
||||
const expectedPayload = {
|
||||
actionId,
|
||||
@ -2268,6 +2437,7 @@ describe('Transaction Controller', function () {
|
||||
token_standard: TokenStandard.none,
|
||||
device_model: 'N/A',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
},
|
||||
sensitiveProperties: {
|
||||
baz: 3.0,
|
||||
|
@ -107,14 +107,16 @@ const rateLimitTimeouts = {};
|
||||
* MetaMetricsController
|
||||
* @param {number} [opts.rateLimitSeconds] - number of seconds to wait before
|
||||
* allowing another set of events to be tracked.
|
||||
* @param opts.securityProviderRequest
|
||||
* @returns {Function}
|
||||
*/
|
||||
export default function createRPCMethodTrackingMiddleware({
|
||||
trackEvent,
|
||||
getMetricsState,
|
||||
rateLimitSeconds = 60 * 5,
|
||||
securityProviderRequest,
|
||||
}) {
|
||||
return function rpcMethodTrackingMiddleware(
|
||||
return async function rpcMethodTrackingMiddleware(
|
||||
/** @type {any} */ req,
|
||||
/** @type {any} */ res,
|
||||
/** @type {Function} */ next,
|
||||
@ -162,22 +164,65 @@ export default function createRPCMethodTrackingMiddleware({
|
||||
|
||||
const properties = {};
|
||||
|
||||
let msgParams;
|
||||
|
||||
if (event === EVENT_NAMES.SIGNATURE_REQUESTED) {
|
||||
properties.signature_type = method;
|
||||
|
||||
const data = req?.params?.[0];
|
||||
const from = req?.params?.[1];
|
||||
const paramsExamplePassword = req?.params?.[2];
|
||||
|
||||
msgParams = {
|
||||
...paramsExamplePassword,
|
||||
from,
|
||||
data,
|
||||
origin,
|
||||
};
|
||||
|
||||
const msgData = {
|
||||
msgParams,
|
||||
status: 'unapproved',
|
||||
type: req.method,
|
||||
};
|
||||
|
||||
try {
|
||||
const securityProviderResponse = await securityProviderRequest(
|
||||
msgData,
|
||||
req.method,
|
||||
);
|
||||
|
||||
if (securityProviderResponse?.flagAsDangerous === 1) {
|
||||
properties.ui_customizations = ['flagged_as_malicious'];
|
||||
} else if (securityProviderResponse?.flagAsDangerous === 2) {
|
||||
properties.ui_customizations = ['flagged_as_safety_unknown'];
|
||||
} else {
|
||||
properties.ui_customizations = null;
|
||||
}
|
||||
|
||||
if (method === MESSAGE_TYPE.PERSONAL_SIGN) {
|
||||
const { isSIWEMessage } = detectSIWE({ data });
|
||||
if (isSIWEMessage) {
|
||||
properties.ui_customizations === null
|
||||
? (properties.ui_customizations = [
|
||||
METAMETRIC_KEY_OPTIONS[METAMETRIC_KEY.UI_CUSTOMIZATIONS]
|
||||
.SIWE,
|
||||
])
|
||||
: properties.ui_customizations.push(
|
||||
METAMETRIC_KEY_OPTIONS[METAMETRIC_KEY.UI_CUSTOMIZATIONS]
|
||||
.SIWE,
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`createRPCMethodTrackingMiddleware: Error calling securityProviderRequest - ${e}`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
properties.method = method;
|
||||
}
|
||||
|
||||
if (method === MESSAGE_TYPE.PERSONAL_SIGN) {
|
||||
const data = req?.params?.[0];
|
||||
const { isSIWEMessage } = detectSIWE({ data });
|
||||
if (isSIWEMessage) {
|
||||
properties.ui_customizations = [
|
||||
METAMETRIC_KEY_OPTIONS[METAMETRIC_KEY.UI_CUSTOMIZATIONS].SIWE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
trackEvent({
|
||||
event,
|
||||
category: EVENT.CATEGORIES.INPAGE_PROVIDER,
|
||||
@ -192,7 +237,7 @@ export default function createRPCMethodTrackingMiddleware({
|
||||
}, SECOND * rateLimitSeconds);
|
||||
}
|
||||
|
||||
next((callback) => {
|
||||
next(async (callback) => {
|
||||
if (shouldTrackEvent === false || typeof eventType === 'undefined') {
|
||||
return callback();
|
||||
}
|
||||
@ -216,22 +261,65 @@ export default function createRPCMethodTrackingMiddleware({
|
||||
event = eventType.APPROVED;
|
||||
}
|
||||
|
||||
let msgParams;
|
||||
|
||||
if (eventType.REQUESTED === EVENT_NAMES.SIGNATURE_REQUESTED) {
|
||||
properties.signature_type = method;
|
||||
|
||||
const data = req?.params?.[0];
|
||||
const from = req?.params?.[1];
|
||||
const paramsExamplePassword = req?.params?.[2];
|
||||
|
||||
msgParams = {
|
||||
...paramsExamplePassword,
|
||||
from,
|
||||
data,
|
||||
origin,
|
||||
};
|
||||
|
||||
const msgData = {
|
||||
msgParams,
|
||||
status: 'unapproved',
|
||||
type: req.method,
|
||||
};
|
||||
|
||||
try {
|
||||
const securityProviderResponse = await securityProviderRequest(
|
||||
msgData,
|
||||
req.method,
|
||||
);
|
||||
|
||||
if (securityProviderResponse?.flagAsDangerous === 1) {
|
||||
properties.ui_customizations = ['flagged_as_malicious'];
|
||||
} else if (securityProviderResponse?.flagAsDangerous === 2) {
|
||||
properties.ui_customizations = ['flagged_as_safety_unknown'];
|
||||
} else {
|
||||
properties.ui_customizations = null;
|
||||
}
|
||||
|
||||
if (method === MESSAGE_TYPE.PERSONAL_SIGN) {
|
||||
const { isSIWEMessage } = detectSIWE({ data });
|
||||
if (isSIWEMessage) {
|
||||
properties.ui_customizations === null
|
||||
? (properties.ui_customizations = [
|
||||
METAMETRIC_KEY_OPTIONS[METAMETRIC_KEY.UI_CUSTOMIZATIONS]
|
||||
.SIWE,
|
||||
])
|
||||
: properties.ui_customizations.push(
|
||||
METAMETRIC_KEY_OPTIONS[METAMETRIC_KEY.UI_CUSTOMIZATIONS]
|
||||
.SIWE,
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`createRPCMethodTrackingMiddleware: Error calling securityProviderRequest - ${e}`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
properties.method = method;
|
||||
}
|
||||
|
||||
if (method === MESSAGE_TYPE.PERSONAL_SIGN) {
|
||||
const data = req?.params?.[0];
|
||||
const { isSIWEMessage } = detectSIWE({ data });
|
||||
if (isSIWEMessage) {
|
||||
properties.ui_customizations = [
|
||||
METAMETRIC_KEY_OPTIONS[METAMETRIC_KEY.UI_CUSTOMIZATIONS].SIWE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
trackEvent({
|
||||
event,
|
||||
category: EVENT.CATEGORIES.INPAGE_PROVIDER,
|
||||
|
@ -8,10 +8,19 @@ const trackEvent = jest.fn();
|
||||
const metricsState = { participateInMetaMetrics: null };
|
||||
const getMetricsState = () => metricsState;
|
||||
|
||||
let flagAsDangerous = 0;
|
||||
|
||||
const securityProviderRequest = () => {
|
||||
return {
|
||||
flagAsDangerous,
|
||||
};
|
||||
};
|
||||
|
||||
const handler = createRPCMethodTrackingMiddleware({
|
||||
trackEvent,
|
||||
getMetricsState,
|
||||
rateLimitSeconds: 1,
|
||||
securityProviderRequest,
|
||||
});
|
||||
|
||||
function getNext(timeout = 500) {
|
||||
@ -92,7 +101,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
|
||||
metricsState.participateInMetaMetrics = true;
|
||||
});
|
||||
|
||||
it(`should immediately track a ${EVENT_NAMES.SIGNATURE_REQUESTED} event`, () => {
|
||||
it(`should immediately track a ${EVENT_NAMES.SIGNATURE_REQUESTED} event`, async () => {
|
||||
const req = {
|
||||
method: MESSAGE_TYPE.ETH_SIGN,
|
||||
origin: 'some.dapp',
|
||||
@ -102,12 +111,14 @@ describe('createRPCMethodTrackingMiddleware', () => {
|
||||
error: null,
|
||||
};
|
||||
const { next } = getNext();
|
||||
handler(req, res, next);
|
||||
await handler(req, res, next);
|
||||
expect(trackEvent).toHaveBeenCalledTimes(1);
|
||||
expect(trackEvent.mock.calls[0][0]).toMatchObject({
|
||||
category: 'inpage_provider',
|
||||
event: EVENT_NAMES.SIGNATURE_REQUESTED,
|
||||
properties: { signature_type: MESSAGE_TYPE.ETH_SIGN },
|
||||
properties: {
|
||||
signature_type: MESSAGE_TYPE.ETH_SIGN,
|
||||
},
|
||||
referrer: { url: 'some.dapp' },
|
||||
});
|
||||
});
|
||||
@ -122,13 +133,15 @@ describe('createRPCMethodTrackingMiddleware', () => {
|
||||
error: null,
|
||||
};
|
||||
const { next, executeMiddlewareStack } = getNext();
|
||||
handler(req, res, next);
|
||||
await handler(req, res, next);
|
||||
await executeMiddlewareStack();
|
||||
expect(trackEvent).toHaveBeenCalledTimes(2);
|
||||
expect(trackEvent.mock.calls[1][0]).toMatchObject({
|
||||
category: 'inpage_provider',
|
||||
event: EVENT_NAMES.SIGNATURE_APPROVED,
|
||||
properties: { signature_type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4 },
|
||||
properties: {
|
||||
signature_type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4,
|
||||
},
|
||||
referrer: { url: 'some.dapp' },
|
||||
});
|
||||
});
|
||||
@ -143,13 +156,15 @@ describe('createRPCMethodTrackingMiddleware', () => {
|
||||
error: { code: 4001 },
|
||||
};
|
||||
const { next, executeMiddlewareStack } = getNext();
|
||||
handler(req, res, next);
|
||||
await handler(req, res, next);
|
||||
await executeMiddlewareStack();
|
||||
expect(trackEvent).toHaveBeenCalledTimes(2);
|
||||
expect(trackEvent.mock.calls[1][0]).toMatchObject({
|
||||
category: 'inpage_provider',
|
||||
event: EVENT_NAMES.SIGNATURE_REJECTED,
|
||||
properties: { signature_type: MESSAGE_TYPE.PERSONAL_SIGN },
|
||||
properties: {
|
||||
signature_type: MESSAGE_TYPE.PERSONAL_SIGN,
|
||||
},
|
||||
referrer: { url: 'some.dapp' },
|
||||
});
|
||||
});
|
||||
@ -162,7 +177,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
|
||||
|
||||
const res = {};
|
||||
const { next, executeMiddlewareStack } = getNext();
|
||||
handler(req, res, next);
|
||||
await handler(req, res, next);
|
||||
await executeMiddlewareStack();
|
||||
expect(trackEvent).toHaveBeenCalledTimes(2);
|
||||
expect(trackEvent.mock.calls[1][0]).toMatchObject({
|
||||
@ -227,7 +242,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
|
||||
};
|
||||
const { next, executeMiddlewareStack } = getNext();
|
||||
|
||||
handler(req, res, next);
|
||||
await handler(req, res, next);
|
||||
await executeMiddlewareStack();
|
||||
|
||||
expect(trackEvent).toHaveBeenCalledTimes(2);
|
||||
@ -244,4 +259,93 @@ describe('createRPCMethodTrackingMiddleware', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('participateInMetaMetrics is set to true with a request flagged as safe', () => {
|
||||
beforeEach(() => {
|
||||
metricsState.participateInMetaMetrics = true;
|
||||
});
|
||||
|
||||
it(`should immediately track a ${EVENT_NAMES.SIGNATURE_REQUESTED} event which is flagged as safe`, async () => {
|
||||
const req = {
|
||||
method: MESSAGE_TYPE.ETH_SIGN,
|
||||
origin: 'some.dapp',
|
||||
};
|
||||
|
||||
const res = {
|
||||
error: null,
|
||||
};
|
||||
const { next } = getNext();
|
||||
await handler(req, res, next);
|
||||
expect(trackEvent).toHaveBeenCalledTimes(1);
|
||||
expect(trackEvent.mock.calls[0][0]).toMatchObject({
|
||||
category: 'inpage_provider',
|
||||
event: EVENT_NAMES.SIGNATURE_REQUESTED,
|
||||
properties: {
|
||||
signature_type: MESSAGE_TYPE.ETH_SIGN,
|
||||
ui_customizations: null,
|
||||
},
|
||||
referrer: { url: 'some.dapp' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('participateInMetaMetrics is set to true with a request flagged as malicious', () => {
|
||||
beforeEach(() => {
|
||||
metricsState.participateInMetaMetrics = true;
|
||||
flagAsDangerous = 1;
|
||||
});
|
||||
|
||||
it(`should immediately track a ${EVENT_NAMES.SIGNATURE_REQUESTED} event which is flagged as malicious`, async () => {
|
||||
const req = {
|
||||
method: MESSAGE_TYPE.ETH_SIGN,
|
||||
origin: 'some.dapp',
|
||||
};
|
||||
|
||||
const res = {
|
||||
error: null,
|
||||
};
|
||||
const { next } = getNext();
|
||||
await handler(req, res, next);
|
||||
expect(trackEvent).toHaveBeenCalledTimes(1);
|
||||
expect(trackEvent.mock.calls[0][0]).toMatchObject({
|
||||
category: 'inpage_provider',
|
||||
event: EVENT_NAMES.SIGNATURE_REQUESTED,
|
||||
properties: {
|
||||
signature_type: MESSAGE_TYPE.ETH_SIGN,
|
||||
ui_customizations: ['flagged_as_malicious'],
|
||||
},
|
||||
referrer: { url: 'some.dapp' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('participateInMetaMetrics is set to true with a request flagged as safety unknown', () => {
|
||||
beforeEach(() => {
|
||||
metricsState.participateInMetaMetrics = true;
|
||||
flagAsDangerous = 2;
|
||||
});
|
||||
|
||||
it(`should immediately track a ${EVENT_NAMES.SIGNATURE_REQUESTED} event which is flagged as safety unknown`, async () => {
|
||||
const req = {
|
||||
method: MESSAGE_TYPE.ETH_SIGN,
|
||||
origin: 'some.dapp',
|
||||
};
|
||||
|
||||
const res = {
|
||||
error: null,
|
||||
};
|
||||
const { next } = getNext();
|
||||
await handler(req, res, next);
|
||||
expect(trackEvent).toHaveBeenCalledTimes(1);
|
||||
expect(trackEvent.mock.calls[0][0]).toMatchObject({
|
||||
category: 'inpage_provider',
|
||||
event: EVENT_NAMES.SIGNATURE_REQUESTED,
|
||||
properties: {
|
||||
signature_type: MESSAGE_TYPE.ETH_SIGN,
|
||||
ui_customizations: ['flagged_as_safety_unknown'],
|
||||
},
|
||||
referrer: { url: 'some.dapp' },
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -39,12 +39,12 @@ export async function securityProviderCheck(
|
||||
rpc_method_name: methodName,
|
||||
chain_id: chainId,
|
||||
data: {
|
||||
from_address: requestData.txParams.from,
|
||||
to_address: requestData.txParams.to,
|
||||
gas: requestData.txParams.gas,
|
||||
gasPrice: requestData.txParams.gasPrice,
|
||||
value: requestData.txParams.value,
|
||||
data: requestData.txParams.data,
|
||||
from_address: requestData?.txParams?.from,
|
||||
to_address: requestData?.txParams?.to,
|
||||
gas: requestData?.txParams?.gas,
|
||||
gasPrice: requestData?.txParams?.gasPrice,
|
||||
value: requestData?.txParams?.value,
|
||||
data: requestData?.txParams?.data,
|
||||
},
|
||||
currentLocale,
|
||||
};
|
||||
|
@ -3729,6 +3729,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
getMetricsState: this.metaMetricsController.store.getState.bind(
|
||||
this.metaMetricsController.store,
|
||||
),
|
||||
securityProviderRequest: this.securityProviderRequest.bind(this),
|
||||
}),
|
||||
);
|
||||
|
||||
@ -4383,11 +4384,11 @@ export default class MetamaskController extends EventEmitter {
|
||||
const { currentLocale, transactionSecurityCheckEnabled } =
|
||||
this.preferencesController.store.getState();
|
||||
|
||||
const chainId = Number(
|
||||
hexToDecimal(this.networkController.store.getState().provider.chainId),
|
||||
);
|
||||
|
||||
if (transactionSecurityCheckEnabled) {
|
||||
const chainId = Number(
|
||||
hexToDecimal(this.networkController.store.getState().provider.chainId),
|
||||
);
|
||||
|
||||
try {
|
||||
const securityProviderResponse = await securityProviderCheck(
|
||||
requestData,
|
||||
|
@ -187,6 +187,8 @@
|
||||
* identify the token_detection_enabled trait
|
||||
* @property {'install_date_ext'} INSTALL_DATE_EXT - when the user installed the extension
|
||||
* @property {'desktop_enabled'} [DESKTOP_ENABLED] - optional / does the user have desktop enabled?
|
||||
* @property {'security_providers'} SECURITY_PROVIDERS - when security provider feature is toggled we
|
||||
* identify the security_providers trait
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -210,6 +212,7 @@ export const TRAITS = {
|
||||
THREE_BOX_ENABLED: 'three_box_enabled',
|
||||
TOKEN_DETECTION_ENABLED: 'token_detection_enabled',
|
||||
DESKTOP_ENABLED: 'desktop_enabled',
|
||||
SECURITY_PROVIDERS: 'security_providers',
|
||||
};
|
||||
|
||||
/**
|
||||
@ -240,6 +243,7 @@ export const TRAITS = {
|
||||
* @property {string} [theme] - which theme the user has selected
|
||||
* @property {boolean} [token_detection_enabled] - does the user have token detection is enabled?
|
||||
* @property {boolean} [desktop_enabled] - optional / does the user have desktop enabled?
|
||||
* @property {Array<string>} [security_providers] - whether security provider feature toggle is on or off
|
||||
*/
|
||||
|
||||
// Mixpanel converts the zero address value to a truly anonymous event, which
|
||||
|
@ -31,10 +31,10 @@ describe('Eth sign', function () {
|
||||
await driver.openNewPage('http://127.0.0.1:8080/');
|
||||
await driver.clickElement('#ethSign');
|
||||
|
||||
await driver.delay(1000);
|
||||
const ethSignButton = await driver.findElement('#ethSign');
|
||||
const exceptionString =
|
||||
'ERROR: ETH_SIGN HAS BEEN DISABLED. YOU MUST ENABLE IT IN THE ADVANCED SETTINGS';
|
||||
|
||||
assert.equal(await ethSignButton.getText(), exceptionString);
|
||||
},
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user