diff --git a/crates/networking/rpc/mempool.rs b/crates/networking/rpc/mempool.rs index 81cf0a59495..4de9fb2d560 100644 --- a/crates/networking/rpc/mempool.rs +++ b/crates/networking/rpc/mempool.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use ethrex_common::Address; +use ethrex_common::{Address, types::TxKind}; use ethrex_crypto::NativeCrypto; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -24,6 +24,22 @@ struct MempoolStatus { queued: String, } +type MempoolContentByNonce = HashMap; + +#[derive(Serialize, Deserialize)] +pub struct MempoolContentFrom { + pub pending: MempoolContentByNonce, + pub queued: MempoolContentByNonce, +} + +type MempoolInspectEntry = HashMap>; + +#[derive(Serialize, Deserialize)] +pub struct MempoolInspect { + pub pending: MempoolInspectEntry, + pub queued: MempoolInspectEntry, +} + /// Handling of rpc endpoint `mempool_content` pub fn content(context: RpcApiContext) -> Result { let transactions = context.blockchain.mempool.content()?; @@ -55,3 +71,64 @@ pub fn status(context: RpcApiContext) -> Result { Ok(serde_json::to_value(response)?) } + +/// Handling of rpc endpoint `txpool_contentFrom` +pub fn content_from(params: &Option>, context: RpcApiContext) -> Result { + let params = params + .as_ref() + .ok_or(RpcErr::BadParams("No params provided".to_owned()))?; + if params.len() != 1 { + return Err(RpcErr::BadParams(format!( + "Expected one param and {} were provided", + params.len() + ))); + } + let address: Address = serde_json::from_value(params[0].clone())?; + let transactions = context.blockchain.mempool.content()?; + let mut by_nonce: MempoolContentByNonce = HashMap::new(); + for tx in transactions { + if tx.sender(&NativeCrypto)? == address { + by_nonce.insert(tx.nonce(), RpcTransaction::build(tx, None, None, None)?); + } + } + let response = MempoolContentFrom { + pending: by_nonce, + // We have no concept of "queued" transactions yet so we will leave this empty + queued: HashMap::new(), + }; + Ok(serde_json::to_value(response)?) +} + +/// Handling of rpc endpoint `txpool_inspect` +pub fn inspect(context: RpcApiContext) -> Result { + let transactions = context.blockchain.mempool.content()?; + let mut pending: MempoolInspectEntry = HashMap::new(); + for tx in transactions { + let sender = tx.sender(&NativeCrypto)?; + let gas_price = tx.gas_price(); + let summary = match tx.to() { + TxKind::Call(to) => format!( + "{to:#x}: {} wei + {} gas × {} wei", + tx.value(), + tx.gas_limit(), + gas_price + ), + TxKind::Create => format!( + "contract creation: {} wei + {} gas × {} wei", + tx.value(), + tx.gas_limit(), + gas_price + ), + }; + pending + .entry(sender) + .or_default() + .insert(tx.nonce(), summary); + } + let response = MempoolInspect { + pending, + // We have no concept of "queued" transactions yet so we will leave this empty + queued: HashMap::new(), + }; + Ok(serde_json::to_value(response)?) +} diff --git a/crates/networking/rpc/rpc.rs b/crates/networking/rpc/rpc.rs index 4ab95d3c11d..58ce694af4c 100644 --- a/crates/networking/rpc/rpc.rs +++ b/crates/networking/rpc/rpc.rs @@ -896,7 +896,9 @@ pub fn map_mempool_requests(req: &RpcRequest, contex: RpcApiContext) -> Result mempool::content(contex), + "txpool_contentFrom" => mempool::content_from(&req.params, contex), "txpool_status" => mempool::status(contex), + "txpool_inspect" => mempool::inspect(contex), unknown_mempool_method => Err(RpcErr::MethodNotFound(unknown_mempool_method.to_owned())), } }