mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-28 23:06:37 +01:00
Add types of hidden properties to Sentry data (#20457)
* Add types of hidden properties to Sentry data The masked wallet state object sent to Sentry has been updated to include the type of each property omitted from the mask. This lets us at least see the full state shape, making it easier to see when errors are caused by invalid state. Relates to #20449 * Remove inconsistent state snapshot properties The state snapshot tests have been updated to exclude properties that were shown to differ between runs.
This commit is contained in:
parent
dc7ebe979e
commit
805ce29e11
@ -7,6 +7,8 @@
|
|||||||
* should be included, and a sub-mask implies the property should be further
|
* should be included, and a sub-mask implies the property should be further
|
||||||
* masked according to that sub-mask.
|
* masked according to that sub-mask.
|
||||||
*
|
*
|
||||||
|
* If a property is not found in the last, its type is included instead.
|
||||||
|
*
|
||||||
* @param {object} object - The object to mask
|
* @param {object} object - The object to mask
|
||||||
* @param {Object<object | boolean>} mask - The mask to apply to the object
|
* @param {Object<object | boolean>} mask - The mask to apply to the object
|
||||||
*/
|
*/
|
||||||
@ -16,6 +18,8 @@ export function maskObject(object, mask) {
|
|||||||
state[key] = object[key];
|
state[key] = object[key];
|
||||||
} else if (mask[key]) {
|
} else if (mask[key]) {
|
||||||
state[key] = maskObject(object[key], mask[key]);
|
state[key] = maskObject(object[key], mask[key]);
|
||||||
|
} else {
|
||||||
|
state[key] = typeof object[key];
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}, {});
|
}, {});
|
||||||
|
@ -1,42 +1,72 @@
|
|||||||
const { resolve } = require('path');
|
const { resolve } = require('path');
|
||||||
const { promises: fs } = require('fs');
|
const { promises: fs } = require('fs');
|
||||||
const { strict: assert } = require('assert');
|
const { strict: assert } = require('assert');
|
||||||
const { get, has, set } = require('lodash');
|
const { get, has, set, unset } = require('lodash');
|
||||||
const { Browser } = require('selenium-webdriver');
|
const { Browser } = require('selenium-webdriver');
|
||||||
const { format } = require('prettier');
|
const { format } = require('prettier');
|
||||||
const { convertToHexValue, withFixtures } = require('../helpers');
|
const { convertToHexValue, withFixtures } = require('../helpers');
|
||||||
const FixtureBuilder = require('../fixture-builder');
|
const FixtureBuilder = require('../fixture-builder');
|
||||||
|
|
||||||
const backgroundDateFields = ['CurrencyController.conversionDate'];
|
const maskedBackgroundFields = [
|
||||||
const uiDateFields = ['metamask.conversionDate'];
|
'CurrencyController.conversionDate', // This is a timestamp that changes each run
|
||||||
|
];
|
||||||
|
const maskedUiFields = [
|
||||||
|
'metamask.conversionDate', // This is a timestamp that changes each run
|
||||||
|
];
|
||||||
|
|
||||||
|
const removedBackgroundFields = [
|
||||||
|
// This property is timing-dependent
|
||||||
|
'AccountTracker.currentBlockGasLimit',
|
||||||
|
// These properties are set to undefined, causing inconsistencies between Chrome and Firefox
|
||||||
|
'AppStateController.currentPopupId',
|
||||||
|
'AppStateController.timeoutMinutes',
|
||||||
|
'TokenListController.tokensChainsCache',
|
||||||
|
];
|
||||||
|
|
||||||
|
const removedUiFields = [
|
||||||
|
// This property is timing-dependent
|
||||||
|
'metamask.currentBlockGasLimit',
|
||||||
|
// These properties are set to undefined, causing inconsistencies between Chrome and Firefox
|
||||||
|
'metamask.currentPopupId',
|
||||||
|
'metamask.timeoutMinutes',
|
||||||
|
'metamask.tokensChainsCache',
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform date properties to value types, to ensure that state is
|
* Transform background state to make it consistent between test runs.
|
||||||
* consistent between test runs.
|
|
||||||
*
|
*
|
||||||
* @param {unknown} data - The data to transform
|
* @param {unknown} data - The data to transform
|
||||||
*/
|
*/
|
||||||
function transformBackgroundDates(data) {
|
function transformBackgroundState(data) {
|
||||||
for (const field of backgroundDateFields) {
|
for (const field of maskedBackgroundFields) {
|
||||||
if (has(data, field)) {
|
if (has(data, field)) {
|
||||||
set(data, field, typeof get(data, field));
|
set(data, field, typeof get(data, field));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const field of removedBackgroundFields) {
|
||||||
|
if (has(data, field)) {
|
||||||
|
unset(data, field);
|
||||||
|
}
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform date properties to value types, to ensure that state is
|
* Transform UI state to make it consistent between test runs.
|
||||||
* consistent between test runs.
|
|
||||||
*
|
*
|
||||||
* @param {unknown} data - The data to transform
|
* @param {unknown} data - The data to transform
|
||||||
*/
|
*/
|
||||||
function transformUiDates(data) {
|
function transformUiState(data) {
|
||||||
for (const field of uiDateFields) {
|
for (const field of maskedUiFields) {
|
||||||
if (has(data, field)) {
|
if (has(data, field)) {
|
||||||
set(data, field, typeof get(data, field));
|
set(data, field, typeof get(data, field));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const field of removedUiFields) {
|
||||||
|
if (has(data, field)) {
|
||||||
|
unset(data, field);
|
||||||
|
}
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +287,7 @@ describe('Sentry errors', function () {
|
|||||||
const mockJsonBody = JSON.parse(mockTextBody[2]);
|
const mockJsonBody = JSON.parse(mockTextBody[2]);
|
||||||
const appState = mockJsonBody?.extra?.appState;
|
const appState = mockJsonBody?.extra?.appState;
|
||||||
await matchesSnapshot({
|
await matchesSnapshot({
|
||||||
data: transformBackgroundDates(appState),
|
data: transformBackgroundState(appState),
|
||||||
snapshot: 'errors-before-init-opt-in-background-state',
|
snapshot: 'errors-before-init-opt-in-background-state',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -342,7 +372,7 @@ describe('Sentry errors', function () {
|
|||||||
const mockJsonBody = JSON.parse(mockTextBody[2]);
|
const mockJsonBody = JSON.parse(mockTextBody[2]);
|
||||||
const appState = mockJsonBody?.extra?.appState;
|
const appState = mockJsonBody?.extra?.appState;
|
||||||
await matchesSnapshot({
|
await matchesSnapshot({
|
||||||
data: transformUiDates(appState),
|
data: transformUiState(appState),
|
||||||
snapshot: 'errors-before-init-opt-in-ui-state',
|
snapshot: 'errors-before-init-opt-in-ui-state',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -509,7 +539,7 @@ describe('Sentry errors', function () {
|
|||||||
'Invalid version state',
|
'Invalid version state',
|
||||||
);
|
);
|
||||||
await matchesSnapshot({
|
await matchesSnapshot({
|
||||||
data: transformBackgroundDates(appState.store),
|
data: transformBackgroundState(appState.store),
|
||||||
snapshot: 'errors-after-init-opt-in-background-state',
|
snapshot: 'errors-after-init-opt-in-background-state',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -603,7 +633,7 @@ describe('Sentry errors', function () {
|
|||||||
'Invalid version state',
|
'Invalid version state',
|
||||||
);
|
);
|
||||||
await matchesSnapshot({
|
await matchesSnapshot({
|
||||||
data: transformUiDates(appState.store),
|
data: transformUiState(appState.store),
|
||||||
snapshot: 'errors-after-init-opt-in-ui-state',
|
snapshot: 'errors-after-init-opt-in-ui-state',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1,34 +1,81 @@
|
|||||||
{
|
{
|
||||||
"AccountTracker": { "currentBlockGasLimit": "0x1c9c380" },
|
"AccountTracker": { "accounts": "object" },
|
||||||
"AppStateController": {
|
"AppStateController": {
|
||||||
"connectedStatusPopoverHasBeenShown": true,
|
"connectedStatusPopoverHasBeenShown": true,
|
||||||
"defaultHomeActiveTabName": null
|
"defaultHomeActiveTabName": null,
|
||||||
|
"browserEnvironment": "object",
|
||||||
|
"popupGasPollTokens": "object",
|
||||||
|
"notificationGasPollTokens": "object",
|
||||||
|
"fullScreenGasPollTokens": "object",
|
||||||
|
"recoveryPhraseReminderHasBeenShown": "boolean",
|
||||||
|
"recoveryPhraseReminderLastShown": "number",
|
||||||
|
"outdatedBrowserWarningLastShown": "number",
|
||||||
|
"nftsDetectionNoticeDismissed": "boolean",
|
||||||
|
"showTestnetMessageInDropdown": "boolean",
|
||||||
|
"showBetaHeader": "boolean",
|
||||||
|
"showProductTour": "boolean",
|
||||||
|
"trezorModel": "object",
|
||||||
|
"nftsDropdownState": "object",
|
||||||
|
"termsOfUseLastAgreed": "number",
|
||||||
|
"qrHardware": "object",
|
||||||
|
"usedNetworks": "object",
|
||||||
|
"snapsInstallPrivacyWarningShown": "boolean",
|
||||||
|
"serviceWorkerLastActiveTime": "number"
|
||||||
},
|
},
|
||||||
|
"ApprovalController": "object",
|
||||||
|
"CachedBalancesController": "object",
|
||||||
"CurrencyController": {
|
"CurrencyController": {
|
||||||
"conversionDate": "number",
|
"conversionDate": "number",
|
||||||
"conversionRate": 1700,
|
"conversionRate": 1700,
|
||||||
"nativeCurrency": "ETH",
|
"nativeCurrency": "ETH",
|
||||||
"currentCurrency": "usd"
|
"currentCurrency": "usd",
|
||||||
|
"pendingCurrentCurrency": "object",
|
||||||
|
"pendingNativeCurrency": "object",
|
||||||
|
"usdConversionRate": "number"
|
||||||
|
},
|
||||||
|
"DecryptMessageController": {
|
||||||
|
"unapprovedDecryptMsgs": "object",
|
||||||
|
"unapprovedDecryptMsgCount": 0
|
||||||
},
|
},
|
||||||
"DecryptMessageController": { "unapprovedDecryptMsgCount": 0 },
|
|
||||||
"EncryptionPublicKeyController": {
|
"EncryptionPublicKeyController": {
|
||||||
|
"unapprovedEncryptionPublicKeyMsgs": "object",
|
||||||
"unapprovedEncryptionPublicKeyMsgCount": 0
|
"unapprovedEncryptionPublicKeyMsgCount": 0
|
||||||
},
|
},
|
||||||
|
"EnsController": "object",
|
||||||
"MetaMetricsController": {
|
"MetaMetricsController": {
|
||||||
"participateInMetaMetrics": true,
|
"participateInMetaMetrics": true,
|
||||||
"metaMetricsId": "fake-metrics-id"
|
"metaMetricsId": "fake-metrics-id",
|
||||||
|
"eventsBeforeMetricsOptIn": "object",
|
||||||
|
"traits": "object",
|
||||||
|
"fragments": "object",
|
||||||
|
"segmentApiCalls": "object",
|
||||||
|
"previousUserTraits": "object"
|
||||||
},
|
},
|
||||||
"NetworkController": {
|
"NetworkController": {
|
||||||
|
"selectedNetworkClientId": "string",
|
||||||
"networkId": "1337",
|
"networkId": "1337",
|
||||||
"providerConfig": {
|
"providerConfig": {
|
||||||
|
"chainId": "string",
|
||||||
"nickname": "Localhost 8545",
|
"nickname": "Localhost 8545",
|
||||||
|
"rpcPrefs": "object",
|
||||||
|
"rpcUrl": "string",
|
||||||
"ticker": "ETH",
|
"ticker": "ETH",
|
||||||
"type": "rpc"
|
"type": "rpc",
|
||||||
}
|
"id": "string"
|
||||||
|
},
|
||||||
|
"networksMetadata": "object",
|
||||||
|
"networkConfigurations": "object"
|
||||||
},
|
},
|
||||||
"SignatureController": {
|
"SignatureController": {
|
||||||
|
"unapprovedMsgs": "object",
|
||||||
|
"unapprovedPersonalMsgs": "object",
|
||||||
|
"unapprovedTypedMessages": "object",
|
||||||
"unapprovedMsgCount": 0,
|
"unapprovedMsgCount": 0,
|
||||||
"unapprovedPersonalMsgCount": 0,
|
"unapprovedPersonalMsgCount": 0,
|
||||||
"unapprovedTypedMessagesCount": 0
|
"unapprovedTypedMessagesCount": 0
|
||||||
}
|
},
|
||||||
|
"SwapsController": "object",
|
||||||
|
"TokenRatesController": "object",
|
||||||
|
"TokensController": "object",
|
||||||
|
"TxController": "object"
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,28 @@
|
|||||||
{
|
{
|
||||||
|
"DNS": "object",
|
||||||
|
"activeTab": "object",
|
||||||
|
"appState": "object",
|
||||||
|
"confirmTransaction": "object",
|
||||||
"gas": { "customData": { "price": null, "limit": null } },
|
"gas": { "customData": { "price": null, "limit": null } },
|
||||||
"history": { "mostRecentOverviewPage": "/" },
|
"history": { "mostRecentOverviewPage": "/" },
|
||||||
|
"invalidCustomNetwork": "object",
|
||||||
|
"localeMessages": "object",
|
||||||
"metamask": {
|
"metamask": {
|
||||||
"isInitialized": true,
|
"isInitialized": true,
|
||||||
"isUnlocked": false,
|
"isUnlocked": false,
|
||||||
"isAccountMenuOpen": false,
|
"isAccountMenuOpen": false,
|
||||||
|
"isNetworkMenuOpen": "boolean",
|
||||||
|
"identities": "object",
|
||||||
|
"unapprovedTxs": "object",
|
||||||
|
"networkConfigurations": "object",
|
||||||
|
"addressBook": "object",
|
||||||
|
"contractExchangeRates": "object",
|
||||||
|
"pendingTokens": "object",
|
||||||
"customNonceValue": "",
|
"customNonceValue": "",
|
||||||
"useBlockie": false,
|
"useBlockie": false,
|
||||||
"featureFlags": { "showIncomingTransactions": true },
|
"featureFlags": { "showIncomingTransactions": true },
|
||||||
"welcomeScreenSeen": false,
|
"welcomeScreenSeen": false,
|
||||||
"currentLocale": "en",
|
"currentLocale": "en",
|
||||||
"currentBlockGasLimit": "",
|
|
||||||
"preferences": {
|
"preferences": {
|
||||||
"hideZeroBalanceTokens": false,
|
"hideZeroBalanceTokens": false,
|
||||||
"showFiatInTestnets": false,
|
"showFiatInTestnets": false,
|
||||||
@ -19,31 +31,89 @@
|
|||||||
},
|
},
|
||||||
"firstTimeFlowType": "import",
|
"firstTimeFlowType": "import",
|
||||||
"completedOnboarding": true,
|
"completedOnboarding": true,
|
||||||
|
"knownMethodData": "object",
|
||||||
|
"use4ByteResolution": "boolean",
|
||||||
"participateInMetaMetrics": true,
|
"participateInMetaMetrics": true,
|
||||||
"nextNonce": null,
|
"nextNonce": null,
|
||||||
"conversionRate": 1300,
|
"conversionRate": 1300,
|
||||||
"nativeCurrency": "ETH",
|
"nativeCurrency": "ETH",
|
||||||
"connectedStatusPopoverHasBeenShown": true,
|
"connectedStatusPopoverHasBeenShown": true,
|
||||||
"defaultHomeActiveTabName": null,
|
"defaultHomeActiveTabName": null,
|
||||||
|
"browserEnvironment": "object",
|
||||||
|
"popupGasPollTokens": "object",
|
||||||
|
"notificationGasPollTokens": "object",
|
||||||
|
"fullScreenGasPollTokens": "object",
|
||||||
|
"recoveryPhraseReminderHasBeenShown": "boolean",
|
||||||
|
"recoveryPhraseReminderLastShown": "number",
|
||||||
|
"outdatedBrowserWarningLastShown": "number",
|
||||||
|
"nftsDetectionNoticeDismissed": "boolean",
|
||||||
|
"showTestnetMessageInDropdown": "boolean",
|
||||||
|
"showBetaHeader": "boolean",
|
||||||
|
"showProductTour": "boolean",
|
||||||
|
"trezorModel": "object",
|
||||||
|
"nftsDropdownState": "object",
|
||||||
|
"termsOfUseLastAgreed": "number",
|
||||||
|
"qrHardware": "object",
|
||||||
|
"usedNetworks": "object",
|
||||||
|
"snapsInstallPrivacyWarningShown": "boolean",
|
||||||
|
"serviceWorkerLastActiveTime": "number",
|
||||||
"currentAppVersion": "10.34.4",
|
"currentAppVersion": "10.34.4",
|
||||||
"previousAppVersion": "",
|
"previousAppVersion": "",
|
||||||
"previousMigrationVersion": 0,
|
"previousMigrationVersion": 0,
|
||||||
"currentMigrationVersion": 94,
|
"currentMigrationVersion": 94,
|
||||||
|
"selectedNetworkClientId": "string",
|
||||||
"networkId": "1337",
|
"networkId": "1337",
|
||||||
"providerConfig": {
|
"providerConfig": {
|
||||||
|
"chainId": "string",
|
||||||
"nickname": "Localhost 8545",
|
"nickname": "Localhost 8545",
|
||||||
|
"rpcPrefs": "object",
|
||||||
|
"rpcUrl": "string",
|
||||||
"ticker": "ETH",
|
"ticker": "ETH",
|
||||||
"type": "rpc"
|
"type": "rpc",
|
||||||
|
"id": "string"
|
||||||
},
|
},
|
||||||
|
"networksMetadata": "object",
|
||||||
|
"cachedBalances": "object",
|
||||||
|
"keyringTypes": "object",
|
||||||
|
"keyrings": "object",
|
||||||
"useNonceField": false,
|
"useNonceField": false,
|
||||||
"usePhishDetect": true,
|
"usePhishDetect": true,
|
||||||
|
"dismissSeedBackUpReminder": "boolean",
|
||||||
|
"disabledRpcMethodPreferences": "object",
|
||||||
|
"useMultiAccountBalanceChecker": "boolean",
|
||||||
|
"useTokenDetection": "boolean",
|
||||||
|
"useNftDetection": "boolean",
|
||||||
|
"useCurrencyRateCheck": "boolean",
|
||||||
|
"openSeaEnabled": "boolean",
|
||||||
|
"advancedGasFee": "object",
|
||||||
|
"lostIdentities": "object",
|
||||||
"forgottenPassword": false,
|
"forgottenPassword": false,
|
||||||
"ipfsGateway": "dweb.link",
|
"ipfsGateway": "dweb.link",
|
||||||
|
"useAddressBarEnsResolution": "boolean",
|
||||||
|
"infuraBlocked": "boolean",
|
||||||
|
"ledgerTransportType": "string",
|
||||||
|
"snapRegistryList": "object",
|
||||||
|
"transactionSecurityCheckEnabled": "boolean",
|
||||||
|
"theme": "string",
|
||||||
|
"isLineaMainnetReleased": "boolean",
|
||||||
|
"selectedAddress": "string",
|
||||||
"metaMetricsId": "fake-metrics-id",
|
"metaMetricsId": "fake-metrics-id",
|
||||||
|
"eventsBeforeMetricsOptIn": "object",
|
||||||
|
"traits": "object",
|
||||||
|
"fragments": "object",
|
||||||
|
"segmentApiCalls": "object",
|
||||||
|
"previousUserTraits": "object",
|
||||||
"conversionDate": "number",
|
"conversionDate": "number",
|
||||||
"currentCurrency": "usd",
|
"currentCurrency": "usd",
|
||||||
|
"pendingCurrentCurrency": "object",
|
||||||
|
"pendingNativeCurrency": "object",
|
||||||
|
"usdConversionRate": "number",
|
||||||
"alertEnabledness": { "unconnectedAccount": true, "web3ShimUsage": true },
|
"alertEnabledness": { "unconnectedAccount": true, "web3ShimUsage": true },
|
||||||
|
"unconnectedAccountAlertShownOrigins": "object",
|
||||||
|
"web3ShimUsageOrigins": "object",
|
||||||
"seedPhraseBackedUp": true,
|
"seedPhraseBackedUp": true,
|
||||||
|
"onboardingTabs": "object",
|
||||||
|
"incomingTransactions": "object",
|
||||||
"incomingTxLastFetchedBlockByChainId": {
|
"incomingTxLastFetchedBlockByChainId": {
|
||||||
"0x1": null,
|
"0x1": null,
|
||||||
"0xe708": null,
|
"0xe708": null,
|
||||||
@ -51,11 +121,45 @@
|
|||||||
"0xaa36a7": null,
|
"0xaa36a7": null,
|
||||||
"0xe704": null
|
"0xe704": null
|
||||||
},
|
},
|
||||||
|
"subjects": "object",
|
||||||
|
"permissionHistory": "object",
|
||||||
|
"permissionActivityLog": "object",
|
||||||
|
"subjectMetadata": "object",
|
||||||
|
"announcements": "object",
|
||||||
|
"gasFeeEstimates": "object",
|
||||||
|
"estimatedGasFeeTimeBounds": "object",
|
||||||
|
"gasEstimateType": "string",
|
||||||
|
"tokenList": "object",
|
||||||
|
"preventPollingOnNetworkRestart": "boolean",
|
||||||
|
"tokens": "object",
|
||||||
|
"ignoredTokens": "object",
|
||||||
|
"detectedTokens": "object",
|
||||||
|
"allTokens": "object",
|
||||||
|
"allIgnoredTokens": "object",
|
||||||
|
"allDetectedTokens": "object",
|
||||||
|
"smartTransactionsState": "object",
|
||||||
|
"allNftContracts": "object",
|
||||||
|
"allNfts": "object",
|
||||||
|
"ignoredNfts": "object",
|
||||||
|
"accounts": "object",
|
||||||
|
"currentNetworkTxList": "object",
|
||||||
|
"unapprovedDecryptMsgs": "object",
|
||||||
"unapprovedDecryptMsgCount": 0,
|
"unapprovedDecryptMsgCount": 0,
|
||||||
|
"unapprovedEncryptionPublicKeyMsgs": "object",
|
||||||
"unapprovedEncryptionPublicKeyMsgCount": 0,
|
"unapprovedEncryptionPublicKeyMsgCount": 0,
|
||||||
|
"unapprovedMsgs": "object",
|
||||||
|
"unapprovedPersonalMsgs": "object",
|
||||||
|
"unapprovedTypedMessages": "object",
|
||||||
"unapprovedMsgCount": 0,
|
"unapprovedMsgCount": 0,
|
||||||
"unapprovedPersonalMsgCount": 0,
|
"unapprovedPersonalMsgCount": 0,
|
||||||
"unapprovedTypedMessagesCount": 0
|
"unapprovedTypedMessagesCount": 0,
|
||||||
|
"swapsState": "object",
|
||||||
|
"ensResolutionsByAddress": "object",
|
||||||
|
"pendingApprovals": "object",
|
||||||
|
"pendingApprovalCount": "number",
|
||||||
|
"approvalFlows": "object"
|
||||||
},
|
},
|
||||||
|
"send": "object",
|
||||||
|
"swaps": "object",
|
||||||
"unconnectedAccount": { "state": "CLOSED" }
|
"unconnectedAccount": { "state": "CLOSED" }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user