Exth.Rpc.Client (Exth v0.3.0)

View Source

Core client module for making JSON-RPC requests to EVM nodes.

This module provides the main client interface for interacting with EVM nodes, handling request creation, response parsing, and client lifecycle management.

Features

  • Atomic request ID generation
  • Transport abstraction
  • Request/response lifecycle management
  • Batch request support
  • Error handling

Usage

# Create a new client
client = Client.new(:http,
  rpc_url: "https://eth-mainnet.example.com",
  timeout: 30_000
)

# Create a request
request = Client.request(client, "eth_blockNumber", [])

# Send the request
{:ok, response} = Client.send(client, request)

# Send batch requests
{:ok, responses} = Client.send(client, [request1, request2])

Client Configuration

The client accepts the following options:

  • :rpc_url - (Required) The endpoint URL
  • :transport_type - Transport to use (:http or :custom)
  • :timeout - Request timeout in milliseconds
  • :headers - Additional HTTP headers (HTTP only)

Request ID Generation

The client uses Erlang's :atomics for thread-safe, monotonic request ID generation. This ensures:

  • Unique IDs across concurrent requests
  • No ID collisions in batch requests
  • Efficient ID allocation
  • Process-independent ID tracking

Transport Layer

The client supports different transport mechanisms through the Exth.Transport.Transportable protocol:

  • Built-in HTTP transport using Tesla/Mint
  • Custom transport implementations
  • Future support for WebSocket and IPC

Error Handling

The client provides consistent error handling:

  • {:ok, response} - Successful request
  • {:error, reason} - Request failed

Best Practices

  • Reuse client instances when possible
  • Use batch requests for multiple calls
  • Implement appropriate timeouts
  • Handle errors gracefully
  • Monitor client health
  • Clean up resources when done

Examples

# Basic request
client = Client.new(:http, rpc_url: "https://eth-mainnet.example.com")
request = Client.request(client, "eth_blockNumber", [])
{:ok, block_number} = Client.send(client, request)

# Batch request
requests = [
  Client.request(client, "eth_blockNumber", []),
  Client.request(client, "eth_gasPrice", [])
]
{:ok, [block_number, gas_price]} = Client.send(client, requests)

See Exth.Transport for transport details and Exth.Rpc.Request for request formatting.

Summary

Types

send_argument_type()

@type send_argument_type() :: t() | Exth.Rpc.Request.t() | [Exth.Rpc.Request.t()] | []

send_response_type()

@type send_response_type() ::
  Exth.Transport.call_response() | {:error, :duplicate_ids}

t()

@type t() :: %Exth.Rpc.Client{
  counter: :atomics.atomics_ref(),
  transport: Exth.Transport.Transportable.t()
}

Functions

new(type, opts)

@spec new(
  Exth.Transport.type(),
  keyword()
) :: t()

request(method, params)

request(client, method, params)

@spec request(t(), Exth.Rpc.method(), Exth.Rpc.params()) :: Exth.Rpc.Request.t()

send(client, request)