使用Node.js可以高效地实现与区块链的交互、开发API服务和处理异步任务。以下是需要掌握的Node.js核心基础及例题例:

一、核心基础知识点

1. 异步编程模型

Node.js的非阻塞I/O模型是处理区块链高频交互的关键,需掌握:

  • 回调函数(Callback)与回调地狱问题
  • Promise与异步函数(async/await)
  • 事件循环(Event Loop)机制
2. 模块化系统
  • CommonJS模块(require/module.exports
  • ES6模块(import/export)在Node.js中的使用
  • 模块加载机制与循环依赖处理
3. 核心模块应用
  • http/https:构建API服务,与区块链节点通信
  • fs:处理智能合约ABI文件、配置文件读写
  • stream:处理大型区块链数据(如区块同步)
  • crypto:实现签名验证、哈希计算等加密操作
4. 包管理与工程化
  • npm/yarn/pnpm的使用(安装、发布、版本管理)
  • package.json配置(依赖、脚本、入口)
  • 环境变量管理(dotenv
5. 常用Web框架
  • Express/Koa:快速构建DApp后端API
  • 中间件机制:处理请求验证、日志、错误捕获

二、例题与实现

1. 异步编程例题

题目:使用async/await实现一个函数,按顺序获取以太坊区块信息:

  1. 先获取最新区块号
  2. 再根据区块号获取区块详情
  3. 最后提取区块中的交易数量
const { ethers } = require("ethers");

// 连接以太坊测试网
const provider = new ethers.providers.JsonRpcProvider(
  "https://eth-sepolia.g.alchemyapi.io/v2/你的API密钥"
);

/**
 * 获取区块交易数量
 * @returns {number} 交易数量
 */
async function getBlockTransactionCount() {
  try {
    // 1. 获取最新区块号
    const latestBlockNumber = await provider.getBlockNumber();
    console.log("最新区块号:", latestBlockNumber);

    // 2. 获取区块详情
    const block = await provider.getBlock(latestBlockNumber);
    if (!block) throw new Error("未找到区块");

    // 3. 返回交易数量
    return block.transactions.length;
  } catch (error) {
    console.error("获取区块信息失败:", error.message);
    throw error;
  }
}

// 执行函数
getBlockTransactionCount()
  .then(count => console.log("区块交易数量:", count))
  .catch(() => process.exit(1));
2. API服务例题

题目:使用Express构建一个DApp后端API,提供:

  • GET /api/balance/:address:查询指定地址的ETH余额
  • POST /api/transaction:接收交易参数并返回预估Gas
require("dotenv").config();
const express = require("express");
const { ethers } = require("ethers");
const app = express();

// 中间件
app.use(express.json()); // 解析JSON请求体

// 连接以太坊节点
const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL);

/**
 * 查询ETH余额接口
 */
app.get("/api/balance/:address", async (req, res) => {
  try {
    const { address } = req.params;
    
    // 验证地址格式
    if (!ethers.utils.isAddress(address)) {
      return res.status(400).json({ error: "无效的以太坊地址" });
    }

    // 获取余额(wei转换为ETH)
    const balance = await provider.getBalance(address);
    const balanceETH = ethers.utils.formatEther(balance);

    res.json({
      address,
      balance: `${balanceETH} ETH`,
      timestamp: new Date().toISOString()
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

/**
 * 预估Gas接口
 */
app.post("/api/transaction", async (req, res) => {
  try {
    const { from, to, value } = req.body;
    
    // 验证参数
    if (!from || !to || !value) {
      return res.status(400).json({ error: "缺少必要参数" });
    }

    // 构建交易
    const tx = {
      from,
      to,
      value: ethers.utils.parseEther(value) // 转换为wei
    };

    // 预估Gas
    const gasEstimate = await provider.estimateGas(tx);
    const gasPrice = await provider.getGasPrice();

    res.json({
      gasEstimate: gasEstimate.toString(),
      gasPrice: ethers.utils.formatUnits(gasPrice, "gwei") + " gwei",
      estimatedTotal: ethers.utils.formatEther(gasEstimate.mul(gasPrice)) + " ETH"
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// 启动服务
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`DApp后端API运行在 http://localhost:${PORT}`);
});
3. 事件监听例题

题目:监听ERC20代币的Transfer事件,将转账记录保存到日志文件

const { ethers } = require("ethers");
const fs = require("fs").promises;
const path = require("path");

// 配置
const RPC_URL = "https://eth-sepolia.g.alchemyapi.io/v2/你的API密钥";
const ERC20_ABI = [
  "event Transfer(address indexed from, address indexed to, uint256 value)"
];
const CONTRACT_ADDRESS = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C723"; // USDC测试网地址
const LOG_FILE = path.join(__dirname, "transfers.log");

// 初始化
const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
const contract = new ethers.Contract(CONTRACT_ADDRESS, ERC20_ABI, provider);

/**
 * 记录转账日志到文件
 */
async function logTransfer(event) {
  const { from, to, value, transactionHash } = event;
  const logEntry = `[${new Date().toISOString()}] Transfer:
    TxHash: ${transactionHash}
    From: ${from}
    To: ${to}
    Value: ${ethers.utils.formatUnits(value, 6)} USDC
    ------------------------\n`;

  await fs.appendFile(LOG_FILE, logEntry);
  console.log("已记录转账事件:", transactionHash);
}

// 监听事件
async function startListening() {
  console.log("开始监听ERC20转账事件...");
  
  // 监听新的Transfer事件
  contract.on("Transfer", async (from, to, value, event) => {
    await logTransfer({ from, to, value, transactionHash: event.transactionHash });
  });

  // 监听历史事件(最近100个区块)
  const latestBlock = await provider.getBlockNumber();
  const filter = contract.filters.Transfer();
  const events = await contract.queryFilter(filter, latestBlock - 100, latestBlock);
  
  for (const event of events) {
    await logTransfer({
      from: event.args.from,
      to: event.args.to,
      value: event.args.value,
      transactionHash: event.transactionHash
    });
  }
}

startListening().catch(console.error);

三、核心知识点应用场景

  1. 异步处理:区块链交互(如查询余额、发送交易)都是异步操作,async/await能简化代码逻辑
  2. API服务:为前端DApp提供链下数据接口,处理合约交互、数据聚合等
  3. 事件监听:实时同步链上状态(如转账、NFT铸造)到数据库,支撑DApp业务逻辑
  4. 加密操作:使用crypto模块处理签名验证、生成随机数等安全相关功能
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