mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-01 13:47:06 +01:00
295 lines
9.3 KiB
JavaScript
295 lines
9.3 KiB
JavaScript
/* eslint-disable no-useless-escape */
|
|
const { isEqual, omit } = require('lodash');
|
|
const {
|
|
defaultGanacheOptions,
|
|
withFixtures,
|
|
unlockWallet,
|
|
sendTransaction,
|
|
getEventPayloads,
|
|
assertInAnyOrder,
|
|
} = require('../helpers');
|
|
const FixtureBuilder = require('../fixture-builder');
|
|
|
|
/**
|
|
* mocks the segment api multiple times for specific payloads that we expect to
|
|
* see when these tests are run. In this case we are looking for
|
|
* 'Transaction Submitted' and 'Transaction Finalized'. In addition on the
|
|
* first event of each series we require a field that should only appear in the
|
|
* anonymized events so that we can guarantee order of seenRequests and can
|
|
* properly make assertions. Do not use the constants from the metrics
|
|
* constants files, because if these change we want a strong indicator to our
|
|
* data team that the shape of data will change.
|
|
*
|
|
* @param {import('mockttp').Mockttp} mockServer
|
|
* @returns {Promise<import('mockttp/dist/pluggable-admin').MockttpClientResponse>[]}
|
|
*/
|
|
async function mockSegment(mockServer) {
|
|
return [
|
|
await mockServer
|
|
.forPost('https://api.segment.io/v1/batch')
|
|
.withJsonBodyIncluding({
|
|
batch: [
|
|
{
|
|
type: 'track',
|
|
event: 'Transaction Submitted',
|
|
properties: { status: 'submitted' },
|
|
},
|
|
],
|
|
})
|
|
.thenCallback(() => {
|
|
return {
|
|
statusCode: 200,
|
|
};
|
|
}),
|
|
await mockServer
|
|
.forPost('https://api.segment.io/v1/batch')
|
|
.withJsonBodyIncluding({
|
|
batch: [
|
|
{
|
|
type: 'track',
|
|
event: 'Transaction Submitted',
|
|
},
|
|
],
|
|
})
|
|
.thenCallback(() => {
|
|
return {
|
|
statusCode: 200,
|
|
};
|
|
}),
|
|
await mockServer
|
|
.forPost('https://api.segment.io/v1/batch')
|
|
.withJsonBodyIncluding({
|
|
batch: [
|
|
{
|
|
type: 'track',
|
|
event: 'Transaction Finalized',
|
|
properties: { status: 'confirmed' },
|
|
},
|
|
],
|
|
})
|
|
.thenCallback(() => {
|
|
return {
|
|
statusCode: 200,
|
|
};
|
|
}),
|
|
await mockServer
|
|
.forPost('https://api.segment.io/v1/batch')
|
|
.withJsonBodyIncluding({
|
|
batch: [
|
|
{
|
|
type: 'track',
|
|
event: 'Transaction Finalized',
|
|
},
|
|
],
|
|
})
|
|
.thenCallback(() => {
|
|
return {
|
|
statusCode: 200,
|
|
};
|
|
}),
|
|
];
|
|
}
|
|
|
|
const RECIPIENT = '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3';
|
|
|
|
/**
|
|
* Assert that the event names begin with the appropriate prefixes. Even
|
|
* finalized events begin with transaction-submitted because they start as
|
|
* event fragments created when the transaction is submitted.
|
|
*
|
|
* @param {object} payload
|
|
*/
|
|
const messageIdStartsWithTransactionSubmitted = (payload) =>
|
|
payload.messageId.startsWith('transaction-submitted');
|
|
|
|
/**
|
|
* Assert that the events with sensitive properties should have messageIds
|
|
* ending in 0x000 this is important because otherwise the events are seen as
|
|
* duplicates in segment
|
|
*
|
|
* @param {object} payload
|
|
*/
|
|
const messageIdEndsWithZeros = (payload) => payload.messageId.endsWith('0x000');
|
|
|
|
/**
|
|
* Assert that the events with sensitive data do not contain a userId (the
|
|
* random anonymous id generated when a user opts into metametrics)
|
|
*
|
|
* @param {object} payload
|
|
*/
|
|
const eventDoesNotIncludeUserId = (payload) =>
|
|
typeof payload.userId === 'undefined';
|
|
|
|
const eventHasUserIdWithoutAnonymousId = (payload) =>
|
|
typeof payload.userId === 'string' &&
|
|
typeof payload.anonymousId === 'undefined';
|
|
|
|
/**
|
|
* Assert that the events with sensitive data have anonymousId set to
|
|
* 0x0000000000000000 which is our universal anonymous record
|
|
*
|
|
* @param {object} payload
|
|
*/
|
|
const eventHasZeroAddressAnonymousId = (payload) =>
|
|
payload.anonymousId === '0x0000000000000000';
|
|
|
|
describe('Transaction Finalized Event', function () {
|
|
it('Successfully tracked when sending a transaction', async function () {
|
|
await withFixtures(
|
|
{
|
|
fixtures: new FixtureBuilder()
|
|
.withMetaMetricsController({
|
|
metaMetricsId: 'fake-metrics-id',
|
|
participateInMetaMetrics: true,
|
|
})
|
|
.build(),
|
|
ganacheOptions: defaultGanacheOptions,
|
|
title: this.test.title,
|
|
testSpecificMock: mockSegment,
|
|
},
|
|
async ({ driver, mockedEndpoint: mockedEndpoints }) => {
|
|
await driver.navigate();
|
|
await unlockWallet(driver);
|
|
|
|
await sendTransaction(driver, RECIPIENT, '2.0');
|
|
|
|
const events = await getEventPayloads(driver, mockedEndpoints);
|
|
|
|
const transactionSubmittedWithSensitivePropertiesAssertions = [
|
|
messageIdStartsWithTransactionSubmitted,
|
|
messageIdEndsWithZeros,
|
|
eventDoesNotIncludeUserId,
|
|
eventHasZeroAddressAnonymousId,
|
|
(payload) =>
|
|
isEqual(omit(payload.properties, ['first_seen']), {
|
|
status: 'submitted',
|
|
transaction_envelope_type: 'legacy',
|
|
gas_limit: '0x5208',
|
|
gas_price: '2',
|
|
default_gas: '0.000021',
|
|
default_gas_price: '2',
|
|
chain_id: '0x539',
|
|
referrer: 'metamask',
|
|
source: 'user',
|
|
network: '1337',
|
|
eip_1559_version: '0',
|
|
gas_edit_type: 'none',
|
|
gas_edit_attempted: 'none',
|
|
account_type: 'MetaMask',
|
|
device_model: 'N/A',
|
|
asset_type: 'NATIVE',
|
|
token_standard: 'NONE',
|
|
transaction_type: 'simpleSend',
|
|
transaction_speed_up: false,
|
|
ui_customizations: null,
|
|
category: 'Transactions',
|
|
locale: 'en',
|
|
environment_type: 'background',
|
|
}),
|
|
];
|
|
|
|
const transactionSubmittedWithoutSensitivePropertiesAssertions = [
|
|
messageIdStartsWithTransactionSubmitted,
|
|
eventHasUserIdWithoutAnonymousId,
|
|
(payload) =>
|
|
isEqual(payload.properties, {
|
|
chain_id: '0x539',
|
|
referrer: 'metamask',
|
|
source: 'user',
|
|
network: '1337',
|
|
eip_1559_version: '0',
|
|
gas_edit_type: 'none',
|
|
gas_edit_attempted: 'none',
|
|
account_type: 'MetaMask',
|
|
device_model: 'N/A',
|
|
asset_type: 'NATIVE',
|
|
token_standard: 'NONE',
|
|
transaction_type: 'simpleSend',
|
|
transaction_speed_up: false,
|
|
ui_customizations: null,
|
|
category: 'Transactions',
|
|
locale: 'en',
|
|
environment_type: 'background',
|
|
status: 'submitted',
|
|
}),
|
|
];
|
|
|
|
const transactionFinalizedWithSensitivePropertiesAssertions = [
|
|
messageIdStartsWithTransactionSubmitted,
|
|
messageIdEndsWithZeros,
|
|
eventDoesNotIncludeUserId,
|
|
eventHasZeroAddressAnonymousId,
|
|
(payload) =>
|
|
isEqual(
|
|
omit(payload.properties, ['first_seen', 'completion_time']),
|
|
{
|
|
status: 'confirmed',
|
|
transaction_envelope_type: 'legacy',
|
|
gas_limit: '0x5208',
|
|
gas_price: '2',
|
|
default_gas: '0.000021',
|
|
default_gas_price: '2',
|
|
chain_id: '0x539',
|
|
referrer: 'metamask',
|
|
source: 'user',
|
|
network: '1337',
|
|
eip_1559_version: '0',
|
|
gas_edit_type: 'none',
|
|
gas_edit_attempted: 'none',
|
|
account_type: 'MetaMask',
|
|
device_model: 'N/A',
|
|
asset_type: 'NATIVE',
|
|
token_standard: 'NONE',
|
|
transaction_type: 'simpleSend',
|
|
transaction_speed_up: false,
|
|
ui_customizations: null,
|
|
gas_used: '5208',
|
|
category: 'Transactions',
|
|
locale: 'en',
|
|
environment_type: 'background',
|
|
},
|
|
),
|
|
];
|
|
|
|
const transactionFinalizedWithoutSensitivePropertiesAssertions = [
|
|
messageIdStartsWithTransactionSubmitted,
|
|
eventHasUserIdWithoutAnonymousId,
|
|
(payload) =>
|
|
isEqual(payload.properties, {
|
|
chain_id: '0x539',
|
|
referrer: 'metamask',
|
|
source: 'user',
|
|
network: '1337',
|
|
eip_1559_version: '0',
|
|
gas_edit_type: 'none',
|
|
gas_edit_attempted: 'none',
|
|
account_type: 'MetaMask',
|
|
device_model: 'N/A',
|
|
asset_type: 'NATIVE',
|
|
token_standard: 'NONE',
|
|
transaction_type: 'simpleSend',
|
|
transaction_speed_up: false,
|
|
ui_customizations: null,
|
|
category: 'Transactions',
|
|
locale: 'en',
|
|
environment_type: 'background',
|
|
status: 'confirmed',
|
|
}),
|
|
];
|
|
|
|
const [event1, event2, event3, event4] = events;
|
|
|
|
assertInAnyOrder(
|
|
[event1, event2, event3, event4],
|
|
[
|
|
transactionSubmittedWithSensitivePropertiesAssertions,
|
|
transactionSubmittedWithoutSensitivePropertiesAssertions,
|
|
transactionFinalizedWithSensitivePropertiesAssertions,
|
|
transactionFinalizedWithoutSensitivePropertiesAssertions,
|
|
],
|
|
);
|
|
},
|
|
);
|
|
});
|
|
});
|