@@ -15,17 +15,19 @@ use jsonrpsee::{
1515use op_alloy_consensus:: OpTxEnvelope ;
1616use op_alloy_network:: Optimism ;
1717use op_alloy_rpc_types:: Transaction ;
18+ use reth:: providers:: TransactionsProvider ;
19+ use reth:: rpc:: server_types:: eth:: TransactionSource ;
1820use reth:: { api:: BlockBody , providers:: HeaderProvider } ;
1921use reth_optimism_chainspec:: OpChainSpec ;
2022use reth_optimism_primitives:: { OpBlock , OpReceipt , OpTransactionSigned } ;
2123use reth_optimism_rpc:: OpReceiptBuilder ;
2224use reth_rpc_eth_api:: helpers:: EthTransactions ;
23- use reth_rpc_eth_api:: RpcReceipt ;
2425use reth_rpc_eth_api:: { helpers:: FullEthApi , RpcBlock } ;
2526use reth_rpc_eth_api:: {
2627 helpers:: { EthBlocks , EthState } ,
2728 RpcNodeCore ,
2829} ;
30+ use reth_rpc_eth_api:: { RpcReceipt , RpcTransaction } ;
2931use tracing:: { debug, info} ;
3032
3133#[ cfg_attr( not( test) , rpc( server, namespace = "eth" ) ) ]
@@ -54,6 +56,12 @@ pub trait EthApiOverride {
5456 address : Address ,
5557 block_number : Option < BlockId > ,
5658 ) -> RpcResult < U256 > ;
59+
60+ #[ method( name = "getTransactionByHash" ) ]
61+ async fn transaction_by_hash (
62+ & self ,
63+ tx_hash : TxHash ,
64+ ) -> RpcResult < Option < RpcTransaction < Optimism > > > ;
5765}
5866
5967#[ derive( Debug ) ]
@@ -89,10 +97,10 @@ impl<E> EthApiExt<E> {
8997 let signed_tx_ec_recovered = Recovered :: new_unchecked ( tx. clone ( ) , sender) ;
9098 let tx_info = TransactionInfo {
9199 hash : Some ( tx. tx_hash ( ) ) ,
92- block_hash : None ,
100+ block_hash : Some ( block . header . hash_slow ( ) ) ,
93101 block_number : Some ( block. number ) ,
94102 index : Some ( idx as u64 ) ,
95- base_fee : None ,
103+ base_fee : block . base_fee_per_gas ,
96104 } ;
97105 self . transform_tx ( signed_tx_ec_recovered, tx_info)
98106 } )
@@ -226,12 +234,14 @@ where
226234 Eth : FullEthApi < NetworkTypes = Optimism > + Send + Sync + ' static ,
227235 Eth : RpcNodeCore ,
228236 <Eth as RpcNodeCore >:: Provider : HeaderProvider < Header = alloy_consensus:: Header > ,
237+ <Eth as RpcNodeCore >:: Provider : TransactionsProvider < Transaction = OpTransactionSigned > ,
229238{
230239 async fn block_by_number (
231240 & self ,
232241 number : BlockNumberOrTag ,
233242 _full : bool ,
234243 ) -> RpcResult < Option < RpcBlock < Optimism > > > {
244+ debug ! ( "block_by_number: {:?}" , number) ;
235245 match number {
236246 BlockNumberOrTag :: Pending => {
237247 debug ! ( "pending block by number, delegating to flashblocks" ) ;
@@ -255,6 +265,7 @@ where
255265 & self ,
256266 tx_hash : TxHash ,
257267 ) -> RpcResult < Option < RpcReceipt < Optimism > > > {
268+ debug ! ( "get_transaction_receipt: {:?}" , tx_hash) ;
258269 let receipt = EthTransactions :: transaction_receipt ( & self . eth_api , tx_hash) . await ;
259270
260271 // check if receipt is none
@@ -285,6 +296,7 @@ where
285296 address : Address ,
286297 block_number : Option < BlockId > ,
287298 ) -> RpcResult < U256 > {
299+ debug ! ( "get_balance: {:?}" , address) ;
288300 let block_id = block_number. unwrap_or_default ( ) ;
289301 if block_id. is_pending ( ) {
290302 self . metrics . get_balance . increment ( 1 ) ;
@@ -304,6 +316,7 @@ where
304316 address : Address ,
305317 block_number : Option < BlockId > ,
306318 ) -> RpcResult < U256 > {
319+ debug ! ( "get_transaction_count: {:?}" , address) ;
307320 let block_id = block_number. unwrap_or_default ( ) ;
308321 if block_id. is_pending ( ) {
309322 self . metrics . get_transaction_count . increment ( 1 ) ;
@@ -341,4 +354,73 @@ where
341354 . await
342355 . map_err ( Into :: into)
343356 }
357+
358+ async fn transaction_by_hash (
359+ & self ,
360+ tx_hash : TxHash ,
361+ ) -> RpcResult < Option < RpcTransaction < Optimism > > > {
362+ debug ! ( "transaction_by_hash: {:?}" , tx_hash) ;
363+ let tx = EthTransactions :: transaction_by_hash ( & self . eth_api , tx_hash)
364+ . await
365+ . map_err ( Into :: into) ?;
366+
367+ // Process the result without using map() and transpose()
368+ if let Some ( tx_source) = tx {
369+ match tx_source {
370+ TransactionSource :: Pool ( tx) => {
371+ // Convert the pool transaction
372+ let tx_info = TransactionInfo :: default ( ) ;
373+ Ok ( Some ( self . transform_tx ( tx, tx_info) ) )
374+ }
375+ TransactionSource :: Block {
376+ transaction,
377+ index,
378+ block_hash,
379+ block_number,
380+ base_fee,
381+ } => {
382+ // Convert the block transaction
383+ let tx_info = TransactionInfo {
384+ hash : Some ( tx_hash) ,
385+ index : Some ( index) ,
386+ block_hash : Some ( block_hash) ,
387+ block_number : Some ( block_number) ,
388+ base_fee,
389+ } ;
390+ Ok ( Some ( self . transform_tx ( transaction, tx_info) ) )
391+ }
392+ }
393+ } else {
394+ // Handle cache lookup for transactions not found in the main lookup
395+ if let Some ( tx) = self . cache . get :: < OpTransactionSigned > ( & tx_hash. to_string ( ) ) {
396+ let sender = self
397+ . cache
398+ . get :: < Address > ( & format ! ( "tx_sender:{}" , tx_hash) )
399+ . unwrap ( ) ;
400+ let block_number = self
401+ . cache
402+ . get :: < u64 > ( & format ! ( "tx_block_number:{}" , tx_hash) )
403+ . unwrap ( ) ;
404+ let block = self
405+ . cache
406+ . get :: < OpBlock > ( & format ! ( "block:{:?}" , block_number) )
407+ . unwrap ( ) ;
408+ let index = self
409+ . cache
410+ . get :: < u64 > ( & format ! ( "tx_idx:{}" , & tx_hash. to_string( ) ) )
411+ . unwrap ( ) ;
412+ let tx_info = TransactionInfo {
413+ hash : Some ( tx. tx_hash ( ) ) ,
414+ block_hash : Some ( block. header . hash_slow ( ) ) ,
415+ block_number : Some ( block. number ) ,
416+ index : Some ( index) ,
417+ base_fee : block. base_fee_per_gas ,
418+ } ;
419+ let tx = Recovered :: new_unchecked ( tx, sender) ;
420+ Ok ( Some ( self . transform_tx ( tx, tx_info) ) )
421+ } else {
422+ Ok ( None )
423+ }
424+ }
425+ }
344426}
0 commit comments