diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index c6d29995e..befecf21c 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -1,6 +1,7 @@ import * as Sentry from '@sentry/browser'; import { Dedupe, ExtraErrorData } from '@sentry/integrations'; +import { AllProperties } from '../../../shared/modules/object.utils'; import { FilterEvents } from './sentry-filter-events'; import extractEthjsErrorMessage from './extractEthjsErrorMessage'; @@ -28,75 +29,254 @@ export const ERROR_URL_ALLOWLIST = { // debugging, and they do not contain any identifiable information. export const SENTRY_BACKGROUND_STATE = { AccountTracker: { + accounts: false, currentBlockGasLimit: true, }, + AddressBookController: { + addressBook: false, + }, AlertController: { alertEnabledness: true, + unconnectedAccountAlertShownOrigins: false, + web3ShimUsageOrigins: false, + }, + AnnouncementController: { + announcements: false, }, AppMetadataController: { currentAppVersion: true, + currentMigrationVersion: true, previousAppVersion: true, previousMigrationVersion: true, - currentMigrationVersion: true, + }, + ApprovalController: { + approvalFlows: false, + pendingApprovals: false, + pendingApprovalCount: false, }, AppStateController: { + browserEnvironment: true, connectedStatusPopoverHasBeenShown: true, + currentPopupId: false, defaultHomeActiveTabName: true, + fullScreenGasPollTokens: true, + hadAdvancedGasFeesSetPriorToMigration92_3: true, + nftsDetectionNoticeDismissed: true, + nftsDropdownState: true, + notificationGasPollTokens: true, + outdatedBrowserWarningLastShown: true, + popupGasPollTokens: true, + qrHardware: true, + recoveryPhraseReminderHasBeenShown: true, + recoveryPhraseReminderLastShown: true, + serviceWorkerLastActiveTime: true, + showBetaHeader: true, + showProductTour: true, + showTestnetMessageInDropdown: true, + snapsInstallPrivacyWarningShown: true, + termsOfUseLastAgreed: true, + timeoutMinutes: true, + trezorModel: true, + usedNetworks: true, + }, + CachedBalancesController: { + cachedBalances: false, }, CurrencyController: { conversionDate: true, conversionRate: true, currentCurrency: true, nativeCurrency: true, + pendingCurrentCurrency: true, + pendingNativeCurrency: true, + usdConversionRate: true, }, DecryptMessageController: { + unapprovedDecryptMsgs: false, unapprovedDecryptMsgCount: true, }, - DesktopController: { - desktopEnabled: true, - }, EncryptionPublicKeyController: { + unapprovedEncryptionPublicKeyMsgs: false, unapprovedEncryptionPublicKeyMsgCount: true, }, + EnsController: { + ensResolutionsByAddress: false, + }, + GasFeeController: { + estimatedGasFeeTimeBounds: true, + gasEstimateType: true, + gasFeeEstimates: true, + }, IncomingTransactionsController: { + incomingTransactions: false, incomingTxLastFetchedBlockByChainId: true, }, KeyringController: { + encryptionKey: false, isUnlocked: true, + keyrings: false, + keyringTypes: false, }, MetaMetricsController: { + eventsBeforeMetricsOptIn: false, + fragments: false, metaMetricsId: true, participateInMetaMetrics: true, + previousUserTraits: false, + segmentApiCalls: false, + traits: false, }, NetworkController: { + networkConfigurations: false, + networkDetails: false, networkId: true, networkStatus: true, providerConfig: { + chainId: true, + id: true, nickname: true, + rpcPrefs: false, + rpcUrl: false, ticker: true, type: true, }, }, + NftController: { + allNftContracts: false, + allNfts: false, + ignoredNfts: false, + }, OnboardingController: { completedOnboarding: true, firstTimeFlowType: true, + onboardingTabs: false, seedPhraseBackedUp: true, }, + PermissionController: { + subjects: false, + }, + PermissionLogController: { + permissionActivityLog: false, + permissionHistory: false, + }, + PhishingController: {}, PreferencesController: { + advancedGasFee: true, currentLocale: true, + disabledRpcMethodPreferences: true, + dismissSeedBackUpReminder: true, featureFlags: true, forgottenPassword: true, - ipfsGateway: true, - preferences: true, + identities: false, + infuraBlocked: true, + ipfsGateway: false, + isLineaMainnetReleased: true, + knownMethodData: false, + ledgerTransportType: true, + lostIdentities: false, + openSeaEnabled: true, + preferences: { + autoLockTimeLimit: true, + hideZeroBalanceTokens: true, + showFiatInTestnets: true, + showTestNetworks: true, + useNativeCurrencyAsPrimaryCurrency: true, + }, + selectedAddress: false, + snapRegistryList: false, + theme: true, + transactionSecurityCheckEnabled: true, useBlockie: true, + useCurrencyRateCheck: true, + useMultiAccountBalanceChecker: true, + useNftDetection: true, useNonceField: true, usePhishDetect: true, + useTokenDetection: true, }, SignatureController: { unapprovedMsgCount: true, + unapprovedMsgs: false, unapprovedPersonalMsgCount: true, + unapprovedPersonalMsgs: false, + unapprovedTypedMessages: false, unapprovedTypedMessagesCount: true, }, + SmartTransactionsController: { + smartTransactionsState: { + fees: { + approvalTxFees: true, + tradeTxFees: true, + }, + liveness: true, + smartTransactions: false, + userOptIn: true, + }, + }, + SubjectMetadataController: { + subjectMetadata: false, + }, + SwapsController: { + swapsState: { + approveTxId: false, + customApproveTxData: false, + customGasPrice: true, + customMaxFeePerGas: true, + customMaxGas: true, + customMaxPriorityFeePerGas: true, + errorKey: true, + fetchParams: true, + quotes: false, + quotesLastFetched: true, + quotesPollingLimitEnabled: true, + routeState: true, + saveFetchedQuotes: true, + selectedAggId: true, + swapsFeatureFlags: true, + swapsFeatureIsLive: true, + swapsQuotePrefetchingRefreshTime: true, + swapsQuoteRefreshTime: true, + swapsStxBatchStatusRefreshTime: true, + swapsStxGetTransactionsRefreshTime: true, + swapsStxMaxFeeMultiplier: true, + swapsUserFeeLevel: true, + tokens: false, + topAggId: false, + tradeTxId: false, + }, + }, + TokenListController: { + preventPollingOnNetworkRestart: true, + tokenList: false, + tokensChainsCache: { + [AllProperties]: false, + }, + }, + TokenRatesController: { + contractExchangeRates: false, + }, + TokensController: { + allDetectedTokens: { + [AllProperties]: false, + }, + allIgnoredTokens: { + [AllProperties]: false, + }, + allTokens: { + [AllProperties]: false, + }, + detectedTokens: false, + ignoredTokens: false, + tokens: false, + }, + TransactionController: { + currentNetworkTxList: false, + lastFetchedBlockNumbers: false, + }, + TxController: { + currentNetworkTxList: false, + unapprovedTxs: false, + }, }; const flattenedBackgroundStateMask = Object.values( @@ -121,7 +301,9 @@ export const SENTRY_UI_STATE = { // These properties are in the `metamask` slice but not in the background state customNonceValue: true, isAccountMenuOpen: true, + isNetworkMenuOpen: true, nextNonce: true, + pendingTokens: false, welcomeScreenSeen: true, }, unconnectedAccount: true, diff --git a/shared/modules/object.utils.js b/shared/modules/object.utils.js index ce7eb1da1..218b5389f 100644 --- a/shared/modules/object.utils.js +++ b/shared/modules/object.utils.js @@ -1,25 +1,43 @@ /** - * Return a "masked" copy of the given object. + * This symbol matches all object properties when used in a mask + */ +export const AllProperties = Symbol('*'); + +/** + * Return a "masked" copy of the given object. The returned object includes + * only the properties present in the mask. * - * The returned object includes only the properties present in the mask. The - * mask is an object that mirrors the structure of the given object, except - * the only values are `true` or a sub-mask. `true` implies the property - * should be included, and a sub-mask implies the property should be further - * masked according to that sub-mask. + * The mask is an object that mirrors the structure of the given object, except + * the only values are `true`, `false, a sub-mask, or the 'AllProperties" + * symbol. `true` implies the property should be included, and `false` will + * exclude it. A sub-mask implies the property should be further masked + * according to that sub-mask. The "AllProperties" symbol is used for objects + * with dynamic keys, and applies a rule (either `true`, `false`, or a + * sub-mask`) to every property in that object. * - * If a property is not found in the last, its type is included instead. + * If a property is excluded, its type is included instead. * * @param {object} object - The object to mask * @param {Object} mask - The mask to apply to the object */ export function maskObject(object, mask) { + let maskAllProperties = false; + if (Object.keys(mask).includes(AllProperties)) { + if (Object.keys(mask).length > 1) { + throw new Error('AllProperties mask key does not support sibling keys'); + } + maskAllProperties = true; + } return Object.keys(object).reduce((state, key) => { - if (mask[key] === true) { + const maskKey = maskAllProperties ? mask[AllProperties] : mask[key]; + if (maskKey === true) { state[key] = object[key]; - } else if (mask[key]) { - state[key] = maskObject(object[key], mask[key]); - } else { + } else if (maskKey && typeof maskKey === 'object') { + state[key] = maskObject(object[key], maskKey); + } else if (maskKey === undefined || maskKey === false) { state[key] = typeof object[key]; + } else { + throw new Error(`Unsupported mask entry: ${maskKey}`); } return state; }, {}); diff --git a/test/e2e/tests/errors.spec.js b/test/e2e/tests/errors.spec.js index 7d7e12424..9c4927a78 100644 --- a/test/e2e/tests/errors.spec.js +++ b/test/e2e/tests/errors.spec.js @@ -4,8 +4,24 @@ const { strict: assert } = require('assert'); const { get, has, set, unset } = require('lodash'); const { Browser } = require('selenium-webdriver'); const { format } = require('prettier'); -const { convertToHexValue, withFixtures } = require('../helpers'); +const { isObject } = require('@metamask/utils'); +const { SENTRY_UI_STATE } = require('../../../app/scripts/lib/setupSentry'); const FixtureBuilder = require('../fixture-builder'); +const { convertToHexValue, withFixtures } = require('../helpers'); + +/** + * Derive a UI state field from a background state field. + * + * @param {string} backgroundField - The path of a background field. + * @returns {string} The path for the corresponding UI field. + */ +function backgroundToUiField(backgroundField) { + // The controller name is lost in the UI due to state flattening + const [, ...rest] = backgroundField.split('.'); + const flattenedBackgroundField = rest.join('.'); + // Controller state is under the 'metamask' slice in the UI + return `metamask.${flattenedBackgroundField}`; +} const maskedBackgroundFields = [ 'CurrencyController.conversionDate', // This is a timestamp that changes each run @@ -13,14 +29,13 @@ const maskedBackgroundFields = [ // part of the release process 'AppMetadataController.currentAppVersion', 'AppMetadataController.currentMigrationVersion', + 'AppStateController.browserEnvironment.browser', + 'AppStateController.browserEnvironment.os', + 'AppStateController.outdatedBrowserWarningLastShown', + 'AppStateController.recoveryPhraseReminderLastShown', + 'AppStateController.termsOfUseLastAgreed', ]; -const maskedUiFields = [ - 'metamask.conversionDate', // This is a timestamp that changes each run - // App metadata is masked so that we don't have to update the snapshot as - // part of the release process - 'metamask.currentAppVersion', - 'metamask.currentMigrationVersion', -]; +const maskedUiFields = maskedBackgroundFields.map(backgroundToUiField); const removedBackgroundFields = [ // This property is timing-dependent @@ -30,13 +45,7 @@ const removedBackgroundFields = [ 'AppStateController.timeoutMinutes', ]; -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', -]; +const removedUiFields = removedBackgroundFields.map(backgroundToUiField); /** * Transform background state to make it consistent between test runs. @@ -115,6 +124,38 @@ async function matchesSnapshot({ } } +/** + * Get an object consisting of all properties in the complete + * object that are missing from the given object. + * + * @param {object} complete - The complete object to compare to. + * @param {object} object - The object to test for missing properties. + */ +function getMissingProperties(complete, object) { + const missing = {}; + for (const [key, value] of Object.entries(complete)) { + if (key in object) { + if (isObject(value) && isObject(object[key])) { + const missingNestedProperties = getMissingProperties( + value, + object[key], + ); + if (Object.keys(missingNestedProperties).length > 0) { + missing[key] = missingNestedProperties; + } else { + // no missing nested properties + } + } else { + // Skip non-object values, they are considered as present + // even if they represent masked data structures + } + } else { + missing[key] = value; + } + } + return missing; +} + describe('Sentry errors', function () { const migrationError = process.env.SELENIUM_BROWSER === Browser.CHROME @@ -320,7 +361,10 @@ describe('Sentry errors', function () { 'Invalid version state', ); await matchesSnapshot({ - data: transformBackgroundState(appState.persistedState), + data: { + ...appState.persistedState, + data: transformBackgroundState(appState.persistedState.data), + }, snapshot: 'errors-before-init-opt-in-background-state', }); }, @@ -468,7 +512,10 @@ describe('Sentry errors', function () { 'Invalid version state', ); await matchesSnapshot({ - data: transformBackgroundState(appState.persistedState), + data: { + ...appState.persistedState, + data: transformBackgroundState(appState.persistedState.data), + }, snapshot: 'errors-before-init-opt-in-ui-state', }); }, @@ -736,4 +783,80 @@ describe('Sentry errors', function () { ); }); }); + + it('should have no policy gaps for UI controller state', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.findElement('#password'); + + const fullUiState = await driver.executeScript(() => + window.stateHooks?.getCleanAppState?.(), + ); + + const missingState = getMissingProperties( + fullUiState.metamask, + SENTRY_UI_STATE.metamask, + ); + assert.deepEqual(missingState, {}); + }, + ); + }); + + it('should not have extra properties in UI state mask', async function () { + const expectedMissingState = { + currentPopupId: false, // Initialized as undefined + // Part of transaction controller store, but missing from the initial + // state + lastFetchedBlockNumbers: false, + preferences: { + autoLockTimeLimit: true, // Initialized as undefined + }, + smartTransactionsState: { + fees: { + approvalTxFees: true, // Initialized as undefined + tradeTxFees: true, // Initialized as undefined + }, + userOptIn: true, // Initialized as undefined + }, + swapsState: { + // This can get wiped out during initialization due to a bug in + // the "resetState" method + swapsFeatureFlags: true, + }, + // This can get erased due to a bug in the app state controller's + // preferences state change handler + timeoutMinutes: true, + }; + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.findElement('#password'); + + const fullUiState = await driver.executeScript(() => + window.stateHooks?.getCleanAppState?.(), + ); + + const extraMaskProperties = getMissingProperties( + SENTRY_UI_STATE.metamask, + fullUiState.metamask, + ); + const unexpectedExtraMaskProperties = getMissingProperties( + extraMaskProperties, + expectedMissingState, + ); + assert.deepEqual(unexpectedExtraMaskProperties, {}); + }, + ); + }); }); diff --git a/test/e2e/tests/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/state-snapshots/errors-after-init-opt-in-background-state.json index e8191f915..8edcbc646 100644 --- a/test/e2e/tests/state-snapshots/errors-after-init-opt-in-background-state.json +++ b/test/e2e/tests/state-snapshots/errors-after-init-opt-in-background-state.json @@ -1,12 +1,12 @@ { "AccountTracker": { "accounts": "object" }, - "AddressBookController": "object", + "AddressBookController": { "addressBook": "object" }, "AlertController": { "alertEnabledness": { "unconnectedAccount": true, "web3ShimUsage": true }, "unconnectedAccountAlertShownOrigins": "object", "web3ShimUsageOrigins": "object" }, - "AnnouncementController": "object", + "AnnouncementController": { "announcements": "object" }, "AppMetadataController": { "currentAppVersion": "string", "previousAppVersion": "", @@ -16,37 +16,41 @@ "AppStateController": { "connectedStatusPopoverHasBeenShown": true, "defaultHomeActiveTabName": null, - "browserEnvironment": "object", - "popupGasPollTokens": "object", - "notificationGasPollTokens": "object", - "fullScreenGasPollTokens": "object", - "recoveryPhraseReminderHasBeenShown": "boolean", + "browserEnvironment": { "os": "string", "browser": "string" }, + "popupGasPollTokens": [], + "notificationGasPollTokens": [], + "fullScreenGasPollTokens": [], + "recoveryPhraseReminderHasBeenShown": true, "recoveryPhraseReminderLastShown": "number", "outdatedBrowserWarningLastShown": "number", - "nftsDetectionNoticeDismissed": "boolean", - "showTestnetMessageInDropdown": "boolean", - "showBetaHeader": "boolean", - "showProductTour": "boolean", - "trezorModel": "object", - "nftsDropdownState": "object", + "nftsDetectionNoticeDismissed": false, + "showTestnetMessageInDropdown": true, + "showBetaHeader": false, + "showProductTour": true, + "trezorModel": null, + "hadAdvancedGasFeesSetPriorToMigration92_3": false, + "nftsDropdownState": {}, "termsOfUseLastAgreed": "number", - "qrHardware": "object", - "usedNetworks": "object", - "snapsInstallPrivacyWarningShown": "boolean", - "hadAdvancedGasFeesSetPriorToMigration92_3": "boolean", - "serviceWorkerLastActiveTime": "number" + "qrHardware": {}, + "usedNetworks": { "0x1": true, "0x5": true, "0x539": true }, + "snapsInstallPrivacyWarningShown": true, + "serviceWorkerLastActiveTime": 0 + }, + "ApprovalController": { + "pendingApprovals": "object", + "pendingApprovalCount": "number", + "approvalFlows": "object" }, - "ApprovalController": "object", "BackupController": "undefined", - "CachedBalancesController": "object", + "CachedBalancesController": { "cachedBalances": "object" }, "CurrencyController": { "conversionDate": "number", "conversionRate": 1700, "nativeCurrency": "ETH", "currentCurrency": "usd", - "pendingCurrentCurrency": "object", - "pendingNativeCurrency": "object", - "usdConversionRate": "number" + "pendingCurrentCurrency": null, + "pendingNativeCurrency": null, + "usdConversionRate": 1700 }, "DecryptMessageController": { "unapprovedDecryptMsgs": "object", @@ -56,8 +60,12 @@ "unapprovedEncryptionPublicKeyMsgs": "object", "unapprovedEncryptionPublicKeyMsgCount": 0 }, - "EnsController": "object", - "GasFeeController": "object", + "EnsController": { "ensResolutionsByAddress": "object" }, + "GasFeeController": { + "gasFeeEstimates": {}, + "estimatedGasFeeTimeBounds": {}, + "gasEstimateType": "none" + }, "IncomingTransactionsController": { "incomingTransactions": "object", "incomingTxLastFetchedBlockByChainId": { @@ -87,38 +95,45 @@ "networkId": "1337", "networkStatus": "available", "providerConfig": { - "chainId": "string", + "chainId": "0x539", "nickname": "Localhost 8545", "rpcPrefs": "object", "rpcUrl": "string", "ticker": "ETH", "type": "rpc", - "id": "string" + "id": "networkConfigurationId" }, "networkDetails": "object", "networkConfigurations": "object" }, - "NftController": "object", + "NftController": { + "allNftContracts": "object", + "allNfts": "object", + "ignoredNfts": "object" + }, "OnboardingController": { "seedPhraseBackedUp": true, "firstTimeFlowType": "import", "completedOnboarding": true, "onboardingTabs": "object" }, - "PermissionController": "object", - "PermissionLogController": "object", + "PermissionController": { "subjects": "object" }, + "PermissionLogController": { + "permissionHistory": "object", + "permissionActivityLog": "object" + }, "PreferencesController": { "useBlockie": false, "useNonceField": false, "usePhishDetect": true, - "dismissSeedBackUpReminder": "boolean", - "disabledRpcMethodPreferences": "object", - "useMultiAccountBalanceChecker": "boolean", - "useTokenDetection": "boolean", - "useNftDetection": "boolean", - "useCurrencyRateCheck": "boolean", - "openSeaEnabled": "boolean", - "advancedGasFee": "object", + "dismissSeedBackUpReminder": true, + "disabledRpcMethodPreferences": { "eth_sign": false }, + "useMultiAccountBalanceChecker": true, + "useTokenDetection": false, + "useNftDetection": false, + "useCurrencyRateCheck": true, + "openSeaEnabled": false, + "advancedGasFee": {}, "featureFlags": { "showIncomingTransactions": true }, "knownMethodData": "object", "currentLocale": "en", @@ -131,13 +146,13 @@ "showTestNetworks": false, "useNativeCurrencyAsPrimaryCurrency": true }, - "ipfsGateway": "dweb.link", - "infuraBlocked": "boolean", - "ledgerTransportType": "string", + "ipfsGateway": "string", + "infuraBlocked": false, + "ledgerTransportType": "webhid", "snapRegistryList": "object", - "transactionSecurityCheckEnabled": "boolean", - "theme": "string", - "isLineaMainnetReleased": "boolean", + "transactionSecurityCheckEnabled": false, + "theme": "light", + "isLineaMainnetReleased": true, "selectedAddress": "string" }, "SignatureController": { @@ -148,11 +163,58 @@ "unapprovedPersonalMsgCount": 0, "unapprovedTypedMessagesCount": 0 }, - "SmartTransactionsController": "object", - "SubjectMetadataController": "object", - "SwapsController": "object", - "TokenListController": "object", - "TokenRatesController": "object", - "TokensController": "object", - "TxController": "object" + "SmartTransactionsController": { + "smartTransactionsState": { + "fees": {}, + "liveness": true, + "smartTransactions": "object" + } + }, + "SubjectMetadataController": { "subjectMetadata": "object" }, + "SwapsController": { + "swapsState": { + "quotes": "object", + "quotesPollingLimitEnabled": false, + "fetchParams": null, + "tokens": "object", + "tradeTxId": "object", + "approveTxId": "object", + "quotesLastFetched": null, + "customMaxGas": "", + "customGasPrice": null, + "customMaxFeePerGas": null, + "customMaxPriorityFeePerGas": null, + "swapsUserFeeLevel": "", + "selectedAggId": null, + "customApproveTxData": "string", + "errorKey": "", + "topAggId": "object", + "routeState": "", + "swapsFeatureIsLive": true, + "saveFetchedQuotes": false, + "swapsQuoteRefreshTime": 60000, + "swapsQuotePrefetchingRefreshTime": 60000, + "swapsStxBatchStatusRefreshTime": 10000, + "swapsStxGetTransactionsRefreshTime": 10000, + "swapsStxMaxFeeMultiplier": 2 + } + }, + "TokenListController": { + "tokenList": "object", + "tokensChainsCache": {}, + "preventPollingOnNetworkRestart": true + }, + "TokenRatesController": { "contractExchangeRates": "object" }, + "TokensController": { + "tokens": "object", + "ignoredTokens": "object", + "detectedTokens": "object", + "allTokens": {}, + "allIgnoredTokens": {}, + "allDetectedTokens": {} + }, + "TxController": { + "unapprovedTxs": "object", + "currentNetworkTxList": "object" + } } diff --git a/test/e2e/tests/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/state-snapshots/errors-after-init-opt-in-ui-state.json index 64a08f7b4..546004f9f 100644 --- a/test/e2e/tests/state-snapshots/errors-after-init-opt-in-ui-state.json +++ b/test/e2e/tests/state-snapshots/errors-after-init-opt-in-ui-state.json @@ -11,7 +11,7 @@ "isInitialized": true, "isUnlocked": false, "isAccountMenuOpen": false, - "isNetworkMenuOpen": "boolean", + "isNetworkMenuOpen": false, "identities": "object", "unapprovedTxs": "object", "networkConfigurations": "object", @@ -38,25 +38,25 @@ "nativeCurrency": "ETH", "connectedStatusPopoverHasBeenShown": true, "defaultHomeActiveTabName": null, - "browserEnvironment": "object", - "popupGasPollTokens": "object", - "notificationGasPollTokens": "object", - "fullScreenGasPollTokens": "object", - "recoveryPhraseReminderHasBeenShown": "boolean", + "browserEnvironment": { "os": "string", "browser": "string" }, + "popupGasPollTokens": [], + "notificationGasPollTokens": [], + "fullScreenGasPollTokens": [], + "recoveryPhraseReminderHasBeenShown": true, "recoveryPhraseReminderLastShown": "number", "outdatedBrowserWarningLastShown": "number", - "nftsDetectionNoticeDismissed": "boolean", - "showTestnetMessageInDropdown": "boolean", - "showBetaHeader": "boolean", - "showProductTour": "boolean", - "trezorModel": "object", - "nftsDropdownState": "object", + "nftsDetectionNoticeDismissed": false, + "showTestnetMessageInDropdown": true, + "showBetaHeader": false, + "showProductTour": true, + "trezorModel": null, + "hadAdvancedGasFeesSetPriorToMigration92_3": false, + "nftsDropdownState": {}, "termsOfUseLastAgreed": "number", - "qrHardware": "object", - "usedNetworks": "object", - "snapsInstallPrivacyWarningShown": "boolean", - "hadAdvancedGasFeesSetPriorToMigration92_3": "boolean", - "serviceWorkerLastActiveTime": "number", + "qrHardware": {}, + "usedNetworks": { "0x1": true, "0x5": true, "0x539": true }, + "snapsInstallPrivacyWarningShown": true, + "serviceWorkerLastActiveTime": 0, "currentAppVersion": "string", "previousAppVersion": "", "previousMigrationVersion": 0, @@ -64,13 +64,13 @@ "networkId": "1337", "networkStatus": "available", "providerConfig": { - "chainId": "string", + "chainId": "0x539", "nickname": "Localhost 8545", "rpcPrefs": "object", "rpcUrl": "string", "ticker": "ETH", "type": "rpc", - "id": "string" + "id": "networkConfigurationId" }, "networkDetails": "object", "cachedBalances": "object", @@ -79,23 +79,23 @@ "encryptionKey": "object", "useNonceField": false, "usePhishDetect": true, - "dismissSeedBackUpReminder": "boolean", - "disabledRpcMethodPreferences": "object", - "useMultiAccountBalanceChecker": "boolean", - "useTokenDetection": "boolean", - "useNftDetection": "boolean", - "useCurrencyRateCheck": "boolean", - "openSeaEnabled": "boolean", - "advancedGasFee": "object", + "dismissSeedBackUpReminder": true, + "disabledRpcMethodPreferences": { "eth_sign": false }, + "useMultiAccountBalanceChecker": true, + "useTokenDetection": false, + "useNftDetection": false, + "useCurrencyRateCheck": true, + "openSeaEnabled": false, + "advancedGasFee": {}, "lostIdentities": "object", "forgottenPassword": false, - "ipfsGateway": "dweb.link", - "infuraBlocked": "boolean", - "ledgerTransportType": "string", + "ipfsGateway": "string", + "infuraBlocked": false, + "ledgerTransportType": "webhid", "snapRegistryList": "object", - "transactionSecurityCheckEnabled": "boolean", - "theme": "string", - "isLineaMainnetReleased": "boolean", + "transactionSecurityCheckEnabled": false, + "theme": "light", + "isLineaMainnetReleased": true, "selectedAddress": "string", "metaMetricsId": "fake-metrics-id", "eventsBeforeMetricsOptIn": "object", @@ -105,9 +105,9 @@ "previousUserTraits": "object", "conversionDate": "number", "currentCurrency": "usd", - "pendingCurrentCurrency": "object", - "pendingNativeCurrency": "object", - "usdConversionRate": "number", + "pendingCurrentCurrency": null, + "pendingNativeCurrency": null, + "usdConversionRate": 1300, "alertEnabledness": { "unconnectedAccount": true, "web3ShimUsage": true }, "unconnectedAccountAlertShownOrigins": "object", "web3ShimUsageOrigins": "object", @@ -126,19 +126,23 @@ "permissionActivityLog": "object", "subjectMetadata": "object", "announcements": "object", - "gasFeeEstimates": "object", - "estimatedGasFeeTimeBounds": "object", - "gasEstimateType": "string", + "gasFeeEstimates": {}, + "estimatedGasFeeTimeBounds": {}, + "gasEstimateType": "none", "tokenList": "object", - "tokensChainsCache": "object", - "preventPollingOnNetworkRestart": "boolean", + "tokensChainsCache": {}, + "preventPollingOnNetworkRestart": true, "tokens": "object", "ignoredTokens": "object", "detectedTokens": "object", - "allTokens": "object", - "allIgnoredTokens": "object", - "allDetectedTokens": "object", - "smartTransactionsState": "object", + "allTokens": {}, + "allIgnoredTokens": {}, + "allDetectedTokens": {}, + "smartTransactionsState": { + "fees": {}, + "liveness": true, + "smartTransactions": "object" + }, "allNftContracts": "object", "allNfts": "object", "ignoredNfts": "object", @@ -154,7 +158,32 @@ "unapprovedMsgCount": 0, "unapprovedPersonalMsgCount": 0, "unapprovedTypedMessagesCount": 0, - "swapsState": "object", + "swapsState": { + "quotes": "object", + "quotesPollingLimitEnabled": false, + "fetchParams": null, + "tokens": "object", + "tradeTxId": "object", + "approveTxId": "object", + "quotesLastFetched": null, + "customMaxGas": "", + "customGasPrice": null, + "customMaxFeePerGas": null, + "customMaxPriorityFeePerGas": null, + "swapsUserFeeLevel": "", + "selectedAggId": null, + "customApproveTxData": "string", + "errorKey": "", + "topAggId": "object", + "routeState": "", + "swapsFeatureIsLive": true, + "saveFetchedQuotes": false, + "swapsQuoteRefreshTime": 60000, + "swapsQuotePrefetchingRefreshTime": 60000, + "swapsStxBatchStatusRefreshTime": 10000, + "swapsStxGetTransactionsRefreshTime": 10000, + "swapsStxMaxFeeMultiplier": 2 + }, "ensResolutionsByAddress": "object", "pendingApprovals": "object", "pendingApprovalCount": "number", diff --git a/test/e2e/tests/state-snapshots/errors-before-init-opt-in-background-state.json b/test/e2e/tests/state-snapshots/errors-before-init-opt-in-background-state.json index f3adc0cd9..394e93c79 100644 --- a/test/e2e/tests/state-snapshots/errors-before-init-opt-in-background-state.json +++ b/test/e2e/tests/state-snapshots/errors-before-init-opt-in-background-state.json @@ -5,33 +5,42 @@ "unconnectedAccountAlertShownOrigins": "object", "web3ShimUsageOrigins": "object" }, - "AnnouncementController": "object", + "AnnouncementController": { "announcements": "object" }, "AppStateController": { - "browserEnvironment": "object", - "nftsDropdownState": "object", + "browserEnvironment": {}, + "nftsDropdownState": {}, "connectedStatusPopoverHasBeenShown": true, "termsOfUseLastAgreed": "number", "defaultHomeActiveTabName": null, - "fullScreenGasPollTokens": "object", - "notificationGasPollTokens": "object", - "popupGasPollTokens": "object", - "qrHardware": "object", - "recoveryPhraseReminderHasBeenShown": "boolean", + "fullScreenGasPollTokens": [], + "notificationGasPollTokens": [], + "popupGasPollTokens": [], + "qrHardware": {}, + "recoveryPhraseReminderHasBeenShown": true, "recoveryPhraseReminderLastShown": "number", - "showTestnetMessageInDropdown": "boolean", - "trezorModel": "object", - "usedNetworks": "object", - "snapsInstallPrivacyWarningShown": "boolean" + "showTestnetMessageInDropdown": true, + "trezorModel": null, + "usedNetworks": { + "0x1": true, + "0xe708": true, + "0x5": true, + "0x539": true + }, + "snapsInstallPrivacyWarningShown": true }, - "CachedBalancesController": "object", + "CachedBalancesController": { "cachedBalances": "object" }, "CurrencyController": { - "conversionDate": 1665507600, + "conversionDate": "number", "conversionRate": 1300, "currentCurrency": "usd", "nativeCurrency": "ETH", - "usdConversionRate": "number" + "usdConversionRate": 1300 + }, + "GasFeeController": { + "estimatedGasFeeTimeBounds": {}, + "gasEstimateType": "none", + "gasFeeEstimates": {} }, - "GasFeeController": "object", "IncomingTransactionsController": { "incomingTransactions": "object", "incomingTxLastFetchedBlockByChainId": { @@ -54,13 +63,13 @@ "networkId": "1337", "networkStatus": "available", "providerConfig": { - "chainId": "string", + "chainId": "0x539", "nickname": "Localhost 8545", "rpcPrefs": "object", "rpcUrl": "string", "ticker": "ETH", "type": "rpc", - "id": "string" + "id": "networkConfigurationId" }, "networkConfigurations": "object" }, @@ -70,20 +79,20 @@ "onboardingTabs": "object", "seedPhraseBackedUp": true }, - "PermissionController": "object", + "PermissionController": { "subjects": "object" }, "PreferencesController": { - "advancedGasFee": "object", + "advancedGasFee": null, "currentLocale": "en", - "dismissSeedBackUpReminder": "boolean", + "dismissSeedBackUpReminder": true, "featureFlags": { "showIncomingTransactions": true }, "forgottenPassword": false, "identities": "object", - "infuraBlocked": "boolean", - "ipfsGateway": "dweb.link", + "infuraBlocked": false, + "ipfsGateway": "string", "knownMethodData": "object", - "ledgerTransportType": "string", + "ledgerTransportType": "webhid", "lostIdentities": "object", - "openSeaEnabled": "boolean", + "openSeaEnabled": false, "preferences": { "hideZeroBalanceTokens": false, "showFiatInTestnets": false, @@ -91,19 +100,32 @@ "useNativeCurrencyAsPrimaryCurrency": true }, "selectedAddress": "string", - "theme": "string", + "theme": "light", "useBlockie": false, - "useNftDetection": "boolean", + "useNftDetection": false, "useNonceField": false, "usePhishDetect": true, - "useTokenDetection": "boolean", - "useCurrencyRateCheck": "boolean", - "useMultiAccountBalanceChecker": "boolean" + "useTokenDetection": false, + "useCurrencyRateCheck": true, + "useMultiAccountBalanceChecker": true }, - "SmartTransactionsController": "object", - "SubjectMetadataController": "object", - "TokensController": "object", - "TransactionController": "object", + "SmartTransactionsController": { + "smartTransactionsState": { + "fees": {}, + "liveness": true, + "smartTransactions": "object" + } + }, + "SubjectMetadataController": { "subjectMetadata": "object" }, + "TokensController": { + "allDetectedTokens": {}, + "allIgnoredTokens": {}, + "allTokens": {}, + "detectedTokens": "object", + "ignoredTokens": "object", + "tokens": "object" + }, + "TransactionController": { "transactions": "object" }, "config": "object", "firstTimeInfo": "object" } diff --git a/test/e2e/tests/state-snapshots/errors-before-init-opt-in-ui-state.json b/test/e2e/tests/state-snapshots/errors-before-init-opt-in-ui-state.json index 704026b0b..474b0205b 100644 --- a/test/e2e/tests/state-snapshots/errors-before-init-opt-in-ui-state.json +++ b/test/e2e/tests/state-snapshots/errors-before-init-opt-in-ui-state.json @@ -5,33 +5,42 @@ "unconnectedAccountAlertShownOrigins": "object", "web3ShimUsageOrigins": "object" }, - "AnnouncementController": "object", + "AnnouncementController": { "announcements": "object" }, "AppStateController": { - "browserEnvironment": "object", - "nftsDropdownState": "object", + "browserEnvironment": {}, + "nftsDropdownState": {}, "connectedStatusPopoverHasBeenShown": true, "termsOfUseLastAgreed": "number", "defaultHomeActiveTabName": null, - "fullScreenGasPollTokens": "object", - "notificationGasPollTokens": "object", - "popupGasPollTokens": "object", - "qrHardware": "object", - "recoveryPhraseReminderHasBeenShown": "boolean", + "fullScreenGasPollTokens": [], + "notificationGasPollTokens": [], + "popupGasPollTokens": [], + "qrHardware": {}, + "recoveryPhraseReminderHasBeenShown": true, "recoveryPhraseReminderLastShown": "number", - "showTestnetMessageInDropdown": "boolean", - "trezorModel": "object", - "usedNetworks": "object", - "snapsInstallPrivacyWarningShown": "boolean" + "showTestnetMessageInDropdown": true, + "trezorModel": null, + "usedNetworks": { + "0x1": true, + "0xe708": true, + "0x5": true, + "0x539": true + }, + "snapsInstallPrivacyWarningShown": true }, - "CachedBalancesController": "object", + "CachedBalancesController": { "cachedBalances": "object" }, "CurrencyController": { - "conversionDate": 1665507600, + "conversionDate": "number", "conversionRate": 1300, "currentCurrency": "usd", "nativeCurrency": "ETH", - "usdConversionRate": "number" + "usdConversionRate": 1300 + }, + "GasFeeController": { + "estimatedGasFeeTimeBounds": {}, + "gasEstimateType": "none", + "gasFeeEstimates": {} }, - "GasFeeController": "object", "IncomingTransactionsController": { "incomingTransactions": "object", "incomingTxLastFetchedBlockByChainId": { @@ -54,13 +63,13 @@ "networkId": "1337", "networkStatus": "available", "providerConfig": { - "chainId": "string", + "chainId": "0x539", "nickname": "Localhost 8545", "rpcPrefs": "object", "rpcUrl": "string", "ticker": "ETH", "type": "rpc", - "id": "string" + "id": "networkConfigurationId" }, "networkConfigurations": "object" }, @@ -70,20 +79,20 @@ "onboardingTabs": "object", "seedPhraseBackedUp": true }, - "PermissionController": "object", + "PermissionController": { "subjects": "object" }, "PreferencesController": { - "advancedGasFee": "object", + "advancedGasFee": null, "currentLocale": "en", - "dismissSeedBackUpReminder": "boolean", + "dismissSeedBackUpReminder": true, "featureFlags": { "showIncomingTransactions": true }, "forgottenPassword": false, "identities": "object", - "infuraBlocked": "boolean", - "ipfsGateway": "dweb.link", + "infuraBlocked": false, + "ipfsGateway": "string", "knownMethodData": "object", - "ledgerTransportType": "string", + "ledgerTransportType": "webhid", "lostIdentities": "object", - "openSeaEnabled": "boolean", + "openSeaEnabled": false, "preferences": { "hideZeroBalanceTokens": false, "showFiatInTestnets": false, @@ -91,19 +100,32 @@ "useNativeCurrencyAsPrimaryCurrency": true }, "selectedAddress": "string", - "theme": "string", + "theme": "light", "useBlockie": false, - "useNftDetection": "boolean", + "useNftDetection": false, "useNonceField": false, "usePhishDetect": true, - "useTokenDetection": "boolean", - "useCurrencyRateCheck": "boolean", - "useMultiAccountBalanceChecker": "boolean" + "useTokenDetection": false, + "useCurrencyRateCheck": true, + "useMultiAccountBalanceChecker": true }, - "SmartTransactionsController": "object", - "SubjectMetadataController": "object", - "TokensController": "object", - "TransactionController": "object", + "SmartTransactionsController": { + "smartTransactionsState": { + "fees": {}, + "liveness": true, + "smartTransactions": "object" + } + }, + "SubjectMetadataController": { "subjectMetadata": "object" }, + "TokensController": { + "allDetectedTokens": {}, + "allIgnoredTokens": {}, + "allTokens": {}, + "detectedTokens": "object", + "ignoredTokens": "object", + "tokens": "object" + }, + "TransactionController": { "transactions": "object" }, "config": "object", "firstTimeInfo": "object" },