web3 6.20.2__py3-none-any.whl → 7.0.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 (270) hide show
  1. ens/__init__.py +13 -2
  2. ens/_normalization.py +2 -17
  3. ens/async_ens.py +33 -21
  4. ens/base_ens.py +3 -1
  5. ens/ens.py +16 -11
  6. ens/exceptions.py +16 -29
  7. ens/specs/nf.json +1 -1
  8. ens/specs/normalization_spec.json +1 -1
  9. ens/utils.py +52 -63
  10. web3/__init__.py +20 -24
  11. web3/_utils/abi.py +115 -271
  12. web3/_utils/async_transactions.py +7 -4
  13. web3/_utils/batching.py +217 -0
  14. web3/_utils/blocks.py +6 -2
  15. web3/_utils/caching.py +128 -5
  16. web3/_utils/compat/__init__.py +2 -3
  17. web3/_utils/contract_sources/compile_contracts.py +1 -1
  18. web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
  19. web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
  20. web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
  21. web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
  22. web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
  23. web3/_utils/contract_sources/contract_data/event_contracts.py +5 -5
  24. web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
  25. web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
  26. web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
  27. web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
  28. web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
  29. web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
  30. web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
  31. web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
  32. web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
  33. web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
  34. web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
  35. web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
  36. web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
  37. web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
  38. web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
  39. web3/_utils/contracts.py +130 -236
  40. web3/_utils/datatypes.py +5 -1
  41. web3/_utils/decorators.py +13 -23
  42. web3/_utils/empty.py +1 -1
  43. web3/_utils/encoding.py +16 -12
  44. web3/_utils/ens.py +2 -1
  45. web3/_utils/error_formatters_utils.py +5 -3
  46. web3/_utils/events.py +66 -69
  47. web3/_utils/fee_utils.py +1 -3
  48. web3/_utils/filters.py +24 -22
  49. web3/_utils/formatters.py +2 -2
  50. web3/_utils/http.py +5 -3
  51. web3/_utils/http_session_manager.py +303 -0
  52. web3/_utils/math.py +14 -15
  53. web3/_utils/method_formatters.py +34 -36
  54. web3/_utils/module.py +2 -1
  55. web3/_utils/module_testing/__init__.py +0 -3
  56. web3/_utils/module_testing/eth_module.py +695 -643
  57. web3/_utils/module_testing/module_testing_utils.py +61 -34
  58. web3/_utils/module_testing/persistent_connection_provider.py +56 -25
  59. web3/_utils/module_testing/utils.py +258 -0
  60. web3/_utils/module_testing/web3_module.py +438 -17
  61. web3/_utils/normalizers.py +13 -11
  62. web3/_utils/rpc_abi.py +5 -32
  63. web3/_utils/threads.py +8 -7
  64. web3/_utils/transactions.py +14 -12
  65. web3/_utils/type_conversion.py +5 -1
  66. web3/_utils/validation.py +17 -17
  67. web3/auto/gethdev.py +7 -2
  68. web3/beacon/__init__.py +6 -1
  69. web3/beacon/async_beacon.py +9 -5
  70. web3/beacon/{main.py → beacon.py} +7 -5
  71. web3/contract/__init__.py +7 -0
  72. web3/contract/async_contract.py +47 -46
  73. web3/contract/base_contract.py +183 -158
  74. web3/contract/contract.py +49 -43
  75. web3/contract/utils.py +203 -59
  76. web3/datastructures.py +79 -31
  77. web3/eth/__init__.py +7 -0
  78. web3/eth/async_eth.py +39 -51
  79. web3/eth/base_eth.py +17 -10
  80. web3/eth/eth.py +30 -68
  81. web3/exceptions.py +108 -82
  82. web3/gas_strategies/time_based.py +8 -6
  83. web3/geth.py +1 -254
  84. web3/main.py +75 -122
  85. web3/manager.py +316 -146
  86. web3/method.py +38 -31
  87. web3/middleware/__init__.py +67 -89
  88. web3/middleware/attrdict.py +36 -49
  89. web3/middleware/base.py +174 -0
  90. web3/middleware/buffered_gas_estimate.py +20 -21
  91. web3/middleware/filter.py +157 -117
  92. web3/middleware/formatting.py +124 -108
  93. web3/middleware/gas_price_strategy.py +20 -32
  94. web3/middleware/names.py +29 -26
  95. web3/middleware/proof_of_authority.py +68 -0
  96. web3/middleware/pythonic.py +2 -2
  97. web3/middleware/signing.py +74 -89
  98. web3/middleware/stalecheck.py +52 -79
  99. web3/middleware/validation.py +5 -13
  100. web3/module.py +54 -10
  101. web3/providers/__init__.py +10 -6
  102. web3/providers/async_base.py +117 -39
  103. web3/providers/auto.py +3 -3
  104. web3/providers/base.py +89 -33
  105. web3/providers/eth_tester/__init__.py +5 -0
  106. web3/providers/eth_tester/defaults.py +1 -64
  107. web3/providers/eth_tester/main.py +99 -31
  108. web3/providers/eth_tester/middleware.py +45 -73
  109. web3/providers/ipc.py +42 -46
  110. web3/providers/{websocket/websocket.py → legacy_websocket.py} +32 -7
  111. web3/providers/persistent/__init__.py +22 -0
  112. web3/providers/persistent/async_ipc.py +153 -0
  113. web3/providers/{persistent.py → persistent/persistent.py} +106 -25
  114. web3/providers/persistent/persistent_connection.py +84 -0
  115. web3/providers/{websocket → persistent}/request_processor.py +94 -32
  116. web3/providers/persistent/utils.py +43 -0
  117. web3/providers/{websocket/websocket_v2.py → persistent/websocket.py} +29 -28
  118. web3/providers/rpc/__init__.py +11 -0
  119. web3/providers/rpc/async_rpc.py +171 -0
  120. web3/providers/rpc/rpc.py +179 -0
  121. web3/providers/rpc/utils.py +92 -0
  122. web3/testing.py +4 -4
  123. web3/tools/benchmark/main.py +22 -22
  124. web3/tools/benchmark/node.py +2 -8
  125. web3/tools/benchmark/reporting.py +2 -2
  126. web3/tools/benchmark/utils.py +1 -1
  127. web3/tracing.py +9 -5
  128. web3/types.py +30 -107
  129. web3/utils/__init__.py +58 -5
  130. web3/utils/abi.py +575 -10
  131. web3/utils/async_exception_handling.py +19 -7
  132. web3/utils/caching.py +32 -13
  133. web3/utils/exception_handling.py +7 -5
  134. {web3-6.20.2.dist-info → web3-7.0.0.dist-info}/LICENSE +1 -1
  135. web3-7.0.0.dist-info/METADATA +112 -0
  136. web3-7.0.0.dist-info/RECORD +167 -0
  137. {web3-6.20.2.dist-info → web3-7.0.0.dist-info}/WHEEL +1 -1
  138. {web3-6.20.2.dist-info → web3-7.0.0.dist-info}/top_level.txt +0 -1
  139. ethpm/__init__.py +0 -20
  140. ethpm/_utils/__init__.py +0 -0
  141. ethpm/_utils/backend.py +0 -93
  142. ethpm/_utils/cache.py +0 -44
  143. ethpm/_utils/chains.py +0 -119
  144. ethpm/_utils/contract.py +0 -35
  145. ethpm/_utils/deployments.py +0 -145
  146. ethpm/_utils/ipfs.py +0 -116
  147. ethpm/_utils/protobuf/__init__.py +0 -0
  148. ethpm/_utils/protobuf/ipfs_file_pb2.py +0 -33
  149. ethpm/_utils/registry.py +0 -29
  150. ethpm/assets/__init__.py +0 -0
  151. ethpm/assets/ens/v3.json +0 -1
  152. ethpm/assets/escrow/with_bytecode_v3.json +0 -1
  153. ethpm/assets/ipfs_file.proto +0 -32
  154. ethpm/assets/owned/output_v3.json +0 -1
  155. ethpm/assets/owned/with_contract_type_v3.json +0 -1
  156. ethpm/assets/registry/contracts/Authority.sol +0 -156
  157. ethpm/assets/registry/contracts/IndexedOrderedSetLib.sol +0 -106
  158. ethpm/assets/registry/contracts/PackageDB.sol +0 -225
  159. ethpm/assets/registry/contracts/PackageRegistry.sol +0 -361
  160. ethpm/assets/registry/contracts/PackageRegistryInterface.sol +0 -97
  161. ethpm/assets/registry/contracts/ReleaseDB.sol +0 -309
  162. ethpm/assets/registry/contracts/ReleaseValidator.sol +0 -152
  163. ethpm/assets/registry/solc_input.json +0 -1
  164. ethpm/assets/registry/solc_output.json +0 -1
  165. ethpm/assets/registry/v3.json +0 -1
  166. ethpm/assets/safe-math-lib/v3-strict-no-deployments.json +0 -1
  167. ethpm/assets/simple-registry/contracts/Ownable.sol +0 -63
  168. ethpm/assets/simple-registry/contracts/PackageRegistry.sol +0 -373
  169. ethpm/assets/simple-registry/contracts/PackageRegistryInterface.sol +0 -96
  170. ethpm/assets/simple-registry/solc_input.json +0 -33
  171. ethpm/assets/simple-registry/solc_output.json +0 -1
  172. ethpm/assets/simple-registry/v3.json +0 -1
  173. ethpm/assets/standard-token/output_v3.json +0 -1
  174. ethpm/assets/standard-token/with_bytecode_v3.json +0 -1
  175. ethpm/assets/vyper_registry/0.1.0.json +0 -1
  176. ethpm/assets/vyper_registry/registry.vy +0 -216
  177. ethpm/assets/vyper_registry/registry_with_delete.vy +0 -244
  178. ethpm/backends/__init__.py +0 -0
  179. ethpm/backends/base.py +0 -43
  180. ethpm/backends/http.py +0 -108
  181. ethpm/backends/ipfs.py +0 -219
  182. ethpm/backends/registry.py +0 -154
  183. ethpm/constants.py +0 -17
  184. ethpm/contract.py +0 -187
  185. ethpm/dependencies.py +0 -58
  186. ethpm/deployments.py +0 -80
  187. ethpm/ethpm-spec/examples/escrow/1.0.0-pretty.json +0 -146
  188. ethpm/ethpm-spec/examples/escrow/1.0.0.json +0 -1
  189. ethpm/ethpm-spec/examples/escrow/contracts/Escrow.sol +0 -32
  190. ethpm/ethpm-spec/examples/escrow/contracts/SafeSendLib.sol +0 -20
  191. ethpm/ethpm-spec/examples/escrow/v3-pretty.json +0 -171
  192. ethpm/ethpm-spec/examples/escrow/v3.json +0 -1
  193. ethpm/ethpm-spec/examples/owned/1.0.0-pretty.json +0 -21
  194. ethpm/ethpm-spec/examples/owned/1.0.0.json +0 -1
  195. ethpm/ethpm-spec/examples/owned/contracts/Owned.sol +0 -12
  196. ethpm/ethpm-spec/examples/owned/v3-pretty.json +0 -27
  197. ethpm/ethpm-spec/examples/owned/v3.json +0 -1
  198. ethpm/ethpm-spec/examples/piper-coin/1.0.0-pretty.json +0 -31
  199. ethpm/ethpm-spec/examples/piper-coin/1.0.0.json +0 -1
  200. ethpm/ethpm-spec/examples/piper-coin/v3-pretty.json +0 -21
  201. ethpm/ethpm-spec/examples/piper-coin/v3.json +0 -1
  202. ethpm/ethpm-spec/examples/safe-math-lib/1.0.0-pretty.json +0 -85
  203. ethpm/ethpm-spec/examples/safe-math-lib/1.0.0.json +0 -1
  204. ethpm/ethpm-spec/examples/safe-math-lib/contracts/SafeMathLib.sol +0 -24
  205. ethpm/ethpm-spec/examples/safe-math-lib/v3-pretty.json +0 -117
  206. ethpm/ethpm-spec/examples/safe-math-lib/v3.json +0 -1
  207. ethpm/ethpm-spec/examples/standard-token/1.0.0-pretty.json +0 -55
  208. ethpm/ethpm-spec/examples/standard-token/1.0.0.json +0 -1
  209. ethpm/ethpm-spec/examples/standard-token/contracts/AbstractToken.sol +0 -20
  210. ethpm/ethpm-spec/examples/standard-token/contracts/StandardToken.sol +0 -84
  211. ethpm/ethpm-spec/examples/standard-token/v3-pretty.json +0 -460
  212. ethpm/ethpm-spec/examples/standard-token/v3.json +0 -1
  213. ethpm/ethpm-spec/examples/transferable/1.0.0-pretty.json +0 -21
  214. ethpm/ethpm-spec/examples/transferable/1.0.0.json +0 -1
  215. ethpm/ethpm-spec/examples/transferable/contracts/Transferable.sol +0 -14
  216. ethpm/ethpm-spec/examples/transferable/v3-pretty.json +0 -27
  217. ethpm/ethpm-spec/examples/transferable/v3.json +0 -1
  218. ethpm/ethpm-spec/examples/wallet/1.0.0-pretty.json +0 -120
  219. ethpm/ethpm-spec/examples/wallet/1.0.0.json +0 -1
  220. ethpm/ethpm-spec/examples/wallet/contracts/Wallet.sol +0 -41
  221. ethpm/ethpm-spec/examples/wallet/v3-pretty.json +0 -181
  222. ethpm/ethpm-spec/examples/wallet/v3.json +0 -1
  223. ethpm/ethpm-spec/examples/wallet-with-send/1.0.0-pretty.json +0 -135
  224. ethpm/ethpm-spec/examples/wallet-with-send/1.0.0.json +0 -1
  225. ethpm/ethpm-spec/examples/wallet-with-send/contracts/WalletWithSend.sol +0 -18
  226. ethpm/ethpm-spec/examples/wallet-with-send/v3-pretty.json +0 -207
  227. ethpm/ethpm-spec/examples/wallet-with-send/v3.json +0 -1
  228. ethpm/ethpm-spec/spec/package.spec.json +0 -379
  229. ethpm/ethpm-spec/spec/v3.spec.json +0 -483
  230. ethpm/exceptions.py +0 -68
  231. ethpm/package.py +0 -438
  232. ethpm/tools/__init__.py +0 -4
  233. ethpm/tools/builder.py +0 -930
  234. ethpm/tools/checker.py +0 -312
  235. ethpm/tools/get_manifest.py +0 -19
  236. ethpm/uri.py +0 -141
  237. ethpm/validation/__init__.py +0 -0
  238. ethpm/validation/manifest.py +0 -146
  239. ethpm/validation/misc.py +0 -39
  240. ethpm/validation/package.py +0 -80
  241. ethpm/validation/uri.py +0 -163
  242. web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
  243. web3/_utils/miner.py +0 -88
  244. web3/_utils/module_testing/go_ethereum_personal_module.py +0 -323
  245. web3/_utils/request.py +0 -265
  246. web3/middleware/abi.py +0 -11
  247. web3/middleware/async_cache.py +0 -99
  248. web3/middleware/cache.py +0 -374
  249. web3/middleware/exception_handling.py +0 -49
  250. web3/middleware/exception_retry_request.py +0 -188
  251. web3/middleware/fixture.py +0 -190
  252. web3/middleware/geth_poa.py +0 -81
  253. web3/middleware/normalize_request_parameters.py +0 -11
  254. web3/middleware/simulate_unmined_transaction.py +0 -43
  255. web3/pm.py +0 -602
  256. web3/providers/async_rpc.py +0 -99
  257. web3/providers/rpc.py +0 -98
  258. web3/providers/websocket/__init__.py +0 -11
  259. web3/providers/websocket/websocket_connection.py +0 -42
  260. web3/tools/__init__.py +0 -4
  261. web3/tools/pytest_ethereum/__init__.py +0 -0
  262. web3/tools/pytest_ethereum/_utils.py +0 -145
  263. web3/tools/pytest_ethereum/deployer.py +0 -48
  264. web3/tools/pytest_ethereum/exceptions.py +0 -22
  265. web3/tools/pytest_ethereum/linker.py +0 -128
  266. web3/tools/pytest_ethereum/plugins.py +0 -33
  267. web3-6.20.2.dist-info/METADATA +0 -103
  268. web3-6.20.2.dist-info/RECORD +0 -283
  269. web3-6.20.2.dist-info/entry_points.txt +0 -2
  270. /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
