QUIC Transaction Submission
Lowest-latency transaction submission via QUIC protocol
Send raw transaction bytes over QUIC — the fastest path with microsecond-level latency, zero JSON overhead, and fire-and-forget delivery.
QUIC access is currently on-demand only. Contact the Raiden team to get it enabled on your account.
Protocol Specification
| Property | Value |
|---|---|
| Transport | QUIC (UDP port 4433) |
| ALPN | raiden-tpu |
| Auth | ed25519 TLS client certificate derived from API key |
| Stream type | Unidirectional (client → server) |
| Max concurrent streams | 64 per connection |
| Max payload | 4096 bytes (Transaction v1); 1232 bytes for legacy / v0 |
| Delivery | Fire-and-forget (no response) |
| 0-RTT | Supported (session resumption) |
| Idle timeout | 30 seconds |
How It Works
1. Connect to {region}.bolt.raiden.wtf:4433 with your derived certificate
2. Open a unidirectional stream
3. Write raw transaction bytes (max 4096 for Transaction v1, 1232 for legacy / v0)
4. Close the stream
5. Repeat from step 2 for more transactionsThe connection stays open — reuse it for all transactions. Each transaction gets its own stream.
Authentication
QUIC uses certificate-based auth. See QUIC Authentication for the full derivation process.
Summary: SHA-256(api_key) → ed25519 seed → keypair → self-signed X.509 certificate → presented as TLS client cert.
Examples
Go
import (
"crypto/ed25519"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"crypto/rand"
"math/big"
"time"
"github.com/quic-go/quic-go"
)
// Derive certificate from API key
hash := sha256.Sum256([]byte(apiKey))
priv := ed25519.NewKeyFromSeed(hash[:])
pub := priv.Public().(ed25519.PublicKey)
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
NotBefore: time.Now().Add(-time.Hour),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
}
certDER, _ := x509.CreateCertificate(rand.Reader, template, template, pub, priv)
cert := tls.Certificate{Certificate: [][]byte{certDER}, PrivateKey: priv}
// Connect
conn, err := quic.DialAddr(ctx, "fra.bolt.raiden.wtf:4433",
&tls.Config{
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: true,
NextProtos: []string{"raiden-tpu"},
},
&quic.Config{
MaxIdleTimeout: 30 * time.Second,
KeepAlivePeriod: 25 * time.Second,
},
)
// Send transactions
stream, _ := conn.OpenUniStream()
stream.Write(txBytes) // raw serialized transaction
stream.Close()Connection Lifecycle
- Connect once — QUIC handshake includes authentication. No separate auth step.
- Reuse connection — Open new streams for each transaction on the same connection.
- 0-RTT resumption — Subsequent connections skip the full handshake.
- Keep-alive — Set a keep-alive period (recommended: 25 seconds) to prevent idle disconnection.
Error Handling
QUIC is fire-and-forget — no per-transaction error responses. The connection itself may be closed by the server:
| Error Code | Meaning |
|---|---|
0 | Normal close |
1 | Unknown certificate — API key not recognized |
3 | QUIC access not enabled on account |
4 | Account suspended or banned |
Oversized payloads (>4096 bytes) and empty streams are silently dropped. A legacy or v0 transaction over 1232 bytes is dropped as well — only Transaction v1 can exceed that size.