# RPC Reference ## Endpoints | Type | Mainnet | Testnet | |------|---------|---------| | HTTP | `https://mainnet.megaeth.com/rpc` | `https://carrot.megaeth.com/rpc` | | WebSocket | `wss://mainnet.megaeth.com/ws` | `wss://carrot.megaeth.com/ws` | Third-party providers: Alchemy, QuickNode (recommended for geo-distributed access) ## MegaETH-Specific Methods ### Instant Transaction Receipts MegaETH supports synchronous transaction submission — get your receipt in <10ms instead of polling. **Two equivalent methods:** | Method | Origin | Status | |--------|--------|--------| | `realtime_sendRawTransaction` | MegaETH original | Supported | | `eth_sendRawTransactionSync` | EIP-7966 standard | Supported (proxied) | **History:** MegaETH created `realtime_sendRawTransaction` first. Later, `eth_sendRawTransactionSync` was standardized as EIP-7966. MegaETH now proxies both — they are functionally identical. Use whichever you prefer; `eth_sendRawTransactionSync` is recommended for cross-chain compatibility. ```bash # Both work identically: curl -X POST https://mainnet.megaeth.com/rpc \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "eth_sendRawTransactionSync", "params": ["0x...signedTx"], "id": 1 }' # Or use the original: curl -X POST https://mainnet.megaeth.com/rpc \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "realtime_sendRawTransaction", "params": ["0x...signedTx"], "id": 1 }' ``` **Response:** Full transaction receipt (same schema as `eth_getTransactionReceipt`) **Corner cases on retry:** - Tx still in pool: "already known" error - Tx already executed: "nonce too low" error (future: will return receipt directly) ### eth_getLogsWithCursor Paginated log queries for large result sets: ```javascript const response = await client.request({ method: 'eth_getLogsWithCursor', params: [{ address: '0x...', topics: ['0x...'], fromBlock: '0x0', toBlock: 'latest' }] }); // Returns { logs: [...], cursor: "..." } // Use cursor in next request to continue ``` ### Mini-Block Subscription ```javascript { "jsonrpc": "2.0", "method": "eth_subscribe", "params": ["miniBlocks"], "id": 1 } ``` **Mini-block schema:** ```json { "payload_id": "0x...", "block_number": 12345, "index": 0, "tx_offset": 0, "log_offset": 0, "gas_offset": 0, "timestamp": 1704067200000, "gas_used": 21000, "transactions": [...], "receipts": [...] } ``` Mini-blocks are ephemeral — cannot be fetched via RPC after assembly into blocks. ## WebSocket Guidelines ### Keepalive Required Send `eth_chainId` every 30 seconds to prevent disconnection: ```javascript const ws = new WebSocket('wss://mainnet.megaeth.com/ws'); const keepalive = setInterval(() => { ws.send(JSON.stringify({ jsonrpc: '2.0', method: 'eth_chainId', params: [], id: Date.now() })); }, 30000); ws.on('close', () => clearInterval(keepalive)); ``` ### Limits - 50 WebSocket connections per VIP endpoint - 10 subscriptions per connection (+1 on subscribe, -1 on unsubscribe) ### Supported Methods on WS - `eth_sendRawTransaction` - `eth_sendRawTransactionSync` - `eth_subscribe` / `eth_unsubscribe` - `eth_chainId` (for keepalive) ## Batching eth_call Requests (v2.0.14+) As of v2.0.14, **Multicall is the preferred approach** for batching `eth_call` requests. ### Why Multicall? With v2.0.14, `eth_call` is 2-10x faster. The EVM execution time is now a small fraction of total CPU time — most overhead is per-RPC framework cost. Multicall amortizes this overhead across multiple calls. ```typescript // ✅ Preferred: Multicall (v2.0.14+) import { multicall } from 'viem/actions'; const results = await multicall(client, { contracts: [ { address: token1, abi: erc20Abi, functionName: 'balanceOf', args: [user] }, { address: token2, abi: erc20Abi, functionName: 'balanceOf', args: [user] }, { address: token3, abi: erc20Abi, functionName: 'balanceOf', args: [user] }, ] }); ``` ### Historical Context Earlier MegaETH guidance recommended JSON-RPC batching over Multicall because: - Multicall made it difficult to cache `eth_call` results effectively - Certain dApps benefited significantly from this caching With v2.0.14's performance improvements, the caching mechanism is deprecated and Multicall is now preferred. ### Still Avoid - **Mixing slow + fast methods** — Don't batch `eth_getLogs` with `eth_call`; logs are always slower - **Blocking UX on historical queries** — Keep `eth_getLogs` in background ## Rate Limiting Public endpoints have rate limits based on: - CPU time consumption - Network bandwidth (32 MB/s average, 15x burst for VIP) ### Methods Vulnerable to Abuse These require VIP endpoints for heavy usage: - `eth_getLogs` (large block ranges) - `eth_call` (complex contracts) - `debug_*` / `trace_*` (disabled on public) ### Best Practices 1. **Warm up connections** — Call `eth_chainId` on app init to pre-establish HTTP connection (avoids DNS/TCP/TLS overhead on first real request) 2. **Use Multicall for eth_call batching** — Amortizes per-RPC overhead (v2.0.14+) 3. **Don't batch slow with fast** — `eth_getLogs` blocks entire batch response 4. **Use cursors** — `eth_getLogsWithCursor` instead of huge `eth_getLogs` 5. **Background historical queries** — Never block UX waiting for logs ## eth_getLogs Limits - Multi-block queries: max 20,000 logs per call - Single-block queries: no limit - Workaround: Get headers first to count logs, then build queries accordingly ## Historical Data Public endpoint supports `eth_call` on blocks from past ~15 days. For older data: - Use Alchemy/QuickNode - Run your own archive node - Use indexers (Envio HyperSync recommended) ## Latency Optimization MegaETH's real-time capabilities shine when you optimize for low latency. Here's what matters: ### Benchmarks (West Coast US → Public RPC) | Method | HTTP | WebSocket | |--------|------|-----------| | eth_chainId | 40ms | **7ms** | | eth_getBalance | 140ms | ~50ms | | eth_sendRawTransactionSync | 200-450ms | **150-300ms** | WebSocket is **5-6x faster** for simple calls due to persistent connection. ### 1. Use WebSocket Over HTTP ```typescript // ❌ Slow: HTTP per request (TCP + TLS handshake each time) const result = await fetch(RPC_URL, { method: 'POST', ... }); // ✅ Fast: Persistent WebSocket connection const ws = new WebSocket('wss://mainnet.megaeth.com/ws'); ws.send(JSON.stringify({ method: 'eth_sendRawTransactionSync', ... })); ``` ### 2. Pre-Sign Transactions Don't sign in the hot path. Prepare transactions ahead of time: ```typescript // Pre-sign with sequential nonces const nonce = await publicClient.getTransactionCount({ address }); const signedTxs = await Promise.all([ wallet.signTransaction({ ...baseTx, nonce: nonce }), wallet.signTransaction({ ...baseTx, nonce: nonce + 1 }), wallet.signTransaction({ ...baseTx, nonce: nonce + 2 }), ]); // Later: fire instantly when needed const receipt = await rpc('eth_sendRawTransactionSync', [signedTxs[0]]); ``` ### 3. Nonce Pipelining Don't wait for confirmations between transactions: ```typescript // ❌ Slow: Wait for each confirmation for (const tx of transactions) { const receipt = await sendAndWait(tx); } // ✅ Fast: Pipeline with sequential nonces let nonce = await getNonce(address); const receipts = await Promise.all( transactions.map((tx, i) => rpc('eth_sendRawTransactionSync', [ signTx({ ...tx, nonce: nonce + i }) ]) ) ); ``` ### 4. HTTP Keep-Alive If using HTTP, ensure connection reuse: ```typescript import https from 'https'; const agent = new https.Agent({ keepAlive: true, maxSockets: 10 }); // Reuse for all requests fetch(RPC_URL, { agent, ... }); ``` ### 5. Geographic Proximity | Setup | Latency | |-------|---------| | Cross-continent | 150-300ms RTT | | Same region (cloud) | 20-50ms RTT | | Local node | **<5ms RTT** | For ultra-low latency: - Use Alchemy/QuickNode geo-distributed endpoints - Run your own node in the same datacenter as your app ### 6. Batch RPC Calls ```typescript // ❌ Slow: 3 sequential calls = 3x latency const a = await rpc('eth_call', [params1]); const b = await rpc('eth_call', [params2]); const c = await rpc('eth_call', [params3]); // ✅ Fast: Single batch = 1x latency const [a, b, c] = await fetch(RPC_URL, { body: JSON.stringify([ { method: 'eth_call', params: [params1], id: 1 }, { method: 'eth_call', params: [params2], id: 2 }, { method: 'eth_call', params: [params3], id: 3 }, ]) }); ``` ### Theoretical Minimum Latency With optimal setup (local node + WebSocket + pre-signed): - Sign: ~1ms (pre-computed) - Network to local node: ~1ms - MegaETH processing: ~10ms - **Total: ~12ms** ## Debugging Commands ```bash # Estimate gas cast estimate \ --from 0xYourAddress \ --value 0.001ether \ 0xRecipient \ --rpc-url https://mainnet.megaeth.com/rpc # Get balance at block cast call --block 12345 0xContract "balanceOf(address)(uint256)" 0xAddress \ --rpc-url https://mainnet.megaeth.com/rpc # Trace transaction (requires VIP or local node) cast run --rpc-url ```