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 CHANGED
@@ -1 +1,2 @@
1
- from .base_multi_rpc_interface import BaseMultiRpc
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 Dict, List, Optional, Union
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: Dict,
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, calculate_chain_id, create_web3_from_rpc, \
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: Dict,
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 calculate_chain_id(self.providers)
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 Dict, List, Optional, Union
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: Dict,
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
- session = await self.async_cache_and_return_session(
160
- endpoint_uri, request_timeout=kwargs["timeout"]
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
- session = await self.async_cache_and_return_session(
178
- endpoint_uri, request_timeout=kwargs["timeout"]
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 calculate_chain_id(providers: NestedDict) -> int:
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.6
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.async_multi_rpc_interface import AsyncMultiRpc
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,,