mm-sol 0.2.5__py3-none-any.whl → 0.2.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.
mm_sol/transfer.py CHANGED
@@ -1,66 +1,165 @@
1
1
  from decimal import Decimal
2
2
 
3
+ import mm_crypto_utils
3
4
  import pydash
5
+ from mm_crypto_utils import Nodes, Proxies
4
6
  from mm_std import Err, Ok, Result
5
7
  from pydantic import BaseModel
6
- from solana.rpc.api import Client
7
8
  from solders.message import Message
8
9
  from solders.pubkey import Pubkey
10
+ from solders.signature import Signature
9
11
  from solders.system_program import TransferParams, transfer
10
12
  from solders.transaction import Transaction
13
+ from spl.token.client import Token
14
+ from spl.token.constants import TOKEN_PROGRAM_ID
15
+ from spl.token.instructions import get_associated_token_address
11
16
 
17
+ import mm_sol.converters
12
18
  from mm_sol import rpc, utils
13
19
  from mm_sol.account import check_private_key, get_keypair
14
20
 
15
21
 
22
+ def transfer_token(
23
+ *,
24
+ node: str,
25
+ token_mint_address: str | Pubkey,
26
+ from_address: str | Pubkey,
27
+ private_key: str,
28
+ to_address: str | Pubkey,
29
+ amount: Decimal,
30
+ decimals: int,
31
+ proxy: str | None = None,
32
+ timeout: float = 10,
33
+ create_token_account_if_not_exists: bool = True,
34
+ ) -> Result[Signature]:
35
+ acc = get_keypair(private_key)
36
+ if not check_private_key(from_address, private_key):
37
+ return Err("invalid_private_key")
38
+
39
+ from_address = utils.pubkey(from_address)
40
+ token_mint_address = utils.pubkey(token_mint_address)
41
+ to_address = utils.pubkey(to_address)
42
+
43
+ client = utils.get_client(node, proxy=proxy, timeout=timeout)
44
+ token_client = Token(conn=client, pubkey=token_mint_address, program_id=TOKEN_PROGRAM_ID, payer=acc)
45
+
46
+ recipient_token_account = get_associated_token_address(to_address, token_mint_address, token_program_id=TOKEN_PROGRAM_ID)
47
+ from_token_account = get_associated_token_address(from_address, token_mint_address, token_program_id=TOKEN_PROGRAM_ID)
48
+
49
+ data: list[object] = []
50
+
51
+ account_info_res = client.get_account_info(recipient_token_account)
52
+ if account_info_res.value is None:
53
+ if create_token_account_if_not_exists:
54
+ create_account_res = token_client.create_account(to_address, skip_confirmation=False)
55
+ data.append(create_account_res)
56
+ else:
57
+ return Err("no_token_account")
58
+
59
+ res = token_client.transfer_checked(
60
+ source=from_token_account,
61
+ dest=recipient_token_account,
62
+ owner=from_address,
63
+ amount=mm_sol.converters.sol_to_lamports(amount),
64
+ decimals=decimals,
65
+ )
66
+ data.append(res)
67
+
68
+ return Ok(res.value, data=data)
69
+
70
+
71
+ def transfer_token_with_retries(
72
+ *,
73
+ nodes: Nodes,
74
+ token_mint_address: str | Pubkey,
75
+ from_address: str | Pubkey,
76
+ private_key: str,
77
+ to_address: str | Pubkey,
78
+ amount: Decimal,
79
+ decimals: int,
80
+ proxies: Proxies = None,
81
+ timeout: float = 10,
82
+ retries: int = 3,
83
+ ) -> Result[Signature]:
84
+ res: Result[Signature] = Err("not started yet")
85
+ for _ in range(retries):
86
+ res = transfer_token(
87
+ node=mm_crypto_utils.random_node(nodes),
88
+ token_mint_address=token_mint_address,
89
+ from_address=from_address,
90
+ private_key=private_key,
91
+ to_address=to_address,
92
+ amount=amount,
93
+ decimals=decimals,
94
+ proxy=mm_crypto_utils.random_proxy(proxies),
95
+ timeout=timeout,
96
+ )
97
+ if res.is_ok():
98
+ return res
99
+ return res
100
+
101
+
16
102
  def transfer_sol(
17
103
  *,
104
+ node: str,
18
105
  from_address: str,
19
- private_key_base58: str,
20
- recipient_address: str,
21
- amount_sol: Decimal,
22
- nodes: str | list[str] | None = None,
23
- attempts: int = 3,
24
- ) -> Result[str]:
25
- acc = get_keypair(private_key_base58)
26
- if not check_private_key(from_address, private_key_base58):
27
- raise ValueError("from_address or private_key_base58 is invalid")
28
-
29
- lamports = int(amount_sol * 10**9)
30
- error = None
106
+ private_key: str,
107
+ to_address: str,
108
+ lamports: int,
109
+ proxy: str | None = None,
110
+ timeout: float = 10,
111
+ ) -> Result[Signature]:
112
+ acc = get_keypair(private_key)
113
+ if not check_private_key(from_address, private_key):
114
+ return Err("invalid_private_key")
115
+
116
+ client = utils.get_client(node, proxy=proxy, timeout=timeout)
31
117
  data = None
