Umotu Explorer
Home/docs/JSON-RPC

Umotu JSON-RPC Guide

This guide documents the JSON‑RPC methods exposed by the Umotu ABCI RPC shim and Umotu‑specific extensions. It's aimed at developers integrating wallets, tooling (cast/forge/web3), and infrastructure.

Endpoints

  • Base HTTP endpoint: POST /rpc (e.g., http://<node>:8080/rpc)
  • WebSocket endpoint: GET /ws (logs/newHeads not supported; see notes)
  • CometBFT RPC (consensus): http://<node>:26657 (for CheckTx/DeliverTx details)
  • Finality push (enable with -ws.finality on the ABCI process):
    • WebSocket: GET /ws/finality (JSON messages per finalized/invalidated block)
    • Server‑Sent Events: GET /sse/finality (data: {json}\n\n per event)

Important Differences vs. Geth

Transaction Hash Types

  • Ethereum tx hash = keccak256(RLP). Use this with eth_getTransaction* and eth_getTransactionReceipt.
  • CometBFT tx hash = sha256(tx bytes). Returned by /broadcast_tx_* on port 26657. Do not pass that to ETH JSON‑RPC.

Send Semantics (Configurable)

  • eth_sendRawTransaction defaults to "sync" (instant hash). Set UMOTU_TX_BROADCAST_MODE=commit to run DeliverTx and surface Tendermint errors during send.
  • Optional receipt wait after commit: UMOTU_RPC_WAIT_RECEIPT_MS (0 = don't wait).

One‑Call Helper (Optional)

  • umotu_sendRawAndWait(rawTx, waitMsHex?) broadcasts via DeliverTx and returns a full receipt after the local node indexes it (or an error / receipt_timeout).

Typical Flows

Standard Two-Step (Like Geth)

  1. eth_sendRawTransaction → tx hash immediately (mode=sync)
  2. Poll eth_getTransactionReceipt until non‑null

One-Call Receipt (Ops)

umotu_sendRawAndWait → full receipt or error, deterministic on one node

Standard ETH/WEB3 Methods

Network Information

  • web3_clientVersion()"umotu-abci/0.3"
  • net_version() → decimal chain ID as string
  • eth_chainId() → hex chain ID (e.g., 0x2581)
  • eth_blockNumber() → latest block number (hex)
  • eth_gasPrice() → base fee (hex)
  • eth_maxPriorityFeePerGas()0x0 (tips not used in this network)
  • eth_feeHistory(blockCount, newestBlock, rewardPercentiles?) → stubbed base fees/gas ratios
  • eth_blobBaseFee()0x0
  • eth_syncing()false
  • eth_protocolVersion()0x1
  • eth_mining()false
  • eth_hashrate()0x0
  • eth_coinbase() → miner (proposer) address for the latest block

Accounts / State

  • eth_getBalance(address, blockTag="latest") → balance (hex)
  • eth_getTransactionCount(address, blockTag="latest") → nonce (hex)
  • eth_getCode(address, blockTag="latest") → code (hex)
  • eth_getStorageAt(address, position, blockTag="latest") → storage slot value (hex)
  • eth_call(callObj, blockTag="latest") → return data (hex)
    • Only latest is supported; from is ignored; gas optional (defaults to ~15M if omitted).
    • Useful for decimals() / view calls when no separate geth RPC is exposed.
  • eth_getProof(address, storageKeys[], blockTag="latest") → account & storage proofs (Merkle nodes as hex strings)

Blocks

  • eth_getBlockByNumber(blockTag, includeTransactions)
  • eth_getBlockByHash(hash, includeTransactions)
  • eth_getBlockTransactionCountByNumber(blockTag)
  • eth_getBlockTransactionCountByHash(hash)

Notes: includeTransactions=false → array of tx hashes; true → array of tx objects (from/to/fee fields etc.). Parent/receipt roots are included in block responses under internal fields where applicable.

Transactions

  • eth_sendRawTransaction(rawTx)
  • eth_getTransactionByHash(hash) → tx object or null
  • eth_getTransactionReceipt(hash) → receipt or null
  • eth_getTransactionByBlockNumberAndIndex(blockTag, index)
  • eth_getTransactionByBlockHashAndIndex(hash, index)
  • eth_estimateGas(callObj, blockTag?) → stubbed 0x3b9aca00 (1e9) (do not rely on this yet)
RAW=$(cast mktx 0x<to> --value 0.1ether --rpc-url $RPC_URL --private-key $PK --gas-limit 21000)
HASH=$(cast rpc eth_sendRawTransaction $RAW --rpc-url $RPC_URL | jq -r .result)
echo $HASH
cast tx $HASH --rpc-url $RPC_URL  # repeats until it returns a receipt
RAW=$(cast mktx 0x<to> --value 0.02ether --rpc-url $RPC_URL --private-key $PK --gas-limit 21000)
curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_sendRawTransaction","params":["'"$RAW"'"]}'
# => {"jsonrpc":"2.0","id":1,"result":"0x<evmHash>"}
curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":2,"method":"eth_getTransactionReceipt","params":["0x<evmHash>"]}'

Logs / Filters

  • eth_getLogs(filter) → array of logs matching { fromBlock, toBlock, address, topics, blockHash }
  • Supports address as string or array of strings; topics supports OR in each position.
  • blockHash restricts to a single block (matches EVM hash or CometBFT hash).
  • eth_subscribe / eth_unsubscribe → not supported (use polling)

Umotu Extensions (umotu_*)

Trace Methods

  • umotu_getTraceRoot(blockTag){ blockNumber, blockHash, cometbftHash, traceRoot }
  • umotu_getTraceProof(heightHex, indexHex){ blockNumber, traceRoot, leaf, index, proof[] }
  • umotu_getTraceSlice(blockTag|"latest", startHex, countHex){ items: [...], sharedProofs?, next? }
    • Returns contiguous tx slice with per‑tx proof or proof indices into sharedProofs.
curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"umotu_getTraceRoot","params":["latest"]}' | jq .
curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"umotu_getTraceSlice","params":["latest","0x0","0x10"]}' | jq .
curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"umotu_getTraceProof","params":["0x12f5","0x0"]}' | jq .

