Infrastructure

Complete Guide to AllenHark Relay: HTTP & QUIC Integration for Solana Trading

December 11, 2025AllenHark Team

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:

  1. Slow: 200-500ms propagation through gossip network
  2. Public: Transactions visible in mempool (vulnerable to front-running)
  3. Unreliable: Packets dropped during congestion
  4. 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:

Request API 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 CodeDescriptionSolution
tip_missingNo tip to AllenHark walletAdd tip transfer instruction
tip_insufficientTip below 0.001 SOLIncrease tip amount
simulate_forbiddensimulate: true not allowedSet simulate: false
invalid_api_keyAPI key invalid or missingCheck API key value
rate_limit_exceededToo many requestsReduce request rate or contact us
invalid_transactionTransaction deserialization failedVerify 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

Learn more about colocation

Benchmarks: Remote vs Colocated

LocationQUIC LatencyHTTP Latency
Colocated (Frankfurt)0.2-0.5ms2-4ms
Frankfurt (Germany)1-2ms5-8ms
London (UK)8-12ms18-25ms
New York (USA)75-85ms90-110ms
Tokyo (Japan)220-240ms250-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

Emergency Support

For production issues affecting trading operations:

  • Priority support: Available for high-volume customers
  • Response time: <2 hours during trading hours

Next Steps

  1. Request API access - Get your credentials
  2. Test on devnet - Validate integration without risk
  3. Deploy to production - Start with HTTP, migrate to QUIC
  4. Monitor performance - Track latency and success rates
  5. Optimize tips - Adjust based on network conditions

Ready to upgrade your Solana trading infrastructure?

Request Access | View Documentation