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-loaderRust
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
- Use Filters: Reduce bandwidth with specific filters
- Batch Processing: Process updates in batches
- Connection Pooling: Multiple streams for high throughput
- 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});