1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

feat: Add more state props from controllers to Sentry mask (#20595)

* feat: update sentry mask adding  controller props to improve error monitoring

* fix:remove changes in chrome-driver dependency

* Remove properties from mask

* Add more values to mask

* Sort the mask alphabetically

* Add termsOfUseLastAgreed to mask

* Fix test imports

* Update policy gap test to compare UI mask

* Reorganize tests under one describe block

* Update snapshots

* Mask another timestamp in state snapshots

* Mask browser environment properties

* Add missing UI field mask, and refactor field masking/removal

* Eliminate remaining policy gaps

* Simplify ganache options

* Eliminate extra mask properties

* Update mask to capture dynamic keys

The mask now supports dynamic keys. This lets set more fine-grained rules
for which data to include within dynamic data structures.

The mask has been updated to include just top-level keys for various
token-related data collections in state. This lets us see the chain IDs
that users have tokens on. This will be useful in debugging Sentry
reports of invalid keys in these data structures.

* Add additional 'expected missing state' entries

* Remove unnecessary properties from state snapshot

* Add providerConfig.chainId to state snapshot

* Update error state snapshots

---------

Co-authored-by: Danica Shen <zhaodanica@gmail.com>
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This commit is contained in:
Pedro Figueiredo 2023-08-30 00:17:58 +01:00 committed by Mark Stacey
parent 052e90ec7c
commit e5ad6ef2b7
7 changed files with 657 additions and 199 deletions

View File

@ -1,6 +1,7 @@
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import { Dedupe, ExtraErrorData } from '@sentry/integrations'; import { Dedupe, ExtraErrorData } from '@sentry/integrations';
import { AllProperties } from '../../../shared/modules/object.utils';
import { FilterEvents } from './sentry-filter-events'; import { FilterEvents } from './sentry-filter-events';
import extractEthjsErrorMessage from './extractEthjsErrorMessage'; import extractEthjsErrorMessage from './extractEthjsErrorMessage';
@ -28,75 +29,254 @@ export const ERROR_URL_ALLOWLIST = {
// debugging, and they do not contain any identifiable information. // debugging, and they do not contain any identifiable information.
export const SENTRY_BACKGROUND_STATE = { export const SENTRY_BACKGROUND_STATE = {
AccountTracker: { AccountTracker: {
accounts: false,
currentBlockGasLimit: true, currentBlockGasLimit: true,
}, },
AddressBookController: {
addressBook: false,
},
AlertController: { AlertController: {
alertEnabledness: true, alertEnabledness: true,
unconnectedAccountAlertShownOrigins: false,
web3ShimUsageOrigins: false,
},
AnnouncementController: {
announcements: false,
}, },
AppMetadataController: { AppMetadataController: {
currentAppVersion: true, currentAppVersion: true,
currentMigrationVersion: true,
previousAppVersion: true, previousAppVersion: true,
previousMigrationVersion: true, previousMigrationVersion: true,
currentMigrationVersion: true, },
ApprovalController: {
approvalFlows: false,
pendingApprovals: false,
pendingApprovalCount: false,
}, },
AppStateController: { AppStateController: {
browserEnvironment: true,
connectedStatusPopoverHasBeenShown: true, connectedStatusPopoverHasBeenShown: true,
currentPopupId: false,
defaultHomeActiveTabName: true, 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: { CurrencyController: {
conversionDate: true, conversionDate: true,
conversionRate: true, conversionRate: true,
currentCurrency: true, currentCurrency: true,
nativeCurrency: true, nativeCurrency: true,
pendingCurrentCurrency: true,
pendingNativeCurrency: true,
usdConversionRate: true,
}, },
DecryptMessageController: { DecryptMessageController: {
unapprovedDecryptMsgs: false,
unapprovedDecryptMsgCount: true, unapprovedDecryptMsgCount: true,
}, },
DesktopController: {
desktopEnabled: true,
},
EncryptionPublicKeyController: { EncryptionPublicKeyController: {
unapprovedEncryptionPublicKeyMsgs: false,
unapprovedEncryptionPublicKeyMsgCount: true, unapprovedEncryptionPublicKeyMsgCount: true,
}, },
EnsController: {
ensResolutionsByAddress: false,
},
GasFeeController: {
estimatedGasFeeTimeBounds: true,
gasEstimateType: true,
gasFeeEstimates: true,
},
IncomingTransactionsController: { IncomingTransactionsController: {
incomingTransactions: false,
incomingTxLastFetchedBlockByChainId: true, incomingTxLastFetchedBlockByChainId: true,
}, },
KeyringController: { KeyringController: {
encryptionKey: false,
isUnlocked: true, isUnlocked: true,
keyrings: false,
keyringTypes: false,
}, },
MetaMetricsController: { MetaMetricsController: {
eventsBeforeMetricsOptIn: false,
fragments: false,
metaMetricsId: true, metaMetricsId: true,
participateInMetaMetrics: true, participateInMetaMetrics: true,
previousUserTraits: false,
segmentApiCalls: false,
traits: false,
}, },
NetworkController: { NetworkController: {
networkConfigurations: false,
networkDetails: false,
networkId: true, networkId: true,
networkStatus: true, networkStatus: true,
providerConfig: { providerConfig: {
chainId: true,
id: true,
nickname: true, nickname: true,
rpcPrefs: false,
rpcUrl: false,
ticker: true, ticker: true,
type: true, type: true,
}, },
}, },
NftController: {
allNftContracts: false,
allNfts: false,
ignoredNfts: false,
},
OnboardingController: { OnboardingController: {
completedOnboarding: true, completedOnboarding: true,
firstTimeFlowType: true, firstTimeFlowType: true,
onboardingTabs: false,
seedPhraseBackedUp: true, seedPhraseBackedUp: true,
}, },
PermissionController: {
subjects: false,
},
PermissionLogController: {
permissionActivityLog: false,
permissionHistory: false,
},
PhishingController: {},
PreferencesController: { PreferencesController: {
advancedGasFee: true,
currentLocale: true, currentLocale: true,
disabledRpcMethodPreferences: true,
dismissSeedBackUpReminder: true,
featureFlags: true, featureFlags: true,
forgottenPassword: true, forgottenPassword: true,
ipfsGateway: true, identities: false,
preferences: true, 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, useBlockie: true,
useCurrencyRateCheck: true,
useMultiAccountBalanceChecker: true,
useNftDetection: true,
useNonceField: true, useNonceField: true,
usePhishDetect: true, usePhishDetect: true,
useTokenDetection: true,
}, },
SignatureController: { SignatureController: {
unapprovedMsgCount: true, unapprovedMsgCount: true,
unapprovedMsgs: false,
unapprovedPersonalMsgCount: true, unapprovedPersonalMsgCount: true,
unapprovedPersonalMsgs: false,
unapprovedTypedMessages: false,
unapprovedTypedMessagesCount: true, 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( 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 // These properties are in the `metamask` slice but not in the background state
customNonceValue: true, customNonceValue: true,
isAccountMenuOpen: true, isAccountMenuOpen: true,
isNetworkMenuOpen: true,
nextNonce: true, nextNonce: true,
pendingTokens: false,
welcomeScreenSeen: true, welcomeScreenSeen: true,
}, },
unconnectedAccount: true, unconnectedAccount: true,

View File

@ -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 * The mask is an object that mirrors the structure of the given object, except
* 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"
* the only values are `true` or a sub-mask. `true` implies the property * symbol. `true` implies the property should be included, and `false` will
* should be included, and a sub-mask implies the property should be further * exclude it. A sub-mask implies the property should be further masked
* masked according to that sub-mask. * 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} 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
*/ */
export function maskObject(object, mask) { 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) => { 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]; state[key] = object[key];
} else if (mask[key]) { } else if (maskKey && typeof maskKey === 'object') {
state[key] = maskObject(object[key], mask[key]); state[key] = maskObject(object[key], maskKey);
} else { } else if (maskKey === undefined || maskKey === false) {
state[key] = typeof object[key]; state[key] = typeof object[key];
} else {
throw new Error(`Unsupported mask entry: ${maskKey}`);
} }
return state; return state;
}, {}); }, {});

