Nitro Routing API
Real-time RPC racing, H3-aware intent routing, and cryptographically-verified task execution on 0G mainnet.
What is Nitro?
Nitro is Opacus's real-time network infrastructure layer. It provides three core capabilities:
- RPC Pool Racing — multiple 0G mainnet endpoints race in parallel on every request; fastest healthy response wins, others discarded
- H3 Intent Routing — each agent request is tagged with an H3 geospatial cell and routed to the nearest Nitro node based on intent type (execution vs interactive)
- Ed25519 Task Signing — every task result is signed by the executing agent keypair; on-chain verifiable, zero extra dependencies
0G RPC Pool
The pool is an in-memory registry of 0G RPC endpoints. On every provider request, all healthy endpoints race via Promise.any(). The winner is selected by first-response latency.
| Endpoint | Notes |
|---|---|
| https://0g-rpc.publicnode.com | Typically fastest (~80–130ms from Asia/EU). Recommended primary. |
| https://evmrpc.0g.ai | Official 0G Foundation node, higher latency (~1500–2500ms) but always-available fallback. |
/v1/nitro/ping
Returns live round-trip latency for each endpoint in the pool, the winning endpoint, and the current 0G block number. No authentication required.
Response Schema
| Field | Type | Description |
|---|---|---|
| ok | boolean | Always true on success |
| rttMs | number | Round-trip time of winning request in milliseconds |
| blockNumber | string | Current 0G mainnet block number (hex, as returned by eth_blockNumber) |
| winner | string | Full URL of the winning RPC endpoint |
| pool[].url | string | RPC endpoint URL |
| pool[].latencyMs | number | Round-trip latency for this endpoint in ms |
| pool[].healthy | boolean | true if endpoint responded within timeout |
{
"ok": true,
"rttMs": 94,
"blockNumber": "0x1D3E7A2",
"winner": "https://0g-rpc.publicnode.com",
"pool": [
{ "url": "https://0g-rpc.publicnode.com", "latencyMs": 94, "healthy": true },
{ "url": "https://evmrpc.0g.ai", "latencyMs": 1843, "healthy": true }
]
}curl https://opacus.xyz/api/v1/nitro/ping | jq .H3 Intent Routing
Tasks are classified into one of two routing modes before handoff:
- EXECUTION MODE — writes to 0G chain (swaps, bridges, storage). Routed to the Nitro node with lowest latency to the 0G execution layer.
- INTERACTIVE MODE — read-only or analytical tasks. Routed to the nearest node to the requesting agent, ignoring chain topology.
Node geography is encoded as H3 cells at resolution 5 (~252km² per cell). The handoff algorithm finds the minimum Haversine distance between the agent's H3 cell and each Nitro node's cell.
/v1/nitro/handoff
Routes an intent to the optimal Nitro node. Returns a QUIC address for direct connection.
Request Body
| Field | Type | Description |
|---|---|---|
| intent | string required | Natural-language intent, e.g. "swap USDC to W0G on Jaine" |
| chain | string optional | "0g" or "base". Inferred from intent if omitted. |
| latitude | number optional | Agent latitude (decimal degrees). Falls back to server-side geo-IP if omitted. |
| longitude | number optional | Agent longitude (decimal degrees). |
Response Schema
| Field | Type | Description |
|---|---|---|
| ok | boolean | Request succeeded |
| quicEndpoint | string | QUIC address for direct Nitro connection, e.g. quic://sg-sin-1.0g.network:4433 |
| nitroLabel | string | Human-readable node label, e.g. "Singapore Nitro" |
| anchor_mode | string | "execution" or "interactive" |
| reason | string | Routing explanation for debugging |
| failover | string | Label of fallback Nitro node |
| latency_p50_ms | number | Expected p50 round-trip in ms to selected node |
// Request
{ "intent": "swap USDC to W0G on Jaine", "chain": "0g", "latitude": 41.0082, "longitude": 28.9784 }
// Response
{
"ok": true,
"quicEndpoint": "quic://sg-sin-1.0g.network:4433",
"nitroLabel": "Singapore Nitro",
"anchor_mode": "execution",
"reason": "Execution anchor: 0G Jaine infra on Singapore (AWS ap-southeast-1)",
"failover": "Mumbai Nitro",
"latency_p50_ms": 16
}// Request
{ "intent": "analyze my portfolio risk", "latitude": 52.5200, "longitude": 13.4050 }
// Response
{
"ok": true,
"quicEndpoint": "quic://eu-fra-1.0g.network:4433",
"nitroLabel": "Frankfurt Nitro",
"anchor_mode": "interactive",
"reason": "Read-only analysis, no execution anchor needed. Nearest node to Frankfurt selected.",
"failover": "Amsterdam Nitro",
"latency_p50_ms": 9
}Ed25519 Task Signing
Every task result is signed using Ed25519 via Node.js node:crypto. Consumers can verify agent identity and detect tampering — zero extra packages required.
import { generateKeyPairSync } from 'node:crypto';
const { privateKey, publicKey } = generateKeyPairSync('ed25519');
const privDer = privateKey.export({ type: 'pkcs8', format: 'der' });
const pubDer = publicKey.export({ type: 'spki', format: 'der' });import { sign } from 'node:crypto';
const payload = Buffer.from(JSON.stringify({ taskId, result, timestamp }));
const signature = sign(null, payload, privateKey).toString('hex');
const signedResult = { taskId, result, timestamp, agentPubKey: pubDer.toString('hex'), sig: signature };import { verify, createPublicKey } from 'node:crypto';
function verifyTaskResult(r) {
const payload = Buffer.from(JSON.stringify({ taskId: r.taskId, result: r.result, timestamp: r.timestamp }));
const pubKey = createPublicKey({ key: Buffer.from(r.agentPubKey, 'hex'), format: 'der', type: 'spki' });
return verify(null, payload, pubKey, Buffer.from(r.sig, 'hex'));
}H3 Spam Filter
Agent submissions are rate-limited per H3 cell at resolution 5 (~252km² per cell). Each cell has an independent token bucket — spam in one region cannot affect others.
| Parameter | Value | Notes |
|---|---|---|
| burst limit | 100 requests | Max submissions per 100ms window per H3 cell |
| window | 100ms | Rolling token bucket |
| violation threshold | 5 | Violations before automatic slash |
| slash penalty | quarantine + stake deduction | 1-hour minimum cooldown on slash |
| resolution | H3 res-5 | ~252km² average cell area |
End-to-End Integration
const API = 'https://opacus.xyz/api';
const KEY = 'YOUR_API_KEY';
async function runTask(intent: string, lat: number, lng: number) {
// 1. Race the RPC pool
const ping = await fetch(`${API}/v1/nitro/ping`).then(r => r.json());
console.log(`Best RPC: ${ping.winner} @ ${ping.rttMs}ms block #${parseInt(ping.blockNumber, 16)}`);
// 2. Get optimal Nitro node
const handoff = await fetch(`${API}/v1/nitro/handoff`, {
method: 'POST',
headers: { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ intent, latitude: lat, longitude: lng })
}).then(r => r.json());
console.log(`→ ${handoff.nitroLabel} (${handoff.anchor_mode}) ${handoff.quicEndpoint}`);
// 3. Execute
const exec = await fetch(`${API}/v1/task-execution`, {
method: 'POST',
headers: { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ intent, nitroEndpoint: handoff.quicEndpoint })
}).then(r => r.json());
// 4. Verify Ed25519 signature
if (exec.sig && exec.agentPubKey) {
const valid = verifyTaskResult(exec);
console.log(`Signature: ${valid ? '✓ valid' : '✗ INVALID'}`);
}
return exec;
}
runTask('swap 10 USDC to W0G on Jaine', 41.0082, 28.9784);Error Reference
| HTTP | Code | Meaning |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid Authorization: Bearer … header |
| 402 | BUDGET_EXHAUSTED | Project balance below $10 minimum lock |
| 429 | H3_SPAM_LIMIT | H3 cell burst limit exceeded. Retry after 100ms. |
| 451 | AGENT_SLASHED | Agent quarantined after 5 H3 violations. On-chain cooldown applies. |
| 503 | NO_HEALTHY_RPC | All RPC pool endpoints unreachable. Very rare — 0G Foundation node is always a backstop. |