AURA Transaction Service

AURA Transaction Service

High-performance Solana transaction service with MEV protection.


Endpoints and Tip Address

Direct Endpoints (HTTP — lowest latency)

Region Endpoint Status
Frankfurt (FRA) http://64.130.32.177:5000 ✅ Available
Amsterdam (AMS) http://198.13.134.177:5000 ✅ Available
New York (NYC) http://45.63.11.162:5000 ✅ Available
Recommended: Use HTTP/2 long connection (Keep Alive)

Tip Address

To ensure your transaction is processed, include a tip of at least 0.001 SOL to one of our tip wallets (7 available). You may randomly select an address from the list for your transfer, which helps distribute the load and improves system efficiency.

Tip Accounts

aura2NHPnnLkPWPXkcqeHkRisDT2b8vy76eMgXH6TsL

auraMDpDVVWxwrJDtBz3Nhog4WGtbrGK2v8y3Pda7ei

auraMkDXGTE678N8LX6cqSV5JJKDpgavVcubPudaVrs

auraSRE5x8CMKbPKto1AkWjLaH4SowAJeAfGqAtdmDC

aurahN2ezg2Ktb2vrDVWqe9yunSZJajzPNTevECSGV4

aurajDJ4Eoq7L6AW36frV8PrrSjf6WMfDjEraU5iFPC

aurarguyidxqBCVtDdoi1FiKrFr3CyyNELGPaU2MWLy

Tip Floor

Minimum Tip
0.001 SOL

Transaction Submission

Endpoint

Endpoint
POST /aura?api-key=YOUR_API_KEY

Base64 Format (JSON-RPC)

Request (`sendTransaction`):

Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "sendTransaction",
  "params": [
    "BASE64_ENCODED_TRANSACTION",
    {
      "skipPreflight": true,
      "encoding": "base64"
    }
  ]
}

Request (`sendBundle`):
Submit up to 4 transactions together. Works out-of-the-box with the same anti-MEV protection endpoints.

Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "sendBundle",
  "params": [
    [
      "BASE64_ENCODED_TRANSACTION_1",
      "BASE64_ENCODED_TRANSACTION_2"
    ]
  ]
}
}

Request (`sendTransactionBatch`):
Send up to 10 transactions in a single request. Each transaction is processed independently — they're not atomic like bundles.

Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "sendTransactionBatch",
  "params": [
    "<base64-tx-1>",
    "<base64-tx-2>",
    "<base64-tx-3>"
  ]
}

Note: unlike sendBundle, the transactions go directly in params (no inner array).

Response (`sendTransactionBatch`):

Response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": ["sig1...", "sig2...", "sig3..."]
}

Returns an array of signatures for the transactions that were accepted.

Response (`sendTransaction` & `sendBundle`):

Response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "TRANSACTION_SIGNATURE"
}

Binary Format (Raw Bytes)

Send raw transaction bytes directly. Fastest option.

Binary
curl -X POST "http://64.130.32.177:5000/aura?api-key=YOUR_KEY" \
  --data-binary @transaction.bin

Response:

Response
TRANSACTION_SIGNATURE

QUIC

Send transactions over QUIC for the lowest possible latency. Raw transaction bytes over a persistent connection — no JSON, no base64.

Connection

Port5001
ALPNsolana-tpu
TLSself-signed (skip verification)
Idle timeout30s
Keep-alive10s

QUIC Regions

Region Endpoint
Frankfurt 64.130.32.177:5001
Amsterdam 198.13.134.177:5001
New York 45.63.11.162:5001

Authentication

The first unidirectional stream on every new connection must contain your API key (36-byte UUID, e.g. 9fd631cf-8c7d-432f-8eb6-4ab17af6ea93). The server validates it and authorizes the connection — all subsequent streams are authenticated with zero overhead.

If the key is invalid or inactive, the server closes the connection immediately.

Sending Transactions

Transactions are raw bincode bytes — bincode::serialize(&versioned_transaction) in Rust, or bytes(transaction) in Python with solders. Valid size: 65–1232 bytes.

Fire-and-forget (fastest)
Open a unidirectional stream, write the bytes, done.

Rust
let mut stream = conn.open_uni().await?;
stream.write_all(&tx_bytes).await?;
stream.finish()?;

With confirmation
Open a bidirectional stream, write the bytes, read back the signature.

Rust
let (mut send, mut recv) = conn.open_bi().await?;
send.write_all(&tx_bytes).await?;
send.finish()?;

let response = recv.read_to_end(256).await?;
let sig = String::from_utf8(response)?;
// "5KtPn1..." or "ERR:invalid_tx"

Dedup

Duplicate transactions are dropped silently. Only the first copy gets forwarded.

Limitations

  • No bundle support — use HTTP sendBundle for atomic bundles
  • Tip requirement still applies (min 0.001 SOL to an Aura tip account)

Code Examples

Rust (Base64)

Rust (Base64)
use solana_sdk::{signature::{Keypair, Signer}, system_instruction, transaction::Transaction};
use base64::Engine;

let tip_account = "auraT1eZF4qTFQbWL6rjHXvh7ciLey6kAhbdLzFEJom".parse()?;
let blockhash = rpc.get_latest_blockhash()?;

let tx = Transaction::new_signed_with_payer(
    &[
        // Your instruction here
        system_instruction::transfer(&payer.pubkey(), &tip_account, 1_000_000),
    ],
    Some(&payer.pubkey()),
    &[&payer],
    blockhash,
);

