Skip to content

Commit 3deaeb3

Browse files
DefiDebaucherypacrob
authored and
pacrob
committed
asyncify eth.get_logs
1 parent fee4f4c commit 3deaeb3

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

docs/providers.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ Eth
418418
- :meth:`web3.eth.get_balance() <web3.eth.Eth.get_balance>`
419419
- :meth:`web3.eth.get_block() <web3.eth.Eth.get_block>`
420420
- :meth:`web3.eth.get_code() <web3.eth.Eth.get_code>`
421+
- :meth:`web3.eth.get_logs() <web3.eth.Eth.get_logs>`
421422
- :meth:`web3.eth.get_raw_transaction() <web3.eth.Eth.get_raw_transaction>`
422423
- :meth:`web3.eth.get_raw_transaction_by_block() <web3.eth.Eth.get_raw_transaction_by_block>`
423424
- :meth:`web3.eth.get_transaction() <web3.eth.Eth.get_transaction>`

newsfragments/2310.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add async `eth.get_logs` method

web3/_utils/module_testing/eth_module.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,141 @@ async def test_async_eth_accounts(self, async_w3: "Web3") -> None:
845845
))
846846
assert await async_w3.eth.coinbase in accounts # type: ignore
847847

848+
@pytest.mark.asyncio
849+
async def test_async_eth_get_logs_without_logs(
850+
self, async_w3: "Web3", block_with_txn_with_log: BlockData
851+
) -> None:
852+
# Test with block range
853+
854+
filter_params: FilterParams = {
855+
"fromBlock": BlockNumber(0),
856+
"toBlock": BlockNumber(block_with_txn_with_log['number'] - 1),
857+
}
858+
result = await async_w3.eth.get_logs(filter_params) # type: ignore
859+
assert len(result) == 0
860+
861+
# the range is wrong
862+
filter_params = {
863+
"fromBlock": block_with_txn_with_log['number'],
864+
"toBlock": BlockNumber(block_with_txn_with_log['number'] - 1),
865+
}
866+
result = await async_w3.eth.get_logs(filter_params) # type: ignore
867+
assert len(result) == 0
868+
869+
# Test with `address`
870+
871+
# filter with other address
872+
filter_params = {
873+
"fromBlock": BlockNumber(0),
874+
"address": UNKNOWN_ADDRESS,
875+
}
876+
result = await async_w3.eth.get_logs(filter_params) # type: ignore
877+
assert len(result) == 0
878+
879+
# Test with multiple `address`
880+
881+
# filter with other address
882+
filter_params = {
883+
"fromBlock": BlockNumber(0),
884+
"address": [UNKNOWN_ADDRESS, UNKNOWN_ADDRESS],
885+
}
886+
result = await async_w3.eth.get_logs(filter_params) # type: ignore
887+
assert len(result) == 0
888+
889+
@pytest.mark.asyncio
890+
async def test_async_eth_get_logs_with_logs(
891+
self,
892+
async_w3: "Web3",
893+
block_with_txn_with_log: BlockData,
894+
emitter_contract_address: ChecksumAddress,
895+
txn_hash_with_log: HexStr,
896+
) -> None:
897+
def assert_contains_log(result: Sequence[LogReceipt]) -> None:
898+
assert len(result) == 1
899+
log_entry = result[0]
900+
assert log_entry['blockNumber'] == block_with_txn_with_log['number']
901+
assert log_entry['blockHash'] == block_with_txn_with_log['hash']
902+
assert log_entry['logIndex'] == 0
903+
assert is_same_address(log_entry['address'], emitter_contract_address)
904+
assert log_entry['transactionIndex'] == 0
905+
assert log_entry['transactionHash'] == HexBytes(txn_hash_with_log)
906+
907+
# Test with block range
908+
909+
# the range includes the block where the log resides in
910+
filter_params: FilterParams = {
911+
"fromBlock": block_with_txn_with_log['number'],
912+
"toBlock": block_with_txn_with_log['number'],
913+
}
914+
result = await async_w3.eth.get_logs(filter_params) # type: ignore
915+
assert_contains_log(result)
916+
917+
# specify only `from_block`. by default `to_block` should be 'latest'
918+
filter_params = {
919+
"fromBlock": BlockNumber(0),
920+
}
921+
result = await async_w3.eth.get_logs(filter_params) # type: ignore
922+
assert_contains_log(result)
923+
924+
# Test with `address`
925+
926+
# filter with emitter_contract.address
927+
filter_params = {
928+
"fromBlock": BlockNumber(0),
929+
"address": emitter_contract_address,
930+
}
931+
932+
@pytest.mark.asyncio
933+
async def test_async_eth_get_logs_with_logs_topic_args(
934+
self,
935+
async_w3: "Web3",
936+
block_with_txn_with_log: BlockData,
937+
emitter_contract_address: ChecksumAddress,
938+
txn_hash_with_log: HexStr,
939+
) -> None:
940+
def assert_contains_log(result: Sequence[LogReceipt]) -> None:
941+
assert len(result) == 1
942+
log_entry = result[0]
943+
assert log_entry['blockNumber'] == block_with_txn_with_log['number']
944+
assert log_entry['blockHash'] == block_with_txn_with_log['hash']
945+
assert log_entry['logIndex'] == 0
946+
assert is_same_address(log_entry['address'], emitter_contract_address)
947+
assert log_entry['transactionIndex'] == 0
948+
assert log_entry['transactionHash'] == HexBytes(txn_hash_with_log)
949+
950+
# Test with None event sig
951+
952+
filter_params: FilterParams = {
953+
"fromBlock": BlockNumber(0),
954+
"topics": [
955+
None,
956+
HexStr('0x000000000000000000000000000000000000000000000000000000000000d431')],
957+
}
958+
959+
result = await async_w3.eth.get_logs(filter_params) # type: ignore
960+
assert_contains_log(result)
961+
962+
# Test with None indexed arg
963+
filter_params = {
964+
"fromBlock": BlockNumber(0),
965+
"topics": [
966+
HexStr('0x057bc32826fbe161da1c110afcdcae7c109a8b69149f727fc37a603c60ef94ca'),
967+
None],
968+
}
969+
result = await async_w3.eth.get_logs(filter_params) # type: ignore
970+
assert_contains_log(result)
971+
972+
@pytest.mark.asyncio
973+
async def test_async_eth_get_logs_with_logs_none_topic_args(self, async_w3: "Web3") -> None:
974+
# Test with None overflowing
975+
filter_params: FilterParams = {
976+
"fromBlock": BlockNumber(0),
977+
"topics": [None, None, None],
978+
}
979+
980+
result = await async_w3.eth.get_logs(filter_params) # type: ignore
981+
assert len(result) == 0
982+
848983

849984
class EthModuleTest:
850985
def test_eth_protocol_version(self, web3: "Web3") -> None:

web3/eth.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,17 @@ async def get_code(
401401
) -> HexBytes:
402402
return await self._get_code(account, block_identifier)
403403

404+
_get_logs: Method[Callable[[FilterParams], Awaitable[List[LogReceipt]]]] = Method(
405+
RPC.eth_getLogs,
406+
mungers=[default_root_munger]
407+
)
408+
409+
async def get_logs(
410+
self,
411+
filter_params: FilterParams,
412+
) -> List[LogReceipt]:
413+
return await self._get_logs(filter_params)
414+
404415
_get_transaction_count: Method[Callable[..., Awaitable[Nonce]]] = Method(
405416
RPC.eth_getTransactionCount,
406417
mungers=[BaseEth.block_id_munger],

0 commit comments

Comments
 (0)