32
- for _ in range(attempts):
33
- try:
34
- client = Client(utils.get_node(nodes))
35
- # tx = Transaction(from_keypairs=[acc])
36
- # ti = transfer(
37
- # TransferParams(from_pubkey=acc.pubkey(), to_pubkey=Pubkey.from_string(recipient_address), lamports=lamports),
38
- # )
39
- # tx.add(ti)
40
- # res = client.send_legacy_transaction(tx, acc)
41
- ixns = [
42
- transfer(
43
- TransferParams(from_pubkey=acc.pubkey(), to_pubkey=Pubkey.from_string(recipient_address), lamports=lamports)
44
- )
45
- ]
46
- msg = Message(ixns, acc.pubkey())
47
- tx = Transaction([acc], msg, client.get_latest_blockhash().value.blockhash)
48
- res = client.send_transaction(tx)
49
- data = res.to_json()
50
- return Ok(str(res.value), data=data)
51
- except Exception as e:
52
- error = e
53
-
54
- return Err(error or "unknown", data=data)
55
-
56
-
57
- class TransferInfo(BaseModel):
118
+ try:
119
+ ixs = [transfer(TransferParams(from_pubkey=acc.pubkey(), to_pubkey=Pubkey.from_string(to_address), lamports=lamports))]
120
+ msg = Message(ixs, acc.pubkey())
121
+ tx = Transaction([acc], msg, client.get_latest_blockhash().value.blockhash)
122
+ res = client.send_transaction(tx)
123
+ data = res.to_json()
124
+ return Ok(res.value, data=data)
125
+ except Exception as e:
126
+ return Err(e, data=data)
127
+
128
+
129
+ def transfer_sol_with_retries(
130
+ *,
131
+ nodes: Nodes,
132
+ from_address: str,
133
+ private_key: str,
134
+ to_address: str,
135
+ lamports: int,
136
+ proxies: Proxies = None,
137
+ timeout: float = 10,
138
+ retries: int = 3,
139
+ ) -> Result[Signature]:
140
+ res: Result[Signature] = Err("not started yet")
141
+ for _ in range(retries):
142
+ res = transfer_sol(
143
+ node=mm_crypto_utils.random_node(nodes),
144
+ from_address=from_address,
145
+ private_key=private_key,
146
+ to_address=to_address,
147
+ lamports=lamports,
148
+ proxy=mm_crypto_utils.random_proxy(proxies),
149
+ timeout=timeout,
150
+ )
151
+ if res.is_ok():
152
+ return res
153
+ return res
154
+
155
+
156
+ class SolTransferInfo(BaseModel):
58
157
  source: str
59
158
  destination: str
60
159
  lamports: int
61
160
 
62
161
 
