Барлық мақалалар
6 мин оқу

TON транзакциялар тарихы: lt, хэш және мұрағат тереңдігі

TON транзакциялар тарихы қалай құрылған: логикалық уақыт (lt), хэштер, соңғы транзакция көрсеткіші. Агентпен MCP арқылы оқу және мұрағат нодасы неге керек.

TON транзакциялар тарихыlogical timelt hash TONget_transactionsTON мұрағат нодасыMCP TON

Түнде жұмыс істеп отырсыз, сағат 3:47-де хабарлама түседі: пайдаланушы тапсырысты TON-мен төлеген, ал бот оны есепке алмаған. Эксплорерді ашасыз — ақша орнында, кіріс аударым көрініп тұр. Демек, мәселе блокчейнде емес, сервисіңіздің транзакциялар тарихын қалай оқитынында. Ал TON-да бұл тарих сіз Ethereum-нан үйренген тәртіппен емес, мүлдем басқаша құрылған.

TON-дағы төлемдер мониторингі алдамшы қарапайым көрінеді: балансты сұрап тұр да, өзгеріске реакция жаса. Бірақ іс жүзінде бұл схема күйреп қалады. Бір минут ішінде бірдей сомаға екі төлем — олар нешеу болды, біреу ме, әлде екеу ме? Пайдаланушы USDT төледі, ал GRAM балансы қыбыр етпеді. Жарты жылдық үзінді-көшірме керек, ал лайтсервер тек соңғы транзакцияларды береді де, қалғаны туралы үндемейді.

Егер сіз ЖИ-агентті TON-ға қоссаңыз немесе төлемдерді салыстыратын бэкенд жазсаңыз, нақтылап талдап көрейік: TON транзакциялар тарихы деген не, lt + hash жұбы не үшін керек, тереңдік неге мұрағат нодасына тіреледі және мұның бәрін агентпен MCP арқылы қалай оқуға болады.

TON-дағы транзакциялар тарихы деген не және ол агентке не үшін керек

TON-да әр аккаунттың — әмиянның, контрактінің, жетон-әмиянның — өз транзакциялар тізбегі бар. Әр транзакция — кіріс хабарламаны өңдеудің нәтижесі: GRAM қабылдау, жетон аудару, контракт әдісін шақыру. Төлем қабылдайтын немесе есеп-қисапты салыстыратын агент (Claude, Cursor, кез келген MCP-клиент) үшін тарих — жалғыз сенімді дереккөз: баланс «қазір қанша» дейді, ал тарих — «нақты не және қашан болды, кімнен және қандай сомаға» дейді.

Агентке тарих қажет болатын нақты міндеттер:

  • төлемнің жеткенін растау («соңғы бір сағатта осы мекенжайға аударым келді ме, тексер»);
  • әмиян бойынша үзінді-көшірме жинау;
  • нақты транзакцияны идентификаторы бойынша қадағалау;
  • кіріс жетондарды (мысалы, USDT) күтілетін сомамен салыстыру.

Мәселе мынада: TON-да «маған №100–120 транзакцияларды бер» деген сұрау жұмыс істемейді. Мұнда «нөмірі N транзакцияны бер» деуге болатындай жаһандық, тұтас блок нөмірлеуі жоқ. Реттілік мүлде басқаша — логикалық уақыт арқылы беріледі.

Логикалық уақыт (lt): TON-да неге әдеттегі блок нөмірлеуі жоқ

Ethereum-да бәрі қарапайым: № 19 000 000 блок бар, оның ішінде транзакциялар рет-ретімен тұр. Бір ғана жаһандық санауыш, монотонды өседі, бәрі бір ғана нөмірге сүйенеді.

TON — көп ағынды жүйе: мастерчейн, воркчейндер, жүктеме кезінде бөлініп әрі қайта бірігіп отыратын шардтар. Желідегі барлық оқиғаны сызықты түрде реттеуге болатын біртұтас «блок нөмірі» мұнда мүлдем жоқ. Оның орнына TON логикалық уақытты (lt, logical time) пайдаланады — желі оқиғаларды, хабарламалар мен транзакцияларды реттейтін, монотонды өсетін санауыш. Ол мынаған кепілдік береді: егер A оқиғасы B оқиғасына әсер еткен болса, онда lt(A) < lt(B).

