/ 币圈行情

创建以太坊钱包代码,从零开始掌握核心技术与实践

发布时间:2025-12-05 03:48:30

区块链世界中,以太坊钱包是用户与以太坊网络交互的核心工具,它不仅存储以太币(ETH),还管理各种代币和智能合约的访问权限,从技术角度看,创建以太坊钱包的核心是生成符合以太坊标准的账户对(公钥 私钥),并实现与以太坊节点的通信,本文将带你从零开始,通过代码实践深入理解以太坊钱包的创建原理与实现过程。

以太坊钱包的核心概念

在动手写代码前,我们需要先明确几个关键概念:

账户结构

以太坊账户分为外部账户(Externally Owned Account, EOA)合约账户,我们通常说的“钱包”指的是外部账户,由以下两部分组成:

  • 私钥(Private Key):32字节的随机数,相当于账户的“密码”,必须严格保密,私钥可以推导出公钥,进而生成地址,一旦丢失,账户中的资产将无法找回。
  • 公钥(Public Key):64字节,通过椭圆曲线算法(secp256k1)由私钥生成,公钥用于生成地址,但不会暴露私钥。
  • 地址(Address):20字节,由公钥通过哈希算法(Keccak-256)计算得出,相当于账户的“身份证”,可以公开分享用于接收资产。

助记词(Mnemonic)

为了方便用户备份私钥,以太坊遵循BIP39标准,将私钥转换为12或24个英文单词(如“witch collapse practice feed shame open despair creek road again ice least”),助记词可以还原出私钥,从而恢复整个钱包,是行业通用的备份方式。

钱包文件(Keystore)

为了保护私钥安全,钱包通常会将私钥加密后存储为JSON文件(如UTC文件),加密时需要用户设置密码,这种方式避免了明文存储私钥,但密码一旦丢失,文件也无法解密。

开发环境准备

在编写代码前,我们需要准备以下工具:

开发语言与库

本文使用JavaScript(Node.js)作为开发语言,借助ethers.js库(以太坊最流行的工具库之一)实现钱包创建功能,ethers.js提供了简洁的API,支持私钥、助记词、钱包文件的生成与解析,同时兼容以太坊节点交互。

安装ethers.js:

npm install ethers

Node.js环境

确保已安装Node.js(建议版本≥16.0),可通过以下命令检查:

node -v
npm -v

创建以太坊钱包的代码实现

我们将通过三种常见方式创建钱包:直接生成私钥、通过助记词生成、从Keystore文件导入。

方式一:直接生成私钥并创建钱包

这是最基础的方式,通过随机生成私钥,直接创建对应的钱包对象。

const { ethers } = require("ethers");
// 1. 生成随机私钥(32字节随机数,以0x开头)
const privateKey = ethers.Wallet.createRandom().privateKey;
console.log("私钥:", privateKey);
// 2. 通过私钥创建钱包对象
const wallet = new ethers.Wallet(privateKey);
// 3. 获取钱包信息
console.log("公钥:", wallet.publicKey);
console.log("地址:", wallet.address);
console.log("助记词:", wallet.mnemonic?.phrase); // 随机生成的钱包会自动关联助记词

代码解析

  • ethers.Wallet.createRandom():生成一个随机钱包,内部会生成私钥、公钥、地址和助记词。
  • new ethers.Wallet(privateKey):通过已有私钥创建钱包对象,无需额外计算。

方式二:通过助记词恢复钱包

助记词是钱包备份的核心,用户可以通过助记词恢复任意已创建的钱包。

const { ethers } = require("ethers");
// 1. 定义助记词(假设用户已有助记词)
const mnemonic = "witch collapse practice feed shame open despair creek road again ice least";
// 2. 通过助记词创建钱包
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
// 3. 获取钱包信息
console.log("助记词:", mnemonic);
console.log("私钥:", wallet.privateKey);
console.log("地址:", wallet.address);
// 4. 支持从指定路径派生地址(遵循BIP44标准,路径:m/44'/60'/0'/0/0)
const walletFromPath = ethers.Wallet.fromMnemonic(mnemonic, "m/44'/60'/0'/0/0");
console.log("派生地址:", walletFromPath.address);

代码解析

  • ethers.Wallet.fromMnemonic(mnemonic):通过助记词创建默认路径的钱包(路径:m/44'/60'/0'/0/0)。
  • 支持自定义派生路径(如多账户管理),BIP44标准中,以太坊的币种类型为60',账户索引从0开始。

方式三:从Keystore文件导入钱包

Keystore文件是加密后的私钥存储方式,用户需要输入密码才能解密并导入钱包。

(1)生成Keystore文件

const { ethers } = require("ethers");
// 1. 创建一个随机钱包(作为待加密的钱包)
const wallet = ethers.Wallet.createRandom();
const password = "MySecurePassword123!"; // 加密密码
// 2. 导出为Keystore文件(JSON格式)
const keystoreJson = wallet.encryptSync(password);
console.log("Keystore文件:", JSON.stringify(keystoreJson, null, 2));

(2)从Keystore文件导入钱包

const { ethers } = require("ethers");
// 1. 假设已有Keystore文件和密码
const keystoreJson = {
  "address": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060",
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "version": 3,
  "Crypto": {
    "cipher": "aes-128-ctr",
    "ciphertext": "0x123...def",
    "cipherparams": { "iv": "0x456...abc" },
    "kdf": "scrypt",
    "kdfparams": {
      "dklen": 32,
      "n": 262144,
      "r": 8,
      "p": 1,
      "salt": "0x789...xyz"
    },
    "mac": "0xabc...def"
  }
};
const password = "MySecurePassword123!";
// 2. 从Keystore文件导入钱包
const importedWallet = await ethers.Wallet.fromEncryptedJson(keystoreJson, password);
console.log("导入的地址:", importedWallet.address);
console.log("导入的私钥:", importedWallet.privateKey);

代码解析

  • wallet.encryptSync(password):同步生成Keystore文件,包含加密后的私钥和元数据。
  • ethers.Wallet.fromEncryptedJson(keystoreJson, password):异步解密Keystore文件,返回钱包对象(需提供正确密码)。

钱包的进阶功能:签名与交易

创建钱包后,核心功能是发送交易(如转账ETH或调用智能合约),下面以发送ETH为例,展示钱包的签名与交易过程。

连接以太坊节点

发送交易需要连接到以太坊节点,可以使用Infura(公共节点服务)或本地节点(如Geth)。

const { ethers } = require("ethers");
// 1. 创建钱包(假设已有)
const privateKey = "0x你的私钥";
const wallet = new ethers.Wallet(privateKey);
// 2. 连接以太坊节点(以Infura为例)
const provider = new ethers.providers.InfuraProvider("goerli", "你的Infura项目ID"); // goerli是测试网
const connectedWallet = wallet.connect(provider);
console.log("钱包地址:", connectedWallet.address);
console.log("当前ETH余额:", await connectedWallet.getBalance());

发送ETH交易

const { ethers } = require("ethers");
// 1. 钱包与节点连接(同上)
const privateKey = "0x你的私钥";
const provider = new ethers.providers.InfuraProvider("goerli", "你的Infura项目ID");
const wallet = new ethers.Wallet(privateKey).connect(provider);
// 2. 定义交易参数
const recipientAddress = "0x接收方地址";
const amount = ethers.utils.parseEther("0

免责声明:本文为转载,非本网原创内容,不代表本网观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。

如有疑问请发送邮件至:bangqikeconnect@gmail.com