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/method.py CHANGED
@@ -10,7 +10,6 @@ from typing import (
10
10
  Sequence,
11
11
  Tuple,
12
12
  Type,
13
- TypeVar,
14
13
  Union,
15
14
  )
16
15
  import warnings
@@ -22,6 +21,9 @@ from eth_utils.toolz import (
22
21
  pipe,
23
22
  )
24
23
 
24
+ from web3._utils.batching import (
25
+ RPC_METHODS_UNSUPPORTED_DURING_BATCH,
26
+ )
25
27
  from web3._utils.method_formatters import (
26
28
  get_error_formatters,
27
29
  get_null_result_formatters,
@@ -32,15 +34,22 @@ from web3._utils.rpc_abi import (
32
34
  RPC,
33
35
  )
34
36
  from web3.exceptions import (
37
+ MethodNotSupported,
38
+ Web3TypeError,
35
39
  Web3ValidationError,
40
+ Web3ValueError,
36
41
  )
37
42
  from web3.types import (
38
43
  RPCEndpoint,
44
+ TFunc,
39
45
  TReturn,
40
46
  )
41
47
 
42
48
  if TYPE_CHECKING:
43
- from web3 import Web3 # noqa: F401
49
+ from web3 import ( # noqa: F401
50
+ PersistentConnectionProvider,
51
+ Web3,
52
+ )
44
53
  from web3.module import Module # noqa: F401
45
54
 
46
55
 
@@ -82,11 +91,9 @@ def default_root_munger(_module: "Module", *args: Any) -> List[Any]:
82
91
  return [*args]
83
92
 
84
93
 
85
- TFunc = TypeVar("TFunc", bound=Callable[..., Any])
86
-
87
-
88
94
  class Method(Generic[TFunc]):
89
- """Method object for web3 module methods
95
+ """
96
+ Method object for web3 module methods
90
97
 
91
98
  Calls to the Method go through these steps:
92
99
 
@@ -146,15 +153,31 @@ class Method(Generic[TFunc]):
146
153
  self.is_property = is_property
147
154
 
148
155
  def __get__(
149
- self, obj: Optional["Module"] = None, obj_type: Optional[Type["Module"]] = None
156
+ self,
157
+ module: Optional["Module"] = None,
158
+ _type: Optional[Type["Module"]] = None,
150
159
  ) -> TFunc:
151
- if obj is None:
152
- raise TypeError(
160
+ self._module = module
161
+ if module is None:
162
+ raise Web3TypeError(
153
163
  "Direct calls to methods are not supported. "
154
- "Methods must be called from an module instance, "
164
+ "Methods must be called from a module instance, "
155
165
  "usually attached to a web3 instance."
156
166
  )
157
- return obj.retrieve_caller_fn(self)
167
+
168
+ provider = module.w3.provider
169
+ if hasattr(provider, "_is_batching") and provider._is_batching:
170
+ if self.json_rpc_method in RPC_METHODS_UNSUPPORTED_DURING_BATCH:
171
+ raise MethodNotSupported(
172
+ f"Method `{self.json_rpc_method}` is not supported within a batch "
173
+ "request."
174
+ )
175
+ return module.retrieve_request_information(self)
176
+ else:
177
+ return module.retrieve_caller_fn(self)
178
+
179
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
180
+ return self.__get__(self._module)(*args, **kwargs)
158
181
 
159
182
  @property
160
183
  def method_selector_fn(
@@ -165,7 +188,7 @@ class Method(Generic[TFunc]):
165
188
  return self.json_rpc_method
166
189
  elif isinstance(self.json_rpc_method, (str,)):
167
190
  return lambda *_: self.json_rpc_method
168
- raise ValueError(
191
+ raise Web3ValueError(
169
192
  "``json_rpc_method`` config invalid. May be a string or function"
170
193
  )
171
194
 
@@ -218,34 +241,18 @@ class Method(Generic[TFunc]):
218
241
 
219
242
  class DeprecatedMethod:
220
243
  def __init__(
221
- self,
222
- method: Method[Callable[..., Any]],
223
- old_name: Optional[str] = None,
224
- new_name: Optional[str] = None,
225
- msg: Optional[str] = None,
244
+ self, method: Method[Callable[..., Any]], old_name: str, new_name: str
226
245
  ) -> None:
227
246
  self.method = method
228
247
  self.old_name = old_name
229
248
  self.new_name = new_name
230
- self.msg = msg
231
249
 
232
250
  def __get__(
233
251
  self, obj: Optional["Module"] = None, obj_type: Optional[Type["Module"]] = None
234
252
  ) -> Any:
235
- if self.old_name is not None and self.new_name is not None:
236
- if self.msg is not None:
237
- raise ValueError(
238
- "Cannot specify `old_name` and `new_name` along with `msg`"
239
- )
240
-
241
- message = f"{self.old_name} is deprecated in favor of {self.new_name}"
242
- elif self.msg is not None:
243
- message = self.msg
244
- else:
245
- raise ValueError("Must provide either `old_name` and `new_name` or `msg`")
246
-
247
253
  warnings.warn(
248
- message,
254
+ f"{self.old_name} is deprecated in favor of {self.new_name}",
249
255
  category=DeprecationWarning,
256
+ stacklevel=2,
250
257
  )
251
258
  return self.method.__get__(obj, obj_type)
@@ -1,133 +1,111 @@
1
- import functools
2
1
  from typing import (
3
- Coroutine,
4
2
  TYPE_CHECKING,
5
3
  Any,
6
4
  Callable,
5
+ Coroutine,
7
6
  Sequence,
8
7
  )
9
8
 
10
- from web3.types import (
11
- AsyncMiddleware,
12
- Middleware,
13
- RPCEndpoint,
14
- RPCResponse,
15
- )
16
-
17
- from .abi import (
18
- abi_middleware,
19
- )
20
- from .async_cache import (
21
- _async_simple_cache_middleware as async_simple_cache_middleware,
22
- async_construct_simple_cache_middleware,
23
- )
24
9
  from .attrdict import (
25
- async_attrdict_middleware,
26
- attrdict_middleware,
27
- )
28
- from .buffered_gas_estimate import (
29
- async_buffered_gas_estimate_middleware,
30
- buffered_gas_estimate_middleware,
10
+ AttributeDictMiddleware,
31
11
  )
32
- from .cache import (
33
- _latest_block_based_cache_middleware as latest_block_based_cache_middleware,
34
- _simple_cache_middleware as simple_cache_middleware,
35
- _time_based_cache_middleware as time_based_cache_middleware,
36
- construct_latest_block_based_cache_middleware,
37
- construct_simple_cache_middleware,
38
- construct_time_based_cache_middleware,
39
- )
40
- from .exception_handling import (
41
- construct_exception_handler_middleware,
12
+ from .base import (
13
+ Middleware,
14
+ Web3Middleware,
42
15
  )
43
- from .exception_retry_request import (
44
- async_http_retry_request_middleware,
45
- http_retry_request_middleware,
16
+ from .buffered_gas_estimate import (
17
+ BufferedGasEstimateMiddleware,
46
18
  )
47
19
  from .filter import (
48
- async_local_filter_middleware,
49
- local_filter_middleware,
50
- )
51
- from .fixture import (
52
- async_construct_error_generator_middleware,
53
- async_construct_result_generator_middleware,
54
- construct_error_generator_middleware,
55
- construct_fixture_middleware,
56
- construct_result_generator_middleware,
20
+ LocalFilterMiddleware,
57
21
  )
58
22
  from .formatting import (
59
- construct_formatting_middleware,
23
+ FormattingMiddlewareBuilder,
60
24
  )
61
25
  from .gas_price_strategy import (
62
- async_gas_price_strategy_middleware,
63
- gas_price_strategy_middleware,
64
- )
65
- from .geth_poa import (
66
- async_geth_poa_middleware,
67
- geth_poa_middleware,
26
+ GasPriceStrategyMiddleware,
68
27
  )
69
28
  from .names import (
70
- async_name_to_address_middleware,
71
- name_to_address_middleware,
29
+ ENSNameToAddressMiddleware,
72
30
  )
73
- from .normalize_request_parameters import (
74
- request_parameter_normalizer,
31
+ from .proof_of_authority import (
32
+ ExtraDataToPOAMiddleware,
75
33
  )
76
34
  from .pythonic import (
77
- pythonic_middleware,
35
+ PythonicMiddleware,
78
36
  )
79
37
  from .signing import (
80
- construct_sign_and_send_raw_middleware,
38
+ SignAndSendRawMiddlewareBuilder,
81
39
  )
82
40
  from .stalecheck import (
83
- async_make_stalecheck_middleware,
84
- make_stalecheck_middleware,
41
+ StalecheckMiddlewareBuilder,
85
42
  )
86
43
  from .validation import (
87
- async_validation_middleware,
88
- validation_middleware,
44
+ ValidationMiddleware,
89
45
  )
46
+ from ..types import (
47
+ AsyncMakeRequestFn,
48
+ MakeRequestFn,
49
+ )
50
+
90
51
 
91
52
  if TYPE_CHECKING:
92
- from web3 import AsyncWeb3, Web3
53
+ from web3 import (
54
+ AsyncWeb3,
55
+ Web3,
56
+ )
57
+ from web3.types import (
58
+ RPCResponse,
59
+ )
93
60
 
94
61
 
95
- def combine_middlewares(
96
- middlewares: Sequence[Middleware],
62
+ def combine_middleware(
63
+ middleware: Sequence[Middleware],
97
64
  w3: "Web3",
98
- provider_request_fn: Callable[[RPCEndpoint, Any], Any],
99
- ) -> Callable[..., RPCResponse]:
65
+ provider_request_fn: MakeRequestFn,
66
+ ) -> Callable[..., "RPCResponse"]:
100
67
  """
101
- Returns a callable function which will call the provider.provider_request
102
- function wrapped with all of the middlewares.
68
+ Returns a callable function which takes method and params as positional arguments
69
+ and passes these args through the request processors, makes the request, and passes
70
+ the response through the response processors.
103
71
  """
104
- return functools.reduce(
105
- lambda request_fn, middleware: middleware(request_fn, w3),
106
- reversed(middlewares),
107
- provider_request_fn,
108
- )
72
+ accumulator_fn = provider_request_fn
73
+ for mw in reversed(middleware):
74
+ # initialize the middleware and wrap the accumulator function down the stack
75
+ accumulator_fn = mw(w3).wrap_make_request(accumulator_fn)
76
+ return accumulator_fn
109
77
 
110
78
 
111
- async def async_combine_middlewares(
112
- middlewares: Sequence[AsyncMiddleware],
79
+ async def async_combine_middleware(
80
+ middleware: Sequence[Middleware],
113
81
  async_w3: "AsyncWeb3",
114
- provider_request_fn: Callable[[RPCEndpoint, Any], Any],
115
- ) -> Callable[..., Coroutine[Any, Any, RPCResponse]]:
82
+ provider_request_fn: AsyncMakeRequestFn,
83
+ ) -> Callable[..., Coroutine[Any, Any, "RPCResponse"]]:
116
84
  """
117
- Returns a callable function which will call the provider.provider_request
118
- function wrapped with all of the middlewares.
85
+ Returns a callable function which takes method and params as positional arguments
86
+ and passes these args through the request processors, makes the request, and passes
87
+ the response through the response processors.
119
88
  """
120
89
  accumulator_fn = provider_request_fn
121
- for middleware in reversed(middlewares):
122
- accumulator_fn = await construct_middleware(
123
- middleware, accumulator_fn, async_w3
124
- )
90
+ for mw in reversed(middleware):
91
+ # initialize the middleware and wrap the accumulator function down the stack
92
+ initialized = mw(async_w3)
93
+ accumulator_fn = await initialized.async_wrap_make_request(accumulator_fn)
125
94
  return accumulator_fn
126
95
 
127
96
 
128
- async def construct_middleware(
129
- async_middleware: AsyncMiddleware,
130
- fn: Callable[..., RPCResponse],
131
- async_w3: "AsyncWeb3",
132
- ) -> Callable[[RPCEndpoint, Any], RPCResponse]:
133
- return await async_middleware(fn, async_w3)
97
+ __all__ = [
98
+ "AttributeDictMiddleware",
99
+ "Middleware",
100
+ "Web3Middleware",
101
+ "BufferedGasEstimateMiddleware",
102
+ "LocalFilterMiddleware",
103
+ "FormattingMiddlewareBuilder",
104
+ "GasPriceStrategyMiddleware",
105
+ "ENSNameToAddressMiddleware",
106
+ "ExtraDataToPOAMiddleware",
107
+ "PythonicMiddleware",
108
+ "SignAndSendRawMiddlewareBuilder",
109
+ "StalecheckMiddlewareBuilder",
110
+ "ValidationMiddleware",
111
+ ]
@@ -1,8 +1,9 @@
1
+ from abc import (
2
+ ABC,
3
+ )
1
4
  from typing import (
2
5
  TYPE_CHECKING,
3
6
  Any,
4
- Callable,
5
- Optional,
6
7
  cast,
7
8
  )
8
9
 
@@ -13,10 +14,8 @@ from eth_utils.toolz import (
13
14
  from web3.datastructures import (
14
15
  AttributeDict,
15
16
  )
16
- from web3.types import (
17
- AsyncMiddlewareCoroutine,
18
- RPCEndpoint,
19
- RPCResponse,
17
+ from web3.middleware.base import (
18
+ Web3Middleware,
20
19
  )
21
20
 
22
21
  if TYPE_CHECKING:
@@ -27,11 +26,31 @@ if TYPE_CHECKING:
27
26
  from web3.providers import ( # noqa: F401
28
27
  PersistentConnectionProvider,
29
28
  )
29
+ from web3.types import ( # noqa: F401
30
+ RPCEndpoint,
31
+ RPCResponse,
32
+ )
30
33
 
31
34
 
32
- def attrdict_middleware(
33
- make_request: Callable[[RPCEndpoint, Any], Any], _w3: "Web3"
34
- ) -> Callable[[RPCEndpoint, Any], RPCResponse]:
35
+ def _handle_async_response(response: "RPCResponse") -> "RPCResponse":
36
+ if "result" in response:
37
+ return assoc(response, "result", AttributeDict.recursive(response["result"]))
38
+ elif "params" in response and "result" in response["params"]:
39
+ # this is a subscription response
40
+ return assoc(
41
+ response,
42
+ "params",
43
+ assoc(
44
+ response["params"],
45
+ "result",
46
+ AttributeDict.recursive(response["params"]["result"]),
47
+ ),
48
+ )
49
+ else:
50
+ return response
51
+
52
+
53
+ class AttributeDictMiddleware(Web3Middleware, ABC):
35
54
  """
36
55
  Converts any result which is a dictionary into an `AttributeDict`.
37
56
 
@@ -39,9 +58,7 @@ def attrdict_middleware(
39
58
  (e.g. my_attribute_dict.property1) will not preserve typing.
40
59
  """
41
60
 
42
- def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
43
- response = make_request(method, params)
44
-
61
+ def response_processor(self, method: "RPCEndpoint", response: "RPCResponse") -> Any:
45
62
  if "result" in response:
46
63
  return assoc(
47
64
  response, "result", AttributeDict.recursive(response["result"])
@@ -49,27 +66,14 @@ def attrdict_middleware(
49
66
  else:
50
67
  return response
51
68
 
52
- return middleware
53
-
54
-
55
- # --- async --- #
56
-
69
+ # -- async -- #
57
70
 
58
- async def async_attrdict_middleware(
59
- make_request: Callable[[RPCEndpoint, Any], Any], async_w3: "AsyncWeb3"
60
- ) -> AsyncMiddlewareCoroutine:
61
- """
62
- Converts any result which is a dictionary into an `AttributeDict`.
63
-
64
- Note: Accessing `AttributeDict` properties via attribute
65
- (e.g. my_attribute_dict.property1) will not preserve typing.
66
- """
67
-
68
- async def middleware(method: RPCEndpoint, params: Any) -> Optional[RPCResponse]:
69
- response = await make_request(method, params)
70
- if async_w3.provider.has_persistent_connection:
71
+ async def async_response_processor(
72
+ self, method: "RPCEndpoint", response: "RPCResponse"
73
+ ) -> Any:
74
+ if self._w3.provider.has_persistent_connection:
71
75
  # asynchronous response processing
72
- provider = cast("PersistentConnectionProvider", async_w3.provider)
76
+ provider = cast("PersistentConnectionProvider", self._w3.provider)
73
77
  provider._request_processor.append_middleware_response_processor(
74
78
  response, _handle_async_response
75
79
  )
@@ -77,22 +81,5 @@ async def async_attrdict_middleware(
77
81
  else:
78
82
  return _handle_async_response(response)
79
83
 
80
- return middleware
81
-
82
84
 
83
- def _handle_async_response(response: RPCResponse) -> RPCResponse:
84
- if "result" in response:
85
- return assoc(response, "result", AttributeDict.recursive(response["result"]))
86
- elif "params" in response and "result" in response["params"]:
87
- # this is a subscription response
88
- return assoc(
89
- response,
90
- "params",
91
- assoc(
92
- response["params"],
93
- "result",
94
- AttributeDict.recursive(response["params"]["result"]),
95
- ),
96
- )
97
- else:
98
- return response
85
+ AttributeDictMiddleware = AttributeDictMiddleware
@@ -0,0 +1,174 @@
1
+ from abc import (
2
+ abstractmethod,
3
+ )
4
+ from typing import (
5
+ TYPE_CHECKING,
6
+ Any,
7
+ List,
8
+ Tuple,
9
+ Type,
10
+ Union,
11
+ )
12
+
13
+ from web3.datastructures import (
14
+ NamedElementOnion,
15
+ )
16
+
17
+ if TYPE_CHECKING:
18
+ from web3 import ( # noqa: F401
19
+ AsyncWeb3,
20
+ Web3,
21
+ )
22
+ from web3.types import ( # noqa: F401
23
+ AsyncMakeBatchRequestFn,
24
+ AsyncMakeRequestFn,
25
+ MakeBatchRequestFn,
26
+ MakeRequestFn,
27
+ RPCEndpoint,
28
+ RPCResponse,
29
+ )
30
+
31
+
32
+ class Web3Middleware:
33
+ """
34
+ Base class for web3.py middleware. This class is not meant to be used directly,
35
+ but instead inherited from.
36
+ """
37
+
38
+ _w3: Union["AsyncWeb3", "Web3"]
39
+
40
+ def __init__(self, w3: Union["AsyncWeb3", "Web3"]) -> None:
41
+ self._w3 = w3
42
+
43
+ # -- sync -- #
44
+
45
+ def wrap_make_request(self, make_request: "MakeRequestFn") -> "MakeRequestFn":
46
+ def middleware(method: "RPCEndpoint", params: Any) -> "RPCResponse":
47
+ method, params = self.request_processor(method, params)
48
+ return self.response_processor(method, make_request(method, params))
49
+
50
+ return middleware
51
+
52
+ def wrap_make_batch_request(
53
+ self, make_batch_request: "MakeBatchRequestFn"
54
+ ) -> "MakeBatchRequestFn":
55
+ def middleware(
56
+ requests_info: List[Tuple["RPCEndpoint", Any]]
57
+ ) -> List["RPCResponse"]:
58
+ req_processed = [
59
+ self.request_processor(method, params)
60
+ for (method, params) in requests_info
61
+ ]
62
+ responses = make_batch_request(req_processed)
63
+ methods, _params = zip(*req_processed)
64
+ formatted_responses = [
65
+ self.response_processor(m, r) for m, r in zip(methods, responses)
66
+ ]
67
+ return formatted_responses
68
+
69
+ return middleware
70
+
71
+ def request_processor(self, method: "RPCEndpoint", params: Any) -> Any:
72
+ return method, params
73
+
74
+ def response_processor(
75
+ self, method: "RPCEndpoint", response: "RPCResponse"
76
+ ) -> "RPCResponse":
77
+ return response
78
+
79
+ # -- async -- #
80
+
81
+ async def async_wrap_make_request(
82
+ self, make_request: "AsyncMakeRequestFn"
83
+ ) -> "AsyncMakeRequestFn":
84
+ async def middleware(method: "RPCEndpoint", params: Any) -> "RPCResponse":
85
+ method, params = await self.async_request_processor(method, params)
86
+ return await self.async_response_processor(
87
+ method,
88
+ await make_request(method, params),
89
+ )
90
+
91
+ return middleware
92
+
93
+ async def async_wrap_make_batch_request(
94
+ self, make_batch_request: "AsyncMakeBatchRequestFn"
95
+ ) -> "AsyncMakeBatchRequestFn":
96
+ async def middleware(
97
+ requests_info: List[Tuple["RPCEndpoint", Any]]
98
+ ) -> List["RPCResponse"]:
99
+ req_processed = [
100
+ await self.async_request_processor(method, params)
101
+ for (method, params) in requests_info
102
+ ]
103
+ responses = await make_batch_request(req_processed)
104
+ methods, _params = zip(*req_processed)
105
+ formatted_responses = [
106
+ await self.async_response_processor(m, r)
107
+ for m, r in zip(methods, responses)
108
+ ]
109
+ return formatted_responses
110
+
111
+ return middleware
112
+
113
+ async def async_request_processor(
114
+ self,
115
+ method: "RPCEndpoint",
116
+ params: Any,
117
+ ) -> Any:
118
+ return method, params
119
+
120
+ async def async_response_processor(
121
+ self,
122
+ method: "RPCEndpoint",
123
+ response: "RPCResponse",
124
+ ) -> "RPCResponse":
125
+ return response
126
+
127
+
128
+ class Web3MiddlewareBuilder(Web3Middleware):
129
+ @staticmethod
130
+ @abstractmethod
131
+ def build(
132
+ w3: Union["AsyncWeb3", "Web3"],
133
+ *args: Any,
134
+ **kwargs: Any,
135
+ ) -> Web3Middleware:
136
+ """
137
+ Implementation should initialize the middleware class that implements it,
138
+ load it with any of the necessary properties that it needs for processing,
139
+ and curry for the ``w3`` argument since it isn't initially present when building
140
+ the middleware.
141
+
142
+ example implementation:
143
+
144
+ ```py
145
+ class MyMiddleware(Web3BuilderMiddleware):
146
+ internal_property: str = None
147
+
148
+ @staticmethod
149
+ @curry
150
+ def builder(user_provided_argument, w3):
151
+ middleware = MyMiddleware(w3)
152
+ middleware.internal_property = user_provided_argument
153
+ return middleware
154
+
155
+ def request_processor(self, method, params):
156
+ ...
157
+
158
+ def response_processor(self, method, response):
159
+ ...
160
+
161
+ construct_my_middleware = MyMiddleware.builder
162
+
163
+ w3 = Web3(provider)
164
+ my_middleware = construct_my_middleware("my argument")
165
+ w3.middleware_onion.inject(my_middleware, layer=0)
166
+ ```
167
+ """
168
+ raise NotImplementedError("Must be implemented by subclasses")
169
+
170
+
171
+ # --- type definitions --- #
172
+
173
+ Middleware = Type[Web3Middleware]
174
+ MiddlewareOnion = NamedElementOnion[str, Middleware]