faster-eth-utils 5.3.22__cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.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.

Potentially problematic release.


This version of faster-eth-utils might be problematic. Click here for more details.

Files changed (53) hide show
  1. faster_eth_utils/__init__.py +144 -0
  2. faster_eth_utils/__json/eth_networks.json +1 -0
  3. faster_eth_utils/__main__.py +5 -0
  4. faster_eth_utils/abi.cpython-312-i386-linux-gnu.so +0 -0
  5. faster_eth_utils/abi.py +868 -0
  6. faster_eth_utils/address.cpython-312-i386-linux-gnu.so +0 -0
  7. faster_eth_utils/address.py +138 -0
  8. faster_eth_utils/applicators.cpython-312-i386-linux-gnu.so +0 -0
  9. faster_eth_utils/applicators.py +196 -0
  10. faster_eth_utils/conversions.cpython-312-i386-linux-gnu.so +0 -0
  11. faster_eth_utils/conversions.py +189 -0
  12. faster_eth_utils/crypto.cpython-312-i386-linux-gnu.so +0 -0
  13. faster_eth_utils/crypto.py +16 -0
  14. faster_eth_utils/currency.cpython-312-i386-linux-gnu.so +0 -0
  15. faster_eth_utils/currency.py +144 -0
  16. faster_eth_utils/curried/__init__.py +297 -0
  17. faster_eth_utils/debug.cpython-312-i386-linux-gnu.so +0 -0
  18. faster_eth_utils/debug.py +20 -0
  19. faster_eth_utils/decorators.cpython-312-i386-linux-gnu.so +0 -0
  20. faster_eth_utils/decorators.py +115 -0
  21. faster_eth_utils/encoding.cpython-312-i386-linux-gnu.so +0 -0
  22. faster_eth_utils/encoding.py +6 -0
  23. faster_eth_utils/exceptions.cpython-312-i386-linux-gnu.so +0 -0
  24. faster_eth_utils/exceptions.py +11 -0
  25. faster_eth_utils/functional.cpython-312-i386-linux-gnu.so +0 -0
  26. faster_eth_utils/functional.py +87 -0
  27. faster_eth_utils/hexadecimal.cpython-312-i386-linux-gnu.so +0 -0
  28. faster_eth_utils/hexadecimal.py +76 -0
  29. faster_eth_utils/humanize.cpython-312-i386-linux-gnu.so +0 -0
  30. faster_eth_utils/humanize.py +201 -0
  31. faster_eth_utils/logging.py +152 -0
  32. faster_eth_utils/module_loading.cpython-312-i386-linux-gnu.so +0 -0
  33. faster_eth_utils/module_loading.py +31 -0
  34. faster_eth_utils/network.cpython-312-i386-linux-gnu.so +0 -0
  35. faster_eth_utils/network.py +91 -0
  36. faster_eth_utils/numeric.cpython-312-i386-linux-gnu.so +0 -0
  37. faster_eth_utils/numeric.py +43 -0
  38. faster_eth_utils/py.typed +0 -0
  39. faster_eth_utils/pydantic.py +103 -0
  40. faster_eth_utils/toolz.cpython-312-i386-linux-gnu.so +0 -0
  41. faster_eth_utils/toolz.py +84 -0
  42. faster_eth_utils/types.cpython-312-i386-linux-gnu.so +0 -0
  43. faster_eth_utils/types.py +65 -0
  44. faster_eth_utils/typing/__init__.py +18 -0
  45. faster_eth_utils/typing/misc.py +14 -0
  46. faster_eth_utils/units.cpython-312-i386-linux-gnu.so +0 -0
  47. faster_eth_utils/units.py +31 -0
  48. faster_eth_utils-5.3.22.dist-info/METADATA +192 -0
  49. faster_eth_utils-5.3.22.dist-info/RECORD +53 -0
  50. faster_eth_utils-5.3.22.dist-info/WHEEL +7 -0
  51. faster_eth_utils-5.3.22.dist-info/licenses/LICENSE +21 -0
  52. faster_eth_utils-5.3.22.dist-info/top_level.txt +3 -0
  53. faster_eth_utils__mypyc.cpython-312-i386-linux-gnu.so +0 -0
