mm-sol 0.3.1__tar.gz → 0.3.3__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.1 → mm_sol-0.3.3}/PKG-INFO +2 -1
  2. {mm_sol-0.3.1 → mm_sol-0.3.3}/pyproject.toml +4 -2
  3. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/account.py +41 -0
  4. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cli.py +12 -6
  5. mm_sol-0.3.3/src/mm_sol/cli/cmd/wallet/mnemonic_cmd.py +19 -0
  6. mm_sol-0.3.3/tests/cli/cmd/wallet/test_mnemonic_cmd.py +38 -0
  7. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/test_account.py +23 -0
  8. {mm_sol-0.3.1 → mm_sol-0.3.3}/uv.lock +29 -18
  9. mm_sol-0.3.1/src/mm_sol/cli/cmd/wallet/new_cmd.py +0 -14
  10. mm_sol-0.3.1/tests/cli/cmd/wallet/test_new_cmd.py +0 -24
  11. {mm_sol-0.3.1 → mm_sol-0.3.3}/.env.example +0 -0
  12. {mm_sol-0.3.1 → mm_sol-0.3.3}/.gitignore +0 -0
  13. {mm_sol-0.3.1 → mm_sol-0.3.3}/README.txt +0 -0
  14. {mm_sol-0.3.1 → mm_sol-0.3.3}/dict.dic +0 -0
  15. {mm_sol-0.3.1 → mm_sol-0.3.3}/justfile +0 -0
  16. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/__init__.py +0 -0
  17. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/balance.py +0 -0
  18. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/block.py +0 -0
  19. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/__init__.py +0 -0
  20. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/calcs.py +0 -0
  21. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cli_utils.py +0 -0
  22. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cmd/__init__.py +0 -0
  23. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cmd/balance_cmd.py +0 -0
  24. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cmd/balances_cmd.py +0 -0
  25. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cmd/example_cmd.py +0 -0
  26. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cmd/node_cmd.py +0 -0
  27. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cmd/transfer_sol_cmd.py +0 -0
  28. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cmd/transfer_token_cmd.py +0 -0
  29. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cmd/wallet/__init__.py +0 -0
  30. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/cmd/wallet/keypair_cmd.py +0 -0
  31. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/examples/balances.toml +0 -0
  32. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/examples/transfer-sol.toml +0 -0
  33. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/examples/transfer-token.toml +0 -0
  34. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/cli/validators.py +0 -0
  35. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/constants.py +0 -0
  36. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/converters.py +0 -0
  37. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/py.typed +0 -0
  38. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/rpc.py +0 -0
  39. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/solana_cli.py +0 -0
  40. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/token.py +0 -0
  41. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/transfer.py +0 -0
  42. {mm_sol-0.3.1 → mm_sol-0.3.3}/src/mm_sol/utils.py +0 -0
  43. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/__init__.py +0 -0
  44. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/cli/__init__.py +0 -0
  45. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/cli/cmd/__init__.py +0 -0
  46. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/cli/cmd/wallet/__init__.py +0 -0
  47. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/cli/cmd/wallet/test_keypair_cmd.py +0 -0
  48. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/conftest.py +0 -0
  49. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/test_balance.py +0 -0
  50. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/test_client.py +0 -0
  51. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/test_converters.py +0 -0
  52. {mm_sol-0.3.1 → mm_sol-0.3.3}/tests/test_rpc.py +0 -0
  53. {mm_sol-0.3.1 → mm_sol-0.3.3}/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.1
3
+ Version: 0.3.3
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,14 +1,16 @@
1
1
  [project]
2
2
  name = "mm-sol"
3
- version = "0.3.1"
3
+ version = "0.3.3"
4
4
  description = ""
5
5
  requires-python = ">=3.12"
6
6
  dependencies = [
7
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,7 +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",
29
+ "mypy~=1.15.0",
28
30
  ]
29
31
 
30
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,16 @@ 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
+ words: int = typer.Option(12, "--words", "-w", help="Number of mnemonic words"),
114
+ limit: int = typer.Option(5, "--limit", "-l"),
109
115
  ) -> None:
110
- new_cmd.run(limit, array)
116
+ mnemonic_cmd.run(mnemonic, passphrase, words, derivation_path, limit)
111
117
 
112
118
 
113
119
  @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, words: int, derivation_path: str, limit: int) -> None: # nosec
10
+ result: dict[str, Any] = {}
11
+ if not mnemonic:
12
+ mnemonic = generate_mnemonic(words)
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)
@@ -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
+ )
@@ -493,12 +493,13 @@ wheels = [
493
493
 
494
494
  [[package]]
495
495
  name = "mm-sol"
496
- version = "0.3.1"
496
+ version = "0.3.3"
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
  ]
@@ -518,6 +519,7 @@ requires-dist = [
518
519
  { name = "base58", specifier = "~=2.1.1" },
519
520
  { name = "jinja2", specifier = ">=3.1.5" },
520
521
  { name = "mm-crypto-utils", specifier = ">=0.1.4" },
522
+ { name = "mnemonic", specifier = "==0.21" },
521
523
  { name = "solana", specifier = "~=0.36.3" },
522
524
  { name = "typer", specifier = ">=0.15.1" },
523
525
  ]
@@ -525,7 +527,7 @@ requires-dist = [
525
527
  [package.metadata.requires-dev]
526
528
  dev = [
527
529
  { name = "bandit", specifier = "~=1.8.2" },
528
- { name = "mypy", specifier = "~=1.14.1" },
530
+ { name = "mypy", specifier = "~=1.15.0" },
529
531
  { name = "pip-audit", specifier = "~=2.7.3" },
530
532
  { name = "pytest", specifier = "~=8.3.4" },
531
533
  { name = "pytest-xdist", specifier = "~=3.6.1" },
@@ -549,6 +551,15 @@ wheels = [
549
551
  { url = "https://files.pythonhosted.org/packages/f3/ef/cb423cc357cc116313fcd97e9d0ff673234f5f1725f4a73929ced27b1d00/mm_std-0.2.1-py3-none-any.whl", hash = "sha256:71fa84f2fa897901c925614327123e8d0bc6ae61ff7873479dc9a53889442237", size = 14620 },
550
552
  ]
551
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
+
552
563
  [[package]]
553
564
  name = "msgpack"
554
565
  version = "1.1.0"
@@ -581,27 +592,27 @@ wheels = [
581
592
 
582
593
  [[package]]
583
594
  name = "mypy"
584
- version = "1.14.1"
595
+ version = "1.15.0"
585
596
  source = { registry = "https://pypi.org/simple" }
586
597
  dependencies = [
587
598
  { name = "mypy-extensions" },
588
599
  { name = "typing-extensions" },
589
600
  ]
590
- sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051 }
591
- wheels = [
592
- { 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 },
593
- { 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 },
594
- { 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 },
595
- { 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 },
596
- { 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 },
597
- { url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016 },
598
- { 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 },
599
- { 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 },
600
- { 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 },
601
- { 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 },
602
- { 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 },
603
- { url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276 },
604
- { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 },
601
+ sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717 }
602
+ wheels = [
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 },
605
616
  ]
606
617
 
607
618
  [[package]]
@@ -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