在以太坊生态系统中,钱包(Wallet)是管理私钥与公钥对的核心工具,用于对交易进行加密签名,并证明用户对账户和资产的所有权。ethers.js 库提供了一个功能完备的 Wallet 类,它实现了 Signer API,适用于所有需要签名的场景。
本文将深入介绍 ethers.js 4.0 中 Wallet 与 Signer 的使用方法,涵盖创建实例、签名操作、区块链交互以及加密存储等关键功能。
创建钱包实例
ethers.js 支持多种方式创建钱包实例,满足不同场景的需求。
从私钥创建
使用私钥字符串直接创建钱包实例,并可选择连接至一个 Provider:
let privateKey = "0x0123456789012345678901234567890123456789012345678901234567890123";
let wallet = new ethers.Wallet(privateKey);
// 连接至主网 Provider
let provider = ethers.getDefaultProvider();
let walletWithProvider = new ethers.Wallet(privateKey, provider);创建随机钱包
使用 createRandom 方法生成一个全新的随机钱包。请务必妥善保管该钱包,一旦丢失将无法恢复。
let randomWallet = ethers.Wallet.createRandom();可选参数包括:
- extraEntropy:附加熵值,用于增强随机性
从助记词创建
基于 BIP-039 和 BIP-044 标准,从助记词生成钱包:
let mnemonic = "radar blur cabbage chef fix engine embark joy scheme fiction master release";
let wallet = ethers.Wallet.fromMnemonic(mnemonic);
// 使用自定义路径生成第二个账户
let path = "m/44'/60'/1'/0/0";
let secondWallet = ethers.Wallet.fromMnemonic(mnemonic, path);ethers.js 支持多种语言助记词词表,包括英文、意大利文、日文、韩文、简体中文和繁体中文。
从加密 JSON 文件导入
解密来自 Geth、Parity 或其他工具的加密 JSON 钱包文件:
let data = { ... }; // JSON 钱包数据
let json = JSON.stringify(data);
let password = "foo";
ethers.Wallet.fromEncryptedJson(json, password).then(function(wallet) {
console.log("地址: " + wallet.address);
});钱包属性与方法
每个钱包实例都包含以下关键属性和方法:
基本属性
- address:钱包的公开地址
- privateKey:钱包的私钥(必须保密)
- provider:连接的 Provider 实例,用于网络交互
- mnemonic:助记词(如果存在)
- path:助记词路径(如果存在)
连接至新 Provider
使用 connect 方法创建连接至新 Provider 的钱包实例:
let newWallet = wallet.connect(newProvider);签名操作
钱包的核心功能是对交易和消息进行签名。
交易签名
使用 sign 方法对交易进行签名:
let transaction = {
nonce: 0,
gasLimit: 21000,
gasPrice: utils.bigNumberify("20000000000"),
to: "0x88a5C2d9919e46F883EB62F7b8Dd9d0CC45bc290",
value: utils.parseEther("1.0"),
data: "0x",
chainId: ethers.utils.getNetwork('homestead').chainId
};
wallet.sign(transaction).then((signedTransaction) => {
console.log("已签名交易: " + signedTransaction);
});消息签名
可以对文本消息或二进制数据进行签名:
文本消息签名:
wallet.signMessage("Hello World!").then((signature) => {
console.log("签名结果: " + signature);
});二进制数据签名:
let hash = "0x3ea2f1d0abf3fc66cf29eebb70cbd4e7fe762ef8a09bcc06c8edf641230afec0";
let binaryData = ethers.utils.arrayify(hash);
wallet.signMessage(binaryData).then((signature) => {
console.log("签名结果: " + signature);
});区块链交互
连接 Provider 后,钱包可以进行各种区块链操作。
查询操作
// 查询余额
wallet.getBalance().then((balance) => {
console.log("余额: " + balance.toString());
});
// 查询交易计数
wallet.getTransactionCount().then((nonce) => {
console.log("交易次数: " + nonce);
});
// 估算gas费用
wallet.estimateGas(transaction).then((gasEstimate) => {
console.log("预估Gas: " + gasEstimate.toString());
});发送交易
使用 sendTransaction 方法发送交易,该方法会自动填充缺失的参数:
let tx = {
to: "0x88a5c2d9919e46f883eb62f7b8dd9d0cc45bc290",
value: ethers.utils.parseEther('1.0')
};
wallet.sendTransaction(tx).then((transaction) => {
console.log("交易已发送: " + transaction.hash);
});加密存储钱包
为了保护私钥安全,可以将钱包加密为 JSON 格式存储:
let password = "password123";
wallet.encrypt(password, function(progress) {
console.log("加密进度: " + parseInt(progress * 100) + "%");
}).then(function(json) {
console.log("加密后的JSON: " + json);
// 可安全存储此JSON字符串
});加密选项包括 salt、iv、uuid 和 scrypt 参数等,但通常不需要手动指定。
Signer API 简介
Signer API 是一个抽象类,为扩展和添加新签名器提供了基础框架。除了 Wallet 类外,JsonRpcSigner 和 Ledger 硬件钱包签名器等也都实现了此 API。
必须实现的属性和方法
- provider:连接的 Provider 实例
- getAddress():获取账户地址
- signMessage(message):对消息进行签名
- sendTransaction(transaction):发送交易
常见问题
什么是以太坊钱包?
以太坊钱包是管理私钥和公钥对的工具,用于对交易进行加密签名并证明账户所有权。它不直接存储资产,而是存储访问和控制资产的密钥。
如何安全地存储钱包?
对于随机生成的钱包,务必离线备份私钥或助记词。推荐使用加密JSON文件结合强密码的方式存储,并将密码与备份分开保管。
助记词和私钥有什么区别?
助记词是一组易于记忆的单词,可以通过标准算法派生出一系列私钥和地址。私钥是直接用于签名的256位数字。助记词更方便备份多个账户,而私钥则针对单个账户。
什么时候需要连接 Provider?
当需要进行区块链查询(如获取余额、nonce)或发送交易时,需要连接 Provider。对于纯签名操作,可以不连接 Provider。
如何选择助记词语言?
英文助记词得到最广泛支持,但 ethers.js 也支持多种语言。选择时考虑兼容性和易记性,简体中文助记词适合中文用户记忆。
加密JSON钱包有哪些优势?
加密JSON钱包提供了安全性与便携性的平衡。通过强密码加密,即使文件泄露,没有密码也无法访问资金。同时方便在不同设备间迁移钱包。
通过掌握 ethers.js 的 Wallet 和 Signer API,开发者可以构建安全可靠的以太坊应用,有效管理数字资产和执行区块链操作。