Skip to content

Commit 5b6138c

Browse files
committed
feat(account-tree-controller): add AccountsController:accountRenamed event handling for legacy account sync compatibility
1 parent caa125c commit 5b6138c

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

packages/account-tree-controller/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- Add support for `AccountsController:accountRenamed` event handling for legacy account syncing compatibility.
1213
- Add persistence support for user customizations ([#6221](https://github.com/MetaMask/core/pull/6221))
1314
- New `accountGroupsMetadata` (of new type `AccountTreeGroupPersistedMetadata`) and `accountWalletsMetadata` (of new type `AccountTreeWalletPersistedMetadata`) state properties to persist custom names, pinning, and hiding states.
1415
- Custom names and metadata survive controller initialization and tree rebuilds.

packages/account-tree-controller/src/AccountTreeController.test.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ function getAccountTreeControllerMessenger(
223223
name: 'AccountTreeController',
224224
allowedEvents: [
225225
'AccountsController:accountAdded',
226+
'AccountsController:accountRenamed',
226227
'AccountsController:accountRemoved',
227228
'AccountsController:selectedAccountChange',
228229
],
@@ -1017,6 +1018,89 @@ describe('AccountTreeController', () => {
10171018
});
10181019
});
10191020

1021+
describe('on AccountsController:accountRenamed', () => {
1022+
it('renames an account in the tree if the renamed internal account is of type KeyringTypes.hd', () => {
1023+
const { controller, messenger } = setup({
1024+
accounts: [MOCK_HD_ACCOUNT_1],
1025+
keyrings: [MOCK_HD_KEYRING_1],
1026+
});
1027+
controller.init();
1028+
1029+
const newName = 'New Account Name';
1030+
messenger.publish('AccountsController:accountRenamed', {
1031+
...MOCK_HD_ACCOUNT_1,
1032+
metadata: {
1033+
...MOCK_HD_ACCOUNT_1.metadata,
1034+
name: newName,
1035+
},
1036+
});
1037+
1038+
const walletId = toMultichainAccountWalletId(
1039+
MOCK_HD_KEYRING_1.metadata.id,
1040+
);
1041+
const group = toMultichainAccountGroupId(
1042+
walletId,
1043+
MOCK_HD_ACCOUNT_1.options.entropy.groupIndex,
1044+
);
1045+
1046+
expect(
1047+
controller.state.accountTree.wallets[walletId]?.groups[group],
1048+
).toBeDefined();
1049+
expect(
1050+
controller.state.accountTree.wallets[walletId]?.groups[group].metadata
1051+
.name,
1052+
).toBe(newName);
1053+
expect(
1054+
controller.state.accountTree.wallets[walletId]?.groups[group].accounts,
1055+
).toContain(MOCK_HD_ACCOUNT_1.id);
1056+
expect(
1057+
controller.state.accountTree.wallets[walletId]?.metadata.name,
1058+
).toBe('Wallet 1');
1059+
});
1060+
1061+
it('does not rename an account in the tree if the renamed internal account is not of type KeyringTypes.hd', () => {
1062+
const { controller, messenger } = setup({
1063+
accounts: [MOCK_HD_ACCOUNT_1],
1064+
keyrings: [MOCK_HD_KEYRING_1],
1065+
});
1066+
controller.init();
1067+
1068+
const newName = 'New Account Name';
1069+
messenger.publish('AccountsController:accountRenamed', {
1070+
...MOCK_HD_ACCOUNT_1,
1071+
metadata: {
1072+
...MOCK_HD_ACCOUNT_1.metadata,
1073+
keyring: {
1074+
type: KeyringTypes.simple,
1075+
},
1076+
name: newName,
1077+
},
1078+
});
1079+
1080+
const walletId = toMultichainAccountWalletId(
1081+
MOCK_HD_KEYRING_1.metadata.id,
1082+
);
1083+
const group = toMultichainAccountGroupId(
1084+
walletId,
1085+
MOCK_HD_ACCOUNT_1.options.entropy.groupIndex,
1086+
);
1087+
1088+
expect(
1089+
controller.state.accountTree.wallets[walletId]?.groups[group],
1090+
).toBeDefined();
1091+
expect(
1092+
controller.state.accountTree.wallets[walletId]?.groups[group].metadata
1093+
.name,
1094+
).toBe(MOCK_HD_ACCOUNT_1.metadata.name);
1095+
expect(
1096+
controller.state.accountTree.wallets[walletId]?.groups[group].accounts,
1097+
).toContain(MOCK_HD_ACCOUNT_1.id);
1098+
expect(
1099+
controller.state.accountTree.wallets[walletId]?.metadata.name,
1100+
).toBe('Wallet 1');
1101+
});
1102+
});
1103+
10201104
describe('getAccountWallet/getAccountWalletOrThrow', () => {
10211105
it('gets a wallet using its ID', () => {
10221106
const { controller } = setup({

packages/account-tree-controller/src/AccountTreeController.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { AccountId } from '@metamask/accounts-controller';
44
import type { StateMetadata } from '@metamask/base-controller';
55
import { BaseController } from '@metamask/base-controller';
66
import { isEvmAccountType } from '@metamask/keyring-api';
7+
import { KeyringTypes } from '@metamask/keyring-controller';
78
import type { InternalAccount } from '@metamask/keyring-internal-api';
89

910
import type { AccountGroupObject } from './group';
@@ -138,6 +139,13 @@ export class AccountTreeController extends BaseController<
138139
},
139140
);
140141

142+
this.messagingSystem.subscribe(
143+
'AccountsController:accountRenamed',
144+
(account) => {
145+
this.#handleAccountRenamed(account);
146+
},
147+
);
148+
141149
this.#registerMessageHandlers();
142150
}
143151

@@ -316,6 +324,29 @@ export class AccountTreeController extends BaseController<
316324
}
317325
}
318326

327+
#handleAccountRenamed(account: InternalAccount) {
328+
// This method is only there to support legacy account syncing programmatic renames.
329+
// Since legacy account syncing only syncs HD EVM accounts, we only
330+
// handle HD EVM accounts here.
331+
if (account.metadata.keyring.type !== (KeyringTypes.hd as string)) {
332+
return;
333+
}
334+
335+
const context = this.#accountIdToContext.get(account.id);
336+
337+
if (context) {
338+
const { walletId, groupId } = context;
339+
340+
const wallet = this.state.accountTree.wallets[walletId];
341+
if (wallet) {
342+
const group = wallet.groups[groupId];
343+
if (group) {
344+
this.setAccountGroupName(groupId, account.metadata.name);
345+
}
346+
}
347+
}
348+
}
349+
319350
/**
320351
* Helper method to prune a group if it holds no accounts and additionally
321352
* prune the wallet if it holds no groups. This action should take place

packages/account-tree-controller/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { AccountGroupId, AccountWalletId } from '@metamask/account-api';
22
import type {
33
AccountsControllerAccountAddedEvent,
4+
AccountsControllerAccountRenamedEvent,
45
AccountsControllerAccountRemovedEvent,
56
AccountsControllerGetAccountAction,
67
AccountsControllerGetSelectedAccountAction,
@@ -95,6 +96,7 @@ export type AccountTreeControllerStateChangeEvent = ControllerStateChangeEvent<
9596

9697
export type AllowedEvents =
9798
| AccountsControllerAccountAddedEvent
99+
| AccountsControllerAccountRenamedEvent
98100
| AccountsControllerAccountRemovedEvent
99101
| AccountsControllerSelectedAccountChangeEvent;
100102

0 commit comments

Comments
 (0)