28 декабря 2022

Бонусный урок для блокчейн-индексеров: делаем простой токен трекер

В курсе мы делали простые проекты вроде статистики бейкинга ликвидности и расчета APY. Сегодня решили показать, как сделать что-то более полезное и сложное — статистику изменения цены токена или же токен-трекер. Madfish, простите нас за грубое использование TzKT API!

Что будет делать наш трекер

Мы будем использовать TzKT API для получения ончейн-данных с пулов QuipuSwap и контрактов токенов. Затем будем обрабатывать их и использовать дальше, чтобы автоматически считать изменения цены токена за сутки и за неделю, а также подтягивать название токена из его контракта. В итоге получилась такая веб-страница:

Как работает трекер:

  1. Получает текущую цену tez на бирже.
  2. Берет из хранилища контракта указанного пула QuipuSwap адрес токена.
  3. Делает запрос по адресу токена, получает его название.
  4. Считает цену токена в пуле.
  5. Запрашивает котировки tez за прошлые сутки, рассчитывает изменение в процентах.
  6. Использует цену tez за прошлые сутки, чтобы посчитать цену токена 24 часа назад и изменение в процентах.
  7. Делает то же самое, но с данными недельной давности, чтобы посчитать изменения цен за неделю.

Наш мини-проект можно масштабировать и сделать полноценный токен-трекер, который бы учитывал ликвидность в пулах всех DEX, считал объемы торговли, хранил все в собственной базе данных и не запрашивал TzKT при каждой перезагрузке страницы. Но у него другая задача: мы хотим показать как работать с индексером, и самое главное — вдохновить новичков. Даже с минимальным опытом в можно сделать полезный проект для экосистемы!

Делаем HTML-страницу

Создадим пустой HTML-файл и импортируем в него библиотеку jQuery — она нужна для ajax-запросов к TzKT API. Сразу сделаем таблицу с названиями столбцов: Token, Price, 24h и 7d.

Также пропишем минимальный стиль, но все еще будем игнорировать возможности CSS. В итоге получим таблицу.

Запрашиваем цену tez

