以太坊 JSON RPC 完全指南,从入门到实践
以太坊作为全球第二大区块链平台,其强大的功能和开放性吸引了无数开发者和企业,而与以太坊网络进行交互,最核心、最底层的方式之一便是通过其 JSON-RPC (JSON Remote Procedure Call) 协议,JSON-RPC 是一种无状态、轻量级的远程过程调用协议,使用 JSON 格式进行数据编码,使得任何编程语言都能方便地与以太坊节点通信,本教程将带你深入了解以太坊 JSON-RPC,从基本概念到实际应用,助你掌握这一关键技能。
什么是以太坊 JSON-RPC
以太坊 JSON-RPC 就是一套“指令集”和“通信规则”,你的应用程序(客户端)可以通过发送符合 JSON-RPC 规范的请求给以太坊节点(如 Geth, Parity, Infura 等),节点执行相应的操作(如查询账户余额、发送交易、获取区块信息等),然后将结果以 JSON 格式返回给你的客户端。
它就像以太坊节点的一个“API 接口”,让你能够以编程方式控制和使用以太坊网络的功能。
JSON-RPC 的基本工作原理
JSON-RPC 通信基于 HTTP 或 WebSocket 协议(通常默认 HTTP 端口为 8545,WebSocket 端口为 8546),其基本工作流程如下:
-
构建请求 (Request):客户端构建一个 JSON 对象,包含以下关键字段:
jsonrpc: 字符串,指定 JSON-RPC 版本,以太坊中通常为 "2.0"。method: 字符串,要调用的方法名(如eth_getBalance,eth_sendTransaction)。params: 数组,传递给方法的参数,顺序和类型需与方法定义匹配。id: 任意类型,请求的唯一标识符,用于客户端匹配响应。
示例请求(查询地址
0x123...的 ETH 余额):{ "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["0x1234567890123456789012345678901234567890", "latest"], "id": 1 } -
发送请求:客户端将此 JSON 对象通过 HTTP POST 或 WebSocket 发送到以太坊节点的 RPC 端口。
-
处理请求:以太坊节点接收到请求后,解析
method和params,执行相应的操作。 -
返回响应 (Response):节点将操作结果封装成 JSON 对象返回,包含:
jsonrpc: 字符串,与请求中一致,为 "2.0"。result: 根据方法返回的结果数据。error: 对象,如果执行出错则包含错误信息,否则为null。id: 与请求中的id一致,用于客户端识别是哪个请求的响应。
示例响应(假设余额为 1 ETH):
{ "jsonrpc": "2.0", "id": 1, "result": "0xde0b6b3a7640000" }(注意:余额通常以 Wei 为单位返回,1 ETH = 10^18 Wei)
如何使用以
太坊 JSON-RPC

启动一个支持 JSON-RPC 的以太坊节点
你需要一个以太坊节点来接收和响应你的 RPC 请求。
-
本地节点:
- Geth (Go-Ethereum):最常用的以太坊客户端之一。
# 启动 Geth 并开启 RPC 服务,允许本地连接 geth --http --http.addr "127.0.0.1" --http.port "8545" --http.api "eth,net,web3,personal"
--http: 启用 HTTP-RPC 服务器。--http.addr: 监听地址。--http.port: 监听端口。--http.api: 暴露的 API 方法列表,安全起见,不要暴露所有 (all)。
- Nethermind (C#): 另一个高性能的以太坊客户端。
配置类似,通常通过配置文件或命令行参数启动 RPC 服务。
- Geth (Go-Ethereum):最常用的以太坊客户端之一。
-
远程节点服务 (推荐用于开发测试):
- Infura: 提供可靠的以太坊节点服务,无需自己维护节点,注册后获取一个 RPC URL (如
https://mainnet.infura.io/v3/YOUR_PROJECT_ID)。 - Alchemy: 类似 Infura,提供高质量的节点服务和额外的开发者工具。
- 这些服务通常已经配置好,直接使用其提供的 RPC URL 即可。
- Infura: 提供可靠的以太坊节点服务,无需自己维护节点,注册后获取一个 RPC URL (如
常用的 JSON-RPC 方法
以太坊 JSON-RPC 提供了大量方法,这里列举一些最常用的:
-
网络与节点信息:
eth_blockNumber: 获取最新区块号。eth_chainId: 获取当前链 ID。net_version: 获取当前网络版本。web3_clientVersion: 获取客户端版本。
-
账户与余额:
eth_getBalance: 查询指定地址的 ETH 余额。eth_getTransactionCount: 查询指定地址的交易次数 (nonce)。
-
区块与交易:
eth_getBlockByNumber: 根据区块号或标签获取区块信息。eth_getBlockByHash: 根据区块哈希获取区块信息。eth_getTransactionByHash: 根据交易哈希获取交易详情。eth_getTransactionReceipt: 获取交易收据(包含交易执行状态、日志等)。
-
交易发送与签名:
eth_sendRawTransaction: 发送已签名的原始交易,这是最常用的发送交易方式,你需要先在客户端对交易进行签名(使用钱包或私钥)。eth_sign: 对数据进行签名(通常用于签名交易或消息)。personal_sign: 个人签名,用于签名消息,更安全。personal_sendTransaction: 通过 personal 模块发送交易,节点可能会提示输入密码或解锁账户。
-
合约交互:
eth_call: 执行一个常量调用(不会修改区块链状态),通常用于读取合约状态。eth_estimateGas: 估算交易执行所需的 Gas 数量。eth_getCode: 获取指定地址的合约代码。
-
事件日志:
eth_getLogs: 根据过滤条件获取日志事件,常用于监听合约事件。
编程示例 (使用 JavaScript + Node.js)
假设我们使用一个本地 Geth 节点 (RPC URL: http://127.0.0.1:8545)。
安装 axios 用于发送 HTTP 请求:
npm install axios
创建一个 eth_rpc_example.js 文件:
const axios = require('axios');
const RPC_URL = 'http://127.0.0.1:8545';
// 封装发送 JSON-RPC 请求的函数
async function sendRpcRequest(method, params = []) {
const requestData = {
jsonrpc: "2.0",
method: method,
params: params,
id: Date.now() // 简单使用时间戳作为 ID
};
try {
const response = await axios.post(RPC_URL, requestData);
return response.data.result;
} catch (error) {
console.error("RPC 请求错误:", error.response ? error.response.data : error.message);
throw error;
}
}
async function main() {
console.log("1. 获取最新区块号...");
const latestBlockNumber = await sendRpcRequest('eth_blockNumber');
console.log(`最新区块号: ${latestBlockNumber}`);
console.log("\n2. 查询示例地址的余额...");
const address = '0x1234567890123456789012345678901234567890'; // 替换为你要查询的地址
const balance = await sendRpcRequest('eth_getBalance', [address, 'latest']);
console.log(`地址 ${address} 的余额 (Wei): ${balance}`);
console.log(`地址 ${address} 的余额 (ETH): ${parseInt(balance, 16) / 1e18}`);
console.log("\n3. 获取最新区块信息...");
const blockInfo = await sendRpcRequest('eth_getBlockByNumber', ['latest', false]); // false 表示不包含交易详情
console.log