上链ON-CHAIN BLOCK 07 / 26
卷二 · 上手BLOCK 07

用 JSON-RPC 裸读链


ethers.js、viem、web3j——所有这些 SDK 底下都是同一件事:向节点发 JSON-RPC 请求。这一章我们把 SDK 拿开,直接用 curlfetch 跟链对话。当你亲手拼过一次请求,以后所有 SDK 对你都不再是黑盒,调试时也能一眼看穿"它到底发了什么"。

节点的对外接口就是一个 HTTP 端点

一个以太坊节点对外暴露一个 JSON-RPC 端点(一个 URL)。你 POST 一个 JSON 过去,它回一个 JSON。协议是标准的 JSON-RPC 2.0,长这样:

JSON-RPC 请求骨架
{
  "jsonrpc": "2.0",
  "method": "eth_blockNumber",   // 调哪个方法
  "params": [],                     // 参数数组
  "id": 1                          // 你自己编的请求编号,用于匹配响应
}
Android 类比

你可以完全把它当成一个只有一个 endpoint、用 method 字段区分动作的 REST 后端。eth_getBalanceGET /balance,eth_sendRawTransactionPOST /tx。ethers/viem 之于 JSON-RPC,正如 Retrofit 之于 OkHttp:给你类型安全的方法签名,底下还是在拼 HTTP 请求。理解了这层,SDK 就没有魔法了。

先拿一个 RPC 端点

你需要一个节点的 URL。三条路:公共 RPC(如 https://rpc.sepolia.org,免费但有限流)、节点服务商(Alchemy/Infura,注册拿带 key 的 URL)、或自建节点。下面例子用占位 $RPC 代表你的端点。

用 curl 读链

bash · 查最新区块高度
curl -s $RPC \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'

# 响应: {"jsonrpc":"2.0","id":1,"result":"0x14a2b3c"}
# result 是十六进制的区块号,0x14a2b3c = 21_636_412

注意返回值几乎都是十六进制字符串——包括余额、区块号、gas。这是新手第一个坑:"0x..." 要自己转十进制,而且金额单位是 wei(1 ETH = 10¹⁸ wei),别把 wei 当成 ETH 直接显示。

bash · 查某地址余额
curl -s $RPC -H "Content-Type: application/json" -d '{
  "jsonrpc":"2.0",
  "method":"eth_getBalance",
  "params":["0xYourAddress", "latest"],
  "id":1
}'
# result: "0x38d7ea4c68000" = 1000000000000000 wei = 0.001 ETH

最常用的一小把方法

方法作用类比
eth_blockNumber最新区块高度健康检查 / ping
eth_getBalance查地址 ETH 余额(wei)GET /balance
eth_getTransactionByHash按哈希查一笔交易GET /tx/{hash}
eth_getTransactionReceipt查交易回执(是否成功、日志、gas used)GET /tx/{hash}/receipt
eth_call只读调用合约(不上链、不花钱)只读查询
eth_estimateGas预估一笔交易要花多少 gas预检
eth_sendRawTransaction广播一笔已签名交易(唯一"写"操作)POST /tx
eth_getLogs按过滤条件查历史事件日志查询数据流

读与写的分水岭

这是理解链上交互的关键切分,请刻进脑子:

注意 eth_call 能"调用"合约函数却不花钱——因为它只是在节点本地模拟执行、拿返回值,不广播、不改状态。你查一个代币余额走的就是它。而真要转账,则必须发交易。SDK 会自动帮你分流:标了 view/pure 的合约函数走 call,会改状态的走 send。

JavaScript · fetch 版
async function rpc(method, params) {
  const res = await fetch(RPC_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ jsonrpc: '2.0', method, params, id: 1 })
  });
  const { result, error } = await res.json();
  if (error) throw new Error(error.message);
  return result;
}

const hex = await rpc('eth_blockNumber', []);
console.log(parseInt(hex, 16));   // 转成十进制区块号
风险记账

公共 RPC 会看到你查询的所有内容(你关心哪些地址、什么时候在线)。对隐私敏感或生产环境,用自己的付费端点或自建节点。另外别把带 API key 的 RPC URL 硬编码进前端打包文件——它会被扒出来盗用你的额度。前端该走后端代理或用专门的前端安全 key。

要点入账

整个以太坊对开发者的接口,归根结底就是这一个 JSON-RPC 端点。读操作用 call 类方法,即时免费;写操作把已签名交易通过 eth_sendRawTransaction 广播,花 gas 等确认。所有 SDK 都是这层之上的糖。下一章我们不再只读,而是自己写一个合约、部署上去,然后调用它——calldata 这个第 6 章 Etherscan 里见过的 Input Data 字段,终于要装东西了。

本章小结

◆ 返回目录