mm-sol 0.3.0__tar.gz → 0.3.2__tar.gz
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-0.3.0 → mm_sol-0.3.2}/PKG-INFO +3 -2
- {mm_sol-0.3.0 → mm_sol-0.3.2}/pyproject.toml +5 -4
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/account.py +41 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cli.py +11 -6
- mm_sol-0.3.2/src/mm_sol/cli/cmd/wallet/mnemonic_cmd.py +19 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/validators.py +3 -3
- mm_sol-0.3.2/tests/cli/cmd/wallet/test_mnemonic_cmd.py +38 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_account.py +23 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/uv.lock +31 -31
- mm_sol-0.3.0/src/mm_sol/cli/cmd/wallet/new_cmd.py +0 -14
- mm_sol-0.3.0/tests/cli/cmd/wallet/test_new_cmd.py +0 -24
- {mm_sol-0.3.0 → mm_sol-0.3.2}/.env.example +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/.gitignore +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/README.txt +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/dict.dic +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/justfile +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/__init__.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/balance.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/block.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/__init__.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/calcs.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cli_utils.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/__init__.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/balance_cmd.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/balances_cmd.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/example_cmd.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/node_cmd.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/transfer_sol_cmd.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/transfer_token_cmd.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/wallet/__init__.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/wallet/keypair_cmd.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/examples/balances.toml +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/examples/transfer-sol.toml +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/examples/transfer-token.toml +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/constants.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/converters.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/py.typed +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/rpc.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/solana_cli.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/token.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/transfer.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/utils.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/__init__.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/cli/__init__.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/cli/cmd/__init__.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/cli/cmd/wallet/__init__.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/cli/cmd/wallet/test_keypair_cmd.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/conftest.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_balance.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_client.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_converters.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_rpc.py +0 -0
- {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_token.py +0 -0
|
@@ -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,14 +1,16 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mm-sol"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.2"
|
|
4
4
|
description = ""
|
|
5
5
|
requires-python = ">=3.12"
|
|
6
6
|
dependencies = [
|
|
7
|
-
"mm-crypto-utils
|
|
7
|
+
"mm-crypto-utils>=0.1.4",
|
|
8
8
|
"solana~=0.36.3",
|
|
9
9
|
"base58~=2.1.1",
|
|
10
|
+
"mnemonic==0.21",
|
|
10
11
|
"typer>=0.15.1",
|
|
11
12
|
"jinja2>=3.1.5",
|
|
13
|
+
|
|
12
14
|
]
|
|
13
15
|
[project.scripts]
|
|
14
16
|
mm-sol = "mm_sol.cli.cli:app"
|
|
@@ -24,8 +26,7 @@ dev-dependencies = [
|
|
|
24
26
|
"ruff~=0.9.4",
|
|
25
27
|
"pip-audit~=2.7.3",
|
|
26
28
|
"bandit~=1.8.2",
|
|
27
|
-
"mypy~=1.
|
|
28
|
-
"types-PyYAML~=6.0.12.20241230",
|
|
29
|
+
"mypy~=1.15.0",
|
|
29
30
|
]
|
|
30
31
|
|
|
31
32
|
[tool.mypy]
|
|
@@ -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())
|
|
@@ -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)
|
|
@@ -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
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from mm_sol.account import PHANTOM_DERIVATION_PATH
|
|
4
|
+
from mm_sol.cli.cli import app
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_mnemonic_cmd(cli_runner):
|
|
8
|
+
mnemonic = "cotton limit tube replace sister flight double muffin health neutral hill maid"
|
|
9
|
+
passphrase = "my-secret"
|
|
10
|
+
path = PHANTOM_DERIVATION_PATH
|
|
11
|
+
|
|
12
|
+
res = cli_runner.invoke(app, f"wallet mnemonic -m '{mnemonic}' -p '{passphrase}' --path '{path}' -l 11")
|
|
13
|
+
assert res.exit_code == 0
|
|
14
|
+
|
|
15
|
+
data = json.loads(res.stdout)
|
|
16
|
+
assert len(data["accounts"]) == 11
|
|
17
|
+
|
|
18
|
+
# pprint(data["accounts"][2])
|
|
19
|
+
|
|
20
|
+
assert data["accounts"][2]["address"] == "Gdfo64rJK6eZBNaN1pRMM6u2aBdpTmuSSzwNNvN8wrbC"
|
|
21
|
+
assert (
|
|
22
|
+
data["accounts"][2]["private_key"]
|
|
23
|
+
== "39YAWGyPPQBuzoCFNndZGqwHciLYPajfq3f9L37TxSrryvDB4cHKfJRWWQPx3shWAjojhayhvq8wfnf4fRrpqz2N"
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_mnemonic_cmd_generates_different_result(cli_runner):
|
|
28
|
+
res1 = cli_runner.invoke(app, "wallet mnemonic -l 2")
|
|
29
|
+
data1 = json.loads(res1.stdout)
|
|
30
|
+
assert res1.exit_code == 0
|
|
31
|
+
|
|
32
|
+
res2 = cli_runner.invoke(app, "wallet mnemonic -l 2")
|
|
33
|
+
data2 = json.loads(res2.stdout)
|
|
34
|
+
assert res2.exit_code == 0
|
|
35
|
+
|
|
36
|
+
assert res1.stdout != res2.stdout
|
|
37
|
+
assert data1["accounts"][1]["address"] != data2["accounts"][1]["address"]
|
|
38
|
+
assert data1["accounts"][1]["private_key"] != data2["accounts"][1]["private_key"]
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
from mm_sol.account import (
|
|
2
|
+
PHANTOM_DERIVATION_PATH,
|
|
3
|
+
DerivedAccount,
|
|
2
4
|
check_private_key,
|
|
5
|
+
derive_accounts,
|
|
3
6
|
generate_account,
|
|
7
|
+
generate_mnemonic,
|
|
4
8
|
get_keypair,
|
|
5
9
|
get_private_key_arr_str,
|
|
6
10
|
get_private_key_base58,
|
|
@@ -127,3 +131,22 @@ def test_is_valid_pubkey():
|
|
|
127
131
|
assert is_address("9nmjQrSpmf51BxcQu6spWD8w4jUzPVrtmtPbDGLyDuan")
|
|
128
132
|
assert is_address("9nmjQrSpmf51BxcQu6spWD8w4jUzPVrtmtPbDGLyDuaN")
|
|
129
133
|
assert not is_address("9nmjQrSpmf51BxcQu6spWD8w4jUzPVrtmtPbDGLyDuama")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_generate_mnemonic():
|
|
137
|
+
assert len(generate_mnemonic().split()) == 24
|
|
138
|
+
assert len(generate_mnemonic(12).split()) == 12
|
|
139
|
+
assert generate_mnemonic() != generate_mnemonic()
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def test_derive_accounts():
|
|
143
|
+
mnemonic = "cotton limit tube replace sister flight double muffin health neutral hill maid"
|
|
144
|
+
passphrase = "my-secret"
|
|
145
|
+
res = derive_accounts(mnemonic=mnemonic, passphrase=passphrase, derivation_path=PHANTOM_DERIVATION_PATH, limit=10)
|
|
146
|
+
assert len(res) == 10
|
|
147
|
+
assert res[2] == DerivedAccount(
|
|
148
|
+
index=2,
|
|
149
|
+
path="m/44'/501'/2'/0'",
|
|
150
|
+
address="Gdfo64rJK6eZBNaN1pRMM6u2aBdpTmuSSzwNNvN8wrbC",
|
|
151
|
+
private_key="39YAWGyPPQBuzoCFNndZGqwHciLYPajfq3f9L37TxSrryvDB4cHKfJRWWQPx3shWAjojhayhvq8wfnf4fRrpqz2N",
|
|
152
|
+
)
|
|
@@ -481,24 +481,25 @@ wheels = [
|
|
|
481
481
|
|
|
482
482
|
[[package]]
|
|
483
483
|
name = "mm-crypto-utils"
|
|
484
|
-
version = "0.1.
|
|
484
|
+
version = "0.1.4"
|
|
485
485
|
source = { registry = "https://pypi.org/simple" }
|
|
486
486
|
dependencies = [
|
|
487
487
|
{ name = "loguru" },
|
|
488
488
|
{ name = "mm-std" },
|
|
489
489
|
]
|
|
490
490
|
wheels = [
|
|
491
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
491
|
+
{ url = "https://files.pythonhosted.org/packages/b8/29/fb0a382faadf0ba377747a551e9136c0ad7f64286163de5d0e1e64ae3456/mm_crypto_utils-0.1.4-py3-none-any.whl", hash = "sha256:3b2e011959fa70f3498ea27b0e741d5e3915be771ec1de63729d8bd97b4d0ff4", size = 7733 },
|
|
492
492
|
]
|
|
493
493
|
|
|
494
494
|
[[package]]
|
|
495
495
|
name = "mm-sol"
|
|
496
|
-
version = "0.3.
|
|
496
|
+
version = "0.3.2"
|
|
497
497
|
source = { editable = "." }
|
|
498
498
|
dependencies = [
|
|
499
499
|
{ name = "base58" },
|
|
500
500
|
{ name = "jinja2" },
|
|
501
501
|
{ name = "mm-crypto-utils" },
|
|
502
|
+
{ name = "mnemonic" },
|
|
502
503
|
{ name = "solana" },
|
|
503
504
|
{ name = "typer" },
|
|
504
505
|
]
|
|
@@ -511,14 +512,14 @@ dev = [
|
|
|
511
512
|
{ name = "pytest" },
|
|
512
513
|
{ name = "pytest-xdist" },
|
|
513
514
|
{ name = "ruff" },
|
|
514
|
-
{ name = "types-pyyaml" },
|
|
515
515
|
]
|
|
516
516
|
|
|
517
517
|
[package.metadata]
|
|
518
518
|
requires-dist = [
|
|
519
519
|
{ name = "base58", specifier = "~=2.1.1" },
|
|
520
520
|
{ name = "jinja2", specifier = ">=3.1.5" },
|
|
521
|
-
{ name = "mm-crypto-utils", specifier = "
|
|
521
|
+
{ name = "mm-crypto-utils", specifier = ">=0.1.4" },
|
|
522
|
+
{ name = "mnemonic", specifier = "==0.21" },
|
|
522
523
|
{ name = "solana", specifier = "~=0.36.3" },
|
|
523
524
|
{ name = "typer", specifier = ">=0.15.1" },
|
|
524
525
|
]
|
|
@@ -526,12 +527,11 @@ requires-dist = [
|
|
|
526
527
|
[package.metadata.requires-dev]
|
|
527
528
|
dev = [
|
|
528
529
|
{ name = "bandit", specifier = "~=1.8.2" },
|
|
529
|
-
{ name = "mypy", specifier = "~=1.
|
|
530
|
+
{ name = "mypy", specifier = "~=1.15.0" },
|
|
530
531
|
{ name = "pip-audit", specifier = "~=2.7.3" },
|
|
531
532
|
{ name = "pytest", specifier = "~=8.3.4" },
|
|
532
533
|
{ name = "pytest-xdist", specifier = "~=3.6.1" },
|
|
533
534
|
{ name = "ruff", specifier = "~=0.9.4" },
|
|
534
|
-
{ name = "types-pyyaml", specifier = "~=6.0.12.20241230" },
|
|
535
535
|
]
|
|
536
536
|
|
|
537
537
|
[[package]]
|
|
@@ -551,6 +551,15 @@ wheels = [
|
|
|
551
551
|
{ url = "https://files.pythonhosted.org/packages/f3/ef/cb423cc357cc116313fcd97e9d0ff673234f5f1725f4a73929ced27b1d00/mm_std-0.2.1-py3-none-any.whl", hash = "sha256:71fa84f2fa897901c925614327123e8d0bc6ae61ff7873479dc9a53889442237", size = 14620 },
|
|
552
552
|
]
|
|
553
553
|
|
|
554
|
+
[[package]]
|
|
555
|
+
name = "mnemonic"
|
|
556
|
+
version = "0.21"
|
|
557
|
+
source = { registry = "https://pypi.org/simple" }
|
|
558
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ff/77/e6232ed59fbd7b90208bb8d4f89ed5aabcf30a524bc2fb8f0dafbe8e7df9/mnemonic-0.21.tar.gz", hash = "sha256:1fe496356820984f45559b1540c80ff10de448368929b9c60a2b55744cc88acf", size = 152462 }
|
|
559
|
+
wheels = [
|
|
560
|
+
{ url = "https://files.pythonhosted.org/packages/57/48/5abb16ce7f9d97b728e6b97c704ceaa614362e0847651f379ed0511942a0/mnemonic-0.21-py3-none-any.whl", hash = "sha256:72dc9de16ec5ef47287237b9b6943da11647a03fe7cf1f139fc3d7c4a7439288", size = 92701 },
|
|
561
|
+
]
|
|
562
|
+
|
|
554
563
|
[[package]]
|
|
555
564
|
name = "msgpack"
|
|
556
565
|
version = "1.1.0"
|
|
@@ -583,27 +592,27 @@ wheels = [
|
|
|
583
592
|
|
|
584
593
|
[[package]]
|
|
585
594
|
name = "mypy"
|
|
586
|
-
version = "1.
|
|
595
|
+
version = "1.15.0"
|
|
587
596
|
source = { registry = "https://pypi.org/simple" }
|
|
588
597
|
dependencies = [
|
|
589
598
|
{ name = "mypy-extensions" },
|
|
590
599
|
{ name = "typing-extensions" },
|
|
591
600
|
]
|
|
592
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
601
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717 }
|
|
593
602
|
wheels = [
|
|
594
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
595
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
596
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
597
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
598
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
599
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
600
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
601
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
602
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
603
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
604
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
605
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
606
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
603
|
+
{ url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981 },
|
|
604
|
+
{ url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175 },
|
|
605
|
+
{ url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675 },
|
|
606
|
+
{ url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020 },
|
|
607
|
+
{ url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582 },
|
|
608
|
+
{ url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614 },
|
|
609
|
+
{ url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592 },
|
|
610
|
+
{ url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611 },
|
|
611
|
+
{ url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443 },
|
|
612
|
+
{ url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541 },
|
|
613
|
+
{ url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348 },
|
|
614
|
+
{ url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648 },
|
|
615
|
+
{ url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777 },
|
|
607
616
|
]
|
|
608
617
|
|
|
609
618
|
[[package]]
|
|
@@ -1042,15 +1051,6 @@ wheels = [
|
|
|
1042
1051
|
{ url = "https://files.pythonhosted.org/packages/d0/cc/0a838ba5ca64dc832aa43f727bd586309846b0ffb2ce52422543e6075e8a/typer-0.15.1-py3-none-any.whl", hash = "sha256:7994fb7b8155b64d3402518560648446072864beefd44aa2dc36972a5972e847", size = 44908 },
|
|
1043
1052
|
]
|
|
1044
1053
|
|
|
1045
|
-
[[package]]
|
|
1046
|
-
name = "types-pyyaml"
|
|
1047
|
-
version = "6.0.12.20241230"
|
|
1048
|
-
source = { registry = "https://pypi.org/simple" }
|
|
1049
|
-
sdist = { url = "https://files.pythonhosted.org/packages/9a/f9/4d566925bcf9396136c0a2e5dc7e230ff08d86fa011a69888dd184469d80/types_pyyaml-6.0.12.20241230.tar.gz", hash = "sha256:7f07622dbd34bb9c8b264fe860a17e0efcad00d50b5f27e93984909d9363498c", size = 17078 }
|
|
1050
|
-
wheels = [
|
|
1051
|
-
{ url = "https://files.pythonhosted.org/packages/e8/c1/48474fbead512b70ccdb4f81ba5eb4a58f69d100ba19f17c92c0c4f50ae6/types_PyYAML-6.0.12.20241230-py3-none-any.whl", hash = "sha256:fa4d32565219b68e6dee5f67534c722e53c00d1cfc09c435ef04d7353e1e96e6", size = 20029 },
|
|
1052
|
-
]
|
|
1053
|
-
|
|
1054
1054
|
[[package]]
|
|
1055
1055
|
name = "typing-extensions"
|
|
1056
1056
|
version = "4.12.2"
|
|
@@ -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)
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
from mm_sol.account import get_public_key
|
|
4
|
-
from mm_sol.cli.cli import app
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def test_new_cmd(cli_runner):
|
|
8
|
-
res = cli_runner.invoke(app, "wallet new -l 11")
|
|
9
|
-
assert res.exit_code == 0
|
|
10
|
-
|
|
11
|
-
accounts = json.loads(res.stdout)
|
|
12
|
-
assert len(accounts) == 11
|
|
13
|
-
for address, private in accounts.items():
|
|
14
|
-
assert address == get_public_key(private)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def test_new_generates_different_keys(cli_runner):
|
|
18
|
-
res1 = cli_runner.invoke(app, "wallet new -l 2")
|
|
19
|
-
assert res1.exit_code == 0
|
|
20
|
-
|
|
21
|
-
res2 = cli_runner.invoke(app, "wallet new -l 2")
|
|
22
|
-
assert res2.exit_code == 0
|
|
23
|
-
|
|
24
|
-
assert res1.stdout != res2.stdout
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|