63
- def find_transfers(node: str, tx_signature: str) -> Result[list[TransferInfo]]:
162
+ def find_sol_transfers(node: str, tx_signature: str) -> Result[list[SolTransferInfo]]:
64
163
  res = rpc.get_transaction(node, tx_signature, encoding="jsonParsed")
65
164
  if res.is_err():
66
165
  return res # type: ignore[return-value]
@@ -74,7 +173,7 @@ def find_transfers(node: str, tx_signature: str) -> Result[list[TransferInfo]]:
74
173
  destination = pydash.get(ix, "parsed.info.destination")
75
174
  lamports = pydash.get(ix, "parsed.info.lamports")
76
175
  if source and destination and lamports:
77
- result.append(TransferInfo(source=source, destination=destination, lamports=lamports))
176
+ result.append(SolTransferInfo(source=source, destination=destination, lamports=lamports))
78
177
  return Ok(result, data=res.data)
79
178
  except Exception as e:
80
179
  return Err(e, res.data)
mm_sol/utils.py CHANGED
@@ -1,31 +1,6 @@
1
- import random
2
- from decimal import Decimal
3
-
4
1
  from solana.rpc.api import Client
5
2
  from solana.rpc.commitment import Commitment
6
-
7
- from mm_sol.rpc import DEFAULT_MAINNET_RPC
8
- from mm_sol.types import Nodes, Proxies
9
-
10
-
11
- def lamports_to_sol(lamports: int, ndigits: int = 4) -> Decimal:
12
- return Decimal(str(round(lamports / 10**9, ndigits=ndigits)))
13
-
14
-
15
- def get_node(nodes: Nodes | None = None) -> str:
16
- if nodes is None:
17
- return DEFAULT_MAINNET_RPC
18
- if isinstance(nodes, str):
19
- return nodes
20
- return random.choice(nodes)
21
-
22
-
23
- def get_proxy(proxies: Proxies) -> str | None:
24
- if not proxies:
25
- return None
26
- if isinstance(proxies, str):
27
- return proxies
28
- return random.choice(proxies)
3
+ from solders.pubkey import Pubkey
29
4
 
30
5
 
