-
-
Notifications
You must be signed in to change notification settings - Fork 246
fix(account-tree-controller): address group names consistency bug #6601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
d7a3248
4fb2af9
b64f14c
b38ffe6
081c4f0
927a774
acd49d8
f495812
90c4056
87a65ea
d26532d
071a074
dca6f2d
1c7c0df
e2a474b
a512217
0ef2ffa
b87494a
7d4e7dc
66fd0a9
c2fe321
e75b4e6
a4a2709
3efc670
9ece24c
70554ef
661b091
d3cb731
9873b6e
87573cd
44600fd
7e6f701
4aa81d4
04239c5
39557d3
156becd
5935c76
986114e
e47a278
ddb42e1
9d37632
6a7184b
47b4e4a
ede8d24
34d02af
d0a9e96
fc9ff35
c43a1d3
646fc06
5bc89b3
895007a
7d0c219
d243c52
38e0b5a
a6ec434
ffe2350
3cc47b4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -394,47 +394,99 @@ | |
wallet: AccountWalletObject, | ||
group: AccountGroupObject, | ||
) { | ||
const persistedMetadata = this.state.accountGroupsMetadata[group.id]; | ||
const persistedGroupMetadata = this.state.accountGroupsMetadata[group.id]; | ||
|
||
// Apply persisted name if available (including empty strings) | ||
if (persistedMetadata?.name !== undefined) { | ||
group.metadata.name = persistedMetadata.name.value; | ||
if (persistedGroupMetadata?.name !== undefined) { | ||
group.metadata.name = persistedGroupMetadata.name.value; | ||
} else if (!group.metadata.name) { | ||
// Get the appropriate rule for this wallet type | ||
const rule = this.#getRuleForWallet(wallet); | ||
const typedWallet = wallet as AccountWalletObjectOf<typeof wallet.type>; | ||
const typedGroup = typedWallet.groups[group.id] as AccountGroupObject; | ||
fabiobozzo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
// Calculate group index based on position within sorted group IDs | ||
// We sort to ensure consistent ordering across all wallet types: | ||
// - Entropy: group IDs like "entropy:abc/0", "entropy:abc/1" sort to logical order | ||
// - Snap/Keyring: group IDs like "keyring:ledger/0xABC" get consistent alphabetical order | ||
const sortedGroupIds = Object.keys(wallet.groups).sort(); | ||
let groupIndex = sortedGroupIds.indexOf(group.id); | ||
|
||
// Defensive fallback: if group.id is not found in sortedGroupIds (should never happen | ||
// in normal operation since we iterate over wallet.groups), use index 0 to prevent | ||
// passing -1 to getDefaultAccountGroupName which would result in "Account 0" | ||
/* istanbul ignore next */ | ||
if (groupIndex === -1) { | ||
groupIndex = 0; | ||
// Try to get computed name first (e.g., from existing EVM account names) | ||
const computedName = rule.getComputedAccountGroupName(typedGroup); | ||
|
||
if (computedName) { | ||
group.metadata.name = computedName; | ||
} else { | ||
// Generate default name based on wallet-specific numbering | ||
group.metadata.name = this.#generateDefaultGroupName( | ||
wallet, | ||
group, | ||
rule, | ||
); | ||
fabiobozzo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Account Group Naming Fails SequentialityThe default account group naming logic can lead to non-sequential numbering. For entropy-based groups, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, that's by design. |
||
// Use computed name first, then fallback to default naming if empty | ||
group.metadata.name = | ||
rule.getComputedAccountGroupName(typedGroup) || | ||
rule.getDefaultAccountGroupName(groupIndex); | ||
// Persist the assigned name to ensure consistency across restarts | ||
// This prevents the name from changing on subsequent inits | ||
this.update((state) => { | ||
fabiobozzo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
if (!state.accountGroupsMetadata[group.id]) { | ||
state.accountGroupsMetadata[group.id] = {}; | ||
} | ||
state.accountGroupsMetadata[group.id].name = { | ||
value: group.metadata.name, | ||
lastUpdatedAt: Date.now(), | ||
}; | ||
}); | ||
} | ||
|
||
// Apply persisted UI states | ||
if (persistedMetadata?.pinned?.value !== undefined) { | ||
group.metadata.pinned = persistedMetadata.pinned.value; | ||
if (persistedGroupMetadata?.pinned?.value !== undefined) { | ||
group.metadata.pinned = persistedGroupMetadata.pinned.value; | ||
} | ||
if (persistedMetadata?.hidden?.value !== undefined) { | ||
group.metadata.hidden = persistedMetadata.hidden.value; | ||
if (persistedGroupMetadata?.hidden?.value !== undefined) { | ||
group.metadata.hidden = persistedGroupMetadata.hidden.value; | ||
} | ||
} | ||
|
||
/** | ||
* Generates a default name for an account group, ensuring unique numbering | ||
* within each wallet. | ||
* | ||
* @param wallet - The wallet containing the group. | ||
* @param group - The group to generate a name for. | ||
* @param rule - The rule for this wallet type. | ||
* @returns The generated default name. | ||
*/ | ||
#generateDefaultGroupName( | ||
wallet: AccountWalletObject, | ||
group: AccountGroupObject, | ||
rule: Rule<AccountWalletType, AccountGroupType>, | ||
): string { | ||
ccharly marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
// For entropy groups, use the groupIndex from metadata for consistent numbering | ||
if (group.type === 'multichain-account' && 'entropy' in group.metadata) { | ||
return rule.getDefaultAccountGroupName(group.metadata.entropy.groupIndex); | ||
} | ||
|
||
// For other types, use sequential numbering within the wallet | ||
// Count existing groups to determine the next number | ||
const existingNumbers = new Set<number>(); | ||
|
||
// Collect all numbers currently in use by this wallet's groups | ||
for (const existingGroup of Object.values(wallet.groups)) { | ||
const { id } = existingGroup; | ||
const { name: persistedName } = this.state.accountGroupsMetadata[id] || {}; | ||
const existingName = persistedName?.value || existingGroup.metadata.name; | ||
|
||
// Extract number from "Account X" pattern | ||
const match = existingName.match(/^Account (\d+)$/); | ||
Check failure on line 474 in packages/account-tree-controller/src/AccountTreeController.ts
|
||
if (match) { | ||
const [, numberStr] = match; | ||
existingNumbers.add(parseInt(numberStr, 10) - 1); // Convert to 0-based index | ||
} | ||
} | ||
|
||
// Find the first available number (0-based) | ||
let accountNumber = 0; | ||
while (existingNumbers.has(accountNumber)) { | ||
accountNumber++; | ||
} | ||
|
||
return rule.getDefaultAccountGroupName(accountNumber); | ||
} | ||
|
||
/** | ||
* Gets the account wallet object from its ID. | ||
* | ||
|
Uh oh!
There was an error while loading. Please reload this page.