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
web3/_utils/encoding.py
CHANGED
|
@@ -55,6 +55,10 @@ from web3._utils.validation import (
|
|
|
55
55
|
from web3.datastructures import (
|
|
56
56
|
AttributeDict,
|
|
57
57
|
)
|
|
58
|
+
from web3.exceptions import (
|
|
59
|
+
Web3TypeError,
|
|
60
|
+
Web3ValueError,
|
|
61
|
+
)
|
|
58
62
|
|
|
59
63
|
|
|
60
64
|
def hex_encode_abi_type(
|
|
@@ -90,7 +94,7 @@ def hex_encode_abi_type(
|
|
|
90
94
|
elif is_string_type(abi_type):
|
|
91
95
|
return to_hex(text=value)
|
|
92
96
|
else:
|
|
93
|
-
raise
|
|
97
|
+
raise Web3ValueError(f"Unsupported ABI type: {abi_type}")
|
|
94
98
|
|
|
95
99
|
|
|
96
100
|
def to_hex_twos_compliment(value: Any, bit_size: int) -> HexStr:
|
|
@@ -169,7 +173,7 @@ def hexstr_if_str(
|
|
|
169
173
|
if isinstance(hexstr_or_primitive, str):
|
|
170
174
|
(primitive, hexstr) = (None, hexstr_or_primitive)
|
|
171
175
|
if remove_0x_prefix(HexStr(hexstr)) and not is_hex(hexstr):
|
|
172
|
-
raise
|
|
176
|
+
raise Web3ValueError(
|
|
173
177
|
"when sending a str, it must be a hex string. "
|
|
174
178
|
f"Got: {hexstr_or_primitive!r}"
|
|
175
179
|
)
|
|
@@ -210,12 +214,12 @@ class FriendlyJsonSerde:
|
|
|
210
214
|
except TypeError as full_exception:
|
|
211
215
|
if hasattr(obj, "items"):
|
|
212
216
|
item_errors = "; ".join(self._json_mapping_errors(obj))
|
|
213
|
-
raise
|
|
217
|
+
raise Web3TypeError(
|
|
214
218
|
f"dict had unencodable value at keys: {{{item_errors}}}"
|
|
215
219
|
)
|
|
216
220
|
elif is_list_like(obj):
|
|
217
221
|
element_errors = "; ".join(self._json_list_errors(obj))
|
|
218
|
-
raise
|
|
222
|
+
raise Web3TypeError(
|
|
219
223
|
f"list had unencodable value at index: [{element_errors}]"
|
|
220
224
|
)
|
|
221
225
|
else:
|
|
@@ -237,19 +241,22 @@ class FriendlyJsonSerde:
|
|
|
237
241
|
try:
|
|
238
242
|
return self._friendly_json_encode(obj, cls=cls)
|
|
239
243
|
except TypeError as exc:
|
|
240
|
-
raise
|
|
244
|
+
raise Web3TypeError(f"Could not encode to JSON: {exc}")
|
|
241
245
|
|
|
242
246
|
|
|
243
247
|
def to_4byte_hex(hex_or_str_or_bytes: Union[HexStr, str, bytes, int]) -> HexStr:
|
|
244
248
|
size_of_4bytes = 4 * 8
|
|
245
249
|
byte_str = hexstr_if_str(to_bytes, hex_or_str_or_bytes)
|
|
246
250
|
if len(byte_str) > 4:
|
|
247
|
-
raise
|
|
251
|
+
raise Web3ValueError(
|
|
252
|
+
f"expected value of size 4 bytes. Got: {len(byte_str)} bytes"
|
|
253
|
+
)
|
|
248
254
|
hex_str = encode_hex(byte_str)
|
|
249
255
|
return pad_hex(hex_str, size_of_4bytes)
|
|
250
256
|
|
|
251
257
|
|
|
252
|
-
|
|
258
|
+
# type ignored because subclassing BaseArrayEncoder which has type Any
|
|
259
|
+
class DynamicArrayPackedEncoder(BaseArrayEncoder): # type: ignore[misc]
|
|
253
260
|
is_dynamic = True
|
|
254
261
|
|
|
255
262
|
def encode(self, value: Sequence[Any]) -> bytes:
|
|
@@ -291,9 +298,7 @@ class Web3JsonEncoder(json.JSONEncoder):
|
|
|
291
298
|
def default(self, obj: Any) -> Union[Dict[Any, Any], HexStr]:
|
|
292
299
|
if isinstance(obj, AttributeDict):
|
|
293
300
|
return obj.__dict__
|
|
294
|
-
elif isinstance(obj, HexBytes):
|
|
295
|
-
return HexStr(obj.hex())
|
|
296
|
-
elif isinstance(obj, bytes):
|
|
301
|
+
elif isinstance(obj, (HexBytes, bytes)):
|
|
297
302
|
return to_hex(obj)
|
|
298
303
|
return json.JSONEncoder.default(self, obj)
|
|
299
304
|
|
|
@@ -13,6 +13,7 @@ from web3.exceptions import (
|
|
|
13
13
|
ContractPanicError,
|
|
14
14
|
OffchainLookup,
|
|
15
15
|
TransactionIndexingInProgress,
|
|
16
|
+
Web3ValueError,
|
|
16
17
|
)
|
|
17
18
|
from web3.types import (
|
|
18
19
|
RPCResponse,
|
|
@@ -76,7 +77,9 @@ def _parse_error_with_reverted_prefix(data: str) -> str:
|
|
|
76
77
|
try:
|
|
77
78
|
error = bytes.fromhex(error).decode("utf8")
|
|
78
79
|
except UnicodeDecodeError:
|
|
79
|
-
warnings.warn(
|
|
80
|
+
warnings.warn(
|
|
81
|
+
"Could not decode revert reason as UTF-8", RuntimeWarning, stacklevel=2
|
|
82
|
+
)
|
|
80
83
|
raise ContractLogicError("execution reverted", data=data)
|
|
81
84
|
|
|
82
85
|
return error
|
|
@@ -140,7 +143,7 @@ def raise_contract_logic_error_on_revert(response: RPCResponse) -> RPCResponse:
|
|
|
140
143
|
"""
|
|
141
144
|
error = response.get("error")
|
|
142
145
|
if error is None or isinstance(error, str):
|
|
143
|
-
raise
|
|
146
|
+
raise Web3ValueError(error)
|
|
144
147
|
|
|
145
148
|
message = error.get("message")
|
|
146
149
|
message_present = message is not None and message != ""
|
|
@@ -172,7 +175,6 @@ def raise_transaction_indexing_error_if_indexing(response: RPCResponse) -> RPCRe
|
|
|
172
175
|
Raise an error if ``eth_getTransactionReceipt`` returns an error indicating that
|
|
173
176
|
transactions are still being indexed.
|
|
174
177
|
"""
|
|
175
|
-
|
|
176
178
|
error = response.get("error")
|
|
177
179
|
if not isinstance(error, str) and error is not None:
|
|
178
180
|
message = error.get("message")
|
web3/_utils/events.py
CHANGED
|
@@ -29,6 +29,7 @@ from eth_abi.codec import (
|
|
|
29
29
|
from eth_typing import (
|
|
30
30
|
ChecksumAddress,
|
|
31
31
|
HexStr,
|
|
32
|
+
Primitives,
|
|
32
33
|
TypeStr,
|
|
33
34
|
)
|
|
34
35
|
from eth_utils import (
|
|
@@ -75,6 +76,7 @@ from web3.exceptions import (
|
|
|
75
76
|
InvalidEventABI,
|
|
76
77
|
LogTopicError,
|
|
77
78
|
MismatchedABI,
|
|
79
|
+
Web3ValueError,
|
|
78
80
|
)
|
|
79
81
|
from web3.types import (
|
|
80
82
|
ABIEvent,
|
|
@@ -99,6 +101,12 @@ if TYPE_CHECKING:
|
|
|
99
101
|
)
|
|
100
102
|
|
|
101
103
|
|
|
104
|
+
def _log_entry_data_to_bytes(
|
|
105
|
+
log_entry_data: Union[Primitives, HexStr, str],
|
|
106
|
+
) -> bytes:
|
|
107
|
+
return hexstr_if_str(to_bytes, log_entry_data)
|
|
108
|
+
|
|
109
|
+
|
|
102
110
|
def construct_event_topic_set(
|
|
103
111
|
event_abi: ABIEvent,
|
|
104
112
|
abi_codec: ABICodec,
|
|
@@ -108,7 +116,7 @@ def construct_event_topic_set(
|
|
|
108
116
|
arguments = {}
|
|
109
117
|
if isinstance(arguments, (list, tuple)):
|
|
110
118
|
if len(arguments) != len(event_abi["inputs"]):
|
|
111
|
-
raise
|
|
119
|
+
raise Web3ValueError(
|
|
112
120
|
"When passing an argument list, the number of arguments must "
|
|
113
121
|
"match the event constructor."
|
|
114
122
|
)
|
|
@@ -123,9 +131,7 @@ def construct_event_topic_set(
|
|
|
123
131
|
for key, value in arguments.items() # type: ignore
|
|
124
132
|
}
|
|
125
133
|
|
|
126
|
-
|
|
127
|
-
# https://github.com/python/mypy/issues/4976
|
|
128
|
-
event_topic = encode_hex(event_abi_to_log_topic(event_abi)) # type: ignore
|
|
134
|
+
event_topic = encode_hex(event_abi_to_log_topic(event_abi))
|
|
129
135
|
indexed_args = get_indexed_event_inputs(event_abi)
|
|
130
136
|
zipped_abi_and_args = [
|
|
131
137
|
(arg, normalized_args.get(arg["name"], [None])) for arg in indexed_args
|
|
@@ -155,7 +161,7 @@ def construct_event_data_set(
|
|
|
155
161
|
arguments = {}
|
|
156
162
|
if isinstance(arguments, (list, tuple)):
|
|
157
163
|
if len(arguments) != len(event_abi["inputs"]):
|
|
158
|
-
raise
|
|
164
|
+
raise Web3ValueError(
|
|
159
165
|
"When passing an argument list, the number of arguments must "
|
|
160
166
|
"match the event constructor."
|
|
161
167
|
)
|
|
@@ -228,23 +234,25 @@ def get_event_data(
|
|
|
228
234
|
log_topics = log_entry["topics"]
|
|
229
235
|
elif not log_entry["topics"]:
|
|
230
236
|
raise MismatchedABI("Expected non-anonymous event to have 1 or more topics")
|
|
231
|
-
|
|
232
|
-
|
|
237
|
+
elif event_abi_to_log_topic(dict(event_abi)) != _log_entry_data_to_bytes(
|
|
238
|
+
log_entry["topics"][0]
|
|
239
|
+
):
|
|
233
240
|
raise MismatchedABI("The event signature did not match the provided ABI")
|
|
234
241
|
else:
|
|
235
242
|
log_topics = log_entry["topics"][1:]
|
|
236
243
|
|
|
244
|
+
log_topics_bytes = [_log_entry_data_to_bytes(topic) for topic in log_topics]
|
|
237
245
|
log_topics_abi = get_indexed_event_inputs(event_abi)
|
|
238
246
|
log_topic_normalized_inputs = normalize_event_input_types(log_topics_abi)
|
|
239
247
|
log_topic_types = get_event_abi_types_for_decoding(log_topic_normalized_inputs)
|
|
240
248
|
log_topic_names = get_abi_input_names(ABIEvent({"inputs": log_topics_abi}))
|
|
241
249
|
|
|
242
|
-
if len(
|
|
250
|
+
if len(log_topics_bytes) != len(log_topic_types):
|
|
243
251
|
raise LogTopicError(
|
|
244
|
-
f"Expected {len(log_topic_types)} log topics. Got {len(
|
|
252
|
+
f"Expected {len(log_topic_types)} log topics. Got {len(log_topics_bytes)}"
|
|
245
253
|
)
|
|
246
254
|
|
|
247
|
-
log_data =
|
|
255
|
+
log_data = _log_entry_data_to_bytes(log_entry["data"])
|
|
248
256
|
log_data_abi = exclude_indexed_event_inputs(event_abi)
|
|
249
257
|
log_data_normalized_inputs = normalize_event_input_types(log_data_abi)
|
|
250
258
|
log_data_types = get_event_abi_types_for_decoding(log_data_normalized_inputs)
|
|
@@ -270,7 +278,7 @@ def get_event_data(
|
|
|
270
278
|
|
|
271
279
|
decoded_topic_data = [
|
|
272
280
|
abi_codec.decode([topic_type], topic_data)[0]
|
|
273
|
-
for topic_type, topic_data in zip(log_topic_types,
|
|
281
|
+
for topic_type, topic_data in zip(log_topic_types, log_topics_bytes)
|
|
274
282
|
]
|
|
275
283
|
normalized_topic_data = map_abi_data(
|
|
276
284
|
BASE_RETURN_NORMALIZERS, log_topic_types, decoded_topic_data
|
|
@@ -361,7 +369,7 @@ class BaseEventFilterBuilder:
|
|
|
361
369
|
if self._fromBlock is None and not self._immutable:
|
|
362
370
|
self._fromBlock = value
|
|
363
371
|
else:
|
|
364
|
-
raise
|
|
372
|
+
raise Web3ValueError(
|
|
365
373
|
f"fromBlock is already set to {self._fromBlock!r}. "
|
|
366
374
|
"Resetting filter parameters is not permitted"
|
|
367
375
|
)
|
|
@@ -375,7 +383,7 @@ class BaseEventFilterBuilder:
|
|
|
375
383
|
if self._toBlock is None and not self._immutable:
|
|
376
384
|
self._toBlock = value
|
|
377
385
|
else:
|
|
378
|
-
raise
|
|
386
|
+
raise Web3ValueError(
|
|
379
387
|
f"toBlock is already set to {self._toBlock!r}. "
|
|
380
388
|
"Resetting filter parameters is not permitted"
|
|
381
389
|
)
|
|
@@ -389,7 +397,7 @@ class BaseEventFilterBuilder:
|
|
|
389
397
|
if self._address is None and not self._immutable:
|
|
390
398
|
self._address = value
|
|
391
399
|
else:
|
|
392
|
-
raise
|
|
400
|
+
raise Web3ValueError(
|
|
393
401
|
f"address is already set to {self.address!r}. "
|
|
394
402
|
"Resetting filter parameters is not permitted"
|
|
395
403
|
)
|
|
@@ -434,9 +442,9 @@ class BaseEventFilterBuilder:
|
|
|
434
442
|
class EventFilterBuilder(BaseEventFilterBuilder):
|
|
435
443
|
def deploy(self, w3: "Web3") -> "LogFilter":
|
|
436
444
|
if not isinstance(w3, web3.Web3):
|
|
437
|
-
raise
|
|
445
|
+
raise Web3ValueError(f"Invalid web3 argument: got: {w3!r}")
|
|
438
446
|
|
|
439
|
-
for arg in AttributeDict.values(self.args):
|
|
447
|
+
for arg in AttributeDict.values(self.args):
|
|
440
448
|
arg._immutable = True # type: ignore[attr-defined]
|
|
441
449
|
self._immutable = True
|
|
442
450
|
|
|
@@ -452,9 +460,9 @@ class EventFilterBuilder(BaseEventFilterBuilder):
|
|
|
452
460
|
class AsyncEventFilterBuilder(BaseEventFilterBuilder):
|
|
453
461
|
async def deploy(self, async_w3: "AsyncWeb3") -> "AsyncLogFilter":
|
|
454
462
|
if not isinstance(async_w3, web3.AsyncWeb3):
|
|
455
|
-
raise
|
|
463
|
+
raise Web3ValueError(f"Invalid web3 argument: got: {async_w3!r}")
|
|
456
464
|
|
|
457
|
-
for arg in AttributeDict.values(self.args):
|
|
465
|
+
for arg in AttributeDict.values(self.args):
|
|
458
466
|
arg._immutable = True # type: ignore[attr-defined]
|
|
459
467
|
self._immutable = True
|
|
460
468
|
|
|
@@ -470,8 +478,7 @@ class AsyncEventFilterBuilder(BaseEventFilterBuilder):
|
|
|
470
478
|
|
|
471
479
|
def initialize_event_topics(event_abi: ABIEvent) -> Union[bytes, List[Any]]:
|
|
472
480
|
if event_abi["anonymous"] is False:
|
|
473
|
-
|
|
474
|
-
return event_abi_to_log_topic(event_abi) # type: ignore
|
|
481
|
+
return event_abi_to_log_topic(event_abi)
|
|
475
482
|
else:
|
|
476
483
|
return list()
|
|
477
484
|
|
|
@@ -510,19 +517,23 @@ class BaseArgumentFilter(ABC):
|
|
|
510
517
|
|
|
511
518
|
def match_single(self, value: Any) -> None:
|
|
512
519
|
if self._immutable:
|
|
513
|
-
raise
|
|
520
|
+
raise Web3ValueError(
|
|
521
|
+
"Setting values is forbidden after filter is deployed."
|
|
522
|
+
)
|
|
514
523
|
if self._match_values is None:
|
|
515
524
|
self._match_values = _normalize_match_values((value,))
|
|
516
525
|
else:
|
|
517
|
-
raise
|
|
526
|
+
raise Web3ValueError("An argument match value/s has already been set.")
|
|
518
527
|
|
|
519
528
|
def match_any(self, *values: Collection[Any]) -> None:
|
|
520
529
|
if self._immutable:
|
|
521
|
-
raise
|
|
530
|
+
raise Web3ValueError(
|
|
531
|
+
"Setting values is forbidden after filter is deployed."
|
|
532
|
+
)
|
|
522
533
|
if self._match_values is None:
|
|
523
534
|
self._match_values = _normalize_match_values(values)
|
|
524
535
|
else:
|
|
525
|
-
raise
|
|
536
|
+
raise Web3ValueError("An argument match value/s has already been set.")
|
|
526
537
|
|
|
527
538
|
@property
|
|
528
539
|
@abstractmethod
|
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)
|
|
49
49
|
return _fee_history_priority_fee_estimate(fee_history)
|
|
50
50
|
|
|
51
51
|
|
|
@@ -53,7 +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(
|
|
57
|
-
*PRIORITY_FEE_HISTORY_PARAMS # type: ignore
|
|
58
|
-
)
|
|
56
|
+
fee_history = await async_eth.fee_history(*PRIORITY_FEE_HISTORY_PARAMS)
|
|
59
57
|
return _fee_history_priority_fee_estimate(fee_history)
|
web3/_utils/filters.py
CHANGED
|
@@ -50,7 +50,9 @@ from web3._utils.validation import (
|
|
|
50
50
|
validate_address,
|
|
51
51
|
)
|
|
52
52
|
from web3.exceptions import (
|
|
53
|
+
Web3TypeError,
|
|
53
54
|
Web3ValidationError,
|
|
55
|
+
Web3ValueError,
|
|
54
56
|
)
|
|
55
57
|
from web3.types import (
|
|
56
58
|
ABIEvent,
|
|
@@ -82,15 +84,14 @@ def construct_event_filter_params(
|
|
|
82
84
|
|
|
83
85
|
if topics is not None:
|
|
84
86
|
if len(topic_set) > 1:
|
|
85
|
-
raise
|
|
87
|
+
raise Web3TypeError(
|
|
86
88
|
"Merging the topics argument with topics generated "
|
|
87
89
|
"from argument_filters is not supported."
|
|
88
90
|
)
|
|
89
91
|
topic_set = topics
|
|
90
92
|
|
|
91
93
|
if len(topic_set) == 1 and is_list_like(topic_set[0]):
|
|
92
|
-
|
|
93
|
-
filter_params["topics"] = topic_set[0] # type: ignore
|
|
94
|
+
filter_params["topics"] = topic_set[0]
|
|
94
95
|
else:
|
|
95
96
|
filter_params["topics"] = topic_set
|
|
96
97
|
|
|
@@ -104,7 +105,7 @@ def construct_event_filter_params(
|
|
|
104
105
|
else [address]
|
|
105
106
|
)
|
|
106
107
|
else:
|
|
107
|
-
raise
|
|
108
|
+
raise Web3ValueError(
|
|
108
109
|
f"Unsupported type for `address` parameter: {type(address)}"
|
|
109
110
|
)
|
|
110
111
|
elif address:
|
|
@@ -178,7 +179,7 @@ class BaseFilter:
|
|
|
178
179
|
class Filter(BaseFilter):
|
|
179
180
|
def __init__(self, filter_id: HexStr, eth_module: "Eth") -> None:
|
|
180
181
|
self.eth_module = eth_module
|
|
181
|
-
super(
|
|
182
|
+
super().__init__(filter_id)
|
|
182
183
|
|
|
183
184
|
def get_new_entries(self) -> List[LogReceipt]:
|
|
184
185
|
log_entries = self._filter_valid_entries(
|
|
@@ -196,7 +197,7 @@ class Filter(BaseFilter):
|
|
|
196
197
|
class AsyncFilter(BaseFilter):
|
|
197
198
|
def __init__(self, filter_id: HexStr, eth_module: "AsyncEth") -> None:
|
|
198
199
|
self.eth_module = eth_module
|
|
199
|
-
super(
|
|
200
|
+
super().__init__(filter_id)
|
|
200
201
|
|
|
201
202
|
async def get_new_entries(self) -> List[LogReceipt]:
|
|
202
203
|
filter_changes = await self.eth_module.get_filter_changes(self.filter_id)
|
|
@@ -250,7 +251,8 @@ class LogFilter(Filter):
|
|
|
250
251
|
def set_data_filters(
|
|
251
252
|
self, data_filter_set: Collection[Tuple[TypeStr, Any]]
|
|
252
253
|
) -> None:
|
|
253
|
-
"""
|
|
254
|
+
"""
|
|
255
|
+
Sets the data filters (non indexed argument filters)
|
|
254
256
|
|
|
255
257
|
Expects a set of tuples with the type and value, e.g.:
|
|
256
258
|
(('uint256', [12345, 54321]), ('string', ('a-single-string',)))
|
|
@@ -292,7 +294,8 @@ class AsyncLogFilter(AsyncFilter):
|
|
|
292
294
|
def set_data_filters(
|
|
293
295
|
self, data_filter_set: Collection[Tuple[TypeStr, Any]]
|
|
294
296
|
) -> None:
|
|
295
|
-
"""
|
|
297
|
+
"""
|
|
298
|
+
Sets the data filters (non indexed argument filters)
|
|
296
299
|
|
|
297
300
|
Expects a set of tuples with the type and value, e.g.:
|
|
298
301
|
(('uint256', [12345, 54321]), ('string', ('a-single-string',)))
|
|
@@ -318,7 +321,8 @@ normalize_to_text = apply_formatter_if(not_text, decode_utf8_bytes)
|
|
|
318
321
|
|
|
319
322
|
|
|
320
323
|
def normalize_data_values(type_string: TypeStr, data_value: Any) -> Any:
|
|
321
|
-
"""
|
|
324
|
+
"""
|
|
325
|
+
Decodes utf-8 bytes to strings for abi string values.
|
|
322
326
|
|
|
323
327
|
eth-abi v1 returns utf-8 bytes for string values.
|
|
324
328
|
This can be removed once eth-abi v2 is required.
|
|
@@ -326,7 +330,7 @@ def normalize_data_values(type_string: TypeStr, data_value: Any) -> Any:
|
|
|
326
330
|
_type = parse_type_string(type_string)
|
|
327
331
|
if _type.base == "string":
|
|
328
332
|
if _type.arrlist is not None:
|
|
329
|
-
return tuple(
|
|
333
|
+
return tuple(normalize_to_text(value) for value in data_value)
|
|
330
334
|
else:
|
|
331
335
|
return normalize_to_text(data_value)
|
|
332
336
|
return data_value
|
|
@@ -336,7 +340,8 @@ def normalize_data_values(type_string: TypeStr, data_value: Any) -> Any:
|
|
|
336
340
|
def match_fn(
|
|
337
341
|
codec: ABICodec, match_values_and_abi: Collection[Tuple[str, Any]], data: Any
|
|
338
342
|
) -> bool:
|
|
339
|
-
"""
|
|
343
|
+
"""
|
|
344
|
+
Match function used for filtering non-indexed event arguments.
|
|
340
345
|
|
|
341
346
|
Values provided through the match_values_and_abi parameter are
|
|
342
347
|
compared to the abi decoded log data.
|
|
@@ -352,7 +357,7 @@ def match_fn(
|
|
|
352
357
|
normalized_data = normalize_data_values(abi_type, data_value)
|
|
353
358
|
for value in match_values:
|
|
354
359
|
if not codec.is_encodable(abi_type, value):
|
|
355
|
-
raise
|
|
360
|
+
raise Web3ValueError(
|
|
356
361
|
f"Value {value} is of the wrong abi type. "
|
|
357
362
|
f"Expected {abi_type} typed value."
|
|
358
363
|
)
|
web3/_utils/formatters.py
CHANGED
|
@@ -114,13 +114,13 @@ def apply_key_map(
|
|
|
114
114
|
def is_array_of_strings(value: Any) -> bool:
|
|
115
115
|
if not is_list_like(value):
|
|
116
116
|
return False
|
|
117
|
-
return all(
|
|
117
|
+
return all(is_string(item) for item in value)
|
|
118
118
|
|
|
119
119
|
|
|
120
120
|
def is_array_of_dicts(value: Any) -> bool:
|
|
121
121
|
if not is_list_like(value):
|
|
122
122
|
return False
|
|
123
|
-
return all(
|
|
123
|
+
return all(is_dict(item) for item in value)
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
@curry
|
web3/_utils/math.py
CHANGED
|
@@ -5,6 +5,7 @@ from typing import (
|
|
|
5
5
|
|
|
6
6
|
from web3.exceptions import (
|
|
7
7
|
InsufficientData,
|
|
8
|
+
Web3ValueError,
|
|
8
9
|
)
|
|
9
10
|
|
|
10
11
|
|
|
@@ -17,23 +18,21 @@ def percentile(
|
|
|
17
18
|
f"Expected a sequence of at least 1 integers, got {values!r}"
|
|
18
19
|
)
|
|
19
20
|
if percentile is None:
|
|
20
|
-
raise
|
|
21
|
+
raise Web3ValueError(f"Expected a percentile choice, got {percentile}")
|
|
22
|
+
if percentile < 0 or percentile > 100:
|
|
23
|
+
raise Web3ValueError("percentile must be in the range [0, 100]")
|
|
21
24
|
|
|
22
25
|
sorted_values = sorted(values)
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
if
|
|
26
|
-
|
|
27
|
-
if index < 0:
|
|
28
|
-
return sorted_values[0]
|
|
29
|
-
else:
|
|
30
|
-
index = rank
|
|
27
|
+
index = len(values) * percentile / 100 - 1
|
|
28
|
+
if index < 0:
|
|
29
|
+
return sorted_values[0]
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
fractional = index % 1
|
|
32
|
+
if fractional == 0:
|
|
33
33
|
return sorted_values[int(index)]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return lower + fractional * (higher - lower)
|
|
34
|
+
|
|
35
|
+
integer = int(index - fractional)
|
|
36
|
+
lower = sorted_values[integer]
|
|
37
|
+
higher = sorted_values[integer + 1]
|
|
38
|
+
return lower + fractional * (higher - lower)
|
web3/_utils/method_formatters.py
CHANGED
|
@@ -99,6 +99,8 @@ from web3.datastructures import (
|
|
|
99
99
|
from web3.exceptions import (
|
|
100
100
|
BlockNotFound,
|
|
101
101
|
TransactionNotFound,
|
|
102
|
+
Web3TypeError,
|
|
103
|
+
Web3ValueError,
|
|
102
104
|
)
|
|
103
105
|
from web3.types import (
|
|
104
106
|
BlockIdentifier,
|
|
@@ -136,7 +138,7 @@ def to_hexbytes(
|
|
|
136
138
|
if isinstance(val, (str, int, bytes)):
|
|
137
139
|
result = HexBytes(val)
|
|
138
140
|
else:
|
|
139
|
-
raise
|
|
141
|
+
raise Web3TypeError(f"Cannot convert {val!r} to HexBytes")
|
|
140
142
|
|
|
141
143
|
extra_bytes = len(result) - num_bytes
|
|
142
144
|
if extra_bytes == 0 or (variable_length and extra_bytes < 0):
|
|
@@ -144,7 +146,7 @@ def to_hexbytes(
|
|
|
144
146
|
elif all(byte == 0 for byte in result[:extra_bytes]):
|
|
145
147
|
return HexBytes(result[extra_bytes:])
|
|
146
148
|
else:
|
|
147
|
-
raise
|
|
149
|
+
raise Web3ValueError(
|
|
148
150
|
f"The value {result!r} is {len(result)} bytes, but should be {num_bytes}"
|
|
149
151
|
)
|
|
150
152
|
|
|
@@ -177,9 +179,9 @@ def type_aware_apply_formatters_to_dict_keys_and_values(
|
|
|
177
179
|
"""
|
|
178
180
|
Preserve ``AttributeDict`` types if original ``value`` was an ``AttributeDict``.
|
|
179
181
|
"""
|
|
180
|
-
formatted_dict =
|
|
181
|
-
|
|
182
|
-
|
|
182
|
+
formatted_dict = {
|
|
183
|
+
key_formatters(k): value_formatters(v) for k, v in dict_like_object.items()
|
|
184
|
+
}
|
|
183
185
|
return (
|
|
184
186
|
AttributeDict.recursive(formatted_dict)
|
|
185
187
|
if is_attrdict(dict_like_object)
|
|
@@ -233,6 +235,10 @@ TRANSACTION_RESULT_FORMATTERS = {
|
|
|
233
235
|
),
|
|
234
236
|
"input": HexBytes,
|
|
235
237
|
"data": HexBytes, # Nethermind, for example, returns both `input` and `data`
|
|
238
|
+
"maxFeePerBlobGas": to_integer_if_hex,
|
|
239
|
+
"blobVersionedHashes": apply_formatter_if(
|
|
240
|
+
is_not_null, apply_formatter_to_array(to_hexbytes(32))
|
|
241
|
+
),
|
|
236
242
|
}
|
|
237
243
|
|
|
238
244
|
|
|
@@ -281,6 +287,8 @@ RECEIPT_FORMATTERS = {
|
|
|
281
287
|
"to": apply_formatter_if(is_address, to_checksum_address),
|
|
282
288
|
"effectiveGasPrice": to_integer_if_hex,
|
|
283
289
|
"type": to_integer_if_hex,
|
|
290
|
+
"blobGasPrice": to_integer_if_hex,
|
|
291
|
+
"blobGasUsed": to_integer_if_hex,
|
|
284
292
|
}
|
|
285
293
|
|
|
286
294
|
|
|
@@ -419,7 +427,22 @@ filter_result_formatter = apply_one_of_formatters(
|
|
|
419
427
|
)
|
|
420
428
|
)
|
|
421
429
|
|
|
430
|
+
ACCESS_LIST_REQUEST_FORMATTER = type_aware_apply_formatters_to_dict(
|
|
431
|
+
{
|
|
432
|
+
"accessList": apply_formatter_if(
|
|
433
|
+
is_not_null,
|
|
434
|
+
apply_list_to_array_formatter(
|
|
435
|
+
apply_formatters_to_dict(
|
|
436
|
+
{
|
|
437
|
+
"storageKeys": apply_list_to_array_formatter(to_hex_if_bytes),
|
|
438
|
+
}
|
|
439
|
+
)
|
|
440
|
+
),
|
|
441
|
+
),
|
|
442
|
+
}
|
|
443
|
+
)
|
|
422
444
|
transaction_param_formatter = compose(
|
|
445
|
+
ACCESS_LIST_REQUEST_FORMATTER,
|
|
423
446
|
remove_key_if("to", lambda txn: txn["to"] in {"", b"", None}),
|
|
424
447
|
remove_key_if("gasPrice", lambda txn: txn["gasPrice"] in {"", b"", None}),
|
|
425
448
|
)
|
|
@@ -516,6 +539,7 @@ PYTHONIC_REQUEST_FORMATTERS: Dict[RPCEndpoint, Callable[..., Any]] = {
|
|
|
516
539
|
),
|
|
517
540
|
RPC.eth_getBalance: apply_formatter_at_index(to_hex_if_integer, 1),
|
|
518
541
|
RPC.eth_getBlockByNumber: apply_formatter_at_index(to_hex_if_integer, 0),
|
|
542
|
+
RPC.eth_getBlockReceipts: apply_formatter_at_index(to_hex_if_integer, 0),
|
|
519
543
|
RPC.eth_getBlockTransactionCountByNumber: apply_formatter_at_index(
|
|
520
544
|
to_hex_if_integer,
|
|
521
545
|
0,
|
|
@@ -723,6 +747,7 @@ PYTHONIC_RESULT_FORMATTERS: Dict[RPCEndpoint, Callable[..., Any]] = {
|
|
|
723
747
|
RPC.eth_getBalance: to_integer_if_hex,
|
|
724
748
|
RPC.eth_getBlockByHash: apply_formatter_if(is_not_null, block_formatter),
|
|
725
749
|
RPC.eth_getBlockByNumber: apply_formatter_if(is_not_null, block_formatter),
|
|
750
|
+
RPC.eth_getBlockReceipts: apply_formatter_to_array(receipt_formatter),
|
|
726
751
|
RPC.eth_getBlockTransactionCountByHash: to_integer_if_hex,
|
|
727
752
|
RPC.eth_getBlockTransactionCountByNumber: to_integer_if_hex,
|
|
728
753
|
RPC.eth_getCode: HexBytes,
|
|
@@ -900,6 +925,7 @@ def raise_transaction_not_found_with_index(
|
|
|
900
925
|
NULL_RESULT_FORMATTERS: Dict[RPCEndpoint, Callable[..., Any]] = {
|
|
901
926
|
RPC.eth_getBlockByHash: raise_block_not_found,
|
|
902
927
|
RPC.eth_getBlockByNumber: raise_block_not_found,
|
|
928
|
+
RPC.eth_getBlockReceipts: raise_block_not_found,
|
|
903
929
|
RPC.eth_getBlockTransactionCountByHash: raise_block_not_found,
|
|
904
930
|
RPC.eth_getBlockTransactionCountByNumber: raise_block_not_found,
|
|
905
931
|
RPC.eth_getUncleCountByBlockHash: raise_block_not_found,
|
web3/_utils/module.py
CHANGED
|
@@ -13,6 +13,7 @@ from typing import (
|
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
from web3.exceptions import (
|
|
16
|
+
Web3AttributeError,
|
|
16
17
|
Web3ValidationError,
|
|
17
18
|
)
|
|
18
19
|
from web3.module import (
|
|
@@ -50,7 +51,7 @@ def attach_modules(
|
|
|
50
51
|
module_class = module_info[0] if module_info_is_list_like else module_info
|
|
51
52
|
|
|
52
53
|
if hasattr(parent_module, module_name):
|
|
53
|
-
raise
|
|
54
|
+
raise Web3AttributeError(
|
|
54
55
|
f"Cannot set {parent_module} module named '{module_name}'. "
|
|
55
56
|
" The web3 object already has an attribute with that name"
|
|
56
57
|
)
|