# Connection

Establish a connection to NextBlock's gRPC API using Tonic.

This page shows the connection pattern and authentication interceptor. Replace the placeholder generated client type with the client generated from [`nextblock-proto`](https://github.com/nextblock-ag/nextblock-proto).

## Prerequisites

Add these dependencies to your `Cargo.toml`:

```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

<pre class="language-rust"><code class="lang-rust"><strong>use std::time::Duration;
</strong>use tonic::{
    transport::{Channel, ClientTlsConfig, Endpoint},
    metadata::{MetadataValue, MetadataMap},
    Request, Status,
};
use tokio::time;

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

impl AuthInterceptor {
    pub fn new(api_key: String) -> Result&#x3C;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(&#x26;mut self, mut request: Request&#x3C;()>) -> Result&#x3C;Request&#x3C;()>, Status> {
        request.metadata_mut().insert("authorization", self.api_key.clone());
        Ok(request)
    }
}

<strong>// Connection configuration
</strong>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://frankfurt.nextblock.io".to_string(),
            api_key: String::new(),
            use_tls: true,
            timeout: Duration::from_secs(30),
        }
    }
}

<strong>// Establish connection to NextBlock
</strong>pub async fn connect_to_nextblock(config: NextBlockConfig) -> Result&#x3C;Channel, Box&#x3C;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);

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

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

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

## Usage Example

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

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

## 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**: `frankfurt.nextblock.io` (Europe)
* **Amsterdam**: `amsterdam.nextblock.io` (Europe)
* **London**: `london.nextblock.io` (Europe)
* **Singapore**: `singapore.nextblock.io` (Asia)
* **Tokyo**: `tokyo.nextblock.io` (Asia)
* **New York**: `ny.nextblock.io` (US East)
* **Salt Lake City**: `slc.nextblock.io` (US West)
* **Dublin**: `dublin.nextblock.io` (Europe)
* **Vilnius**: `vilnius.nextblock.io` (Europe)

## Environment Configuration

<pre class="language-rust"><code class="lang-rust"><strong>use std::env;
</strong>
pub fn config_from_env() -> NextBlockConfig {
    NextBlockConfig {
        endpoint: env::var("NEXTBLOCK_ENDPOINT")
            .unwrap_or_else(|_| "https://frankfurt.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)
        ),
    }
}
</code></pre>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.nextblock.io/api/examples/rust/connection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
