web3 7.0.0b4__py3-none-any.whl → 7.0.0b5__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.
- web3/_utils/contracts.py +5 -5
- web3/_utils/events.py +18 -18
- web3/_utils/filters.py +6 -6
- web3/_utils/method_formatters.py +0 -23
- web3/_utils/module_testing/__init__.py +0 -3
- web3/_utils/module_testing/eth_module.py +434 -365
- web3/_utils/rpc_abi.py +0 -18
- web3/contract/async_contract.py +11 -11
- web3/contract/base_contract.py +19 -18
- web3/contract/contract.py +13 -13
- web3/eth/async_eth.py +5 -4
- web3/eth/eth.py +2 -2
- web3/exceptions.py +55 -21
- web3/geth.py +0 -188
- web3/main.py +0 -4
- web3/manager.py +124 -66
- web3/middleware/filter.py +18 -6
- web3/middleware/signing.py +2 -2
- web3/providers/eth_tester/defaults.py +0 -48
- web3/providers/eth_tester/main.py +36 -11
- web3/providers/eth_tester/middleware.py +3 -8
- web3/providers/rpc/async_rpc.py +1 -1
- web3/providers/rpc/rpc.py +3 -1
- web3/providers/rpc/utils.py +1 -10
- web3/tools/benchmark/node.py +2 -8
- web3/types.py +1 -1
- {web3-7.0.0b4.dist-info → web3-7.0.0b5.dist-info}/METADATA +2 -2
- {web3-7.0.0b4.dist-info → web3-7.0.0b5.dist-info}/RECORD +31 -32
- web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
- {web3-7.0.0b4.dist-info → web3-7.0.0b5.dist-info}/LICENSE +0 -0
- {web3-7.0.0b4.dist-info → web3-7.0.0b5.dist-info}/WHEEL +0 -0
- {web3-7.0.0b4.dist-info → web3-7.0.0b5.dist-info}/top_level.txt +0 -0
web3/main.py
CHANGED
|
@@ -91,11 +91,9 @@ from web3.exceptions import (
|
|
|
91
91
|
from web3.geth import (
|
|
92
92
|
AsyncGeth,
|
|
93
93
|
AsyncGethAdmin,
|
|
94
|
-
AsyncGethPersonal,
|
|
95
94
|
AsyncGethTxPool,
|
|
96
95
|
Geth,
|
|
97
96
|
GethAdmin,
|
|
98
|
-
GethPersonal,
|
|
99
97
|
GethTxPool,
|
|
100
98
|
)
|
|
101
99
|
from web3.manager import (
|
|
@@ -156,7 +154,6 @@ def get_async_default_modules() -> Dict[str, Union[Type[Module], Sequence[Any]]]
|
|
|
156
154
|
AsyncGeth,
|
|
157
155
|
{
|
|
158
156
|
"admin": AsyncGethAdmin,
|
|
159
|
-
"personal": AsyncGethPersonal,
|
|
160
157
|
"txpool": AsyncGethTxPool,
|
|
161
158
|
},
|
|
162
159
|
),
|
|
@@ -171,7 +168,6 @@ def get_default_modules() -> Dict[str, Union[Type[Module], Sequence[Any]]]:
|
|
|
171
168
|
Geth,
|
|
172
169
|
{
|
|
173
170
|
"admin": GethAdmin,
|
|
174
|
-
"personal": GethPersonal,
|
|
175
171
|
"txpool": GethTxPool,
|
|
176
172
|
},
|
|
177
173
|
),
|
web3/manager.py
CHANGED
|
@@ -35,8 +35,8 @@ from web3.exceptions import (
|
|
|
35
35
|
BadResponseFormat,
|
|
36
36
|
MethodUnavailable,
|
|
37
37
|
ProviderConnectionError,
|
|
38
|
+
Web3RPCError,
|
|
38
39
|
Web3TypeError,
|
|
39
|
-
Web3ValueError,
|
|
40
40
|
)
|
|
41
41
|
from web3.middleware import (
|
|
42
42
|
AttributeDictMiddleware,
|
|
@@ -87,6 +87,7 @@ def _raise_bad_response_format(response: RPCResponse, error: str = "") -> None:
|
|
|
87
87
|
raw_response = f"The raw response is: {response}"
|
|
88
88
|
|
|
89
89
|
if error is not None and error != "":
|
|
90
|
+
error = error[:-1] if error.endswith(".") else error
|
|
90
91
|
message = f"{message} {error}. {raw_response}"
|
|
91
92
|
else:
|
|
92
93
|
message = f"{message} {raw_response}"
|
|
@@ -117,6 +118,111 @@ def apply_null_result_formatters(
|
|
|
117
118
|
return response
|
|
118
119
|
|
|
119
120
|
|
|
121
|
+
def _validate_subscription_fields(response: RPCResponse) -> None:
|
|
122
|
+
params = response["params"]
|
|
123
|
+
subscription = params["subscription"]
|
|
124
|
+
if not isinstance(subscription, str) and not len(subscription) == 34:
|
|
125
|
+
_raise_bad_response_format(
|
|
126
|
+
response, "eth_subscription 'params' must include a 'subscription' field."
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _validate_response(
|
|
131
|
+
response: RPCResponse,
|
|
132
|
+
error_formatters: Optional[Callable[..., Any]],
|
|
133
|
+
is_subscription_response: bool = False,
|
|
134
|
+
logger: Optional[logging.Logger] = None,
|
|
135
|
+
) -> None:
|
|
136
|
+
if "jsonrpc" not in response or response["jsonrpc"] != "2.0":
|
|
137
|
+
_raise_bad_response_format(
|
|
138
|
+
response, 'The "jsonrpc" field must be present with a value of "2.0".'
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
response_id = response.get("id")
|
|
142
|
+
if "id" in response:
|
|
143
|
+
int_error_msg = (
|
|
144
|
+
'"id" must be an integer or a string representation of an integer.'
|
|
145
|
+
)
|
|
146
|
+
if response_id is None and "error" in response:
|
|
147
|
+
# errors can sometimes have null `id`, according to the JSON-RPC spec
|
|
148
|
+
pass
|
|
149
|
+
elif not isinstance(response_id, (str, int)):
|
|
150
|
+
_raise_bad_response_format(response, int_error_msg)
|
|
151
|
+
elif isinstance(response_id, str):
|
|
152
|
+
try:
|
|
153
|
+
int(response_id)
|
|
154
|
+
except ValueError:
|
|
155
|
+
_raise_bad_response_format(response, int_error_msg)
|
|
156
|
+
elif is_subscription_response:
|
|
157
|
+
# if `id` is not present, this must be a subscription response
|
|
158
|
+
_validate_subscription_fields(response)
|
|
159
|
+
else:
|
|
160
|
+
_raise_bad_response_format(
|
|
161
|
+
response,
|
|
162
|
+
'Response must include an "id" field or be formatted as an '
|
|
163
|
+
"`eth_subscription` response.",
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
if all(key in response for key in {"error", "result"}):
|
|
167
|
+
_raise_bad_response_format(
|
|
168
|
+
response, 'Response cannot include both "error" and "result".'
|
|
169
|
+
)
|
|
170
|
+
elif (
|
|
171
|
+
not any(key in response for key in {"error", "result"})
|
|
172
|
+
and not is_subscription_response
|
|
173
|
+
):
|
|
174
|
+
_raise_bad_response_format(
|
|
175
|
+
response, 'Response must include either "error" or "result".'
|
|
176
|
+
)
|
|
177
|
+
elif "error" in response:
|
|
178
|
+
error = response["error"]
|
|
179
|
+
|
|
180
|
+
# raise the error when the value is a string
|
|
181
|
+
if error is None or not isinstance(error, dict):
|
|
182
|
+
_raise_bad_response_format(
|
|
183
|
+
response,
|
|
184
|
+
'response["error"] must be a valid object as defined by the '
|
|
185
|
+
"JSON-RPC 2.0 specification.",
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# errors must include an integer code
|
|
189
|
+
code = error.get("code")
|
|
190
|
+
if not isinstance(code, int):
|
|
191
|
+
_raise_bad_response_format(
|
|
192
|
+
response, 'error["code"] is required and must be an integer value.'
|
|
193
|
+
)
|
|
194
|
+
elif code == METHOD_NOT_FOUND:
|
|
195
|
+
exception = MethodUnavailable(
|
|
196
|
+
repr(error),
|
|
197
|
+
rpc_response=response,
|
|
198
|
+
user_message=(
|
|
199
|
+
"This method is not available. Check your node provider or your "
|
|
200
|
+
"client's API docs to see what methods are supported and / or "
|
|
201
|
+
"currently enabled."
|
|
202
|
+
),
|
|
203
|
+
)
|
|
204
|
+
logger.error(exception.user_message)
|
|
205
|
+
logger.debug(f"RPC error response: {response}")
|
|
206
|
+
raise exception
|
|
207
|
+
|
|
208
|
+
# errors must include a message
|
|
209
|
+
error_message = error.get("message")
|
|
210
|
+
if not isinstance(error_message, str):
|
|
211
|
+
_raise_bad_response_format(
|
|
212
|
+
response, 'error["message"] is required and must be a string value.'
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
apply_error_formatters(error_formatters, response)
|
|
216
|
+
|
|
217
|
+
web3_rpc_error = Web3RPCError(repr(error), rpc_response=response)
|
|
218
|
+
logger.error(web3_rpc_error.user_message)
|
|
219
|
+
logger.debug(f"RPC error response: {response}")
|
|
220
|
+
raise web3_rpc_error
|
|
221
|
+
|
|
222
|
+
elif "result" not in response and not is_subscription_response:
|
|
223
|
+
_raise_bad_response_format(response)
|
|
224
|
+
|
|
225
|
+
|
|
120
226
|
class RequestManager:
|
|
121
227
|
logger = logging.getLogger("web3.manager.RequestManager")
|
|
122
228
|
|
|
@@ -203,90 +309,42 @@ class RequestManager:
|
|
|
203
309
|
#
|
|
204
310
|
# See also: https://www.jsonrpc.org/specification
|
|
205
311
|
#
|
|
206
|
-
@staticmethod
|
|
207
312
|
def formatted_response(
|
|
313
|
+
self,
|
|
208
314
|
response: RPCResponse,
|
|
209
315
|
params: Any,
|
|
210
316
|
error_formatters: Optional[Callable[..., Any]] = None,
|
|
211
317
|
null_result_formatters: Optional[Callable[..., Any]] = None,
|
|
212
318
|
) -> Any:
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
)
|
|
319
|
+
is_subscription_response = (
|
|
320
|
+
response.get("method") == "eth_subscription"
|
|
321
|
+
and response.get("params") is not None
|
|
322
|
+
and response["params"].get("subscription") is not None
|
|
323
|
+
and response["params"].get("result") is not None
|
|
324
|
+
)
|
|
218
325
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if response_id is None and "error" not in response:
|
|
226
|
-
_raise_bad_response_format(
|
|
227
|
-
response, '"id" must be None when an error is present'
|
|
228
|
-
)
|
|
229
|
-
elif not isinstance(response_id, (str, int, type(None))):
|
|
230
|
-
_raise_bad_response_format(response, '"id" must be a string or integer')
|
|
231
|
-
|
|
232
|
-
# Response may not include both "error" and "result"
|
|
233
|
-
if "error" in response and "result" in response:
|
|
234
|
-
_raise_bad_response_format(
|
|
235
|
-
response, 'Response cannot include both "error" and "result"'
|
|
236
|
-
)
|
|
326
|
+
_validate_response(
|
|
327
|
+
response,
|
|
328
|
+
error_formatters,
|
|
329
|
+
is_subscription_response=is_subscription_response,
|
|
330
|
+
logger=self.logger,
|
|
331
|
+
)
|
|
237
332
|
|
|
238
|
-
#
|
|
239
|
-
|
|
240
|
-
error = response.get("error")
|
|
241
|
-
# Raise the error when the value is a string
|
|
242
|
-
if error is None or isinstance(error, str):
|
|
243
|
-
raise Web3ValueError(error)
|
|
244
|
-
|
|
245
|
-
# Errors must include an integer code
|
|
246
|
-
code = error.get("code")
|
|
247
|
-
if not isinstance(code, int):
|
|
248
|
-
_raise_bad_response_format(response, "error['code'] must be an integer")
|
|
249
|
-
elif code == METHOD_NOT_FOUND:
|
|
250
|
-
raise MethodUnavailable(
|
|
251
|
-
error,
|
|
252
|
-
user_message="Check your node provider's API docs to see what "
|
|
253
|
-
"methods are supported",
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
# Errors must include a message
|
|
257
|
-
if not isinstance(error.get("message"), str):
|
|
258
|
-
_raise_bad_response_format(
|
|
259
|
-
response, "error['message'] must be a string"
|
|
260
|
-
)
|
|
261
|
-
|
|
262
|
-
apply_error_formatters(error_formatters, response)
|
|
263
|
-
|
|
264
|
-
raise Web3ValueError(error)
|
|
265
|
-
|
|
266
|
-
# Format and validate results
|
|
267
|
-
elif "result" in response:
|
|
333
|
+
# format results
|
|
334
|
+
if "result" in response:
|
|
268
335
|
# Null values for result should apply null_result_formatters
|
|
269
336
|
# Skip when result not present in the response (fallback to False)
|
|
270
337
|
if response.get("result", False) in NULL_RESPONSES:
|
|
271
338
|
apply_null_result_formatters(null_result_formatters, response, params)
|
|
272
339
|
return response.get("result")
|
|
273
340
|
|
|
274
|
-
#
|
|
275
|
-
elif
|
|
276
|
-
response.get("method") == "eth_subscription"
|
|
277
|
-
and response.get("params") is not None
|
|
278
|
-
and response["params"].get("subscription") is not None
|
|
279
|
-
and response["params"].get("result") is not None
|
|
280
|
-
):
|
|
341
|
+
# response from eth_subscription includes response["params"]["result"]
|
|
342
|
+
elif is_subscription_response:
|
|
281
343
|
return {
|
|
282
344
|
"subscription": response["params"]["subscription"],
|
|
283
345
|
"result": response["params"]["result"],
|
|
284
346
|
}
|
|
285
347
|
|
|
286
|
-
# Any other response type raises BadResponseFormat
|
|
287
|
-
else:
|
|
288
|
-
_raise_bad_response_format(response)
|
|
289
|
-
|
|
290
348
|
def request_blocking(
|
|
291
349
|
self,
|
|
292
350
|
method: Union[RPCEndpoint, Callable[..., RPCEndpoint]],
|
web3/middleware/filter.py
CHANGED
|
@@ -589,6 +589,10 @@ SyncFilter = Union[RequestLogs, RequestBlocks]
|
|
|
589
589
|
AsyncFilter = Union[AsyncRequestLogs, AsyncRequestBlocks]
|
|
590
590
|
|
|
591
591
|
|
|
592
|
+
def _simulate_rpc_response_with_result(filter_id: str) -> "RPCResponse":
|
|
593
|
+
return {"jsonrpc": "2.0", "id": -1, "result": filter_id}
|
|
594
|
+
|
|
595
|
+
|
|
592
596
|
class LocalFilterMiddleware(Web3Middleware):
|
|
593
597
|
def __init__(self, w3: Union["Web3", "AsyncWeb3"]):
|
|
594
598
|
self.filters: Dict[str, SyncFilter] = {}
|
|
@@ -615,7 +619,7 @@ class LocalFilterMiddleware(Web3Middleware):
|
|
|
615
619
|
raise NotImplementedError(method)
|
|
616
620
|
|
|
617
621
|
self.filters[filter_id] = _filter
|
|
618
|
-
return
|
|
622
|
+
return _simulate_rpc_response_with_result(filter_id)
|
|
619
623
|
|
|
620
624
|
elif method in FILTER_CHANGES_METHODS:
|
|
621
625
|
_filter_id = params[0]
|
|
@@ -626,12 +630,16 @@ class LocalFilterMiddleware(Web3Middleware):
|
|
|
626
630
|
|
|
627
631
|
_filter = self.filters[_filter_id]
|
|
628
632
|
if method == RPC.eth_getFilterChanges:
|
|
629
|
-
return
|
|
633
|
+
return _simulate_rpc_response_with_result(
|
|
634
|
+
next(_filter.filter_changes) # type: ignore
|
|
635
|
+
)
|
|
630
636
|
|
|
631
637
|
elif method == RPC.eth_getFilterLogs:
|
|
632
638
|
# type ignored b/c logic prevents RequestBlocks which
|
|
633
639
|
# doesn't implement get_logs
|
|
634
|
-
return
|
|
640
|
+
return _simulate_rpc_response_with_result(
|
|
641
|
+
_filter.get_logs() # type: ignore
|
|
642
|
+
)
|
|
635
643
|
else:
|
|
636
644
|
raise NotImplementedError(method)
|
|
637
645
|
else:
|
|
@@ -663,7 +671,7 @@ class LocalFilterMiddleware(Web3Middleware):
|
|
|
663
671
|
raise NotImplementedError(method)
|
|
664
672
|
|
|
665
673
|
self.async_filters[filter_id] = _filter
|
|
666
|
-
return
|
|
674
|
+
return _simulate_rpc_response_with_result(filter_id)
|
|
667
675
|
|
|
668
676
|
elif method in FILTER_CHANGES_METHODS:
|
|
669
677
|
_filter_id = params[0]
|
|
@@ -674,12 +682,16 @@ class LocalFilterMiddleware(Web3Middleware):
|
|
|
674
682
|
|
|
675
683
|
_filter = self.async_filters[_filter_id]
|
|
676
684
|
if method == RPC.eth_getFilterChanges:
|
|
677
|
-
return
|
|
685
|
+
return _simulate_rpc_response_with_result(
|
|
686
|
+
await _filter.filter_changes.__anext__() # type: ignore
|
|
687
|
+
)
|
|
678
688
|
|
|
679
689
|
elif method == RPC.eth_getFilterLogs:
|
|
680
690
|
# type ignored b/c logic prevents RequestBlocks which
|
|
681
691
|
# doesn't implement get_logs
|
|
682
|
-
return
|
|
692
|
+
return _simulate_rpc_response_with_result(
|
|
693
|
+
await _filter.get_logs() # type: ignore
|
|
694
|
+
)
|
|
683
695
|
else:
|
|
684
696
|
raise NotImplementedError(method)
|
|
685
697
|
else:
|
web3/middleware/signing.py
CHANGED
|
@@ -182,7 +182,7 @@ class SignAndSendRawMiddlewareBuilder(Web3MiddlewareBuilder):
|
|
|
182
182
|
return method, params
|
|
183
183
|
else:
|
|
184
184
|
account = self._accounts[to_checksum_address(tx_from)]
|
|
185
|
-
raw_tx = account.sign_transaction(filled_transaction).
|
|
185
|
+
raw_tx = account.sign_transaction(filled_transaction).raw_transaction
|
|
186
186
|
|
|
187
187
|
return (
|
|
188
188
|
RPCEndpoint("eth_sendRawTransaction"),
|
|
@@ -211,7 +211,7 @@ class SignAndSendRawMiddlewareBuilder(Web3MiddlewareBuilder):
|
|
|
211
211
|
return method, params
|
|
212
212
|
else:
|
|
213
213
|
account = self._accounts[to_checksum_address(tx_from)]
|
|
214
|
-
raw_tx = account.sign_transaction(filled_transaction).
|
|
214
|
+
raw_tx = account.sign_transaction(filled_transaction).raw_transaction
|
|
215
215
|
|
|
216
216
|
return (
|
|
217
217
|
RPCEndpoint("eth_sendRawTransaction"),
|
|
@@ -21,7 +21,6 @@ from eth_tester.exceptions import (
|
|
|
21
21
|
FilterNotFound,
|
|
22
22
|
TransactionFailed,
|
|
23
23
|
TransactionNotFound,
|
|
24
|
-
ValidationError,
|
|
25
24
|
)
|
|
26
25
|
from eth_typing import (
|
|
27
26
|
HexAddress,
|
|
@@ -226,18 +225,6 @@ def create_new_account(eth_tester: "EthereumTester") -> HexAddress:
|
|
|
226
225
|
return eth_tester.add_account(_generate_random_private_key())
|
|
227
226
|
|
|
228
227
|
|
|
229
|
-
def personal_send_transaction(eth_tester: "EthereumTester", params: Any) -> HexStr:
|
|
230
|
-
transaction, password = params
|
|
231
|
-
|
|
232
|
-
try:
|
|
233
|
-
eth_tester.unlock_account(transaction["from"], password)
|
|
234
|
-
transaction_hash = eth_tester.send_transaction(transaction)
|
|
235
|
-
finally:
|
|
236
|
-
eth_tester.lock_account(transaction["from"])
|
|
237
|
-
|
|
238
|
-
return transaction_hash
|
|
239
|
-
|
|
240
|
-
|
|
241
228
|
API_ENDPOINTS = {
|
|
242
229
|
"web3": {
|
|
243
230
|
"clientVersion": client_version,
|
|
@@ -404,41 +391,6 @@ API_ENDPOINTS = {
|
|
|
404
391
|
"writeBlockProfile": not_implemented,
|
|
405
392
|
"writeMemProfile": not_implemented,
|
|
406
393
|
},
|
|
407
|
-
"personal": {
|
|
408
|
-
"ec_recover": not_implemented,
|
|
409
|
-
"import_raw_key": call_eth_tester("add_account"),
|
|
410
|
-
"list_accounts": call_eth_tester("get_accounts"),
|
|
411
|
-
"list_wallets": not_implemented,
|
|
412
|
-
"lock_account": excepts(
|
|
413
|
-
ValidationError,
|
|
414
|
-
compose(static_return(True), call_eth_tester("lock_account")),
|
|
415
|
-
static_return(False),
|
|
416
|
-
),
|
|
417
|
-
"new_account": create_new_account,
|
|
418
|
-
"unlock_account": excepts(
|
|
419
|
-
ValidationError,
|
|
420
|
-
compose(static_return(True), call_eth_tester("unlock_account")),
|
|
421
|
-
static_return(False),
|
|
422
|
-
),
|
|
423
|
-
"send_transaction": personal_send_transaction,
|
|
424
|
-
"sign": not_implemented,
|
|
425
|
-
# deprecated
|
|
426
|
-
"ecRecover": not_implemented,
|
|
427
|
-
"importRawKey": call_eth_tester("add_account"),
|
|
428
|
-
"listAccounts": call_eth_tester("get_accounts"),
|
|
429
|
-
"lockAccount": excepts(
|
|
430
|
-
ValidationError,
|
|
431
|
-
compose(static_return(True), call_eth_tester("lock_account")),
|
|
432
|
-
static_return(False),
|
|
433
|
-
),
|
|
434
|
-
"newAccount": create_new_account,
|
|
435
|
-
"unlockAccount": excepts(
|
|
436
|
-
ValidationError,
|
|
437
|
-
compose(static_return(True), call_eth_tester("unlock_account")),
|
|
438
|
-
static_return(False),
|
|
439
|
-
),
|
|
440
|
-
"sendTransaction": personal_send_transaction,
|
|
441
|
-
},
|
|
442
394
|
"testing": {
|
|
443
395
|
"timeTravel": call_eth_tester("time_travel"),
|
|
444
396
|
},
|
|
@@ -7,6 +7,7 @@ from typing import (
|
|
|
7
7
|
Literal,
|
|
8
8
|
Optional,
|
|
9
9
|
Union,
|
|
10
|
+
cast,
|
|
10
11
|
)
|
|
11
12
|
|
|
12
13
|
from eth_abi import (
|
|
@@ -59,6 +60,7 @@ if TYPE_CHECKING:
|
|
|
59
60
|
|
|
60
61
|
|
|
61
62
|
class AsyncEthereumTesterProvider(AsyncBaseProvider):
|
|
63
|
+
_current_request_id = 0
|
|
62
64
|
_middleware = (
|
|
63
65
|
default_transaction_fields_middleware,
|
|
64
66
|
ethereum_tester_middleware,
|
|
@@ -99,13 +101,22 @@ class AsyncEthereumTesterProvider(AsyncBaseProvider):
|
|
|
99
101
|
return self._request_func_cache[-1]
|
|
100
102
|
|
|
101
103
|
async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
102
|
-
|
|
104
|
+
response = _make_request(
|
|
105
|
+
method,
|
|
106
|
+
params,
|
|
107
|
+
self.api_endpoints,
|
|
108
|
+
self.ethereum_tester,
|
|
109
|
+
repr(self._current_request_id),
|
|
110
|
+
)
|
|
111
|
+
self._current_request_id += 1
|
|
112
|
+
return response
|
|
103
113
|
|
|
104
114
|
async def is_connected(self, show_traceback: bool = False) -> Literal[True]:
|
|
105
115
|
return True
|
|
106
116
|
|
|
107
117
|
|
|
108
118
|
class EthereumTesterProvider(BaseProvider):
|
|
119
|
+
_current_request_id = 0
|
|
109
120
|
_middleware = (
|
|
110
121
|
default_transaction_fields_middleware,
|
|
111
122
|
ethereum_tester_middleware,
|
|
@@ -173,23 +184,32 @@ class EthereumTesterProvider(BaseProvider):
|
|
|
173
184
|
return self._request_func_cache[-1]
|
|
174
185
|
|
|
175
186
|
def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
176
|
-
|
|
187
|
+
response = _make_request(
|
|
188
|
+
method,
|
|
189
|
+
params,
|
|
190
|
+
self.api_endpoints,
|
|
191
|
+
self.ethereum_tester,
|
|
192
|
+
repr(self._current_request_id),
|
|
193
|
+
)
|
|
194
|
+
self._current_request_id += 1
|
|
195
|
+
return response
|
|
177
196
|
|
|
178
197
|
def is_connected(self, show_traceback: bool = False) -> Literal[True]:
|
|
179
198
|
return True
|
|
180
199
|
|
|
181
200
|
|
|
182
|
-
def _make_response(result: Any, message: str = "") -> RPCResponse:
|
|
201
|
+
def _make_response(result: Any, response_id: str, message: str = "") -> RPCResponse:
|
|
183
202
|
if isinstance(result, Exception):
|
|
184
|
-
return
|
|
203
|
+
return cast(
|
|
204
|
+
RPCResponse,
|
|
185
205
|
{
|
|
186
|
-
"id":
|
|
206
|
+
"id": response_id,
|
|
187
207
|
"jsonrpc": "2.0",
|
|
188
|
-
"error": RPCError
|
|
189
|
-
}
|
|
208
|
+
"error": cast(RPCError, {"code": -32601, "message": message}),
|
|
209
|
+
},
|
|
190
210
|
)
|
|
191
211
|
|
|
192
|
-
return RPCResponse
|
|
212
|
+
return cast(RPCResponse, {"id": response_id, "jsonrpc": "2.0", "result": result})
|
|
193
213
|
|
|
194
214
|
|
|
195
215
|
def _make_request(
|
|
@@ -197,6 +217,7 @@ def _make_request(
|
|
|
197
217
|
params: Any,
|
|
198
218
|
api_endpoints: Dict[str, Dict[str, Any]],
|
|
199
219
|
ethereum_tester_instance: "EthereumTester",
|
|
220
|
+
request_id: str,
|
|
200
221
|
) -> RPCResponse:
|
|
201
222
|
# do not import eth_tester derivatives until runtime,
|
|
202
223
|
# it is not a default dependency
|
|
@@ -209,11 +230,15 @@ def _make_request(
|
|
|
209
230
|
try:
|
|
210
231
|
delegator = api_endpoints[namespace][endpoint]
|
|
211
232
|
except KeyError as e:
|
|
212
|
-
return _make_response(e, f"Unknown RPC Endpoint: {method}")
|
|
233
|
+
return _make_response(e, request_id, message=f"Unknown RPC Endpoint: {method}")
|
|
213
234
|
try:
|
|
214
235
|
response = delegator(ethereum_tester_instance, params)
|
|
215
236
|
except NotImplementedError as e:
|
|
216
|
-
return _make_response(
|
|
237
|
+
return _make_response(
|
|
238
|
+
e,
|
|
239
|
+
request_id,
|
|
240
|
+
message=f"RPC Endpoint has not been implemented: {method}",
|
|
241
|
+
)
|
|
217
242
|
except TransactionFailed as e:
|
|
218
243
|
first_arg = e.args[0]
|
|
219
244
|
try:
|
|
@@ -230,4 +255,4 @@ def _make_request(
|
|
|
230
255
|
reason = first_arg
|
|
231
256
|
raise TransactionFailed(f"execution reverted: {reason}")
|
|
232
257
|
else:
|
|
233
|
-
return _make_response(response)
|
|
258
|
+
return _make_response(response, request_id)
|
|
@@ -110,14 +110,14 @@ filter_request_remapper = apply_key_map(FILTER_REQUEST_KEY_MAPPING)
|
|
|
110
110
|
|
|
111
111
|
|
|
112
112
|
FILTER_REQUEST_FORMATTERS = {
|
|
113
|
-
"
|
|
114
|
-
"
|
|
113
|
+
"from_block": to_integer_if_hex,
|
|
114
|
+
"to_block": to_integer_if_hex,
|
|
115
115
|
}
|
|
116
116
|
filter_request_formatter = apply_formatters_to_dict(FILTER_REQUEST_FORMATTERS)
|
|
117
117
|
|
|
118
118
|
filter_request_transformer = compose(
|
|
119
|
-
filter_request_remapper,
|
|
120
119
|
filter_request_formatter,
|
|
120
|
+
filter_request_remapper,
|
|
121
121
|
)
|
|
122
122
|
|
|
123
123
|
|
|
@@ -285,11 +285,6 @@ request_formatters = {
|
|
|
285
285
|
),
|
|
286
286
|
# EVM
|
|
287
287
|
RPCEndpoint("evm_revert"): apply_formatters_to_args(hex_to_integer),
|
|
288
|
-
# Personal
|
|
289
|
-
RPCEndpoint("personal_sendTransaction"): apply_formatters_to_args(
|
|
290
|
-
transaction_request_transformer,
|
|
291
|
-
identity,
|
|
292
|
-
),
|
|
293
288
|
}
|
|
294
289
|
|
|
295
290
|
result_formatters: Optional[Dict[RPCEndpoint, Callable[..., Any]]] = {
|
web3/providers/rpc/async_rpc.py
CHANGED
|
@@ -123,7 +123,7 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
|
|
|
123
123
|
except tuple(self.exception_retry_configuration.errors):
|
|
124
124
|
if i < self.exception_retry_configuration.retries - 1:
|
|
125
125
|
await asyncio.sleep(
|
|
126
|
-
self.exception_retry_configuration.backoff_factor
|
|
126
|
+
self.exception_retry_configuration.backoff_factor * 2**i
|
|
127
127
|
)
|
|
128
128
|
continue
|
|
129
129
|
else:
|
web3/providers/rpc/rpc.py
CHANGED
|
@@ -130,7 +130,9 @@ class HTTPProvider(JSONBaseProvider):
|
|
|
130
130
|
)
|
|
131
131
|
except tuple(self.exception_retry_configuration.errors) as e:
|
|
132
132
|
if i < self.exception_retry_configuration.retries - 1:
|
|
133
|
-
time.sleep(
|
|
133
|
+
time.sleep(
|
|
134
|
+
self.exception_retry_configuration.backoff_factor * 2**i
|
|
135
|
+
)
|
|
134
136
|
continue
|
|
135
137
|
else:
|
|
136
138
|
raise e
|
web3/providers/rpc/utils.py
CHANGED
|
@@ -58,15 +58,6 @@ REQUEST_RETRY_ALLOWLIST = [
|
|
|
58
58
|
"eth_sign",
|
|
59
59
|
"eth_signTypedData",
|
|
60
60
|
"eth_sendRawTransaction",
|
|
61
|
-
"personal_importRawKey",
|
|
62
|
-
"personal_newAccount",
|
|
63
|
-
"personal_listAccounts",
|
|
64
|
-
"personal_listWallets",
|
|
65
|
-
"personal_lockAccount",
|
|
66
|
-
"personal_unlockAccount",
|
|
67
|
-
"personal_ecRecover",
|
|
68
|
-
"personal_sign",
|
|
69
|
-
"personal_signTypedData",
|
|
70
61
|
]
|
|
71
62
|
|
|
72
63
|
|
|
@@ -93,7 +84,7 @@ class ExceptionRetryConfiguration(BaseModel):
|
|
|
93
84
|
self,
|
|
94
85
|
errors: Sequence[Type[BaseException]] = None,
|
|
95
86
|
retries: int = 5,
|
|
96
|
-
backoff_factor: float = 0.
|
|
87
|
+
backoff_factor: float = 0.125,
|
|
97
88
|
method_allowlist: Sequence[str] = None,
|
|
98
89
|
):
|
|
99
90
|
super().__init__(
|
web3/tools/benchmark/node.py
CHANGED
|
@@ -24,10 +24,7 @@ from web3.tools.benchmark.utils import (
|
|
|
24
24
|
kill_proc_gracefully,
|
|
25
25
|
)
|
|
26
26
|
|
|
27
|
-
GETH_FIXTURE_ZIP = "geth-1.13.
|
|
28
|
-
|
|
29
|
-
# use same coinbase value as in `web3.py/tests/integration/generate_fixtures/common.py`
|
|
30
|
-
COINBASE = "0xdc544d1aa88ff8bbd2f2aec754b1f1e99e1812fd"
|
|
27
|
+
GETH_FIXTURE_ZIP = "geth-1.13.14-fixture.zip"
|
|
31
28
|
|
|
32
29
|
|
|
33
30
|
class GethBenchmarkFixture:
|
|
@@ -84,7 +81,7 @@ class GethBenchmarkFixture:
|
|
|
84
81
|
"--dev.period",
|
|
85
82
|
"100",
|
|
86
83
|
"--datadir",
|
|
87
|
-
|
|
84
|
+
datadir,
|
|
88
85
|
"--nodiscover",
|
|
89
86
|
"--http",
|
|
90
87
|
"--http.port",
|
|
@@ -92,9 +89,6 @@ class GethBenchmarkFixture:
|
|
|
92
89
|
"--http.api",
|
|
93
90
|
"admin,eth,net,web3",
|
|
94
91
|
"--ipcdisable",
|
|
95
|
-
"--allow-insecure-unlock",
|
|
96
|
-
"--miner.etherbase",
|
|
97
|
-
COINBASE[2:],
|
|
98
92
|
"--password",
|
|
99
93
|
os.path.join(datadir, "keystore", "pw.txt"),
|
|
100
94
|
)
|
web3/types.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: web3
|
|
3
|
-
Version: 7.0.
|
|
3
|
+
Version: 7.0.0b5
|
|
4
4
|
Summary: web3.py
|
|
5
5
|
Home-page: https://github.com/ethereum/web3.py
|
|
6
6
|
Author: The Ethereum Foundation
|
|
@@ -21,7 +21,7 @@ Description-Content-Type: text/markdown
|
|
|
21
21
|
License-File: LICENSE
|
|
22
22
|
Requires-Dist: aiohttp >=3.7.4.post0
|
|
23
23
|
Requires-Dist: eth-abi >=5.0.1
|
|
24
|
-
Requires-Dist: eth-account >=0.12.
|
|
24
|
+
Requires-Dist: eth-account >=0.12.2
|
|
25
25
|
Requires-Dist: eth-hash[pycryptodome] >=0.5.1
|
|
26
26
|
Requires-Dist: eth-typing >=4.0.0
|
|
27
27
|
Requires-Dist: eth-utils >=4.0.0
|