以太坊,作为全球领先的智能合约平台,其强大的功能离不开开发者与节点之间的顺畅交互,而以太坊JSON-RPC API(通常简称为“RPC命令”)正是实现这种交互的核心桥梁,它允许应用程序通过发送标准的JSON格式请求,与以太坊节点进行通信,从而读取链上数据、发送交易、调用智能合约等,本文将详细介绍以太坊RPC命令的使用方法,帮助开发者掌握这一 essential 工具。

什么是以太坊RPC?

以太坊RPC(Remote Procedure Call,远程过程调用)是一种基于HTTP或WebSocket的通信协议,它定义了一套标准化的JSON接口,以太坊节点(如Geth、Nethermind、OpenEthereum等)通过暴露这些RPC接口,使得外部程序(如Web应用、Python脚本、Java应用等)能够远程调用节点提供的各种功能。

RPC就像是以太坊节点的“遥控器”,通过发送特定的“指令”(JSON请求),你就可以控制节点执行操作,并获取返回结果。

如何连接到以太坊节点的RPC接口?

在使用RPC命令之前,首先需要确保你的应用能够连接到一个以太坊节点的RPC接口,这通常涉及以下步骤:

  1. 运行一个以太坊节点

    • 全节点:例如使用Geth (geth --http) 或 Nethermind 运行一个完整同步的节点,这需要大量的存储空间和时间,但提供最高的数据完整性和自主性。
    • 归档节点:在全节点基础上,进一步同步历史状态数据,可以查询任何历史区块的状态。
    • 第三方服务节点:例如Infura、Alchemy等,它们提供公共的或私有的RPC端点,无需自己运行节点,方便快捷,适合开发和测试。
  2. 启用RPC服务

    • 如果你使用Geth,启动时需要添加 --http--ws 参数来启用HTTP或WebSocket RPC服务。
    • geth --http --http.addr "0.0.0.0" --http.port "8545" --http.api "eth,net,web3,personal"
      • --http.addr:监听地址,"0.0.0.0"表示允许任何IP连接。
      • --http.port:RPC服务端口。
      • --http.api:暴露的API模块,如eth(以太坊核心)、net(网络)、web3(Web3.js工具)、personal(账户管理)等,出于安全考虑,不要暴露不必要的API。
  3. 获取RPC端点URL

    • 对于本地节点,通常是 http://localhost:8545ws://localhost:8545
    • 对于第三方服务,注册后会在控制台提供相应的RPC URL(通常包含API Key)。

常用以太坊RPC命令详解

以太坊RPC命令非常丰富,以下是一些最常用和核心的命令,按功能分类:

网络与节点信息相关

  • web3_clientVersion: 获取客户端版本信息。
    • 请求: {"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}
    • 响应: {"jsonrpc":"2.0","id":1,"result":"Geth/v1.10.23-stable/linux-amd64/go1.17.3"}
  • net_version: 获取当前网络的链ID(Chain ID)。
    • 请求: {"jsonrpc":"2.0","method":"net_version","params":[],"id":1}
    • 响应: {"jsonrpc":"2.0","id":1,"result":"1"} (1代表主网)
  • net_peerCount: 获取连接到的对等节点数量。
    • 请求: {"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}
    • 响应: {"jsonrpc":"2.0","id":1,"result":"0x2"} (十六进制)

区块与交易信息相关

  • eth_blockNumber: 获取最新区块号。
    • 请求: {"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}
    • 响应: {"jsonrpc":"2.0","id":1,"result":"0x123456"}
  • eth_getBlockByNumber: 根据区块号或区块标签获取区块详细信息。
    • 参数: ["latest", false] (第二个参数表示是否包含完整交易详情)
    • 请求: {"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",false],"id":1}
    • 响应: 包含区块哈希、父哈希、时间戳、交易列表等信息的JSON对象。
  • eth_getTransactionByHash: 根据交易哈希获取交易详情。
    • 参数: ["0x交易哈希"]
    • 请求: {"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0x..."],"id":1}
    • 响应: 包含发送方、接收方、金额、gas限制、gas价格、输入数据等信息的JSON对象。
  • eth_getTransactionReceipt: 获取交易收据(交易执行后的状态,如是否成功,消耗的gas,日志等)。
    • 参数: ["0x交易哈希"]
    • 请求: {"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x..."],"id":1}
    • 响应: 包含交易状态(status)、累计消耗gas(cumulativeGasUsed)、日志(logs)等。

账户与余额查询

  • eth_getBalance: 查询指定地址的ETH余额。
    • 参数: ["0x地址", "latest"] (第二个参数是区块号或标签,"latest"表示最新区块)
    • 请求: {"jsonrpc":"2.0","method":"eth_getBalance","params":["0x742d35Cc6634C0532925a3b844Bc9e7595f8e5a8","latest"],"id":1}
    • 响应: {"jsonrpc":"2.0","id":1,"result":"0x123456789abc"} (十六进制,单位是wei)

智能合约交互

  • eth_call: 执行对智能合约的静态调用(不修改链上状态)。
    • 参数: [交易对象, "latest"]
      • 交易对象包含 from (调用者地址), to (合约地址), data (函数选择器和参数编码)。
    • 示例(调用合约的balanceOf函数):
      {
        "jsonrpc": "2.0",
        "method": "eth_call",
        "params": [
          {
            "from": "0x调用者地址",
            "to": "0x合约地址",
            "data": "0x70a08231000000000000000000000000调用者地址" // balanceOf(address)的函数选择器 参数编码
          },
          "latest"
        ],
        "id": 1
      }
    • 响应: 返回函数调用的结果(通常是十六进制编码)。
  • eth_sendRawTransaction: 发送原始交易(通常由钱包或应用签名后发送,用于修改链上状态,如调用合约写入函数、转账等)。
    • 参数: ["0x原始交易签名数据"]
    • 请求: {"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["0x..."],"id":1}
    • 响应: {"jsonrpc":"2.0","id":1,"result":"0x交易哈希"}

Gas与费用相关

  • eth_gasPrice: 获取当前推荐的gas价格。
    • 请求: {"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}
    • 响应: {"jsonrpc":"2.0","id":1,"result":"0x9184e72a000"} (十六进制,单位是wei)
  • eth_estimateGas: 估算执行特定交易所需的gas数量。
    • 参数: [交易对象] (与eth_call中的交易对象类似,但通常包含value和可能的data)
    • 请求: `{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{"from":"0x发送方地址","to":"0x接收方地址","value":"0x123456789","data":"0