Skip to main content
The SolanaJsonRpcClient class is the concrete HTTP implementation of the SolanaRpcClient interface. It handles JSON-RPC communication over HTTP and provides a builder for flexible configuration.

SolanaJsonRpcClient Class

Package: software.sava.rpc.json.http.client File: SolanaJsonRpcClient.java:34
final class SolanaJsonRpcClient extends BaseSolanaJsonRpcClient 
    implements SolanaRpcClient

Default Timeouts

The class defines standard timeout constants:
DEFAULT_REQUEST_TIMEOUT
Duration
default:"8 seconds"
Default timeout for most RPC requests
PROGRAM_ACCOUNTS_TIMEOUT
Duration
default:"120 seconds"
Extended timeout for getProgramAccounts() requests which can be slow
Defined in SolanaJsonRpcClient.java:36-37.

Constructor

The constructor is package-private and should not be called directly. Use SolanaRpcClient.build() or factory methods instead.
SolanaJsonRpcClient(
    URI endpoint,
    HttpClient httpClient,
    Duration requestTimeout,
    UnaryOperator<HttpRequest.Builder> extendRequest,
    Predicate<HttpResponse<byte[]>> applyResponse,
    BiPredicate<HttpResponse<?>, byte[]> testResponse,
    Commitment defaultCommitment
)
See SolanaJsonRpcClient.java:110-120.

SolanaRpcClientBuilder Class

Package: software.sava.rpc.json.http.client File: SolanaRpcClientBuilder.java:17 Builder for configuring and creating SolanaRpcClient instances.
public final class SolanaRpcClientBuilder

Create Builder

var builder = SolanaRpcClient.build();

Configuration Methods

endpoint()

Set the RPC endpoint URI.
SolanaRpcClientBuilder endpoint(URI endpoint)
endpoint
URI
required
RPC endpoint (e.g., https://api.mainnet-beta.solana.com)
Default: Solana mainnet (SolanaNetwork.MAIN_NET.getEndpoint()) Example:
builder.endpoint(URI.create("https://api.devnet.solana.com"));
See SolanaRpcClientBuilder.java:46-49.

httpClient()

Set the underlying HTTP client.
SolanaRpcClientBuilder httpClient(HttpClient httpClient)
httpClient
HttpClient
required
Java HTTP client instance
Default: HttpClient.newHttpClient() Example:
var httpClient = HttpClient.newBuilder()
    .connectTimeout(Duration.ofSeconds(10))
    .build();
    
builder.httpClient(httpClient);
See SolanaRpcClientBuilder.java:51-54.

requestTimeout()

Set the request timeout duration.
SolanaRpcClientBuilder requestTimeout(Duration requestTimeout)
requestTimeout
Duration
required
Timeout for RPC requests
Default: 8 seconds (DEFAULT_REQUEST_TIMEOUT) Example:
builder.requestTimeout(Duration.ofSeconds(15));
See SolanaRpcClientBuilder.java:56-59.

defaultCommitment()

Set the default commitment level for requests.
SolanaRpcClientBuilder defaultCommitment(Commitment defaultCommitment)
defaultCommitment
Commitment
required
Default commitment level (PROCESSED, CONFIRMED, or FINALIZED)
Default: CONFIRMED Example:
builder.defaultCommitment(Commitment.FINALIZED);
See SolanaRpcClientBuilder.java:75-78.

extendRequest()

Provide a function to customize HTTP request builders.
SolanaRpcClientBuilder extendRequest(
    UnaryOperator<HttpRequest.Builder> extendRequest
)
extendRequest
UnaryOperator<HttpRequest.Builder>
required
Function to modify HTTP request builders before sending
Example:
// Add custom headers
builder.extendRequest(requestBuilder -> 
    requestBuilder.header("X-API-Key", "your-api-key")
);
See SolanaRpcClientBuilder.java:61-64.

compressResponses()

Enable gzip compression for responses (convenience method).
SolanaRpcClientBuilder compressResponses()
Example:
builder.compressResponses();
This is equivalent to:
builder.extendRequest(r -> r.header("Accept-Encoding", "gzip"));
See SolanaRpcClientBuilder.java:66-68.

testResponse()

Provide a function to test/validate responses.
SolanaRpcClientBuilder testResponse(
    BiPredicate<HttpResponse<?>, byte[]> testResponse
)
testResponse
BiPredicate<HttpResponse<?>, byte[]>
required
Function to validate HTTP responses
See SolanaRpcClientBuilder.java:70-73.

Build Client

createClient()

Build the configured SolanaRpcClient instance.
SolanaRpcClient createClient()
Returns: Configured SolanaRpcClient instance Example:
var client = SolanaRpcClient.build()
    .endpoint(URI.create("https://api.mainnet-beta.solana.com"))
    .defaultCommitment(Commitment.CONFIRMED)
    .requestTimeout(Duration.ofSeconds(10))
    .compressResponses()
    .createClient();
See SolanaRpcClientBuilder.java:29-44.

Complete Examples

Basic Client

import software.sava.rpc.json.http.client.SolanaRpcClient;
import software.sava.rpc.json.http.request.Commitment;
import java.net.URI;

// Minimal configuration
var client = SolanaRpcClient.build()
    .endpoint(URI.create("https://api.devnet.solana.com"))
    .createClient();

// Use client
var balance = client.getBalance(publicKey).join();
System.out.println("Balance: " + balance.lamports());

Advanced Client

import java.net.http.HttpClient;
import java.time.Duration;

// Custom HTTP client
var httpClient = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_2)
    .connectTimeout(Duration.ofSeconds(10))
    .build();