web3/utils/abi.py CHANGED
@@ -1,21 +1,586 @@
1
+ import functools
1
2
  from typing import (
3
+ Any,
4
+ Dict,
2
5
  List,
6
+ Optional,
7
+ Sequence,
8
+ Tuple,
3
9
  Union,
10
+ cast,
4
11
  )
5
12
 
6
- from web3.types import (
13
+ from eth_abi import (
14
+ codec,
15
+ )
16
+ from eth_abi.codec import (
17
+ ABICodec,
18
+ )
19
+ from eth_abi.registry import (
20
+ registry as default_registry,
21
+ )
22
+ from eth_typing import (
23
+ ABI,
24
+ ABICallable,
25
+ ABIConstructor,
26
+ ABIElement,
27
+ ABIElementInfo,
7
28
  ABIEvent,
8
- ABIFunction,
29
+ ABIFallback,
30
+ ABIReceive,
31
+ HexStr,
32
+ Primitives,
33
+ )
34
+ from eth_utils.address import (
35
+ is_binary_address,
36
+ is_checksum_address,
37
+ )
38
+ from eth_utils.conversions import (
39
+ hexstr_if_str,
40
+ to_bytes,
41
+ )
42
+ from eth_utils.hexadecimal import (
43
+ encode_hex,
44
+ )
45
+ from eth_utils.toolz import (
46
+ pipe,
47
+ )
48
+ from eth_utils.types import (
49
+ is_list_like,
50
+ is_text,
51
+ )
52
+ from hexbytes import (
53
+ HexBytes,
54
+ )
55
+
56
+ from web3._utils.abi import (
57
+ filter_by_argument_name,
58
+ )
59
+ from web3._utils.abi_element_identifiers import (
60
+ FallbackFn,
61
+ ReceiveFn,
9
62
  )
63
+ from web3.exceptions import (
64
+ ABIConstructorNotFound,
65
+ ABIFallbackNotFound,
66
+ ABIReceiveNotFound,
67
+ MismatchedABI,
68
+ Web3TypeError,
69
+ Web3ValidationError,
70
+ Web3ValueError,
71
+ )
72
+ from web3.types import (
73
+ ABIElementIdentifier,
74
+ )
75
+
76
+ from eth_utils.abi import ( # noqa
77
+ abi_to_signature,
78
+ event_abi_to_log_topic,
79
+ filter_abi_by_name,
80
+ filter_abi_by_type,
81
+ function_abi_to_4byte_selector,
82
+ get_aligned_abi_inputs,
83
+ get_normalized_abi_inputs,
84
+ )
85
+
86
+
87
+ def _filter_by_argument_count(
88
+ num_arguments: int, contract_abi: ABI
89
+ ) -> List[ABIElement]:
90
+ return [
91
+ abi
92
+ for abi in contract_abi
93
+ if abi["type"] != "fallback"
94
+ and abi["type"] != "receive"
95
+ and len(abi.get("inputs", [])) == num_arguments
96
+ ]
97
+
98
+
99
+ def _filter_by_encodability(
100
+ abi_codec: codec.ABIEncoder,
101
+ contract_abi: ABI,
102
+ *args: Optional[Sequence[Any]],
103
+ **kwargs: Optional[Dict[str, Any]],
104
+ ) -> List[ABICallable]:
105
+ return [
106
+ cast(ABICallable, function_abi)
107
+ for function_abi in contract_abi
108
+ if check_if_arguments_can_be_encoded(
109
+ function_abi, *args, abi_codec=abi_codec, **kwargs
110
+ )
111
+ ]
112
+
113
+
114
+ def _get_constructor_function_abi(contract_abi: ABI) -> ABIConstructor:
115
+ """
116
+ Return the receive function ABI from the contract ABI.
117
+ """
118
+ filtered_abis = filter_abi_by_type("constructor", contract_abi)
119
+
120
+ if len(filtered_abis) > 1:
121
+ raise MismatchedABI("Multiple constructor functions found in the contract ABI.")
122
+
123
+ if filtered_abis:
124
+ return filtered_abis[0]
125
+ else:
126
+ raise ABIConstructorNotFound(
127
+ "No constructor function was found in the contract ABI."
128
+ )
129
+
130
+
131
+ def _get_receive_function_abi(contract_abi: ABI) -> ABIReceive:
132
+ """
133
+ Return the receive function ABI from the contract ABI.
134
+ """
135
+ filtered_abis = filter_abi_by_type("receive", contract_abi)
136
+
137
+ if len(filtered_abis) > 1:
138
+ raise MismatchedABI("Multiple receive functions found in the contract ABI.")
139
+
140
+ if filtered_abis:
141
+ return filtered_abis[0]
142
+ else:
143
+ raise ABIReceiveNotFound("No receive function was found in the contract ABI.")
144
+
145
+
146
+ def _get_fallback_function_abi(contract_abi: ABI) -> ABIFallback:
147
+ """
148
+ Return the fallback function ABI from the contract ABI.
149
+ """
150
+ filtered_abis = filter_abi_by_type("fallback", contract_abi)
151
+
152
+ if len(filtered_abis) > 1:
153
+ raise MismatchedABI("Multiple fallback functions found in the contract ABI.")
154
+
155
+ if filtered_abis:
156
+ return filtered_abis[0]
157
+ else:
158
+ raise ABIFallbackNotFound("No fallback function was found in the contract ABI.")
159
+
160
+
161
+ def _mismatched_abi_error_diagnosis(
162
+ 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]],
168
+ ) -> str:
169
+ """
170
+ Raise a ``MismatchedABI`` when a function ABI lookup results in an error.
171
+
172
+ An error may result from multiple functions matching the provided signature and
173
+ arguments or no functions are identified.
174
+ """
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
+ )
186
+
187
+ collapsed_args = _extract_argument_types(*args)
188
+ collapsed_kwargs = dict(
189
+ {(k, _extract_argument_types([v])) for k, v in kwargs.items()}
190
+ )
191
+
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}"
199
+ )
200
+
201
+
202
+ def _extract_argument_types(*args: Sequence[Any]) -> str:
203
+ """
204
+ Takes a list of arguments and returns a string representation of the argument types,
205
+ appropriately collapsing `tuple` types into the respective nested types.
206
+ """
207
+ collapsed_args = []
208
+
209
+ for arg in args:
210
+ if is_list_like(arg):
211
+ collapsed_nested = []
212
+ for nested in arg:
213
+ if is_list_like(nested):
214
+ collapsed_nested.append(f"({_extract_argument_types(nested)})")
215
+ else:
216
+ collapsed_nested.append(_get_argument_readable_type(nested))
217
+ collapsed_args.append(",".join(collapsed_nested))
218
+ else:
219
+ collapsed_args.append(_get_argument_readable_type(arg))
220
+
221
+ return ",".join(collapsed_args)
222
+
223
+
224
+ def _get_argument_readable_type(arg: Any) -> str:
225
+ """
226
+ Returns the class name of the argument, or `address` if the argument is an address.
227
+ """
228
+ if is_checksum_address(arg) or is_binary_address(arg):
229
+ return "address"
230
+
231
+ return arg.__class__.__name__
232
+
233
+
234
+ def get_abi_element_info(
235
+ abi: ABI,
236
+ abi_element_identifier: ABIElementIdentifier,
237
+ *args: Optional[Sequence[Any]],
238
+ abi_codec: Optional[Any] = None,
239
+ **kwargs: Optional[Dict[str, Any]],
240
+ ) -> ABIElementInfo:
241
+ """
242
+ Information about the function ABI, selector and input arguments.
243
+
244
+ Returns the ABI which matches the provided identifier, named arguments (``args``)
245
+ and keyword args (``kwargs``).
246
+
247
+ :param abi: Contract ABI.
248
+ :type abi: `ABI`
249
+ :param abi_element_identifier: Find an element ABI with matching identifier.
250
+ :type abi_element_identifier: `ABIElementIdentifier`
251
+ :param args: Find a function ABI with matching args.
252
+ :type args: `Optional[Sequence[Any]]`
253
+ :param abi_codec: Codec used for encoding and decoding. Default with \
254
+ `strict_bytes_type_checking` enabled.
255
+ :type abi_codec: `Optional[Any]`
256
+ :param kwargs: Find an element ABI with matching kwargs.
257
+ :type kwargs: `Optional[Dict[str, Any]]`
258
+ :return: Element information including the ABI, selector and args.
259
+ :rtype: `ABIElementInfo`
260
+
261
+ .. doctest::
262
+
263
+ >>> from web3.utils.abi import get_abi_element_info
264
+ >>> abi = [
265
+ ... {
266
+ ... "constant": False,
267
+ ... "inputs": [
268
+ ... {"name": "a", "type": "uint256"},
269
+ ... {"name": "b", "type": "uint256"},
270
+ ... ],
271
+ ... "name": "multiply",
272
+ ... "outputs": [{"name": "result", "type": "uint256"}],
273
+ ... "payable": False,
274
+ ... "stateMutability": "nonpayable",
275
+ ... "type": "function",
276
+ ... }
277
+ ... ]
278
+ >>> fn_info = get_abi_element_info(abi, "multiply", *[7, 3])
279
+ >>> fn_info["abi"]
280
+ {'constant': False, 'inputs': [{'name': 'a', 'type': 'uint256'}, {\
281
+ 'name': 'b', 'type': 'uint256'}], 'name': 'multiply', 'outputs': [{\
282
+ 'name': 'result', 'type': 'uint256'}], 'payable': False, \
283
+ 'stateMutability': 'nonpayable', 'type': 'function'}
284
+ >>> fn_info["selector"]
285
+ '0x165c4a16'
286
+ >>> fn_info["arguments"]
287
+ (7, 3)
288
+ """
289
+ fn_abi = get_abi_element(
290
+ abi, abi_element_identifier, *args, abi_codec=abi_codec, **kwargs
291
+ )
292
+ fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi))
293
+ fn_inputs: Tuple[Any, ...] = tuple()
294
+
295
+ if fn_abi["type"] == "fallback" or fn_abi["type"] == "receive":
296
+ return ABIElementInfo(abi=fn_abi, selector=fn_selector, arguments=tuple())
297
+ else:
298
+ fn_inputs = get_normalized_abi_inputs(fn_abi, *args, **kwargs)
299
+ _, aligned_fn_inputs = get_aligned_abi_inputs(fn_abi, fn_inputs)
300
+
301
+ return ABIElementInfo(
302
+ abi=fn_abi, selector=fn_selector, arguments=aligned_fn_inputs
303
+ )
304
+
305
+
306
+ def get_abi_element(
307
+ abi: ABI,
308
+ abi_element_identifier: ABIElementIdentifier,
309
+ *args: Optional[Sequence[Any]],
310
+ abi_codec: Optional[Any] = None,
311
+ **kwargs: Optional[Dict[str, Any]],
312
+ ) -> ABIElement:
313
+ """
314
+ Return the interface for an ``ABIElement`` which matches the provided identifier
315
+ and arguments.
316
+
317
+ The ABI which matches the provided identifier, named arguments (``args``) and
318
+ keyword args (``kwargs``) will be returned.
319
+
320
+ The `abi_codec` may be overridden if custom encoding and decoding is required. The
321
+ default is used if no codec is provided. More details about customizations are in
322
+ the `eth-abi Codecs Doc <https://eth-abi.readthedocs.io/en/latest/codecs.html>`__.
323
+
324
+ :param abi: Contract ABI.
325
+ :type abi: `ABI`
326
+ :param abi_element_identifier: Find an element ABI with matching identifier.
327
+ :type abi_element_identifier: `ABIElementIdentifier`
328
+ :param args: Find an element ABI with matching args.
329
+ :type args: `Optional[Sequence[Any]]`
330
+ :param abi_codec: Codec used for encoding and decoding. Default with \
331
+ `strict_bytes_type_checking` enabled.
332
+ :type abi_codec: `Optional[Any]`
333
+ :param kwargs: Find an element ABI with matching kwargs.
334
+ :type kwargs: `Optional[Dict[str, Any]]`
335
+ :return: ABI element for the specific ABI element.
336
+ :rtype: `ABIElement`
337
+
338
+ .. doctest::
339
+
340
+ >>> from web3.utils.abi import get_abi_element
341
+ >>> abi = [
342
+ ... {
343
+ ... "constant": False,
344
+ ... "inputs": [
345
+ ... {"name": "a", "type": "uint256"},
346
+ ... {"name": "b", "type": "uint256"},
347
+ ... ],
348
+ ... "name": "multiply",
349
+ ... "outputs": [{"name": "result", "type": "uint256"}],
350
+ ... "payable": False,
351
+ ... "stateMutability": "nonpayable",
352
+ ... "type": "function",
353
+ ... }
354
+ ... ]
355
+ >>> get_abi_element(abi, "multiply", *[7, 3])
356
+ {'constant': False, 'inputs': [{'name': 'a', 'type': 'uint256'}, {\
357
+ 'name': 'b', 'type': 'uint256'}], 'name': 'multiply', 'outputs': [{'name': 'result', \
358
+ 'type': 'uint256'}], 'payable': False, 'stateMutability': 'nonpayable', \
359
+ 'type': 'function'}
360
+ """
361
+ if abi_codec is None:
362
+ abi_codec = ABICodec(default_registry)
363
+
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
391
+ )
392
+
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
+ ]
397
+
398
+ error_diagnosis = _mismatched_abi_error_diagnosis(
399
+ abi_element_identifier,
400
+ matching_function_signatures,
401
+ len(filtered_abis_by_arg_count),
402
+ len(elements_with_encodable_args),
403
+ *args,
404
+ **kwargs,
405
+ )
406
+
407
+ raise MismatchedABI(error_diagnosis)
408
+
409
+ return elements_with_encodable_args[0]
410
+
411
+
412
+ def check_if_arguments_can_be_encoded(
413
+ abi_element: ABIElement,
414
+ *args: Optional[Sequence[Any]],
415
+ abi_codec: Optional[Any] = None,
416
+ **kwargs: Optional[Dict[str, Any]],
417
+ ) -> bool:
418
+ """
419
+ Check if the provided arguments can be encoded with the element ABI.
420
+
421
+ :param abi_element: The ABI element.
422
+ :type abi_element: `ABIElement`
423
+ :param args: Positional arguments.
424
+ :type args: `Optional[Sequence[Any]]`
425
+ :param abi_codec: Codec used for encoding and decoding. Default with \
426
+ `strict_bytes_type_checking` enabled.
427
+ :type abi_codec: `Optional[Any]`
428
+ :param kwargs: Keyword arguments.
429
+ :type kwargs: `Optional[Dict[str, Any]]`
430
+ :return: True if the arguments can be encoded, False otherwise.
431
+ :rtype: `bool`
432
+
433
+ .. doctest::
434
+
435
+ >>> from web3.utils.abi import check_if_arguments_can_be_encoded
436
+ >>> abi = {
437
+ ... "constant": False,
438
+ ... "inputs": [
439
+ ... {"name": "a", "type": "uint256"},
440
+ ... {"name": "b", "type": "uint256"},
441
+ ... ],
442
+ ... "name": "multiply",
443
+ ... "outputs": [{"name": "result", "type": "uint256"}],
444
+ ... "payable": False,
445
+ ... "stateMutability": "nonpayable",
446
+ ... "type": "function",
447
+ ... }
448
+ >>> check_if_arguments_can_be_encoded(abi, *[7, 3], **{})
449
+ True
450
+ """
451
+ if abi_element["type"] == "fallback" or abi_element["type"] == "receive":
452
+ return True
453
+
454
+ try:
455
+ arguments = get_normalized_abi_inputs(abi_element, *args, **kwargs)
456
+ except TypeError:
457
+ return False
458
+
459
+ if len(abi_element.get("inputs", ())) != len(arguments):
460
+ return False
461
+
462
+ try:
463
+ types, aligned_args = get_aligned_abi_inputs(abi_element, arguments)
464
+ except TypeError:
465
+ return False
466
+
467
+ if abi_codec is None:
468
+ abi_codec = ABICodec(default_registry)
469
+
470
+ return all(
471
+ abi_codec.is_encodable(_type, arg) for _type, arg in zip(types, aligned_args)
472
+ )
473
+
474
+
475
+ def get_event_abi(
476
+ abi: ABI,
477
+ event_name: str,
478
+ argument_names: Optional[Sequence[str]] = None,
479
+ ) -> ABIEvent:
480
+ """
481
+ Find the event interface with the given name and/or arguments.
482
+
483
+ :param abi: Contract ABI.
484
+ :type abi: `ABI`
485
+ :param event_name: Find an event abi with matching event name.
486
+ :type event_name: `str`
487
+ :param argument_names: Find an event abi with matching arguments.
488
+ :type argument_names: `Optional[Sequence[str]]`
489
+ :return: ABI for the event interface.
490
+ :rtype: `ABIEvent`
491
+
492
+ .. doctest::
493
+
494
+ >>> from web3.utils import get_event_abi
495
+ >>> abi = [
496
+ ... {"type": "function", "name": "myFunction", "inputs": [], "outputs": []},
497
+ ... {"type": "function", "name": "myFunction2", "inputs": [], "outputs": []},
498
+ ... {"type": "event", "name": "MyEvent", "inputs": []}
499
+ ... ]
500
+ >>> get_event_abi(abi, 'MyEvent')
501
+ {'type': 'event', 'name': 'MyEvent', 'inputs': []}
502
+ """
503
+ filters: List[functools.partial[Sequence[ABIElement]]] = [
504
+ functools.partial(filter_abi_by_type, "event"),
505
+ ]
506
+
507
+ if event_name is None or event_name == "":
508
+ raise Web3ValidationError(
509
+ "event_name is required in order to match an event ABI."
510
+ )
511
+
512
+ filters.append(functools.partial(filter_abi_by_name, event_name))
513
+
514
+ if argument_names is not None:
515
+ filters.append(functools.partial(filter_by_argument_name, argument_names))
516
+
517
+ event_abi_candidates = cast(Sequence[ABIEvent], pipe(abi, *filters))
518
+
519
+ if len(event_abi_candidates) == 1:
520
+ return event_abi_candidates[0]
521
+ elif len(event_abi_candidates) == 0:
522
+ raise Web3ValueError("No matching events found")
523
+ else:
524
+ raise Web3ValueError("Multiple events found")
525
+
526
+
527
+ def get_event_log_topics(
528
+ event_abi: ABIEvent,
529
+ topics: Sequence[HexBytes],
530
+ ) -> Sequence[HexBytes]:
531
+ r"""
532
+ Return topics for an event ABI.
533
+
534
+ :param event_abi: Event ABI.
535
+ :type event_abi: `ABIEvent`
536
+ :param topics: Transaction topics from a `LogReceipt`.
537
+ :type topics: `Sequence[HexBytes]`
538
+ :return: Event topics for the event ABI.
539
+ :rtype: `Sequence[HexBytes]`
540
+
541
+ .. doctest::
542
+
543
+ >>> from web3.utils import get_event_log_topics
544
+ >>> abi = {
545
+ ... 'type': 'event',
546
+ ... 'anonymous': False,
547
+ ... 'name': 'MyEvent',
548
+ ... 'inputs': [
549
+ ... {
550
+ ... 'name': 's',
551
+ ... 'type': 'uint256'
552
+ ... }
553
+ ... ]
554
+ ... }
555
+ >>> 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
556
+ >>> get_event_log_topics(abi, [keccak_signature, '0x1', '0x2'])
557
+ ['0x1', '0x2']
558
+ """
559
+ if event_abi["anonymous"]:
560
+ return topics
561
+ elif not topics or len(topics) == 0:
562
+ raise MismatchedABI("Expected non-anonymous event to have 1 or more topics")
563
+ elif event_abi_to_log_topic(event_abi) != log_topic_to_bytes(topics[0]):
564
+ raise MismatchedABI("The event signature did not match the provided ABI")
565
+ else:
566
+ return topics[1:]
567
+
10
568
 
