Skip to main content

Prerequisites

Before you begin, make sure you have:
  • Rust (1.70 or later) or Node.js (16 or later)
  • Access to a Yellowstone gRPC endpoint
  • Optional: Authentication token (x-token) for protected endpoints

Installation

# Add to Cargo.toml
[dependencies]
yellowstone-grpc-client = "2.0.0"
yellowstone-grpc-proto = "2.0.0"
tokio = { version = "1", features = ["full"] }
futures = "0.3"

Your First Stream

1

Connect to Yellowstone gRPC

Establish a connection to the gRPC server with your endpoint.
use yellowstone_grpc_client::GeyserGrpcClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Build client with endpoint
    let client = GeyserGrpcClient::build_from_shared("http://127.0.0.1:10000")?
        .x_token(None::<String>)?  // Add your token here if needed
        .connect()
        .await?;
    
    println!("Connected to Yellowstone gRPC!");
    Ok(())
}
2

Create a Subscription Request

Define what data you want to receive using filters. This example subscribes to slot updates.
use yellowstone_grpc_proto::prelude::{
    SubscribeRequest,
    SubscribeRequestFilterSlots,
};
use std::collections::HashMap;

// Create slots filter
let mut slots = HashMap::new();
slots.insert(
    "client".to_string(),
    SubscribeRequestFilterSlots {
        filter_by_commitment: Some(true),
        ..Default::default()
    },
);

// Build subscribe request
let request = SubscribeRequest {
    slots,
    accounts: HashMap::new(),
    transactions: HashMap::new(),
    transactions_status: HashMap::new(),
    entry: HashMap::new(),
    blocks: HashMap::new(),
    blocks_meta: HashMap::new(),
    commitment: None,
    accounts_data_slice: vec![],
    ping: None,
    from_slot: None,
};
3

Handle Streaming Updates

Process the stream of updates from Yellowstone gRPC.
use futures::stream::StreamExt;
use yellowstone_grpc_proto::prelude::subscribe_update::UpdateOneof;

let (mut subscribe_tx, mut stream) = client.subscribe_with_request(Some(request)).await?;

println!("Stream opened, receiving updates...");

while let Some(message) = stream.next().await {
    match message {
        Ok(msg) => {
            match msg.update_oneof {
                Some(UpdateOneof::Slot(slot_update)) => {
                    println!(
                        "Slot: {}, Parent: {}, Status: {:?}",
                        slot_update.slot,
                        slot_update.parent,
                        slot_update.status
                    );
                }
                Some(UpdateOneof::Ping(_)) => {
                    // Respond to ping to keep connection alive
                    println!("Received ping");
                }
                _ => {}
            }
        }
        Err(error) => {
            eprintln!("Stream error: {:?}", error);
            break;
        }
    }
}

Common Subscription Patterns

Subscribe to Account Updates

Monitor specific accounts or filter by owner, data size, or lamport balance.
use yellowstone_grpc_proto::prelude::SubscribeRequestFilterAccounts;

let mut accounts = HashMap::new();
accounts.insert(
    "client".to_string(),
    SubscribeRequestFilterAccounts {
        account: vec!["Vote111111111111111111111111111111111111111".to_string()],
        owner: vec![],
        filters: vec![],
        nonempty_txn_signature: None,
    },
);

let request = SubscribeRequest {
    accounts,
    ..Default::default()
};

Subscribe to Transactions

Filter transactions by vote status, account involvement, or success/failure.
use yellowstone_grpc_proto::prelude::SubscribeRequestFilterTransactions;

let mut transactions = HashMap::new();
transactions.insert(
    "client".to_string(),
    SubscribeRequestFilterTransactions {
        vote: Some(false),  // Exclude vote transactions
        failed: Some(false),  // Only successful transactions
        signature: None,
        account_include: vec!["YourProgramId111111111111111111111111111111".to_string()],
        account_exclude: vec![],
        account_required: vec![],
    },
);

let request = SubscribeRequest {
    transactions,
    ..Default::default()
};

Subscribe to Blocks

Receive complete block data including transactions, accounts, and entries.
use yellowstone_grpc_proto::prelude::SubscribeRequestFilterBlocks;

let mut blocks = HashMap::new();
blocks.insert(
    "client".to_string(),
    SubscribeRequestFilterBlocks {
        account_include: vec![],
        include_transactions: Some(true),
        include_accounts: Some(false),
        include_entries: Some(false),
    },
);

let request = SubscribeRequest {
    blocks,
    ..Default::default()
};

Ping/Pong for Connection Keepalive

Some load balancers require periodic client activity to maintain connections. Handle ping/pong to keep your stream alive.
use yellowstone_grpc_proto::prelude::{
    SubscribeRequestPing,
    subscribe_update::UpdateOneof,
};

while let Some(message) = stream.next().await {
    match message {
        Ok(msg) => {
            match msg.update_oneof {
                Some(UpdateOneof::Ping(_)) => {
                    // Respond to server ping
                    subscribe_tx.send(SubscribeRequest {
                        ping: Some(SubscribeRequestPing { id: 1 }),
                        ..Default::default()
                    }).await?;
                }
                Some(UpdateOneof::Pong(_)) => {
                    // Server acknowledged our ping
                }
                _ => { /* Handle other updates */ }
            }
        }
        Err(error) => break,
    }
}

Next Steps

Filters & Subscriptions

Learn about advanced filtering options for accounts, transactions, and blocks

Plugin Configuration

Configure the Geyser plugin settings, compression, and message sizes

API Reference

Explore the complete gRPC API documentation

Client SDKs

Browse client libraries for Rust, TypeScript, and other languages

Build docs developers (and LLMs) love