let tx_base64 = base64::engine::general_purpose::STANDARD.encode(bincode::serialize(&tx)?);

let body = serde_json::json!({
    "jsonrpc": "2.0",
    "id": 1,
    "method": "sendTransaction",
    "params": [tx_base64, {"skipPreflight": true, "encoding": "base64"}]
});

let response = client
    .post("http://64.130.32.177:5000/aura?api-key=YOUR_KEY")
    .json(&body)
    .send()
    .await?;

Rust (Binary)

Rust (Binary)
let tx_bytes = bincode::serialize(&tx)?;

let response = client
    .post("http://64.130.32.177:5000/aura?api-key=YOUR_KEY")
    .body(tx_bytes)
    .send()
    .await?;

TypeScript (Base64)

TypeScript (Base64)
import { Connection, Keypair, SystemProgram, Transaction, PublicKey, LAMPORTS_PER_SOL } from '@solana/web3.js';

const tipAccount = new PublicKey('auraT1eZF4qTFQbWL6rjHXvh7ciLey6kAhbdLzFEJom');
const blockhash = await connection.getLatestBlockhash();

const tx = new Transaction({
  recentBlockhash: blockhash.blockhash,
  feePayer: payer.publicKey,
});

// Add your instruction
tx.add(SystemProgram.transfer({
  fromPubkey: payer.publicKey,
  toPubkey: tipAccount,
  lamports: 0.001 * LAMPORTS_PER_SOL,
}));

tx.sign(payer);

const txBase64 = Buffer.from(tx.serialize()).toString('base64');

const response = await fetch('http://64.130.32.177:5000/aura?api-key=YOUR_KEY', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'sendTransaction',
    params: [txBase64, { skipPreflight: true, encoding: 'base64' }],
  }),
});

TypeScript (Binary)

TypeScript (Binary)
const txBytes = tx.serialize();

const response = await fetch('http://64.130.32.177:5000/aura?api-key=YOUR_KEY', {
  method: 'POST',
  body: txBytes,
});

Rust (QUIC — using aura-quic-client)

Use the aura-quic-client library — handles TLS, auth, reconnection.

View on GitHub
Cargo.toml
[dependencies]
aura-quic-client = { git = "https://github.com/aurabooster/aura-quic-client" }
Rust (aura-quic-client)
use aura_quic_client::AuraQuicClient;

let client = AuraQuicClient::connect("64.130.32.177:5001", "your-api-key").await?;

// fire-and-forget
client.send_transaction(&tx_bytes).await?;

// or with confirmation
let sig = client.send_transaction_confirmed(&tx_bytes).await?;

The client reconnects automatically if the connection drops.

Rust (QUIC — raw quinn)

If you prefer no dependencies:

Rust (raw quinn)
use quinn::{ClientConfig, Endpoint};
use std::sync::Arc;

let mut crypto = rustls::ClientConfig::builder()
    .dangerous()
    .with_custom_certificate_verifier(Arc::new(SkipVerification))
    .with_no_client_auth();
crypto.alpn_protocols = vec![b"solana-tpu".to_vec()];

let config = ClientConfig::new(Arc::new(
    quinn::crypto::rustls::QuicClientConfig::try_from(crypto)?
));

let mut endpoint = Endpoint::client("0.0.0.0:0".parse()?)?;
endpoint.set_default_client_config(config);

let conn = endpoint.connect("64.130.32.177:5001".parse()?, "localhost")?.await?;

// authenticate — first stream must be your API key
let mut auth = conn.open_uni().await?;
auth.write_all(b"your-api-key-uuid-here").await?;
auth.finish()?;

// send transactions on subsequent streams
let tx_bytes = bincode::serialize(&my_transaction)?;
let mut stream = conn.open_uni().await?;
stream.write_all(&tx_bytes).await?;
stream.finish()?;

Python (QUIC)

Python (QUIC)
import asyncio
from aioquic.asyncio import connect
from aioquic.quic.configuration import QuicConfiguration

API_KEY = "your-api-key-uuid-here"

config = QuicConfiguration(is_client=True, alpn_protocols=["solana-tpu"])
config.verify_mode = False

async with connect("64.130.32.177", 5001, configuration=config) as protocol:
    quic = protocol._quic

    # authenticate — first stream must be your API key
    auth_stream = quic.get_next_available_stream_id(is_unidirectional=True)
    quic.send_stream_data(auth_stream, API_KEY.encode(), end_stream=True)

    await asyncio.sleep(0.05)  # let server validate

    # send transaction
    tx_bytes = bytes(my_transaction)  # solders VersionedTransaction
    stream_id = quic.get_next_available_stream_id(is_unidirectional=True)
    quic.send_stream_data(stream_id, tx_bytes, end_stream=True)

TypeScript (HTTP fallback)

There's no mature QUIC library for Node.js/browser yet. Use HTTP — it's still fast with HTTP/2 keep-alive:

TypeScript (HTTP)
const resp = await fetch("http://64.130.32.177:5000/aura?api-key=YOUR_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0", id: 1,
    method: "sendTransaction",
    params: [base64EncodedTx]
  })
});

Keep Alive

getHealth

Check service status. No API key required.

getHealth
curl -X POST "http://64.130.32.177:5000/aura" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}'

Response:

Response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "ok"
}

Error Codes

Code Message
-32001 API key required
-32002 Invalid API key
-32003 Rate limit exceeded
-32004 Tip required
-32005 Tip too low

MEV Protection

Include this account in your transaction to enable MEV protection:

MEV Account
auradontfront111111111111111111111111111123

Contact Us