mm-strk 0.4.2__py3-none-any.whl → 0.5.0__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_strk/__init__.py CHANGED
@@ -0,0 +1 @@
1
+ """Starknet utilities library."""
mm_strk/account.py CHANGED
@@ -1,3 +1,5 @@
1
+ """Starknet address validation."""
2
+
1
3
  import re
2
4
 
3
5
  # Maximum allowable value for a StarkNet address (251 bits)
@@ -5,15 +7,14 @@ MAX_STARKNET_ADDRESS = 2**251
5
7
 
6
8
 
7
9
  def is_address(address: str) -> bool:
8
- """
9
- Validates a StarkNet address.
10
+ """Validate a Starknet address.
10
11
 
11
12
  - Must be a string starting with '0x'.
12
13
  - Hex part 1-64 chars.
13
14
  - Integer value < 2**251.
14
15
  - Accepts either:
15
- Full 64-hex-character padded form.
16
- Minimal form without leading zeros (canonical).
16
+ * Full 64-hex-character padded form.
17
+ * Minimal form without leading zeros (canonical).
17
18
  """
18
19
  # Type and prefix
19
20
  if not isinstance(address, str) or not address.startswith("0x"):
@@ -39,5 +40,5 @@ def is_address(address: str) -> bool:
39
40
  return True
40
41
 
41
42
  # Minimal form (no leading zeros)
42
- canonical = hex(value)[2:]
43
+ canonical = f"{value:x}"
43
44
  return hex_part.lower() == canonical
mm_strk/balance.py CHANGED
@@ -1,3 +1,5 @@
1
+ """Token balance querying on Starknet."""
2
+
1
3
  import aiohttp
2
4
  from aiohttp_socks import ProxyConnector
3
5
  from mm_result import Result
@@ -19,6 +21,7 @@ STRK_DECIMALS = 18
19
21
 
20
22
 
21
23
  async def get_balance(rpc_url: str, address: str, token: str, timeout: float = 5, proxy: str | None = None) -> Result[int]:
24
+ """Get token balance for a Starknet address."""
22
25
  try:
23
26
  timeout_config = aiohttp.ClientTimeout(total=timeout)
24
27
  connector = ProxyConnector.from_url(proxy) if proxy else None
mm_strk/cli/__init__.py CHANGED
@@ -0,0 +1 @@
1
+ """CLI package for mm-strk."""
mm_strk/cli/cli.py CHANGED
@@ -1,7 +1,9 @@
1
+ """CLI entry point for mm-strk."""
2
+
1
3
  from typing import Annotated
2
4
 
3
- import mm_print
4
5
  import typer
6
+ from mm_print import print_plain
5
7
 
6
8
  from mm_strk.cli import cli_utils, commands
7
9
 
@@ -9,14 +11,15 @@ app = typer.Typer(no_args_is_help=True, pretty_exceptions_enable=False, add_comp
9
11
 
10
12
 
11
13
  def version_callback(value: bool) -> None:
14
+ """Print version and exit when --version is passed."""
12
15
  if value:
13
- mm_print.plain(f"mm-strk: {cli_utils.get_version()}")
16
+ print_plain(f"mm-strk: {cli_utils.get_version()}")
14
17
  raise typer.Exit
15
18
 
16
19
 
17
20
  @app.callback()
18
21
  def main(_version: bool = typer.Option(None, "--version", callback=version_callback, is_eager=True)) -> None:
19
- pass
22
+ """Starknet utilities CLI."""
20
23
 
21
24
 
22
25
  @app.command(name="node", help="Checks RPC URLs for availability and status")
@@ -24,4 +27,5 @@ def node_command(
24
27
  urls: Annotated[list[str], typer.Argument()],
25
28
  proxy: Annotated[str | None, typer.Option("--proxy", "-p", help="Proxy")] = None,
26
29
  ) -> None:
30
+ """Check RPC node availability and status."""
27
31
  commands.node.run(urls, proxy)
mm_strk/cli/cli_utils.py CHANGED
@@ -1,5 +1,8 @@
1
+ """CLI utility functions."""
2
+
1
3
  import importlib.metadata
2
4
 
3
5
 
4
6
  def get_version() -> str:
7
+ """Return the installed version of mm-strk."""
5
8
  return importlib.metadata.version("mm-strk")
@@ -1,3 +1,5 @@
1
+ """CLI commands for mm-strk."""
2
+
1
3
  from . import node
2
4
 
3
5
  __all__ = ["node"]
@@ -1,19 +1,25 @@
1
+ """Starknet node status checking."""
2
+
1
3
  import asyncio
2
4
 
3
- import mm_print
4
5
  import typer
6
+ from mm_print import print_json
5
7
  from pydantic import BaseModel
6
8
  from starknet_py.net.client_models import SyncStatus
7
9
  from starknet_py.net.full_node_client import FullNodeClient
8
10
 
9
11
 
10
12
  class NodeStatus(BaseModel):
13
+ """Starknet node status response."""
14
+
15
+ spec_version: str
11
16
  block_number: int | str
12
17
  chain_id: int | str
13
18
  syncing_status: bool | SyncStatus | str
14
19
 
15
20
 
16
21
  def run(urls: list[str], proxy: str | None) -> None:
22
+ """Check status of Starknet nodes."""
17
23
  if proxy:
18
24
  typer.echo("proxy is not supported yet")
19
25
  raise typer.Exit(code=1)
@@ -21,16 +27,23 @@ def run(urls: list[str], proxy: str | None) -> None:
21
27
 
22
28
 
23
29
  async def _run(urls: list[str]) -> None:
30
+ """Fetch and print status for all given node URLs."""
24
31
  result = {}
25
32
  for url in urls:
26
33
  result[url] = (await _node_status(url)).model_dump()
27
34
 
28
- mm_print.json(result)
35
+ print_json(result)
29
36
 
30
37
 
31
38
  async def _node_status(url: str) -> NodeStatus:
39
+ """Fetch status from a single node."""
32
40
  client = FullNodeClient(node_url=url)
33
41
 
42
+ try:
43
+ spec_version: str = await client.spec_version()
44
+ except Exception as e:
45
+ spec_version = str(e)
46
+
34
47
  try:
35
48
  block_number: int | str = await client.get_block_number()
36
49
  except Exception as e:
@@ -46,4 +59,4 @@ async def _node_status(url: str) -> NodeStatus:
46
59
  except Exception as e:
47
60
  syncing_status = str(e)
48
61
 
49
- return NodeStatus(block_number=block_number, chain_id=chain_id, syncing_status=syncing_status)
62
+ return NodeStatus(spec_version=spec_version, block_number=block_number, chain_id=chain_id, syncing_status=syncing_status)
mm_strk/domain.py CHANGED
@@ -1,9 +1,12 @@
1
+ """Starknet domain resolution via starknet.id API."""
2
+
1
3
  from mm_http import http_request
2
4
  from mm_result import Result
3
5
  from mm_std import str_contains_any
4
6
 
5
7
 
6
8
  async def address_to_domain(address: str, timeout: float = 5.0, proxy: str | None = None) -> Result[str | None]:
9
+ """Resolve a Starknet address to its .stark domain name."""
7
10
  url = "https://api.starknet.id/addr_to_domain"
8
11
  res = await http_request(url, params={"addr": address}, proxy=proxy, timeout=timeout)
9
12
  if (
@@ -14,7 +17,7 @@ async def address_to_domain(address: str, timeout: float = 5.0, proxy: str | Non
14
17
  return res.to_result_ok(None)
15
18
  if res.is_err():
16
19
  return res.to_result_err()
17
- domain = res.parse_json_body("domain")
18
- if domain:
19
- return res.to_result_ok(domain)
20
+ domain_res = res.json_body("domain")
21
+ if domain_res.is_ok():
22
+ return res.to_result_ok(domain_res.unwrap())
20
23
  return res.to_result_err("unknown_response")
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: mm-strk
3
+ Version: 0.5.0
4
+ Requires-Python: >=3.14
5
+ Requires-Dist: mm-web3~=0.6.2
6
+ Requires-Dist: starknet-py~=0.29.0
7
+ Requires-Dist: typer~=0.21.1
@@ -0,0 +1,14 @@
1
+ mm_strk/__init__.py,sha256=iVp6MtowXGcOwwIwwoVjvBUFURUA8c6A_HiQDb7lNDw,34
2
+ mm_strk/account.py,sha256=WqoUhqdqIMccrlKjUi6Xw6aK7hZX1yDzcXA1VMwDmbo,1123
3
+ mm_strk/balance.py,sha256=gteqS9o4b_kI7uHm6CnGbRVdJPFu8rUNwouQB77LkQU,1774
4
+ mm_strk/domain.py,sha256=oeX45K7WBn_jAoNZ3EXHYN5CglDAwXvtRdxtC8o4_ys,902
5
+ mm_strk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ mm_strk/cli/__init__.py,sha256=UZhmfBAMir94NIN3gk9u4hKTdwqjAzv-Aq3J3--PsIM,31
7
+ mm_strk/cli/cli.py,sha256=Mfrx-9oEWV6yY0YCoEdHSmhepneY1ImsbvRtcYgEqcs,946
8
+ mm_strk/cli/cli_utils.py,sha256=G-JltQCbj7SrE98GXgyrfOX3PW7gPwkMf-ATZV4MABM,184
9
+ mm_strk/cli/commands/__init__.py,sha256=EYFq7dwcjxWGV28xbSgF0OqFxD8ecRJi3K2FUCkhy-k,72
10
+ mm_strk/cli/commands/node.py,sha256=SC4eI75jzFtYdEhGS_2x6lcR-4VWqnyMNs_rScEiV_Q,1679
11
+ mm_strk-0.5.0.dist-info/METADATA,sha256=gt3HeSL7lYOrgQhEqqvvtHJFve3cAltgwBwQvTu3cCk,169
12
+ mm_strk-0.5.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
13
+ mm_strk-0.5.0.dist-info/entry_points.txt,sha256=X6zWJaYaUkTgJrY4LAVpcov8O43PmUU4cQ1ue8prYqQ,48
14
+ mm_strk-0.5.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,7 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: mm-strk
3
- Version: 0.4.2
4
- Requires-Python: >=3.13
5
- Requires-Dist: mm-web3~=0.5.1
6
- Requires-Dist: starknet-py~=0.27.0
7
- Requires-Dist: typer>=0.16.0
@@ -1,14 +0,0 @@
1
- mm_strk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- mm_strk/account.py,sha256=kalmNZgM-X2aEGWIk4s4XJUpS3TM2LL188Vjd-hMVds,1099
3
- mm_strk/balance.py,sha256=jOCV1rm4lqXwwGU8CO49znOaUJWQxPukAbJiMkmti7k,1679
4
- mm_strk/domain.py,sha256=cE_f7RZaifjuJaUa7G5bJRvQ8-jr1nszMtLZPI4oQYw,760
5
- mm_strk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- mm_strk/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- mm_strk/cli/cli.py,sha256=nQfgYlgaXPD9MEiTkUTwgHeWPqwavv1VtfYp-rWL2hY,762
8
- mm_strk/cli/cli_utils.py,sha256=4_QLJ_rEotHK90PRQqsvCuFydDOXPrXrnMndBffMPIg,103
9
- mm_strk/cli/commands/__init__.py,sha256=ipr1wm0YQIJoEZLupmrGaom6uJUENhxFuSCOVvCJuW8,39
10
- mm_strk/cli/commands/node.py,sha256=Lt7t8z5inY4G12gHI-4uSEIAYuuNyHwaJ55apOBkNEk,1271
11
- mm_strk-0.4.2.dist-info/METADATA,sha256=X7fkV7pBHHR5J_NQLTSbkfgUdAhvoNMBF0wP0Eru_g0,169
12
- mm_strk-0.4.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
13
- mm_strk-0.4.2.dist-info/entry_points.txt,sha256=X6zWJaYaUkTgJrY4LAVpcov8O43PmUU4cQ1ue8prYqQ,48
14
- mm_strk-0.4.2.dist-info/RECORD,,