NexusgRPC API
Getting Started with gRPC
Install gRPC clients and start streaming blockchain data in 5 minutes
Getting Started with gRPC
This guide will help you connect to FortiBlox gRPC and start streaming blockchain data in minutes.
Prerequisites
- API Key - Generate from Nexus Dashboard
- Network access - Professional tier required for mainnet
- Development environment - Node.js, Python, Rust, or Go
Quick Start
Install Dependencies
npm install @grpc/grpc-js @grpc/proto-loaderDownload Protocol Buffers
curl -O https://raw.githubusercontent.com/rpcpool/yellowstone-grpc/master/yellowstone-grpc-proto/proto/geyser.protoCreate Client
// grpc-client.js
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
// Load protocol buffers
const packageDefinition = protoLoader.loadSync('geyser.proto', {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
const proto = grpc.loadPackageDefinition(packageDefinition);
// Create client
const client = new proto.geyser.Geyser(
'grpc.fortiblox.com:443',
grpc.credentials.createSsl()
);
// Add API key metadata
const metadata = new grpc.Metadata();
metadata.add('x-api-key', process.env.FORTIBLOX_API_KEY);
// Create bidirectional stream
const stream = client.subscribe(metadata);
// Subscribe to transactions
stream.write({
transactions: {
'all_txs': {
vote: false,
failed: false,
accountInclude: []
}
},
commitment: 'CONFIRMED'
});
// Handle updates
stream.on('data', (update) => {
if (update.transaction) {
console.log('Transaction:', update.transaction.transaction.signature);
}
});
stream.on('error', (err) => {
console.error('Stream error:', err);
});
stream.on('end', () => {
console.log('Stream ended');
});Run
export FORTIBLOX_API_KEY="your_api_key"
node grpc-client.jsInstall Dependencies
pip install grpcio grpcio-toolsGenerate Python Code from Proto
# Download proto file
curl -O https://raw.githubusercontent.com/rpcpool/yellowstone-grpc/master/yellowstone-grpc-proto/proto/geyser.proto
# Generate Python code
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. geyser.protoCreate Client
# grpc_client.py
import grpc
import os
import geyser_pb2
import geyser_pb2_grpc
# Create channel with SSL
credentials = grpc.ssl_channel_credentials()
channel = grpc.secure_channel(
'grpc.fortiblox.com:443',
credentials
)
# Create stub
stub = geyser_pb2_grpc.GeyserStub(channel)
# Prepare metadata
metadata = [('x-api-key', os.getenv('FORTIBLOX_API_KEY'))]
# Create subscription request
def request_generator():
yield geyser_pb2.SubscribeRequest(
transactions={
'all_txs': geyser_pb2.SubscribeRequestFilterTransactions(
vote=False,
failed=False,
account_include=[]
)
},
commitment=geyser_pb2.CommitmentLevel.CONFIRMED
)
# Subscribe
try:
for update in stub.Subscribe(request_generator(), metadata=metadata):
if update.HasField('transaction'):
tx = update.transaction.transaction
print(f"Transaction: {tx.signature.hex()}")
elif update.HasField('slot'):
print(f"Slot: {update.slot.slot}")
except grpc.RpcError as e:
print(f"gRPC error: {e.code()} - {e.details()}")Run
export FORTIBLOX_API_KEY="your_api_key"
python grpc_client.pyAdd Dependencies
# Cargo.toml
[dependencies]
tonic = "0.11"
prost = "0.12"
tokio = { version = "1", features = ["full"] }
tokio-stream = "0.1"
[build-dependencies]
tonic-build = "0.11"Build Script
// build.rs
fn main() -> Result<(), Box<dyn std::error::Error>> {
tonic_build::compile_protos("proto/geyser.proto")?;
Ok(())
}Create Client
// src/main.rs
use tonic::{transport::Channel, metadata::MetadataValue, Request};
use tokio_stream::StreamExt;
pub mod geyser {
tonic::include_proto!("geyser");
}
use geyser::{geyser_client::GeyserClient, SubscribeRequest};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create channel
let channel = Channel::from_static("https://grpc.fortiblox.com:443")
.connect()
.await?;
let mut client = GeyserClient::new(channel);
// Create request with API key
let api_key = std::env::var("FORTIBLOX_API_KEY")?;
let token = MetadataValue::try_from(api_key)?;
let mut request = Request::new(tokio_stream::iter(vec![
SubscribeRequest {
transactions: std::collections::HashMap::from([(
"all_txs".to_string(),
geyser::SubscribeRequestFilterTransactions {
vote: Some(false),
failed: Some(false),
..Default::default()
}
)]),
commitment: Some(geyser::CommitmentLevel::Confirmed as i32),
..Default::default()
}
]));
request.metadata_mut().insert("x-api-key", token);
// Subscribe
let mut stream = client.subscribe(request).await?.into_inner();
// Process updates
while let Some(update) = stream.next().await {
match update {
Ok(msg) => {
if let Some(tx) = msg.transaction {
println!("Transaction: {:?}", tx.signature);
}
}
Err(e) => eprintln!("Error: {}", e),
}
}
Ok(())
}Run
export FORTIBLOX_API_KEY="your_api_key"
cargo runInstall Dependencies
go get google.golang.org/grpc
go get google.golang.org/protobufGenerate Go Code
# Install protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# Download proto
curl -O https://raw.githubusercontent.com/rpcpool/yellowstone-grpc/master/yellowstone-grpc-proto/proto/geyser.proto
# Generate code
protoc --go_out=. --go-grpc_out=. geyser.protoCreate Client
// main.go
package main
import (
"context"
"fmt"
"io"
"log"
"os"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
pb "your-module/geyser"
)
func main() {
// Create secure connection
creds := credentials.NewTLS(nil)
conn, err := grpc.Dial(
"grpc.fortiblox.com:443",
grpc.WithTransportCredentials(creds),
)
if err != nil {
log.Fatalf("Failed to connect: %v", err)
}
defer conn.Close()
// Create client
client := pb.NewGeyserClient(conn)
// Add API key to context
md := metadata.New(map[string]string{
"x-api-key": os.Getenv("FORTIBLOX_API_KEY"),
})
ctx := metadata.NewOutgoingContext(context.Background(), md)
// Create stream
stream, err := client.Subscribe(ctx)
if err != nil {
log.Fatalf("Failed to subscribe: %v", err)
}
// Send subscription request
req := &pb.SubscribeRequest{
Transactions: map[string]*pb.SubscribeRequestFilterTransactions{
"all_txs": {
Vote: false,
Failed: false,
},
},
Commitment: pb.CommitmentLevel_CONFIRMED,
}
if err := stream.Send(req); err != nil {
log.Fatalf("Failed to send request: %v", err)
}
// Receive updates
for {
update, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("Stream error: %v", err)
}
if tx := update.GetTransaction(); tx != nil {
fmt.Printf("Transaction: %x\n", tx.Transaction.Signature)
}
}
}Run
export FORTIBLOX_API_KEY="your_api_key"
go run main.goConnection Configuration
TLS/SSL
Always use secure connections in production:
// Enable SSL
const client = new proto.geyser.Geyser(
'grpc.fortiblox.com:443',
grpc.credentials.createSsl()
);Metadata Headers
Required headers for authentication:
const metadata = new grpc.Metadata();
metadata.add('x-api-key', process.env.FORTIBLOX_API_KEY);
metadata.add('x-client-version', '1.0.0'); // OptionalTimeouts and Deadlines
Set appropriate timeouts:
const deadline = new Date();
deadline.setSeconds(deadline.getSeconds() + 30);
const call = client.subscribe(metadata, { deadline });Subscription Patterns
Filter by Account
Monitor specific accounts:
stream.write({
transactions: {
'jupiter': {
accountInclude: ['JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'],
vote: false
}
}
});Filter by Program
Track program interactions:
stream.write({
transactions: {
'token_program': {
accountInclude: ['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'],
vote: false
}
}
});Multiple Subscriptions
Subscribe to different event types:
stream.write({
transactions: {
'swaps': { accountInclude: ['JUP6...'], vote: false }
},
slots: {
'slot_updates': {}
},
blocks: {
'new_blocks': {}
},
commitment: 'CONFIRMED'
});Error Handling
Connection Errors
stream.on('error', (err) => {
console.error('Stream error:', err.code, err.message);
// Reconnect logic
if (err.code === grpc.status.UNAVAILABLE) {
setTimeout(() => reconnect(), 5000);
}
});Automatic Reconnection
function createStream() {
const stream = client.subscribe(metadata);
stream.on('error', (err) => {
console.error('Stream error:', err);
setTimeout(() => createStream(), 5000);
});
stream.on('end', () => {
console.log('Stream ended, reconnecting...');
setTimeout(() => createStream(), 1000);
});
// Subscribe
stream.write({
transactions: { 'all': { vote: false } }
});
return stream;
}
let stream = createStream();Health Checks
Test connection with ping:
client.ping({ count: 1 }, metadata, (err, response) => {
if (err) {
console.error('Ping failed:', err);
} else {
console.log('Ping successful:', response);
}
});Next Steps
Streaming Guide
Learn about different streaming modes
Code Examples
Production-ready implementations
Protocol Reference
Complete protobuf definitions
Overview
Learn about gRPC capabilities
Troubleshooting
Connection Refused
- Check network tier (mainnet requires Professional+)
- Verify endpoint and port
- Ensure firewall allows outbound connections
Authentication Errors
- Verify API key is correct
- Check metadata header name (
x-api-key) - Ensure API key has gRPC access enabled
No Data Received
- Verify subscription filters
- Check commitment level
- Ensure events match your filters
Support
- Discord: discord.gg/fortiblox
- Email: [email protected]
- Examples: github.com/fortiblox/geyser-grpc/examples