AllenHark Relay is a production-grade transaction relay service designed for traders, market makers, and automated systems requiring sub-millisecond transaction dispatch to the Solana network.
This comprehensive integration guide covers everything from API key authentication to advanced QUIC Protocol setup, tip validation requirements, and performance optimization strategies.
What is AllenHark Relay?
AllenHark Relay is a private transaction propagation network that bypasses the public Solana gossip network to deliver your transactions directly to validator TPU (Transaction Processing Unit) ports with:
- Sub-millisecond latency via QUIC protocol
- MEV protection through private transaction routing
- Leader-aware delivery to current and upcoming block leaders
- Multi-RPC broadcasting for maximum delivery reliability
- API key authentication with configurable rate limits
Why Use a Private Relay?
Standard Solana RPC submission has critical limitations:
- Slow: 200-500ms propagation through gossip network
- Public: Transactions visible in mempool (vulnerable to front-running)
- Unreliable: Packets dropped during congestion
- No prioritization: Your high-value trades compete with spam
AllenHark Relay solves these problems with direct validator connections and priority routing.
Service Overview
Two Integration Options
AllenHark Relay supports two protocols to balance simplicity and performance:
Option 1: QUIC Protocol (Recommended)
Best for: Production trading systems, HFT bots, MEV operations
Advantages:
- 0.1-2ms latency (colocated: <0.5ms)
- 0-RTT connection resumption (instant reconnection)
- Connection multiplexing (multiple transactions over one connection)
- 50-80% faster than HTTP/2
Port: 4433
Endpoint: relay.allenhark.com:4433
Option 2: HTTPS REST API
Best for: Development, testing, low-frequency operations
Advantages:
- Simple integration (standard HTTP client)
- Wide language support (any HTTP library)
- Easy debugging (use curl, Postman, etc.)
Latency: 5-10ms (10x slower than QUIC)
Endpoint: https://relay.allenhark.com/v1/sendTx
[!TIP] Start with HTTPS for development, migrate to QUIC for production. The API format is identical.
Getting Started
Step 1: Obtain API Credentials
AllenHark Relay uses API key authentication. Contact us to request access:
You'll receive:
- API Key:
32-character alphanumeric string - Rate Limit: Default 100 requests/second (customizable)
- Support: Discord community access
Step 2: Understand Tip Requirements
Every transaction must include a tip transfer to one of the AllenHark tip wallets. This economic model ensures:
- Fair resource allocation
- Spam prevention
- Priority processing
Tip Wallets (select random):
const TIP_WALLETS = [
"hark1zxc5Rz3K8Kquz79WPWFEgNCFeJnsMJ16f22uNP",
"harkm2BTWxZuszoNpZnfe84jRbQTg6KGHaQBmWzDGQQ",
"hark4CwtTnN2y9FaxjcFBAJdJqQrpouu5pgEixfqdEz",
"harkoJfnM6dxrJydx5eVmDVwAgwC94KbhuxF69UbXwP",
"hark6hUDUTekc1DGxWdJcuyDZwf6pJdCxd4SXAVtta6",
"harkoTvFpKSrEQduYrNHXCurARVT19Ud3BnFhVxabos",
"harkEpXoJv5qVzHaN7HSuUAd6PHjyMcFMcDYBMDJCEQ",
"harkyXDdZSoJGyCxa24t2QXx1poPyp8YfghbtpzGSzK",
"harkR2YJ4Dpt4UDJTcBirjnSPBhNpQFcoFkNpCkVqNk",
"harkRBygM8pHYe4K8eBjfxyEX19oJn3LepFjvNbLbyi",
"harkYFxB6DuUFNwDLvA5CQ66KpfRvFgUoVypMagNcmd",
];
function getRandomTipWallet() {
return TIP_WALLETS[Math.floor(Math.random() * TIP_WALLETS.length)];
}
Minimum tip amount: 0.001 SOL (1,000,000 lamports)
Recommended during congestion: 0.002-0.005 SOL
Integration Guide: HTTPS REST API
The simplest way to get started. Perfect for development and testing.
API Specification
Endpoint: POST https://relay.allenhark.com/v1/sendTx
Alternative: POST https://relay.allenhark.com/broadcast
Request format:
{
"tx": "BASE64_ENCODED_TRANSACTION",
"simulate": false
}
Authentication Methods
Option 1: Header Authentication (Recommended)
curl -X POST https://relay.allenhark.com/v1/sendTx \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"tx": "BASE64_ENCODED_TRANSACTION",
"simulate": false
}'
Option 2: Query Parameter
curl -X POST "https://relay.allenhark.com/v1/sendTx?api-key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tx": "BASE64_ENCODED_TRANSACTION",
"simulate": false
}'
JavaScript/TypeScript Example
import fetch from 'node-fetch';
import { Transaction, Keypair, SystemProgram, LAMPORTS_PER_SOL, Connection } from '@solana/web3.js';
import bs58 from 'bs58';
const ALLENHARK_API_KEY = process.env.ALLENHARK_API_KEY!;
const TIP_WALLETS = [
"hark1zxc5Rz3K8Kquz79WPWFEgNCFeJnsMJ16f22uNP",
// ... (include all tip wallets)
];
async function sendTransactionViaRelay(
transaction: Transaction,
payer: Keypair
): Promise<{ status: string; request_id: string }> {
// Add tip instruction
const tipWallet = TIP_WALLETS[Math.floor(Math.random() * TIP_WALLETS.length)];
const tipAmount = 0.001 * LAMPORTS_PER_SOL; // 0.001 SOL
transaction.add(
SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: new PublicKey(tipWallet),
lamports: tipAmount,
})
);
// Get recent blockhash
const connection = new Connection('https://api.mainnet-beta.solana.com');
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.feePayer = payer.publicKey;
// Sign transaction
transaction.sign(payer);
// Serialize to base64
const txBase64 = transaction.serialize().toString('base64');
// Submit to relay
const response = await fetch('https://relay.allenhark.com/v1/sendTx', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': ALLENHARK_API_KEY,
},
body: JSON.stringify({
tx: txBase64,
simulate: false,
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Relay error: ${error.code} - ${error.message}`);
}
return await response.json();
}
// Usage
const tx = new Transaction();
// ... add your instructions ...
const result = await sendTransactionViaRelay(tx, myKeypair);
console.log(`Transaction relayed: ${result.request_id}`);
Rust Example
use reqwest::Client;
use serde_json::json;
use solana_client::rpc_client::RpcClient;
use solana_sdk::{
signature::{Keypair, Signer},
system_instruction,
transaction::Transaction,
pubkey::Pubkey,
};
use std::str::FromStr;
const TIP_WALLETS: [&str; 11] = [
"hark1zxc5Rz3K8Kquz79WPWFEgNCFeJnsMJ16f22uNP",
// ... (include all)
];
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = std::env::var("ALLENHARK_API_KEY")?;
let payer = Keypair::new(); // Your keypair
// Create your transaction
let rpc_client = RpcClient::new("https://api.mainnet-beta.solana.com");
let recent_blockhash = rpc_client.get_latest_blockhash()?;
// Add tip instruction
let tip_wallet = Pubkey::from_str(
TIP_WALLETS[rand::random::<usize>() % TIP_WALLETS.len()]
)?;
let tip_instruction = system::transfer(
&payer.pubkey(),
&tip_wallet,
1_000_000, // 0.001 SOL in lamports
);
let mut transaction = Transaction::new_with_payer(
&[tip_instruction /* , ...your other instructions */],
Some(&payer.pubkey()),
);
transaction.sign(&[&payer], recent_blockhash);
// Serialize to base64
let tx_bytes = bincode::serialize(&transaction)?;
let tx_base64 = base64::encode(&tx_bytes);
// Send to relay
let client = Client::new();
let response = client
.post("https://relay.allenhark.com/v1/sendTx")
.header("x-api-key", api_key)
.json(&json!({
"tx": tx_base64,
"simulate": false
}))
.send()
.await?;
if response.status().is_success() {
let result: serde_json::Value = response.json().await?;
println!("✓ Transaction relayed: {}", result["request_id"]);
} else {
let error: serde_json::Value = response.json().await?;
eprintln!("✗ Error: {} - {}", error["code"], error["message"]);
}
Ok(())
}
Response Handling
Success response:
{
"status": "accepted",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
Error responses:
| Error Code | Description | Solution |
|---|---|---|
tip_missing | No tip to AllenHark wallet | Add tip transfer instruction |
tip_insufficient | Tip below 0.001 SOL | Increase tip amount |
simulate_forbidden | simulate: true not allowed | Set simulate: false |
invalid_api_key | API key invalid or missing | Check API key value |
rate_limit_exceeded | Too many requests | Reduce request rate or contact us |
invalid_transaction | Transaction deserialization failed | Verify transaction format |
Integration Guide: QUIC Protocol
For production systems requiring sub-millisecond latency.
QUIC Advantages Over HTTPS
- 0-RTT Connection Resumption: No handshake overhead after first connection
- Independent Stream Processing: No head-of-line blocking
- Connection Multiplexing: 100+ concurrent streams
- 50-80% latency reduction compared to HTTP/2
Tradeoff: More complex implementation (requires QUIC library)
Rust Example (Quinn - Production Ready)
use quinn::{ClientConfig, Endpoint};
use rustls::RootCertStore;
use serde_json::json;
use std::sync::Arc;
struct RelayClient {
endpoint: Endpoint,
api_key: String,
}
impl RelayClient {
pub async fn new(api_key: String) -> Result<Self, Box<dyn std::error::Error>> {
// Configure TLS with system root certificates
let mut roots = RootCertStore::empty();
roots.add_trust_anchors(
webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| {
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
}),
);
let client_config = ClientConfig::with_root_certificates(roots);
let mut endpoint = Endpoint::client("0.0.0.0:0".parse()?)?;
endpoint.set_default_client_config(client_config);
Ok(Self { endpoint, api_key })
}
pub async fn send_transaction(
&self,
tx_base64: &str,
) -> Result<String, Box<dyn std::error::Error>> {
// Connect to relay (uses 0-RTT on subsequent connections)
let conn = self
.endpoint
.connect("relay.allenhark.com:4433".parse()?, "relay.allenhark.com")?
.await?;
// Open bidirectional stream
let (mut send, mut recv) = conn.open_bi().await?;
// Send API key header
send.write_all(format!("api-key: {}\n", self.api_key).as_bytes())
.await?;
// Send transaction payload
let payload = json!({
"tx": tx_base64,
"simulate": false
});
send.write_all(&serde_json::to_vec(&payload)?).await?;
send.finish().await?;
// Read response
let response_bytes = recv.read_to_end(4096).await?;
let response: serde_json::Value = serde_json::from_slice(&response_bytes)?;
Ok(response["request_id"].as_str().unwrap().to_string())
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = RelayClient::new(std::env::var("ALLENHARK_API_KEY")?).await?;
// First request: Normal QUIC handshake (~1-2ms)
let request_id = client.send_transaction("BASE64_TX_1").await?;
println!("Transaction 1: {}", request_id);
// Subsequent requests: 0-RTT resumption (~0.1-0.5ms)
let request_id = client.send_transaction("BASE64_TX_2").await?;
println!("Transaction 2: {} (0-RTT)", request_id);
Ok(())
}
Python Example (aioquic)
import asyncio
import json
import os
from aioquic.asyncio import connect
from aioquic.quic.configuration import QuicConfiguration
class RelayClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.host = "relay.allenhark.com"
self.port = 4433
async def send_transaction(self, tx_base64: str) -> dict:
"""Send transaction via QUIC and return response."""
config = QuicConfiguration(is_client=True)
config.verify_mode = True
async with connect(
self.host,
self.port,
configuration=config,
) as client:
# Open stream
stream_id = client._quic.get_next_available_stream_id()
# Send API key
client._quic.send_stream_data(
stream_id,
f"api-key: {self.api_key}\n".encode()
)
# Send transaction
payload = json.dumps({
"tx": tx_base64,
"simulate": False
})
client._quic.send_stream_data(
stream_id,
payload.encode(),
end_stream=True
)
# Read response
response_data = await client._quic.receive_stream_data(stream_id)
return json.loads(response_data.decode())
async def main():
client = RelayClient(os.environ["ALLENHARK_API_KEY"])
# Send transaction
response = await client.send_transaction("BASE64_TX")
print(f"✓ Transaction relayed: {response['request_id']}")
if __name__ == "__main__":
asyncio.run(main())
Rate Limits and Best Practices
Default Rate Limits
- Default: 100 requests/second per API key
- Burst: 200 requests/second peak
- Daily limit: Unlimited
Custom Rate Limits
For high-volume trading (>1,000 tx/day), contact us for:
- Dedicated rate limits
- Custom SLA agreements
- Priority support
Best Practices
1. Connection Pooling
QUIC: Maintain persistent connection
// Good: Reuse connection
let client = RelayClient::new(api_key).await?;
for tx in transactions {
client.send_transaction(&tx).await?;
}
// Bad: New connection per TX (loses 0-RTT benefit)
for tx in transactions {
let client = RelayClient::new(api_key).await?;
client.send_transaction(&tx).await?;
}
HTTPS: Use HTTP keep-alive
// Good: Reuse HTTP agent
const agent = new https.Agent({ keepAlive: true });
const api = axios.create({
baseURL: 'https://relay.allenhark.com',
httpsAgent: agent,
});
// Use for all requests
await api.post('/v1/sendTx', payload);
2. Error Handling with Retry Logic
async function sendWithRetry(
transaction: string,
maxRetries: number = 3
): Promise<any> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fetch('https://relay.allenhark.com/v1/sendTx', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY,
},
body: JSON.stringify({ tx: transaction, simulate: false }),
});
} catch (error) {
if (attempt === maxRetries - 1) throw error;
// Exponential backoff
await new Promise(resolve =>
setTimeout(resolve, 100 * Math.pow(2, attempt))
);
}
}
}
3. Dynamic Tip Adjustment
Increase tips during network congestion:
const TIP_LEVELS = {
LOW: 0.001, // Normal conditions
MEDIUM: 0.003, // High congestion
HIGH: 0.005, // Extreme congestion
};
function getTipAmount(networkCongestion: 'low' | 'medium' | 'high'): number {
return TIP_LEVELS[networkCongestion.toUpperCase()] * LAMPORTS_PER_SOL;
}
4. Monitor Request Latency
use std::time::Instant;
let start = Instant::now();
let response = client.send_transaction(&tx).await?;
let latency = start.elapsed();
// Log slow requests
if latency.as_millis() > 10 {
warn!("High latency: {}ms", latency.as_millis());
}
Performance Optimization
Colocation for True 0.1ms Latency
For absolute lowest latency, colocate your trading infrastructure in the same datacenter as AllenHark Relay.
Available locations:
- Tokyo: Equinix TY3
- New York: Equinix NY5
- London: Equinix LD5 (coming soon)
Benefits:
- True sub-millisecond latency (<0.5ms)
- Direct private link to relay
- Guaranteed network throughput
- Priority engineering support
Benchmarks: Remote vs Colocated
| Location | QUIC Latency | HTTP Latency |
|---|---|---|
| Colocated (Frankfurt) | 0.2-0.5ms | 2-4ms |
| Frankfurt (Germany) | 1-2ms | 5-8ms |
| London (UK) | 8-12ms | 18-25ms |
| New York (USA) | 75-85ms | 90-110ms |
| Tokyo (Japan) | 220-240ms | 250-280ms |
Takeaway: For non-EU traders, colocation provides 100-500x latency improvement.
Monitoring and Health Checks
Ping Endpoint
Verify relay connectivity:
curl https://relay.allenhark.com/ping
# Response: {"status": "ok", "ts": 1701234567890}
Monitoring Dashboard
Track your relay usage:
- Request count
- Error rates
- Latency percentiles
- Rate limit status
Access Dashboard (coming soon)
Pricing
AllenHark Relay uses a pay-per-transaction model via on-chain tips.
Cost structure:
- Base fee: None (free to obtain API key)
- Per-transaction: 0.001 SOL minimum tip
- High volume: Discounts available for >10,000 tx/month
Calculate your monthly cost:
Daily transactions: 1,000
Monthly cost: 1,000 tx/day × 30 days × 0.001 SOL = 30 SOL (~$3,000 at $100/SOL)
Compare to:
- Jito bundles: 0.0001-0.01 SOL per transaction (variable)
- Public RPC: Free but 10-100x slower
For high-volume traders, contact us for volume pricing.
Getting Help
Documentation
Support Channels
- Discord: Join our community
- Email: support@allenhark.com
Emergency Support
For production issues affecting trading operations:
- Priority support: Available for high-volume customers
- Response time: <2 hours during trading hours
Next Steps
- Request API access - Get your credentials
- Test on devnet - Validate integration without risk
- Deploy to production - Start with HTTP, migrate to QUIC
- Monitor performance - Track latency and success rates
- Optimize tips - Adjust based on network conditions
Ready to upgrade your Solana trading infrastructure?