mm-sol 0.5.9__py3-none-any.whl → 0.6.1__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/solana_cli.py DELETED
@@ -1,252 +0,0 @@
1
- import json
2
- import random
3
- from decimal import Decimal
4
- from pathlib import Path
5
- from typing import Literal
6
-
7
- import pydash
8
- from mm_std import CommandResult, Err, Ok, Result, run_command, run_ssh_command
9
- from pydantic import BaseModel, ConfigDict, Field, field_validator
10
-
11
-
12
- class ValidatorInfo(BaseModel):
13
- identity_address: str
14
- info_address: str
15
- name: str | None
16
- keybase: str | None
17
- website: str | None
18
- details: str | None
19
-
20
-
21
- class StakeAccount(BaseModel):
22
- type: str = Field(..., alias="stakeType")
23
- balance: float | None = Field(..., alias="accountBalance")
24
- withdrawer: str
25
- staker: str
26
- vote: str | None = Field(None, alias="delegatedVoteAccountAddress")
27
-
28
- @field_validator("balance")
29
- def from_lamports_to_sol(cls, v: int | None) -> float | None:
30
- if v:
31
- return v / 1_000_000_000
32
-
33
-
34
- class Stake(BaseModel):
35
- model_config = ConfigDict(populate_by_name=True)
36
-
37
- stake_address: str = Field(..., alias="stakePubkey")
38
- withdrawer_address: str = Field(..., alias="withdrawer")
39
- vote_address: str | None = Field(None, alias="delegatedVoteAccountAddress")
40
- balance: float | None = Field(..., alias="accountBalance")
41
- delegated: float | None = Field(None, alias="delegatedStake")
42
- active: float | None = Field(None, alias="activeStake")
43
- lock_time: int | None = Field(None, alias="unixTimestamp")
44
-
45
- @field_validator("balance", "delegated", "active")
46
- def from_lamports_to_sol(cls, v: int | None) -> float | None:
47
- if v:
48
- return v / 1_000_000_000
49
-
50
-
51
- def get_balance(
52
- *,
53
- address: str,
54
- solana_dir: str = "",
55
- url: str = "localhost",
56
- ssh_host: str | None = None,
57
- ssh_key_path: str | None = None,
58
- timeout: int = 60,
59
- ) -> Result[Decimal]:
60
- solana_dir = _solana_dir(solana_dir)
61
- cmd = f"{solana_dir}solana balance {address} -u {url}"
62
- res = _exec_cmd(cmd, ssh_host, ssh_key_path, timeout)
63
- data = {"cmd": cmd, "stdout": res.stdout, "stderr": res.stderr}
64
- try:
65
- return Ok(Decimal(res.stdout.replace("SOL", "").strip()), data=data)
66
- except Exception as e:
67
- return Err(e, data=data)
68
-
69
-
70
- def get_stake_account(
71
- *,
72
- address: str,
73
- solana_dir: str = "",
74
- url: str = "localhost",
75
- ssh_host: str | None = None,
76
- ssh_key_path: str | None = None,
77
- timeout: int = 60,
78
- ) -> Result[StakeAccount]:
79
- solana_dir = _solana_dir(solana_dir)
80
- cmd = f"{solana_dir}solana stake-account --output json -u {url} {address}"
81
- res = _exec_cmd(cmd, ssh_host, ssh_key_path, timeout)
82
- data = {"cmd": cmd, "stdout": res.stdout, "stderr": res.stderr}
83
- try:
84
- json_res = json.loads(res.stdout)
85
- return Ok(StakeAccount(**json_res), data=data)
86
- except Exception as e:
87
- return Err(e, data=data)
88
-
89
-
90
- def transfer_with_private_key_file(
91
- *,
92
- recipient: str,
93
- amount: Decimal,
94
- private_key_path: str,
95
- solana_dir: str = "",
96
- url: str = "localhost",
97
- ssh_host: str | None = None,
98
- ssh_key_path: str | None = None,
99
- allow_unfunded_recipient: bool = True,
100
- timeout: int = 60,
101
- ) -> Result[str]:
102
- solana_dir = _solana_dir(solana_dir)
103
- cmd = f"{solana_dir}solana transfer {recipient} {amount} --from {private_key_path} --fee-payer {private_key_path}"
104
- if allow_unfunded_recipient:
105
- cmd += " --allow-unfunded-recipient"
106
- cmd += f" -u {url} --output json"
107
- res = _exec_cmd(cmd, ssh_host, ssh_key_path, timeout)
108
- data = {"cmd": cmd, "stdout": res.stdout, "stderr": res.stderr}
109
- try:
110
- json_res = json.loads(res.stdout)
111
- return Ok(json_res["signature"], data=data)
112
- except Exception as e:
113
- return Err(e, data=data)
114
-
115
-
116
- def transfer_with_private_key_str(
117
- *,
118
- recipient: str,
119
- amount: Decimal,
120
- private_key: str,
121
- tmp_dir_path: str,
122
- solana_dir: str = "",
123
- url: str = "localhost",
124
- ssh_host: str | None = None,
125
- ssh_key_path: str | None = None,
126
- timeout: int = 60,
127
- ) -> Result[str]:
128
- # make private_key file
129
- private_key_path = Path(f"{tmp_dir_path}/solana__{random.randint(1, 10_000_000_000)}.json")
130
- private_key_path.write_text(private_key)
131
-
132
- try:
133
- return transfer_with_private_key_file(
134
- recipient=recipient,
135
- amount=amount,
136
- private_key_path=private_key_path.as_posix(),
137
- solana_dir=solana_dir,
138
- url=url,
139
- ssh_host=ssh_host,
140
- ssh_key_path=ssh_key_path,
141
- timeout=timeout,
142
- )
143
- finally:
144
- private_key_path.unlink()
145
-
146
-
147
- def withdraw_from_vote_account(
148
- *,
149
- recipient: str,
150
- amount: Decimal | Literal["ALL"],
151
- vote_key_path: str,
152
- fee_payer_key_path: str,
153
- solana_dir: str = "",
154
- url: str = "localhost",
155
- ssh_host: str | None = None,
156
- ssh_key_path: str | None = None,
157
- timeout: int = 60,
158
- ) -> Result[str]:
159
- solana_dir = _solana_dir(solana_dir)
160
- cmd = f"{solana_dir}solana withdraw-from-vote-account --keypair {fee_payer_key_path} -u {url} --output json {vote_key_path} {recipient} {amount}" # noqa: E501
161
- res = _exec_cmd(cmd, ssh_host, ssh_key_path, timeout)
162
- data = {"cmd": cmd, "stdout": res.stdout, "stderr": res.stderr}
163
- try:
164
- json_res = json.loads(res.stdout)
165
- return Ok(json_res["signature"], data=data)
166
- except Exception as e:
167
- return Err(e, data=data)
168
-
169
-
170
- def get_validators_info(
171
- *,
172
- solana_dir: str = "",
173
- url: str = "localhost",
174
- ssh_host: str | None = None,
175
- ssh_key_path: str | None = None,
176
- timeout: int = 60,
177
- ) -> Result[list[ValidatorInfo]]:
178
- solana_dir = _solana_dir(solana_dir)
179
- cmd = f"{solana_dir}solana validator-info get --output json -u {url}"
180
- res = _exec_cmd(cmd, ssh_host, ssh_key_path, timeout)
181
- data = {"cmd": cmd, "stdout": res.stdout, "stderr": res.stderr}
182
- try:
183
- validators = []
184
- for v in json.loads(res.stdout):
185
- validators.append( # noqa: PERF401
186
- ValidatorInfo(
187
- info_address=v["infoPubkey"],
188
- identity_address=v["identityPubkey"],
189
- name=pydash.get(v, "info.name"),
190
- keybase=pydash.get(v, "info.keybaseUsername"),
191
- details=pydash.get(v, "info.details"),
192
- website=pydash.get(v, "info.website"),
193
- ),
194
- )
195
- return Ok(validators, data=data)
196
- except Exception as e:
197
- return Err(e, data=data)
198
-
199
-
200
- def get_vote_account_rewards(
201
- *,
202
- address: str,
203
- solana_dir: str = "",
204
- url: str = "localhost",
205
- ssh_host: str | None = None,
206
- ssh_key_path: str | None = None,
207
- num_rewards_epochs: int = 10,
208
- timeout: int = 60,
209
- ) -> Result[dict[int, float]]:
210
- solana_dir = _solana_dir(solana_dir)
211
- cmd = f"{solana_dir}solana vote-account {address} --with-rewards --num-rewards-epochs={num_rewards_epochs} -u {url}"
212
- cmd += " --output json 2>/dev/null"
213
- res = _exec_cmd(cmd, ssh_host, ssh_key_path, timeout)
214
- data = {"cmd": cmd, "stdout": res.stdout, "stderr": res.stderr}
215
- try:
216
- rewards: dict[int, float] = {}
217
- for r in reversed(json.loads(res.stdout)["epochRewards"]):
218
- rewards[r["epoch"]] = r["amount"] / 10**9
219
- return Ok(rewards, data=data)
220
- except Exception as e:
221
- return Err(e, data=data)
222
-
223
-
224
- def get_stakes(
225
- *,
226
- vote_address: str = "",
227
- solana_dir: str = "",
228
- url: str = "localhost",
229
- ssh_host: str | None = None,
230
- ssh_key_path: str | None = None,
231
- timeout: int = 60,
232
- ) -> Result[list[Stake]]:
233
- solana_dir = _solana_dir(solana_dir)
234
- cmd = f"{solana_dir}solana stakes --output json -u {url} {vote_address}"
235
- res = _exec_cmd(cmd, ssh_host, ssh_key_path, timeout)
236
- data = {"stdout": res.stdout, "stderr": res.stderr}
237
- try:
238
- return Ok([Stake(**x) for x in json.loads(res.stdout)], data=data)
239
- except Exception as e:
240
- return Err(e, data=data)
241
-
242
-
243
- def _exec_cmd(cmd: str, ssh_host: str | None, ssh_key_path: str | None, timeout: int) -> CommandResult:
244
- if ssh_host:
245
- return run_ssh_command(ssh_host, cmd, ssh_key_path, timeout=timeout)
246
- return run_command(cmd, timeout=timeout)
247
-
248
-
249
- def _solana_dir(solana_dir: str) -> str:
250
- if solana_dir and not solana_dir.endswith("/"):
251
- solana_dir += "/"
252
- return solana_dir
mm_sol/token.py DELETED
@@ -1,33 +0,0 @@
1
- import mm_crypto_utils
2
- from mm_crypto_utils import Nodes, Proxies
3
- from mm_std import Err, Ok, Result
4
- from solders.pubkey import Pubkey
5
-
6
- from mm_sol.utils import get_client
7
-
8
-
9
- def get_decimals(node: str, token_mint_address: str, timeout: float = 10, proxy: str | None = None) -> Result[int]:
10
- data = None
11
- try:
12
- client = get_client(node, proxy=proxy, timeout=timeout)
13
- res = client.get_token_supply(Pubkey.from_string(token_mint_address))
14
- data = res
15
- return Ok(res.value.decimals)
16
- except Exception as e:
17
- return Err(e, data=data)
18
-
19
-
20
- def get_decimals_with_retries(
21
- nodes: Nodes, token_mint_address: str, retries: int, timeout: float = 10, proxies: Proxies = None
22
- ) -> Result[int]:
23
- res: Result[int] = Err("not started yet")
24
- for _ in range(retries):
25
- res = get_decimals(
26
- node=mm_crypto_utils.random_node(nodes),
27
- token_mint_address=token_mint_address,
28
- timeout=timeout,
29
- proxy=mm_crypto_utils.random_proxy(proxies),
30
- )
31
- if res.is_ok():
32
- return res
33
- return res
mm_sol/token_async.py DELETED
@@ -1,40 +0,0 @@
1
- import httpx
2
- from mm_std import DataResult
3
- from solana.exceptions import SolanaRpcException
4
- from solana.rpc.core import RPCException
5
- from solders.solders import InvalidParamsMessage, Pubkey, get_associated_token_address
6
-
7
- from mm_sol.utils import get_async_client
8
-
9
-
10
- async def get_token_balance(
11
- node: str,
12
- owner_address: str,
13
- token_mint_address: str,
14
- token_account: str | None = None,
15
- timeout: float = 10,
16
- proxy: str | None = None,
17
- ) -> DataResult[int]:
18
- try:
19
- client = get_async_client(node, proxy=proxy, timeout=timeout)
20
- if not token_account:
21
- token_account = str(
22
- get_associated_token_address(Pubkey.from_string(owner_address), Pubkey.from_string(token_mint_address))
23
- )
24
-
25
- res = await client.get_token_account_balance(Pubkey.from_string(token_account))
26
-
27
- # Sometimes it not raise an error, but it returns this :(
28
- if isinstance(res, InvalidParamsMessage) and "could not find account" in res.message:
29
- return DataResult.ok(0, {"res": res.to_json()})
30
- return DataResult.ok(int(res.value.amount), {"res": res.to_json()})
31
- except RPCException as err:
32
- if "could not find account" in str(err):
33
- return DataResult.ok(0, {"rpc_exception": str(err)})
34
- return DataResult.exception(err)
35
- except httpx.HTTPStatusError as err:
36
- return DataResult.err(f"http error: {err}")
37
- except SolanaRpcException as err:
38
- return DataResult.err(err.error_msg)
39
- except Exception as err:
40
- return DataResult.exception(err)
@@ -1,35 +0,0 @@
1
- mm_sol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- mm_sol/account.py,sha256=9aDP5si-QJfSF8fz8K6geGUGh9GL83YJNkdU1qd4Xu8,4515
3
- mm_sol/async_rpc.py,sha256=3_pEu4ywBjA_ej6cX5q4WJcN1oaPDeIAFa5xNceFCGw,1406
4
- mm_sol/balance.py,sha256=5sSIQbipNUeB_Hn7piwrYt-PuSEf4ZKB8puUmC986iY,5112
5
- mm_sol/block.py,sha256=4Lc4TANgpGvPflVumC9MR-3vIl1dedGyci3cgzczuds,1794
6
- mm_sol/constants.py,sha256=WSpfz5_cq_8XbIrNFJGu9okwbfPTL00zsyR_k9-7O0o,29
7
- mm_sol/converters.py,sha256=rBxe3SIADZS8hG7TYl4FgjmvKH-ykaTmNbnWWQDiFZ4,1430
8
- mm_sol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- mm_sol/rpc.py,sha256=Tw7THbU0lShjTGNGe4-Mc6q1U5E2dgjY2LIfrMTSfeA,8057
10
- mm_sol/rpc_async.py,sha256=_cKqyd5oLArm9VWWuYNqq2PbkqEu7KrsH2r4IAEevGY,2476
11
- mm_sol/solana_cli.py,sha256=ig3OoTvmkrl7MFQSZjRHIraLSmtse0_9kn5Nsw8_zb0,8258
12
- mm_sol/token.py,sha256=O8z3UE3iZGYLWw8fnd9weYMcoQO0m88noqbRO_jntGg,1092
13
- mm_sol/token_async.py,sha256=6IWlQOnyTWA2e3_bccxa10Y4BhbgQpXUAS1NrTyw67E,1572
14
- mm_sol/transfer.py,sha256=taf2NTLpo-bxISeaILARXEGLldUvqvP-agp5IDva7Hw,5825
15
- mm_sol/utils.py,sha256=oD06NsMSMhN6lqsM6mSgLTtiKwA1uAsen9WR82ofRTE,923
16
- mm_sol/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- mm_sol/cli/calcs.py,sha256=-r9RlsQyOziTDf84uIsvTgZmsUdNrVeazu3vTj9hhNA,1887
18
- mm_sol/cli/cli.py,sha256=a28Cy1X2bRSIAAJu2HHoPoTJYOPvff-anVcL0BJnwRI,4610
19
- mm_sol/cli/cli_utils.py,sha256=nFdY8tJFZxyssEBEFCc3VTNJt447e6vMnugx4GBPL4o,1840
20
- mm_sol/cli/validators.py,sha256=M_Rr7JoG3TUYTDAGkjQLDH6l9i9FOrSpss30KdY3UlM,1379
21
- mm_sol/cli/cmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- mm_sol/cli/cmd/balance_cmd.py,sha256=DfUZY3-Hr-F7Y0xp1faol0yLnPu6iDU3b839VhdwAbw,2587
23
- mm_sol/cli/cmd/balances_cmd.py,sha256=gMRZXAnCOPESsKRqz33ALPzSOqGGeZF225kMRO6sV-c,2876
24
- mm_sol/cli/cmd/example_cmd.py,sha256=ZLTy1-cmapiCyYvjFInVE-pQCGKZzDgYKUhsOwtbSIY,234
25
- mm_sol/cli/cmd/node_cmd.py,sha256=-T3AvUOHPKEQWET7gyDVtwNT24SFX0_9rsgfSjnM_Cw,331
26
- mm_sol/cli/cmd/transfer_cmd.py,sha256=eQzD7LispR4KFMUlXdXMBGbXs7b0A-iHJHs7VkxH1UA,11021
27
- mm_sol/cli/cmd/wallet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- mm_sol/cli/cmd/wallet/keypair_cmd.py,sha256=cRHVVTs9zNYmUozZ8ZlJoutn9V6r8I1AEHBrszR7dTE,538
29
- mm_sol/cli/cmd/wallet/mnemonic_cmd.py,sha256=IiON_fJT5AFfIr_E1LR6_iDYZ3c_jWCFc-wSYqk61V8,648
30
- mm_sol/cli/examples/balances.toml,sha256=333g2EkyYBDW7OWFGMIWVZGkdFQMMo0Ag-bg-BvS4Zg,349
31
- mm_sol/cli/examples/transfer.toml,sha256=kOCdmuwmhlOam4LVtlcYTKF0PoZYHWMlv9gWxNSXMOk,1624
32
- mm_sol-0.5.9.dist-info/METADATA,sha256=rPkIVLM-UIwT_o9HLo8E_EqputbOZ44gfIGxw8_rstA,321
33
- mm_sol-0.5.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
34
- mm_sol-0.5.9.dist-info/entry_points.txt,sha256=MrYnosumy9nsITSAw5TiR3WXDwsdoF0YvUIlZ38TLLs,46
35
- mm_sol-0.5.9.dist-info/RECORD,,
File without changes