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
@@ -19,6 +19,9 @@ from eth_account import (
19
19
  from eth_account.signers.local import (
20
20
  LocalAccount,
21
21
  )
22
+ from eth_account.types import (
23
+ TransactionDictType as EthAccountTxParams,
24
+ )
22
25
  from eth_keys.datatypes import (
23
26
  PrivateKey,
24
27
  )
@@ -55,6 +58,9 @@ from web3._utils.transactions import (
55
58
  fill_nonce,
56
59
  fill_transaction_defaults,
57
60
  )
61
+ from web3.exceptions import (
62
+ Web3TypeError,
63
+ )
58
64
  from web3.middleware.base import (
59
65
  Web3MiddlewareBuilder,
60
66
  )
@@ -108,7 +114,7 @@ def gen_normalized_accounts(
108
114
 
109
115
  @singledispatch
110
116
  def to_account(val: Any) -> LocalAccount:
111
- raise TypeError(
117
+ raise Web3TypeError(
112
118
  "key must be one of the types: "
113
119
  "eth_keys.datatype.PrivateKey, eth_account.signers.local.LocalAccount, "
114
120
  "or raw private key as a hex string or byte string. "
@@ -132,7 +138,8 @@ to_account.register(bytes, private_key_to_account)
132
138
 
133
139
 
134
140
  def format_transaction(transaction: TxParams) -> TxParams:
135
- """Format transaction so that it can be used correctly in the signing middleware.
141
+ """
142
+ Format transaction so that it can be used correctly in the signing middleware.
136
143
 
137
144
  Converts bytes to hex strings and other types that can be passed to
138
145
  the underlying layers. Also has the effect of normalizing 'from' for
@@ -178,11 +185,11 @@ class SignAndSendRawMiddlewareBuilder(Web3MiddlewareBuilder):
178
185
  return method, params
179
186
  else:
180
187
  account = self._accounts[to_checksum_address(tx_from)]
181
- raw_tx = account.sign_transaction(filled_transaction).rawTransaction
188
+ raw_tx = account.sign_transaction(filled_transaction).raw_transaction
182
189
 
183
190
  return (
184
191
  RPCEndpoint("eth_sendRawTransaction"),
185
- [raw_tx.hex()],
192
+ [raw_tx.to_0x_hex()],
186
193
  )
187
194
 
188
195
  # -- async -- #
@@ -207,9 +214,11 @@ class SignAndSendRawMiddlewareBuilder(Web3MiddlewareBuilder):
207
214
  return method, params
208
215
  else:
209
216
  account = self._accounts[to_checksum_address(tx_from)]
210
- raw_tx = account.sign_transaction(filled_transaction).rawTransaction
217
+ raw_tx = account.sign_transaction(
218
+ cast(EthAccountTxParams, filled_transaction)
219
+ ).raw_transaction
211
220
 
212
221
  return (
213
222
  RPCEndpoint("eth_sendRawTransaction"),
214
- [raw_tx.hex()],
223
+ [raw_tx.to_0x_hex()],
215
224
  )
@@ -16,6 +16,7 @@ from toolz import (
16
16
 
17
17
  from web3.exceptions import (
18
18
  StaleBlockchain,
19
+ Web3ValueError,
19
20
  )
20
21
  from web3.middleware.base import (
21
22
  Web3Middleware,
@@ -54,7 +55,7 @@ class StalecheckMiddlewareBuilder(Web3MiddlewareBuilder):
54
55
  skip_stalecheck_for_methods: Collection[str] = SKIP_STALECHECK_FOR_METHODS,
55
56
  ) -> Web3Middleware:
56
57
  if allowable_delay <= 0:
57
- raise ValueError(
58
+ raise Web3ValueError(
58
59
  "You must set a positive allowable_delay in seconds for this middleware"
59
60
  )
60
61
  middleware = StalecheckMiddlewareBuilder(w3)
web3/module.py CHANGED
@@ -5,6 +5,8 @@ from typing import (
5
5
  Coroutine,
6
6
  Dict,
7
7
  Optional,
8
+ Sequence,
9
+ Tuple,
8
10
  TypeVar,
9
11
  Union,
10
12
  cast,
@@ -30,6 +32,7 @@ from web3.providers.persistent import (
30
32
  PersistentConnectionProvider,
31
33
  )
32
34
  from web3.types import (
35
+ FormattedEthSubscriptionResponse,
33
36
  RPCEndpoint,
34
37
  RPCResponse,
35
38
  )
@@ -55,9 +58,43 @@ def apply_result_formatters(
55
58
  TReturn = TypeVar("TReturn")
56
59
 
57
60
 
61
+ @curry
62
+ def retrieve_request_information_for_batching(
63
+ w3: Union["AsyncWeb3", "Web3"],
64
+ module: "Module",
65
+ method: Method[Callable[..., Any]],
66
+ ) -> Union[
67
+ Callable[..., Tuple[Tuple[RPCEndpoint, Any], Sequence[Any]]],
68
+ Callable[..., Coroutine[Any, Any, Tuple[Tuple[RPCEndpoint, Any], Sequence[Any]]]],
69
+ ]:
70
+ async def async_inner(
71
+ *args: Any, **kwargs: Any
72
+ ) -> Tuple[Tuple[RPCEndpoint, Any], Sequence[Any]]:
73
+ (method_str, params), response_formatters = method.process_params(
74
+ module, *args, **kwargs
75
+ )
76
+ if isinstance(w3.provider, PersistentConnectionProvider):
77
+ w3.provider._request_processor.cache_request_information(
78
+ None, cast(RPCEndpoint, method_str), params, response_formatters
79
+ )
80
+ return (cast(RPCEndpoint, method_str), params), response_formatters
81
+
82
+ def inner(
83
+ *args: Any, **kwargs: Any
84
+ ) -> Tuple[Tuple[RPCEndpoint, Any], Sequence[Any]]:
85
+ (method_str, params), response_formatters = method.process_params(
86
+ module, *args, **kwargs
87
+ )
88
+ return (cast(RPCEndpoint, method_str), params), response_formatters
89
+
90
+ return async_inner if module.is_async else inner
91
+
92
+
58
93
  @curry
59
94
  def retrieve_blocking_method_call_fn(
60
- w3: "Web3", module: "Module", method: Method[Callable[..., TReturn]]
95
+ w3: "Web3",
96
+ module: "Module",
97
+ method: Method[Callable[..., TReturn]],
61
98
  ) -> Callable[..., Union[TReturn, LogFilter]]:
62
99
  def caller(*args: Any, **kwargs: Any) -> Union[TReturn, LogFilter]:
63
100
  try:
@@ -82,9 +119,20 @@ def retrieve_blocking_method_call_fn(
82
119
 
83
120
  @curry
84
121
  def retrieve_async_method_call_fn(
85
- async_w3: "AsyncWeb3", module: "Module", method: Method[Callable[..., Any]]
86
- ) -> Callable[..., Coroutine[Any, Any, Optional[Union[RPCResponse, AsyncLogFilter]]]]:
87
- async def caller(*args: Any, **kwargs: Any) -> Union[RPCResponse, AsyncLogFilter]:
122
+ async_w3: "AsyncWeb3",
123
+ module: "Module",
124
+ method: Method[Callable[..., Any]],
125
+ ) -> Callable[
126
+ ...,
127
+ Coroutine[
128
+ Any,
129
+ Any,
130
+ Optional[Union[RPCResponse, FormattedEthSubscriptionResponse, AsyncLogFilter]],
131
+ ],
132
+ ]:
133
+ async def caller(
134
+ *args: Any, **kwargs: Any
135
+ ) -> Union[RPCResponse, FormattedEthSubscriptionResponse, AsyncLogFilter]:
88
136
  try:
89
137
  (method_str, params), response_formatters = method.process_params(
90
138
  module, *args, **kwargs
@@ -93,32 +141,17 @@ def retrieve_async_method_call_fn(
93
141
  return AsyncLogFilter(eth_module=module, filter_id=err.filter_id)
94
142
 
95
143
  if isinstance(async_w3.provider, PersistentConnectionProvider):
96
- # TODO: The typing does not seem to be correct for response_formatters.
97
- # For now, keep the expected typing but ignore it here.
98
- provider = async_w3.provider
99
- cache_key = provider._request_processor.cache_request_information(
100
- cast(RPCEndpoint, method_str), params, response_formatters # type: ignore # noqa: E501
144
+ return await async_w3.manager.socket_request(
145
+ cast(RPCEndpoint, method_str),
146
+ params,
147
+ response_formatters=response_formatters,
101
148
  )
102
- try:
103
- method_str = cast(RPCEndpoint, method_str)
104
- return await async_w3.manager.send(method_str, params)
105
- except Exception as e:
106
- if (
107
- cache_key is not None
108
- and cache_key
109
- in provider._request_processor._request_information_cache
110
- ):
111
- provider._request_processor.pop_cached_request_information(
112
- cache_key
113
- )
114
- raise e
115
149
  else:
116
150
  (
117
151
  result_formatters,
118
152
  error_formatters,
119
153
  null_result_formatters,
120
154
  ) = response_formatters
121
-
122
155
  result = await async_w3.manager.coro_request(
123
156
  method_str, params, error_formatters, null_result_formatters
124
157
  )
@@ -129,7 +162,7 @@ def retrieve_async_method_call_fn(
129
162
 
130
163
  # Module should no longer have access to the full web3 api.
131
164
  # Only the calling functions need access to the request methods.
132
- # Any "re-entrant" shenanigans can go in the middlewares, which do
165
+ # Any "re-entrant" shenanigans can go in the middleware, which do
133
166
  # have web3 access.
134
167
  class Module:
135
168
  is_async = False
@@ -139,6 +172,9 @@ class Module:
139
172
  self.retrieve_caller_fn = retrieve_async_method_call_fn(w3, self)
140
173
  else:
141
174
  self.retrieve_caller_fn = retrieve_blocking_method_call_fn(w3, self)
175
+ self.retrieve_request_information = retrieve_request_information_for_batching(
176
+ w3, self
177
+ )
142
178
  self.w3 = w3
143
179
 
144
180
  @property
@@ -152,8 +188,8 @@ class Module:
152
188
  ) -> None:
153
189
  for method_name, method_class in methods.items():
154
190
  klass = (
155
- method_class.__get__(obj=self)()
191
+ method_class.__get__(module=self)()
156
192
  if method_class.is_property
157
- else method_class.__get__(obj=self)
193
+ else method_class.__get__(module=self)
158
194
  )
159
195
  setattr(self, method_name, klass)
@@ -8,6 +8,10 @@ from .base import (
8
8
  BaseProvider,
9
9
  JSONBaseProvider,
10
10
  )
11
+ from .eth_tester import (
12
+ AsyncEthereumTesterProvider,
13
+ EthereumTesterProvider,
14
+ )
11
15
  from .ipc import (
12
16
  IPCProvider,
13
17
  )
@@ -26,3 +30,20 @@ from .persistent import (
26
30
  from .auto import (
27
31
  AutoProvider,
28
32
  )
33
+
34
+ __all__ = [
35
+ "AsyncBaseProvider",
36
+ "AsyncEthereumTesterProvider",
37
+ "AsyncHTTPProvider",
38
+ "AsyncIPCProvider",
39
+ "AutoProvider",
40
+ "BaseProvider",
41
+ "EthereumTesterProvider",
42
+ "HTTPProvider",
43
+ "IPCProvider",
44
+ "JSONBaseProvider",
45
+ "LegacyWebSocketProvider",
46
+ "PersistentConnection",
47
+ "PersistentConnectionProvider",
48
+ "WebSocketProvider",
49
+ ]
@@ -1,13 +1,17 @@
1
1
  import asyncio
2
2
  import itertools
3
+ import logging
3
4
  from typing import (
4
5
  TYPE_CHECKING,
5
6
  Any,
6
7
  Callable,
7
8
  Coroutine,
9
+ Dict,
10
+ List,
8
11
  Optional,
9
12
  Set,
10
13
  Tuple,
14
+ Union,
11
15
  cast,
12
16
  )
13
17
 
@@ -18,7 +22,11 @@ from eth_utils import (
18
22
  )
19
23
 
20
24
  from web3._utils.caching import (
21
- async_handle_request_caching,
25
+ CACHEABLE_REQUESTS,
26
+ )
27
+ from web3._utils.empty import (
28
+ Empty,
29
+ empty,
22
30
  )
23
31
  from web3._utils.encoding import (
24
32
  FriendlyJsonSerde,
@@ -28,7 +36,7 @@ from web3.exceptions import (
28
36
  ProviderConnectionError,
29
37
  )
30
38
  from web3.middleware import (
31
- async_combine_middlewares,
39
+ async_combine_middleware,
32
40
  )
33
41
  from web3.middleware.base import (
34
42
  Middleware,
@@ -36,9 +44,11 @@ from web3.middleware.base import (
36
44
  )
37
45
  from web3.types import (
38
46
  RPCEndpoint,
47
+ RPCRequest,
39
48
  RPCResponse,
40
49
  )
41
50
  from web3.utils import (
51
+ RequestCacheValidationThreshold,
42
52
  SimpleCache,
43
53
  )
44
54
 
@@ -56,63 +66,84 @@ if TYPE_CHECKING:
56
66
  )
57
67
 
58
68
 
59
- CACHEABLE_REQUESTS = cast(
60
- Set[RPCEndpoint],
61
- (
62
- "eth_chainId",
63
- "eth_getBlockByHash",
64
- "eth_getBlockTransactionCountByHash",
65
- "eth_getRawTransactionByHash",
66
- "eth_getTransactionByBlockHashAndIndex",
67
- "eth_getTransactionByHash",
68
- "eth_getUncleByBlockHashAndIndex",
69
- "eth_getUncleCountByBlockHash",
70
- "net_version",
71
- "web3_clientVersion",
72
- ),
73
- )
74
-
75
-
76
69
  class AsyncBaseProvider:
70
+ # Set generic logger for the provider. Override in subclasses for more specificity.
71
+ logger: logging.Logger = logging.getLogger(
72
+ "web3.providers.async_base.AsyncBaseProvider"
73
+ )
77
74
  _request_func_cache: Tuple[
78
75
  Tuple[Middleware, ...], Callable[..., Coroutine[Any, Any, RPCResponse]]
79
76
  ] = (None, None)
80
77
 
78
+ _is_batching: bool = False
79
+ _batch_request_func_cache: Tuple[
80
+ Tuple[Middleware, ...], Callable[..., Coroutine[Any, Any, List[RPCResponse]]]
81
+ ] = (None, None)
82
+
81
83
  is_async = True
82
84
  has_persistent_connection = False
83
85
  global_ccip_read_enabled: bool = True
84
86
  ccip_read_max_redirects: int = 4
85
87
 
86
- # request caching
87
- cache_allowed_requests: bool = False
88
- cacheable_requests: Set[RPCEndpoint] = CACHEABLE_REQUESTS
89
- _request_cache: SimpleCache
90
- _request_cache_lock: asyncio.Lock = asyncio.Lock()
91
-
92
- def __init__(self) -> None:
88
+ def __init__(
89
+ self,
90
+ cache_allowed_requests: bool = False,
91
+ cacheable_requests: Set[RPCEndpoint] = None,
92
+ request_cache_validation_threshold: Optional[
93
+ Union[RequestCacheValidationThreshold, int, Empty]
94
+ ] = empty,
95
+ ) -> None:
93
96
  self._request_cache = SimpleCache(1000)
97
+ self._request_cache_lock: asyncio.Lock = asyncio.Lock()
98
+
99
+ self.cache_allowed_requests = cache_allowed_requests
100
+ self.cacheable_requests = cacheable_requests or CACHEABLE_REQUESTS
101
+ self.request_cache_validation_threshold = request_cache_validation_threshold
94
102
 
95
103
  async def request_func(
96
104
  self, async_w3: "AsyncWeb3", middleware_onion: MiddlewareOnion
97
105
  ) -> Callable[..., Coroutine[Any, Any, RPCResponse]]:
98
- middlewares: Tuple[Middleware, ...] = middleware_onion.as_tuple_of_middlewares()
106
+ middleware: Tuple[Middleware, ...] = middleware_onion.as_tuple_of_middleware()
99
107
 
100
108
  cache_key = self._request_func_cache[0]
101
- if cache_key != middlewares:
109
+ if cache_key != middleware:
102
110
  self._request_func_cache = (
103
- middlewares,
104
- await async_combine_middlewares(
105
- middlewares=middlewares,
111
+ middleware,
112
+ await async_combine_middleware(
113
+ middleware=middleware,
106
114
  async_w3=async_w3,
107
115
  provider_request_fn=self.make_request,
108
116
  ),
109
117
  )
110
118
  return self._request_func_cache[-1]
111
119
 
112
- @async_handle_request_caching
120
+ async def batch_request_func(
121
+ self, async_w3: "AsyncWeb3", middleware_onion: MiddlewareOnion
122
+ ) -> Callable[..., Coroutine[Any, Any, List[RPCResponse]]]:
123
+ middleware: Tuple[Middleware, ...] = middleware_onion.as_tuple_of_middleware()
124
+
125
+ cache_key = self._batch_request_func_cache[0]
126
+ if cache_key != middleware:
127
+ accumulator_fn = self.make_batch_request
128
+ for mw in reversed(middleware):
129
+ initialized = mw(async_w3)
130
+ # type ignore bc in order to wrap the method, we have to call
131
+ # `async_wrap_make_batch_request` with the accumulator_fn as the
132
+ # argument which breaks the type hinting for this particular case.
133
+ accumulator_fn = await initialized.async_wrap_make_batch_request( # type: ignore # noqa: E501
134
+ accumulator_fn
135
+ )
136
+ self._batch_request_func_cache = (middleware, accumulator_fn)
137
+ return self._batch_request_func_cache[-1]
138
+
113
139
  async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
114
140
  raise NotImplementedError("Providers must implement this method")
115
141
 
142
+ async def make_batch_request(
143
+ self, requests: List[Tuple[RPCEndpoint, Any]]
144
+ ) -> List[RPCResponse]:
145
+ raise NotImplementedError("Only AsyncHTTPProvider supports this method")
146
+
116
147
  async def is_connected(self, show_traceback: bool = False) -> bool:
117
148
  raise NotImplementedError("Providers must implement this method")
118
149
 
@@ -141,22 +172,33 @@ class AsyncBaseProvider:
141
172
 
142
173
 
143
174
  class AsyncJSONBaseProvider(AsyncBaseProvider):
144
- def __init__(self) -> None:
145
- super().__init__()
175
+ def __init__(self, **kwargs: Any) -> None:
176
+ super().__init__(**kwargs)
146
177
  self.request_counter = itertools.count()
147
178
 
148
- def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
179
+ def form_request(self, method: RPCEndpoint, params: Any = None) -> RPCRequest:
149
180
  request_id = next(self.request_counter)
150
181
  rpc_dict = {
182
+ "id": request_id,
151
183
  "jsonrpc": "2.0",
152
184
  "method": method,
153
185
  "params": params or [],
154
- "id": request_id,
155
186
  }
156
- encoded = FriendlyJsonSerde().json_encode(rpc_dict, cls=Web3JsonEncoder)
187
+ return cast(RPCRequest, rpc_dict)
188
+
189
+ @staticmethod
190
+ def encode_rpc_dict(rpc_dict: RPCRequest) -> bytes:
191
+ encoded = FriendlyJsonSerde().json_encode(
192
+ cast(Dict[str, Any], rpc_dict), cls=Web3JsonEncoder
193
+ )
157
194
  return to_bytes(text=encoded)
158
195
 
159
- def decode_rpc_response(self, raw_response: bytes) -> RPCResponse:
196
+ def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
197
+ rpc_dict = self.form_request(method, params)
198
+ return self.encode_rpc_dict(rpc_dict)
199
+
200
+ @staticmethod
201
+ def decode_rpc_response(raw_response: bytes) -> RPCResponse:
160
202
  text_response = str(
161
203
  to_text(raw_response) if not is_text(raw_response) else raw_response
162
204
  )
@@ -185,3 +227,16 @@ class AsyncJSONBaseProvider(AsyncBaseProvider):
185
227
  if show_traceback:
186
228
  raise ProviderConnectionError(f"Bad jsonrpc version: {response}")
187
229
  return False
230
+
231
+ # -- batch requests -- #
232
+
233
+ def encode_batch_rpc_request(
234
+ self, requests: List[Tuple[RPCEndpoint, Any]]
235
+ ) -> bytes:
236
+ return (
237
+ b"["
238
+ + b", ".join(
239
+ self.encode_rpc_request(method, params) for method, params in requests
240
+ )
241
+ + b"]"
242
+ )