TractionEye: индексатор стоимости кошельков в TON

Индексатор, который по запросу восстанавливает историю стоимости любого кошелька TON — от нативных монет до жетонов и LP-позиций на DEX.

Область
Финтех, блокчейн TON
Наша роль
Архитектура, бэкенд, обработка данных, DevOps, нагрузочное тестирование
Год
2024

TractionEye — Telegram Mini App, которое показывает, как менялась стоимость кошелька в сети TON: график и список активов с ценами и суммой в USD. Мы спроектировали и написали бэкенд: набор микросервисов на Python, которые по первому запросу восстанавливают полную историю балансов из публичных данных блокчейна, оценивают каждый актив, включая LP-токены DEX, и хранят временные ряды в TimescaleDB на PostgreSQL 16.

Мини-приложение TractionEye: график стоимости кошелька за месяц и список активов с ценой и стоимостью в USD

Задача

  • Публичные API отдают текущее состояние и сырые транзакции, а не историю баланса. Её нужно было получить для TON и для каждого жетона, который когда-либо был в кошельке.
  • Для графиков за день и за месяц нужна история цен каждого токена в USD с достаточно мелким шагом.
  • У LP-токенов DEX нет рыночной цены: её приходится выводить из резервов пула и общего предложения на каждый момент времени.
  • Пользователь может открыть любой кошелёк, поэтому индексация должна стартовать с первого запроса и укладываться в секунды или минуты, а не часы.
  • Все данные идут от публичных провайдеров TON с жёсткими лимитами RPS на ключ, и эти лимиты делят между собой параллельные воркеры.

Решение

Мы собрали конвейер из независимых сервисов с одной задачей у каждого вокруг общей базы временных рядов. Индексатор кошельков листает транзакции по логическому времени и проигрывает их в обратном порядке от текущего баланса — для TON и для каждого жетон-кошелька. Индексатор цен находит новые токены и подгружает до двух лет истории цен в USD с адаптивным шагом, а потом дополняет ряд инкрементально. Индексатор пулов находит пулы DeDust и STON.fi и считает цены LP-токенов по резервам и предложению из архивного состояния сети. API запросов соединяет балансы с ценами по временным интервалам и отдаёт мини-приложению готовый ряд стоимости. Перед всем этим стоит шлюз на OpenResty с TLS и автоматическим продлением сертификатов. Кошелёк регистрируется при первом запросе и сразу попадает к воркерам; дальше его история за каждый проход углубляется на месяц, а свежие операции подтягиваются каждые несколько минут.

Архитектура

Архитектура: шлюз, API запросов, три индексатора, хранилище временных рядов и внешние источники данных TON
Архитектура: шлюз, API запросов, три индексатора, хранилище временных рядов и внешние источники данных TON

Что умеет система

Стоимость кошелька во времени
График стоимости любого кошелька TON за период и с шагом, которые запрашивает клиент.
Разбивка по активам
Баланс, текущая цена и стоимость в USD для TON, жетонов и LP-токенов, плюс отдельный эндпоинт истории по каждому токену для детальных графиков.
Подключение по запросу
Первый запрос по кошельку запускает его индексацию — без ручной настройки.
Постоянное обновление
Свежие операции подхватываются каждые несколько минут, а история в фоне уходит всё глубже.
Оценка LP-позиций
Цены LP-токенов пулов DeDust и STON.fi, включая обработку переводов фарминга на DEX.
Документация и отладка
Документация OpenAPI (Swagger) и HTML-страницы, на которых рассчитанные ряды можно проверить глазами.

Инженерные решения

  • Точный баланс без своей ноды: индексатор идёт от текущего баланса назад по каждой транзакции, вычитая суммы и комиссии, и получает точный баланс после каждого события. Для жетонов направление и сумма перевода декодируются из опкодов сообщений.
  • Очередь задач в самой базе: воркер атомарно забирает задачу одним запросом «выбрать, заблокировать, вернуть». Параллельно работают несколько процессов без внешнего брокера, а каждый шаг — одна транзакция, так что при сбое теряется максимум одна единица работы.
  • Клиенты API с учётом лимитов: каждый ключ провайдера обёрнут в token bucket не больше чем на N запросов в секунду, а неудачные вызовы повторяются ограниченное число раз.
  • Временные ряды в TimescaleDB: агрегация через time_bucket и перенос последнего известного баланса в начало окна превращают редкие транзакции в равномерные точки графика.
  • Нагрузочное тестирование: распределённые воркеры Locust на Docker Swarm и отдельный бенчмарк времени до первого графика. В этих тестах медиана первой синхронизации составила около 13 секунд для самых маленьких кошельков и около 2 минут для самых активных.

Схемы

Поток данных: первый запрос по кошельку, индексация по требованию и запрос графика
Поток данных: первый запрос по кошельку, индексация по требованию и запрос графика
Развёртывание: общий базовый образ, конфигурация в отдельной ветке на каждое окружение, контейнеры на хосте
Развёртывание: общий базовый образ, конфигурация в отдельной ветке на каждое окружение, контейнеры на хосте

Стек

  • Python 3.12
  • Flask
  • uWSGI
  • SQLAlchemy 2
  • PostgreSQL 16
  • TimescaleDB
  • OpenResty
  • Lua
  • Docker Compose
  • Ansible Vault
  • Locust
  • pytoniq
  • Telegram Mini Apps

Что это показывает

  • Индексаторы, которые превращают сырые транзакции блокчейна в готовые для аналитики временные ряды
  • Оценка DeFi-активов, включая позиции в пулах ликвидности, по состоянию сети
  • Микросервисы, которые координируются через базу данных без брокера сообщений и работают в пределах лимитов сторонних API
  • Поставка в прод: контейнеры, автоматический TLS, зашифрованная конфигурация и повторяемый деплой в несколько окружений

Вопросы по кейсу

Нужна ли своя нода TON, чтобы получить историю балансов?

Нет. Индексатор берёт данные у публичных провайдеров TON и восстанавливает историю, проигрывая транзакции назад от текущего баланса. Для цен LP-токенов состояние пулов на нужной высоте блока читается из архивного эндпоинта.

Как быстро появляется график для нового кошелька?

Индексация начинается с первого запроса. В нагрузочных тестах медиана первой синхронизации — от примерно 13 секунд для небольших кошельков до примерно 2 минут для самых активных. Дальше история углубляется в фоне.

Подойдёт ли этот подход для других задач?

Да. Та же схема работает для трекеров портфеля, отчётов по PnL и налогам, аналитики кошельков и казначейских дашбордов — на TON и на других блокчейнах с моделью аккаунтов.