mm-apt 0.4.1__tar.gz → 0.5.0__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.
@@ -0,0 +1,15 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "WebSearch",
5
+ "Bash(curl:*)",
6
+ "Bash(just test:*)",
7
+ "Bash(just lint:*)",
8
+ "WebFetch(domain:aptoscan.com)",
9
+ "WebFetch(domain:github.com)",
10
+ "WebFetch(domain:aptos.dev)"
11
+ ],
12
+ "deny": [],
13
+ "ask": []
14
+ }
15
+ }
@@ -0,0 +1 @@
1
+ MAINNET_RPC_URL=https://api.mainnet.aptoslabs.com/v1
@@ -0,0 +1,10 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v6.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-toml
9
+ - id: check-json
10
+ - id: check-added-large-files
mm_apt-0.5.0/CLAUDE.md ADDED
@@ -0,0 +1,13 @@
1
+ # Claude Guidelines
2
+
3
+ ## Critical Guidelines
4
+
5
+ 1. **Always communicate in English** - Regardless of the language the user speaks, always respond in English. All code, comments, and documentation must be in English.
6
+
7
+ 2. **Minimal documentation** - Only add comments/documentation when it simplifies understanding and isn't obvious from the code itself. Keep it strictly relevant and concise.
8
+
9
+ 3. **Critical thinking** - Always critically evaluate user ideas. Users can make mistakes. Think first about whether the user's idea is good before implementing.
10
+
11
+ 4. **Lint after changes** - After making code changes, always run `just lint` to verify code quality and fix any linter issues.
12
+
13
+ 5. **No disabling linter rules** - Never use special disabling comments (like `# noqa`, `# type: ignore`, `# ruff: noqa`, etc.) to turn off linter rules without explicit permission. If you believe a rule should be disabled, ask first.
@@ -1,5 +1,5 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mm-apt
3
- Version: 0.4.1
3
+ Version: 0.5.0
4
4
  Requires-Python: >=3.13
5
- Requires-Dist: mm-cryptocurrency~=0.4.7
5
+ Requires-Dist: mm-web3~=0.5.4
@@ -0,0 +1,2 @@
1
+ https://aptos.dev/
2
+ https://aptoscan.com/
@@ -15,7 +15,7 @@ format:
15
15
  test:
16
16
  uv run pytest -n auto tests
17
17
 
18
- lint: format
18
+ lint: format pre-commit
19
19
  uv run ruff check src tests
20
20
  uv run mypy src
21
21
 
@@ -33,3 +33,9 @@ publish: build
33
33
 
34
34
  sync:
35
35
  uv sync
