web3 7.0.0b1__py3-none-any.whl → 7.7.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 (261) hide show
  1. ens/__init__.py +13 -2
  2. ens/_normalization.py +4 -4
  3. ens/async_ens.py +31 -21
  4. ens/base_ens.py +3 -1
  5. ens/contract_data.py +2 -2
  6. ens/ens.py +14 -11
  7. ens/exceptions.py +16 -29
  8. ens/specs/nf.json +1 -1
  9. ens/specs/normalization_spec.json +1 -1
  10. ens/utils.py +33 -41
  11. web3/__init__.py +23 -12
  12. web3/_utils/abi.py +162 -274
  13. web3/_utils/async_transactions.py +34 -20
  14. web3/_utils/batching.py +217 -0
  15. web3/_utils/blocks.py +6 -2
  16. web3/_utils/caching/__init__.py +12 -0
  17. web3/_utils/caching/caching_utils.py +433 -0
  18. web3/_utils/caching/request_caching_validation.py +287 -0
  19. web3/_utils/compat/__init__.py +2 -3
  20. web3/_utils/contract_sources/compile_contracts.py +1 -1
  21. web3/_utils/contract_sources/contract_data/ambiguous_function_contract.py +42 -0
  22. web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
  23. web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
  24. web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
  25. web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
  26. web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
  27. web3/_utils/contract_sources/contract_data/event_contracts.py +50 -5
  28. web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
  29. web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
  30. web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
  31. web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
  32. web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
  33. web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
  34. web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
  35. web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
  36. web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
  37. web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
  38. web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
  39. web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
  40. web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
  41. web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
  42. web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
  43. web3/_utils/contracts.py +172 -220
  44. web3/_utils/datatypes.py +5 -1
  45. web3/_utils/decorators.py +6 -1
  46. web3/_utils/empty.py +1 -1
  47. web3/_utils/encoding.py +16 -12
  48. web3/_utils/error_formatters_utils.py +5 -3
  49. web3/_utils/events.py +78 -72
  50. web3/_utils/fee_utils.py +1 -3
  51. web3/_utils/filters.py +24 -22
  52. web3/_utils/formatters.py +2 -2
  53. web3/_utils/http.py +8 -2
  54. web3/_utils/http_session_manager.py +314 -0
  55. web3/_utils/math.py +14 -15
  56. web3/_utils/method_formatters.py +161 -34
  57. web3/_utils/module.py +2 -1
  58. web3/_utils/module_testing/__init__.py +3 -2
  59. web3/_utils/module_testing/eth_module.py +736 -583
  60. web3/_utils/module_testing/go_ethereum_debug_module.py +128 -0
  61. web3/_utils/module_testing/module_testing_utils.py +81 -24
  62. web3/_utils/module_testing/persistent_connection_provider.py +702 -220
  63. web3/_utils/module_testing/utils.py +114 -33
  64. web3/_utils/module_testing/web3_module.py +438 -17
  65. web3/_utils/normalizers.py +13 -11
  66. web3/_utils/rpc_abi.py +10 -22
  67. web3/_utils/threads.py +8 -7
  68. web3/_utils/transactions.py +32 -25
  69. web3/_utils/type_conversion.py +5 -1
  70. web3/_utils/validation.py +20 -17
  71. web3/beacon/__init__.py +5 -0
  72. web3/beacon/api_endpoints.py +3 -0
  73. web3/beacon/async_beacon.py +29 -6
  74. web3/beacon/beacon.py +24 -6
  75. web3/contract/__init__.py +7 -0
  76. web3/contract/async_contract.py +285 -82
  77. web3/contract/base_contract.py +556 -258
  78. web3/contract/contract.py +295 -84
  79. web3/contract/utils.py +251 -55
  80. web3/datastructures.py +56 -41
  81. web3/eth/__init__.py +7 -0
  82. web3/eth/async_eth.py +89 -69
  83. web3/eth/base_eth.py +7 -3
  84. web3/eth/eth.py +43 -66
  85. web3/exceptions.py +158 -83
  86. web3/gas_strategies/time_based.py +8 -6
  87. web3/geth.py +53 -184
  88. web3/main.py +77 -43
  89. web3/manager.py +368 -101
  90. web3/method.py +43 -15
  91. web3/middleware/__init__.py +26 -8
  92. web3/middleware/attrdict.py +12 -22
  93. web3/middleware/base.py +55 -2
  94. web3/middleware/filter.py +45 -23
  95. web3/middleware/formatting.py +6 -3
  96. web3/middleware/names.py +4 -1
  97. web3/middleware/signing.py +15 -6
  98. web3/middleware/stalecheck.py +2 -1
  99. web3/module.py +62 -26
  100. web3/providers/__init__.py +21 -0
  101. web3/providers/async_base.py +93 -38
  102. web3/providers/base.py +85 -40
  103. web3/providers/eth_tester/__init__.py +5 -0
  104. web3/providers/eth_tester/defaults.py +2 -55
  105. web3/providers/eth_tester/main.py +57 -35
  106. web3/providers/eth_tester/middleware.py +16 -17
  107. web3/providers/ipc.py +42 -18
  108. web3/providers/legacy_websocket.py +27 -2
  109. web3/providers/persistent/__init__.py +7 -0
  110. web3/providers/persistent/async_ipc.py +61 -121
  111. web3/providers/persistent/persistent.py +324 -17
  112. web3/providers/persistent/persistent_connection.py +54 -5
  113. web3/providers/persistent/request_processor.py +136 -56
  114. web3/providers/persistent/subscription_container.py +56 -0
  115. web3/providers/persistent/subscription_manager.py +233 -0
  116. web3/providers/persistent/websocket.py +29 -92
  117. web3/providers/rpc/__init__.py +5 -0
  118. web3/providers/rpc/async_rpc.py +73 -18
  119. web3/providers/rpc/rpc.py +73 -30
  120. web3/providers/rpc/utils.py +1 -13
  121. web3/scripts/install_pre_releases.py +33 -0
  122. web3/scripts/parse_pygeth_version.py +16 -0
  123. web3/testing.py +4 -4
  124. web3/tracing.py +9 -5
  125. web3/types.py +141 -74
  126. web3/utils/__init__.py +64 -5
  127. web3/utils/abi.py +790 -10
  128. web3/utils/address.py +8 -0
  129. web3/utils/async_exception_handling.py +20 -11
  130. web3/utils/caching.py +34 -4
  131. web3/utils/exception_handling.py +9 -12
  132. web3/utils/subscriptions.py +285 -0
  133. {web3-7.0.0b1.dist-info → web3-7.7.0.dist-info}/LICENSE +1 -1
  134. web3-7.7.0.dist-info/METADATA +130 -0
  135. web3-7.7.0.dist-info/RECORD +171 -0
  136. {web3-7.0.0b1.dist-info → web3-7.7.0.dist-info}/WHEEL +1 -1
  137. {web3-7.0.0b1.dist-info → web3-7.7.0.dist-info}/top_level.txt +0 -1
  138. ethpm/__init__.py +0 -20
  139. ethpm/_utils/__init__.py +0 -0
  140. ethpm/_utils/backend.py +0 -93
  141. ethpm/_utils/cache.py +0 -44
  142. ethpm/_utils/chains.py +0 -119
  143. ethpm/_utils/contract.py +0 -35
  144. ethpm/_utils/deployments.py +0 -145
  145. ethpm/_utils/ipfs.py +0 -116
  146. ethpm/_utils/protobuf/__init__.py +0 -0
  147. ethpm/_utils/protobuf/ipfs_file_pb2.py +0 -33
  148. ethpm/_utils/registry.py +0 -29
  149. ethpm/assets/__init__.py +0 -0
  150. ethpm/assets/ens/v3.json +0 -1
  151. ethpm/assets/escrow/with_bytecode_v3.json +0 -1
  152. ethpm/assets/ipfs_file.proto +0 -32
  153. ethpm/assets/owned/output_v3.json +0 -1
  154. ethpm/assets/owned/with_contract_type_v3.json +0 -1
  155. ethpm/assets/registry/contracts/Authority.sol +0 -156
  156. ethpm/assets/registry/contracts/IndexedOrderedSetLib.sol +0 -106
  157. ethpm/assets/registry/contracts/PackageDB.sol +0 -225
  158. ethpm/assets/registry/contracts/PackageRegistry.sol +0 -361
  159. ethpm/assets/registry/contracts/PackageRegistryInterface.sol +0 -97
  160. ethpm/assets/registry/contracts/ReleaseDB.sol +0 -309
  161. ethpm/assets/registry/contracts/ReleaseValidator.sol +0 -152
  162. ethpm/assets/registry/solc_input.json +0 -1
  163. ethpm/assets/registry/solc_output.json +0 -1
  164. ethpm/assets/registry/v3.json +0 -1
  165. ethpm/assets/safe-math-lib/v3-strict-no-deployments.json +0 -1
  166. ethpm/assets/simple-registry/contracts/Ownable.sol +0 -63
  167. ethpm/assets/simple-registry/contracts/PackageRegistry.sol +0 -373
  168. ethpm/assets/simple-registry/contracts/PackageRegistryInterface.sol +0 -96
  169. ethpm/assets/simple-registry/solc_input.json +0 -33
  170. ethpm/assets/simple-registry/solc_output.json +0 -1
  171. ethpm/assets/simple-registry/v3.json +0 -1
  172. ethpm/assets/standard-token/output_v3.json +0 -1
  173. ethpm/assets/standard-token/with_bytecode_v3.json +0 -1
  174. ethpm/assets/vyper_registry/0.1.0.json +0 -1
  175. ethpm/assets/vyper_registry/registry.vy +0 -216
  176. ethpm/assets/vyper_registry/registry_with_delete.vy +0 -244
  177. ethpm/backends/__init__.py +0 -0
  178. ethpm/backends/base.py +0 -43
  179. ethpm/backends/http.py +0 -108
  180. ethpm/backends/ipfs.py +0 -219
  181. ethpm/backends/registry.py +0 -154
  182. ethpm/constants.py +0 -17
  183. ethpm/contract.py +0 -187
  184. ethpm/dependencies.py +0 -58
  185. ethpm/deployments.py +0 -80
  186. ethpm/ethpm-spec/examples/escrow/1.0.0-pretty.json +0 -146
  187. ethpm/ethpm-spec/examples/escrow/1.0.0.json +0 -1
  188. ethpm/ethpm-spec/examples/escrow/contracts/Escrow.sol +0 -32
  189. ethpm/ethpm-spec/examples/escrow/contracts/SafeSendLib.sol +0 -20
  190. ethpm/ethpm-spec/examples/escrow/v3-pretty.json +0 -171
  191. ethpm/ethpm-spec/examples/escrow/v3.json +0 -1
  192. ethpm/ethpm-spec/examples/owned/1.0.0-pretty.json +0 -21
  193. ethpm/ethpm-spec/examples/owned/1.0.0.json +0 -1
  194. ethpm/ethpm-spec/examples/owned/contracts/Owned.sol +0 -12
  195. ethpm/ethpm-spec/examples/owned/v3-pretty.json +0 -27
  196. ethpm/ethpm-spec/examples/owned/v3.json +0 -1
  197. ethpm/ethpm-spec/examples/piper-coin/1.0.0-pretty.json +0 -31
  198. ethpm/ethpm-spec/examples/piper-coin/1.0.0.json +0 -1
  199. ethpm/ethpm-spec/examples/piper-coin/v3-pretty.json +0 -21
  200. ethpm/ethpm-spec/examples/piper-coin/v3.json +0 -1
  201. ethpm/ethpm-spec/examples/safe-math-lib/1.0.0-pretty.json +0 -85
  202. ethpm/ethpm-spec/examples/safe-math-lib/1.0.0.json +0 -1
  203. ethpm/ethpm-spec/examples/safe-math-lib/contracts/SafeMathLib.sol +0 -24
  204. ethpm/ethpm-spec/examples/safe-math-lib/v3-pretty.json +0 -117
  205. ethpm/ethpm-spec/examples/safe-math-lib/v3.json +0 -1
  206. ethpm/ethpm-spec/examples/standard-token/1.0.0-pretty.json +0 -55
  207. ethpm/ethpm-spec/examples/standard-token/1.0.0.json +0 -1
  208. ethpm/ethpm-spec/examples/standard-token/contracts/AbstractToken.sol +0 -20
  209. ethpm/ethpm-spec/examples/standard-token/contracts/StandardToken.sol +0 -84
  210. ethpm/ethpm-spec/examples/standard-token/v3-pretty.json +0 -460
  211. ethpm/ethpm-spec/examples/standard-token/v3.json +0 -1
  212. ethpm/ethpm-spec/examples/transferable/1.0.0-pretty.json +0 -21
  213. ethpm/ethpm-spec/examples/transferable/1.0.0.json +0 -1
  214. ethpm/ethpm-spec/examples/transferable/contracts/Transferable.sol +0 -14
  215. ethpm/ethpm-spec/examples/transferable/v3-pretty.json +0 -27
  216. ethpm/ethpm-spec/examples/transferable/v3.json +0 -1
  217. ethpm/ethpm-spec/examples/wallet/1.0.0-pretty.json +0 -120
  218. ethpm/ethpm-spec/examples/wallet/1.0.0.json +0 -1
  219. ethpm/ethpm-spec/examples/wallet/contracts/Wallet.sol +0 -41
  220. ethpm/ethpm-spec/examples/wallet/v3-pretty.json +0 -181
  221. ethpm/ethpm-spec/examples/wallet/v3.json +0 -1
  222. ethpm/ethpm-spec/examples/wallet-with-send/1.0.0-pretty.json +0 -135
  223. ethpm/ethpm-spec/examples/wallet-with-send/1.0.0.json +0 -1
  224. ethpm/ethpm-spec/examples/wallet-with-send/contracts/WalletWithSend.sol +0 -18
  225. ethpm/ethpm-spec/examples/wallet-with-send/v3-pretty.json +0 -207
  226. ethpm/ethpm-spec/examples/wallet-with-send/v3.json +0 -1
  227. ethpm/ethpm-spec/spec/package.spec.json +0 -379
  228. ethpm/ethpm-spec/spec/v3.spec.json +0 -483
  229. ethpm/exceptions.py +0 -68
  230. ethpm/package.py +0 -438
  231. ethpm/tools/__init__.py +0 -4
  232. ethpm/tools/builder.py +0 -930
  233. ethpm/tools/checker.py +0 -312
  234. ethpm/tools/get_manifest.py +0 -19
  235. ethpm/uri.py +0 -141
  236. ethpm/validation/__init__.py +0 -0
  237. ethpm/validation/manifest.py +0 -146
  238. ethpm/validation/misc.py +0 -39
  239. ethpm/validation/package.py +0 -80
  240. ethpm/validation/uri.py +0 -163
  241. web3/_utils/caching.py +0 -155
  242. web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
  243. web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
  244. web3/_utils/request.py +0 -265
  245. web3/pm.py +0 -602
  246. web3/tools/__init__.py +0 -4
  247. web3/tools/benchmark/__init__.py +0 -0
  248. web3/tools/benchmark/main.py +0 -185
  249. web3/tools/benchmark/node.py +0 -126
  250. web3/tools/benchmark/reporting.py +0 -39
  251. web3/tools/benchmark/utils.py +0 -69
  252. web3/tools/pytest_ethereum/__init__.py +0 -0
  253. web3/tools/pytest_ethereum/_utils.py +0 -145
  254. web3/tools/pytest_ethereum/deployer.py +0 -48
  255. web3/tools/pytest_ethereum/exceptions.py +0 -22
  256. web3/tools/pytest_ethereum/linker.py +0 -128
  257. web3/tools/pytest_ethereum/plugins.py +0 -33
  258. web3-7.0.0b1.dist-info/METADATA +0 -114
  259. web3-7.0.0b1.dist-info/RECORD +0 -280
  260. web3-7.0.0b1.dist-info/entry_points.txt +0 -2
  261. /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