// Advanced configuration
var client = SolanaRpcClient.build()
    .endpoint(URI.create("https://api.mainnet-beta.solana.com"))
    .httpClient(httpClient)
    .requestTimeout(Duration.ofSeconds(15))
    .defaultCommitment(Commitment.FINALIZED)
    .compressResponses()
    .extendRequest(req -> req.header("X-Custom-Header", "value"))
    .createClient();

Rate-Limited Client with API Key

import java.net.http.HttpClient;
import java.time.Duration;

// For services like QuickNode, Alchemy, etc.
var client = SolanaRpcClient.build()
    .endpoint(URI.create("https://your-endpoint.quiknode.pro/token/"))
    .requestTimeout(Duration.ofSeconds(20))
    .extendRequest(req -> req
        .header("Content-Type", "application/json")
        .header("Accept-Encoding", "gzip")
    )
    .defaultCommitment(Commitment.CONFIRMED)
    .createClient();

Multiple Clients

// Mainnet client
var mainnetClient = SolanaRpcClient.build()
    .endpoint(URI.create("https://api.mainnet-beta.solana.com"))
    .defaultCommitment(Commitment.FINALIZED)
    .createClient();

// Devnet client
var devnetClient = SolanaRpcClient.build()
    .endpoint(URI.create("https://api.devnet.solana.com"))
    .defaultCommitment(Commitment.CONFIRMED)
    .createClient();

// Use different clients
var mainnetBalance = mainnetClient.getBalance(publicKey).join();
var devnetBalance = devnetClient.getBalance(publicKey).join();

Using SolanaNetwork Enum

import software.sava.rpc.json.http.SolanaNetwork;

// Use predefined network endpoints
var mainnetClient = SolanaRpcClient.build()
    .endpoint(SolanaNetwork.MAIN_NET.getEndpoint())
    .createClient();

var devnetClient = SolanaRpcClient.build()
    .endpoint(SolanaNetwork.DEV_NET.getEndpoint())
    .createClient();

var testnetClient = SolanaRpcClient.build()
    .endpoint(SolanaNetwork.TEST_NET.getEndpoint())
    .createClient();

Request Flow

Internal Architecture

  1. Client Method Call → User calls method like getAccountInfo()
  2. JSON Request Building → Method constructs JSON-RPC payload
  3. Request ExtensionextendRequest function modifies HTTP request
  4. HTTP POST → Send request to endpoint with configured timeout
  5. Response ValidationtestResponse function validates response
  6. JSON Parsing → Custom parsers deserialize response
  7. Type Conversion → Convert to strongly-typed Java objects
  8. CompletableFuture → Return async result to caller

Example Request

When you call:
client.getAccountInfo(Commitment.CONFIRMED, publicKey)
The implementation builds this JSON-RPC request:
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "getAccountInfo",
  "params": [
    "PublicKeyBase58String",
    {
      "encoding": "base64",
      "commitment": "confirmed"
    }
  ]
}
See implementation in SolanaJsonRpcClient.java:226-270.

Performance Tuning

Connection Pooling

// Reuse HTTP client for connection pooling
var httpClient = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_2)
    .build();

// Create multiple RPC clients sharing the same HTTP client
var mainnetClient = SolanaRpcClient.build()
    .httpClient(httpClient)
    .endpoint(SolanaNetwork.MAIN_NET.getEndpoint())
    .createClient();

var devnetClient = SolanaRpcClient.build()
    .httpClient(httpClient)
    .endpoint(SolanaNetwork.DEV_NET.getEndpoint())
    .createClient();

Timeouts by Operation Type

// Fast operations (balance, slot, etc.)
var fastClient = SolanaRpcClient.build()
    .requestTimeout(Duration.ofSeconds(5))
    .createClient();

// Slow operations (getProgramAccounts)
// Note: getProgramAccounts has its own 120s timeout
var slowClient = SolanaRpcClient.build()
    .requestTimeout(Duration.ofSeconds(30))
    .createClient();

Compression

// Enable compression for reduced bandwidth
var client = SolanaRpcClient.build()
    .compressResponses()
    .createClient();

Error Handling

The client throws exceptions for various error conditions:
  • Connection errors: Network unreachable, timeout
  • HTTP errors: 4xx, 5xx status codes
  • JSON-RPC errors: Invalid request, method not found
  • Parsing errors: Malformed response data
client.getAccountInfo(publicKey)
    .thenAccept(accountInfo -> {
        System.out.println("Success: " + accountInfo);
    })
    .exceptionally(error -> {
        if (error.getCause() instanceof HttpTimeoutException) {
            System.err.println("Request timed out");
        } else {
            System.err.println("Error: " + error.getMessage());
        }
        return null;
    });

See Also

Build docs developers (and LLMs) love