web3 7.0.0b3__py3-none-any.whl → 7.0.0b5__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/_normalization.py +1 -3
- ens/async_ens.py +12 -9
- ens/contract_data.py +2 -2
- ens/ens.py +8 -5
- ens/exceptions.py +19 -27
- ens/specs/nf.json +1 -1
- ens/specs/normalization_spec.json +1 -1
- ens/utils.py +17 -10
- web3/__init__.py +2 -7
- web3/_utils/abi.py +30 -29
- web3/_utils/async_transactions.py +7 -4
- web3/_utils/blocks.py +6 -2
- web3/_utils/caching.py +7 -3
- web3/_utils/compat/__init__.py +0 -3
- web3/_utils/contract_sources/compile_contracts.py +1 -1
- web3/_utils/contracts.py +17 -17
- web3/_utils/datatypes.py +5 -1
- web3/_utils/decorators.py +6 -1
- web3/_utils/empty.py +1 -1
- web3/_utils/encoding.py +15 -10
- web3/_utils/error_formatters_utils.py +5 -3
- web3/_utils/events.py +38 -36
- web3/_utils/fee_utils.py +2 -4
- web3/_utils/filters.py +23 -18
- web3/_utils/formatters.py +2 -2
- web3/_utils/math.py +3 -2
- web3/_utils/method_formatters.py +24 -28
- web3/_utils/module.py +2 -1
- web3/_utils/module_testing/__init__.py +0 -3
- web3/_utils/module_testing/eth_module.py +494 -432
- web3/_utils/module_testing/module_testing_utils.py +1 -3
- web3/_utils/module_testing/utils.py +14 -7
- web3/_utils/normalizers.py +3 -3
- web3/_utils/request.py +4 -4
- web3/_utils/rpc_abi.py +5 -19
- web3/_utils/threads.py +8 -7
- web3/_utils/transactions.py +14 -12
- web3/_utils/type_conversion.py +5 -1
- web3/_utils/validation.py +12 -10
- web3/contract/async_contract.py +23 -18
- web3/contract/base_contract.py +69 -74
- web3/contract/contract.py +25 -19
- web3/contract/utils.py +11 -6
- web3/datastructures.py +22 -12
- web3/eth/async_eth.py +38 -32
- web3/eth/base_eth.py +7 -3
- web3/eth/eth.py +20 -15
- web3/exceptions.py +83 -78
- web3/gas_strategies/time_based.py +2 -4
- web3/geth.py +1 -191
- web3/main.py +6 -6
- web3/manager.py +128 -68
- web3/method.py +13 -5
- web3/middleware/base.py +4 -2
- web3/middleware/filter.py +45 -23
- web3/middleware/formatting.py +6 -3
- web3/middleware/names.py +4 -1
- web3/middleware/signing.py +8 -4
- web3/middleware/stalecheck.py +2 -1
- web3/providers/eth_tester/defaults.py +1 -49
- web3/providers/eth_tester/main.py +41 -15
- web3/providers/eth_tester/middleware.py +13 -9
- web3/providers/ipc.py +7 -3
- web3/providers/persistent/async_ipc.py +6 -7
- web3/providers/persistent/persistent.py +11 -1
- web3/providers/persistent/request_processor.py +7 -7
- web3/providers/persistent/websocket.py +3 -3
- web3/providers/rpc/async_rpc.py +24 -7
- web3/providers/rpc/rpc.py +30 -17
- web3/providers/rpc/utils.py +1 -10
- web3/testing.py +4 -4
- web3/tools/benchmark/main.py +13 -9
- web3/tools/benchmark/node.py +2 -8
- web3/tools/benchmark/utils.py +1 -1
- web3/tracing.py +9 -5
- web3/types.py +20 -23
- {web3-7.0.0b3.dist-info → web3-7.0.0b5.dist-info}/METADATA +13 -28
- {web3-7.0.0b3.dist-info → web3-7.0.0b5.dist-info}/RECORD +81 -82
- web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
- {web3-7.0.0b3.dist-info → web3-7.0.0b5.dist-info}/LICENSE +0 -0
- {web3-7.0.0b3.dist-info → web3-7.0.0b5.dist-info}/WHEEL +0 -0
- {web3-7.0.0b3.dist-info → web3-7.0.0b5.dist-info}/top_level.txt +0 -0
|
@@ -7,6 +7,7 @@ from typing import (
|
|
|
7
7
|
Collection,
|
|
8
8
|
Dict,
|
|
9
9
|
Generator,
|
|
10
|
+
Literal,
|
|
10
11
|
Sequence,
|
|
11
12
|
Union,
|
|
12
13
|
)
|
|
@@ -28,9 +29,6 @@ from hexbytes import (
|
|
|
28
29
|
HexBytes,
|
|
29
30
|
)
|
|
30
31
|
|
|
31
|
-
from web3._utils.compat import (
|
|
32
|
-
Literal,
|
|
33
|
-
)
|
|
34
32
|
from web3._utils.request import (
|
|
35
33
|
async_cache_and_return_session,
|
|
36
34
|
cache_and_return_session,
|
|
@@ -36,6 +36,7 @@ class RequestMocker:
|
|
|
36
36
|
via a ``request_mocker`` fixture defined within the appropriate context.
|
|
37
37
|
|
|
38
38
|
Example:
|
|
39
|
+
-------
|
|
39
40
|
|
|
40
41
|
def test_my_w3(w3, request_mocker):
|
|
41
42
|
assert w3.eth.block_number == 0
|
|
@@ -46,6 +47,7 @@ class RequestMocker:
|
|
|
46
47
|
assert w3.eth.block_number == 0
|
|
47
48
|
|
|
48
49
|
Example with async and a mocked response object:
|
|
50
|
+
-----------------------------------------------
|
|
49
51
|
|
|
50
52
|
async def test_my_w3(async_w3, request_mocker):
|
|
51
53
|
def _iter_responses():
|
|
@@ -77,6 +79,7 @@ class RequestMocker:
|
|
|
77
79
|
|
|
78
80
|
If a method name is not present in any of the dicts above, the request is made as
|
|
79
81
|
usual.
|
|
82
|
+
|
|
80
83
|
"""
|
|
81
84
|
|
|
82
85
|
def __init__(
|
|
@@ -90,12 +93,13 @@ class RequestMocker:
|
|
|
90
93
|
self.mock_results = mock_results or {}
|
|
91
94
|
self.mock_errors = mock_errors or {}
|
|
92
95
|
self.mock_responses = mock_responses or {}
|
|
93
|
-
self._make_request: Union[
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
self._make_request: Union[
|
|
97
|
+
"AsyncMakeRequestFn", "MakeRequestFn"
|
|
98
|
+
] = w3.provider.make_request
|
|
96
99
|
|
|
97
100
|
def __enter__(self) -> "Self":
|
|
98
|
-
|
|
101
|
+
# mypy error: Cannot assign to a method
|
|
102
|
+
self.w3.provider.make_request = self._mock_request_handler # type: ignore[method-assign] # noqa: E501
|
|
99
103
|
# reset request func cache to re-build request_func with mocked make_request
|
|
100
104
|
self.w3.provider._request_func_cache = (None, None)
|
|
101
105
|
|
|
@@ -103,7 +107,8 @@ class RequestMocker:
|
|
|
103
107
|
|
|
104
108
|
# define __exit__ with typing information
|
|
105
109
|
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
|
106
|
-
|
|
110
|
+
# mypy error: Cannot assign to a method
|
|
111
|
+
self.w3.provider.make_request = self._make_request # type: ignore[method-assign] # noqa: E501
|
|
107
112
|
# reset request func cache to re-build request_func with original make_request
|
|
108
113
|
self.w3.provider._request_func_cache = (None, None)
|
|
109
114
|
|
|
@@ -163,13 +168,15 @@ class RequestMocker:
|
|
|
163
168
|
|
|
164
169
|
# -- async -- #
|
|
165
170
|
async def __aenter__(self) -> "Self":
|
|
166
|
-
|
|
171
|
+
# mypy error: Cannot assign to a method
|
|
172
|
+
self.w3.provider.make_request = self._async_mock_request_handler # type: ignore[method-assign] # noqa: E501
|
|
167
173
|
# reset request func cache to re-build request_func with mocked make_request
|
|
168
174
|
self.w3.provider._request_func_cache = (None, None)
|
|
169
175
|
return self
|
|
170
176
|
|
|
171
177
|
async def __aexit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
|
172
|
-
|
|
178
|
+
# mypy error: Cannot assign to a method
|
|
179
|
+
self.w3.provider.make_request = self._make_request # type: ignore[method-assign] # noqa: E501
|
|
173
180
|
# reset request func cache to re-build request_func with original make_request
|
|
174
181
|
self.w3.provider._request_func_cache = (None, None)
|
|
175
182
|
|
web3/_utils/normalizers.py
CHANGED
|
@@ -60,6 +60,7 @@ from web3._utils.validation import (
|
|
|
60
60
|
from web3.exceptions import (
|
|
61
61
|
InvalidAddress,
|
|
62
62
|
NameNotFound,
|
|
63
|
+
Web3ValueError,
|
|
63
64
|
)
|
|
64
65
|
from web3.types import (
|
|
65
66
|
ABI,
|
|
@@ -151,7 +152,7 @@ def abi_bytes_to_hex(
|
|
|
151
152
|
|
|
152
153
|
num_bytes = abi_type.sub
|
|
153
154
|
if len(bytes_data) > num_bytes:
|
|
154
|
-
raise
|
|
155
|
+
raise Web3ValueError(
|
|
155
156
|
f"This value was expected to be at most {num_bytes} bytes, "
|
|
156
157
|
f"but instead was {len(bytes_data)}: {data!r}"
|
|
157
158
|
)
|
|
@@ -273,8 +274,7 @@ def normalize_address_no_ens(address: ChecksumAddress) -> ChecksumAddress:
|
|
|
273
274
|
def normalize_bytecode(bytecode: bytes) -> HexBytes:
|
|
274
275
|
if bytecode:
|
|
275
276
|
bytecode = HexBytes(bytecode)
|
|
276
|
-
|
|
277
|
-
return bytecode # type: ignore
|
|
277
|
+
return bytecode
|
|
278
278
|
|
|
279
279
|
|
|
280
280
|
# --- async -- #
|
web3/_utils/request.py
CHANGED
|
@@ -109,9 +109,9 @@ def get_response_from_post_request(
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
def make_post_request(
|
|
112
|
-
endpoint_uri: URI, data: Union[bytes, Dict[str, Any]],
|
|
112
|
+
endpoint_uri: URI, data: Union[bytes, Dict[str, Any]], **kwargs: Any
|
|
113
113
|
) -> bytes:
|
|
114
|
-
response = get_response_from_post_request(endpoint_uri, data=data,
|
|
114
|
+
response = get_response_from_post_request(endpoint_uri, data=data, **kwargs)
|
|
115
115
|
response.raise_for_status()
|
|
116
116
|
return response.content
|
|
117
117
|
|
|
@@ -236,10 +236,10 @@ async def async_get_response_from_post_request(
|
|
|
236
236
|
|
|
237
237
|
|
|
238
238
|
async def async_make_post_request(
|
|
239
|
-
endpoint_uri: URI, data: Union[bytes, Dict[str, Any]],
|
|
239
|
+
endpoint_uri: URI, data: Union[bytes, Dict[str, Any]], **kwargs: Any
|
|
240
240
|
) -> bytes:
|
|
241
241
|
response = await async_get_response_from_post_request(
|
|
242
|
-
endpoint_uri, data=data,
|
|
242
|
+
endpoint_uri, data=data, **kwargs
|
|
243
243
|
)
|
|
244
244
|
response.raise_for_status()
|
|
245
245
|
return await response.read()
|
web3/_utils/rpc_abi.py
CHANGED
|
@@ -24,6 +24,9 @@ from eth_utils.toolz import (
|
|
|
24
24
|
from web3._utils.abi import (
|
|
25
25
|
map_abi_data,
|
|
26
26
|
)
|
|
27
|
+
from web3.exceptions import (
|
|
28
|
+
Web3TypeError,
|
|
29
|
+
)
|
|
27
30
|
from web3.types import (
|
|
28
31
|
RPCEndpoint,
|
|
29
32
|
)
|
|
@@ -120,18 +123,6 @@ class RPC:
|
|
|
120
123
|
net_peerCount = RPCEndpoint("net_peerCount")
|
|
121
124
|
net_version = RPCEndpoint("net_version")
|
|
122
125
|
|
|
123
|
-
# personal
|
|
124
|
-
personal_ecRecover = RPCEndpoint("personal_ecRecover")
|
|
125
|
-
personal_importRawKey = RPCEndpoint("personal_importRawKey")
|
|
126
|
-
personal_listAccounts = RPCEndpoint("personal_listAccounts")
|
|
127
|
-
personal_listWallets = RPCEndpoint("personal_listWallets")
|
|
128
|
-
personal_lockAccount = RPCEndpoint("personal_lockAccount")
|
|
129
|
-
personal_newAccount = RPCEndpoint("personal_newAccount")
|
|
130
|
-
personal_sendTransaction = RPCEndpoint("personal_sendTransaction")
|
|
131
|
-
personal_sign = RPCEndpoint("personal_sign")
|
|
132
|
-
personal_signTypedData = RPCEndpoint("personal_signTypedData")
|
|
133
|
-
personal_unlockAccount = RPCEndpoint("personal_unlockAccount")
|
|
134
|
-
|
|
135
126
|
# testing
|
|
136
127
|
testing_timeTravel = RPCEndpoint("testing_timeTravel")
|
|
137
128
|
|
|
@@ -158,6 +149,7 @@ TRANSACTION_PARAMS_ABIS = {
|
|
|
158
149
|
"from": "address",
|
|
159
150
|
"gas": "uint",
|
|
160
151
|
"gasPrice": "uint",
|
|
152
|
+
"maxFeePerBlobGas": "uint",
|
|
161
153
|
"maxFeePerGas": "uint",
|
|
162
154
|
"maxPriorityFeePerGas": "uint",
|
|
163
155
|
"nonce": "uint",
|
|
@@ -207,12 +199,6 @@ RPC_ABIS: Dict[str, Union[Sequence[Any], Dict[str, str]]] = {
|
|
|
207
199
|
"eth_signTypedData": ["address", None],
|
|
208
200
|
"eth_submitHashrate": ["uint", "bytes32"],
|
|
209
201
|
"eth_submitWork": ["bytes8", "bytes32", "bytes32"],
|
|
210
|
-
# personal
|
|
211
|
-
"personal_sendTransaction": TRANSACTION_PARAMS_ABIS,
|
|
212
|
-
"personal_lockAccount": ["address"],
|
|
213
|
-
"personal_unlockAccount": ["address", None, None],
|
|
214
|
-
"personal_sign": [None, "address", None],
|
|
215
|
-
"personal_signTypedData": [None, "address", None],
|
|
216
202
|
"trace_call": TRANSACTION_PARAMS_ABIS,
|
|
217
203
|
"trace_filter": TRACE_FILTER_PARAM_ABIS,
|
|
218
204
|
}
|
|
@@ -246,6 +232,6 @@ def abi_request_formatters(
|
|
|
246
232
|
single_dict_formatter = apply_abi_formatters_to_dict(normalizers, abi_types)
|
|
247
233
|
yield method, apply_formatter_at_index(single_dict_formatter, 0)
|
|
248
234
|
else:
|
|
249
|
-
raise
|
|
235
|
+
raise Web3TypeError(
|
|
250
236
|
f"ABI definitions must be a list or dictionary, got {abi_types!r}"
|
|
251
237
|
)
|
web3/_utils/threads.py
CHANGED
|
@@ -12,11 +12,12 @@ from typing import (
|
|
|
12
12
|
Any,
|
|
13
13
|
Callable,
|
|
14
14
|
Generic,
|
|
15
|
+
Literal,
|
|
15
16
|
Type,
|
|
16
17
|
)
|
|
17
18
|
|
|
18
|
-
from web3.
|
|
19
|
-
|
|
19
|
+
from web3.exceptions import (
|
|
20
|
+
Web3ValueError,
|
|
20
21
|
)
|
|
21
22
|
from web3.types import (
|
|
22
23
|
TReturn,
|
|
@@ -63,24 +64,24 @@ class Timeout(Exception):
|
|
|
63
64
|
@property
|
|
64
65
|
def expire_at(self) -> int:
|
|
65
66
|
if self.seconds is None:
|
|
66
|
-
raise
|
|
67
|
+
raise Web3ValueError(
|
|
67
68
|
"Timeouts with `seconds == None` do not have an expiration time"
|
|
68
69
|
)
|
|
69
70
|
elif self.begun_at is None:
|
|
70
|
-
raise
|
|
71
|
+
raise Web3ValueError("Timeout has not been started")
|
|
71
72
|
return self.begun_at + self.seconds
|
|
72
73
|
|
|
73
74
|
def start(self) -> None:
|
|
74
75
|
if self.is_running is not None:
|
|
75
|
-
raise
|
|
76
|
+
raise Web3ValueError("Timeout has already been started")
|
|
76
77
|
self.begun_at = time.time()
|
|
77
78
|
self.is_running = True
|
|
78
79
|
|
|
79
80
|
def check(self) -> None:
|
|
80
81
|
if self.is_running is None:
|
|
81
|
-
raise
|
|
82
|
+
raise Web3ValueError("Timeout has not been started")
|
|
82
83
|
elif self.is_running is False:
|
|
83
|
-
raise
|
|
84
|
+
raise Web3ValueError("Timeout has already been cancelled")
|
|
84
85
|
elif self.seconds is None:
|
|
85
86
|
return
|
|
86
87
|
elif time.time() > self.expire_at:
|
web3/_utils/transactions.py
CHANGED
|
@@ -2,6 +2,7 @@ import math
|
|
|
2
2
|
from typing import (
|
|
3
3
|
TYPE_CHECKING,
|
|
4
4
|
List,
|
|
5
|
+
Literal,
|
|
5
6
|
Optional,
|
|
6
7
|
Union,
|
|
7
8
|
cast,
|
|
@@ -19,9 +20,6 @@ from hexbytes import (
|
|
|
19
20
|
HexBytes,
|
|
20
21
|
)
|
|
21
22
|
|
|
22
|
-
from web3._utils.compat import (
|
|
23
|
-
Literal,
|
|
24
|
-
)
|
|
25
23
|
from web3._utils.utility_methods import (
|
|
26
24
|
all_in_dict,
|
|
27
25
|
any_in_dict,
|
|
@@ -29,6 +27,10 @@ from web3._utils.utility_methods import (
|
|
|
29
27
|
from web3.constants import (
|
|
30
28
|
DYNAMIC_FEE_TXN_PARAMS,
|
|
31
29
|
)
|
|
30
|
+
from web3.exceptions import (
|
|
31
|
+
Web3AttributeError,
|
|
32
|
+
Web3ValueError,
|
|
33
|
+
)
|
|
32
34
|
from web3.types import (
|
|
33
35
|
BlockIdentifier,
|
|
34
36
|
TxData,
|
|
@@ -107,7 +109,7 @@ def fill_nonce(w3: "Web3", transaction: TxParams) -> TxParams:
|
|
|
107
109
|
@curry
|
|
108
110
|
def fill_transaction_defaults(w3: "Web3", transaction: TxParams) -> TxParams:
|
|
109
111
|
"""
|
|
110
|
-
|
|
112
|
+
If w3 is None, fill as much as possible while offline
|
|
111
113
|
"""
|
|
112
114
|
strategy_based_gas_price = w3.eth.generate_gas_price(transaction)
|
|
113
115
|
is_dynamic_fee_transaction = strategy_based_gas_price is None and (
|
|
@@ -130,7 +132,7 @@ def fill_transaction_defaults(w3: "Web3", transaction: TxParams) -> TxParams:
|
|
|
130
132
|
|
|
131
133
|
if callable(default_getter):
|
|
132
134
|
if w3 is None:
|
|
133
|
-
raise
|
|
135
|
+
raise Web3ValueError(
|
|
134
136
|
f"You must specify a '{key}' value in the transaction"
|
|
135
137
|
)
|
|
136
138
|
default_val = default_getter(w3, transaction)
|
|
@@ -160,7 +162,7 @@ def get_buffered_gas_estimate(
|
|
|
160
162
|
gas_limit = get_block_gas_limit(w3)
|
|
161
163
|
|
|
162
164
|
if gas_estimate > gas_limit:
|
|
163
|
-
raise
|
|
165
|
+
raise Web3ValueError(
|
|
164
166
|
"Contract does not appear to be deployable within the "
|
|
165
167
|
f"current network gas limits. Estimated: {gas_estimate}. "
|
|
166
168
|
f"Current gas limit: {gas_limit}"
|
|
@@ -172,7 +174,7 @@ def get_buffered_gas_estimate(
|
|
|
172
174
|
def get_required_transaction(w3: "Web3", transaction_hash: _Hash32) -> TxData:
|
|
173
175
|
current_transaction = w3.eth.get_transaction(transaction_hash)
|
|
174
176
|
if not current_transaction:
|
|
175
|
-
raise
|
|
177
|
+
raise Web3ValueError(
|
|
176
178
|
f"Supplied transaction with hash {transaction_hash!r} does not exist"
|
|
177
179
|
)
|
|
178
180
|
return current_transaction
|
|
@@ -204,7 +206,7 @@ def extract_valid_transaction_params(transaction_params: TxData) -> TxParams:
|
|
|
204
206
|
msg = 'failure to handle this transaction due to both "input: {}" and'
|
|
205
207
|
msg += ' "data: {}" are populated. You need to resolve this conflict.'
|
|
206
208
|
err_vals = (transaction_params["input"], extracted_params["data"])
|
|
207
|
-
raise
|
|
209
|
+
raise Web3AttributeError(msg.format(*err_vals))
|
|
208
210
|
else:
|
|
209
211
|
return extracted_params
|
|
210
212
|
else:
|
|
@@ -223,7 +225,7 @@ def extract_valid_transaction_params(transaction_params: TxData) -> TxParams:
|
|
|
223
225
|
def assert_valid_transaction_params(transaction_params: TxParams) -> None:
|
|
224
226
|
for param in transaction_params:
|
|
225
227
|
if param not in VALID_TRANSACTION_PARAMS:
|
|
226
|
-
raise
|
|
228
|
+
raise Web3ValueError(f"{param} is not a valid transaction parameter")
|
|
227
229
|
|
|
228
230
|
|
|
229
231
|
def prepare_replacement_transaction(
|
|
@@ -233,14 +235,14 @@ def prepare_replacement_transaction(
|
|
|
233
235
|
gas_multiplier: float = 1.125,
|
|
234
236
|
) -> TxParams:
|
|
235
237
|
if original_transaction["blockHash"] is not None:
|
|
236
|
-
raise
|
|
238
|
+
raise Web3ValueError(
|
|
237
239
|
f'Supplied transaction with hash {original_transaction["hash"]!r} '
|
|
238
240
|
"has already been mined"
|
|
239
241
|
)
|
|
240
242
|
if "nonce" in replacement_transaction and (
|
|
241
243
|
replacement_transaction["nonce"] != original_transaction["nonce"]
|
|
242
244
|
):
|
|
243
|
-
raise
|
|
245
|
+
raise Web3ValueError(
|
|
244
246
|
"Supplied nonce in new_transaction must match the pending transaction"
|
|
245
247
|
)
|
|
246
248
|
|
|
@@ -259,7 +261,7 @@ def prepare_replacement_transaction(
|
|
|
259
261
|
and original_transaction["gasPrice"] is not None
|
|
260
262
|
):
|
|
261
263
|
if replacement_transaction["gasPrice"] <= original_transaction["gasPrice"]:
|
|
262
|
-
raise
|
|
264
|
+
raise Web3ValueError(
|
|
263
265
|
"Supplied gas price must exceed existing transaction gas price"
|
|
264
266
|
)
|
|
265
267
|
|
web3/_utils/type_conversion.py
CHANGED
|
@@ -10,6 +10,10 @@ from eth_utils import (
|
|
|
10
10
|
to_hex,
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
+
from web3.exceptions import (
|
|
14
|
+
Web3ValueError,
|
|
15
|
+
)
|
|
16
|
+
|
|
13
17
|
|
|
14
18
|
def to_hex_if_bytes(val: Union[HexStr, str, bytes, bytearray]) -> HexStr:
|
|
15
19
|
"""
|
|
@@ -17,7 +21,7 @@ def to_hex_if_bytes(val: Union[HexStr, str, bytes, bytearray]) -> HexStr:
|
|
|
17
21
|
meant to work with bytes and hex strings.
|
|
18
22
|
"""
|
|
19
23
|
if isinstance(val, str) and not val.startswith("0x"):
|
|
20
|
-
raise
|
|
24
|
+
raise Web3ValueError(f"Expected a hex string. Got: {val!r}")
|
|
21
25
|
|
|
22
26
|
return to_hex(val) if isinstance(val, (bytes, bytearray)) else to_hex(hexstr=val)
|
|
23
27
|
|
web3/_utils/validation.py
CHANGED
|
@@ -53,6 +53,8 @@ from web3._utils.abi import (
|
|
|
53
53
|
)
|
|
54
54
|
from web3.exceptions import (
|
|
55
55
|
InvalidAddress,
|
|
56
|
+
Web3TypeError,
|
|
57
|
+
Web3ValueError,
|
|
56
58
|
)
|
|
57
59
|
from web3.types import (
|
|
58
60
|
ABI,
|
|
@@ -74,16 +76,16 @@ def validate_abi(abi: ABI) -> None:
|
|
|
74
76
|
Helper function for validating an ABI
|
|
75
77
|
"""
|
|
76
78
|
if not is_list_like(abi):
|
|
77
|
-
raise
|
|
79
|
+
raise Web3ValueError("'abi' is not a list")
|
|
78
80
|
|
|
79
81
|
if not all(is_dict(e) for e in abi):
|
|
80
|
-
raise
|
|
82
|
+
raise Web3ValueError("'abi' is not a list of dictionaries")
|
|
81
83
|
|
|
82
84
|
functions = filter_by_type("function", abi)
|
|
83
85
|
selectors = groupby(compose(encode_hex, function_abi_to_4byte_selector), functions)
|
|
84
86
|
duplicates = valfilter(lambda funcs: len(funcs) > 1, selectors)
|
|
85
87
|
if duplicates:
|
|
86
|
-
raise
|
|
88
|
+
raise Web3ValueError(
|
|
87
89
|
"Abi contains functions with colliding selectors. "
|
|
88
90
|
f"Functions {_prepare_selector_collision_msg(duplicates)}"
|
|
89
91
|
)
|
|
@@ -94,7 +96,7 @@ def validate_abi_type(abi_type: TypeStr) -> None:
|
|
|
94
96
|
Helper function for validating an abi_type
|
|
95
97
|
"""
|
|
96
98
|
if not is_recognized_type(abi_type):
|
|
97
|
-
raise
|
|
99
|
+
raise Web3ValueError(f"Unrecognized abi_type: {abi_type}")
|
|
98
100
|
|
|
99
101
|
|
|
100
102
|
def validate_abi_value(abi_type: TypeStr, value: Any) -> None:
|
|
@@ -107,12 +109,12 @@ def validate_abi_value(abi_type: TypeStr, value: Any) -> None:
|
|
|
107
109
|
specified_length = length_of_array_type(abi_type)
|
|
108
110
|
if specified_length is not None:
|
|
109
111
|
if specified_length < 1:
|
|
110
|
-
raise
|
|
112
|
+
raise Web3TypeError(
|
|
111
113
|
f"Invalid abi-type: {abi_type}. Length of fixed sized "
|
|
112
114
|
"arrays must be greater than 0."
|
|
113
115
|
)
|
|
114
116
|
if specified_length != len(value):
|
|
115
|
-
raise
|
|
117
|
+
raise Web3TypeError(
|
|
116
118
|
"The following array length does not the length specified"
|
|
117
119
|
f"by the abi-type, {abi_type}: {value}"
|
|
118
120
|
)
|
|
@@ -138,14 +140,14 @@ def validate_abi_value(abi_type: TypeStr, value: Any) -> None:
|
|
|
138
140
|
if is_0x_prefixed(value):
|
|
139
141
|
return
|
|
140
142
|
else:
|
|
141
|
-
raise
|
|
143
|
+
raise Web3TypeError(
|
|
142
144
|
"ABI values of abi-type 'bytes' must be either"
|
|
143
145
|
"a python3 'bytes' object or an '0x' prefixed string."
|
|
144
146
|
)
|
|
145
147
|
elif is_string_type(abi_type) and is_string(value):
|
|
146
148
|
return
|
|
147
149
|
|
|
148
|
-
raise
|
|
150
|
+
raise Web3TypeError(f"The following abi value is not a '{abi_type}': {value}")
|
|
149
151
|
|
|
150
152
|
|
|
151
153
|
def is_not_address_string(value: Any) -> bool:
|
|
@@ -173,7 +175,7 @@ def validate_address(value: Any) -> None:
|
|
|
173
175
|
return
|
|
174
176
|
|
|
175
177
|
if not isinstance(value, str):
|
|
176
|
-
raise
|
|
178
|
+
raise Web3TypeError(f"Address {value} must be provided as a string")
|
|
177
179
|
if not is_hex_address(value):
|
|
178
180
|
raise InvalidAddress(
|
|
179
181
|
"Address must be 20 bytes, as a hex string with a 0x prefix", value
|
|
@@ -204,7 +206,7 @@ def has_one_val(*args: Any, **kwargs: Any) -> bool:
|
|
|
204
206
|
|
|
205
207
|
def assert_one_val(*args: Any, **kwargs: Any) -> None:
|
|
206
208
|
if not has_one_val(*args, **kwargs):
|
|
207
|
-
raise
|
|
209
|
+
raise Web3TypeError(
|
|
208
210
|
"Exactly one of the passed values can be specified. "
|
|
209
211
|
f"Instead, values were: {args!r}, {kwargs!r}"
|
|
210
212
|
)
|
web3/contract/async_contract.py
CHANGED
|
@@ -82,7 +82,10 @@ from web3.exceptions import (
|
|
|
82
82
|
ABIFunctionNotFound,
|
|
83
83
|
NoABIFound,
|
|
84
84
|
NoABIFunctionsFound,
|
|
85
|
+
Web3AttributeError,
|
|
86
|
+
Web3TypeError,
|
|
85
87
|
Web3ValidationError,
|
|
88
|
+
Web3ValueError,
|
|
86
89
|
)
|
|
87
90
|
from web3.types import (
|
|
88
91
|
ABI,
|
|
@@ -108,11 +111,12 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
108
111
|
async def get_logs(
|
|
109
112
|
self,
|
|
110
113
|
argument_filters: Optional[Dict[str, Any]] = None,
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
from_block: Optional[BlockIdentifier] = None,
|
|
115
|
+
to_block: Optional[BlockIdentifier] = None,
|
|
113
116
|
block_hash: Optional[HexBytes] = None,
|
|
114
117
|
) -> Awaitable[Iterable[EventData]]:
|
|
115
|
-
"""
|
|
118
|
+
"""
|
|
119
|
+
Get events for this contract instance using eth_getLogs API.
|
|
116
120
|
|
|
117
121
|
This is a stateless method, as opposed to createFilter.
|
|
118
122
|
It can be safely called against nodes which do not provide
|
|
@@ -131,7 +135,7 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
131
135
|
from = max(mycontract.web3.eth.block_number - 10, 1)
|
|
132
136
|
to = mycontract.web3.eth.block_number
|
|
133
137
|
|
|
134
|
-
events = mycontract.events.Transfer.getLogs(
|
|
138
|
+
events = mycontract.events.Transfer.getLogs(from_block=from, to_block=to)
|
|
135
139
|
|
|
136
140
|
for e in events:
|
|
137
141
|
print(e["args"]["from"],
|
|
@@ -161,10 +165,10 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
161
165
|
|
|
162
166
|
:param argument_filters: Filter by argument values. Indexed arguments are
|
|
163
167
|
filtered by the node while non-indexed arguments are filtered by the library.
|
|
164
|
-
:param
|
|
165
|
-
:param
|
|
168
|
+
:param from_block: block number or "latest", defaults to "latest"
|
|
169
|
+
:param to_block: block number or "latest". Defaults to "latest"
|
|
166
170
|
:param block_hash: block hash. Cannot be set at the
|
|
167
|
-
same time as
|
|
171
|
+
same time as ``from_block`` or ``to_block``
|
|
168
172
|
:yield: Tuple of :class:`AttributeDict` instances
|
|
169
173
|
"""
|
|
170
174
|
event_abi = self._get_event_abi()
|
|
@@ -179,7 +183,7 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
179
183
|
)
|
|
180
184
|
|
|
181
185
|
_filter_params = self._get_event_filter_params(
|
|
182
|
-
event_abi, argument_filters,
|
|
186
|
+
event_abi, argument_filters, from_block, to_block, block_hash
|
|
183
187
|
)
|
|
184
188
|
# call JSON-RPC API
|
|
185
189
|
logs = await self.w3.eth.get_logs(_filter_params)
|
|
@@ -200,8 +204,8 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
200
204
|
self,
|
|
201
205
|
*, # PEP 3102
|
|
202
206
|
argument_filters: Optional[Dict[str, Any]] = None,
|
|
203
|
-
|
|
204
|
-
|
|
207
|
+
from_block: Optional[BlockIdentifier] = None,
|
|
208
|
+
to_block: BlockIdentifier = "latest",
|
|
205
209
|
address: Optional[ChecksumAddress] = None,
|
|
206
210
|
topics: Optional[Sequence[Any]] = None,
|
|
207
211
|
) -> AsyncLogFilter:
|
|
@@ -211,8 +215,8 @@ class AsyncContractEvent(BaseContractEvent):
|
|
|
211
215
|
filter_builder = AsyncEventFilterBuilder(self._get_event_abi(), self.w3.codec)
|
|
212
216
|
self._set_up_filter_builder(
|
|
213
217
|
argument_filters,
|
|
214
|
-
|
|
215
|
-
|
|
218
|
+
from_block,
|
|
219
|
+
to_block,
|
|
216
220
|
address,
|
|
217
221
|
topics,
|
|
218
222
|
filter_builder,
|
|
@@ -440,12 +444,13 @@ class AsyncContract(BaseContract):
|
|
|
440
444
|
events: AsyncContractEvents = None
|
|
441
445
|
|
|
442
446
|
def __init__(self, address: Optional[ChecksumAddress] = None) -> None:
|
|
443
|
-
"""
|
|
444
|
-
|
|
445
|
-
:param address: Contract address as 0x hex string"""
|
|
447
|
+
"""
|
|
448
|
+
Create a new smart contract proxy object.
|
|
446
449
|
|
|
450
|
+
:param address: Contract address as 0x hex string
|
|
451
|
+
"""
|
|
447
452
|
if self.w3 is None:
|
|
448
|
-
raise
|
|
453
|
+
raise Web3AttributeError(
|
|
449
454
|
"The `Contract` class has not been initialized. Please use the "
|
|
450
455
|
"`web3.contract` interface to create your contract class."
|
|
451
456
|
)
|
|
@@ -454,7 +459,7 @@ class AsyncContract(BaseContract):
|
|
|
454
459
|
self.address = normalize_address_no_ens(address)
|
|
455
460
|
|
|
456
461
|
if not self.address:
|
|
457
|
-
raise
|
|
462
|
+
raise Web3TypeError(
|
|
458
463
|
"The address argument is required to instantiate a contract."
|
|
459
464
|
)
|
|
460
465
|
self.functions = AsyncContractFunctions(
|
|
@@ -523,7 +528,7 @@ class AsyncContract(BaseContract):
|
|
|
523
528
|
:return: a contract constructor object
|
|
524
529
|
"""
|
|
525
530
|
if cls.bytecode is None:
|
|
526
|
-
raise
|
|
531
|
+
raise Web3ValueError(
|
|
527
532
|
"Cannot call constructor on a contract that does not have "
|
|
528
533
|
"'bytecode' associated with it"
|
|
529
534
|
)
|