@@ -15,17 +15,19 @@ use jsonrpsee::{
15
15
use op_alloy_consensus:: OpTxEnvelope ;
16
16
use op_alloy_network:: Optimism ;
17
17
use op_alloy_rpc_types:: Transaction ;
18
+ use reth:: providers:: TransactionsProvider ;
19
+ use reth:: rpc:: server_types:: eth:: TransactionSource ;
18
20
use reth:: { api:: BlockBody , providers:: HeaderProvider } ;
19
21
use reth_optimism_chainspec:: OpChainSpec ;
20
22
use reth_optimism_primitives:: { OpBlock , OpReceipt , OpTransactionSigned } ;
21
23
use reth_optimism_rpc:: OpReceiptBuilder ;
22
24
use reth_rpc_eth_api:: helpers:: EthTransactions ;
23
- use reth_rpc_eth_api:: RpcReceipt ;
24
25
use reth_rpc_eth_api:: { helpers:: FullEthApi , RpcBlock } ;
25
26
use reth_rpc_eth_api:: {
26
27
helpers:: { EthBlocks , EthState } ,
27
28
RpcNodeCore ,
28
29
} ;
30
+ use reth_rpc_eth_api:: { RpcReceipt , RpcTransaction } ;
29
31
use tracing:: { debug, info} ;
30
32
31
33
#[ cfg_attr( not( test) , rpc( server, namespace = "eth" ) ) ]
@@ -54,6 +56,12 @@ pub trait EthApiOverride {
54
56
address : Address ,
55
57
block_number : Option < BlockId > ,
56
58
) -> RpcResult < U256 > ;
59
+
60
+ #[ method( name = "getTransactionByHash" ) ]
61
+ async fn transaction_by_hash (
62
+ & self ,
63
+ tx_hash : TxHash ,
64
+ ) -> RpcResult < Option < RpcTransaction < Optimism > > > ;
57
65
}
58
66
59
67
#[ derive( Debug ) ]
@@ -89,10 +97,10 @@ impl<E> EthApiExt<E> {
89
97
let signed_tx_ec_recovered = Recovered :: new_unchecked ( tx. clone ( ) , sender) ;
90
98
let tx_info = TransactionInfo {
91
99
hash : Some ( tx. tx_hash ( ) ) ,
92
- block_hash : None ,
100
+ block_hash : Some ( block . header . hash_slow ( ) ) ,
93
101
block_number : Some ( block. number ) ,
94
102
index : Some ( idx as u64 ) ,
95
- base_fee : None ,
103
+ base_fee : block . base_fee_per_gas ,
96
104
} ;
97
105
self . transform_tx ( signed_tx_ec_recovered, tx_info)
98
106
} )
@@ -226,12 +234,14 @@ where
226
234
Eth : FullEthApi < NetworkTypes = Optimism > + Send + Sync + ' static ,
227
235
Eth : RpcNodeCore ,
228
236
<Eth as RpcNodeCore >:: Provider : HeaderProvider < Header = alloy_consensus:: Header > ,
237
+ <Eth as RpcNodeCore >:: Provider : TransactionsProvider < Transaction = OpTransactionSigned > ,
229
238
{
230
239
async fn block_by_number (
231
240
& self ,
232
241
number : BlockNumberOrTag ,
233
242
_full : bool ,
234
243
) -> RpcResult < Option < RpcBlock < Optimism > > > {
244
+ debug ! ( "block_by_number: {:?}" , number) ;
235
245
match number {
236
246
BlockNumberOrTag :: Pending => {
237
247
debug ! ( "pending block by number, delegating to flashblocks" ) ;
@@ -255,6 +265,7 @@ where
255
265
& self ,
256
266
tx_hash : TxHash ,
257
267
) -> RpcResult < Option < RpcReceipt < Optimism > > > {
268
+ debug ! ( "get_transaction_receipt: {:?}" , tx_hash) ;
258
269
let receipt = EthTransactions :: transaction_receipt ( & self . eth_api , tx_hash) . await ;
259
270
260
271
// check if receipt is none
@@ -285,6 +296,7 @@ where
285
296
address : Address ,
286
297
block_number : Option < BlockId > ,
287
298
) -> RpcResult < U256 > {
299
+ debug ! ( "get_balance: {:?}" , address) ;
288
300
let block_id = block_number. unwrap_or_default ( ) ;
289
301
if block_id. is_pending ( ) {
290
302
self . metrics . get_balance . increment ( 1 ) ;
@@ -304,6 +316,7 @@ where
304
316
address : Address ,
305
317
block_number : Option < BlockId > ,
306
318
) -> RpcResult < U256 > {
319
+ debug ! ( "get_transaction_count: {:?}" , address) ;
307
320
let block_id = block_number. unwrap_or_default ( ) ;
308
321
if block_id. is_pending ( ) {
309
322
self . metrics . get_transaction_count . increment ( 1 ) ;
@@ -341,4 +354,73 @@ where
341
354
. await
342
355
. map_err ( Into :: into)
343
356
}
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
+ }
344
426
}
0 commit comments