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.finalityon the ABCI process):- WebSocket:
GET /ws/finality(JSON messages per finalized/invalidated block) - Server‑Sent Events:
GET /sse/finality(data: {json}\n\nper event)
- WebSocket:
Important Differences vs. Geth
Transaction Hash Types
- Ethereum tx hash = keccak256(RLP). Use this with
eth_getTransaction*andeth_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_sendRawTransactiondefaults to "sync" (instant hash). SetUMOTU_TX_BROADCAST_MODE=committo 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)
eth_sendRawTransaction→ tx hash immediately (mode=sync)- Poll
eth_getTransactionReceiptuntil 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 stringeth_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 ratioseth_blobBaseFee()→0x0eth_syncing()→falseeth_protocolVersion()→0x1eth_mining()→falseeth_hashrate()→0x0eth_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
latestis supported;fromis ignored;gasoptional (defaults to ~15M if omitted). - Useful for
decimals()/ view calls when no separate geth RPC is exposed.
- Only
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 nulleth_getTransactionReceipt(hash)→ receipt or nulleth_getTransactionByBlockNumberAndIndex(blockTag, index)eth_getTransactionByBlockHashAndIndex(hash, index)eth_estimateGas(callObj, blockTag?)→ stubbed0x3b9aca00(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 $HASHcast tx $HASH --rpc-url $RPC_URL # repeats until it returns a receiptRAW=$(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
addressas string or array of strings;topicssupports OR in each position. blockHashrestricts 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 controlumotu_getFinalizedHead()→{ blockNumber, blockHash, cometbftHash, stateRoot, traceRoot, daCommitment, challengeEnds, finalized }
Dispute/Slashing (Internal Ops)
umotu_setDisputeResult(heightHex, validBool, token, challenger?)→ true | errorumotu_getDisputeEvents()→ array of dispute/finality eventsumotu_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_txdetails 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_URLUsage Tips & Pitfalls
- Hash mismatch: Do not pass CometBFT tx hash (from
broadcast_tx_*) toeth_getTransaction*; use the EVM hash frometh_sendRawTransactionorcast 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=commitand optionallyUMOTU_RPC_WAIT_RECEIPT_MSfor the local wait. Otherwise use the standard two‑step flow. - Rate limiting: Consider enabling nginx
rpc-limits.conffor 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, Tendermintcheck_tx/deliver_txfailures).
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 receiptOne‑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_URLTrace 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) |commitUMOTU_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 sourcingUMOTU_SLASH_WEBHOOK*: slashing executor integration
If something is missing or you need additional RPCs for tooling, open an issue or ping the core team.