mirror of
https://github.com/bohd4nx/FragmentAPI.git
synced 2026-07-25 14:24:31 +00:00
01a5befd87
- Removed wallet transaction and transfer logic from the wallet domain. - Introduced a new tonapi module to handle transactions and balance checks. - Updated tests to reflect the new structure and ensure functionality remains intact. - Added functionality for sending TON and USDT transfers through the tonapi module. - Improved error handling and validation for payment balances. - Cleaned up and organized imports across the codebase.
133 lines
4.1 KiB
Python
133 lines
4.1 KiB
Python
"""Decode Fragment BOC payloads so comments become text and structured messages stay raw."""
|
|
|
|
import base64
|
|
import re
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from ton_core import Cell
|
|
|
|
from pyfragment import ParseError
|
|
from pyfragment.domains.tonapi.transaction import clean_decode
|
|
|
|
PAYLOAD_CASES = [
|
|
pytest.param(
|
|
"te6ccgEBAgEALwABTgAAAAAxMDAwMDAwIFRlbGVncmFtIFN0YXJzIAoKUmVmI1RQb01wegEABkM3ZQ",
|
|
True,
|
|
id="stars",
|
|
),
|
|
pytest.param(
|
|
"te6ccgEBAgEANAABTgAAAABUZWxlZ3JhbSBQcmVtaXVtIGZvciAxIHllYXIgCgpSZWYjcgEAEE9OQnM2cmNt",
|
|
True,
|
|
id="premium",
|
|
),
|
|
pytest.param(
|
|
"te6ccgEBAgEAMAABTgAAAABUZWxlZ3JhbSBhY2NvdW50IHRvcCB1cCAKClJlZiNrMXpDRQEACFkxd3g",
|
|
True,
|
|
id="topup",
|
|
),
|
|
pytest.param(
|
|
"te6ccgEBAgEAfgABqA-KfqVP885dhccidjC3GwgBCkiH8LM_zUu0afyGCTWJwX1mDjdlf2rMa9UoQlD4UHUAF1jLlcMomlo5RJTwl8jnDDdfdhc7EgQQWPqFQ9IjyLPCAwEASgAAAAA1MCBUZWxlZ3JhbSBTdGFycyAKClJlZiNtOUpoWndBcFE",
|
|
False,
|
|
id="real_stars_50",
|
|
),
|
|
pytest.param(
|
|
"te6ccgEBAgEANgABTgAAAABUZWxlZ3JhbSBQcmVtaXVtIGZvciAzIG1vbnRocyAKClJlZgEAFCMzcFdKdGJkYnU",
|
|
False,
|
|
id="real_premium_3m",
|
|
),
|
|
pytest.param(
|
|
"te6ccgEBAwEAhgABqg-KfqWibdDaYaJCPUWWgvAIAQpIh_CzP81LtGn8hgk1icF9Zg43ZX9qzGvVKEJQ-FB1ABdYy5XDKJpaOUSU8JfI5ww3X3YXOxIEEFj6hUPSI8izwgMBAU4AAAAAMTAwMDAwIFRlbGVncmFtIFN0YXJzIAoKUmVmIzBoZ0RmNEYCAAQ5VA",
|
|
False,
|
|
id="real_stars_100k",
|
|
),
|
|
]
|
|
|
|
|
|
# Decode valid payload tests
|
|
|
|
|
|
@pytest.mark.parametrize(("payload", "strict_ref"), PAYLOAD_CASES)
|
|
def test_decode_payload(payload: str, strict_ref: bool) -> None:
|
|
result = clean_decode(payload)
|
|
if isinstance(result, str):
|
|
assert "Telegram" in result
|
|
if strict_ref:
|
|
assert re.search(r"Ref#[A-Za-z0-9]+", result), f"no Ref# in {result!r}"
|
|
assert all(ord(c) < 128 for c in result), f"non-ASCII chars in {result!r}"
|
|
else:
|
|
assert isinstance(result, Cell)
|
|
|
|
|
|
# Edge case tests
|
|
|
|
|
|
def test_empty_payload_returns_empty_string() -> None:
|
|
assert clean_decode("") == ""
|
|
|
|
|
|
def test_invalid_payload_raises_parse_error() -> None:
|
|
with pytest.raises(ParseError):
|
|
clean_decode("!!!not-valid-base64!!!")
|
|
|
|
|
|
def test_decode_payload_accepts_base64url_alphabet() -> None:
|
|
class _FakeSlice:
|
|
def load_uint(self, _: int) -> int:
|
|
return 0
|
|
|
|
def load_snake_string(self) -> str:
|
|
return "Telegram Stars Ref#abc"
|
|
|
|
class _FakeCell:
|
|
def begin_parse(self) -> _FakeSlice:
|
|
return _FakeSlice()
|
|
|
|
raw = b"\xfb\xef\xff\x00"
|
|
payload = base64.urlsafe_b64encode(raw).decode().rstrip("=")
|
|
|
|
with patch("pyfragment.domains.tonapi.transaction.Cell.one_from_boc", return_value=_FakeCell()) as mocked:
|
|
result = clean_decode(payload)
|
|
|
|
mocked.assert_called_once_with(raw)
|
|
assert result == "Telegram Stars Ref#abc"
|
|
|
|
|
|
def test_clean_decode_returns_text_comment_when_utf8() -> None:
|
|
class _FakeSlice:
|
|
def load_uint(self, _: int) -> int:
|
|
return 0
|
|
|
|
def load_snake_string(self) -> str:
|
|
return "Telegram Premium Ref#abc"
|
|
|
|
class _FakeCell:
|
|
def begin_parse(self) -> _FakeSlice:
|
|
return _FakeSlice()
|
|
|
|
payload = base64.urlsafe_b64encode(b"\x00\x01").decode().rstrip("=")
|
|
with patch("pyfragment.domains.tonapi.transaction.Cell.one_from_boc", return_value=_FakeCell()):
|
|
parsed = clean_decode(payload)
|
|
|
|
assert parsed == "Telegram Premium Ref#abc"
|
|
|
|
|
|
def test_clean_decode_returns_cell_for_binary_payload() -> None:
|
|
class _FakeSlice:
|
|
def load_uint(self, _: int) -> int:
|
|
return 0
|
|
|
|
def load_snake_string(self) -> str:
|
|
raise UnicodeDecodeError("utf-8", b"\xff", 0, 1, "invalid start byte")
|
|
|
|
class _FakeCell:
|
|
def begin_parse(self) -> _FakeSlice:
|
|
return _FakeSlice()
|
|
|
|
payload = base64.urlsafe_b64encode(b"\x00\x01").decode().rstrip("=")
|
|
fake_cell: object = _FakeCell()
|
|
with patch("pyfragment.domains.tonapi.transaction.Cell.one_from_boc", return_value=fake_cell):
|
|
parsed = clean_decode(payload)
|
|
|
|
assert parsed is fake_cell
|