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
|
@@ -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)
|
|
@@ -59,7 +59,7 @@ if TYPE_CHECKING:
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
def is_named_block(value: Any) -> bool:
|
|
62
|
-
return value in {"latest", "earliest", "
|
|
62
|
+
return value in {"latest", "earliest", "safe", "finalized"}
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
def is_hexstr(value: Any) -> bool:
|
|
@@ -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]]] = {
|
|
@@ -330,9 +334,7 @@ result_formatters: Optional[Dict[RPCEndpoint, Callable[..., Any]]] = {
|
|
|
330
334
|
|
|
331
335
|
|
|
332
336
|
def guess_from(w3: "Web3", _: TxParams) -> ChecksumAddress:
|
|
333
|
-
if w3.eth.
|
|
334
|
-
return w3.eth.coinbase
|
|
335
|
-
elif w3.eth.accounts and len(w3.eth.accounts) > 0:
|
|
337
|
+
if w3.eth.accounts and len(w3.eth.accounts) > 0:
|
|
336
338
|
return w3.eth.accounts[0]
|
|
337
339
|
|
|
338
340
|
return None
|
|
@@ -356,11 +358,8 @@ def fill_default(
|
|
|
356
358
|
async def async_guess_from(
|
|
357
359
|
async_w3: "AsyncWeb3", _: TxParams
|
|
358
360
|
) -> Optional[ChecksumAddress]:
|
|
359
|
-
coinbase = await async_w3.eth.coinbase
|
|
360
361
|
accounts = await async_w3.eth.accounts
|
|
361
|
-
if
|
|
362
|
-
return coinbase
|
|
363
|
-
elif accounts is not None and len(accounts) > 0:
|
|
362
|
+
if accounts is not None and len(accounts) > 0:
|
|
364
363
|
return accounts[0]
|
|
365
364
|
return None
|
|
366
365
|
|
web3/providers/ipc.py
CHANGED
|
@@ -14,8 +14,11 @@ from types import (
|
|
|
14
14
|
)
|
|
15
15
|
from typing import (
|
|
16
16
|
Any,
|
|
17
|
+
List,
|
|
18
|
+
Tuple,
|
|
17
19
|
Type,
|
|
18
20
|
Union,
|
|
21
|
+
cast,
|
|
19
22
|
)
|
|
20
23
|
|
|
21
24
|
from web3._utils.threads import (
|
|
@@ -26,6 +29,16 @@ from web3.types import (
|
|
|
26
29
|
RPCResponse,
|
|
27
30
|
)
|
|
28
31
|
|
|
32
|
+
from .._utils.batching import (
|
|
33
|
+
sort_batch_response_by_response_ids,
|
|
34
|
+
)
|
|
35
|
+
from .._utils.caching import (
|
|
36
|
+
handle_request_caching,
|
|
37
|
+
)
|
|
38
|
+
from ..exceptions import (
|
|
39
|
+
Web3TypeError,
|
|
40
|
+
Web3ValueError,
|
|
41
|
+
)
|
|
29
42
|
from .base import (
|
|
30
43
|
JSONBaseProvider,
|
|
31
44
|
)
|
|
@@ -96,28 +109,29 @@ def get_default_ipc_path() -> str:
|
|
|
96
109
|
return r"\\.\pipe\geth.ipc"
|
|
97
110
|
|
|
98
111
|
else:
|
|
99
|
-
raise
|
|
112
|
+
raise Web3ValueError(
|
|
100
113
|
f"Unsupported platform '{sys.platform}'. Only darwin/linux/win32/"
|
|
101
114
|
"freebsd are supported. You must specify the ipc_path"
|
|
102
115
|
)
|
|
103
116
|
|
|
104
117
|
|
|
105
118
|
def get_dev_ipc_path() -> str:
|
|
106
|
-
|
|
107
|
-
|
|
119
|
+
web3_provider_uri = os.environ.get("WEB3_PROVIDER_URI", "")
|
|
120
|
+
if web3_provider_uri and "geth.ipc" in web3_provider_uri:
|
|
121
|
+
return web3_provider_uri
|
|
108
122
|
|
|
109
|
-
elif sys.platform == "darwin":
|
|
110
|
-
tmpdir = os.environ.get("TMPDIR", "")
|
|
123
|
+
elif sys.platform == "darwin" or sys.platform.startswith("linux"):
|
|
124
|
+
tmpdir = os.environ.get("TMPDIR", "/tmp")
|
|
111
125
|
return os.path.expanduser(os.path.join(tmpdir, "geth.ipc"))
|
|
112
126
|
|
|
113
|
-
elif sys.platform.
|
|
127
|
+
elif sys.platform.endswith("freebsd"):
|
|
114
128
|
return os.path.expanduser(os.path.join("/tmp", "geth.ipc"))
|
|
115
129
|
|
|
116
130
|
elif sys.platform == "win32":
|
|
117
131
|
return r"\\.\pipe\geth.ipc"
|
|
118
132
|
|
|
119
133
|
else:
|
|
120
|
-
raise
|
|
134
|
+
raise Web3ValueError(
|
|
121
135
|
f"Unsupported platform '{sys.platform}'. Only darwin/linux/win32/"
|
|
122
136
|
"freebsd are supported. You must specify the ipc_path"
|
|
123
137
|
)
|
|
@@ -131,33 +145,27 @@ class IPCProvider(JSONBaseProvider):
|
|
|
131
145
|
self,
|
|
132
146
|
ipc_path: Union[str, Path] = None,
|
|
133
147
|
timeout: int = 30,
|
|
134
|
-
*args: Any,
|
|
135
148
|
**kwargs: Any,
|
|
136
149
|
) -> None:
|
|
150
|
+
super().__init__(**kwargs)
|
|
137
151
|
if ipc_path is None:
|
|
138
152
|
self.ipc_path = get_default_ipc_path()
|
|
139
153
|
elif isinstance(ipc_path, str) or isinstance(ipc_path, Path):
|
|
140
154
|
self.ipc_path = str(Path(ipc_path).expanduser().resolve())
|
|
141
155
|
else:
|
|
142
|
-
raise
|
|
156
|
+
raise Web3TypeError("ipc_path must be of type string or pathlib.Path")
|
|
143
157
|
|
|
144
158
|
self.timeout = timeout
|
|
145
159
|
self._lock = threading.Lock()
|
|
146
160
|
self._socket = PersistantSocket(self.ipc_path)
|
|
147
|
-
super().__init__()
|
|
148
161
|
|
|
149
162
|
def __str__(self) -> str:
|
|
150
163
|
return f"<{self.__class__.__name__} {self.ipc_path}>"
|
|
151
164
|
|
|
152
|
-
def
|
|
153
|
-
self.logger.debug(
|
|
154
|
-
f"Making request IPC. Path: {self.ipc_path}, Method: {method}"
|
|
155
|
-
)
|
|
156
|
-
request = self.encode_rpc_request(method, params)
|
|
157
|
-
|
|
165
|
+
def _make_request(self, request: bytes) -> RPCResponse:
|
|
158
166
|
with self._lock, self._socket as sock:
|
|
159
167
|
try:
|
|
160
|
-
sock.sendall(request)
|
|
168
|
+
sock.sendall(request + b"\n")
|
|
161
169
|
except BrokenPipeError:
|
|
162
170
|
# one extra attempt, then give up
|
|
163
171
|
sock = self._socket.reset()
|
|
@@ -185,6 +193,22 @@ class IPCProvider(JSONBaseProvider):
|
|
|
185
193
|
timeout.sleep(0)
|
|
186
194
|
continue
|
|
187
195
|
|
|
196
|
+
@handle_request_caching
|
|
197
|
+
def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
198
|
+
self.logger.debug(
|
|
199
|
+
f"Making request IPC. Path: {self.ipc_path}, Method: {method}"
|
|
200
|
+
)
|
|
201
|
+
request = self.encode_rpc_request(method, params)
|
|
202
|
+
return self._make_request(request)
|
|
203
|
+
|
|
204
|
+
def make_batch_request(
|
|
205
|
+
self, requests: List[Tuple[RPCEndpoint, Any]]
|
|
206
|
+
) -> List[RPCResponse]:
|
|
207
|
+
self.logger.debug(f"Making batch request IPC. Path: {self.ipc_path}")
|
|
208
|
+
request_data = self.encode_batch_rpc_request(requests)
|
|
209
|
+
response = cast(List[RPCResponse], self._make_request(request_data))
|
|
210
|
+
return sort_batch_response_by_response_ids(response)
|
|
211
|
+
|
|
188
212
|
|
|
189
213
|
# A valid JSON RPC response can only end in } or ] http://www.jsonrpc.org/specification
|
|
190
214
|
def has_valid_json_rpc_ending(raw_response: bytes) -> bool:
|
|
@@ -10,9 +10,12 @@ from types import (
|
|
|
10
10
|
)
|
|
11
11
|
from typing import (
|
|
12
12
|
Any,
|
|
13
|
+
List,
|
|
13
14
|
Optional,
|
|
15
|
+
Tuple,
|
|
14
16
|
Type,
|
|
15
17
|
Union,
|
|
18
|
+
cast,
|
|
16
19
|
)
|
|
17
20
|
|
|
18
21
|
from eth_typing import (
|
|
@@ -25,6 +28,12 @@ from websockets.legacy.client import (
|
|
|
25
28
|
WebSocketClientProtocol,
|
|
26
29
|
)
|
|
27
30
|
|
|
31
|
+
from web3._utils.batching import (
|
|
32
|
+
sort_batch_response_by_response_ids,
|
|
33
|
+
)
|
|
34
|
+
from web3._utils.caching import (
|
|
35
|
+
handle_request_caching,
|
|
36
|
+
)
|
|
28
37
|
from web3.exceptions import (
|
|
29
38
|
Web3ValidationError,
|
|
30
39
|
)
|
|
@@ -91,7 +100,9 @@ class LegacyWebSocketProvider(JSONBaseProvider):
|
|
|
91
100
|
endpoint_uri: Optional[Union[URI, str]] = None,
|
|
92
101
|
websocket_kwargs: Optional[Any] = None,
|
|
93
102
|
websocket_timeout: int = DEFAULT_WEBSOCKET_TIMEOUT,
|
|
103
|
+
**kwargs: Any,
|
|
94
104
|
) -> None:
|
|
105
|
+
super().__init__(**kwargs)
|
|
95
106
|
self.endpoint_uri = URI(endpoint_uri)
|
|
96
107
|
self.websocket_timeout = websocket_timeout
|
|
97
108
|
if self.endpoint_uri is None:
|
|
@@ -110,7 +121,6 @@ class LegacyWebSocketProvider(JSONBaseProvider):
|
|
|
110
121
|
f"in websocket_kwargs, found: {found_restricted_keys}"
|
|
111
122
|
)
|
|
112
123
|
self.conn = PersistentWebSocket(self.endpoint_uri, websocket_kwargs)
|
|
113
|
-
super().__init__()
|
|
114
124
|
|
|
115
125
|
def __str__(self) -> str:
|
|
116
126
|
return f"WS connection {self.endpoint_uri}"
|
|
@@ -124,6 +134,7 @@ class LegacyWebSocketProvider(JSONBaseProvider):
|
|
|
124
134
|
await asyncio.wait_for(conn.recv(), timeout=self.websocket_timeout)
|
|
125
135
|
)
|
|
126
136
|
|
|
137
|
+
@handle_request_caching
|
|
127
138
|
def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
128
139
|
self.logger.debug(
|
|
129
140
|
f"Making request WebSocket. URI: {self.endpoint_uri}, " f"Method: {method}"
|
|
@@ -133,3 +144,17 @@ class LegacyWebSocketProvider(JSONBaseProvider):
|
|
|
133
144
|
self.coro_make_request(request_data), LegacyWebSocketProvider._loop
|
|
134
145
|
)
|
|
135
146
|
return future.result()
|
|
147
|
+
|
|
148
|
+
def make_batch_request(
|
|
149
|
+
self, requests: List[Tuple[RPCEndpoint, Any]]
|
|
150
|
+
) -> List[RPCResponse]:
|
|
151
|
+
self.logger.debug(
|
|
152
|
+
f"Making batch request WebSocket. URI: {self.endpoint_uri}, "
|
|
153
|
+
f"Methods: {requests}"
|
|
154
|
+
)
|
|
155
|
+
request_data = self.encode_batch_rpc_request(requests)
|
|
156
|
+
future = asyncio.run_coroutine_threadsafe(
|
|
157
|
+
self.coro_make_request(request_data), LegacyWebSocketProvider._loop
|
|
158
|
+
)
|
|
159
|
+
response = cast(List[RPCResponse], future.result())
|
|
160
|
+
return sort_batch_response_by_response_ids(response)
|