Бұдан тәжірибелік салдар шығады: транзакцияның позициясы блок нөмірімен емес, (lt, hash) жұбымен беріледі. lt реттілікке жауап береді (кім бұрын), hash — нақты транзакцияны бірмәнді сәйкестендіруге. Жеке-жеке алғанда олар нүктелік сұрау үшін пайдасыз: әртүрлі нысандардың lt мәндері жақын болуы мүмкін, ал жалғыз hash liteserver-ге оқуды қай жерден бастау керегін айтпайды.

Транзакция хэші және lt + hash жұбы: аккаунттың соңғы транзакциясының көрсеткіші

Транзакция хэші — оның криптографиялық ізі; TON-да ол base64 немесе hex түрінде келеді. lt «реті бойынша қашан» дейді, hash — «нақты қайсысы» дейді, өйткені бір lt-қимасында теориялық тұрғыда екіұштылық болуы мүмкін, ал хэшсіз liteserver транзакцияны бермейді. Мықтап есте сақтаңыз: (lt, hash) жұбы міндетті түрде бірге жүреді. Тек lt немесе тек hash — жеткіліксіз.

Бастапқы нүктені қайдан алуға болады? Аккаунт күйі ең соңғы транзакцияға көрсеткішті сақтайды — last_transaction_id, бұл дәл сол lt + hash жұбы (last_trans_lt / last_trans_hash өрістері). Бұл — тізімнің «басы», тарихты кері қарай аралау сол жерден басталады.

TONNode-тың MCP-құралдар жинағында мұны get_account_state атқарады — ол аккаунттың статусын, жалаушаларын және соңғы транзакцияға көрсеткішті қайтарады.

get_transactions тарихты қалай парақтайды: lt + hash және prev_trans тізбегі

Енді тарихты парақтауға мүмкіндік беретін ең түйінді тұсқа келейік. Әр транзакция өзінің lt және hash мәндерінен бөлек екі өрісті қамтиды: prev_trans_lt және prev_trans_hash — сол аккаунттың алдыңғы транзакциясына сілтеме. Яғни транзакциялар уақытта кері қарай жүретін бір бағытты байланысқан тізім құрайды; тізімнің басы — күйден алынатын last_transaction_id.

get_transactions мыналарды қабылдайды:

  • account — аккаунт мекенжайы;
  • бастапқы lt және hash — оқуды бастайтын нүкте;
  • count — топтама өлшемі.

Ол көрсетілген нүктеден кері қарай жүріп, транзакциялар топтамасын қайтарады. Беттеп аралау логикасы:

  1. get_account_state-тен last_trans_lt / last_trans_hash мәндерін алу — бұл тізімнің басы.
  2. get_transactions(account, lt, hash, count) шақыру — топтаманы алу.
  3. Топтамадағы соңғы транзакциядан prev_trans_lt және prev_trans_hash мәндерін алу.
  4. get_transactions-ті енді осы жұппен қайта шақыру — бұл келесі бет.
  5. prev_trans_lt 0 болғанша (аккаунт өмірінің басы) немесе қажетті тереңдікке жеткенше қайталау.

TON-дағы пагинация осылай жұмыс істейді: «2-бет» емес, «осы (lt, hash) жұбынан жалғастыр».

Жаңа блоктар мен терең тарих: мұрағат нодасы не үшін керек

Дәл осы жерде көпшілік сүрінеді. Кәдімгі liteserver аккаунттың жаңа блоктары мен жақындағы тарихын береді: ол күйдің шектеулі терезесін — соңғы бірнеше блокты — сақтайды, ал желі өскен сайын ескі деректер одан шайылып кетеді. prev_trans тізбегімен жеткілікті тереңдікке түсіңіз — бір сәтте liteserver транзакцияларды беруді жай ғана тоқтатады: олар оның терезесінде физикалық тұрғыда қалмаған. Жаңа төлемді көресіз, ал жарты жыл бұрынғы транзакцияны — жоқ.

