web3 7.14.1__py3-none-any.whl → 8.0.0b1__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.
- ens/_normalization.py +23 -29
- ens/async_ens.py +30 -24
- ens/base_ens.py +2 -3
- ens/ens.py +18 -20
- ens/utils.py +6 -10
- web3/__init__.py +0 -4
- web3/_utils/abi.py +38 -40
- web3/_utils/async_transactions.py +6 -9
- web3/_utils/batching.py +11 -15
- web3/_utils/blocks.py +1 -2
- web3/_utils/caching/caching_utils.py +12 -17
- web3/_utils/caching/request_caching_validation.py +7 -9
- web3/_utils/compat/__init__.py +2 -2
- web3/_utils/contract_sources/compile_contracts.py +4 -6
- web3/_utils/contracts.py +25 -29
- web3/_utils/datatypes.py +6 -10
- web3/_utils/decorators.py +1 -3
- web3/_utils/encoding.py +10 -14
- web3/_utils/ens.py +4 -5
- web3/_utils/events.py +19 -24
- web3/_utils/filters.py +23 -29
- web3/_utils/formatters.py +8 -13
- web3/_utils/http_session_manager.py +11 -22
- web3/_utils/math.py +1 -2
- web3/_utils/method_formatters.py +41 -43
- web3/_utils/module.py +3 -6
- web3/_utils/module_testing/eth_module.py +7 -9
- web3/_utils/module_testing/go_ethereum_admin_module.py +1 -2
- web3/_utils/module_testing/module_testing_utils.py +9 -5
- web3/_utils/module_testing/persistent_connection_provider.py +3 -7
- web3/_utils/module_testing/utils.py +32 -21
- web3/_utils/normalizers.py +21 -24
- web3/_utils/rpc_abi.py +8 -11
- web3/_utils/threads.py +3 -4
- web3/_utils/transactions.py +3 -6
- web3/_utils/type_conversion.py +2 -6
- web3/_utils/utility_methods.py +5 -7
- web3/_utils/validation.py +6 -8
- web3/_utils/windows.py +1 -4
- web3/beacon/async_beacon.py +50 -54
- web3/beacon/beacon.py +50 -54
- web3/contract/async_contract.py +38 -46
- web3/contract/base_contract.py +70 -75
- web3/contract/contract.py +39 -43
- web3/contract/utils.py +47 -51
- web3/datastructures.py +10 -15
- web3/eth/async_eth.py +64 -70
- web3/eth/base_eth.py +40 -44
- web3/eth/eth.py +50 -66
- web3/exceptions.py +8 -13
- web3/gas_strategies/rpc.py +1 -7
- web3/gas_strategies/time_based.py +2 -3
- web3/geth.py +17 -17
- web3/main.py +43 -52
- web3/manager.py +32 -35
- web3/method.py +22 -29
- web3/middleware/base.py +5 -8
- web3/middleware/filter.py +41 -46
- web3/middleware/formatting.py +5 -6
- web3/middleware/names.py +1 -3
- web3/middleware/signing.py +3 -4
- web3/middleware/stalecheck.py +1 -2
- web3/middleware/validation.py +1 -2
- web3/module.py +11 -14
- web3/providers/__init__.py +0 -4
- web3/providers/async_base.py +21 -27
- web3/providers/auto.py +9 -20
- web3/providers/base.py +12 -17
- web3/providers/eth_tester/defaults.py +4 -8
- web3/providers/eth_tester/main.py +4 -8
- web3/providers/eth_tester/middleware.py +2 -4
- web3/providers/ipc.py +6 -10
- web3/providers/persistent/async_ipc.py +4 -7
- web3/providers/persistent/persistent.py +22 -25
- web3/providers/persistent/persistent_connection.py +2 -4
- web3/providers/persistent/request_processor.py +11 -32
- web3/providers/persistent/subscription_container.py +5 -8
- web3/providers/persistent/subscription_manager.py +13 -19
- web3/providers/persistent/websocket.py +15 -12
- web3/providers/rpc/async_rpc.py +10 -16
- web3/providers/rpc/rpc.py +17 -20
- web3/providers/rpc/utils.py +2 -3
- web3/scripts/release/test_package.py +1 -4
- web3/testing.py +1 -5
- web3/tracing.py +9 -13
- web3/types.py +51 -58
- web3/utils/abi.py +28 -33
- web3/utils/async_exception_handling.py +1 -2
- web3/utils/caching.py +6 -10
- web3/utils/exception_handling.py +1 -2
- web3/utils/subscriptions.py +30 -34
- {web3-7.14.1.dist-info → web3-8.0.0b1.dist-info}/METADATA +10 -9
- web3-8.0.0b1.dist-info/RECORD +170 -0
- {web3-7.14.1.dist-info → web3-8.0.0b1.dist-info}/WHEEL +1 -1
- ens/specs/.DS_Store +0 -0
- web3/providers/legacy_websocket.py +0 -159
- web3-7.14.1.dist-info/RECORD +0 -172
- {web3-7.14.1.dist-info → web3-8.0.0b1.dist-info}/licenses/LICENSE +0 -0
- {web3-7.14.1.dist-info → web3-8.0.0b1.dist-info}/top_level.txt +0 -0
web3/providers/base.py
CHANGED
|
@@ -6,11 +6,7 @@ from typing import (
|
|
|
6
6
|
TYPE_CHECKING,
|
|
7
7
|
Any,
|
|
8
8
|
Callable,
|
|
9
|
-
List,
|
|
10
9
|
Optional,
|
|
11
|
-
Set,
|
|
12
|
-
Tuple,
|
|
13
|
-
Union,
|
|
14
10
|
cast,
|
|
15
11
|
)
|
|
16
12
|
|
|
@@ -60,7 +56,7 @@ class BaseProvider:
|
|
|
60
56
|
# Set generic logger for the provider. Override in subclasses for more specificity.
|
|
61
57
|
logger: logging.Logger = logging.getLogger("web3.providers.base.BaseProvider")
|
|
62
58
|
# a tuple of (middleware, request_func)
|
|
63
|
-
_request_func_cache:
|
|
59
|
+
_request_func_cache: tuple[tuple[Middleware, ...], Callable[..., RPCResponse]] = (
|
|
64
60
|
None,
|
|
65
61
|
None,
|
|
66
62
|
)
|
|
@@ -73,10 +69,9 @@ class BaseProvider:
|
|
|
73
69
|
def __init__(
|
|
74
70
|
self,
|
|
75
71
|
cache_allowed_requests: bool = False,
|
|
76
|
-
cacheable_requests:
|
|
77
|
-
request_cache_validation_threshold:
|
|
78
|
-
|
|
79
|
-
] = empty,
|
|
72
|
+
cacheable_requests: set[RPCEndpoint] = None,
|
|
73
|
+
request_cache_validation_threshold: None
|
|
74
|
+
| (RequestCacheValidationThreshold | int | Empty) = empty,
|
|
80
75
|
) -> None:
|
|
81
76
|
self._request_cache = SimpleCache(1000)
|
|
82
77
|
self._request_cache_lock: threading.Lock = threading.Lock()
|
|
@@ -88,8 +83,8 @@ class BaseProvider:
|
|
|
88
83
|
self._batching_context: contextvars.ContextVar[
|
|
89
84
|
Optional["RequestBatcher[Any]"]
|
|
90
85
|
] = contextvars.ContextVar("batching_context", default=None)
|
|
91
|
-
self._batch_request_func_cache:
|
|
92
|
-
|
|
86
|
+
self._batch_request_func_cache: tuple[
|
|
87
|
+
tuple[Middleware, ...], Callable[..., list[RPCResponse] | RPCResponse]
|
|
93
88
|
] = (None, None)
|
|
94
89
|
|
|
95
90
|
@property
|
|
@@ -109,7 +104,7 @@ class BaseProvider:
|
|
|
109
104
|
@returns a function that calls all the middleware and
|
|
110
105
|
eventually self.make_request()
|
|
111
106
|
"""
|
|
112
|
-
middleware:
|
|
107
|
+
middleware: tuple[Middleware, ...] = middleware_onion.as_tuple_of_middleware()
|
|
113
108
|
|
|
114
109
|
cache_key = self._request_func_cache[0]
|
|
115
110
|
if cache_key != middleware:
|
|
@@ -181,8 +176,8 @@ class JSONBaseProvider(BaseProvider):
|
|
|
181
176
|
|
|
182
177
|
def batch_request_func(
|
|
183
178
|
self, w3: "Web3", middleware_onion: MiddlewareOnion
|
|
184
|
-
) -> Callable[...,
|
|
185
|
-
middleware:
|
|
179
|
+
) -> Callable[..., list[RPCResponse] | RPCResponse]:
|
|
180
|
+
middleware: tuple[Middleware, ...] = middleware_onion.as_tuple_of_middleware()
|
|
186
181
|
|
|
187
182
|
cache_key = self._batch_request_func_cache[0]
|
|
188
183
|
if cache_key != middleware:
|
|
@@ -200,7 +195,7 @@ class JSONBaseProvider(BaseProvider):
|
|
|
200
195
|
return self._batch_request_func_cache[-1]
|
|
201
196
|
|
|
202
197
|
def encode_batch_rpc_request(
|
|
203
|
-
self, requests:
|
|
198
|
+
self, requests: list[tuple[RPCEndpoint, Any]]
|
|
204
199
|
) -> bytes:
|
|
205
200
|
return (
|
|
206
201
|
b"["
|
|
@@ -211,6 +206,6 @@ class JSONBaseProvider(BaseProvider):
|
|
|
211
206
|
)
|
|
212
207
|
|
|
213
208
|
def make_batch_request(
|
|
214
|
-
self, requests:
|
|
215
|
-
) ->
|
|
209
|
+
self, requests: list[tuple[RPCEndpoint, Any]]
|
|
210
|
+
) -> list[RPCResponse] | RPCResponse:
|
|
216
211
|
raise NotImplementedError("Providers must implement this method")
|
|
@@ -6,11 +6,7 @@ from typing import (
|
|
|
6
6
|
TYPE_CHECKING,
|
|
7
7
|
Any,
|
|
8
8
|
Callable,
|
|
9
|
-
List,
|
|
10
9
|
NoReturn,
|
|
11
|
-
Optional,
|
|
12
|
-
Tuple,
|
|
13
|
-
Type,
|
|
14
10
|
)
|
|
15
11
|
|
|
16
12
|
from eth_abi import (
|
|
@@ -76,7 +72,7 @@ def call_eth_tester(
|
|
|
76
72
|
fn_name: str,
|
|
77
73
|
eth_tester: "EthereumTester",
|
|
78
74
|
fn_args: Any,
|
|
79
|
-
fn_kwargs:
|
|
75
|
+
fn_kwargs: Any | None = None,
|
|
80
76
|
) -> RPCResponse:
|
|
81
77
|
if fn_kwargs is None:
|
|
82
78
|
fn_kwargs = {}
|
|
@@ -140,7 +136,7 @@ def without_params(
|
|
|
140
136
|
@curry
|
|
141
137
|
def preprocess_params(
|
|
142
138
|
eth_tester: "EthereumTester", params: Any, preprocessor_fn: Callable[..., Any]
|
|
143
|
-
) ->
|
|
139
|
+
) -> tuple["EthereumTester", Callable[..., Any]]:
|
|
144
140
|
return eth_tester, preprocessor_fn(params)
|
|
145
141
|
|
|
146
142
|
|
|
@@ -163,7 +159,7 @@ def client_version(eth_tester: "EthereumTester", params: Any) -> str:
|
|
|
163
159
|
|
|
164
160
|
@curry
|
|
165
161
|
def null_if_excepts(
|
|
166
|
-
exc_type:
|
|
162
|
+
exc_type: type[BaseException], fn: Callable[..., TReturn]
|
|
167
163
|
) -> Callable[..., TReturn]:
|
|
168
164
|
return excepts(
|
|
169
165
|
exc_type,
|
|
@@ -206,7 +202,7 @@ def create_log_filter(eth_tester: "EthereumTester", params: Any) -> int:
|
|
|
206
202
|
return filter_id
|
|
207
203
|
|
|
208
204
|
|
|
209
|
-
def get_logs(eth_tester: "EthereumTester", params: Any) ->
|
|
205
|
+
def get_logs(eth_tester: "EthereumTester", params: Any) -> list[LogReceipt]:
|
|
210
206
|
filter_params = params[0]
|
|
211
207
|
logs = eth_tester.get_logs(**filter_params)
|
|
212
208
|
return logs
|
|
@@ -3,9 +3,7 @@ from typing import (
|
|
|
3
3
|
Any,
|
|
4
4
|
Callable,
|
|
5
5
|
Coroutine,
|
|
6
|
-
Dict,
|
|
7
6
|
Literal,
|
|
8
|
-
Optional,
|
|
9
7
|
Union,
|
|
10
8
|
cast,
|
|
11
9
|
)
|
|
@@ -122,14 +120,12 @@ class EthereumTesterProvider(BaseProvider):
|
|
|
122
120
|
ethereum_tester_middleware,
|
|
123
121
|
)
|
|
124
122
|
ethereum_tester = None
|
|
125
|
-
api_endpoints:
|
|
123
|
+
api_endpoints: dict[str, dict[str, Callable[..., RPCResponse]]] | None = None
|
|
126
124
|
|
|
127
125
|
def __init__(
|
|
128
126
|
self,
|
|
129
|
-
ethereum_tester:
|
|
130
|
-
api_endpoints:
|
|
131
|
-
Dict[str, Dict[str, Callable[..., RPCResponse]]]
|
|
132
|
-
] = None,
|
|
127
|
+
ethereum_tester: Union["EthereumTester", "BaseChainBackend"] | None = None,
|
|
128
|
+
api_endpoints: None | (dict[str, dict[str, Callable[..., RPCResponse]]]) = None,
|
|
133
129
|
) -> None:
|
|
134
130
|
# do not import eth_tester until runtime, it is not a default dependency
|
|
135
131
|
super().__init__()
|
|
@@ -215,7 +211,7 @@ def _make_response(result: Any, response_id: str, message: str = "") -> RPCRespo
|
|
|
215
211
|
def _make_request(
|
|
216
212
|
method: RPCEndpoint,
|
|
217
213
|
params: Any,
|
|
218
|
-
api_endpoints:
|
|
214
|
+
api_endpoints: dict[str, dict[str, Any]],
|
|
219
215
|
ethereum_tester_instance: "EthereumTester",
|
|
220
216
|
request_id: str,
|
|
221
217
|
) -> RPCResponse:
|
|
@@ -3,8 +3,6 @@ from typing import (
|
|
|
3
3
|
TYPE_CHECKING,
|
|
4
4
|
Any,
|
|
5
5
|
Callable,
|
|
6
|
-
Dict,
|
|
7
|
-
Optional,
|
|
8
6
|
)
|
|
9
7
|
|
|
10
8
|
from eth_typing import (
|
|
@@ -307,7 +305,7 @@ request_formatters = {
|
|
|
307
305
|
RPCEndpoint("evm_revert"): apply_formatters_to_args(hex_to_integer),
|
|
308
306
|
}
|
|
309
307
|
|
|
310
|
-
result_formatters:
|
|
308
|
+
result_formatters: dict[RPCEndpoint, Callable[..., Any]] | None = {
|
|
311
309
|
RPCEndpoint("eth_getBlockByHash"): apply_formatter_if(
|
|
312
310
|
is_dict, compose(block_result_remapper, block_result_formatter)
|
|
313
311
|
),
|
|
@@ -377,7 +375,7 @@ def fill_default(
|
|
|
377
375
|
|
|
378
376
|
async def async_guess_from(
|
|
379
377
|
async_w3: "AsyncWeb3[Any]", _: TxParams
|
|
380
|
-
) ->
|
|
378
|
+
) -> ChecksumAddress | None:
|
|
381
379
|
accounts = await async_w3.eth.accounts
|
|
382
380
|
if accounts is not None and len(accounts) > 0:
|
|
383
381
|
return accounts[0]
|
web3/providers/ipc.py
CHANGED
|
@@ -14,10 +14,6 @@ from types import (
|
|
|
14
14
|
)
|
|
15
15
|
from typing import (
|
|
16
16
|
Any,
|
|
17
|
-
List,
|
|
18
|
-
Tuple,
|
|
19
|
-
Type,
|
|
20
|
-
Union,
|
|
21
17
|
cast,
|
|
22
18
|
)
|
|
23
19
|
|
|
@@ -77,7 +73,7 @@ class PersistentSocket:
|
|
|
77
73
|
|
|
78
74
|
def __exit__(
|
|
79
75
|
self,
|
|
80
|
-
exc_type:
|
|
76
|
+
exc_type: type[BaseException],
|
|
81
77
|
exc_value: BaseException,
|
|
82
78
|
traceback: TracebackType,
|
|
83
79
|
) -> None:
|
|
@@ -143,7 +139,7 @@ class IPCProvider(JSONBaseProvider):
|
|
|
143
139
|
|
|
144
140
|
def __init__(
|
|
145
141
|
self,
|
|
146
|
-
ipc_path:
|
|
142
|
+
ipc_path: str | Path = None,
|
|
147
143
|
timeout: int = 30,
|
|
148
144
|
**kwargs: Any,
|
|
149
145
|
) -> None:
|
|
@@ -176,7 +172,7 @@ class IPCProvider(JSONBaseProvider):
|
|
|
176
172
|
while True:
|
|
177
173
|
try:
|
|
178
174
|
raw_response += sock.recv(4096)
|
|
179
|
-
except
|
|
175
|
+
except TimeoutError:
|
|
180
176
|
timeout.sleep(0)
|
|
181
177
|
continue
|
|
182
178
|
if raw_response == b"":
|
|
@@ -202,11 +198,11 @@ class IPCProvider(JSONBaseProvider):
|
|
|
202
198
|
return self._make_request(request)
|
|
203
199
|
|
|
204
200
|
def make_batch_request(
|
|
205
|
-
self, requests:
|
|
206
|
-
) ->
|
|
201
|
+
self, requests: list[tuple[RPCEndpoint, Any]]
|
|
202
|
+
) -> list[RPCResponse]:
|
|
207
203
|
self.logger.debug("Making batch request IPC. Path: %s", self.ipc_path)
|
|
208
204
|
request_data = self.encode_batch_rpc_request(requests)
|
|
209
|
-
response = cast(
|
|
205
|
+
response = cast(list[RPCResponse], self._make_request(request_data))
|
|
210
206
|
return sort_batch_response_by_response_ids(response)
|
|
211
207
|
|
|
212
208
|
|
|
@@ -8,9 +8,6 @@ from pathlib import (
|
|
|
8
8
|
import sys
|
|
9
9
|
from typing import (
|
|
10
10
|
Any,
|
|
11
|
-
Optional,
|
|
12
|
-
Tuple,
|
|
13
|
-
Union,
|
|
14
11
|
)
|
|
15
12
|
|
|
16
13
|
from web3.types import (
|
|
@@ -34,7 +31,7 @@ from ..ipc import (
|
|
|
34
31
|
|
|
35
32
|
async def async_get_ipc_socket(
|
|
36
33
|
ipc_path: str, read_buffer_limit: int
|
|
37
|
-
) ->
|
|
34
|
+
) -> tuple[asyncio.StreamReader, asyncio.StreamWriter]:
|
|
38
35
|
if sys.platform == "win32":
|
|
39
36
|
# On Windows named pipe is used. Simulate socket with it.
|
|
40
37
|
from web3._utils.windows import (
|
|
@@ -49,13 +46,13 @@ async def async_get_ipc_socket(
|
|
|
49
46
|
class AsyncIPCProvider(PersistentConnectionProvider):
|
|
50
47
|
logger = logging.getLogger("web3.providers.AsyncIPCProvider")
|
|
51
48
|
|
|
52
|
-
_reader:
|
|
53
|
-
_writer:
|
|
49
|
+
_reader: asyncio.StreamReader | None = None
|
|
50
|
+
_writer: asyncio.StreamWriter | None = None
|
|
54
51
|
_decoder: json.JSONDecoder = json.JSONDecoder()
|
|
55
52
|
|
|
56
53
|
def __init__(
|
|
57
54
|
self,
|
|
58
|
-
ipc_path:
|
|
55
|
+
ipc_path: str | Path | None = None,
|
|
59
56
|
read_buffer_limit: int = 20 * 1024 * 1024, # 20 MB
|
|
60
57
|
# `PersistentConnectionProvider` kwargs can be passed through
|
|
61
58
|
**kwargs: Any,
|
|
@@ -10,10 +10,7 @@ from typing import (
|
|
|
10
10
|
Any,
|
|
11
11
|
Callable,
|
|
12
12
|
Coroutine,
|
|
13
|
-
List,
|
|
14
13
|
Optional,
|
|
15
|
-
Tuple,
|
|
16
|
-
Union,
|
|
17
14
|
cast,
|
|
18
15
|
)
|
|
19
16
|
|
|
@@ -68,17 +65,17 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
|
|
|
68
65
|
logger = logging.getLogger("web3.providers.PersistentConnectionProvider")
|
|
69
66
|
has_persistent_connection = True
|
|
70
67
|
|
|
71
|
-
_send_func_cache:
|
|
72
|
-
|
|
68
|
+
_send_func_cache: tuple[
|
|
69
|
+
int | None, Callable[..., Coroutine[Any, Any, RPCRequest]] | None
|
|
73
70
|
] = (None, None)
|
|
74
|
-
_recv_func_cache:
|
|
75
|
-
|
|
71
|
+
_recv_func_cache: tuple[
|
|
72
|
+
int | None, Callable[..., Coroutine[Any, Any, RPCResponse]] | None
|
|
76
73
|
] = (None, None)
|
|
77
|
-
_send_batch_func_cache:
|
|
78
|
-
|
|
74
|
+
_send_batch_func_cache: tuple[
|
|
75
|
+
int | None, Callable[..., Coroutine[Any, Any, list[RPCRequest]]] | None
|
|
79
76
|
] = (None, None)
|
|
80
|
-
_recv_batch_func_cache:
|
|
81
|
-
|
|
77
|
+
_recv_batch_func_cache: tuple[
|
|
78
|
+
int | None, Callable[..., Coroutine[Any, Any, list[RPCResponse]]] | None
|
|
82
79
|
] = (None, None)
|
|
83
80
|
|
|
84
81
|
def __init__(
|
|
@@ -157,15 +154,15 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
|
|
|
157
154
|
|
|
158
155
|
async def send_batch_func(
|
|
159
156
|
self, async_w3: "AsyncWeb3[Any]", middleware_onion: "MiddlewareOnion"
|
|
160
|
-
) -> Callable[..., Coroutine[Any, Any,
|
|
157
|
+
) -> Callable[..., Coroutine[Any, Any, list[RPCRequest]]]:
|
|
161
158
|
middleware = middleware_onion.as_tuple_of_middleware()
|
|
162
159
|
cache_key = hash(tuple(id(mw) for mw in middleware))
|
|
163
160
|
|
|
164
161
|
if cache_key != self._send_batch_func_cache[0]:
|
|
165
162
|
|
|
166
163
|
async def send_func(
|
|
167
|
-
requests:
|
|
168
|
-
) ->
|
|
164
|
+
requests: list[tuple[RPCEndpoint, Any]],
|
|
165
|
+
) -> list[RPCRequest]:
|
|
169
166
|
for mw in middleware:
|
|
170
167
|
initialized = mw(async_w3)
|
|
171
168
|
requests = [
|
|
@@ -180,15 +177,15 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
|
|
|
180
177
|
|
|
181
178
|
async def recv_batch_func(
|
|
182
179
|
self, async_w3: "AsyncWeb3[Any]", middleware_onion: "MiddlewareOnion"
|
|
183
|
-
) -> Callable[..., Coroutine[Any, Any,
|
|
180
|
+
) -> Callable[..., Coroutine[Any, Any, list[RPCResponse]]]:
|
|
184
181
|
middleware = middleware_onion.as_tuple_of_middleware()
|
|
185
182
|
cache_key = hash(tuple(id(mw) for mw in middleware))
|
|
186
183
|
|
|
187
184
|
if cache_key != self._recv_batch_func_cache[0]:
|
|
188
185
|
|
|
189
186
|
async def recv_function(
|
|
190
|
-
rpc_requests:
|
|
191
|
-
) ->
|
|
187
|
+
rpc_requests: list[RPCRequest],
|
|
188
|
+
) -> list[RPCResponse]:
|
|
192
189
|
methods = [rpc_request["method"] for rpc_request in rpc_requests]
|
|
193
190
|
responses = await self.recv_for_batch_request(rpc_requests)
|
|
194
191
|
for mw in reversed(middleware):
|
|
@@ -296,8 +293,8 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
|
|
|
296
293
|
# -- batch requests -- #
|
|
297
294
|
|
|
298
295
|
async def send_batch_request(
|
|
299
|
-
self, requests:
|
|
300
|
-
) ->
|
|
296
|
+
self, requests: list[tuple[RPCEndpoint, Any]]
|
|
297
|
+
) -> list[RPCRequest]:
|
|
301
298
|
request_dicts = [
|
|
302
299
|
self.form_request(method, params) for (method, params) in requests
|
|
303
300
|
]
|
|
@@ -306,17 +303,17 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
|
|
|
306
303
|
return request_dicts
|
|
307
304
|
|
|
308
305
|
async def recv_for_batch_request(
|
|
309
|
-
self, _request_dicts:
|
|
310
|
-
) ->
|
|
306
|
+
self, _request_dicts: list[RPCRequest]
|
|
307
|
+
) -> list[RPCResponse]:
|
|
311
308
|
response = cast(
|
|
312
|
-
|
|
309
|
+
list[RPCResponse],
|
|
313
310
|
await self._get_response_for_request_id(BATCH_REQUEST_ID),
|
|
314
311
|
)
|
|
315
312
|
return response
|
|
316
313
|
|
|
317
314
|
async def make_batch_request(
|
|
318
|
-
self, requests:
|
|
319
|
-
) ->
|
|
315
|
+
self, requests: list[tuple[RPCEndpoint, Any]]
|
|
316
|
+
) -> list[RPCResponse]:
|
|
320
317
|
request_dicts = await self.send_batch_request(requests)
|
|
321
318
|
return await self.recv_for_batch_request(request_dicts)
|
|
322
319
|
|
|
@@ -471,7 +468,7 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
|
|
|
471
468
|
raise msg_listener_task.exception()
|
|
472
469
|
|
|
473
470
|
async def _get_response_for_request_id(
|
|
474
|
-
self, request_id:
|
|
471
|
+
self, request_id: RPCId | list[RPCId], timeout: float | None = None
|
|
475
472
|
) -> RPCResponse:
|
|
476
473
|
if timeout is None:
|
|
477
474
|
timeout = self.request_timeout
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
from typing import (
|
|
2
2
|
TYPE_CHECKING,
|
|
3
3
|
Any,
|
|
4
|
-
Dict,
|
|
5
|
-
Union,
|
|
6
4
|
cast,
|
|
7
5
|
)
|
|
8
6
|
|
|
@@ -35,7 +33,7 @@ class PersistentConnection:
|
|
|
35
33
|
self.provider = cast("PersistentConnectionProvider", self._manager.provider)
|
|
36
34
|
|
|
37
35
|
@property
|
|
38
|
-
def subscriptions(self) ->
|
|
36
|
+
def subscriptions(self) -> dict[str, Any]:
|
|
39
37
|
"""
|
|
40
38
|
Return the active subscriptions on the persistent connection.
|
|
41
39
|
|
|
@@ -70,7 +68,7 @@ class PersistentConnection:
|
|
|
70
68
|
"""
|
|
71
69
|
await self._manager.send(method, params)
|
|
72
70
|
|
|
73
|
-
async def recv(self) ->
|
|
71
|
+
async def recv(self) -> RPCResponse | FormattedEthSubscriptionResponse:
|
|
74
72
|
"""
|
|
75
73
|
Receive the next unprocessed response for a request from the persistent
|
|
76
74
|
connection.
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import sys
|
|
3
2
|
from typing import (
|
|
4
3
|
TYPE_CHECKING,
|
|
5
4
|
Any,
|
|
6
5
|
Callable,
|
|
7
|
-
Dict,
|
|
8
|
-
Generic,
|
|
9
|
-
List,
|
|
10
|
-
Optional,
|
|
11
|
-
Tuple,
|
|
12
6
|
TypeVar,
|
|
13
|
-
Union,
|
|
14
7
|
)
|
|
15
8
|
|
|
16
9
|
from web3._utils.batching import (
|
|
@@ -44,20 +37,8 @@ if TYPE_CHECKING:
|
|
|
44
37
|
|
|
45
38
|
T = TypeVar("T")
|
|
46
39
|
|
|
47
|
-
# TODO: This is an ugly hack for python 3.8. Remove this after we drop support for it
|
|
48
|
-
# and use `asyncio.Queue[T]` type directly in the `TaskReliantQueue` class.
|
|
49
|
-
if sys.version_info >= (3, 9):
|
|
50
40
|
|
|
51
|
-
|
|
52
|
-
pass
|
|
53
|
-
|
|
54
|
-
else:
|
|
55
|
-
|
|
56
|
-
class _TaskReliantQueue(asyncio.Queue, Generic[T]): # type: ignore
|
|
57
|
-
pass
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
class TaskReliantQueue(_TaskReliantQueue[T]):
|
|
41
|
+
class TaskReliantQueue(asyncio.Queue[T]):
|
|
61
42
|
"""
|
|
62
43
|
A queue that relies on a task to be running to process items in the queue.
|
|
63
44
|
"""
|
|
@@ -75,7 +56,7 @@ class RequestProcessor:
|
|
|
75
56
|
_subscription_queue_synced_with_ws_stream: bool = False
|
|
76
57
|
|
|
77
58
|
# set by the subscription manager when it is initialized
|
|
78
|
-
_subscription_container:
|
|
59
|
+
_subscription_container: SubscriptionContainer | None = None
|
|
79
60
|
|
|
80
61
|
def __init__(
|
|
81
62
|
self,
|
|
@@ -89,14 +70,14 @@ class RequestProcessor:
|
|
|
89
70
|
)
|
|
90
71
|
self._request_response_cache: SimpleCache = SimpleCache(500)
|
|
91
72
|
self._subscription_response_queue: TaskReliantQueue[
|
|
92
|
-
|
|
73
|
+
RPCResponse | TaskNotRunning
|
|
93
74
|
] = TaskReliantQueue(maxsize=subscription_response_queue_size)
|
|
94
75
|
self._handler_subscription_queue: TaskReliantQueue[
|
|
95
|
-
|
|
76
|
+
RPCResponse | TaskNotRunning | SubscriptionProcessingFinished
|
|
96
77
|
] = TaskReliantQueue(maxsize=subscription_response_queue_size)
|
|
97
78
|
|
|
98
79
|
@property
|
|
99
|
-
def active_subscriptions(self) ->
|
|
80
|
+
def active_subscriptions(self) -> dict[str, Any]:
|
|
100
81
|
return {
|
|
101
82
|
value.subscription_id: {"params": value.params}
|
|
102
83
|
for key, value in self._request_information_cache.items()
|
|
@@ -107,15 +88,15 @@ class RequestProcessor:
|
|
|
107
88
|
|
|
108
89
|
def cache_request_information(
|
|
109
90
|
self,
|
|
110
|
-
request_id:
|
|
91
|
+
request_id: RPCId | None,
|
|
111
92
|
method: RPCEndpoint,
|
|
112
93
|
params: Any,
|
|
113
|
-
response_formatters:
|
|
114
|
-
|
|
94
|
+
response_formatters: tuple[
|
|
95
|
+
dict[str, Callable[..., Any]] | Callable[..., Any],
|
|
115
96
|
Callable[..., Any],
|
|
116
97
|
Callable[..., Any],
|
|
117
98
|
],
|
|
118
|
-
) ->
|
|
99
|
+
) -> str | None:
|
|
119
100
|
cached_requests_key = generate_cache_key((method, params))
|
|
120
101
|
if cached_requests_key in self._provider._request_cache._data:
|
|
121
102
|
cached_response = self._provider._request_cache._data[cached_requests_key]
|
|
@@ -163,7 +144,7 @@ class RequestProcessor:
|
|
|
163
144
|
|
|
164
145
|
def pop_cached_request_information(
|
|
165
146
|
self, cache_key: str
|
|
166
|
-
) ->
|
|
147
|
+
) -> RequestInformation | None:
|
|
167
148
|
request_info = self._request_information_cache.pop(cache_key)
|
|
168
149
|
if request_info is not None:
|
|
169
150
|
self._provider.logger.debug(
|
|
@@ -256,9 +237,7 @@ class RequestProcessor:
|
|
|
256
237
|
|
|
257
238
|
# raw response cache
|
|
258
239
|
|
|
259
|
-
def _is_batch_response(
|
|
260
|
-
self, raw_response: Union[List[RPCResponse], RPCResponse]
|
|
261
|
-
) -> bool:
|
|
240
|
+
def _is_batch_response(self, raw_response: list[RPCResponse] | RPCResponse) -> bool:
|
|
262
241
|
return isinstance(raw_response, list) or (
|
|
263
242
|
isinstance(raw_response, dict)
|
|
264
243
|
and raw_response.get("id") is None
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
from typing import (
|
|
2
2
|
Any,
|
|
3
|
-
Dict,
|
|
4
3
|
Iterator,
|
|
5
|
-
List,
|
|
6
|
-
Optional,
|
|
7
4
|
)
|
|
8
5
|
|
|
9
6
|
from eth_typing import (
|
|
@@ -17,9 +14,9 @@ from web3.utils import (
|
|
|
17
14
|
|
|
18
15
|
class SubscriptionContainer:
|
|
19
16
|
def __init__(self) -> None:
|
|
20
|
-
self.subscriptions:
|
|
21
|
-
self.subscriptions_by_id:
|
|
22
|
-
self.subscriptions_by_label:
|
|
17
|
+
self.subscriptions: list[EthSubscription[Any]] = []
|
|
18
|
+
self.subscriptions_by_id: dict[HexStr, EthSubscription[Any]] = {}
|
|
19
|
+
self.subscriptions_by_label: dict[str, EthSubscription[Any]] = {}
|
|
23
20
|
|
|
24
21
|
def __len__(self) -> int:
|
|
25
22
|
return len(self.subscriptions)
|
|
@@ -44,12 +41,12 @@ class SubscriptionContainer:
|
|
|
44
41
|
return self.subscriptions_by_label.get(label)
|
|
45
42
|
|
|
46
43
|
@property
|
|
47
|
-
def handler_subscriptions(self) ->
|
|
44
|
+
def handler_subscriptions(self) -> list[EthSubscription[Any]]:
|
|
48
45
|
return [sub for sub in self.subscriptions if sub._handler is not None]
|
|
49
46
|
|
|
50
47
|
def get_handler_subscription_by_id(
|
|
51
48
|
self, sub_id: HexStr
|
|
52
|
-
) ->
|
|
49
|
+
) -> EthSubscription[Any] | None:
|
|
53
50
|
sub = self.get_by_id(sub_id)
|
|
54
51
|
if sub and sub._handler:
|
|
55
52
|
return sub
|
|
@@ -3,10 +3,7 @@ import logging
|
|
|
3
3
|
from typing import (
|
|
4
4
|
TYPE_CHECKING,
|
|
5
5
|
Any,
|
|
6
|
-
List,
|
|
7
6
|
Sequence,
|
|
8
|
-
Set,
|
|
9
|
-
Union,
|
|
10
7
|
cast,
|
|
11
8
|
overload,
|
|
12
9
|
)
|
|
@@ -61,8 +58,7 @@ class SubscriptionManager:
|
|
|
61
58
|
# parallelize all subscription handler calls
|
|
62
59
|
self.parallelize = False
|
|
63
60
|
self.task_timeout = 1
|
|
64
|
-
|
|
65
|
-
self._tasks: Set["asyncio.Task[None]"] = set()
|
|
61
|
+
self._tasks: set[asyncio.Task[None]] = set()
|
|
66
62
|
|
|
67
63
|
# share the subscription container with the request processor so it can separate
|
|
68
64
|
# subscriptions into different queues based on ``sub._handler`` presence
|
|
@@ -95,8 +91,7 @@ class SubscriptionManager:
|
|
|
95
91
|
f"labels.\n label: {subscription._label}"
|
|
96
92
|
)
|
|
97
93
|
|
|
98
|
-
|
|
99
|
-
def _handler_task_callback(self, task: "asyncio.Task[None]") -> None:
|
|
94
|
+
def _handler_task_callback(self, task: asyncio.Task[None]) -> None:
|
|
100
95
|
"""
|
|
101
96
|
Callback when a handler task completes. Similar to _message_listener_callback.
|
|
102
97
|
Puts handler exceptions into the queue to be raised in the main loop, else
|
|
@@ -125,7 +120,7 @@ class SubscriptionManager:
|
|
|
125
120
|
self._tasks.clear()
|
|
126
121
|
|
|
127
122
|
@property
|
|
128
|
-
def subscriptions(self) ->
|
|
123
|
+
def subscriptions(self) -> list[EthSubscription[Any]]:
|
|
129
124
|
return self._subscription_container.subscriptions
|
|
130
125
|
|
|
131
126
|
def get_by_id(self, sub_id: HexStr) -> EthSubscription[Any]:
|
|
@@ -141,12 +136,13 @@ class SubscriptionManager:
|
|
|
141
136
|
@overload
|
|
142
137
|
async def subscribe(
|
|
143
138
|
self, subscriptions: Sequence[EthSubscription[Any]]
|
|
144
|
-
) ->
|
|
139
|
+
) -> list[HexStr]:
|
|
145
140
|
...
|
|
146
141
|
|
|
147
142
|
async def subscribe(
|
|
148
|
-
self,
|
|
149
|
-
|
|
143
|
+
self,
|
|
144
|
+
subscriptions: EthSubscription[Any] | Sequence[EthSubscription[Any]],
|
|
145
|
+
) -> HexStr | list[HexStr]:
|
|
150
146
|
"""
|
|
151
147
|
Used to subscribe to a single or multiple subscriptions.
|
|
152
148
|
|
|
@@ -170,7 +166,7 @@ class SubscriptionManager:
|
|
|
170
166
|
if len(subscriptions) == 0:
|
|
171
167
|
raise Web3ValueError("No subscriptions provided.")
|
|
172
168
|
|
|
173
|
-
sub_ids:
|
|
169
|
+
sub_ids: list[HexStr] = []
|
|
174
170
|
for sub in subscriptions:
|
|
175
171
|
sub_ids.append(await self.subscribe(sub))
|
|
176
172
|
return sub_ids
|
|
@@ -187,17 +183,15 @@ class SubscriptionManager:
|
|
|
187
183
|
@overload
|
|
188
184
|
async def unsubscribe(
|
|
189
185
|
self,
|
|
190
|
-
subscriptions: Sequence[
|
|
186
|
+
subscriptions: Sequence[EthSubscription[Any] | HexStr],
|
|
191
187
|
) -> bool:
|
|
192
188
|
...
|
|
193
189
|
|
|
194
190
|
async def unsubscribe(
|
|
195
191
|
self,
|
|
196
|
-
subscriptions:
|
|
197
|
-
EthSubscription[Any]
|
|
198
|
-
|
|
199
|
-
Sequence[Union[EthSubscription[Any], HexStr]],
|
|
200
|
-
],
|
|
192
|
+
subscriptions: (
|
|
193
|
+
EthSubscription[Any] | HexStr | Sequence[EthSubscription[Any] | HexStr]
|
|
194
|
+
),
|
|
201
195
|
) -> bool:
|
|
202
196
|
"""
|
|
203
197
|
Used to unsubscribe from one or multiple subscriptions.
|
|
@@ -246,7 +240,7 @@ class SubscriptionManager:
|
|
|
246
240
|
if len(subscriptions) == 0:
|
|
247
241
|
raise Web3ValueError("No subscriptions provided.")
|
|
248
242
|
|
|
249
|
-
unsubscribed:
|
|
243
|
+
unsubscribed: list[bool] = []
|
|
250
244
|
# re-create the subscription list to prevent modifying the original list
|
|
251
245
|
# in case ``subscription_manager.subscriptions`` was passed in directly
|
|
252
246
|
subs = list(subscriptions)
|