solver-multirpc 3.1.10__py3-none-any.whl → 3.1.11__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/async_multi_rpc_interface.py +9 -7
- multirpc/base_multi_rpc_interface.py +23 -10
- multirpc/constants.py +4 -0
- multirpc/exceptions.py +3 -0
- multirpc/sync_multi_rpc_interface.py +11 -10
- multirpc/utils.py +2 -1
- {solver_multirpc-3.1.10.dist-info → solver_multirpc-3.1.11.dist-info}/METADATA +1 -1
- solver_multirpc-3.1.11.dist-info/RECORD +12 -0
- solver_multirpc-3.1.10.dist-info/RECORD +0 -12
- {solver_multirpc-3.1.10.dist-info → solver_multirpc-3.1.11.dist-info}/WHEEL +0 -0
|
@@ -34,12 +34,13 @@ class AsyncMultiRpc(BaseMultiRpc):
|
|
|
34
34
|
is_proof_authority: bool = False,
|
|
35
35
|
multicall_custom_address: str = None,
|
|
36
36
|
log_level: logging = logging.WARN,
|
|
37
|
-
setup_on_init: bool = True
|
|
37
|
+
setup_on_init: bool = True,
|
|
38
|
+
is_flash_block_aware: Optional[bool] = None
|
|
38
39
|
):
|
|
39
40
|
super().__init__(rpc_urls, contract_address, contract_abi, rpcs_supporting_tx_trace,
|
|
40
41
|
view_policy, gas_estimation, gas_limit,
|
|
41
42
|
gas_upper_bound, apm, enable_estimate_gas_limit,
|
|
42
|
-
is_proof_authority, multicall_custom_address, log_level)
|
|
43
|
+
is_proof_authority, multicall_custom_address, log_level, is_flash_block_aware)
|
|
43
44
|
|
|
44
45
|
for func_abi in self.contract_abi:
|
|
45
46
|
if func_abi.get("stateMutability") in ("view", "pure"):
|
|
@@ -55,13 +56,14 @@ class AsyncMultiRpc(BaseMultiRpc):
|
|
|
55
56
|
if setup_on_init:
|
|
56
57
|
asyncio.run(self.setup())
|
|
57
58
|
|
|
58
|
-
async def get_nonce(self, address: Union[Address, ChecksumAddress, str]
|
|
59
|
-
|
|
59
|
+
async def get_nonce(self, address: Union[Address, ChecksumAddress, str],
|
|
60
|
+
block_identifier: BlockIdentifier = None) -> int:
|
|
61
|
+
return await super()._get_nonce(address, block_identifier)
|
|
60
62
|
|
|
61
63
|
async def get_tx_receipt(self, tx_hash) -> TxReceipt:
|
|
62
64
|
return await super().get_tx_receipt(tx_hash)
|
|
63
65
|
|
|
64
|
-
async def get_block(self, block_identifier: BlockIdentifier =
|
|
66
|
+
async def get_block(self, block_identifier: BlockIdentifier = None,
|
|
65
67
|
full_transactions: bool = False) -> BlockData:
|
|
66
68
|
return await super().get_block(block_identifier, full_transactions)
|
|
67
69
|
|
|
@@ -84,7 +86,7 @@ class AsyncMultiRpc(BaseMultiRpc):
|
|
|
84
86
|
wait_for_receipt: int = 90,
|
|
85
87
|
priority: TxPriority = TxPriority.Low,
|
|
86
88
|
gas_estimation_method: GasEstimationMethod = None,
|
|
87
|
-
block_identifier: Union[str, int] =
|
|
89
|
+
block_identifier: Union[str, int] = None,
|
|
88
90
|
enable_estimate_gas_limit: Optional[bool] = None,
|
|
89
91
|
):
|
|
90
92
|
if self.mr.providers.get(self.typ) is None:
|
|
@@ -110,7 +112,7 @@ class AsyncMultiRpc(BaseMultiRpc):
|
|
|
110
112
|
|
|
111
113
|
async def multicall(
|
|
112
114
|
self,
|
|
113
|
-
block_identifier: Union[str, int] =
|
|
115
|
+
block_identifier: Union[str, int] = None,
|
|
114
116
|
):
|
|
115
117
|
if self.mr.providers.get(self.typ) is None:
|
|
116
118
|
raise DontHaveThisRpcType(f"Doesn't have {self.typ} RPCs")
|
|
@@ -19,12 +19,13 @@ from web3.contract import Contract
|
|
|
19
19
|
from web3.exceptions import BadResponseFormat, BlockNotFound, TimeExhausted, TransactionNotFound, Web3RPCError
|
|
20
20
|
from web3.types import BlockData, BlockIdentifier, TxReceipt
|
|
21
21
|
|
|
22
|
-
from .constants import EstimateGasLimitBuffer, GasLimit, GasUpperBound, MultiRPCLogger,
|
|
22
|
+
from .constants import EstimateGasLimitBuffer, FlashBlockSupportedChains, GasLimit, GasUpperBound, MultiRPCLogger, \
|
|
23
|
+
ViewPolicy
|
|
23
24
|
from .exceptions import (DontHaveThisRpcType, FailedOnAllRPCs, GetBlockFailed, NotValidViewPolicy,
|
|
24
25
|
TransactionFailedStatus, TransactionValueError, Web3InterfaceException)
|
|
25
26
|
from .gas_estimation import GasEstimation, GasEstimationMethod
|
|
26
27
|
from .tx_trace import TxTrace
|
|
27
|
-
from .utils import NestedDict, ResultEvent, TxPriority,
|
|
28
|
+
from .utils import NestedDict, ResultEvent, TxPriority, create_web3_from_rpc, get_chain_id, \
|
|
28
29
|
get_span_proper_label_from_provider, get_unix_time, reduce_list_of_list
|
|
29
30
|
|
|
30
31
|
T = TypeVar("T")
|
|
@@ -49,7 +50,8 @@ class BaseMultiRpc(ABC):
|
|
|
49
50
|
enable_estimate_gas_limit: bool = False,
|
|
50
51
|
is_proof_authority: bool = False,
|
|
51
52
|
multicall_custom_address: str = None,
|
|
52
|
-
log_level: logging = logging.WARN
|
|
53
|
+
log_level: logging = logging.WARN,
|
|
54
|
+
is_flash_block_aware: Optional[bool] = None
|
|
53
55
|
):
|
|
54
56
|
"""
|
|
55
57
|
Args:
|
|
@@ -90,7 +92,7 @@ class BaseMultiRpc(ABC):
|
|
|
90
92
|
self.address = None
|
|
91
93
|
self.private_key = None
|
|
92
94
|
self.chain_id = None
|
|
93
|
-
|
|
95
|
+
self.is_flash_block_aware = is_flash_block_aware
|
|
94
96
|
MultiRPCLogger.setLevel(log_level)
|
|
95
97
|
|
|
96
98
|
def _logger_params(self, **kwargs) -> None:
|
|
@@ -99,6 +101,9 @@ class BaseMultiRpc(ABC):
|
|
|
99
101
|
else:
|
|
100
102
|
MultiRPCLogger.info(f'params={kwargs}')
|
|
101
103
|
|
|
104
|
+
def get_block_identifier(self, block_identifier=None):
|
|
105
|
+
return block_identifier or ('pending' if self.is_flash_block_aware else 'latest')
|
|
106
|
+
|
|
102
107
|
def set_account(self, address: Union[ChecksumAddress, str], private_key: str) -> None:
|
|
103
108
|
"""
|
|
104
109
|
Set public key and private key for sending transactions. If these values set, there is no need to pass address,
|
|
@@ -114,6 +119,11 @@ class BaseMultiRpc(ABC):
|
|
|
114
119
|
self.providers = await create_web3_from_rpc(self.rpc_urls, self.is_proof_authority)
|
|
115
120
|
self.chain_id = await get_chain_id(self.providers)
|
|
116
121
|
|
|
122
|
+
if self.is_flash_block_aware is None:
|
|
123
|
+
self.is_flash_block_aware = self.chain_id in FlashBlockSupportedChains
|
|
124
|
+
|
|
125
|
+
MultiRPCLogger.debug(f"{self.chain_id=}, {self.is_flash_block_aware=}")
|
|
126
|
+
|
|
117
127
|
if self.gas_estimation is None and self.providers.get('transaction'):
|
|
118
128
|
self.gas_estimation = GasEstimation(
|
|
119
129
|
self.chain_id,
|
|
@@ -196,7 +206,7 @@ class BaseMultiRpc(ABC):
|
|
|
196
206
|
|
|
197
207
|
async def _call_view_function(self,
|
|
198
208
|
func_name: str,
|
|
199
|
-
block_identifier: Union[str, int] =
|
|
209
|
+
block_identifier: Union[str, int] = None,
|
|
200
210
|
use_multicall=False,
|
|
201
211
|
*args, **kwargs):
|
|
202
212
|
"""
|
|
@@ -222,6 +232,7 @@ class BaseMultiRpc(ABC):
|
|
|
222
232
|
return results[max_index][2]
|
|
223
233
|
return results[max_index][2][0]
|
|
224
234
|
|
|
235
|
+
block_identifier = self.get_block_identifier(block_identifier)
|
|
225
236
|
last_error = None
|
|
226
237
|
for contracts, multi_calls in zip(self.contracts['view'].values(),
|
|
227
238
|
self.multi_calls['view'].values()): # type: any, List[AsyncMulticall]
|
|
@@ -246,7 +257,8 @@ class BaseMultiRpc(ABC):
|
|
|
246
257
|
last_error = None
|
|
247
258
|
for providers in providers_4_nonce.values():
|
|
248
259
|
execution_list = [
|
|
249
|
-
prov.eth.get_transaction_count(address, block_identifier=block_identifier)
|
|
260
|
+
prov.eth.get_transaction_count(address, block_identifier=self.get_block_identifier(block_identifier))
|
|
261
|
+
for prov in providers
|
|
250
262
|
]
|
|
251
263
|
try:
|
|
252
264
|
return await self.__gather_tasks(execution_list, max)
|
|
@@ -295,7 +307,7 @@ class BaseMultiRpc(ABC):
|
|
|
295
307
|
account: LocalAccount = Account.from_key(signer_private_key)
|
|
296
308
|
if enable_estimate_gas_limit:
|
|
297
309
|
del tx['gas']
|
|
298
|
-
estimate_gas = await provider.eth.estimate_gas(tx)
|
|
310
|
+
estimate_gas = await provider.eth.estimate_gas(tx, block_identifier=self.get_block_identifier())
|
|
299
311
|
MultiRPCLogger.info(f"gas_estimation({estimate_gas} gas needed) is successful")
|
|
300
312
|
return account.sign_transaction({**tx, 'gas': int(estimate_gas * EstimateGasLimitBuffer)})
|
|
301
313
|
return account.sign_transaction(tx)
|
|
@@ -577,14 +589,15 @@ class BaseMultiRpc(ABC):
|
|
|
577
589
|
raise
|
|
578
590
|
raise last_exception
|
|
579
591
|
|
|
580
|
-
async def get_block(self, block_identifier: BlockIdentifier =
|
|
581
|
-
full_transactions: bool = False) -> BlockData:
|
|
592
|
+
async def get_block(self, block_identifier: BlockIdentifier = None, full_transactions: bool = False) -> BlockData:
|
|
582
593
|
self.check_for_view()
|
|
583
594
|
|
|
584
595
|
exceptions = (HTTPError, ConnectionError, ReadTimeout, ValueError, TimeExhausted, BlockNotFound)
|
|
585
596
|
last_exception = None
|
|
586
597
|
for provider in self.providers['view'].values(): # type: List[AsyncWeb3]
|
|
587
|
-
execution_tx_params_list = [
|
|
598
|
+
execution_tx_params_list = [
|
|
599
|
+
p.eth.get_block(self.get_block_identifier(block_identifier), full_transactions) for p in provider
|
|
600
|
+
]
|
|
588
601
|
try:
|
|
589
602
|
return await self.__execute_batch_tasks(
|
|
590
603
|
execution_tx_params_list,
|
multirpc/constants.py
CHANGED
|
@@ -36,6 +36,10 @@ ChainIdToGas = {
|
|
|
36
36
|
GasFromRpcChainIds = [] # for this chain ids use rpc to estimate gas
|
|
37
37
|
FixedValueGas = 30
|
|
38
38
|
|
|
39
|
+
FlashBlockSupportedChains = [
|
|
40
|
+
8453 # base
|
|
41
|
+
]
|
|
42
|
+
|
|
39
43
|
MultiRPCLoggerName = 'Multi-RPC'
|
|
40
44
|
GasEstimationLoggerName = MultiRPCLoggerName + '.Gas-Estimation'
|
|
41
45
|
|
multirpc/exceptions.py
CHANGED
|
@@ -54,6 +54,9 @@ class MaximumRPCInEachBracketReached(Web3InterfaceException):
|
|
|
54
54
|
class AtLastProvideOneValidRPCInEachBracket(Web3InterfaceException):
|
|
55
55
|
pass
|
|
56
56
|
|
|
57
|
+
class AllRPCShouldSupportFlashBlockOrNot(Web3InterfaceException):
|
|
58
|
+
pass
|
|
59
|
+
|
|
57
60
|
|
|
58
61
|
class TransactionValueError(Web3InterfaceException):
|
|
59
62
|
pass
|
|
@@ -34,12 +34,13 @@ class MultiRpc(BaseMultiRpc):
|
|
|
34
34
|
is_proof_authority: bool = False,
|
|
35
35
|
multicall_custom_address: str = None,
|
|
36
36
|
log_level: logging = logging.WARN,
|
|
37
|
-
setup_on_init: bool = True
|
|
37
|
+
setup_on_init: bool = True,
|
|
38
|
+
is_flash_block_aware: Optional[bool] = None
|
|
38
39
|
):
|
|
39
40
|
super().__init__(rpc_urls, contract_address, contract_abi, rpcs_supporting_tx_trace,
|
|
40
41
|
view_policy, gas_estimation, gas_limit,
|
|
41
42
|
gas_upper_bound, apm, enable_estimate_gas_limit,
|
|
42
|
-
is_proof_authority, multicall_custom_address, log_level)
|
|
43
|
+
is_proof_authority, multicall_custom_address, log_level, is_flash_block_aware)
|
|
43
44
|
|
|
44
45
|
for func_abi in self.contract_abi:
|
|
45
46
|
if func_abi.get("stateMutability") in ("view", "pure"):
|
|
@@ -60,15 +61,15 @@ class MultiRpc(BaseMultiRpc):
|
|
|
60
61
|
return asyncio.run(super().setup())
|
|
61
62
|
|
|
62
63
|
@thread_safe
|
|
63
|
-
def get_nonce(self, address: Union[Address, ChecksumAddress, str]) -> int:
|
|
64
|
-
return asyncio.run(super()._get_nonce(address))
|
|
64
|
+
def get_nonce(self, address: Union[Address, ChecksumAddress, str], block_identifier: BlockIdentifier = None) -> int:
|
|
65
|
+
return asyncio.run(super()._get_nonce(address, block_identifier))
|
|
65
66
|
|
|
66
67
|
@thread_safe
|
|
67
68
|
def get_tx_receipt(self, tx_hash) -> TxReceipt:
|
|
68
69
|
return asyncio.run(super().get_tx_receipt(tx_hash))
|
|
69
70
|
|
|
70
71
|
@thread_safe
|
|
71
|
-
def get_block(self, block_identifier: BlockIdentifier =
|
|
72
|
+
def get_block(self, block_identifier: BlockIdentifier = None, full_transactions: bool = False) -> BlockData:
|
|
72
73
|
return asyncio.run(super().get_block(block_identifier, full_transactions))
|
|
73
74
|
|
|
74
75
|
@thread_safe
|
|
@@ -92,7 +93,7 @@ class MultiRpc(BaseMultiRpc):
|
|
|
92
93
|
wait_for_receipt: int = 90,
|
|
93
94
|
priority: TxPriority = TxPriority.Low,
|
|
94
95
|
gas_estimation_method: GasEstimationMethod = None,
|
|
95
|
-
block_identifier: Union[str, int] =
|
|
96
|
+
block_identifier: Union[str, int] = None,
|
|
96
97
|
enable_estimate_gas_limit: Optional[bool] = None,
|
|
97
98
|
use_multicall=False,
|
|
98
99
|
):
|
|
@@ -100,7 +101,7 @@ class MultiRpc(BaseMultiRpc):
|
|
|
100
101
|
raise DontHaveThisRpcType(f"Doesn't have {self.typ} RPCs")
|
|
101
102
|
if self.typ == ContractFunctionType.View:
|
|
102
103
|
return asyncio.run(self.mr._call_view_function(
|
|
103
|
-
self.name, block_identifier, use_multicall, *self.args, **self.kwargs
|
|
104
|
+
self.name, block_identifier, use_multicall, *self.args, **self.kwargs
|
|
104
105
|
))
|
|
105
106
|
elif self.typ == ContractFunctionType.Transaction:
|
|
106
107
|
return asyncio.run(self.mr._call_tx_function(
|
|
@@ -114,13 +115,13 @@ class MultiRpc(BaseMultiRpc):
|
|
|
114
115
|
wait_for_receipt=wait_for_receipt,
|
|
115
116
|
priority=priority,
|
|
116
117
|
gas_estimation_method=gas_estimation_method,
|
|
117
|
-
enable_estimate_gas_limit=enable_estimate_gas_limit
|
|
118
|
+
enable_estimate_gas_limit=enable_estimate_gas_limit,
|
|
118
119
|
))
|
|
119
120
|
|
|
120
121
|
@thread_safe
|
|
121
122
|
def multicall(
|
|
122
123
|
self,
|
|
123
|
-
block_identifier: Union[str, int] =
|
|
124
|
+
block_identifier: Union[str, int] = None,
|
|
124
125
|
):
|
|
125
126
|
if self.mr.providers.get(self.typ) is None:
|
|
126
127
|
raise DontHaveThisRpcType(f"Doesn't have {self.typ} RPCs")
|
|
@@ -128,7 +129,7 @@ class MultiRpc(BaseMultiRpc):
|
|
|
128
129
|
raise KwargsNotSupportedInMultiCall
|
|
129
130
|
if self.typ == ContractFunctionType.View:
|
|
130
131
|
return asyncio.run(self.mr._call_view_function(
|
|
131
|
-
self.name, block_identifier, True, *self.args, **self.kwargs
|
|
132
|
+
self.name, block_identifier, True, *self.args, **self.kwargs
|
|
132
133
|
))
|
|
133
134
|
elif self.typ == ContractFunctionType.Transaction:
|
|
134
135
|
raise TransactionTypeNotSupportedInMultiCall
|
multirpc/utils.py
CHANGED
|
@@ -17,7 +17,8 @@ from web3._utils.http_session_manager import HTTPSessionManager
|
|
|
17
17
|
from web3.middleware import ExtraDataToPOAMiddleware
|
|
18
18
|
|
|
19
19
|
from .constants import MaxRPCInEachBracket, MultiRPCLogger
|
|
20
|
-
from .exceptions import AtLastProvideOneValidRPCInEachBracket,
|
|
20
|
+
from .exceptions import AtLastProvideOneValidRPCInEachBracket, \
|
|
21
|
+
MaximumRPCInEachBracketReached
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
def get_span_proper_label_from_provider(endpoint_uri):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: solver-multirpc
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.11
|
|
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
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
multirpc/__init__.py,sha256=f7h3txKkb_WQX6u-PzbgMpHt1VGqA0OjhrSe4Vdsk5I,100
|
|
2
|
+
multirpc/async_multi_rpc_interface.py,sha256=NTwdOyMbghekredlYR64kr0eiPRxzvUirGBZpFzRgig,5699
|
|
3
|
+
multirpc/base_multi_rpc_interface.py,sha256=9TPQABrutwe8yHu05Nt5Uv5_jZlMdlu8XyY1PIQoUiU,29238
|
|
4
|
+
multirpc/constants.py,sha256=B21pS85Vnm65vvjt25_9TTxviRHYCUlgpIDGOrs1rmg,1262
|
|
5
|
+
multirpc/exceptions.py,sha256=Tfi4aHeOiH1OaYeNBEDX3fJNAUyPgs42VXrRG62IgJs,1937
|
|
6
|
+
multirpc/gas_estimation.py,sha256=k0FVO9FgSRuRQhEkQ9YZZ-rSpW_zxaLLFdMAYOF3xco,7276
|
|
7
|
+
multirpc/sync_multi_rpc_interface.py,sha256=Zs3FVSGNJDhrFBi3m9sn4pMuYGzLwaiz0qy_R9VIo04,5888
|
|
8
|
+
multirpc/tx_trace.py,sha256=G7sTVMzALtTeC1F2JjxMSGRRFlmAAZG-Sdhd4UQtfw8,7885
|
|
9
|
+
multirpc/utils.py,sha256=bhrP15IY_TOB1dK8HP35rRxs9FIIWKoSUY6EVOA4FEA,9073
|
|
10
|
+
solver_multirpc-3.1.11.dist-info/METADATA,sha256=6AwwApO4kTI_q0SDqCKh4rb9wmi3IBj66oISHIwz2t4,8287
|
|
11
|
+
solver_multirpc-3.1.11.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
12
|
+
solver_multirpc-3.1.11.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
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=PHQFRLIfXvEIixu8IwOc9EKKviSRxkCmZxD6saYr5tw,28546
|
|
4
|
-
multirpc/constants.py,sha256=h0njFnxTtWU8-NO_3q7sMrLAqQAv4JxM3nZcc2WOqEc,1210
|
|
5
|
-
multirpc/exceptions.py,sha256=acoy8mjlAth-r0sJ5PJCTI2xOS4LAROdnPDCxLu0oLs,1861
|
|
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=V0hosPMFqsvZy1OtWUOR-4xk1U4bPmGUfviBivygZJw,9067
|
|
10
|
-
solver_multirpc-3.1.10.dist-info/METADATA,sha256=lgSPN5WKGOcFHhKAtec-IfhgoQELWItw5oWmz7QAY9A,8287
|
|
11
|
-
solver_multirpc-3.1.10.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
12
|
-
solver_multirpc-3.1.10.dist-info/RECORD,,
|
|
File without changes
|