web3 6.20.3__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.3.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.3.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.3.dist-info/METADATA +0 -104
- web3-6.20.3.dist-info/RECORD +0 -283
- web3-6.20.3.dist-info/entry_points.txt +0 -2
- /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
- {web3-6.20.3.dist-info → web3-7.0.0.dist-info}/WHEEL +0 -0
web3/middleware/cache.py
DELETED
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
import functools
|
|
2
|
-
import threading
|
|
3
|
-
import time
|
|
4
|
-
from typing import (
|
|
5
|
-
TYPE_CHECKING,
|
|
6
|
-
Any,
|
|
7
|
-
Callable,
|
|
8
|
-
Collection,
|
|
9
|
-
Dict,
|
|
10
|
-
Set,
|
|
11
|
-
cast,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
from eth_utils import (
|
|
15
|
-
is_list_like,
|
|
16
|
-
)
|
|
17
|
-
import lru
|
|
18
|
-
|
|
19
|
-
from web3._utils.caching import (
|
|
20
|
-
generate_cache_key,
|
|
21
|
-
)
|
|
22
|
-
from web3._utils.compat import (
|
|
23
|
-
Literal,
|
|
24
|
-
TypedDict,
|
|
25
|
-
)
|
|
26
|
-
from web3.types import (
|
|
27
|
-
BlockData,
|
|
28
|
-
BlockNumber,
|
|
29
|
-
Middleware,
|
|
30
|
-
RPCEndpoint,
|
|
31
|
-
RPCResponse,
|
|
32
|
-
)
|
|
33
|
-
from web3.utils.caching import (
|
|
34
|
-
SimpleCache,
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
if TYPE_CHECKING:
|
|
38
|
-
from web3 import Web3 # noqa: F401
|
|
39
|
-
|
|
40
|
-
SIMPLE_CACHE_RPC_WHITELIST = cast(
|
|
41
|
-
Set[RPCEndpoint],
|
|
42
|
-
(
|
|
43
|
-
"web3_clientVersion",
|
|
44
|
-
"net_version",
|
|
45
|
-
"eth_getBlockTransactionCountByHash",
|
|
46
|
-
"eth_getUncleCountByBlockHash",
|
|
47
|
-
"eth_getBlockByHash",
|
|
48
|
-
"eth_getTransactionByHash",
|
|
49
|
-
"eth_getTransactionByBlockHashAndIndex",
|
|
50
|
-
"eth_getRawTransactionByHash",
|
|
51
|
-
"eth_getUncleByBlockHashAndIndex",
|
|
52
|
-
"eth_chainId",
|
|
53
|
-
),
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def _should_cache_response(
|
|
58
|
-
_method: RPCEndpoint, _params: Any, response: RPCResponse
|
|
59
|
-
) -> bool:
|
|
60
|
-
return (
|
|
61
|
-
"error" not in response
|
|
62
|
-
and "result" in response
|
|
63
|
-
and response["result"] is not None
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def construct_simple_cache_middleware(
|
|
68
|
-
cache: SimpleCache = None,
|
|
69
|
-
rpc_whitelist: Collection[RPCEndpoint] = None,
|
|
70
|
-
should_cache_fn: Callable[
|
|
71
|
-
[RPCEndpoint, Any, RPCResponse], bool
|
|
72
|
-
] = _should_cache_response,
|
|
73
|
-
) -> Middleware:
|
|
74
|
-
"""
|
|
75
|
-
Constructs a middleware which caches responses based on the request
|
|
76
|
-
``method`` and ``params``
|
|
77
|
-
|
|
78
|
-
:param cache: A ``SimpleCache`` class.
|
|
79
|
-
:param rpc_whitelist: A set of RPC methods which may have their responses cached.
|
|
80
|
-
:param should_cache_fn: A callable which accepts ``method`` ``params`` and
|
|
81
|
-
``response`` and returns a boolean as to whether the response should be
|
|
82
|
-
cached.
|
|
83
|
-
"""
|
|
84
|
-
if rpc_whitelist is None:
|
|
85
|
-
rpc_whitelist = SIMPLE_CACHE_RPC_WHITELIST
|
|
86
|
-
|
|
87
|
-
def simple_cache_middleware(
|
|
88
|
-
make_request: Callable[[RPCEndpoint, Any], RPCResponse], _w3: "Web3"
|
|
89
|
-
) -> Callable[[RPCEndpoint, Any], RPCResponse]:
|
|
90
|
-
lock = threading.Lock()
|
|
91
|
-
|
|
92
|
-
# Setting the cache here, rather than in ``construct_simple_cache_middleware``,
|
|
93
|
-
# ensures that each instance of the middleware has its own cache. This is
|
|
94
|
-
# important for compatibility with multiple ``Web3`` instances.
|
|
95
|
-
_cache = cache if cache else SimpleCache(256)
|
|
96
|
-
|
|
97
|
-
def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
98
|
-
if method in rpc_whitelist:
|
|
99
|
-
cache_key = generate_cache_key(
|
|
100
|
-
f"{threading.get_ident()}:{(method, params)}"
|
|
101
|
-
)
|
|
102
|
-
cached_request = _cache.get_cache_entry(cache_key)
|
|
103
|
-
if cached_request is not None:
|
|
104
|
-
return cached_request
|
|
105
|
-
|
|
106
|
-
response = make_request(method, params)
|
|
107
|
-
if should_cache_fn(method, params, response):
|
|
108
|
-
if lock.acquire(blocking=False):
|
|
109
|
-
try:
|
|
110
|
-
_cache.cache(cache_key, response)
|
|
111
|
-
finally:
|
|
112
|
-
lock.release()
|
|
113
|
-
return response
|
|
114
|
-
else:
|
|
115
|
-
return make_request(method, params)
|
|
116
|
-
|
|
117
|
-
return middleware
|
|
118
|
-
|
|
119
|
-
return simple_cache_middleware
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
_simple_cache_middleware = construct_simple_cache_middleware()
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
TIME_BASED_CACHE_RPC_WHITELIST = cast(
|
|
126
|
-
Set[RPCEndpoint],
|
|
127
|
-
{
|
|
128
|
-
"eth_coinbase",
|
|
129
|
-
"eth_accounts",
|
|
130
|
-
},
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def construct_time_based_cache_middleware(
|
|
135
|
-
cache_class: Callable[..., Dict[Any, Any]],
|
|
136
|
-
cache_expire_seconds: int = 15,
|
|
137
|
-
rpc_whitelist: Collection[RPCEndpoint] = TIME_BASED_CACHE_RPC_WHITELIST,
|
|
138
|
-
should_cache_fn: Callable[
|
|
139
|
-
[RPCEndpoint, Any, RPCResponse], bool
|
|
140
|
-
] = _should_cache_response,
|
|
141
|
-
) -> Middleware:
|
|
142
|
-
"""
|
|
143
|
-
Constructs a middleware which caches responses based on the request
|
|
144
|
-
``method`` and ``params`` for a maximum amount of time as specified
|
|
145
|
-
|
|
146
|
-
:param cache_class: Any dictionary-like object
|
|
147
|
-
:param cache_expire_seconds: The number of seconds an item may be cached
|
|
148
|
-
before it should expire.
|
|
149
|
-
:param rpc_whitelist: A set of RPC methods which may have their responses cached.
|
|
150
|
-
:param should_cache_fn: A callable which accepts ``method`` ``params`` and
|
|
151
|
-
``response`` and returns a boolean as to whether the response should be
|
|
152
|
-
cached.
|
|
153
|
-
"""
|
|
154
|
-
|
|
155
|
-
def time_based_cache_middleware(
|
|
156
|
-
make_request: Callable[[RPCEndpoint, Any], Any], w3: "Web3"
|
|
157
|
-
) -> Callable[[RPCEndpoint, Any], RPCResponse]:
|
|
158
|
-
cache = cache_class()
|
|
159
|
-
lock = threading.Lock()
|
|
160
|
-
|
|
161
|
-
def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
162
|
-
lock_acquired = (
|
|
163
|
-
lock.acquire(blocking=False) if method in rpc_whitelist else False
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
try:
|
|
167
|
-
if lock_acquired and method in rpc_whitelist:
|
|
168
|
-
cache_key = generate_cache_key((method, params))
|
|
169
|
-
if cache_key in cache:
|
|
170
|
-
# check that the cached response is not expired.
|
|
171
|
-
cached_at, cached_response = cache[cache_key]
|
|
172
|
-
cached_for = time.time() - cached_at
|
|
173
|
-
|
|
174
|
-
if cached_for <= cache_expire_seconds:
|
|
175
|
-
return cached_response
|
|
176
|
-
else:
|
|
177
|
-
del cache[cache_key]
|
|
178
|
-
|
|
179
|
-
# cache either missed or expired so make the request.
|
|
180
|
-
response = make_request(method, params)
|
|
181
|
-
|
|
182
|
-
if should_cache_fn(method, params, response):
|
|
183
|
-
cache[cache_key] = (time.time(), response)
|
|
184
|
-
|
|
185
|
-
return response
|
|
186
|
-
else:
|
|
187
|
-
return make_request(method, params)
|
|
188
|
-
finally:
|
|
189
|
-
if lock_acquired:
|
|
190
|
-
lock.release()
|
|
191
|
-
|
|
192
|
-
return middleware
|
|
193
|
-
|
|
194
|
-
return time_based_cache_middleware
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
_time_based_cache_middleware = construct_time_based_cache_middleware(
|
|
198
|
-
cache_class=functools.partial(lru.LRU, 256),
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
BLOCK_NUMBER_RPC_WHITELIST = cast(
|
|
203
|
-
Set[RPCEndpoint],
|
|
204
|
-
{
|
|
205
|
-
"eth_gasPrice",
|
|
206
|
-
"eth_blockNumber",
|
|
207
|
-
"eth_getBalance",
|
|
208
|
-
"eth_getStorageAt",
|
|
209
|
-
"eth_getTransactionCount",
|
|
210
|
-
"eth_getBlockTransactionCountByNumber",
|
|
211
|
-
"eth_getUncleCountByBlockNumber",
|
|
212
|
-
"eth_getCode",
|
|
213
|
-
"eth_call",
|
|
214
|
-
"eth_createAccessList",
|
|
215
|
-
"eth_estimateGas",
|
|
216
|
-
"eth_getBlockByNumber",
|
|
217
|
-
"eth_getTransactionByBlockNumberAndIndex",
|
|
218
|
-
"eth_getTransactionReceipt",
|
|
219
|
-
"eth_getUncleByBlockNumberAndIndex",
|
|
220
|
-
"eth_getLogs",
|
|
221
|
-
},
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
AVG_BLOCK_TIME_KEY: Literal["avg_block_time"] = "avg_block_time"
|
|
225
|
-
AVG_BLOCK_SAMPLE_SIZE_KEY: Literal["avg_block_sample_size"] = "avg_block_sample_size"
|
|
226
|
-
AVG_BLOCK_TIME_UPDATED_AT_KEY: Literal[
|
|
227
|
-
"avg_block_time_updated_at"
|
|
228
|
-
] = "avg_block_time_updated_at"
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
def _is_latest_block_number_request(method: RPCEndpoint, params: Any) -> bool:
|
|
232
|
-
if method != "eth_getBlockByNumber":
|
|
233
|
-
return False
|
|
234
|
-
elif is_list_like(params) and tuple(params[:1]) == ("latest",):
|
|
235
|
-
return True
|
|
236
|
-
return False
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
BlockInfoCache = TypedDict(
|
|
240
|
-
"BlockInfoCache",
|
|
241
|
-
{
|
|
242
|
-
"avg_block_time": float,
|
|
243
|
-
"avg_block_sample_size": int,
|
|
244
|
-
"avg_block_time_updated_at": float,
|
|
245
|
-
"latest_block": BlockData,
|
|
246
|
-
},
|
|
247
|
-
total=False,
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
def construct_latest_block_based_cache_middleware(
|
|
252
|
-
cache_class: Callable[..., Dict[Any, Any]],
|
|
253
|
-
rpc_whitelist: Collection[RPCEndpoint] = BLOCK_NUMBER_RPC_WHITELIST,
|
|
254
|
-
average_block_time_sample_size: int = 240,
|
|
255
|
-
default_average_block_time: int = 15,
|
|
256
|
-
should_cache_fn: Callable[
|
|
257
|
-
[RPCEndpoint, Any, RPCResponse], bool
|
|
258
|
-
] = _should_cache_response,
|
|
259
|
-
) -> Middleware:
|
|
260
|
-
"""
|
|
261
|
-
Constructs a middleware which caches responses based on the request
|
|
262
|
-
``method``, ``params``, and the current latest block hash.
|
|
263
|
-
|
|
264
|
-
:param cache_class: Any dictionary-like object
|
|
265
|
-
:param rpc_whitelist: A set of RPC methods which may have their responses cached.
|
|
266
|
-
:param average_block_time_sample_size: number of blocks to look back when computing
|
|
267
|
-
average block time
|
|
268
|
-
:param default_average_block_time: estimated number of seconds per block
|
|
269
|
-
:param should_cache_fn: A callable which accepts ``method`` ``params`` and
|
|
270
|
-
``response`` and returns a boolean as to whether the response should be
|
|
271
|
-
cached.
|
|
272
|
-
|
|
273
|
-
.. note::
|
|
274
|
-
This middleware avoids re-fetching the current latest block for each
|
|
275
|
-
request by tracking the current average block time and only requesting
|
|
276
|
-
a new block when the last seen latest block is older than the average
|
|
277
|
-
block time.
|
|
278
|
-
"""
|
|
279
|
-
|
|
280
|
-
def latest_block_based_cache_middleware(
|
|
281
|
-
make_request: Callable[[RPCEndpoint, Any], Any], w3: "Web3"
|
|
282
|
-
) -> Callable[[RPCEndpoint, Any], RPCResponse]:
|
|
283
|
-
cache = cache_class()
|
|
284
|
-
block_info: BlockInfoCache = {}
|
|
285
|
-
|
|
286
|
-
def _update_block_info_cache() -> None:
|
|
287
|
-
avg_block_time = block_info.get(
|
|
288
|
-
AVG_BLOCK_TIME_KEY, default_average_block_time
|
|
289
|
-
)
|
|
290
|
-
avg_block_sample_size = block_info.get(AVG_BLOCK_SAMPLE_SIZE_KEY, 0)
|
|
291
|
-
avg_block_time_updated_at = block_info.get(AVG_BLOCK_TIME_UPDATED_AT_KEY, 0)
|
|
292
|
-
|
|
293
|
-
# compute age as counted by number of blocks since the avg_block_time
|
|
294
|
-
if avg_block_time == 0:
|
|
295
|
-
avg_block_time_age_in_blocks: float = avg_block_sample_size
|
|
296
|
-
else:
|
|
297
|
-
avg_block_time_age_in_blocks = (
|
|
298
|
-
time.time() - avg_block_time_updated_at
|
|
299
|
-
) / avg_block_time
|
|
300
|
-
|
|
301
|
-
if avg_block_time_age_in_blocks >= avg_block_sample_size:
|
|
302
|
-
# If the length of time since the average block time as
|
|
303
|
-
# measured by blocks is greater than or equal to the number of
|
|
304
|
-
# blocks sampled then we need to recompute the average block
|
|
305
|
-
# time.
|
|
306
|
-
latest_block = w3.eth.get_block("latest")
|
|
307
|
-
ancestor_block_number = BlockNumber(
|
|
308
|
-
max(
|
|
309
|
-
0,
|
|
310
|
-
latest_block["number"] - average_block_time_sample_size,
|
|
311
|
-
)
|
|
312
|
-
)
|
|
313
|
-
ancestor_block = w3.eth.get_block(ancestor_block_number)
|
|
314
|
-
sample_size = latest_block["number"] - ancestor_block_number
|
|
315
|
-
|
|
316
|
-
block_info[AVG_BLOCK_SAMPLE_SIZE_KEY] = sample_size
|
|
317
|
-
if sample_size != 0:
|
|
318
|
-
block_info[AVG_BLOCK_TIME_KEY] = (
|
|
319
|
-
latest_block["timestamp"] - ancestor_block["timestamp"]
|
|
320
|
-
) / sample_size
|
|
321
|
-
else:
|
|
322
|
-
block_info[AVG_BLOCK_TIME_KEY] = avg_block_time
|
|
323
|
-
block_info[AVG_BLOCK_TIME_UPDATED_AT_KEY] = time.time()
|
|
324
|
-
|
|
325
|
-
if "latest_block" in block_info:
|
|
326
|
-
latest_block = block_info["latest_block"]
|
|
327
|
-
time_since_latest_block = time.time() - latest_block["timestamp"]
|
|
328
|
-
|
|
329
|
-
# latest block is too old so update cache
|
|
330
|
-
if time_since_latest_block > avg_block_time:
|
|
331
|
-
block_info["latest_block"] = w3.eth.get_block("latest")
|
|
332
|
-
else:
|
|
333
|
-
# latest block has not been fetched so we fetch it.
|
|
334
|
-
block_info["latest_block"] = w3.eth.get_block("latest")
|
|
335
|
-
|
|
336
|
-
lock = threading.Lock()
|
|
337
|
-
|
|
338
|
-
def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
339
|
-
lock_acquired = (
|
|
340
|
-
lock.acquire(blocking=False) if method in rpc_whitelist else False
|
|
341
|
-
)
|
|
342
|
-
|
|
343
|
-
try:
|
|
344
|
-
should_try_cache = (
|
|
345
|
-
lock_acquired
|
|
346
|
-
and method in rpc_whitelist
|
|
347
|
-
and not _is_latest_block_number_request(method, params)
|
|
348
|
-
)
|
|
349
|
-
if should_try_cache:
|
|
350
|
-
_update_block_info_cache()
|
|
351
|
-
latest_block_hash = block_info["latest_block"]["hash"]
|
|
352
|
-
cache_key = generate_cache_key((latest_block_hash, method, params))
|
|
353
|
-
if cache_key in cache:
|
|
354
|
-
return cache[cache_key]
|
|
355
|
-
|
|
356
|
-
response = make_request(method, params)
|
|
357
|
-
if should_cache_fn(method, params, response):
|
|
358
|
-
cache[cache_key] = response
|
|
359
|
-
return response
|
|
360
|
-
else:
|
|
361
|
-
return make_request(method, params)
|
|
362
|
-
finally:
|
|
363
|
-
if lock_acquired:
|
|
364
|
-
lock.release()
|
|
365
|
-
|
|
366
|
-
return middleware
|
|
367
|
-
|
|
368
|
-
return latest_block_based_cache_middleware
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
_latest_block_based_cache_middleware = construct_latest_block_based_cache_middleware(
|
|
372
|
-
cache_class=functools.partial(lru.LRU, 256),
|
|
373
|
-
rpc_whitelist=BLOCK_NUMBER_RPC_WHITELIST,
|
|
374
|
-
)
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
from typing import (
|
|
2
|
-
TYPE_CHECKING,
|
|
3
|
-
Any,
|
|
4
|
-
Callable,
|
|
5
|
-
Dict,
|
|
6
|
-
Optional,
|
|
7
|
-
Tuple,
|
|
8
|
-
Type,
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
from eth_utils.toolz import (
|
|
12
|
-
excepts,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
from web3.types import (
|
|
16
|
-
Middleware,
|
|
17
|
-
RPCEndpoint,
|
|
18
|
-
RPCResponse,
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
if TYPE_CHECKING:
|
|
22
|
-
from web3 import Web3 # noqa: F401
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def construct_exception_handler_middleware(
|
|
26
|
-
method_handlers: Optional[
|
|
27
|
-
Dict[RPCEndpoint, Tuple[Type[BaseException], Callable[..., None]]]
|
|
28
|
-
] = None
|
|
29
|
-
) -> Middleware:
|
|
30
|
-
if method_handlers is None:
|
|
31
|
-
method_handlers = {}
|
|
32
|
-
|
|
33
|
-
def exception_handler_middleware(
|
|
34
|
-
make_request: Callable[[RPCEndpoint, Any], Any], w3: "Web3"
|
|
35
|
-
) -> Callable[[RPCEndpoint, Any], RPCResponse]:
|
|
36
|
-
def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
|
|
37
|
-
if method in method_handlers:
|
|
38
|
-
exc_type, handler = method_handlers[method]
|
|
39
|
-
return excepts(
|
|
40
|
-
exc_type,
|
|
41
|
-
make_request,
|
|
42
|
-
handler,
|
|
43
|
-
)(method, params)
|
|
44
|
-
else:
|
|
45
|
-
return make_request(method, params)
|
|
46
|
-
|
|
47
|
-
return middleware
|
|
48
|
-
|
|
49
|
-
return exception_handler_middleware
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import time
|
|
3
|
-
from typing import (
|
|
4
|
-
TYPE_CHECKING,
|
|
5
|
-
Any,
|
|
6
|
-
Callable,
|
|
7
|
-
Collection,
|
|
8
|
-
List,
|
|
9
|
-
Optional,
|
|
10
|
-
Type,
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
import aiohttp
|
|
14
|
-
from requests.exceptions import (
|
|
15
|
-
ConnectionError,
|
|
16
|
-
HTTPError,
|
|
17
|
-
Timeout,
|
|
18
|
-
TooManyRedirects,
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
from web3.types import (
|
|
22
|
-
AsyncMiddlewareCoroutine,
|
|
23
|
-
RPCEndpoint,
|
|
24
|
-
RPCResponse,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
if TYPE_CHECKING:
|
|
28
|
-
from web3 import ( # noqa: F401
|
|
29
|
-
AsyncWeb3,
|
|
30
|
-
Web3,
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
DEFAULT_ALLOWLIST = [
|
|
34
|
-
"admin",
|
|
35
|
-
"miner",
|
|
36
|
-
"net",
|
|
37
|
-
"txpool",
|
|
38
|
-
"testing",
|
|
39
|
-
"evm",
|
|
40
|
-
"eth_protocolVersion",
|
|
41
|
-
"eth_syncing",
|
|
42
|
-
"eth_coinbase",
|
|
43
|
-
"eth_mining",
|
|
44
|
-
"eth_hashrate",
|
|
45
|
-
"eth_chainId",
|
|
46
|
-
"eth_gasPrice",
|
|
47
|
-
"eth_accounts",
|
|
48
|
-
"eth_blockNumber",
|
|
49
|
-
"eth_getBalance",
|
|
50
|
-
"eth_getStorageAt",
|
|
51
|
-
"eth_getProof",
|
|
52
|
-
"eth_getCode",
|
|
53
|
-
"eth_getBlockByNumber",
|
|
54
|
-
"eth_getBlockByHash",
|
|
55
|
-
"eth_getBlockTransactionCountByNumber",
|
|
56
|
-
"eth_getBlockTransactionCountByHash",
|
|
57
|
-
"eth_getUncleCountByBlockNumber",
|
|
58
|
-
"eth_getUncleCountByBlockHash",
|
|
59
|
-
"eth_getTransactionByHash",
|
|
60
|
-
"eth_getTransactionByBlockHashAndIndex",
|
|
61
|
-
"eth_getTransactionByBlockNumberAndIndex",
|
|
62
|
-
"eth_getTransactionReceipt",
|
|
63
|
-
"eth_getTransactionCount",
|
|
64
|
-
"eth_getRawTransactionByHash",
|
|
65
|
-
"eth_call",
|
|
66
|
-
"eth_createAccessList",
|
|
67
|
-
"eth_estimateGas",
|
|
68
|
-
"eth_maxPriorityFeePerGas",
|
|
69
|
-
"eth_newBlockFilter",
|
|
70
|
-
"eth_newPendingTransactionFilter",
|
|
71
|
-
"eth_newFilter",
|
|
72
|
-
"eth_getFilterChanges",
|
|
73
|
-
"eth_getFilterLogs",
|
|
74
|
-
"eth_getLogs",
|
|
75
|
-
"eth_uninstallFilter",
|
|
76
|
-
"eth_getCompilers",
|
|
77
|
-
"eth_getWork",
|
|
78
|
-
"eth_sign",
|
|
79
|
-
"eth_signTypedData",
|
|
80
|
-
"eth_sendRawTransaction",
|
|
81
|
-
"personal_importRawKey",
|
|
82
|
-
"personal_newAccount",
|
|
83
|
-
"personal_listAccounts",
|
|
84
|
-
"personal_listWallets",
|
|
85
|
-
"personal_lockAccount",
|
|
86
|
-
"personal_unlockAccount",
|
|
87
|
-
"personal_ecRecover",
|
|
88
|
-
"personal_sign",
|
|
89
|
-
"personal_signTypedData",
|
|
90
|
-
]
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def check_if_retry_on_failure(
|
|
94
|
-
method: str, allow_list: Optional[List[str]] = None
|
|
95
|
-
) -> bool:
|
|
96
|
-
if allow_list is None:
|
|
97
|
-
allow_list = DEFAULT_ALLOWLIST
|
|
98
|
-
|
|
99
|
-
root = method.split("_")[0]
|
|
100
|
-
if root in allow_list:
|
|
101
|
-
return True
|
|
102
|
-
elif method in allow_list:
|
|
103
|
-
return True
|
|
104
|
-
else:
|
|
105
|
-
return False
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def exception_retry_middleware(
|
|
109
|
-
make_request: Callable[[RPCEndpoint, Any], RPCResponse],
|
|
110
|
-
_w3: "Web3",
|
|
111
|
-
errors: Collection[Type[BaseException]],
|
|
112
|
-
retries: int = 5,
|
|
113
|
-
backoff_factor: float = 0.3,
|
|
114
|
-
allow_list: Optional[List[str]] = None,
|
|
115
|
-
) -> Callable[[RPCEndpoint, Any], RPCResponse]:
|
|
116
|
-
"""
|
|
117
|
-
Creates middleware that retries failed HTTP requests. Is a default
|
|
118
|
-
middleware for HTTPProvider.
|
|
119
|
-
"""
|
|
120
|
-
|
|
121
|
-
def middleware(method: RPCEndpoint, params: Any) -> Optional[RPCResponse]:
|
|
122
|
-
if check_if_retry_on_failure(method, allow_list):
|
|
123
|
-
for i in range(retries):
|
|
124
|
-
try:
|
|
125
|
-
return make_request(method, params)
|
|
126
|
-
except tuple(errors):
|
|
127
|
-
if i < retries - 1:
|
|
128
|
-
time.sleep(backoff_factor)
|
|
129
|
-
continue
|
|
130
|
-
else:
|
|
131
|
-
raise
|
|
132
|
-
return None
|
|
133
|
-
else:
|
|
134
|
-
return make_request(method, params)
|
|
135
|
-
|
|
136
|
-
return middleware
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
def http_retry_request_middleware(
|
|
140
|
-
make_request: Callable[[RPCEndpoint, Any], Any], w3: "Web3"
|
|
141
|
-
) -> Callable[[RPCEndpoint, Any], Any]:
|
|
142
|
-
return exception_retry_middleware(
|
|
143
|
-
make_request, w3, (ConnectionError, HTTPError, Timeout, TooManyRedirects)
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
# -- async -- #
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
async def async_exception_retry_middleware(
|
|
151
|
-
make_request: Callable[[RPCEndpoint, Any], Any],
|
|
152
|
-
_async_w3: "AsyncWeb3",
|
|
153
|
-
errors: Collection[Type[BaseException]],
|
|
154
|
-
retries: int = 5,
|
|
155
|
-
backoff_factor: float = 0.3,
|
|
156
|
-
allow_list: Optional[List[str]] = None,
|
|
157
|
-
) -> AsyncMiddlewareCoroutine:
|
|
158
|
-
"""
|
|
159
|
-
Creates middleware that retries failed HTTP requests.
|
|
160
|
-
Is a default middleware for AsyncHTTPProvider.
|
|
161
|
-
"""
|
|
162
|
-
|
|
163
|
-
async def middleware(method: RPCEndpoint, params: Any) -> Optional[RPCResponse]:
|
|
164
|
-
if check_if_retry_on_failure(method, allow_list):
|
|
165
|
-
for i in range(retries):
|
|
166
|
-
try:
|
|
167
|
-
return await make_request(method, params)
|
|
168
|
-
except tuple(errors):
|
|
169
|
-
if i < retries - 1:
|
|
170
|
-
await asyncio.sleep(backoff_factor)
|
|
171
|
-
continue
|
|
172
|
-
else:
|
|
173
|
-
raise
|
|
174
|
-
return None
|
|
175
|
-
else:
|
|
176
|
-
return await make_request(method, params)
|
|
177
|
-
|
|
178
|
-
return middleware
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
async def async_http_retry_request_middleware(
|
|
182
|
-
make_request: Callable[[RPCEndpoint, Any], Any], async_w3: "AsyncWeb3"
|
|
183
|
-
) -> Callable[[RPCEndpoint, Any], Any]:
|
|
184
|
-
return await async_exception_retry_middleware(
|
|
185
|
-
make_request,
|
|
186
|
-
async_w3,
|
|
187
|
-
(TimeoutError, aiohttp.ClientError),
|
|
188
|
-
)
|