Skip to content

Commit

Permalink
clean up per comments in #2265 & #2269
Browse files Browse the repository at this point in the history
- cleaned up async wait_for_transaction_receipt()
- added tests for sync wait_for_transaction_receipt()
- updated tests for async wait_for_transaction_receipt()
  • Loading branch information
Paul Robinson authored Dec 21, 2021
1 parent c70f7fb commit a6642a2
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 30 deletions.
11 changes: 11 additions & 0 deletions tests/integration/test_ethereum_tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,17 @@ def test_eth_getTransactionReceipt_mined_deprecated(self, web3, block_with_txn,
block_with_txn,
mined_txn_hash)

@pytest.mark.xfail(raises=KeyError, reason="ethereum tester doesn't return 'to' key")
def test_eth_wait_for_transaction_receipt_mined(self, web3, block_with_txn, mined_txn_hash):
super().test_eth_wait_for_transaction_receipt_mined(web3, block_with_txn, mined_txn_hash)

@disable_auto_mine
def test_eth_wait_for_transaction_receipt_unmined(self,
eth_tester,
web3,
unlocked_account_dual_type):
super().test_eth_wait_for_transaction_receipt_unmined(web3, unlocked_account_dual_type)

@pytest.mark.xfail(raises=TypeError, reason="call override param not implemented on eth-tester")
def test_eth_call_with_override(self, web3, revert_contract):
super().test_eth_call_with_override(web3, revert_contract)
Expand Down
71 changes: 69 additions & 2 deletions web3/_utils/module_testing/eth_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -800,8 +800,13 @@ async def test_async_eth_wait_for_transaction_receipt_unmined(
'maxFeePerGas': async_w3.toWei(3, 'gwei'),
'maxPriorityFeePerGas': async_w3.toWei(1, 'gwei')
})
with pytest.raises(TimeExhausted):
await async_w3.eth.wait_for_transaction_receipt(txn_hash, timeout=2) # type: ignore

timeout = 2
with pytest.raises(TimeExhausted) as exc_info:
await async_w3.eth.wait_for_transaction_receipt(txn_hash, # type: ignore
timeout=timeout)

assert (_ in str(exc_info) for _ in [repr(txn_hash), timeout])

@pytest.mark.asyncio
async def test_async_eth_wait_for_transaction_receipt_with_log_entry(
Expand Down Expand Up @@ -2484,6 +2489,68 @@ def test_eth_get_transaction_receipt_with_log_entry(
assert log_entry['transactionIndex'] == 0
assert log_entry['transactionHash'] == HexBytes(txn_hash_with_log)

def test_eth_wait_for_transaction_receipt_mined(
self,
web3: "Web3",
block_with_txn: BlockData,
mined_txn_hash: HexStr
) -> None:
receipt = web3.eth.wait_for_transaction_receipt(mined_txn_hash)
assert is_dict(receipt)
assert receipt['blockNumber'] == block_with_txn['number']
assert receipt['blockHash'] == block_with_txn['hash']
assert receipt['transactionIndex'] == 0
assert receipt['transactionHash'] == HexBytes(mined_txn_hash)
assert is_checksum_address(receipt['to'])
assert receipt['from'] is not None
assert is_checksum_address(receipt['from'])

effective_gas_price = receipt['effectiveGasPrice']
assert isinstance(effective_gas_price, int)
assert effective_gas_price > 0

def test_eth_wait_for_transaction_receipt_unmined(
self, web3: "Web3", unlocked_account_dual_type: ChecksumAddress
) -> None:
txn_hash = web3.eth.send_transaction({
'from': unlocked_account_dual_type,
'to': unlocked_account_dual_type,
'value': Wei(1),
'gas': Wei(21000),
'maxFeePerGas': web3.toWei(3, 'gwei'),
'maxPriorityFeePerGas': web3.toWei(1, 'gwei')
})

timeout = 2
with pytest.raises(TimeExhausted) as exc_info:
web3.eth.wait_for_transaction_receipt(txn_hash, timeout=timeout)

assert (_ in str(exc_info) for _ in [repr(txn_hash), timeout])

def test_eth_wait_for_transaction_receipt_with_log_entry(
self,
web3: "Web3",
block_with_txn_with_log: BlockData,
emitter_contract: "Contract",
txn_hash_with_log: HexStr,
) -> None:
receipt = web3.eth.wait_for_transaction_receipt(txn_hash_with_log)
assert is_dict(receipt)
assert receipt['blockNumber'] == block_with_txn_with_log['number']
assert receipt['blockHash'] == block_with_txn_with_log['hash']
assert receipt['transactionIndex'] == 0
assert receipt['transactionHash'] == HexBytes(txn_hash_with_log)

assert len(receipt['logs']) == 1
log_entry = receipt['logs'][0]

assert log_entry['blockNumber'] == block_with_txn_with_log['number']
assert log_entry['blockHash'] == block_with_txn_with_log['hash']
assert log_entry['logIndex'] == 0
assert is_same_address(log_entry['address'], emitter_contract.address)
assert log_entry['transactionIndex'] == 0
assert log_entry['transactionHash'] == HexBytes(txn_hash_with_log)

def test_eth_getUncleByBlockHashAndIndex(self, web3: "Web3") -> None:
# TODO: how do we make uncles....
pass
Expand Down
50 changes: 22 additions & 28 deletions web3/eth.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
from typing import (
Any,
Awaitable,
Expand Down Expand Up @@ -282,12 +283,6 @@ def call_munger(
mungers=[default_root_munger]
)

# _get_transaction_receipt_awaitable: Method[Callable[[_Hash32],
# Awaitable[TxReceipt]]] = Method(
# RPC.eth_getTransactionReceipt,
# mungers=[default_root_munger]
# )


class AsyncEth(BaseEth):
is_async = True
Expand Down Expand Up @@ -422,26 +417,27 @@ async def get_transaction_receipt(
async def wait_for_transaction_receipt(
self, transaction_hash: _Hash32, timeout: float = 120, poll_latency: float = 0.1
) -> TxReceipt:
try:
with Timeout(timeout) as _timeout:
while True:
try:
tx_receipt = await self._get_transaction_receipt( # type: ignore
transaction_hash
)
except TransactionNotFound:
tx_receipt = None
if tx_receipt is not None:
break
_timeout.sleep(poll_latency)
async def _wait_for_tx_receipt_with_timeout(
_tx_hash: _Hash32, _poll_latence: float
) -> TxReceipt:
while True:
try:
tx_receipt = await self._get_transaction_receipt(_tx_hash) # type: ignore
except TransactionNotFound:
tx_receipt = None
if tx_receipt is not None:
break
await asyncio.sleep(poll_latency)
return tx_receipt

except Timeout:
try:
return await asyncio.wait_for(
_wait_for_tx_receipt_with_timeout(transaction_hash, poll_latency),
timeout=timeout,
)
except asyncio.TimeoutError:
raise TimeExhausted(
"Transaction {!r} is not in the chain, after {} seconds".format(
HexBytes(transaction_hash),
timeout,
)
f"Transaction {HexBytes(transaction_hash) !r} is not in the chain "
f"after {timeout} seconds"
)

async def call(
Expand Down Expand Up @@ -737,10 +733,8 @@ def wait_for_transaction_receipt(

except Timeout:
raise TimeExhausted(
"Transaction {!r} is not in the chain, after {} seconds".format(
HexBytes(transaction_hash),
timeout,
)
f"Transaction {HexBytes(transaction_hash) !r} is not in the chain "
f"after {timeout} seconds"
)

def get_transaction_receipt(
Expand Down

0 comments on commit a6642a2

Please sign in to comment.