以太坊 JSON RPC 完全指南,从入门到实践

时间: 2026-03-06 17:36 阅读数: 1人阅读

以太坊作为全球第二大区块链平台,其强大的功能和开放性吸引了无数开发者和企业,而与以太坊网络进行交互,最核心、最底层的方式之一便是通过其 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),其基本工作流程如下:

  1. 构建请求 (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
    }
  2. 发送请求:客户端将此 JSON 对象通过 HTTP POST 或 WebSocket 发送到以太坊节点的 RPC 端口。

  3. 处理请求:以太坊节点接收到请求后,解析 methodparams,执行相应的操作。

  4. 返回响应 (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 服务。

  • 远程节点服务 (推荐用于开发测试)

    • Infura: 提供可靠的以太坊节点服务,无需自己维护节点,注册后获取一个 RPC URL (如 https://mainnet.infura.io/v3/YOUR_PROJECT_ID)。
    • Alchemy: 类似 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