web3 7.0.0b8__py3-none-any.whl → 7.1.0__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/beacon/api_endpoints.py +3 -0
- web3/beacon/async_beacon.py +18 -2
- web3/beacon/beacon.py +18 -2
- web3/contract/async_contract.py +26 -25
- web3/contract/base_contract.py +116 -80
- web3/contract/contract.py +26 -25
- web3/contract/utils.py +86 -55
- web3/datastructures.py +21 -11
- 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/base.py +8 -0
- web3/middleware/filter.py +3 -3
- web3/middleware/signing.py +6 -1
- web3/scripts/install_pre_releases.py +33 -0
- web3/scripts/parse_pygeth_version.py +16 -0
- 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.1.0.dist-info}/METADATA +10 -10
- {web3-7.0.0b8.dist-info → web3-7.1.0.dist-info}/RECORD +46 -44
- {web3-7.0.0b8.dist-info → web3-7.1.0.dist-info}/WHEEL +1 -1
- /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
- {web3-7.0.0b8.dist-info → web3-7.1.0.dist-info}/LICENSE +0 -0
- {web3-7.0.0b8.dist-info → web3-7.1.0.dist-info}/top_level.txt +0 -0
web3/contract/utils.py
CHANGED
|
@@ -16,9 +16,16 @@ from eth_abi.exceptions import (
|
|
|
16
16
|
DecodingError,
|
|
17
17
|
)
|
|
18
18
|
from eth_typing import (
|
|
19
|
+
ABI,
|
|
20
|
+
ABICallable,
|
|
21
|
+
ABIFunction,
|
|
19
22
|
ChecksumAddress,
|
|
20
23
|
TypeStr,
|
|
21
24
|
)
|
|
25
|
+
from eth_utils.abi import (
|
|
26
|
+
filter_abi_by_type,
|
|
27
|
+
get_abi_output_types,
|
|
28
|
+
)
|
|
22
29
|
from eth_utils.toolz import (
|
|
23
30
|
compose,
|
|
24
31
|
curry,
|
|
@@ -28,8 +35,6 @@ from hexbytes import (
|
|
|
28
35
|
)
|
|
29
36
|
|
|
30
37
|
from web3._utils.abi import (
|
|
31
|
-
filter_by_type,
|
|
32
|
-
get_abi_output_types,
|
|
33
38
|
map_abi_data,
|
|
34
39
|
named_tree,
|
|
35
40
|
recursive_dict_to_namedtuple,
|
|
@@ -37,8 +42,10 @@ from web3._utils.abi import (
|
|
|
37
42
|
from web3._utils.async_transactions import (
|
|
38
43
|
async_fill_transaction_defaults,
|
|
39
44
|
)
|
|
45
|
+
from web3._utils.compat import (
|
|
46
|
+
TypeAlias,
|
|
47
|
+
)
|
|
40
48
|
from web3._utils.contracts import (
|
|
41
|
-
find_matching_fn_abi,
|
|
42
49
|
prepare_transaction,
|
|
43
50
|
)
|
|
44
51
|
from web3._utils.normalizers import (
|
|
@@ -52,14 +59,16 @@ from web3.exceptions import (
|
|
|
52
59
|
Web3ValueError,
|
|
53
60
|
)
|
|
54
61
|
from web3.types import (
|
|
55
|
-
|
|
56
|
-
ABIFunction,
|
|
62
|
+
ABIElementIdentifier,
|
|
57
63
|
BlockIdentifier,
|
|
58
|
-
|
|
64
|
+
RPCEndpoint,
|
|
59
65
|
StateOverride,
|
|
60
66
|
TContractFn,
|
|
61
67
|
TxParams,
|
|
62
68
|
)
|
|
69
|
+
from web3.utils.abi import (
|
|
70
|
+
get_abi_element,
|
|
71
|
+
)
|
|
63
72
|
|
|
64
73
|
if TYPE_CHECKING:
|
|
65
74
|
from web3 import ( # noqa: F401
|
|
@@ -77,8 +86,8 @@ ACCEPTABLE_EMPTY_STRINGS = ["0x", b"0x", "", b""]
|
|
|
77
86
|
def format_contract_call_return_data_curried(
|
|
78
87
|
async_w3: Union["AsyncWeb3", "Web3"],
|
|
79
88
|
decode_tuples: bool,
|
|
80
|
-
fn_abi:
|
|
81
|
-
|
|
89
|
+
fn_abi: ABICallable,
|
|
90
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
82
91
|
normalizers: Tuple[Callable[..., Any], ...],
|
|
83
92
|
output_types: Sequence[TypeStr],
|
|
84
93
|
return_data: Any,
|
|
@@ -92,7 +101,7 @@ def format_contract_call_return_data_curried(
|
|
|
92
101
|
output_data = async_w3.codec.decode(output_types, return_data)
|
|
93
102
|
except DecodingError as e:
|
|
94
103
|
msg = (
|
|
95
|
-
f"Could not decode contract function call to {
|
|
104
|
+
f"Could not decode contract function call to {abi_element_identifier} "
|
|
96
105
|
f"with return data: {str(return_data)}, output_types: {output_types}"
|
|
97
106
|
)
|
|
98
107
|
raise BadFunctionCallOutput(msg) from e
|
|
@@ -103,7 +112,7 @@ def format_contract_call_return_data_curried(
|
|
|
103
112
|
)
|
|
104
113
|
normalized_data = map_abi_data(_normalizers, output_types, output_data)
|
|
105
114
|
|
|
106
|
-
if decode_tuples:
|
|
115
|
+
if decode_tuples and fn_abi["type"] == "function":
|
|
107
116
|
decoded = named_tree(fn_abi["outputs"], normalized_data)
|
|
108
117
|
normalized_data = recursive_dict_to_namedtuple(decoded)
|
|
109
118
|
|
|
@@ -114,11 +123,11 @@ def call_contract_function(
|
|
|
114
123
|
w3: "Web3",
|
|
115
124
|
address: ChecksumAddress,
|
|
116
125
|
normalizers: Tuple[Callable[..., Any], ...],
|
|
117
|
-
|
|
126
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
118
127
|
transaction: TxParams,
|
|
119
128
|
block_id: Optional[BlockIdentifier] = None,
|
|
120
129
|
contract_abi: Optional[ABI] = None,
|
|
121
|
-
|
|
130
|
+
abi_callable: Optional[ABICallable] = None,
|
|
122
131
|
state_override: Optional[StateOverride] = None,
|
|
123
132
|
ccip_read_enabled: Optional[bool] = None,
|
|
124
133
|
decode_tuples: Optional[bool] = False,
|
|
@@ -132,9 +141,9 @@ def call_contract_function(
|
|
|
132
141
|
call_transaction = prepare_transaction(
|
|
133
142
|
address,
|
|
134
143
|
w3,
|
|
135
|
-
|
|
144
|
+
abi_element_identifier=abi_element_identifier,
|
|
136
145
|
contract_abi=contract_abi,
|
|
137
|
-
|
|
146
|
+
abi_callable=abi_callable,
|
|
138
147
|
transaction=transaction,
|
|
139
148
|
fn_args=args,
|
|
140
149
|
fn_kwargs=kwargs,
|
|
@@ -147,17 +156,27 @@ def call_contract_function(
|
|
|
147
156
|
ccip_read_enabled=ccip_read_enabled,
|
|
148
157
|
)
|
|
149
158
|
|
|
150
|
-
if
|
|
151
|
-
|
|
152
|
-
|
|
159
|
+
if abi_callable is None:
|
|
160
|
+
abi_callable = cast(
|
|
161
|
+
ABIFunction,
|
|
162
|
+
get_abi_element(
|
|
163
|
+
contract_abi,
|
|
164
|
+
abi_element_identifier,
|
|
165
|
+
*args,
|
|
166
|
+
abi_codec=w3.codec,
|
|
167
|
+
**kwargs,
|
|
168
|
+
),
|
|
153
169
|
)
|
|
154
170
|
|
|
155
|
-
|
|
171
|
+
# get the output types, which only exist for function types
|
|
172
|
+
output_types = []
|
|
173
|
+
if abi_callable["type"] == "function":
|
|
174
|
+
output_types = get_abi_output_types(abi_callable)
|
|
156
175
|
|
|
157
176
|
provider = w3.provider
|
|
158
177
|
if hasattr(provider, "_is_batching") and provider._is_batching:
|
|
159
|
-
|
|
160
|
-
request_information = tuple(return_data)
|
|
178
|
+
BatchingReturnData: TypeAlias = Tuple[Tuple[RPCEndpoint, Any], Tuple[Any, ...]]
|
|
179
|
+
request_information = tuple(cast(BatchingReturnData, return_data))
|
|
161
180
|
method_and_params = request_information[0]
|
|
162
181
|
|
|
163
182
|
# append return data formatting to result formatters
|
|
@@ -168,8 +187,8 @@ def call_contract_function(
|
|
|
168
187
|
format_contract_call_return_data_curried(
|
|
169
188
|
w3,
|
|
170
189
|
decode_tuples,
|
|
171
|
-
|
|
172
|
-
|
|
190
|
+
abi_callable,
|
|
191
|
+
abi_element_identifier,
|
|
173
192
|
normalizers,
|
|
174
193
|
output_types,
|
|
175
194
|
),
|
|
@@ -198,7 +217,7 @@ def call_contract_function(
|
|
|
198
217
|
)
|
|
199
218
|
else:
|
|
200
219
|
msg = (
|
|
201
|
-
f"Could not decode contract function call to {
|
|
220
|
+
f"Could not decode contract function call to {abi_element_identifier} "
|
|
202
221
|
f"with return data: {str(return_data)}, output_types: {output_types}"
|
|
203
222
|
)
|
|
204
223
|
raise BadFunctionCallOutput(msg) from e
|
|
@@ -209,8 +228,8 @@ def call_contract_function(
|
|
|
209
228
|
)
|
|
210
229
|
normalized_data = map_abi_data(_normalizers, output_types, output_data)
|
|
211
230
|
|
|
212
|
-
if decode_tuples:
|
|
213
|
-
decoded = named_tree(
|
|
231
|
+
if decode_tuples and abi_callable["type"] == "function":
|
|
232
|
+
decoded = named_tree(abi_callable["outputs"], normalized_data)
|
|
214
233
|
normalized_data = recursive_dict_to_namedtuple(decoded)
|
|
215
234
|
|
|
216
235
|
if len(normalized_data) == 1:
|
|
@@ -222,7 +241,7 @@ def call_contract_function(
|
|
|
222
241
|
def transact_with_contract_function(
|
|
223
242
|
address: ChecksumAddress,
|
|
224
243
|
w3: "Web3",
|
|
225
|
-
|
|
244
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
226
245
|
transaction: Optional[TxParams] = None,
|
|
227
246
|
contract_abi: Optional[ABI] = None,
|
|
228
247
|
fn_abi: Optional[ABIFunction] = None,
|
|
@@ -236,10 +255,10 @@ def transact_with_contract_function(
|
|
|
236
255
|
transact_transaction = prepare_transaction(
|
|
237
256
|
address,
|
|
238
257
|
w3,
|
|
239
|
-
|
|
258
|
+
abi_element_identifier=abi_element_identifier,
|
|
240
259
|
contract_abi=contract_abi,
|
|
241
260
|
transaction=transaction,
|
|
242
|
-
|
|
261
|
+
abi_callable=fn_abi,
|
|
243
262
|
fn_args=args,
|
|
244
263
|
fn_kwargs=kwargs,
|
|
245
264
|
)
|
|
@@ -251,7 +270,7 @@ def transact_with_contract_function(
|
|
|
251
270
|
def estimate_gas_for_function(
|
|
252
271
|
address: ChecksumAddress,
|
|
253
272
|
w3: "Web3",
|
|
254
|
-
|
|
273
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
255
274
|
transaction: Optional[TxParams] = None,
|
|
256
275
|
contract_abi: Optional[ABI] = None,
|
|
257
276
|
fn_abi: Optional[ABIFunction] = None,
|
|
@@ -269,9 +288,9 @@ def estimate_gas_for_function(
|
|
|
269
288
|
estimate_transaction = prepare_transaction(
|
|
270
289
|
address,
|
|
271
290
|
w3,
|
|
272
|
-
|
|
291
|
+
abi_element_identifier=abi_element_identifier,
|
|
273
292
|
contract_abi=contract_abi,
|
|
274
|
-
|
|
293
|
+
abi_callable=fn_abi,
|
|
275
294
|
transaction=transaction,
|
|
276
295
|
fn_args=args,
|
|
277
296
|
fn_kwargs=kwargs,
|
|
@@ -283,7 +302,7 @@ def estimate_gas_for_function(
|
|
|
283
302
|
def build_transaction_for_function(
|
|
284
303
|
address: ChecksumAddress,
|
|
285
304
|
w3: "Web3",
|
|
286
|
-
|
|
305
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
287
306
|
transaction: Optional[TxParams] = None,
|
|
288
307
|
contract_abi: Optional[ABI] = None,
|
|
289
308
|
fn_abi: Optional[ABIFunction] = None,
|
|
@@ -299,9 +318,9 @@ def build_transaction_for_function(
|
|
|
299
318
|
prepared_transaction = prepare_transaction(
|
|
300
319
|
address,
|
|
301
320
|
w3,
|
|
302
|
-
|
|
321
|
+
abi_element_identifier=abi_element_identifier,
|
|
303
322
|
contract_abi=contract_abi,
|
|
304
|
-
|
|
323
|
+
abi_callable=fn_abi,
|
|
305
324
|
transaction=transaction,
|
|
306
325
|
fn_args=args,
|
|
307
326
|
fn_kwargs=kwargs,
|
|
@@ -319,14 +338,14 @@ def find_functions_by_identifier(
|
|
|
319
338
|
callable_check: Callable[..., Any],
|
|
320
339
|
function_type: Type[TContractFn],
|
|
321
340
|
) -> List[TContractFn]:
|
|
322
|
-
fns_abi =
|
|
341
|
+
fns_abi = filter_abi_by_type("function", contract_abi)
|
|
323
342
|
return [
|
|
324
343
|
function_type.factory(
|
|
325
344
|
fn_abi["name"],
|
|
326
345
|
w3=w3,
|
|
327
346
|
contract_abi=contract_abi,
|
|
328
347
|
address=address,
|
|
329
|
-
|
|
348
|
+
abi_element_identifier=fn_abi["name"],
|
|
330
349
|
abi=fn_abi,
|
|
331
350
|
)
|
|
332
351
|
for fn_abi in fns_abi
|
|
@@ -353,7 +372,7 @@ async def async_call_contract_function(
|
|
|
353
372
|
async_w3: "AsyncWeb3",
|
|
354
373
|
address: ChecksumAddress,
|
|
355
374
|
normalizers: Tuple[Callable[..., Any], ...],
|
|
356
|
-
|
|
375
|
+
abi_element_identifier: ABIElementIdentifier,
|
|
357
376
|
transaction: TxParams,
|
|
358
377
|
block_id: Optional[BlockIdentifier] = None,
|
|
359
378
|
contract_abi: Optional[ABI] = None,
|
|
@@ -371,9 +390,9 @@ async def async_call_contract_function(
|
|
|
371
390
|
call_transaction = prepare_transaction(
|
|
372
391
|
address,
|
|
373
392
|
async_w3,
|
|
374
|
-
|
|
393
|
+
abi_element_identifier=abi_element_identifier,
|
|
375
394
|
contract_abi=contract_abi,
|
|
376
|
-
|
|
395
|
+
abi_callable=fn_abi,
|
|
377
396
|
transaction=transaction,
|
|
378
397
|
fn_args=args,
|
|
379
398
|
fn_kwargs=kwargs,
|
|
@@ -387,18 +406,28 @@ async def async_call_contract_function(
|
|
|
387
406
|
)
|
|
388
407
|
|
|
389
408
|
if fn_abi is None:
|
|
390
|
-
fn_abi =
|
|
391
|
-
|
|
409
|
+
fn_abi = cast(
|
|
410
|
+
ABIFunction,
|
|
411
|
+
get_abi_element(
|
|
412
|
+
contract_abi,
|
|
413
|
+
abi_element_identifier,
|
|
414
|
+
*args,
|
|
415
|
+
abi_codec=async_w3.codec,
|
|
416
|
+
**kwargs,
|
|
417
|
+
),
|
|
392
418
|
)
|
|
393
419
|
|
|
394
|
-
|
|
420
|
+
# get the output types, which only exist for function types
|
|
421
|
+
output_types = []
|
|
422
|
+
if fn_abi["type"] == "function":
|
|
423
|
+
output_types = get_abi_output_types(fn_abi)
|
|
395
424
|
|
|
396
425
|
if async_w3.provider._is_batching:
|
|
397
426
|
contract_call_return_data_formatter = format_contract_call_return_data_curried(
|
|
398
427
|
async_w3,
|
|
399
428
|
decode_tuples,
|
|
400
429
|
fn_abi,
|
|
401
|
-
|
|
430
|
+
abi_element_identifier,
|
|
402
431
|
normalizers,
|
|
403
432
|
output_types,
|
|
404
433
|
)
|
|
@@ -410,8 +439,10 @@ async def async_call_contract_function(
|
|
|
410
439
|
current_request_id, contract_call_return_data_formatter
|
|
411
440
|
)
|
|
412
441
|
else:
|
|
413
|
-
|
|
414
|
-
|
|
442
|
+
BatchingReturnData: TypeAlias = Tuple[
|
|
443
|
+
Tuple[RPCEndpoint, Any], Tuple[Any, ...]
|
|
444
|
+
]
|
|
445
|
+
request_information = tuple(cast(BatchingReturnData, return_data))
|
|
415
446
|
method_and_params = request_information[0]
|
|
416
447
|
|
|
417
448
|
# append return data formatter to result formatters
|
|
@@ -446,7 +477,7 @@ async def async_call_contract_function(
|
|
|
446
477
|
)
|
|
447
478
|
else:
|
|
448
479
|
msg = (
|
|
449
|
-
f"Could not decode contract function call to {
|
|
480
|
+
f"Could not decode contract function call to {abi_element_identifier} "
|
|
450
481
|
f"with return data: {str(return_data)}, output_types: {output_types}"
|
|
451
482
|
)
|
|
452
483
|
raise BadFunctionCallOutput(msg) from e
|
|
@@ -467,7 +498,7 @@ async def async_call_contract_function(
|
|
|
467
498
|
async def async_transact_with_contract_function(
|
|
468
499
|
address: ChecksumAddress,
|
|
469
500
|
async_w3: "AsyncWeb3",
|
|
470
|
-
|
|
501
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
471
502
|
transaction: Optional[TxParams] = None,
|
|
472
503
|
contract_abi: Optional[ABI] = None,
|
|
473
504
|
fn_abi: Optional[ABIFunction] = None,
|
|
@@ -481,10 +512,10 @@ async def async_transact_with_contract_function(
|
|
|
481
512
|
transact_transaction = prepare_transaction(
|
|
482
513
|
address,
|
|
483
514
|
async_w3,
|
|
484
|
-
|
|
515
|
+
abi_element_identifier=abi_element_identifier,
|
|
485
516
|
contract_abi=contract_abi,
|
|
486
517
|
transaction=transaction,
|
|
487
|
-
|
|
518
|
+
abi_callable=fn_abi,
|
|
488
519
|
fn_args=args,
|
|
489
520
|
fn_kwargs=kwargs,
|
|
490
521
|
)
|
|
@@ -496,7 +527,7 @@ async def async_transact_with_contract_function(
|
|
|
496
527
|
async def async_estimate_gas_for_function(
|
|
497
528
|
address: ChecksumAddress,
|
|
498
529
|
async_w3: "AsyncWeb3",
|
|
499
|
-
|
|
530
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
500
531
|
transaction: Optional[TxParams] = None,
|
|
501
532
|
contract_abi: Optional[ABI] = None,
|
|
502
533
|
fn_abi: Optional[ABIFunction] = None,
|
|
@@ -514,9 +545,9 @@ async def async_estimate_gas_for_function(
|
|
|
514
545
|
estimate_transaction = prepare_transaction(
|
|
515
546
|
address,
|
|
516
547
|
async_w3,
|
|
517
|
-
|
|
548
|
+
abi_element_identifier=abi_element_identifier,
|
|
518
549
|
contract_abi=contract_abi,
|
|
519
|
-
|
|
550
|
+
abi_callable=fn_abi,
|
|
520
551
|
transaction=transaction,
|
|
521
552
|
fn_args=args,
|
|
522
553
|
fn_kwargs=kwargs,
|
|
@@ -530,7 +561,7 @@ async def async_estimate_gas_for_function(
|
|
|
530
561
|
async def async_build_transaction_for_function(
|
|
531
562
|
address: ChecksumAddress,
|
|
532
563
|
async_w3: "AsyncWeb3",
|
|
533
|
-
|
|
564
|
+
abi_element_identifier: Optional[ABIElementIdentifier] = None,
|
|
534
565
|
transaction: Optional[TxParams] = None,
|
|
535
566
|
contract_abi: Optional[ABI] = None,
|
|
536
567
|
fn_abi: Optional[ABIFunction] = None,
|
|
@@ -546,9 +577,9 @@ async def async_build_transaction_for_function(
|
|
|
546
577
|
prepared_transaction = prepare_transaction(
|
|
547
578
|
address,
|
|
548
579
|
async_w3,
|
|
549
|
-
|
|
580
|
+
abi_element_identifier=abi_element_identifier,
|
|
550
581
|
contract_abi=contract_abi,
|
|
551
|
-
|
|
582
|
+
abi_callable=fn_abi,
|
|
552
583
|
transaction=transaction,
|
|
553
584
|
fn_args=args,
|
|
554
585
|
fn_kwargs=kwargs,
|
web3/datastructures.py
CHANGED
|
@@ -182,7 +182,7 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
182
182
|
if name is None:
|
|
183
183
|
name = cast(TKey, element)
|
|
184
184
|
|
|
185
|
-
name = self.
|
|
185
|
+
name = self._build_name(name)
|
|
186
186
|
|
|
187
187
|
if name in self._queue:
|
|
188
188
|
if name is element:
|
|
@@ -219,7 +219,7 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
219
219
|
if name is None:
|
|
220
220
|
name = cast(TKey, element)
|
|
221
221
|
|
|
222
|
-
name = self.
|
|
222
|
+
name = self._build_name(name)
|
|
223
223
|
|
|
224
224
|
self._queue.move_to_end(name, last=False)
|
|
225
225
|
elif layer == len(self._queue):
|
|
@@ -233,7 +233,7 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
233
233
|
self._queue.clear()
|
|
234
234
|
|
|
235
235
|
def replace(self, old: TKey, new: TKey) -> TValue:
|
|
236
|
-
old_name = self.
|
|
236
|
+
old_name = self._build_name(old)
|
|
237
237
|
|
|
238
238
|
if old_name not in self._queue:
|
|
239
239
|
raise Web3ValueError(
|
|
@@ -248,15 +248,25 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
248
248
|
self._queue[old_name] = new
|
|
249
249
|
return to_be_replaced
|
|
250
250
|
|
|
251
|
-
|
|
251
|
+
@staticmethod
|
|
252
|
+
def _build_name(value: TKey) -> TKey:
|
|
252
253
|
try:
|
|
253
254
|
value.__hash__()
|
|
255
|
+
return value
|
|
254
256
|
except TypeError:
|
|
255
|
-
|
|
256
|
-
|
|
257
|
+
# unhashable, unnamed elements
|
|
258
|
+
if not callable(value):
|
|
259
|
+
raise Web3TypeError(
|
|
260
|
+
f"Expected a callable or hashable type, got {type(value)}"
|
|
261
|
+
)
|
|
262
|
+
# This will either be ``Web3Middleware`` class or the ``build`` method of a
|
|
263
|
+
# ``Web3MiddlewareBuilder``. Instantiate with empty ``Web3`` and use a
|
|
264
|
+
# unique identifier with the ``__hash__()`` as the name.
|
|
265
|
+
v = value(None)
|
|
266
|
+
return cast(TKey, f"{v.__class__}<{v.__hash__()}>")
|
|
257
267
|
|
|
258
268
|
def remove(self, old: TKey) -> None:
|
|
259
|
-
old_name = self.
|
|
269
|
+
old_name = self._build_name(old)
|
|
260
270
|
if old_name not in self._queue:
|
|
261
271
|
raise Web3ValueError("You can only remove something that has been added")
|
|
262
272
|
del self._queue[old_name]
|
|
@@ -270,8 +280,8 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
270
280
|
return [(val, key) for key, val in reversed(self._queue.items())]
|
|
271
281
|
|
|
272
282
|
def _replace_with_new_name(self, old: TKey, new: TKey) -> None:
|
|
273
|
-
old_name = self.
|
|
274
|
-
new_name = self.
|
|
283
|
+
old_name = self._build_name(old)
|
|
284
|
+
new_name = self._build_name(new)
|
|
275
285
|
|
|
276
286
|
self._queue[new_name] = new
|
|
277
287
|
found_old = False
|
|
@@ -293,11 +303,11 @@ class NamedElementOnion(Mapping[TKey, TValue]):
|
|
|
293
303
|
return NamedElementOnion(cast(List[Any], combined.items()))
|
|
294
304
|
|
|
295
305
|
def __contains__(self, element: Any) -> bool:
|
|
296
|
-
element_name = self.
|
|
306
|
+
element_name = self._build_name(element)
|
|
297
307
|
return element_name in self._queue
|
|
298
308
|
|
|
299
309
|
def __getitem__(self, element: TKey) -> TValue:
|
|
300
|
-
element_name = self.
|
|
310
|
+
element_name = self._build_name(element)
|
|
301
311
|
return self._queue[element_name]
|
|
302
312
|
|
|
303
313
|
def __len__(self) -> int:
|
web3/eth/async_eth.py
CHANGED
|
@@ -732,8 +732,7 @@ class AsyncEth(BaseEth):
|
|
|
732
732
|
# -- contract methods -- #
|
|
733
733
|
|
|
734
734
|
@overload
|
|
735
|
-
|
|
736
|
-
def contract(self, address: None = None, **kwargs: Any) -> Type[AsyncContract]: # type: ignore[overload-overlap] # noqa: E501
|
|
735
|
+
def contract(self, address: None = None, **kwargs: Any) -> Type[AsyncContract]:
|
|
737
736
|
...
|
|
738
737
|
|
|
739
738
|
@overload
|
web3/eth/eth.py
CHANGED
|
@@ -629,8 +629,7 @@ class Eth(BaseEth):
|
|
|
629
629
|
)
|
|
630
630
|
|
|
631
631
|
@overload
|
|
632
|
-
|
|
633
|
-
def contract(self, address: None = None, **kwargs: Any) -> Type[Contract]: # type: ignore[overload-overlap] # noqa: E501
|
|
632
|
+
def contract(self, address: None = None, **kwargs: Any) -> Type[Contract]:
|
|
634
633
|
...
|
|
635
634
|
|
|
636
635
|
@overload
|
web3/exceptions.py
CHANGED
|
@@ -8,10 +8,6 @@ from typing import (
|
|
|
8
8
|
Union,
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
-
from eth_utils import (
|
|
12
|
-
ValidationError,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
11
|
from web3.types import (
|
|
16
12
|
BlockData,
|
|
17
13
|
RPCResponse,
|
|
@@ -164,7 +160,7 @@ class MismatchedABI(Web3Exception):
|
|
|
164
160
|
"""
|
|
165
161
|
|
|
166
162
|
|
|
167
|
-
class
|
|
163
|
+
class ABIEventNotFound(AttributeError, MismatchedABI):
|
|
168
164
|
"""
|
|
169
165
|
Raised when an attempt is made to access an event
|
|
170
166
|
that does not exist in the ABI.
|
|
@@ -178,14 +174,25 @@ class ABIFunctionNotFound(AttributeError, MismatchedABI):
|
|
|
178
174
|
"""
|
|
179
175
|
|
|
180
176
|
|
|
181
|
-
class
|
|
177
|
+
class ABIConstructorNotFound(Web3Exception):
|
|
178
|
+
"""
|
|
179
|
+
Raised when a constructor function doesn't exist in contract.
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class ABIFallbackNotFound(Web3Exception):
|
|
184
|
+
"""
|
|
185
|
+
Raised when a fallback function doesn't exist in contract.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class ABIReceiveNotFound(Web3Exception):
|
|
182
190
|
"""
|
|
183
|
-
Raised when
|
|
191
|
+
Raised when a receive function doesn't exist in contract.
|
|
184
192
|
"""
|
|
185
193
|
|
|
186
194
|
|
|
187
|
-
|
|
188
|
-
class Web3ValidationError(Web3Exception, ValidationError): # type: ignore[misc]
|
|
195
|
+
class Web3ValidationError(Web3Exception):
|
|
189
196
|
"""
|
|
190
197
|
Raised when a supplied value is invalid.
|
|
191
198
|
"""
|
|
@@ -364,6 +371,12 @@ class MethodUnavailable(Web3RPCError):
|
|
|
364
371
|
"""
|
|
365
372
|
|
|
366
373
|
|
|
374
|
+
class RequestTimedOut(Web3RPCError):
|
|
375
|
+
"""
|
|
376
|
+
Raised when a request to the node times out.
|
|
377
|
+
"""
|
|
378
|
+
|
|
379
|
+
|
|
367
380
|
class TransactionNotFound(Web3RPCError):
|
|
368
381
|
"""
|
|
369
382
|
Raised when a tx hash used to look up a tx in a jsonrpc call cannot be found.
|
|
@@ -5,6 +5,7 @@ from typing import (
|
|
|
5
5
|
Iterable,
|
|
6
6
|
Sequence,
|
|
7
7
|
Tuple,
|
|
8
|
+
cast,
|
|
8
9
|
)
|
|
9
10
|
|
|
10
11
|
from eth_typing import (
|
|
@@ -35,6 +36,7 @@ from web3.exceptions import (
|
|
|
35
36
|
from web3.types import (
|
|
36
37
|
BlockNumber,
|
|
37
38
|
GasPriceStrategy,
|
|
39
|
+
TxData,
|
|
38
40
|
TxParams,
|
|
39
41
|
Wei,
|
|
40
42
|
)
|
|
@@ -84,6 +86,7 @@ def _get_raw_miner_data(
|
|
|
84
86
|
latest = w3.eth.get_block("latest", full_transactions=True)
|
|
85
87
|
|
|
86
88
|
for transaction in latest["transactions"]:
|
|
89
|
+
transaction = cast(TxData, transaction)
|
|
87
90
|
yield (latest["miner"], latest["hash"], transaction["gasPrice"])
|
|
88
91
|
|
|
89
92
|
block = latest
|
|
@@ -96,6 +99,7 @@ def _get_raw_miner_data(
|
|
|
96
99
|
# block numbers to make caching the data easier to implement.
|
|
97
100
|
block = w3.eth.get_block(block["parentHash"], full_transactions=True)
|
|
98
101
|
for transaction in block["transactions"]:
|
|
102
|
+
transaction = cast(TxData, transaction)
|
|
99
103
|
yield (block["miner"], block["hash"], transaction["gasPrice"])
|
|
100
104
|
|
|
101
105
|
|
web3/manager.py
CHANGED
|
@@ -37,6 +37,7 @@ from web3.exceptions import (
|
|
|
37
37
|
BadResponseFormat,
|
|
38
38
|
MethodUnavailable,
|
|
39
39
|
ProviderConnectionError,
|
|
40
|
+
RequestTimedOut,
|
|
40
41
|
TaskNotRunning,
|
|
41
42
|
Web3RPCError,
|
|
42
43
|
Web3TypeError,
|
|
@@ -89,6 +90,13 @@ if TYPE_CHECKING:
|
|
|
89
90
|
|
|
90
91
|
|
|
91
92
|
NULL_RESPONSES = [None, HexBytes("0x"), "0x"]
|
|
93
|
+
KNOWN_REQUEST_TIMEOUT_MESSAGING = {
|
|
94
|
+
# Note: It's important to be very explicit here and not too broad. We don't want
|
|
95
|
+
# to accidentally catch a message that is not for a request timeout. In the worst
|
|
96
|
+
# case, we raise something more generic like `Web3RPCError`. JSON-RPC unfortunately
|
|
97
|
+
# has not standardized error codes for request timeouts.
|
|
98
|
+
"request timed out", # go-ethereum
|
|
99
|
+
}
|
|
92
100
|
METHOD_NOT_FOUND = -32601
|
|
93
101
|
|
|
94
102
|
|
|
@@ -185,6 +193,7 @@ def _validate_response(
|
|
|
185
193
|
response, 'Response must include either "error" or "result".'
|
|
186
194
|
)
|
|
187
195
|
elif "error" in response:
|
|
196
|
+
web3_rpc_error: Optional[Web3RPCError] = None
|
|
188
197
|
error = response["error"]
|
|
189
198
|
|
|
190
199
|
# raise the error when the value is a string
|
|
@@ -195,6 +204,13 @@ def _validate_response(
|
|
|
195
204
|
"JSON-RPC 2.0 specification.",
|
|
196
205
|
)
|
|
197
206
|
|
|
207
|
+
# errors must include a message
|
|
208
|
+
error_message = error.get("message")
|
|
209
|
+
if not isinstance(error_message, str):
|
|
210
|
+
_raise_bad_response_format(
|
|
211
|
+
response, 'error["message"] is required and must be a string value.'
|
|
212
|
+
)
|
|
213
|
+
|
|
198
214
|
# errors must include an integer code
|
|
199
215
|
code = error.get("code")
|
|
200
216
|
if not isinstance(code, int):
|
|
@@ -202,7 +218,7 @@ def _validate_response(
|
|
|
202
218
|
response, 'error["code"] is required and must be an integer value.'
|
|
203
219
|
)
|
|
204
220
|
elif code == METHOD_NOT_FOUND:
|
|
205
|
-
|
|
221
|
+
web3_rpc_error = MethodUnavailable(
|
|
206
222
|
repr(error),
|
|
207
223
|
rpc_response=response,
|
|
208
224
|
user_message=(
|
|
@@ -211,20 +227,26 @@ def _validate_response(
|
|
|
211
227
|
"currently enabled."
|
|
212
228
|
),
|
|
213
229
|
)
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
230
|
+
elif any(
|
|
231
|
+
# parse specific timeout messages
|
|
232
|
+
timeout_str in error_message.lower()
|
|
233
|
+
for timeout_str in KNOWN_REQUEST_TIMEOUT_MESSAGING
|
|
234
|
+
):
|
|
235
|
+
web3_rpc_error = RequestTimedOut(
|
|
236
|
+
repr(error),
|
|
237
|
+
rpc_response=response,
|
|
238
|
+
user_message=(
|
|
239
|
+
"The request timed out. Check the connection to your node and "
|
|
240
|
+
"try again."
|
|
241
|
+
),
|
|
223
242
|
)
|
|
224
243
|
|
|
225
|
-
|
|
244
|
+
if web3_rpc_error is None:
|
|
245
|
+
# if no condition was met above, raise a more generic `Web3RPCError`
|
|
246
|
+
web3_rpc_error = Web3RPCError(repr(error), rpc_response=response)
|
|
247
|
+
|
|
248
|
+
response = apply_error_formatters(error_formatters, response)
|
|
226
249
|
|
|
227
|
-
web3_rpc_error = Web3RPCError(repr(error), rpc_response=response)
|
|
228
250
|
logger.error(web3_rpc_error.user_message)
|
|
229
251
|
logger.debug(f"RPC error response: {response}")
|
|
230
252
|
raise web3_rpc_error
|