Бұл — баг емес, дизайн: әр аккаунттың генезистен бергі толық жолын ұстау қымбат. Терең тарихты мұрағат нодасы сақтайды — ескі блоктарды тастамай, желінің бүкіл тарихы бойынша толық күйді ұстайтын түйін.

Тәжірибелік қорытынды:

  • төлемді анықтау, жаңа үзінді-көшірме, «соңғы бір сағатта келді ме» — әдеттегі liteserver жетеді;
  • әмиянның ең бірінші күнінен бергі толық аудиті — мұрағат нодасы керек.

Бөлек ауыртпалық — TON-ның жаһандық конфигіндегі жария лайтсерверлер. Олар ортақ әрі лимиттелген: жүктеме кезінде жиі not ready деп жауап береді немесе ADNL-таймаутқа кетеді, әрі оларда терең тарих та жоқ. Дәл not ready жауабын алсаңыз, бұл — шамадан тыс жүктелген ортақ лайтсервердің симптомы, талдау liteserver неге not ready деп жауап береді және мұны қалай түзету керек деген жазбада.

TONNode туралы адал айтқанда: мұрағат нодасы роадмапта тұр әрі қазір синхрондалып жатыр — мұрағат тереңдігін дайын функция ретінде уәде етпеймін. Бүгінгі күні бұл — жария лайтсерверлермен лотерея ойнамай, басқарылатын эндпоинт арқылы жаңа әрі жақындағы тарихты оқу. Генезистен бергі толық мұрағат үшін жеке анонсты күтіңіз.

TON тарихын ЖИ-агентпен MCP арқылы қалай оқуға болады

TONNode — бұл TON үшін hosted MCP-сервер, дәл 16 құрал, әрі get_transactions оқу блогына кіреді. MCP (Model Context Protocol) — сіз ADNL-сұрауларды қолмен жинамай-ақ, агенттің құралдарды өзі шақыруына мүмкіндік беретін стандарт. SDK орнатудың, лайтсервер көтерудің және TL-B талдаудың қажеті жоқ — агент құралды тікелей шақырады.

Тегін жергілікті қосылу

Оқу құралдарының толық жинағы, жария конфиг, @tonnode/mcp пакеті — open source, MIT:

{
  "mcpServers": {
    "ton": {
      "command": "npx",
      "args": ["-y", "@tonnode/mcp"]
    }
  }
}

Пакет HTTP-қабаттарсыз, TON-ның нативті ADNL-протоколы бойынша жұмыс істейді.

Өз кілтіңізбен hosted-эндпоинт

Кепілді өткізу қабілеті керек болса, өз кілтіңіз бар hosted-эндпоинт алынады:

{
  "mcpServers": {
    "ton": {
      "type": "http",
      "url": "https://mcp.tonnode.io/mcp",
      "headers": { "Authorization": "Bearer tn_live_…" }
    }
  }
}

Тарихты оқу үшін мыналар пайдалы:

  • get_account_state — аралаудың бастапқы нүктесі (last_trans_lt / last_trans_hash), аккаунттың статусы мен жалаушалары;
  • get_transactions — транзакциялардың өзі, (lt, hash) жұбы бойынша беттеп;
  • parse_address — мекенжайларды EQ / UQ / raw арасында офлайн түрлендіру;
  • get_jetton_info және get_jetton_balance — жетондар бойынша тарих үшін.

Тәжірибе: төлемді анықтау және тарихты беттеп аралау

Типтік сценарий жинайық — «төлем келді ме және қандай сомаға».

Агентке арналған промпт

ton құралы арқылы EQC…myshop үшін get_account_state ал, содан кейін оның last_trans_lt / last_trans_hash мәндерінен бастап get_transactions, count 20. Соңғы 10 минутта 5 GRAM-ға келген кіріс аударымды тап. Жіберушілердің мекенжайларын салыстырар алдында parse_address арқылы EQ форматына келтір. Тарих тереңірек керек болса — соңғы транзакцияның prev_trans_lt / prev_trans_hash мәндерін алып, get_transactions-ті қайтала.