36
+
37
+ pre-commit:
38
+ uv run pre-commit run --all-files
39
+
40
+ pre-commit-autoupdate:
41
+ uv run pre-commit autoupdate
@@ -0,0 +1,73 @@
1
+ [project]
2
+ name = "mm-apt"
3
+ version = "0.5.0"
4
+ description = ""
5
+ requires-python = ">=3.13"
6
+ dependencies = ["mm-web3~=0.5.4"]
7
+
8
+ [build-system]
9
+ requires = ["hatchling"]
10
+ build-backend = "hatchling.build"
11
+
12
+ [dependency-groups]
13
+ dev = [
14
+ "pytest~=8.4.2",
15
+ "pytest-asyncio~=1.2.0",
16
+ "pytest-xdist~=3.8.0",
17
+ "ruff~=0.14.2",
18
+ "pip-audit~=2.9.0",
19
+ "bandit~=1.8.6",
20
+ "mypy~=1.18.2",
21
+ "pre-commit~=4.3.0",
22
+ "python-dotenv~=1.2.1",
23
+ ]
24
+
25
+ [tool.mypy]
26
+ python_version = "3.13"
27
+ warn_no_return = false
28
+ strict = true
29
+ exclude = ["^tests/", "^tmp/"]
30
+
31
+ [tool.ruff]
32
+ line-length = 130
33
+ target-version = "py313"
34
+ [tool.ruff.lint]
35
+ select = ["ALL"]
36
+ ignore = [
37
+ "TC", # flake8-type-checking, TYPE_CHECKING is dangerous, for example it doesn't work with pydantic
38
+ "A005", # flake8-builtins: stdlib-module-shadowing
39
+ "ERA001", # eradicate: commented-out-code
40
+ "PT", # flake8-pytest-style
41
+ "D", # pydocstyle
42
+ "FIX", # flake8-fixme
43
+ "PLR0911", # pylint: too-many-return-statements
44
+ "PLR0912", # pylint: too-many-branches
45
+ "PLR0913", # pylint: too-many-arguments
46
+ "PLR2004", # pylint: magic-value-comparison
47
+ "PLC0414", # pylint: useless-import-alias
48
+ "FBT", # flake8-boolean-trap
49
+ "EM", # flake8-errmsg
50
+ "TRY003", # tryceratops: raise-vanilla-args
51
+ "C901", # mccabe: complex-structure,
52
+ "BLE001", # flake8-blind-except
53
+ "S311", # bandit: suspicious-non-cryptographic-random-usage
54
+ "TD002", # flake8-todos: missing-todo-author
55
+ "TD003", # flake8-todos: missing-todo-link
56
+ "RET503", # flake8-return: implicit-return
57
+ "COM812", # it's used in ruff formatter
58
+ "ASYNC109",
59
+ "G004",
60
+ ]
61
+ [tool.ruff.lint.per-file-ignores]
62
+ "tests/*.py" = ["ANN", "S"]
63
+ [tool.ruff.format]
64
+ quote-style = "double"
65
+ indent-style = "space"
66
+
67
+ [tool.bandit]
68
+ exclude_dirs = ["tests"]
69
+ skips = ["B311"]
70
+
71
+ [tool.pytest.ini_options]
72
+ asyncio_mode = "auto"
73
+ asyncio_default_fixture_loop_scope = "function"
@@ -7,7 +7,7 @@ async def address_to_name(address: str, timeout: float = 5, proxy: str | None =
7
7
  res = await http_request(url, proxy=proxy, timeout=timeout)
8
8
  if res.is_err():
9
9
  return res.to_result_err()
10
- json_res = res.parse_json_body()
10
+ json_res = res.parse_json()
11
11
  if res.status_code == 200 and json_res == {}:
12
12
  return res.to_result_ok(None)
13
13
  if "name" in json_res:
@@ -20,7 +20,7 @@ async def address_to_primary_name(address: str, timeout: float = 5, proxy: str |
20
20
  res = await http_request(url, proxy=proxy, timeout=timeout)
21
21
  if res.is_err():
22
22
  return res.to_result_err()
23
- json_res = res.parse_json_body()
23
+ json_res = res.parse_json()
24
24
  if res.status_code == 200 and json_res == {}:
25
25
  return res.to_result_ok(None)
26
26
  if "name" in json_res:
@@ -0,0 +1,32 @@
1
+ from mm_http import http_request
2
+ from mm_result import Result
3
+
4
+
5
+ async def get_balance(node: str, account: str, coin_type: str, timeout: float = 5, proxy: str | None = None) -> Result[int]:
6
+ url = f"{node}/view"
7
+
8
+ if "::" in coin_type:
9
+ # Coin type (e.g., 0x1::aptos_coin::AptosCoin)
10
+ body = {
11
+ "function": "0x1::coin::balance",
12
+ "type_arguments": [coin_type],
13
+ "arguments": [account],
14
+ }
15
+ else:
16
+ # Fungible Asset metadata address
17
+ body = {
18
+ "function": "0x1::primary_fungible_store::balance",
19
+ "type_arguments": ["0x1::fungible_asset::Metadata"],
20
+ "arguments": [account, coin_type],
21
+ }
22
+
23
+ res = await http_request(url, method="POST", json=body, proxy=proxy, timeout=timeout)
24
+ try:
25
+ json_res = res.parse_json()
26
+ if isinstance(json_res, list) and len(json_res) > 0:
27
+ return res.to_result_ok(int(json_res[0]))
28
+ if isinstance(json_res, dict) and json_res.get("error_code") == "resource_not_found":
29
+ return res.to_result_ok(0)
30
+ return res.to_result_err(f"Unexpected response format: {json_res}")
31
+ except Exception as e:
32
+ return res.to_result_err(e)
@@ -0,0 +1,5 @@
1
+ APTOS_COIN_TYPE = "0x1::aptos_coin::AptosCoin"
2
+ APTOS_COIN_DECIMALS = 8
3
+
4
+ USDT_METADATA = "0x357b0b74bc833e95a115ad22604854d6b0fca151cecd94111770e5d6ffc9dc2b"
5
+ USDT_DECIMALS = 6
@@ -1,5 +1,5 @@
1
- from mm_cryptocurrency import Nodes, Proxies, retry_with_node_and_proxy
2
1
  from mm_result import Result
2
+ from mm_web3 import Nodes, Proxies, retry_with_node_and_proxy
3
3
 
4
4
  from mm_apt import balance
5
5
 
@@ -32,7 +32,7 @@ def test_invalid_full_length_addresses():
32
32
  bad_char = "0x" + "g" + "0" * 63
33
33
  assert is_valid_address(bad_char) is False
34
34
  # Numeric type
35
- assert is_valid_address(123) is False
35
+ assert is_valid_address(123) is False # pyright: ignore[reportArgumentType]
36
36
 
37
37
 
38
38
  def test_address_out_of_range():
@@ -0,0 +1,12 @@
1
+ from mm_apt.balance import get_balance
2
+ from mm_apt.coin import APTOS_COIN_TYPE, USDT_METADATA
3
+
4
+
5
+ async def test_get_balance(mainnet_rpc_url, okx_address):
6
+ res = await get_balance(mainnet_rpc_url, okx_address, APTOS_COIN_TYPE)
7
+ assert res.unwrap() > 1000
8
+
9
+
10
+ async def test_get_balance_usdt(mainnet_rpc_url, okx_address):
11
+ res = await get_balance(mainnet_rpc_url, okx_address, USDT_METADATA)
12
+ assert res.unwrap() > 0