# Author: Simon-Pierre Boucher # Mail: contact@spboucher.ai """Unit checks for the Tron and Solana adapters (plain asserts).""" import pathlib import sys sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) from indexer import db from indexer.adapters.solana import SolanaIndexer from indexer.adapters.tron import ( TronIndexer, b58check_decode, hex20_to_taddr, taddr_to_hex20, ) # Known vector: Tron USDT contract (verified via tronscan + tether.to) USDT_T = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t" USDT_HEX = "a614f803b6fd780986a42c78ec9c7f77e6ded13c" def test_base58check_roundtrip(): assert taddr_to_hex20(USDT_T) == USDT_HEX assert hex20_to_taddr(USDT_HEX) == USDT_T try: b58check_decode("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj7t") # corrupted raise AssertionError("bad checksum accepted") except ValueError: pass def make_tron(): ix = TronIndexer( "tron", {"rpcs": ["http://unused.invalid"]}, [{"symbol": "USDT", "id": USDT_T, "decimals": 6, "native": True}], ":memory:", ) ix.conn = db.connect(":memory:") return ix def test_tron_decodes_trc20_transfer(): ix = make_tron() frm_hex, to_hex = "11" * 20, "22" * 20 ix.block_infos = lambda n: [{ "id": "deadbeef" * 8, "blockTimeStamp": 1785975000123, "receipt": {"result": "SUCCESS"}, "log": [{ "address": "41" + USDT_HEX, # some nodes include the 41 prefix "topics": [ "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", frm_hex.rjust(64, "0"), to_hex.rjust(64, "0"), ], "data": hex(5_000_000)[2:].rjust(64, "0"), }], }] n = ix.process_block(75_000_000) assert n == 1 row = ix.conn.execute("SELECT token, symbol, \"from\", \"to\", amount, timestamp FROM transfers").fetchone() assert row[0] == USDT_T and row[1] == "USDT" assert row[2] == hex20_to_taddr(frm_hex) and row[3] == hex20_to_taddr(to_hex) assert row[4] == "5000000" and row[5] == 1785975000 USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" def make_solana(): ix = SolanaIndexer( "solana", {"rpcs": ["http://unused.invalid"]}, [{"symbol": "USDC", "id": USDC_MINT, "decimals": 6, "native": True}], ":memory:", ) ix.conn = db.connect(":memory:") return ix def bal(idx, owner, amount): return {"accountIndex": idx, "mint": USDC_MINT, "owner": owner, "uiTokenAmount": {"amount": str(amount)}} def test_solana_balance_diff_pairing(): ix = make_solana() blk = { "blockTime": 1785975100, "blockhash": "H" * 44, "transactions": [{ "meta": { "err": None, "preTokenBalances": [bal(1, "AliceOwner", 10_000_000), bal(2, "BobOwner", 0)], "postTokenBalances": [bal(1, "AliceOwner", 4_000_000), bal(2, "BobOwner", 6_000_000)], }, "transaction": {"signatures": ["5igSig"]}, }], } n = ix.process_block(360_000_000, blk) assert n == 1 row = ix.conn.execute('SELECT "from", "to", amount, symbol FROM transfers').fetchone() assert tuple(row) == ("AliceOwner", "BobOwner", "6000000", "USDC") def test_solana_ambiguous_senders_kept_with_null_from(): ix = make_solana() blk = { "blockTime": 1785975100, "blockhash": "H" * 44, "transactions": [{ "meta": { "err": None, "preTokenBalances": [bal(1, "A", 5), bal(2, "B", 5), bal(3, "C", 0)], "postTokenBalances": [bal(1, "A", 0), bal(2, "B", 0), bal(3, "C", 10)], }, "transaction": {"signatures": ["sig2"]}, }], } assert ix.process_block(360_000_001, blk) == 1 row = ix.conn.execute('SELECT "from", "to", amount FROM transfers').fetchone() assert tuple(row) == (None, "C", "10") # amount exact, sender ambiguous def test_solana_failed_tx_skipped(): ix = make_solana() blk = { "blockTime": 1, "transactions": [{ "meta": {"err": {"InstructionError": [0, "Custom"]}, "preTokenBalances": [bal(1, "A", 5)], "postTokenBalances": [bal(1, "A", 0)]}, "transaction": {"signatures": ["sig3"]}, }], } assert ix.process_block(1, blk) == 0 if __name__ == "__main__": for name, fn in sorted(globals().items()): if name.startswith("test_"): fn() print(f"ok {name}") print("all adapter tests passed")