mm-sol 0.3.1__py3-none-any.whl → 0.3.2__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/account.py CHANGED
@@ -1,15 +1,20 @@
1
1
  import contextlib
2
2
  import random
3
+ from dataclasses import dataclass
3
4
 
4
5
  import base58
5
6
  import pydash
6
7
  from mm_std import Err, Ok, Result
8
+ from mnemonic import Mnemonic
7
9
  from pydantic import BaseModel
8
10
  from solana.rpc.api import Client
9
11
  from solders.keypair import Keypair
10
12
  from solders.pubkey import Pubkey
11
13
  from solders.rpc.responses import GetAccountInfoResp
12
14
 
15
+ PHANTOM_DERIVATION_PATH = "m/44'/501'/{i}'/0'"
16
+ WORD_STRENGTH = {12: 128, 15: 160, 18: 192, 21: 224, 24: 256}
17
+
13
18
 
14
19
  class NewAccount(BaseModel):
15
20
  public_key: str
@@ -17,6 +22,42 @@ class NewAccount(BaseModel):
17
22
  private_key_arr: list[int]
18
23
 
19
24
 
25
+ @dataclass
26
+ class DerivedAccount:
27
+ index: int
28
+ path: str
29
+ address: str
30
+ private_key: str
31
+
32
+
33
+ def generate_mnemonic(num_words: int = 24) -> str:
34
+ if num_words not in WORD_STRENGTH:
35
+ raise ValueError(f"num_words must be one of {list(WORD_STRENGTH.keys())}")
36
+ mnemonic = Mnemonic("english")
37
+ return mnemonic.generate(strength=WORD_STRENGTH[num_words])
38
+
39
+
40
+ def derive_accounts(mnemonic: str, passphrase: str, derivation_path: str, limit: int) -> list[DerivedAccount]:
41
+ if "{i}" not in derivation_path:
42
+ raise ValueError("derivation_path must contain {i}, for example: m/44'/501'/{i}'/0'")
43
+
44
+ result: list[DerivedAccount] = []
45
+ seed = Mnemonic.to_seed(mnemonic, passphrase)
46
+ for i in range(limit):
47
+ path = derivation_path.replace("{i}", str(i))
48
+ keypair = Keypair.from_seed_and_derivation_path(seed, path)
49
+ result.append(
50
+ DerivedAccount(
51
+ index=i,
52
+ path=path,
53
+ address=str(keypair.pubkey()),
54
+ private_key=base58.b58encode(bytes(keypair.to_bytes_array())).decode("utf-8"),
55
+ )
56
+ )
57
+
58
+ return result
59
+
60
+
20
61
  def generate_account() -> NewAccount:
21
62
  keypair = Keypair()
22
63
  public_key = str(keypair.pubkey())
mm_sol/cli/cli.py CHANGED
@@ -5,9 +5,11 @@ from typing import Annotated
5
5
  import typer
6
6
  from mm_std import print_plain
7
7
 
8
+ from mm_sol.account import PHANTOM_DERIVATION_PATH
9
+
8
10
  from . import cli_utils
9
11
  from .cmd import balance_cmd, balances_cmd, example_cmd, node_cmd, transfer_sol_cmd, transfer_token_cmd
10
- from .cmd.wallet import keypair_cmd, new_cmd
12
+ from .cmd.wallet import keypair_cmd, mnemonic_cmd
11
13
 
12
14
  app = typer.Typer(no_args_is_help=True, pretty_exceptions_enable=False, add_completion=False)
13
15
 
