web3 7.0.0b6__py3-none-any.whl → 7.0.0b8__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 (68) hide show
  1. ens/__init__.py +13 -2
  2. web3/__init__.py +21 -5
  3. web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
  4. web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
  5. web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
  6. web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
  7. web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
  8. web3/_utils/contract_sources/contract_data/event_contracts.py +5 -5
  9. web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
  10. web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
  11. web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
  12. web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
  13. web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
  14. web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
  15. web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
  16. web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
  17. web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
  18. web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
  19. web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
  20. web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
  21. web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
  22. web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
  23. web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
  24. web3/_utils/http.py +3 -0
  25. web3/_utils/http_session_manager.py +280 -0
  26. web3/_utils/method_formatters.py +19 -3
  27. web3/_utils/module_testing/eth_module.py +84 -111
  28. web3/_utils/module_testing/module_testing_utils.py +22 -18
  29. web3/_utils/module_testing/persistent_connection_provider.py +45 -16
  30. web3/_utils/rpc_abi.py +0 -3
  31. web3/beacon/__init__.py +5 -0
  32. web3/beacon/async_beacon.py +9 -5
  33. web3/beacon/beacon.py +7 -5
  34. web3/contract/__init__.py +7 -0
  35. web3/contract/base_contract.py +10 -1
  36. web3/eth/__init__.py +7 -0
  37. web3/eth/async_eth.py +0 -33
  38. web3/eth/eth.py +2 -53
  39. web3/exceptions.py +6 -0
  40. web3/manager.py +34 -11
  41. web3/middleware/__init__.py +17 -0
  42. web3/module.py +1 -1
  43. web3/providers/__init__.py +21 -0
  44. web3/providers/eth_tester/__init__.py +5 -0
  45. web3/providers/eth_tester/defaults.py +0 -6
  46. web3/providers/eth_tester/middleware.py +3 -8
  47. web3/providers/persistent/__init__.py +7 -0
  48. web3/providers/persistent/async_ipc.py +34 -79
  49. web3/providers/persistent/persistent.py +76 -7
  50. web3/providers/persistent/persistent_connection.py +47 -5
  51. web3/providers/persistent/websocket.py +19 -59
  52. web3/providers/rpc/__init__.py +5 -0
  53. web3/providers/rpc/async_rpc.py +16 -12
  54. web3/providers/rpc/rpc.py +16 -12
  55. web3/providers/rpc/utils.py +0 -3
  56. web3/tools/benchmark/main.py +7 -6
  57. web3/tools/benchmark/node.py +1 -1
  58. web3/utils/__init__.py +14 -5
  59. web3/utils/async_exception_handling.py +19 -7
  60. web3/utils/caching.py +24 -0
  61. web3/utils/exception_handling.py +7 -5
  62. {web3-7.0.0b6.dist-info → web3-7.0.0b8.dist-info}/METADATA +14 -8
  63. {web3-7.0.0b6.dist-info → web3-7.0.0b8.dist-info}/RECORD +66 -67
  64. {web3-7.0.0b6.dist-info → web3-7.0.0b8.dist-info}/WHEEL +1 -1
  65. web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
  66. web3/_utils/request.py +0 -265
  67. {web3-7.0.0b6.dist-info → web3-7.0.0b8.dist-info}/LICENSE +0 -0
  68. {web3-7.0.0b6.dist-info → web3-7.0.0b8.dist-info}/top_level.txt +0 -0
