@@ -24,8 +24,6 @@ import type { InternalAccount } from '@metamask/keyring-internal-api';
24
24
import type { GetSnap as SnapControllerGetSnap } from '@metamask/snaps-controllers' ;
25
25
26
26
import { AccountTreeController } from './AccountTreeController' ;
27
- import type { AccountGroupObject } from './group' ;
28
- import { BaseRule } from './rule' ;
29
27
import { getAccountWalletNameFromKeyringType } from './rules/keyring' ;
30
28
import {
31
29
type AccountTreeControllerMessenger ,
@@ -1732,38 +1730,6 @@ describe('AccountTreeController', () => {
1732
1730
} ) ;
1733
1731
} ) ;
1734
1732
1735
- describe ( 'BaseRule' , ( ) => {
1736
- it ( 'fallbacks to emptry group name if we cannot get its account' , ( ) => {
1737
- const rootMessenger = getRootMessenger ( ) ;
1738
- const messenger = getAccountTreeControllerMessenger ( rootMessenger ) ;
1739
- const rule = new BaseRule ( messenger ) ;
1740
-
1741
- rootMessenger . registerActionHandler (
1742
- 'AccountsController:getAccount' ,
1743
- ( ) => undefined ,
1744
- ) ;
1745
-
1746
- const group : AccountGroupObject = {
1747
- id : toMultichainAccountGroupId (
1748
- toMultichainAccountWalletId ( 'test' ) ,
1749
- MOCK_HD_ACCOUNT_1 . options . entropy . groupIndex ,
1750
- ) ,
1751
- type : AccountGroupType . MultichainAccount ,
1752
- accounts : [ MOCK_HD_ACCOUNT_1 . id ] ,
1753
- metadata : {
1754
- name : MOCK_HD_ACCOUNT_1 . metadata . name ,
1755
- entropy : {
1756
- groupIndex : MOCK_HD_ACCOUNT_1 . options . entropy . groupIndex ,
1757
- } ,
1758
- pinned : false ,
1759
- hidden : false ,
1760
- } ,
1761
- } ;
1762
-
1763
- expect ( rule . getDefaultAccountGroupName ( group ) ) . toBe ( '' ) ;
1764
- } ) ;
1765
- } ) ;
1766
-
1767
1733
describe ( 'Persistence - Custom Names' , ( ) => {
1768
1734
it ( 'persists custom account group names across init calls' , ( ) => {
1769
1735
const { controller } = setup ( {
@@ -2108,4 +2074,228 @@ describe('AccountTreeController', () => {
2108
2074
) . toBeUndefined ( ) ;
2109
2075
} ) ;
2110
2076
} ) ;
2077
+
2078
+ describe ( 'Fallback Naming' , ( ) => {
2079
+ it ( 'detects new groups based on account import time' , ( ) => {
2080
+ const serviceStartTime = Date . now ( ) ;
2081
+ const mockAccountWithNewImportTime : Bip44Account < InternalAccount > = {
2082
+ ...MOCK_HD_ACCOUNT_1 ,
2083
+ options : {
2084
+ ...MOCK_HD_ACCOUNT_1 . options ,
2085
+ entropy : {
2086
+ ...MOCK_HD_ACCOUNT_1 . options . entropy ,
2087
+ id : MOCK_HD_KEYRING_1 . metadata . id ,
2088
+ groupIndex : 0 ,
2089
+ } ,
2090
+ } ,
2091
+ metadata : {
2092
+ ...MOCK_HD_ACCOUNT_1 . metadata ,
2093
+ importTime : serviceStartTime + 1000 , // Imported after service start
2094
+ } ,
2095
+ } ;
2096
+
2097
+ const mockAccountWithOldImportTime : Bip44Account < InternalAccount > = {
2098
+ ...MOCK_HD_ACCOUNT_2 ,
2099
+ options : {
2100
+ ...MOCK_HD_ACCOUNT_2 . options ,
2101
+ entropy : {
2102
+ ...MOCK_HD_ACCOUNT_2 . options . entropy ,
2103
+ id : MOCK_HD_KEYRING_1 . metadata . id ,
2104
+ groupIndex : 1 ,
2105
+ } ,
2106
+ } ,
2107
+ metadata : {
2108
+ ...MOCK_HD_ACCOUNT_2 . metadata ,
2109
+ importTime : serviceStartTime - 1000 , // Imported before service start
2110
+ } ,
2111
+ } ;
2112
+
2113
+ const { controller } = setup ( {
2114
+ accounts : [ mockAccountWithOldImportTime , mockAccountWithNewImportTime ] ,
2115
+ keyrings : [ MOCK_HD_KEYRING_1 ] ,
2116
+ } ) ;
2117
+
2118
+ controller . init ( ) ;
2119
+
2120
+ const expectedWalletId = toMultichainAccountWalletId (
2121
+ MOCK_HD_KEYRING_1 . metadata . id ,
2122
+ ) ;
2123
+
2124
+ const expectedGroupId1 = toMultichainAccountGroupId (
2125
+ expectedWalletId ,
2126
+ mockAccountWithNewImportTime . options . entropy . groupIndex ,
2127
+ ) ;
2128
+
2129
+ const expectedGroupId2 = toMultichainAccountGroupId (
2130
+ expectedWalletId ,
2131
+ mockAccountWithOldImportTime . options . entropy . groupIndex ,
2132
+ ) ;
2133
+
2134
+ const wallet = controller . state . accountTree . wallets [ expectedWalletId ] ;
2135
+ const group1 = wallet ?. groups [ expectedGroupId1 ] ;
2136
+ const group2 = wallet ?. groups [ expectedGroupId2 ] ;
2137
+
2138
+ // Groups should be named by index within the wallet
2139
+ expect ( group1 ?. metadata . name ) . toBe ( 'Account 1' ) ;
2140
+ expect ( group2 ?. metadata . name ) . toBe ( 'Account 2' ) ;
2141
+ } ) ;
2142
+
2143
+ it ( 'uses fallback naming when rule-based naming returns empty string' , ( ) => {
2144
+ // Create accounts with empty names to trigger fallback naming
2145
+ const mockAccountWithEmptyName1 : Bip44Account < InternalAccount > = {
2146
+ ...MOCK_HD_ACCOUNT_1 ,
2147
+ id : 'account-1' ,
2148
+ metadata : {
2149
+ ...MOCK_HD_ACCOUNT_1 . metadata ,
2150
+ name : '' , // Empty name will cause rule-based naming to fail
2151
+ } ,
2152
+ } ;
2153
+
2154
+ const mockAccountWithEmptyName2 : Bip44Account < InternalAccount > = {
2155
+ ...MOCK_HD_ACCOUNT_1 ,
2156
+ id : 'account-2' ,
2157
+ options : {
2158
+ ...MOCK_HD_ACCOUNT_1 . options ,
2159
+ entropy : {
2160
+ ...MOCK_HD_ACCOUNT_1 . options . entropy ,
2161
+ groupIndex : 1 , // Different group index
2162
+ } ,
2163
+ } ,
2164
+ metadata : {
2165
+ ...MOCK_HD_ACCOUNT_1 . metadata ,
2166
+ name : '' , // Empty name will cause rule-based naming to fail
2167
+ } ,
2168
+ } ;
2169
+
2170
+ const { controller } = setup ( {
2171
+ accounts : [ mockAccountWithEmptyName1 , mockAccountWithEmptyName2 ] ,
2172
+ keyrings : [ MOCK_HD_KEYRING_1 ] ,
2173
+ } ) ;
2174
+
2175
+ controller . init ( ) ;
2176
+
2177
+ const expectedWalletId = toMultichainAccountWalletId (
2178
+ MOCK_HD_KEYRING_1 . metadata . id ,
2179
+ ) ;
2180
+
2181
+ const expectedGroupId1 = toMultichainAccountGroupId (
2182
+ expectedWalletId ,
2183
+ 0 , // First group
2184
+ ) ;
2185
+
2186
+ const expectedGroupId2 = toMultichainAccountGroupId (
2187
+ expectedWalletId ,
2188
+ 1 , // Second group
2189
+ ) ;
2190
+
2191
+ const wallet = controller . state . accountTree . wallets [ expectedWalletId ] ;
2192
+ const group1 = wallet ?. groups [ expectedGroupId1 ] ;
2193
+ const group2 = wallet ?. groups [ expectedGroupId2 ] ;
2194
+
2195
+ // Verify fallback naming: "Account 1", "Account 2" within the same wallet
2196
+ expect ( group1 ?. metadata . name ) . toBe ( 'Account 1' ) ;
2197
+ expect ( group2 ?. metadata . name ) . toBe ( 'Account 2' ) ;
2198
+ } ) ;
2199
+
2200
+ it ( 'handles adding new accounts to existing groups correctly' , ( ) => {
2201
+ const serviceStartTime = Date . now ( ) ;
2202
+ // Create an existing account (imported before service start)
2203
+ const existingAccount : Bip44Account < InternalAccount > = {
2204
+ ...MOCK_HD_ACCOUNT_1 ,
2205
+ id : 'existing-account' ,
2206
+ options : {
2207
+ ...MOCK_HD_ACCOUNT_1 . options ,
2208
+ entropy : {
2209
+ ...MOCK_HD_ACCOUNT_1 . options . entropy ,
2210
+ id : MOCK_HD_KEYRING_1 . metadata . id ,
2211
+ groupIndex : 0 ,
2212
+ } ,
2213
+ } ,
2214
+ metadata : {
2215
+ ...MOCK_HD_ACCOUNT_1 . metadata ,
2216
+ name : '' , // Empty name to trigger naming logic
2217
+ importTime : serviceStartTime - 1000 , // Imported before service start
2218
+ } ,
2219
+ } ;
2220
+
2221
+ // Create a new account (imported after service start) for the same group
2222
+ const newAccount : Bip44Account < InternalAccount > = {
2223
+ ...MOCK_HD_ACCOUNT_1 ,
2224
+ id : 'new-account' ,
2225
+ options : {
2226
+ ...MOCK_HD_ACCOUNT_1 . options ,
2227
+ entropy : {
2228
+ ...MOCK_HD_ACCOUNT_1 . options . entropy ,
2229
+ id : MOCK_HD_KEYRING_1 . metadata . id ,
2230
+ groupIndex : 0 , // Same group as existing account
2231
+ } ,
2232
+ } ,
2233
+ metadata : {
2234
+ ...MOCK_HD_ACCOUNT_1 . metadata ,
2235
+ name : '' , // Empty name to trigger naming logic
2236
+ importTime : serviceStartTime + 1000 , // Imported after service start
2237
+ } ,
2238
+ } ;
2239
+
2240
+ const { controller, messenger, mocks } = setup ( {
2241
+ accounts : [ existingAccount ] ,
2242
+ keyrings : [ MOCK_HD_KEYRING_1 ] ,
2243
+ } ) ;
2244
+
2245
+ controller . init ( ) ;
2246
+
2247
+ // Add the new account to the existing group
2248
+ mocks . AccountsController . accounts = [ existingAccount , newAccount ] ;
2249
+ messenger . publish ( 'AccountsController:accountAdded' , newAccount ) ;
2250
+
2251
+ const expectedWalletId = toMultichainAccountWalletId (
2252
+ MOCK_HD_KEYRING_1 . metadata . id ,
2253
+ ) ;
2254
+ const expectedGroupId = toMultichainAccountGroupId (
2255
+ expectedWalletId ,
2256
+ 0 , // Same group index
2257
+ ) ;
2258
+
2259
+ const wallet = controller . state . accountTree . wallets [ expectedWalletId ] ;
2260
+ const group = wallet ?. groups [ expectedGroupId ] ;
2261
+
2262
+ // The group should now be treated as "new" and use fallback naming
2263
+ expect ( group ?. metadata . name ) . toBe ( 'Account 1' ) ;
2264
+ expect ( group ?. accounts ) . toHaveLength ( 2 ) ;
2265
+ expect ( group ?. accounts ) . toContain ( existingAccount . id ) ;
2266
+ expect ( group ?. accounts ) . toContain ( newAccount . id ) ;
2267
+ } ) ;
2268
+
2269
+ it ( 'handles groups not in WeakMap (fallback to false)' , ( ) => {
2270
+ // Create an account with empty name to trigger naming logic
2271
+ const mockAccountWithEmptyName : Bip44Account < InternalAccount > = {
2272
+ ...MOCK_HD_ACCOUNT_1 ,
2273
+ id : 'account-with-empty-name' ,
2274
+ metadata : {
2275
+ ...MOCK_HD_ACCOUNT_1 . metadata ,
2276
+ name : '' , // Empty name will cause rule-based naming to fail
2277
+ importTime : Date . now ( ) - 1000 , // Old account (not new)
2278
+ } ,
2279
+ } ;
2280
+
2281
+ const { controller } = setup ( {
2282
+ accounts : [ mockAccountWithEmptyName ] ,
2283
+ keyrings : [ MOCK_HD_KEYRING_1 ] ,
2284
+ } ) ;
2285
+
2286
+ controller . init ( ) ;
2287
+
2288
+ const expectedWalletId = toMultichainAccountWalletId (
2289
+ MOCK_HD_KEYRING_1 . metadata . id ,
2290
+ ) ;
2291
+ const expectedGroupId = toMultichainAccountGroupId ( expectedWalletId , 0 ) ;
2292
+
2293
+ const wallet = controller . state . accountTree . wallets [ expectedWalletId ] ;
2294
+ const group = wallet ?. groups [ expectedGroupId ] ;
2295
+
2296
+ // Should use computed name first since it's not a new group, then fallback to default
2297
+ // Since the account has empty name, computed name will be empty, so it falls back to default
2298
+ expect ( group ?. metadata . name ) . toBe ( 'Account 1' ) ;
2299
+ } ) ;
2300
+ } ) ;
2111
2301
} ) ;
0 commit comments