Connectivity Guide
This document provides the official specifications and code standards for connecting to the Solana Indexer. Following these guidelines ensures secure, high-performance, and reliable data access for production services.
1. Overview#
Our infrastructure is exposed via a secure HTTPS API. To maintain the security standards, every connect must pass a two-tier authentication process. This guide outlines the necessary configurations for various programming environments.
2. Connection Specifications#
2.1 Endpoint Information#
- Host:
soldata.supanode.xyz - Port:
29001 - Protocol:
HTTPS / TLS 1.2+
2.2 Authentication Requirements#
All requests must provide two sets of credentials:
- Standard Credentials: Database
usernameandpasswordsent via HTTP Basic Authentication. - Security Token: A mandatory API key sent via the
x-tokenHTTP header.
Important: Failure to provide a valid
x-tokenwill result in an immediate403 Forbiddenor401 Unauthorizedresponse, regardless of the database credentials.
curl -H "x-token: PutYourXtokenHere" 'https://soldata.supanode.xyz:29001/?user=user_name&password=user_password' -d "SELECT version(), now(), 'Connect Success' as status"
3. Implementation Examples#
3.1 Node.js (@clickhouse/client)#
The modern Node.js client (v2+ / ESM) supports custom headers natively. Ensure you use the url parameter for connection strings.
import { createClient } from '@clickhouse/client'
const client = createClient({
url: 'INDEXER_URL',
username: 'your_user',
password: 'your_password',
http_headers: {
'x-token': 'your_api_token'
},
tls: {
rejectUnauthorized: false
}
})
// Query execution example
const resultSet = await client.query({
query: "SELECT version() AS v, now() AS t",
format: 'JSONEachRow'
})
3.2 Go (clickhouse-go/v2)#
When using the Go driver, you must explicitly set the Protocol to clickhouse.HTTP.
package main
import (
"context"
"crypto/tls"
"https://github.com/ClickHouse/clickhouse-go/v2"
)
func main() {
conn, _ := clickhouse.Open(&clickhouse.Options{
Addr: []string{"indexer_url"},
Auth: clickhouse.Auth{
Username: "your_user",
Password: "your_password",
},
Protocol: clickhouse.HTTP,
TLS: &tls.Config{ InsecureSkipVerify: true },
// Inject security token
HttpHeaders: map[string]string{
"x-token": "your_api_token",
},
})
// ... execution logic
}
3.3 Python (clickhouse-connect)#
For Python-based services, use the clickhouse-connect library. Since this driver strictly validates initialization parameters, use the following "Common Settings" patch to inject the security header.
import clickhouse_connect
import urllib3
from urllib3 import PoolManager
# Suppress SSL warnings when verify=False is used
urllib3.disable_warnings()
# Authentication token required by the reverse proxy (OpenResty/Nginx)
# passed as HTTP header 'x-token' on every request
X_TOKEN = 'YouXtoken'
def get_clickhouse_client(x_token: str):
"""
Creates and returns a ClickHouse client with x-token header injection.
The server requires an 'x-token' header for authentication.
clickhouse-connect uses urllib3 directly (not requests),
so standard header params like http_headers= are not supported in v0.15.x.
Workaround:
1. Temporarily monkey-patch PoolManager.urlopen at the class level so that
the token header is injected into the very first request made during
client.__init__ (which calls SELECT version() internally).
2. After get_client() returns, restore the original urlopen immediately
so the patch doesn't affect any other connections in the process.
3. Also set the token in client.headers so it is included in all
subsequent queries made through this client instance.
Args:
x-token: The authentication token.
Returns:
A configured clickhouse_connect HttpClient instance.
"""
# Save the original urlopen method so we can restore it after client init
_orig = PoolManager.urlopen
def _patched(self, method, url, **kwargs):
# Inject x-token into every outgoing HTTP request
# setdefault ensures we don't overwrite existing headers if any
kwargs.setdefault('headers', {})['x-token'] = x_token
return _orig(self, method, url, **kwargs)
# Apply the patch globally — required because get_client() fires
# a SELECT version() request inside __init__ before we can hook the instance
PoolManager.urlopen = _patched
try:
client = clickhouse_connect.get_client(
host='HOST',
port=PORT,
username='',
password='',
secure=True, # use HTTPS
verify=False, # skip SSL certificate verification (self-signed cert)
)
# Also inject the token into client.headers so all future queries
# made through this instance include the header automatically
client.headers['x-token'] = x_token
return client
finally:
# Always restore the original method, even if get_client() raises,
# to avoid leaking the patch into other parts of the application
PoolManager.urlopen = _orig
try:
client = get_clickhouse_client(X_TOKEN)
result = client.query("SELECT version()")
print("✅", result.result_rows)
except Exception as e:
print(f"❌ {e}")
4. Best Practices#
Connection Pooling#
Do not re-initialize the client for every query. Establish a single client instance and reuse it throughout the lifecycle of your application to reduce overhead from TLS handshakes.
Environment Security#
Never hardcode API tokens or passwords in your repository. Use environment variables (e.g., CLICKHOUSE_TOKEN) or a dedicated secret management service.
Troubleshooting#
| Error Code | Potential Cause | Action |
|---|---|---|
401 Unauthorized | Invalid DB Credentials | Verify username and password. |
403 Forbidden | Token Mismatch / IP Lock | Verify x-token value or check if your source IP is allowed. |
Unknown Setting | Incorrect Header Passing | Ensure x-token is sent as a Header, not as a URL parameter. |