web3/utils/abi.py CHANGED
@@ -1,21 +1,801 @@
1
+ import functools
1
2
  from typing import (
3
+ Any,
4
+ Callable,
5
+ Dict,
2
6
  List,
7
+ Optional,
8
+ Sequence,
9
+ Tuple,
3
10
  Union,
11
+ cast,
4
12
  )
5
13
 
6
- from web3.types import (
14
+ from eth_abi import (
15
+ codec,
16
+ )
17
+ from eth_abi.codec import (
18
+ ABICodec,
19
+ )
20
+ from eth_abi.registry import (
21
+ registry as default_registry,
22
+ )
23
+ from eth_typing import (
24
+ ABI,
25
+ ABICallable,
26
+ ABIConstructor,
27
+ ABIElement,
28
+ ABIElementInfo,
7
29
  ABIEvent,
8
- ABIFunction,
30
+ ABIFallback,
31
+ ABIReceive,
32
+ HexStr,
33
+ Primitives,
34
+ )
35
+ from eth_utils.abi import (
36
+ abi_to_signature,
37
+ event_abi_to_log_topic,
38
+ filter_abi_by_name,
39
+ filter_abi_by_type,
40
+ function_abi_to_4byte_selector,
41
+ get_abi_input_types,
42
+ get_aligned_abi_inputs,
43
+ get_normalized_abi_inputs,
44
+ )
45
+ from eth_utils.address import (
46
+ is_binary_address,
47
+ is_checksum_address,
48
+ )
49
+ from eth_utils.conversions import (
50
+ hexstr_if_str,
51
+ to_bytes,
52
+ )
53
+ from eth_utils.hexadecimal import (
54
+ encode_hex,
55
+ )
56
+ from eth_utils.toolz import (
57
+ pipe,
58
+ )
59
+ from eth_utils.types import (
60
+ is_list_like,
61
+ )
62
+ from hexbytes import (
63
+ HexBytes,
64
+ )
65
+
66
+ from web3._utils.abi import (
67
+ filter_by_argument_name,
68
+ get_abi_element_signature,
69
+ get_name_from_abi_element_identifier,
70
+ )
71
+ from web3._utils.decorators import (
72
+ deprecated_for,
73
+ )
74
+ from web3._utils.validation import (
75
+ validate_abi,
76
+ )
77
+ from web3.exceptions import (
78
+ ABIConstructorNotFound,
79
+ ABIFallbackNotFound,
80
+ ABIReceiveNotFound,
81
+ MismatchedABI,
82
+ Web3ValidationError,
83
+ Web3ValueError,
9
84
  )
85
+ from web3.types import (
86
+ ABIElementIdentifier,
87
+ )
88
+
89
+
90
+ def _filter_by_signature(signature: str, contract_abi: ABI) -> List[ABIElement]:
91
+ return [abi for abi in contract_abi if abi_to_signature(abi) == signature]
92
+
93
+
94
+ def _filter_by_argument_count(
95
+ num_arguments: int, contract_abi: ABI
96
+ ) -> List[ABIElement]:
97
+ return [
98
+ abi
99
+ for abi in contract_abi
100
+ if abi["type"] != "fallback"
101
+ and abi["type"] != "receive"
102
+ and len(abi.get("inputs", [])) == num_arguments
103
+ ]
104
+
105
+
106
+ def _filter_by_encodability(
107
+ abi_codec: codec.ABIEncoder,
108
+ args: Sequence[Any],
109
+ kwargs: Dict[str, Any],
110
+ contract_abi: ABI,
111
+ ) -> List[ABICallable]:
112
+ return [
113
+ cast(ABICallable, function_abi)
114
+ for function_abi in contract_abi
115
+ if check_if_arguments_can_be_encoded(
116
+ function_abi, *args, abi_codec=abi_codec, **kwargs
117
+ )
118
+ ]
119
+
120
+
121
+ def _get_constructor_function_abi(contract_abi: ABI) -> ABIConstructor:
122
+ """
123
+ Return the receive function ABI from the contract ABI.
124
+ """
125
+ filtered_abis = filter_abi_by_type("constructor", contract_abi)
126
+
127
+ if len(filtered_abis) > 1:
128
+ raise MismatchedABI("Multiple constructor functions found in the contract ABI.")
129
+
130
+ if filtered_abis:
131
+ return filtered_abis[0]
132
+ else:
133
+ raise ABIConstructorNotFound(
134
+ "No constructor function was found in the contract ABI."
135
+ )
136
+
137
+
138
+ def _get_receive_function_abi(contract_abi: ABI) -> ABIReceive:
139
+ """
140
+ Return the receive function ABI from the contract ABI.
141
+ """
142
+ filtered_abis = filter_abi_by_type("receive", contract_abi)
143
+
144
+ if len(filtered_abis) > 1:
145
+ raise MismatchedABI("Multiple receive functions found in the contract ABI.")
146
+
147
+ if filtered_abis:
148
+ return filtered_abis[0]
149
+ else:
150
+ raise ABIReceiveNotFound("No receive function was found in the contract ABI.")
151
+
152
+
153
+ def _get_fallback_function_abi(contract_abi: ABI) -> ABIFallback:
154
+ """
155
+ Return the fallback function ABI from the contract ABI.
156
+ """
157
+ filtered_abis = filter_abi_by_type("fallback", contract_abi)
158
+
159
+ if len(filtered_abis) > 1:
160
+ raise MismatchedABI("Multiple fallback functions found in the contract ABI.")
161
+
162
+ if filtered_abis:
163
+ return filtered_abis[0]
164
+ else:
165
+ raise ABIFallbackNotFound("No fallback function was found in the contract ABI.")
166
+
167
+
168
+ def _get_any_abi_signature_with_name(
169
+ element_name: str, elements: Sequence[ABIElement]
170
+ ) -> str:
171
+ """
172
+ Find an ABI identifier signature by element name. A signature identifier is
173
+ returned, "name(arg1Type,arg2Type,...)".
174
+
175
+ If multiple ABIs match the name and every one contain arguments, the first
176
+ result is returned. Otherwise the signature without arguments is returned.
177
+ Returns None if no ABI exists with the provided name.
178
+ """
179
+ element_signatures_with_name = [
180
+ abi_to_signature(element)
181
+ for element in elements
182
+ if element.get("name", "") == get_name_from_abi_element_identifier(element_name)
183
+ ]
184
+
185
+ if len(element_signatures_with_name) == 1:
186
+ return element_signatures_with_name[0]
187
+ elif len(element_signatures_with_name) > 1:
188
+ # Check for function signature without args
189
+ signature_without_args = f"{element_name}()"
190
+ if signature_without_args not in element_signatures_with_name:
191
+ # Element without arguments not found, use the first available signature
192
+ return element_signatures_with_name[0]
193
+ else:
194
+ return signature_without_args
195
+ else:
196
+ return None
197
+
198
+
199
+ def _build_abi_input_error(
200
+ abi: ABI,
201
+ num_args: int,
202
+ *args: Any,
203
+ abi_codec: ABICodec,
204
+ **kwargs: Any,
205
+ ) -> str:
206
+ """
207
+ Build a string representation of the ABI input error.
208
+ """
209
+ errors: Dict[str, str] = dict(
210
+ {
211
+ "zero_args": "",
212
+ "invalid_args": "",
213
+ "encoding": "",
214
+ "unexpected_args": "",
215
+ }
216
+ )
217
+
218
+ for abi_element in abi:
219
+ abi_element_input_types = get_abi_input_types(abi_element)
220
+ abi_signature = abi_to_signature(abi_element)
221
+ abi_element_name = get_name_from_abi_element_identifier(abi_signature)
222
+ types: Tuple[str, ...] = tuple()
223
+ aligned_args: Tuple[Any, ...] = tuple()
224
+
225
+ if len(abi_element_input_types) == num_args:
226
+ if num_args == 0:
227
+ if not errors["zero_args"]:
228
+ errors["zero_args"] += (
229
+ "The provided identifier matches multiple elements.\n"
230
+ f"If you meant to call `{abi_element_name}()`, "
231
+ "please specify the full signature.\n"
232
+ )
233
+
234
+ errors["zero_args"] += (
235
+ f" - signature: {abi_to_signature(abi_element)}, "
236
+ f"type: {abi_element['type']}\n"
237
+ )
238
+ else:
239
+ try:
240
+ arguments = get_normalized_abi_inputs(abi_element, *args, **kwargs)
241
+ types, aligned_args = get_aligned_abi_inputs(abi_element, arguments)
242
+ except TypeError as e:
243
+ errors["invalid_args"] += (
244
+ f"Signature: {abi_signature}, type: {abi_element['type']}\n"
245
+ f"Arguments do not match types in `{abi_signature}`.\n"
246
+ f"Error: {e}\n"
247
+ )
248
+
249
+ argument_errors = ""
250
+ for position, (_type, arg) in enumerate(zip(types, aligned_args), start=1):
251
+ if abi_codec.is_encodable(_type, arg):
252
+ argument_errors += f"Argument {position} value `{arg}` is valid.\n"
253
+ else:
254
+ argument_errors += (
255
+ f"Argument {position} value `{arg}` is not compatible with "
256
+ f"type `{_type}`.\n"
257
+ )
258
+
259
+ if argument_errors != "":
260
+ errors["encoding"] += (
261
+ f"Signature: {abi_signature}, type: {abi_element['type']}\n"
262
+ + argument_errors
263
+ )
264
+
265
+ else:
266
+ errors["unexpected_args"] += (
267
+ f"Signature: {abi_signature}, type: {abi_element['type']}\n"
268
+ f"Expected {len(abi_element_input_types)} argument(s) but received "
269
+ f"{num_args} argument(s).\n"
270
+ )
271
+
272
+ return "".join(errors.values())
273
+
274
+
275
+ def _mismatched_abi_error_diagnosis(
276
+ abi_element_identifier: ABIElementIdentifier,
277
+ abi: ABI,
278
+ num_matches: int = 0,
279
+ num_args: int = 0,
280
+ *args: Optional[Any],
281
+ abi_codec: Optional[Any] = None,
282
+ **kwargs: Optional[Any],
283
+ ) -> str:
284
+ """
285
+ Raise a ``MismatchedABI`` when a function ABI lookup results in an error.
286
+
287
+ An error may result from multiple functions matching the provided signature and
288
+ arguments or no functions are identified.
289
+ """
290
+ name = get_name_from_abi_element_identifier(abi_element_identifier)
291
+ abis_matching_names = filter_abi_by_name(name, abi)
292
+ abis_matching_arg_count = [
293
+ abi_to_signature(abi)
294
+ for abi in _filter_by_argument_count(num_args, abis_matching_names)
295
+ ]
296
+ num_abis_matching_arg_count = len(abis_matching_arg_count)
297
+
298
+ if abi_codec is None:
299
+ abi_codec = ABICodec(default_registry)
300
+
301
+ error = "ABI Not Found!\n"
302
+ if num_matches == 0 and num_abis_matching_arg_count == 0:
303
+ error += f"No element named `{name}` with {num_args} argument(s).\n"
304
+ elif num_matches > 1 or num_abis_matching_arg_count > 1:
305
+ error += (
306
+ f"Found multiple elements named `{name}` that accept {num_args} "
307
+ "argument(s).\n"
308
+ )
309
+ elif num_abis_matching_arg_count == 1:
310
+ error += (
311
+ f"Found {num_abis_matching_arg_count} element(s) named `{name}` that "
312
+ f"accept {num_args} argument(s).\n"
313
+ "The provided arguments are not valid.\n"
314
+ )
315
+ elif num_matches == 0:
316
+ error += (
317
+ f"Unable to find an element named `{name}` that matches the provided "
318
+ "identifier and argument types.\n"
319
+ )
320
+ arg_types = _extract_argument_types(*args)
321
+ kwarg_types = dict({(k, _extract_argument_types([v])) for k, v in kwargs.items()})
322
+ error += (
323
+ f"Provided argument types: ({arg_types})\n"
324
+ f"Provided keyword argument types: {kwarg_types}\n\n"
325
+ )
326
+
327
+ if abis_matching_names:
328
+ error += (
329
+ f"Tried to find a matching ABI element named `{name}`, but encountered "
330
+ "the following problems:\n"
331
+ )
332
+
333
+ error += _build_abi_input_error(
334
+ abis_matching_names,
335
+ num_args,
336
+ *args,
337
+ abi_codec=abi_codec,
338
+ **kwargs,
339
+ )
340
+
341
+ return f"\n{error}"
342
+
343
+
344
+ def _extract_argument_types(*args: Sequence[Any]) -> str:
345
+ """
346
+ Takes a list of arguments and returns a string representation of the argument types,
347
+ appropriately collapsing `tuple` types into the respective nested types.
348
+ """
349
+ collapsed_args = []
350
+
351
+ for arg in args:
352
+ if is_list_like(arg):
353
+ collapsed_nested = []
354
+ for nested in arg:
355
+ if is_list_like(nested):
356
+ collapsed_nested.append(f"({_extract_argument_types(nested)})")
357
+ else:
358
+ collapsed_nested.append(_get_argument_readable_type(nested))
359
+ collapsed_args.append(",".join(collapsed_nested))
360
+ else:
361
+ collapsed_args.append(_get_argument_readable_type(arg))
362
+
363
+ return ",".join(collapsed_args)
364
+
365
+
366
+ def _get_argument_readable_type(arg: Any) -> str:
367
+ """
368
+ Returns the class name of the argument, or `address` if the argument is an address.
369
+ """
370
+ if is_checksum_address(arg) or is_binary_address(arg):
371
+ return "address"
372
+
373
+ return arg.__class__.__name__
374
+
375
+
376
+ def _build_abi_filters(
377
+ abi_element_identifier: ABIElementIdentifier,
378
+ *args: Optional[Any],
379
+ abi_codec: Optional[Any] = None,
380
+ **kwargs: Optional[Any],
381
+ ) -> List[Callable[..., Sequence[ABIElement]]]:
382
+ """
383
+ Build a list of ABI filters to find an ABI element within a contract ABI. Each
384
+ filter is a partial function that takes a contract ABI and returns a filtered list.
385
+ Each parameter is checked before applying the relevant filter.
386
+
387
+ When the ``abi_element_identifier`` is a function name or signature and no arguments
388
+ are provided, the returned filters include the function name or signature.
389
+
390
+ A function ABI may take arguments and keyword arguments. When the ``args`` and
391
+ ``kwargs`` values are passed, several filters are combined together. Available
392
+ filters include the function name, argument count, argument name, argument type,
393
+ and argument encodability.
394
+
395
+ ``constructor``, ``fallback``, and ``receive`` ABI elements are handled only with a
396
+ filter by type.
397
+ """
398
+ if not isinstance(abi_element_identifier, str):
399
+ abi_element_identifier = get_abi_element_signature(abi_element_identifier)
400
+
401
+ if abi_element_identifier in ["constructor", "fallback", "receive"]:
402
+ return [functools.partial(filter_abi_by_type, abi_element_identifier)]
403
+
404
+ filters: List[Callable[..., Sequence[ABIElement]]] = []
405
+
406
+ arg_count = 0
407
+ if args or kwargs:
408
+ arg_count = len(args) + len(kwargs)
409
+
410
+ # Filter by arg count only if the identifier contains arguments
411
+ if "()" not in abi_element_identifier and arg_count:
412
+ filters.append(functools.partial(_filter_by_argument_count, arg_count))
413
+
414
+ if arg_count > 0:
415
+ filters.append(
416
+ functools.partial(
417
+ filter_abi_by_name,
418
+ get_name_from_abi_element_identifier(abi_element_identifier),
419
+ )
420
+ )
421
+
422
+ if args or kwargs:
423
+ if abi_codec is None:
424
+ abi_codec = ABICodec(default_registry)
425
+
426
+ filters.append(
427
+ functools.partial(
428
+ _filter_by_encodability,
429
+ abi_codec,
430
+ args,
431
+ kwargs,
432
+ )
433
+ )
434
+
435
+ if "(" in abi_element_identifier:
436
+ filters.append(
437
+ functools.partial(_filter_by_signature, abi_element_identifier)
438
+ )
439
+ else:
440
+ filters.append(
441
+ functools.partial(
442
+ filter_abi_by_name,
443
+ get_name_from_abi_element_identifier(abi_element_identifier),
444
+ )
445
+ )
446
+ if "(" in abi_element_identifier:
447
+ filters.append(
448
+ functools.partial(_filter_by_signature, abi_element_identifier)
449
+ )
450
+
451
+ return filters
452
+
453
+
454
+ def get_abi_element_info(
455
+ abi: ABI,
456
+ abi_element_identifier: ABIElementIdentifier,
457
+ *args: Optional[Sequence[Any]],
458
+ abi_codec: Optional[Any] = None,
459
+ **kwargs: Optional[Dict[str, Any]],
460
+ ) -> ABIElementInfo:
461
+ """
462
+ Information about the function ABI, selector and input arguments.
463
+
464
+ Returns the ABI which matches the provided identifier, named arguments (``args``)
465
+ and keyword args (``kwargs``).
466
+
467
+ :param abi: Contract ABI.
468
+ :type abi: `ABI`
469
+ :param abi_element_identifier: Find an element ABI with matching identifier.
470
+ :type abi_element_identifier: `ABIElementIdentifier`
471
+ :param args: Find a function ABI with matching args.
472
+ :type args: `Optional[Sequence[Any]]`
473
+ :param abi_codec: Codec used for encoding and decoding. Default with \
474
+ `strict_bytes_type_checking` enabled.
475
+ :type abi_codec: `Optional[Any]`
476
+ :param kwargs: Find an element ABI with matching kwargs.
477
+ :type kwargs: `Optional[Dict[str, Any]]`
478
+ :return: Element information including the ABI, selector and args.
479
+ :rtype: `ABIElementInfo`
480
+
481
+ .. doctest::
482
+
483
+ >>> from web3.utils.abi import get_abi_element_info
484
+ >>> abi = [
485
+ ... {
486
+ ... "constant": False,
487
+ ... "inputs": [
488
+ ... {"name": "a", "type": "uint256"},
489
+ ... {"name": "b", "type": "uint256"},
490
+ ... ],
491
+ ... "name": "multiply",
492
+ ... "outputs": [{"name": "result", "type": "uint256"}],
493
+ ... "payable": False,
494
+ ... "stateMutability": "nonpayable",
495
+ ... "type": "function",
496
+ ... }
497
+ ... ]
498
+ >>> fn_info = get_abi_element_info(abi, "multiply", *[7, 3])
499
+ >>> fn_info["abi"]
500
+ {'constant': False, 'inputs': [{'name': 'a', 'type': 'uint256'}, {\
501
+ 'name': 'b', 'type': 'uint256'}], 'name': 'multiply', 'outputs': [{\
502
+ 'name': 'result', 'type': 'uint256'}], 'payable': False, \
503
+ 'stateMutability': 'nonpayable', 'type': 'function'}
504
+ >>> fn_info["selector"]
505
+ '0x165c4a16'
506
+ >>> fn_info["arguments"]
507
+ (7, 3)
508
+ """
509
+ fn_abi = get_abi_element(
510
+ abi, abi_element_identifier, *args, abi_codec=abi_codec, **kwargs
511
+ )
512
+ fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi))
513
+ fn_inputs: Tuple[Any, ...] = tuple()
514
+
515
+ if fn_abi["type"] == "fallback" or fn_abi["type"] == "receive":
516
+ return ABIElementInfo(abi=fn_abi, selector=fn_selector, arguments=tuple())
517
+ else:
518
+ fn_inputs = get_normalized_abi_inputs(fn_abi, *args, **kwargs)
519
+ _, aligned_fn_inputs = get_aligned_abi_inputs(fn_abi, fn_inputs)
520
+
521
+ return ABIElementInfo(
522
+ abi=fn_abi, selector=fn_selector, arguments=aligned_fn_inputs
523
+ )
524
+
525
+
526
+ def get_abi_element(
527
+ abi: ABI,
528
+ abi_element_identifier: ABIElementIdentifier,
529
+ *args: Optional[Any],
530
+ abi_codec: Optional[Any] = None,
531
+ **kwargs: Optional[Any],
532
+ ) -> ABIElement:
533
+ """
534
+ Return the interface for an ``ABIElement`` from the ``abi`` that matches the
535
+ provided identifier and arguments.
536
+
537
+ ``abi`` may be a list of all ABI elements in a contract or a subset of elements.
538
+ Passing only functions or events can be useful when names are not deterministic.
539
+ For example, if names overlap between functions and events.
540
+
541
+ The ``ABIElementIdentifier`` value may be a function name, signature, or a
542
+ ``FallbackFn`` or ``ReceiveFn``. When named arguments (``args``) and/or keyword args
543
+ (``kwargs``) are provided, they are included in the search filters.
544
+
545
+ The `abi_codec` may be overridden if custom encoding and decoding is required. The
546
+ default is used if no codec is provided. More details about customizations are in
547
+ the `eth-abi Codecs Doc <https://eth-abi.readthedocs.io/en/latest/codecs.html>`__.
548
+
549
+ :param abi: Contract ABI.
550
+ :type abi: `ABI`
551
+ :param abi_element_identifier: Find an element ABI with matching identifier. The \
552
+ identifier may be a function name, signature, or ``FallbackFn`` or ``ReceiveFn``. \
553
+ A function signature is in the form ``name(arg1Type,arg2Type,...)``.
554
+ :type abi_element_identifier: `ABIElementIdentifier`
555
+ :param args: Find an element ABI with matching args.
556
+ :type args: `Optional[Sequence[Any]]`
557
+ :param abi_codec: Codec used for encoding and decoding. Default with \
558
+ `strict_bytes_type_checking` enabled.
559
+ :type abi_codec: `Optional[Any]`
560
+ :param kwargs: Find an element ABI with matching kwargs.
561
+ :type kwargs: `Optional[Dict[str, Any]]`
562
+ :return: ABI element for the specific ABI element.
563
+ :rtype: `ABIElement`
564
+
565
+ .. doctest::
566
+
567
+ >>> from web3.utils.abi import get_abi_element
568
+ >>> abi = [
569
+ ... {
570
+ ... "constant": False,
571
+ ... "inputs": [
572
+ ... {"name": "a", "type": "uint256"},
573
+ ... {"name": "b", "type": "uint256"},
574
+ ... ],
575
+ ... "name": "multiply",
576
+ ... "outputs": [{"name": "result", "type": "uint256"}],
577
+ ... "payable": False,
578
+ ... "stateMutability": "nonpayable",
579
+ ... "type": "function",
580
+ ... }
581
+ ... ]
582
+ >>> get_abi_element(abi, "multiply", *[7, 3])
583
+ {'constant': False, 'inputs': [{'name': 'a', 'type': 'uint256'}, {\
584
+ 'name': 'b', 'type': 'uint256'}], 'name': 'multiply', 'outputs': [{'name': 'result', \
585
+ 'type': 'uint256'}], 'payable': False, 'stateMutability': 'nonpayable', \
586
+ 'type': 'function'}
587
+ """
588
+ validate_abi(abi)
589
+
590
+ if abi_codec is None:
591
+ abi_codec = ABICodec(default_registry)
592
+
593
+ abi_element_matches: Sequence[ABIElement] = pipe(
594
+ abi,
595
+ *_build_abi_filters(
596
+ abi_element_identifier,
597
+ *args,
598
+ abi_codec=abi_codec,
599
+ **kwargs,
600
+ ),
601
+ )
602
+
603
+ num_matches = len(abi_element_matches)
604
+
605
+ # Raise MismatchedABI unless one match is found
606
+ if num_matches != 1:
607
+ error_diagnosis = _mismatched_abi_error_diagnosis(
608
+ abi_element_identifier,
609
+ abi,
610
+ num_matches,
611
+ len(args) + len(kwargs),
612
+ *args,
613
+ abi_codec=abi_codec,
614
+ **kwargs,
615
+ )
616
+
617
+ raise MismatchedABI(error_diagnosis)
618
+
619
+ return abi_element_matches[0]
620
+
621
+
622
+ def check_if_arguments_can_be_encoded(
623
+ abi_element: ABIElement,
624
+ *args: Optional[Sequence[Any]],
625
+ abi_codec: Optional[Any] = None,
626
+ **kwargs: Optional[Dict[str, Any]],
627
+ ) -> bool:
628
+ """
629
+ Check if the provided arguments can be encoded with the element ABI.
630
+
631
+ :param abi_element: The ABI element.
632
+ :type abi_element: `ABIElement`
633
+ :param args: Positional arguments.
634
+ :type args: `Optional[Sequence[Any]]`
635
+ :param abi_codec: Codec used for encoding and decoding. Default with \
636
+ `strict_bytes_type_checking` enabled.
637
+ :type abi_codec: `Optional[Any]`
638
+ :param kwargs: Keyword arguments.
639
+ :type kwargs: `Optional[Dict[str, Any]]`
640
+ :return: True if the arguments can be encoded, False otherwise.
641
+ :rtype: `bool`
642
+
643
+ .. doctest::
644
+
645
+ >>> from web3.utils.abi import check_if_arguments_can_be_encoded
646
+ >>> abi = {
647
+ ... "constant": False,
648
+ ... "inputs": [
649
+ ... {"name": "a", "type": "uint256"},
650
+ ... {"name": "b", "type": "uint256"},
651
+ ... ],
652
+ ... "name": "multiply",
653
+ ... "outputs": [{"name": "result", "type": "uint256"}],
654
+ ... "payable": False,
655
+ ... "stateMutability": "nonpayable",
656
+ ... "type": "function",
657
+ ... }
658
+ >>> check_if_arguments_can_be_encoded(abi, *[7, 3], **{})
659
+ True
660
+ """
661
+ if abi_element["type"] == "fallback" or abi_element["type"] == "receive":
662
+ return True
663
+
664
+ try:
665
+ arguments = get_normalized_abi_inputs(abi_element, *args, **kwargs)
666
+ except TypeError:
667
+ return False
668
+
669
+ if len(abi_element.get("inputs", ())) != len(arguments):
670
+ return False
671
+
672
+ try:
673
+ types, aligned_args = get_aligned_abi_inputs(abi_element, arguments)
674
+ except TypeError:
675
+ return False
676
+
677
+ if abi_codec is None:
678
+ abi_codec = ABICodec(default_registry)
679
+
680
+ return all(
681
+ abi_codec.is_encodable(_type, arg) for _type, arg in zip(types, aligned_args)
682
+ )
683
+
684
+
685
+ @deprecated_for("get_abi_element")
686
+ def get_event_abi(
687
+ abi: ABI,
688
+ event_name: str,
689
+ argument_names: Optional[Sequence[str]] = None,
690
+ ) -> ABIEvent:
691
+ """
692
+ .. warning::
693
+ This function is deprecated. It is unable to distinguish between
694
+ overloaded events. Use ``get_abi_element`` instead.
695
+
696
+ Find the event interface with the given name and/or arguments.
697
+
698
+ :param abi: Contract ABI.
699
+ :type abi: `ABI`
700
+ :param event_name: Find an event abi with matching event name.
701
+ :type event_name: `str`
702
+ :param argument_names: Find an event abi with matching arguments.
703
+ :type argument_names: `Optional[Sequence[str]]`
704
+ :return: ABI for the event interface.
705
+ :rtype: `ABIEvent`
706
+
707
+ .. doctest::
708
+
709
+ >>> from web3.utils import get_event_abi
710
+ >>> abi = [
711
+ ... {"type": "function", "name": "myFunction", "inputs": [], "outputs": []},
712
+ ... {"type": "function", "name": "myFunction2", "inputs": [], "outputs": []},
713
+ ... {"type": "event", "name": "MyEvent", "inputs": []}
714
+ ... ]
715
+ >>> get_event_abi(abi, 'MyEvent')
716
+ {'type': 'event', 'name': 'MyEvent', 'inputs': []}
717
+ """
718
+ filters: List[functools.partial[Sequence[ABIElement]]] = [
719
+ functools.partial(filter_abi_by_type, "event"),
720
+ ]
721
+
722
+ if event_name is None or event_name == "":
723
+ raise Web3ValidationError(
724
+ "event_name is required in order to match an event ABI."
725
+ )
726
+
727
+ filters.append(functools.partial(filter_abi_by_name, event_name))
728
+
729
+ if argument_names is not None:
730
+ filters.append(functools.partial(filter_by_argument_name, argument_names))
731
+
732
+ event_abi_candidates = cast(Sequence[ABIEvent], pipe(abi, *filters))
733
+
734
+ if len(event_abi_candidates) == 1:
735
+ return event_abi_candidates[0]
736
+ elif len(event_abi_candidates) == 0:
737
+ raise Web3ValueError("No matching events found")
738
+ else:
739
+ raise Web3ValueError("Multiple events found")
740
+
741
+
742
+ def get_event_log_topics(
743
+ event_abi: ABIEvent,
744
+ topics: Sequence[HexBytes],
745
+ ) -> Sequence[HexBytes]:
746
+ r"""
747
+ Return topics for an event ABI.
748
+
749
+ :param event_abi: Event ABI.
750
+ :type event_abi: `ABIEvent`
751
+ :param topics: Transaction topics from a `LogReceipt`.
752
+ :type topics: `Sequence[HexBytes]`
753
+ :return: Event topics for the event ABI.
754
+ :rtype: `Sequence[HexBytes]`
755
+
756
+ .. doctest::
757
+
758
+ >>> from web3.utils import get_event_log_topics
759
+ >>> abi = {
760
+ ... 'type': 'event',
761
+ ... 'anonymous': False,
762
+ ... 'name': 'MyEvent',
763
+ ... 'inputs': [
764
+ ... {
765
+ ... 'name': 's',
766
+ ... 'type': 'uint256'
767
+ ... }
768
+ ... ]
769
+ ... }
770
+ >>> keccak_signature = b'l+Ff\xba\x8d\xa5\xa9W\x17b\x1d\x87\x9aw\xder_=\x81g\t\xb9\xcb\xe9\xf0Y\xb8\xf8u\xe2\x84' # noqa: E501
771
+ >>> get_event_log_topics(abi, [keccak_signature, '0x1', '0x2'])
772
+ ['0x1', '0x2']
773
+ """
774
+ if event_abi["anonymous"]:
775
+ return topics
776
+ elif not topics or len(topics) == 0:
777
+ raise MismatchedABI("Expected non-anonymous event to have 1 or more topics")
778
+ elif event_abi_to_log_topic(event_abi) != log_topic_to_bytes(topics[0]):
779
+ raise MismatchedABI("The event signature did not match the provided ABI")
780
+ else:
781
+ return topics[1:]
782
+
10
783
 
784
+ def log_topic_to_bytes(
785
+ log_topic: Union[Primitives, HexStr, str],
786
+ ) -> bytes:
787
+ r"""
788
+ Return topic signature as bytes.
11
789
 
12
- def get_abi_input_names(abi: Union[ABIFunction, ABIEvent]) -> List[str]:
13
- if "inputs" not in abi and abi["type"] == "fallback":
14
- return []
15
- return [arg["name"] for arg in abi["inputs"]]
790
+ :param log_topic: Event topic from a `LogReceipt`.
791
+ :type log_topic: `Union[Primitives, HexStr, str]`
792
+ :return: Topic signature as bytes.
793
+ :rtype: `bytes`
16
794
 
795
+ .. doctest::
17
796
 
18
- def get_abi_output_names(abi: Union[ABIFunction]) -> List[str]:
19
- if "outputs" not in abi and abi["type"] == "fallback":
20
- return []
21
- return [arg["name"] for arg in abi["outputs"]]
797
+ >>> from web3.utils import log_topic_to_bytes
798
+ >>> log_topic_to_bytes('0xa12fd1')
799
+ b'\xa1/\xd1'
800
+ """
801
+ return hexstr_if_str(to_bytes, log_topic)