Data Availability

  • umotu_getDACommitment(blockTag|"latest"){ blockNumber, commitment, params? }
  • params: { scheme, k, n, chunkSize, chunkCount, blobId, providers[] }
curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"umotu_getDACommitment","params":["latest"]}' | jq .
# => { blockNumber, commitment, params: { scheme: "xor-erasure-v1", k, n, chunkSize, chunkCount, blobId, providers: [...] } }

State & Finalization

  • umotu_getStateRoot(blockTag|"latest")0x...
  • umotu_getRetention() / umotu_setRetention(blocks) → retention info and control
  • umotu_getFinalizedHead(){ blockNumber, blockHash, cometbftHash, stateRoot, traceRoot, daCommitment, challengeEnds, finalized }

Dispute/Slashing (Internal Ops)

  • umotu_setDisputeResult(heightHex, validBool, token, challenger?) → true | error
  • umotu_getDisputeEvents() → array of dispute/finality events
  • umotu_getSlashQueue() → array of pending slash actions

One‑Call Helper (Optional)

  • umotu_sendRawAndWait(rawTxHex, waitMsHex?) → receipt | error
  • Broadcasts via commit; waits until local index has the tx (default 10s; env UMOTU_RPC_WAIT_RECEIPT_MS) then returns a full receipt object.
  • On failure: returns JSON‑RPC error with check_tx/deliver_tx details and { hash } in the result for diagnostics.
RAW=$(cast mktx 0x<to> --value 0.1ether --rpc-url $RPC_URL --private-key $PK --gas-limit 21000)
cast rpc umotu_sendRawAndWait $RAW --rpc-url $RPC_URL

