web3 7.0.0b3__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.
- ens/_normalization.py +1 -3
- ens/async_ens.py +12 -9
- ens/contract_data.py +2 -2
- ens/ens.py +8 -5
- ens/exceptions.py +19 -27
- ens/specs/nf.json +1 -1
- ens/specs/normalization_spec.json +1 -1
- ens/utils.py +17 -10
- web3/__init__.py +2 -7
- web3/_utils/abi.py +30 -29
- web3/_utils/async_transactions.py +7 -4
- web3/_utils/blocks.py +6 -2
- web3/_utils/caching.py +7 -3
- web3/_utils/compat/__init__.py +0 -3
- web3/_utils/contract_sources/compile_contracts.py +1 -1
- web3/_utils/contracts.py +17 -17
- web3/_utils/datatypes.py +5 -1
- web3/_utils/decorators.py +6 -1
- web3/_utils/empty.py +1 -1
- web3/_utils/encoding.py +15 -10
- web3/_utils/error_formatters_utils.py +5 -3
- web3/_utils/events.py +38 -36
- web3/_utils/fee_utils.py +2 -4
- web3/_utils/filters.py +23 -18
- web3/_utils/formatters.py +2 -2
- web3/_utils/math.py +3 -2
- web3/_utils/method_formatters.py +24 -28
- web3/_utils/module.py +2 -1
- web3/_utils/module_testing/__init__.py +0 -3
- web3/_utils/module_testing/eth_module.py +494 -432
- web3/_utils/module_testing/module_testing_utils.py +1 -3
- web3/_utils/module_testing/utils.py +14 -7
- web3/_utils/normalizers.py +3 -3
- web3/_utils/request.py +4 -4
- web3/_utils/rpc_abi.py +5 -19
- web3/_utils/threads.py +8 -7
- web3/_utils/transactions.py +14 -12
- web3/_utils/type_conversion.py +5 -1
- web3/_utils/validation.py +12 -10
- web3/contract/async_contract.py +23 -18
- web3/contract/base_contract.py +69 -74
- web3/contract/contract.py +25 -19
- web3/contract/utils.py +11 -6
- web3/datastructures.py +22 -12
- web3/eth/async_eth.py +38 -32
- web3/eth/base_eth.py +7 -3
- web3/eth/eth.py +20 -15
- web3/exceptions.py +83 -78
- web3/gas_strategies/time_based.py +2 -4
- web3/geth.py +1 -191
- web3/main.py +6 -6
- web3/manager.py +128 -68
- web3/method.py +13 -5
- web3/middleware/base.py +4 -2
- web3/middleware/filter.py +45 -23
- web3/middleware/formatting.py +6 -3
- web3/middleware/names.py +4 -1
- web3/middleware/signing.py +8 -4
- web3/middleware/stalecheck.py +2 -1
- web3/providers/eth_tester/defaults.py +1 -49
- web3/providers/eth_tester/main.py +41 -15
- web3/providers/eth_tester/middleware.py +13 -9
- web3/providers/ipc.py +7 -3
- web3/providers/persistent/async_ipc.py +6 -7
- web3/providers/persistent/persistent.py +11 -1
- web3/providers/persistent/request_processor.py +7 -7
- web3/providers/persistent/websocket.py +3 -3
- web3/providers/rpc/async_rpc.py +24 -7
- web3/providers/rpc/rpc.py +30 -17
- web3/providers/rpc/utils.py +1 -10
- web3/testing.py +4 -4
- web3/tools/benchmark/main.py +13 -9
- web3/tools/benchmark/node.py +2 -8
- web3/tools/benchmark/utils.py +1 -1
- web3/tracing.py +9 -5
- web3/types.py +20 -23
- {web3-7.0.0b3.dist-info → web3-7.0.0b5.dist-info}/METADATA +13 -28
- {web3-7.0.0b3.dist-info → web3-7.0.0b5.dist-info}/RECORD +81 -82
- web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
- {web3-7.0.0b3.dist-info → web3-7.0.0b5.dist-info}/LICENSE +0 -0
- {web3-7.0.0b3.dist-info → web3-7.0.0b5.dist-info}/WHEEL +0 -0
- {web3-7.0.0b3.dist-info → web3-7.0.0b5.dist-info}/top_level.txt +0 -0
|
@@ -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,
|
|
@@ -218,7 +217,7 @@ def _generate_random_private_key() -> HexStr:
|
|
|
218
217
|
WARNING: This is not a secure way to generate private keys and should only
|
|
219
218
|
be used for testing purposes.
|
|
220
219
|
"""
|
|
221
|
-
return encode_hex(bytes(bytearray(
|
|
220
|
+
return encode_hex(bytes(bytearray(random.randint(0, 255) for _ in range(32))))
|
|
222
221
|
|
|
223
222
|
|
|
224
223
|
@without_params
|
|
@@ -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
|
},
|
|
@@ -4,8 +4,10 @@ from typing import (
|
|
|
4
4
|
Callable,
|
|
5
5
|
Coroutine,
|
|
6
6
|
Dict,
|
|
7
|
+
Literal,
|
|
7
8
|
Optional,
|
|
8
9
|
Union,
|
|
10
|
+
cast,
|
|
9
11
|
)
|
|
10
12
|
|
|
11
13
|
from eth_abi import (
|
|
@@ -18,9 +20,6 @@ from eth_utils import (
|
|
|
18
20
|
is_bytes,
|
|
19
21
|
)
|
|
20
22
|
|
|
21
|
-
from web3._utils.compat import (
|
|
22
|
-
Literal,
|
|
23
|
-
)
|
|
24
23
|
from web3.providers import (
|
|
25
24
|
BaseProvider,
|
|
26
25
|
)
|
|
@@ -33,6 +32,9 @@ from web3.types import (
|
|
|
33
32
|
RPCResponse,
|
|
34
33
|
)
|
|
35
34
|
|
|
35
|
+
from ...exceptions import (
|
|
36
|
+
Web3TypeError,
|
|
37
|
+
)
|
|
36
38
|
from ...middleware import (
|
|
37
39
|
async_combine_middleware,
|
|
38
40
|
combine_middleware,
|
|
@@ -58,6 +60,7 @@ if TYPE_CHECKING:
|
|
|
58
60
|
|
|
59
61
|
|
|
60
62
|
class AsyncEthereumTesterProvider(AsyncBaseProvider):
|
|
63
|
+
_current_request_id = 0
|
|
61
64
|
_middleware = (
|
|
62
65
|
default_transaction_fields_middleware,
|
|
63
66
|
ethereum_tester_middleware,
|
|
@@ -98,13 +101,22 @@ class AsyncEthereumTesterProvider(AsyncBaseProvider):
|
|
|
98
101
|
return self._request_func_cache[-1]
|
|
99
102
|
|
|
100
103
|
async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
101
|
-
|
|
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
|
|
102
113
|
|
|
103
114
|
async def is_connected(self, show_traceback: bool = False) -> Literal[True]:
|
|
104
115
|
return True
|
|
105
116
|
|
|
106
117
|
|
|
107
118
|
class EthereumTesterProvider(BaseProvider):
|
|
119
|
+
_current_request_id = 0
|
|
108
120
|
_middleware = (
|
|
109
121
|
default_transaction_fields_middleware,
|
|
110
122
|
ethereum_tester_middleware,
|
|
@@ -133,7 +145,7 @@ class EthereumTesterProvider(BaseProvider):
|
|
|
133
145
|
elif isinstance(ethereum_tester, BaseChainBackend):
|
|
134
146
|
self.ethereum_tester = EthereumTester(ethereum_tester)
|
|
135
147
|
else:
|
|
136
|
-
raise
|
|
148
|
+
raise Web3TypeError(
|
|
137
149
|
"Expected ethereum_tester to be of type `eth_tester.EthereumTester` or "
|
|
138
150
|
"a subclass of `eth_tester.backends.base.BaseChainBackend`, "
|
|
139
151
|
f"instead received {type(ethereum_tester)}. "
|
|
@@ -172,23 +184,32 @@ class EthereumTesterProvider(BaseProvider):
|
|
|
172
184
|
return self._request_func_cache[-1]
|
|
173
185
|
|
|
174
186
|
def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
175
|
-
|
|
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
|
|
176
196
|
|
|
177
197
|
def is_connected(self, show_traceback: bool = False) -> Literal[True]:
|
|
178
198
|
return True
|
|
179
199
|
|
|
180
200
|
|
|
181
|
-
def _make_response(result: Any, message: str = "") -> RPCResponse:
|
|
201
|
+
def _make_response(result: Any, response_id: str, message: str = "") -> RPCResponse:
|
|
182
202
|
if isinstance(result, Exception):
|
|
183
|
-
return
|
|
203
|
+
return cast(
|
|
204
|
+
RPCResponse,
|
|
184
205
|
{
|
|
185
|
-
"id":
|
|
206
|
+
"id": response_id,
|
|
186
207
|
"jsonrpc": "2.0",
|
|
187
|
-
"error": RPCError
|
|
188
|
-
}
|
|
208
|
+
"error": cast(RPCError, {"code": -32601, "message": message}),
|
|
209
|
+
},
|
|
189
210
|
)
|
|
190
211
|
|
|
191
|
-
return RPCResponse
|
|
212
|
+
return cast(RPCResponse, {"id": response_id, "jsonrpc": "2.0", "result": result})
|
|
192
213
|
|
|
193
214
|
|
|
194
215
|
def _make_request(
|
|
@@ -196,6 +217,7 @@ def _make_request(
|
|
|
196
217
|
params: Any,
|
|
197
218
|
api_endpoints: Dict[str, Dict[str, Any]],
|
|
198
219
|
ethereum_tester_instance: "EthereumTester",
|
|
220
|
+
request_id: str,
|
|
199
221
|
) -> RPCResponse:
|
|
200
222
|
# do not import eth_tester derivatives until runtime,
|
|
201
223
|
# it is not a default dependency
|
|
@@ -208,11 +230,15 @@ def _make_request(
|
|
|
208
230
|
try:
|
|
209
231
|
delegator = api_endpoints[namespace][endpoint]
|
|
210
232
|
except KeyError as e:
|
|
211
|
-
return _make_response(e, f"Unknown RPC Endpoint: {method}")
|
|
233
|
+
return _make_response(e, request_id, message=f"Unknown RPC Endpoint: {method}")
|
|
212
234
|
try:
|
|
213
235
|
response = delegator(ethereum_tester_instance, params)
|
|
214
236
|
except NotImplementedError as e:
|
|
215
|
-
return _make_response(
|
|
237
|
+
return _make_response(
|
|
238
|
+
e,
|
|
239
|
+
request_id,
|
|
240
|
+
message=f"RPC Endpoint has not been implemented: {method}",
|
|
241
|
+
)
|
|
216
242
|
except TransactionFailed as e:
|
|
217
243
|
first_arg = e.args[0]
|
|
218
244
|
try:
|
|
@@ -229,4 +255,4 @@ def _make_request(
|
|
|
229
255
|
reason = first_arg
|
|
230
256
|
raise TransactionFailed(f"execution reverted: {reason}")
|
|
231
257
|
else:
|
|
232
|
-
return _make_response(response)
|
|
258
|
+
return _make_response(response, request_id)
|
|
@@ -72,7 +72,9 @@ is_not_named_block = complement(is_named_block)
|
|
|
72
72
|
# --- Request Mapping --- #
|
|
73
73
|
|
|
74
74
|
TRANSACTION_REQUEST_KEY_MAPPING = {
|
|
75
|
+
"blobVersionedHashes": "blob_versioned_hashes",
|
|
75
76
|
"gasPrice": "gas_price",
|
|
77
|
+
"maxFeePerBlobGas": "max_fee_per_blob_gas",
|
|
76
78
|
"maxFeePerGas": "max_fee_per_gas",
|
|
77
79
|
"maxPriorityFeePerGas": "max_priority_fee_per_gas",
|
|
78
80
|
"accessList": "access_list",
|
|
@@ -90,7 +92,7 @@ TRANSACTION_REQUEST_FORMATTERS = {
|
|
|
90
92
|
"maxFeePerGas": to_integer_if_hex,
|
|
91
93
|
"maxPriorityFeePerGas": to_integer_if_hex,
|
|
92
94
|
"accessList": apply_list_to_array_formatter(
|
|
93
|
-
|
|
95
|
+
apply_key_map({"storageKeys": "storage_keys"})
|
|
94
96
|
),
|
|
95
97
|
}
|
|
96
98
|
transaction_request_formatter = apply_formatters_to_dict(TRANSACTION_REQUEST_FORMATTERS)
|
|
@@ -108,14 +110,14 @@ filter_request_remapper = apply_key_map(FILTER_REQUEST_KEY_MAPPING)
|
|
|
108
110
|
|
|
109
111
|
|
|
110
112
|
FILTER_REQUEST_FORMATTERS = {
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
+
"from_block": to_integer_if_hex,
|
|
114
|
+
"to_block": to_integer_if_hex,
|
|
113
115
|
}
|
|
114
116
|
filter_request_formatter = apply_formatters_to_dict(FILTER_REQUEST_FORMATTERS)
|
|
115
117
|
|
|
116
118
|
filter_request_transformer = compose(
|
|
117
|
-
filter_request_remapper,
|
|
118
119
|
filter_request_formatter,
|
|
120
|
+
filter_request_remapper,
|
|
119
121
|
)
|
|
120
122
|
|
|
121
123
|
|
|
@@ -123,10 +125,12 @@ filter_request_transformer = compose(
|
|
|
123
125
|
|
|
124
126
|
TRANSACTION_RESULT_KEY_MAPPING = {
|
|
125
127
|
"access_list": "accessList",
|
|
128
|
+
"blob_versioned_hashes": "blobVersionedHashes",
|
|
126
129
|
"block_hash": "blockHash",
|
|
127
130
|
"block_number": "blockNumber",
|
|
128
131
|
"chain_id": "chainId",
|
|
129
132
|
"gas_price": "gasPrice",
|
|
133
|
+
"max_fee_per_blob_gas": "maxFeePerBlobGas",
|
|
130
134
|
"max_fee_per_gas": "maxFeePerGas",
|
|
131
135
|
"max_priority_fee_per_gas": "maxPriorityFeePerGas",
|
|
132
136
|
"transaction_hash": "transactionHash",
|
|
@@ -164,6 +168,8 @@ RECEIPT_RESULT_KEY_MAPPING = {
|
|
|
164
168
|
"effective_gas_price": "effectiveGasPrice",
|
|
165
169
|
"transaction_hash": "transactionHash",
|
|
166
170
|
"transaction_index": "transactionIndex",
|
|
171
|
+
"blob_gas_used": "blobGasUsed",
|
|
172
|
+
"blob_gas_price": "blobGasPrice",
|
|
167
173
|
}
|
|
168
174
|
receipt_result_remapper = apply_key_map(RECEIPT_RESULT_KEY_MAPPING)
|
|
169
175
|
|
|
@@ -186,6 +192,9 @@ BLOCK_RESULT_KEY_MAPPING = {
|
|
|
186
192
|
# JSON-RPC spec still says miner
|
|
187
193
|
"coinbase": "miner",
|
|
188
194
|
"withdrawals_root": "withdrawalsRoot",
|
|
195
|
+
"parent_beacon_block_root": "parentBeaconBlockRoot",
|
|
196
|
+
"blob_gas_used": "blobGasUsed",
|
|
197
|
+
"excess_blob_gas": "excessBlobGas",
|
|
189
198
|
}
|
|
190
199
|
block_result_remapper = apply_key_map(BLOCK_RESULT_KEY_MAPPING)
|
|
191
200
|
|
|
@@ -276,11 +285,6 @@ request_formatters = {
|
|
|
276
285
|
),
|
|
277
286
|
# EVM
|
|
278
287
|
RPCEndpoint("evm_revert"): apply_formatters_to_args(hex_to_integer),
|
|
279
|
-
# Personal
|
|
280
|
-
RPCEndpoint("personal_sendTransaction"): apply_formatters_to_args(
|
|
281
|
-
transaction_request_transformer,
|
|
282
|
-
identity,
|
|
283
|
-
),
|
|
284
288
|
}
|
|
285
289
|
|
|
286
290
|
result_formatters: Optional[Dict[RPCEndpoint, Callable[..., Any]]] = {
|
web3/providers/ipc.py
CHANGED
|
@@ -26,6 +26,10 @@ from web3.types import (
|
|
|
26
26
|
RPCResponse,
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
+
from ..exceptions import (
|
|
30
|
+
Web3TypeError,
|
|
31
|
+
Web3ValueError,
|
|
32
|
+
)
|
|
29
33
|
from .base import (
|
|
30
34
|
JSONBaseProvider,
|
|
31
35
|
)
|
|
@@ -96,7 +100,7 @@ def get_default_ipc_path() -> str:
|
|
|
96
100
|
return r"\\.\pipe\geth.ipc"
|
|
97
101
|
|
|
98
102
|
else:
|
|
99
|
-
raise
|
|
103
|
+
raise Web3ValueError(
|
|
100
104
|
f"Unsupported platform '{sys.platform}'. Only darwin/linux/win32/"
|
|
101
105
|
"freebsd are supported. You must specify the ipc_path"
|
|
102
106
|
)
|
|
@@ -117,7 +121,7 @@ def get_dev_ipc_path() -> str:
|
|
|
117
121
|
return r"\\.\pipe\geth.ipc"
|
|
118
122
|
|
|
119
123
|
else:
|
|
120
|
-
raise
|
|
124
|
+
raise Web3ValueError(
|
|
121
125
|
f"Unsupported platform '{sys.platform}'. Only darwin/linux/win32/"
|
|
122
126
|
"freebsd are supported. You must specify the ipc_path"
|
|
123
127
|
)
|
|
@@ -139,7 +143,7 @@ class IPCProvider(JSONBaseProvider):
|
|
|
139
143
|
elif isinstance(ipc_path, str) or isinstance(ipc_path, Path):
|
|
140
144
|
self.ipc_path = str(Path(ipc_path).expanduser().resolve())
|
|
141
145
|
else:
|
|
142
|
-
raise
|
|
146
|
+
raise Web3TypeError("ipc_path must be of type string or pathlib.Path")
|
|
143
147
|
|
|
144
148
|
self.timeout = timeout
|
|
145
149
|
self._lock = threading.Lock()
|
|
@@ -33,6 +33,7 @@ from ..._utils.caching import (
|
|
|
33
33
|
)
|
|
34
34
|
from ...exceptions import (
|
|
35
35
|
ProviderConnectionError,
|
|
36
|
+
Web3TypeError,
|
|
36
37
|
)
|
|
37
38
|
from ..ipc import (
|
|
38
39
|
get_default_ipc_path,
|
|
@@ -71,7 +72,7 @@ class AsyncIPCProvider(PersistentConnectionProvider):
|
|
|
71
72
|
elif isinstance(ipc_path, str) or isinstance(ipc_path, Path):
|
|
72
73
|
self.ipc_path = str(Path(ipc_path).expanduser().resolve())
|
|
73
74
|
else:
|
|
74
|
-
raise
|
|
75
|
+
raise Web3TypeError("ipc_path must be of type string or pathlib.Path")
|
|
75
76
|
|
|
76
77
|
self._max_connection_retries = max_connection_retries
|
|
77
78
|
super().__init__(**kwargs)
|
|
@@ -91,7 +92,7 @@ class AsyncIPCProvider(PersistentConnectionProvider):
|
|
|
91
92
|
current_request_id = json.loads(request_data)["id"]
|
|
92
93
|
await self._get_response_for_request_id(current_request_id, timeout=2)
|
|
93
94
|
return True
|
|
94
|
-
except (OSError,
|
|
95
|
+
except (OSError, ProviderConnectionError) as e:
|
|
95
96
|
if show_traceback:
|
|
96
97
|
raise ProviderConnectionError(
|
|
97
98
|
f"Problem connecting to provider with error: {type(e)}: {e}"
|
|
@@ -114,11 +115,11 @@ class AsyncIPCProvider(PersistentConnectionProvider):
|
|
|
114
115
|
except OSError as e:
|
|
115
116
|
if _connection_attempts == self._max_connection_retries:
|
|
116
117
|
raise ProviderConnectionError(
|
|
117
|
-
f"Could not connect to
|
|
118
|
+
f"Could not connect to: {self.ipc_path}. "
|
|
118
119
|
f"Retries exceeded max of {self._max_connection_retries}."
|
|
119
120
|
) from e
|
|
120
121
|
self.logger.info(
|
|
121
|
-
f"Could not connect to
|
|
122
|
+
f"Could not connect to: {self.ipc_path}. Retrying in "
|
|
122
123
|
f"{round(_backoff_time, 1)} seconds.",
|
|
123
124
|
exc_info=True,
|
|
124
125
|
)
|
|
@@ -130,9 +131,7 @@ class AsyncIPCProvider(PersistentConnectionProvider):
|
|
|
130
131
|
self._writer.close()
|
|
131
132
|
await self._writer.wait_closed()
|
|
132
133
|
self._writer = None
|
|
133
|
-
self.logger.debug(
|
|
134
|
-
f'Successfully disconnected from endpoint: "{self.endpoint_uri}'
|
|
135
|
-
)
|
|
134
|
+
self.logger.debug(f'Successfully disconnected from : "{self.ipc_path}')
|
|
136
135
|
|
|
137
136
|
try:
|
|
138
137
|
self._message_listener_task.cancel()
|
|
@@ -30,7 +30,6 @@ DEFAULT_PERSISTENT_CONNECTION_TIMEOUT = 30.0
|
|
|
30
30
|
class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
|
|
31
31
|
logger = logging.getLogger("web3.providers.PersistentConnectionProvider")
|
|
32
32
|
has_persistent_connection = True
|
|
33
|
-
endpoint_uri: Optional[str] = None
|
|
34
33
|
|
|
35
34
|
_request_processor: RequestProcessor
|
|
36
35
|
_message_listener_task: Optional["asyncio.Task[None]"] = None
|
|
@@ -50,6 +49,17 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
|
|
|
50
49
|
self.request_timeout = request_timeout
|
|
51
50
|
self.silence_listener_task_exceptions = silence_listener_task_exceptions
|
|
52
51
|
|
|
52
|
+
def get_endpoint_uri_or_ipc_path(self) -> str:
|
|
53
|
+
if hasattr(self, "endpoint_uri"):
|
|
54
|
+
return str(self.endpoint_uri)
|
|
55
|
+
elif hasattr(self, "ipc_path"):
|
|
56
|
+
return str(self.ipc_path)
|
|
57
|
+
else:
|
|
58
|
+
raise AttributeError(
|
|
59
|
+
"`PersistentConnectionProvider` must have either `endpoint_uri` or "
|
|
60
|
+
"`ipc_path` attribute."
|
|
61
|
+
)
|
|
62
|
+
|
|
53
63
|
async def connect(self) -> None:
|
|
54
64
|
raise NotImplementedError("Must be implemented by subclasses")
|
|
55
65
|
|
|
@@ -15,6 +15,9 @@ from web3._utils.caching import (
|
|
|
15
15
|
RequestInformation,
|
|
16
16
|
generate_cache_key,
|
|
17
17
|
)
|
|
18
|
+
from web3.exceptions import (
|
|
19
|
+
Web3ValueError,
|
|
20
|
+
)
|
|
18
21
|
from web3.types import (
|
|
19
22
|
RPCEndpoint,
|
|
20
23
|
RPCResponse,
|
|
@@ -136,9 +139,9 @@ class RequestProcessor:
|
|
|
136
139
|
) -> RequestInformation:
|
|
137
140
|
if "method" in response and response["method"] == "eth_subscription":
|
|
138
141
|
if "params" not in response:
|
|
139
|
-
raise
|
|
142
|
+
raise Web3ValueError("Subscription response must have params field")
|
|
140
143
|
if "subscription" not in response["params"]:
|
|
141
|
-
raise
|
|
144
|
+
raise Web3ValueError(
|
|
142
145
|
"Subscription response params must have subscription field"
|
|
143
146
|
)
|
|
144
147
|
|
|
@@ -266,7 +269,7 @@ class RequestProcessor:
|
|
|
266
269
|
)
|
|
267
270
|
else:
|
|
268
271
|
if not cache_key:
|
|
269
|
-
raise
|
|
272
|
+
raise Web3ValueError(
|
|
270
273
|
"Must provide cache key when popping a non-subscription response."
|
|
271
274
|
)
|
|
272
275
|
|
|
@@ -283,10 +286,7 @@ class RequestProcessor:
|
|
|
283
286
|
# request processor class methods
|
|
284
287
|
|
|
285
288
|
def clear_caches(self) -> None:
|
|
286
|
-
"""
|
|
287
|
-
Clear the request processor caches.
|
|
288
|
-
"""
|
|
289
|
-
|
|
289
|
+
"""Clear the request processor caches."""
|
|
290
290
|
self._request_information_cache.clear()
|
|
291
291
|
self._request_response_cache.clear()
|
|
292
292
|
self._subscription_response_queue = asyncio.Queue(
|
|
@@ -71,9 +71,9 @@ class WebSocketProvider(PersistentConnectionProvider):
|
|
|
71
71
|
# `PersistentConnectionProvider` kwargs can be passed through
|
|
72
72
|
**kwargs: Any,
|
|
73
73
|
) -> None:
|
|
74
|
-
self.endpoint_uri =
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
self.endpoint_uri = (
|
|
75
|
+
URI(endpoint_uri) if endpoint_uri is not None else get_default_endpoint()
|
|
76
|
+
)
|
|
77
77
|
|
|
78
78
|
if not any(
|
|
79
79
|
self.endpoint_uri.startswith(prefix)
|
web3/providers/rpc/async_rpc.py
CHANGED
|
@@ -20,6 +20,10 @@ from eth_utils import (
|
|
|
20
20
|
to_dict,
|
|
21
21
|
)
|
|
22
22
|
|
|
23
|
+
from web3._utils.empty import (
|
|
24
|
+
Empty,
|
|
25
|
+
empty,
|
|
26
|
+
)
|
|
23
27
|
from web3._utils.http import (
|
|
24
28
|
construct_user_agent,
|
|
25
29
|
)
|
|
@@ -54,9 +58,9 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
|
|
|
54
58
|
self,
|
|
55
59
|
endpoint_uri: Optional[Union[URI, str]] = None,
|
|
56
60
|
request_kwargs: Optional[Any] = None,
|
|
57
|
-
exception_retry_configuration:
|
|
58
|
-
ExceptionRetryConfiguration
|
|
59
|
-
] =
|
|
61
|
+
exception_retry_configuration: Union[
|
|
62
|
+
ExceptionRetryConfiguration, Empty
|
|
63
|
+
] = empty,
|
|
60
64
|
) -> None:
|
|
61
65
|
if endpoint_uri is None:
|
|
62
66
|
self.endpoint_uri = get_default_http_endpoint()
|
|
@@ -64,7 +68,7 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
|
|
|
64
68
|
self.endpoint_uri = URI(endpoint_uri)
|
|
65
69
|
|
|
66
70
|
self._request_kwargs = request_kwargs or {}
|
|
67
|
-
self.
|
|
71
|
+
self._exception_retry_configuration = exception_retry_configuration
|
|
68
72
|
|
|
69
73
|
super().__init__()
|
|
70
74
|
|
|
@@ -74,12 +78,25 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
|
|
|
74
78
|
def __str__(self) -> str:
|
|
75
79
|
return f"RPC connection {self.endpoint_uri}"
|
|
76
80
|
|
|
81
|
+
@property
|
|
82
|
+
def exception_retry_configuration(self) -> ExceptionRetryConfiguration:
|
|
83
|
+
if isinstance(self._exception_retry_configuration, Empty):
|
|
84
|
+
self._exception_retry_configuration = ExceptionRetryConfiguration(
|
|
85
|
+
errors=(ClientError, TimeoutError)
|
|
86
|
+
)
|
|
87
|
+
return self._exception_retry_configuration
|
|
88
|
+
|
|
89
|
+
@exception_retry_configuration.setter
|
|
90
|
+
def exception_retry_configuration(
|
|
91
|
+
self, value: Union[ExceptionRetryConfiguration, Empty]
|
|
92
|
+
) -> None:
|
|
93
|
+
self._exception_retry_configuration = value
|
|
94
|
+
|
|
77
95
|
@to_dict
|
|
78
96
|
def get_request_kwargs(self) -> Iterable[Tuple[str, Any]]:
|
|
79
97
|
if "headers" not in self._request_kwargs:
|
|
80
98
|
yield "headers", self.get_request_headers()
|
|
81
|
-
|
|
82
|
-
yield key, value
|
|
99
|
+
yield from self._request_kwargs.items()
|
|
83
100
|
|
|
84
101
|
def get_request_headers(self) -> Dict[str, str]:
|
|
85
102
|
return {
|
|
@@ -106,7 +123,7 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
|
|
|
106
123
|
except tuple(self.exception_retry_configuration.errors):
|
|
107
124
|
if i < self.exception_retry_configuration.retries - 1:
|
|
108
125
|
await asyncio.sleep(
|
|
109
|
-
self.exception_retry_configuration.backoff_factor
|
|
126
|
+
self.exception_retry_configuration.backoff_factor * 2**i
|
|
110
127
|
)
|
|
111
128
|
continue
|
|
112
129
|
else:
|
web3/providers/rpc/rpc.py
CHANGED
|
@@ -18,6 +18,10 @@ from eth_utils import (
|
|
|
18
18
|
)
|
|
19
19
|
import requests
|
|
20
20
|
|
|
21
|
+
from web3._utils.empty import (
|
|
22
|
+
Empty,
|
|
23
|
+
empty,
|
|
24
|
+
)
|
|
21
25
|
from web3._utils.http import (
|
|
22
26
|
construct_user_agent,
|
|
23
27
|
)
|
|
@@ -51,26 +55,16 @@ if TYPE_CHECKING:
|
|
|
51
55
|
class HTTPProvider(JSONBaseProvider):
|
|
52
56
|
logger = logging.getLogger("web3.providers.HTTPProvider")
|
|
53
57
|
endpoint_uri = None
|
|
54
|
-
|
|
55
|
-
_request_args = None
|
|
56
58
|
_request_kwargs = None
|
|
57
59
|
|
|
58
|
-
exception_retry_configuration: Optional[ExceptionRetryConfiguration] = None
|
|
59
|
-
|
|
60
60
|
def __init__(
|
|
61
61
|
self,
|
|
62
62
|
endpoint_uri: Optional[Union[URI, str]] = None,
|
|
63
63
|
request_kwargs: Optional[Any] = None,
|
|
64
64
|
session: Optional[Any] = None,
|
|
65
|
-
exception_retry_configuration:
|
|
66
|
-
ExceptionRetryConfiguration
|
|
67
|
-
|
|
68
|
-
ConnectionError,
|
|
69
|
-
requests.HTTPError,
|
|
70
|
-
requests.Timeout,
|
|
71
|
-
)
|
|
72
|
-
)
|
|
73
|
-
),
|
|
65
|
+
exception_retry_configuration: Union[
|
|
66
|
+
ExceptionRetryConfiguration, Empty
|
|
67
|
+
] = empty,
|
|
74
68
|
) -> None:
|
|
75
69
|
if endpoint_uri is None:
|
|
76
70
|
self.endpoint_uri = get_default_http_endpoint()
|
|
@@ -78,7 +72,7 @@ class HTTPProvider(JSONBaseProvider):
|
|
|
78
72
|
self.endpoint_uri = URI(endpoint_uri)
|
|
79
73
|
|
|
80
74
|
self._request_kwargs = request_kwargs or {}
|
|
81
|
-
self.
|
|
75
|
+
self._exception_retry_configuration = exception_retry_configuration
|
|
82
76
|
|
|
83
77
|
if session:
|
|
84
78
|
cache_and_return_session(self.endpoint_uri, session)
|
|
@@ -88,12 +82,29 @@ class HTTPProvider(JSONBaseProvider):
|
|
|
88
82
|
def __str__(self) -> str:
|
|
89
83
|
return f"RPC connection {self.endpoint_uri}"
|
|
90
84
|
|
|
85
|
+
@property
|
|
86
|
+
def exception_retry_configuration(self) -> ExceptionRetryConfiguration:
|
|
87
|
+
if isinstance(self._exception_retry_configuration, Empty):
|
|
88
|
+
self._exception_retry_configuration = ExceptionRetryConfiguration(
|
|
89
|
+
errors=(
|
|
90
|
+
ConnectionError,
|
|
91
|
+
requests.HTTPError,
|
|
92
|
+
requests.Timeout,
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
return self._exception_retry_configuration
|
|
96
|
+
|
|
97
|
+
@exception_retry_configuration.setter
|
|
98
|
+
def exception_retry_configuration(
|
|
99
|
+
self, value: Union[ExceptionRetryConfiguration, Empty]
|
|
100
|
+
) -> None:
|
|
101
|
+
self._exception_retry_configuration = value
|
|
102
|
+
|
|
91
103
|
@to_dict
|
|
92
104
|
def get_request_kwargs(self) -> Iterable[Tuple[str, Any]]:
|
|
93
105
|
if "headers" not in self._request_kwargs:
|
|
94
106
|
yield "headers", self.get_request_headers()
|
|
95
|
-
|
|
96
|
-
yield key, value
|
|
107
|
+
yield from self._request_kwargs.items()
|
|
97
108
|
|
|
98
109
|
def get_request_headers(self) -> Dict[str, str]:
|
|
99
110
|
return {
|
|
@@ -119,7 +130,9 @@ class HTTPProvider(JSONBaseProvider):
|
|
|
119
130
|
)
|
|
120
131
|
except tuple(self.exception_retry_configuration.errors) as e:
|
|
121
132
|
if i < self.exception_retry_configuration.retries - 1:
|
|
122
|
-
time.sleep(
|
|
133
|
+
time.sleep(
|
|
134
|
+
self.exception_retry_configuration.backoff_factor * 2**i
|
|
135
|
+
)
|
|
123
136
|
continue
|
|
124
137
|
else:
|
|
125
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/testing.py
CHANGED
|
@@ -12,21 +12,21 @@ from web3.module import (
|
|
|
12
12
|
|
|
13
13
|
class Testing(Module):
|
|
14
14
|
def timeTravel(self, timestamp: int) -> None:
|
|
15
|
-
|
|
15
|
+
self.w3.manager.request_blocking(RPC.testing_timeTravel, [timestamp])
|
|
16
16
|
|
|
17
17
|
def mine(self, num_blocks: int = 1) -> None:
|
|
18
|
-
|
|
18
|
+
self.w3.manager.request_blocking(RPC.evm_mine, [num_blocks])
|
|
19
19
|
|
|
20
20
|
def snapshot(self) -> int:
|
|
21
21
|
self.last_snapshot_idx = self.w3.manager.request_blocking(RPC.evm_snapshot, [])
|
|
22
22
|
return self.last_snapshot_idx
|
|
23
23
|
|
|
24
24
|
def reset(self) -> None:
|
|
25
|
-
|
|
25
|
+
self.w3.manager.request_blocking(RPC.evm_reset, [])
|
|
26
26
|
|
|
27
27
|
def revert(self, snapshot_idx: Optional[int] = None) -> None:
|
|
28
28
|
if snapshot_idx is None:
|
|
29
29
|
revert_target = self.last_snapshot_idx
|
|
30
30
|
else:
|
|
31
31
|
revert_target = snapshot_idx
|
|
32
|
-
|
|
32
|
+
self.w3.manager.request_blocking(RPC.evm_revert, [revert_target])
|