Connection

Establish a connection to NextBlock's gRPC API using Tonic. You can configure both secure (TLS) and insecure connections.

Prerequisites

Add these dependencies to your Cargo.toml:

[dependencies]
tonic = "0.10"
tokio = { version = "1.0", features = ["full"] }
solana-sdk = "1.17"
solana-client = "1.17"
base64 = "0.21"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rand = "0.8"

# Add your generated proto dependencies here
# nextblock-proto = { path = "./generated" }

Connection Setup

use std::time::Duration;
use tonic::{
    transport::{Channel, ClientTlsConfig, Endpoint},
    metadata::{MetadataValue, MetadataMap},
    Request, Status,
};
use tokio::time;

// Authentication interceptor for API key
#[derive(Clone)]
pub struct AuthInterceptor {
    api_key: MetadataValue<tonic::metadata::Ascii>,
}

impl AuthInterceptor {
    pub fn new(api_key: String) -> Result<Self, tonic::metadata::errors::InvalidMetadataValue> {
        let api_key = MetadataValue::try_from(api_key)?;
        Ok(Self { api_key })
    }
}

impl tonic::service::Interceptor for AuthInterceptor {
    fn call(&mut self, mut request: Request<()>) -> Result<Request<()>, Status> {
        request.metadata_mut().insert("authorization", self.api_key.clone());
        Ok(request)
    }
}

// Connection configuration
pub struct NextBlockConfig {
    pub endpoint: String,
    pub api_key: String,
    pub use_tls: bool,
    pub timeout: Duration,
}

impl Default for NextBlockConfig {
    fn default() -> Self {
        Self {
            endpoint: "https://fra.nextblock.io".to_string(),
            api_key: String::new(),
            use_tls: true,
            timeout: Duration::from_secs(30),
        }
    }
}

// Establish connection to NextBlock
pub async fn connect_to_nextblock(config: NextBlockConfig) -> Result<Channel, Box<dyn std::error::Error>> {
    let mut endpoint = Endpoint::from_shared(config.endpoint)?
        .timeout(config.timeout)
        .tcp_keepalive(Some(Duration::from_secs(60)))
        .http2_keep_alive_interval(Some(Duration::from_secs(30)))
        .keep_alive_timeout(Duration::from_secs(15))
        .keep_alive_while_idle(true);

    // Configure TLS if enabled
    if config.use_tls {
        let tls_config = ClientTlsConfig::new()
            .with_native_roots();
        endpoint = endpoint.tls_config(tls_config)?;
    }

    // Create the channel
    let channel = endpoint.connect().await?;
    Ok(channel)
}

// Create authenticated client
pub async fn create_nextblock_client(
    config: NextBlockConfig,
) -> Result</* YourGeneratedClient */(), Box<dyn std::error::Error>> {
    let channel = connect_to_nextblock(config.clone()).await?;
    
    // Create authentication interceptor
    let auth_interceptor = AuthInterceptor::new(config.api_key)?;
    
    // Create the client with authentication
    // let client = YourGeneratedApiClient::with_interceptor(channel, auth_interceptor);
    
    // Return the client
    // Ok(client)
    Ok(())
}

Usage Example

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Configure connection
    let config = NextBlockConfig {
        endpoint: "https://fra.nextblock.io".to_string(),
        api_key: "<your-api-key-here>".to_string(),
        use_tls: true,
        timeout: Duration::from_secs(30),
    };

    // Create authenticated client
    let client = create_nextblock_client(config).await?;
    
    // Use the client for API calls
    // See other examples for specific usage patterns
    
    println!("Successfully connected to NextBlock!");
    Ok(())
}

Connection Best Practices

  1. Use TLS in production: Always enable TLS for production environments

  2. Configure keepalive: HTTP/2 keepalive helps maintain persistent connections

  3. Set appropriate timeouts: Configure timeouts based on your use case

  4. Handle authentication: Use the interceptor pattern for API key authentication

  5. Error handling: Implement proper error handling and retry logic

Available Endpoints

  • Frankfurt: https://fra.nextblock.io (Europe)

  • New York: https://ny.nextblock.io (US East)

  • Direct NY: https://direct-ny.nextblock.io (US East, optimized routing)

Environment Configuration

use std::env;

pub fn config_from_env() -> NextBlockConfig {
    NextBlockConfig {
        endpoint: env::var("NEXTBLOCK_ENDPOINT")
            .unwrap_or_else(|_| "https://fra.nextblock.io".to_string()),
        api_key: env::var("NEXTBLOCK_API_KEY")
            .expect("NEXTBLOCK_API_KEY must be set"),
        use_tls: env::var("NEXTBLOCK_USE_TLS")
            .map(|v| v.to_lowercase() == "true")
            .unwrap_or(true),
        timeout: Duration::from_secs(
            env::var("NEXTBLOCK_TIMEOUT")
                .and_then(|v| v.parse().ok())
                .unwrap_or(30)
        ),
    }
}

Last updated