Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

HTTP Provider

Basic Usage

import sh.brane.rpc.Brane;
 
// Simple read-only client
Brane client = Brane.connect("https://eth.llamarpc.com");
var block = client.getLatestBlock();
System.out.println("Block #" + block.number());

For more control, use the builder:

import sh.brane.rpc.Brane;
import sh.brane.core.chain.ChainProfiles;
 
Brane client = Brane.builder()
    .rpcUrl("https://eth.llamarpc.com")
    .chain(ChainProfiles.MAINNET)
    .retries(5)
    .build();

Why Loom (Virtual Threads)?

Brane's HTTP provider is built from the ground up for Java 21's virtual threads:

// Under the hood, Brane uses virtual threads
// Each HTTP request runs on a lightweight virtual thread
// that parks efficiently during I/O wait
 
try (var exec = Executors.newVirtualThreadPerTaskExecutor()) {
    // 10,000 concurrent requests? No problem.
    for (int i = 0; i < 10_000; i++) {
        exec.submit(() -> client.getLatestBlock());
    }
}

Virtual Threads vs Platform Threads

AspectPlatform ThreadsVirtual Threads (Loom)
Memory per thread~1MB stack~1KB
Max concurrentHundreds to low thousandsMillions
I/O blockingTies up OS threadParks cheaply
Best forCPU-bound workI/O-bound work

Builder Options

Brane client = Brane.builder()
    .rpcUrl("https://eth.llamarpc.com")      // HTTP/HTTPS RPC endpoint
    .chain(ChainProfiles.MAINNET)             // Network-specific config
    .retries(5)                               // Retry transient failures
    .build();

The builder provides a clean fluent API for configuration:

OptionDescription
rpcUrl(String)HTTP/HTTPS RPC endpoint URL (required unless using provider())
chain(ChainProfile)Network-specific configuration (EIP-1559 support, etc.)
retries(int)Max retry attempts for transient failures (default: 3)
retryConfig(RpcRetryConfig)Custom backoff timing configuration

Raw JSON-RPC Access

For low-level access to any Ethereum RPC method, use the provider directly:

import sh.brane.rpc.BraneProvider;
import sh.brane.rpc.JsonRpcResponse;
import java.util.List;
 
BraneProvider provider = BraneProvider.http("https://eth.llamarpc.com");
 
// Any standard JSON-RPC method
JsonRpcResponse response = provider.send("eth_chainId", List.of());
System.out.println("Chain ID: " + response.result());
 
// With parameters
JsonRpcResponse balance = provider.send("eth_getBalance",
    List.of("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest"));

Parallel Requests

For maximum throughput, fire requests in parallel:

import sh.brane.rpc.BraneExecutors;
import java.util.concurrent.Future;
import java.util.ArrayList;
 
Brane client = Brane.connect("https://eth.llamarpc.com");
 
try (var exec = BraneExecutors.newIoBoundExecutor()) {
    var futures = new ArrayList<>();
 
    for (int i = 0; i < 100; i++) {
        futures.add(exec.submit(() -> client.getLatestBlock()));
    }
 
    for (var f : futures) {
        f.get(); // Process results
    }
}

HTTP vs WebSocket

Use CaseRecommended
Serverless / LambdaHTTP
Mobile apps (battery)HTTP
Simple scriptsHTTP
Low request volume (<100/s)HTTP
Real-time subscriptionsWebSocket
High-frequency tradingWebSocket
Persistent connectionsWebSocket

Client Types

The builder creates different client types based on configuration:

import sh.brane.rpc.Brane;
import sh.brane.core.crypto.PrivateKeySigner;
import sh.brane.core.types.Address;
 
// Read-only client (Brane.Reader)
Brane.Reader reader = Brane.builder()
    .rpcUrl("https://eth.llamarpc.com")
    .buildReader();
 
var balance = reader.getBalance(new Address("0x..."));
 
// Signing client (Brane.Signer) - can send transactions
Brane.Signer signer = Brane.builder()
    .rpcUrl("https://eth.llamarpc.com")
    .signer(new PrivateKeySigner("0x..."))
    .buildSigner();
 
Hash txHash = signer.sendTransaction(request);

Error Handling

HTTP transport errors are wrapped in RpcException:

import sh.brane.core.error.RpcException;
 
try {
    var block = client.getLatestBlock();
} catch (RpcException e) {
    System.err.println("RPC Error: " + e.getMessage());
    System.err.println("Error Code: " + e.code());
}

When to Use HTTP

Use HTTP when:
  • You don't need real-time subscriptions
  • Your application is serverless or short-lived
  • You want simple, stateless connections
  • Battery efficiency matters (mobile)
Consider WebSocket when:
  • You need eth_subscribe for blocks/logs
  • You're building MEV or HFT systems
  • You want persistent connections with lower per-request overhead