solver-multirpc 3.1.6__py3-none-any.whl → 3.1.7__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.
- multirpc/__init__.py +2 -1
- multirpc/async_multi_rpc_interface.py +3 -4
- multirpc/base_multi_rpc_interface.py +3 -3
- multirpc/sync_multi_rpc_interface.py +3 -4
- multirpc/utils.py +57 -9
- {solver_multirpc-3.1.6.dist-info → solver_multirpc-3.1.7.dist-info}/METADATA +2 -3
- solver_multirpc-3.1.7.dist-info/RECORD +12 -0
- solver_multirpc-3.1.6.dist-info/RECORD +0 -12
- {solver_multirpc-3.1.6.dist-info → solver_multirpc-3.1.7.dist-info}/WHEEL +0 -0
multirpc/__init__.py
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
from .
|
|
1
|
+
from .sync_multi_rpc_interface import MultiRpc
|
|
2
|
+
from .async_multi_rpc_interface import AsyncMultiRpc
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import List, Optional, Union
|
|
4
4
|
|
|
5
5
|
from eth_typing import Address, ChecksumAddress
|
|
6
6
|
from web3._utils.contracts import encode_transaction_data # noqa
|
|
7
7
|
from web3.types import BlockData, BlockIdentifier, TxReceipt
|
|
8
8
|
|
|
9
|
-
from . import BaseMultiRpc
|
|
10
|
-
from .base_multi_rpc_interface import BaseContractFunction
|
|
9
|
+
from .base_multi_rpc_interface import BaseContractFunction, BaseMultiRpc
|
|
11
10
|
from .constants import GasLimit, GasUpperBound, ViewPolicy
|
|
12
11
|
from .exceptions import DontHaveThisRpcType, KwargsNotSupportedInMultiCall, TransactionTypeNotSupportedInMultiCall
|
|
13
12
|
from .gas_estimation import GasEstimation, GasEstimationMethod
|
|
@@ -24,7 +23,7 @@ class AsyncMultiRpc(BaseMultiRpc):
|
|
|
24
23
|
self,
|
|
25
24
|
rpc_urls: NestedDict,
|
|
26
25
|
contract_address: Union[Address, ChecksumAddress, str],
|
|
27
|
-
contract_abi:
|
|
26
|
+
contract_abi: list,
|
|
28
27
|
rpcs_supporting_tx_trace: Optional[List[str]] = None,
|
|
29
28
|
view_policy: ViewPolicy = ViewPolicy.MostUpdated,
|
|
30
29
|
gas_estimation: Optional[GasEstimation] = None,
|
|
@@ -24,7 +24,7 @@ from .exceptions import (DontHaveThisRpcType, FailedOnAllRPCs, GetBlockFailed, N
|
|
|
24
24
|
TransactionFailedStatus, TransactionValueError, Web3InterfaceException)
|
|
25
25
|
from .gas_estimation import GasEstimation, GasEstimationMethod
|
|
26
26
|
from .tx_trace import TxTrace
|
|
27
|
-
from .utils import NestedDict, ResultEvent, TxPriority,
|
|
27
|
+
from .utils import NestedDict, ResultEvent, TxPriority, get_chain_id, create_web3_from_rpc, \
|
|
28
28
|
get_span_proper_label_from_provider, get_unix_time, reduce_list_of_list
|
|
29
29
|
|
|
30
30
|
T = TypeVar("T")
|
|
@@ -39,7 +39,7 @@ class BaseMultiRpc(ABC):
|
|
|
39
39
|
self,
|
|
40
40
|
rpc_urls: NestedDict,
|
|
41
41
|
contract_address: Union[Address, ChecksumAddress, str],
|
|
42
|
-
contract_abi:
|
|
42
|
+
contract_abi: list,
|
|
43
43
|
rpcs_supporting_tx_trace: Optional[List[str]] = None,
|
|
44
44
|
view_policy: ViewPolicy = ViewPolicy.MostUpdated,
|
|
45
45
|
gas_estimation: Optional[GasEstimation] = None,
|
|
@@ -112,7 +112,7 @@ class BaseMultiRpc(ABC):
|
|
|
112
112
|
|
|
113
113
|
async def setup(self) -> None:
|
|
114
114
|
self.providers = await create_web3_from_rpc(self.rpc_urls, self.is_proof_authority)
|
|
115
|
-
self.chain_id = await
|
|
115
|
+
self.chain_id = await get_chain_id(self.providers)
|
|
116
116
|
|
|
117
117
|
if self.gas_estimation is None and self.providers.get('transaction'):
|
|
118
118
|
self.gas_estimation = GasEstimation(
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import List, Optional, Union
|
|
4
4
|
|
|
5
5
|
from eth_typing import Address, ChecksumAddress
|
|
6
6
|
from web3._utils.contracts import encode_transaction_data # noqa
|
|
7
7
|
from web3.types import BlockData, BlockIdentifier, TxReceipt
|
|
8
8
|
|
|
9
|
-
from . import BaseMultiRpc
|
|
10
|
-
from .base_multi_rpc_interface import BaseContractFunction
|
|
9
|
+
from .base_multi_rpc_interface import BaseContractFunction, BaseMultiRpc
|
|
11
10
|
from .constants import GasLimit, GasUpperBound, ViewPolicy
|
|
12
11
|
from .exceptions import DontHaveThisRpcType, KwargsNotSupportedInMultiCall, TransactionTypeNotSupportedInMultiCall
|
|
13
12
|
from .gas_estimation import GasEstimation, GasEstimationMethod
|
|
@@ -24,7 +23,7 @@ class MultiRpc(BaseMultiRpc):
|
|
|
24
23
|
self,
|
|
25
24
|
rpc_urls: NestedDict,
|
|
26
25
|
contract_address: Union[Address, ChecksumAddress, str],
|
|
27
|
-
contract_abi:
|
|
26
|
+
contract_abi: list,
|
|
28
27
|
rpcs_supporting_tx_trace: Optional[List[str]] = None,
|
|
29
28
|
view_policy: ViewPolicy = ViewPolicy.MostUpdated,
|
|
30
29
|
gas_estimation: Optional[GasEstimation] = None,
|
multirpc/utils.py
CHANGED
|
@@ -9,12 +9,12 @@ from threading import Thread
|
|
|
9
9
|
from typing import Any, Dict, List, Tuple, Union
|
|
10
10
|
|
|
11
11
|
import aiohttp.client_exceptions
|
|
12
|
-
from aiohttp import ClientTimeout
|
|
12
|
+
from aiohttp import ClientSession, ClientTimeout
|
|
13
13
|
from eth_typing import URI
|
|
14
14
|
from web3 import AsyncHTTPProvider, AsyncWeb3, Web3, WebSocketProvider
|
|
15
15
|
from web3._utils.http import DEFAULT_HTTP_TIMEOUT
|
|
16
16
|
from web3._utils.http_session_manager import HTTPSessionManager
|
|
17
|
-
from web3.middleware import ExtraDataToPOAMiddleware
|
|
17
|
+
from web3.middleware import ExtraDataToPOAMiddleware, Web3Middleware
|
|
18
18
|
|
|
19
19
|
from .constants import MaxRPCInEachBracket, MultiRPCLogger
|
|
20
20
|
from .exceptions import AtLastProvideOneValidRPCInEachBracket, MaximumRPCInEachBracketReached
|
|
@@ -156,9 +156,11 @@ class MultiRpcHTTPSessionManager(HTTPSessionManager):
|
|
|
156
156
|
self, endpoint_uri: URI, data: Union[bytes, Dict[str, Any]], **kwargs: Any
|
|
157
157
|
) -> bytes:
|
|
158
158
|
kwargs.setdefault("timeout", ClientTimeout(DEFAULT_HTTP_TIMEOUT))
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
|
|
160
|
+
session = ClientSession(raise_for_status=True)
|
|
161
|
+
# session = await self.async_cache_and_return_session( # fixme: original code
|
|
162
|
+
# endpoint_uri, request_timeout=kwargs["timeout"]
|
|
163
|
+
# )
|
|
162
164
|
|
|
163
165
|
try:
|
|
164
166
|
self.logger.debug(f'making post request, {endpoint_uri=}, {kwargs=}')
|
|
@@ -174,9 +176,12 @@ class MultiRpcHTTPSessionManager(HTTPSessionManager):
|
|
|
174
176
|
self, endpoint_uri: URI, *args: Any, **kwargs: Any
|
|
175
177
|
) -> Dict[str, Any]:
|
|
176
178
|
kwargs.setdefault("timeout", ClientTimeout(DEFAULT_HTTP_TIMEOUT))
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
179
|
+
|
|
180
|
+
session = ClientSession(raise_for_status=True)
|
|
181
|
+
# session = await self.async_cache_and_return_session( # fixme: original code
|
|
182
|
+
# endpoint_uri, request_timeout=kwargs["timeout"]
|
|
183
|
+
# )
|
|
184
|
+
|
|
180
185
|
try:
|
|
181
186
|
response = await session.get(endpoint_uri, *args, **kwargs)
|
|
182
187
|
response.raise_for_status()
|
|
@@ -197,6 +202,48 @@ class MultiRpcAsyncHTTPProvider(AsyncHTTPProvider):
|
|
|
197
202
|
self._request_session_manager = MultiRpcHTTPSessionManager()
|
|
198
203
|
|
|
199
204
|
|
|
205
|
+
class SimpleCacheMiddleware(Web3Middleware):
|
|
206
|
+
rpc_whitelist = {
|
|
207
|
+
"web3_clientVersion",
|
|
208
|
+
"net_version",
|
|
209
|
+
"eth_chainId",
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
def __init__(self, w3):
|
|
213
|
+
super().__init__(w3)
|
|
214
|
+
self.cache = {}
|
|
215
|
+
|
|
216
|
+
def wrap_make_request(self, make_request):
|
|
217
|
+
def middleware(method, params: Any):
|
|
218
|
+
cache_key = (method, tuple(params))
|
|
219
|
+
if method in self.rpc_whitelist and cache_key in self.cache:
|
|
220
|
+
return self.cache[cache_key] # Return cached response
|
|
221
|
+
|
|
222
|
+
response = make_request(method, params) # Make actual RPC request
|
|
223
|
+
|
|
224
|
+
if method in self.rpc_whitelist:
|
|
225
|
+
self.cache[cache_key] = response # Store response in cache
|
|
226
|
+
|
|
227
|
+
return response
|
|
228
|
+
|
|
229
|
+
return middleware
|
|
230
|
+
|
|
231
|
+
async def async_wrap_make_request(self, make_request):
|
|
232
|
+
async def middleware(method, params: Any):
|
|
233
|
+
cache_key = (method, tuple(params))
|
|
234
|
+
if method in self.rpc_whitelist and cache_key in self.cache:
|
|
235
|
+
return self.cache[cache_key] # Return cached response
|
|
236
|
+
|
|
237
|
+
response = await make_request(method, params) # Make actual RPC request
|
|
238
|
+
|
|
239
|
+
if method in self.rpc_whitelist:
|
|
240
|
+
self.cache[cache_key] = response # Store response in cache
|
|
241
|
+
|
|
242
|
+
return response
|
|
243
|
+
|
|
244
|
+
return middleware
|
|
245
|
+
|
|
246
|
+
|
|
200
247
|
async def create_web3_from_rpc(rpc_urls: NestedDict, is_proof_of_authority: bool) -> NestedDict:
|
|
201
248
|
async def create_web3(rpc_: str):
|
|
202
249
|
async_w3: AsyncWeb3
|
|
@@ -206,6 +253,7 @@ async def create_web3_from_rpc(rpc_urls: NestedDict, is_proof_of_authority: bool
|
|
|
206
253
|
async_w3 = AsyncWeb3(WebSocketProvider(rpc_))
|
|
207
254
|
if is_proof_of_authority:
|
|
208
255
|
async_w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
|
|
256
|
+
async_w3.middleware_onion.add(SimpleCacheMiddleware, 'simple_cache')
|
|
209
257
|
try:
|
|
210
258
|
status = await async_w3.is_connected()
|
|
211
259
|
except (asyncio.exceptions.TimeoutError, aiohttp.client_exceptions.ClientResponseError):
|
|
@@ -234,7 +282,7 @@ async def create_web3_from_rpc(rpc_urls: NestedDict, is_proof_of_authority: bool
|
|
|
234
282
|
return providers
|
|
235
283
|
|
|
236
284
|
|
|
237
|
-
async def
|
|
285
|
+
async def get_chain_id(providers: NestedDict) -> int:
|
|
238
286
|
last_error = None
|
|
239
287
|
for key, providers in providers.items():
|
|
240
288
|
for provider in providers:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: solver-multirpc
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.7
|
|
4
4
|
Summary: A robust Python library for interacting with Ethereum smart contracts via multiple RPC endpoints, ensuring reliability, availability, and load distribution with automatic retries on failure.
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: rorschach
|
|
@@ -52,7 +52,7 @@ Below is an example of how to use the AsyncMultiRpc class for asynchronous opera
|
|
|
52
52
|
import asyncio
|
|
53
53
|
import json
|
|
54
54
|
from multirpc.utils import NestedDict
|
|
55
|
-
from multirpc
|
|
55
|
+
from multirpc import AsyncMultiRpc
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
async def main():
|
|
@@ -198,7 +198,6 @@ Here is an example:
|
|
|
198
198
|
```python
|
|
199
199
|
from multirpc import GasEstimation, TxPriority, GasEstimationMethod
|
|
200
200
|
from web3 import Web3
|
|
201
|
-
from web3.types import Wei
|
|
202
201
|
|
|
203
202
|
|
|
204
203
|
class CustomGasEstimation(GasEstimation):
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
multirpc/__init__.py,sha256=f7h3txKkb_WQX6u-PzbgMpHt1VGqA0OjhrSe4Vdsk5I,100
|
|
2
|
+
multirpc/async_multi_rpc_interface.py,sha256=2YyGXst5jyxZ7ro7z7qeOAF2wKC4JEgbwkR-ADCa-9w,5548
|
|
3
|
+
multirpc/base_multi_rpc_interface.py,sha256=I6WP0e3hcJ1IMVipuWdrZFNjoZBdL4BGZ4eXQVT11oI,28502
|
|
4
|
+
multirpc/constants.py,sha256=h0njFnxTtWU8-NO_3q7sMrLAqQAv4JxM3nZcc2WOqEc,1210
|
|
5
|
+
multirpc/exceptions.py,sha256=V8WDmDWeeTLQ1TOJ9_IWXt0z-qefJiDfQ6pAdhuwdcA,1785
|
|
6
|
+
multirpc/gas_estimation.py,sha256=k0FVO9FgSRuRQhEkQ9YZZ-rSpW_zxaLLFdMAYOF3xco,7276
|
|
7
|
+
multirpc/sync_multi_rpc_interface.py,sha256=T9x5bLbLJF_1XorkkDqzc8pZmbdNs6OE9trGjVWQBdg,5762
|
|
8
|
+
multirpc/tx_trace.py,sha256=G7sTVMzALtTeC1F2JjxMSGRRFlmAAZG-Sdhd4UQtfw8,7885
|
|
9
|
+
multirpc/utils.py,sha256=ZyFzFT6UDSaMRV_F_fXHyCMm1-jRcPvV_oX1NAtwPek,10212
|
|
10
|
+
solver_multirpc-3.1.7.dist-info/METADATA,sha256=e95fhgu4DJIyuq92GH0toEkwS9LI9XYX6T16Goyc3tM,8286
|
|
11
|
+
solver_multirpc-3.1.7.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
12
|
+
solver_multirpc-3.1.7.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
multirpc/__init__.py,sha256=uZJfs4NxerMAEVi_FX15MO5RCc1o15i_kYECoPp43ec,51
|
|
2
|
-
multirpc/async_multi_rpc_interface.py,sha256=8W3V3HfrlVbI6DGNkxRw1ZuduM6t24MObLIKh6Zq1ZU,5567
|
|
3
|
-
multirpc/base_multi_rpc_interface.py,sha256=aMIXXX5S-UvXiNBqr1EUxMngHO_dgJL7v2J9lqJ2zdU,28514
|
|
4
|
-
multirpc/constants.py,sha256=h0njFnxTtWU8-NO_3q7sMrLAqQAv4JxM3nZcc2WOqEc,1210
|
|
5
|
-
multirpc/exceptions.py,sha256=V8WDmDWeeTLQ1TOJ9_IWXt0z-qefJiDfQ6pAdhuwdcA,1785
|
|
6
|
-
multirpc/gas_estimation.py,sha256=k0FVO9FgSRuRQhEkQ9YZZ-rSpW_zxaLLFdMAYOF3xco,7276
|
|
7
|
-
multirpc/sync_multi_rpc_interface.py,sha256=6zKEtuXq7Uy7MDEe7nM-ifdpMZNrRYbIIsJSxiRVW_Q,5781
|
|
8
|
-
multirpc/tx_trace.py,sha256=G7sTVMzALtTeC1F2JjxMSGRRFlmAAZG-Sdhd4UQtfw8,7885
|
|
9
|
-
multirpc/utils.py,sha256=YYX628ZAsNf3nuY4XicsxtHs69WKYl0kX2Uh--Xpj5o,8586
|
|
10
|
-
solver_multirpc-3.1.6.dist-info/METADATA,sha256=JQlH_vWFxJf7hriNUCYwTRElhD8ERMHiA_ZtRwvxBMo,8339
|
|
11
|
-
solver_multirpc-3.1.6.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
12
|
-
solver_multirpc-3.1.6.dist-info/RECORD,,
|
|
File without changes
|