Skip to main content

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}