@@ -11,11 +11,9 @@ from pathlib import (
11
11
  import sys
12
12
  from typing import (
13
13
  Any,
14
- List,
15
14
  Optional,
16
15
  Tuple,
17
16
  Union,
18
- cast,
19
17
  )
20
18
 
21
19
  from eth_utils import (
@@ -23,20 +21,12 @@ from eth_utils import (
23
21
  )
24
22
 
25
23
  from web3.types import (
26
- RPCEndpoint,
27
24
  RPCResponse,
28
25
  )
29
26
 
30
27
  from . import (
31
28
  PersistentConnectionProvider,
32
29
  )
33
- from ..._utils.batching import (
34
- BATCH_REQUEST_ID,
35
- sort_batch_response_by_response_ids,
36
- )
37
- from ..._utils.caching import (
38
- async_handle_request_caching,
39
- )
40
30
  from ...exceptions import (
41
31
  ProviderConnectionError,
42
32
  Web3TypeError,
@@ -91,12 +81,7 @@ class AsyncIPCProvider(PersistentConnectionProvider):
91
81
  return False
92
82
 
93
83
  try:
94
- request_data = self.encode_rpc_request(
95
- RPCEndpoint("web3_clientVersions"), []
96
- )
97
- self._writer.write(request_data)
98
- current_request_id = json.loads(request_data)["id"]
99
- await self._get_response_for_request_id(current_request_id, timeout=2)
84
+ await self.make_request("web3_clientVersion", [])
100
85
  return True
101
86
  except (OSError, ProviderConnectionError) as e:
102
87
  if show_traceback:
@@ -105,55 +90,33 @@ class AsyncIPCProvider(PersistentConnectionProvider):
105
90
  )
106
91
  return False
107
92
 
108
- async def _provider_specific_connect(self) -> None:
109
- self._reader, self._writer = await async_get_ipc_socket(self.ipc_path)
110
-
111
- async def _provider_specific_disconnect(self) -> None:
112
- if self._writer and not self._writer.is_closing():
113
- self._writer.close()
114
- await self._writer.wait_closed()
115
- self._writer = None
116
- if self._reader:
117
- self._reader = None
118
-
119
- async def _reset_socket(self) -> None:
120
- self._writer.close()
121
- await self._writer.wait_closed()
122
- self._reader, self._writer = await async_get_ipc_socket(self.ipc_path)
123
-
124
- @async_handle_request_caching
125
- async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
93
+ async def socket_send(self, request_data: bytes) -> None:
126
94
  if self._writer is None:
127
95
  raise ProviderConnectionError(
128
96
  "Connection to ipc socket has not been initiated for the provider."
129
97
  )
130
98
 
131
- request_data = self.encode_rpc_request(method, params)
132
- try:
133
- self._writer.write(request_data)
134
- await self._writer.drain()
135
- except OSError as e:
136
- # Broken pipe
137
- if e.errno == errno.EPIPE:
138
- # one extra attempt, then give up
139
- await self._reset_socket()
140
- self._writer.write(request_data)
141
- await self._writer.drain()
99
+ return await asyncio.wait_for(
100
+ self._socket_send(request_data), timeout=self.request_timeout
101
+ )
142
102
 
143
- current_request_id = json.loads(request_data)["id"]
144
- response = await self._get_response_for_request_id(current_request_id)
103
+ async def socket_recv(self) -> RPCResponse:
104
+ while True:
105
+ # yield to the event loop to allow other tasks to run
106
+ await asyncio.sleep(0)
145
107
 
146
- return response
108
+ try:
109
+ response, pos = self._decoder.raw_decode(self._raw_message)
110
+ self._raw_message = self._raw_message[pos:].lstrip()
111
+ return response
112
+ except JSONDecodeError:
113
+ # read more data from the socket if the current raw message is
114
+ # incomplete
115
+ self._raw_message += to_text(await self._reader.read(4096)).lstrip()
147
116
 
148
- async def make_batch_request(
149
- self, requests: List[Tuple[RPCEndpoint, Any]]
150
- ) -> List[RPCResponse]:
151
- if self._writer is None:
152
- raise ProviderConnectionError(
153
- "Connection to ipc socket has not been initiated for the provider."
154
- )
117
+ # -- private methods -- #
155
118
 
156
- request_data = self.encode_batch_rpc_request(requests)
119
+ async def _socket_send(self, request_data: bytes) -> None:
157
120
  try:
158
121
  self._writer.write(request_data)
159
122
  await self._writer.drain()
@@ -165,32 +128,24 @@ class AsyncIPCProvider(PersistentConnectionProvider):
165
128
  self._writer.write(request_data)
166
129
  await self._writer.drain()
167
130
 
168
- response = cast(
169
- List[RPCResponse], await self._get_response_for_request_id(BATCH_REQUEST_ID)
170
- )
171
- return response
172
-
173
- async def _provider_specific_message_listener(self) -> None:
174
- self._raw_message += to_text(await self._reader.read(4096)).lstrip()
131
+ async def _reset_socket(self) -> None:
132
+ self._writer.close()
133
+ await self._writer.wait_closed()
134
+ self._reader, self._writer = await async_get_ipc_socket(self.ipc_path)
175
135
 
176
- while self._raw_message:
177
- try:
178
- response, pos = self._decoder.raw_decode(self._raw_message)
179
- except JSONDecodeError:
180
- break
136
+ async def _provider_specific_connect(self) -> None:
137
+ self._reader, self._writer = await async_get_ipc_socket(self.ipc_path)
181
138
 
182
- if isinstance(response, list):
183
- response = sort_batch_response_by_response_ids(response)
139
+ async def _provider_specific_disconnect(self) -> None:
140
+ if self._writer and not self._writer.is_closing():
141
+ self._writer.close()
142
+ await self._writer.wait_closed()
143
+ self._writer = None
144
+ if self._reader:
145
+ self._reader = None
184
146
 
185
- is_subscription = (
186
- response.get("method") == "eth_subscription"
187
- if not isinstance(response, list)
188
- else False
189
- )
190
- await self._request_processor.cache_raw_response(
191
- response, subscription=is_subscription
192
- )
193
- self._raw_message = self._raw_message[pos:].lstrip()
147
+ async def _provider_specific_socket_reader(self) -> RPCResponse:
148
+ return await self.socket_recv()
194
149
 
195
150
  def _error_log_listener_task_exception(self, e: Exception) -> None:
196
151
  super()._error_log_listener_task_exception(e)
@@ -1,13 +1,17 @@
1
1
  from abc import (
2
2
  ABC,
3
+ abstractmethod,
3
4
  )
4
5
  import asyncio
6
+ import json
5
7
  import logging
6
8
  from typing import (
7
9
  Any,
8
10
  List,
9
11
  Optional,
12
+ Tuple,
10
13
  Union,
14
+ cast,
11
15
  )
12
16
 
13
17
  from websockets import (
@@ -15,13 +19,20 @@ from websockets import (
15
19
  WebSocketException,
16
20
  )
17
21
 
22
+ from web3._utils.batching import (
23
+ BATCH_REQUEST_ID,
24
+ sort_batch_response_by_response_ids,
25
+ )
18
26
  from web3._utils.caching import (
27
+ async_handle_request_caching,
19
28
  generate_cache_key,
20
29
  )
21
30
  from web3.exceptions import (
31
+ PersistentConnectionClosedOK,
22
32
  ProviderConnectionError,
23
33
  TaskNotRunning,
24
34
  TimeExhausted,
35
+ Web3AttributeError,
25
36
  )
26
37
  from web3.providers.async_base import (
27
38
  AsyncJSONBaseProvider,
@@ -30,6 +41,7 @@ from web3.providers.persistent.request_processor import (
30
41
  RequestProcessor,
31
42
  )
32
43
  from web3.types import (
44
+ RPCEndpoint,
33
45
  RPCId,
34
46
  RPCResponse,
35
47
  )
@@ -70,7 +82,7 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
70
82
  elif hasattr(self, "ipc_path"):
71
83
  return str(self.ipc_path)
72
84
  else:
73
- raise AttributeError(
85
+ raise Web3AttributeError(
74
86
  "`PersistentConnectionProvider` must have either `endpoint_uri` or "
75
87
  "`ipc_path` attribute."
76
88
  )
@@ -128,6 +140,44 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
128
140
  f"Successfully disconnected from: {self.get_endpoint_uri_or_ipc_path()}"
129
141
  )
130
142
 
143
+ @async_handle_request_caching
144
+ async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
145
+ request_data = self.encode_rpc_request(method, params)
146
+ await self.socket_send(request_data)
147
+
148
+ current_request_id = json.loads(request_data)["id"]
149
+ response = await self._get_response_for_request_id(current_request_id)
150
+
151
+ return response
152
+
153
+ async def make_batch_request(
154
+ self, requests: List[Tuple[RPCEndpoint, Any]]
155
+ ) -> List[RPCResponse]:
156
+ request_data = self.encode_batch_rpc_request(requests)
157
+ await self.socket_send(request_data)
158
+
159
+ response = cast(
160
+ List[RPCResponse], await self._get_response_for_request_id(BATCH_REQUEST_ID)
161
+ )
162
+ return response
163
+
164
+ # -- abstract methods -- #
165
+
166
+ @abstractmethod
167
+ async def socket_send(self, request_data: bytes) -> None:
168
+ """
169
+ Send an encoded RPC request to the provider over the persistent connection.
170
+ """
171
+ raise NotImplementedError("Must be implemented by subclasses")
172
+
173
+ @abstractmethod
174
+ async def socket_recv(self) -> RPCResponse:
175
+ """
176
+ Receive, decode, and return an RPC response from the provider over the
177
+ persistent connection.
178
+ """
179
+ raise NotImplementedError("Must be implemented by subclasses")
180
+
131
181
  # -- private methods -- #
132
182
 
133
183
  async def _provider_specific_connect(self) -> None:
@@ -136,7 +186,7 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
136
186
  async def _provider_specific_disconnect(self) -> None:
137
187
  raise NotImplementedError("Must be implemented by subclasses")
138
188
 
139
- async def _provider_specific_message_listener(self) -> None:
189
+ async def _provider_specific_socket_reader(self) -> RPCResponse:
140
190
  raise NotImplementedError("Must be implemented by subclasses")
141
191
 
142
192
  def _message_listener_callback(
@@ -158,8 +208,28 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
158
208
  # the use of sleep(0) seems to be the most efficient way to yield control
159
209
  # back to the event loop to share the loop with other tasks.
160
210
  await asyncio.sleep(0)
211
+
161
212
  try:
162
- await self._provider_specific_message_listener()
213
+ response = await self._provider_specific_socket_reader()
214
+
215
+ if isinstance(response, list):
216
+ response = sort_batch_response_by_response_ids(response)
217
+
218
+ subscription = (
219
+ response.get("method") == "eth_subscription"
220
+ if not isinstance(response, list)
221
+ else False
222
+ )
223
+ await self._request_processor.cache_raw_response(
224
+ response, subscription=subscription
225
+ )
226
+ except PersistentConnectionClosedOK as e:
227
+ self.logger.info(
228
+ "Message listener background task has ended gracefully: "
229
+ f"{e.user_message}"
230
+ )
231
+ # trigger a return to end the listener task and initiate the callback fn
232
+ return
163
233
  except Exception as e:
164
234
  if not self.silence_listener_task_exceptions:
165
235
  raise e
@@ -202,10 +272,6 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
202
272
  request_cache_key = generate_cache_key(request_id)
203
273
 
204
274
  while True:
205
- # check if an exception was recorded in the listener task and raise it
206
- # in the main loop if so
207
- self._handle_listener_task_exceptions()
208
-
209
275
  if request_cache_key in self._request_processor._request_response_cache:
210
276
  self.logger.debug(
211
277
  f"Popping response for id {request_id} from cache."
@@ -215,6 +281,9 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
215
281
  )
216
282
  return popped_response
217
283
  else:
284
+ # check if an exception was recorded in the listener task and raise
285
+ # it in the main loop if so
286
+ self._handle_listener_task_exceptions()
218
287
  await asyncio.sleep(0)
219
288
 
220
289
  try:
@@ -27,16 +27,58 @@ class PersistentConnection:
27
27
  def __init__(self, w3: "AsyncWeb3"):
28
28
  self._manager = w3.manager
29
29
 
30
- # -- public methods -- #
31
30
  @property
32
31
  def subscriptions(self) -> Dict[str, Any]:
32
+ """
33
+ Return the active subscriptions on the persistent connection.
34
+
35
+ :return: The active subscriptions on the persistent connection.
36
+ :rtype: Dict[str, Any]
37
+ """
33
38
  return self._manager._request_processor.active_subscriptions
34
39
 
35
- async def send(self, method: RPCEndpoint, params: Any) -> RPCResponse:
36
- return await self._manager.send(method, params)
40
+ async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
41
+ """
42
+ Make a request to the persistent connection and return the response. This method
43
+ does not process the response as it would when invoking a method via the
44
+ appropriate module on the `AsyncWeb3` instance,
45
+ e.g. `w3.eth.get_block("latest")`.
46
+
47
+ :param method: The RPC method, e.g. `eth_getBlockByNumber`.
48
+ :param params: The RPC method parameters, e.g. `["0x1337", False]`.
49
+
50
+ :return: The processed response from the persistent connection.
51
+ :rtype: RPCResponse
52
+ """
53
+ return await self._manager.socket_request(method, params)
54
+
55
+ async def send(self, method: RPCEndpoint, params: Any) -> None:
56
+ """
57
+ Send a raw, unprocessed message to the persistent connection.
37
58
 
38
- async def recv(self) -> Any:
39
- return await self._manager._get_next_message()
59
+ :param method: The RPC method, e.g. `eth_getBlockByNumber`.
60
+ :param params: The RPC method parameters, e.g. `["0x1337", False]`.
61
+
62
+ :return: None
63
+ """
64
+ await self._manager.send(method, params)
65
+
66
+ async def recv(self) -> RPCResponse:
67
+ """
68
+ Receive the next unprocessed response for a request from the persistent
69
+ connection.
70
+
71
+ :return: The next unprocessed response for a request from the persistent
72
+ connection.
73
+ :rtype: RPCResponse
74
+ """
75
+ return await self._manager.recv()
40
76
 
41
77
  def process_subscriptions(self) -> "_AsyncPersistentMessageStream":
78
+ """
79
+ Asynchronous iterator that yields messages from the subscription message stream.
80
+
81
+ :return: The subscription message stream.
82
+ :rtype: _AsyncPersistentMessageStream
83
+ """
42
84
  return self._manager._persistent_message_stream()
@@ -5,11 +5,8 @@ import os
5
5
  from typing import (
6
6
  Any,
7
7
  Dict,
8
- List,
9
8
  Optional,
10
- Tuple,
11
9
  Union,
12
- cast,
13
10
  )
14
11
 
15
12
  from eth_typing import (
@@ -25,17 +22,12 @@ from websockets.client import (
25
22
  connect,
26
23
  )
27
24
  from websockets.exceptions import (
25
+ ConnectionClosedOK,
28
26
  WebSocketException,
29
27
  )
30
28
 
31
- from web3._utils.batching import (
32
- BATCH_REQUEST_ID,
33
- sort_batch_response_by_response_ids,
34
- )
35
- from web3._utils.caching import (
36
- async_handle_request_caching,
37
- )
38
29
  from web3.exceptions import (
30
+ PersistentConnectionClosedOK,
39
31
  ProviderConnectionError,
40
32
  Web3ValidationError,
41
33
  )
@@ -43,7 +35,6 @@ from web3.providers.persistent import (
43
35
  PersistentConnectionProvider,
44
36
  )
45
37
  from web3.types import (
46
- RPCEndpoint,
47
38
  RPCResponse,
48
39
  )
49
40
 
@@ -122,18 +113,7 @@ class WebSocketProvider(PersistentConnectionProvider):
122
113
  ) from e
123
114
  return False
124
115
 
125
- async def _provider_specific_connect(self) -> None:
126
- self._ws = await connect(self.endpoint_uri, **self.websocket_kwargs)
127
-
128
- async def _provider_specific_disconnect(self) -> None:
129
- if self._ws is not None and not self._ws.closed:
130
- await self._ws.close()
131
- self._ws = None
132
-
133
- @async_handle_request_caching
134
- async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
135
- request_data = self.encode_rpc_request(method, params)
136
-
116
+ async def socket_send(self, request_data: bytes) -> None:
137
117
  if self._ws is None:
138
118
  raise ProviderConnectionError(
139
119
  "Connection to websocket has not been initiated for the provider."
@@ -143,44 +123,24 @@ class WebSocketProvider(PersistentConnectionProvider):
143
123
  self._ws.send(request_data), timeout=self.request_timeout
144
124
  )
145
125
 
146
- current_request_id = json.loads(request_data)["id"]
147
- response = await self._get_response_for_request_id(current_request_id)
148
-
149
- return response
126
+ async def socket_recv(self) -> RPCResponse:
127
+ raw_response = await self._ws.recv()
128
+ return json.loads(raw_response)
150
129
 
151
- async def make_batch_request(
152
- self, requests: List[Tuple[RPCEndpoint, Any]]
153
- ) -> List[RPCResponse]:
154
- request_data = self.encode_batch_rpc_request(requests)
130
+ # -- private methods -- #
155
131
 
156
- if self._ws is None:
157
- raise ProviderConnectionError(
158
- "Connection to websocket has not been initiated for the provider."
159
- )
160
-
161
- await asyncio.wait_for(
162
- self._ws.send(request_data), timeout=self.request_timeout
163
- )
164
-
165
- response = cast(
166
- List[RPCResponse],
167
- await self._get_response_for_request_id(BATCH_REQUEST_ID),
168
- )
169
- return response
170
-
171
- async def _provider_specific_message_listener(self) -> None:
172
- async for raw_message in self._ws:
173
- await asyncio.sleep(0)
132
+ async def _provider_specific_connect(self) -> None:
133
+ self._ws = await connect(self.endpoint_uri, **self.websocket_kwargs)
174
134
 
175
- response = json.loads(raw_message)
176
- if isinstance(response, list):
177
- response = sort_batch_response_by_response_ids(response)
135
+ async def _provider_specific_disconnect(self) -> None:
136
+ if self._ws is not None and not self._ws.closed:
137
+ await self._ws.close()
138
+ self._ws = None
178
139
 
179
- subscription = (
180
- response.get("method") == "eth_subscription"
181
- if not isinstance(response, list)
182
- else False
183
- )
184
- await self._request_processor.cache_raw_response(
185
- response, subscription=subscription
140
+ async def _provider_specific_socket_reader(self) -> RPCResponse:
141
+ try:
142
+ return await self.socket_recv()
143
+ except ConnectionClosedOK:
144
+ raise PersistentConnectionClosedOK(
145
+ user_message="WebSocket connection received `ConnectionClosedOK`."
186
146
  )
@@ -4,3 +4,8 @@ from .async_rpc import (
4
4
  from .rpc import (
5
5
  HTTPProvider,
6
6
  )
7
+
8
+ __all__ = [
9
+ "AsyncHTTPProvider",
10
+ "HTTPProvider",
11
+ ]
@@ -29,11 +29,6 @@ from web3._utils.empty import (
29
29
  from web3._utils.http import (
30
30
  construct_user_agent,
31
31
  )
32
- from web3._utils.request import (
33
- async_cache_and_return_session as _async_cache_and_return_session,
34
- async_make_post_request,
35
- get_default_http_endpoint,
36
- )
37
32
  from web3.types import (
38
33
  RPCEndpoint,
39
34
  RPCResponse,
@@ -45,6 +40,9 @@ from ..._utils.batching import (
45
40
  from ..._utils.caching import (
46
41
  async_handle_request_caching,
47
42
  )
43
+ from ..._utils.http_session_manager import (
44
+ HTTPSessionManager,
45
+ )
48
46
  from ..async_base import (
49
47
  AsyncJSONBaseProvider,
50
48
  )
@@ -63,13 +61,17 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
63
61
  self,
64
62
  endpoint_uri: Optional[Union[URI, str]] = None,
65
63
  request_kwargs: Optional[Any] = None,
66
- exception_retry_configuration: Union[
67
- ExceptionRetryConfiguration, Empty
64
+ exception_retry_configuration: Optional[
65
+ Union[ExceptionRetryConfiguration, Empty]
68
66
  ] = empty,
69
67
  **kwargs: Any,
70
68
  ) -> None:
69
+ self._request_session_manager = HTTPSessionManager()
70
+
71
71
  if endpoint_uri is None:
72
- self.endpoint_uri = get_default_http_endpoint()
72
+ self.endpoint_uri = (
73
+ self._request_session_manager.get_default_http_endpoint()
74
+ )
73
75
  else:
74
76
  self.endpoint_uri = URI(endpoint_uri)
75
77
 
@@ -79,7 +81,9 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
79
81
  super().__init__(**kwargs)
80
82
 
81
83
  async def cache_async_session(self, session: ClientSession) -> ClientSession:
82
- return await _async_cache_and_return_session(self.endpoint_uri, session)
84
+ return await self._request_session_manager.async_cache_and_return_session(
85
+ self.endpoint_uri, session
86
+ )
83
87
 
84
88
  def __str__(self) -> str:
85
89
  return f"RPC connection {self.endpoint_uri}"
@@ -123,7 +127,7 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
123
127
  ):
124
128
  for i in range(self.exception_retry_configuration.retries):
125
129
  try:
126
- return await async_make_post_request(
130
+ return await self._request_session_manager.async_make_post_request(
127
131
  self.endpoint_uri, request_data, **self.get_request_kwargs()
128
132
  )
129
133
  except tuple(self.exception_retry_configuration.errors):
@@ -136,7 +140,7 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
136
140
  raise
137
141
  return None
138
142
  else:
139
- return await async_make_post_request(
143
+ return await self._request_session_manager.async_make_post_request(
140
144
  self.endpoint_uri, request_data, **self.get_request_kwargs()
141
145
  )
142
146
 
@@ -159,7 +163,7 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
159
163
  ) -> List[RPCResponse]:
160
164
  self.logger.debug(f"Making batch request HTTP - uri: `{self.endpoint_uri}`")
161
165
  request_data = self.encode_batch_rpc_request(batch_requests)
162
- raw_response = await async_make_post_request(
166
+ raw_response = await self._request_session_manager.async_make_post_request(
163
167
  self.endpoint_uri, request_data, **self.get_request_kwargs()
164
168
  )
165
169
  self.logger.debug("Received batch response HTTP.")
web3/providers/rpc/rpc.py CHANGED
@@ -27,11 +27,6 @@ from web3._utils.empty import (
27
27
  from web3._utils.http import (
28
28
  construct_user_agent,
29
29
  )
30
- from web3._utils.request import (
31
- cache_and_return_session,
32
- get_default_http_endpoint,
33
- make_post_request,
34
- )
35
30
  from web3.types import (
36
31
  RPCEndpoint,
37
32
  RPCResponse,
@@ -43,6 +38,9 @@ from ..._utils.batching import (
43
38
  from ..._utils.caching import (
44
39
  handle_request_caching,
45
40
  )
41
+ from ..._utils.http_session_manager import (
42
+ HTTPSessionManager,
43
+ )
46
44
  from ..base import (
47
45
  JSONBaseProvider,
48
46
  )
@@ -67,13 +65,17 @@ class HTTPProvider(JSONBaseProvider):
67
65
  endpoint_uri: Optional[Union[URI, str]] = None,
68
66
  request_kwargs: Optional[Any] = None,
69
67
  session: Optional[Any] = None,
70
- exception_retry_configuration: Union[
71
- ExceptionRetryConfiguration, Empty
68
+ exception_retry_configuration: Optional[
69
+ Union[ExceptionRetryConfiguration, Empty]
72
70
  ] = empty,
73
71
  **kwargs: Any,
74
72
  ) -> None:
73
+ self._request_session_manager = HTTPSessionManager()
74
+
75
75
  if endpoint_uri is None:
76
- self.endpoint_uri = get_default_http_endpoint()
76
+ self.endpoint_uri = (
77
+ self._request_session_manager.get_default_http_endpoint()
78
+ )
77
79
  else:
78
80
  self.endpoint_uri = URI(endpoint_uri)
79
81
 
@@ -81,7 +83,9 @@ class HTTPProvider(JSONBaseProvider):
81
83
  self._exception_retry_configuration = exception_retry_configuration
82
84
 
83
85
  if session:
84
- cache_and_return_session(self.endpoint_uri, session)
86
+ self._request_session_manager.cache_and_return_session(
87
+ self.endpoint_uri, session
88
+ )
85
89
 
86
90
  super().__init__(**kwargs)
87
91
 
@@ -131,7 +135,7 @@ class HTTPProvider(JSONBaseProvider):
131
135
  ):
132
136
  for i in range(self.exception_retry_configuration.retries):
133
137
  try:
134
- return make_post_request(
138
+ return self._request_session_manager.make_post_request(
135
139
  self.endpoint_uri, request_data, **self.get_request_kwargs()
136
140
  )
137
141
  except tuple(self.exception_retry_configuration.errors) as e:
@@ -144,7 +148,7 @@ class HTTPProvider(JSONBaseProvider):
144
148
  raise e
145
149
  return None
146
150
  else:
147
- return make_post_request(
151
+ return self._request_session_manager.make_post_request(
148
152
  self.endpoint_uri, request_data, **self.get_request_kwargs()
149
153
  )
150
154
 
@@ -167,7 +171,7 @@ class HTTPProvider(JSONBaseProvider):
167
171
  ) -> List[RPCResponse]:
168
172
  self.logger.debug(f"Making batch request HTTP, uri: `{self.endpoint_uri}`")
169
173
  request_data = self.encode_batch_rpc_request(batch_requests)
170
- raw_response = make_post_request(
174
+ raw_response = self._request_session_manager.make_post_request(
171
175
  self.endpoint_uri, request_data, **self.get_request_kwargs()
172
176
  )
173
177
  self.logger.debug("Received batch response HTTP.")
@@ -19,9 +19,6 @@ REQUEST_RETRY_ALLOWLIST = [
19
19
  "evm",
20
20
  "eth_protocolVersion",
21
21
  "eth_syncing",
22
- "eth_coinbase",
23
- "eth_mining",
24
- "eth_hashrate",
25
22
  "eth_chainId",
26
23
  "eth_gasPrice",
27
24
  "eth_accounts",