solana-stream-sdk 0.5.0

Rust SDK for Solana streaming data
Documentation

@validators-dao/solana-stream-sdk

Solana Stream SDK

A Rust SDK for streaming Solana Data by Validators DAO. This SDK provides a simple and efficient way to connect to Jito's Shredstream service, allowing you to subscribe to real-time Solana entries and transactions.

Features

  • Easy-to-use API - Simple wrapper around Jito shredstream protocols
  • Async Support - Built with tokio for async/await patterns
  • Type Safety - Strongly typed Rust interfaces
  • Error Handling - Comprehensive error types with proper error propagation
  • Streaming - Efficient streaming of Solana entries and transactions

Installation

Add this to your Cargo.toml:

[dependencies]
solana-stream-sdk = "0.2.5"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
dotenvy = "0.15"  # Optional: for loading environment variables from .env files

Usage

Quick Start Guide for Sample Shreds Client

Follow these steps to quickly run the sample client provided in this repository:

  1. Clone the repository
git clone https://github.com/ValidatorsDAO/solana-stream.git
cd solana-stream
  1. Create a .env file (placed in the project root)
SHREDS_ENDPOINT=https://shreds-ams.erpc.global

⚠️ Please note: This endpoint is a sample and cannot be used as is. Please obtain and configure the appropriate endpoint for your environment.

  1. Run the sample client
cargo run -p shreds-rs

The sample code can be found at: https://github.com/ValidatorsDAO/solana-stream/blob/main/client/shreds-rs/src/main.rs

A 7-day free trial for Shreds endpoints is available by joining the Validators DAO Discord community. Please try it out: https://discord.gg/C7ZQSrCkYR

Basic Example

use solana_stream_sdk::{CommitmentLevel, ShredstreamClient};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to the Jito shredstream proxy
    let mut client = ShredstreamClient::connect("https://shreds-ams.erpc.global").await?;

    // Create a subscription request for a specific account
    let request = ShredstreamClient::create_entries_request_for_account(
        "L1ocbjmuFUQDVwwUWi8HjXjg1RYEeN58qQx6iouAsGF",
        Some(CommitmentLevel::Processed),
    );

    // Subscribe to entries stream
    let mut stream = client.subscribe_entries(request).await?;

    // Process incoming entries
    while let Some(entry) = stream.message().await? {
        println!("Received entry for slot: {}", entry.slot);

        // Deserialize entries
        let entries = bincode::deserialize::<Vec<solana_entry::entry::Entry>>(&entry.entries)?;

        for entry in entries {
            println!("Entry has {} transactions", entry.transactions.len());
        }
    }

    Ok(())
}

Using Environment Variables

Create a .env file in your project root:

SHREDS_ENDPOINT=https://shreds-ams.erpc.global

Then use it in your code:

use solana_stream_sdk::{CommitmentLevel, ShredstreamClient};
use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Load environment variables from .env file
    dotenvy::dotenv().ok();

    // Get the shreds endpoint from environment variable
    let endpoint = env::var("SHREDS_ENDPOINT")
        .unwrap_or_else(|_| "https://shreds-ams.erpc.global".to_string());

    let mut client = ShredstreamClient::connect(&endpoint).await?;

    let request = ShredstreamClient::create_entries_request_for_account(
        "L1ocbjmuFUQDVwwUWi8HjXjg1RYEeN58qQx6iouAsGF",
        Some(CommitmentLevel::Processed),
    );

    let mut stream = client.subscribe_entries(request).await?;

    while let Some(entry) = stream.message().await? {
        println!("Received entry for slot: {}", entry.slot);

        let entries = bincode::deserialize::<Vec<solana_entry::entry::Entry>>(&entry.entries)?;

        for entry in entries {
            println!("Entry has {} transactions", entry.transactions.len());
        }
    }

    Ok(())
}

Custom Subscription Request

use solana_stream_sdk::{
    CommitmentLevel, SubscribeEntriesRequest, SubscribeRequestFilterAccounts,
    SubscribeRequestFilterSlots, SubscribeRequestFilterTransactions, ShredstreamClient
};
use std::collections::HashMap;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = ShredstreamClient::connect("https://shreds-ams.erpc.global").await?;

    // Create custom subscription filters
    let mut accounts = HashMap::new();
    accounts.insert(
        "my-filter".to_string(),
        SubscribeRequestFilterAccounts {
            account: vec!["EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v".to_string()], // USDC
            owner: vec![],
            filters: vec![],
            nonempty_txn_signature: None,
        },
    );

    let mut slots = HashMap::new();
    slots.insert(
        "slot-filter".to_string(),
        SubscribeRequestFilterSlots {
            filter_by_commitment: Some(true),
            interslot_updates: Some(false),
        },
    );

    let request = SubscribeEntriesRequest {
        accounts,
        transactions: HashMap::new(),
        slots,
        commitment: Some(CommitmentLevel::Confirmed as i32),
    };

    let mut stream = client.subscribe_entries(request).await?;

    while let Some(entry) = stream.message().await? {
        println!("Slot: {}, Entry data: {} bytes", entry.slot, entry.entries.len());
    }

    Ok(())
}

API Reference

ShredstreamClient

The main client for connecting to Jito shredstream services.

Methods

  • connect(endpoint: impl AsRef<str>) -> Result<Self> - Connect to a shredstream endpoint
  • subscribe_entries(&mut self, request: SubscribeEntriesRequest) -> Result<Stream<Entry>> - Subscribe to entries
  • create_entries_request_for_account(account: impl AsRef<str>, commitment: Option<CommitmentLevel>) -> SubscribeEntriesRequest - Helper to create account-specific requests
  • create_empty_entries_request() -> SubscribeEntriesRequest - Create an empty request for customization

Error Types

The SDK provides a comprehensive SolanaStreamError enum that covers:

  • Transport - Network/transport errors
  • Status - gRPC status errors
  • Serialization - Data serialization errors
  • Connection - Connection-related errors
  • Configuration - Configuration errors

Re-exported Types

For convenience, the following types are re-exported from jito_protos:

  • CommitmentLevel
  • SubscribeEntriesRequest
  • SubscribeRequestFilterAccounts
  • SubscribeRequestFilterSlots
  • SubscribeRequestFilterTransactions

Requirements

  • Rust 1.70+
  • Tokio runtime for async operations

⚠️ Experimental Filtering Feature Notice

The filtering functionality provided by this SDK is currently experimental. Occasionally, data may not be fully available, and filters may not be applied correctly.

If you encounter such cases, please report them by opening an issue at: https://github.com/ValidatorsDAO/solana-stream/issues

Your feedback greatly assists our debugging efforts and overall improvement of this feature.

Other reports and suggestions are also highly appreciated.

You can also join discussions or share feedback on Validators DAO's Discord community: https://discord.gg/C7ZQSrCkYR

License

The package is available as open source under the terms of the Apache-2.0 License.

Code of Conduct

Everyone interacting in the Validators DAO project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.