mm-sol 0.3.0__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 +41 -0
- mm_sol/cli/cli.py +11 -6
- mm_sol/cli/cmd/wallet/mnemonic_cmd.py +19 -0
- mm_sol/cli/validators.py +3 -3
- {mm_sol-0.3.0.dist-info → mm_sol-0.3.2.dist-info}/METADATA +3 -2
- {mm_sol-0.3.0.dist-info → mm_sol-0.3.2.dist-info}/RECORD +8 -8
- mm_sol/cli/cmd/wallet/new_cmd.py +0 -14
- {mm_sol-0.3.0.dist-info → mm_sol-0.3.2.dist-info}/WHEEL +0 -0
- {mm_sol-0.3.0.dist-info → mm_sol-0.3.2.dist-info}/entry_points.txt +0 -0
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,
|
|
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="
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
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)
|
mm_sol/cli/validators.py
CHANGED
|
@@ -12,15 +12,15 @@ class Validators(ConfigValidators):
|
|
|
12
12
|
return ConfigValidators.address(is_address)
|
|
13
13
|
|
|
14
14
|
@staticmethod
|
|
15
|
-
def sol_addresses(unique: bool) -> Callable[[str
|
|
15
|
+
def sol_addresses(unique: bool) -> Callable[[str], list[str]]:
|
|
16
16
|
return ConfigValidators.addresses(unique, is_address=is_address)
|
|
17
17
|
|
|
18
18
|
@staticmethod
|
|
19
|
-
def sol_routes() -> Callable[[str
|
|
19
|
+
def sol_routes() -> Callable[[str], list[TxRoute]]:
|
|
20
20
|
return ConfigValidators.routes(is_address)
|
|
21
21
|
|
|
22
22
|
@staticmethod
|
|
23
|
-
def sol_private_keys() -> Callable[[str
|
|
23
|
+
def sol_private_keys() -> Callable[[str], AddressToPrivate]:
|
|
24
24
|
return ConfigValidators.private_keys(get_public_key)
|
|
25
25
|
|
|
26
26
|
@staticmethod
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mm-sol
|
|
3
|
-
Version: 0.3.
|
|
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
|
-
Requires-Dist: mm-crypto-utils
|
|
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=
|
|
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,9 +12,9 @@ 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=
|
|
15
|
+
mm_sol/cli/cli.py,sha256=Au_NjmvvX4A482nBP-b95tlARWEvqjTIo2CYIx0vyok,4854
|
|
16
16
|
mm_sol/cli/cli_utils.py,sha256=Skj0SCHPWMHGr2ag-em1JtIK9Qdh7xeJafMzvCgChnc,2254
|
|
17
|
-
mm_sol/cli/validators.py,sha256=
|
|
17
|
+
mm_sol/cli/validators.py,sha256=HLCFRrBOdyAMj_ibdAkkP36y9Zm2Dt3gMKoyPOcaiQE,1164
|
|
18
18
|
mm_sol/cli/cmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
19
|
mm_sol/cli/cmd/balance_cmd.py,sha256=DfUZY3-Hr-F7Y0xp1faol0yLnPu6iDU3b839VhdwAbw,2587
|
|
20
20
|
mm_sol/cli/cmd/balances_cmd.py,sha256=mLKulZnmWGixzbzYYvb4dUvJcNPKFHnNyk3WnuAmKio,2215
|
|
@@ -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/
|
|
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.
|
|
32
|
-
mm_sol-0.3.
|
|
33
|
-
mm_sol-0.3.
|
|
34
|
-
mm_sol-0.3.
|
|
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,,
|
mm_sol/cli/cmd/wallet/new_cmd.py
DELETED
|
@@ -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
|
|
File without changes
|