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.
Files changed (53) hide show
  1. {mm_sol-0.3.0 → mm_sol-0.3.2}/PKG-INFO +3 -2
  2. {mm_sol-0.3.0 → mm_sol-0.3.2}/pyproject.toml +5 -4
  3. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/account.py +41 -0
  4. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cli.py +11 -6
  5. mm_sol-0.3.2/src/mm_sol/cli/cmd/wallet/mnemonic_cmd.py +19 -0
  6. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/validators.py +3 -3
  7. mm_sol-0.3.2/tests/cli/cmd/wallet/test_mnemonic_cmd.py +38 -0
  8. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_account.py +23 -0
  9. {mm_sol-0.3.0 → mm_sol-0.3.2}/uv.lock +31 -31
  10. mm_sol-0.3.0/src/mm_sol/cli/cmd/wallet/new_cmd.py +0 -14
  11. mm_sol-0.3.0/tests/cli/cmd/wallet/test_new_cmd.py +0 -24
  12. {mm_sol-0.3.0 → mm_sol-0.3.2}/.env.example +0 -0
  13. {mm_sol-0.3.0 → mm_sol-0.3.2}/.gitignore +0 -0
  14. {mm_sol-0.3.0 → mm_sol-0.3.2}/README.txt +0 -0
  15. {mm_sol-0.3.0 → mm_sol-0.3.2}/dict.dic +0 -0
  16. {mm_sol-0.3.0 → mm_sol-0.3.2}/justfile +0 -0
  17. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/__init__.py +0 -0
  18. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/balance.py +0 -0
  19. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/block.py +0 -0
  20. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/__init__.py +0 -0
  21. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/calcs.py +0 -0
  22. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cli_utils.py +0 -0
  23. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/__init__.py +0 -0
  24. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/balance_cmd.py +0 -0
  25. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/balances_cmd.py +0 -0
  26. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/example_cmd.py +0 -0
  27. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/node_cmd.py +0 -0
  28. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/transfer_sol_cmd.py +0 -0
  29. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/transfer_token_cmd.py +0 -0
  30. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/wallet/__init__.py +0 -0
  31. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/cmd/wallet/keypair_cmd.py +0 -0
  32. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/examples/balances.toml +0 -0
  33. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/examples/transfer-sol.toml +0 -0
  34. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/cli/examples/transfer-token.toml +0 -0
  35. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/constants.py +0 -0
  36. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/converters.py +0 -0
  37. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/py.typed +0 -0
  38. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/rpc.py +0 -0
  39. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/solana_cli.py +0 -0
  40. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/token.py +0 -0
  41. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/transfer.py +0 -0
  42. {mm_sol-0.3.0 → mm_sol-0.3.2}/src/mm_sol/utils.py +0 -0
  43. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/__init__.py +0 -0
  44. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/cli/__init__.py +0 -0
  45. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/cli/cmd/__init__.py +0 -0
  46. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/cli/cmd/wallet/__init__.py +0 -0
  47. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/cli/cmd/wallet/test_keypair_cmd.py +0 -0
  48. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/conftest.py +0 -0
  49. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_balance.py +0 -0
  50. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_client.py +0 -0
  51. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_converters.py +0 -0
  52. {mm_sol-0.3.0 → mm_sol-0.3.2}/tests/test_rpc.py +0 -0
  53. {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.0
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~=0.1.1
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.0"
3
+ version = "0.3.2"
4
4
  description = ""
5
5
  requires-python = ">=3.12"
6
6
  dependencies = [
7
- "mm-crypto-utils~=0.1.1",
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.14.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, 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)
@@ -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 | list[str] | None], list[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 | None], list[TxRoute]]:
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 | list[str] | None], AddressToPrivate]:
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.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/0f/e2/9cb771e5af1d555b1fe34a9b8f301b8ae62f2ec3a53b2599232dcb5af221/mm_crypto_utils-0.1.1-py3-none-any.whl", hash = "sha256:5f743d4e2f100e05c932d3a1819115dd37212dece8ed444025263daa0ea88402", size = 7327 },
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.0"
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 = "~=0.1.1" },
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.14.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.14.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/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051 }
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/43/1b/b38c079609bb4627905b74fc6a49849835acf68547ac33d8ceb707de5f52/mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", size = 11266668 },
595
- { url = "https://files.pythonhosted.org/packages/6b/75/2ed0d2964c1ffc9971c729f7a544e9cd34b2cdabbe2d11afd148d7838aa2/mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", size = 10254060 },
596
- { url = "https://files.pythonhosted.org/packages/a1/5f/7b8051552d4da3c51bbe8fcafffd76a6823779101a2b198d80886cd8f08e/mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", size = 11933167 },
597
- { url = "https://files.pythonhosted.org/packages/04/90/f53971d3ac39d8b68bbaab9a4c6c58c8caa4d5fd3d587d16f5927eeeabe1/mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", size = 12864341 },
598
- { url = "https://files.pythonhosted.org/packages/03/d2/8bc0aeaaf2e88c977db41583559319f1821c069e943ada2701e86d0430b7/mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89", size = 12972991 },
599
- { url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016 },
600
- { url = "https://files.pythonhosted.org/packages/9e/15/bb6a686901f59222275ab228453de741185f9d54fecbaacec041679496c6/mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255", size = 11252097 },
601
- { url = "https://files.pythonhosted.org/packages/f8/b3/8b0f74dfd072c802b7fa368829defdf3ee1566ba74c32a2cb2403f68024c/mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34", size = 10239728 },
602
- { url = "https://files.pythonhosted.org/packages/c5/9b/4fd95ab20c52bb5b8c03cc49169be5905d931de17edfe4d9d2986800b52e/mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a", size = 11924965 },
603
- { url = "https://files.pythonhosted.org/packages/56/9d/4a236b9c57f5d8f08ed346914b3f091a62dd7e19336b2b2a0d85485f82ff/mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", size = 12867660 },
604
- { url = "https://files.pythonhosted.org/packages/40/88/a61a5497e2f68d9027de2bb139c7bb9abaeb1be1584649fa9d807f80a338/mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", size = 12969198 },
605
- { url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276 },
606
- { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 },
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