Overview
Rust is a modern systems programming language that emphasizes safety, performance, and concurrency. Its speed, strong type system, and memory safety guarantees make it an excellent choice for developing reliable Solana applications. This document provides a step-by-step process for setting up a Rust environment for interacting with Yellowstone gRPC, including setting up a project, configuring dependencies, and implementing client code.
Setting up Rust
To run the Rust code examples, you'll need to have Rust and Cargo installed. If you haven't installed Rust yet, you can do so by following the instructions at rustup.rs.
Authentication Required for Rust
To communicate with the Yellowstone gRPC plugin, you'll need to create a client using an endpoint URL and an authentication token for secure access.
use yellowstone_grpc_client::{GeyserGrpcClient, ClientTlsConfig};
async fn setup_client() -> Result<GeyserGrpcClient<impl Interceptor>, Box<dyn std::error::Error>> {
// For HTTP Provider URL: https://example-guide-demo.solana-mainnet.quiknode.pro/123456789/
let endpoint = "https://example-guide-demo.solana-mainnet.quiknode.pro:10000";
let token = "123456789";
// Build the gRPC client with TLS config
let client = GeyserGrpcClient::build_from_shared(endpoint.to_string())?
.x_token(Some(token.to_string()))?
.tls_config(ClientTlsConfig::new().with_native_roots())?
.connect()
.await?;
Ok(client)
}
To learn how to split your Solana Yellowstone enabled URL into endpoint
and token
, refer to this section - Endpoint and Token Configuration
Create a Filter
Filters determine which on-chain events your application receives. Here's a simple example creating a transaction filter:
// Create a transaction filter to monitor specific accounts
let mut transactions_filter = HashMap::new();
transactions_filter.insert(
"my_filter".to_string(), // A name for your filter
SubscribeRequestFilterTransactions {
// Only include transactions that involve these accounts
account_required: vec![program_id.to_string(), fee_account.to_string()],
// Exclude vote transactions
vote: Some(false),
// Include failed transactions
failed: Some(false),
// Other fields omitted for brevity
..Default::default()
},
);
Send Subscription Request
The subscription request includes your filters and desired commitment level:
// Send the subscription request with your filters
subscribe_tx
.send(SubscribeRequest {
// Include your transaction filter
transactions: transactions_filter,
// Set commitment level
commitment: Some(CommitmentLevel::Processed as i32),
// Use default values for other fields
..Default::default()
})
.await?;
info!("Subscription established. Listening for updates...");
Receive and Process Responses
Process the stream of updates with pattern matching:
// Process incoming messages from the stream
while let Some(message) = stream.next().await {
match message {
Ok(msg) => {
// Example for processing transaction updates
match msg.update_oneof {
Some(UpdateOneof::Transaction(tx_update)) => {
if let Some(tx_info) = &tx_update.transaction {
let tx_id = bs58::encode(&tx_info.signature).into_string();
info!("Transaction: {} at slot {}", tx_id, tx_update.slot);
}
},
// Handle other update types as needed
_ => {}
}
},
Err(e) => {
error!("Stream error: {:?}", e);
break;
}
}
}
Essential Dependencies
To interact with Yellowstone gRPC in Rust, you'll need the following dependencies:
Yellowstone gRPC Client Libraries
These libraries provide the core functionality for connecting to and interacting with Solana's gRPC interface:
- yellowstone-grpc-client - Client interface for the Yellowstone gRPC plugin
- yellowstone-grpc-proto - Protocol buffer definitions and data structures/schemas
Asynchronous Runtime
An async runtime is needed to handle the non-blocking nature of gRPC connections, e.g.:
You may also want to use additional async utilities like futures for working with streaming data.
Logging Framework
For debugging and monitoring your application's behavior, any standard Rust logging system will work (e.g., log, env_logger, or tracing).
Base58 Encoding/Decoding
For working with Solana addresses, signatures, and other Base58-encoded values, bs58 is a popular choice for Base58 encoding and decoding in Rust.
Each project may require additional dependencies based on specific needs, but these form the foundation for any Rust application working with Yellowstone gRPC.
Example Dependencies
Here's a minimal Cargo.toml
for getting started:
[dependencies]
tokio = { version = "1.28", features = ["rt-multi-thread", "macros"] }
yellowstone-grpc-client = "6.0.0"
yellowstone-grpc-proto = "6.0.0"
futures = "0.3"
log = "0.4"
env_logger = "0.11.8"
bs58 = "0.5.0"
Sample Code
A simple example of a Yellowstone Pump.fun monitor is available in our Sample Apps repo here.
We ❤️ Feedback!
If you have any feedback or questions about this documentation, let us know. We'd love to hear from you!