mirror of
https://github.com/bohd4nx/FragmentAPI.git
synced 2026-07-25 14:24:31 +00:00
155 lines
5.9 KiB
Python
155 lines
5.9 KiB
Python
"""Verify wallet inspection returns friendly GRAM (ex TON) and USDT balances from Tonapi."""
|
|
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from pyfragment import FragmentClient, WalletInfo
|
|
from tests.shared import FAKE_ADDRESS, FAKE_BALANCE_NANOGRAM
|
|
|
|
# Wallet mocked tests (GRAM and USDT balances are returned separately)
|
|
|
|
|
|
@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_NANOGRAM
|
|
mock_wallet.state = MagicMock(value="active")
|
|
mock_wallet.address.to_str.return_value = FAKE_ADDRESS
|
|
|
|
with (
|
|
patch("pyfragment.services.tonapi.account._make_ton_client") as mock_tonapi,
|
|
patch("pyfragment.services.tonapi.account.WALLET_CLASSES") as mock_classes,
|
|
patch("pyfragment.services.tonapi.account.get_usdt_balance", AsyncMock(return_value=12.3456)),
|
|
):
|
|
mock_tonapi.return_value.__aenter__ = AsyncMock(return_value=MagicMock())
|
|
mock_tonapi.return_value.__aexit__ = AsyncMock(return_value=False) # _make_ton_client returns context manager
|
|
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.gram_balance == round(FAKE_BALANCE_NANOGRAM / 1_000_000_000, 4)
|
|
assert result.usdt_balance == 12.3456
|
|
|
|
|
|
@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.services.tonapi.account._make_ton_client") as mock_tonapi,
|
|
patch("pyfragment.services.tonapi.account.WALLET_CLASSES") as mock_classes,
|
|
patch("pyfragment.services.tonapi.account.get_usdt_balance", AsyncMock(return_value=0.0)),
|
|
):
|
|
mock_tonapi.return_value.__aenter__ = AsyncMock(return_value=MagicMock())
|
|
mock_tonapi.return_value.__aexit__ = AsyncMock(return_value=False) # _make_ton_client returns context manager
|
|
mock_classes["V5R1"].from_mnemonic.return_value = (mock_wallet, MagicMock(), None, None)
|
|
|
|
result = await client.get_wallet()
|
|
|
|
assert result.gram_balance == 0.0
|
|
assert result.usdt_balance == 0.0
|
|
assert result.state == "uninit"
|
|
|
|
|
|
# _make_ton_client — provider selection
|
|
|
|
|
|
def test_make_ton_client_uses_toncenter_for_toncenter_provider(client: FragmentClient) -> None:
|
|
from tonutils.clients import ToncenterClient
|
|
|
|
from pyfragment.enums import ApiProvider
|
|
from pyfragment.services.tonapi.account import _make_ton_client
|
|
|
|
client.api_provider = ApiProvider.TONCENTER
|
|
result = _make_ton_client(client)
|
|
assert isinstance(result, ToncenterClient)
|
|
|
|
|
|
def test_make_ton_client_uses_tonapi_for_tonapi_provider(client: FragmentClient) -> None:
|
|
from tonutils.clients import TonapiClient
|
|
|
|
from pyfragment.enums import ApiProvider
|
|
from pyfragment.services.tonapi.account import _make_ton_client
|
|
|
|
client.api_provider = ApiProvider.TONAPI
|
|
result = _make_ton_client(client)
|
|
assert isinstance(result, TonapiClient)
|
|
|
|
|
|
# get_usdt_balance — error paths
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_usdt_balance_non_404_provider_error_raises() -> None:
|
|
from tonutils.exceptions import ProviderResponseError
|
|
|
|
from pyfragment import WalletError
|
|
from pyfragment.services.tonapi.account import get_usdt_balance
|
|
|
|
ton = MagicMock()
|
|
err = ProviderResponseError(code=500, message="server error", endpoint="api.tonapi.io")
|
|
|
|
with patch("pyfragment.services.tonapi.account.get_wallet_address_get_method", AsyncMock(side_effect=err)):
|
|
with pytest.raises(WalletError):
|
|
await get_usdt_balance(ton, "0:abc")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_usdt_balance_generic_exception_raises() -> None:
|
|
from pyfragment import WalletError
|
|
from pyfragment.services.tonapi.account import get_usdt_balance
|
|
|
|
ton = MagicMock()
|
|
|
|
with patch(
|
|
"pyfragment.services.tonapi.account.get_wallet_address_get_method", AsyncMock(side_effect=RuntimeError("timeout"))
|
|
):
|
|
with pytest.raises(WalletError):
|
|
await get_usdt_balance(ton, "0:abc")
|
|
|
|
|
|
# get_account_info / get_wallet_info — exception paths
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_account_info_exception_raises_wallet_error(client: FragmentClient) -> None:
|
|
from pyfragment import WalletError
|
|
from pyfragment.services.tonapi.account import get_account_info
|
|
|
|
with (
|
|
patch("pyfragment.services.tonapi.account._make_ton_client") as mock_tonapi,
|
|
patch("pyfragment.services.tonapi.account.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.side_effect = RuntimeError("wallet init failed")
|
|
|
|
with pytest.raises(WalletError, match="account info"):
|
|
await get_account_info(client)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_wallet_info_exception_raises_wallet_error(client: FragmentClient) -> None:
|
|
from pyfragment import WalletError
|
|
from pyfragment.services.tonapi.account import get_wallet_info
|
|
|
|
with (
|
|
patch("pyfragment.services.tonapi.account._make_ton_client") as mock_tonapi,
|
|
patch("pyfragment.services.tonapi.account.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.side_effect = RuntimeError("key derivation failed")
|
|
|
|
with pytest.raises(WalletError, match="wallet info"):
|
|
await get_wallet_info(client)
|