使用助记词与派生路径创建钱包:Fuel SDK 助记词钱包完整指南
【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts
本文以 Fuel 官方文档 mnemonic-wallet.md 为骨架,讲解 Fuel TypeScript SDK(fuels-ts)中从助记词(mnemonic phrase)派生钱包的核心概念与两种用法:使用默认派生路径与自定义派生路径。读者将理解助记词→种子→HD 钱包→私钥的完整链路,掌握Wallet.fromMnemonic的完整签名、BIP-44 派生路径各段含义,以及对应源码在packages/account中的具体实现,可直接在自己的 dApp 或脚本中落地使用。
助记词:可读、可备份的私钥载体
钱包本质上是一对公私钥,私钥是 32 字节的随机数,难以记忆与抄写。BIP-39 提出的助记词方案用一组人类可读的单词来编码熵(entropy),从而让你可以用一句话"保管"一个钱包。
助记词短语(mnemonic phrase)是一串由密码学算法生成的单词序列,用于派生私钥。Fuel SDK 官方指南给出了这样一个例子:助记词
oblige salon price punch saddle immune slogan rare snap desert retire surprise将派生(配合 Fuel 默认派生路径)出地址:
0xdf9d0e6c6c5f5da6e82e5e1a77974af6642bdb450a10c43f0c6910a212600185值得注意的是,该示例助记词共 12 个单词,恰好落在 Fuel SDK 支持的最小助记词长度上——从 mnemonic.ts 源码中的MNEMONIC_SIZES = [12, 15, 18, 21, 24]可以看到,SDK 校验助记词只接受 12、15、18、21、24 五种长度(对应 BIP-39 的 128~256 bit 熵 + 校验和)。任何其他长度的助记词都会被assertMnemonic拒绝并抛出错误。
在真正上手前请务必理解:助记词就是钱包的主密钥载体,谁掌握助记词谁就掌握资产,请务必通过离线或加密渠道妥善保存。
不止一个钱包:HD 分层确定性钱包与派生路径
仅仅从助记词生成一个私钥并不稀奇。Fuel SDK 更进一步,完整实现了Hierarchical Deterministic (HD) 分层确定性钱包与派生路径(derivation path)机制,允许从同一个根助记词派生出一整棵树的钱包地址——这正是各大加密钱包"一套助记词、多链多账户多地址"的底层原理。
你很可能在钱包产品中见过这样的路径:
m/44'/1179993420'/0'/0/0SDK 文档明确指出,该结构的价值在于:同一个助记词短语可以创建出多个钱包地址。只需改变路径最后几段的下标,即可得到互不相同、且可随时重现的地址序列;只要备份了助记词,任意路径下的钱包都能被重新还原。
解析 Fuel 的默认派生路径
Fuel SDK 的默认派生路径定义在 base-wallet-unlocked.ts:
static defaultPath = "m/44'/1179993420'/0'/0/0";按照 BIP-44(由 BIP-32 派生规则演化而来)的分层约定,可以把这段路径自左向右拆解如下:
| 路径段 | 层级含义 | 说明 |
|---|---|---|
m | master(主节点) | 由助记词生成的种子经 HMAC-SHA512 得到的根密钥 |
44' | purpose(用途) | 固定为44,声明使用 BIP-44 的多币种分层规范 |
1179993420' | coin type(币种) | Fuel 网络专属的币种编号 |
0' | account(账户) | 第 0 号账户 |
0 | change(找零/外部链) | BIP-44 中0通常表示外部收款地址链 |
0 | address index(地址索引) | 该链上的第 0 个地址 |
其中1179993420这个数字值得玩味:将其换算为十六进制是0x4655454C,而这串字节恰好是 ASCII 编码的字符串FUEL——据此可以推断,Fuel 选择了把"FUEL"的 ASCII 值直接作为其 BIP-44 coin type,便于在生态内统一识别与记忆。
路径中带'(如44'、1179993420'、0')的段称为硬化索引(hardened index)。在 hdwallet.ts 的源码实现中:
const HARDENED_INDEX = 0x80000000;parsePath会把'解析为在原索引上加0x80000000(即 2147483648)。硬化派生只允许由父私钥推导子密钥,可防止"子公钥泄露导致整棵树被攻破",因此 BIP-44 规定目的、币种、账户三层必须硬化。若尝试用不含私钥的扩展公钥去派生硬化索引,deriveIndex会抛出Cannot derive a hardened index without a private Key.(见 hdwallet.ts)。
两种实例化方式:默认路径 vs 自定义路径
SDK 通过同一个入口Wallet.fromMnemonic对外暴露两种用法——这也是官方文档 mnemonic-wallet.md 给出的两条主线:
- 不传派生路径:自动使用默认路径
m/44'/1179993420'/0'/0/0; - 显式传入自定义派生路径:适合需要多账户、复用通用路径(如以太坊风格的
m/44'/60'/...)或与既有钱包同步的场景。
这两种用法对应的可运行示例位于文档同级目录下:
- from-mnemonic-phrases-1.ts(默认路径)
- from-mnemonic-phrases-2.ts(自定义路径)
方式一:使用默认派生路径
如果你不需要(或不关心)派生路径的具体配置,只需一行Wallet.fromMnemonic(mnemonic):
import { Wallet } from 'fuels'; const mnemonic = 'oblige salon price punch saddle immune slogan rare snap desert retire surprise'; const wallet = Wallet.fromMnemonic(mnemonic);此时的内部行为等价于Wallet.fromMnemonic(mnemonic, Wallet.defaultPath),即路径取默认值m/44'/1179993420'/0'/0/0。wallet是一个已解锁的WalletUnlocked实例,wallet.address即前文所示地址;也可以进一步拿到wallet.privateKey、wallet.publicKey。
方式二:使用自定义派生路径
当你想从同一助记词管理多个账户,或想让 Fuel 钱包与某个既有的 HD 钱包路径对齐时,把路径作为第二个参数传入即可:
import { Wallet } from 'fuels'; const mnemonic = 'oblige salon price punch saddle immune slogan rare snap desert retire surprise'; const path = "m/44'/60'/1'/0/0"; // 注意:这是以太坊常用的路径形式,仅作示例 const wallet = Wallet.fromMnemonic(mnemonic, path);示例中的m/44'/60'/1'/0/0与默认路径的唯一区别是 coin type 由1179993420'(Fuel)换成了60'(以太坊的 BIP-44 编号),并且账户号从0'变成了1'——这会导致派生出完全不同的私钥与地址。要点如下:
- 派生路径是确定性的:相同的(助记词, 路径)必然还原出相同的私钥与地址,这是 HD 钱包可用于备份恢复的根本原因;
- 路径段须为合法的非负整数,且遵循 BIP-32 语法;非法路径(如空段、异常层级)会在 hdwallet.ts 的
parsePath中直接抛错; - 若要接入真实网络,一般应优先使用 Fuel 生态约定的默认路径,自定义路径适合需要"一套助记词多钱包"或兼容既有导入流程的场景。
Wallet.fromMnemonic完整签名:不止两个参数
虽然文档只演示了两个参数,但从源码看该 API 实际支持四个参数,wallets.ts 中的完整定义如下:
static fromMnemonic( mnemonic: string, path?: string, passphrase?: BytesLike, provider?: Provider ): WalletUnlocked { const seed = Mnemonic.mnemonicToSeed(mnemonic, passphrase); const hdWallet = HDWallet.fromSeed(seed); const childWallet = hdWallet.derivePath(path || WalletUnlocked.defaultPath); return new WalletUnlocked(<string>childWallet.privateKey, provider); }| 参数 | 类型 | 必填 | 作用 |
|---|---|---|---|
mnemonic | string | 是 | 由 12/15/18/21/24 个单词组成的助记词短语 |
path | string | 否 | BIP-32/44 派生路径,缺省为m/44'/1179993420'/0'/0/0 |
passphrase | BytesLike | 否 | BIP-39 附加口令(见下文"进阶"一节) |
provider | Provider | 否 | 燃料提供者实例,传入后钱包可立即执行链上操作 |
另外,类Wallet上的入口只是一个静态转发,见 wallet.ts:
static fromMnemonic = WalletUnlocked.fromMnemonic;也就是说,真正实现位于WalletUnlocked(Wallet是其便捷门面),你也可以绕过门面直接使用WalletUnlocked.fromMnemonic(...)。
底层原理:从助记词到私钥的三步调用链
fromMnemonic内部虽只有三行,却串起了packages/account中 BIP-39 与 BIP-32/44 两套完整实现。梳理调用链有助于你判断何时需要更底层的 API。
第 1 步:助记词 → BIP-39 种子(PBKDF2-SHA512)
Mnemonic.mnemonicToSeed(phrase, passphrase)的实现见 mnemonic.ts:
const phraseBytes = toUtf8Bytes(getPhrase(phrase)); const salt = toUtf8Bytes(`mnemonic${passphrase}`); return pbkdf2(phraseBytes, salt, 2048, 64, 'sha512');它严格遵循 BIP-39 规范:将单词短语 UTF-8 化,拼上盐"mnemonic" + passphrase,经PBKDF2(2048 轮、HMAC-SHA512)派生出 64 字节种子。调用前还会通过assertMnemonic校验单词数量是否落在MNEMONIC_SIZES中。
若想在不真正生成钱包的情况下预检助记词是否合法,可调用 mnemonic.ts 中的Mnemonic.isMnemonicValid(phrase)——它会逐词在 2048 词的英文词表中做二分查找校验(词表即english导入的 BIP-39 标准词表,见 mnemonic.ts)。
第 2 步:种子 → 主 HD 节点
HDWallet.fromSeed(seed)见 hdwallet.ts,其本质是对种子做一次以"Bitcoin seed"为 HMAC key 的 HMAC-SHA512:
static fromSeed(seed: string) { const masterKey = Mnemonic.masterKeysFromSeed(seed); return new HDWallet({ chainCode: arrayify(masterKey.slice(32)), privateKey: arrayify(masterKey.slice(0, 32)), }); }得到的 64 字节主密钥中,前 32 字节作为根私钥、后 32 字节作为链码(chain code),二者共同构成 HD 树的根节点。
第 3 步:沿派生路径逐级下钻
hdWallet.derivePath(path)(hdwallet.ts)先把路径按/拆成若干段并经parsePath处理硬化标记,然后逐级调用deriveIndex:
derivePath(path: string) { const paths = parsePath(path, this.depth); return paths.reduce((hdwallet, index) => hdwallet.deriveIndex(index), <HDWallet>this); }每一级子密钥都通过"父密钥 + 链码 + 索引"做 HMAC-SHA512(Key = 链码,Data = 0x00‖父私钥 或 父压缩公钥 + 4 字节索引)计算出子私钥与子链码,对应 BIP-32 的 CKD(Child Key Derivation)流程,细节见 hdwallet.ts。走到路径终点得到的子私钥,被封装进new WalletUnlocked(privateKey, provider),即返回给你的已解锁钱包。
进阶:口令、Provider 与兄弟 API
给助记词加一层口令(passphrase)
fromMnemonic的第三个参数passphrase是 BIP-39 的可选"第 25 个单词"。它不参与助记词本身的编码,而是混入 PBKDF2 的盐中,用于改变最终派生的种子。源码注释特别警示(见 mnemonic.ts):口令一旦遗忘,所有由该助记词派生的钱包都将永久丢失——备份时必须连同口令一同保存。
传入 Provider,一步到位可上链
默认创建的WalletUnlocked是离线实例。若你后续要转账、调用合约等链上操作,有两种选择:
- 创建后连接:
wallet.connect(provider); - 或在实例化时直接传入第四参数
provider(更推荐的"Create a Wallet Unlocked from a mnemonic"链路),使返回的钱包立即可用。
关于 Provider 连接的完整做法可参见 instantiating-wallets.md。
同族兄弟 API:种子 / 扩展密钥
理解了fromMnemonic的三步链路后,你会发现同文件中的另两个静态方法只是"入口不同、链路相同":
WalletUnlocked.fromSeed(seed, path?, provider?)(wallets.ts):跳过第 1 步,直接由现成的 64 字节种子走 HD 派生;WalletUnlocked.fromExtendedKey(extendedKey, provider?)(wallets.ts):从 BIP-32 扩展密钥(含 base58check 校验与主/测试网前缀识别)直接恢复钱包。
它们与助记词方式共享同一套HDWallet派生实现,适合"只拿到种子或 xprv、而非助记词"的导入场景。
工程质量:测试与钱包管理器中的实际使用
这套助记词能力并非孤立实现,而是被全仓库充分验证与复用的:
- 单元测试:助记词 BIP-39 相关行为有 mnemonic.test.ts,HD 派生有 hdwallet.test.ts,而
WalletUnlocked.fromMnemonic的实例化与签名、交易能力在 wallet-unlocked.test.ts 中覆盖; - 钱包管理器集成:在需要助记词管理多个钱包的
wallet-manager中,助记词被封装为一种 vault 类型(mnemonic-vault.ts),其测试 mnemonic-vault.test.ts 也验证了"一套助记词 + 派生路径树"在真实账户管理场景下的可用性。
若你的需求演化为"多账户、多钱包统一管理、加密持久化",可以进一步阅读 wallet-manager.md 了解在此基础上构建的管理器方案。
小结
本文基于官方指南 mnemonic-wallet.md 展开了从概念到源码的完整梳理,核心结论可归纳为:
- 助记词(BIP-39)是私钥的可读载体,Fuel SDK 支持 12~24 词;
- HD 钱包机制让你可以用一个助记词派生无数地址,Fuel 默认路径为
m/44'/1179993420'/0'/0/0(coin type1179993420的十六进制0x4655454C正是 ASCIIFUEL); Wallet.fromMnemonic(mnemonic)走默认路径,Wallet.fromMnemonic(mnemonic, path)走自定义路径,二者分别对应文档示例 from-mnemonic-phrases-1.ts 与 from-mnemonic-phrases-2.ts;- 方法实际还支持
passphrase与provider参数,其底层依次经历mnemonicToSeed(PBKDF2-SHA512)、HDWallet.fromSeed(HMAC-SHA512 主密钥)、derivePath(BIP-32 逐级下钻)三步。
对多数应用而言,直接使用默认路径即可安全、简单地落地;只有当你需要"一套助记词支撑多账户 / 多链路径对齐"时,才需要显式传入自定义派生路径。
【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考