From b0f2e1179cf248e040344cf7ca5293eded5df656 Mon Sep 17 00:00:00 2001 From: ZePedroResende Date: Wed, 12 Jul 2023 22:02:42 +0100 Subject: [PATCH 1/7] Adding ots_ namespace and trait bindings Co-Authored-By: Miguel Palhas --- crates/rpc/rpc-api/src/lib.rs | 3 + crates/rpc/rpc-api/src/otterscan.rs | 85 +++++++++++++++++++++++++++ crates/rpc/rpc-builder/src/lib.rs | 12 +++- crates/rpc/rpc-types/src/lib.rs | 2 + crates/rpc/rpc-types/src/otterscan.rs | 72 +++++++++++++++++++++++ crates/rpc/rpc/src/lib.rs | 2 + crates/rpc/rpc/src/otterscan.rs | 85 +++++++++++++++++++++++++++ 7 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 crates/rpc/rpc-api/src/otterscan.rs create mode 100644 crates/rpc/rpc-types/src/otterscan.rs create mode 100644 crates/rpc/rpc/src/otterscan.rs diff --git a/crates/rpc/rpc-api/src/lib.rs b/crates/rpc/rpc-api/src/lib.rs index acca756711c..b9c17e8b2b4 100644 --- a/crates/rpc/rpc-api/src/lib.rs +++ b/crates/rpc/rpc-api/src/lib.rs @@ -26,6 +26,7 @@ mod eth; mod eth_filter; mod eth_pubsub; mod net; +mod otterscan; mod rpc; mod trace; mod txpool; @@ -44,6 +45,7 @@ pub mod servers { eth_filter::EthFilterApiServer, eth_pubsub::EthPubSubApiServer, net::NetApiServer, + otterscan::OtterscanServer, rpc::RpcApiServer, trace::TraceApiServer, txpool::TxPoolApiServer, @@ -64,6 +66,7 @@ pub mod clients { engine::{EngineApiClient, EngineEthApiClient}, eth::EthApiClient, net::NetApiClient, + otterscan::OtterscanClient, rpc::RpcApiServer, trace::TraceApiClient, txpool::TxPoolApiClient, diff --git a/crates/rpc/rpc-api/src/otterscan.rs b/crates/rpc/rpc-api/src/otterscan.rs new file mode 100644 index 00000000000..fba34efc429 --- /dev/null +++ b/crates/rpc/rpc-api/src/otterscan.rs @@ -0,0 +1,85 @@ +use jsonrpsee::{core::RpcResult, proc_macros::rpc}; +use reth_primitives::{Address, BlockId, TxHash, H256, U256}; +use reth_rpc_types::{ + BlockDetails, ContractCreator, InternalOperation, TraceEntry, Transaction, + TransactionsWithReceipts, +}; + +/// Otterscan rpc interface. +#[cfg_attr(not(feature = "client"), rpc(server, namespace = "ots"))] +#[cfg_attr(feature = "client", rpc(server, client, namespace = "ots"))] +pub trait Otterscan { + /// Check if a certain address contains a deployed code. + #[method(name = "hasCode")] + async fn has_code(&self, address: Address, block_number: Option) -> RpcResult; + + /// Very simple API versioning scheme. Every time we add a new capability, the number is + /// incremented. This allows for Otterscan to check if the Erigon node contains all API it + /// needs. + #[method(name = "getApiLevel")] + async fn get_api_level(&self) -> RpcResult; + + /// Return the internal ETH transfers inside a transaction. + #[method(name = "getInternalOperations")] + async fn get_internal_operations(&self, tx_hash: TxHash) -> RpcResult>; + + /// Given a transaction hash, returns its raw revert reason. + #[method(name = "getTransactionError")] + async fn get_transaction_error(&self, tx_hash: TxHash) -> RpcResult; + + /// Extract all variations of calls, contract creation and self-destructs and returns a call + /// tree. + #[method(name = "traceTransaction")] + async fn trace_transaction(&self, tx_hash: TxHash) -> RpcResult; + + /// Tailor-made and expanded version of eth_getBlockByNumber for block details page in + /// Otterscan. + #[method(name = "getBlockDetails")] + async fn get_block_details(&self, block_number: U256) -> RpcResult; + + /// Tailor-made and expanded version of eth_getBlockByHash for block details page in Otterscan. + #[method(name = "getBlockDetailsByHash")] + async fn get_block_details_by_hash(&self, block_hash: H256) -> RpcResult; + + /// Get paginated transactions for a certain block. Also remove some verbose fields like logs. + #[method(name = "getBlockTransactions")] + async fn get_block_transactions( + &self, + block_number: U256, + page_number: u8, + page_size: u8, + ) -> RpcResult>; + + //custom return + /// Gets paginated inbound/outbound transaction calls for a certain address. + #[method(name = "searchTransactionsBefore")] + async fn search_transactions_before( + &self, + address: Address, + block_number: U256, + page_size: u8, + ) -> RpcResult; + + //custom return + /// Gets paginated inbound/outbound transaction calls for a certain address. + #[method(name = "searchTransactionsAfter")] + async fn search_transactions_after( + &self, + address: Address, + block_number: U256, + page_size: u8, + ) -> RpcResult; + + /// Gets the transaction hash for a certain sender address, given its nonce. + #[method(name = "getTransactionBySenderAndNonce")] + async fn get_transaction_by_sender_and_nonce( + &self, + sender: Address, + nonce: u64, + ) -> RpcResult; + + //custom return + /// Gets the transaction hash and the address who created a contract. + #[method(name = "getContractCreator")] + async fn get_contract_creator(&self, address: Address) -> RpcResult; +} diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index eb9f0d1fd39..d5242f51d98 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -122,7 +122,7 @@ use reth_rpc::{ gas_oracle::GasPriceOracle, }, AdminApi, DebugApi, EngineEthApi, EthApi, EthFilter, EthPubSub, EthSubscriptionIdProvider, - NetApi, RPCApi, TraceApi, TracingCallGuard, TxPoolApi, Web3Api, + NetApi, OtterscanApi, RPCApi, TraceApi, TracingCallGuard, TxPoolApi, Web3Api, }; use reth_rpc_api::{servers::*, EngineApiServer}; use reth_tasks::{TaskSpawner, TokioTaskExecutor}; @@ -646,6 +646,8 @@ pub enum RethRpcModule { Web3, /// `rpc_` module Rpc, + /// `ots_` module + Ots, } // === impl RethRpcModule === @@ -773,6 +775,13 @@ where self } + /// Register Otterscan Namespace + pub fn register_ots(&mut self) -> &mut Self { + let eth_api = self.eth_api(); + self.modules.insert(RethRpcModule::Ots, OtterscanApi::new(eth_api).into_rpc().into()); + self + } + /// Register Debug Namespace pub fn register_debug(&mut self) -> &mut Self { let eth_api = self.eth_api(); @@ -921,6 +930,7 @@ where ) .into_rpc() .into(), + RethRpcModule::Ots => OtterscanApi::new(eth_api.clone()).into_rpc().into(), }) .clone() }) diff --git a/crates/rpc/rpc-types/src/lib.rs b/crates/rpc/rpc-types/src/lib.rs index 64d6537291e..8b3542e6d35 100644 --- a/crates/rpc/rpc-types/src/lib.rs +++ b/crates/rpc/rpc-types/src/lib.rs @@ -17,8 +17,10 @@ mod admin; mod eth; +mod otterscan; mod rpc; pub use admin::*; pub use eth::*; +pub use otterscan::*; pub use rpc::*; diff --git a/crates/rpc/rpc-types/src/otterscan.rs b/crates/rpc/rpc-types/src/otterscan.rs new file mode 100644 index 00000000000..5adfe83d621 --- /dev/null +++ b/crates/rpc/rpc-types/src/otterscan.rs @@ -0,0 +1,72 @@ +use crate::{Block, Transaction, TransactionReceipt}; +use reth_primitives::{Address, Bytes}; +use serde::{Deserialize, Serialize}; + +/// Operation type enum for `InternalOperation` struct +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub enum OperationType { + /// Operation Transfer + OpTransfer, + /// Operation Contract self destruct + OpSelfDestruct, + /// Operation Create + OpCreate, + /// Operation Create2 + OpCreate2, +} + +/// Custom struct for otterscan `getInternalOperations` RPC response +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct InternalOperation { + r#type: OperationType, + from: Address, + to: Address, + value: u128, +} + +/// Custom struct for otterscan `traceTransaction` RPC response +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct TraceEntry { + r#type: String, + depth: u32, + from: Address, + to: Address, + value: u128, + input: Bytes, +} + +/// Internal issuance struct for `BlockDetails` struct +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InternalIssuance { + block_reward: String, + uncle_reward: String, + issuance: String, +} + +/// Custom struct for otterscan `getBlockDetails` RPC response +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BlockDetails { + block: Block, + issuance: InternalIssuance, + total_fees: u64, +} + +/// Custom struct for otterscan `searchTransactionsAfter`and `searchTransactionsBefore` RPC +/// responses +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TransactionsWithReceipts { + txs: Vec, + receipts: TransactionReceipt, + first_page: bool, + last_page: bool, +} + +/// Custom struct for otterscan `getContractCreator` RPC responses +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct ContractCreator { + tx: Transaction, + creator: Address, +} diff --git a/crates/rpc/rpc/src/lib.rs b/crates/rpc/rpc/src/lib.rs index 8ec0893a028..dfd5efbd134 100644 --- a/crates/rpc/rpc/src/lib.rs +++ b/crates/rpc/rpc/src/lib.rs @@ -37,6 +37,7 @@ mod engine; pub mod eth; mod layers; mod net; +mod otterscan; mod rpc; mod trace; mod txpool; @@ -49,6 +50,7 @@ pub use engine::{EngineApi, EngineEthApi}; pub use eth::{EthApi, EthApiSpec, EthFilter, EthPubSub, EthSubscriptionIdProvider}; pub use layers::{AuthLayer, AuthValidator, Claims, JwtAuthValidator, JwtError, JwtSecret}; pub use net::NetApi; +pub use otterscan::OtterscanApi; pub use rpc::RPCApi; pub use trace::TraceApi; pub use txpool::TxPoolApi; diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs new file mode 100644 index 00000000000..9b1dc4f1106 --- /dev/null +++ b/crates/rpc/rpc/src/otterscan.rs @@ -0,0 +1,85 @@ +#![allow(dead_code, unused_variables)] +use async_trait::async_trait; +use jsonrpsee::core::RpcResult; +use reth_primitives::{Address, BlockId, TxHash, H256, U256}; +use reth_rpc_api::{EthApiServer, OtterscanServer}; +use reth_rpc_types::{ + BlockDetails, ContractCreator, InternalOperation, TraceEntry, Transaction, + TransactionsWithReceipts, +}; + +/// Otterscan Api +#[derive(Debug)] +pub struct OtterscanApi { + eth: Eth, +} + +impl OtterscanApi { + /// Creates a new instance of `Otterscan`. + pub fn new(eth: Eth) -> Self { + Self { eth } + } +} +#[async_trait] +impl OtterscanServer for OtterscanApi +where + Eth: EthApiServer, +{ + async fn has_code(&self, address: Address, block_number: Option) -> RpcResult { + todo!() + } + + async fn get_api_level(&self) -> RpcResult { + todo!() + } + async fn get_internal_operations(&self, tx_hash: TxHash) -> RpcResult> { + todo!() + } + async fn get_transaction_error(&self, tx_hash: TxHash) -> RpcResult { + todo!() + } + async fn trace_transaction(&self, tx_hash: TxHash) -> RpcResult { + todo!() + } + async fn get_block_details(&self, block_number: U256) -> RpcResult { + todo!() + } + async fn get_block_details_by_hash(&self, block_hash: H256) -> RpcResult { + todo!() + } + async fn get_block_transactions( + &self, + block_number: U256, + page_number: u8, + page_size: u8, + ) -> RpcResult> { + todo!() + } + + async fn search_transactions_before( + &self, + address: Address, + block_number: U256, + page_size: u8, + ) -> RpcResult { + todo!() + } + async fn search_transactions_after( + &self, + address: Address, + block_number: U256, + page_size: u8, + ) -> RpcResult { + todo!() + } + async fn get_transaction_by_sender_and_nonce( + &self, + sender: Address, + nonce: u64, + ) -> RpcResult { + todo!() + } + async fn get_contract_creator(&self, address: Address) -> RpcResult { + todo!() + } +} From 92852f78d81d65c1d9f72c7afe13a82c8c5ecb23 Mon Sep 17 00:00:00 2001 From: ZePedroResende Date: Fri, 14 Jul 2023 15:48:38 +0100 Subject: [PATCH 2/7] code review --- crates/rpc/rpc-api/src/otterscan.rs | 3 -- crates/rpc/rpc/src/otterscan.rs | 47 +++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/crates/rpc/rpc-api/src/otterscan.rs b/crates/rpc/rpc-api/src/otterscan.rs index fba34efc429..4be0715c4ed 100644 --- a/crates/rpc/rpc-api/src/otterscan.rs +++ b/crates/rpc/rpc-api/src/otterscan.rs @@ -50,7 +50,6 @@ pub trait Otterscan { page_size: u8, ) -> RpcResult>; - //custom return /// Gets paginated inbound/outbound transaction calls for a certain address. #[method(name = "searchTransactionsBefore")] async fn search_transactions_before( @@ -60,7 +59,6 @@ pub trait Otterscan { page_size: u8, ) -> RpcResult; - //custom return /// Gets paginated inbound/outbound transaction calls for a certain address. #[method(name = "searchTransactionsAfter")] async fn search_transactions_after( @@ -78,7 +76,6 @@ pub trait Otterscan { nonce: u64, ) -> RpcResult; - //custom return /// Gets the transaction hash and the address who created a contract. #[method(name = "getContractCreator")] async fn get_contract_creator(&self, address: Address) -> RpcResult; diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index 9b1dc4f1106..0f5a0f54444 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -1,4 +1,5 @@ #![allow(dead_code, unused_variables)] +use crate::result::internal_rpc_err; use async_trait::async_trait; use jsonrpsee::core::RpcResult; use reth_primitives::{Address, BlockId, TxHash, H256, U256}; @@ -20,66 +21,88 @@ impl OtterscanApi { Self { eth } } } + #[async_trait] impl OtterscanServer for OtterscanApi where Eth: EthApiServer, { + /// Handler for `ots_hasCode` async fn has_code(&self, address: Address, block_number: Option) -> RpcResult { - todo!() + Err(internal_rpc_err("unimplemented")) } + /// Handler for `ots_getApiLevel` async fn get_api_level(&self) -> RpcResult { - todo!() + Err(internal_rpc_err("unimplmented")) } + + /// Handler for `ots_getInternalOperations` async fn get_internal_operations(&self, tx_hash: TxHash) -> RpcResult> { - todo!() + Err(internal_rpc_err("unimplemented")) } + + /// Handler for `ots_getTransactionError` async fn get_transaction_error(&self, tx_hash: TxHash) -> RpcResult { - todo!() + Err(internal_rpc_err("unimplmented")) } + + /// Handler for `ots_traceTransaction` async fn trace_transaction(&self, tx_hash: TxHash) -> RpcResult { - todo!() + Err(internal_rpc_err("unimplmented")) } + + /// Handler for `ots_getBlockDetails` async fn get_block_details(&self, block_number: U256) -> RpcResult { - todo!() + Err(internal_rpc_err("unimplemented")) } + + /// Handler for `getBlockDetailsByHash` async fn get_block_details_by_hash(&self, block_hash: H256) -> RpcResult { - todo!() + Err(internal_rpc_err("unimplmented")) } + + /// Handler for `getBlockTransactions` async fn get_block_transactions( &self, block_number: U256, page_number: u8, page_size: u8, ) -> RpcResult> { - todo!() + Err(internal_rpc_err("unimplmented")) } + /// Handler for `searchTransactionsBefore` async fn search_transactions_before( &self, address: Address, block_number: U256, page_size: u8, ) -> RpcResult { - todo!() + Err(internal_rpc_err("unimplmented")) } + + /// Handler for `searchTransactionsAfter` async fn search_transactions_after( &self, address: Address, block_number: U256, page_size: u8, ) -> RpcResult { - todo!() + Err(internal_rpc_err("unimplmented")) } + + /// Handler for `getTransactionBySenderAndNonce` async fn get_transaction_by_sender_and_nonce( &self, sender: Address, nonce: u64, ) -> RpcResult { - todo!() + Err(internal_rpc_err("unimplmented")) } + + /// Handler for `getContractCreator` async fn get_contract_creator(&self, address: Address) -> RpcResult { - todo!() + Err(internal_rpc_err("unimplmented")) } } From ab84d33a3603dbe19b8b94e16f92cb34e2d7dcd1 Mon Sep 17 00:00:00 2001 From: ZePedroResende Date: Fri, 14 Jul 2023 19:06:42 +0100 Subject: [PATCH 3/7] code review --- crates/rpc/rpc-api/src/otterscan.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rpc/rpc-api/src/otterscan.rs b/crates/rpc/rpc-api/src/otterscan.rs index 4be0715c4ed..b0558442934 100644 --- a/crates/rpc/rpc-api/src/otterscan.rs +++ b/crates/rpc/rpc-api/src/otterscan.rs @@ -14,7 +14,7 @@ pub trait Otterscan { async fn has_code(&self, address: Address, block_number: Option) -> RpcResult; /// Very simple API versioning scheme. Every time we add a new capability, the number is - /// incremented. This allows for Otterscan to check if the Erigon node contains all API it + /// incremented. This allows for Otterscan to check if the node contains all API it /// needs. #[method(name = "getApiLevel")] async fn get_api_level(&self) -> RpcResult; From fdb04f3b63e9d6ea74ca2885204cfd2701d44a03 Mon Sep 17 00:00:00 2001 From: ZePedroResende Date: Sat, 15 Jul 2023 22:18:15 +0100 Subject: [PATCH 4/7] code review --- crates/rpc/rpc-builder/src/lib.rs | 1 + crates/rpc/rpc/src/otterscan.rs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index d5242f51d98..e6034de1562 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -1763,6 +1763,7 @@ mod tests { "trace" => RethRpcModule::Trace, "web3" => RethRpcModule::Web3, "rpc" => RethRpcModule::Rpc, + "ots" => RethRpcModule::Ots, ); } diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index 0f5a0f54444..9bc5d0cf734 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -34,7 +34,7 @@ where /// Handler for `ots_getApiLevel` async fn get_api_level(&self) -> RpcResult { - Err(internal_rpc_err("unimplmented")) + Err(internal_rpc_err("unimplemented")) } /// Handler for `ots_getInternalOperations` @@ -44,12 +44,12 @@ where /// Handler for `ots_getTransactionError` async fn get_transaction_error(&self, tx_hash: TxHash) -> RpcResult { - Err(internal_rpc_err("unimplmented")) + Err(internal_rpc_err("unimplemented")) } /// Handler for `ots_traceTransaction` async fn trace_transaction(&self, tx_hash: TxHash) -> RpcResult { - Err(internal_rpc_err("unimplmented")) + Err(internal_rpc_err("unimplemented")) } /// Handler for `ots_getBlockDetails` @@ -59,7 +59,7 @@ where /// Handler for `getBlockDetailsByHash` async fn get_block_details_by_hash(&self, block_hash: H256) -> RpcResult { - Err(internal_rpc_err("unimplmented")) + Err(internal_rpc_err("unimplemented")) } /// Handler for `getBlockTransactions` @@ -69,7 +69,7 @@ where page_number: u8, page_size: u8, ) -> RpcResult> { - Err(internal_rpc_err("unimplmented")) + Err(internal_rpc_err("unimplemented")) } /// Handler for `searchTransactionsBefore` @@ -79,7 +79,7 @@ where block_number: U256, page_size: u8, ) -> RpcResult { - Err(internal_rpc_err("unimplmented")) + Err(internal_rpc_err("unimplemented")) } /// Handler for `searchTransactionsAfter` @@ -89,7 +89,7 @@ where block_number: U256, page_size: u8, ) -> RpcResult { - Err(internal_rpc_err("unimplmented")) + Err(internal_rpc_err("unimplemented")) } /// Handler for `getTransactionBySenderAndNonce` @@ -98,11 +98,11 @@ where sender: Address, nonce: u64, ) -> RpcResult { - Err(internal_rpc_err("unimplmented")) + Err(internal_rpc_err("unimplemented")) } /// Handler for `getContractCreator` async fn get_contract_creator(&self, address: Address) -> RpcResult { - Err(internal_rpc_err("unimplmented")) + Err(internal_rpc_err("unimplemented")) } } From a39b60a9d4d925c9828b59592cd211c61c73e837 Mon Sep 17 00:00:00 2001 From: ZePedroResende Date: Sun, 16 Jul 2023 18:57:10 +0100 Subject: [PATCH 5/7] Missing vec --- crates/rpc/rpc-types/src/otterscan.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rpc/rpc-types/src/otterscan.rs b/crates/rpc/rpc-types/src/otterscan.rs index 5adfe83d621..88faf66dbfe 100644 --- a/crates/rpc/rpc-types/src/otterscan.rs +++ b/crates/rpc/rpc-types/src/otterscan.rs @@ -59,7 +59,7 @@ pub struct BlockDetails { #[serde(rename_all = "camelCase")] pub struct TransactionsWithReceipts { txs: Vec, - receipts: TransactionReceipt, + receipts: Vec, first_page: bool, last_page: bool, } From 33bc94e888ec874b854ee0f4f379c174995ab81d Mon Sep 17 00:00:00 2001 From: ZePedroResende Date: Mon, 17 Jul 2023 19:25:34 +0100 Subject: [PATCH 6/7] Types code review --- crates/rpc/rpc-api/src/otterscan.rs | 22 ++++++------- crates/rpc/rpc-types/src/otterscan.rs | 47 ++++++++++++++++++++------- crates/rpc/rpc/src/otterscan.rs | 22 ++++++------- 3 files changed, 58 insertions(+), 33 deletions(-) diff --git a/crates/rpc/rpc-api/src/otterscan.rs b/crates/rpc/rpc-api/src/otterscan.rs index b0558442934..1bbfba6b255 100644 --- a/crates/rpc/rpc-api/src/otterscan.rs +++ b/crates/rpc/rpc-api/src/otterscan.rs @@ -1,8 +1,8 @@ use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use reth_primitives::{Address, BlockId, TxHash, H256, U256}; use reth_rpc_types::{ - BlockDetails, ContractCreator, InternalOperation, TraceEntry, Transaction, - TransactionsWithReceipts, + BlockDetails, ContractCreator, InternalOperation, OtsBlockTransactions, TraceEntry, + Transaction, TransactionsWithReceipts, }; /// Otterscan rpc interface. @@ -35,20 +35,20 @@ pub trait Otterscan { /// Tailor-made and expanded version of eth_getBlockByNumber for block details page in /// Otterscan. #[method(name = "getBlockDetails")] - async fn get_block_details(&self, block_number: U256) -> RpcResult; + async fn get_block_details(&self, block_number: U256) -> RpcResult>; /// Tailor-made and expanded version of eth_getBlockByHash for block details page in Otterscan. #[method(name = "getBlockDetailsByHash")] - async fn get_block_details_by_hash(&self, block_hash: H256) -> RpcResult; + async fn get_block_details_by_hash(&self, block_hash: H256) -> RpcResult>; /// Get paginated transactions for a certain block. Also remove some verbose fields like logs. #[method(name = "getBlockTransactions")] async fn get_block_transactions( &self, block_number: U256, - page_number: u8, - page_size: u8, - ) -> RpcResult>; + page_number: usize, + page_size: usize, + ) -> RpcResult; /// Gets paginated inbound/outbound transaction calls for a certain address. #[method(name = "searchTransactionsBefore")] @@ -56,7 +56,7 @@ pub trait Otterscan { &self, address: Address, block_number: U256, - page_size: u8, + page_size: usize, ) -> RpcResult; /// Gets paginated inbound/outbound transaction calls for a certain address. @@ -65,7 +65,7 @@ pub trait Otterscan { &self, address: Address, block_number: U256, - page_size: u8, + page_size: usize, ) -> RpcResult; /// Gets the transaction hash for a certain sender address, given its nonce. @@ -74,9 +74,9 @@ pub trait Otterscan { &self, sender: Address, nonce: u64, - ) -> RpcResult; + ) -> RpcResult>; /// Gets the transaction hash and the address who created a contract. #[method(name = "getContractCreator")] - async fn get_contract_creator(&self, address: Address) -> RpcResult; + async fn get_contract_creator(&self, address: Address) -> RpcResult>; } diff --git a/crates/rpc/rpc-types/src/otterscan.rs b/crates/rpc/rpc-types/src/otterscan.rs index 88faf66dbfe..57e12e8bf12 100644 --- a/crates/rpc/rpc-types/src/otterscan.rs +++ b/crates/rpc/rpc-types/src/otterscan.rs @@ -1,18 +1,18 @@ use crate::{Block, Transaction, TransactionReceipt}; -use reth_primitives::{Address, Bytes}; +use reth_primitives::{Address, Bytes, U256}; use serde::{Deserialize, Serialize}; /// Operation type enum for `InternalOperation` struct #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub enum OperationType { /// Operation Transfer - OpTransfer, + OpTransfer = 0, /// Operation Contract self destruct - OpSelfDestruct, + OpSelfDestruct = 1, /// Operation Create - OpCreate, + OpCreate = 2, /// Operation Create2 - OpCreate2, + OpCreate2 = 3, } /// Custom struct for otterscan `getInternalOperations` RPC response @@ -39,18 +39,43 @@ pub struct TraceEntry { #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct InternalIssuance { - block_reward: String, - uncle_reward: String, - issuance: String, + block_reward: U256, + uncle_reward: U256, + issuance: U256, +} + +/// Custom `Block` struct that includes transaction count for Otterscan responses +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OtsBlock { + #[serde(flatten)] + block: Block, + transaction_count: usize, } /// Custom struct for otterscan `getBlockDetails` RPC response #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct BlockDetails { - block: Block, + block: OtsBlock, issuance: InternalIssuance, - total_fees: u64, + total_fees: U256, +} + +/// Custom transaction receipt struct for otterscan `OtsBlockTransactions` struct +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OtsTransactionReceipt { + #[serde(flatten)] + receipt: TransactionReceipt, + timestamp: u64, +} + +/// Custom struct for otterscan `getBlockTransactions` RPC response +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct OtsBlockTransactions { + fullblock: OtsBlock, + receipts: Vec, } /// Custom struct for otterscan `searchTransactionsAfter`and `searchTransactionsBefore` RPC @@ -59,7 +84,7 @@ pub struct BlockDetails { #[serde(rename_all = "camelCase")] pub struct TransactionsWithReceipts { txs: Vec, - receipts: Vec, + receipts: Vec, first_page: bool, last_page: bool, } diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index 9bc5d0cf734..5c03efe3e90 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -5,8 +5,8 @@ use jsonrpsee::core::RpcResult; use reth_primitives::{Address, BlockId, TxHash, H256, U256}; use reth_rpc_api::{EthApiServer, OtterscanServer}; use reth_rpc_types::{ - BlockDetails, ContractCreator, InternalOperation, TraceEntry, Transaction, - TransactionsWithReceipts, + BlockDetails, ContractCreator, InternalOperation, OtsBlockTransactions, TraceEntry, + Transaction, TransactionsWithReceipts, }; /// Otterscan Api @@ -53,12 +53,12 @@ where } /// Handler for `ots_getBlockDetails` - async fn get_block_details(&self, block_number: U256) -> RpcResult { + async fn get_block_details(&self, block_number: U256) -> RpcResult> { Err(internal_rpc_err("unimplemented")) } /// Handler for `getBlockDetailsByHash` - async fn get_block_details_by_hash(&self, block_hash: H256) -> RpcResult { + async fn get_block_details_by_hash(&self, block_hash: H256) -> RpcResult> { Err(internal_rpc_err("unimplemented")) } @@ -66,9 +66,9 @@ where async fn get_block_transactions( &self, block_number: U256, - page_number: u8, - page_size: u8, - ) -> RpcResult> { + page_number: usize, + page_size: usize, + ) -> RpcResult { Err(internal_rpc_err("unimplemented")) } @@ -77,7 +77,7 @@ where &self, address: Address, block_number: U256, - page_size: u8, + page_size: usize, ) -> RpcResult { Err(internal_rpc_err("unimplemented")) } @@ -87,7 +87,7 @@ where &self, address: Address, block_number: U256, - page_size: u8, + page_size: usize, ) -> RpcResult { Err(internal_rpc_err("unimplemented")) } @@ -97,12 +97,12 @@ where &self, sender: Address, nonce: u64, - ) -> RpcResult { + ) -> RpcResult> { Err(internal_rpc_err("unimplemented")) } /// Handler for `getContractCreator` - async fn get_contract_creator(&self, address: Address) -> RpcResult { + async fn get_contract_creator(&self, address: Address) -> RpcResult> { Err(internal_rpc_err("unimplemented")) } } From 6f286f8fbc77fa26e7df4181bdccf086f3c858f3 Mon Sep 17 00:00:00 2001 From: ZePedroResende Date: Tue, 18 Jul 2023 14:41:26 +0100 Subject: [PATCH 7/7] Fix block_number type --- crates/rpc/rpc-api/src/otterscan.rs | 13 ++++++++----- crates/rpc/rpc/src/otterscan.rs | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/crates/rpc/rpc-api/src/otterscan.rs b/crates/rpc/rpc-api/src/otterscan.rs index 1bbfba6b255..9ac585991fe 100644 --- a/crates/rpc/rpc-api/src/otterscan.rs +++ b/crates/rpc/rpc-api/src/otterscan.rs @@ -1,5 +1,5 @@ use jsonrpsee::{core::RpcResult, proc_macros::rpc}; -use reth_primitives::{Address, BlockId, TxHash, H256, U256}; +use reth_primitives::{Address, BlockId, BlockNumberOrTag, TxHash, H256}; use reth_rpc_types::{ BlockDetails, ContractCreator, InternalOperation, OtsBlockTransactions, TraceEntry, Transaction, TransactionsWithReceipts, @@ -35,7 +35,10 @@ pub trait Otterscan { /// Tailor-made and expanded version of eth_getBlockByNumber for block details page in /// Otterscan. #[method(name = "getBlockDetails")] - async fn get_block_details(&self, block_number: U256) -> RpcResult>; + async fn get_block_details( + &self, + block_number: BlockNumberOrTag, + ) -> RpcResult>; /// Tailor-made and expanded version of eth_getBlockByHash for block details page in Otterscan. #[method(name = "getBlockDetailsByHash")] @@ -45,7 +48,7 @@ pub trait Otterscan { #[method(name = "getBlockTransactions")] async fn get_block_transactions( &self, - block_number: U256, + block_number: BlockNumberOrTag, page_number: usize, page_size: usize, ) -> RpcResult; @@ -55,7 +58,7 @@ pub trait Otterscan { async fn search_transactions_before( &self, address: Address, - block_number: U256, + block_number: BlockNumberOrTag, page_size: usize, ) -> RpcResult; @@ -64,7 +67,7 @@ pub trait Otterscan { async fn search_transactions_after( &self, address: Address, - block_number: U256, + block_number: BlockNumberOrTag, page_size: usize, ) -> RpcResult; diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index 5c03efe3e90..93d0ba167e2 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -2,7 +2,7 @@ use crate::result::internal_rpc_err; use async_trait::async_trait; use jsonrpsee::core::RpcResult; -use reth_primitives::{Address, BlockId, TxHash, H256, U256}; +use reth_primitives::{Address, BlockId, BlockNumberOrTag, TxHash, H256}; use reth_rpc_api::{EthApiServer, OtterscanServer}; use reth_rpc_types::{ BlockDetails, ContractCreator, InternalOperation, OtsBlockTransactions, TraceEntry, @@ -53,7 +53,10 @@ where } /// Handler for `ots_getBlockDetails` - async fn get_block_details(&self, block_number: U256) -> RpcResult> { + async fn get_block_details( + &self, + block_number: BlockNumberOrTag, + ) -> RpcResult> { Err(internal_rpc_err("unimplemented")) } @@ -65,7 +68,7 @@ where /// Handler for `getBlockTransactions` async fn get_block_transactions( &self, - block_number: U256, + block_number: BlockNumberOrTag, page_number: usize, page_size: usize, ) -> RpcResult { @@ -76,7 +79,7 @@ where async fn search_transactions_before( &self, address: Address, - block_number: U256, + block_number: BlockNumberOrTag, page_size: usize, ) -> RpcResult { Err(internal_rpc_err("unimplemented")) @@ -86,7 +89,7 @@ where async fn search_transactions_after( &self, address: Address, - block_number: U256, + block_number: BlockNumberOrTag, page_size: usize, ) -> RpcResult { Err(internal_rpc_err("unimplemented"))