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.
Files changed (83) hide show
  1. ens/_normalization.py +1 -3
  2. ens/async_ens.py +14 -11
  3. ens/contract_data.py +2 -2
  4. ens/ens.py +10 -7
  5. ens/exceptions.py +19 -27
  6. ens/specs/nf.json +1 -1
  7. ens/specs/normalization_spec.json +1 -1
  8. ens/utils.py +24 -15
  9. web3/__init__.py +2 -7
  10. web3/_utils/abi.py +30 -29
  11. web3/_utils/async_transactions.py +7 -4
  12. web3/_utils/blocks.py +6 -2
  13. web3/_utils/caching.py +7 -3
  14. web3/_utils/compat/__init__.py +0 -3
  15. web3/_utils/contract_sources/compile_contracts.py +1 -1
  16. web3/_utils/contracts.py +12 -12
  17. web3/_utils/datatypes.py +5 -1
  18. web3/_utils/decorators.py +6 -1
  19. web3/_utils/empty.py +1 -1
  20. web3/_utils/encoding.py +15 -10
  21. web3/_utils/error_formatters_utils.py +5 -3
  22. web3/_utils/events.py +35 -24
  23. web3/_utils/fee_utils.py +2 -4
  24. web3/_utils/filters.py +17 -12
  25. web3/_utils/formatters.py +2 -2
  26. web3/_utils/math.py +14 -15
  27. web3/_utils/method_formatters.py +31 -5
  28. web3/_utils/module.py +2 -1
  29. web3/_utils/module_testing/eth_module.py +129 -75
  30. web3/_utils/module_testing/go_ethereum_personal_module.py +1 -1
  31. web3/_utils/module_testing/module_testing_utils.py +1 -3
  32. web3/_utils/module_testing/utils.py +14 -7
  33. web3/_utils/normalizers.py +3 -3
  34. web3/_utils/request.py +4 -4
  35. web3/_utils/rpc_abi.py +6 -1
  36. web3/_utils/threads.py +8 -7
  37. web3/_utils/transactions.py +18 -12
  38. web3/_utils/type_conversion.py +5 -1
  39. web3/_utils/validation.py +12 -10
  40. web3/contract/async_contract.py +12 -7
  41. web3/contract/base_contract.py +51 -57
  42. web3/contract/contract.py +12 -6
  43. web3/contract/utils.py +11 -6
  44. web3/datastructures.py +22 -12
  45. web3/eth/async_eth.py +53 -30
  46. web3/eth/base_eth.py +7 -3
  47. web3/eth/eth.py +31 -14
  48. web3/exceptions.py +41 -59
  49. web3/gas_strategies/time_based.py +2 -4
  50. web3/geth.py +1 -3
  51. web3/main.py +6 -2
  52. web3/manager.py +13 -12
  53. web3/method.py +13 -5
  54. web3/middleware/base.py +4 -2
  55. web3/middleware/filter.py +27 -17
  56. web3/middleware/formatting.py +6 -3
  57. web3/middleware/names.py +4 -1
  58. web3/middleware/signing.py +6 -2
  59. web3/middleware/stalecheck.py +2 -1
  60. web3/providers/eth_tester/defaults.py +1 -1
  61. web3/providers/eth_tester/main.py +5 -4
  62. web3/providers/eth_tester/middleware.py +10 -1
  63. web3/providers/ipc.py +7 -3
  64. web3/providers/persistent/async_ipc.py +6 -7
  65. web3/providers/persistent/persistent.py +12 -2
  66. web3/providers/persistent/request_processor.py +10 -12
  67. web3/providers/persistent/websocket.py +3 -3
  68. web3/providers/rpc/async_rpc.py +23 -6
  69. web3/providers/rpc/rpc.py +27 -16
  70. web3/testing.py +4 -4
  71. web3/tools/benchmark/__init__.py +0 -0
  72. web3/tools/benchmark/main.py +189 -0
  73. web3/tools/benchmark/node.py +126 -0
  74. web3/tools/benchmark/reporting.py +39 -0
  75. web3/tools/benchmark/utils.py +69 -0
  76. web3/tracing.py +9 -5
  77. web3/types.py +23 -22
  78. web3/utils/caching.py +2 -4
  79. {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/METADATA +13 -26
  80. {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/RECORD +83 -78
  81. {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/LICENSE +0 -0
  82. {web3-7.0.0b2.dist-info → web3-7.0.0b4.dist-info}/WHEEL +0 -0
  83. {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 ValueError(f"Unsupported ABI type: {abi_type}")
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 ValueError(
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 TypeError(
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 TypeError(
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 TypeError(f"Could not encode to JSON: {exc}")
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 ValueError(f"expected value of size 4 bytes. Got: {len(byte_str)} bytes")
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
- class DynamicArrayPackedEncoder(BaseArrayEncoder):
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("Could not decode revert reason as UTF-8", RuntimeWarning)
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 ValueError(error)
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 ValueError(
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
- # typed dict cannot be used w/ a normal Dict
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 ValueError(
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
- # type ignored b/c event_abi_to_log_topic(event_abi: Dict[str, Any])
232
- elif event_abi_to_log_topic(event_abi) != log_entry["topics"][0]: # type: ignore
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(log_topics) != len(log_topic_types):
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(log_topics)}"
252
+ f"Expected {len(log_topic_types)} log topics. Got {len(log_topics_bytes)}"
245
253
  )
246
254
 
247
- log_data = hexstr_if_str(to_bytes, log_entry["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, log_topics)
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 ValueError(
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 ValueError(
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 ValueError(
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 ValueError(f"Invalid web3 argument: got: {w3!r}")
445
+ raise Web3ValueError(f"Invalid web3 argument: got: {w3!r}")
438
446
 
439
- for arg in AttributeDict.values(self.args): # type: ignore[arg-type]
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 ValueError(f"Invalid web3 argument: got: {async_w3!r}")
463
+ raise Web3ValueError(f"Invalid web3 argument: got: {async_w3!r}")
456
464
 
457
- for arg in AttributeDict.values(self.args): # type: ignore[arg-type]
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
- # https://github.com/python/mypy/issues/4976
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 ValueError("Setting values is forbidden after filter is deployed.")
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 ValueError("An argument match value/s has already been set.")
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 ValueError("Setting values is forbidden after filter is deployed.")
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 ValueError("An argument match value/s has already been set.")
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) # type: ignore
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 TypeError(
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
- # type ignored b/c list-like check on line 88
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 ValueError(
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(Filter, self).__init__(filter_id)
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(AsyncFilter, self).__init__(filter_id)
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
- """Sets the data filters (non indexed argument filters)
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
- """Sets the data filters (non indexed argument filters)
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
- """Decodes utf-8 bytes to strings for abi string values.
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((normalize_to_text(value) for value in data_value))
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
- """Match function used for filtering non-indexed event arguments.
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 ValueError(
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((is_string(item) for item in value))
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((is_dict(item) for item in value))
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 ValueError(f"Expected a percentile choice, got {percentile}")
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
- rank = len(values) * percentile / 100
25
- if rank > 0:
26
- index = rank - 1
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
- if index % 1 == 0:
31
+ fractional = index % 1
32
+ if fractional == 0:
33
33
  return sorted_values[int(index)]
34
- else:
35
- fractional = index % 1
36
- integer = int(index - fractional)
37
- lower = sorted_values[integer]
38
- higher = sorted_values[integer + 1]
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)
@@ -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 TypeError(f"Cannot convert {val!r} to HexBytes")
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 ValueError(
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 = dict(
181
- (key_formatters(k), value_formatters(v)) for k, v in dict_like_object.items()
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 AttributeError(
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
  )