reth_rpc_api/otterscan.rs
1use alloy_eips::{eip1898::LenientBlockNumberOrTag, BlockId};
2use alloy_json_rpc::RpcObject;
3use alloy_primitives::{Address, Bytes, TxHash, B256};
4use alloy_rpc_types_trace::otterscan::{
5 BlockDetails, ContractCreator, InternalOperation, OtsBlockTransactions, TraceEntry,
6 TransactionsWithReceipts,
7};
8use jsonrpsee::{core::RpcResult, proc_macros::rpc};
9
10/// Otterscan RPC interface.
11///
12/// Reth implements a subset of the API. In particular, address history search is unimplemented
13/// even though `getApiLevel` returns 8. Historical queries require the relevant state and history.
14#[rpc(server, namespace = "ots")]
15pub trait Otterscan<T: RpcObject, H: RpcObject> {
16 /// Get the block header by block number, required by otterscan.
17 /// Otterscan currently requires this endpoint, used as:
18 ///
19 /// 1. check if the node is Erigon or not
20 /// 2. get block header instead of the full block
21 ///
22 /// Ref: <https://github.com/otterscan/otterscan/blob/071d8c55202badf01804f6f8d53ef9311d4a9e47/src/useProvider.ts#L71>
23 #[method(name = "getHeaderByNumber", aliases = ["erigon_getHeaderByNumber"])]
24 async fn get_header_by_number(
25 &self,
26 block_number: LenientBlockNumberOrTag,
27 ) -> RpcResult<Option<H>>;
28
29 /// Check if a certain address contains a deployed code.
30 #[method(name = "hasCode")]
31 async fn has_code(&self, address: Address, block_id: Option<BlockId>) -> RpcResult<bool>;
32
33 /// Returns API level 8 for frontend compatibility, not a guarantee of complete support.
34 /// In particular, both address history search methods remain unimplemented.
35 #[method(name = "getApiLevel")]
36 async fn get_api_level(&self) -> RpcResult<u64>;
37
38 /// Return the internal ETH transfers inside a transaction.
39 #[method(name = "getInternalOperations")]
40 async fn get_internal_operations(&self, tx_hash: TxHash) -> RpcResult<Vec<InternalOperation>>;
41
42 /// Given a transaction hash, returns its raw revert reason.
43 /// Known transactions without revert data return empty bytes; unknown transactions return
44 /// `None`.
45 #[method(name = "getTransactionError")]
46 async fn get_transaction_error(&self, tx_hash: TxHash) -> RpcResult<Option<Bytes>>;
47
48 /// Extract all variations of calls, contract creation and self-destructs and returns a call
49 /// tree.
50 #[method(name = "traceTransaction")]
51 async fn trace_transaction(&self, tx_hash: TxHash) -> RpcResult<Option<Vec<TraceEntry>>>;
52
53 /// Tailor-made and expanded version of `eth_getBlockByNumber` for block details page in
54 /// Otterscan.
55 #[method(name = "getBlockDetails")]
56 async fn get_block_details(
57 &self,
58 block_number: LenientBlockNumberOrTag,
59 ) -> RpcResult<BlockDetails<H>>;
60
61 /// Tailor-made and expanded version of `eth_getBlockByHash` for block details page in
62 /// Otterscan.
63 #[method(name = "getBlockDetailsByHash")]
64 async fn get_block_details_by_hash(&self, block_hash: B256) -> RpcResult<BlockDetails<H>>;
65
66 /// Get paginated transactions for a certain block. Also remove some verbose fields like logs.
67 /// Page zero selects the block's last transactions; each page retains ascending block order.
68 #[method(name = "getBlockTransactions")]
69 async fn get_block_transactions(
70 &self,
71 block_number: LenientBlockNumberOrTag,
72 page_number: usize,
73 page_size: usize,
74 ) -> RpcResult<OtsBlockTransactions<T, H>>;
75
76 /// Gets paginated inbound/outbound transaction calls for a certain address.
77 ///
78 /// Unimplemented: returns JSON-RPC error -32603 with message "unimplemented".
79 /// See <https://github.com/paradigmxyz/reth/issues/13499>.
80 #[method(name = "searchTransactionsBefore")]
81 async fn search_transactions_before(
82 &self,
83 address: Address,
84 block_number: LenientBlockNumberOrTag,
85 page_size: usize,
86 ) -> RpcResult<TransactionsWithReceipts>;
87
88 /// Gets paginated inbound/outbound transaction calls for a certain address.
89 ///
90 /// Unimplemented: returns JSON-RPC error -32603 with message "unimplemented".
91 /// See <https://github.com/paradigmxyz/reth/issues/13499>.
92 #[method(name = "searchTransactionsAfter")]
93 async fn search_transactions_after(
94 &self,
95 address: Address,
96 block_number: LenientBlockNumberOrTag,
97 page_size: usize,
98 ) -> RpcResult<TransactionsWithReceipts>;
99
100 /// Gets the transaction hash for a certain sender address, given its nonce.
101 #[method(name = "getTransactionBySenderAndNonce")]
102 async fn get_transaction_by_sender_and_nonce(
103 &self,
104 sender: Address,
105 nonce: u64,
106 ) -> RpcResult<Option<TxHash>>;
107
108 /// Gets the transaction hash and the address who created a contract.
109 /// Requires historical state. Code-presence binary search is unreliable for destroyed and
110 /// redeployed contracts, and cannot identify genesis allocations or EIP-7702 delegations.
111 #[method(name = "getContractCreator")]
112 async fn get_contract_creator(&self, address: Address) -> RpcResult<Option<ContractCreator>>;
113}