Skip to content

JSON-RPC

Overview

For an Application to communicate with the Ethereum network, it needs to establish a connection to an Ethereum Node, and be able to send and receive messages in a standardized format.

All Ethereum Nodes implement the JSON-RPC specification, which is a stateless & lightweight remote procedure call (RPC) protocol.

Ox provides type-safe primitives for working with the JSON-RPC specification.

Examples

Sending a Request

The example below demonstrates sending a strongly-typed JSON-RPC request to an Ethereum Node using an auto-incrementing JSON-RPC id store via RpcRequest.createStore.

import { RpcRequest } from 'ox'
 
// 1. Create a request store.
const store = RpcRequest.createStore()
 
// 2. Prepare a request.
const request = store.prepare({
  method: 'eth_getBlockByNumber',
  params: ['latest', false],
})
{ id: 0, jsonrpc: '2.0', method: 'eth_getBlockByNumber', params: ['latest', false] }
// 3. Send the request to an Ethereum Node. const response = await fetch('https://1.rpc.thirdweb.com', { body: JSON.stringify(request), method: 'POST', headers: { 'Content-Type': 'application/json', }, }).then((res) => res.json())

Parsing a Response

The example below demonstrates parsing a JSON-RPC response using the RpcResponse.parse function. This will extract the JSON-RPC result and and strongly type the response based on the request used.

import { RpcRequest, RpcResponse } from 'ox'
 
// 1. Create a request store.
const store = RpcRequest.createStore()
 
// 2. Prepare a request.
const request = store.prepare({
  method: 'eth_getBlockByNumber',
  params: ['latest', false],
})
 
// 3. Send the request to an Ethereum Node.
const response = await fetch('https://1.rpc.thirdweb.com', {
  body: JSON.stringify(request),
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
})
  .then((res) => res.json())
  // 4. Parse the response.
  .then((res) => RpcResponse.parse(res, { request }))
 
const response: { baseFeePerGas?: `0x${string}` | undefined; blobGasUsed?: `0x${string}` | undefined; difficulty?: `0x${string}` | undefined; excessBlobGas?: `0x${string}` | undefined; extraData?: Hex | undefined; ... 21 more ...; withdrawalsRoot?: Hex | undefined; } | null
response

Handling Requests

If you need to handle incoming JSON-RPC requests and return a respective response (for example, if you are building an JSON-RPC API handler or an EIP-1193 Provider request handler in a Wallet), you can utilize the RpcResponse.from function.

import { RpcRequest, RpcResponse, RpcSchema } from 'ox'
 
const accounts = ['0x...', '0x...'] as const
 
async function handleRequest(request: RpcRequest.RpcRequest<RpcSchema.Eth>) {
  if (request.method === 'eth_accounts')
    return RpcResponse.from({ result: accounts }, { request })
  if (request.method === 'eth_chainId')
    return RpcResponse.from({ result: '0x1' }, { request })
  if (request.method === 'eth_getBlock
eth_getBlockByHash
eth_getBlockByNumber
eth_getBlockTransactionCountByHash
eth_getBlockTransactionCountByNumber
')
return await fetch('https://1.rpc.thirdweb.com', { body: JSON.stringify(request), method: 'POST', headers: { 'Content-Type': 'application/json', }, }) .then((res) => res.json()) .then((res) => RpcResponse.from(res)) }

Related Modules

ModuleDescription
RpcRequestUtility types & functions for working with JSON-RPC 2.0 Requests and Ethereum JSON-RPC methods as defined on the Ethereum API specification
RpcResponseUtility types & functions for working with JSON-RPC 2.0 Responses
RpcSchemaUtility types for working with Ethereum JSON-RPC namespaces & schemas.
RpcTransportUtility functions for working with JSON-RPC Transports.