@@ -0,0 +1,868 @@
1
+ import copy
2
+ import itertools
3
+ import re
4
+ from collections.abc import (
5
+ Iterable,
6
+ Mapping,
7
+ Sequence,
8
+ )
9
+ from typing import (
10
+ Any,
11
+ Final,
12
+ Generic,
13
+ Literal,
14
+ TypeVar,
15
+ cast,
16
+ overload,
17
+ )
18
+
19
+ from eth_typing import (
20
+ ABI,
21
+ ABIComponent,
22
+ ABIConstructor,
23
+ ABIElement,
24
+ ABIError,
25
+ ABIEvent,
26
+ ABIFallback,
27
+ ABIFunction,
28
+ ABIReceive,
29
+ )
30
+ from typing_extensions import (
31
+ Self,
32
+ )
33
+
34
+ from faster_eth_utils.types import (
35
+ is_list_like,
36
+ )
37
+
38
+ from .crypto import (
39
+ keccak,
40
+ )
41
+
42
+
43
+ T = TypeVar("T")
44
+
45
+ ABIType = Literal["function", "constructor", "fallback", "receive", "event", "error"]
46
+
47
+ _TUPLE_TYPE_STR_RE: Final = re.compile("^(tuple)((\\[([1-9]\\d*\\b)?])*)??$")
48
+
49
+ _chain: Final = itertools.chain
50
+
51
+
52
+ class _repeat(Generic[T]):
53
+
54
+ def __init__(self, value: T, times: int | None = None) -> None:
55
+ self._value: Final[T] = value
56
+ self._times: Final[int | None] = times
57
+ self._index = 0
58
+
59
+ def __iter__(self) -> Self:
60
+ return self
61
+
62
+ def __next__(self) -> T:
63
+ if self._times is None:
64
+ return self._value
65
+ if self._index >= self._times:
66
+ raise StopIteration
67
+ self._index += 1
68
+ return self._value
69
+
70
+
71
+ def _align_abi_input(
72
+ arg_abi: ABIComponent, normalized_arg: Any
73
+ ) -> Any | tuple[Any, ...]:
74
+ """
75
+ Aligns the values of any mapping at any level of nesting in ``normalized_arg``
76
+ according to the layout of the corresponding abi spec.
77
+ """
78
+ tuple_parts = _get_tuple_type_str_and_dims(arg_abi.get("type", ""))
79
+
80
+ if tuple_parts is None:
81
+ # normalized_arg is non-tuple. Just return value.
82
+ return normalized_arg
83
+
84
+ tuple_prefix, tuple_dims = tuple_parts
85
+ if tuple_dims is None:
86
+ # normalized_arg is non-list tuple. Each sub arg in `normalized_arg` will be
87
+ # aligned according to its corresponding abi.
88
+ sub_abis = cast(Iterable[ABIComponent], arg_abi.get("components", []))
89
+ else:
90
+ num_dims = tuple_dims.count("[")
91
+
92
+ # normalized_arg is list tuple. A non-list version of its abi will be used to
93
+ # align each element in `normalized_arg`.
94
+ new_abi = copy.copy(arg_abi)
95
+ new_abi["type"] = tuple_prefix + "[]" * (num_dims - 1)
96
+
97
+ sub_abis = _repeat(new_abi)
98
+
99
+ aligned_arg: Any
100
+ if isinstance(normalized_arg, Mapping):
101
+ # normalized_arg is mapping. Align values according to abi order.
102
+ aligned_arg = tuple(normalized_arg[abi["name"]] for abi in sub_abis)
103
+ else:
104
+ aligned_arg = normalized_arg
105
+
106
+ # We can generate more optimized C code if we branch by arg type
107
+ if isinstance(aligned_arg, tuple):
108
+ # convert NamedTuple to regular tuple
109
+ return tuple(map(_align_abi_input, sub_abis, aligned_arg))
110
+
111
+ elif type(aligned_arg) is list:
112
+ return list(map(_align_abi_input, sub_abis, aligned_arg))
113
+
114
+ elif is_list_like(aligned_arg):
115
+ return type(aligned_arg)(map(_align_abi_input, sub_abis, aligned_arg)) # type: ignore [call-arg]
116
+
117
+ raise TypeError(
118
+ f'Expected non-string sequence for "{arg_abi.get("type")}" '
119
+ f"component type: got {aligned_arg}"
120
+ )
121
+
122
+
123
+ def _get_tuple_type_str_and_dims(s: str) -> tuple[str, str | None] | None:
124
+ """
125
+ Takes a JSON ABI type string. For tuple type strings, returns the separated
126
+ prefix and array dimension parts. For all other strings, returns ``None``.
127
+ """
128
+ match = _TUPLE_TYPE_STR_RE.match(s)
129
+
130
+ return None if match is None else (match[1], match[2])
131
+
132
+
133
+ def _raise_if_not_function_abi(abi_element: ABIElement) -> None:
134
+ if abi_element["type"] != "function":
135
+ raise ValueError(
136
+ f"Outputs only supported for ABI type `function`. Provided"
137
+ f" ABI type was `{abi_element.get('type')}` and outputs were "
138
+ f"`{abi_element.get('outputs')}`."
139
+ )
140
+
141
+
142
+ def _raise_if_fallback_or_receive_abi(abi_element: ABIElement) -> None:
143
+ if abi_element["type"] in ["fallback", "receive"]:
144
+ raise ValueError(
145
+ f"Inputs not supported for function types `fallback` or `receive`. Provided"
146
+ f" ABI type was `{abi_element.get('type')}` with inputs "
147
+ f"`{abi_element.get('inputs')}`."
148
+ )
149
+
150
+
151
+ def collapse_if_tuple(abi: ABIComponent | dict[str, Any] | str) -> str:
152
+ """
153
+ Extract argument types from a function or event ABI parameter.
154
+
155
+ With tuple argument types, return a Tuple of each type.
156
+ Returns the param if `abi` is an instance of str or another non-tuple
157
+ type.
158
+
159
+ :param abi: A Function or Event ABI component or a string with type info.
160
+ :type abi: `Union[ABIComponent, Dict[str, Any], str]`
161
+ :return: Type(s) for the function or event ABI param.
162
+ :rtype: `str`
163
+
164
+ .. doctest::
165
+
166
+ >>> from eth_utils.abi import collapse_if_tuple
167
+ >>> abi = {
168
+ ... 'components': [
169
+ ... {'name': 'anAddress', 'type': 'address'},
170
+ ... {'name': 'anInt', 'type': 'uint256'},
171
+ ... {'name': 'someBytes', 'type': 'bytes'},
172
+ ... ],
173
+ ... 'type': 'tuple',
174
+ ... }
175
+ >>> collapse_if_tuple(abi)
176
+ '(address,uint256,bytes)'
177
+ """
178
+ if isinstance(abi, str):
179
+ return abi
180
+
181
+ element_type = abi.get("type")
182
+ if not isinstance(element_type, str):
183
+ raise TypeError(
184
+ f"The 'type' must be a string, but got {repr(element_type)} of type "
185
+ f"{type(element_type)}"
186
+ )
187
+ elif not element_type.startswith("tuple"):
188
+ return element_type
189
+
190
+ delimited = ",".join(collapse_if_tuple(c) for c in abi["components"])
191
+ # Whatever comes after "tuple" is the array dims. The ABI spec states that
192
+ # this will have the form "", "[]", or "[k]".
193
+ array_dim = element_type[5:]
194
+ return f"({delimited}){array_dim}"
195
+
196
+
197
+ def abi_to_signature(abi_element: ABIElement) -> str:
198
+ """
199
+ Returns a string signature representation of the function or event ABI
200
+ and arguments.
201
+
202
+ Signatures consist of the name followed by a list of arguments.
203
+
204
+ :param abi_element: ABI element.
205
+ :type abi_element: `ABIElement`
206
+ :return: Stringified ABI signature
207
+ :rtype: `str`
208
+
209
+ .. doctest::
210
+
211
+ >>> from eth_utils import abi_to_signature
212
+ >>> abi_element = {
213
+ ... 'constant': False,
214
+ ... 'inputs': [
215
+ ... {
216
+ ... 'name': 's',
217
+ ... 'type': 'uint256'
218
+ ... }
219
+ ... ],
220
+ ... 'name': 'f',
221
+ ... 'outputs': [],
222
+ ... 'payable': False,
223
+ ... 'stateMutability': 'nonpayable',
224
+ ... 'type': 'function'
225
+ ... }
226
+ >>> abi_to_signature(abi_element)
227
+ 'f(uint256)'
228
+ """
229
+ signature = "{name}({input_types})"
230
+
231
+ abi_type = str(abi_element.get("type", ""))
232
+ if abi_type in {"fallback", "receive"}:
233
+ return signature.format(name=abi_type, input_types="")
234
+
235
+ if abi_type == "constructor":
236
+ fn_name = abi_type
237
+ else:
238
+ fn_name = str(abi_element.get("name", abi_type))
239
+
240
+ return signature.format(
241
+ name=fn_name, input_types=",".join(get_abi_input_types(abi_element))
242
+ )
243
+
244
+
245
+ def filter_abi_by_name(abi_name: str, contract_abi: ABI) -> Sequence[ABIElement]:
246
+ """
247
+ Get one or more function and event ABIs by name.
248
+
249
+ :param abi_name: Name of the function, event or error.
250
+ :type abi_name: `str`
251
+ :param contract_abi: Contract ABI.
252
+ :type contract_abi: `ABI`
253
+ :return: Function or event ABIs with matching name.
254
+ :rtype: `Sequence[ABIElement]`
255
+
256
+ .. doctest::
257
+
258
+ >>> from eth_utils.abi import filter_abi_by_name
259
+ >>> abi = [
260
+ ... {
261
+ ... "constant": False,
262
+ ... "inputs": [],
263
+ ... "name": "func_1",
264
+ ... "outputs": [],
265
+ ... "type": "function",
266
+ ... },
267
+ ... {
268
+ ... "constant": False,
269
+ ... "inputs": [
270
+ ... {"name": "a", "type": "uint256"},
271
+ ... ],
272
+ ... "name": "func_2",
273
+ ... "outputs": [],
274
+ ... "type": "function",
275
+ ... },
276
+ ... {
277
+ ... "constant": False,
278
+ ... "inputs": [
279
+ ... {"name": "a", "type": "uint256"},
280
+ ... {"name": "b", "type": "uint256"},
281
+ ... ],
282
+ ... "name": "func_3",
283
+ ... "outputs": [],
284
+ ... "type": "function",
285
+ ... },
286
+ ... {
287
+ ... "constant": False,
288
+ ... "inputs": [
289
+ ... {"name": "a", "type": "uint256"},
290
+ ... {"name": "b", "type": "uint256"},
291
+ ... {"name": "c", "type": "uint256"},
292
+ ... ],
293
+ ... "name": "func_4",
294
+ ... "outputs": [],
295
+ ... "type": "function",
296
+ ... },
297
+ ... ]
298
+ >>> filter_abi_by_name("func_1", abi)
299
+ [{'constant': False, 'inputs': [], 'name': 'func_1', 'outputs': [], \
300
+ 'type': 'function'}]
301
+ """
302
+ return [
303
+ abi
304
+ for abi in contract_abi
305
+ if abi["type"] in ["function", "event", "error"]
306
+ and abi["name"] == abi_name # type: ignore [typeddict-item]
307
+ ]
308
+
309
+
310
+ __ABI_TYPE_LITERALS: Final = {
311
+ Literal["function"]: "function",
312
+ Literal["constructor"]: "constructor",
313
+ Literal["fallback"]: "fallback",
314
+ Literal["receive"]: "receive",
315
+ Literal["event"]: "event",
316
+ Literal["error"]: "error",
317
+ }
318
+
319
+
320
+ @overload
321
+ def filter_abi_by_type(
322
+ abi_type: Literal["function"],
323
+ contract_abi: ABI,
324
+ ) -> list[ABIFunction]:
325
+ pass
326
+
327
+
328
+ @overload
329
+ def filter_abi_by_type(
330
+ abi_type: Literal["constructor"],
331
+ contract_abi: ABI,
332
+ ) -> list[ABIConstructor]:
333
+ pass
334
+
335
+
336
+ @overload
337
+ def filter_abi_by_type(
338
+ abi_type: Literal["fallback"],
339
+ contract_abi: ABI,
340
+ ) -> list[ABIFallback]:
341
+ pass
342
+
343
+
344
+ @overload
345
+ def filter_abi_by_type(
346
+ abi_type: Literal["receive"],
347
+ contract_abi: ABI,
348
+ ) -> list[ABIReceive]:
349
+ pass
350
+
351
+
352
+ @overload
353
+ def filter_abi_by_type(
354
+ abi_type: Literal["event"],
355
+ contract_abi: ABI,
356
+ ) -> list[ABIEvent]:
357
+ pass
358
+
359
+
360
+ @overload
361
+ def filter_abi_by_type(
362
+ abi_type: Literal["error"],
363
+ contract_abi: ABI,
364
+ ) -> list[ABIError]:
365
+ pass
366
+
367
+
368
+ def filter_abi_by_type(
369
+ abi_type: ABIType,
370
+ contract_abi: ABI,
371
+ ) -> (
372
+ list[ABIFunction] | list[ABIConstructor] | list[ABIFallback] | list[ABIReceive] | list[ABIEvent] | list[ABIError]
373
+ ):
374
+ """
375
+ Return a list of each ``ABIElement`` that is of type ``abi_type``.
376
+
377
+ For mypy, function overloads ensures the correct type is returned based on the
378
+ ``abi_type``. For example, if ``abi_type`` is "function", the return type will be
379
+ ``Sequence[ABIFunction]``.
380
+
381
+ :param abi_type: Type of ABI element to filter by.
382
+ :type abi_type: `str`
383
+ :param contract_abi: Contract ABI.
384
+ :type contract_abi: `ABI`
385
+ :return: List of ABI elements of the specified type.
386
+ :rtype: `Sequence[Union[ABIFunction, ABIConstructor, ABIFallback, ABIReceive, \
387
+ ABIEvent, ABIError]]`
388
+
389
+ .. doctest::
390
+
391
+ >>> from eth_utils import filter_abi_by_type
392
+ >>> abi = [
393
+ ... {"type": "function", "name": "myFunction", "inputs": [], "outputs": []},
394
+ ... {"type": "function", "name": "myFunction2", "inputs": [], "outputs": []},
395
+ ... {"type": "event", "name": "MyEvent", "inputs": []}
396
+ ... ]
397
+ >>> filter_abi_by_type("function", abi)
398
+ [{'type': 'function', 'name': 'myFunction', 'inputs': [], 'outputs': []}, \
399
+ {'type': 'function', 'name': 'myFunction2', 'inputs': [], 'outputs': []}]
400
+ """
401
+ if abi_type in ("function", "constructor", "fallback", "receive", "event", "error"):
402
+ return [abi for abi in contract_abi if abi["type"] == abi_type] # type: ignore [return-value]
403
+ abi_type_string: ABIType | None = __ABI_TYPE_LITERALS.get(abi_type) # type: ignore [call-overload]
404
+ if abi_type_string is None:
405
+ raise ValueError(f"Unsupported ABI type: {abi_type}")
406
+ return [abi for abi in contract_abi if abi["type"] == abi_type_string] # type: ignore [return-value]
407
+
408
+
409
+ def get_all_function_abis(contract_abi: ABI) -> Sequence[ABIFunction]:
410
+ """
411
+ Return interfaces for each function in the contract ABI.
412
+
413
+ :param contract_abi: Contract ABI.
414
+ :type contract_abi: `ABI`
415
+ :return: List of ABIs for each function interface.
416
+ :rtype: `Sequence[ABIFunction]`
417
+
418
+ .. doctest::
419
+
420
+ >>> from eth_utils import get_all_function_abis
421
+ >>> contract_abi = [
422
+ ... {"type": "function", "name": "myFunction", "inputs": [], "outputs": []},
423
+ ... {"type": "function", "name": "myFunction2", "inputs": [], "outputs": []},
424
+ ... {"type": "event", "name": "MyEvent", "inputs": []}
425
+ ... ]
426
+ >>> get_all_function_abis(contract_abi)
427
+ [{'type': 'function', 'name': 'myFunction', 'inputs': [], 'outputs': []}, \
428
+ {'type': 'function', 'name': 'myFunction2', 'inputs': [], 'outputs': []}]
429
+ """
430
+ return filter_abi_by_type("function", contract_abi)
431
+
432
+
433
+ def get_all_event_abis(contract_abi: ABI) -> Sequence[ABIEvent]:
434
+ """
435
+ Return interfaces for each event in the contract ABI.
436
+
437
+ :param contract_abi: Contract ABI.
438
+ :type contract_abi: `ABI`
439
+ :return: List of ABIs for each event interface.
440
+ :rtype: `Sequence[ABIEvent]`
441
+
442
+ .. doctest::
443
+
444
+ >>> from eth_utils import get_all_event_abis
445
+ >>> contract_abi = [
446
+ ... {"type": "function", "name": "myFunction", "inputs": [], "outputs": []},
447
+ ... {"type": "function", "name": "myFunction2", "inputs": [], "outputs": []},
448
+ ... {"type": "event", "name": "MyEvent", "inputs": []}
449
+ ... ]
450
+ >>> get_all_event_abis(contract_abi)
451
+ [{'type': 'event', 'name': 'MyEvent', 'inputs': []}]
452
+ """
453
+ return filter_abi_by_type("event", contract_abi)
454
+
455
+
456
+ def get_normalized_abi_inputs(
457
+ abi_element: ABIElement,
458
+ *args: Any,
459
+ **kwargs: Any,
460
+ ) -> tuple[Any, ...]:
461
+ r"""
462
+ Flattens positional args (``args``) and keyword args (``kwargs``) into a Tuple and
463
+ uses the ``abi_element`` for validation.
464
+
465
+ Checks to ensure that the correct number of args were given, no duplicate args were
466
+ given, and no unknown args were given. Returns a list of argument values aligned
467
+ to the order of inputs defined in ``abi_element``.
468
+
469
+ :param abi_element: ABI element.
470
+ :type abi_element: `ABIElement`
471
+ :param args: Positional arguments for the function.
472
+ :type args: `Optional[Sequence[Any]]`
473
+ :param kwargs: Keyword arguments for the function.
474
+ :type kwargs: `Optional[Dict[str, Any]]`
475
+ :return: Arguments list.
476
+ :rtype: `Tuple[Any, ...]`
477
+
478
+ .. doctest::
479
+
480
+ >>> from eth_utils import get_normalized_abi_inputs
481
+ >>> abi = {
482
+ ... 'constant': False,
483
+ ... 'inputs': [
484
+ ... {
485
+ ... 'name': 'name',
486
+ ... 'type': 'string'
487
+ ... },
488
+ ... {
489
+ ... 'name': 's',
490
+ ... 'type': 'uint256'
491
+ ... },
492
+ ... {
493
+ ... 'name': 't',
494
+ ... 'components': [
495
+ ... {'name': 'anAddress', 'type': 'address'},
496
+ ... {'name': 'anInt', 'type': 'uint256'},
497
+ ... {'name': 'someBytes', 'type': 'bytes'},
498
+ ... ],
499
+ ... 'type': 'tuple'
500
+ ... }
501
+ ... ],
502
+ ... 'name': 'f',
503
+ ... 'outputs': [],
504
+ ... 'payable': False,
505
+ ... 'stateMutability': 'nonpayable',
506
+ ... 'type': 'function'
507
+ ... }
508
+ >>> get_normalized_abi_inputs(
509
+ ... abi, *('myName', 123), **{'t': ('0x1', 1, b'\x01')}
510
+ ... )
511
+ ('myName', 123, ('0x1', 1, b'\x01'))
512
+ """
513
+ _raise_if_fallback_or_receive_abi(abi_element)
514
+
515
+ function_inputs = cast(Sequence[ABIComponent], abi_element.get("inputs", []))
516
+ if len(args) + len(kwargs) != len(function_inputs):
517
+ raise TypeError(
518
+ f"Incorrect argument count. Expected '{len(function_inputs)}'"
519
+ f", got '{len(args) + len(kwargs)}'."
520
+ )
521
+
522
+ # If no keyword args were given, we don't need to align them
523
+ if not kwargs:
524
+ return args
525
+
526
+ kwarg_names = set(kwargs.keys())
527
+ sorted_arg_names = tuple(arg_abi["name"] for arg_abi in function_inputs)
528
+ arg_positions = {name: index for index, name in enumerate(sorted_arg_names)}
529
+ args_as_kwargs = dict(zip(sorted_arg_names, args))
530
+
531
+ # Check for duplicate args
532
+ if duplicate_args := kwarg_names.intersection(args_as_kwargs.keys()):
533
+ raise TypeError(
534
+ f"{abi_element.get('name')}() got multiple values for argument(s) "
535
+ f"'{', '.join(duplicate_args)}'."
536
+ )
537
+
538
+ # Check for unknown args
539
+ # Arg names sorted to raise consistent error messages
540
+ if unknown_args := tuple(sorted(kwarg_names.difference(sorted_arg_names))):
541
+ message = "{} got unexpected keyword argument(s) '{}'."
542
+ if abi_element.get("name"):
543
+ raise TypeError(
544
+ message.format(f"{abi_element.get('name')}()", ", ".join(unknown_args))
545
+ )
546
+ raise TypeError(
547
+ message.format(
548
+ f"Type: '{abi_element.get('type')}'", ", ".join(unknown_args)
549
+ )
550
+ )
551
+
552
+ # Sort args according to their position in the ABI and unzip them from their
553
+ # names
554
+ sorted_items = sorted(
555
+ _chain(kwargs.items(), args_as_kwargs.items()),
556
+ key=lambda kv: arg_positions[kv[0]],
557
+ )
558
+ return tuple(val for _, val in sorted_items)
559
+
560
+
561
+ def get_aligned_abi_inputs(
562
+ abi_element: ABIElement,
563
+ normalized_args: tuple[Any, ...] | Mapping[Any, Any],
564
+ ) -> tuple[tuple[str, ...], tuple[Any, ...]]:
565
+ """
566
+ Returns a pair of nested Tuples containing a list of types and a list of input
567
+ values sorted by the order specified by the ``abi``.
568
+
569
+ ``normalized_args`` can be obtained by using
570
+ :py:meth:`eth_utils.abi.get_normalized_abi_inputs`, which returns nested mappings
571
+ or sequences corresponding to tuple-encoded values in ``abi``.
572
+
573
+ :param abi_element: ABI element.
574
+ :type abi_element: `ABIElement`
575
+ :param normalized_args: Normalized arguments for the function.
576
+ :type normalized_args: `Union[Tuple[Any, ...], Mapping[Any, Any]]`
577
+ :return: Tuple of types and aligned arguments.
578
+ :rtype: `Tuple[Tuple[str, ...], Tuple[Any, ...]]`
579
+
580
+ .. doctest::
581
+
582
+ >>> from eth_utils import get_aligned_abi_inputs
583
+ >>> abi = {
584
+ ... 'constant': False,
585
+ ... 'inputs': [
586
+ ... {
587
+ ... 'name': 'name',
588
+ ... 'type': 'string'
589
+ ... },
590
+ ... {
591
+ ... 'name': 's',
592
+ ... 'type': 'uint256'
593
+ ... }
594
+ ... ],
595
+ ... 'name': 'f',
596
+ ... 'outputs': [],
597
+ ... 'payable': False,
598
+ ... 'stateMutability': 'nonpayable',
599
+ ... 'type': 'function'
600
+ ... }
601
+ >>> get_aligned_abi_inputs(abi, ('myName', 123))
602
+ (('string', 'uint256'), ('myName', 123))
603
+ """
604
+ _raise_if_fallback_or_receive_abi(abi_element)
605
+
606
+ abi_element_inputs = cast(Sequence[ABIComponent], abi_element.get("inputs", []))
607
+ if isinstance(normalized_args, Mapping):
608
+ # `args` is mapping. Align values according to abi order.
609
+ normalized_args = tuple(
610
+ normalized_args[abi["name"]] for abi in abi_element_inputs
611
+ )
612
+
613
+ return (
614
+ tuple(collapse_if_tuple(abi) for abi in abi_element_inputs),
615
+ type(normalized_args)(
616
+ _align_abi_input(abi, arg)
617
+ for abi, arg in zip(abi_element_inputs, normalized_args)
618
+ ),
619
+ )
620
+
621
+
622
+ def get_abi_input_names(abi_element: ABIElement) -> list[str | None]:
623
+ """
624
+ Return names for each input from the function or event ABI.
625
+
626
+ :param abi_element: ABI element.
627
+ :type abi_element: `ABIElement`
628
+ :return: Names for each input in the function or event ABI.
629
+ :rtype: `List[Optional[str]]`
630
+
631
+ .. doctest::
632
+
633
+ >>> from eth_utils import get_abi_input_names
634
+ >>> abi = {
635
+ ... 'constant': False,
636
+ ... 'inputs': [
637
+ ... {
638
+ ... 'name': 's',
639
+ ... 'type': 'uint256'
640
+ ... }
641
+ ... ],
642
+ ... 'name': 'f',
643
+ ... 'outputs': [],
644
+ ... 'payable': False,
645
+ ... 'stateMutability': 'nonpayable',
646
+ ... 'type': 'function'
647
+ ... }
648
+ >>> get_abi_input_names(abi)
649
+ ['s']
650
+ """
651
+ _raise_if_fallback_or_receive_abi(abi_element)
652
+ return [
653
+ arg.get("name", None)
654
+ for arg in cast(Sequence[ABIComponent], abi_element.get("inputs", []))
655
+ ]
656
+
657
+
658
+ def get_abi_input_types(abi_element: ABIElement) -> list[str]:
659
+ """
660
+ Return types for each input from the function or event ABI.
661
+
662
+ :param abi_element: ABI element.
663
+ :type abi_element: `ABIElement`
664
+ :return: Types for each input in the function or event ABI.
665
+ :rtype: `List[str]`
666
+
667
+ .. doctest::
668
+
669
+ >>> from eth_utils import get_abi_input_types
670
+ >>> abi = {
671
+ ... 'constant': False,
672
+ ... 'inputs': [
673
+ ... {
674
+ ... 'name': 's',
675
+ ... 'type': 'uint256'
676
+ ... }
677
+ ... ],
678
+ ... 'name': 'f',
679
+ ... 'outputs': [],
680
+ ... 'payable': False,
681
+ ... 'stateMutability': 'nonpayable',
682
+ ... 'type': 'function'
683
+ ... }
684
+ >>> get_abi_input_types(abi)
685
+ ['uint256']
686
+ """
687
+ _raise_if_fallback_or_receive_abi(abi_element)
688
+ return [
689
+ collapse_if_tuple(arg)
690
+ for arg in cast(Sequence[ABIComponent], abi_element.get("inputs", []))
691
+ ]
692
+
693
+
694
+ def get_abi_output_names(abi_element: ABIElement) -> list[str | None]:
695
+ """
696
+ Return names for each output from the ABI element.
697
+
698
+ :param abi_element: ABI element.
699
+ :type abi_element: `ABIElement`
700
+ :return: Names for each function output in the function ABI.
701
+ :rtype: `List[Optional[str]]`
702
+
703
+ .. doctest::
704
+
705
+ >>> from eth_utils import get_abi_output_names
706
+ >>> abi = {
707
+ ... 'constant': False,
708
+ ... 'inputs': [
709
+ ... {
710
+ ... 'name': 's',
711
+ ... 'type': 'uint256'
712
+ ... }
713
+ ... ],
714
+ ... 'name': 'f',
715
+ ... 'outputs': [
716
+ ... {
717
+ ... 'name': 'name',
718
+ ... 'type': 'string'
719
+ ... },
720
+ ... {
721
+ ... 'name': 's',
722
+ ... 'type': 'uint256'
723
+ ... }
724
+ ... ],
725
+ ... 'payable': False,
726
+ ... 'stateMutability': 'nonpayable',
727
+ ... 'type': 'function'
728
+ ... }
729
+ >>> get_abi_output_names(abi)
730
+ ['name', 's']
731
+ """
732
+ _raise_if_not_function_abi(abi_element)
733
+ return [
734
+ arg.get("name", None)
735
+ for arg in cast(Sequence[ABIComponent], abi_element.get("outputs", []))
736
+ ]
737
+
738
+
739
+ def get_abi_output_types(abi_element: ABIElement) -> list[str]:
740
+ """
741
+ Return types for each output from the function ABI.
742
+
743
+ :param abi_element: ABI element.
744
+ :type abi_element: `ABIElement`
745
+ :return: Types for each function output in the function ABI.
746
+ :rtype: `List[str]`
747
+
748
+ .. doctest::
749
+
750
+ >>> from eth_utils import get_abi_output_types
751
+ >>> abi = {
752
+ ... 'constant': False,
753
+ ... 'inputs': [
754
+ ... {
755
+ ... 'name': 's',
756
+ ... 'type': 'uint256'
757
+ ... }
758
+ ... ],
759
+ ... 'name': 'f',
760
+ ... 'outputs': [
761
+ ... {
762
+ ... 'name': 'name',
763
+ ... 'type': 'string'
764
+ ... },
765
+ ... {
766
+ ... 'name': 's',
767
+ ... 'type': 'uint256'
768
+ ... }
769
+ ... ],
770
+ ... 'payable': False,
771
+ ... 'stateMutability': 'nonpayable',
772
+ ... 'type': 'function'
773
+ ... }
774
+ >>> get_abi_output_types(abi)
775
+ ['string', 'uint256']
776
+
777
+ """
778
+ _raise_if_not_function_abi(abi_element)
779
+ return [
780
+ collapse_if_tuple(arg)
781
+ for arg in cast(Sequence[ABIComponent], abi_element.get("outputs", []))
782
+ ]
783
+
784
+
785
+ def function_signature_to_4byte_selector(function_signature: str) -> bytes:
786
+ r"""
787
+ Return the 4-byte function selector from a function signature string.
788
+
789
+ :param function_signature: String representation of the function name and arguments.
790
+ :type function_signature: `str`
791
+ :return: 4-byte function selector.
792
+ :rtype: `bytes`
793
+
794
+ .. doctest::
795
+
796
+ >>> from eth_utils import function_signature_to_4byte_selector
797
+ >>> function_signature_to_4byte_selector('myFunction()')
798
+ b'\xc3x\n:'
799
+ """
800
+ return keccak(text=function_signature.replace(" ", ""))[:4]
801
+
802
+
803
+ def function_abi_to_4byte_selector(abi_element: ABIElement) -> bytes:
804
+ r"""
805
+ Return the 4-byte function signature of the provided function ABI.
806
+
807
+ :param abi_element: ABI element.
808
+ :type abi_element: `ABIElement`
809
+ :return: 4-byte function signature.
810
+ :rtype: `bytes`
811
+
812
+ .. doctest::
813
+
814
+ >>> from eth_utils import function_abi_to_4byte_selector
815
+ >>> abi_element = {
816
+ ... 'type': 'function',
817
+ ... 'name': 'myFunction',
818
+ ... 'inputs': [],
819
+ ... 'outputs': []
820
+ ... }
821
+ >>> function_abi_to_4byte_selector(abi_element)
822
+ b'\xc3x\n:'
823
+ """
824
+ function_signature = abi_to_signature(abi_element)
825
+ return function_signature_to_4byte_selector(function_signature)
826
+
827
+
828
+ def event_signature_to_log_topic(event_signature: str) -> bytes:
829
+ r"""
830
+ Return the 32-byte keccak signature of the log topic for an event signature.
831
+
832
+ :param event_signature: String representation of the event name and arguments.
833
+ :type event_signature: `str`
834
+ :return: Log topic bytes.
835
+ :rtype: `bytes`
836
+
837
+ .. doctest::
838
+
839
+ >>> from eth_utils import event_signature_to_log_topic
840
+ >>> event_signature_to_log_topic('MyEvent()')
841
+ b'M\xbf\xb6\x8bC\xdd\xdf\xa1+Q\xeb\xe9\x9a\xb8\xfd\xedb\x0f\x9a\n\xc21B\x87\x9aO\x19*\x1byR\xd2'
842
+ """
843
+ return keccak(text=event_signature.replace(" ", ""))
844
+
845
+
846
+ def event_abi_to_log_topic(event_abi: ABIEvent) -> bytes:
847
+ r"""
848
+ Return the 32-byte keccak signature of the log topic from an event ABI.
849
+
850
+ :param event_abi: Event ABI.
851
+ :type event_abi: `ABIEvent`
852
+ :return: Log topic bytes.
853
+ :rtype: `bytes`
854
+
855
+ .. doctest::
856
+
857
+ >>> from eth_utils import event_abi_to_log_topic
858
+ >>> abi = {
859
+ ... 'type': 'event',
860
+ ... 'anonymous': False,
861
+ ... 'name': 'MyEvent',
862
+ ... 'inputs': []
863
+ ... }
864
+ >>> event_abi_to_log_topic(abi)
865
+ b'M\xbf\xb6\x8bC\xdd\xdf\xa1+Q\xeb\xe9\x9a\xb8\xfd\xedb\x0f\x9a\n\xc21B\x87\x9aO\x19*\x1byR\xd2'
866
+ """
867
+ event_signature = abi_to_signature(event_abi)
868
+ return event_signature_to_log_topic(event_signature)