web3 7.0.0b2__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.
- ens/__init__.py +13 -2
- ens/_normalization.py +4 -4
- ens/async_ens.py +27 -15
- ens/base_ens.py +3 -1
- ens/contract_data.py +2 -2
- ens/ens.py +10 -7
- ens/exceptions.py +16 -29
- ens/specs/nf.json +1 -1
- ens/specs/normalization_spec.json +1 -1
- ens/utils.py +24 -32
- web3/__init__.py +23 -12
- web3/_utils/abi.py +157 -263
- web3/_utils/async_transactions.py +34 -20
- web3/_utils/batching.py +217 -0
- web3/_utils/blocks.py +6 -2
- web3/_utils/caching/__init__.py +12 -0
- web3/_utils/caching/caching_utils.py +433 -0
- web3/_utils/caching/request_caching_validation.py +287 -0
- web3/_utils/compat/__init__.py +2 -3
- web3/_utils/contract_sources/compile_contracts.py +1 -1
- web3/_utils/contract_sources/contract_data/ambiguous_function_contract.py +42 -0
- web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
- web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
- web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
- web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/event_contracts.py +50 -5
- web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
- web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
- web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
- web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
- web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
- web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
- web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
- web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
- web3/_utils/contracts.py +172 -220
- web3/_utils/datatypes.py +5 -1
- web3/_utils/decorators.py +6 -1
- web3/_utils/empty.py +1 -1
- web3/_utils/encoding.py +16 -12
- web3/_utils/error_formatters_utils.py +5 -3
- web3/_utils/events.py +78 -72
- web3/_utils/fee_utils.py +1 -3
- web3/_utils/filters.py +24 -22
- web3/_utils/formatters.py +2 -2
- web3/_utils/http.py +8 -2
- web3/_utils/http_session_manager.py +314 -0
- web3/_utils/math.py +14 -15
- web3/_utils/method_formatters.py +161 -34
- web3/_utils/module.py +2 -1
- web3/_utils/module_testing/__init__.py +3 -2
- web3/_utils/module_testing/eth_module.py +736 -583
- web3/_utils/module_testing/go_ethereum_debug_module.py +128 -0
- web3/_utils/module_testing/module_testing_utils.py +81 -24
- web3/_utils/module_testing/persistent_connection_provider.py +702 -220
- web3/_utils/module_testing/utils.py +114 -33
- web3/_utils/module_testing/web3_module.py +438 -17
- web3/_utils/normalizers.py +13 -11
- web3/_utils/rpc_abi.py +10 -22
- web3/_utils/threads.py +8 -7
- web3/_utils/transactions.py +32 -25
- web3/_utils/type_conversion.py +5 -1
- web3/_utils/validation.py +20 -17
- web3/beacon/__init__.py +5 -0
- web3/beacon/api_endpoints.py +3 -0
- web3/beacon/async_beacon.py +29 -6
- web3/beacon/beacon.py +24 -6
- web3/contract/__init__.py +7 -0
- web3/contract/async_contract.py +285 -82
- web3/contract/base_contract.py +556 -258
- web3/contract/contract.py +295 -84
- web3/contract/utils.py +251 -55
- web3/datastructures.py +49 -34
- web3/eth/__init__.py +7 -0
- web3/eth/async_eth.py +89 -69
- web3/eth/base_eth.py +7 -3
- web3/eth/eth.py +43 -66
- web3/exceptions.py +158 -83
- web3/gas_strategies/time_based.py +8 -6
- web3/geth.py +53 -184
- web3/main.py +77 -17
- web3/manager.py +362 -95
- web3/method.py +43 -15
- web3/middleware/__init__.py +17 -0
- web3/middleware/attrdict.py +12 -22
- web3/middleware/base.py +55 -2
- web3/middleware/filter.py +45 -23
- web3/middleware/formatting.py +6 -3
- web3/middleware/names.py +4 -1
- web3/middleware/signing.py +15 -6
- web3/middleware/stalecheck.py +2 -1
- web3/module.py +61 -25
- web3/providers/__init__.py +21 -0
- web3/providers/async_base.py +87 -32
- web3/providers/base.py +77 -32
- web3/providers/eth_tester/__init__.py +5 -0
- web3/providers/eth_tester/defaults.py +2 -55
- web3/providers/eth_tester/main.py +41 -15
- web3/providers/eth_tester/middleware.py +16 -17
- web3/providers/ipc.py +41 -17
- web3/providers/legacy_websocket.py +26 -1
- web3/providers/persistent/__init__.py +7 -0
- web3/providers/persistent/async_ipc.py +61 -121
- web3/providers/persistent/persistent.py +323 -16
- web3/providers/persistent/persistent_connection.py +54 -5
- web3/providers/persistent/request_processor.py +136 -56
- web3/providers/persistent/subscription_container.py +56 -0
- web3/providers/persistent/subscription_manager.py +233 -0
- web3/providers/persistent/websocket.py +29 -92
- web3/providers/rpc/__init__.py +5 -0
- web3/providers/rpc/async_rpc.py +73 -18
- web3/providers/rpc/rpc.py +73 -30
- web3/providers/rpc/utils.py +1 -13
- web3/scripts/install_pre_releases.py +33 -0
- web3/scripts/parse_pygeth_version.py +16 -0
- web3/testing.py +4 -4
- web3/tracing.py +9 -5
- web3/types.py +141 -74
- web3/utils/__init__.py +64 -5
- web3/utils/abi.py +790 -10
- web3/utils/address.py +8 -0
- web3/utils/async_exception_handling.py +20 -11
- web3/utils/caching.py +34 -4
- web3/utils/exception_handling.py +9 -12
- web3/utils/subscriptions.py +285 -0
- {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/LICENSE +1 -1
- web3-7.7.0.dist-info/METADATA +130 -0
- web3-7.7.0.dist-info/RECORD +171 -0
- {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/WHEEL +1 -1
- web3/_utils/caching.py +0 -155
- web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
- web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
- web3/_utils/request.py +0 -265
- web3-7.0.0b2.dist-info/METADATA +0 -106
- web3-7.0.0b2.dist-info/RECORD +0 -163
- /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
- {web3-7.0.0b2.dist-info → web3-7.7.0.dist-info}/top_level.txt +0 -0
web3/method.py
CHANGED
|
@@ -10,7 +10,6 @@ from typing import (
|
|
|
10
10
|
Sequence,
|
|
11
11
|
Tuple,
|
|
12
12
|
Type,
|
|
13
|
-
TypeVar,
|
|
14
13
|
Union,
|
|
15
14
|
)
|
|
16
15
|
import warnings
|
|
@@ -22,6 +21,9 @@ from eth_utils.toolz import (
|
|
|
22
21
|
pipe,
|
|
23
22
|
)
|
|
24
23
|
|
|
24
|
+
from web3._utils.batching import (
|
|
25
|
+
RPC_METHODS_UNSUPPORTED_DURING_BATCH,
|
|
26
|
+
)
|
|
25
27
|
from web3._utils.method_formatters import (
|
|
26
28
|
get_error_formatters,
|
|
27
29
|
get_null_result_formatters,
|
|
@@ -32,15 +34,22 @@ from web3._utils.rpc_abi import (
|
|
|
32
34
|
RPC,
|
|
33
35
|
)
|
|
34
36
|
from web3.exceptions import (
|
|
37
|
+
MethodNotSupported,
|
|
38
|
+
Web3TypeError,
|
|
35
39
|
Web3ValidationError,
|
|
40
|
+
Web3ValueError,
|
|
36
41
|
)
|
|
37
42
|
from web3.types import (
|
|
38
43
|
RPCEndpoint,
|
|
44
|
+
TFunc,
|
|
39
45
|
TReturn,
|
|
40
46
|
)
|
|
41
47
|
|
|
42
48
|
if TYPE_CHECKING:
|
|
43
|
-
from web3 import
|
|
49
|
+
from web3 import ( # noqa: F401
|
|
50
|
+
PersistentConnectionProvider,
|
|
51
|
+
Web3,
|
|
52
|
+
)
|
|
44
53
|
from web3.module import Module # noqa: F401
|
|
45
54
|
|
|
46
55
|
|
|
@@ -66,7 +75,9 @@ def _set_mungers(
|
|
|
66
75
|
return (
|
|
67
76
|
mungers
|
|
68
77
|
if mungers
|
|
69
|
-
else [default_munger]
|
|
78
|
+
else [default_munger]
|
|
79
|
+
if is_property
|
|
80
|
+
else [default_root_munger]
|
|
70
81
|
)
|
|
71
82
|
|
|
72
83
|
|
|
@@ -80,11 +91,9 @@ def default_root_munger(_module: "Module", *args: Any) -> List[Any]:
|
|
|
80
91
|
return [*args]
|
|
81
92
|
|
|
82
93
|
|
|
83
|
-
TFunc = TypeVar("TFunc", bound=Callable[..., Any])
|
|
84
|
-
|
|
85
|
-
|
|
86
94
|
class Method(Generic[TFunc]):
|
|
87
|
-
"""
|
|
95
|
+
"""
|
|
96
|
+
Method object for web3 module methods
|
|
88
97
|
|
|
89
98
|
Calls to the Method go through these steps:
|
|
90
99
|
|
|
@@ -144,15 +153,31 @@ class Method(Generic[TFunc]):
|
|
|
144
153
|
self.is_property = is_property
|
|
145
154
|
|
|
146
155
|
def __get__(
|
|
147
|
-
self,
|
|
156
|
+
self,
|
|
157
|
+
module: Optional["Module"] = None,
|
|
158
|
+
_type: Optional[Type["Module"]] = None,
|
|
148
159
|
) -> TFunc:
|
|
149
|
-
|
|
150
|
-
|
|
160
|
+
self._module = module
|
|
161
|
+
if module is None:
|
|
162
|
+
raise Web3TypeError(
|
|
151
163
|
"Direct calls to methods are not supported. "
|
|
152
|
-
"Methods must be called from
|
|
164
|
+
"Methods must be called from a module instance, "
|
|
153
165
|
"usually attached to a web3 instance."
|
|
154
166
|
)
|
|
155
|
-
|
|
167
|
+
|
|
168
|
+
provider = module.w3.provider
|
|
169
|
+
if hasattr(provider, "_is_batching") and provider._is_batching:
|
|
170
|
+
if self.json_rpc_method in RPC_METHODS_UNSUPPORTED_DURING_BATCH:
|
|
171
|
+
raise MethodNotSupported(
|
|
172
|
+
f"Method `{self.json_rpc_method}` is not supported within a batch "
|
|
173
|
+
"request."
|
|
174
|
+
)
|
|
175
|
+
return module.retrieve_request_information(self)
|
|
176
|
+
else:
|
|
177
|
+
return module.retrieve_caller_fn(self)
|
|
178
|
+
|
|
179
|
+
def __call__(self, *args: Any, **kwargs: Any) -> Any:
|
|
180
|
+
return self.__get__(self._module)(*args, **kwargs)
|
|
156
181
|
|
|
157
182
|
@property
|
|
158
183
|
def method_selector_fn(
|
|
@@ -163,7 +188,7 @@ class Method(Generic[TFunc]):
|
|
|
163
188
|
return self.json_rpc_method
|
|
164
189
|
elif isinstance(self.json_rpc_method, (str,)):
|
|
165
190
|
return lambda *_: self.json_rpc_method
|
|
166
|
-
raise
|
|
191
|
+
raise Web3ValueError(
|
|
167
192
|
"``json_rpc_method`` config invalid. May be a string or function"
|
|
168
193
|
)
|
|
169
194
|
|
|
@@ -175,8 +200,10 @@ class Method(Generic[TFunc]):
|
|
|
175
200
|
lambda args, munger: munger(module, *args, **kwargs), self.mungers, args
|
|
176
201
|
)
|
|
177
202
|
|
|
178
|
-
def process_params(
|
|
179
|
-
|
|
203
|
+
def process_params(
|
|
204
|
+
self, module: "Module", *args: Any, **kwargs: Any
|
|
205
|
+
) -> Tuple[
|
|
206
|
+
Tuple[Union[RPCEndpoint, Callable[..., RPCEndpoint]], Tuple[RPCEndpoint, ...]],
|
|
180
207
|
Tuple[
|
|
181
208
|
Union[TReturn, Dict[str, Callable[..., Any]]],
|
|
182
209
|
Callable[..., Any],
|
|
@@ -226,5 +253,6 @@ class DeprecatedMethod:
|
|
|
226
253
|
warnings.warn(
|
|
227
254
|
f"{self.old_name} is deprecated in favor of {self.new_name}",
|
|
228
255
|
category=DeprecationWarning,
|
|
256
|
+
stacklevel=2,
|
|
229
257
|
)
|
|
230
258
|
return self.method.__get__(obj, obj_type)
|
web3/middleware/__init__.py
CHANGED
|
@@ -92,3 +92,20 @@ async def async_combine_middleware(
|
|
|
92
92
|
initialized = mw(async_w3)
|
|
93
93
|
accumulator_fn = await initialized.async_wrap_make_request(accumulator_fn)
|
|
94
94
|
return accumulator_fn
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
__all__ = [
|
|
98
|
+
"AttributeDictMiddleware",
|
|
99
|
+
"Middleware",
|
|
100
|
+
"Web3Middleware",
|
|
101
|
+
"BufferedGasEstimateMiddleware",
|
|
102
|
+
"LocalFilterMiddleware",
|
|
103
|
+
"FormattingMiddlewareBuilder",
|
|
104
|
+
"GasPriceStrategyMiddleware",
|
|
105
|
+
"ENSNameToAddressMiddleware",
|
|
106
|
+
"ExtraDataToPOAMiddleware",
|
|
107
|
+
"PythonicMiddleware",
|
|
108
|
+
"SignAndSendRawMiddlewareBuilder",
|
|
109
|
+
"StalecheckMiddlewareBuilder",
|
|
110
|
+
"ValidationMiddleware",
|
|
111
|
+
]
|
web3/middleware/attrdict.py
CHANGED
|
@@ -7,10 +7,6 @@ from typing import (
|
|
|
7
7
|
cast,
|
|
8
8
|
)
|
|
9
9
|
|
|
10
|
-
from eth_utils.toolz import (
|
|
11
|
-
assoc,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
10
|
from web3.datastructures import (
|
|
15
11
|
AttributeDict,
|
|
16
12
|
)
|
|
@@ -33,21 +29,18 @@ if TYPE_CHECKING:
|
|
|
33
29
|
|
|
34
30
|
|
|
35
31
|
def _handle_async_response(response: "RPCResponse") -> "RPCResponse":
|
|
32
|
+
"""
|
|
33
|
+
Process the RPC response by converting nested dictionaries into AttributeDict.
|
|
34
|
+
"""
|
|
36
35
|
if "result" in response:
|
|
37
|
-
|
|
36
|
+
response["result"] = AttributeDict.recursive(response["result"])
|
|
38
37
|
elif "params" in response and "result" in response["params"]:
|
|
39
|
-
#
|
|
40
|
-
|
|
41
|
-
response
|
|
42
|
-
"params",
|
|
43
|
-
assoc(
|
|
44
|
-
response["params"],
|
|
45
|
-
"result",
|
|
46
|
-
AttributeDict.recursive(response["params"]["result"]),
|
|
47
|
-
),
|
|
38
|
+
# subscription response
|
|
39
|
+
response["params"]["result"] = AttributeDict.recursive(
|
|
40
|
+
response["params"]["result"]
|
|
48
41
|
)
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
|
|
43
|
+
return response
|
|
51
44
|
|
|
52
45
|
|
|
53
46
|
class AttributeDictMiddleware(Web3Middleware, ABC):
|
|
@@ -60,11 +53,9 @@ class AttributeDictMiddleware(Web3Middleware, ABC):
|
|
|
60
53
|
|
|
61
54
|
def response_processor(self, method: "RPCEndpoint", response: "RPCResponse") -> Any:
|
|
62
55
|
if "result" in response:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
else:
|
|
67
|
-
return response
|
|
56
|
+
new_result = AttributeDict.recursive(response["result"])
|
|
57
|
+
response = {**response, "result": new_result}
|
|
58
|
+
return response
|
|
68
59
|
|
|
69
60
|
# -- async -- #
|
|
70
61
|
|
|
@@ -72,7 +63,6 @@ class AttributeDictMiddleware(Web3Middleware, ABC):
|
|
|
72
63
|
self, method: "RPCEndpoint", response: "RPCResponse"
|
|
73
64
|
) -> Any:
|
|
74
65
|
if self._w3.provider.has_persistent_connection:
|
|
75
|
-
# asynchronous response processing
|
|
76
66
|
provider = cast("PersistentConnectionProvider", self._w3.provider)
|
|
77
67
|
provider._request_processor.append_middleware_response_processor(
|
|
78
68
|
response, _handle_async_response
|
web3/middleware/base.py
CHANGED
|
@@ -4,6 +4,8 @@ from abc import (
|
|
|
4
4
|
from typing import (
|
|
5
5
|
TYPE_CHECKING,
|
|
6
6
|
Any,
|
|
7
|
+
List,
|
|
8
|
+
Tuple,
|
|
7
9
|
Type,
|
|
8
10
|
Union,
|
|
9
11
|
)
|
|
@@ -18,7 +20,9 @@ if TYPE_CHECKING:
|
|
|
18
20
|
Web3,
|
|
19
21
|
)
|
|
20
22
|
from web3.types import ( # noqa: F401
|
|
23
|
+
AsyncMakeBatchRequestFn,
|
|
21
24
|
AsyncMakeRequestFn,
|
|
25
|
+
MakeBatchRequestFn,
|
|
22
26
|
MakeRequestFn,
|
|
23
27
|
RPCEndpoint,
|
|
24
28
|
RPCResponse,
|
|
@@ -36,6 +40,14 @@ class Web3Middleware:
|
|
|
36
40
|
def __init__(self, w3: Union["AsyncWeb3", "Web3"]) -> None:
|
|
37
41
|
self._w3 = w3
|
|
38
42
|
|
|
43
|
+
def __hash__(self) -> int:
|
|
44
|
+
return hash(f"{self.__class__.__name__}({str(self.__dict__)})")
|
|
45
|
+
|
|
46
|
+
def __eq__(self, other: Any) -> bool:
|
|
47
|
+
if not isinstance(other, Web3Middleware):
|
|
48
|
+
return False
|
|
49
|
+
return self.__hash__() == other.__hash__()
|
|
50
|
+
|
|
39
51
|
# -- sync -- #
|
|
40
52
|
|
|
41
53
|
def wrap_make_request(self, make_request: "MakeRequestFn") -> "MakeRequestFn":
|
|
@@ -45,10 +57,31 @@ class Web3Middleware:
|
|
|
45
57
|
|
|
46
58
|
return middleware
|
|
47
59
|
|
|
60
|
+
def wrap_make_batch_request(
|
|
61
|
+
self, make_batch_request: "MakeBatchRequestFn"
|
|
62
|
+
) -> "MakeBatchRequestFn":
|
|
63
|
+
def middleware(
|
|
64
|
+
requests_info: List[Tuple["RPCEndpoint", Any]]
|
|
65
|
+
) -> List["RPCResponse"]:
|
|
66
|
+
req_processed = [
|
|
67
|
+
self.request_processor(method, params)
|
|
68
|
+
for (method, params) in requests_info
|
|
69
|
+
]
|
|
70
|
+
responses = make_batch_request(req_processed)
|
|
71
|
+
methods, _params = zip(*req_processed)
|
|
72
|
+
formatted_responses = [
|
|
73
|
+
self.response_processor(m, r) for m, r in zip(methods, responses)
|
|
74
|
+
]
|
|
75
|
+
return formatted_responses
|
|
76
|
+
|
|
77
|
+
return middleware
|
|
78
|
+
|
|
48
79
|
def request_processor(self, method: "RPCEndpoint", params: Any) -> Any:
|
|
49
80
|
return method, params
|
|
50
81
|
|
|
51
|
-
def response_processor(
|
|
82
|
+
def response_processor(
|
|
83
|
+
self, method: "RPCEndpoint", response: "RPCResponse"
|
|
84
|
+
) -> "RPCResponse":
|
|
52
85
|
return response
|
|
53
86
|
|
|
54
87
|
# -- async -- #
|
|
@@ -65,6 +98,26 @@ class Web3Middleware:
|
|
|
65
98
|
|
|
66
99
|
return middleware
|
|
67
100
|
|
|
101
|
+
async def async_wrap_make_batch_request(
|
|
102
|
+
self, make_batch_request: "AsyncMakeBatchRequestFn"
|
|
103
|
+
) -> "AsyncMakeBatchRequestFn":
|
|
104
|
+
async def middleware(
|
|
105
|
+
requests_info: List[Tuple["RPCEndpoint", Any]]
|
|
106
|
+
) -> List["RPCResponse"]:
|
|
107
|
+
req_processed = [
|
|
108
|
+
await self.async_request_processor(method, params)
|
|
109
|
+
for (method, params) in requests_info
|
|
110
|
+
]
|
|
111
|
+
responses = await make_batch_request(req_processed)
|
|
112
|
+
methods, _params = zip(*req_processed)
|
|
113
|
+
formatted_responses = [
|
|
114
|
+
await self.async_response_processor(m, r)
|
|
115
|
+
for m, r in zip(methods, responses)
|
|
116
|
+
]
|
|
117
|
+
return formatted_responses
|
|
118
|
+
|
|
119
|
+
return middleware
|
|
120
|
+
|
|
68
121
|
async def async_request_processor(
|
|
69
122
|
self,
|
|
70
123
|
method: "RPCEndpoint",
|
|
@@ -76,7 +129,7 @@ class Web3Middleware:
|
|
|
76
129
|
self,
|
|
77
130
|
method: "RPCEndpoint",
|
|
78
131
|
response: "RPCResponse",
|
|
79
|
-
) ->
|
|
132
|
+
) -> "RPCResponse":
|
|
80
133
|
return response
|
|
81
134
|
|
|
82
135
|
|
web3/middleware/filter.py
CHANGED
|
@@ -42,6 +42,9 @@ from web3._utils.formatters import (
|
|
|
42
42
|
from web3._utils.rpc_abi import (
|
|
43
43
|
RPC,
|
|
44
44
|
)
|
|
45
|
+
from web3.exceptions import (
|
|
46
|
+
Web3TypeError,
|
|
47
|
+
)
|
|
45
48
|
from web3.middleware.base import (
|
|
46
49
|
Web3Middleware,
|
|
47
50
|
)
|
|
@@ -71,7 +74,8 @@ else:
|
|
|
71
74
|
|
|
72
75
|
|
|
73
76
|
def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, int]]:
|
|
74
|
-
"""
|
|
77
|
+
"""
|
|
78
|
+
Creates a segment counting generator
|
|
75
79
|
|
|
76
80
|
The generator returns tuple pairs of integers
|
|
77
81
|
that correspond to segments in the provided range.
|
|
@@ -84,6 +88,7 @@ def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, i
|
|
|
84
88
|
|
|
85
89
|
|
|
86
90
|
Example:
|
|
91
|
+
-------
|
|
87
92
|
|
|
88
93
|
>>> segment_counter = segment_count(start=0, stop=10, step=3)
|
|
89
94
|
>>> next(segment_counter)
|
|
@@ -94,6 +99,7 @@ def segment_count(start: int, stop: int, step: int = 5) -> Iterable[Tuple[int, i
|
|
|
94
99
|
(6, 9)
|
|
95
100
|
>>> next(segment_counter) # Remainder is also returned
|
|
96
101
|
(9, 10)
|
|
102
|
+
|
|
97
103
|
"""
|
|
98
104
|
return gen_bounded_segments(start, stop, step)
|
|
99
105
|
|
|
@@ -104,10 +110,9 @@ def gen_bounded_segments(start: int, stop: int, step: int) -> Iterable[Tuple[int
|
|
|
104
110
|
if start + step >= stop:
|
|
105
111
|
yield (start, stop)
|
|
106
112
|
return
|
|
107
|
-
|
|
113
|
+
yield from zip(
|
|
108
114
|
range(start, stop - step + 1, step), range(start + step, stop + 1, step)
|
|
109
|
-
)
|
|
110
|
-
yield segment
|
|
115
|
+
)
|
|
111
116
|
|
|
112
117
|
remainder = (stop - start) % step
|
|
113
118
|
# Handle the remainder
|
|
@@ -118,13 +123,14 @@ def gen_bounded_segments(start: int, stop: int, step: int) -> Iterable[Tuple[int
|
|
|
118
123
|
def block_ranges(
|
|
119
124
|
start_block: BlockNumber, last_block: Optional[BlockNumber], step: int = 5
|
|
120
125
|
) -> Iterable[Tuple[BlockNumber, BlockNumber]]:
|
|
121
|
-
"""
|
|
126
|
+
"""
|
|
127
|
+
Returns 2-tuple ranges describing ranges of block from start_block to last_block
|
|
122
128
|
|
|
123
129
|
Ranges do not overlap to facilitate use as ``toBlock``, ``fromBlock``
|
|
124
130
|
json-rpc arguments, which are both inclusive.
|
|
125
131
|
"""
|
|
126
132
|
if last_block is not None and start_block > last_block:
|
|
127
|
-
raise
|
|
133
|
+
raise Web3TypeError(
|
|
128
134
|
"Incompatible start and stop arguments.",
|
|
129
135
|
"Start must be less than or equal to stop.",
|
|
130
136
|
)
|
|
@@ -138,7 +144,8 @@ def block_ranges(
|
|
|
138
144
|
def iter_latest_block(
|
|
139
145
|
w3: "Web3", to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None
|
|
140
146
|
) -> Iterable[BlockNumber]:
|
|
141
|
-
"""
|
|
147
|
+
"""
|
|
148
|
+
Returns a generator that dispenses the latest block, if
|
|
142
149
|
any new blocks have been mined since last iteration.
|
|
143
150
|
|
|
144
151
|
If there are no new blocks or the latest block is greater than
|
|
@@ -160,8 +167,7 @@ def iter_latest_block(
|
|
|
160
167
|
|
|
161
168
|
while True:
|
|
162
169
|
latest_block = w3.eth.block_number
|
|
163
|
-
|
|
164
|
-
if is_bounded_range and latest_block > to_block: # type: ignore
|
|
170
|
+
if is_bounded_range and latest_block > cast(BlockNumber, to_block):
|
|
165
171
|
yield None
|
|
166
172
|
# No new blocks since last iteration.
|
|
167
173
|
if _last is not None and _last == latest_block:
|
|
@@ -176,7 +182,8 @@ def iter_latest_block_ranges(
|
|
|
176
182
|
from_block: BlockNumber,
|
|
177
183
|
to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
|
|
178
184
|
) -> Iterable[Tuple[Optional[BlockNumber], Optional[BlockNumber]]]:
|
|
179
|
-
"""
|
|
185
|
+
"""
|
|
186
|
+
Returns an iterator unloading ranges of available blocks
|
|
180
187
|
|
|
181
188
|
starting from `fromBlock` to the latest mined block,
|
|
182
189
|
until reaching toBlock. e.g.:
|
|
@@ -212,7 +219,8 @@ def get_logs_multipart(
|
|
|
212
219
|
topics: List[Optional[Union[_Hash32, List[_Hash32]]]],
|
|
213
220
|
max_blocks: int,
|
|
214
221
|
) -> Iterable[List[LogReceipt]]:
|
|
215
|
-
"""
|
|
222
|
+
"""
|
|
223
|
+
Used to break up requests to ``eth_getLogs``
|
|
216
224
|
|
|
217
225
|
The getLog request is partitioned into multiple calls of the max number of blocks
|
|
218
226
|
``max_blocks``.
|
|
@@ -247,9 +255,8 @@ class RequestLogs:
|
|
|
247
255
|
if from_block is None or from_block == "latest":
|
|
248
256
|
self._from_block = BlockNumber(w3.eth.block_number + 1)
|
|
249
257
|
elif is_string(from_block) and is_hex(from_block):
|
|
250
|
-
self._from_block = BlockNumber(hex_to_integer(from_block))
|
|
258
|
+
self._from_block = BlockNumber(hex_to_integer(cast(HexStr, from_block)))
|
|
251
259
|
else:
|
|
252
|
-
# cast b/c LatestBlockParam is handled above
|
|
253
260
|
self._from_block = from_block
|
|
254
261
|
self._to_block = to_block
|
|
255
262
|
self.filter_changes = self._get_filter_changes()
|
|
@@ -265,7 +272,7 @@ class RequestLogs:
|
|
|
265
272
|
elif self._to_block == "latest":
|
|
266
273
|
to_block = self.w3.eth.block_number
|
|
267
274
|
elif is_string(self._to_block) and is_hex(self._to_block):
|
|
268
|
-
to_block = BlockNumber(hex_to_integer(self._to_block))
|
|
275
|
+
to_block = BlockNumber(hex_to_integer(cast(HexStr, self._to_block)))
|
|
269
276
|
else:
|
|
270
277
|
to_block = self._to_block
|
|
271
278
|
|
|
@@ -352,7 +359,8 @@ def block_hashes_in_range(
|
|
|
352
359
|
async def async_iter_latest_block(
|
|
353
360
|
w3: "AsyncWeb3", to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None
|
|
354
361
|
) -> AsyncIterable[BlockNumber]:
|
|
355
|
-
"""
|
|
362
|
+
"""
|
|
363
|
+
Returns a generator that dispenses the latest block, if
|
|
356
364
|
any new blocks have been mined since last iteration.
|
|
357
365
|
|
|
358
366
|
If there are no new blocks or the latest block is greater than
|
|
@@ -390,7 +398,8 @@ async def async_iter_latest_block_ranges(
|
|
|
390
398
|
from_block: BlockNumber,
|
|
391
399
|
to_block: Optional[Union[BlockNumber, LatestBlockParam]] = None,
|
|
392
400
|
) -> AsyncIterable[Tuple[Optional[BlockNumber], Optional[BlockNumber]]]:
|
|
393
|
-
"""
|
|
401
|
+
"""
|
|
402
|
+
Returns an iterator unloading ranges of available blocks
|
|
394
403
|
|
|
395
404
|
starting from `from_block` to the latest mined block,
|
|
396
405
|
until reaching to_block. e.g.:
|
|
@@ -423,7 +432,8 @@ async def async_get_logs_multipart(
|
|
|
423
432
|
topics: List[Optional[Union[_Hash32, List[_Hash32]]]],
|
|
424
433
|
max_blocks: int,
|
|
425
434
|
) -> AsyncIterable[List[LogReceipt]]:
|
|
426
|
-
"""
|
|
435
|
+
"""
|
|
436
|
+
Used to break up requests to ``eth_getLogs``
|
|
427
437
|
|
|
428
438
|
The getLog request is partitioned into multiple calls of the max number of blocks
|
|
429
439
|
``max_blocks``.
|
|
@@ -579,6 +589,10 @@ SyncFilter = Union[RequestLogs, RequestBlocks]
|
|
|
579
589
|
AsyncFilter = Union[AsyncRequestLogs, AsyncRequestBlocks]
|
|
580
590
|
|
|
581
591
|
|
|
592
|
+
def _simulate_rpc_response_with_result(filter_id: str) -> "RPCResponse":
|
|
593
|
+
return {"jsonrpc": "2.0", "id": -1, "result": filter_id}
|
|
594
|
+
|
|
595
|
+
|
|
582
596
|
class LocalFilterMiddleware(Web3Middleware):
|
|
583
597
|
def __init__(self, w3: Union["Web3", "AsyncWeb3"]):
|
|
584
598
|
self.filters: Dict[str, SyncFilter] = {}
|
|
@@ -605,7 +619,7 @@ class LocalFilterMiddleware(Web3Middleware):
|
|
|
605
619
|
raise NotImplementedError(method)
|
|
606
620
|
|
|
607
621
|
self.filters[filter_id] = _filter
|
|
608
|
-
return
|
|
622
|
+
return _simulate_rpc_response_with_result(filter_id)
|
|
609
623
|
|
|
610
624
|
elif method in FILTER_CHANGES_METHODS:
|
|
611
625
|
_filter_id = params[0]
|
|
@@ -616,12 +630,16 @@ class LocalFilterMiddleware(Web3Middleware):
|
|
|
616
630
|
|
|
617
631
|
_filter = self.filters[_filter_id]
|
|
618
632
|
if method == RPC.eth_getFilterChanges:
|
|
619
|
-
return
|
|
633
|
+
return _simulate_rpc_response_with_result(
|
|
634
|
+
next(_filter.filter_changes) # type: ignore
|
|
635
|
+
)
|
|
620
636
|
|
|
621
637
|
elif method == RPC.eth_getFilterLogs:
|
|
622
638
|
# type ignored b/c logic prevents RequestBlocks which
|
|
623
639
|
# doesn't implement get_logs
|
|
624
|
-
return
|
|
640
|
+
return _simulate_rpc_response_with_result(
|
|
641
|
+
_filter.get_logs() # type: ignore
|
|
642
|
+
)
|
|
625
643
|
else:
|
|
626
644
|
raise NotImplementedError(method)
|
|
627
645
|
else:
|
|
@@ -653,7 +671,7 @@ class LocalFilterMiddleware(Web3Middleware):
|
|
|
653
671
|
raise NotImplementedError(method)
|
|
654
672
|
|
|
655
673
|
self.async_filters[filter_id] = _filter
|
|
656
|
-
return
|
|
674
|
+
return _simulate_rpc_response_with_result(filter_id)
|
|
657
675
|
|
|
658
676
|
elif method in FILTER_CHANGES_METHODS:
|
|
659
677
|
_filter_id = params[0]
|
|
@@ -664,12 +682,16 @@ class LocalFilterMiddleware(Web3Middleware):
|
|
|
664
682
|
|
|
665
683
|
_filter = self.async_filters[_filter_id]
|
|
666
684
|
if method == RPC.eth_getFilterChanges:
|
|
667
|
-
return
|
|
685
|
+
return _simulate_rpc_response_with_result(
|
|
686
|
+
await _filter.filter_changes.__anext__() # type: ignore
|
|
687
|
+
)
|
|
668
688
|
|
|
669
689
|
elif method == RPC.eth_getFilterLogs:
|
|
670
690
|
# type ignored b/c logic prevents RequestBlocks which
|
|
671
691
|
# doesn't implement get_logs
|
|
672
|
-
return
|
|
692
|
+
return _simulate_rpc_response_with_result(
|
|
693
|
+
await _filter.get_logs() # type: ignore
|
|
694
|
+
)
|
|
673
695
|
else:
|
|
674
696
|
raise NotImplementedError(method)
|
|
675
697
|
else:
|
web3/middleware/formatting.py
CHANGED
|
@@ -3,6 +3,7 @@ from typing import (
|
|
|
3
3
|
Any,
|
|
4
4
|
Callable,
|
|
5
5
|
Coroutine,
|
|
6
|
+
Literal,
|
|
6
7
|
Optional,
|
|
7
8
|
Union,
|
|
8
9
|
cast,
|
|
@@ -14,6 +15,9 @@ from eth_utils.toolz import (
|
|
|
14
15
|
merge,
|
|
15
16
|
)
|
|
16
17
|
|
|
18
|
+
from web3.exceptions import (
|
|
19
|
+
Web3ValueError,
|
|
20
|
+
)
|
|
17
21
|
from web3.middleware.base import (
|
|
18
22
|
Web3MiddlewareBuilder,
|
|
19
23
|
)
|
|
@@ -21,7 +25,6 @@ from web3.types import (
|
|
|
21
25
|
EthSubscriptionParams,
|
|
22
26
|
Formatters,
|
|
23
27
|
FormattersDict,
|
|
24
|
-
Literal,
|
|
25
28
|
RPCEndpoint,
|
|
26
29
|
RPCResponse,
|
|
27
30
|
)
|
|
@@ -118,7 +121,7 @@ class FormattingMiddlewareBuilder(Web3MiddlewareBuilder):
|
|
|
118
121
|
if (
|
|
119
122
|
sync_formatters_builder is None and async_formatters_builder is not None
|
|
120
123
|
) or (sync_formatters_builder is not None and async_formatters_builder is None):
|
|
121
|
-
raise
|
|
124
|
+
raise Web3ValueError(
|
|
122
125
|
"Must specify both sync_formatters_builder and async_formatters_builder"
|
|
123
126
|
)
|
|
124
127
|
|
|
@@ -128,7 +131,7 @@ class FormattingMiddlewareBuilder(Web3MiddlewareBuilder):
|
|
|
128
131
|
or result_formatters is not None
|
|
129
132
|
or error_formatters is not None
|
|
130
133
|
):
|
|
131
|
-
raise
|
|
134
|
+
raise Web3ValueError(
|
|
132
135
|
"Cannot specify formatters_builder and formatters at the same time"
|
|
133
136
|
)
|
|
134
137
|
|
web3/middleware/names.py
CHANGED
|
@@ -31,6 +31,9 @@ from .._utils.abi import (
|
|
|
31
31
|
from .._utils.formatters import (
|
|
32
32
|
recursive_map,
|
|
33
33
|
)
|
|
34
|
+
from ..exceptions import (
|
|
35
|
+
Web3TypeError,
|
|
36
|
+
)
|
|
34
37
|
from .base import (
|
|
35
38
|
Web3Middleware,
|
|
36
39
|
)
|
|
@@ -92,7 +95,7 @@ async def async_apply_ens_to_address_conversion(
|
|
|
92
95
|
return (formatted_params_dict, *params[1:])
|
|
93
96
|
|
|
94
97
|
else:
|
|
95
|
-
raise
|
|
98
|
+
raise Web3TypeError(
|
|
96
99
|
f"ABI definitions must be a list or dictionary, "
|
|
97
100
|
f"got {abi_types_for_method!r}"
|
|
98
101
|
)
|
web3/middleware/signing.py
CHANGED
|
@@ -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
|
|
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
|
-
"""
|
|
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).
|
|
188
|
+
raw_tx = account.sign_transaction(filled_transaction).raw_transaction
|
|
182
189
|
|
|
183
190
|
return (
|
|
184
191
|
RPCEndpoint("eth_sendRawTransaction"),
|
|
185
|
-
[raw_tx.
|
|
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(
|
|
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.
|
|
223
|
+
[raw_tx.to_0x_hex()],
|
|
215
224
|
)
|
web3/middleware/stalecheck.py
CHANGED
|
@@ -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
|
|
58
|
+
raise Web3ValueError(
|
|
58
59
|
"You must set a positive allowable_delay in seconds for this middleware"
|
|
59
60
|
)
|
|
60
61
|
middleware = StalecheckMiddlewareBuilder(w3)
|