569
+ def log_topic_to_bytes(
570
+ log_topic: Union[Primitives, HexStr, str],
571
+ ) -> bytes:
572
+ r"""
573
+ Return topic signature as bytes.
11
574
 
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"]]
575
+ :param log_topic: Event topic from a `LogReceipt`.
576
+ :type log_topic: `Union[Primitives, HexStr, str]`
577
+ :return: Topic signature as bytes.
578
+ :rtype: `bytes`
16
579
 
580
+ .. doctest::
17
581
 
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"]]
582
+ >>> from web3.utils import log_topic_to_bytes
583
+ >>> log_topic_to_bytes('0xa12fd1')
584
+ b'\xa1/\xd1'
585
+ """
586
+ return hexstr_if_str(to_bytes, log_topic)
@@ -3,6 +3,10 @@ from typing import (
3
3
  Dict,
4
4
  )
5
5
 
6
+ from aiohttp import (
7
+ ClientSession,
8
+ ClientTimeout,
9
+ )
6
10
  from eth_abi import (
7
11
  abi,
8
12
  )
@@ -10,10 +14,8 @@ from eth_typing import (
10
14
  URI,
11
15
  )
12
16
 
13
- from web3._utils.request import (
14
- async_get_json_from_client_response,
15
- async_get_response_from_get_request,
16
- async_get_response_from_post_request,
17
+ from web3._utils.http import (
18
+ DEFAULT_HTTP_TIMEOUT,
17
19
  )
18
20
  from web3._utils.type_conversion import (
19
21
  to_bytes_if_hex,
@@ -41,6 +43,7 @@ async def async_handle_offchain_lookup(
41
43
  "`sender` value does not equal `to` address in transaction."
42
44
  )
43
45
 
46
+ session = ClientSession()
44
47
  for url in offchain_lookup_payload["urls"]:
45
48
  formatted_url = URI(
46
49
  str(url)
@@ -50,13 +53,17 @@ async def async_handle_offchain_lookup(
50
53
 
51
54
  try:
52
55
  if "{data}" in url and "{sender}" in url:
53
- response = await async_get_response_from_get_request(formatted_url)
56
+ response = await session.get(
57
+ formatted_url, timeout=ClientTimeout(DEFAULT_HTTP_TIMEOUT)
58
+ )
54
59
  elif "{sender}" in url:
55
- response = await async_get_response_from_post_request(
60
+ response = await session.post(
56
61
  formatted_url,
57
62
  data={"data": formatted_data, "sender": formatted_sender},
63
+ timeout=ClientTimeout(DEFAULT_HTTP_TIMEOUT),
58
64
  )
59
65
  else:
66
+ await session.close()
60
67
  raise Web3ValidationError("url not formatted properly.")
61
68
  except Exception:
62
69
  continue # try next url if timeout or issues making the request
@@ -64,13 +71,15 @@ async def async_handle_offchain_lookup(
64
71
  if (
65
72
  400 <= response.status <= 499
66
73
  ): # if request returns 400 error, raise exception
74
+ await session.close()
67
75
  response.raise_for_status()
68
76
  if not 200 <= response.status <= 299: # if not 400 error, try next url
69
77
  continue
70
78
 
71
- result = await async_get_json_from_client_response(response)
79
+ result = await response.json()
72
80
 
73
81
  if "data" not in result.keys():
82
+ await session.close()
74
83
  raise Web3ValidationError(
75
84
  "Improperly formatted response for offchain lookup HTTP request"
76
85
  " - missing 'data' field."
@@ -91,5 +100,8 @@ async def async_handle_offchain_lookup(
91
100
  ]
92
101
  )
93
102
 
103
+ await session.close()
94
104
  return encoded_data_with_function_selector
105
+
106
+ await session.close()
95
107
  raise MultipleFailedRequests("Offchain lookup failed for supplied urls.")