Задаем функцию $(document).ready(function(){}, которая запустится после загрузки страницы.

В ней с помощью ajax вызываем quotes/last с TzKT API. Записываем цену в USD в переменную tezPriceExchange и присваиваем элементу tezPriceExchange это значение.

Добавляем этот id в соответствующую ячейку таблицы в элементе <span>, перезагружаем страницу и получаем текущую цену tez.

Получаем название токена и его цену из пула QuipuSwap

Добавляем в первую функцию переменную с адресом контракта пула токена к tez (мы выбрали пул QUIPU/tez). Вызываем функцию meta, которой передаем адрес пула.

Создаем в папке проекта файл meta.js, импортируем его в страницу. В самом файле объявляем функцию meta. В ней запрашиваем в API TzKT хранилище контракта пула и с помощью фильтра ?path получаем только адрес токена, который свопается в этом пуле. Записываем адрес в переменную tokenAddress. Не забываем про toString(), чтобы значение можно было вставить в API-запрос.

Пишем еще один ajax-запрос, но теперь запрашиваем данные о контракте токена — не хранилище, а именно общие данные. Из него получаем alias — название токена. Записываем в соответствующую переменную.

Возвращаемся к HTML-файлу, добавляем вторую строку в таблицу и элемент tokenAlias в ячейку Name. Перезагружаем страницу, получаем название токена QUIPU.

Все работает, идем считать цены.

Делаем базу для расчета изменения цен tez и токена

Чтобы посчитать цену токена в пуле ликвидности QuipuSwap нужно получить из его контракта два значения: количество tez и количество токенов. В хранилище они записаны под ключами tez_pool и token_pool. Итоговая формула будет выглядеть как tez_pool/token_pool×tez_price (но переменные в коде назвали по-другому).

С помощью TzKT API мы можем получить значения хранилища на указанном уровне блокчейна. Чтобы узнать прошлое соотношение, нам нужно узнать текущий уровень, отнять от него количество блоков, созданных за 24 часа и 7 дней, и запросить состояние хранилища в этом блоке. Аналогично получим цену tez — запросим котировки на нужном уровне.

Возвращаемся к коду. Добавляем запрос к TzKT API для получения текущего уровня, записываем его в переменную и вызываем функцию tokenPriceFunc. Дальше мы сделаем несколько встроенных функций, которые будут последовательно вызывать друг друга, и передадим tokenPriceFunc необходимые для расчетов параметры: адрес контракта пула и текущую цену tez.

Создадим файл tokenPriceCurrent.js. В нем объявим функцию tokenPriceFunc. Внутри запросим состояние хранилища указанного контракта. Из него получим количество tez — переменная balanceInTez, и количество токенов — balanceInToken. Разделим количество токенов в пуле на нужное количество нулей после запятой.

В переменной tokenPrice посчитаем цену токена в пуле и сразу присвоим это значение HTML-элементу tokenPrice.

Добавим элемент tokenPrice в таблицу, перезагрузим страницу.

Считаем изменение цены tez за 24 часа

В вызов функции tokenPriceFunc в HTML-файле добавим параметр level.

Также добавим его в объявление функции в currentPrice.js. В конце вызовем функцию priceDayAgo с нужными параметрами: адресом контракта пула, уровнем, текущими ценами tez и токена.

Создадим файл priceDayAgo.js, импортируем его в HTML-файл. В нем объявим функцию priceDayAgo и начнем делать самое сложное.

Сначала посчитаем уровень блока, который был создан 24 часа назад. Для этого отнимем от текущего уровня 2880, то есть среднее количество создаваемых блоков в сутки — 1440 минут × 2 блока в минуту. Запишем его в переменную level24h.

Затем запросим по API цену tez на нужном блоке. Запишем эту цену во вспомогательную переменную tezPriceExchange24h_e и округлим. Теперь посчитаем изменение цены в процентах — отнимем от текущей цены старую и разделим на текущую.

Добавим if else — если разница цен, то есть значение tezPriceExchange24h_e, положительная, добавим в итоговую переменную tezPriceExchange24h плюсик. Если отрицательное, оставим как есть — минус появится автоматически.

В конце присвоим это значение новому HTML-элементу и добавим его в таблицу.

Считаем изменение цены токена за 24 часа

В конце функции priceDayAgo вызовем функцию tokenPriceChange24 (да, мы не любим стандартизировать названия).

Передадим ей адрес контракта, уровень блока суточной давности, цену tez 24 часа назад и текущую цену токена.

Затем объединим функцию расчета цены токена с функцией расчета разницы цен. Запросим состояние хранилища сутки назад, посчитаем цену по количеству токенов в пуле, сравним ее с текущей ценой и добавим плюсик.

Запишем элемент в таблицу.

Аналогично посчитаем изменение цен за неделю. Создадим новый js-файл, скопируем в него содержание priceDayAgo, скорректируем уровень с -2880 на -20160, а также подправим названия переменных, чтобы не запутаться. Когда закончим, получим наши значения.

А теперь к интересному: заменим контракт пула QUIPU/tez на другой, например на контракт USDtz/tez. Перезагрузим страницу и получим статистику.

Неужели все так просто?

Нет. Мы не сделали несколько важных вещей. Например, расчеты цены токена и процента изменения цен можно вынести в отдельные функции. Так же можно запрашивать количество нулей после запятой из таблицы tokens, чтобы трекер правильно отображать цены вообще всех токенов FA1.2/FA2. Еще можно чаще использовать фильтры, чтобы снизить нагрузку на TzKT.

Но как мы писали раньше, наша задача — показать, что полезный проект можно создать с минимальным опытом в разработке. Просто нужно знать где хранятся нужные данные и как их использовать.

Код проекта на GitHub.

Обсудить в Discord!