web3 7.4.0__py3-none-any.whl → 7.6.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.
Files changed (46) hide show
  1. web3/_utils/abi.py +59 -1
  2. web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
  3. web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
  4. web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
  5. web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
  6. web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
  7. web3/_utils/contract_sources/contract_data/event_contracts.py +50 -5
  8. web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
  9. web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
  10. web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
  11. web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
  12. web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
  13. web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
  14. web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
  15. web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
  16. web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
  17. web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
  18. web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
  19. web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
  20. web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
  21. web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
  22. web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
  23. web3/_utils/contracts.py +48 -7
  24. web3/_utils/method_formatters.py +109 -1
  25. web3/_utils/module_testing/__init__.py +4 -0
  26. web3/_utils/module_testing/eth_module.py +11 -0
  27. web3/_utils/module_testing/go_ethereum_debug_module.py +128 -0
  28. web3/_utils/rpc_abi.py +4 -0
  29. web3/_utils/validation.py +3 -0
  30. web3/contract/async_contract.py +191 -41
  31. web3/contract/base_contract.py +373 -152
  32. web3/contract/contract.py +182 -34
  33. web3/contract/utils.py +51 -2
  34. web3/eth/async_eth.py +11 -0
  35. web3/eth/eth.py +11 -0
  36. web3/geth.py +59 -0
  37. web3/main.py +4 -0
  38. web3/manager.py +10 -0
  39. web3/providers/eth_tester/defaults.py +1 -0
  40. web3/types.py +87 -2
  41. web3/utils/abi.py +308 -76
  42. {web3-7.4.0.dist-info → web3-7.6.0.dist-info}/METADATA +3 -2
  43. {web3-7.4.0.dist-info → web3-7.6.0.dist-info}/RECORD +46 -45
  44. {web3-7.4.0.dist-info → web3-7.6.0.dist-info}/WHEEL +1 -1
  45. {web3-7.4.0.dist-info → web3-7.6.0.dist-info}/LICENSE +0 -0
  46. {web3-7.4.0.dist-info → web3-7.6.0.dist-info}/top_level.txt +0 -0