View File

@ -4,8 +4,24 @@ const { strict: assert } = require('assert');
const { get, has, set, unset } = 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 { isObject } = require('@metamask/utils');
const { SENTRY_UI_STATE } = require('../../../app/scripts/lib/setupSentry');
const FixtureBuilder = require('../fixture-builder'); 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 = [ const maskedBackgroundFields = [
'CurrencyController.conversionDate', // This is a timestamp that changes each run 'CurrencyController.conversionDate', // This is a timestamp that changes each run
@ -13,14 +29,13 @@ const maskedBackgroundFields = [
// part of the release process // part of the release process
'AppMetadataController.currentAppVersion', 'AppMetadataController.currentAppVersion',
'AppMetadataController.currentMigrationVersion', 'AppMetadataController.currentMigrationVersion',
'AppStateController.browserEnvironment.browser',
'AppStateController.browserEnvironment.os',
'AppStateController.outdatedBrowserWarningLastShown',
'AppStateController.recoveryPhraseReminderLastShown',
'AppStateController.termsOfUseLastAgreed',
]; ];
const maskedUiFields = [ const maskedUiFields = maskedBackgroundFields.map(backgroundToUiField);
'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 removedBackgroundFields = [ const removedBackgroundFields = [
// This property is timing-dependent // This property is timing-dependent
@ -30,13 +45,7 @@ const removedBackgroundFields = [
'AppStateController.timeoutMinutes', 'AppStateController.timeoutMinutes',
]; ];
const removedUiFields = [ const removedUiFields = removedBackgroundFields.map(backgroundToUiField);
// This property is timing-dependent
'metamask.currentBlockGasLimit',
// These properties are set to undefined, causing inconsistencies between Chrome and Firefox
'metamask.currentPopupId',
'metamask.timeoutMinutes',
];
/** /**
* Transform background state to make it consistent between test runs. * 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 () { describe('Sentry errors', function () {
const migrationError = const migrationError =
process.env.SELENIUM_BROWSER === Browser.CHROME process.env.SELENIUM_BROWSER === Browser.CHROME
@ -320,7 +361,10 @@ describe('Sentry errors', function () {
'Invalid version state', 'Invalid version state',
); );
await matchesSnapshot({ await matchesSnapshot({
data: transformBackgroundState(appState.persistedState), data: {
...appState.persistedState,
data: transformBackgroundState(appState.persistedState.data),
},
snapshot: 'errors-before-init-opt-in-background-state', snapshot: 'errors-before-init-opt-in-background-state',
}); });
}, },
@ -468,7 +512,10 @@ describe('Sentry errors', function () {
'Invalid version state', 'Invalid version state',
); );
await matchesSnapshot({ await matchesSnapshot({
data: transformBackgroundState(appState.persistedState), data: {
...appState.persistedState,
data: transformBackgroundState(appState.persistedState.data),
},
snapshot: 'errors-before-init-opt-in-ui-state', 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, {});
},
);
});
}); });

View File

@ -1,12 +1,12 @@
{ {
"AccountTracker": { "accounts": "object" }, "AccountTracker": { "accounts": "object" },
"AddressBookController": "object", "AddressBookController": { "addressBook": "object" },
"AlertController": { "AlertController": {
"alertEnabledness": { "unconnectedAccount": true, "web3ShimUsage": true }, "alertEnabledness": { "unconnectedAccount": true, "web3ShimUsage": true },
"unconnectedAccountAlertShownOrigins": "object", "unconnectedAccountAlertShownOrigins": "object",
"web3ShimUsageOrigins": "object" "web3ShimUsageOrigins": "object"
}, },
"AnnouncementController": "object", "AnnouncementController": { "announcements": "object" },
"AppMetadataController": { "AppMetadataController": {
"currentAppVersion": "string", "currentAppVersion": "string",
"previousAppVersion": "", "previousAppVersion": "",
@ -16,37 +16,41 @@
"AppStateController": { "AppStateController": {
"connectedStatusPopoverHasBeenShown": true, "connectedStatusPopoverHasBeenShown": true,
"defaultHomeActiveTabName": null, "defaultHomeActiveTabName": null,
"browserEnvironment": "object", "browserEnvironment": { "os": "string", "browser": "string" },
"popupGasPollTokens": "object", "popupGasPollTokens": [],
"notificationGasPollTokens": "object", "notificationGasPollTokens": [],
"fullScreenGasPollTokens": "object", "fullScreenGasPollTokens": [],
"recoveryPhraseReminderHasBeenShown": "boolean", "recoveryPhraseReminderHasBeenShown": true,
"recoveryPhraseReminderLastShown": "number", "recoveryPhraseReminderLastShown": "number",
"outdatedBrowserWarningLastShown": "number", "outdatedBrowserWarningLastShown": "number",
"nftsDetectionNoticeDismissed": "boolean", "nftsDetectionNoticeDismissed": false,
"showTestnetMessageInDropdown": "boolean", "showTestnetMessageInDropdown": true,
"showBetaHeader": "boolean", "showBetaHeader": false,
"showProductTour": "boolean", "showProductTour": true,
"trezorModel": "object", "trezorModel": null,
"nftsDropdownState": "object", "hadAdvancedGasFeesSetPriorToMigration92_3": false,
"nftsDropdownState": {},
"termsOfUseLastAgreed": "number", "termsOfUseLastAgreed": "number",
"qrHardware": "object", "qrHardware": {},
"usedNetworks": "object", "usedNetworks": { "0x1": true, "0x5": true, "0x539": true },
"snapsInstallPrivacyWarningShown": "boolean", "snapsInstallPrivacyWarningShown": true,
"hadAdvancedGasFeesSetPriorToMigration92_3": "boolean", "serviceWorkerLastActiveTime": 0
"serviceWorkerLastActiveTime": "number" },
"ApprovalController": {
"pendingApprovals": "object",
"pendingApprovalCount": "number",
"approvalFlows": "object"
}, },
"ApprovalController": "object",
"BackupController": "undefined", "BackupController": "undefined",
"CachedBalancesController": "object", "CachedBalancesController": { "cachedBalances": "object" },
"CurrencyController": { "CurrencyController": {
"conversionDate": "number", "conversionDate": "number",
"conversionRate": 1700, "conversionRate": 1700,
"nativeCurrency": "ETH", "nativeCurrency": "ETH",
"currentCurrency": "usd", "currentCurrency": "usd",
"pendingCurrentCurrency": "object", "pendingCurrentCurrency": null,
"pendingNativeCurrency": "object", "pendingNativeCurrency": null,
"usdConversionRate": "number" "usdConversionRate": 1700
}, },
"DecryptMessageController": { "DecryptMessageController": {
"unapprovedDecryptMsgs": "object", "unapprovedDecryptMsgs": "object",
@ -56,8 +60,12 @@
"unapprovedEncryptionPublicKeyMsgs": "object", "unapprovedEncryptionPublicKeyMsgs": "object",
"unapprovedEncryptionPublicKeyMsgCount": 0 "unapprovedEncryptionPublicKeyMsgCount": 0
}, },
"EnsController": "object", "EnsController": { "ensResolutionsByAddress": "object" },
"GasFeeController": "object", "GasFeeController": {
"gasFeeEstimates": {},
"estimatedGasFeeTimeBounds": {},
"gasEstimateType": "none"
},
"IncomingTransactionsController": { "IncomingTransactionsController": {
"incomingTransactions": "object", "incomingTransactions": "object",
"incomingTxLastFetchedBlockByChainId": { "incomingTxLastFetchedBlockByChainId": {
@ -87,38 +95,45 @@
"networkId": "1337", "networkId": "1337",
"networkStatus": "available", "networkStatus": "available",
"providerConfig": { "providerConfig": {
"chainId": "string", "chainId": "0x539",
"nickname": "Localhost 8545", "nickname": "Localhost 8545",
"rpcPrefs": "object", "rpcPrefs": "object",
"rpcUrl": "string", "rpcUrl": "string",
"ticker": "ETH", "ticker": "ETH",
"type": "rpc", "type": "rpc",
"id": "string" "id": "networkConfigurationId"
}, },
"networkDetails": "object", "networkDetails": "object",
"networkConfigurations": "object" "networkConfigurations": "object"
}, },
"NftController": "object", "NftController": {
"allNftContracts": "object",
"allNfts": "object",
"ignoredNfts": "object"
},
"OnboardingController": { "OnboardingController": {
"seedPhraseBackedUp": true, "seedPhraseBackedUp": true,
"firstTimeFlowType": "import", "firstTimeFlowType": "import",
"completedOnboarding": true, "completedOnboarding": true,
"onboardingTabs": "object" "onboardingTabs": "object"
}, },
"PermissionController": "object", "PermissionController": { "subjects": "object" },
"PermissionLogController": "object", "PermissionLogController": {
"permissionHistory": "object",
"permissionActivityLog": "object"
},
"PreferencesController": { "PreferencesController": {
"useBlockie": false, "useBlockie": false,
"useNonceField": false, "useNonceField": false,
"usePhishDetect": true, "usePhishDetect": true,
"dismissSeedBackUpReminder": "boolean", "dismissSeedBackUpReminder": true,
"disabledRpcMethodPreferences": "object", "disabledRpcMethodPreferences": { "eth_sign": false },
"useMultiAccountBalanceChecker": "boolean", "useMultiAccountBalanceChecker": true,
"useTokenDetection": "boolean", "useTokenDetection": false,
"useNftDetection": "boolean", "useNftDetection": false,
"useCurrencyRateCheck": "boolean", "useCurrencyRateCheck": true,
"openSeaEnabled": "boolean", "openSeaEnabled": false,
"advancedGasFee": "object", "advancedGasFee": {},
"featureFlags": { "showIncomingTransactions": true }, "featureFlags": { "showIncomingTransactions": true },
"knownMethodData": "object", "knownMethodData": "object",
"currentLocale": "en", "currentLocale": "en",
@ -131,13 +146,13 @@
"showTestNetworks": false, "showTestNetworks": false,
"useNativeCurrencyAsPrimaryCurrency": true "useNativeCurrencyAsPrimaryCurrency": true
}, },
"ipfsGateway": "dweb.link", "ipfsGateway": "string",
"infuraBlocked": "boolean", "infuraBlocked": false,
"ledgerTransportType": "string", "ledgerTransportType": "webhid",
"snapRegistryList": "object", "snapRegistryList": "object",
"transactionSecurityCheckEnabled": "boolean", "transactionSecurityCheckEnabled": false,
"theme": "string", "theme": "light",
"isLineaMainnetReleased": "boolean", "isLineaMainnetReleased": true,
"selectedAddress": "string" "selectedAddress": "string"
}, },
"SignatureController": { "SignatureController": {
@ -148,11 +163,58 @@
"unapprovedPersonalMsgCount": 0, "unapprovedPersonalMsgCount": 0,
"unapprovedTypedMessagesCount": 0 "unapprovedTypedMessagesCount": 0
}, },
"SmartTransactionsController": "object", "SmartTransactionsController": {
"SubjectMetadataController": "object", "smartTransactionsState": {
"SwapsController": "object", "fees": {},
"TokenListController": "object", "liveness": true,
"TokenRatesController": "object", "smartTransactions": "object"
"TokensController": "object", }
"TxController": "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"
}
} }

View File

@ -11,7 +11,7 @@
"isInitialized": true, "isInitialized": true,
"isUnlocked": false, "isUnlocked": false,
"isAccountMenuOpen": false, "isAccountMenuOpen": false,
"isNetworkMenuOpen": "boolean", "isNetworkMenuOpen": false,
"identities": "object", "identities": "object",
"unapprovedTxs": "object", "unapprovedTxs": "object",
"networkConfigurations": "object", "networkConfigurations": "object",
@ -38,25 +38,25 @@
"nativeCurrency": "ETH", "nativeCurrency": "ETH",
"connectedStatusPopoverHasBeenShown": true, "connectedStatusPopoverHasBeenShown": true,
"defaultHomeActiveTabName": null, "defaultHomeActiveTabName": null,
"browserEnvironment": "object", "browserEnvironment": { "os": "string", "browser": "string" },
"popupGasPollTokens": "object", "popupGasPollTokens": [],
"notificationGasPollTokens": "object", "notificationGasPollTokens": [],
"fullScreenGasPollTokens": "object", "fullScreenGasPollTokens": [],
"recoveryPhraseReminderHasBeenShown": "boolean", "recoveryPhraseReminderHasBeenShown": true,
"recoveryPhraseReminderLastShown": "number", "recoveryPhraseReminderLastShown": "number",
"outdatedBrowserWarningLastShown": "number", "outdatedBrowserWarningLastShown": "number",
"nftsDetectionNoticeDismissed": "boolean", "nftsDetectionNoticeDismissed": false,
"showTestnetMessageInDropdown": "boolean", "showTestnetMessageInDropdown": true,
"showBetaHeader": "boolean", "showBetaHeader": false,
"showProductTour": "boolean", "showProductTour": true,
"trezorModel": "object", "trezorModel": null,
"nftsDropdownState": "object", "hadAdvancedGasFeesSetPriorToMigration92_3": false,
"nftsDropdownState": {},
"termsOfUseLastAgreed": "number", "termsOfUseLastAgreed": "number",
"qrHardware": "object", "qrHardware": {},
"usedNetworks": "object", "usedNetworks": { "0x1": true, "0x5": true, "0x539": true },
"snapsInstallPrivacyWarningShown": "boolean", "snapsInstallPrivacyWarningShown": true,
"hadAdvancedGasFeesSetPriorToMigration92_3": "boolean", "serviceWorkerLastActiveTime": 0,
"serviceWorkerLastActiveTime": "number",
"currentAppVersion": "string", "currentAppVersion": "string",
"previousAppVersion": "", "previousAppVersion": "",
"previousMigrationVersion": 0, "previousMigrationVersion": 0,
@ -64,13 +64,13 @@
"networkId": "1337", "networkId": "1337",
"networkStatus": "available", "networkStatus": "available",
"providerConfig": { "providerConfig": {
"chainId": "string", "chainId": "0x539",
"nickname": "Localhost 8545", "nickname": "Localhost 8545",
"rpcPrefs": "object", "rpcPrefs": "object",
"rpcUrl": "string", "rpcUrl": "string",
"ticker": "ETH", "ticker": "ETH",
"type": "rpc", "type": "rpc",
"id": "string" "id": "networkConfigurationId"
}, },
"networkDetails": "object", "networkDetails": "object",
"cachedBalances": "object", "cachedBalances": "object",
@ -79,23 +79,23 @@
"encryptionKey": "object", "encryptionKey": "object",
"useNonceField": false, "useNonceField": false,
"usePhishDetect": true, "usePhishDetect": true,
"dismissSeedBackUpReminder": "boolean", "dismissSeedBackUpReminder": true,
"disabledRpcMethodPreferences": "object", "disabledRpcMethodPreferences": { "eth_sign": false },
"useMultiAccountBalanceChecker": "boolean", "useMultiAccountBalanceChecker": true,
"useTokenDetection": "boolean", "useTokenDetection": false,
"useNftDetection": "boolean", "useNftDetection": false,
"useCurrencyRateCheck": "boolean", "useCurrencyRateCheck": true,
"openSeaEnabled": "boolean", "openSeaEnabled": false,
"advancedGasFee": "object", "advancedGasFee": {},
"lostIdentities": "object", "lostIdentities": "object",
"forgottenPassword": false, "forgottenPassword": false,
"ipfsGateway": "dweb.link", "ipfsGateway": "string",
"infuraBlocked": "boolean", "infuraBlocked": false,
"ledgerTransportType": "string", "ledgerTransportType": "webhid",
"snapRegistryList": "object", "snapRegistryList": "object",
"transactionSecurityCheckEnabled": "boolean", "transactionSecurityCheckEnabled": false,
"theme": "string", "theme": "light",
"isLineaMainnetReleased": "boolean", "isLineaMainnetReleased": true,
"selectedAddress": "string", "selectedAddress": "string",
"metaMetricsId": "fake-metrics-id", "metaMetricsId": "fake-metrics-id",
"eventsBeforeMetricsOptIn": "object", "eventsBeforeMetricsOptIn": "object",
@ -105,9 +105,9 @@
"previousUserTraits": "object", "previousUserTraits": "object",
"conversionDate": "number", "conversionDate": "number",
"currentCurrency": "usd", "currentCurrency": "usd",
"pendingCurrentCurrency": "object", "pendingCurrentCurrency": null,
"pendingNativeCurrency": "object", "pendingNativeCurrency": null,
"usdConversionRate": "number", "usdConversionRate": 1300,
"alertEnabledness": { "unconnectedAccount": true, "web3ShimUsage": true }, "alertEnabledness": { "unconnectedAccount": true, "web3ShimUsage": true },
"unconnectedAccountAlertShownOrigins": "object", "unconnectedAccountAlertShownOrigins": "object",
"web3ShimUsageOrigins": "object", "web3ShimUsageOrigins": "object",
@ -126,19 +126,23 @@
"permissionActivityLog": "object", "permissionActivityLog": "object",
"subjectMetadata": "object", "subjectMetadata": "object",
"announcements": "object", "announcements": "object",
"gasFeeEstimates": "object", "gasFeeEstimates": {},
"estimatedGasFeeTimeBounds": "object", "estimatedGasFeeTimeBounds": {},
"gasEstimateType": "string", "gasEstimateType": "none",
"tokenList": "object", "tokenList": "object",
"tokensChainsCache": "object", "tokensChainsCache": {},
"preventPollingOnNetworkRestart": "boolean", "preventPollingOnNetworkRestart": true,
"tokens": "object", "tokens": "object",
"ignoredTokens": "object", "ignoredTokens": "object",
"detectedTokens": "object", "detectedTokens": "object",
"allTokens": "object", "allTokens": {},
"allIgnoredTokens": "object", "allIgnoredTokens": {},
"allDetectedTokens": "object", "allDetectedTokens": {},
"smartTransactionsState": "object", "smartTransactionsState": {
"fees": {},
"liveness": true,
"smartTransactions": "object"
},
"allNftContracts": "object", "allNftContracts": "object",
"allNfts": "object", "allNfts": "object",
"ignoredNfts": "object", "ignoredNfts": "object",
@ -154,7 +158,32 @@
"unapprovedMsgCount": 0, "unapprovedMsgCount": 0,
"unapprovedPersonalMsgCount": 0, "unapprovedPersonalMsgCount": 0,
"unapprovedTypedMessagesCount": 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", "ensResolutionsByAddress": "object",
"pendingApprovals": "object", "pendingApprovals": "object",
"pendingApprovalCount": "number", "pendingApprovalCount": "number",

View File

@ -5,33 +5,42 @@
"unconnectedAccountAlertShownOrigins": "object", "unconnectedAccountAlertShownOrigins": "object",
"web3ShimUsageOrigins": "object" "web3ShimUsageOrigins": "object"
}, },
"AnnouncementController": "object", "AnnouncementController": { "announcements": "object" },
"AppStateController": { "AppStateController": {
"browserEnvironment": "object", "browserEnvironment": {},
"nftsDropdownState": "object", "nftsDropdownState": {},
"connectedStatusPopoverHasBeenShown": true, "connectedStatusPopoverHasBeenShown": true,
"termsOfUseLastAgreed": "number", "termsOfUseLastAgreed": "number",
"defaultHomeActiveTabName": null, "defaultHomeActiveTabName": null,
"fullScreenGasPollTokens": "object", "fullScreenGasPollTokens": [],
"notificationGasPollTokens": "object", "notificationGasPollTokens": [],
"popupGasPollTokens": "object", "popupGasPollTokens": [],
"qrHardware": "object", "qrHardware": {},
"recoveryPhraseReminderHasBeenShown": "boolean", "recoveryPhraseReminderHasBeenShown": true,
"recoveryPhraseReminderLastShown": "number", "recoveryPhraseReminderLastShown": "number",
"showTestnetMessageInDropdown": "boolean", "showTestnetMessageInDropdown": true,
"trezorModel": "object", "trezorModel": null,
"usedNetworks": "object", "usedNetworks": {
"snapsInstallPrivacyWarningShown": "boolean" "0x1": true,
"0xe708": true,
"0x5": true,
"0x539": true
}, },
"CachedBalancesController": "object", "snapsInstallPrivacyWarningShown": true
},
"CachedBalancesController": { "cachedBalances": "object" },
"CurrencyController": { "CurrencyController": {
"conversionDate": 1665507600, "conversionDate": "number",
"conversionRate": 1300, "conversionRate": 1300,
"currentCurrency": "usd", "currentCurrency": "usd",
"nativeCurrency": "ETH", "nativeCurrency": "ETH",
"usdConversionRate": "number" "usdConversionRate": 1300
},
"GasFeeController": {
"estimatedGasFeeTimeBounds": {},
"gasEstimateType": "none",
"gasFeeEstimates": {}
}, },
"GasFeeController": "object",
"IncomingTransactionsController": { "IncomingTransactionsController": {
"incomingTransactions": "object", "incomingTransactions": "object",
"incomingTxLastFetchedBlockByChainId": { "incomingTxLastFetchedBlockByChainId": {
@ -54,13 +63,13 @@
"networkId": "1337", "networkId": "1337",
"networkStatus": "available", "networkStatus": "available",
"providerConfig": { "providerConfig": {
"chainId": "string", "chainId": "0x539",
"nickname": "Localhost 8545", "nickname": "Localhost 8545",
"rpcPrefs": "object", "rpcPrefs": "object",
"rpcUrl": "string", "rpcUrl": "string",
"ticker": "ETH", "ticker": "ETH",
"type": "rpc", "type": "rpc",
"id": "string" "id": "networkConfigurationId"
}, },
"networkConfigurations": "object" "networkConfigurations": "object"
}, },
@ -70,20 +79,20 @@
"onboardingTabs": "object", "onboardingTabs": "object",
"seedPhraseBackedUp": true "seedPhraseBackedUp": true
}, },
"PermissionController": "object", "PermissionController": { "subjects": "object" },
"PreferencesController": { "PreferencesController": {
"advancedGasFee": "object", "advancedGasFee": null,
"currentLocale": "en", "currentLocale": "en",
"dismissSeedBackUpReminder": "boolean", "dismissSeedBackUpReminder": true,
"featureFlags": { "showIncomingTransactions": true }, "featureFlags": { "showIncomingTransactions": true },
"forgottenPassword": false, "forgottenPassword": false,
"identities": "object", "identities": "object",
"infuraBlocked": "boolean", "infuraBlocked": false,
"ipfsGateway": "dweb.link", "ipfsGateway": "string",
"knownMethodData": "object", "knownMethodData": "object",
"ledgerTransportType": "string", "ledgerTransportType": "webhid",
"lostIdentities": "object", "lostIdentities": "object",
"openSeaEnabled": "boolean", "openSeaEnabled": false,
"preferences": { "preferences": {
"hideZeroBalanceTokens": false, "hideZeroBalanceTokens": false,
"showFiatInTestnets": false, "showFiatInTestnets": false,
@ -91,19 +100,32 @@
"useNativeCurrencyAsPrimaryCurrency": true "useNativeCurrencyAsPrimaryCurrency": true
}, },
"selectedAddress": "string", "selectedAddress": "string",
"theme": "string", "theme": "light",
"useBlockie": false, "useBlockie": false,
"useNftDetection": "boolean", "useNftDetection": false,
"useNonceField": false, "useNonceField": false,
"usePhishDetect": true, "usePhishDetect": true,
"useTokenDetection": "boolean", "useTokenDetection": false,
"useCurrencyRateCheck": "boolean", "useCurrencyRateCheck": true,
"useMultiAccountBalanceChecker": "boolean" "useMultiAccountBalanceChecker": true
}, },
"SmartTransactionsController": "object", "SmartTransactionsController": {
"SubjectMetadataController": "object", "smartTransactionsState": {
"TokensController": "object", "fees": {},
"TransactionController": "object", "liveness": true,
"smartTransactions": "object"
}
},
"SubjectMetadataController": { "subjectMetadata": "object" },
"TokensController": {
"allDetectedTokens": {},
"allIgnoredTokens": {},
"allTokens": {},
"detectedTokens": "object",
"ignoredTokens": "object",
"tokens": "object"
},
"TransactionController": { "transactions": "object" },
"config": "object", "config": "object",
"firstTimeInfo": "object" "firstTimeInfo": "object"
} }

View File

@ -5,33 +5,42 @@
"unconnectedAccountAlertShownOrigins": "object", "unconnectedAccountAlertShownOrigins": "object",
"web3ShimUsageOrigins": "object" "web3ShimUsageOrigins": "object"
}, },
"AnnouncementController": "object", "AnnouncementController": { "announcements": "object" },
"AppStateController": { "AppStateController": {
"browserEnvironment": "object", "browserEnvironment": {},
"nftsDropdownState": "object", "nftsDropdownState": {},
"connectedStatusPopoverHasBeenShown": true, "connectedStatusPopoverHasBeenShown": true,
"termsOfUseLastAgreed": "number", "termsOfUseLastAgreed": "number",
"defaultHomeActiveTabName": null, "defaultHomeActiveTabName": null,
"fullScreenGasPollTokens": "object", "fullScreenGasPollTokens": [],
"notificationGasPollTokens": "object", "notificationGasPollTokens": [],
"popupGasPollTokens": "object", "popupGasPollTokens": [],
"qrHardware": "object", "qrHardware": {},
"recoveryPhraseReminderHasBeenShown": "boolean", "recoveryPhraseReminderHasBeenShown": true,
"recoveryPhraseReminderLastShown": "number", "recoveryPhraseReminderLastShown": "number",
"showTestnetMessageInDropdown": "boolean", "showTestnetMessageInDropdown": true,
"trezorModel": "object", "trezorModel": null,
"usedNetworks": "object", "usedNetworks": {
"snapsInstallPrivacyWarningShown": "boolean" "0x1": true,
"0xe708": true,
"0x5": true,
"0x539": true
}, },
"CachedBalancesController": "object", "snapsInstallPrivacyWarningShown": true
},
"CachedBalancesController": { "cachedBalances": "object" },
"CurrencyController": { "CurrencyController": {
"conversionDate": 1665507600, "conversionDate": "number",
"conversionRate": 1300, "conversionRate": 1300,
"currentCurrency": "usd", "currentCurrency": "usd",
"nativeCurrency": "ETH", "nativeCurrency": "ETH",
"usdConversionRate": "number" "usdConversionRate": 1300
},
"GasFeeController": {
"estimatedGasFeeTimeBounds": {},
"gasEstimateType": "none",
"gasFeeEstimates": {}
}, },
"GasFeeController": "object",
"IncomingTransactionsController": { "IncomingTransactionsController": {
"incomingTransactions": "object", "incomingTransactions": "object",
"incomingTxLastFetchedBlockByChainId": { "incomingTxLastFetchedBlockByChainId": {
@ -54,13 +63,13 @@
"networkId": "1337", "networkId": "1337",
"networkStatus": "available", "networkStatus": "available",
"providerConfig": { "providerConfig": {
"chainId": "string", "chainId": "0x539",
"nickname": "Localhost 8545", "nickname": "Localhost 8545",
"rpcPrefs": "object", "rpcPrefs": "object",
"rpcUrl": "string", "rpcUrl": "string",
"ticker": "ETH", "ticker": "ETH",
"type": "rpc", "type": "rpc",
"id": "string" "id": "networkConfigurationId"
}, },
"networkConfigurations": "object" "networkConfigurations": "object"
}, },
@ -70,20 +79,20 @@
"onboardingTabs": "object", "onboardingTabs": "object",
"seedPhraseBackedUp": true "seedPhraseBackedUp": true
}, },
"PermissionController": "object", "PermissionController": { "subjects": "object" },
"PreferencesController": { "PreferencesController": {
"advancedGasFee": "object", "advancedGasFee": null,
"currentLocale": "en", "currentLocale": "en",
"dismissSeedBackUpReminder": "boolean", "dismissSeedBackUpReminder": true,
"featureFlags": { "showIncomingTransactions": true }, "featureFlags": { "showIncomingTransactions": true },
"forgottenPassword": false, "forgottenPassword": false,
"identities": "object", "identities": "object",
"infuraBlocked": "boolean", "infuraBlocked": false,
"ipfsGateway": "dweb.link", "ipfsGateway": "string",
"knownMethodData": "object", "knownMethodData": "object",
"ledgerTransportType": "string", "ledgerTransportType": "webhid",
"lostIdentities": "object", "lostIdentities": "object",
"openSeaEnabled": "boolean", "openSeaEnabled": false,
"preferences": { "preferences": {
"hideZeroBalanceTokens": false, "hideZeroBalanceTokens": false,
"showFiatInTestnets": false, "showFiatInTestnets": false,
@ -91,19 +100,32 @@
"useNativeCurrencyAsPrimaryCurrency": true "useNativeCurrencyAsPrimaryCurrency": true
}, },
"selectedAddress": "string", "selectedAddress": "string",
"theme": "string", "theme": "light",
"useBlockie": false, "useBlockie": false,
"useNftDetection": "boolean", "useNftDetection": false,
"useNonceField": false, "useNonceField": false,
"usePhishDetect": true, "usePhishDetect": true,
"useTokenDetection": "boolean", "useTokenDetection": false,
"useCurrencyRateCheck": "boolean", "useCurrencyRateCheck": true,
"useMultiAccountBalanceChecker": "boolean" "useMultiAccountBalanceChecker": true
}, },
"SmartTransactionsController": "object", "SmartTransactionsController": {
"SubjectMetadataController": "object", "smartTransactionsState": {
"TokensController": "object", "fees": {},
"TransactionController": "object", "liveness": true,
"smartTransactions": "object"
}
},
"SubjectMetadataController": { "subjectMetadata": "object" },
"TokensController": {
"allDetectedTokens": {},
"allIgnoredTokens": {},
"allTokens": {},
"detectedTokens": "object",
"ignoredTokens": "object",
"tokens": "object"
},
"TransactionController": { "transactions": "object" },
"config": "object", "config": "object",
"firstTimeInfo": "object" "firstTimeInfo": "object"
}, },