31
6
  def get_client(
@@ -36,3 +11,9 @@ def get_client(
36
11
  timeout: float = 10,
37
12
  ) -> Client:
38
13
  return Client(endpoint, commitment=commitment, extra_headers=extra_headers, timeout=timeout, proxy=proxy)
14
+
15
+
16
+ def pubkey(value: str | Pubkey) -> Pubkey:
17
+ if isinstance(value, Pubkey):
18
+ return value
19
+ return Pubkey.from_string(value)
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mm-sol
3
- Version: 0.2.5
4
- Requires-Python: >=3.12
3
+ Version: 0.2.7
4
+ Requires-Python: >=3.13
5
5
  Requires-Dist: base58~=2.1.1
6
6
  Requires-Dist: jinja2>=3.1.5
7
- Requires-Dist: mm-std~=0.1.12
8
- Requires-Dist: solana~=0.36.2
7
+ Requires-Dist: mm-crypto-utils>=0.0.15
8
+ Requires-Dist: solana~=0.36.3
9
9
  Requires-Dist: typer>=0.15.1
@@ -0,0 +1,32 @@
1
+ mm_sol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ mm_sol/account.py,sha256=32PR3kAoZJLEtKzwfWeQXnMxZeFO8NVXjG8HnHpnJgM,3225
3
+ mm_sol/balance.py,sha256=Idx7h9yhRLbrIEDFCBI5QSHE7OT2pYWEZrbHj9XFrkM,3147
4
+ mm_sol/block.py,sha256=4Lc4TANgpGvPflVumC9MR-3vIl1dedGyci3cgzczuds,1794
5
+ mm_sol/converters.py,sha256=jY3wZeo1326z8M-AMS4OEzspRaGt4Tbk0y2SPI-oDFE,1153
6
+ mm_sol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ mm_sol/rpc.py,sha256=TspD_KZQp_KJDQzRknxaT8DR03okok26UWDQWF7Zflg,8031
8
+ mm_sol/solana_cli.py,sha256=ig3OoTvmkrl7MFQSZjRHIraLSmtse0_9kn5Nsw8_zb0,8258
9
+ mm_sol/token.py,sha256=O8z3UE3iZGYLWw8fnd9weYMcoQO0m88noqbRO_jntGg,1092
10
+ mm_sol/transfer.py,sha256=-76gSHbQGOZeOgVgo10QWjAcv_9mnGrBNvpRCvXBlZQ,5872
11
+ mm_sol/utils.py,sha256=NE0G564GiT9d7rW_lPPxUb1eq62WiXh28xtvtzNQIqw,556
12
+ mm_sol/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ mm_sol/cli/calcs.py,sha256=jtFTODBHOkeSR5SARksQ7dDw2BATQYdhc8PtUskfEPk,4152
14
+ mm_sol/cli/cli.py,sha256=SZwvxbiEXHgnhZ_Zg7GsgOm0Y2-WYHSQSuaO2xTaOnk,4496
15
+ mm_sol/cli/cli_utils.py,sha256=EJTWdccXg8mvkK7E-Dt7zmULzc1WoqFlbu8ASGT2SVI,1381
16
+ mm_sol/cli/validators.py,sha256=uKAZfKx4a11kLnxnD98duCMUEswj9UTJkWVVjlW0cDw,500
17
+ mm_sol/cli/cmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ mm_sol/cli/cmd/balance_cmd.py,sha256=DfUZY3-Hr-F7Y0xp1faol0yLnPu6iDU3b839VhdwAbw,2587
19
+ mm_sol/cli/cmd/balances_cmd.py,sha256=yfiRMR3inxz0eXKR4rC9Ii8XsED_3mn46LX_C6Zf0MA,2624
20
+ mm_sol/cli/cmd/example_cmd.py,sha256=bK_z4du0UPGAoiHnYdi6iaZim_kKlYw4NKBbzvyes28,221
21
+ mm_sol/cli/cmd/node_cmd.py,sha256=2AEAjq2M9f8-RZiI0rif6wITdns9QUb4Kr34QPsI2CA,238
22
+ mm_sol/cli/cmd/transfer_sol_cmd.py,sha256=BmPCKr9D1rc7EQ9fuuShlrhiYYli1v1EHY3gkygrFJU,7083
23
+ mm_sol/cli/cmd/transfer_token_cmd.py,sha256=bfDhy0s1i9qaXeGWLk1CnSnxS6wJKdDAM4f3f07RWJA,5148
24
+ mm_sol/cli/cmd/wallet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ mm_sol/cli/cmd/wallet/keypair_cmd.py,sha256=cRHVVTs9zNYmUozZ8ZlJoutn9V6r8I1AEHBrszR7dTE,538
26
+ mm_sol/cli/cmd/wallet/new_cmd.py,sha256=hcP9NZPkwYkTBEvT5rBntFtCIvx1QnPGn5FUDnvz5sM,425
27
+ mm_sol/cli/examples/balances.yml,sha256=SoFcf_IhgA2zrbihrVpqm-ikes80wLFGVzafrjO00UY,290
28
+ mm_sol/cli/examples/transfer-sol.yml,sha256=YFIM36NhaSEPeck6yQMvcgy3MWxgsfDqmMLRqz6P1dk,346
29
+ mm_sol-0.2.7.dist-info/METADATA,sha256=7vvn9NEvyV0s-z6iQ1xVNW3pJwps9XBKspM_8qUdb1g,230
30
+ mm_sol-0.2.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
+ mm_sol-0.2.7.dist-info/entry_points.txt,sha256=MrYnosumy9nsITSAw5TiR3WXDwsdoF0YvUIlZ38TLLs,46
32
+ mm_sol-0.2.7.dist-info/RECORD,,
mm_sol/types.py DELETED
@@ -1,4 +0,0 @@
1
- from collections.abc import Sequence
2
-
3
- type Proxies = str | Sequence[str] | None
4
- type Nodes = str | Sequence[str]
@@ -1,29 +0,0 @@
1
- mm_sol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- mm_sol/account.py,sha256=WlcbPsRpseC507J3E_G-A2-PJGUToNqzSGjrg0pc-B8,3144
3
- mm_sol/balance.py,sha256=QzLjzW2fCGH9Uo8gjxerUnwCStsbkVrguXdPs5N6R5I,667
4
- mm_sol/block.py,sha256=4Lc4TANgpGvPflVumC9MR-3vIl1dedGyci3cgzczuds,1794
5
- mm_sol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- mm_sol/rpc.py,sha256=TspD_KZQp_KJDQzRknxaT8DR03okok26UWDQWF7Zflg,8031
7
- mm_sol/solana_cli.py,sha256=odXNPe8G7dvsGcZxujAFjkd0vWM6fdVvt_mzPulgDZQ,8292
8
- mm_sol/token.py,sha256=LpFnmTzbtKo_Z5hWX96k1Z153640N8VzXHCvsH5zArs,4903
9
- mm_sol/transfer.py,sha256=Bdh3amO-sO180Clq5RVgB9y7NXHhu1EbFNgEsGzHjFY,2911
10
- mm_sol/types.py,sha256=vXXP5Dc72BpHv5tsyws0KDZebG1W1-5HH0UjL7N2Mgc,113
11
- mm_sol/utils.py,sha256=tjV2d6ZZ-Z61cS0WWTPX2yZ2VoJUQv11CNW0p3nO54M,1016
12
- mm_sol/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- mm_sol/cli/cli.py,sha256=l3AKhrgO6GEFrwh3gov9_cfjyFZY0VbZGc0o7NqUWrU,3078
14
- mm_sol/cli/cli_utils.py,sha256=bOrU1LFgndBv4hlNNviHQOob3NfiOsS5YWWDm6fzpCs,1032
15
- mm_sol/cli/cmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- mm_sol/cli/cmd/balance_cmd.py,sha256=IryMXq_8yGF9lDXO5kmUo6TRGgedl_9rS3bE1iRPTw0,2516
17
- mm_sol/cli/cmd/balances_cmd.py,sha256=x6PdXqZgkSmHAsbxim06T4_iPbihUIB4GLy0ZPy5t0s,2168
18
- mm_sol/cli/cmd/example_cmd.py,sha256=bK_z4du0UPGAoiHnYdi6iaZim_kKlYw4NKBbzvyes28,221
19
- mm_sol/cli/cmd/node_cmd.py,sha256=UKlZZzd8MVfQHqAjigJRwPj95Mwq2cpHfWgH8BVuwaw,242
20
- mm_sol/cli/cmd/transfer_sol_cmd.py,sha256=Ta3H4TXxlCCKgcedphN6PU90iYQiZvmYYuKPO044ciw,1196
21
- mm_sol/cli/cmd/wallet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- mm_sol/cli/cmd/wallet/keypair_cmd.py,sha256=7Dk2eT6hfWRLI0uHO_rAQS8xRwY2S6Uk4iBEIO9aQ_w,561
23
- mm_sol/cli/cmd/wallet/new_cmd.py,sha256=nvFy5lkk8XUM5jchx0rn0aHHQ0LGVgbwpn7-kej9ccI,448
24
- mm_sol/cli/examples/balances.yml,sha256=SoFcf_IhgA2zrbihrVpqm-ikes80wLFGVzafrjO00UY,290
25
- mm_sol/cli/examples/transfer-sol.yml,sha256=fEf5lxnotLwQHt85JzwN0o6kax_Am88VKH5e-n1HP94,290
26
- mm_sol-0.2.5.dist-info/METADATA,sha256=CARYWN8yylvN_Py6sDi3DBhOcrMlXja6IPlK-LxoiF4,221
27
- mm_sol-0.2.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
28
- mm_sol-0.2.5.dist-info/entry_points.txt,sha256=MrYnosumy9nsITSAw5TiR3WXDwsdoF0YvUIlZ38TLLs,46
29
- mm_sol-0.2.5.dist-info/RECORD,,
File without changes