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