@@ -102,12 +104,15 @@ def node_command(
102
104
  node_cmd.run(urls, proxy)
103
105
 
104
106
 
105
- @wallet_app.command(name="new", help="Generate new accounts")
106
- def generate_accounts_command(
107
- limit: Annotated[int, typer.Option("--limit", "-l")] = 5,
108
- array: Annotated[bool, typer.Option("--array", help="Print private key in the array format.")] = False,
107
+ @wallet_app.command(name="mnemonic", help="Derive accounts from a mnemonic")
108
+ @wallet_app.command(name="m", hidden=True)
109
+ def wallet_mnemonic_command( # nosec
110
+ mnemonic: Annotated[str, typer.Option("--mnemonic", "-m")] = "",
111
+ passphrase: Annotated[str, typer.Option("--passphrase", "-p")] = "",
112
+ derivation_path: Annotated[str, typer.Option("--path")] = PHANTOM_DERIVATION_PATH,
113
+ limit: int = typer.Option(10, "--limit", "-l"),
109
114
  ) -> None:
110
- new_cmd.run(limit, array)
115
+ mnemonic_cmd.run(mnemonic, passphrase, derivation_path, limit)
111
116
 
112
117
 
113
118
  @wallet_app.command(name="keypair", help="Print public, private_base58, private_arr by a private key")
@@ -0,0 +1,19 @@
1
+ from dataclasses import asdict
2
+ from typing import Any
3
+
4
+ from mm_std import print_json
5
+
6
+ from mm_sol.account import derive_accounts, generate_mnemonic
7
+
8
+
9
+ def run(mnemonic: str, passphrase: str, derivation_path: str, limit: int) -> None: # nosec
10
+ result: dict[str, Any] = {}
11
+ if not mnemonic:
12
+ mnemonic = generate_mnemonic()
13
+ result["mnemonic"] = mnemonic
14
+ if passphrase:
15
+ result["passphrase"] = passphrase
16
+ accounts = derive_accounts(mnemonic=mnemonic, passphrase=passphrase, derivation_path=derivation_path, limit=limit)
17
+
18
+ result["accounts"] = [asdict(acc) for acc in accounts]
19
+ print_json(result)
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mm-sol
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Requires-Python: >=3.12
5
5
  Requires-Dist: base58~=2.1.1
6
6
  Requires-Dist: jinja2>=3.1.5
7
7
  Requires-Dist: mm-crypto-utils>=0.1.4
8
+ Requires-Dist: mnemonic==0.21
8
9
  Requires-Dist: solana~=0.36.3
9
10
  Requires-Dist: typer>=0.15.1
@@ -1,5 +1,5 @@
1
1
  mm_sol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- mm_sol/account.py,sha256=32PR3kAoZJLEtKzwfWeQXnMxZeFO8NVXjG8HnHpnJgM,3225
2
+ mm_sol/account.py,sha256=0pjvNxwhpmDHoXY3oTY2fNlQHoWPmlS77r8JcP8lAy4,4545
3
3
  mm_sol/balance.py,sha256=Idx7h9yhRLbrIEDFCBI5QSHE7OT2pYWEZrbHj9XFrkM,3147
4
4
  mm_sol/block.py,sha256=4Lc4TANgpGvPflVumC9MR-3vIl1dedGyci3cgzczuds,1794
5
5
  mm_sol/constants.py,sha256=WSpfz5_cq_8XbIrNFJGu9okwbfPTL00zsyR_k9-7O0o,29
@@ -12,7 +12,7 @@ mm_sol/transfer.py,sha256=Gu6UYEjY5OECSusKJO-VA8C3B7W6ZJGjegUv67EQdfs,5809
12
12
  mm_sol/utils.py,sha256=NE0G564GiT9d7rW_lPPxUb1eq62WiXh28xtvtzNQIqw,556
13
13
  mm_sol/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  mm_sol/cli/calcs.py,sha256=-r9RlsQyOziTDf84uIsvTgZmsUdNrVeazu3vTj9hhNA,1887
15
- mm_sol/cli/cli.py,sha256=CWzpH96zmODarCm4gfrj6_jXCPdPI-tMmbtqMYdnMqA,4584
15
+ mm_sol/cli/cli.py,sha256=Au_NjmvvX4A482nBP-b95tlARWEvqjTIo2CYIx0vyok,4854
16
16
  mm_sol/cli/cli_utils.py,sha256=Skj0SCHPWMHGr2ag-em1JtIK9Qdh7xeJafMzvCgChnc,2254
17
17
  mm_sol/cli/validators.py,sha256=HLCFRrBOdyAMj_ibdAkkP36y9Zm2Dt3gMKoyPOcaiQE,1164
18
18
  mm_sol/cli/cmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -24,11 +24,11 @@ mm_sol/cli/cmd/transfer_sol_cmd.py,sha256=ZBdkb7YrR88foT3zobMZGnDYAHWgx8ljkxRKpk
24
24
  mm_sol/cli/cmd/transfer_token_cmd.py,sha256=NCaSdO-eud-ef7SdWyTwWdSLiBegYAHySvKz22_j1cg,5911
25
25
  mm_sol/cli/cmd/wallet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  mm_sol/cli/cmd/wallet/keypair_cmd.py,sha256=cRHVVTs9zNYmUozZ8ZlJoutn9V6r8I1AEHBrszR7dTE,538
27
- mm_sol/cli/cmd/wallet/new_cmd.py,sha256=hcP9NZPkwYkTBEvT5rBntFtCIvx1QnPGn5FUDnvz5sM,425
27
+ mm_sol/cli/cmd/wallet/mnemonic_cmd.py,sha256=dw6KmgNGYl2pW0JTCNri4pj-GJ3BdOia6Ef37prJydU,631
28
28
  mm_sol/cli/examples/balances.toml,sha256=8WvnKD1yUz51K1Rd3kkDQI5uOmRwE7DH8paibI-i1uM,262
29
29
  mm_sol/cli/examples/transfer-sol.toml,sha256=1LdkhSBC0y5oMJXjm8MVIMyZruIrYSIm3LBDGmcS5Iw,353
30
30
  mm_sol/cli/examples/transfer-token.toml,sha256=I_Wof-APv-h6xeYVq0zbWfLbpDny2kz9U0xJifVNEtU,401
31
- mm_sol-0.3.1.dist-info/METADATA,sha256=fi-ndt62HZOk5xyiUPQe_Y2iKjLNvi8stAR95yD72mk,229
32
- mm_sol-0.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
33
- mm_sol-0.3.1.dist-info/entry_points.txt,sha256=MrYnosumy9nsITSAw5TiR3WXDwsdoF0YvUIlZ38TLLs,46
34
- mm_sol-0.3.1.dist-info/RECORD,,
31
+ mm_sol-0.3.2.dist-info/METADATA,sha256=K4DNT0cuwNpzt-AqiVtbW--s9-l5s0EQtaLCWfORNAU,259
32
+ mm_sol-0.3.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
33
+ mm_sol-0.3.2.dist-info/entry_points.txt,sha256=MrYnosumy9nsITSAw5TiR3WXDwsdoF0YvUIlZ38TLLs,46
34
+ mm_sol-0.3.2.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- from mm_std import print_json
2
-
3
- from mm_sol.account import generate_account, get_private_key_arr_str
4
-
5
-
6
- def run(limit: int, array: bool) -> None:
7
- result = {}
8
- for _ in range(limit):
9
- acc = generate_account()
10
- private_key = acc.private_key_base58
11
- if array:
12
- private_key = get_private_key_arr_str(acc.private_key_base58)
13
- result[acc.public_key] = private_key
14
- print_json(result)
File without changes