Skip to main content
The sava-rpc module provides a complete implementation for interacting with Solana’s JSON-RPC API and WebSocket subscriptions. It handles HTTP communication, request/response serialization, and real-time data streaming.

Features

  • HTTP RPC Client: Full implementation of Solana JSON-RPC methods
  • WebSocket Subscriptions: Real-time account, program, and transaction updates
  • Type Safety: Strongly-typed request and response objects
  • Async Operations: CompletableFuture-based API for non-blocking operations
  • Configurable: Builder pattern for client configuration
  • Performance: Optimized JSON parsing with systems.comodal.json_iterator

Exported Packages

The module exports the following packages (from module-info.java:8-13):
exports software.sava.rpc.json;
exports software.sava.rpc.json.http;
exports software.sava.rpc.json.http.client;
exports software.sava.rpc.json.http.request;
exports software.sava.rpc.json.http.response;
exports software.sava.rpc.json.http.ws;

Dependencies

Required modules:
  • java.net.http - HTTP client functionality
  • systems.comodal.json_iterator - High-performance JSON parsing (transitive)
  • software.sava.core - Core types and utilities (transitive)

Quick Start

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

// Create client using builder
var client = SolanaRpcClient.build()
    .endpoint(URI.create("https://api.mainnet-beta.solana.com"))
    .defaultCommitment(Commitment.CONFIRMED)
    .createClient();

// Get account balance
var balance = client.getBalance(publicKey).join();

// Get account info with custom factory
var accountInfo = client.getAccountInfo(
    publicKey,
    (key, data) -> MyAccount.deserialize(data)
).join();

API Reference

SolanaRpcClient

Main RPC client interface with all JSON-RPC methods

HTTP Client

HTTP implementation and builder configuration

WebSocket Client

Real-time subscriptions for accounts and programs

Request Types

Commitment levels, filters, and request options

Response Types

Account info, transactions, blocks, and more

Commitment Levels

Understanding PROCESSED, CONFIRMED, and FINALIZED

Architecture

Client Hierarchy

SolanaRpcClient (interface)

    |
SolanaJsonRpcClient (implementation)

    |
BaseSolanaJsonRpcClient (base class)

Request Flow

  1. Method Call → Client method (e.g., getAccountInfo())
  2. JSON Construction → Build JSON-RPC request payload
  3. HTTP Request → Send POST request to endpoint
  4. Response Parsing → Parse JSON response with custom parsers
  5. Type Conversion → Convert to strongly-typed response objects
  6. CompletableFuture → Return async result to caller

Common Patterns

Generic Account Factory

// Define a factory function for custom deserialization
BiFunction<PublicKey, byte[], MyAccount> factory = (pubKey, data) -> {
    return MyAccount.deserialize(data);
};

// Use with getAccountInfo
CompletableFuture<AccountInfo<MyAccount>> future = 
    client.getAccountInfo(publicKey, factory);

Commitment Levels

// Use default commitment (set during client creation)
var info1 = client.getAccountInfo(publicKey).join();

// Override with specific commitment
var info2 = client.getAccountInfo(
    Commitment.FINALIZED, 
    publicKey
).join();

Batch Operations

// Get multiple accounts (max 100)
List<PublicKey> keys = List.of(key1, key2, key3);
CompletableFuture<List<AccountInfo<byte[]>>> accounts = 
    client.getMultipleAccounts(keys);

Performance Considerations

Request Timeouts

  • Default: 8 seconds (DEFAULT_REQUEST_TIMEOUT)
  • Program Accounts: 120 seconds (PROGRAM_ACCOUNTS_TIMEOUT)
  • Configurable via SolanaRpcClientBuilder.requestTimeout()

Rate Limits

The client enforces Solana RPC limits:
  • MAX_MULTIPLE_ACCOUNTS = 100 - Maximum accounts per getMultipleAccounts call
  • MAX_GET_SIGNATURES = 1000 - Maximum signatures per getSignaturesForAddress call
  • MAX_SIG_STATUS = 256 - Maximum signatures per getSignatureStatuses call
These constants are defined in SolanaRpcClient.java:37-39.

Error Handling

client.getAccountInfo(publicKey)
    .thenAccept(accountInfo -> {
        // Success handler
        System.out.println("Lamports: " + accountInfo.lamports());
    })
    .exceptionally(throwable -> {
        // Error handler
        System.err.println("Failed to fetch account: " + throwable.getMessage());
        return null;
    });

Next Steps

Build docs developers (and LLMs) love