fix: derive xprv addresses from correct BIP44 path (m/44'/60'/0'/0)

hdWalletFromXprv() and getSignerForAddress() for xprv type were deriving
addresses directly from the root key (m/N) instead of the standard BIP44
Ethereum path (m/44'/60'/0'/0/N). This caused imported xprv wallets to
generate completely wrong addresses.

Navigate to the BIP44 Ethereum derivation path before deriving child
addresses, matching the behavior of mnemonic-based wallet imports.
This commit is contained in:
user
2026-02-28 10:36:28 -08:00
parent 7a7f9c5135
commit 57959b70c3

View File

@@ -25,10 +25,11 @@ function hdWalletFromMnemonic(mnemonic) {
} }
function hdWalletFromXprv(xprv) { function hdWalletFromXprv(xprv) {
const node = HDNodeWallet.fromExtendedKey(xprv); const root = HDNodeWallet.fromExtendedKey(xprv);
if (!node.privateKey) { if (!root.privateKey) {
throw new Error("Not an extended private key (xprv)."); throw new Error("Not an extended private key (xprv).");
} }
const node = root.derivePath("44'/60'/0'/0");
const xpub = node.neuter().extendedKey; const xpub = node.neuter().extendedKey;
const firstAddress = node.deriveChild(0).address; const firstAddress = node.deriveChild(0).address;
return { xpub, firstAddress }; return { xpub, firstAddress };
@@ -58,7 +59,8 @@ function getSignerForAddress(walletData, addrIndex, decryptedSecret) {
return node.deriveChild(addrIndex); return node.deriveChild(addrIndex);
} }
if (walletData.type === "xprv") { if (walletData.type === "xprv") {
const node = HDNodeWallet.fromExtendedKey(decryptedSecret); const root = HDNodeWallet.fromExtendedKey(decryptedSecret);
const node = root.derivePath("44'/60'/0'/0");
return node.deriveChild(addrIndex); return node.deriveChild(addrIndex);
} }
return new Wallet(decryptedSecret); return new Wallet(decryptedSecret);