@@ -75,13 +75,20 @@ def __init_subclass__(cls) -> None:
7575 namespace = namespace .removesuffix ("RPC" )
7676 cls .namespace = namespace .lower ()
7777
78- def post_request (self , method : str , * params : Any , extra_headers : Dict | None = None ) -> Any :
78+ def post_request (
79+ self ,
80+ * ,
81+ method : str ,
82+ params : Any | None = None ,
83+ extra_headers : Dict | None = None ,
84+ timeout : int | None = None ,
85+ ) -> Any :
7986 """Send JSON-RPC POST request to the client RPC server at port defined in the url."""
8087 if extra_headers is None :
8188 extra_headers = {}
8289 assert self .namespace , "RPC namespace not set"
8390
84- payload = {
91+ json = {
8592 "jsonrpc" : "2.0" ,
8693 "method" : f"{ self .namespace } _{ method } " ,
8794 "params" : params ,
@@ -92,7 +99,9 @@ def post_request(self, method: str, *params: Any, extra_headers: Dict | None = N
9299 }
93100 headers = base_header | self .extra_headers | extra_headers
94101
95- response = requests .post (self .url , json = payload , headers = headers )
102+ print (f"Sending RPC request to { self .url } , timeout is set to { timeout } ..." )
103+ # WHY IS TIMEOUT ALWAYS NONE IT SHOULD HAVE RECEIVED AN ACTUAL VALUE
104+ response = requests .post (self .url , json = json , headers = headers , timeout = timeout )
96105 response .raise_for_status ()
97106 response_json = response .json ()
98107
@@ -130,53 +139,79 @@ def __init__(
130139 )
131140 self .transaction_wait_timeout = transaction_wait_timeout
132141
133- def config (self ):
142+ def config (self , timeout : int | None = None ):
134143 """`eth_config`: Returns information about a fork configuration of the client."""
135144 try :
136- response = self .post_request ("config" )
145+ response = self .post_request (method = "config" , timeout = timeout )
137146 if response is None :
147+ print ("eth_config request: failed to get response" )
138148 return None
139149 return EthConfigResponse .model_validate (
140150 response , context = self .response_validation_context
141151 )
142152 except ValidationError as e :
143153 pprint (e .errors ())
144154 raise e
155+ except Exception as e :
156+ print (f"exception occurred when sending JSON-RPC request: { e } " )
157+ raise e
145158
146159 def chain_id (self ) -> int :
147160 """`eth_chainId`: Returns the current chain id."""
148- return int (self .post_request ("chainId" ), 16 )
161+ response = self .post_request (method = "chainId" )
162+
163+ return int (response , 16 )
149164
150165 def get_block_by_number (self , block_number : BlockNumberType = "latest" , full_txs : bool = True ):
151166 """`eth_getBlockByNumber`: Returns information about a block by block number."""
152167 block = hex (block_number ) if isinstance (block_number , int ) else block_number
153- return self .post_request ("getBlockByNumber" , block , full_txs )
168+ params = [block , full_txs ]
169+ response = self .post_request (method = "getBlockByNumber" , params = params )
170+
171+ return response
154172
155173 def get_block_by_hash (self , block_hash : Hash , full_txs : bool = True ):
156174 """`eth_getBlockByHash`: Returns information about a block by hash."""
157- return self .post_request ("getBlockByHash" , f"{ block_hash } " , full_txs )
175+ params = [f"{ block_hash } " , full_txs ]
176+ response = self .post_request (method = "getBlockByHash" , params = params )
177+
178+ return response
158179
159180 def get_balance (self , address : Address , block_number : BlockNumberType = "latest" ) -> int :
160181 """`eth_getBalance`: Returns the balance of the account of given address."""
161182 block = hex (block_number ) if isinstance (block_number , int ) else block_number
162- return int (self .post_request ("getBalance" , f"{ address } " , block ), 16 )
183+ params = [f"{ address } " , block ]
184+
185+ response = self .post_request (method = "getBalance" , params = params )
186+
187+ return int (response , 16 )
163188
164189 def get_code (self , address : Address , block_number : BlockNumberType = "latest" ) -> Bytes :
165190 """`eth_getCode`: Returns code at a given address."""
166191 block = hex (block_number ) if isinstance (block_number , int ) else block_number
167- return Bytes (self .post_request ("getCode" , f"{ address } " , block ))
192+ params = [f"{ address } " , block ]
193+
194+ response = self .post_request (method = "getCode" , params = params )
195+
196+ return Bytes (response )
168197
169198 def get_transaction_count (
170199 self , address : Address , block_number : BlockNumberType = "latest"
171200 ) -> int :
172201 """`eth_getTransactionCount`: Returns the number of transactions sent from an address."""
173202 block = hex (block_number ) if isinstance (block_number , int ) else block_number
174- return int (self .post_request ("getTransactionCount" , f"{ address } " , block ), 16 )
203+ params = [f"{ address } " , block ]
204+
205+ response = self .post_request (method = "getTransactionCount" , params = params )
206+
207+ return int (response , 16 )
175208
176209 def get_transaction_by_hash (self , transaction_hash : Hash ) -> TransactionByHashResponse | None :
177210 """`eth_getTransactionByHash`: Returns transaction details."""
178211 try :
179- response = self .post_request ("getTransactionByHash" , f"{ transaction_hash } " )
212+ response = self .post_request (
213+ method = "getTransactionByHash" , params = f"{ transaction_hash } "
214+ )
180215 if response is None :
181216 return None
182217 return TransactionByHashResponse .model_validate (
@@ -191,27 +226,39 @@ def get_storage_at(
191226 ) -> Hash :
192227 """`eth_getStorageAt`: Returns the value from a storage position at a given address."""
193228 block = hex (block_number ) if isinstance (block_number , int ) else block_number
194- return Hash (self .post_request ("getStorageAt" , f"{ address } " , f"{ position } " , block ))
229+ params = [f"{ address } " , f"{ position } " , block ]
230+
231+ response = self .post_request (method = "getStorageAt" , params = params )
232+ return Hash (response )
195233
196234 def gas_price (self ) -> int :
197235 """`eth_gasPrice`: Returns the number of transactions sent from an address."""
198- return int (self .post_request ("gasPrice" ), 16 )
236+ response = self .post_request (method = "gasPrice" )
237+
238+ return int (response , 16 )
199239
200240 def send_raw_transaction (self , transaction_rlp : Bytes ) -> Hash :
201241 """`eth_sendRawTransaction`: Send a transaction to the client."""
202242 try :
203- result_hash = Hash (self .post_request ("sendRawTransaction" , f"{ transaction_rlp .hex ()} " ))
243+ response = self .post_request (
244+ method = "sendRawTransaction" , params = f"{ transaction_rlp .hex ()} "
245+ )
246+
247+ result_hash = Hash (response )
204248 assert result_hash is not None
205249 return result_hash
206250 except Exception as e :
207251 raise SendTransactionExceptionError (str (e ), tx_rlp = transaction_rlp ) from e
208252
209253 def send_transaction (self , transaction : Transaction ) -> Hash :
210254 """`eth_sendRawTransaction`: Send a transaction to the client."""
255+ # TODO: is this a copypaste error from above?
211256 try :
212- result_hash = Hash (
213- self . post_request ( "sendRawTransaction" , f"{ transaction .rlp ().hex ()} " )
257+ response = self . post_request (
258+ method = "sendRawTransaction" , params = f"{ transaction .rlp ().hex ()} "
214259 )
260+
261+ result_hash = Hash (response )
215262 assert result_hash == transaction .hash
216263 assert result_hash is not None
217264 return transaction .hash
@@ -303,7 +350,8 @@ class DebugRPC(EthRPC):
303350
304351 def trace_call (self , tr : dict [str , str ], block_number : str ):
305352 """`debug_traceCall`: Returns pre state required for transaction."""
306- return self .post_request ("traceCall" , tr , block_number , {"tracer" : "prestateTracer" })
353+ params = [tr , block_number , {"tracer" : "prestateTracer" }]
354+ return self .post_request (method = "traceCall" , params = params )
307355
308356
309357class EngineRPC (BaseRPC ):
@@ -312,7 +360,14 @@ class EngineRPC(BaseRPC):
312360 simulators.
313361 """
314362
315- def post_request (self , method : str , * params : Any , extra_headers : Dict | None = None ) -> Any :
363+ def post_request (
364+ self ,
365+ * ,
366+ method : str ,
367+ params : Any | None = None ,
368+ extra_headers : Dict | None = None ,
369+ timeout : int | None = None ,
370+ ) -> Any :
316371 """Send JSON-RPC POST request to the client RPC server at port defined in the url."""
317372 if extra_headers is None :
318373 extra_headers = {}
@@ -324,12 +379,18 @@ def post_request(self, method: str, *params: Any, extra_headers: Dict | None = N
324379 extra_headers = {
325380 "Authorization" : f"Bearer { jwt_token } " ,
326381 } | extra_headers
327- return super ().post_request (method , * params , extra_headers = extra_headers )
382+
383+ return super ().post_request (
384+ method = method , params = params , extra_headers = extra_headers , timeout = timeout
385+ )
328386
329387 def new_payload (self , * params : Any , version : int ) -> PayloadStatus :
330388 """`engine_newPayloadVX`: Attempts to execute the given payload on an execution client."""
389+ method = f"newPayloadV{ version } "
390+ params_list = [to_json (param ) for param in params ]
391+
331392 return PayloadStatus .model_validate (
332- self .post_request (f"newPayloadV { version } " , * [ to_json ( param ) for param in params ] ),
393+ self .post_request (method = method , params = params_list ),
333394 context = self .response_validation_context ,
334395 )
335396
@@ -341,11 +402,17 @@ def forkchoice_updated(
341402 version : int ,
342403 ) -> ForkchoiceUpdateResponse :
343404 """`engine_forkchoiceUpdatedVX`: Updates the forkchoice state of the execution client."""
405+ method = f"forkchoiceUpdatedV{ version } "
406+
407+ if payload_attributes is None :
408+ params = [to_json (forkchoice_state )]
409+ else :
410+ params = [to_json (forkchoice_state ), to_json (payload_attributes )]
411+
344412 return ForkchoiceUpdateResponse .model_validate (
345413 self .post_request (
346- f"forkchoiceUpdatedV{ version } " ,
347- to_json (forkchoice_state ),
348- to_json (payload_attributes ) if payload_attributes is not None else None ,
414+ method = method ,
415+ params = params ,
349416 ),
350417 context = self .response_validation_context ,
351418 )
@@ -360,10 +427,12 @@ def get_payload(
360427 `engine_getPayloadVX`: Retrieves a payload that was requested through
361428 `engine_forkchoiceUpdatedVX`.
362429 """
430+ method = f"getPayloadV{ version } "
431+
363432 return GetPayloadResponse .model_validate (
364433 self .post_request (
365- f"getPayloadV { version } " ,
366- f"{ payload_id } " ,
434+ method = method ,
435+ params = f"{ payload_id } " ,
367436 ),
368437 context = self .response_validation_context ,
369438 )
@@ -375,10 +444,13 @@ def get_blobs(
375444 version : int ,
376445 ) -> GetBlobsResponse :
377446 """`engine_getBlobsVX`: Retrieves blobs from an execution layers tx pool."""
447+ method = f"getBlobsV{ version } "
448+ params = [f"{ h } " for h in versioned_hashes ]
449+
378450 return GetBlobsResponse .model_validate (
379451 self .post_request (
380- f"getBlobsV { version } " ,
381- [ f" { h } " for h in versioned_hashes ] ,
452+ method = method ,
453+ params = params ,
382454 ),
383455 context = self .response_validation_context ,
384456 )
@@ -389,7 +461,7 @@ class NetRPC(BaseRPC):
389461
390462 def peer_count (self ) -> int :
391463 """`net_peerCount`: Get the number of peers connected to the client."""
392- response = self .post_request ("peerCount" )
464+ response = self .post_request (method = "peerCount" )
393465 return int (response , 16 ) # hex -> int
394466
395467
@@ -398,4 +470,4 @@ class AdminRPC(BaseRPC):
398470
399471 def add_peer (self , enode : str ) -> bool :
400472 """`admin_addPeer`: Add a peer by enode URL."""
401- return self .post_request ("addPeer" , enode )
473+ return self .post_request (method = "addPeer" , params = enode )
0 commit comments