feat: add API key validation and corresponding error handling; update tests for validation

This commit is contained in:
bohd4nx
2026-03-15 23:01:37 +02:00
parent f4a96bb01a
commit 041081b919
6 changed files with 29 additions and 10 deletions
+1
View File
@@ -31,6 +31,7 @@ Thumbs.db
.ruff_cache/
.coverage
htmlcov/
demo.run.py
# Build & distribution
dist/
+3
View File
@@ -58,6 +58,9 @@ class FragmentClient:
if word_count not in (12, 18, 24):
raise ConfigurationError(ConfigurationError.INVALID_MNEMONIC.format(count=word_count))
if len(api_key.strip()) < 68:
raise ConfigurationError(ConfigurationError.INVALID_API_KEY.format(length=len(api_key.strip())))
if isinstance(cookies, str):
try:
cookies = json.loads(cookies)
+1
View File
@@ -12,6 +12,7 @@ class ConfigurationError(ClientError):
MISSING_VARS = "Missing required parameter(s): {keys}."
UNSUPPORTED_VERSION = "Unsupported wallet_version '{version}'. Must be one of: {supported}."
INVALID_MNEMONIC = "Invalid mnemonic: got {count} words, expected 12, 18, or 24."
INVALID_API_KEY = "Invalid Tonapi key: got {length} characters, expected at least 68. Get one at https://tonconsole.com."
INVALID_MONTHS = "Invalid duration. Choose 3, 6, or 12 months."
INVALID_STARS_AMOUNT = "Amount must be an integer between 50 and 1 000 000 stars."
INVALID_TON_AMOUNT = "Amount must be an integer between 1 and 1 000 000 000 TON."
+15 -6
View File
@@ -1,7 +1,9 @@
import asyncio
import base64
from typing import TYPE_CHECKING, Any
from tonutils.clients import TonapiClient
from tonutils.exceptions import ProviderResponseError
from tonutils.types import NetworkGlobalID
from pyfragment.types import MIN_TON_BALANCE, WALLET_CLASSES, TransactionError, WalletError
@@ -57,12 +59,19 @@ async def process_transaction(client: "FragmentClient", transaction_data: dict)
try:
payload = clean_decode(message["payload"])
result = await wallet.transfer(
destination=message["address"],
amount=int(message["amount"]), # nanotons, not TON
body=payload,
)
return result.normalized_hash
for attempt in range(2):
try:
result = await wallet.transfer(
destination=message["address"],
amount=int(message["amount"]), # nanotons, not TON
body=payload,
)
return result.normalized_hash
except ProviderResponseError as exc:
if exc.code == 429 and attempt == 0:
await asyncio.sleep(1)
continue
raise
except (WalletError, TransactionError):
raise
except Exception as exc:
+3 -3
View File
@@ -27,13 +27,13 @@ classifiers = [
]
dependencies = [
"httpx==0.28.1",
"tonutils[pytoniq]==2.0.0",
"tonutils[pytoniq]==2.0.4",
]
[project.optional-dependencies]
dev = [
"pytest>=9.0",
"pytest-asyncio>=1.0",
"pytest==9.0.2",
"pytest-asyncio==1.3.0",
"ruff",
"black",
]
+6 -1
View File
@@ -8,7 +8,7 @@ from pyfragment import FragmentClient
from pyfragment.types import ConfigurationError, CookieError
VALID_SEED = "abandon " * 23 + "about"
VALID_API_KEY = "test_api_key"
VALID_API_KEY = "A" * 68
VALID_COOKIES = {
"stel_ssid": "x",
"stel_dt": "x",
@@ -92,3 +92,8 @@ def test_valid_mnemonic_lengths() -> None:
seed = " ".join(["abandon"] * (length - 1) + ["about"])
client = FragmentClient(seed=seed, api_key=VALID_API_KEY, cookies=VALID_COOKIES)
assert len(client.seed.split()) == length
def test_short_api_key_raises() -> None:
with pytest.raises(ConfigurationError):
FragmentClient(seed=VALID_SEED, api_key="A" * 42, cookies=VALID_COOKIES)