@@ -246,6 +246,7 @@ API_ENDPOINTS = {
246
246
  "chainId": static_return(131277322940537), # from fixture generation file
247
247
  "feeHistory": call_eth_tester("get_fee_history"),
248
248
  "maxPriorityFeePerGas": static_return(10**9),
249
+ "blobBaseFee": static_return(10**9),
249
250
  "gasPrice": static_return(10**9), # must be >= base fee post-London
250
251
  "accounts": call_eth_tester("get_accounts"),
251
252
  "blockNumber": compose(
web3/types.py CHANGED
@@ -36,8 +36,14 @@ from web3._utils.compat import (
36
36
  )
37
37
 
38
38
  if TYPE_CHECKING:
39
- from web3.contract.async_contract import AsyncContractFunction # noqa: F401
40
- from web3.contract.contract import ContractFunction # noqa: F401
39
+ from web3.contract.async_contract import ( # noqa: F401
40
+ AsyncContractEvent,
41
+ AsyncContractFunction,
42
+ )
43
+ from web3.contract.contract import ( # noqa: F401
44
+ ContractEvent,
45
+ ContractFunction,
46
+ )
41
47
  from web3.main import ( # noqa: F401
42
48
  AsyncWeb3,
43
49
  Web3,
@@ -469,6 +475,84 @@ class TxPoolStatus(TypedDict, total=False):
469
475
  queued: int
470
476
 
471
477
 
478
+ #
479
+ # debug types
480
+ #
481
+ class TraceConfig(TypedDict, total=False):
482
+ disableStorage: bool
483
+ disableStack: bool
484
+ enableMemory: bool
485
+ enableReturnData: bool
486
+ tracer: str
487
+ tracerConfig: Dict[str, Any]
488
+ timeout: int
489
+
490
+
491
+ class CallTraceLog(TypedDict):
492
+ address: ChecksumAddress
493
+ data: HexBytes
494
+ topics: Sequence[HexBytes]
495
+ position: int
496
+
497
+
498
+ # syntax b/c "from" keyword not allowed w/ class construction
499
+ CallTrace = TypedDict(
500
+ "CallTrace",
501
+ {
502
+ "type": str,
503
+ "from": ChecksumAddress,
504
+ "to": ChecksumAddress,
505
+ "value": Wei,
506
+ "gas": int,
507
+ "gasUsed": int,
508
+ "input": HexBytes,
509
+ "output": HexBytes,
510
+ "error": str,
511
+ "revertReason": str,
512
+ "calls": Sequence["CallTrace"],
513
+ "logs": Sequence[CallTraceLog],
514
+ },
515
+ total=False,
516
+ )
517
+
518
+
519
+ class TraceData(TypedDict, total=False):
520
+ balance: int
521
+ nonce: int
522
+ code: str
523
+ storage: Dict[str, str]
524
+
525
+
526
+ class DiffModeTrace(TypedDict):
527
+ post: Dict[ChecksumAddress, TraceData]
528
+ pre: Dict[ChecksumAddress, TraceData]
529
+
530
+
531
+ PrestateTrace = Dict[ChecksumAddress, TraceData]
532
+
533
+
534
+ # 4byte tracer returns something like:
535
+ # { '0x27dc297e-128' : 1 }
536
+ # which is: { 4byte signature - calldata size : # of occurrences of key }
537
+ FourByteTrace = Dict[str, int]
538
+
539
+
540
+ class StructLog(TypedDict):
541
+ pc: int
542
+ op: str
543
+ gas: int
544
+ gasCost: int
545
+ depth: int
546
+ stack: List[HexStr]
547
+
548
+
549
+ class OpcodeTrace(TypedDict, total=False):
550
+ gas: int
551
+ failed: bool
552
+ returnValue: str
553
+ structLogs: List[StructLog]
554
+
555
+
472
556
  #
473
557
  # web3.geth types
474
558
  #
@@ -483,6 +567,7 @@ class GethWallet(TypedDict):
483
567
  # Contract types
484
568
 
485
569
  TContractFn = TypeVar("TContractFn", "ContractFunction", "AsyncContractFunction")
570
+ TContractEvent = TypeVar("TContractEvent", "ContractEvent", "AsyncContractEvent")
486
571
 
487
572
 
488
573
  # Tracing types
web3/utils/abi.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import functools
2
2
  from typing import (
3
3
  Any,
4
+ Callable,
4
5
  Dict,
5
6
  List,
6
7
  Optional,
@@ -47,7 +48,6 @@ from eth_utils.toolz import (
47
48
  )
48
49
  from eth_utils.types import (
49
50
  is_list_like,
50
- is_text,
51
51
  )
52
52
  from hexbytes import (
53
53
  HexBytes,
@@ -55,17 +55,21 @@ from hexbytes import (
55
55
 
56
56
  from web3._utils.abi import (
57
57
  filter_by_argument_name,
58
+ filter_by_argument_type,
59
+ get_abi_element_signature,
60
+ get_name_from_abi_element_identifier,
58
61
  )
59
- from web3._utils.abi_element_identifiers import (
60
- FallbackFn,
61
- ReceiveFn,
62
+ from web3._utils.decorators import (
63
+ deprecated_for,
64
+ )
65
+ from web3._utils.validation import (
66
+ validate_abi,
62
67
  )
63
68
  from web3.exceptions import (
64
69
  ABIConstructorNotFound,
65
70
  ABIFallbackNotFound,
66
71
  ABIReceiveNotFound,
67
72
  MismatchedABI,
68
- Web3TypeError,
69
73
  Web3ValidationError,
70
74
  Web3ValueError,
71
75
  )
@@ -81,9 +85,14 @@ from eth_utils.abi import ( # noqa
81
85
  function_abi_to_4byte_selector,
82
86
  get_aligned_abi_inputs,
83
87
  get_normalized_abi_inputs,
88
+ get_abi_input_types,
84
89
  )
85
90
 
86
91
 
92
+ def _filter_by_signature(signature: str, contract_abi: ABI) -> List[ABIElement]:
93
+ return [abi for abi in contract_abi if abi_to_signature(abi) == signature]
94
+
95
+
87
96
  def _filter_by_argument_count(
88
97
  num_arguments: int, contract_abi: ABI
89
98
  ) -> List[ABIElement]:
@@ -98,9 +107,9 @@ def _filter_by_argument_count(
98
107
 
99
108
  def _filter_by_encodability(
100
109
  abi_codec: codec.ABIEncoder,
110
+ args: Sequence[Any],
111
+ kwargs: Dict[str, Any],
101
112
  contract_abi: ABI,
102
- *args: Optional[Sequence[Any]],
103
- **kwargs: Optional[Dict[str, Any]],
104
113
  ) -> List[ABICallable]:
105
114
  return [
106
115
  cast(ABICallable, function_abi)
@@ -158,13 +167,118 @@ def _get_fallback_function_abi(contract_abi: ABI) -> ABIFallback:
158
167
  raise ABIFallbackNotFound("No fallback function was found in the contract ABI.")
159
168
 
160
169
 
170
+ def _get_any_abi_signature_with_name(element_name: str, contract_abi: ABI) -> str:
171
+ """
172
+ Find an ABI identifier signature by element name. A signature identifier is
173
+ returned, "name(arg1Type,arg2Type,...)".
174
+
175
+ This function forces one result to be returned even if multiple are found.
176
+ If multiple ABIs are found and all contain arguments, the first result is returned.
177
+ Otherwise when one of the ABIs has zero arguments, that signature is returned.
178
+ """
179
+ try:
180
+ # search for function abis with the same name
181
+ function_abi = get_abi_element(
182
+ contract_abi, get_name_from_abi_element_identifier(element_name)
183
+ )
184
+ return abi_to_signature(function_abi)
185
+ except MismatchedABI:
186
+ # If all matching functions have arguments, cannot determine which one
187
+ # to use. Instead of an exception, return the first matching function.
188
+ function_abis = filter_abi_by_name(element_name, contract_abi)
189
+ if len(function_abis) > 0 and all(
190
+ len(get_abi_input_types(fn)) > 0 for fn in function_abis
191
+ ):
192
+ return abi_to_signature(function_abis[0])
193
+
194
+ # Use signature for function that does not take arguments
195
+ return str(get_abi_element_signature(element_name))
196
+
197
+
198
+ def _build_abi_input_error(
199
+ abi: ABI,
200
+ num_args: int,
201
+ *args: Any,
202
+ abi_codec: ABICodec,
203
+ **kwargs: Any,
204
+ ) -> str:
205
+ """
206
+ Build a string representation of the ABI input error.
207
+ """
208
+ errors: Dict[str, str] = dict(
209
+ {
210
+ "zero_args": "",
211
+ "invalid_args": "",
212
+ "encoding": "",
213
+ "unexpected_args": "",
214
+ }
215
+ )
216
+
217
+ for abi_element in abi:
218
+ abi_element_input_types = get_abi_input_types(abi_element)
219
+ abi_signature = abi_to_signature(abi_element)
220
+ abi_element_name = get_name_from_abi_element_identifier(abi_signature)
221
+ types: Tuple[str, ...] = tuple()
222
+ aligned_args: Tuple[Any, ...] = tuple()
223
+
224
+ if len(abi_element_input_types) == num_args:
225
+ if num_args == 0:
226
+ if not errors["zero_args"]:
227
+ errors["zero_args"] += (
228
+ "The provided identifier matches multiple elements.\n"
229
+ f"If you meant to call `{abi_element_name}()`, "
230
+ "please specify the full signature.\n"
231
+ )
232
+
233
+ errors["zero_args"] += (
234
+ f" - signature: {abi_to_signature(abi_element)}, "
235
+ f"type: {abi_element['type']}\n"
236
+ )
237
+ else:
238
+ try:
239
+ arguments = get_normalized_abi_inputs(abi_element, *args, **kwargs)
240
+ types, aligned_args = get_aligned_abi_inputs(abi_element, arguments)
241
+ except TypeError as e:
242
+ errors["invalid_args"] += (
243
+ f"Signature: {abi_signature}, type: {abi_element['type']}\n"
244
+ f"Arguments do not match types in `{abi_signature}`.\n"
245
+ f"Error: {e}\n"
246
+ )
247
+
248
+ argument_errors = ""
249
+ for position, (_type, arg) in enumerate(zip(types, aligned_args), start=1):
250
+ if abi_codec.is_encodable(_type, arg):
251
+ argument_errors += f"Argument {position} value `{arg}` is valid.\n"
252
+ else:
253
+ argument_errors += (
254
+ f"Argument {position} value `{arg}` is not compatible with "
255
+ f"type `{_type}`.\n"
256
+ )
257
+
258
+ if argument_errors != "":
259
+ errors["encoding"] += (
260
+ f"Signature: {abi_signature}, type: {abi_element['type']}\n"
261
+ + argument_errors
262
+ )
263
+
264
+ else:
265
+ errors["unexpected_args"] += (
266
+ f"Signature: {abi_signature}, type: {abi_element['type']}\n"
267
+ f"Expected {len(abi_element_input_types)} argument(s) but received "
268
+ f"{num_args} argument(s).\n"
269
+ )
270
+
271
+ return "".join(errors.values())
272
+
273
+
161
274
  def _mismatched_abi_error_diagnosis(
162
275
  abi_element_identifier: ABIElementIdentifier,
163
- matching_function_signatures: Sequence[str],
164
- arg_count_matches: int,
165
- encoding_matches: int,
166
- *args: Optional[Sequence[Any]],
167
- **kwargs: Optional[Dict[str, Any]],
276
+ abi: ABI,
277
+ num_matches: int = 0,
278
+ num_args: int = 0,
279
+ *args: Optional[Any],
280
+ abi_codec: Optional[Any] = None,
281
+ **kwargs: Optional[Any],
168
282
  ) -> str:
169
283
  """
170
284
  Raise a ``MismatchedABI`` when a function ABI lookup results in an error.
@@ -172,32 +286,59 @@ def _mismatched_abi_error_diagnosis(
172
286
  An error may result from multiple functions matching the provided signature and
173
287
  arguments or no functions are identified.
174
288
  """
175
- diagnosis = "\n"
176
- if arg_count_matches == 0:
177
- diagnosis += "Function invocation failed due to improper number of arguments."
178
- elif encoding_matches == 0:
179
- diagnosis += "Function invocation failed due to no matching argument types."
180
- elif encoding_matches > 1:
181
- diagnosis += (
182
- "Ambiguous argument encoding. "
183
- "Provided arguments can be encoded to multiple functions "
184
- "matching this call."
185
- )
289
+ name = get_name_from_abi_element_identifier(abi_element_identifier)
290
+ abis_matching_names = filter_abi_by_name(name, abi)
291
+ abis_matching_arg_count = [
292
+ abi_to_signature(abi)
293
+ for abi in _filter_by_argument_count(num_args, abis_matching_names)
294
+ ]
295
+ num_abis_matching_arg_count = len(abis_matching_arg_count)
186
296
 
187
- collapsed_args = _extract_argument_types(*args)
188
- collapsed_kwargs = dict(
189
- {(k, _extract_argument_types([v])) for k, v in kwargs.items()}
190
- )
297
+ if abi_codec is None:
298
+ abi_codec = ABICodec(default_registry)
191
299
 
192
- return (
193
- f"\nCould not identify the intended function with name "
194
- f"`{abi_element_identifier}`, positional arguments with type(s) "
195
- f"`({collapsed_args})` and keyword arguments with type(s) "
196
- f"`{collapsed_kwargs}`."
197
- f"\nFound {len(matching_function_signatures)} function(s) with the name "
198
- f"`{abi_element_identifier}`: {matching_function_signatures}{diagnosis}"
300
+ error = "ABI Not Found!\n"
301
+ if num_matches == 0 and num_abis_matching_arg_count == 0:
302
+ error += f"No element named `{name}` with {num_args} argument(s).\n"
303
+ elif num_matches > 1 or num_abis_matching_arg_count > 1:
304
+ error += (
305
+ f"Found multiple elements named `{name}` that accept {num_args} "
306
+ "argument(s).\n"
307
+ )
308
+ elif num_abis_matching_arg_count == 1:
309
+ error += (
310
+ f"Found {num_abis_matching_arg_count} element(s) named `{name}` that "
311
+ f"accept {num_args} argument(s).\n"
312
+ "The provided arguments are not valid.\n"
313
+ )
314
+ elif num_matches == 0:
315
+ error += (
316
+ f"Unable to find an element named `{name}` that matches the provided "
317
+ "identifier and argument types.\n"
318
+ )
319
+ arg_types = _extract_argument_types(*args)
320
+ kwarg_types = dict({(k, _extract_argument_types([v])) for k, v in kwargs.items()})
321
+ error += (
322
+ f"Provided argument types: ({arg_types})\n"
323
+ f"Provided keyword argument types: {kwarg_types}\n\n"
199
324
  )
200
325
 
326
+ if abis_matching_names:
327
+ error += (
328
+ f"Tried to find a matching ABI element named `{name}`, but encountered "
329
+ "the following problems:\n"
330
+ )
331
+
332
+ error += _build_abi_input_error(
333
+ abis_matching_names,
334
+ num_args,
335
+ *args,
336
+ abi_codec=abi_codec,
337
+ **kwargs,
338
+ )
339
+
340
+ return f"\n{error}"
341
+
201
342
 
202
343
  def _extract_argument_types(*args: Sequence[Any]) -> str:
203
344
  """
@@ -231,6 +372,102 @@ def _get_argument_readable_type(arg: Any) -> str:
231
372
  return arg.__class__.__name__
232
373
 
233
374
 
375
+ def _build_abi_filters(
376
+ abi_element_identifier: ABIElementIdentifier,
377
+ *args: Optional[Any],
378
+ abi_type: Optional[str] = None,
379
+ argument_names: Optional[Sequence[str]] = None,
380
+ argument_types: Optional[Sequence[str]] = None,
381
+ abi_codec: Optional[Any] = None,
382
+ **kwargs: Optional[Any],
383
+ ) -> List[Callable[..., Sequence[ABIElement]]]:
384
+ """
385
+ Build a list of ABI filters to find an ABI element within a contract ABI. Each
386
+ filter is a partial function that takes a contract ABI and returns a filtered list.
387
+ Each parameter is checked before applying the relevant filter.
388
+
389
+ When the ``abi_element_identifier`` is a function name or signature and no arguments
390
+ are provided, the returned filters include the function name or signature.
391
+
392
+ A function ABI may take arguments and keyword arguments. When the ``args`` and
393
+ ``kwargs`` values are passed, several filters are combined together. Available
394
+ filters include the function name, argument count, argument name, argument type,
395
+ and argument encodability.
396
+
397
+ ``constructor``, ``fallback``, and ``receive`` ABI elements are handled only with a
398
+ filter by type.
399
+ """
400
+ if not isinstance(abi_element_identifier, str):
401
+ abi_element_identifier = get_abi_element_signature(abi_element_identifier)
402
+
403
+ if abi_element_identifier in ["constructor", "fallback", "receive"]:
404
+ return [functools.partial(filter_abi_by_type, abi_element_identifier)]
405
+
406
+ filters: List[Callable[..., Sequence[ABIElement]]] = []
407
+
408
+ if abi_type:
409
+ filters.append(functools.partial(filter_abi_by_type, abi_type))
410
+
411
+ arg_count = 0
412
+ if argument_names:
413
+ arg_count = len(argument_names)
414
+ elif args or kwargs:
415
+ arg_count = len(args) + len(kwargs)
416
+
417
+ if arg_count > 0:
418
+ filters.append(
419
+ functools.partial(
420
+ filter_abi_by_name,
421
+ get_name_from_abi_element_identifier(abi_element_identifier),
422
+ )
423
+ )
424
+ filters.append(functools.partial(_filter_by_argument_count, arg_count))
425
+
426
+ if args or kwargs:
427
+ if abi_codec is None:
428
+ abi_codec = ABICodec(default_registry)
429
+
430
+ filters.append(
431
+ functools.partial(
432
+ _filter_by_encodability,
433
+ abi_codec,
434
+ args,
435
+ kwargs,
436
+ )
437
+ )
438
+
439
+ if argument_names:
440
+ filters.append(functools.partial(filter_by_argument_name, argument_names))
441
+
442
+ if argument_types:
443
+ if arg_count != len(argument_types):
444
+ raise Web3ValidationError(
445
+ "The number of argument names and types must match."
446
+ )
447
+
448
+ filters.append(
449
+ functools.partial(filter_by_argument_type, argument_types)
450
+ )
451
+
452
+ if "(" in abi_element_identifier:
453
+ filters.append(
454
+ functools.partial(_filter_by_signature, abi_element_identifier)
455
+ )
456
+ else:
457
+ filters.append(
458
+ functools.partial(
459
+ filter_abi_by_name,
460
+ get_name_from_abi_element_identifier(abi_element_identifier),
461
+ )
462
+ )
463
+ if "(" in abi_element_identifier:
464
+ filters.append(
465
+ functools.partial(_filter_by_signature, abi_element_identifier)
466
+ )
467
+
468
+ return filters
469
+
470
+
234
471
  def get_abi_element_info(
235
472
  abi: ABI,
236
473
  abi_element_identifier: ABIElementIdentifier,
@@ -306,16 +543,21 @@ def get_abi_element_info(
306
543
  def get_abi_element(
307
544
  abi: ABI,
308
545
  abi_element_identifier: ABIElementIdentifier,
309
- *args: Optional[Sequence[Any]],
546
+ *args: Optional[Any],
310
547
  abi_codec: Optional[Any] = None,
311
- **kwargs: Optional[Dict[str, Any]],
548
+ **kwargs: Optional[Any],
312
549
  ) -> ABIElement:
313
550
  """
314
- Return the interface for an ``ABIElement`` which matches the provided identifier
315
- and arguments.
551
+ Return the interface for an ``ABIElement`` from the ``abi`` that matches the
552
+ provided identifier and arguments.
553
+
554
+ ``abi`` may be a list of all ABI elements in a contract or a subset of elements.
555
+ Passing only functions or events can be useful when names are not deterministic.
556
+ For example, if names overlap between functions and events.
316
557
 
317
- The ABI which matches the provided identifier, named arguments (``args``) and
318
- keyword args (``kwargs``) will be returned.
558
+ The ``ABIElementIdentifier`` value may be a function name, signature, or a
559
+ ``FallbackFn`` or ``ReceiveFn``. When named arguments (``args``) and/or keyword args
560
+ (``kwargs``) are provided, they are included in the search filters.
319
561
 
320
562
  The `abi_codec` may be overridden if custom encoding and decoding is required. The
321
563
  default is used if no codec is provided. More details about customizations are in
@@ -323,7 +565,9 @@ def get_abi_element(
323
565
 
324
566
  :param abi: Contract ABI.
325
567
  :type abi: `ABI`
326
- :param abi_element_identifier: Find an element ABI with matching identifier.
568
+ :param abi_element_identifier: Find an element ABI with matching identifier. The \
569
+ identifier may be a function name, signature, or ``FallbackFn`` or ``ReceiveFn``. \
570
+ A function signature is in the form ``name(arg1Type,arg2Type,...)``.
327
571
  :type abi_element_identifier: `ABIElementIdentifier`
328
572
  :param args: Find an element ABI with matching args.
329
573
  :type args: `Optional[Sequence[Any]]`
@@ -358,55 +602,38 @@ def get_abi_element(
358
602
  'type': 'uint256'}], 'payable': False, 'stateMutability': 'nonpayable', \
359
603
  'type': 'function'}
360
604
  """
605
+ validate_abi(abi)
606
+
361
607
  if abi_codec is None:
362
608
  abi_codec = ABICodec(default_registry)
363
609
 
364
- if abi_element_identifier is FallbackFn or abi_element_identifier == "fallback":
365
- return _get_fallback_function_abi(abi)
366
-
367
- if abi_element_identifier is ReceiveFn or abi_element_identifier == "receive":
368
- return _get_receive_function_abi(abi)
369
-
370
- if abi_element_identifier is None or not is_text(abi_element_identifier):
371
- raise Web3TypeError("Unsupported function identifier")
372
-
373
- filtered_abis_by_name: Sequence[ABIElement]
374
- if abi_element_identifier == "constructor":
375
- filtered_abis_by_name = [_get_constructor_function_abi(abi)]
376
- else:
377
- filtered_abis_by_name = filter_abi_by_name(
378
- cast(str, abi_element_identifier), abi
379
- )
380
-
381
- arg_count = len(args) + len(kwargs)
382
- filtered_abis_by_arg_count = _filter_by_argument_count(
383
- arg_count, filtered_abis_by_name
384
- )
385
-
386
- if not args and not kwargs and len(filtered_abis_by_arg_count) == 1:
387
- return filtered_abis_by_arg_count[0]
388
-
389
- elements_with_encodable_args = _filter_by_encodability(
390
- abi_codec, filtered_abis_by_arg_count, *args, **kwargs
610
+ abi_element_matches: Sequence[ABIElement] = pipe(
611
+ abi,
612
+ *_build_abi_filters(
613
+ abi_element_identifier,
614
+ *args,
615
+ abi_codec=abi_codec,
616
+ **kwargs,
617
+ ),
391
618
  )
392
619
 
393
- if len(elements_with_encodable_args) != 1:
394
- matching_function_signatures = [
395
- abi_to_signature(func) for func in filtered_abis_by_name
396
- ]
620
+ num_matches = len(abi_element_matches)
397
621
 
622
+ # Raise MismatchedABI when more than one found
623
+ if num_matches != 1:
398
624
  error_diagnosis = _mismatched_abi_error_diagnosis(
399
625
  abi_element_identifier,
400
- matching_function_signatures,
401
- len(filtered_abis_by_arg_count),
402
- len(elements_with_encodable_args),
626
+ abi,
627
+ num_matches,
628
+ len(args) + len(kwargs),
403
629
  *args,
630
+ abi_codec=abi_codec,
404
631
  **kwargs,
405
632
  )
406
633
 
407
634
  raise MismatchedABI(error_diagnosis)
408
635
 
409
- return elements_with_encodable_args[0]
636
+ return abi_element_matches[0]
410
637
 
411
638
 
412
639
  def check_if_arguments_can_be_encoded(
@@ -472,12 +699,17 @@ def check_if_arguments_can_be_encoded(
472
699
  )
473
700
 
474
701
 
702
+ @deprecated_for("get_abi_element")
475
703
  def get_event_abi(
476
704
  abi: ABI,
477
705
  event_name: str,
478
706
  argument_names: Optional[Sequence[str]] = None,
479
707
  ) -> ABIEvent:
480
708
  """
709
+ .. warning::
710
+ This function is deprecated. It is unable to distinguish between
711
+ overloaded events. Use ``get_abi_element`` instead.
712
+
481
713
  Find the event interface with the given name and/or arguments.
482
714
 
483
715
  :param abi: Contract ABI.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: web3
3
- Version: 7.4.0
3
+ Version: 7.6.0
4
4
  Summary: web3: A Python library for interacting with Ethereum
5
5
  Home-page: https://github.com/ethereum/web3.py
6
6
  Author: The Ethereum Foundation
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.9
17
17
  Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
20
21
  Requires-Python: >=3.8, <4
21
22
  Description-Content-Type: text/markdown
22
23
  License-File: LICENSE
@@ -31,7 +32,7 @@ Requires-Dist: pydantic >=2.4.0
31
32
  Requires-Dist: requests >=2.23.0
32
33
  Requires-Dist: typing-extensions >=4.0.1
33
34
  Requires-Dist: types-requests >=2.0.0
34
- Requires-Dist: websockets >=10.0.0
35
+ Requires-Dist: websockets <14.0.0,>=10.0.0
35
36
  Requires-Dist: pyunormalize >=15.0.0
36
37
  Requires-Dist: pywin32 >=223 ; platform_system == "Windows"
37
38
  Provides-Extra: dev