From c7b6c6c93318be23de42c2294c0650e170c25405 Mon Sep 17 00:00:00 2001 From: bohd4nx Date: Sat, 21 Mar 2026 16:30:44 +0200 Subject: [PATCH] feat: add comprehensive unit tests for FragmentClient methods; include shared test constants --- tests/001_test_decode.py | 6 ++ tests/002_test_client.py | 62 ++++++++++--------- tests/004_test_balance.py | 9 ++- tests/005_test_stars.py | 125 ++++++++++++++++++++++++++++++++++++++ tests/006_test_premium.py | 119 ++++++++++++++++++++++++++++++++++++ tests/007_test_topup.py | 72 ++++++++++++++++++++++ tests/008_test_wallet.py | 59 ++++++++++++++++++ tests/conftest.py | 9 +++ tests/shared.py | 23 +++++++ 9 files changed, 454 insertions(+), 30 deletions(-) create mode 100644 tests/005_test_stars.py create mode 100644 tests/006_test_premium.py create mode 100644 tests/007_test_topup.py create mode 100644 tests/008_test_wallet.py create mode 100644 tests/shared.py diff --git a/tests/001_test_decode.py b/tests/001_test_decode.py index 170fa1e..0b59b82 100644 --- a/tests/001_test_decode.py +++ b/tests/001_test_decode.py @@ -23,6 +23,9 @@ PAYLOADS = [ ] +# Decode valid payload tests + + @pytest.mark.parametrize("payload", PAYLOADS) def test_decode_payload(payload: str) -> None: result = clean_decode(payload) @@ -31,6 +34,9 @@ def test_decode_payload(payload: str) -> None: assert all(ord(c) < 128 for c in result), f"non-ASCII chars in {result!r}" +# Edge case tests + + def test_empty_payload_returns_empty_string() -> None: assert clean_decode("") == "" diff --git a/tests/002_test_client.py b/tests/002_test_client.py index ccf10fe..8e5607e 100644 --- a/tests/002_test_client.py +++ b/tests/002_test_client.py @@ -6,15 +6,9 @@ import pytest from pyfragment import FragmentClient from pyfragment.types import ConfigurationError, CookieError +from tests.shared import VALID_API_KEY, VALID_COOKIES, VALID_SEED -VALID_SEED = "abandon " * 23 + "about" -VALID_API_KEY = "A" * 68 -VALID_COOKIES = { - "stel_ssid": "x", - "stel_dt": "x", - "stel_token": "x", - "stel_ton_token": "x", -} +# Client init tests def test_valid_init() -> None: @@ -24,6 +18,9 @@ def test_valid_init() -> None: assert client.wallet_version == "V5R1" +# Wallet version tests + + def test_wallet_version_v4r2() -> None: client = FragmentClient(seed=VALID_SEED, api_key=VALID_API_KEY, cookies=VALID_COOKIES, wallet_version="V4R2") assert client.wallet_version == "V4R2" @@ -34,6 +31,14 @@ def test_wallet_version_is_case_insensitive() -> None: assert client.wallet_version == "V5R1" +def test_unsupported_wallet_version_raises() -> None: + with pytest.raises(ConfigurationError): + FragmentClient(seed=VALID_SEED, api_key=VALID_API_KEY, cookies=VALID_COOKIES, wallet_version="V3R2") + + +# Seed and mnemonic validation tests + + def test_missing_seed_raises() -> None: with pytest.raises(ConfigurationError): FragmentClient(seed="", api_key=VALID_API_KEY, cookies=VALID_COOKIES) @@ -44,14 +49,33 @@ def test_whitespace_only_seed_raises() -> None: FragmentClient(seed=" ", api_key=VALID_API_KEY, cookies=VALID_COOKIES) +def test_invalid_mnemonic_length_raises() -> None: + bad_seed = " ".join(["word"] * 23) + with pytest.raises(ConfigurationError): + FragmentClient(seed=bad_seed, api_key=VALID_API_KEY, cookies=VALID_COOKIES) + + +def test_valid_mnemonic_lengths() -> None: + for length in (12, 18, 24): + seed = " ".join(["abandon"] * (length - 1) + ["about"]) + client = FragmentClient(seed=seed, api_key=VALID_API_KEY, cookies=VALID_COOKIES) + assert len(client.seed.split()) == length + + +# API key validation tests + + def test_missing_api_key_raises() -> None: with pytest.raises(ConfigurationError): FragmentClient(seed=VALID_SEED, api_key="", cookies=VALID_COOKIES) -def test_unsupported_wallet_version_raises() -> None: +def test_short_api_key_raises() -> None: with pytest.raises(ConfigurationError): - FragmentClient(seed=VALID_SEED, api_key=VALID_API_KEY, cookies=VALID_COOKIES, wallet_version="V3R2") + FragmentClient(seed=VALID_SEED, api_key="A" * 42, cookies=VALID_COOKIES) + + +# Cookie validation tests def test_cookies_as_json_string() -> None: @@ -81,24 +105,6 @@ def test_whitespace_cookie_value_raises() -> None: FragmentClient(seed=VALID_SEED, api_key=VALID_API_KEY, cookies=bad) -def test_invalid_mnemonic_length_raises() -> None: - bad_seed = " ".join(["word"] * 23) - with pytest.raises(ConfigurationError): - FragmentClient(seed=bad_seed, api_key=VALID_API_KEY, cookies=VALID_COOKIES) - - -def test_valid_mnemonic_lengths() -> None: - for length in (12, 18, 24): - 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) - - def test_repr() -> None: client = FragmentClient(seed=VALID_SEED, api_key=VALID_API_KEY, cookies=VALID_COOKIES) r = repr(client) diff --git a/tests/004_test_balance.py b/tests/004_test_balance.py index a784300..6d48f23 100644 --- a/tests/004_test_balance.py +++ b/tests/004_test_balance.py @@ -7,8 +7,7 @@ import pytest from pyfragment.types import TransactionError, WalletError from pyfragment.utils.wallet import process_transaction - -VALID_SEED = "abandon " * 23 + "about" +from tests.shared import VALID_SEED TRANSACTION_DATA = { "transaction": { @@ -51,6 +50,9 @@ def _patch_wallet(wallet: MagicMock): yield +# Balance threshold tests + + @pytest.mark.asyncio async def test_sufficient_balance_broadcasts() -> None: wallet = _make_wallet(balance_nanotons=1_000_000_000) # 1 TON, needs 0.556 TON @@ -85,6 +87,9 @@ async def test_one_nanoton_below_minimum_raises() -> None: await process_transaction(_make_client(), TRANSACTION_DATA) +# Error handling tests + + @pytest.mark.asyncio async def test_invalid_payload_raises() -> None: with pytest.raises(TransactionError): diff --git a/tests/005_test_stars.py b/tests/005_test_stars.py new file mode 100644 index 0000000..826dc04 --- /dev/null +++ b/tests/005_test_stars.py @@ -0,0 +1,125 @@ +"""Unit tests for purchase_stars and giveaway_stars — validation and mocked network calls.""" + +from unittest.mock import AsyncMock, patch + +import pytest + +from pyfragment import FragmentClient +from pyfragment.types import ConfigurationError, StarsGiveawayResult, StarsResult, UserNotFoundError +from tests.shared import FAKE_ACCOUNT, FAKE_HASH, FAKE_RECIPIENT, FAKE_REQ_ID, FAKE_TRANSACTION, FAKE_TX_HASH + +# Stars purchase validation tests + + +@pytest.mark.asyncio +async def test_purchase_stars_amount_too_low(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.purchase_stars("@user", amount=49) + + +@pytest.mark.asyncio +async def test_purchase_stars_amount_too_high(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.purchase_stars("@user", amount=1_000_001) + + +@pytest.mark.asyncio +async def test_purchase_stars_float_amount(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.purchase_stars("@user", amount=100.5) # type: ignore[arg-type] + + +# Stars purchase mocked tests + + +@pytest.mark.asyncio +async def test_purchase_stars_success(client: FragmentClient) -> None: + with ( + patch("pyfragment.methods.purchase_stars.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)), + patch("pyfragment.methods.purchase_stars.get_account_info", AsyncMock(return_value=FAKE_ACCOUNT)), + patch( + "pyfragment.methods.purchase_stars.fragment_request", + AsyncMock(side_effect=[{"found": {"recipient": FAKE_RECIPIENT}}, {"req_id": FAKE_REQ_ID}]), + ), + patch("pyfragment.methods.purchase_stars.execute_transaction_request", AsyncMock(return_value=FAKE_TRANSACTION)), + patch("pyfragment.methods.purchase_stars.process_transaction", AsyncMock(return_value=FAKE_TX_HASH)), + ): + result = await client.purchase_stars("@user", amount=500) + + assert isinstance(result, StarsResult) + assert result.transaction_id == FAKE_TX_HASH + assert result.username == "@user" + assert result.amount == 500 + + +@pytest.mark.asyncio +async def test_purchase_stars_user_not_found(client: FragmentClient) -> None: + with ( + patch("pyfragment.methods.purchase_stars.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)), + patch("pyfragment.methods.purchase_stars.get_account_info", AsyncMock(return_value=FAKE_ACCOUNT)), + patch("pyfragment.methods.purchase_stars.fragment_request", AsyncMock(return_value={"found": {}})), + ): + with pytest.raises(UserNotFoundError): + await client.purchase_stars("@ghost", amount=500) + + +# Stars giveaway validation tests + + +@pytest.mark.asyncio +async def test_giveaway_stars_winners_too_low(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.giveaway_stars("@channel", winners=0, amount=500) + + +@pytest.mark.asyncio +async def test_giveaway_stars_winners_too_high(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.giveaway_stars("@channel", winners=6, amount=500) + + +@pytest.mark.asyncio +async def test_giveaway_stars_amount_too_low(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.giveaway_stars("@channel", winners=1, amount=499) + + +@pytest.mark.asyncio +async def test_giveaway_stars_amount_too_high(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.giveaway_stars("@channel", winners=1, amount=1_000_001) + + +# Stars giveaway mocked tests + + +@pytest.mark.asyncio +async def test_giveaway_stars_success(client: FragmentClient) -> None: + with ( + patch("pyfragment.methods.giveaway_stars.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)), + patch("pyfragment.methods.giveaway_stars.get_account_info", AsyncMock(return_value=FAKE_ACCOUNT)), + patch( + "pyfragment.methods.giveaway_stars.fragment_request", + AsyncMock(side_effect=[{"found": {"recipient": FAKE_RECIPIENT}}, {"req_id": FAKE_REQ_ID}]), + ), + patch("pyfragment.methods.giveaway_stars.execute_transaction_request", AsyncMock(return_value=FAKE_TRANSACTION)), + patch("pyfragment.methods.giveaway_stars.process_transaction", AsyncMock(return_value=FAKE_TX_HASH)), + ): + result = await client.giveaway_stars("@channel", winners=3, amount=1000) + + assert isinstance(result, StarsGiveawayResult) + assert result.transaction_id == FAKE_TX_HASH + assert result.channel == "@channel" + assert result.winners == 3 + assert result.amount == 1000 + + +@pytest.mark.asyncio +async def test_giveaway_stars_channel_not_found(client: FragmentClient) -> None: + with ( + patch("pyfragment.methods.giveaway_stars.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)), + patch("pyfragment.methods.giveaway_stars.get_account_info", AsyncMock(return_value=FAKE_ACCOUNT)), + patch("pyfragment.methods.giveaway_stars.fragment_request", AsyncMock(return_value={"found": {}})), + ): + with pytest.raises(UserNotFoundError): + await client.giveaway_stars("@ghost", winners=1, amount=500) diff --git a/tests/006_test_premium.py b/tests/006_test_premium.py new file mode 100644 index 0000000..1495474 --- /dev/null +++ b/tests/006_test_premium.py @@ -0,0 +1,119 @@ +"""Unit tests for purchase_premium and giveaway_premium — validation and mocked network calls.""" + +from unittest.mock import AsyncMock, patch + +import pytest + +from pyfragment import FragmentClient +from pyfragment.types import ConfigurationError, PremiumGiveawayResult, PremiumResult, UserNotFoundError +from tests.shared import FAKE_ACCOUNT, FAKE_HASH, FAKE_RECIPIENT, FAKE_REQ_ID, FAKE_TRANSACTION, FAKE_TX_HASH + +# Premium purchase validation tests + + +@pytest.mark.asyncio +async def test_purchase_premium_invalid_months(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.purchase_premium("@user", months=5) + + +@pytest.mark.asyncio +async def test_purchase_premium_months_zero(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.purchase_premium("@user", months=0) + + +# Premium purchase mocked tests + + +@pytest.mark.asyncio +async def test_purchase_premium_success(client: FragmentClient) -> None: + with ( + patch("pyfragment.methods.purchase_premium.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)), + patch("pyfragment.methods.purchase_premium.get_account_info", AsyncMock(return_value=FAKE_ACCOUNT)), + patch( + "pyfragment.methods.purchase_premium.fragment_request", + AsyncMock( + side_effect=[ + {"found": {"recipient": FAKE_RECIPIENT}}, + {}, # updatePremiumState + {"req_id": FAKE_REQ_ID}, + ] + ), + ), + patch("pyfragment.methods.purchase_premium.execute_transaction_request", AsyncMock(return_value=FAKE_TRANSACTION)), + patch("pyfragment.methods.purchase_premium.process_transaction", AsyncMock(return_value=FAKE_TX_HASH)), + ): + result = await client.purchase_premium("@user", months=3) + + assert isinstance(result, PremiumResult) + assert result.transaction_id == FAKE_TX_HASH + assert result.username == "@user" + assert result.amount == 3 + + +@pytest.mark.asyncio +async def test_purchase_premium_user_not_found(client: FragmentClient) -> None: + with ( + patch("pyfragment.methods.purchase_premium.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)), + patch("pyfragment.methods.purchase_premium.get_account_info", AsyncMock(return_value=FAKE_ACCOUNT)), + patch("pyfragment.methods.purchase_premium.fragment_request", AsyncMock(return_value={"found": {}})), + ): + with pytest.raises(UserNotFoundError): + await client.purchase_premium("@ghost", months=3) + + +# Premium giveaway validation tests + + +@pytest.mark.asyncio +async def test_giveaway_premium_winners_too_low(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.giveaway_premium("@channel", winners=0, months=3) + + +@pytest.mark.asyncio +async def test_giveaway_premium_winners_too_high(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.giveaway_premium("@channel", winners=24_001, months=3) + + +@pytest.mark.asyncio +async def test_giveaway_premium_invalid_months(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.giveaway_premium("@channel", winners=10, months=5) + + +# Premium giveaway mocked tests + + +@pytest.mark.asyncio +async def test_giveaway_premium_success(client: FragmentClient) -> None: + with ( + patch("pyfragment.methods.giveaway_premium.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)), + patch("pyfragment.methods.giveaway_premium.get_account_info", AsyncMock(return_value=FAKE_ACCOUNT)), + patch( + "pyfragment.methods.giveaway_premium.fragment_request", + AsyncMock(side_effect=[{"found": {"recipient": FAKE_RECIPIENT}}, {"req_id": FAKE_REQ_ID}]), + ), + patch("pyfragment.methods.giveaway_premium.execute_transaction_request", AsyncMock(return_value=FAKE_TRANSACTION)), + patch("pyfragment.methods.giveaway_premium.process_transaction", AsyncMock(return_value=FAKE_TX_HASH)), + ): + result = await client.giveaway_premium("@channel", winners=10, months=3) + + assert isinstance(result, PremiumGiveawayResult) + assert result.transaction_id == FAKE_TX_HASH + assert result.channel == "@channel" + assert result.winners == 10 + assert result.amount == 3 + + +@pytest.mark.asyncio +async def test_giveaway_premium_channel_not_found(client: FragmentClient) -> None: + with ( + patch("pyfragment.methods.giveaway_premium.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)), + patch("pyfragment.methods.giveaway_premium.get_account_info", AsyncMock(return_value=FAKE_ACCOUNT)), + patch("pyfragment.methods.giveaway_premium.fragment_request", AsyncMock(return_value={"found": {}})), + ): + with pytest.raises(UserNotFoundError): + await client.giveaway_premium("@ghost", winners=1, months=3) diff --git a/tests/007_test_topup.py b/tests/007_test_topup.py new file mode 100644 index 0000000..3cad838 --- /dev/null +++ b/tests/007_test_topup.py @@ -0,0 +1,72 @@ +"""Unit tests for topup_ton — validation and mocked network calls.""" + +from unittest.mock import AsyncMock, patch + +import pytest + +from pyfragment import FragmentClient +from pyfragment.types import AdsTopupResult, ConfigurationError, UserNotFoundError +from tests.shared import FAKE_ACCOUNT, FAKE_HASH, FAKE_RECIPIENT, FAKE_REQ_ID, FAKE_TRANSACTION, FAKE_TX_HASH + +# Topup TON validation tests + + +@pytest.mark.asyncio +async def test_topup_ton_amount_zero(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.topup_ton("@user", amount=0) + + +@pytest.mark.asyncio +async def test_topup_ton_amount_too_high(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.topup_ton("@user", amount=1_000_000_001) + + +@pytest.mark.asyncio +async def test_topup_ton_float_amount(client: FragmentClient) -> None: + with pytest.raises(ConfigurationError): + await client.topup_ton("@user", amount=1.5) # type: ignore[arg-type] + + +# Topup TON mocked tests + + +@pytest.mark.asyncio +async def test_topup_ton_success(client: FragmentClient) -> None: + with ( + patch("pyfragment.methods.topup_ton.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)), + patch("pyfragment.methods.topup_ton.get_account_info", AsyncMock(return_value=FAKE_ACCOUNT)), + patch( + "pyfragment.methods.topup_ton.fragment_request", + AsyncMock( + side_effect=[ + {}, # updateAdsTopupState + {"found": {"recipient": FAKE_RECIPIENT}}, + {"req_id": FAKE_REQ_ID}, + ] + ), + ), + patch("pyfragment.methods.topup_ton.execute_transaction_request", AsyncMock(return_value=FAKE_TRANSACTION)), + patch("pyfragment.methods.topup_ton.process_transaction", AsyncMock(return_value=FAKE_TX_HASH)), + ): + result = await client.topup_ton("@user", amount=10) + + assert isinstance(result, AdsTopupResult) + assert result.transaction_id == FAKE_TX_HASH + assert result.username == "@user" + assert result.amount == 10 + + +@pytest.mark.asyncio +async def test_topup_ton_user_not_found(client: FragmentClient) -> None: + with ( + patch("pyfragment.methods.topup_ton.get_fragment_hash", AsyncMock(return_value=FAKE_HASH)), + patch("pyfragment.methods.topup_ton.get_account_info", AsyncMock(return_value=FAKE_ACCOUNT)), + patch( + "pyfragment.methods.topup_ton.fragment_request", + AsyncMock(side_effect=[{}, {"found": {}}]), + ), + ): + with pytest.raises(UserNotFoundError): + await client.topup_ton("@ghost", amount=10) diff --git a/tests/008_test_wallet.py b/tests/008_test_wallet.py new file mode 100644 index 0000000..b4279dd --- /dev/null +++ b/tests/008_test_wallet.py @@ -0,0 +1,59 @@ +"""Unit tests for get_wallet — mocked network calls.""" + +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest + +from pyfragment import FragmentClient, WalletInfo + +FAKE_ADDRESS = "UQCppfw5DxWgdVHf3zkmZS8k1mt9oAUYxQLwq2fz3nhO8No5" +FAKE_BALANCE_NANOTON = 1_500_000_000 # 1.5 TON + + +# Wallet mocked tests + + +@pytest.mark.asyncio +async def test_get_wallet_returns_wallet_info(client: FragmentClient) -> None: + mock_wallet = MagicMock() + mock_wallet.refresh = AsyncMock() + mock_wallet.balance = FAKE_BALANCE_NANOTON + mock_wallet.state = MagicMock(value="active") + mock_wallet.address.to_str.return_value = FAKE_ADDRESS + + with ( + patch("pyfragment.utils.wallet.TonapiClient") as mock_tonapi, + patch("pyfragment.utils.wallet.WALLET_CLASSES") as mock_classes, + ): + mock_tonapi.return_value.__aenter__ = AsyncMock(return_value=MagicMock()) + mock_tonapi.return_value.__aexit__ = AsyncMock(return_value=False) + mock_classes["V5R1"].from_mnemonic.return_value = (mock_wallet, MagicMock(), None, None) + + result = await client.get_wallet() + + assert isinstance(result, WalletInfo) + assert result.address == FAKE_ADDRESS + assert result.state == "active" + assert result.balance == round(FAKE_BALANCE_NANOTON / 1_000_000_000, 4) + + +@pytest.mark.asyncio +async def test_get_wallet_balance_is_zero(client: FragmentClient) -> None: + mock_wallet = MagicMock() + mock_wallet.refresh = AsyncMock() + mock_wallet.balance = 0 + mock_wallet.state = MagicMock(value="uninit") + mock_wallet.address.to_str.return_value = FAKE_ADDRESS + + with ( + patch("pyfragment.utils.wallet.TonapiClient") as mock_tonapi, + patch("pyfragment.utils.wallet.WALLET_CLASSES") as mock_classes, + ): + mock_tonapi.return_value.__aenter__ = AsyncMock(return_value=MagicMock()) + mock_tonapi.return_value.__aexit__ = AsyncMock(return_value=False) + mock_classes["V5R1"].from_mnemonic.return_value = (mock_wallet, MagicMock(), None, None) + + result = await client.get_wallet() + + assert result.balance == 0.0 + assert result.state == "uninit" diff --git a/tests/conftest.py b/tests/conftest.py index 68c5e75..a05bfd4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,6 +3,9 @@ import os import pytest +from pyfragment import FragmentClient +from tests.shared import VALID_API_KEY, VALID_COOKIES, VALID_SEED + @pytest.fixture def cookies(): @@ -14,3 +17,9 @@ def cookies(): return json.loads(raw) except Exception as exc: pytest.skip(f"Cookies unavailable — {exc}") + + +@pytest.fixture +def client() -> FragmentClient: + """Pre-built FragmentClient with dummy credentials.""" + return FragmentClient(seed=VALID_SEED, api_key=VALID_API_KEY, cookies=VALID_COOKIES) diff --git a/tests/shared.py b/tests/shared.py new file mode 100644 index 0000000..042095b --- /dev/null +++ b/tests/shared.py @@ -0,0 +1,23 @@ +"""Shared test constants — imported by all test modules that need them.""" + +from typing import Any + +# Shared test credentials + +VALID_SEED: str = "abandon " * 23 + "about" +VALID_API_KEY: str = "A" * 68 +VALID_COOKIES: dict[str, str] = { + "stel_ssid": "x", + "stel_dt": "x", + "stel_token": "x", + "stel_ton_token": "x", +} + +# Fake values for mocked tests + +FAKE_HASH: str = "abc123" +FAKE_RECIPIENT: str = "recipient_token" +FAKE_REQ_ID: str = "req_42" +FAKE_TX_HASH: str = "deadbeef" * 8 +FAKE_ACCOUNT: dict[str, Any] = {"address": "0:abc", "publicKey": "pub", "chain": "-239", "walletStateInit": "base64=="} +FAKE_TRANSACTION: dict[str, Any] = {"transaction": {"messages": [{"address": "0:abc", "amount": "100000000", "payload": ""}]}}