web3 6.20.2__py3-none-any.whl → 7.0.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 +2 -17
- ens/async_ens.py +33 -21
- ens/base_ens.py +3 -1
- ens/ens.py +16 -11
- ens/exceptions.py +16 -29
- ens/specs/nf.json +1 -1
- ens/specs/normalization_spec.json +1 -1
- ens/utils.py +52 -63
- web3/__init__.py +20 -24
- web3/_utils/abi.py +115 -271
- web3/_utils/async_transactions.py +7 -4
- web3/_utils/batching.py +217 -0
- web3/_utils/blocks.py +6 -2
- web3/_utils/caching.py +128 -5
- web3/_utils/compat/__init__.py +2 -3
- web3/_utils/contract_sources/compile_contracts.py +1 -1
- 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 +5 -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 +130 -236
- web3/_utils/datatypes.py +5 -1
- web3/_utils/decorators.py +13 -23
- web3/_utils/empty.py +1 -1
- web3/_utils/encoding.py +16 -12
- web3/_utils/ens.py +2 -1
- web3/_utils/error_formatters_utils.py +5 -3
- web3/_utils/events.py +66 -69
- web3/_utils/fee_utils.py +1 -3
- web3/_utils/filters.py +24 -22
- web3/_utils/formatters.py +2 -2
- web3/_utils/http.py +5 -3
- web3/_utils/http_session_manager.py +303 -0
- web3/_utils/math.py +14 -15
- web3/_utils/method_formatters.py +34 -36
- web3/_utils/module.py +2 -1
- web3/_utils/module_testing/__init__.py +0 -3
- web3/_utils/module_testing/eth_module.py +695 -643
- web3/_utils/module_testing/module_testing_utils.py +61 -34
- web3/_utils/module_testing/persistent_connection_provider.py +56 -25
- web3/_utils/module_testing/utils.py +258 -0
- web3/_utils/module_testing/web3_module.py +438 -17
- web3/_utils/normalizers.py +13 -11
- web3/_utils/rpc_abi.py +5 -32
- web3/_utils/threads.py +8 -7
- web3/_utils/transactions.py +14 -12
- web3/_utils/type_conversion.py +5 -1
- web3/_utils/validation.py +17 -17
- web3/auto/gethdev.py +7 -2
- web3/beacon/__init__.py +6 -1
- web3/beacon/async_beacon.py +9 -5
- web3/beacon/{main.py → beacon.py} +7 -5
- web3/contract/__init__.py +7 -0
- web3/contract/async_contract.py +47 -46
- web3/contract/base_contract.py +183 -158
- web3/contract/contract.py +49 -43
- web3/contract/utils.py +203 -59
- web3/datastructures.py +79 -31
- web3/eth/__init__.py +7 -0
- web3/eth/async_eth.py +39 -51
- web3/eth/base_eth.py +17 -10
- web3/eth/eth.py +30 -68
- web3/exceptions.py +108 -82
- web3/gas_strategies/time_based.py +8 -6
- web3/geth.py +1 -254
- web3/main.py +75 -122
- web3/manager.py +316 -146
- web3/method.py +38 -31
- web3/middleware/__init__.py +67 -89
- web3/middleware/attrdict.py +36 -49
- web3/middleware/base.py +174 -0
- web3/middleware/buffered_gas_estimate.py +20 -21
- web3/middleware/filter.py +157 -117
- web3/middleware/formatting.py +124 -108
- web3/middleware/gas_price_strategy.py +20 -32
- web3/middleware/names.py +29 -26
- web3/middleware/proof_of_authority.py +68 -0
- web3/middleware/pythonic.py +2 -2
- web3/middleware/signing.py +74 -89
- web3/middleware/stalecheck.py +52 -79
- web3/middleware/validation.py +5 -13
- web3/module.py +54 -10
- web3/providers/__init__.py +10 -6
- web3/providers/async_base.py +117 -39
- web3/providers/auto.py +3 -3
- web3/providers/base.py +89 -33
- web3/providers/eth_tester/__init__.py +5 -0
- web3/providers/eth_tester/defaults.py +1 -64
- web3/providers/eth_tester/main.py +99 -31
- web3/providers/eth_tester/middleware.py +45 -73
- web3/providers/ipc.py +42 -46
- web3/providers/{websocket/websocket.py → legacy_websocket.py} +32 -7
- web3/providers/persistent/__init__.py +22 -0
- web3/providers/persistent/async_ipc.py +153 -0
- web3/providers/{persistent.py → persistent/persistent.py} +106 -25
- web3/providers/persistent/persistent_connection.py +84 -0
- web3/providers/{websocket → persistent}/request_processor.py +94 -32
- web3/providers/persistent/utils.py +43 -0
- web3/providers/{websocket/websocket_v2.py → persistent/websocket.py} +29 -28
- web3/providers/rpc/__init__.py +11 -0
- web3/providers/rpc/async_rpc.py +171 -0
- web3/providers/rpc/rpc.py +179 -0
- web3/providers/rpc/utils.py +92 -0
- web3/testing.py +4 -4
- web3/tools/benchmark/main.py +22 -22
- web3/tools/benchmark/node.py +2 -8
- web3/tools/benchmark/reporting.py +2 -2
- web3/tools/benchmark/utils.py +1 -1
- web3/tracing.py +9 -5
- web3/types.py +30 -107
- web3/utils/__init__.py +58 -5
- web3/utils/abi.py +575 -10
- web3/utils/async_exception_handling.py +19 -7
- web3/utils/caching.py +32 -13
- web3/utils/exception_handling.py +7 -5
- {web3-6.20.2.dist-info → web3-7.0.0.dist-info}/LICENSE +1 -1
- web3-7.0.0.dist-info/METADATA +112 -0
- web3-7.0.0.dist-info/RECORD +167 -0
- {web3-6.20.2.dist-info → web3-7.0.0.dist-info}/WHEEL +1 -1
- {web3-6.20.2.dist-info → web3-7.0.0.dist-info}/top_level.txt +0 -1
- ethpm/__init__.py +0 -20
- ethpm/_utils/__init__.py +0 -0
- ethpm/_utils/backend.py +0 -93
- ethpm/_utils/cache.py +0 -44
- ethpm/_utils/chains.py +0 -119
- ethpm/_utils/contract.py +0 -35
- ethpm/_utils/deployments.py +0 -145
- ethpm/_utils/ipfs.py +0 -116
- ethpm/_utils/protobuf/__init__.py +0 -0
- ethpm/_utils/protobuf/ipfs_file_pb2.py +0 -33
- ethpm/_utils/registry.py +0 -29
- ethpm/assets/__init__.py +0 -0
- ethpm/assets/ens/v3.json +0 -1
- ethpm/assets/escrow/with_bytecode_v3.json +0 -1
- ethpm/assets/ipfs_file.proto +0 -32
- ethpm/assets/owned/output_v3.json +0 -1
- ethpm/assets/owned/with_contract_type_v3.json +0 -1
- ethpm/assets/registry/contracts/Authority.sol +0 -156
- ethpm/assets/registry/contracts/IndexedOrderedSetLib.sol +0 -106
- ethpm/assets/registry/contracts/PackageDB.sol +0 -225
- ethpm/assets/registry/contracts/PackageRegistry.sol +0 -361
- ethpm/assets/registry/contracts/PackageRegistryInterface.sol +0 -97
- ethpm/assets/registry/contracts/ReleaseDB.sol +0 -309
- ethpm/assets/registry/contracts/ReleaseValidator.sol +0 -152
- ethpm/assets/registry/solc_input.json +0 -1
- ethpm/assets/registry/solc_output.json +0 -1
- ethpm/assets/registry/v3.json +0 -1
- ethpm/assets/safe-math-lib/v3-strict-no-deployments.json +0 -1
- ethpm/assets/simple-registry/contracts/Ownable.sol +0 -63
- ethpm/assets/simple-registry/contracts/PackageRegistry.sol +0 -373
- ethpm/assets/simple-registry/contracts/PackageRegistryInterface.sol +0 -96
- ethpm/assets/simple-registry/solc_input.json +0 -33
- ethpm/assets/simple-registry/solc_output.json +0 -1
- ethpm/assets/simple-registry/v3.json +0 -1
- ethpm/assets/standard-token/output_v3.json +0 -1
- ethpm/assets/standard-token/with_bytecode_v3.json +0 -1
- ethpm/assets/vyper_registry/0.1.0.json +0 -1
- ethpm/assets/vyper_registry/registry.vy +0 -216
- ethpm/assets/vyper_registry/registry_with_delete.vy +0 -244
- ethpm/backends/__init__.py +0 -0
- ethpm/backends/base.py +0 -43
- ethpm/backends/http.py +0 -108
- ethpm/backends/ipfs.py +0 -219
- ethpm/backends/registry.py +0 -154
- ethpm/constants.py +0 -17
- ethpm/contract.py +0 -187
- ethpm/dependencies.py +0 -58
- ethpm/deployments.py +0 -80
- ethpm/ethpm-spec/examples/escrow/1.0.0-pretty.json +0 -146
- ethpm/ethpm-spec/examples/escrow/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/escrow/contracts/Escrow.sol +0 -32
- ethpm/ethpm-spec/examples/escrow/contracts/SafeSendLib.sol +0 -20
- ethpm/ethpm-spec/examples/escrow/v3-pretty.json +0 -171
- ethpm/ethpm-spec/examples/escrow/v3.json +0 -1
- ethpm/ethpm-spec/examples/owned/1.0.0-pretty.json +0 -21
- ethpm/ethpm-spec/examples/owned/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/owned/contracts/Owned.sol +0 -12
- ethpm/ethpm-spec/examples/owned/v3-pretty.json +0 -27
- ethpm/ethpm-spec/examples/owned/v3.json +0 -1
- ethpm/ethpm-spec/examples/piper-coin/1.0.0-pretty.json +0 -31
- ethpm/ethpm-spec/examples/piper-coin/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/piper-coin/v3-pretty.json +0 -21
- ethpm/ethpm-spec/examples/piper-coin/v3.json +0 -1
- ethpm/ethpm-spec/examples/safe-math-lib/1.0.0-pretty.json +0 -85
- ethpm/ethpm-spec/examples/safe-math-lib/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/safe-math-lib/contracts/SafeMathLib.sol +0 -24
- ethpm/ethpm-spec/examples/safe-math-lib/v3-pretty.json +0 -117
- ethpm/ethpm-spec/examples/safe-math-lib/v3.json +0 -1
- ethpm/ethpm-spec/examples/standard-token/1.0.0-pretty.json +0 -55
- ethpm/ethpm-spec/examples/standard-token/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/standard-token/contracts/AbstractToken.sol +0 -20
- ethpm/ethpm-spec/examples/standard-token/contracts/StandardToken.sol +0 -84
- ethpm/ethpm-spec/examples/standard-token/v3-pretty.json +0 -460
- ethpm/ethpm-spec/examples/standard-token/v3.json +0 -1
- ethpm/ethpm-spec/examples/transferable/1.0.0-pretty.json +0 -21
- ethpm/ethpm-spec/examples/transferable/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/transferable/contracts/Transferable.sol +0 -14
- ethpm/ethpm-spec/examples/transferable/v3-pretty.json +0 -27
- ethpm/ethpm-spec/examples/transferable/v3.json +0 -1
- ethpm/ethpm-spec/examples/wallet/1.0.0-pretty.json +0 -120
- ethpm/ethpm-spec/examples/wallet/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/wallet/contracts/Wallet.sol +0 -41
- ethpm/ethpm-spec/examples/wallet/v3-pretty.json +0 -181
- ethpm/ethpm-spec/examples/wallet/v3.json +0 -1
- ethpm/ethpm-spec/examples/wallet-with-send/1.0.0-pretty.json +0 -135
- ethpm/ethpm-spec/examples/wallet-with-send/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/wallet-with-send/contracts/WalletWithSend.sol +0 -18
- ethpm/ethpm-spec/examples/wallet-with-send/v3-pretty.json +0 -207
- ethpm/ethpm-spec/examples/wallet-with-send/v3.json +0 -1
- ethpm/ethpm-spec/spec/package.spec.json +0 -379
- ethpm/ethpm-spec/spec/v3.spec.json +0 -483
- ethpm/exceptions.py +0 -68
- ethpm/package.py +0 -438
- ethpm/tools/__init__.py +0 -4
- ethpm/tools/builder.py +0 -930
- ethpm/tools/checker.py +0 -312
- ethpm/tools/get_manifest.py +0 -19
- ethpm/uri.py +0 -141
- ethpm/validation/__init__.py +0 -0
- ethpm/validation/manifest.py +0 -146
- ethpm/validation/misc.py +0 -39
- ethpm/validation/package.py +0 -80
- ethpm/validation/uri.py +0 -163
- web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
- web3/_utils/miner.py +0 -88
- web3/_utils/module_testing/go_ethereum_personal_module.py +0 -323
- web3/_utils/request.py +0 -265
- web3/middleware/abi.py +0 -11
- web3/middleware/async_cache.py +0 -99
- web3/middleware/cache.py +0 -374
- web3/middleware/exception_handling.py +0 -49
- web3/middleware/exception_retry_request.py +0 -188
- web3/middleware/fixture.py +0 -190
- web3/middleware/geth_poa.py +0 -81
- web3/middleware/normalize_request_parameters.py +0 -11
- web3/middleware/simulate_unmined_transaction.py +0 -43
- web3/pm.py +0 -602
- web3/providers/async_rpc.py +0 -99
- web3/providers/rpc.py +0 -98
- web3/providers/websocket/__init__.py +0 -11
- web3/providers/websocket/websocket_connection.py +0 -42
- web3/tools/__init__.py +0 -4
- web3/tools/pytest_ethereum/__init__.py +0 -0
- web3/tools/pytest_ethereum/_utils.py +0 -145
- web3/tools/pytest_ethereum/deployer.py +0 -48
- web3/tools/pytest_ethereum/exceptions.py +0 -22
- web3/tools/pytest_ethereum/linker.py +0 -128
- web3/tools/pytest_ethereum/plugins.py +0 -33
- web3-6.20.2.dist-info/METADATA +0 -103
- web3-6.20.2.dist-info/RECORD +0 -283
- web3-6.20.2.dist-info/entry_points.txt +0 -2
- /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
web3/providers/async_base.py
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import itertools
|
|
2
3
|
from typing import (
|
|
3
4
|
TYPE_CHECKING,
|
|
4
5
|
Any,
|
|
5
6
|
Callable,
|
|
6
7
|
Coroutine,
|
|
7
|
-
|
|
8
|
+
List,
|
|
9
|
+
Optional,
|
|
10
|
+
Set,
|
|
8
11
|
Tuple,
|
|
9
12
|
cast,
|
|
10
13
|
)
|
|
@@ -15,6 +18,10 @@ from eth_utils import (
|
|
|
15
18
|
to_text,
|
|
16
19
|
)
|
|
17
20
|
|
|
21
|
+
from web3._utils.caching import (
|
|
22
|
+
CACHEABLE_REQUESTS,
|
|
23
|
+
async_handle_request_caching,
|
|
24
|
+
)
|
|
18
25
|
from web3._utils.encoding import (
|
|
19
26
|
FriendlyJsonSerde,
|
|
20
27
|
Web3JsonEncoder,
|
|
@@ -23,81 +30,138 @@ from web3.exceptions import (
|
|
|
23
30
|
ProviderConnectionError,
|
|
24
31
|
)
|
|
25
32
|
from web3.middleware import (
|
|
26
|
-
|
|
33
|
+
async_combine_middleware,
|
|
27
34
|
)
|
|
28
|
-
from web3.
|
|
29
|
-
|
|
30
|
-
AsyncMiddlewareOnion,
|
|
35
|
+
from web3.middleware.base import (
|
|
36
|
+
Middleware,
|
|
31
37
|
MiddlewareOnion,
|
|
38
|
+
)
|
|
39
|
+
from web3.types import (
|
|
32
40
|
RPCEndpoint,
|
|
33
41
|
RPCResponse,
|
|
34
42
|
)
|
|
43
|
+
from web3.utils import (
|
|
44
|
+
SimpleCache,
|
|
45
|
+
)
|
|
35
46
|
|
|
36
47
|
if TYPE_CHECKING:
|
|
48
|
+
from websockets import (
|
|
49
|
+
WebSocketClientProtocol,
|
|
50
|
+
)
|
|
51
|
+
|
|
37
52
|
from web3 import ( # noqa: F401
|
|
38
53
|
AsyncWeb3,
|
|
39
|
-
|
|
54
|
+
WebSocketProvider,
|
|
55
|
+
)
|
|
56
|
+
from web3.providers.persistent import ( # noqa: F401
|
|
57
|
+
RequestProcessor,
|
|
40
58
|
)
|
|
41
59
|
|
|
42
60
|
|
|
43
61
|
class AsyncBaseProvider:
|
|
44
|
-
_middlewares: Tuple[AsyncMiddleware, ...] = ()
|
|
45
|
-
# a tuple of (all_middlewares, request_func)
|
|
46
62
|
_request_func_cache: Tuple[
|
|
47
|
-
Tuple[
|
|
48
|
-
] = (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
63
|
+
Tuple[Middleware, ...], Callable[..., Coroutine[Any, Any, RPCResponse]]
|
|
64
|
+
] = (None, None)
|
|
65
|
+
|
|
66
|
+
_is_batching: bool = False
|
|
67
|
+
_batch_request_func_cache: Tuple[
|
|
68
|
+
Tuple[Middleware, ...], Callable[..., Coroutine[Any, Any, List[RPCResponse]]]
|
|
69
|
+
] = (None, None)
|
|
52
70
|
|
|
53
71
|
is_async = True
|
|
54
72
|
has_persistent_connection = False
|
|
55
73
|
global_ccip_read_enabled: bool = True
|
|
56
74
|
ccip_read_max_redirects: int = 4
|
|
57
75
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
76
|
+
# request caching
|
|
77
|
+
_request_cache: SimpleCache
|
|
78
|
+
_request_cache_lock: asyncio.Lock = asyncio.Lock()
|
|
61
79
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
80
|
+
def __init__(
|
|
81
|
+
self,
|
|
82
|
+
cache_allowed_requests: bool = False,
|
|
83
|
+
cacheable_requests: Set[RPCEndpoint] = None,
|
|
84
|
+
) -> None:
|
|
85
|
+
self._request_cache = SimpleCache(1000)
|
|
86
|
+
self.cache_allowed_requests = cache_allowed_requests
|
|
87
|
+
self.cacheable_requests = cacheable_requests or CACHEABLE_REQUESTS
|
|
66
88
|
|
|
67
89
|
async def request_func(
|
|
68
|
-
self, async_w3: "AsyncWeb3",
|
|
90
|
+
self, async_w3: "AsyncWeb3", middleware_onion: MiddlewareOnion
|
|
69
91
|
) -> Callable[..., Coroutine[Any, Any, RPCResponse]]:
|
|
70
|
-
|
|
71
|
-
all_middlewares: Tuple[AsyncMiddleware] = tuple(outer_middlewares) + tuple(self.middlewares) # type: ignore # noqa: E501
|
|
92
|
+
middleware: Tuple[Middleware, ...] = middleware_onion.as_tuple_of_middleware()
|
|
72
93
|
|
|
73
94
|
cache_key = self._request_func_cache[0]
|
|
74
|
-
if cache_key
|
|
95
|
+
if cache_key != middleware:
|
|
75
96
|
self._request_func_cache = (
|
|
76
|
-
|
|
77
|
-
await
|
|
97
|
+
middleware,
|
|
98
|
+
await async_combine_middleware(
|
|
99
|
+
middleware=middleware,
|
|
100
|
+
async_w3=async_w3,
|
|
101
|
+
provider_request_fn=self.make_request,
|
|
102
|
+
),
|
|
78
103
|
)
|
|
79
104
|
return self._request_func_cache[-1]
|
|
80
105
|
|
|
81
|
-
async def
|
|
82
|
-
self, async_w3: "AsyncWeb3",
|
|
83
|
-
) -> Callable[..., Coroutine[Any, Any, RPCResponse]]:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
106
|
+
async def batch_request_func(
|
|
107
|
+
self, async_w3: "AsyncWeb3", middleware_onion: MiddlewareOnion
|
|
108
|
+
) -> Callable[..., Coroutine[Any, Any, List[RPCResponse]]]:
|
|
109
|
+
middleware: Tuple[Middleware, ...] = middleware_onion.as_tuple_of_middleware()
|
|
110
|
+
|
|
111
|
+
cache_key = self._batch_request_func_cache[0]
|
|
112
|
+
if cache_key != middleware:
|
|
113
|
+
accumulator_fn = self.make_batch_request
|
|
114
|
+
for mw in reversed(middleware):
|
|
115
|
+
initialized = mw(async_w3)
|
|
116
|
+
# type ignore bc in order to wrap the method, we have to call
|
|
117
|
+
# `async_wrap_make_batch_request` with the accumulator_fn as the
|
|
118
|
+
# argument which breaks the type hinting for this particular case.
|
|
119
|
+
accumulator_fn = await initialized.async_wrap_make_batch_request( # type: ignore # noqa: E501
|
|
120
|
+
accumulator_fn
|
|
121
|
+
)
|
|
122
|
+
self._batch_request_func_cache = (middleware, accumulator_fn)
|
|
123
|
+
return self._batch_request_func_cache[-1]
|
|
89
124
|
|
|
125
|
+
@async_handle_request_caching
|
|
90
126
|
async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
91
127
|
raise NotImplementedError("Providers must implement this method")
|
|
92
128
|
|
|
129
|
+
async def make_batch_request(
|
|
130
|
+
self, requests: List[Tuple[RPCEndpoint, Any]]
|
|
131
|
+
) -> List[RPCResponse]:
|
|
132
|
+
raise NotImplementedError("Only AsyncHTTPProvider supports this method")
|
|
133
|
+
|
|
93
134
|
async def is_connected(self, show_traceback: bool = False) -> bool:
|
|
94
135
|
raise NotImplementedError("Providers must implement this method")
|
|
95
136
|
|
|
137
|
+
# -- persistent connection providers -- #
|
|
138
|
+
|
|
139
|
+
_request_processor: "RequestProcessor"
|
|
140
|
+
_message_listener_task: "asyncio.Task[None]"
|
|
141
|
+
_listen_event: "asyncio.Event"
|
|
142
|
+
|
|
143
|
+
async def connect(self) -> None:
|
|
144
|
+
raise NotImplementedError(
|
|
145
|
+
"Persistent connection providers must implement this method"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
async def disconnect(self) -> None:
|
|
149
|
+
raise NotImplementedError(
|
|
150
|
+
"Persistent connection providers must implement this method"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# WebSocket typing
|
|
154
|
+
_ws: "WebSocketClientProtocol"
|
|
155
|
+
|
|
156
|
+
# IPC typing
|
|
157
|
+
_reader: Optional[asyncio.StreamReader]
|
|
158
|
+
_writer: Optional[asyncio.StreamWriter]
|
|
159
|
+
|
|
96
160
|
|
|
97
161
|
class AsyncJSONBaseProvider(AsyncBaseProvider):
|
|
98
|
-
def __init__(self) -> None:
|
|
99
|
-
super().__init__()
|
|
162
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
100
163
|
self.request_counter = itertools.count()
|
|
164
|
+
super().__init__(**kwargs)
|
|
101
165
|
|
|
102
166
|
def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
|
|
103
167
|
request_id = next(self.request_counter)
|
|
@@ -110,7 +174,8 @@ class AsyncJSONBaseProvider(AsyncBaseProvider):
|
|
|
110
174
|
encoded = FriendlyJsonSerde().json_encode(rpc_dict, cls=Web3JsonEncoder)
|
|
111
175
|
return to_bytes(text=encoded)
|
|
112
176
|
|
|
113
|
-
|
|
177
|
+
@staticmethod
|
|
178
|
+
def decode_rpc_response(raw_response: bytes) -> RPCResponse:
|
|
114
179
|
text_response = str(
|
|
115
180
|
to_text(raw_response) if not is_text(raw_response) else raw_response
|
|
116
181
|
)
|
|
@@ -119,7 +184,7 @@ class AsyncJSONBaseProvider(AsyncBaseProvider):
|
|
|
119
184
|
async def is_connected(self, show_traceback: bool = False) -> bool:
|
|
120
185
|
try:
|
|
121
186
|
response = await self.make_request(RPCEndpoint("web3_clientVersion"), [])
|
|
122
|
-
except OSError as e:
|
|
187
|
+
except (OSError, ProviderConnectionError) as e:
|
|
123
188
|
if show_traceback:
|
|
124
189
|
raise ProviderConnectionError(
|
|
125
190
|
f"Problem connecting to provider with error: {type(e)}: {e}"
|
|
@@ -133,9 +198,22 @@ class AsyncJSONBaseProvider(AsyncBaseProvider):
|
|
|
133
198
|
)
|
|
134
199
|
return False
|
|
135
200
|
|
|
136
|
-
if response
|
|
201
|
+
if response.get("jsonrpc") == "2.0":
|
|
137
202
|
return True
|
|
138
203
|
else:
|
|
139
204
|
if show_traceback:
|
|
140
205
|
raise ProviderConnectionError(f"Bad jsonrpc version: {response}")
|
|
141
206
|
return False
|
|
207
|
+
|
|
208
|
+
# -- batch requests -- #
|
|
209
|
+
|
|
210
|
+
def encode_batch_rpc_request(
|
|
211
|
+
self, requests: List[Tuple[RPCEndpoint, Any]]
|
|
212
|
+
) -> bytes:
|
|
213
|
+
return (
|
|
214
|
+
b"["
|
|
215
|
+
+ b", ".join(
|
|
216
|
+
self.encode_rpc_request(method, params) for method, params in requests
|
|
217
|
+
)
|
|
218
|
+
+ b"]"
|
|
219
|
+
)
|
web3/providers/auto.py
CHANGED
|
@@ -24,7 +24,7 @@ from web3.providers import (
|
|
|
24
24
|
BaseProvider,
|
|
25
25
|
HTTPProvider,
|
|
26
26
|
IPCProvider,
|
|
27
|
-
|
|
27
|
+
LegacyWebSocketProvider,
|
|
28
28
|
)
|
|
29
29
|
from web3.types import (
|
|
30
30
|
RPCEndpoint,
|
|
@@ -52,7 +52,7 @@ def load_provider_from_uri(
|
|
|
52
52
|
elif uri.scheme in HTTP_SCHEMES:
|
|
53
53
|
return HTTPProvider(uri_string, headers)
|
|
54
54
|
elif uri.scheme in WS_SCHEMES:
|
|
55
|
-
return
|
|
55
|
+
return LegacyWebSocketProvider(uri_string)
|
|
56
56
|
else:
|
|
57
57
|
raise NotImplementedError(
|
|
58
58
|
"Web3 does not know how to connect to scheme "
|
|
@@ -65,7 +65,7 @@ class AutoProvider(BaseProvider):
|
|
|
65
65
|
load_provider_from_environment,
|
|
66
66
|
IPCProvider,
|
|
67
67
|
HTTPProvider,
|
|
68
|
-
|
|
68
|
+
LegacyWebSocketProvider,
|
|
69
69
|
)
|
|
70
70
|
_active_provider = None
|
|
71
71
|
|
web3/providers/base.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import itertools
|
|
2
|
+
import threading
|
|
2
3
|
from typing import (
|
|
3
4
|
TYPE_CHECKING,
|
|
4
5
|
Any,
|
|
5
6
|
Callable,
|
|
6
|
-
|
|
7
|
+
List,
|
|
8
|
+
Set,
|
|
7
9
|
Tuple,
|
|
8
10
|
cast,
|
|
9
11
|
)
|
|
@@ -13,6 +15,10 @@ from eth_utils import (
|
|
|
13
15
|
to_text,
|
|
14
16
|
)
|
|
15
17
|
|
|
18
|
+
from web3._utils.caching import (
|
|
19
|
+
CACHEABLE_REQUESTS,
|
|
20
|
+
handle_request_caching,
|
|
21
|
+
)
|
|
16
22
|
from web3._utils.encoding import (
|
|
17
23
|
FriendlyJsonSerde,
|
|
18
24
|
Web3JsonEncoder,
|
|
@@ -21,22 +27,26 @@ from web3.exceptions import (
|
|
|
21
27
|
ProviderConnectionError,
|
|
22
28
|
)
|
|
23
29
|
from web3.middleware import (
|
|
24
|
-
|
|
30
|
+
combine_middleware,
|
|
25
31
|
)
|
|
26
|
-
from web3.
|
|
32
|
+
from web3.middleware.base import (
|
|
27
33
|
Middleware,
|
|
28
34
|
MiddlewareOnion,
|
|
35
|
+
)
|
|
36
|
+
from web3.types import (
|
|
29
37
|
RPCEndpoint,
|
|
30
38
|
RPCResponse,
|
|
31
39
|
)
|
|
40
|
+
from web3.utils import (
|
|
41
|
+
SimpleCache,
|
|
42
|
+
)
|
|
32
43
|
|
|
33
44
|
if TYPE_CHECKING:
|
|
34
45
|
from web3 import Web3 # noqa: F401
|
|
35
46
|
|
|
36
47
|
|
|
37
48
|
class BaseProvider:
|
|
38
|
-
|
|
39
|
-
# a tuple of (all_middlewares, request_func)
|
|
49
|
+
# a tuple of (middleware, request_func)
|
|
40
50
|
_request_func_cache: Tuple[Tuple[Middleware, ...], Callable[..., RPCResponse]] = (
|
|
41
51
|
None,
|
|
42
52
|
None,
|
|
@@ -47,44 +57,45 @@ class BaseProvider:
|
|
|
47
57
|
global_ccip_read_enabled: bool = True
|
|
48
58
|
ccip_read_max_redirects: int = 4
|
|
49
59
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
# request caching
|
|
61
|
+
_request_cache: SimpleCache
|
|
62
|
+
_request_cache_lock: threading.Lock = threading.Lock()
|
|
53
63
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
cache_allowed_requests: bool = False,
|
|
67
|
+
cacheable_requests: Set[RPCEndpoint] = None,
|
|
68
|
+
) -> None:
|
|
69
|
+
self._request_cache = SimpleCache(1000)
|
|
70
|
+
self.cache_allowed_requests = cache_allowed_requests
|
|
71
|
+
self.cacheable_requests = cacheable_requests or CACHEABLE_REQUESTS
|
|
58
72
|
|
|
59
73
|
def request_func(
|
|
60
|
-
self, w3: "Web3",
|
|
74
|
+
self, w3: "Web3", middleware_onion: MiddlewareOnion
|
|
61
75
|
) -> Callable[..., RPCResponse]:
|
|
62
76
|
"""
|
|
63
|
-
@param
|
|
77
|
+
@param w3 is the web3 instance
|
|
78
|
+
@param middleware_onion is an iterable of middleware,
|
|
64
79
|
ordered by first to execute
|
|
65
80
|
@returns a function that calls all the middleware and
|
|
66
81
|
eventually self.make_request()
|
|
67
82
|
"""
|
|
68
|
-
|
|
69
|
-
all_middlewares: Tuple[Middleware] = tuple(outer_middlewares) + tuple(self.middlewares) # type: ignore # noqa: E501
|
|
83
|
+
middleware: Tuple[Middleware, ...] = middleware_onion.as_tuple_of_middleware()
|
|
70
84
|
|
|
71
85
|
cache_key = self._request_func_cache[0]
|
|
72
|
-
if cache_key
|
|
86
|
+
if cache_key != middleware:
|
|
73
87
|
self._request_func_cache = (
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
middleware,
|
|
89
|
+
combine_middleware(
|
|
90
|
+
middleware=middleware,
|
|
91
|
+
w3=w3,
|
|
92
|
+
provider_request_fn=self.make_request,
|
|
93
|
+
),
|
|
76
94
|
)
|
|
77
|
-
return self._request_func_cache[-1]
|
|
78
95
|
|
|
79
|
-
|
|
80
|
-
self, w3: "Web3", middlewares: Sequence[Middleware]
|
|
81
|
-
) -> Callable[..., RPCResponse]:
|
|
82
|
-
return combine_middlewares(
|
|
83
|
-
middlewares=middlewares,
|
|
84
|
-
w3=w3,
|
|
85
|
-
provider_request_fn=self.make_request,
|
|
86
|
-
)
|
|
96
|
+
return self._request_func_cache[-1]
|
|
87
97
|
|
|
98
|
+
@handle_request_caching
|
|
88
99
|
def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
89
100
|
raise NotImplementedError("Providers must implement this method")
|
|
90
101
|
|
|
@@ -93,12 +104,14 @@ class BaseProvider:
|
|
|
93
104
|
|
|
94
105
|
|
|
95
106
|
class JSONBaseProvider(BaseProvider):
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
_is_batching: bool = False
|
|
108
|
+
_batch_request_func_cache: Tuple[
|
|
109
|
+
Tuple[Middleware, ...], Callable[..., List[RPCResponse]]
|
|
110
|
+
] = (None, None)
|
|
98
111
|
|
|
99
|
-
def
|
|
100
|
-
|
|
101
|
-
|
|
112
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
113
|
+
self.request_counter = itertools.count()
|
|
114
|
+
super().__init__(**kwargs)
|
|
102
115
|
|
|
103
116
|
def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
|
|
104
117
|
rpc_dict = {
|
|
@@ -110,6 +123,11 @@ class JSONBaseProvider(BaseProvider):
|
|
|
110
123
|
encoded = FriendlyJsonSerde().json_encode(rpc_dict, Web3JsonEncoder)
|
|
111
124
|
return to_bytes(text=encoded)
|
|
112
125
|
|
|
126
|
+
@staticmethod
|
|
127
|
+
def decode_rpc_response(raw_response: bytes) -> RPCResponse:
|
|
128
|
+
text_response = to_text(raw_response)
|
|
129
|
+
return cast(RPCResponse, FriendlyJsonSerde().json_decode(text_response))
|
|
130
|
+
|
|
113
131
|
def is_connected(self, show_traceback: bool = False) -> bool:
|
|
114
132
|
try:
|
|
115
133
|
response = self.make_request(RPCEndpoint("web3_clientVersion"), [])
|
|
@@ -133,3 +151,41 @@ class JSONBaseProvider(BaseProvider):
|
|
|
133
151
|
if show_traceback:
|
|
134
152
|
raise ProviderConnectionError(f"Bad jsonrpc version: {response}")
|
|
135
153
|
return False
|
|
154
|
+
|
|
155
|
+
# -- batch requests -- #
|
|
156
|
+
|
|
157
|
+
def batch_request_func(
|
|
158
|
+
self, w3: "Web3", middleware_onion: MiddlewareOnion
|
|
159
|
+
) -> Callable[..., List[RPCResponse]]:
|
|
160
|
+
middleware: Tuple[Middleware, ...] = middleware_onion.as_tuple_of_middleware()
|
|
161
|
+
|
|
162
|
+
cache_key = self._batch_request_func_cache[0]
|
|
163
|
+
if cache_key != middleware:
|
|
164
|
+
accumulator_fn = self.make_batch_request
|
|
165
|
+
for mw in reversed(middleware):
|
|
166
|
+
initialized = mw(w3)
|
|
167
|
+
# type ignore bc in order to wrap the method, we have to call
|
|
168
|
+
# `wrap_make_batch_request` with the accumulator_fn as the argument
|
|
169
|
+
# which breaks the type hinting for this particular case.
|
|
170
|
+
accumulator_fn = initialized.wrap_make_batch_request(
|
|
171
|
+
accumulator_fn
|
|
172
|
+
) # type: ignore # noqa: E501
|
|
173
|
+
self._batch_request_func_cache = (middleware, accumulator_fn)
|
|
174
|
+
|
|
175
|
+
return self._batch_request_func_cache[-1]
|
|
176
|
+
|
|
177
|
+
def encode_batch_rpc_request(
|
|
178
|
+
self, requests: List[Tuple[RPCEndpoint, Any]]
|
|
179
|
+
) -> bytes:
|
|
180
|
+
return (
|
|
181
|
+
b"["
|
|
182
|
+
+ b", ".join(
|
|
183
|
+
self.encode_rpc_request(method, params) for method, params in requests
|
|
184
|
+
)
|
|
185
|
+
+ b"]"
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
def make_batch_request(
|
|
189
|
+
self, requests: List[Tuple[RPCEndpoint, Any]]
|
|
190
|
+
) -> List[RPCResponse]:
|
|
191
|
+
raise NotImplementedError("Providers must implement this method")
|
|
@@ -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,
|
|
@@ -256,12 +243,6 @@ API_ENDPOINTS = {
|
|
|
256
243
|
"eth": {
|
|
257
244
|
"protocolVersion": static_return(63),
|
|
258
245
|
"syncing": static_return(False),
|
|
259
|
-
"coinbase": compose(
|
|
260
|
-
operator.itemgetter(0),
|
|
261
|
-
call_eth_tester("get_accounts"),
|
|
262
|
-
),
|
|
263
|
-
"mining": static_return(False),
|
|
264
|
-
"hashrate": static_return(0),
|
|
265
246
|
"chainId": static_return(131277322940537), # from fixture generation file
|
|
266
247
|
"feeHistory": call_eth_tester("get_fee_history"),
|
|
267
248
|
"maxPriorityFeePerGas": static_return(10**9),
|
|
@@ -404,50 +385,6 @@ API_ENDPOINTS = {
|
|
|
404
385
|
"writeBlockProfile": not_implemented,
|
|
405
386
|
"writeMemProfile": not_implemented,
|
|
406
387
|
},
|
|
407
|
-
"miner": {
|
|
408
|
-
"make_dag": not_implemented,
|
|
409
|
-
"set_extra": not_implemented,
|
|
410
|
-
"set_gas_price": not_implemented,
|
|
411
|
-
"start": not_implemented,
|
|
412
|
-
"stop": not_implemented,
|
|
413
|
-
"start_auto_dag": not_implemented,
|
|
414
|
-
"stop_auto_dag": not_implemented,
|
|
415
|
-
},
|
|
416
|
-
"personal": {
|
|
417
|
-
"ec_recover": not_implemented,
|
|
418
|
-
"import_raw_key": call_eth_tester("add_account"),
|
|
419
|
-
"list_accounts": call_eth_tester("get_accounts"),
|
|
420
|
-
"list_wallets": not_implemented,
|
|
421
|
-
"lock_account": excepts(
|
|
422
|
-
ValidationError,
|
|
423
|
-
compose(static_return(True), call_eth_tester("lock_account")),
|
|
424
|
-
static_return(False),
|
|
425
|
-
),
|
|
426
|
-
"new_account": create_new_account,
|
|
427
|
-
"unlock_account": excepts(
|
|
428
|
-
ValidationError,
|
|
429
|
-
compose(static_return(True), call_eth_tester("unlock_account")),
|
|
430
|
-
static_return(False),
|
|
431
|
-
),
|
|
432
|
-
"send_transaction": personal_send_transaction,
|
|
433
|
-
"sign": not_implemented,
|
|
434
|
-
# deprecated
|
|
435
|
-
"ecRecover": not_implemented,
|
|
436
|
-
"importRawKey": call_eth_tester("add_account"),
|
|
437
|
-
"listAccounts": call_eth_tester("get_accounts"),
|
|
438
|
-
"lockAccount": excepts(
|
|
439
|
-
ValidationError,
|
|
440
|
-
compose(static_return(True), call_eth_tester("lock_account")),
|
|
441
|
-
static_return(False),
|
|
442
|
-
),
|
|
443
|
-
"newAccount": create_new_account,
|
|
444
|
-
"unlockAccount": excepts(
|
|
445
|
-
ValidationError,
|
|
446
|
-
compose(static_return(True), call_eth_tester("unlock_account")),
|
|
447
|
-
static_return(False),
|
|
448
|
-
),
|
|
449
|
-
"sendTransaction": personal_send_transaction,
|
|
450
|
-
},
|
|
451
388
|
"testing": {
|
|
452
389
|
"timeTravel": call_eth_tester("time_travel"),
|
|
453
390
|
},
|