diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 79eac0c88f1e..a30013f6bb56 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -88,6 +88,7 @@ import { hexToBytes, bytesToHex, KnownCaipNamespace, + isObject, } from '@metamask/utils'; import { normalize } from '@metamask/eth-sig-util'; @@ -1010,6 +1011,9 @@ export default class MetamaskController extends EventEmitter { this.networkController.getProviderAndBlockTracker().blockTracker; this.on('update', (update) => { + if (!isObject(update)) { + return; + } this.metaMetricsController.handleMetaMaskStateUpdate(update); }); @@ -1336,7 +1340,12 @@ export default class MetamaskController extends EventEmitter { }); // ensure isClientOpenAndUnlocked is updated when memState updates - this.on('update', (memState) => this._onStateUpdate(memState)); + this.on('update', (memState) => { + if (!isObject(memState) || !('isUnlocked' in memState)) { + return; + } + this._onStateUpdate(memState); + }); /** * All controllers in Memstore but not in store. They are not persisted. @@ -2282,6 +2291,13 @@ export default class MetamaskController extends EventEmitter { }; const updatePublicConfigStore = async (memState) => { + if ( + !isObject(memState) || + !('networksMetadata' in memState) || + !('selectedNetworkId' in memState) + ) { + return; + } const networkStatus = memState.networksMetadata[memState.selectedNetworkClientId]?.status; if (networkStatus === NetworkStatus.Available) { @@ -7753,12 +7769,18 @@ export default class MetamaskController extends EventEmitter { // misc /** - * A method for emitting the full MetaMask state to all registered listeners. + * A method for emitting either the full MetaMask state or pending patches to all registered listeners of the 'update' event. + * This method can be used to force UI updates in response to background actions or events e.g. state updates. * - * @private + * @param sendFullState - If set to true, the full MetaMask state is sent. If set to false, only pending patches are sent. + * @see {@link {import('../../ui/store/actions.ts').forceUpdateMetamaskState}} also force-syncs UI state with background state, but in response to UI events or user actions. */ - privateSendUpdate() { - this.emit('update', this.getState()); + privateSendUpdate(sendFullState = true) { + if (sendFullState) { + this.emit('update', this.getState()); + } else { + this.emit('update'); + } } /**