Skip to content

Commit 1ad826a

Browse files
committed
fix(accounts): fix account id indexing when there an index gap
1 parent 9ccc83a commit 1ad826a

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

packages/accounts-controller/src/AccountsController.ts

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -652,17 +652,15 @@ export class AccountsController extends BaseController<
652652
}
653653

654654
/**
655-
* Returns the next account number for a given keyring type.
655+
* Returns the list of accounts for a given keyring type.
656656
* @param keyringType - The type of keyring.
657-
* @returns An object containing the account prefix and index to use.
657+
* @returns The list of accounts associcated with this keyring type.
658658
*/
659-
#getNextAccountNumber(keyringType: string): {
660-
accountPrefix: string;
661-
indexToUse: number;
662-
} {
663-
const keyringName = keyringTypeToName(keyringType);
664-
const previousKeyringAccounts = this.listAccounts().filter(
659+
#getAccountsByKeyringType(keyringType: string) {
660+
return this.listAccounts().filter(
665661
(internalAccount) => {
662+
// We do consider `hd` and `simple` keyrings to be of same type. So we check those 2 types
663+
// to group those accounts together!
666664
if (
667665
keyringType === KeyringTypes.hd ||
668666
keyringType === KeyringTypes.simple
@@ -672,24 +670,47 @@ export class AccountsController extends BaseController<
672670
internalAccount.metadata.keyring.type === KeyringTypes.simple
673671
);
674672
}
673+
675674
return internalAccount.metadata.keyring.type === keyringType;
676675
},
677676
);
677+
}
678+
679+
/**
680+
* Returns the next account number for a given keyring type.
681+
* @param keyringType - The type of keyring.
682+
* @returns An object containing the account prefix and index to use.
683+
*/
684+
#getNextAccountNumber(keyringType: string): {
685+
accountPrefix: string;
686+
indexToUse: number;
687+
} {
688+
const keyringName = keyringTypeToName(keyringType);
689+
const keyringAccounts = this.#getAccountsByKeyringType(keyringType);
678690
const lastDefaultIndexUsedForKeyringType =
679-
previousKeyringAccounts
680-
.filter((internalAccount) =>
681-
new RegExp(`${keyringName} \\d+$`, 'u').test(
691+
keyringAccounts
692+
.reduce((maxInternalAccountIndex, internalAccount) => {
693+
// We **DO NOT USE** `\d+` here to only consider valid "human"
694+
// number (rounded decimal number)
695+
const match = (new RegExp(`${keyringName} ([0-9]+)$`, 'u')).exec(
682696
internalAccount.metadata.name,
683-
),
684-
)
685-
.map((internalAccount) => {
686-
const nameToWords = internalAccount.metadata.name.split(' '); // get the index of a default account name
687-
return parseInt(nameToWords[nameToWords.length], 10);
688-
})
689-
.sort((a, b) => b - a)[0] || 0;
697+
);
698+
699+
if (match) {
700+
// Quoting `RegExp.exec` documentation:
701+
// > The returned array has the matched text as the first item, and then one item for
702+
// > each capturing group of the matched text.
703+
// So use `match[1]` to get the captured value
704+
const internalAccountIndex = parseInt(match[1], 10);
705+
return Math.max(maxInternalAccountIndex, internalAccountIndex);
706+
}
707+
708+
return maxInternalAccountIndex;
709+
710+
}, 0);
690711

691712
const indexToUse = Math.max(
692-
previousKeyringAccounts.length + 1,
713+
keyringAccounts.length + 1,
693714
lastDefaultIndexUsedForKeyringType + 1,
694715
);
695716

0 commit comments

Comments
 (0)