Lessons 1/4 · 15 min
Asking a node: JSON-RPC request and response
How does a wallet know your balance?
It reads no disk: it sends a question to a node, which answers. JSON-RPC is a very simple protocol for that: "RPC" means remote procedure call (calling a function that runs elsewhere), and the messages are JSON. The version described here is 2.0 (the "JSON-RPC 2.0 specification"). Several families of nodes speak it: Ethereum-style nodes, those built on Substrate, and Bitcoin Core also offers a JSON-RPC interface with its own methods. Method names differ from one ecosystem to another.
In this workshop, the practice node uses made-up names: chain_blockNumber, chain_getBalance, chain_getBlockByNumber. Remember the shape, not the names. Another difference from Ethereum: here quantities (such as a block height) are JSON numbers, whereas Ethereum-style nodes write them as hexadecimal strings.
A request has four fields
{"jsonrpc":"2.0","method":"chain_getBalance","params":["0xAAAA…","latest"],"id":7}jsonrpc: always the string"2.0".method: the name of the procedure.params: the arguments, either a list (by position, as above) or an object (by name). Optional when there is nothing to pass.id: an identifier you choose (number or string). The server copies it into its reply, so you can match each answer to its question when several are in flight.
It is sent in the body of an HTTP POST with the header Content-Type: application/json, to the endpoint's address (<endpoint> below), for example with curl:
curl -s -X POST <endpoint> -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"chain_blockNumber","params":[],"id":7}'A response has a result OR an error
{"jsonrpc":"2.0","result":"0x1f4","id":7}
{"jsonrpc":"2.0","error":{"code":-32601,"message":"Method not found"},"id":7}A response holds result or error, never both. Here "0x1f4" is a hexadecimal number: 1×256 + 15×16 + 4 = 500. Ethereum-style nodes return most numbers this way, as a hexadecimal string; other ecosystems return JSON numbers. Read your node's documentation and convert explicitly: never add two hexadecimal strings.
A big value (a balance in the smallest unit) often exceeds what a JavaScript number can represent exactly; keep it as a string or a bigint until display. You will see this again in the TypeScript workshop.
Notifications and batches
- A request without an
idis a notification: the server answers nothing. Useful to inform, useless to ask. - A batch is an array of requests sent at once; the response is an array, in an order that is not guaranteed: you match by
id. Handy to save round trips on a slow connection, but some providers cap the batch size.
What this does NOT guarantee
- JSON-RPC says nothing about the authenticity of the answer: a node can be wrong, late or lying. Nothing here proves that the announced balance is the chain's.
- The specification says nothing about HTTP: some servers answer "200" even for a JSON-RPC error. Do not trust the HTTP status alone; look at the body.
- A
chain_getBalancemethod exists on no real node under that name; go read your own node's method list.
Recap: four fields in, result OR error out, id to match.
