Skip to content

Commit 6e804d2

Browse files
authored
feat: Implement configurable poll interval for transactions (#2286)
* Implement configurable poll interval for transactions Add poll interval configuration for transaction polling * liint
1 parent 63bc826 commit 6e804d2

File tree

1 file changed

+23
-18
lines changed

1 file changed

+23
-18
lines changed

src/ethereum_test_rpc/rpc.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
import logging
6+
import os
67
import time
78
from itertools import count
89
from pprint import pprint
@@ -58,11 +59,12 @@ def __init__(self, *args, tx: Transaction | None = None, tx_rlp: Bytes | None =
5859

5960
def __str__(self):
6061
"""Return string representation of the exception."""
62+
base = super().__str__()
6163
if self.tx is not None:
62-
f"{super().__str__()} Transaction={self.tx.model_dump_json()}"
64+
return f"{base} Transaction={self.tx.model_dump_json()}"
6365
elif self.tx_rlp is not None:
64-
return f"{super().__str__()} Transaction RLP={self.tx_rlp.hex()}"
65-
return super().__str__()
66+
return f"{base} Transaction RLP={self.tx_rlp.hex()}"
67+
return base
6668

6769

6870
class BaseRPC:
@@ -183,13 +185,15 @@ class EthRPC(BaseRPC):
183185
"""
184186

185187
transaction_wait_timeout: int = 60
188+
poll_interval: float = 1.0 # how often to poll for tx inclusion
186189

187190
BlockNumberType = int | Literal["latest", "earliest", "pending"]
188191

189192
def __init__(
190193
self,
191194
*args,
192195
transaction_wait_timeout: int = 60,
196+
poll_interval: float | None = None,
193197
**kwargs,
194198
):
195199
"""
@@ -199,6 +203,20 @@ def __init__(
199203
super().__init__(*args, **kwargs)
200204
self.transaction_wait_timeout = transaction_wait_timeout
201205

206+
# Allow overriding via env "flag" EEST_POLL_INTERVAL or ctor arg
207+
# Priority: ctor arg > env var > default (1.0)
208+
env_val = os.getenv("EEST_POLL_INTERVAL")
209+
if poll_interval is not None:
210+
self.poll_interval = float(poll_interval)
211+
elif env_val:
212+
try:
213+
self.poll_interval = float(env_val)
214+
except ValueError:
215+
logger.warning("Invalid EEST_POLL_INTERVAL=%r; falling back to 1.0s", env_val)
216+
self.poll_interval = 1.0
217+
else:
218+
self.poll_interval = 1.0
219+
202220
def config(self, timeout: int | None = None):
203221
"""
204222
`eth_config`: Returns information about a fork configuration of the
@@ -222,7 +240,6 @@ def config(self, timeout: int | None = None):
222240
def chain_id(self) -> int:
223241
"""`eth_chainId`: Returns the current chain id."""
224242
response = self.post_request(method="chainId", timeout=10)
225-
226243
return int(response, 16)
227244

228245
def get_block_by_number(self, block_number: BlockNumberType = "latest", full_txs: bool = True):
@@ -233,14 +250,12 @@ def get_block_by_number(self, block_number: BlockNumberType = "latest", full_txs
233250
block = hex(block_number) if isinstance(block_number, int) else block_number
234251
params = [block, full_txs]
235252
response = self.post_request(method="getBlockByNumber", params=params)
236-
237253
return response
238254

239255
def get_block_by_hash(self, block_hash: Hash, full_txs: bool = True):
240256
"""`eth_getBlockByHash`: Returns information about a block by hash."""
241257
params = [f"{block_hash}", full_txs]
242258
response = self.post_request(method="getBlockByHash", params=params)
243-
244259
return response
245260

246261
def get_balance(self, address: Address, block_number: BlockNumberType = "latest") -> int:
@@ -249,18 +264,14 @@ def get_balance(self, address: Address, block_number: BlockNumberType = "latest"
249264
"""
250265
block = hex(block_number) if isinstance(block_number, int) else block_number
251266
params = [f"{address}", block]
252-
253267
response = self.post_request(method="getBalance", params=params)
254-
255268
return int(response, 16)
256269

257270
def get_code(self, address: Address, block_number: BlockNumberType = "latest") -> Bytes:
258271
"""`eth_getCode`: Returns code at a given address."""
259272
block = hex(block_number) if isinstance(block_number, int) else block_number
260273
params = [f"{address}", block]
261-
262274
response = self.post_request(method="getCode", params=params)
263-
264275
return Bytes(response)
265276

266277
def get_transaction_count(
@@ -272,9 +283,7 @@ def get_transaction_count(
272283
"""
273284
block = hex(block_number) if isinstance(block_number, int) else block_number
274285
params = [f"{address}", block]
275-
276286
response = self.post_request(method="getTransactionCount", params=params)
277-
278287
return int(response, 16)
279288

280289
def get_transaction_by_hash(self, transaction_hash: Hash) -> TransactionByHashResponse | None:
@@ -313,7 +322,6 @@ def get_storage_at(
313322
"""
314323
block = hex(block_number) if isinstance(block_number, int) else block_number
315324
params = [f"{address}", f"{position}", block]
316-
317325
response = self.post_request(method="getStorageAt", params=params)
318326
return Hash(response)
319327

@@ -323,7 +331,6 @@ def gas_price(self) -> int:
323331
address.
324332
"""
325333
response = self.post_request(method="gasPrice")
326-
327334
return int(response, 16)
328335

329336
def send_raw_transaction(
@@ -336,7 +343,6 @@ def send_raw_transaction(
336343
params=[transaction_rlp.hex()],
337344
request_id=request_id,
338345
)
339-
340346
result_hash = Hash(response)
341347
assert result_hash is not None
342348
return result_hash
@@ -352,7 +358,6 @@ def send_transaction(self, transaction: Transaction) -> Hash:
352358
params=[transaction.rlp().hex()],
353359
request_id=transaction.metadata_string(),
354360
)
355-
356361
result_hash = Hash(response)
357362
assert result_hash == transaction.hash
358363
assert result_hash is not None
@@ -393,7 +398,7 @@ def wait_for_transaction(self, transaction: Transaction) -> TransactionByHashRes
393398
return tx
394399
if (time.time() - start_time) > self.transaction_wait_timeout:
395400
break
396-
time.sleep(1)
401+
time.sleep(self.poll_interval)
397402
raise Exception(
398403
f"Transaction {tx_hash} ({transaction.model_dump_json()}) not included in a "
399404
f"block after {self.transaction_wait_timeout} seconds"
@@ -423,7 +428,7 @@ def wait_for_transactions(
423428
return responses
424429
if (time.time() - start_time) > self.transaction_wait_timeout:
425430
break
426-
time.sleep(1)
431+
time.sleep(self.poll_interval)
427432
missing_txs_strings = [
428433
f"{tx.hash} ({tx.model_dump_json()})" for tx in transactions if tx.hash in tx_hashes
429434
]

0 commit comments

Comments
 (0)