The SolanaRpcWebsocket interface provides WebSocket-based subscriptions for real-time updates from Solana. It enables monitoring of account changes, transaction confirmations, and program state updates.
Interface Definition
Package: software.sava.rpc.json.http.ws
File: SolanaRpcWebsocket.java:22
public interface SolanaRpcWebsocket extends AutoCloseable
Creating a WebSocket Client
Factory Method
Returns: Builder instance for configuration
Example:
import software.sava.rpc.json.http.ws.SolanaRpcWebsocket;
import software.sava.rpc.json.http.SolanaNetwork;
var ws = SolanaRpcWebsocket.build()
.uri(SolanaNetwork.MAIN_NET)
.commitment(Commitment.CONFIRMED)
.create();
// Connect and start receiving updates
ws.connect().join();
See SolanaRpcWebsocket.java:41-43.
Core Methods
endpoint()
Get the WebSocket endpoint URI.
defaultCommitment()
Get the default commitment level for subscriptions.
Commitment defaultCommitment()
connect()
Connect or reconnect the underlying WebSocket.
CompletableFuture<?> connect()
Returns: CompletableFuture that completes when connected, or null if closed
Note: Connection attempts are delayed by Timings.reConnectDelay on subsequent attempts.
See SolanaRpcWebsocket.java:55-62.
close()
Close the WebSocket connection permanently.
Note: Once closed, the WebSocket cannot be reused.
See SolanaRpcWebsocket.java:238-239.
closed()
Check if the WebSocket has been closed.
Account Subscriptions
accountSubscribe()
Subscribe to account changes.
boolean accountSubscribe(
PublicKey key,
Consumer<AccountInfo<byte[]>> consumer
)
Account public key to monitor
Optional commitment level (defaults to client’s defaultCommitment)
onSub
Consumer<Subscription<AccountInfo<byte[]>>>
Optional callback when subscription is confirmed
consumer
Consumer<AccountInfo<byte[]>>
required
Callback for account updates
Returns: true if subscription was initiated, false if already subscribed or closed
Example:
ws.accountSubscribe(
tokenAccount,
accountInfo -> {
System.out.println("Account updated: " + accountInfo.lamports());
}
);
See SolanaRpcWebsocket.java:66-84.
accountUnsubscribe()
Unsubscribe from account updates.
boolean accountUnsubscribe(PublicKey key)
Account to unsubscribe from
Commitment level used in original subscription
See SolanaRpcWebsocket.java:86-88.
Program Subscriptions
programSubscribe()
Subscribe to all accounts owned by a program.
boolean programSubscribe(
PublicKey program,
Consumer<AccountInfo<byte[]>> consumer
)
Optional filters (memcmp, dataSize)
onSub
Consumer<Subscription<AccountInfo<byte[]>>>
Callback when subscription is confirmed
consumer
Consumer<AccountInfo<byte[]>>
required
Callback for account updates
Example:
import software.sava.core.rpc.Filter;
import java.util.List;
// Subscribe to all token accounts for a mint
var filters = List.of(
Filter.createMemCompFilter(0, tokenMint) // Filter by mint
);
ws.programSubscribe(
Commitment.CONFIRMED,
TokenProgram.PROGRAM_ID,
filters,
accountInfo -> {
System.out.println("Token account updated: " + accountInfo.pubKey());
}
);
See SolanaRpcWebsocket.java:176-223.
programUnsubscribe()
Unsubscribe from program updates.
boolean programUnsubscribe(PublicKey program)
See SolanaRpcWebsocket.java:225-227.
Transaction Subscriptions
signatureSubscribe()
Subscribe to transaction confirmation.
boolean signatureSubscribe(
String b58TxSig,
Consumer<TxResult> consumer
)
Transaction signature (base58)
Commitment level for confirmation
enableReceivedNotification
Enable notification when transaction is received (PROCESSED only)
onSub
Consumer<Subscription<TxResult>>
Callback when subscription is confirmed
consumer
Consumer<TxResult>
required
Callback for transaction result
Example:
// Send transaction and monitor confirmation
String txSig = client.sendTransaction(transaction, feePayer).join();
ws.signatureSubscribe(
Commitment.FINALIZED,
txSig,
result -> {
if (result.error() == null) {
System.out.println("Transaction confirmed!");
} else {
System.err.println("Transaction failed: " + result.error());
}
ws.signatureUnsubscribe(txSig);
}
);
See SolanaRpcWebsocket.java:111-154.
signatureUnsubscribe()
Unsubscribe from signature updates.
boolean signatureUnsubscribe(String b58TxSig)
See SolanaRpcWebsocket.java:156-158.
Logs Subscriptions
logsSubscribe()
Subscribe to transaction logs mentioning an account.
boolean logsSubscribe(
PublicKey key,
Consumer<TxLogs> consumer
)
Account or program to monitor
onSub
Consumer<Subscription<TxLogs>>
Callback when subscription is confirmed
Callback for transaction logs
Example:
ws.logsSubscribe(
programId,
logs -> {
System.out.println("Transaction: " + logs.signature());
for (String log : logs.logs()) {
System.out.println(" " + log);
}
}
);
See SolanaRpcWebsocket.java:90-105.
logsUnsubscribe()
Unsubscribe from log updates.
boolean logsUnsubscribe(PublicKey key)
See SolanaRpcWebsocket.java:107-109.
Slot Subscriptions
slotSubscribe()
Subscribe to slot updates.
boolean slotSubscribe(Consumer<ProcessedSlot> consumer)
onSub
Consumer<Subscription<ProcessedSlot>>
Optional callback when subscription is confirmed
consumer
Consumer<ProcessedSlot>
required
Callback for slot updates
Example:
ws.slotSubscribe(slot -> {
System.out.println("Slot: " + slot.slot());
System.out.println("Parent: " + slot.parent());
System.out.println("Root: " + slot.root());
});
See SolanaRpcWebsocket.java:229-233.
slotUnsubscribe()
Unsubscribe from slot updates.
boolean slotUnsubscribe()
See SolanaRpcWebsocket.java:235.
Token Account Subscriptions
subscribeToTokenAccount()
Subscribe to a specific token account.
boolean subscribeToTokenAccount(
PublicKey tokenMint,
PublicKey ownerAddress,
Consumer<AccountInfo<byte[]>> consumer
)
consumer
Consumer<AccountInfo<byte[]>>
required
Callback for account updates
See SolanaRpcWebsocket.java:160-167.
subscribeToTokenAccounts()
Subscribe to all token accounts owned by an address.
boolean subscribeToTokenAccounts(
PublicKey ownerAddress,
Consumer<AccountInfo<byte[]>> consumer
)
See SolanaRpcWebsocket.java:169-174.
Exception Handling
exceptionSubscribe()
Subscribe to WebSocket exceptions.
void exceptionSubscribe(Consumer<RuntimeException> consumer)
consumer
Consumer<RuntimeException>
required
Callback for exceptions
Example:
ws.exceptionSubscribe(error -> {
System.err.println("WebSocket error: " + error.getMessage());
// Optionally reconnect
ws.connect();
});
See SolanaRpcWebsocket.java:64.
Builder Configuration
The Builder interface provides configuration options:
uri()
Set the WebSocket endpoint.
WebSocket endpoint (wss://…)
Variants:
uri(String endpoint) - Parse from string
uri(SolanaNetwork network) - Use predefined network
See SolanaRpcWebsocket.java:245-253.
webSocketBuilder()
Provide a custom WebSocket builder.
Builder webSocketBuilder(WebSocket.Builder webSocketBuilder)
See SolanaRpcWebsocket.java:255-259.
commitment()
Set default commitment level.
Builder commitment(Commitment commitment)
See SolanaRpcWebsocket.java:277.
Timing Configuration
Builder reConnectDelay(long reConnectDelay)
Builder pingDelay(long pingDelay)
Builder subscriptionAndPingCheckDelay(long subscriptionAndPingCheckDelay)
See SolanaRpcWebsocket.java:261-275.
Lifecycle Callbacks
Builder onOpen(Consumer<SolanaRpcWebsocket> onOpen)
Builder onClose(OnClose onClose)
Builder onError(BiConsumer<SolanaRpcWebsocket, Throwable> onError)
See SolanaRpcWebsocket.java:296-311.
Complete Examples
Monitor Token Account Balance
import software.sava.rpc.json.http.ws.SolanaRpcWebsocket;
import software.sava.rpc.json.http.SolanaNetwork;
import software.sava.rpc.json.http.request.Commitment;
var ws = SolanaRpcWebsocket.build()
.uri(SolanaNetwork.MAIN_NET)
.commitment(Commitment.CONFIRMED)
.create();
ws.connect().join();
ws.accountSubscribe(
tokenAccount,
accountInfo -> {
long lamports = accountInfo.lamports();
System.out.println("New balance: " + lamports);
}
);
Track Transaction Confirmation
// Send transaction
String txSig = rpcClient.sendTransaction(transaction, signer).join();
System.out.println("Transaction sent: " + txSig);
// Monitor confirmation with WebSocket
ws.signatureSubscribe(
Commitment.FINALIZED,
true, // Enable received notification
txSig,
subscription -> {
System.out.println("Subscription ID: " + subscription.id());
},
result -> {
if (result.error() == null) {
System.out.println("Transaction finalized!");
} else {
System.err.println("Transaction error: " + result.error());
}
ws.signatureUnsubscribe(Commitment.FINALIZED, txSig);
}
);
Monitor Program Activity
import software.sava.core.rpc.Filter;
import java.util.List;
var ws = SolanaRpcWebsocket.build()
.uri("wss://api.mainnet-beta.solana.com")
.commitment(Commitment.CONFIRMED)
.onError((websocket, error) -> {
System.err.println("Error: " + error.getMessage());
websocket.connect(); // Auto-reconnect
})
.create();
ws.connect().join();
// Filter for specific account type
var filters = List.of(
Filter.createDataSizeFilter(165) // Token account size
);
ws.programSubscribe(
Commitment.CONFIRMED,
TokenProgram.PROGRAM_ID,
filters,
accountInfo -> {
System.out.println("Token account updated: " + accountInfo.pubKey());
// Parse and process token account data
}
);
Slot Monitoring
var ws = SolanaRpcWebsocket.build()
.uri(SolanaNetwork.MAIN_NET)
.create();
ws.connect().join();
ws.slotSubscribe(
subscription -> {
System.out.println("Slot subscription active: " + subscription.id());
},
slot -> {
System.out.printf(
"Slot %d (parent: %d, root: %d)%n",
slot.slot(),
slot.parent(),
slot.root()
);
}
);
Best Practices
Connection Management
// Create with auto-reconnect on error
var ws = SolanaRpcWebsocket.build()
.uri(SolanaNetwork.MAIN_NET)
.onError((websocket, error) -> {
System.err.println("Connection error, reconnecting...");
websocket.connect();
})
.create();
// Always connect after creation
ws.connect().join();
// Clean up when done
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
ws.close();
}));
Subscription Cleanup
// Track subscriptions
Set<PublicKey> subscribedAccounts = new HashSet<>();
// Subscribe
if (ws.accountSubscribe(account, consumer)) {
subscribedAccounts.add(account);
}
// Clean up on shutdown
for (PublicKey account : subscribedAccounts) {
ws.accountUnsubscribe(account);
}
ws.close();
Error Recovery
ws.exceptionSubscribe(error -> {
System.err.println("WebSocket exception: " + error);
// Attempt to reconnect after delay
CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS)
.execute(() -> {
if (!ws.closed()) {
ws.connect();
}
});
});
See Also