diff --git a/packages/accounts-controller/CHANGELOG.md b/packages/accounts-controller/CHANGELOG.md index fbf98f64b2d..e4357206b66 100644 --- a/packages/accounts-controller/CHANGELOG.md +++ b/packages/accounts-controller/CHANGELOG.md @@ -26,6 +26,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bump `@metamask/messenger` from `^2.0.0` to `^3.0.0` ([#10160](https://github.com/MetaMask/core/pull/10160)) - Bump `@metamask/network-controller` from `^36.0.0` to `^37.0.0` ([#10160](https://github.com/MetaMask/core/pull/10160)) +### Fixed + +- Now properly sends `:account*Removed` events during `clearState` ([#10150](https://github.com/MetaMask/core/pull/10150)) + ## [39.1.1] ### Changed diff --git a/packages/accounts-controller/src/AccountsController.test.ts b/packages/accounts-controller/src/AccountsController.test.ts index b8deb353ba2..25c10b71673 100644 --- a/packages/accounts-controller/src/AccountsController.test.ts +++ b/packages/accounts-controller/src/AccountsController.test.ts @@ -3421,6 +3421,90 @@ describe('AccountsController', () => { ); }); + it('publishes accountRemoved for each removed account', () => { + const { accountsController, accountsControllerMessenger } = + setupAccountsController({ + initialState: { + internalAccounts: { + accounts: { + [mockAccount.id]: mockAccount, + [mockAccount2.id]: mockAccount2, + }, + selectedAccount: mockAccount.id, + }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, + }, + }); + + const messengerSpy = jest.spyOn(accountsControllerMessenger, 'publish'); + + accountsController.clearState(); + + expect(messengerSpy).toHaveBeenCalledWith( + 'AccountsController:accountRemoved', + mockAccount.id, + ); + expect(messengerSpy).toHaveBeenCalledWith( + 'AccountsController:accountRemoved', + mockAccount2.id, + ); + }); + + it('publishes accountsRemoved with all account ids', () => { + const { accountsController, accountsControllerMessenger } = + setupAccountsController({ + initialState: { + internalAccounts: { + accounts: { + [mockAccount.id]: mockAccount, + [mockAccount2.id]: mockAccount2, + }, + selectedAccount: mockAccount.id, + }, + accountIdByAddress: { + [mockAccount.address]: mockAccount.id, + [mockAccount2.address]: mockAccount2.id, + }, + }, + }); + + const accountsRemovedListener = jest.fn(); + accountsControllerMessenger.subscribe( + 'AccountsController:accountsRemoved', + accountsRemovedListener, + ); + + accountsController.clearState(); + + expect(accountsRemovedListener).toHaveBeenCalledTimes(1); + expect(accountsRemovedListener).toHaveBeenCalledWith( + expect.arrayContaining([mockAccount.id, mockAccount2.id]), + ); + }); + + it('does not publish removal events when state is already empty', () => { + const { accountsController, accountsControllerMessenger } = + setupAccountsController({ + initialState: getDefaultAccountsControllerState(), + }); + + const messengerSpy = jest.spyOn(accountsControllerMessenger, 'publish'); + + accountsController.clearState(); + + expect(messengerSpy).not.toHaveBeenCalledWith( + 'AccountsController:accountRemoved', + expect.anything(), + ); + expect(messengerSpy).not.toHaveBeenCalledWith( + 'AccountsController:accountsRemoved', + expect.anything(), + ); + }); + it('is a no-op when state is already empty', () => { const { accountsController } = setupAccountsController({ initialState: getDefaultAccountsControllerState(), diff --git a/packages/accounts-controller/src/AccountsController.ts b/packages/accounts-controller/src/AccountsController.ts index 50af609db83..cc4204d6e4d 100644 --- a/packages/accounts-controller/src/AccountsController.ts +++ b/packages/accounts-controller/src/AccountsController.ts @@ -763,9 +763,18 @@ export class AccountsController extends BaseController< * Use `AccountTreeController`, `MultichainAccountService`, or the Keyring API v2 instead. */ clearState(): void { + const removedIds = Object.keys(this.state.internalAccounts.accounts); + this.update(() => { return getDefaultAccountsControllerState(); }); + + for (const id of removedIds) { + this.messenger.publish('AccountsController:accountRemoved', id); + } + if (removedIds.length > 0) { + this.messenger.publish('AccountsController:accountsRemoved', removedIds); + } } /**