web3 7.0.0b2__py3-none-any.whl → 7.0.0b4__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 +14 -11
- ens/contract_data.py +2 -2
- ens/ens.py +10 -7
- ens/exceptions.py +19 -27
- ens/specs/nf.json +1 -1
- ens/specs/normalization_spec.json +1 -1
- ens/utils.py +24 -15
- 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 +12 -12
- 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 +35 -24
- web3/_utils/fee_utils.py +2 -4
- web3/_utils/filters.py +17 -12
- web3/_utils/formatters.py +2 -2
- web3/_utils/math.py +14 -15
- web3/_utils/method_formatters.py +31 -5
- web3/_utils/module.py +2 -1
- web3/_utils/module_testing/eth_module.py +129 -75
- web3/_utils/module_testing/go_ethereum_personal_module.py +1 -1
- 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 +6 -1
- web3/_utils/threads.py +8 -7
- web3/_utils/transactions.py +18 -12
- web3/_utils/type_conversion.py +5 -1
- web3/_utils/validation.py +12 -10
- web3/contract/async_contract.py +12 -7
- web3/contract/base_contract.py +51 -57
- web3/contract/contract.py +12 -6
- web3/contract/utils.py +11 -6
- web3/datastructures.py +22 -12
- web3/eth/async_eth.py +53 -30
- web3/eth/base_eth.py +7 -3
- web3/eth/eth.py +31 -14
- web3/exceptions.py +41 -59
- web3/gas_strategies/time_based.py +2 -4
- web3/geth.py +1 -3
- web3/main.py +6 -2
- web3/manager.py +13 -12
- web3/method.py +13 -5
- web3/middleware/base.py +4 -2
- web3/middleware/filter.py +27 -17
- web3/middleware/formatting.py +6 -3
- web3/middleware/names.py +4 -1
- web3/middleware/signing.py +6 -2
- web3/middleware/stalecheck.py +2 -1
- web3/providers/eth_tester/defaults.py +1 -1
- web3/providers/eth_tester/main.py +5 -4
- web3/providers/eth_tester/middleware.py +10 -1
- web3/providers/ipc.py +7 -3
- web3/providers/persistent/async_ipc.py +6 -7
- web3/providers/persistent/persistent.py +12 -2
- web3/providers/persistent/request_processor.py +10 -12
- web3/providers/persistent/websocket.py +3 -3
- web3/providers/rpc/async_rpc.py +23 -6
- web3/providers/rpc/rpc.py +27 -16
- web3/testing.py +4 -4
- web3/tools/benchmark/__init__.py +0 -0
- web3/tools/benchmark/main.py +189 -0
- web3/tools/benchmark/node.py +126 -0
- web3/tools/benchmark/reporting.py +39 -0
- web3/tools/benchmark/utils.py +69 -0
- web3/tracing.py +9 -5
- web3/types.py +23 -22
- web3/utils/caching.py +2 -4
- {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/METADATA +13 -26
- {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/RECORD +83 -78
- {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/LICENSE +0 -0
- {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/WHEEL +0 -0
- {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/top_level.txt +0 -0
ens/utils.py
CHANGED
|
@@ -35,9 +35,11 @@ from hexbytes import (
|
|
|
35
35
|
HexBytes,
|
|
36
36
|
)
|
|
37
37
|
|
|
38
|
-
from .
|
|
39
|
-
|
|
38
|
+
from ens.exceptions import (
|
|
39
|
+
ENSTypeError,
|
|
40
|
+
ENSValueError,
|
|
40
41
|
)
|
|
42
|
+
|
|
41
43
|
from .constants import (
|
|
42
44
|
ACCEPTABLE_STALE_HOURS,
|
|
43
45
|
AUCTION_START_GAS_CONSTANT,
|
|
@@ -80,7 +82,7 @@ def Web3() -> Type["_Web3"]:
|
|
|
80
82
|
|
|
81
83
|
|
|
82
84
|
def init_web3(
|
|
83
|
-
provider: "BaseProvider" =
|
|
85
|
+
provider: "BaseProvider" = None,
|
|
84
86
|
middleware: Optional[Sequence[Tuple["Middleware", str]]] = None,
|
|
85
87
|
) -> "_Web3":
|
|
86
88
|
from web3 import (
|
|
@@ -90,6 +92,7 @@ def init_web3(
|
|
|
90
92
|
Eth as EthMain,
|
|
91
93
|
)
|
|
92
94
|
|
|
95
|
+
provider = provider or cast("BaseProvider", default)
|
|
93
96
|
if provider is default:
|
|
94
97
|
w3 = Web3Main(ens=None, modules={"eth": (EthMain)})
|
|
95
98
|
else:
|
|
@@ -117,13 +120,18 @@ def customize_web3(w3: "_Web3") -> "_Web3":
|
|
|
117
120
|
def normalize_name(name: str) -> str:
|
|
118
121
|
"""
|
|
119
122
|
Clean the fully qualified name, as defined in ENS `EIP-137
|
|
120
|
-
<https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_
|
|
123
|
+
<https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_ # blocklint: pragma # noqa: E501
|
|
121
124
|
|
|
122
125
|
This does *not* enforce whether ``name`` is a label or fully qualified domain.
|
|
123
126
|
|
|
124
127
|
:param str name: the dot-separated ENS name
|
|
125
128
|
:raises InvalidName: if ``name`` has invalid syntax
|
|
126
129
|
"""
|
|
130
|
+
# Defer import because module initialization takes > 0.1 ms
|
|
131
|
+
from ._normalization import (
|
|
132
|
+
normalize_name_ensip15,
|
|
133
|
+
)
|
|
134
|
+
|
|
127
135
|
if is_empty_name(name):
|
|
128
136
|
return ""
|
|
129
137
|
elif isinstance(name, (bytes, bytearray)):
|
|
@@ -133,7 +141,7 @@ def normalize_name(name: str) -> str:
|
|
|
133
141
|
|
|
134
142
|
|
|
135
143
|
def ens_encode_name(name: str) -> bytes:
|
|
136
|
-
"""
|
|
144
|
+
r"""
|
|
137
145
|
Encode a name according to DNS standards specified in section 3.1
|
|
138
146
|
of RFC1035 with the following validations:
|
|
139
147
|
|
|
@@ -169,7 +177,7 @@ def ens_encode_name(name: str) -> bytes:
|
|
|
169
177
|
def is_valid_name(name: str) -> bool:
|
|
170
178
|
"""
|
|
171
179
|
Validate whether the fully qualified name is valid, as defined in ENS `EIP-137
|
|
172
|
-
<https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_
|
|
180
|
+
<https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_ # blocklint: pragma # noqa: E501
|
|
173
181
|
|
|
174
182
|
:param str name: the dot-separated ENS name
|
|
175
183
|
:returns: True if ``name`` is set, and :meth:`~ens.ENS.nameprep` will not
|
|
@@ -197,17 +205,17 @@ def sha3_text(val: Union[str, bytes]) -> HexBytes:
|
|
|
197
205
|
def label_to_hash(label: str) -> HexBytes:
|
|
198
206
|
label = normalize_name(label)
|
|
199
207
|
if "." in label:
|
|
200
|
-
raise
|
|
208
|
+
raise ENSValueError(f"Cannot generate hash for label {label!r} with a '.'")
|
|
201
209
|
return Web3().keccak(text=label)
|
|
202
210
|
|
|
203
211
|
|
|
204
212
|
def normal_name_to_hash(name: str) -> HexBytes:
|
|
205
213
|
"""
|
|
206
|
-
|
|
207
|
-
|
|
214
|
+
Hashes a pre-normalized name.
|
|
215
|
+
The normalization of the name is a prerequisite and is not handled by this function.
|
|
208
216
|
|
|
209
|
-
:param name:
|
|
210
|
-
:return: namehash
|
|
217
|
+
:param str name: A normalized name string to be hashed.
|
|
218
|
+
:return: namehash - the hash of the name
|
|
211
219
|
:rtype: HexBytes
|
|
212
220
|
"""
|
|
213
221
|
node = EMPTY_SHA3_BYTES
|
|
@@ -229,7 +237,7 @@ def raw_name_to_hash(name: str) -> HexBytes:
|
|
|
229
237
|
behind the scenes. For advanced usage, it is a helpful utility.
|
|
230
238
|
|
|
231
239
|
This normalizes the name with `nameprep
|
|
232
|
-
<https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_
|
|
240
|
+
<https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax>`_ # blocklint: pragma # noqa: E501
|
|
233
241
|
before hashing.
|
|
234
242
|
|
|
235
243
|
:param str name: ENS name to hash
|
|
@@ -262,7 +270,7 @@ def assert_signer_in_modifier_kwargs(modifier_kwargs: Any) -> ChecksumAddress:
|
|
|
262
270
|
|
|
263
271
|
_modifier_type, modifier_dict = dict(modifier_kwargs).popitem()
|
|
264
272
|
if "from" not in modifier_dict:
|
|
265
|
-
raise
|
|
273
|
+
raise ENSTypeError(ERR_MSG)
|
|
266
274
|
|
|
267
275
|
return modifier_dict["from"]
|
|
268
276
|
|
|
@@ -298,7 +306,7 @@ def get_abi_output_types(abi: "ABIFunction") -> List[str]:
|
|
|
298
306
|
|
|
299
307
|
|
|
300
308
|
def init_async_web3(
|
|
301
|
-
provider: "AsyncBaseProvider" =
|
|
309
|
+
provider: "AsyncBaseProvider" = None,
|
|
302
310
|
middleware: Optional[Sequence[Tuple["Middleware", str]]] = (),
|
|
303
311
|
) -> "AsyncWeb3":
|
|
304
312
|
from web3 import (
|
|
@@ -311,8 +319,9 @@ def init_async_web3(
|
|
|
311
319
|
StalecheckMiddlewareBuilder,
|
|
312
320
|
)
|
|
313
321
|
|
|
322
|
+
provider = provider or cast("AsyncBaseProvider", default)
|
|
314
323
|
middleware = list(middleware)
|
|
315
|
-
for i, (
|
|
324
|
+
for i, (_mw, name) in enumerate(middleware):
|
|
316
325
|
if name == "ens_name_to_address":
|
|
317
326
|
middleware.pop(i)
|
|
318
327
|
|
web3/__init__.py
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
from eth_account import Account # noqa: E402
|
|
2
2
|
import sys
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
import pkg_resources
|
|
4
|
+
from importlib.metadata import version
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
else:
|
|
9
|
-
from importlib.metadata import version
|
|
10
|
-
|
|
11
|
-
__version__ = version("web3")
|
|
6
|
+
__version__ = version("web3")
|
|
12
7
|
|
|
13
8
|
|
|
14
9
|
from web3.main import (
|
web3/_utils/abi.py
CHANGED
|
@@ -80,6 +80,9 @@ from web3._utils.formatters import (
|
|
|
80
80
|
from web3.exceptions import (
|
|
81
81
|
FallbackNotFound,
|
|
82
82
|
MismatchedABI,
|
|
83
|
+
Web3AttributeError,
|
|
84
|
+
Web3TypeError,
|
|
85
|
+
Web3ValueError,
|
|
83
86
|
)
|
|
84
87
|
from web3.types import (
|
|
85
88
|
ABI,
|
|
@@ -187,7 +190,8 @@ def filter_by_argument_name(
|
|
|
187
190
|
]
|
|
188
191
|
|
|
189
192
|
|
|
190
|
-
|
|
193
|
+
# type ignored because subclassing encoding.AddressEncoder which has type Any
|
|
194
|
+
class AddressEncoder(encoding.AddressEncoder): # type: ignore[misc]
|
|
191
195
|
@classmethod
|
|
192
196
|
def validate_value(cls, value: Any) -> None:
|
|
193
197
|
if is_ens_name(value):
|
|
@@ -196,7 +200,8 @@ class AddressEncoder(encoding.AddressEncoder):
|
|
|
196
200
|
super().validate_value(value)
|
|
197
201
|
|
|
198
202
|
|
|
199
|
-
|
|
203
|
+
# type ignored because subclassing encoding.BytesEncoder which has type Any
|
|
204
|
+
class AcceptsHexStrEncoder(encoding.BaseEncoder): # type: ignore[misc]
|
|
200
205
|
subencoder_cls: Type[encoding.BaseEncoder] = None
|
|
201
206
|
is_strict: bool = None
|
|
202
207
|
is_big_endian: bool = False
|
|
@@ -227,7 +232,7 @@ class AcceptsHexStrEncoder(encoding.BaseEncoder):
|
|
|
227
232
|
@classmethod
|
|
228
233
|
def get_subencoder_class(cls) -> Type[encoding.BaseEncoder]:
|
|
229
234
|
if cls.subencoder_cls is None:
|
|
230
|
-
raise
|
|
235
|
+
raise Web3AttributeError(f"No subencoder class is set. {cls.__name__}")
|
|
231
236
|
return cls.subencoder_cls
|
|
232
237
|
|
|
233
238
|
def validate_value(self, value: Any) -> None:
|
|
@@ -287,20 +292,20 @@ class ExactLengthBytesEncoder(BytesEncoder):
|
|
|
287
292
|
def validate(self) -> None:
|
|
288
293
|
super().validate()
|
|
289
294
|
if self.value_bit_size is None:
|
|
290
|
-
raise
|
|
295
|
+
raise Web3ValueError("`value_bit_size` may not be none")
|
|
291
296
|
if self.data_byte_size is None:
|
|
292
|
-
raise
|
|
297
|
+
raise Web3ValueError("`data_byte_size` may not be none")
|
|
293
298
|
if self.is_big_endian is None:
|
|
294
|
-
raise
|
|
299
|
+
raise Web3ValueError("`is_big_endian` may not be none")
|
|
295
300
|
|
|
296
301
|
if self.value_bit_size % 8 != 0:
|
|
297
|
-
raise
|
|
302
|
+
raise Web3ValueError(
|
|
298
303
|
f"Invalid value bit size: {self.value_bit_size}. "
|
|
299
304
|
"Must be a multiple of 8"
|
|
300
305
|
)
|
|
301
306
|
|
|
302
307
|
if self.value_bit_size > self.data_byte_size * 8:
|
|
303
|
-
raise
|
|
308
|
+
raise Web3ValueError("Value byte size exceeds data size")
|
|
304
309
|
|
|
305
310
|
@parse_type_str("bytes")
|
|
306
311
|
def from_type_str(
|
|
@@ -308,9 +313,7 @@ class ExactLengthBytesEncoder(BytesEncoder):
|
|
|
308
313
|
) -> "ExactLengthBytesEncoder":
|
|
309
314
|
subencoder_cls = cls.get_subencoder_class()
|
|
310
315
|
subencoder = subencoder_cls.from_type_str(abi_type.to_type_str(), registry)
|
|
311
|
-
|
|
312
|
-
# so mypy thinks cls(...) is a call to __call__, but actually calls __init__
|
|
313
|
-
return cls( # type: ignore
|
|
316
|
+
return cls(
|
|
314
317
|
subencoder,
|
|
315
318
|
value_bit_size=abi_type.sub * 8,
|
|
316
319
|
data_byte_size=abi_type.sub,
|
|
@@ -327,7 +330,8 @@ class StrictByteStringEncoder(AcceptsHexStrEncoder):
|
|
|
327
330
|
is_strict = True
|
|
328
331
|
|
|
329
332
|
|
|
330
|
-
|
|
333
|
+
# type ignored because subclassing encoding.TextStringEncoder which has type Any
|
|
334
|
+
class TextStringEncoder(encoding.TextStringEncoder): # type: ignore[misc]
|
|
331
335
|
@classmethod
|
|
332
336
|
def validate_value(cls, value: Any) -> None:
|
|
333
337
|
if is_bytes(value):
|
|
@@ -394,7 +398,7 @@ def merge_args_and_kwargs(
|
|
|
394
398
|
"""
|
|
395
399
|
# Ensure the function is being applied to the correct number of args
|
|
396
400
|
if len(args) + len(kwargs) != len(function_abi.get("inputs", [])):
|
|
397
|
-
raise
|
|
401
|
+
raise Web3TypeError(
|
|
398
402
|
f"Incorrect argument count. Expected '{len(function_abi['inputs'])}'"
|
|
399
403
|
f". Got '{len(args) + len(kwargs)}'"
|
|
400
404
|
)
|
|
@@ -410,7 +414,7 @@ def merge_args_and_kwargs(
|
|
|
410
414
|
# Check for duplicate args
|
|
411
415
|
duplicate_args = kwarg_names.intersection(args_as_kwargs.keys())
|
|
412
416
|
if duplicate_args:
|
|
413
|
-
raise
|
|
417
|
+
raise Web3TypeError(
|
|
414
418
|
f"{function_abi.get('name')}() got multiple values for argument(s) "
|
|
415
419
|
f"'{', '.join(duplicate_args)}'"
|
|
416
420
|
)
|
|
@@ -419,11 +423,11 @@ def merge_args_and_kwargs(
|
|
|
419
423
|
unknown_args = kwarg_names.difference(sorted_arg_names)
|
|
420
424
|
if unknown_args:
|
|
421
425
|
if function_abi.get("name"):
|
|
422
|
-
raise
|
|
426
|
+
raise Web3TypeError(
|
|
423
427
|
f"{function_abi.get('name')}() got unexpected keyword argument(s)"
|
|
424
428
|
f" '{', '.join(unknown_args)}'"
|
|
425
429
|
)
|
|
426
|
-
raise
|
|
430
|
+
raise Web3TypeError(
|
|
427
431
|
f"Type: '{function_abi.get('type')}' got unexpected keyword argument(s)"
|
|
428
432
|
f" '{', '.join(unknown_args)}'"
|
|
429
433
|
)
|
|
@@ -497,7 +501,7 @@ def _align_abi_input(arg_abi: ABIFunctionParams, arg: Any) -> Tuple[Any, ...]:
|
|
|
497
501
|
aligned_arg = arg
|
|
498
502
|
|
|
499
503
|
if not is_list_like(aligned_arg):
|
|
500
|
-
raise
|
|
504
|
+
raise Web3TypeError(
|
|
501
505
|
f'Expected non-string sequence for "{arg_abi.get("type")}" '
|
|
502
506
|
f"component type: got {aligned_arg}"
|
|
503
507
|
)
|
|
@@ -528,9 +532,7 @@ def get_aligned_abi_inputs(
|
|
|
528
532
|
args = tuple(args[abi["name"]] for abi in input_abis)
|
|
529
533
|
|
|
530
534
|
return (
|
|
531
|
-
|
|
532
|
-
# https://github.com/python/mypy/issues/4976
|
|
533
|
-
tuple(collapse_if_tuple(abi) for abi in input_abis), # type: ignore
|
|
535
|
+
tuple(collapse_if_tuple(abi) for abi in input_abis),
|
|
534
536
|
type(args)(_align_abi_input(abi, arg) for abi, arg in zip(input_abis, args)),
|
|
535
537
|
)
|
|
536
538
|
|
|
@@ -542,7 +544,7 @@ def get_constructor_abi(contract_abi: ABI) -> ABIFunction:
|
|
|
542
544
|
elif len(candidates) == 0:
|
|
543
545
|
return None
|
|
544
546
|
elif len(candidates) > 1:
|
|
545
|
-
raise
|
|
547
|
+
raise Web3ValueError("Found multiple constructors.")
|
|
546
548
|
return None
|
|
547
549
|
|
|
548
550
|
|
|
@@ -564,7 +566,7 @@ STATIC_TYPES = list(
|
|
|
564
566
|
)
|
|
565
567
|
|
|
566
568
|
BASE_TYPE_REGEX = "|".join(
|
|
567
|
-
|
|
569
|
+
_type + "(?![a-z0-9])" for _type in itertools.chain(STATIC_TYPES, DYNAMIC_TYPES)
|
|
568
570
|
)
|
|
569
571
|
|
|
570
572
|
SUB_TYPE_REGEX = r"\[" "[0-9]*" r"\]"
|
|
@@ -630,14 +632,14 @@ END_BRACKETS_OF_ARRAY_TYPE_REGEX = r"\[[^]]*\]$"
|
|
|
630
632
|
|
|
631
633
|
def sub_type_of_array_type(abi_type: TypeStr) -> str:
|
|
632
634
|
if not is_array_type(abi_type):
|
|
633
|
-
raise
|
|
635
|
+
raise Web3ValueError(f"Cannot parse subtype of nonarray abi-type: {abi_type}")
|
|
634
636
|
|
|
635
|
-
return re.sub(END_BRACKETS_OF_ARRAY_TYPE_REGEX, "", abi_type, 1)
|
|
637
|
+
return re.sub(END_BRACKETS_OF_ARRAY_TYPE_REGEX, "", abi_type, count=1)
|
|
636
638
|
|
|
637
639
|
|
|
638
640
|
def length_of_array_type(abi_type: TypeStr) -> int:
|
|
639
641
|
if not is_array_type(abi_type):
|
|
640
|
-
raise
|
|
642
|
+
raise Web3ValueError(f"Cannot parse length of nonarray abi-type: {abi_type}")
|
|
641
643
|
|
|
642
644
|
inner_brackets = (
|
|
643
645
|
re.search(END_BRACKETS_OF_ARRAY_TYPE_REGEX, abi_type).group(0).strip("[]")
|
|
@@ -705,8 +707,8 @@ def map_abi_data(
|
|
|
705
707
|
data: Sequence[Any],
|
|
706
708
|
) -> Any:
|
|
707
709
|
"""
|
|
708
|
-
|
|
709
|
-
|
|
710
|
+
Applies normalizers to your data, in the context of the relevant types.
|
|
711
|
+
Each normalizer is in the format:
|
|
710
712
|
|
|
711
713
|
def normalizer(datatype, data):
|
|
712
714
|
# Conditionally modify data
|
|
@@ -772,7 +774,7 @@ def data_tree_map(
|
|
|
772
774
|
|
|
773
775
|
class ABITypedData(namedtuple("ABITypedData", "abi_type, data")):
|
|
774
776
|
"""
|
|
775
|
-
|
|
777
|
+
Marks data as having a certain ABI-type.
|
|
776
778
|
|
|
777
779
|
>>> a1 = ABITypedData(['address', addr1])
|
|
778
780
|
>>> a2 = ABITypedData(['address', addr2])
|
|
@@ -1029,7 +1031,6 @@ async def async_map_if_collection(
|
|
|
1029
1031
|
Apply an awaitable method to each element of a collection or value of a dictionary.
|
|
1030
1032
|
If the value is not a collection, return it unmodified.
|
|
1031
1033
|
"""
|
|
1032
|
-
|
|
1033
1034
|
datatype = type(value)
|
|
1034
1035
|
if isinstance(value, Mapping):
|
|
1035
1036
|
return datatype({key: await func(val) for key, val in value.values()})
|
|
@@ -24,6 +24,9 @@ from web3._utils.utility_methods import (
|
|
|
24
24
|
from web3.constants import (
|
|
25
25
|
DYNAMIC_FEE_TXN_PARAMS,
|
|
26
26
|
)
|
|
27
|
+
from web3.exceptions import (
|
|
28
|
+
Web3ValueError,
|
|
29
|
+
)
|
|
27
30
|
from web3.types import (
|
|
28
31
|
BlockIdentifier,
|
|
29
32
|
TxData,
|
|
@@ -87,7 +90,7 @@ async def get_buffered_gas_estimate(
|
|
|
87
90
|
gas_limit = await get_block_gas_limit(async_w3.eth)
|
|
88
91
|
|
|
89
92
|
if gas_estimate > gas_limit:
|
|
90
|
-
raise
|
|
93
|
+
raise Web3ValueError(
|
|
91
94
|
"Contract does not appear to be deployable within the "
|
|
92
95
|
f"current network gas limits. Estimated: {gas_estimate}. "
|
|
93
96
|
f"Current gas limit: {gas_limit}"
|
|
@@ -110,7 +113,7 @@ async def async_fill_transaction_defaults(
|
|
|
110
113
|
async_w3: "AsyncWeb3", transaction: TxParams
|
|
111
114
|
) -> TxParams:
|
|
112
115
|
"""
|
|
113
|
-
|
|
116
|
+
If async_w3 is None, fill as much as possible while offline
|
|
114
117
|
"""
|
|
115
118
|
strategy_based_gas_price = async_w3.eth.generate_gas_price(transaction)
|
|
116
119
|
|
|
@@ -134,7 +137,7 @@ async def async_fill_transaction_defaults(
|
|
|
134
137
|
|
|
135
138
|
if callable(default_getter):
|
|
136
139
|
if async_w3 is None:
|
|
137
|
-
raise
|
|
140
|
+
raise Web3ValueError(
|
|
138
141
|
f"You must specify a '{key}' value in the transaction"
|
|
139
142
|
)
|
|
140
143
|
if key == "gasPrice":
|
|
@@ -155,7 +158,7 @@ async def async_get_required_transaction(
|
|
|
155
158
|
) -> TxData:
|
|
156
159
|
current_transaction = await async_w3.eth.get_transaction(transaction_hash)
|
|
157
160
|
if not current_transaction:
|
|
158
|
-
raise
|
|
161
|
+
raise Web3ValueError(
|
|
159
162
|
f"Supplied transaction with hash {transaction_hash!r} does not exist"
|
|
160
163
|
)
|
|
161
164
|
return current_transaction
|
web3/_utils/blocks.py
CHANGED
|
@@ -15,6 +15,10 @@ from eth_utils.toolz import (
|
|
|
15
15
|
curry,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
|
+
from web3.exceptions import (
|
|
19
|
+
Web3TypeError,
|
|
20
|
+
Web3ValueError,
|
|
21
|
+
)
|
|
18
22
|
from web3.types import (
|
|
19
23
|
RPCEndpoint,
|
|
20
24
|
)
|
|
@@ -32,7 +36,7 @@ def is_predefined_block_number(value: Any) -> bool:
|
|
|
32
36
|
elif is_integer(value):
|
|
33
37
|
return False
|
|
34
38
|
else:
|
|
35
|
-
raise
|
|
39
|
+
raise Web3TypeError(f"unrecognized block reference: {value!r}")
|
|
36
40
|
|
|
37
41
|
return value_text in {"latest", "pending", "earliest", "safe", "finalized"}
|
|
38
42
|
|
|
@@ -70,6 +74,6 @@ def select_method_for_block_identifier(
|
|
|
70
74
|
elif is_hex_encoded_block_number(value):
|
|
71
75
|
return if_number
|
|
72
76
|
else:
|
|
73
|
-
raise
|
|
77
|
+
raise Web3ValueError(
|
|
74
78
|
f"Value did not match any of the recognized block identifiers: {value}"
|
|
75
79
|
)
|
web3/_utils/caching.py
CHANGED
|
@@ -23,6 +23,10 @@ from eth_utils import (
|
|
|
23
23
|
to_bytes,
|
|
24
24
|
)
|
|
25
25
|
|
|
26
|
+
from web3.exceptions import (
|
|
27
|
+
Web3TypeError,
|
|
28
|
+
)
|
|
29
|
+
|
|
26
30
|
if TYPE_CHECKING:
|
|
27
31
|
from web3.providers import ( # noqa: F401
|
|
28
32
|
AsyncBaseProvider,
|
|
@@ -51,11 +55,11 @@ def generate_cache_key(value: Any) -> str:
|
|
|
51
55
|
elif is_boolean(value) or is_null(value) or is_number(value):
|
|
52
56
|
return generate_cache_key(repr(value))
|
|
53
57
|
elif is_dict(value):
|
|
54
|
-
return generate_cache_key((
|
|
58
|
+
return generate_cache_key((key, value[key]) for key in sorted(value.keys()))
|
|
55
59
|
elif is_list_like(value) or isinstance(value, collections.abc.Generator):
|
|
56
|
-
return generate_cache_key("".join(
|
|
60
|
+
return generate_cache_key("".join(generate_cache_key(item) for item in value))
|
|
57
61
|
else:
|
|
58
|
-
raise
|
|
62
|
+
raise Web3TypeError(
|
|
59
63
|
f"Cannot generate cache key for value {value} of type {type(value)}"
|
|
60
64
|
)
|
|
61
65
|
|
web3/_utils/compat/__init__.py
CHANGED
|
@@ -116,7 +116,7 @@ contracts_in_file = {}
|
|
|
116
116
|
|
|
117
117
|
def compile_files(file_list: List[str]) -> None:
|
|
118
118
|
for filename in file_list:
|
|
119
|
-
with open(os.path.join(os.getcwd(), filename)
|
|
119
|
+
with open(os.path.join(os.getcwd(), filename)) as f:
|
|
120
120
|
dot_sol_file = f.readlines()
|
|
121
121
|
|
|
122
122
|
contract_names = []
|
web3/_utils/contracts.py
CHANGED
|
@@ -76,7 +76,9 @@ from web3._utils.normalizers import (
|
|
|
76
76
|
)
|
|
77
77
|
from web3.exceptions import (
|
|
78
78
|
BlockNumberOutofRange,
|
|
79
|
+
Web3TypeError,
|
|
79
80
|
Web3ValidationError,
|
|
81
|
+
Web3ValueError,
|
|
80
82
|
)
|
|
81
83
|
from web3.types import (
|
|
82
84
|
ABI,
|
|
@@ -136,9 +138,9 @@ def find_matching_event_abi(
|
|
|
136
138
|
if len(event_abi_candidates) == 1:
|
|
137
139
|
return event_abi_candidates[0]
|
|
138
140
|
elif not event_abi_candidates:
|
|
139
|
-
raise
|
|
141
|
+
raise Web3ValueError("No matching events found")
|
|
140
142
|
else:
|
|
141
|
-
raise
|
|
143
|
+
raise Web3ValueError("Multiple events found")
|
|
142
144
|
|
|
143
145
|
|
|
144
146
|
def find_matching_fn_abi(
|
|
@@ -159,7 +161,7 @@ def find_matching_fn_abi(
|
|
|
159
161
|
return get_receive_func_abi(abi)
|
|
160
162
|
|
|
161
163
|
if not is_text(fn_identifier):
|
|
162
|
-
raise
|
|
164
|
+
raise Web3TypeError("Unsupported function identifier")
|
|
163
165
|
|
|
164
166
|
name_filter = functools.partial(filter_by_name, fn_identifier)
|
|
165
167
|
arg_count_filter = functools.partial(filter_by_argument_count, num_arguments)
|
|
@@ -217,7 +219,7 @@ def encode_abi(
|
|
|
217
219
|
argument_types = get_abi_input_types(abi)
|
|
218
220
|
|
|
219
221
|
if not check_if_arguments_can_be_encoded(abi, w3.codec, arguments, {}):
|
|
220
|
-
raise
|
|
222
|
+
raise Web3TypeError(
|
|
221
223
|
"One or more arguments could not be encoded to the necessary "
|
|
222
224
|
f"ABI type. Expected types are: {', '.join(argument_types)}"
|
|
223
225
|
)
|
|
@@ -274,7 +276,7 @@ def prepare_transaction(
|
|
|
274
276
|
prepared_transaction = cast(TxParams, dict(**transaction))
|
|
275
277
|
|
|
276
278
|
if "data" in prepared_transaction:
|
|
277
|
-
raise
|
|
279
|
+
raise Web3ValueError("Transaction parameter may not contain a 'data' key")
|
|
278
280
|
|
|
279
281
|
if address:
|
|
280
282
|
prepared_transaction.setdefault("to", address)
|
|
@@ -317,7 +319,7 @@ def encode_transaction_data(
|
|
|
317
319
|
kwargs,
|
|
318
320
|
)
|
|
319
321
|
else:
|
|
320
|
-
raise
|
|
322
|
+
raise Web3TypeError("Unsupported function identifier")
|
|
321
323
|
|
|
322
324
|
return add_0x_prefix(encode_abi(w3, fn_abi, fn_arguments, fn_selector))
|
|
323
325
|
|
|
@@ -327,8 +329,7 @@ def decode_transaction_data(
|
|
|
327
329
|
data: HexStr,
|
|
328
330
|
normalizers: Sequence[Callable[[TypeStr, Any], Tuple[TypeStr, Any]]] = None,
|
|
329
331
|
) -> Dict[str, Any]:
|
|
330
|
-
|
|
331
|
-
data = HexBytes(data) # type: ignore
|
|
332
|
+
data = HexBytes(data)
|
|
332
333
|
types = get_abi_input_types(fn_abi)
|
|
333
334
|
abi_codec = ABICodec(default_registry)
|
|
334
335
|
decoded = abi_codec.decode(types, HexBytes(data[4:]))
|
|
@@ -373,9 +374,7 @@ def get_function_info(
|
|
|
373
374
|
if fn_abi is None:
|
|
374
375
|
fn_abi = find_matching_fn_abi(contract_abi, abi_codec, fn_name, args, kwargs)
|
|
375
376
|
|
|
376
|
-
|
|
377
|
-
# https://github.com/python/mypy/issues/4976
|
|
378
|
-
fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi)) # type: ignore
|
|
377
|
+
fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi))
|
|
379
378
|
|
|
380
379
|
fn_arguments = merge_args_and_kwargs(fn_abi, args, kwargs)
|
|
381
380
|
|
|
@@ -385,7 +384,8 @@ def get_function_info(
|
|
|
385
384
|
|
|
386
385
|
|
|
387
386
|
def validate_payable(transaction: TxParams, abi: ABIFunction) -> None:
|
|
388
|
-
"""
|
|
387
|
+
"""
|
|
388
|
+
Raise Web3ValidationError if non-zero ether
|
|
389
389
|
is sent to a non-payable function.
|
|
390
390
|
"""
|
|
391
391
|
if "value" in transaction:
|
web3/_utils/datatypes.py
CHANGED
|
@@ -14,10 +14,14 @@ from eth_utils.toolz import (
|
|
|
14
14
|
concat,
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
+
from web3.exceptions import (
|
|
18
|
+
Web3AttributeError,
|
|
19
|
+
)
|
|
20
|
+
|
|
17
21
|
|
|
18
22
|
def verify_attr(class_name: str, key: str, namespace: Collection[str]) -> None:
|
|
19
23
|
if key not in namespace:
|
|
20
|
-
raise
|
|
24
|
+
raise Web3AttributeError(
|
|
21
25
|
f"Property {key} not found on {class_name} class. "
|
|
22
26
|
f"`{class_name}.factory` only accepts keyword arguments which are "
|
|
23
27
|
f"present on the {class_name} class"
|
web3/_utils/decorators.py
CHANGED
|
@@ -8,6 +8,10 @@ from typing import (
|
|
|
8
8
|
)
|
|
9
9
|
import warnings
|
|
10
10
|
|
|
11
|
+
from web3.exceptions import (
|
|
12
|
+
Web3ValueError,
|
|
13
|
+
)
|
|
14
|
+
|
|
11
15
|
TFunc = TypeVar("TFunc", bound=Callable[..., Any])
|
|
12
16
|
|
|
13
17
|
|
|
@@ -24,7 +28,7 @@ def reject_recursive_repeats(to_wrap: Callable[..., Any]) -> Callable[..., Any]:
|
|
|
24
28
|
thread_id = threading.get_ident()
|
|
25
29
|
thread_local_args = (thread_id,) + arg_instances
|
|
26
30
|
if thread_local_args in to_wrap.__already_called: # type: ignore
|
|
27
|
-
raise
|
|
31
|
+
raise Web3ValueError(f"Recursively called {to_wrap} with {args!r}")
|
|
28
32
|
to_wrap.__already_called[thread_local_args] = True # type: ignore
|
|
29
33
|
try:
|
|
30
34
|
wrapped_val = to_wrap(*args)
|
|
@@ -50,6 +54,7 @@ def deprecated_for(replace_message: str) -> Callable[..., Any]:
|
|
|
50
54
|
warnings.warn(
|
|
51
55
|
f"{to_wrap.__name__} is deprecated in favor of {replace_message}",
|
|
52
56
|
category=DeprecationWarning,
|
|
57
|
+
stacklevel=2,
|
|
53
58
|
)
|
|
54
59
|
return to_wrap(*args, **kwargs)
|
|
55
60
|
|
web3/_utils/empty.py
CHANGED