web3 7.0.0b8__py3-none-any.whl → 7.0.0b9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ens/async_ens.py +16 -7
- ens/base_ens.py +3 -1
- ens/exceptions.py +2 -7
- ens/utils.py +0 -17
- web3/_utils/abi.py +100 -257
- web3/_utils/compat/__init__.py +1 -0
- web3/_utils/contracts.py +116 -205
- web3/_utils/encoding.py +4 -5
- web3/_utils/events.py +28 -33
- web3/_utils/fee_utils.py +2 -2
- web3/_utils/filters.py +2 -5
- web3/_utils/http_session_manager.py +30 -7
- web3/_utils/method_formatters.py +3 -3
- web3/_utils/module_testing/eth_module.py +59 -37
- web3/_utils/module_testing/module_testing_utils.py +43 -1
- web3/_utils/module_testing/persistent_connection_provider.py +2 -0
- web3/_utils/module_testing/web3_module.py +8 -8
- web3/_utils/normalizers.py +10 -8
- web3/_utils/validation.py +5 -7
- web3/contract/async_contract.py +18 -17
- web3/contract/base_contract.py +116 -80
- web3/contract/contract.py +16 -17
- web3/contract/utils.py +86 -55
- web3/eth/async_eth.py +1 -2
- web3/eth/eth.py +1 -2
- web3/exceptions.py +22 -9
- web3/gas_strategies/time_based.py +4 -0
- web3/manager.py +34 -12
- web3/middleware/filter.py +3 -3
- web3/middleware/signing.py +6 -1
- web3/types.py +5 -45
- web3/utils/__init__.py +48 -4
- web3/utils/abi.py +575 -10
- {web3-7.0.0b8.dist-info → web3-7.0.0b9.dist-info}/METADATA +7 -5
- {web3-7.0.0b8.dist-info → web3-7.0.0b9.dist-info}/RECORD +39 -44
- {web3-7.0.0b8.dist-info → web3-7.0.0b9.dist-info}/WHEEL +1 -1
- web3/tools/benchmark/__init__.py +0 -0
- web3/tools/benchmark/main.py +0 -190
- web3/tools/benchmark/node.py +0 -120
- web3/tools/benchmark/reporting.py +0 -39
- web3/tools/benchmark/utils.py +0 -69
- /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
- {web3-7.0.0b8.dist-info → web3-7.0.0b9.dist-info}/LICENSE +0 -0
- {web3-7.0.0b8.dist-info → web3-7.0.0b9.dist-info}/top_level.txt +0 -0
web3/_utils/fee_utils.py
CHANGED
|
@@ -45,7 +45,7 @@ def fee_history_priority_fee(eth: "Eth") -> Wei:
|
|
|
45
45
|
# This is a tested internal call so no need for type hinting. We can keep
|
|
46
46
|
# better consistency between the sync and async calls by unpacking
|
|
47
47
|
# PRIORITY_FEE_HISTORY_PARAMS as constants here.
|
|
48
|
-
fee_history = eth.fee_history(*PRIORITY_FEE_HISTORY_PARAMS)
|
|
48
|
+
fee_history = eth.fee_history(*PRIORITY_FEE_HISTORY_PARAMS) # type: ignore
|
|
49
49
|
return _fee_history_priority_fee_estimate(fee_history)
|
|
50
50
|
|
|
51
51
|
|
|
@@ -53,5 +53,5 @@ async def async_fee_history_priority_fee(async_eth: "AsyncEth") -> Wei:
|
|
|
53
53
|
# This is a tested internal call so no need for type hinting. We can keep
|
|
54
54
|
# better consistency between the sync and async calls by unpacking
|
|
55
55
|
# PRIORITY_FEE_HISTORY_PARAMS as constants here.
|
|
56
|
-
fee_history = await async_eth.fee_history(*PRIORITY_FEE_HISTORY_PARAMS)
|
|
56
|
+
fee_history = await async_eth.fee_history(*PRIORITY_FEE_HISTORY_PARAMS) # type: ignore # noqa: E501
|
|
57
57
|
return _fee_history_priority_fee_estimate(fee_history)
|
web3/_utils/filters.py
CHANGED
|
@@ -19,6 +19,7 @@ from eth_abi.grammar import (
|
|
|
19
19
|
parse as parse_type_string,
|
|
20
20
|
)
|
|
21
21
|
from eth_typing import (
|
|
22
|
+
ABIEvent,
|
|
22
23
|
ChecksumAddress,
|
|
23
24
|
HexStr,
|
|
24
25
|
TypeStr,
|
|
@@ -55,7 +56,6 @@ from web3.exceptions import (
|
|
|
55
56
|
Web3ValueError,
|
|
56
57
|
)
|
|
57
58
|
from web3.types import (
|
|
58
|
-
ABIEvent,
|
|
59
59
|
BlockIdentifier,
|
|
60
60
|
FilterParams,
|
|
61
61
|
LogReceipt,
|
|
@@ -90,10 +90,7 @@ def construct_event_filter_params(
|
|
|
90
90
|
)
|
|
91
91
|
topic_set = topics
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
filter_params["topics"] = topic_set[0]
|
|
95
|
-
else:
|
|
96
|
-
filter_params["topics"] = topic_set
|
|
93
|
+
filter_params["topics"] = topic_set
|
|
97
94
|
|
|
98
95
|
if address and contract_address:
|
|
99
96
|
if is_list_like(address):
|
|
@@ -5,6 +5,7 @@ from concurrent.futures import (
|
|
|
5
5
|
import logging
|
|
6
6
|
import os
|
|
7
7
|
import threading
|
|
8
|
+
import time
|
|
8
9
|
from typing import (
|
|
9
10
|
Any,
|
|
10
11
|
Dict,
|
|
@@ -32,6 +33,9 @@ from web3._utils.caching import (
|
|
|
32
33
|
from web3._utils.http import (
|
|
33
34
|
DEFAULT_HTTP_TIMEOUT,
|
|
34
35
|
)
|
|
36
|
+
from web3.exceptions import (
|
|
37
|
+
TimeExhausted,
|
|
38
|
+
)
|
|
35
39
|
from web3.utils.caching import (
|
|
36
40
|
SimpleCache,
|
|
37
41
|
)
|
|
@@ -115,21 +119,40 @@ class HTTPSessionManager:
|
|
|
115
119
|
def get_response_from_post_request(
|
|
116
120
|
self, endpoint_uri: URI, *args: Any, **kwargs: Any
|
|
117
121
|
) -> requests.Response:
|
|
118
|
-
kwargs.setdefault("timeout", DEFAULT_HTTP_TIMEOUT)
|
|
119
122
|
session = self.cache_and_return_session(
|
|
120
123
|
endpoint_uri, request_timeout=kwargs["timeout"]
|
|
121
124
|
)
|
|
122
|
-
|
|
123
|
-
return response
|
|
125
|
+
return session.post(endpoint_uri, *args, **kwargs)
|
|
124
126
|
|
|
125
127
|
def make_post_request(
|
|
126
128
|
self, endpoint_uri: URI, data: Union[bytes, Dict[str, Any]], **kwargs: Any
|
|
127
129
|
) -> bytes:
|
|
128
|
-
|
|
130
|
+
kwargs.setdefault("timeout", DEFAULT_HTTP_TIMEOUT)
|
|
131
|
+
kwargs.setdefault("stream", False)
|
|
132
|
+
|
|
133
|
+
start = time.time()
|
|
134
|
+
timeout = kwargs["timeout"]
|
|
135
|
+
|
|
136
|
+
with self.get_response_from_post_request(
|
|
129
137
|
endpoint_uri, data=data, **kwargs
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
|
|
138
|
+
) as response:
|
|
139
|
+
response.raise_for_status()
|
|
140
|
+
if kwargs.get("stream"):
|
|
141
|
+
return self._handle_streaming_response(response, start, timeout)
|
|
142
|
+
else:
|
|
143
|
+
return response.content
|
|
144
|
+
|
|
145
|
+
def _handle_streaming_response(
|
|
146
|
+
self, response: requests.Response, start: float, timeout: float
|
|
147
|
+
) -> bytes:
|
|
148
|
+
response_body = b""
|
|
149
|
+
for data in response.iter_content():
|
|
150
|
+
response_body += data
|
|
151
|
+
# Manually manage timeout so streaming responses time out
|
|
152
|
+
# rather than resetting the timeout each time a response comes back
|
|
153
|
+
if (time.time() - start) > timeout:
|
|
154
|
+
raise TimeExhausted
|
|
155
|
+
return response_body
|
|
133
156
|
|
|
134
157
|
def _close_evicted_sessions(self, evicted_sessions: List[requests.Session]) -> None:
|
|
135
158
|
for evicted_session in evicted_sessions:
|
web3/_utils/method_formatters.py
CHANGED
|
@@ -199,7 +199,7 @@ def storage_key_to_hexstr(value: Union[bytes, int, str]) -> HexStr:
|
|
|
199
199
|
return HexStr(f"0x{value}")
|
|
200
200
|
elif isinstance(value, bytes):
|
|
201
201
|
if len(value) == 32:
|
|
202
|
-
return HexBytes(value).to_0x_hex()
|
|
202
|
+
return cast(HexStr, HexBytes(value).to_0x_hex())
|
|
203
203
|
elif isinstance(value, int):
|
|
204
204
|
return storage_key_to_hexstr(hex(value))
|
|
205
205
|
raise Web3ValueError(f"Storage key must be a 32-byte value, got {value!r}")
|
|
@@ -424,8 +424,8 @@ ACCOUNT_PROOF_FORMATTERS = {
|
|
|
424
424
|
proof_formatter = type_aware_apply_formatters_to_dict(ACCOUNT_PROOF_FORMATTERS)
|
|
425
425
|
|
|
426
426
|
FILTER_PARAMS_FORMATTERS = {
|
|
427
|
-
"fromBlock":
|
|
428
|
-
"toBlock":
|
|
427
|
+
"fromBlock": to_hex_if_integer,
|
|
428
|
+
"toBlock": to_hex_if_integer,
|
|
429
429
|
}
|
|
430
430
|
|
|
431
431
|
|
|
@@ -58,6 +58,7 @@ from web3._utils.module_testing.module_testing_utils import (
|
|
|
58
58
|
assert_contains_log,
|
|
59
59
|
async_mock_offchain_lookup_request_response,
|
|
60
60
|
flaky_geth_dev_mining,
|
|
61
|
+
flaky_with_xfail_on_exception,
|
|
61
62
|
mock_offchain_lookup_request_response,
|
|
62
63
|
)
|
|
63
64
|
from web3._utils.module_testing.utils import (
|
|
@@ -76,6 +77,7 @@ from web3.exceptions import (
|
|
|
76
77
|
MultipleFailedRequests,
|
|
77
78
|
NameNotFound,
|
|
78
79
|
OffchainLookup,
|
|
80
|
+
RequestTimedOut,
|
|
79
81
|
TimeExhausted,
|
|
80
82
|
TooManyRequests,
|
|
81
83
|
TransactionNotFound,
|
|
@@ -498,6 +500,7 @@ class AsyncEthModuleTest:
|
|
|
498
500
|
"maxFeePerGas": async_w3.to_wei(3, "gwei"),
|
|
499
501
|
"maxPriorityFeePerGas": async_w3.to_wei(1, "gwei"),
|
|
500
502
|
}
|
|
503
|
+
|
|
501
504
|
txn_hash = await async_w3.eth.send_transaction(txn_params)
|
|
502
505
|
txn = await async_w3.eth.get_transaction(txn_hash)
|
|
503
506
|
|
|
@@ -507,7 +510,7 @@ class AsyncEthModuleTest:
|
|
|
507
510
|
assert txn["gas"] == 21000
|
|
508
511
|
assert txn["maxFeePerGas"] == txn_params["maxFeePerGas"]
|
|
509
512
|
assert txn["maxPriorityFeePerGas"] == txn_params["maxPriorityFeePerGas"]
|
|
510
|
-
assert txn["gasPrice"]
|
|
513
|
+
assert txn["gasPrice"] <= txn["maxFeePerGas"] # effective gas price
|
|
511
514
|
|
|
512
515
|
@pytest.mark.asyncio
|
|
513
516
|
async def test_eth_send_transaction_default_fees(
|
|
@@ -521,6 +524,7 @@ class AsyncEthModuleTest:
|
|
|
521
524
|
"value": Wei(1),
|
|
522
525
|
"gas": 21000,
|
|
523
526
|
}
|
|
527
|
+
|
|
524
528
|
txn_hash = await async_w3.eth.send_transaction(txn_params)
|
|
525
529
|
txn = await async_w3.eth.get_transaction(txn_hash)
|
|
526
530
|
|
|
@@ -530,7 +534,7 @@ class AsyncEthModuleTest:
|
|
|
530
534
|
assert txn["gas"] == 21000
|
|
531
535
|
assert is_integer(txn["maxPriorityFeePerGas"])
|
|
532
536
|
assert is_integer(txn["maxFeePerGas"])
|
|
533
|
-
assert txn["gasPrice"]
|
|
537
|
+
assert txn["gasPrice"] <= txn["maxFeePerGas"] # effective gas price
|
|
534
538
|
|
|
535
539
|
@pytest.mark.asyncio
|
|
536
540
|
async def test_eth_send_transaction_hex_fees(
|
|
@@ -807,7 +811,7 @@ class AsyncEthModuleTest:
|
|
|
807
811
|
else 2 * latest_block["baseFeePerGas"] + max_priority_fee
|
|
808
812
|
)
|
|
809
813
|
assert txn["maxPriorityFeePerGas"] == max_priority_fee
|
|
810
|
-
assert txn["gasPrice"]
|
|
814
|
+
assert txn["gasPrice"] <= txn["maxFeePerGas"] # effective gas price
|
|
811
815
|
|
|
812
816
|
async_w3.eth.set_gas_price_strategy(None) # reset strategy
|
|
813
817
|
|
|
@@ -1145,7 +1149,8 @@ class AsyncEthModuleTest:
|
|
|
1145
1149
|
f"{unknown_identifier}"
|
|
1146
1150
|
),
|
|
1147
1151
|
):
|
|
1148
|
-
|
|
1152
|
+
# type ignored because we are testing an invalid block identifier
|
|
1153
|
+
await async_w3.eth.get_raw_transaction_by_block(unknown_identifier, 0) # type: ignore # noqa: E501
|
|
1149
1154
|
|
|
1150
1155
|
@pytest.mark.asyncio
|
|
1151
1156
|
async def test_eth_get_balance(self, async_w3: "AsyncWeb3") -> None:
|
|
@@ -1240,7 +1245,7 @@ class AsyncEthModuleTest:
|
|
|
1240
1245
|
account = accounts[0]
|
|
1241
1246
|
|
|
1242
1247
|
txn_params = async_math_contract._prepare_transaction(
|
|
1243
|
-
|
|
1248
|
+
abi_element_identifier="add",
|
|
1244
1249
|
fn_args=(7, 11),
|
|
1245
1250
|
transaction={"from": account, "to": async_math_contract.address},
|
|
1246
1251
|
)
|
|
@@ -1258,7 +1263,7 @@ class AsyncEthModuleTest:
|
|
|
1258
1263
|
accounts = await async_w3.eth.accounts
|
|
1259
1264
|
account = accounts[0]
|
|
1260
1265
|
txn_params = async_revert_contract._prepare_transaction(
|
|
1261
|
-
|
|
1266
|
+
abi_element_identifier="normalFunction",
|
|
1262
1267
|
transaction={"from": account, "to": async_revert_contract.address},
|
|
1263
1268
|
)
|
|
1264
1269
|
call_result = await async_w3.eth.call(txn_params)
|
|
@@ -1327,7 +1332,7 @@ class AsyncEthModuleTest:
|
|
|
1327
1332
|
) -> None:
|
|
1328
1333
|
accounts = await async_w3.eth.accounts
|
|
1329
1334
|
txn_params = async_math_contract._prepare_transaction(
|
|
1330
|
-
|
|
1335
|
+
abi_element_identifier="add",
|
|
1331
1336
|
fn_args=(0, 0),
|
|
1332
1337
|
transaction={"from": accounts[0], "to": async_math_contract.address},
|
|
1333
1338
|
)
|
|
@@ -1344,7 +1349,7 @@ class AsyncEthModuleTest:
|
|
|
1344
1349
|
async_keyfile_account_address: ChecksumAddress,
|
|
1345
1350
|
) -> None:
|
|
1346
1351
|
txn_params = async_revert_contract._prepare_transaction(
|
|
1347
|
-
|
|
1352
|
+
abi_element_identifier="revertWithMessage",
|
|
1348
1353
|
transaction={
|
|
1349
1354
|
"from": async_keyfile_account_address,
|
|
1350
1355
|
"to": async_revert_contract.address,
|
|
@@ -1364,7 +1369,7 @@ class AsyncEthModuleTest:
|
|
|
1364
1369
|
) -> None:
|
|
1365
1370
|
with pytest.raises(ContractLogicError, match="execution reverted"):
|
|
1366
1371
|
txn_params = async_revert_contract._prepare_transaction(
|
|
1367
|
-
|
|
1372
|
+
abi_element_identifier="revertWithoutMessage",
|
|
1368
1373
|
transaction={
|
|
1369
1374
|
"from": async_keyfile_account_address,
|
|
1370
1375
|
"to": async_revert_contract.address,
|
|
@@ -1380,10 +1385,11 @@ class AsyncEthModuleTest:
|
|
|
1380
1385
|
async_keyfile_account_address: ChecksumAddress,
|
|
1381
1386
|
) -> None:
|
|
1382
1387
|
data = async_revert_contract.encode_abi(
|
|
1383
|
-
|
|
1388
|
+
abi_element_identifier="UnauthorizedWithMessage",
|
|
1389
|
+
args=["You are not authorized"],
|
|
1384
1390
|
)
|
|
1385
1391
|
txn_params = async_revert_contract._prepare_transaction(
|
|
1386
|
-
|
|
1392
|
+
abi_element_identifier="customErrorWithMessage",
|
|
1387
1393
|
transaction={
|
|
1388
1394
|
"from": async_keyfile_account_address,
|
|
1389
1395
|
"to": async_revert_contract.address,
|
|
@@ -1399,9 +1405,9 @@ class AsyncEthModuleTest:
|
|
|
1399
1405
|
async_revert_contract: "AsyncContract",
|
|
1400
1406
|
async_keyfile_account_address: ChecksumAddress,
|
|
1401
1407
|
) -> None:
|
|
1402
|
-
data = async_revert_contract.encode_abi(
|
|
1408
|
+
data = async_revert_contract.encode_abi(abi_element_identifier="Unauthorized")
|
|
1403
1409
|
txn_params = async_revert_contract._prepare_transaction(
|
|
1404
|
-
|
|
1410
|
+
abi_element_identifier="customErrorWithoutMessage",
|
|
1405
1411
|
transaction={
|
|
1406
1412
|
"from": async_keyfile_account_address,
|
|
1407
1413
|
"to": async_revert_contract.address,
|
|
@@ -1692,6 +1698,7 @@ class AsyncEthModuleTest:
|
|
|
1692
1698
|
assert isinstance(effective_gas_price, int)
|
|
1693
1699
|
assert effective_gas_price > 0
|
|
1694
1700
|
|
|
1701
|
+
@flaky_geth_dev_mining
|
|
1695
1702
|
@pytest.mark.asyncio
|
|
1696
1703
|
async def test_async_eth_get_transaction_receipt_unmined(
|
|
1697
1704
|
self,
|
|
@@ -1757,6 +1764,7 @@ class AsyncEthModuleTest:
|
|
|
1757
1764
|
assert isinstance(effective_gas_price, int)
|
|
1758
1765
|
assert effective_gas_price > 0
|
|
1759
1766
|
|
|
1767
|
+
@flaky_geth_dev_mining
|
|
1760
1768
|
@pytest.mark.asyncio
|
|
1761
1769
|
async def test_async_eth_wait_for_transaction_receipt_unmined(
|
|
1762
1770
|
self,
|
|
@@ -2356,7 +2364,10 @@ class AsyncEthModuleTest:
|
|
|
2356
2364
|
with pytest.raises(Web3ValueError):
|
|
2357
2365
|
await async_w3.eth.replace_transaction(txn_hash, txn_params)
|
|
2358
2366
|
|
|
2359
|
-
@
|
|
2367
|
+
@flaky_with_xfail_on_exception(
|
|
2368
|
+
reason="Very flaky on CI runs, hard to reproduce locally.",
|
|
2369
|
+
exception=RequestTimedOut,
|
|
2370
|
+
)
|
|
2360
2371
|
@pytest.mark.asyncio
|
|
2361
2372
|
async def test_async_eth_replace_transaction_gas_price_defaulting_minimum(
|
|
2362
2373
|
self, async_w3: "AsyncWeb3", async_keyfile_account_address: ChecksumAddress
|
|
@@ -2380,7 +2391,10 @@ class AsyncEthModuleTest:
|
|
|
2380
2391
|
gas_price * 1.125
|
|
2381
2392
|
) # minimum gas price
|
|
2382
2393
|
|
|
2383
|
-
@
|
|
2394
|
+
@flaky_with_xfail_on_exception(
|
|
2395
|
+
reason="Very flaky on CI runs, hard to reproduce locally.",
|
|
2396
|
+
exception=RequestTimedOut,
|
|
2397
|
+
)
|
|
2384
2398
|
@pytest.mark.asyncio
|
|
2385
2399
|
async def test_async_eth_replace_transaction_gas_price_defaulting_strategy_higher(
|
|
2386
2400
|
self, async_w3: "AsyncWeb3", async_keyfile_account_address: ChecksumAddress
|
|
@@ -2409,7 +2423,10 @@ class AsyncEthModuleTest:
|
|
|
2409
2423
|
) # Strategy provides higher gas price
|
|
2410
2424
|
async_w3.eth.set_gas_price_strategy(None) # reset strategy
|
|
2411
2425
|
|
|
2412
|
-
@
|
|
2426
|
+
@flaky_with_xfail_on_exception(
|
|
2427
|
+
reason="Very flaky on CI runs, hard to reproduce locally.",
|
|
2428
|
+
exception=RequestTimedOut,
|
|
2429
|
+
)
|
|
2413
2430
|
@pytest.mark.asyncio
|
|
2414
2431
|
async def test_async_eth_replace_transaction_gas_price_defaulting_strategy_lower(
|
|
2415
2432
|
self, async_w3: "AsyncWeb3", async_keyfile_account_address: ChecksumAddress
|
|
@@ -3101,6 +3118,7 @@ class EthModuleTest:
|
|
|
3101
3118
|
"maxFeePerGas": w3.to_wei(3, "gwei"),
|
|
3102
3119
|
"maxPriorityFeePerGas": w3.to_wei(1, "gwei"),
|
|
3103
3120
|
}
|
|
3121
|
+
|
|
3104
3122
|
txn_hash = w3.eth.send_transaction(txn_params)
|
|
3105
3123
|
txn = w3.eth.get_transaction(txn_hash)
|
|
3106
3124
|
|
|
@@ -3110,7 +3128,7 @@ class EthModuleTest:
|
|
|
3110
3128
|
assert txn["gas"] == 21000
|
|
3111
3129
|
assert txn["maxFeePerGas"] == txn_params["maxFeePerGas"]
|
|
3112
3130
|
assert txn["maxPriorityFeePerGas"] == txn_params["maxPriorityFeePerGas"]
|
|
3113
|
-
assert txn["gasPrice"]
|
|
3131
|
+
assert txn["gasPrice"] <= txn["maxFeePerGas"] # effective gas price
|
|
3114
3132
|
|
|
3115
3133
|
def test_eth_send_transaction_with_nonce(
|
|
3116
3134
|
self, w3: "Web3", keyfile_account_address: ChecksumAddress
|
|
@@ -3161,7 +3179,7 @@ class EthModuleTest:
|
|
|
3161
3179
|
assert txn["gas"] == 21000
|
|
3162
3180
|
assert is_integer(txn["maxPriorityFeePerGas"])
|
|
3163
3181
|
assert is_integer(txn["maxFeePerGas"])
|
|
3164
|
-
assert txn["gasPrice"]
|
|
3182
|
+
assert txn["gasPrice"] <= txn["maxFeePerGas"] # effective gas price
|
|
3165
3183
|
|
|
3166
3184
|
def test_eth_send_transaction_hex_fees(
|
|
3167
3185
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
@@ -3327,7 +3345,7 @@ class EthModuleTest:
|
|
|
3327
3345
|
else 2 * latest_block["baseFeePerGas"] + max_priority_fee
|
|
3328
3346
|
)
|
|
3329
3347
|
assert txn["maxPriorityFeePerGas"] == max_priority_fee
|
|
3330
|
-
assert txn["gasPrice"]
|
|
3348
|
+
assert txn["gasPrice"] <= txn["maxFeePerGas"] # effective gas price
|
|
3331
3349
|
|
|
3332
3350
|
w3.eth.set_gas_price_strategy(None) # reset strategy
|
|
3333
3351
|
|
|
@@ -3596,7 +3614,6 @@ class EthModuleTest:
|
|
|
3596
3614
|
self, w3: "Web3", keyfile_account_address: ChecksumAddress
|
|
3597
3615
|
) -> None:
|
|
3598
3616
|
gas_price = w3.to_wei(2, "gwei")
|
|
3599
|
-
|
|
3600
3617
|
txn_params: TxParams = {
|
|
3601
3618
|
"from": keyfile_account_address,
|
|
3602
3619
|
"to": keyfile_account_address,
|
|
@@ -3701,7 +3718,7 @@ class EthModuleTest:
|
|
|
3701
3718
|
|
|
3702
3719
|
def test_eth_call(self, w3: "Web3", math_contract: "Contract") -> None:
|
|
3703
3720
|
txn_params = math_contract._prepare_transaction(
|
|
3704
|
-
|
|
3721
|
+
abi_element_identifier="add",
|
|
3705
3722
|
fn_args=(7, 11),
|
|
3706
3723
|
transaction={"from": w3.eth.accounts[0], "to": math_contract.address},
|
|
3707
3724
|
)
|
|
@@ -3714,7 +3731,7 @@ class EthModuleTest:
|
|
|
3714
3731
|
self, w3: "Web3", revert_contract: "Contract"
|
|
3715
3732
|
) -> None:
|
|
3716
3733
|
txn_params = revert_contract._prepare_transaction(
|
|
3717
|
-
|
|
3734
|
+
abi_element_identifier="normalFunction",
|
|
3718
3735
|
transaction={"from": w3.eth.accounts[0], "to": revert_contract.address},
|
|
3719
3736
|
)
|
|
3720
3737
|
call_result = w3.eth.call(txn_params)
|
|
@@ -3775,7 +3792,7 @@ class EthModuleTest:
|
|
|
3775
3792
|
self, w3: "Web3", math_contract: "Contract"
|
|
3776
3793
|
) -> None:
|
|
3777
3794
|
txn_params = math_contract._prepare_transaction(
|
|
3778
|
-
|
|
3795
|
+
abi_element_identifier="add",
|
|
3779
3796
|
fn_args=(0, 0),
|
|
3780
3797
|
transaction={"from": w3.eth.accounts[0], "to": math_contract.address},
|
|
3781
3798
|
)
|
|
@@ -3791,7 +3808,7 @@ class EthModuleTest:
|
|
|
3791
3808
|
keyfile_account_address: ChecksumAddress,
|
|
3792
3809
|
) -> None:
|
|
3793
3810
|
txn_params = revert_contract._prepare_transaction(
|
|
3794
|
-
|
|
3811
|
+
abi_element_identifier="revertWithMessage",
|
|
3795
3812
|
transaction={
|
|
3796
3813
|
"from": keyfile_account_address,
|
|
3797
3814
|
"to": revert_contract.address,
|
|
@@ -3812,7 +3829,7 @@ class EthModuleTest:
|
|
|
3812
3829
|
) -> None:
|
|
3813
3830
|
with pytest.raises(ContractLogicError, match="execution reverted"):
|
|
3814
3831
|
txn_params = revert_contract._prepare_transaction(
|
|
3815
|
-
|
|
3832
|
+
abi_element_identifier="revertWithoutMessage",
|
|
3816
3833
|
transaction={
|
|
3817
3834
|
"from": keyfile_account_address,
|
|
3818
3835
|
"to": revert_contract.address,
|
|
@@ -3827,10 +3844,11 @@ class EthModuleTest:
|
|
|
3827
3844
|
keyfile_account_address: ChecksumAddress,
|
|
3828
3845
|
) -> None:
|
|
3829
3846
|
data = revert_contract.encode_abi(
|
|
3830
|
-
|
|
3847
|
+
abi_element_identifier="UnauthorizedWithMessage",
|
|
3848
|
+
args=["You are not authorized"],
|
|
3831
3849
|
)
|
|
3832
3850
|
txn_params = revert_contract._prepare_transaction(
|
|
3833
|
-
|
|
3851
|
+
abi_element_identifier="customErrorWithMessage",
|
|
3834
3852
|
transaction={
|
|
3835
3853
|
"from": keyfile_account_address,
|
|
3836
3854
|
"to": revert_contract.address,
|
|
@@ -3846,9 +3864,9 @@ class EthModuleTest:
|
|
|
3846
3864
|
revert_contract: "Contract",
|
|
3847
3865
|
keyfile_account_address: ChecksumAddress,
|
|
3848
3866
|
) -> None:
|
|
3849
|
-
data = revert_contract.encode_abi(
|
|
3867
|
+
data = revert_contract.encode_abi(abi_element_identifier="Unauthorized")
|
|
3850
3868
|
txn_params = revert_contract._prepare_transaction(
|
|
3851
|
-
|
|
3869
|
+
abi_element_identifier="customErrorWithoutMessage",
|
|
3852
3870
|
transaction={
|
|
3853
3871
|
"from": keyfile_account_address,
|
|
3854
3872
|
"to": revert_contract.address,
|
|
@@ -4102,7 +4120,7 @@ class EthModuleTest:
|
|
|
4102
4120
|
ContractLogicError, match="execution reverted: Function has been reverted"
|
|
4103
4121
|
):
|
|
4104
4122
|
txn_params = revert_contract._prepare_transaction(
|
|
4105
|
-
|
|
4123
|
+
abi_element_identifier="revertWithMessage",
|
|
4106
4124
|
transaction={
|
|
4107
4125
|
"from": keyfile_account_address,
|
|
4108
4126
|
"to": revert_contract.address,
|
|
@@ -4118,7 +4136,7 @@ class EthModuleTest:
|
|
|
4118
4136
|
) -> None:
|
|
4119
4137
|
with pytest.raises(ContractLogicError, match="execution reverted"):
|
|
4120
4138
|
txn_params = revert_contract._prepare_transaction(
|
|
4121
|
-
|
|
4139
|
+
abi_element_identifier="revertWithoutMessage",
|
|
4122
4140
|
transaction={
|
|
4123
4141
|
"from": keyfile_account_address,
|
|
4124
4142
|
"to": revert_contract.address,
|
|
@@ -4133,10 +4151,11 @@ class EthModuleTest:
|
|
|
4133
4151
|
keyfile_account_address: ChecksumAddress,
|
|
4134
4152
|
) -> None:
|
|
4135
4153
|
data = revert_contract.encode_abi(
|
|
4136
|
-
|
|
4154
|
+
abi_element_identifier="UnauthorizedWithMessage",
|
|
4155
|
+
args=["You are not authorized"],
|
|
4137
4156
|
)
|
|
4138
4157
|
txn_params = revert_contract._prepare_transaction(
|
|
4139
|
-
|
|
4158
|
+
abi_element_identifier="customErrorWithMessage",
|
|
4140
4159
|
transaction={
|
|
4141
4160
|
"from": keyfile_account_address,
|
|
4142
4161
|
"to": revert_contract.address,
|
|
@@ -4152,9 +4171,9 @@ class EthModuleTest:
|
|
|
4152
4171
|
revert_contract: "Contract",
|
|
4153
4172
|
keyfile_account_address: ChecksumAddress,
|
|
4154
4173
|
) -> None:
|
|
4155
|
-
data = revert_contract.encode_abi(
|
|
4174
|
+
data = revert_contract.encode_abi(abi_element_identifier="Unauthorized")
|
|
4156
4175
|
txn_params = revert_contract._prepare_transaction(
|
|
4157
|
-
|
|
4176
|
+
abi_element_identifier="customErrorWithoutMessage",
|
|
4158
4177
|
transaction={
|
|
4159
4178
|
"from": keyfile_account_address,
|
|
4160
4179
|
"to": revert_contract.address,
|
|
@@ -4286,7 +4305,7 @@ class EthModuleTest:
|
|
|
4286
4305
|
self, w3: "Web3", block_with_txn: BlockData
|
|
4287
4306
|
) -> None:
|
|
4288
4307
|
block = w3.eth.get_block(block_with_txn["number"], True)
|
|
4289
|
-
transaction = block["transactions"][0]
|
|
4308
|
+
transaction = cast(TxData, block["transactions"][0])
|
|
4290
4309
|
assert transaction["hash"] == block_with_txn["transactions"][0]
|
|
4291
4310
|
|
|
4292
4311
|
def test_eth_getBlockReceipts_hash(
|
|
@@ -4360,6 +4379,7 @@ class EthModuleTest:
|
|
|
4360
4379
|
assert isinstance(effective_gas_price, int)
|
|
4361
4380
|
assert effective_gas_price > 0
|
|
4362
4381
|
|
|
4382
|
+
@flaky_geth_dev_mining
|
|
4363
4383
|
def test_eth_get_transaction_receipt_unmined(
|
|
4364
4384
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
4365
4385
|
) -> None:
|
|
@@ -4417,6 +4437,7 @@ class EthModuleTest:
|
|
|
4417
4437
|
assert isinstance(effective_gas_price, int)
|
|
4418
4438
|
assert effective_gas_price > 0
|
|
4419
4439
|
|
|
4440
|
+
@flaky_geth_dev_mining
|
|
4420
4441
|
def test_eth_wait_for_transaction_receipt_unmined(
|
|
4421
4442
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
4422
4443
|
) -> None:
|
|
@@ -4751,7 +4772,8 @@ class EthModuleTest:
|
|
|
4751
4772
|
f"{unknown_identifier}"
|
|
4752
4773
|
),
|
|
4753
4774
|
):
|
|
4754
|
-
|
|
4775
|
+
# type ignored because we are testing an invalid input
|
|
4776
|
+
w3.eth.get_raw_transaction_by_block(unknown_identifier, 0) # type: ignore
|
|
4755
4777
|
|
|
4756
4778
|
def test_default_account(
|
|
4757
4779
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import functools
|
|
3
|
+
import pytest
|
|
2
4
|
from typing import (
|
|
3
5
|
TYPE_CHECKING,
|
|
4
6
|
Any,
|
|
7
|
+
Callable,
|
|
5
8
|
Collection,
|
|
6
9
|
Dict,
|
|
7
10
|
Generator,
|
|
8
11
|
Literal,
|
|
9
12
|
Sequence,
|
|
13
|
+
Tuple,
|
|
14
|
+
Type,
|
|
10
15
|
Union,
|
|
11
16
|
)
|
|
12
17
|
|
|
@@ -55,7 +60,44 @@ flaky_geth_dev_mining decorator for tests requiring a pending block
|
|
|
55
60
|
for the duration of the test. This behavior can be flaky
|
|
56
61
|
due to timing of the test running as a block is mined.
|
|
57
62
|
"""
|
|
58
|
-
flaky_geth_dev_mining = flaky(max_runs=3)
|
|
63
|
+
flaky_geth_dev_mining = flaky(max_runs=3, min_passes=1)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def flaky_with_xfail_on_exception(
|
|
67
|
+
reason: str,
|
|
68
|
+
exception: Union[Type[Exception], Tuple[Type[Exception], ...]],
|
|
69
|
+
max_runs: int = 3,
|
|
70
|
+
min_passes: int = 1,
|
|
71
|
+
) -> Callable[[Any], Any]:
|
|
72
|
+
"""
|
|
73
|
+
Some tests inconsistently fail hard with a particular exception and retrying
|
|
74
|
+
these tests often times does not get them "unstuck". If we've exhausted all flaky
|
|
75
|
+
retries and this expected exception is raised, `xfail` the test with the given
|
|
76
|
+
reason.
|
|
77
|
+
"""
|
|
78
|
+
runs = max_runs
|
|
79
|
+
|
|
80
|
+
def decorator(func: Any) -> Any:
|
|
81
|
+
@flaky(max_runs=max_runs, min_passes=min_passes)
|
|
82
|
+
@functools.wraps(func)
|
|
83
|
+
async def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
84
|
+
nonlocal runs
|
|
85
|
+
try:
|
|
86
|
+
return await func(self, *args, **kwargs)
|
|
87
|
+
except exception:
|
|
88
|
+
# xfail the test only if the exception is raised and we have exhausted
|
|
89
|
+
# all flaky retries
|
|
90
|
+
if runs == 1:
|
|
91
|
+
pytest.xfail(reason)
|
|
92
|
+
runs -= 1
|
|
93
|
+
pytest.fail(f"xfailed but {runs} run(s) remaining with flaky...")
|
|
94
|
+
except Exception as e:
|
|
95
|
+
# let flaky handle it
|
|
96
|
+
raise e
|
|
97
|
+
|
|
98
|
+
return wrapper
|
|
99
|
+
|
|
100
|
+
return decorator
|
|
59
101
|
|
|
60
102
|
|
|
61
103
|
def assert_contains_log(
|
|
@@ -389,7 +389,9 @@ class PersistentConnectionProviderTest:
|
|
|
389
389
|
assert isinstance(pending, AttributeDict)
|
|
390
390
|
|
|
391
391
|
# assert block values
|
|
392
|
+
assert latest is not None
|
|
392
393
|
assert all(k in latest.keys() for k in SOME_BLOCK_KEYS)
|
|
394
|
+
assert pending is not None
|
|
393
395
|
assert all(k in pending.keys() for k in SOME_BLOCK_KEYS)
|
|
394
396
|
|
|
395
397
|
assert isinstance(block_num, int)
|
|
@@ -522,12 +522,12 @@ class AsyncWeb3ModuleTest(Web3ModuleTest):
|
|
|
522
522
|
# an asynchronous test should have the exact same name.
|
|
523
523
|
|
|
524
524
|
@pytest.mark.asyncio
|
|
525
|
-
async def test_web3_client_version(self, async_w3: AsyncWeb3) -> None:
|
|
525
|
+
async def test_web3_client_version(self, async_w3: AsyncWeb3) -> None: # type: ignore[override] # noqa: E501
|
|
526
526
|
client_version = await async_w3.client_version
|
|
527
527
|
self._check_web3_client_version(client_version)
|
|
528
528
|
|
|
529
529
|
@pytest.mark.asyncio
|
|
530
|
-
async def test_batch_requests(
|
|
530
|
+
async def test_batch_requests( # type: ignore[override]
|
|
531
531
|
self, async_w3: AsyncWeb3, async_math_contract: "AsyncContract"
|
|
532
532
|
) -> None:
|
|
533
533
|
async with async_w3.batch_requests() as batch:
|
|
@@ -595,8 +595,8 @@ class AsyncWeb3ModuleTest(Web3ModuleTest):
|
|
|
595
595
|
assert last_three_responses[2]["number"] == 5
|
|
596
596
|
|
|
597
597
|
@pytest.mark.asyncio
|
|
598
|
-
async def test_batch_requests_initialized_as_object(
|
|
599
|
-
self, async_w3: AsyncWeb3, async_math_contract: "AsyncContract"
|
|
598
|
+
async def test_batch_requests_initialized_as_object( # type: ignore[override]
|
|
599
|
+
self, async_w3: AsyncWeb3, async_math_contract: "AsyncContract" # type: ignore[override] # noqa: E501
|
|
600
600
|
) -> None:
|
|
601
601
|
batch = async_w3.batch_requests()
|
|
602
602
|
batch.add(async_w3.eth.get_block(1))
|
|
@@ -643,7 +643,7 @@ class AsyncWeb3ModuleTest(Web3ModuleTest):
|
|
|
643
643
|
assert cast(BlockData, b4)["number"] == 4
|
|
644
644
|
|
|
645
645
|
@pytest.mark.asyncio
|
|
646
|
-
async def test_batch_requests_clear(self, async_w3: AsyncWeb3) -> None:
|
|
646
|
+
async def test_batch_requests_clear(self, async_w3: AsyncWeb3) -> None: # type: ignore[override] # noqa: E501
|
|
647
647
|
async with async_w3.batch_requests() as batch:
|
|
648
648
|
batch.add(async_w3.eth.get_block(1))
|
|
649
649
|
batch.add(async_w3.eth.get_block(2))
|
|
@@ -672,7 +672,7 @@ class AsyncWeb3ModuleTest(Web3ModuleTest):
|
|
|
672
672
|
assert cast(BlockData, r3)["number"] == 6
|
|
673
673
|
|
|
674
674
|
@pytest.mark.asyncio
|
|
675
|
-
async def test_batch_requests_cancel(self, async_w3: AsyncWeb3) -> None:
|
|
675
|
+
async def test_batch_requests_cancel(self, async_w3: AsyncWeb3) -> None: # type: ignore[override] # noqa: E501
|
|
676
676
|
# as context manager
|
|
677
677
|
async with async_w3.batch_requests() as batch:
|
|
678
678
|
batch.add(async_w3.eth.get_block(1))
|
|
@@ -712,8 +712,8 @@ class AsyncWeb3ModuleTest(Web3ModuleTest):
|
|
|
712
712
|
assert isinstance(block_num, int)
|
|
713
713
|
|
|
714
714
|
@pytest.mark.asyncio
|
|
715
|
-
async def test_batch_requests_raises_for_common_unsupported_methods(
|
|
716
|
-
self, async_w3: AsyncWeb3, async_math_contract: "AsyncContract"
|
|
715
|
+
async def test_batch_requests_raises_for_common_unsupported_methods( # type: ignore[override] # noqa: E501
|
|
716
|
+
self, async_w3: AsyncWeb3, async_math_contract: "AsyncContract" # type: ignore[override] # noqa: E501
|
|
717
717
|
) -> None:
|
|
718
718
|
async with async_w3.batch_requests() as batch:
|
|
719
719
|
with pytest.raises(MethodNotSupported, match="eth_sendTransaction"):
|