mm-sol 0.5.3__py3-none-any.whl → 0.5.5__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.
- mm_sol/async_rpc.py +42 -0
- mm_sol/balance.py +79 -4
- mm_sol/rpc.py +13 -13
- mm_sol/utils.py +11 -0
- mm_sol-0.5.5.dist-info/METADATA +11 -0
- {mm_sol-0.5.3.dist-info → mm_sol-0.5.5.dist-info}/RECORD +8 -7
- mm_sol-0.5.3.dist-info/METADATA +0 -11
- {mm_sol-0.5.3.dist-info → mm_sol-0.5.5.dist-info}/WHEEL +0 -0
- {mm_sol-0.5.3.dist-info → mm_sol-0.5.5.dist-info}/entry_points.txt +0 -0
mm_sol/async_rpc.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from mm_std import Result, ahr
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async def rpc_call(
|
|
7
|
+
*,
|
|
8
|
+
node: str,
|
|
9
|
+
method: str,
|
|
10
|
+
params: list[Any],
|
|
11
|
+
id_: int = 1,
|
|
12
|
+
timeout: float = 10,
|
|
13
|
+
proxy: str | None = None,
|
|
14
|
+
) -> Result[Any]:
|
|
15
|
+
data = {"jsonrpc": "2.0", "method": method, "params": params, "id": id_}
|
|
16
|
+
if node.startswith("http"):
|
|
17
|
+
return await _http_call(node, data, timeout, proxy)
|
|
18
|
+
raise NotImplementedError("ws is not implemented")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def _http_call(node: str, data: dict[str, object], timeout: float, proxy: str | None) -> Result[Any]:
|
|
22
|
+
res = await ahr(node, method="POST", proxy=proxy, timeout=timeout, params=data, json_params=True)
|
|
23
|
+
try:
|
|
24
|
+
if res.is_error():
|
|
25
|
+
return res.to_err_result()
|
|
26
|
+
|
|
27
|
+
err = res.json.get("error", {}).get("message", "")
|
|
28
|
+
if err:
|
|
29
|
+
return res.to_err_result(f"service_error: {err}")
|
|
30
|
+
if "result" in res.json:
|
|
31
|
+
return res.to_ok_result(res.json["result"])
|
|
32
|
+
|
|
33
|
+
return res.to_err_result("unknown_response")
|
|
34
|
+
except Exception as e:
|
|
35
|
+
return res.to_err_result(f"exception: {e!s}")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
async def get_balance(node: str, address: str, timeout: float = 10, proxy: str | None = None) -> Result[int]:
|
|
39
|
+
"""Returns balance in lamports"""
|
|
40
|
+
return (await rpc_call(node=node, method="getBalance", params=[address], timeout=timeout, proxy=proxy)).and_then(
|
|
41
|
+
lambda r: r["value"]
|
|
42
|
+
)
|
mm_sol/balance.py
CHANGED
|
@@ -7,16 +7,20 @@ from solders.pubkey import Pubkey
|
|
|
7
7
|
from solders.rpc.errors import InvalidParamsMessage
|
|
8
8
|
from spl.token.instructions import get_associated_token_address
|
|
9
9
|
|
|
10
|
-
from mm_sol import rpc
|
|
11
|
-
from mm_sol.utils import get_client
|
|
10
|
+
from mm_sol import async_rpc, rpc
|
|
11
|
+
from mm_sol.utils import get_async_client, get_client
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def get_sol_balance(node: str, address: str, timeout:
|
|
14
|
+
def get_sol_balance(node: str, address: str, timeout: float = 10, proxy: str | None = None) -> Result[int]:
|
|
15
15
|
return rpc.get_balance(node, address, timeout, proxy)
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
async def get_sol_balance_async(node: str, address: str, timeout: float = 10, proxy: str | None = None) -> Result[int]:
|
|
19
|
+
return await async_rpc.get_balance(node, address, timeout, proxy)
|
|
20
|
+
|
|
21
|
+
|
|
18
22
|
def get_sol_balance_with_retries(
|
|
19
|
-
nodes: Nodes, address: str, retries: int, timeout:
|
|
23
|
+
nodes: Nodes, address: str, retries: int, timeout: float = 10, proxies: Proxies = None
|
|
20
24
|
) -> Result[int]:
|
|
21
25
|
res: Result[int] = Err("not started yet")
|
|
22
26
|
for _ in range(retries):
|
|
@@ -26,6 +30,17 @@ def get_sol_balance_with_retries(
|
|
|
26
30
|
return res
|
|
27
31
|
|
|
28
32
|
|
|
33
|
+
async def get_sol_balance_with_retries_async(
|
|
34
|
+
nodes: Nodes, address: str, retries: int, timeout: float = 10, proxies: Proxies = None
|
|
35
|
+
) -> Result[int]:
|
|
36
|
+
res: Result[int] = Err("not started yet")
|
|
37
|
+
for _ in range(retries):
|
|
38
|
+
res = await get_sol_balance_async(random_node(nodes), address, timeout=timeout, proxy=random_proxy(proxies))
|
|
39
|
+
if res.is_ok():
|
|
40
|
+
return res
|
|
41
|
+
return res
|
|
42
|
+
|
|
43
|
+
|
|
29
44
|
def get_token_balance(
|
|
30
45
|
node: str,
|
|
31
46
|
owner_address: str,
|
|
@@ -61,6 +76,41 @@ def get_token_balance(
|
|
|
61
76
|
return Err(e)
|
|
62
77
|
|
|
63
78
|
|
|
79
|
+
async def get_token_balance_async(
|
|
80
|
+
node: str,
|
|
81
|
+
owner_address: str,
|
|
82
|
+
token_mint_address: str,
|
|
83
|
+
token_account: str | None = None,
|
|
84
|
+
timeout: float = 10,
|
|
85
|
+
proxy: str | None = None,
|
|
86
|
+
) -> Result[int]:
|
|
87
|
+
try:
|
|
88
|
+
client = get_async_client(node, proxy=proxy, timeout=timeout)
|
|
89
|
+
if not token_account:
|
|
90
|
+
token_account = str(
|
|
91
|
+
get_associated_token_address(Pubkey.from_string(owner_address), Pubkey.from_string(token_mint_address))
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
res = await client.get_token_account_balance(Pubkey.from_string(token_account))
|
|
95
|
+
|
|
96
|
+
# Sometimes it not raise an error, but it returns this :(
|
|
97
|
+
if isinstance(res, InvalidParamsMessage) and "could not find account" in res.message:
|
|
98
|
+
return Ok(0)
|
|
99
|
+
return Ok(int(res.value.amount), data=res.to_json())
|
|
100
|
+
except RPCException as e:
|
|
101
|
+
if len(e.args) > 1:
|
|
102
|
+
s = e.args[0]
|
|
103
|
+
if isinstance(s, InvalidParamsMessage) and "could not find account" in s.message:
|
|
104
|
+
return Ok(0)
|
|
105
|
+
return Err(e)
|
|
106
|
+
except httpx.HTTPStatusError as e:
|
|
107
|
+
return Err(f"http error: {e}")
|
|
108
|
+
except SolanaRpcException as e:
|
|
109
|
+
return Err(e.error_msg)
|
|
110
|
+
except Exception as e:
|
|
111
|
+
return Err(e)
|
|
112
|
+
|
|
113
|
+
|
|
64
114
|
def get_token_balance_with_retries(
|
|
65
115
|
nodes: Nodes,
|
|
66
116
|
owner_address: str,
|
|
@@ -84,3 +134,28 @@ def get_token_balance_with_retries(
|
|
|
84
134
|
return res
|
|
85
135
|
|
|
86
136
|
return res
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
async def get_token_balance_with_retries_async(
|
|
140
|
+
nodes: Nodes,
|
|
141
|
+
owner_address: str,
|
|
142
|
+
token_mint_address: str,
|
|
143
|
+
retries: int,
|
|
144
|
+
token_account: str | None = None,
|
|
145
|
+
timeout: float = 10,
|
|
146
|
+
proxies: Proxies = None,
|
|
147
|
+
) -> Result[int]:
|
|
148
|
+
res: Result[int] = Err("not started yet")
|
|
149
|
+
for _ in range(retries):
|
|
150
|
+
res = await get_token_balance_async(
|
|
151
|
+
random_node(nodes),
|
|
152
|
+
owner_address,
|
|
153
|
+
token_mint_address,
|
|
154
|
+
token_account,
|
|
155
|
+
timeout=timeout,
|
|
156
|
+
proxy=random_proxy(proxies),
|
|
157
|
+
)
|
|
158
|
+
if res.is_ok():
|
|
159
|
+
return res
|
|
160
|
+
|
|
161
|
+
return res
|
mm_sol/rpc.py
CHANGED
|
@@ -78,7 +78,7 @@ def rpc_call(
|
|
|
78
78
|
method: str,
|
|
79
79
|
params: list[Any],
|
|
80
80
|
id_: int = 1,
|
|
81
|
-
timeout:
|
|
81
|
+
timeout: float = 10,
|
|
82
82
|
proxy: str | None = None,
|
|
83
83
|
) -> Result[Any]:
|
|
84
84
|
data = {"jsonrpc": "2.0", "method": method, "params": params, "id": id_}
|
|
@@ -87,7 +87,7 @@ def rpc_call(
|
|
|
87
87
|
raise NotImplementedError("ws is not implemented")
|
|
88
88
|
|
|
89
89
|
|
|
90
|
-
def _http_call(node: str, data: dict[str, object], timeout:
|
|
90
|
+
def _http_call(node: str, data: dict[str, object], timeout: float, proxy: str | None) -> Result[Any]:
|
|
91
91
|
res = hr(node, method="POST", proxy=proxy, timeout=timeout, params=data, json_params=True)
|
|
92
92
|
try:
|
|
93
93
|
if res.is_error():
|
|
@@ -104,38 +104,38 @@ def _http_call(node: str, data: dict[str, object], timeout: int, proxy: str | No
|
|
|
104
104
|
return res.to_err_result(f"exception: {e!s}")
|
|
105
105
|
|
|
106
106
|
|
|
107
|
-
def get_balance(node: str, address: str, timeout:
|
|
107
|
+
def get_balance(node: str, address: str, timeout: float = 10, proxy: str | None = None) -> Result[int]:
|
|
108
108
|
"""Returns balance in lamports"""
|
|
109
109
|
return rpc_call(node=node, method="getBalance", params=[address], timeout=timeout, proxy=proxy).and_then(lambda r: r["value"])
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
def get_block_height(node: str, timeout:
|
|
112
|
+
def get_block_height(node: str, timeout: float = 10, proxy: str | None = None) -> Result[int]:
|
|
113
113
|
"""Returns balance in lamports"""
|
|
114
114
|
return rpc_call(node=node, method="getBlockHeight", params=[], timeout=timeout, proxy=proxy)
|
|
115
115
|
|
|
116
116
|
|
|
117
|
-
def get_slot(node: str, timeout:
|
|
117
|
+
def get_slot(node: str, timeout: float = 10, proxy: str | None = None) -> Result[int]:
|
|
118
118
|
return rpc_call(node=node, method="getSlot", params=[], timeout=timeout, proxy=proxy)
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
def get_epoch_info(node: str, epoch: int | None = None, timeout:
|
|
121
|
+
def get_epoch_info(node: str, epoch: int | None = None, timeout: float = 10, proxy: str | None = None) -> Result[EpochInfo]:
|
|
122
122
|
params = [epoch] if epoch else []
|
|
123
123
|
return rpc_call(node=node, method="getEpochInfo", params=params, timeout=timeout, proxy=proxy).and_then(
|
|
124
124
|
lambda r: EpochInfo(**r),
|
|
125
125
|
)
|
|
126
126
|
|
|
127
127
|
|
|
128
|
-
def get_health(node: str, timeout:
|
|
128
|
+
def get_health(node: str, timeout: float = 10, proxy: str | None = None) -> Result[bool]:
|
|
129
129
|
return rpc_call(node=node, method="getHealth", params=[], timeout=timeout, proxy=proxy).and_then(lambda r: r == "ok")
|
|
130
130
|
|
|
131
131
|
|
|
132
|
-
def get_cluster_nodes(node: str, timeout:
|
|
132
|
+
def get_cluster_nodes(node: str, timeout: float = 30, proxy: str | None = None) -> Result[list[ClusterNode]]:
|
|
133
133
|
return rpc_call(node=node, method="getClusterNodes", timeout=timeout, proxy=proxy, params=[]).and_then(
|
|
134
134
|
lambda r: [ClusterNode(**n) for n in r],
|
|
135
135
|
)
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
def get_vote_accounts(node: str, timeout:
|
|
138
|
+
def get_vote_accounts(node: str, timeout: float = 30, proxy: str | None = None) -> Result[list[VoteAccount]]:
|
|
139
139
|
res = rpc_call(node=node, method="getVoteAccounts", timeout=timeout, proxy=proxy, params=[])
|
|
140
140
|
if res.is_err():
|
|
141
141
|
return res
|
|
@@ -182,7 +182,7 @@ def get_vote_accounts(node: str, timeout: int = 30, proxy: str | None = None) ->
|
|
|
182
182
|
def get_leader_scheduler(
|
|
183
183
|
node: str,
|
|
184
184
|
slot: int | None = None,
|
|
185
|
-
timeout:
|
|
185
|
+
timeout: float = 10,
|
|
186
186
|
proxy: str | None = None,
|
|
187
187
|
) -> Result[dict[str, list[int]]]:
|
|
188
188
|
return rpc_call(
|
|
@@ -194,7 +194,7 @@ def get_leader_scheduler(
|
|
|
194
194
|
)
|
|
195
195
|
|
|
196
196
|
|
|
197
|
-
def get_block_production(node: str, timeout:
|
|
197
|
+
def get_block_production(node: str, timeout: float = 60, proxy: str | None = None) -> Result[BlockProduction]:
|
|
198
198
|
res = rpc_call(node=node, method="getBlockProduction", timeout=timeout, proxy=proxy, params=[])
|
|
199
199
|
if res.is_err():
|
|
200
200
|
return res
|
|
@@ -211,7 +211,7 @@ def get_block_production(node: str, timeout: int = 60, proxy: str | None = None)
|
|
|
211
211
|
return Err(e, data=res.data)
|
|
212
212
|
|
|
213
213
|
|
|
214
|
-
def get_stake_activation(node: str, address: str, timeout:
|
|
214
|
+
def get_stake_activation(node: str, address: str, timeout: float = 60, proxy: str | None = None) -> Result[StakeActivation]:
|
|
215
215
|
return rpc_call(node=node, method="getStakeActivation", timeout=timeout, proxy=proxy, params=[address]).and_then(
|
|
216
216
|
lambda ok: StakeActivation(**ok),
|
|
217
217
|
)
|
|
@@ -222,7 +222,7 @@ def get_transaction(
|
|
|
222
222
|
signature: str,
|
|
223
223
|
max_supported_transaction_version: int | None = None,
|
|
224
224
|
encoding: str = "json",
|
|
225
|
-
timeout:
|
|
225
|
+
timeout: float = 60,
|
|
226
226
|
proxy: str | None = None,
|
|
227
227
|
) -> Result[dict[str, object] | None]:
|
|
228
228
|
if max_supported_transaction_version is not None:
|
mm_sol/utils.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from solana.rpc.api import Client
|
|
2
|
+
from solana.rpc.async_api import AsyncClient
|
|
2
3
|
from solana.rpc.commitment import Commitment
|
|
3
4
|
from solders.pubkey import Pubkey
|
|
4
5
|
|
|
@@ -13,6 +14,16 @@ def get_client(
|
|
|
13
14
|
return Client(endpoint, commitment=commitment, extra_headers=extra_headers, timeout=timeout, proxy=proxy)
|
|
14
15
|
|
|
15
16
|
|
|
17
|
+
def get_async_client(
|
|
18
|
+
endpoint: str,
|
|
19
|
+
commitment: Commitment | None = None,
|
|
20
|
+
extra_headers: dict[str, str] | None = None,
|
|
21
|
+
proxy: str | None = None,
|
|
22
|
+
timeout: float = 10,
|
|
23
|
+
) -> AsyncClient:
|
|
24
|
+
return AsyncClient(endpoint, commitment=commitment, extra_headers=extra_headers, timeout=timeout, proxy=proxy)
|
|
25
|
+
|
|
26
|
+
|
|
16
27
|
def pubkey(value: str | Pubkey) -> Pubkey:
|
|
17
28
|
if isinstance(value, Pubkey):
|
|
18
29
|
return value
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mm-sol
|
|
3
|
+
Version: 0.5.5
|
|
4
|
+
Requires-Python: >=3.12
|
|
5
|
+
Requires-Dist: base58~=2.1.1
|
|
6
|
+
Requires-Dist: jinja2>=3.1.6
|
|
7
|
+
Requires-Dist: mm-crypto-utils>=0.2.9
|
|
8
|
+
Requires-Dist: mnemonic==0.21
|
|
9
|
+
Requires-Dist: socksio>=1.0.0
|
|
10
|
+
Requires-Dist: solana~=0.36.6
|
|
11
|
+
Requires-Dist: typer>=0.15.2
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
mm_sol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
mm_sol/account.py,sha256=0pjvNxwhpmDHoXY3oTY2fNlQHoWPmlS77r8JcP8lAy4,4545
|
|
3
|
-
mm_sol/
|
|
3
|
+
mm_sol/async_rpc.py,sha256=VpAovAgtDT-5OmwGyT8b-Ky_EtrGPKENKxZGGnw3_D8,1406
|
|
4
|
+
mm_sol/balance.py,sha256=cMn9y0StOUwQM3Je4so6AoFCy3lS0JpaiEk-TnUp0Q4,5321
|
|
4
5
|
mm_sol/block.py,sha256=4Lc4TANgpGvPflVumC9MR-3vIl1dedGyci3cgzczuds,1794
|
|
5
6
|
mm_sol/constants.py,sha256=WSpfz5_cq_8XbIrNFJGu9okwbfPTL00zsyR_k9-7O0o,29
|
|
6
7
|
mm_sol/converters.py,sha256=rBxe3SIADZS8hG7TYl4FgjmvKH-ykaTmNbnWWQDiFZ4,1430
|
|
7
8
|
mm_sol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
mm_sol/rpc.py,sha256=
|
|
9
|
+
mm_sol/rpc.py,sha256=Tw7THbU0lShjTGNGe4-Mc6q1U5E2dgjY2LIfrMTSfeA,8057
|
|
9
10
|
mm_sol/solana_cli.py,sha256=ig3OoTvmkrl7MFQSZjRHIraLSmtse0_9kn5Nsw8_zb0,8258
|
|
10
11
|
mm_sol/token.py,sha256=O8z3UE3iZGYLWw8fnd9weYMcoQO0m88noqbRO_jntGg,1092
|
|
11
12
|
mm_sol/transfer.py,sha256=taf2NTLpo-bxISeaILARXEGLldUvqvP-agp5IDva7Hw,5825
|
|
12
|
-
mm_sol/utils.py,sha256=
|
|
13
|
+
mm_sol/utils.py,sha256=oD06NsMSMhN6lqsM6mSgLTtiKwA1uAsen9WR82ofRTE,923
|
|
13
14
|
mm_sol/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
15
|
mm_sol/cli/calcs.py,sha256=-r9RlsQyOziTDf84uIsvTgZmsUdNrVeazu3vTj9hhNA,1887
|
|
15
16
|
mm_sol/cli/cli.py,sha256=a28Cy1X2bRSIAAJu2HHoPoTJYOPvff-anVcL0BJnwRI,4610
|
|
@@ -26,7 +27,7 @@ mm_sol/cli/cmd/wallet/keypair_cmd.py,sha256=cRHVVTs9zNYmUozZ8ZlJoutn9V6r8I1AEHBr
|
|
|
26
27
|
mm_sol/cli/cmd/wallet/mnemonic_cmd.py,sha256=IiON_fJT5AFfIr_E1LR6_iDYZ3c_jWCFc-wSYqk61V8,648
|
|
27
28
|
mm_sol/cli/examples/balances.toml,sha256=333g2EkyYBDW7OWFGMIWVZGkdFQMMo0Ag-bg-BvS4Zg,349
|
|
28
29
|
mm_sol/cli/examples/transfer.toml,sha256=kOCdmuwmhlOam4LVtlcYTKF0PoZYHWMlv9gWxNSXMOk,1624
|
|
29
|
-
mm_sol-0.5.
|
|
30
|
-
mm_sol-0.5.
|
|
31
|
-
mm_sol-0.5.
|
|
32
|
-
mm_sol-0.5.
|
|
30
|
+
mm_sol-0.5.5.dist-info/METADATA,sha256=90sfCL0vDIivEZTDRLHZGgu9leQSarrcyLQq3Th-yxo,289
|
|
31
|
+
mm_sol-0.5.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
32
|
+
mm_sol-0.5.5.dist-info/entry_points.txt,sha256=MrYnosumy9nsITSAw5TiR3WXDwsdoF0YvUIlZ38TLLs,46
|
|
33
|
+
mm_sol-0.5.5.dist-info/RECORD,,
|
mm_sol-0.5.3.dist-info/METADATA
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: mm-sol
|
|
3
|
-
Version: 0.5.3
|
|
4
|
-
Requires-Python: >=3.12
|
|
5
|
-
Requires-Dist: base58~=2.1.1
|
|
6
|
-
Requires-Dist: jinja2>=3.1.5
|
|
7
|
-
Requires-Dist: mm-crypto-utils>=0.2.6
|
|
8
|
-
Requires-Dist: mnemonic==0.21
|
|
9
|
-
Requires-Dist: solana~=0.36.5
|
|
10
|
-
Requires-Dist: solders~=0.23.0
|
|
11
|
-
Requires-Dist: typer>=0.15.1
|
|
File without changes
|
|
File without changes
|