feat(account-tree-controller): re-introduce lastSelected metadata#8261
feat(account-tree-controller): re-introduce lastSelected metadata#8261
lastSelected metadata#8261Conversation
ba6d99f to
cc3d9fe
Compare
|
@metamaskbot publish-preview |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
cc3d9fe to
f34c64d
Compare
|
@metamaskbot publish-preview |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
| 'AccountsController:setSelectedAccount', | ||
| accountToSelect, | ||
| ); | ||
| if (forwardSelectedAccount) { |
There was a problem hiding this comment.
I think we shouldn't really need that flag given that this method is idempotent. Added it for more fine-grained control still + to be explicit
| // track of the most recently selected groups. | ||
| const now = Date.now(); | ||
|
|
||
| /* istanbul ignore next */ |
There was a problem hiding this comment.
We usually ignore those as there's just here to auto-inject the default state when needed
| * @param groupId - The account group ID to select. | ||
| */ | ||
| setSelectedAccountGroup(groupId: AccountGroupId): void { | ||
| this.#setSelectedAccountGroup(groupId); |
There was a problem hiding this comment.
Created this new private method so we can re-use it with the event handling from the AccountsController
| // Apply persisted lastSelected (plain number, not synced). | ||
| if ( | ||
| persistedGroupMetadata?.lastSelected !== undefined && | ||
| persistedGroupMetadata.lastSelected >= 0 | ||
| ) { | ||
| group.metadata.lastSelected = persistedGroupMetadata.lastSelected; | ||
| } else { | ||
| // Automatiacally inject default value. | ||
| state.accountGroupsMetadata[groupId].lastSelected = 0; | ||
|
|
||
| group.metadata.lastSelected = 0; | ||
| } |
There was a problem hiding this comment.
The usual logic for the tree metadata, use the persistent data if any, otherwise we auto-inject the default values.
| state.selectedAccountGroup = this.#getDefaultSelectedAccountGroup( | ||
| state.accountTree.wallets, // Re-use updated wallets with metadata here. | ||
| ); |
There was a problem hiding this comment.
This got flagged by Cursor initially, we need to state.accountTree.wallets now, since #getDefaultSelectedAccountGroup uses group.metadata.lastSelected for its logic and they get populated on the state directly during that state update call.
wallets is not getting updated, thus, we would miss them and not use them.

Explanation
Some logic still relies on this metadata on accounts. Since we want to deprecate the
AccountsControllerat some point, we need to reintroduce this concept, but at the group level this time.References
N/A
Checklist
Note
Medium Risk
Changes selected-group state transitions and fallback selection logic, which could affect which account group becomes active after removals or restarts. Adds new persisted metadata fields and update paths that must stay consistent across init/reinit and event-driven selection updates.
Overview
Re-introduces a local-only
lastSelectedtimestamp on account group metadata, persisted inaccountGroupsMetadataand restored during tree rebuilds (init/reinit). The controller now updateslastSelectedwhenever a group becomes selected (viasetSelectedAccountGrouporAccountsController:selectedAccountChange).Updates default-group fallback logic to prefer the most recently selected non-empty group, with an EVM-group tiebreaker when timestamps match, and refactors selection syncing to avoid infinite loops. Tests and rule-generated default metadata are updated accordingly.
Written by Cursor Bugbot for commit d00ac94. This will update automatically on new commits. Configure here.