【Web3 后端】Node.js基础
本文介绍了使用Node.js进行区块链开发的核心知识点,包括异步编程、模块化系统、核心模块应用、包管理和Web框架。重点讲解了三个典型例题:1)使用async/await获取以太坊区块交易信息;2)构建Express API服务查询ETH余额和预估Gas;3)监听ERC20代币转账事件并记录日志。这些内容涵盖了Node.js在区块链开发中的关键应用场景,如API开发、异步任务处理和事件监听等,为开
·
使用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实现一个函数,按顺序获取以太坊区块信息:
- 先获取最新区块号
- 再根据区块号获取区块详情
- 最后提取区块中的交易数量
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);
三、核心知识点应用场景
- 异步处理:区块链交互(如查询余额、发送交易)都是异步操作,async/await能简化代码逻辑
- API服务:为前端DApp提供链下数据接口,处理合约交互、数据聚合等
- 事件监听:实时同步链上状态(如转账、NFT铸造)到数据库,支撑DApp业务逻辑
- 加密操作:使用
crypto
模块处理签名验证、生成随机数等安全相关功能
更多推荐
所有评论(0)