Агент тізбектің басына өзі барады, топтаманы парақтап шығады және сомаларды салыстырады.

Беттеп аралаудың псевдокоды

Дәл сол аралау псевдокод түрінде (шақырулар — агент іске қосатын MCP-құралдар):

state = get_account_state(account)
lt    = state.last_trans_lt
hash  = state.last_trans_hash

while lt != 0:
    batch = get_transactions(account, lt, hash, count=20)
    for tx in batch:
        if matches_expected_payment(tx):   # қажетті сомасы/пікірі бар кіріс хабарлама
            return tx
    last = batch[-1]
    lt   = last.prev_trans_lt
    hash = last.prev_trans_hash   # hash болмаса, келесі бет сұралмайды

Дебагқа кететін сағаттарды үнемдейтін бөлшектер

  • Транзакция өрістеріндегі мекенжайлар raw-форматта келеді (0:abcd…). Жіберушіні немесе алушыны әдеттегі EQ…-мекенжаймен салыстырар алдында екеуін де parse_address арқылы бір форматқа келтіріңіз — әйтпесе мекенжай біреу болса да, жолдар бір-біріне сәйкес келмейді. Форматтар туралы толығырақ — TON мекенжайларындағы EQ, UQ және raw.
  • USDT-мен төлемдер GRAM әмиянының тізбегінде көрінбейді. Жетондар бөлек жетон-әмиянда тұрады, оның мекенжайы он-чейн есептеледі (get_jetton_balance мұны сіздің орныңызға жасайды және ағымдағы балансты береді). Жетондар бойынша тарих үшін негізгі әмиянның емес, жетон-әмиянның транзакцияларын аралаңыз.
  • raw-сомаларды decimals арқылы қайта санаңыз. Жетон сомалары ең кіші бірліктермен келеді: 5000000 санын адам оқитын 5 USDT-ға айналдыру үшін get_jetton_info-дан decimals мәнін алыңыз — USDT-де ол 6, жетондардың көпшілігінде 9. Шатастырсаңыз — 1000 есе жаңылысасыз. Толық талдау — TON-дағы кіріс USDT төлемін қалай ұстау керек.
  • Дедуп сома бойынша емес, (lt, hash) бойынша. Екі бірдей төлем тек lt+hash жұбымен ажыратылады — идемпотенттіліктің кілті дәл сол.

Егер агентке тарихтан бөлек контрактінің ағымдағы күйін сұрау керек болса, мұны run_get_method атқарады — get-әдістерді SDK-сыз қалай шақыру керегі TON-ды SDK-сыз get-әдіс арқылы оқуда көрсетілген.

Қысқаша

  • TON-да Ethereum-дағыдай блок нөмірлері жоқ — транзакцияның позициясы (lt, hash) жұбымен беріледі: lt — реттілік, hash — сәйкестендіру, әрі олар міндетті түрде бірге жүреді.
  • Аккаунт транзакциялары — prev_trans_lt / prev_trans_hash арқылы байланысқан тізім; get_account_state-тен алынған last_transaction_id-дан бастап кері қарай парақтайсыз.
  • Кәдімгі liteserver жаңа әрі жақындағы тарихты береді; толық тереңдік — мұрағат нодасының міндеті.
  • Жетондар үшін get_jetton_info-дан алынатын decimals (USDT = 6) мен parse_address арқылы өткізілуі тиіс raw-мекенжайларды ұмытпаңыз.

not ready деп жауап беретін жария лайтсерверлермен әуре болғыңыз келмей ме? get_transactions тегін Hobby тарифінде бірден, қосымша баптаусыз қолжетімді — минутына 60 сұрау, мәңгілікке, картасыз, кілт кірген бойда беріледі.

TON тарихын оқуды бір минутта қосыңыз → tonnode.io/dashboard?plan=hobby

TON-дағы агент тарихты оқудан бөлек тағы не істей алады — барлық 16 құрал TONNode құралдары бетінде.

Агентіңізге TON-ға қолжетімділік беріңіз

16 MCP-құрал: оқу, кастодиалды емес сваптар, кроссчейн және әмияндар. Тегін тариф — 60 сұрау/мин, карта керек емес.