本实验报告详细记录了基于以太坊区块链的API接口编写过程,实验旨在通过使用Web3.js库与以太坊节点(如Infura或本地Geth节点)进行交互,实现账户信息查询、余额获取、交易发送以及智能合约调用等核心功能,通过本次实验,深入理解了以太坊JSON-RPC API的原理,掌握了使用JavaScript进行以太坊应用开发的基本方法,并体验了去中心化应用(DApp)后端接口的设计与实现。
以太坊;API接口;Web3.js;JSON-RPC;智能合约;DApp
实验目的
- 理解以太坊区块链及其JSON-RPC API的基本概念和工作原理。
- 掌握使用Web3.js库与以太坊节点进行通信的方法。
- 学习编写能够查询账户信息、获取代币余额、发送交易以及调用智能合约函数的API接口。
- 熟悉以太坊开发环境(如MetaMask、节点客户端)的配置与使用。
- 提升区块链应用后端接口设计与实现的能力。
实验环境与工具

- 操作系统: Windows 11 / macOS / Linux (Ubuntu 20.04 LTS)
- 编程语言: JavaScript (ES6+)
- 开发框架: Node.js (v14.x 或更高版本)
- 核心库: Web3.js (v1.x 或更高版本)
- 以太坊节点:
- 远程节点服务:Infura (https://infura.io/)
- 本地节点客户端(可选):Geth 或 Parity
- 浏览器插件钱包: MetaMask (用于测试账户管理和交易签名)
- 代码编辑器: Visual Studio Code
- 其他工具: npm (Node包管理器), Git
实验原理
以太坊作为一个开放的区块链平台,提供了JSON-RPC API作为与区块链网络进行交互的标准接口,应用程序通过向以太坊节点发送JSON-RPC请求(通常通过HTTP或WebSocket协议),可以查询区块链状态(如账户余额、区块信息、交易详情)或发起状态改变的操作(如发送交易、调用智能合约)。
Web3.js是一个JavaScript库,它封装了以太坊JSON-RPC API的复杂性,提供了简洁易用的JavaScript接口,使得开发者可以在前端浏览器或Node.js后端应用中与以太坊网络进行交互,其核心功能包括:
- 连接到以太坊节点(Provider)。
- 账户管理(获取账户、签名交易等)。
- 读取区块链数据(区块、交易、日志、智能合约状态)。
- 发送交易(转账、部署合约、调用合约函数)。
- 事件监听。
实验步骤与过程
环境搭建与项目初始化

- 安装Node.js和npm:从Node.js官网下载并安装适合操作系统的Node.js版本。
- 安装MetaMask:在浏览器(如Chrome, Firefox)中安装MetaMask扩展,并创建/导入测试账户。
- 创建项目目录:在终端中创建一个新的项目文件夹,例如
ethereum-api-experiment。 - 初始化npm项目:进入项目目录,运行
npm init -y,生成package.json文件。 - 安装Web3.js:运行
npm install web3安装Web3.js库。
连接以太坊节点
在项目中创建一个JavaScript文件(如app.js),首先引入Web3.js库,并创建一个Web3实例,连接到以太坊节点可以通过Infura提供的节点URL,或本地运行的节点。
const Web3 = require('web3');
// 使用Infura节点URL (需要替换为你的Infura项目ID)
const INFURA_URL = 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID';
// 或者连接到本地Geth节点 (默认端口8545)
// const LOCAL_NODE_URL = 'http://localhost:8545';
// 创建Web3实例
const web3 = new Web3(INFURA_URL); // 或 new Web3(LOCAL_NODE_URL);
// 测试连接
web3.eth.getBlockNumber()
.then(console.log)
.catch(err => console.error('连接失败:', err));
运行node app.js,若成功输出当前区块号,则表示连接成功。
API接口编写示例
以下为几个核心API接口的编写示例:

1 查询账户余额
编写一个函数,根据以太坊地址查询其ETH余额。
// 查询账户ETH余额
async function getBalance(address) {
try {
const balance = await web3.eth.getBalance(address);
// 将余额从Wei转换为ETH
const balanceInETH = web3.utils.fromWei(balance, 'ether');
console.log(`地址 ${address} 的余额: ${balanceInETH} ETH`);
return balanceInETH;
} catch (error) {
console.error('查询余额失败:', error);
return null;
}
}
// 示例:查询MetaMask中第一个账户的余额
// (注意:实际API中,地址通常来自请求参数)
// metaMaskAccounts[0] 可以通过 MetaMask API 获取,但后端API通常接收前端传来的地址
// const accounts = await web3.eth.getAccounts(); // 如果节点开启了账户管理
// if (accounts.length > 0) {
// getBalance(accounts[0]);
// }
2 发送ETH交易
编写一个函数,用于发送ETH交易,这需要发送者的私钥(在实际应用中需妥善保管,通常使用钱包软件签名交易,后端只负责广播或提供签名服务)。
// 发送ETH交易
async function sendTransaction(privateKey, fromAddress, toAddress, amountInETH) {
try {
// 将ETH转换为Wei
const amountInWei = web3.utils.toWei(amountInETH.toString(), 'ether');
// 获取当前nonce
const nonce = await web3.eth.getTransactionCount(fromAddress, 'latest');
// 构建交易对象
const transaction = {
to: toAddress,
value: amountInWei,
gas: 21000, // 转账ETH的固定gas限制
gasPrice: await web3.eth.getGasPrice(), // 获取当前gas价格
nonce: nonce,
chainId: 1 // 主网chainId,测试网为3 (Ropsten), 4 (Rinkeby)等
};
// 签名交易
const signedTx = await web3.eth.accounts.signTransaction(transaction, privateKey);
// 发送交易
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
console.log('交易成功! 交易哈希:', receipt.transactionHash);
return receipt.transactionHash;
} catch (error) {
console.error('发送交易失败:', error);
return null;
}
}
// 示例 (注意:私钥极度敏感,切勿硬编码在实际生产环境中!)
// const senderPrivateKey = 'YOUR_PRIVATE_KEY';
// const senderAddress = '0xSenderAddress';
// const receiverAddress = '0xReceiverAddress';
// const amountToSend = 0.01;
// sendTransaction(senderPrivateKey, senderAddress, receiverAddress, amountToSend);
3 智能合约交互
假设我们有一个已部署的简单智能合约(例如一个ERC20代币合约),我们需要编写接口来调用其读/写函数。
- 获取合约ABI和地址: 智能合约的ABI(Application Binary Interface)是合约与交互的接口描述,地址是合约部署在区块链上的位置,这些通常可以从以太坊浏览器(如Etherscan)或合约部署文档中获取。
- 创建合约实例:
// 假设的ERC20代币合约ABI (简化版,实际需完整ABI)
const tokenABI = [
{
"constant": true,
"inputs": [{"name": "_owner", "type": "address"}],
"name": "balanceOf",
"outputs": [{"name": "balance", "type": "uint256"}],
"type": "function"
},
{
"constant": false,
"inputs": [
{"name": "_to", "type": "address"},
{"name": "_value", "type": "uint256"}
],
"name": "transfer",
"outputs": [{"name": "success", "type": "bool"}],
"type": "function"
}
// 其他函数...
];
// 代币合约地址 (示例,需替换为实际地址)
const tokenAddress = '0xYourTokenContractAddress';
// 创建合约实例
const tokenContract = new web3.eth.Contract(tokenABI, tokenAddress);
- 调用合约读函数(不修改状态,无需gas):
// 查询代
