diff --git a/crates/rpc/rpc-api/src/otterscan.rs b/crates/rpc/rpc-api/src/otterscan.rs index 4d45cba358e1..c87a128bfbe0 100644 --- a/crates/rpc/rpc-api/src/otterscan.rs +++ b/crates/rpc/rpc-api/src/otterscan.rs @@ -43,7 +43,7 @@ pub trait Otterscan { /// 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; + async fn trace_transaction(&self, tx_hash: TxHash) -> RpcResult>>; /// Tailor-made and expanded version of eth_getBlockByNumber for block details page in /// Otterscan. diff --git a/crates/rpc/rpc-builder/tests/it/http.rs b/crates/rpc/rpc-builder/tests/it/http.rs index 968280296b06..37c33551f597 100644 --- a/crates/rpc/rpc-builder/tests/it/http.rs +++ b/crates/rpc/rpc-builder/tests/it/http.rs @@ -311,9 +311,7 @@ where OtterscanClient::get_transaction_error(client, tx_hash).await.unwrap(); - assert!(is_unimplemented( - OtterscanClient::trace_transaction(client, tx_hash).await.err().unwrap() - )); + OtterscanClient::trace_transaction(client, tx_hash).await.unwrap(); OtterscanClient::get_block_details(client, block_number).await.unwrap(); diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index 214315f8aa3a..a309b141ea54 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -17,7 +17,7 @@ use reth_rpc_types::{ BlockTransactions, Header, Transaction, }; use revm_inspectors::{ - tracing::TracingInspectorConfig, + tracing::{types::CallTraceNode, TracingInspectorConfig}, transfer::{TransferInspector, TransferKind}, }; use revm_primitives::ExecutionResult; @@ -101,8 +101,34 @@ where } /// Handler for `ots_traceTransaction` - async fn trace_transaction(&self, _tx_hash: TxHash) -> RpcResult { - Err(internal_rpc_err("unimplemented")) + async fn trace_transaction(&self, tx_hash: TxHash) -> RpcResult>> { + let traces = self + .eth + .spawn_trace_transaction_in_block( + tx_hash, + TracingInspectorConfig::default_parity(), + move |_tx_info, inspector, _, _| Ok(inspector.into_traces().into_nodes()), + ) + .await? + .map(|traces| { + traces + .into_iter() + .map(|CallTraceNode { trace, .. }| TraceEntry { + r#type: if trace.is_selfdestruct() { + "SELFDESTRUCT".to_string() + } else { + trace.kind.to_string() + }, + depth: trace.depth as u32, + from: trace.caller, + to: trace.address, + value: trace.value, + input: trace.data, + output: trace.output, + }) + .collect::>() + }); + Ok(traces) } /// Handler for `ots_getBlockDetails`