solver-multirpc 3.1.4__tar.gz → 3.1.5__tar.gz
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.
- {solver_multirpc-3.1.4 → solver_multirpc-3.1.5}/PKG-INFO +3 -3
- {solver_multirpc-3.1.4 → solver_multirpc-3.1.5}/README.md +2 -2
- {solver_multirpc-3.1.4/src → solver_multirpc-3.1.5}/multirpc/exceptions.py +1 -1
- {solver_multirpc-3.1.4/src → solver_multirpc-3.1.5}/multirpc/tx_trace.py +1 -1
- {solver_multirpc-3.1.4 → solver_multirpc-3.1.5}/pyproject.toml +2 -2
- solver_multirpc-3.1.4/src/__init__.py +0 -0
- solver_multirpc-3.1.4/src/tests/__init__.py +0 -0
- solver_multirpc-3.1.4/src/tests/abi.json +0 -34
- solver_multirpc-3.1.4/src/tests/constants.py +0 -78
- solver_multirpc-3.1.4/src/tests/contract.sol +0 -16
- solver_multirpc-3.1.4/src/tests/test.py +0 -138
- solver_multirpc-3.1.4/src/tests/test_settings.py.example +0 -7
- {solver_multirpc-3.1.4/src → solver_multirpc-3.1.5}/multirpc/__init__.py +0 -0
- {solver_multirpc-3.1.4/src → solver_multirpc-3.1.5}/multirpc/async_multi_rpc_interface.py +0 -0
- {solver_multirpc-3.1.4/src → solver_multirpc-3.1.5}/multirpc/base_multi_rpc_interface.py +0 -0
- {solver_multirpc-3.1.4/src → solver_multirpc-3.1.5}/multirpc/constants.py +0 -0
- {solver_multirpc-3.1.4/src → solver_multirpc-3.1.5}/multirpc/gas_estimation.py +0 -0
- {solver_multirpc-3.1.4/src → solver_multirpc-3.1.5}/multirpc/sync_multi_rpc_interface.py +0 -0
- {solver_multirpc-3.1.4/src → solver_multirpc-3.1.5}/multirpc/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: solver-multirpc
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.5
|
|
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
|
|
@@ -51,8 +51,8 @@ Below is an example of how to use the AsyncMultiRpc class for asynchronous opera
|
|
|
51
51
|
```python
|
|
52
52
|
import asyncio
|
|
53
53
|
import json
|
|
54
|
-
from
|
|
55
|
-
from multirpc import AsyncMultiRpc
|
|
54
|
+
from multirpc.utils import NestedDict
|
|
55
|
+
from multirpc.async_multi_rpc_interface import AsyncMultiRpc
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
async def main():
|
|
@@ -32,8 +32,8 @@ Below is an example of how to use the AsyncMultiRpc class for asynchronous opera
|
|
|
32
32
|
```python
|
|
33
33
|
import asyncio
|
|
34
34
|
import json
|
|
35
|
-
from
|
|
36
|
-
from multirpc import AsyncMultiRpc
|
|
35
|
+
from multirpc.utils import NestedDict
|
|
36
|
+
from multirpc.async_multi_rpc_interface import AsyncMultiRpc
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
async def main():
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "solver-multirpc"
|
|
3
|
-
version = "3.1.
|
|
3
|
+
version = "3.1.5"
|
|
4
4
|
description = "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
|
authors = ["rorschach <rorschach45001@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
packages = [
|
|
9
|
-
{ include = "
|
|
9
|
+
{ include = "multirpc" }
|
|
10
10
|
]
|
|
11
11
|
|
|
12
12
|
[tool.poetry.dependencies]
|
|
File without changes
|
|
File without changes
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"inputs": [
|
|
4
|
-
{
|
|
5
|
-
"internalType": "uint256",
|
|
6
|
-
"name": "value",
|
|
7
|
-
"type": "uint256"
|
|
8
|
-
}
|
|
9
|
-
],
|
|
10
|
-
"name": "set",
|
|
11
|
-
"outputs": [],
|
|
12
|
-
"stateMutability": "nonpayable",
|
|
13
|
-
"type": "function"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"inputs": [
|
|
17
|
-
{
|
|
18
|
-
"internalType": "address",
|
|
19
|
-
"name": "",
|
|
20
|
-
"type": "address"
|
|
21
|
-
}
|
|
22
|
-
],
|
|
23
|
-
"name": "map",
|
|
24
|
-
"outputs": [
|
|
25
|
-
{
|
|
26
|
-
"internalType": "uint256",
|
|
27
|
-
"name": "",
|
|
28
|
-
"type": "uint256"
|
|
29
|
-
}
|
|
30
|
-
],
|
|
31
|
-
"stateMutability": "view",
|
|
32
|
-
"type": "function"
|
|
33
|
-
}
|
|
34
|
-
]
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
from src.multirpc.utils import ChainConfigTest, NestedDict
|
|
4
|
-
|
|
5
|
-
# Arbitrum Configuration
|
|
6
|
-
ArbConfig = ChainConfigTest(
|
|
7
|
-
'Arbitrum',
|
|
8
|
-
'0xCFE3c06Fe982A7D16ce3826C64c5f0730054Dc95',
|
|
9
|
-
NestedDict({
|
|
10
|
-
"view": {
|
|
11
|
-
1: ['https://1rpc.io/arb', 'https://rpc.ankr.com/arbitrum', 'https://arbitrum.drpc.org'],
|
|
12
|
-
},
|
|
13
|
-
"transaction": {
|
|
14
|
-
1: ['https://1rpc.io/arb', 'https://rpc.ankr.com/arbitrum', 'https://arbitrum.drpc.org'],
|
|
15
|
-
}
|
|
16
|
-
}),
|
|
17
|
-
'0xbc0f34536fdf5d2593081b112d49d714993d879032e0e9c6998afc3110b7f0ed'
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
# Polygon Configuration
|
|
21
|
-
PolyConfig = ChainConfigTest(
|
|
22
|
-
'Polygon',
|
|
23
|
-
'0xCa7DFDc4dB0F27484Cf5EEa1CdF380301Ef07Ce2',
|
|
24
|
-
NestedDict({
|
|
25
|
-
"view": {
|
|
26
|
-
1: ['https://1rpc.io/matic', 'https://polygon-rpc.com'],
|
|
27
|
-
},
|
|
28
|
-
"transaction": {
|
|
29
|
-
1: ['https://1rpc.io/matic', 'https://polygon-rpc.com'],
|
|
30
|
-
}
|
|
31
|
-
}),
|
|
32
|
-
'0x4b8756bd1d32f62b2b9e3b46b80917bd3de4fd95695bad33e483293284f28678',
|
|
33
|
-
is_proof_authority=True
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
# Base Configuration
|
|
37
|
-
BaseConfig = ChainConfigTest(
|
|
38
|
-
'Base',
|
|
39
|
-
'0x1d58e7F58d085c87E34b18DAe5A6D08d187cbcbe',
|
|
40
|
-
NestedDict({
|
|
41
|
-
"view": {
|
|
42
|
-
1: ['https://base-rpc.publicnode.com', 'https://base.drpc.org'],
|
|
43
|
-
},
|
|
44
|
-
"transaction": {
|
|
45
|
-
1: ['https://base-rpc.publicnode.com', 'https://base.drpc.org'],
|
|
46
|
-
}
|
|
47
|
-
}),
|
|
48
|
-
'0xbd342d36d503af057cd79fd4f252b4629d6013d0748a2742dc99c9fcbe522072',
|
|
49
|
-
is_proof_authority=True
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
# Mantle Configuration
|
|
53
|
-
MantleConfig = ChainConfigTest(
|
|
54
|
-
'Mantle',
|
|
55
|
-
'0x535D41D93cDc0818Ad8Eeb452B74e502A5742874',
|
|
56
|
-
NestedDict({
|
|
57
|
-
"view": {
|
|
58
|
-
1: ['https://1rpc.io/mantle', 'https://mantle.drpc.org'],
|
|
59
|
-
},
|
|
60
|
-
"transaction": {
|
|
61
|
-
1: ['https://1rpc.io/mantle', 'https://mantle.drpc.org'],
|
|
62
|
-
}
|
|
63
|
-
}),
|
|
64
|
-
'0x9f33a56be9983753abebbe8fb048601a141097289d96b9844afb36e68f72ef82',
|
|
65
|
-
is_proof_authority=False,
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
RPCsSupportingTxTrace = [
|
|
69
|
-
'https://arbitrum.drpc.org', # Arbitrum
|
|
70
|
-
'https://polygon-rpc.com', # Polygon
|
|
71
|
-
'https://base.drpc.org', # Base
|
|
72
|
-
'https://mantle.drpc.org' # Mantle
|
|
73
|
-
]
|
|
74
|
-
|
|
75
|
-
with open("tests/abi.json", "r") as f:
|
|
76
|
-
abi = json.load(f)
|
|
77
|
-
|
|
78
|
-
PreviousBlock = 3
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: UNLICENSED
|
|
2
|
-
pragma solidity ^0.8.9;
|
|
3
|
-
|
|
4
|
-
contract Mapping {
|
|
5
|
-
mapping(address => uint256) public map;
|
|
6
|
-
|
|
7
|
-
function set(uint256 value) public {
|
|
8
|
-
// Revert if the input is exactly one byte of 0x00
|
|
9
|
-
require(
|
|
10
|
-
value >= 10,
|
|
11
|
-
"Error: 10 < value is not allowed."
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
map[msg.sender] = value;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import logging
|
|
3
|
-
import random
|
|
4
|
-
|
|
5
|
-
from eth_account import Account
|
|
6
|
-
from web3.exceptions import MismatchedABI
|
|
7
|
-
|
|
8
|
-
from src.multirpc.async_multi_rpc_interface import AsyncMultiRpc
|
|
9
|
-
from src.multirpc.constants import GasEstimationMethod, ViewPolicy
|
|
10
|
-
from src.multirpc.sync_multi_rpc_interface import MultiRpc
|
|
11
|
-
from src.multirpc.utils import ChainConfigTest
|
|
12
|
-
from src.tests.constants import ArbConfig, BaseConfig, PolyConfig, RPCsSupportingTxTrace, abi
|
|
13
|
-
from src.tests.test_settings import LogLevel, PrivateKey1, PrivateKey2
|
|
14
|
-
|
|
15
|
-
PreviousBlock = 3
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
async def async_test_map(mr: AsyncMultiRpc, addr: str = None, pk: str = None):
|
|
19
|
-
random_int = random.randint(10, 100)
|
|
20
|
-
print(f"Random int: {random_int}")
|
|
21
|
-
# await mr.functions.set(random_int).call(address=addr, private_key=pk,
|
|
22
|
-
# gas_estimation_method=GasEstimationMethod.GAS_API_PROVIDER)
|
|
23
|
-
# await mr.functions.set(random_int).call(address=addr, private_key=pk,
|
|
24
|
-
# gas_estimation_method=GasEstimationMethod.FIXED)
|
|
25
|
-
|
|
26
|
-
# for failure purpose
|
|
27
|
-
try:
|
|
28
|
-
await mr.functions.set(random_int, random_int).call(address=addr, private_key=pk,
|
|
29
|
-
gas_estimation_method=GasEstimationMethod.RPC)
|
|
30
|
-
except MismatchedABI:
|
|
31
|
-
pass
|
|
32
|
-
|
|
33
|
-
type(random_int)
|
|
34
|
-
|
|
35
|
-
try:
|
|
36
|
-
await mr.functions.set(random.randint(1, 9)
|
|
37
|
-
).call(address=addr, private_key=pk,
|
|
38
|
-
gas_estimation_method=GasEstimationMethod.RPC,
|
|
39
|
-
enable_estimate_gas_limit=False
|
|
40
|
-
)
|
|
41
|
-
except Exception as e:
|
|
42
|
-
print(e)
|
|
43
|
-
|
|
44
|
-
print(f'encoded function: {mr.functions.set(random_int).get_encoded_data()}')
|
|
45
|
-
tx_receipt = await mr.functions.set(random_int).call(address=addr, private_key=pk,
|
|
46
|
-
gas_estimation_method=GasEstimationMethod.RPC)
|
|
47
|
-
|
|
48
|
-
print(f"{tx_receipt=}")
|
|
49
|
-
result = await mr.functions.map(addr).call()
|
|
50
|
-
print(f"map(addr: {addr}): {result}")
|
|
51
|
-
assert random_int == result, "test was not successful"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
async def async_main(chain_config: ChainConfigTest):
|
|
55
|
-
multi_rpc = AsyncMultiRpc(chain_config.rpc, chain_config.contract_address,
|
|
56
|
-
rpcs_supporting_tx_trace=RPCsSupportingTxTrace,
|
|
57
|
-
view_policy=ViewPolicy.MostUpdated,
|
|
58
|
-
contract_abi=abi, gas_estimation=None, log_level=LogLevel,
|
|
59
|
-
is_proof_authority=config_.is_proof_authority,
|
|
60
|
-
multicall_custom_address=chain_config.multicall_address, enable_estimate_gas_limit=True)
|
|
61
|
-
multi_rpc.set_account(address1, private_key=PrivateKey1)
|
|
62
|
-
|
|
63
|
-
p_block = await multi_rpc.get_block_number() - PreviousBlock
|
|
64
|
-
print(f"tx_receipt: {await multi_rpc.get_tx_receipt(chain_config.tx_hash)}")
|
|
65
|
-
print(f"block: {await multi_rpc.get_block(p_block - 1000)}")
|
|
66
|
-
print(f"Nonce: {await multi_rpc.get_nonce(address1)}")
|
|
67
|
-
print(f"map({address1}): {await multi_rpc.functions.map(address1).call()}")
|
|
68
|
-
|
|
69
|
-
results = await multi_rpc.functions.map([(address1,), (address2,)] * 100).multicall()
|
|
70
|
-
print(f"map({address1, address2}): {[res for res in results]}")
|
|
71
|
-
print(f"map({address1}) in {p_block=}: "
|
|
72
|
-
f"{await multi_rpc.functions.map(address1).call(block_identifier=p_block)}")
|
|
73
|
-
|
|
74
|
-
await async_test_map(multi_rpc, address1)
|
|
75
|
-
# await async_test_map(multi_rpc, address2, PrivateKey2)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def sync_test_map(mr: MultiRpc, addr: str = None, pk: str = None):
|
|
79
|
-
random_int = random.randint(10, 100)
|
|
80
|
-
print(f"Random int: {random_int}")
|
|
81
|
-
print(f'encoded function: {mr.functions.set(random_int).get_encoded_data()}')
|
|
82
|
-
mr.functions.set(random_int).call(address=addr, private_key=pk)
|
|
83
|
-
|
|
84
|
-
result = mr.functions.map(addr).call()
|
|
85
|
-
print(f"map(addr: {addr}): {result}")
|
|
86
|
-
assert random_int == result, "test was not successful"
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def sync_main(chain_config: ChainConfigTest):
|
|
90
|
-
multi_rpc = MultiRpc(chain_config.rpc, chain_config.contract_address, contract_abi=abi,
|
|
91
|
-
rpcs_supporting_tx_trace=RPCsSupportingTxTrace,
|
|
92
|
-
gas_estimation=None,
|
|
93
|
-
enable_estimate_gas_limit=True, log_level=LogLevel,
|
|
94
|
-
is_proof_authority=config_.is_proof_authority,
|
|
95
|
-
multicall_custom_address=chain_config.multicall_address)
|
|
96
|
-
multi_rpc.set_account(address1, private_key=PrivateKey1)
|
|
97
|
-
|
|
98
|
-
p_block = multi_rpc.get_block_number() - PreviousBlock
|
|
99
|
-
print(f"tx_receipt: {multi_rpc.get_tx_receipt(chain_config.tx_hash)}")
|
|
100
|
-
print(f"block: {multi_rpc.get_block(p_block - 1000)}")
|
|
101
|
-
print(f"Nonce: {multi_rpc.get_nonce(address1)}")
|
|
102
|
-
print(f"map({address1}): {multi_rpc.functions.map(address1).call()}")
|
|
103
|
-
|
|
104
|
-
results = multi_rpc.functions.map([(address1,), (address2,)]).multicall()
|
|
105
|
-
print(f"map({address1, address2}): {[res for res in results]}")
|
|
106
|
-
print(f"map({address1}) in {p_block=}: "
|
|
107
|
-
f"{multi_rpc.functions.map(address1).call(block_identifier=p_block)}")
|
|
108
|
-
|
|
109
|
-
sync_test_map(multi_rpc, address1)
|
|
110
|
-
sync_test_map(multi_rpc, address2, PrivateKey2)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
async def test(chain_config: ChainConfigTest):
|
|
114
|
-
# try:
|
|
115
|
-
# sync_main(chain_config)
|
|
116
|
-
# print("###sync test was successful###")
|
|
117
|
-
# except Exception as e:
|
|
118
|
-
# logging.error(e)
|
|
119
|
-
|
|
120
|
-
try:
|
|
121
|
-
await async_main(chain_config)
|
|
122
|
-
print('###async test was successful###')
|
|
123
|
-
except Exception as e:
|
|
124
|
-
logging.error(e)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if __name__ == '__main__':
|
|
128
|
-
address1 = Account.from_key(PrivateKey1).address
|
|
129
|
-
address2 = Account.from_key(PrivateKey2).address
|
|
130
|
-
for config_ in [
|
|
131
|
-
ArbConfig,
|
|
132
|
-
PolyConfig,
|
|
133
|
-
BaseConfig,
|
|
134
|
-
# MantleConfig
|
|
135
|
-
]:
|
|
136
|
-
print(f"=============================== Start Testing on {config_.name} ===============================")
|
|
137
|
-
asyncio.run(test(config_))
|
|
138
|
-
print(f"=============================== Test on {config_.name} Completed ===============================\n\n")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|