### JSON Configuration File Example Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md An example of a JSON configuration file structure containing address and token details for the Geyser client. ```json { "geyser": { "address": "127.0.0.1:10000", "token": "production-token-abc123" } } ``` -------------------------------- ### Complete Production Configuration Example Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/configuration.md A comprehensive JSON configuration for a production-grade Geyser gRPC plugin setup, including various buffer sizes and service-specific settings. ```json { "libpath": "/opt/solana/lib/libgeyser_grpc_plugin_server.so", "bind_address": "0.0.0.0:10000", "account_update_buffer_size": 500000, "slot_update_buffer_size": 200000, "slot_entry_update_buffer_size": 2000000, "block_update_buffer_size": 200000, "transaction_update_buffer_size": 500000, "geyser_service_config": { "heartbeat_interval_ms": 2000, "subscriber_buffer_size": 2000000 } } ``` -------------------------------- ### Build the Jito Geyser CLI Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/cli/README.md Build the Jito Geyser CLI binary. Ensure you have Rust and Cargo installed. ```bash cargo run --bin jito-geyser-cli ``` -------------------------------- ### Rust Environment Variable Token Example (Good Practice) Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Shows a recommended practice for securely managing access tokens by reading them from an environment variable. ```rust let token = std::env::var("GEYSER_TOKEN") .expect("GEYSER_TOKEN environment variable not set"); let consumer = connect( addr, token, None, exit, ).await; ``` -------------------------------- ### Rust Configuration File Token Reading Example (Good Practice) Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Shows how to parse a JSON configuration file and extract the Geyser address and access token. ```rust let config: serde_json::Value = serde_json::from_str( &std::fs::read_to_string("config.json")? )?; let token = config["geyser"]["token"] .as_str() .ok_or("Missing token in config")?; let consumer = connect( config["geyser"]["address"].as_str().unwrap().to_string(), token.to_string(), None, exit, ).await; ``` -------------------------------- ### Rust File-based Token Reading Example (Good Practice) Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Demonstrates reading an access token from a file in the user's home directory, ensuring to trim whitespace. ```rust let token = std::fs::read_to_string( std::path::Path::new(&std::env::var("HOME").unwrap()) .join(".geyser_token") ).expect("Failed to read token file"); let consumer = connect( addr, token.trim().to_string(), // Remove newline None, exit, ).await; ``` -------------------------------- ### Example Geyser gRPC Plugin Configuration Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/configuration.md A complete example of the Geyser gRPC Plugin's JSON configuration file, showing all root-level options. ```json { "libpath": "/path/to/container-output/libgeyser_grpc_plugin_server.so", "bind_address": "0.0.0.0:10000", "account_update_buffer_size": 100000, "slot_update_buffer_size": 100000, "slot_entry_update_buffer_size": 1000000, "block_update_buffer_size": 100000, "transaction_update_buffer_size": 100000, "geyser_service_config": { "heartbeat_interval_ms": 1000, "subscriber_buffer_size": 1000000 } } ``` -------------------------------- ### Subscribe to Account Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/cli/README.md Subscribe to updates for specific accounts. This example subscribes to the SOL/USD price on Pyth. ```bash cargo run --bin jito-geyser-cli -- --access-token "${ACCESS_TOKEN}" accounts H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG ``` -------------------------------- ### Subscribe to Program Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/cli/README.md Subscribe to updates for accounts owned by a specific program. This example subscribes to accounts owned by the Pyth program. ```bash cargo run --bin jito-geyser-cli -- --access-token "${ACCESS_TOKEN}" programs FsJ3A3u2vn5cTVofAjvy6y5kwABJAqYWpe4975bi2epH ``` -------------------------------- ### Geyser Server Configuration Example Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/README.md An example JSON configuration file for the Geyser gRPC server. It specifies the bind address, buffer sizes, and heartbeat interval. ```json { "libpath": "/opt/solana/lib/libgeyser_grpc_plugin_server.so", "bind_address": "0.0.0.0:10000", "account_update_buffer_size": 100000, "geyser_service_config": { "heartbeat_interval_ms": 1000, "subscriber_buffer_size": 1000000 } } ``` -------------------------------- ### Multiple Consumers for Load Balancing Example Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/README.md Shows a deployment pattern for load balancing by using multiple consumers, each connecting to potentially different server instances and consuming specific streams. ```rust let consumer1 = connect("http://geyser1:10000", token1, ...).await; let consumer2 = connect("http://geyser2:10000", token2, ...).await; tokio::join!( async { let _ = consumer1.consume_slot_updates(tx1).await; }, async { let _ = consumer2.consume_slot_updates(tx2).await; } ); ``` -------------------------------- ### Rust Graceful Token Rotation Example Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Illustrates the concept of graceful token rotation by showing how both old and new tokens can be used concurrently during a transition period. ```rust // Old token still works let consumer_old = connect(addr, "old-token".to_string(), None, exit_old).await; // New token also works let consumer_new = connect(addr, "new-token".to_string(), None, exit_new).await; // Eventually disable old token after all clients updated ``` -------------------------------- ### Rust Connect Function Usage Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Demonstrates the user-facing usage of the connect function, highlighting that the access token is only needed once during connection setup. ```rust let consumer = connect( "http://127.0.0.1:10000".to_string(), "my-secret-token-here".to_string(), // Only place token is needed None, exit, ).await; ``` -------------------------------- ### Connect to Geyser gRPC Plugin Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/endpoints.md Example of connecting to the geyser-grpc-plugin using the client library. This function is typically called internally by other subscription methods. ```rust use geyser_grpc_plugin_client::connect; use std::sync::{Arc, atomic::AtomicBool}; #[tokio::main] async fn main() { let consumer = connect( "http://0.0.0.0:10000".to_string(), "secret-token".to_string(), None, Arc::new(AtomicBool::new(false)), ).await; // Client would call GetHeartbeatInterval internally // to determine timeout for MaybePartialAccountUpdate stream } ``` -------------------------------- ### Single Consumer, Multiple Subscriptions Example Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/README.md Illustrates a deployment pattern where a single consumer connects and subscribes to multiple Geyser streams simultaneously using tokio::join. ```rust let consumer = connect(...).await; // Subscribe to multiple streams simultaneously tokio::join!( async { let (tx, mut rx) = unbounded_channel(); let _ = consumer.consume_slot_updates(tx).await; // process slots }, async { let (tx, mut rx) = unbounded_channel(); let _ = consumer.consume_account_updates(tx, ..., accounts).await; // process accounts } ); ``` -------------------------------- ### Rust Hardcoded Token Example (Bad Practice) Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Illustrates a bad practice of hardcoding the access token directly in the code. This is insecure and should be avoided. ```rust let consumer = connect( addr, "hardcoded-token-123".to_string(), None, exit, ).await; ``` -------------------------------- ### Consume Partial Account Updates with Heartbeats Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/endpoints.md Stream lightweight account updates and handle potential connection loss using heartbeats. This example demonstrates how to set up the consumer and detect missed heartbeats, which indicate a dead connection. ```rust let (tx, mut rx) = unbounded_channel(); let highest_rooted = Arc::new(AtomicU64::new(0)); let result = consumer.consume_partial_account_updates( tx, highest_rooted, 100, // max_rooted_slot_distance 3, // max_allowable_missed_heartbeats false, // skip_vote_accounts=false (include vote accounts) ).await; if let Err(GeyserConsumerError::MissedHeartbeat) = result { eprintln!("Connection lost, server not responding"); } ``` -------------------------------- ### Consume Account Updates Example Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/geyser-consumer.md Subscribes to complete account updates for specified accounts and processes them. Ensure the receiver of the `account_updates_tx` channel is held open to maintain the stream. ```rust use geyser_grpc_plugin_client::connect; use std::sync::{Arc, atomic::AtomicU64}; use tokio::sync::mpsc::unbounded_channel; #[tokio::main] async fn main() { let consumer = connect( "http://127.0.0.1:10000".to_string(), "token".to_string(), None, Arc::new(std::sync::atomic::AtomicBool::new(false)), ).await; let (tx, mut rx) = unbounded_channel(); let highest_rooted = Arc::new(AtomicU64::new(0)); let accounts = vec![ // Token program bs58::decode("TokenkegQfeZyiNwAJsyFbPVwwQQfstapzwUL8ajS") .into_vec() .unwrap(), ]; tokio::spawn({ let consumer = consumer.clone(); let highest_rooted = highest_rooted.clone(); async move { match consumer.consume_account_updates( tx, highest_rooted, 100, // tolerance: updates must be within 100 slots of root accounts, ).await { Ok(_) => println!("Account updates finished"), Err(e) => eprintln!("Error: {}", e), } } }); // Process updates while let Some(update) = rx.recv().await { println!( "Account {} updated in slot {} (balance: {} lamports)", bs58::encode(&update.pubkey).into_string(), update.slot, update.lamports, ); } } ``` -------------------------------- ### Implement Timeout-based Shutdown Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/client-connection.md This example shows how to shut down the consumer after a specified duration using `tokio::time::timeout`. If the timeout is reached, it requests a graceful shutdown by setting an atomic boolean flag. ```rust use tokio::time::timeout; use std::sync::{Arc, atomic::AtomicBool}; use std::time::Duration; #[tokio::main] async fn main() { let exit = Arc::new(AtomicBool::new(false)); let consumer = connect( "http://127.0.0.1:10000".to_string(), "token".to_string(), None, exit.clone(), ).await; let (tx, _rx) = tokio::sync::mpsc::unbounded_channel(); // Run for at most 60 seconds let result = timeout( Duration::from_secs(60), consumer.consume_slot_updates(tx) ).await; match result { Ok(Ok(())) => println!("Completed normally"), Ok(Err(e)) => eprintln!("Error: {}", e), Err(_) => { println!("Timeout, requesting graceful shutdown"); exit.store(true, std::sync::atomic::Ordering::Relaxed); } } } ``` -------------------------------- ### Handle Block Updates in Rust Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/endpoints.md Process incoming block updates from the Geyser gRPC stream. This example demonstrates how to receive block data, print block details, and calculate total rewards. ```rust let (tx, mut rx) = unbounded_channel(); let result = consumer.consume_block_updates(tx).await; tokio::spawn(async move { while let Some(block_update) = rx.recv().await { println!("Block {}: {}", block_update.slot, block_update.blockhash); let total_rewards: i64 = block_update .rewards .iter() .map(|r| r.lamports) .sum(); println!(" Total rewards: {} lamports", total_rewards); println!(" Transactions: {}", block_update.executed_transaction_count.unwrap_or(0)); } }); ``` -------------------------------- ### Handle Transaction Updates in Rust Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/endpoints.md Process incoming transaction updates from the Geyser gRPC stream. This example demonstrates how to receive updates, print transaction details, and check execution status. ```rust let (tx, mut rx) = unbounded_channel(); let result = consumer.consume_transaction_updates(tx).await; tokio::spawn(async move { while let Some(tx_update) = rx.recv().await { println!( "Slot {}: transaction {} ({})", tx_update.slot, tx_update.signature, if tx_update.is_vote { "VOTE" } else { "USER" } ); if let Some(meta) = &tx_update.tx.meta { if meta.status.is_ok() { println!(" Status: SUCCESS"); } else { println!(" Status: FAILED"); } println!(" Fee: {} lamports", meta.fee); } } }); ``` -------------------------------- ### gRPC Response Metadata Example Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/endpoints.md Streaming RPCs include metadata in the initial response, such as `content-type` and `highest-write-slot`. The `highest-write-slot` header helps clients initialize stale update detection. ```text HTTP/2 Headers: content-type: application/grpc highest-write-slot: ``` -------------------------------- ### Get Heartbeat Interval Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/cli/README.md Retrieve the heartbeat interval from the geyser. Requires an access token. ```bash cargo run --bin jito-geyser-cli -- --access-token "${ACCESS_TOKEN}" get-heartbeat-interval ``` -------------------------------- ### Rust Client Initialization with Interceptor Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Shows how to create a GrpcInterceptor and pass it to the GeyserClient during initialization. ```rust // In client/src/lib.rs:32-33 let interceptor = GrpcInterceptor { access_token }; let c = GeyserClient::with_interceptor(ch, interceptor); ``` -------------------------------- ### Get Heartbeat Interval Response Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Response indicating the server's heartbeat interval in milliseconds. Used to configure client-side heartbeats. ```protobuf message GetHeartbeatIntervalResponse { uint64 heartbeat_interval_ms = 1; } ``` -------------------------------- ### Token Loading from Environment or Config Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/client-connection.md Demonstrates how to securely load the access token from environment variables or a configuration file before establishing a gRPC connection. This avoids hardcoding sensitive credentials. ```rust // Load from environment let token = std::env::var("GEYSER_TOKEN") .expect("GEYSER_TOKEN not set"); // Or from config file let config: serde_json::Value = serde_json::from_str( &std::fs::read_to_string("config.json")? )?; let token = config["geyser_token"].as_str().unwrap(); let consumer = connect( "http://geyser.local:10000".to_string(), token.to_string(), None, exit, ).await; ``` -------------------------------- ### Rust Multiple Consumers with Different Tokens Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Demonstrates how to connect to multiple servers or different instances of the same server, each requiring a unique access token, and run them concurrently. ```rust // Server A with token1 let consumer_a = connect( "http://server-a:10000".to_string(), "token1".to_string(), None, exit_a.clone(), ).await; // Server B with token2 let consumer_b = connect( "http://server-b:10000".to_string(), "token2".to_string(), None, exit_b.clone(), ).await; // Run both consumers in parallel tokio::join!( async { let _ = consumer_a.consume_slot_updates(tx_a).await; }, async { let _ = consumer_b.consume_slot_updates(tx_b).await; } ); ``` -------------------------------- ### Include Solana Storage Transaction by Address Protobufs in lib.rs Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/proto/README.md Include the Solana storage transaction by address protobuf definitions by adding this module to your lib.rs file. ```rust pub mod tx_by_addr { tonic::include_proto!("solana.storage.transaction_by_addr"); } ``` -------------------------------- ### Add Jito Geyser Protobufs to Cargo.toml Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/proto/README.md Add the jito-geyser-protos library as a dependency in your Cargo.toml file. ```toml jito-geyser-protos = "0.0.2" ``` -------------------------------- ### Include Solana Geyser Protobufs in lib.rs Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/proto/README.md Include the Solana geyser protobuf definitions by adding this module to your lib.rs file. ```rust pub mod solana { pub mod geyser { tonic::include_proto!("solana.geyser"); } pub mod storage { pub mod confirmed_block { tonic::include_proto!("solana.storage.confirmed_block"); } } } ``` -------------------------------- ### Connect to Geyser gRPC Service Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/geyser-consumer.md Demonstrates how to establish a connection to the Geyser gRPC service using the `connect` function. This is the recommended way to create a `GeyserConsumer` instance. ```rust let consumer = geyser_grpc_plugin_client::connect( "http://127.0.0.1:10000".to_string(), "token".to_string(), None, Arc::new(AtomicBool::new(false)), ).await; ``` -------------------------------- ### Release Plugin Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/README.md Execute this script to create a release for the geyser-grpc-plugin. Ensure the release version matches the Solana version. ```bash ./release ``` -------------------------------- ### Build Plugin with Cargo Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/README.md Use this command to build the geyser-grpc-plugin for your validator using cargo. ```bash cargo b --release ``` -------------------------------- ### Subscribe to Partial Account Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/cli/README.md Subscribe to partial account updates for low-latency access without full data. Requires an access token. ```bash cargo run --bin jito-geyser-cli -- --access-token "${ACCESS_TOKEN}" partial-accounts ``` -------------------------------- ### Build Plugin in Docker Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/README.md Use this command to build the geyser-grpc-plugin within a Docker container. The output binary will be placed in the 'container-output' folder. ```bash ./f ``` -------------------------------- ### Bash File-based Token Creation Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Provides bash commands to create a token file and set restricted file permissions (chmod 600) for secure token storage. ```bash # Create token file with restricted permissions echo "my-token-xyz" > ~/.geyser_token chmod 600 ~/.geyser_token ``` -------------------------------- ### Load Geyser gRPC Plugin Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/configuration.md Specifies the command-line argument to load the Geyser gRPC plugin configuration file. ```bash solana-validator ... --geyser-plugin-config /path/to/geyser.json ``` -------------------------------- ### Subscribe to Program Account Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Request to subscribe to updates for all accounts owned by specified programs. Provide a list of program IDs to monitor. ```protobuf message SubscribeProgramsUpdatesRequest { repeated bytes programs = 1; } ``` -------------------------------- ### gRPC Connection with TLS Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/client-connection.md Establishes a secure gRPC connection using TLS configuration. Ensure the domain name matches the server's certificate. ```rust use geyser_grpc_plugin_client::connect; use tonic::transport::ClientTlsConfig; use std::sync::{Arc, atomic::AtomicBool}; #[tokio::main] async fn main() { let exit = Arc::new(AtomicBool::new(false)); let tls = ClientTlsConfig::new() .domain_name("geyser.example.com".to_string()); let consumer = connect( "https://geyser.example.com:10000".to_string(), "secure-token-abc123".to_string(), Some(tls), exit, ).await; println!("Connected securely"); } ``` -------------------------------- ### Subscribe to Slot Entry Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Request to subscribe to slot entry updates. This message has no parameters. ```protobuf message SubscribeSlotEntryUpdateRequest {} ``` -------------------------------- ### Configure Plugin Library Path Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/configuration.md Sets the absolute path to the compiled Geyser gRPC plugin shared object file. ```json { "libpath": "/opt/solana/lib/libgeyser_grpc_plugin_server.so" } ``` -------------------------------- ### Graceful Connection Error Handling with Retries Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/client-connection.md Provides a workaround for the `connect()` function's default panic behavior on connection failure. This function attempts to connect with retries and returns a `Result`. ```rust async fn connect_with_retry( addr: String, token: String, max_retries: u32, ) -> Result { for attempt in 0..max_retries { match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { let rt = tokio::runtime::Handle::current(); rt.block_on(connect( addr.clone(), token.clone(), None, Arc::new(AtomicBool::new(false)), )) })) { Ok(consumer) => return Ok(consumer), Err(_) => { if attempt < max_retries - 1 { tokio::time::sleep(Duration::from_secs(2)).await; continue; } else { return Err("Failed to connect after retries".to_string()); } } } } Err("Connection failed".to_string()) } ``` -------------------------------- ### Subscribe to Account Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/endpoints.md This Rust snippet demonstrates how to subscribe to account updates. It sets up a channel to receive updates and spawns a task to consume them. The highest_rooted slot is tracked for stale detection. ```rust use tokio::sync::mpsc::unbounded_channel; use std::sync::{Arc, atomic::AtomicU64}; let (tx, mut rx) = unbounded_channel(); let highest_rooted = Arc::new(AtomicU64::new(0)); let accounts = vec![ bs58::decode("TokenkegQfeZyiNwAJsyFbPVwwQQfstapzwUL8ajS").into_vec().unwrap(), ]; // Spawn task to consume updates tokio::spawn({ let consumer = consumer.clone(); async move { let result = consumer.consume_account_updates( tx, highest_rooted.clone(), 100, // max_rooted_slot_distance accounts, ).await; if let Err(e) = result { eprintln!("Account update error: {}", e); } } }); // Main loop processes updates while let Some(update) = rx.recv().await { println!("Account {} updated at slot {}", update.pubkey, update.slot); } ``` -------------------------------- ### Subscribe to Block Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Request to subscribe to block updates. This message has no parameters. ```protobuf message SubscribeBlockUpdatesRequest {} ``` -------------------------------- ### Handle Authentication Errors Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Demonstrates how to catch and handle `GrpcError` specifically for authentication failures (UNAUTHENTICATED). This is useful for validating tokens and providing user feedback. ```rust use geyser_grpc_plugin_client::{connect, GeyserConsumerError}; use tonic::Code; let consumer = connect( "http://127.0.0.1:10000".to_string(), "wrong-token".to_string(), None, exit, ).await; let (tx, _rx) = unbounded_channel(); match consumer.consume_slot_updates(tx).await { Err(GeyserConsumerError::GrpcError(status)) => { if status.code() == Code::Unauthenticated { eprintln!("Authentication failed: {}", status.message()); // Token is invalid, check your token configuration } } Err(e) => eprintln!("Other error: {}", e), Ok(()) => {}, } ``` -------------------------------- ### Export Access Token Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/cli/README.md Export your access token as an environment variable. This is required for connecting to Jito's RPC cluster. ```bash export ACCESS_TOKEN= ``` -------------------------------- ### Configure Account Update Buffer Size Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/configuration.md Sets the buffer size for full account updates. If the queue fills, older updates are dropped. Larger values tolerate slower subscribers but consume more memory. ```json { "account_update_buffer_size": 200000 } ``` -------------------------------- ### Configure gRPC Server Bind Address Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/configuration.md Specifies the IP address and port for the gRPC server to listen on. Use '0.0.0.0' to listen on all interfaces. ```json { "bind_address": "0.0.0.0:10000" } ``` -------------------------------- ### Connect and Consume Account Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/README.md Connects to the gRPC service and consumes account updates. Requires an exit signal, authentication token, and a list of accounts to monitor. The tolerance parameter defines how many missed updates are acceptable before potential disconnection. ```rust use geyser_grpc_plugin_client::connect; use std::sync::{Arc, atomic::AtomicU64}; use tokio::sync::mpsc::unbounded_channel; #[tokio::main] async fn main() { let exit = Arc::new(std::sync::atomic::AtomicBool::new(false)); let consumer = connect( "http://127.0.0.1:10000".to_string(), "my-token".to_string(), None, exit, ).await; let accounts = vec![ // Add account pubkeys here (32 bytes each) ]; let (tx, mut rx) = unbounded_channel(); let highest_rooted = Arc::new(AtomicU64::new(0)); tokio::spawn({ let consumer = consumer.clone(); let highest_rooted = highest_rooted.clone(); async move { let _ = consumer.consume_account_updates( tx, highest_rooted, 100, // tolerance accounts, ).await; } }); while let Some(update) = rx.recv().await { println!("Update: {} at slot {}", update.pubkey, update.slot); } } ``` -------------------------------- ### Subscribe to Transaction Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Request to subscribe to all transaction updates. This message has no parameters. ```protobuf message SubscribeTransactionUpdatesRequest {} ``` -------------------------------- ### Subscribe to Account Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Request to subscribe to updates for specific accounts. Provide a list of account public keys to monitor. ```protobuf message SubscribeAccountUpdatesRequest { repeated bytes accounts = 1; } ``` -------------------------------- ### Connect With TLS (Production) Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Establishes a secure connection to the Geyser gRPC service using HTTPS with TLS encryption. This is recommended for production environments to protect data in transit. ```rust use tonic::transport::ClientTlsConfig; let tls = ClientTlsConfig::new() .domain_name("geyser.example.com".to_string()); let consumer = connect( "https://geyser.example.com:10000".to_string(), "token".to_string(), Some(tls), exit, ).await; ``` -------------------------------- ### Subscribe to Slot Status Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Request to subscribe to all slot status updates. This message has no parameters. ```protobuf message SubscribeSlotUpdateRequest {} ``` -------------------------------- ### Client-Side Connection Configuration Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/configuration.md Connect to the Geyser gRPC server programmatically using the client library. Ensure the bind address matches the server's configuration. TLS is optional. ```rust use geyser_grpc_plugin_client::connect; use std::sync::{Arc, atomic::AtomicBool}; let exit = Arc::new(AtomicBool::new(false)); let consumer = connect( "http://0.0.0.0:10000".to_string(), // Must match server bind_address "my-secret-token".to_string(), // Access token for auth None, // TLS config (None = no TLS) exit, ).await; ``` -------------------------------- ### Import ConfirmedBlock from Jito Geyser Protobufs Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/proto/README.md Import the ConfirmedBlock struct from the jito_geyser_protos library for use in your Rust code. ```rust use jito_geyser_protos::solana::storage::confirmed_block::ConfirmedBlock; ``` -------------------------------- ### SubscribeProgramsUpdatesRequest Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Request to subscribe to updates for all accounts owned by specified programs. Provide a list of program IDs to monitor. ```APIDOC ## SubscribeProgramsUpdatesRequest ### Description Request to subscribe to updates for all accounts owned by specified programs. ### Method (Not specified, likely gRPC stream) ### Endpoint (Not specified, likely gRPC service method) ### Parameters #### Path Parameters (None) #### Query Parameters (None) #### Request Body - **programs** (repeated bytes) - Required - List of program IDs to monitor (32 bytes each) ### Request Example (Not specified) ### Response (Not specified) ``` -------------------------------- ### Graceful Shutdown with AtomicBool Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/README.md Demonstrates how to gracefully shut down a Geyser consumer using an atomic boolean flag. The consumer checks this flag periodically and exits when it's set to true. ```rust let exit = Arc::new(AtomicBool::new(false)); let consumer = connect(addr, token, None, exit.clone()).await; // ... run consumer ... // To stop: exit.store(true, Ordering::Relaxed); // Consumer exits within ~1 second ``` -------------------------------- ### Handle SIGTERM for Graceful Shutdown Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/client-connection.md This snippet demonstrates how to handle SIGTERM signals to initiate a graceful shutdown. It uses `tokio::signal::ctrl_c` to listen for the interrupt signal and sets an atomic boolean flag to signal the consumer to stop. ```rust use tokio::signal; use std::sync::{Arc, atomic::{AtomicBool, Ordering}}; #[tokio::main] async fn main() { let exit = Arc::new(AtomicBool::new(false)); let exit_signal = exit.clone(); tokio::spawn(async move { if let Ok(_) = signal::ctrl_c().await { println!("Shutting down..."); exit_signal.store(true, Ordering::Relaxed); } }); let consumer = connect( "http://127.0.0.1:10000".to_string(), "token".to_string(), None, exit, ).await; let (tx, _rx) = tokio::sync::mpsc::unbounded_channel(); let _ = consumer.consume_slot_updates(tx).await; } ``` -------------------------------- ### PartialAccountUpdate Struct Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Represents a lightweight account update with essential fields. Use this to reduce bandwidth when full account data is not needed. ```rust pub struct PartialAccountUpdate { pub pubkey: Pubkey, pub tx_signature: Option, pub slot: Slot, pub seq: u64, pub is_startup: bool, } ``` -------------------------------- ### Subscribe to Slot Entry Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/endpoints.md Stream individual entries (blocks or ticks) as they are processed within slots. Use this for per-entry transaction processing, real-time transaction detection, or entry-level analytics. Requires setting up an unbounded channel and spawning a tokio task to receive updates. ```rust let (tx, mut rx) = unbounded_channel(); let result = consumer.consume_slot_entry_updates(tx).await; tokio::spawn(async move { while let Some(entry) = rx.recv().await { if entry.index == 0 { println!("Slot {} processing...", entry.slot); } if entry.executed_transaction_count > 0 { println!( "Slot {}: entry {} has {} transactions", entry.slot, entry.index, entry.executed_transaction_count ); } else { println!("Slot {}: entry {} is a tick", entry.slot, entry.index); } } }); ``` -------------------------------- ### gRPC Connection with Graceful Shutdown Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/client-connection.md Connects to the Geyser service and sets up a consumer task that can be gracefully shut down using an atomic boolean flag. The shutdown signal is checked periodically by consumer loops. ```rust use geyser_grpc_plugin_client::connect; use std::sync::{Arc, atomic::{AtomicBool, Ordering}}; use tokio::time::{sleep, Duration}; #[tokio::main] async fn main() { let exit = Arc::new(AtomicBool::new(false)); let exit_clone = exit.clone(); // Consumer task tokio::spawn({ let consumer = connect( "http://127.0.0.1:10000".to_string(), "token".to_string(), None, exit.clone(), ).await; async move { let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel(); let result = consumer.consume_slot_updates(tx).await; match result { Ok(_) => println!("Slot updates finished"), Err(e) => eprintln!("Error: {}", e), } } }); // Shutdown after 10 seconds sleep(Duration::from_secs(10)).await; exit_clone.store(true, Ordering::Relaxed); // Wait for task to finish sleep(Duration::from_millis(2000)).await; } ``` -------------------------------- ### Connect Without TLS (Development) Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Establishes a connection to the Geyser gRPC service using HTTP without TLS encryption. This is suitable for local testing or development environments where security is less critical. ```rust let consumer = connect( "http://127.0.0.1:10000".to_string(), "token".to_string(), None, // No TLS exit, ).await; ``` -------------------------------- ### Set Access Token for gRPC Requests Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/endpoints.md All RPCs require an 'access-token' in the request metadata. This Rust snippet shows how to add it using the tonic client library. ```rust use tonic::metadata::MetadataValue; // The interceptor adds: access-token: request.metadata_mut().insert("access-token", token.parse().unwrap()); ``` -------------------------------- ### Subscribe to Partial Account Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Request to subscribe to lightweight partial account updates. Optionally filter out vote account updates by setting skip_vote_accounts to true. ```protobuf message SubscribePartialAccountUpdatesRequest { bool skip_vote_accounts = 1; } ``` -------------------------------- ### Basic gRPC Connection Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/client-connection.md Establishes a basic, unencrypted gRPC connection to the Geyser service. Use this for local development or trusted networks. ```rust use geyser_grpc_plugin_client::connect; use std::sync::{Arc, atomic::AtomicBool}; #[tokio::main] async fn main() { let exit = Arc::new(AtomicBool::new(false)); let consumer = connect( "http://127.0.0.1:10000".to_string(), "my-secret-token".to_string(), None, // No TLS exit, ).await; println!("Connected to Geyser service"); } ``` -------------------------------- ### Subscribe to Block Updates Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/endpoints.md Stream finalized blocks with their rewards and metadata. This is useful for block explorers, reward tracking, and inflation monitoring. ```protobuf message SubscribeBlockUpdatesRequest {} ``` ```protobuf message TimestampedBlockUpdate { google.protobuf.Timestamp ts = 1; BlockUpdate block_update = 2; } message BlockUpdate { uint64 slot = 1; string blockhash = 2; repeated storage.ConfirmedBlock.Reward rewards = 3; google.protobuf.Timestamp block_time = 4; optional uint64 block_height = 5; optional uint64 executed_transaction_count = 6; optional uint64 entry_count = 7; } ``` ```protobuf message Reward { string pubkey = 1; // Validator/program pubkey receiving reward int64 lamports = 2; // Lamports awarded (may be negative for rent) uint64 post_balance = 3; // Balance after reward RewardType reward_type = 4; // Fee, Rent, Staking, or Voting string commission = 5; // Validator commission (if applicable) } enum RewardType { UNSPECIFIED = 0; Fee = 1; Rent = 2; Staking = 3; Voting = 4; } ``` -------------------------------- ### AccountUpdate Struct Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/types.md Represents a full account state update. Use this when complete account information is required. ```rust pub struct AccountUpdate { pub pubkey: Pubkey, pub owner: Pubkey, pub data: Vec, pub tx_signature: Option, pub slot: Slot, pub lamports: u64, pub rent_epoch: u64, pub seq: u64, pub replica_version: u32, pub is_executable: bool, pub is_startup: bool, } ``` -------------------------------- ### Catching GrpcError with Tonic Status Codes Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/errors.md Illustrates how to catch GrpcError and inspect the associated tonic::Status to handle specific gRPC error codes like Unauthenticated, Unavailable, or DeadlineExceeded. This is useful for diagnosing connection and server-side issues. ```rust use tonic::Code; match consumer.consume_account_updates(tx, highest_rooted, max_distance, accounts).await { Err(GeyserConsumerError::GrpcError(status)) => { match status.code() { Code::Unauthenticated => eprintln!("Bad access token: {}", status.message()), Code::Unavailable => eprintln!("Server unavailable: {}", status.message()), Code::DeadlineExceeded => eprintln!("Request timeout"), _ => eprintln!("gRPC error {}: {}", status.code(), status.message()), } } Err(e) => eprintln!("Other error: {}", e), Ok(()) => {}, } ``` -------------------------------- ### Implement Custom Interceptor for gRPC Metadata Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/authentication.md Shows how to extend the `Interceptor` trait to add custom metadata, such as an `access-token` and `user-agent`, to gRPC requests. This is useful for scenarios requiring additional authentication or identification beyond the standard token. ```rust use tonic::transport::Endpoint; use std::str::FromStr; #[derive(Clone)] pub struct CustomInterceptor { access_token: String, user_agent: String, } impl Interceptor for CustomInterceptor { fn call(&mut self, mut request: tonic::Request<()>) -> Result, Status> { request .metadata_mut() .insert("access-token", self.access_token.parse().unwrap()); request .metadata_mut() .insert("user-agent", self.user_agent.parse().unwrap()); Ok(request) } } // Then use with custom client setup: let endpoint = Endpoint::from_str("http://127.0.0.1:10000").unwrap(); let channel = endpoint.connect().await.expect("failed to connect"); let custom_interceptor = CustomInterceptor { access_token: "token".to_string(), user_agent: "my-app/1.0".to_string(), }; let client = GeyserClient::with_interceptor(channel, custom_interceptor); // ... use client for manual RPC calls ``` -------------------------------- ### Subscribe to Blocks Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/cli/README.md Subscribe to block updates from the geyser feed. Requires an access token. ```bash cargo run --bin jito-geyser-cli -- --access-token "${ACCESS_TOKEN}" blocks ``` -------------------------------- ### Consume Partial Account Updates for Low-Bandwidth Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/README.md Consumes partial account updates, which are less verbose than full account updates, making them suitable for low-bandwidth scenarios. This method allows for a tolerance for missed heartbeats and can optionally include vote accounts. ```rust let (tx, mut rx) = unbounded_channel(); tokio::spawn({ let consumer = consumer.clone(); async move { let _ = consumer.consume_partial_account_updates( tx, highest_rooted.clone(), 100, 3, // max missed heartbeats false, // include vote accounts ).await; } }); while let Some(maybe_update) = rx.recv().await { // Filter out heartbeats, process only updates } ``` -------------------------------- ### connect Source: https://github.com/jito-foundation/geyser-grpc-plugin/blob/master/_autodocs/api-reference/client-connection.md Establishes a gRPC connection to the Geyser service and creates a consumer. This function is used to authenticate and connect to the Geyser server, returning a `GeyserConsumer` for subscribing to blockchain updates. ```APIDOC ## connect ### Description Establishes a gRPC connection to the Geyser service and creates a consumer. This function is used to authenticate and connect to the Geyser server, returning a `GeyserConsumer` for subscribing to blockchain updates. ### Method `connect` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **geyser_addr** (`String`) - Required - Connection address in URL format: `http://host:port` or `https://host:port`. Must match server's `bind_address` config. - **access_token** (`String`) - Required - Authentication token sent in gRPC metadata header `access-token`. Can be any non-empty string; server validates it. - **tls_config** (`Option`) - Optional - TLS configuration for secure connections. Pass `None` for unencrypted connections (suitable for local/private networks). Use `tonic::transport::ClientTlsConfig` for production. - **exit** (`Arc`) - Required - Shared atomic flag used to signal graceful shutdown to consumers. Consumer loops check this flag periodically (every 1 second) and exit when `true`. Can be shared across multiple consumer tasks. ### Returns `GeyserConsumer` - A cloneable consumer struct containing the gRPC client. Can be cloned and used from multiple async tasks simultaneously. ### Errors Panics on connection failure (unwrap in implementation). This is intentional for initial connection setup—failure to connect means unrecoverable configuration/network error. Network failures during streaming are handled gracefully by individual consumer methods. ### Examples #### Basic Connection ```rust use geyser_grpc_plugin_client::connect; use std::sync::{Arc, atomic::AtomicBool}; #[tokio::main] async fn main() { let exit = Arc::new(AtomicBool::new(false)); let consumer = connect( "http://127.0.0.1:10000".to_string(), "my-secret-token".to_string(), None, // No TLS exit, ).await; println!("Connected to Geyser service"); } ``` #### With TLS Configuration ```rust use geyser_grpc_plugin_client::connect; use tonic::transport::ClientTlsConfig; use std::sync::{Arc, atomic::AtomicBool}; #[tokio::main] async fn main() { let exit = Arc::new(AtomicBool::new(false)); let tls = ClientTlsConfig::new() .domain_name("geyser.example.com".to_string()); let consumer = connect( "https://geyser.example.com:10000".to_string(), "secure-token-abc123".to_string(), Some(tls), exit, ).await; println!("Connected securely"); } ``` #### With Graceful Shutdown ```rust use geyser_grpc_plugin_client::connect; use std::sync::{Arc, atomic::{AtomicBool, Ordering}}; use tokio::time::{sleep, Duration}; #[tokio::main] async fn main() { let exit = Arc::new(AtomicBool::new(false)); let exit_clone = exit.clone(); // Consumer task tokio::spawn({ let consumer = connect( "http://127.0.0.1:10000".to_string(), "token".to_string(), None, exit.clone(), ).await; async move { let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel(); let result = consumer.consume_slot_updates(tx).await; match result { Ok(_) => println!("Slot updates finished"), Err(e) => eprintln!("Error: {}", e), } } }); // Shutdown after 10 seconds sleep(Duration::from_secs(10)).await; exit_clone.store(true, Ordering::Relaxed); // Wait for task to finish sleep(Duration::from_millis(2000)).await; } ``` ### Address Format **Valid formats:** - `http://127.0.0.1:10000` — Loopback, default port - `http://0.0.0.0:10000` — May work but typically not used (connects to 0.0.0.0) - `http://192.168.1.100:10000` — Private network - `https://validator.example.com:443` — With TLS - `http://[::1]:10000` — IPv6 loopback **Invalid formats:** - `127.0.0.1:10000` — Missing scheme (will panic) - `geyser.local:10000` — Missing scheme - `http://geyser.local` — Missing port (uses default 443 for https, but needs explicit port for http) ### Token Best Practices ```rust // Load from environment let token = std::env::var("GEYSER_TOKEN") .expect("GEYSER_TOKEN not set"); // Or from config file let config: serde_json::Value = serde_json::from_str( &std::fs::read_to_string("config.json")? )?; let token = config["geyser_token"].as_str().unwrap(); let consumer = connect( "http://geyser.local:10000".to_string(), token.to_string(), None, exit, ).await; ``` ```