44from .etheno import EthenoPlugin
55from .utils import format_hex_address
66
7+
8+ # source: https://ethereum.stackexchange.com/a/83855
9+ import rlp
10+ from eth_typing import HexStr
11+ from eth_utils import keccak , to_bytes
12+ from rlp .sedes import Binary , big_endian_int , binary
13+ from web3 import Web3
14+ from web3 .auto import w3
15+
16+
17+ class Transaction (rlp .Serializable ):
18+ fields = [
19+ ("nonce" , big_endian_int ),
20+ ("gas_price" , big_endian_int ),
21+ ("gas" , big_endian_int ),
22+ ("to" , Binary .fixed_length (20 , allow_empty = True )),
23+ ("value" , big_endian_int ),
24+ ("data" , binary ),
25+ ("v" , big_endian_int ),
26+ ("r" , big_endian_int ),
27+ ("s" , big_endian_int ),
28+ ]
29+
30+
31+ def hex_to_bytes (data : str ) -> bytes :
32+ return to_bytes (hexstr = HexStr (data ))
33+
34+
35+ def decode_raw_tx (raw_tx : str ):
36+ tx_bytes = hex_to_bytes (raw_tx )
37+ tx = rlp .decode (tx_bytes , Transaction )
38+ hash_tx = Web3 .toHex (keccak (tx_bytes ))
39+ from_ = w3 .eth .account .recover_transaction (raw_tx )
40+ to = w3 .toChecksumAddress (tx .to ) if tx .to else None
41+ data = w3 .toHex (tx .data )
42+ r = hex (tx .r )
43+ s = hex (tx .s )
44+ chain_id = (tx .v - 35 ) // 2 if tx .v % 2 else (tx .v - 36 ) // 2
45+ return {
46+ 'txHash' : hash_tx ,
47+ 'from' : from_ ,
48+ 'to' : to ,
49+ 'nonce' : tx .nonce ,
50+ 'gas' : tx .gas ,
51+ 'gasPrice' : tx .gas_price ,
52+ 'value' : tx .value ,
53+ 'data' : data ,
54+ 'chainId' : chain_id ,
55+ 'r' : r ,
56+ 's' : s ,
57+ 'v' : tx .v
58+ }
59+
60+
761class JSONExporter :
862 def __init__ (self , out_stream : Union [str , TextIO ]):
963 self ._was_path = isinstance (out_stream , str )
@@ -65,12 +119,15 @@ def after_post(self, post_data, result):
65119 result = result [0 ]
66120 if 'method' not in post_data :
67121 return
68- elif post_data ['method' ] == 'eth_sendTransaction' and 'result' in result :
122+ elif ( post_data ['method' ] == 'eth_sendTransaction' or post_data [ 'method' ] == 'eth_sendRawTransaction' ) and 'result' in result :
69123 try :
70124 transaction_hash = int (result ['result' ], 16 )
71125 except ValueError :
72126 return
73- self ._transactions [transaction_hash ] = post_data
127+ if post_data ['method' ] == 'eth_sendRawTransaction' :
128+ self ._transactions [transaction_hash ] = decode_raw_tx (post_data ['params' ][0 ])
129+ else :
130+ self ._transactions [transaction_hash ] = post_data ['params' ][0 ]
74131 elif post_data ['method' ] == 'evm_mine' :
75132 self .handle_increase_block_number ()
76133 elif post_data ['method' ] == 'evm_increaseTime' :
@@ -80,7 +137,7 @@ def after_post(self, post_data, result):
80137 if transaction_hash not in self ._transactions :
81138 self .logger .error (f'Received transaction receipt { result } for unknown transaction hash { post_data ["params" ][0 ]} ' )
82139 return
83- original_transaction = self ._transactions [transaction_hash ][ 'params' ][ 0 ]
140+ original_transaction = self ._transactions [transaction_hash ]
84141 if 'value' not in original_transaction or original_transaction ['value' ] is None :
85142 value = '0x0'
86143 else :
0 commit comments