Ethereum-compatible nodes expose a JSON-RPC API over HTTP or WebSocket. Every call sends `{ jsonrpc: "2.0", id, method, params }` and gets back `{ jsonrpc: "2.0", id, result }` or an `error` object.
js
async function rpcCall(url, method, params = []) {
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
});
const json = await res.json();
if (json.error) throw new Error(json.error.message);
return json.result;
}
const blockHex = await rpcCall(process.env.RPC_URL, "eth_blockNumber");
console.log(parseInt(blockHex, 16));Libraries like ethers.js and viem wrap this pattern with typed helpers, retries, batching and ABI encoding/decoding — but understanding the raw JSON-RPC exchange helps you debug when those libraries surface a confusing error.