由于ed25519-hd-key 在 React Native (RN) 上没法直接用,由于它内部依赖了 Node.js 的 crypto 模块,RN 环境里没有,导致使用
import { derivePath } from ed25519-hd-key ;
中的 derivePath这个方法一直会报错,
解决方案一:
写一个 React Native 兼容版的助记词 → Solana Keypair 导入工具,不依赖 ed25519-hd-key,只用轻量的 noble 库
依赖安装
yarn add @noble/hashes @noble/ed25519 @scure/bip39
@scure/bip39:助记词 → seed
@noble/hashes:实现 HMAC-SHA512
@noble/ed25519:Ed25519 密钥生成
@solana/web3.js:Solana Keypair
具体代码:
import * as bip39 from "bip39";
import { mnemonicToSeedSync } from "@scure/bip39";
import { hmac } from @noble/hashes/hmac ;
import { sha512 } from @noble/hashes/sha512 ;
import { Keypair } from "@solana/web3.js";
import bs58 from "bs58";
function deriveEd25519Path(seed: Uint8Array, path: string): Uint8Array {
// 解析 path,例如 m/44 /501 /0 /0
const segments = path
.split( / )
.slice(1)
.map((part) => {
if (!part.endsWith(" ")) throw new Error( Only hardened paths allowed );
return (parseInt(part.slice(0, -1)) | 0x80000000) >>> 0;
});
let key = hmac.create(sha512, Buffer.from( ed25519 seed )).update(seed).digest();
let priv = key.slice(0, 32);
let chainCode = key.slice(32);
for (const index of segments) {
const data = new Uint8Array(1 + 32 + 4);
data[0] = 0x00;
data.set(priv, 1);
data[33] = (index >> 24) & 0xff;
data[34] = (index >> 16) & 0xff;
data[35] = (index >> 8) & 0xff;
data[36] = index & 0xff;
const I = hmac.create(sha512, chainCode).update(data).digest();
priv = I.slice(0, 32);
chainCode = I.slice(32);
}
return priv;
}
export const testNewImportSol = async (
mnemonic: string
): Promise<{ publicKey: string; secretKey: string; keyStore: string }> => {
try {
// 验证助记词
if (!bip39.validateMnemonic(mnemonic)) {
throw new Error("Invalid mnemonic");
}
const seed = mnemonicToSeedSync(mnemonic);
const path = `m/44 /501 /0 /0 `;
const privateKey = deriveEd25519Path(seed,path);
const keypair = Keypair.fromSeed(privateKey);
console.log("Generated keypair======:", {
publicKey: keypair.publicKey.toBase58(),
secretKeyLength: bs58.encode(keypair.secretKey),
});
return {
publicKey: keypair.publicKey.toBase58(), // Base58 编码的公钥
secretKey: bs58.encode(keypair.secretKey), // Base58 编码的私钥
keyStore: "",
};
} catch (error: any) {
console.error("Error generating Solana account:", error.message);
throw new Error(`Failed to generate Solana account: ${error.message}`);
}
};
使用:
export const testNewImportSol = async (
mnemonic: string
): Promise<{ publicKey: string; secretKey: string; keyStore: string }> => {
try {
// 验证助记词
if (!bip39.validateMnemonic(mnemonic)) {
throw new Error("Invalid mnemonic");
}
const seed = mnemonicToSeedSync(mnemonic);
const path = `m/44 /501 /0 /0 `;
const privateKey = deriveEd25519Path(seed,path);
const keypair = Keypair.fromSeed(privateKey);
console.log("Generated keypair======:", {
publicKey: keypair.publicKey.toBase58(),
secretKeyLength: bs58.encode(keypair.secretKey),
});
return {
publicKey: keypair.publicKey.toBase58(), // Base58 编码的公钥
secretKey: bs58.encode(keypair.secretKey), // Base58 编码的私钥
keyStore: "",
};
} catch (error: any) {
console.error("Error generating Solana account:", error.message);
throw new Error(`Failed to generate Solana account: ${error.message}`);
}
};
方案二 :不使用ed25519
使用 @scure/bip39 @scure/bip32 @noble/curves
具体代码
import * as bip39 from "bip39";
import { mnemonicToSeedSync } from "@scure/bip39";
import { Keypair } from "@solana/web3.js";
import { HDKey } from "@scure/bip32";
import bs58 from "bs58";
// 可以直接生成solana账户,但是不是ed25519
export const testImportSol = async (
mnemonic: string,
): Promise<{ publicKey: string; secretKey: string; keyStore: string }> => {
try {
if (!bip39.validateMnemonic(mnemonic)) {
throw new Error("Invalid mnemonic");
}
const seed = mnemonicToSeedSync(mnemonic);
const hd = HDKey.fromMasterSeed(seed);
console.log("Seed:", seed, "Length:", seed.length);
const path = `m/44 /501 /0 /0 `;
const child = hd.derive(path);
if (!child.privateKey) {
throw new Error("Failed to derive private key");
}
const privateKey = child.privateKey;
console.log("privateKey====", privateKey);
const keypair = Keypair.fromSeed(privateKey);
console.log("Generated keypair======:", {
publicKey: keypair.publicKey.toBase58(),
secretKey: bs58.encode(keypair.secretKey),
});
return {
publicKey: keypair.publicKey.toBase58(), // Base58 编码的公钥
secretKey: bs58.encode(keypair.secretKey), // Base58 编码的私钥
keyStore: "",
};
} catch (error: any) {
console.error("Error generating Solana account:", error.message);
throw new Error(`Failed to generate Solana account: ${error.message}`);
}
};
提议使用方案一,这样可以兼容网页端react,使用 phantom 亲测有效
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...


