gRPC Streaming

Real-time account and transaction streaming via high-performance gRPC. Powered by custom Geyser plugins.

Features

  • Sub-millisecond Latency: Faster than WebSocket
  • Account Streaming: Real-time account updates
  • Transaction Streaming: Pre-confirmation transaction data
  • Block Streaming: Full block data as it's produced
  • Filtered Streams: Subscribe to specific accounts/programs

Endpoint

grpc.allenhark.com/(API Key)

Proto Definition

You will need the standard Solana Geyser proto file. Save this as geyser.proto.

Download Standard Geyser Proto

Installation

Node.js

1npm install @grpc/grpc-js @grpc/proto-loader

Rust

Add to Cargo.toml:

1[dependencies]
2tonic = "0.10"
3prost = "0.12"
4tokio = { version = "1.0", features = ["full"] }
5yellowstone-grpc-proto = "1.4.0"

Usage

Node.js Example

1const grpc = require('@grpc/grpc-js');
2const protoLoader = require('@grpc/proto-loader');
3
4// Load the protobuf definition
5const packageDefinition = protoLoader.loadSync('geyser.proto', {
6  keepCase: true,
7  longs: String,
8  enums: String,
9  defaults: true,
10  oneofs: true
11});
12const proto = grpc.loadPackageDefinition(packageDefinition).geyser;
13
14// Create client
15const client = new proto.Geyser('grpc.allenhark.com', grpc.credentials.createSsl());
16
17// Metadata for authentication
18const metadata = new grpc.Metadata();
19metadata.add('x-api-key', 'YOUR_API_KEY');
20
21// Create stream
22const stream = client.subscribe(metadata);
23
24stream.on('data', (data) => {
25  console.log('Update received:', data);
26});
27
28stream.on('error', (error) => {
29  console.error('Stream error:', error);
30});
31
32// Send subscription request
33const request = {
34  accounts: {
35    'client': {
36      account: [],
37      owner: [],
38      filters: []
39    }
40  },
41  slots: {},
42  transactions: {},
43  blocks: {},
44  blocksMeta: {},
45  commitment: 'processed',
46  entry: {}
47};
48
49stream.write(request);

Rust Example

1use yellowstone_grpc_proto::geyser::geyser_client::GeyserClient;
2use yellowstone_grpc_proto::geyser::{SubscribeRequest, SubscribeRequestFilterAccounts};
3use tonic::transport::{Channel, ClientTlsConfig};
4use tonic::Request;
5
6#[tokio::main]
7async fn main() -> Result<(), Box<dyn std::error::Error>> {
8    let endpoint = Channel::from_static("https://grpc.allenhark.com")
9        .tls_config(ClientTlsConfig::new())?;
10
11    let channel = endpoint.connect().await?;
12    let mut client = GeyserClient::with_interceptor(channel, |mut req: Request<()>| {
13        req.metadata_mut().insert("x-api-key", "YOUR_API_KEY".parse().unwrap());
14        Ok(req)
15    });
16
17    let request = SubscribeRequest {
18        accounts: [("client".to_string(), SubscribeRequestFilterAccounts {
19            account: vec![],
20            owner: vec![],
21            filters: vec![],
22        })].into_iter().collect(),
23        slots: Default::default(),
24        transactions: Default::default(),
25        blocks: Default::default(),
26        blocks_meta: Default::default(),
27        commitment: Some(1), // Processed
28        entry: Default::default(),
29    };
30
31    let mut stream = client.subscribe(std::iter::once(request)).await?.into_inner();
32
33    while let Some(message) = stream.message().await? {
34        println!("Update received: {:?}", message);
35    }
36
37    Ok(())
38}

Performance Tips

  1. Use Filters: Reduce bandwidth with specific filters
  2. Batch Processing: Process updates in batches
  3. Connection Pooling: Multiple streams for high throughput
  4. Backpressure Handling: Implement flow control

Error Handling

1stream.on('error', (error) => {
2  console.error('Stream error:', error);
3  // Implement reconnection logic
4});
5
6stream.on('end', () => {
7  console.log('Stream ended, reconnecting...');
8  // Reconnect
9});