Usage Tips & Pitfalls

  • Hash mismatch: Do not pass CometBFT tx hash (from broadcast_tx_*) to eth_getTransaction*; use the EVM hash from eth_sendRawTransaction or cast keccak <raw>.
  • Single node for send+poll: To avoid receipt races, use the same node for both (no LB rotation). If you must use an LB, prefer client‑IP sticky hashing and disable POST retries.
  • Timeouts: If you rely on blocking sends, set UMOTU_TX_BROADCAST_MODE=commit and optionally UMOTU_RPC_WAIT_RECEIPT_MS for the local wait. Otherwise use the standard two‑step flow.
  • Rate limiting: Consider enabling nginx rpc-limits.conf for public endpoints.

Finality Push Endpoints

Enable at startup with -ws.finality (already set in our docker compose). Two options:

WebSocket (/ws/finality)

Emits JSON objects with fields height, valid, blockHash, traceRoot, stateRoot, receiptRoot, proposer, challenger, slashProposer, rewardChallenger.

SSE (/sse/finality)

Emits Server‑Sent Events where the body is a JSON object as above.

curl -N http://<node>:8080/sse/finality
# data: {"height":123,"valid":true,"blockHash":"0x...","traceRoot":"0x...","stateRoot":"0x...","receiptRoot":"0x...","proposer":"0x...","challenger":"0x...","slashProposer":false,"rewardChallenger":false}

Batch JSON‑RPC

The /rpc handler supports batch arrays per JSON‑RPC 2.0. You can POST an array of request objects and receive an array of responses. Order is preserved (responses are returned in the same order as requests).

Behavior

  • Empty batch [] → JSON‑RPC error -32600 invalid request.
  • Parse error → -32700.
  • Unknown method → -32601 method not found.
  • Implemented methods may still return application errors as -32000 (e.g., method_not_supported, Tendermint check_tx/deliver_tx failures).

Mixed Batch (blockNumber + chainId)

curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '[
    {"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]},
    {"jsonrpc":"2.0","id":2,"method":"eth_chainId","params":[]}
  ]' | jq .

Batch with Custom Methods

curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '[
    {"jsonrpc":"2.0","id":"a","method":"umotu_getTraceRoot","params":["latest"]},
    {"jsonrpc":"2.0","id":"b","method":"umotu_getDACommitment","params":["latest"]}
  ]' | jq .

Empty Batch (Error Demo)

curl -s -X POST $RPC_URL -H 'content-type: application/json' --data '[]'
# => {"jsonrpc":"2.0","error":{"code":-32600,"message":"invalid request"},"id":null}

Examples

Send + Poll (Standard)

RAW=$(cast mktx 0x<to> --value 0.1ether --rpc-url $RPC_URL --private-key $PK --gas-limit 21000)
HASH=$(cast rpc eth_sendRawTransaction $RAW --rpc-url $RPC_URL | jq -r .result)
echo $HASH
cast tx $HASH --rpc-url $RPC_URL  # repeats until it returns a receipt

One‑Call Receipt (Ops)

RAW=$(cast mktx 0x<to> --value 0.1ether --rpc-url $RPC_URL --private-key $PK --gas-limit 21000)
cast rpc umotu_sendRawAndWait $RAW --rpc-url $RPC_URL

Trace Slice (Latest Block, First 16 Txs)

curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"umotu_getTraceSlice","params":["latest","0x0","0x10"]}' | jq .

Get Block by Number (With Txs)

curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["0x1","true"]}' | jq .

Filters and Logs

# Logs from a single contract since block 0x100
curl -s -X POST $RPC_URL -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_getLogs","params":[{"fromBlock":"0x100","address":"0x<contract>"}]}' | jq .

Environment Variables (Node‑Side)

  • UMOTU_TX_BROADCAST_MODE: sync (default) | commit
  • UMOTU_RPC_WAIT_RECEIPT_MS: ms to wait for local indexing after commit (0 disables)
  • UMOTU_DA_SERVICE_URL, UMOTU_DA_CHUNK_SIZE, UMOTU_DA_PARITY_CHUNKS, UMOTU_DA_PROVIDERS: DA commitment sourcing
  • UMOTU_SLASH_WEBHOOK*: slashing executor integration

If something is missing or you need additional RPCs for tooling, open an issue or ping the core team.