diff --git a/packages/account-tree-controller/src/AccountTreeController.test.ts b/packages/account-tree-controller/src/AccountTreeController.test.ts index ae6a5e1e16d..25df8c5d446 100644 --- a/packages/account-tree-controller/src/AccountTreeController.test.ts +++ b/packages/account-tree-controller/src/AccountTreeController.test.ts @@ -4502,6 +4502,48 @@ describe('AccountTreeController', () => { ); }); + it('always emits selectedAccountGroupChange on init even if the selected group did not change', () => { + const { controller, messenger, mocks } = setup({ + accounts: [MOCK_HD_ACCOUNT_1], + keyrings: [MOCK_HD_KEYRING_1], + }); + + mocks.AccountsController.getSelectedMultichainAccount.mockImplementation( + () => MOCK_HD_ACCOUNT_1, + ); + + controller.init(); + + const defaultAccountGroupId = toMultichainAccountGroupId( + toMultichainAccountWalletId(MOCK_HD_ACCOUNT_1.options.entropy.id), + MOCK_HD_ACCOUNT_1.options.entropy.groupIndex, + ); + + expect(controller.state.selectedAccountGroup).toStrictEqual( + defaultAccountGroupId, + ); + + const selectedAccountGroupChangeListener = jest.fn(); + messenger.subscribe( + 'AccountTreeController:selectedAccountGroupChange', + selectedAccountGroupChangeListener, + ); + + // Re-init with the same accounts — the selected group still exists and has not changed. + controller.reinit(); + + expect(controller.state.selectedAccountGroup).toStrictEqual( + defaultAccountGroupId, + ); + // The event must fire even though the group did not change, so that + // subscribers that missed the first init can still react accordingly. + expect(selectedAccountGroupChangeListener).toHaveBeenCalledWith( + defaultAccountGroupId, + defaultAccountGroupId, + ); + expect(selectedAccountGroupChangeListener).toHaveBeenCalledTimes(1); + }); + it('emits selectedAccountGroupChange when setSelectedAccountGroup is called', () => { // Use different keyring types to ensure different groups const { controller, messenger } = setup({ diff --git a/packages/account-tree-controller/src/AccountTreeController.ts b/packages/account-tree-controller/src/AccountTreeController.ts index f1839d969aa..6cf4bd5f4a1 100644 --- a/packages/account-tree-controller/src/AccountTreeController.ts +++ b/packages/account-tree-controller/src/AccountTreeController.ts @@ -369,18 +369,15 @@ export class AccountTreeController extends BaseController< } }); - // We still compare the previous and new value, the previous one could have been - // an empty string and `#getDefaultSelectedAccountGroup` could also return an - // empty string too, thus, we would re-use the same value here again. In that - // case, no need to fire any event. - if (previousSelectedAccountGroup !== this.state.selectedAccountGroup) { - log(`Selected (initial) group is: [${this.state.selectedAccountGroup}]`); - this.messenger.publish( - `${controllerName}:selectedAccountGroupChange`, - this.state.selectedAccountGroup, - previousSelectedAccountGroup, - ); - } + // We always fire the current selected group after init, even if it did not change, to ensure that + // all subscribers are aware of it and can react accordingly (e.g. by fetching accounts from + // the selected group). + log(`Selected (initial) group is: [${this.state.selectedAccountGroup}]`); + this.messenger.publish( + `${controllerName}:selectedAccountGroupChange`, + this.state.selectedAccountGroup, + previousSelectedAccountGroup, + ); log('Initialized!'); this.#initialized = true;