web3 7.8.0__py3-none-any.whl → 7.10.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 (47) hide show
  1. web3/_utils/abi.py +3 -3
  2. web3/_utils/batching.py +1 -1
  3. web3/_utils/contract_sources/contract_data/ambiguous_function_contract.py +3 -3
  4. web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
  5. web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
  6. web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
  7. web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
  8. web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
  9. web3/_utils/contract_sources/contract_data/event_contracts.py +7 -7
  10. web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
  11. web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
  12. web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
  13. web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
  14. web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
  15. web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
  16. web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
  17. web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
  18. web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
  19. web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
  20. web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
  21. web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
  22. web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
  23. web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
  24. web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
  25. web3/_utils/error_formatters_utils.py +1 -1
  26. web3/_utils/formatters.py +28 -0
  27. web3/_utils/method_formatters.py +121 -20
  28. web3/_utils/module_testing/eth_module.py +99 -2
  29. web3/_utils/module_testing/persistent_connection_provider.py +1 -1
  30. web3/_utils/rpc_abi.py +1 -0
  31. web3/_utils/validation.py +192 -1
  32. web3/eth/async_eth.py +19 -0
  33. web3/eth/eth.py +15 -0
  34. web3/gas_strategies/rpc.py +1 -1
  35. web3/gas_strategies/time_based.py +1 -1
  36. web3/manager.py +13 -204
  37. web3/providers/async_base.py +1 -1
  38. web3/providers/legacy_websocket.py +1 -3
  39. web3/providers/persistent/persistent.py +35 -5
  40. web3/providers/persistent/subscription_manager.py +7 -2
  41. web3/providers/persistent/websocket.py +12 -9
  42. web3/types.py +26 -2
  43. {web3-7.8.0.dist-info → web3-7.10.0.dist-info}/METADATA +14 -9
  44. {web3-7.8.0.dist-info → web3-7.10.0.dist-info}/RECORD +47 -47
  45. {web3-7.8.0.dist-info → web3-7.10.0.dist-info}/WHEEL +1 -1
  46. {web3-7.8.0.dist-info → web3-7.10.0.dist-info/licenses}/LICENSE +0 -0
  47. {web3-7.8.0.dist-info → web3-7.10.0.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,8 @@
1
+ import pytest
1
2
  import asyncio
2
3
  from dataclasses import (
3
4
  dataclass,
4
5
  )
5
- import pytest
6
6
  from typing import (
7
7
  TYPE_CHECKING,
8
8
  Any,
web3/_utils/rpc_abi.py CHANGED
@@ -51,6 +51,7 @@ class RPC:
51
51
  eth_blobBaseFee = RPCEndpoint("eth_blobBaseFee")
52
52
  eth_blockNumber = RPCEndpoint("eth_blockNumber")
53
53
  eth_call = RPCEndpoint("eth_call")
54
+ eth_simulateV1 = RPCEndpoint("eth_simulateV1")
54
55
  eth_createAccessList = RPCEndpoint("eth_createAccessList")
55
56
  eth_chainId = RPCEndpoint("eth_chainId")
56
57
  eth_estimateGas = RPCEndpoint("eth_estimateGas")
web3/_utils/validation.py CHANGED
@@ -1,7 +1,11 @@
1
1
  import itertools
2
+ import logging
2
3
  from typing import (
3
4
  Any,
5
+ Callable,
4
6
  Dict,
7
+ NoReturn,
8
+ Optional,
5
9
  )
6
10
 
7
11
  from eth_typing import (
@@ -53,11 +57,22 @@ from web3._utils.abi import (
53
57
  length_of_array_type,
54
58
  sub_type_of_array_type,
55
59
  )
60
+ from web3._utils.formatters import (
61
+ apply_error_formatters,
62
+ )
56
63
  from web3.exceptions import (
64
+ BadResponseFormat,
57
65
  InvalidAddress,
66
+ MethodUnavailable,
67
+ RequestTimedOut,
68
+ TransactionNotFound,
69
+ Web3RPCError,
58
70
  Web3TypeError,
59
71
  Web3ValueError,
60
72
  )
73
+ from web3.types import (
74
+ RPCResponse,
75
+ )
61
76
 
62
77
 
63
78
  def _prepare_selector_collision_msg(duplicates: Dict[HexStr, ABIFunction]) -> str:
@@ -116,7 +131,7 @@ def validate_abi_value(abi_type: TypeStr, value: Any) -> None:
116
131
  )
117
132
  if specified_length != len(value):
118
133
  raise Web3TypeError(
119
- "The following array length does not the length specified"
134
+ "The following array length does not match the length specified "
120
135
  f"by the abi-type, {abi_type}: {value}"
121
136
  )
122
137
 
@@ -211,3 +226,179 @@ def assert_one_val(*args: Any, **kwargs: Any) -> None:
211
226
  "Exactly one of the passed values can be specified. "
212
227
  f"Instead, values were: {args!r}, {kwargs!r}"
213
228
  )
229
+
230
+
231
+ # -- RPC Response Validation -- #
232
+
233
+ KNOWN_REQUEST_TIMEOUT_MESSAGING = {
234
+ # Note: It's important to be very explicit here and not too broad. We don't want
235
+ # to accidentally catch a message that is not for a request timeout. In the worst
236
+ # case, we raise something more generic like `Web3RPCError`. JSON-RPC unfortunately
237
+ # has not standardized error codes for request timeouts.
238
+ "request timed out", # go-ethereum
239
+ }
240
+ METHOD_NOT_FOUND = -32601
241
+
242
+
243
+ def _validate_subscription_fields(response: RPCResponse) -> None:
244
+ params = response["params"]
245
+ subscription = params["subscription"]
246
+ if not isinstance(subscription, str) and not len(subscription) == 34:
247
+ _raise_bad_response_format(
248
+ response, "eth_subscription 'params' must include a 'subscription' field."
249
+ )
250
+
251
+
252
+ def _raise_bad_response_format(response: RPCResponse, error: str = "") -> None:
253
+ message = "The response was in an unexpected format and unable to be parsed."
254
+ raw_response = f"The raw response is: {response}"
255
+
256
+ if error is not None and error != "":
257
+ error = error[:-1] if error.endswith(".") else error
258
+ message = f"{message} {error}. {raw_response}"
259
+ else:
260
+ message = f"{message} {raw_response}"
261
+
262
+ raise BadResponseFormat(message)
263
+
264
+
265
+ def raise_error_for_batch_response(
266
+ response: RPCResponse,
267
+ logger: Optional[logging.Logger] = None,
268
+ ) -> NoReturn:
269
+ error = response.get("error")
270
+ if error is None:
271
+ _raise_bad_response_format(
272
+ response,
273
+ "Batch response must be formatted as a list of responses or "
274
+ "as a single JSON-RPC error response.",
275
+ )
276
+ validate_rpc_response_and_raise_if_error(
277
+ response,
278
+ None,
279
+ is_subscription_response=False,
280
+ logger=logger,
281
+ params=[],
282
+ )
283
+ # This should not be reached, but if it is, raise a generic `BadResponseFormat`
284
+ raise BadResponseFormat(
285
+ "Batch response was in an unexpected format and unable to be parsed."
286
+ )
287
+
288
+
289
+ def validate_rpc_response_and_raise_if_error(
290
+ response: RPCResponse,
291
+ error_formatters: Optional[Callable[..., Any]],
292
+ is_subscription_response: bool = False,
293
+ logger: Optional[logging.Logger] = None,
294
+ params: Optional[Any] = None,
295
+ ) -> None:
296
+ if "jsonrpc" not in response or response["jsonrpc"] != "2.0":
297
+ _raise_bad_response_format(
298
+ response, 'The "jsonrpc" field must be present with a value of "2.0".'
299
+ )
300
+
301
+ response_id = response.get("id")
302
+ if "id" in response:
303
+ int_error_msg = (
304
+ '"id" must be an integer or a string representation of an integer.'
305
+ )
306
+ if response_id is None and "error" in response:
307
+ # errors can sometimes have null `id`, according to the JSON-RPC spec
308
+ pass
309
+ elif not isinstance(response_id, (str, int)):
310
+ _raise_bad_response_format(response, int_error_msg)
311
+ elif isinstance(response_id, str):
312
+ try:
313
+ int(response_id)
314
+ except ValueError:
315
+ _raise_bad_response_format(response, int_error_msg)
316
+ elif is_subscription_response:
317
+ # if `id` is not present, this must be a subscription response
318
+ _validate_subscription_fields(response)
319
+ else:
320
+ _raise_bad_response_format(
321
+ response,
322
+ 'Response must include an "id" field or be formatted as an '
323
+ "`eth_subscription` response.",
324
+ )
325
+
326
+ if all(key in response for key in {"error", "result"}):
327
+ _raise_bad_response_format(
328
+ response, 'Response cannot include both "error" and "result".'
329
+ )
330
+ elif (
331
+ not any(key in response for key in {"error", "result"})
332
+ and not is_subscription_response
333
+ ):
334
+ _raise_bad_response_format(
335
+ response, 'Response must include either "error" or "result".'
336
+ )
337
+ elif "error" in response:
338
+ web3_rpc_error: Optional[Web3RPCError] = None
339
+ error = response["error"]
340
+
341
+ # raise the error when the value is a string
342
+ if error is None or not isinstance(error, dict):
343
+ _raise_bad_response_format(
344
+ response,
345
+ 'response["error"] must be a valid object as defined by the '
346
+ "JSON-RPC 2.0 specification.",
347
+ )
348
+
349
+ # errors must include a message
350
+ error_message = error.get("message")
351
+ if not isinstance(error_message, str):
352
+ _raise_bad_response_format(
353
+ response, 'error["message"] is required and must be a string value.'
354
+ )
355
+ elif error_message == "transaction not found":
356
+ transaction_hash = params[0]
357
+ web3_rpc_error = TransactionNotFound(
358
+ repr(error),
359
+ rpc_response=response,
360
+ user_message=(f"Transaction with hash {transaction_hash!r} not found."),
361
+ )
362
+
363
+ # errors must include an integer code
364
+ code = error.get("code")
365
+ if not isinstance(code, int):
366
+ _raise_bad_response_format(
367
+ response, 'error["code"] is required and must be an integer value.'
368
+ )
369
+ elif code == METHOD_NOT_FOUND:
370
+ web3_rpc_error = MethodUnavailable(
371
+ repr(error),
372
+ rpc_response=response,
373
+ user_message=(
374
+ "This method is not available. Check your node provider or your "
375
+ "client's API docs to see what methods are supported and / or "
376
+ "currently enabled."
377
+ ),
378
+ )
379
+ elif any(
380
+ # parse specific timeout messages
381
+ timeout_str in error_message.lower()
382
+ for timeout_str in KNOWN_REQUEST_TIMEOUT_MESSAGING
383
+ ):
384
+ web3_rpc_error = RequestTimedOut(
385
+ repr(error),
386
+ rpc_response=response,
387
+ user_message=(
388
+ "The request timed out. Check the connection to your node and "
389
+ "try again."
390
+ ),
391
+ )
392
+
393
+ if web3_rpc_error is None:
394
+ # if no condition was met above, raise a more generic `Web3RPCError`
395
+ web3_rpc_error = Web3RPCError(repr(error), rpc_response=response)
396
+
397
+ response = apply_error_formatters(error_formatters, response)
398
+ if logger is not None:
399
+ logger.debug(f"RPC error response: {response}")
400
+
401
+ raise web3_rpc_error
402
+
403
+ elif "result" not in response and not is_subscription_response:
404
+ _raise_bad_response_format(response)
web3/eth/async_eth.py CHANGED
@@ -7,6 +7,7 @@ from typing import (
7
7
  Dict,
8
8
  List,
9
9
  Optional,
10
+ Sequence,
10
11
  Tuple,
11
12
  Type,
12
13
  Union,
@@ -89,6 +90,8 @@ from web3.types import (
89
90
  LogsSubscriptionArg,
90
91
  Nonce,
91
92
  SignedTx,
93
+ SimulateV1Payload,
94
+ SimulateV1Result,
92
95
  StateOverride,
93
96
  SubscriptionType,
94
97
  SyncStatus,
@@ -288,6 +291,22 @@ class AsyncEth(BaseEth):
288
291
 
289
292
  raise TooManyRequests("Too many CCIP read redirects")
290
293
 
294
+ # eth_simulateV1
295
+
296
+ _simulateV1: Method[
297
+ Callable[
298
+ [SimulateV1Payload, BlockIdentifier],
299
+ Awaitable[Sequence[SimulateV1Result]],
300
+ ]
301
+ ] = Method(RPC.eth_simulateV1)
302
+
303
+ async def simulate_v1(
304
+ self,
305
+ payload: SimulateV1Payload,
306
+ block_identifier: BlockIdentifier,
307
+ ) -> Sequence[SimulateV1Result]:
308
+ return await self._simulateV1(payload, block_identifier)
309
+
291
310
  # eth_createAccessList
292
311
 
293
312
  _create_access_list: Method[
web3/eth/eth.py CHANGED
@@ -85,6 +85,8 @@ from web3.types import (
85
85
  MerkleProof,
86
86
  Nonce,
87
87
  SignedTx,
88
+ SimulateV1Payload,
89
+ SimulateV1Result,
88
90
  StateOverride,
89
91
  SyncStatus,
90
92
  TxData,
@@ -270,6 +272,19 @@ class Eth(BaseEth):
270
272
 
271
273
  raise TooManyRequests("Too many CCIP read redirects")
272
274
 
275
+ # eth_simulateV1
276
+
277
+ _simulateV1: Method[
278
+ Callable[[SimulateV1Payload, BlockIdentifier], Sequence[SimulateV1Result]]
279
+ ] = Method(RPC.eth_simulateV1)
280
+
281
+ def simulate_v1(
282
+ self,
283
+ payload: SimulateV1Payload,
284
+ block_identifier: BlockIdentifier,
285
+ ) -> Sequence[SimulateV1Result]:
286
+ return self._simulateV1(payload, block_identifier)
287
+
273
288
  # eth_createAccessList
274
289
 
275
290
  _create_access_list: Method[
@@ -15,6 +15,6 @@ def rpc_gas_price_strategy(
15
15
  w3: Web3, transaction_params: Optional[TxParams] = None
16
16
  ) -> Wei:
17
17
  """
18
- A simple gas price strategy deriving it's value from the eth_gasPrice JSON-RPC call.
18
+ A simple gas price strategy deriving its value from the eth_gasPrice JSON-RPC call.
19
19
  """
20
20
  return w3.eth.gas_price
@@ -158,7 +158,7 @@ def _compute_gas_price(
158
158
 
159
159
  :param probabilities: An iterable of `Probability` named-tuples
160
160
  sorted in reverse order.
161
- :param desired_probability: An floating point representation of the desired
161
+ :param desired_probability: A floating point representation of the desired
162
162
  probability. (e.g. ``85% -> 0.85``)
163
163
  """
164
164
  first = probabilities[0]
web3/manager.py CHANGED
@@ -8,7 +8,6 @@ from typing import (
8
8
  Coroutine,
9
9
  Dict,
10
10
  List,
11
- NoReturn,
12
11
  Optional,
13
12
  Sequence,
14
13
  Tuple,
@@ -32,17 +31,19 @@ from web3._utils.caching import (
32
31
  from web3._utils.compat import (
33
32
  Self,
34
33
  )
34
+ from web3._utils.formatters import (
35
+ apply_null_result_formatters,
36
+ )
37
+ from web3._utils.validation import (
38
+ raise_error_for_batch_response,
39
+ validate_rpc_response_and_raise_if_error,
40
+ )
35
41
  from web3.datastructures import (
36
42
  NamedElementOnion,
37
43
  )
38
44
  from web3.exceptions import (
39
- BadResponseFormat,
40
- MethodUnavailable,
41
45
  ProviderConnectionError,
42
- RequestTimedOut,
43
46
  TaskNotRunning,
44
- TransactionNotFound,
45
- Web3RPCError,
46
47
  Web3TypeError,
47
48
  )
48
49
  from web3.method import (
@@ -95,200 +96,6 @@ if TYPE_CHECKING:
95
96
 
96
97
 
97
98
  NULL_RESPONSES = [None, HexBytes("0x"), "0x"]
98
- KNOWN_REQUEST_TIMEOUT_MESSAGING = {
99
- # Note: It's important to be very explicit here and not too broad. We don't want
100
- # to accidentally catch a message that is not for a request timeout. In the worst
101
- # case, we raise something more generic like `Web3RPCError`. JSON-RPC unfortunately
102
- # has not standardized error codes for request timeouts.
103
- "request timed out", # go-ethereum
104
- }
105
- METHOD_NOT_FOUND = -32601
106
-
107
-
108
- def _raise_bad_response_format(response: RPCResponse, error: str = "") -> None:
109
- message = "The response was in an unexpected format and unable to be parsed."
110
- raw_response = f"The raw response is: {response}"
111
-
112
- if error is not None and error != "":
113
- error = error[:-1] if error.endswith(".") else error
114
- message = f"{message} {error}. {raw_response}"
115
- else:
116
- message = f"{message} {raw_response}"
117
-
118
- raise BadResponseFormat(message)
119
-
120
-
121
- def apply_error_formatters(
122
- error_formatters: Callable[..., Any],
123
- response: RPCResponse,
124
- ) -> RPCResponse:
125
- if error_formatters:
126
- formatted_resp = pipe(response, error_formatters)
127
- return formatted_resp
128
- else:
129
- return response
130
-
131
-
132
- def apply_null_result_formatters(
133
- null_result_formatters: Callable[..., Any],
134
- response: RPCResponse,
135
- params: Optional[Any] = None,
136
- ) -> RPCResponse:
137
- if null_result_formatters:
138
- formatted_resp = pipe(params, null_result_formatters)
139
- return formatted_resp
140
- else:
141
- return response
142
-
143
-
144
- def _validate_subscription_fields(response: RPCResponse) -> None:
145
- params = response["params"]
146
- subscription = params["subscription"]
147
- if not isinstance(subscription, str) and not len(subscription) == 34:
148
- _raise_bad_response_format(
149
- response, "eth_subscription 'params' must include a 'subscription' field."
150
- )
151
-
152
-
153
- def _validate_response(
154
- response: RPCResponse,
155
- error_formatters: Optional[Callable[..., Any]],
156
- is_subscription_response: bool = False,
157
- logger: Optional[logging.Logger] = None,
158
- params: Optional[Any] = None,
159
- ) -> None:
160
- if "jsonrpc" not in response or response["jsonrpc"] != "2.0":
161
- _raise_bad_response_format(
162
- response, 'The "jsonrpc" field must be present with a value of "2.0".'
163
- )
164
-
165
- response_id = response.get("id")
166
- if "id" in response:
167
- int_error_msg = (
168
- '"id" must be an integer or a string representation of an integer.'
169
- )
170
- if response_id is None and "error" in response:
171
- # errors can sometimes have null `id`, according to the JSON-RPC spec
172
- pass
173
- elif not isinstance(response_id, (str, int)):
174
- _raise_bad_response_format(response, int_error_msg)
175
- elif isinstance(response_id, str):
176
- try:
177
- int(response_id)
178
- except ValueError:
179
- _raise_bad_response_format(response, int_error_msg)
180
- elif is_subscription_response:
181
- # if `id` is not present, this must be a subscription response
182
- _validate_subscription_fields(response)
183
- else:
184
- _raise_bad_response_format(
185
- response,
186
- 'Response must include an "id" field or be formatted as an '
187
- "`eth_subscription` response.",
188
- )
189
-
190
- if all(key in response for key in {"error", "result"}):
191
- _raise_bad_response_format(
192
- response, 'Response cannot include both "error" and "result".'
193
- )
194
- elif (
195
- not any(key in response for key in {"error", "result"})
196
- and not is_subscription_response
197
- ):
198
- _raise_bad_response_format(
199
- response, 'Response must include either "error" or "result".'
200
- )
201
- elif "error" in response:
202
- web3_rpc_error: Optional[Web3RPCError] = None
203
- error = response["error"]
204
-
205
- # raise the error when the value is a string
206
- if error is None or not isinstance(error, dict):
207
- _raise_bad_response_format(
208
- response,
209
- 'response["error"] must be a valid object as defined by the '
210
- "JSON-RPC 2.0 specification.",
211
- )
212
-
213
- # errors must include a message
214
- error_message = error.get("message")
215
- if not isinstance(error_message, str):
216
- _raise_bad_response_format(
217
- response, 'error["message"] is required and must be a string value.'
218
- )
219
- elif error_message == "transaction not found":
220
- transaction_hash = params[0]
221
- web3_rpc_error = TransactionNotFound(
222
- repr(error),
223
- rpc_response=response,
224
- user_message=(f"Transaction with hash {transaction_hash!r} not found."),
225
- )
226
-
227
- # errors must include an integer code
228
- code = error.get("code")
229
- if not isinstance(code, int):
230
- _raise_bad_response_format(
231
- response, 'error["code"] is required and must be an integer value.'
232
- )
233
- elif code == METHOD_NOT_FOUND:
234
- web3_rpc_error = MethodUnavailable(
235
- repr(error),
236
- rpc_response=response,
237
- user_message=(
238
- "This method is not available. Check your node provider or your "
239
- "client's API docs to see what methods are supported and / or "
240
- "currently enabled."
241
- ),
242
- )
243
- elif any(
244
- # parse specific timeout messages
245
- timeout_str in error_message.lower()
246
- for timeout_str in KNOWN_REQUEST_TIMEOUT_MESSAGING
247
- ):
248
- web3_rpc_error = RequestTimedOut(
249
- repr(error),
250
- rpc_response=response,
251
- user_message=(
252
- "The request timed out. Check the connection to your node and "
253
- "try again."
254
- ),
255
- )
256
-
257
- if web3_rpc_error is None:
258
- # if no condition was met above, raise a more generic `Web3RPCError`
259
- web3_rpc_error = Web3RPCError(repr(error), rpc_response=response)
260
-
261
- response = apply_error_formatters(error_formatters, response)
262
- logger.debug(f"RPC error response: {response}")
263
-
264
- raise web3_rpc_error
265
-
266
- elif "result" not in response and not is_subscription_response:
267
- _raise_bad_response_format(response)
268
-
269
-
270
- def _raise_error_for_batch_response(
271
- response: RPCResponse,
272
- logger: Optional[logging.Logger] = None,
273
- ) -> NoReturn:
274
- error = response.get("error")
275
- if error is None:
276
- _raise_bad_response_format(
277
- response,
278
- "Batch response must be formatted as a list of responses or "
279
- "as a single JSON-RPC error response.",
280
- )
281
- _validate_response(
282
- response,
283
- None,
284
- is_subscription_response=False,
285
- logger=logger,
286
- params=[],
287
- )
288
- # This should not be reached, but if it is, raise a generic `BadResponseFormat`
289
- raise BadResponseFormat(
290
- "Batch response was in an unexpected format and unable to be parsed."
291
- )
292
99
 
293
100
 
294
101
  class RequestManager:
@@ -388,7 +195,7 @@ class RequestManager:
388
195
  and response["params"].get("result") is not None
389
196
  )
390
197
 
391
- _validate_response(
198
+ validate_rpc_response_and_raise_if_error(
392
199
  response,
393
200
  error_formatters,
394
201
  is_subscription_response=is_subscription_response,
@@ -447,6 +254,8 @@ class RequestManager:
447
254
  """
448
255
  Context manager for making batch requests
449
256
  """
257
+ if isinstance(self.provider, AutoProvider):
258
+ self.provider = self.provider._get_active_provider(use_cache=True)
450
259
  if not isinstance(self.provider, (AsyncJSONBaseProvider, JSONBaseProvider)):
451
260
  raise Web3TypeError("Batch requests are not supported by this provider.")
452
261
  return RequestBatcher(self.w3)
@@ -477,7 +286,7 @@ class RequestManager:
477
286
  return list(formatted_responses)
478
287
  else:
479
288
  # expect a single response with an error
480
- _raise_error_for_batch_response(response, self.logger)
289
+ raise_error_for_batch_response(response, self.logger)
481
290
 
482
291
  async def _async_make_batch_request(
483
292
  self,
@@ -520,7 +329,7 @@ class RequestManager:
520
329
  return list(formatted_responses)
521
330
  else:
522
331
  # expect a single response with an error
523
- _raise_error_for_batch_response(response, self.logger)
332
+ raise_error_for_batch_response(response, self.logger)
524
333
 
525
334
  def _format_batched_response(
526
335
  self,
@@ -528,7 +337,7 @@ class RequestManager:
528
337
  response: RPCResponse,
529
338
  ) -> RPCResponse:
530
339
  result_formatters, error_formatters, null_result_formatters = requests_info[1]
531
- _validate_response(
340
+ validate_rpc_response_and_raise_if_error(
532
341
  response,
533
342
  error_formatters,
534
343
  is_subscription_response=False,
@@ -53,7 +53,7 @@ from web3.utils import (
53
53
  )
54
54
 
55
55
  if TYPE_CHECKING:
56
- from websockets import (
56
+ from websockets.legacy.client import (
57
57
  WebSocketClientProtocol,
58
58
  )
59
59
 
@@ -21,11 +21,9 @@ from typing import (
21
21
  from eth_typing import (
22
22
  URI,
23
23
  )
24
- from websockets.client import (
25
- connect,
26
- )
27
24
  from websockets.legacy.client import (
28
25
  WebSocketClientProtocol,
26
+ connect,
29
27
  )
30
28
 
31
29
  from web3._utils.batching import (