Skip to content

Commit 1ce9033

Browse files
committed
fix: handle mnemonic as object
1 parent 7adb29b commit 1ce9033

3 files changed

Lines changed: 35 additions & 72 deletions

File tree

packages/keyring-eth-hd/src/hd-keyring.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,29 @@ describe('hd-keyring', () => {
340340
expect(accounts[0]).toStrictEqual(firstAcct);
341341
});
342342

343+
it('validates mnemonic passed as plain object (simulating encryption/decryption cycle)', async () => {
344+
const keyring = new HdKeyring();
345+
346+
const tempKeyring = new HdKeyring();
347+
await tempKeyring.deserialize({ mnemonic: sampleMnemonic });
348+
const { mnemonic } = tempKeyring;
349+
assert(mnemonic, 'Mnemonic should be defined');
350+
351+
const mnemonicAsPlainObject: Record<string, number> = {};
352+
mnemonic.forEach((value, index) => {
353+
mnemonicAsPlainObject[index] = value;
354+
});
355+
356+
await keyring.deserialize({
357+
// @ts-expect-error testing plain object mnemonic directly
358+
mnemonic: mnemonicAsPlainObject,
359+
numberOfAccounts: 1,
360+
});
361+
362+
const accounts = await keyring.getAccounts();
363+
expect(accounts[0]).toStrictEqual(firstAcct);
364+
});
365+
343366
it('throws when numberOfAccounts is passed with no mnemonic', async () => {
344367
const keyring = new HdKeyring();
345368

packages/keyring-eth-hd/src/hd-keyring.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import { keccak256 } from 'ethereum-cryptography/keccak';
3838
const hdPathString = `m/44'/60'/0'/0`;
3939
const type = 'HD Key Tree';
4040

41+
type Mnemonic = string | number[] | SerializedBuffer | Buffer | Uint8Array;
42+
4143
export type HDKeyringOptions = {
4244
cryptographicFunctions?: CryptographicFunctions;
4345
};
@@ -601,9 +603,7 @@ export class HdKeyring implements Keyring {
601603
* as a string, an array of UTF-8 bytes, or a Buffer. Mnemonic input
602604
* passed as type buffer or array of UTF-8 bytes must be NFKD normalized.
603605
*/
604-
async #initFromMnemonic(
605-
mnemonic: string | number[] | SerializedBuffer | Buffer | Uint8Array,
606-
): Promise<void> {
606+
async #initFromMnemonic(mnemonic: Mnemonic): Promise<void> {
607607
if (this.root) {
608608
throw new Error(
609609
'Eth-Hd-Keyring: Secret recovery phrase already provided',
@@ -652,9 +652,7 @@ export class HdKeyring implements Keyring {
652652
* @param mnemonic - The mnemonic seed phrase to validate.
653653
* @throws If the mnemonic is invalid.
654654
*/
655-
#isValidMnemonic(
656-
mnemonic: string | number[] | SerializedBuffer | Buffer | Uint8Array,
657-
): void {
655+
#isValidMnemonic(mnemonic: Mnemonic): void {
658656
let mnemonicString: string;
659657

660658
if (typeof mnemonic === 'string') {
@@ -667,6 +665,13 @@ export class HdKeyring implements Keyring {
667665
mnemonicString = mnemonic.toString();
668666
} else if (mnemonic instanceof Uint8Array) {
669667
mnemonicString = this.#uint8ArrayToString(mnemonic);
668+
} else if (typeof mnemonic === 'object') {
669+
// When encrypted/decrypted, Uint8Arrays can become plain objects like {0: ..., 1: ..., ...}
670+
// Convert back to Uint8Array first, then to mnemonic string
671+
const mnemonicAsUint8Array = Uint8Array.from(
672+
Object.values(mnemonic as Record<string, number>),
673+
);
674+
mnemonicString = this.#uint8ArrayToString(mnemonicAsUint8Array);
670675
} else {
671676
throw new Error('Eth-Hd-Keyring: Invalid mnemonic format');
672677
}

yarn.lock

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -673,16 +673,6 @@ __metadata:
673673
languageName: node
674674
linkType: hard
675675

676-
"@ethersproject/basex@npm:^5.8.0":
677-
version: 5.8.0
678-
resolution: "@ethersproject/basex@npm:5.8.0"
679-
dependencies:
680-
"@ethersproject/bytes": "npm:^5.8.0"
681-
"@ethersproject/properties": "npm:^5.8.0"
682-
checksum: 10/1a8d48a9397461ea42ec43b69a15a0d13ba0b9192695713750d9d391503c55b258cca435fa78a4014d23a813053f1a471593b89c7c0d89351639a78d50a12ef2
683-
languageName: node
684-
linkType: hard
685-
686676
"@ethersproject/bignumber@npm:^5.7.0, @ethersproject/bignumber@npm:^5.8.0":
687677
version: 5.8.0
688678
resolution: "@ethersproject/bignumber@npm:5.8.0"
@@ -712,7 +702,7 @@ __metadata:
712702
languageName: node
713703
linkType: hard
714704

715-
"@ethersproject/hash@npm:^5.7.0, @ethersproject/hash@npm:^5.8.0":
705+
"@ethersproject/hash@npm:^5.7.0":
716706
version: 5.8.0
717707
resolution: "@ethersproject/hash@npm:5.8.0"
718708
dependencies:
@@ -729,26 +719,6 @@ __metadata:
729719
languageName: node
730720
linkType: hard
731721

732-
"@ethersproject/hdnode@npm:^5.8.0":
733-
version: 5.8.0
734-
resolution: "@ethersproject/hdnode@npm:5.8.0"
735-
dependencies:
736-
"@ethersproject/abstract-signer": "npm:^5.8.0"
737-
"@ethersproject/basex": "npm:^5.8.0"
738-
"@ethersproject/bignumber": "npm:^5.8.0"
739-
"@ethersproject/bytes": "npm:^5.8.0"
740-
"@ethersproject/logger": "npm:^5.8.0"
741-
"@ethersproject/pbkdf2": "npm:^5.8.0"
742-
"@ethersproject/properties": "npm:^5.8.0"
743-
"@ethersproject/sha2": "npm:^5.8.0"
744-
"@ethersproject/signing-key": "npm:^5.8.0"
745-
"@ethersproject/strings": "npm:^5.8.0"
746-
"@ethersproject/transactions": "npm:^5.8.0"
747-
"@ethersproject/wordlists": "npm:^5.8.0"
748-
checksum: 10/55b35cf30f0dd40e2d5ecd4b2f005ebea82a85a440717a61d4a483074f652d2c7063e9c704272b894bfdd500f7883aa36692931c6808591f702c1da7107ebb61
749-
languageName: node
750-
linkType: hard
751-
752722
"@ethersproject/keccak256@npm:^5.7.0, @ethersproject/keccak256@npm:^5.8.0":
753723
version: 5.8.0
754724
resolution: "@ethersproject/keccak256@npm:5.8.0"
@@ -775,16 +745,6 @@ __metadata:
775745
languageName: node
776746
linkType: hard
777747

778-
"@ethersproject/pbkdf2@npm:^5.8.0":
779-
version: 5.8.0
780-
resolution: "@ethersproject/pbkdf2@npm:5.8.0"
781-
dependencies:
782-
"@ethersproject/bytes": "npm:^5.8.0"
783-
"@ethersproject/sha2": "npm:^5.8.0"
784-
checksum: 10/203bb992eec3042256702f4c8259a37202af7b341cc6e370614cdc52541042fc3b795fb040592bd6be8b67376a798c45312ca1e6d5d179c3e8eb7431882f1fd1
785-
languageName: node
786-
linkType: hard
787-
788748
"@ethersproject/properties@npm:^5.7.0, @ethersproject/properties@npm:^5.8.0":
789749
version: 5.8.0
790750
resolution: "@ethersproject/properties@npm:5.8.0"
@@ -804,17 +764,6 @@ __metadata:
804764
languageName: node
805765
linkType: hard
806766

807-
"@ethersproject/sha2@npm:^5.8.0":
808-
version: 5.8.0
809-
resolution: "@ethersproject/sha2@npm:5.8.0"
810-
dependencies:
811-
"@ethersproject/bytes": "npm:^5.8.0"
812-
"@ethersproject/logger": "npm:^5.8.0"
813-
hash.js: "npm:1.1.7"
814-
checksum: 10/ef8916e3033502476fba9358ba1993722ac3bb99e756d5681e4effa3dfa0f0bf0c29d3fa338662830660b45dd359cccb06ba40bc7b62cfd44f4a177b25829404
815-
languageName: node
816-
linkType: hard
817-
818767
"@ethersproject/signing-key@npm:^5.8.0":
819768
version: 5.8.0
820769
resolution: "@ethersproject/signing-key@npm:5.8.0"
@@ -870,19 +819,6 @@ __metadata:
870819
languageName: node
871820
linkType: hard
872821

873-
"@ethersproject/wordlists@npm:^5.8.0":
874-
version: 5.8.0
875-
resolution: "@ethersproject/wordlists@npm:5.8.0"
876-
dependencies:
877-
"@ethersproject/bytes": "npm:^5.8.0"
878-
"@ethersproject/hash": "npm:^5.8.0"
879-
"@ethersproject/logger": "npm:^5.8.0"
880-
"@ethersproject/properties": "npm:^5.8.0"
881-
"@ethersproject/strings": "npm:^5.8.0"
882-
checksum: 10/b8e6aa7d2195bb568847f360f6525ddc3d145404fbd4553e2e05daf4a95f58167591feb69e16e3398a28114ea85e1895fc8f5bd1c0cbf8b578123d7c1d21c32d
883-
languageName: node
884-
linkType: hard
885-
886822
"@fivebinaries/coin-selection@npm:3.0.0":
887823
version: 3.0.0
888824
resolution: "@fivebinaries/coin-selection@npm:3.0.0"
@@ -1748,7 +1684,6 @@ __metadata:
17481684
dependencies:
17491685
"@ethereumjs/tx": "npm:^5.4.0"
17501686
"@ethereumjs/util": "npm:^9.1.0"
1751-
"@ethersproject/hdnode": "npm:^5.8.0"
17521687
"@lavamoat/allow-scripts": "npm:^3.2.1"
17531688
"@lavamoat/preinstall-always-fail": "npm:^2.1.0"
17541689
"@metamask/account-api": "workspace:^"

0 commit comments

Comments
 (0)