Skip to content

Commit 96faa58

Browse files
authored
Merge branch 'main' into jc/WAPI-728
2 parents dbdc6e6 + ede9bdb commit 96faa58

File tree

116 files changed

+3717
-737
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+3717
-737
lines changed

eslint-warning-thresholds.json

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -349,21 +349,10 @@
349349
"jest/no-conditional-in-test": 1
350350
},
351351
"packages/signature-controller/src/SignatureController.ts": {
352-
"@typescript-eslint/no-unsafe-enum-comparison": 4
353-
},
354-
"packages/signature-controller/src/utils/decoding-api.test.ts": {
355-
"import-x/order": 1,
356-
"jsdoc/tag-lines": 1
357-
},
358-
"packages/signature-controller/src/utils/decoding-api.ts": {
359-
"import-x/order": 1
360-
},
361-
"packages/signature-controller/src/utils/normalize.test.ts": {
362-
"import-x/order": 1
352+
"@typescript-eslint/no-unsafe-enum-comparison": 3
363353
},
364354
"packages/signature-controller/src/utils/normalize.ts": {
365-
"@typescript-eslint/no-unused-vars": 1,
366-
"jsdoc/tag-lines": 2
355+
"@typescript-eslint/no-unused-vars": 1
367356
},
368357
"packages/signature-controller/src/utils/validation.ts": {
369358
"@typescript-eslint/no-base-to-string": 1,

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@metamask/core-monorepo",
3-
"version": "569.0.0",
3+
"version": "574.0.0",
44
"private": true,
55
"description": "Monorepo for packages shared between MetaMask clients",
66
"repository": {
@@ -61,8 +61,8 @@
6161
"@metamask/eslint-config-nodejs": "^14.0.0",
6262
"@metamask/eslint-config-typescript": "^14.0.0",
6363
"@metamask/eth-block-tracker": "^12.0.1",
64-
"@metamask/eth-json-rpc-provider": "^4.1.8",
65-
"@metamask/json-rpc-engine": "^10.0.3",
64+
"@metamask/eth-json-rpc-provider": "^5.0.0",
65+
"@metamask/json-rpc-engine": "^10.1.0",
6666
"@metamask/utils": "^11.8.0",
6767
"@ts-bridge/cli": "^0.6.1",
6868
"@types/jest": "^27.4.1",

packages/account-tree-controller/CHANGELOG.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- Set the `setAccountGroupName`'s option `autoHandleConflict` to `true` for all backup & sync operations ([#6697](https://github.com/MetaMask/core/pull/6697))
13+
- Add new group naming for non-HD keyring accounts ([#6679](https://github.com/MetaMask/core/pull/6679)), ([#6696](https://github.com/MetaMask/core/pull/6696))
14+
- Hardware-wallet account groups are now named: "Ledger|Trezor|QR|Lattice|OneKey Account N".
15+
- Private key account groups are now named: "Imported Account N".
16+
- Snap account groups are now named: "Snap Account N".
17+
- Account group names now use natural indexing as a fallback ([#6677](https://github.com/MetaMask/core/pull/6677)), ([#6679](https://github.com/MetaMask/core/pull/6679)), ([#6696](https://github.com/MetaMask/core/pull/6696))
18+
- If a user names his accounts without any indexes, we would just use the number of accounts to compute the next available index.
19+
20+
### Fixed
21+
22+
- Fix group naming for non-HD keyring accounts ([#6677](https://github.com/MetaMask/core/pull/6677)), ([#6679](https://github.com/MetaMask/core/pull/6679))
23+
- Previously, the first non-HD keyring account would start as `Account 2` as opposed to `Account 1` and thus subsequent group names were off as well.
24+
25+
## [1.0.0]
26+
27+
### Changed
28+
29+
- **BREAKING:** Bump peer dependency `@metamask/multichain-account-service` from `^0.8.0` to `^1.0.0` ([#6652](https://github.com/MetaMask/core/pull/6652), [#6676](https://github.com/MetaMask/core/pull/6676))
30+
31+
## [0.18.1]
32+
33+
### Fixed
34+
35+
- Set `lastUpdatedAt` to `0` when generating default account group names ([#6672](https://github.com/MetaMask/core/pull/6672))
36+
- This created conflicts with backup and sync, where newly created local groups' names were taking precedence over user-defined backed up names.
37+
1038
## [0.18.0]
1139

1240
### Added
@@ -276,7 +304,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
276304
- Initial release ([#5847](https://github.com/MetaMask/core/pull/5847))
277305
- Grouping accounts into 3 main categories: Entropy source, Snap ID, keyring types.
278306

279-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@0.18.0...HEAD
307+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@1.0.0...HEAD
308+
[1.0.0]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@0.18.1...@metamask/account-tree-controller@1.0.0
309+
[0.18.1]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@0.18.0...@metamask/account-tree-controller@0.18.1
280310
[0.18.0]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@0.17.0...@metamask/account-tree-controller@0.18.0
281311
[0.17.0]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@0.16.1...@metamask/account-tree-controller@0.17.0
282312
[0.16.1]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@0.16.0...@metamask/account-tree-controller@0.16.1

packages/account-tree-controller/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@metamask/account-tree-controller",
3-
"version": "0.18.0",
3+
"version": "1.0.0",
44
"description": "Controller to group account together based on some pre-defined rules",
55
"keywords": [
66
"MetaMask",
@@ -61,7 +61,7 @@
6161
"@metamask/auto-changelog": "^3.4.4",
6262
"@metamask/keyring-api": "^21.0.0",
6363
"@metamask/keyring-controller": "^23.1.0",
64-
"@metamask/multichain-account-service": "^0.11.0",
64+
"@metamask/multichain-account-service": "^1.0.0",
6565
"@metamask/profile-sync-controller": "^25.0.0",
6666
"@metamask/providers": "^22.1.0",
6767
"@metamask/snaps-controllers": "^14.0.1",
@@ -78,7 +78,7 @@
7878
"@metamask/account-api": "^0.12.0",
7979
"@metamask/accounts-controller": "^33.0.0",
8080
"@metamask/keyring-controller": "^23.0.0",
81-
"@metamask/multichain-account-service": "^0.8.0",
81+
"@metamask/multichain-account-service": "^1.0.0",
8282
"@metamask/profile-sync-controller": "^25.0.0",
8383
"@metamask/providers": "^22.0.0",
8484
"@metamask/snaps-controllers": "^14.0.0",

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

Lines changed: 223 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ describe('AccountTreeController', () => {
587587
type: AccountGroupType.SingleAccount,
588588
accounts: [MOCK_SNAP_ACCOUNT_2.id],
589589
metadata: {
590-
name: 'Account 2', // Updated: per-wallet numbering (different wallet)
590+
name: 'Snap Account 1', // Updated: per-wallet numbering (different wallet)
591591
pinned: false,
592592
hidden: false,
593593
},
@@ -610,7 +610,7 @@ describe('AccountTreeController', () => {
610610
type: AccountGroupType.SingleAccount,
611611
accounts: [MOCK_HARDWARE_ACCOUNT_1.id],
612612
metadata: {
613-
name: 'Account 2', // Updated: per-wallet numbering (different wallet)
613+
name: 'Ledger Account 1', // Updated: per-wallet numbering (different wallet)
614614
pinned: false,
615615
hidden: false,
616616
},
@@ -652,13 +652,13 @@ describe('AccountTreeController', () => {
652652
},
653653
[expectedKeyringWalletIdGroup]: {
654654
name: {
655-
value: 'Account 2', // Updated: per-wallet numbering (different wallet)
655+
value: 'Ledger Account 1', // Updated: per-wallet numbering (different wallet)
656656
lastUpdatedAt: expect.any(Number),
657657
},
658658
},
659659
[expectedSnapWalletIdGroup]: {
660660
name: {
661-
value: 'Account 2', // Updated: per-wallet numbering (different wallet)
661+
value: 'Snap Account 1', // Updated: per-wallet numbering (different wallet)
662662
lastUpdatedAt: expect.any(Number),
663663
},
664664
},
@@ -2430,8 +2430,8 @@ describe('AccountTreeController', () => {
24302430

24312431
// Groups should use consistent default naming regardless of import time
24322432
// Updated expectations based on per-wallet sequential naming logic
2433-
expect(group1?.metadata.name).toBe('Account 3'); // Updated: reflects actual naming logic
2434-
expect(group2?.metadata.name).toBe('Account 2'); // Updated: reflects actual naming logic
2433+
expect(group1?.metadata.name).toBe('Account 2'); // Updated: reflects actual naming logic
2434+
expect(group2?.metadata.name).toBe('Account 1'); // Updated: reflects actual naming logic
24352435
});
24362436

24372437
it('uses fallback naming when rule-based naming returns empty string', () => {
@@ -2903,8 +2903,8 @@ describe('AccountTreeController', () => {
29032903
expect(uniqueNames.size).toBe(2);
29042904

29052905
// Due to optimization, names start at wallet.length, so we get "Account 3" and "Account 4"
2906-
expect(allNames).toContain('Account 3');
2907-
expect(allNames).toContain('Account 4');
2906+
expect(allNames).toContain('Ledger Account 1');
2907+
expect(allNames).toContain('Ledger Account 2');
29082908

29092909
// Verify they're actually different
29102910
expect(group1.metadata.name).not.toBe(group2.metadata.name);
@@ -4033,4 +4033,219 @@ describe('AccountTreeController', () => {
40334033
).toBe('Conflict Name (2)');
40344034
});
40354035
});
4036+
4037+
describe('naming', () => {
4038+
const mockAccount1 = {
4039+
...MOCK_HARDWARE_ACCOUNT_1,
4040+
id: 'mock-id-1',
4041+
address: '0x123',
4042+
};
4043+
const mockAccount2 = {
4044+
...MOCK_HARDWARE_ACCOUNT_1,
4045+
id: 'mock-id-2',
4046+
address: '0x456',
4047+
};
4048+
const mockAccount3 = {
4049+
...MOCK_HARDWARE_ACCOUNT_1,
4050+
id: 'mock-id-3',
4051+
address: '0x789',
4052+
};
4053+
const mockAccount4 = {
4054+
...MOCK_HARDWARE_ACCOUNT_1,
4055+
id: 'mock-id-4',
4056+
address: '0xabc',
4057+
};
4058+
4059+
const mockWalletId = toAccountWalletId(
4060+
AccountWalletType.Keyring,
4061+
KeyringTypes.ledger,
4062+
);
4063+
4064+
const getAccountGroupFromAccount = (
4065+
controller: AccountTreeController,
4066+
mockAccount: InternalAccount,
4067+
) => {
4068+
const groupId = toAccountGroupId(mockWalletId, mockAccount.address);
4069+
return controller.state.accountTree.wallets[mockWalletId].groups[groupId];
4070+
};
4071+
4072+
it('names non-HD keyrings accounts properly', () => {
4073+
const { controller, messenger } = setup();
4074+
4075+
// Add all 3 accounts.
4076+
[mockAccount1, mockAccount2, mockAccount3].forEach(
4077+
(mockAccount, index) => {
4078+
messenger.publish('AccountsController:accountAdded', mockAccount);
4079+
4080+
const mockGroup = getAccountGroupFromAccount(controller, mockAccount);
4081+
expect(mockGroup).toBeDefined();
4082+
expect(mockGroup.metadata.name).toBe(`Ledger Account ${index + 1}`);
4083+
},
4084+
);
4085+
4086+
// Remove account 2, should still create account 4 afterward.
4087+
messenger.publish('AccountsController:accountRemoved', mockAccount2.id);
4088+
4089+
expect(
4090+
getAccountGroupFromAccount(controller, mockAccount4),
4091+
).toBeUndefined();
4092+
messenger.publish('AccountsController:accountAdded', mockAccount4);
4093+
4094+
const mockGroup4 = getAccountGroupFromAccount(controller, mockAccount4);
4095+
expect(mockGroup4).toBeDefined();
4096+
expect(mockGroup4.metadata.name).toBe('Ledger Account 4');
4097+
4098+
// Now, removing account 3 and 4, should defaults to an index of "2" (since only
4099+
// account 1 remains), thus, re-inserting account 2, should be named "* Account 2".
4100+
messenger.publish('AccountsController:accountRemoved', mockAccount4.id);
4101+
messenger.publish('AccountsController:accountRemoved', mockAccount3.id);
4102+
4103+
expect(
4104+
getAccountGroupFromAccount(controller, mockAccount2),
4105+
).toBeUndefined();
4106+
messenger.publish('AccountsController:accountAdded', mockAccount2);
4107+
4108+
const mockGroup2 = getAccountGroupFromAccount(controller, mockAccount2);
4109+
expect(mockGroup2).toBeDefined();
4110+
expect(mockGroup2.metadata.name).toBe('Ledger Account 2');
4111+
});
4112+
4113+
it('ignores bad account group name pattern and fallback to natural indexing', () => {
4114+
const { controller, messenger } = setup({
4115+
accounts: [mockAccount1],
4116+
});
4117+
4118+
controller.init();
4119+
4120+
const mockGroup1 = getAccountGroupFromAccount(controller, mockAccount1);
4121+
expect(mockGroup1).toBeDefined();
4122+
4123+
const mockIndex = 90;
4124+
controller.setAccountGroupName(
4125+
mockGroup1.id,
4126+
`Account${mockIndex}`, // No space, so this should fallback to natural indexing
4127+
);
4128+
4129+
// The first account has a non-matching pattern, thus we should fallback to the next
4130+
// natural index.
4131+
messenger.publish('AccountsController:accountAdded', mockAccount2);
4132+
const mockGroup2 = getAccountGroupFromAccount(controller, mockAccount2);
4133+
expect(mockGroup2).toBeDefined();
4134+
expect(mockGroup2.metadata.name).toBe(`Ledger Account 2`); // Natural indexing.
4135+
});
4136+
4137+
it.each([
4138+
['Account', 'account'],
4139+
['Account', 'aCCount'],
4140+
['Account', 'accOunT'],
4141+
[' ', ' '],
4142+
[' ', '\t'],
4143+
[' ', ' \t'],
4144+
[' ', '\t '],
4145+
])(
4146+
'ignores case (case-insensitive) and spaces when extracting highest index: "$0" -> "$1"',
4147+
(toReplace, replaced) => {
4148+
const { controller, messenger } = setup({
4149+
accounts: [mockAccount1],
4150+
});
4151+
4152+
controller.init();
4153+
4154+
const mockGroup1 = getAccountGroupFromAccount(controller, mockAccount1);
4155+
expect(mockGroup1).toBeDefined();
4156+
4157+
const mockIndex = 90;
4158+
controller.setAccountGroupName(
4159+
mockGroup1.id,
4160+
mockGroup1.metadata.name
4161+
.replace(toReplace, replaced)
4162+
.replace('1', `${mockIndex}`), // Use index different than 1.
4163+
);
4164+
4165+
// Even if the account is not strictly named "Ledger Account 90", we should be able
4166+
// to compute the next index from there.
4167+
messenger.publish('AccountsController:accountAdded', mockAccount2);
4168+
const mockGroup2 = getAccountGroupFromAccount(controller, mockAccount2);
4169+
expect(mockGroup2).toBeDefined();
4170+
expect(mockGroup2.metadata.name).toBe(
4171+
`Ledger Account ${mockIndex + 1}`,
4172+
);
4173+
},
4174+
);
4175+
4176+
it.each([' ', ' ', '\t', ' \t'])(
4177+
'extract name indexes and ignore multiple spaces: "%s"',
4178+
(space) => {
4179+
const { controller, messenger } = setup({
4180+
accounts: [mockAccount1],
4181+
});
4182+
4183+
controller.init();
4184+
4185+
const mockGroup1 = getAccountGroupFromAccount(controller, mockAccount1);
4186+
expect(mockGroup1).toBeDefined();
4187+
4188+
const mockIndex = 90;
4189+
controller.setAccountGroupName(
4190+
mockGroup1.id,
4191+
mockGroup1.metadata.name
4192+
.replace(' ', space)
4193+
.replace('1', `${mockIndex}`), // Use index different than 1.
4194+
);
4195+
4196+
// Even if the account is not strictly named "Ledger Account 90", we should be able
4197+
// to compute the next index from there.
4198+
messenger.publish('AccountsController:accountAdded', mockAccount2);
4199+
const mockGroup2 = getAccountGroupFromAccount(controller, mockAccount2);
4200+
expect(mockGroup2).toBeDefined();
4201+
expect(mockGroup2.metadata.name).toBe(
4202+
`Ledger Account ${mockIndex + 1}`,
4203+
);
4204+
},
4205+
);
4206+
4207+
it('uses natural indexing for pre-existing accounts', () => {
4208+
const { controller } = setup({
4209+
accounts: [mockAccount1, mockAccount2, mockAccount3],
4210+
});
4211+
4212+
controller.init();
4213+
4214+
// After initializing the controller, all accounts should be named appropriately.
4215+
[mockAccount1, mockAccount2, mockAccount3].forEach(
4216+
(mockAccount, index) => {
4217+
const mockGroup = getAccountGroupFromAccount(controller, mockAccount);
4218+
expect(mockGroup).toBeDefined();
4219+
expect(mockGroup.metadata.name).toBe(`Ledger Account ${index + 1}`);
4220+
},
4221+
);
4222+
});
4223+
4224+
it('fallbacks to natural indexing if group names are not using our default name pattern', () => {
4225+
const { controller, messenger } = setup();
4226+
4227+
[mockAccount1, mockAccount2, mockAccount3].forEach((mockAccount) =>
4228+
messenger.publish('AccountsController:accountAdded', mockAccount),
4229+
);
4230+
4231+
const mockGroup1 = getAccountGroupFromAccount(controller, mockAccount1);
4232+
const mockGroup2 = getAccountGroupFromAccount(controller, mockAccount2);
4233+
const mockGroup3 = getAccountGroupFromAccount(controller, mockAccount3);
4234+
expect(mockGroup1).toBeDefined();
4235+
expect(mockGroup2).toBeDefined();
4236+
expect(mockGroup3).toBeDefined();
4237+
4238+
// Rename all accounts to something different than "* Account <index>".
4239+
controller.setAccountGroupName(mockGroup1.id, 'Account A');
4240+
controller.setAccountGroupName(mockGroup2.id, 'The next account');
4241+
controller.setAccountGroupName(mockGroup3.id, 'Best account so far');
4242+
4243+
// Adding a new account should not reset back to "Account 1", but it should
4244+
// use the next natural index, here, "Account 4".
4245+
messenger.publish('AccountsController:accountAdded', mockAccount4);
4246+
const mockGroup4 = getAccountGroupFromAccount(controller, mockAccount4);
4247+
expect(mockGroup4).toBeDefined();
4248+
expect(mockGroup4.metadata.name).toBe('Ledger Account 4');
4249+
});
4250+
});
40364251
});

0 commit comments

Comments
 (0)