Отображаем баланс адреса с помощью публичного индексера TzKT
Наверное, самый популярный вариант использования блокчейн-обозревателей и индексеров — проверка балансов токенов на указанном адресе. Это удобно при хранении криптовалюты на холодном кошельке: не нужно лишний раз подключать его к сети и подвергать опасности средства на нем.
Мы сделаем простую страницу, на которой пользователь сможет ввести свой адрес и узнать баланс в tez. Затем добавим к ней отображение балансов токенов и немного другой информации. Для этого будем использовать Visual Studio Code и TzKT API.
Сначала создадим пустой html-файл в VS Code (вы можете использовать другой редактор) и добавим базовые элементы: doctype, head, title и body.
Для запроса данных по API и их обработки мы будем использовать AJAX и библиотеку jQuerry. Подключить библиотеку просто: надо только указать на нее ссылку в элементе script.
Теперь попробуем получить баланс нашего адреса через AJAX.
Сначала добавим команду $(document).ready(), которая удостовериться в загрузке страницы до начала обработки скриптов.
Затем напишем запрос к TzKT с помощью AJAX: в "url" — ссылку запроса для получения баланса, в "type" — типа запроса GET для получения информации, в "success" — функцию, которая обработает ответ.
В функции объявим переменную balance, присвоим ей значение ответа (data) и сразу разделим его на миллион. Это нужно сделать, потому что индексер возвращает баланс в mutez — миллионных долях tez.
Чтобы использовать переменную balance в HTML, нужно присвоить этой переменной внутренний id. Сделаем это с помощью метода document.getElementById.
В конце добавим элемент h2, в котором и будем отображать баланс. Чтобы вывести значение переменной, используем элемент span и ранее присвоенный id переменной balance.
Откроем страницу и проверим результат.
Добавляем кнопку и поле для проверки указанного баланса
Сейчас AJAX отправляет API-запрос сразу при загрузке страницы. Добавим кнопку, нажатие которой будет запускать запрос.
Для этого обернем h2 в элемент div и сделаем его скрытым с помощью параметра style="display:none".
Создадим кнопку и добавим к ней вызов функции check, в которую поместим весь код запроса. В конец функции добавим изменение стиля отображения div на видимый block.
Теперь нам нужно добавить поле для ввода адреса пользователя и подправить функцию check(), чтобы вставлять его в API-запрос.
Для этого мы сделали следующее:
- Добавили параметр address в функцию check().
- Изменили значение поля "url". При запуске скрипт составит корректный API-запрос с использованием полученного адреса.
- Добавили поле для ввода адреса с id
- Изменили код кнопки, чтобы ее нажатие запускало функцию check() и передавало ей введенный адрес.
Теперь можно ввести любой адрес и по нажатии кнопки получить его баланс в tez.
Поэкспериментируйте: возьмите код этой страницы, вставьте ее в пустой html-файл и откройте в браузере.
Это очень простой пример, так как TzKT API возвращает баланс пользователя в виде JSON с лишь одним числом. Ответ даже не надо дополнительно обрабатывать — все работает и так.
Однако при решении реальных кейсов придется работать с JSON-массивами и изучать ответы API, чтобы выбирать нужные данные.
Отображаем статистику бейкинга ликвидности
Тот контракт с 5 млн tez — это Sirius DEX, больше известный как бейкинг ликвидности. Он использует только один смарт-контракт.
Бейкинг ликвидности — уникальный DeFi-протокол Tezos. Пользователи вносят в него tez и tzBTC, чтобы предоставить ликвидность для обмена, а сама сеть Tezos в каждом блоке добавляет в пул еще 2,5 tez. Таким образом балансы провайдеров ликвидности этого пула постоянно растут.
Так как все данные о бейкинге ликвидности хранятся ончейн, мы можем их получить с помощью API-запросов к публичным индексерам, а затем посчитать годовую доходность и другую полезную информацию.
В первую очередь нас интересует баланс Sirius DEX — сколько у контракта tez и tzBTC. Эти числа мы получим от индексера.
Затем нам нужно посчитать, сколько tez субсидирует протокол за год. Тут можно посчитать количество секунд в году, разделить это значение на среднее время создания блока — 30 секунд — и умножить на одну субсидию.
Остается узнать текущую стоимость активов в Sirius DEX и стоимость субсидированных tez за год, и разделить эти значения — это и будет годовая доходность, или APY.
Начинаем собирать новую страницу. Сначала попробуем получить что-то простое, например id контракта Sirius DEX.
Скопируем код первого примера, удалим из него кнопку и поле для ввода адреса. Заменим url API-запроса на https://api.tzkt.io/v1/contracts/KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5, чтобы получить от индексера информацию о контракте.
Изменим функцию для обработки данных. Индексер возвращает данные в виде массива. Его не нужно дополнительно парсить или как-то обрабатывать, но для получения конкретных значений нужно указать ключ. В нашем случае ключ — id, и запрос значения по этому ключу будет выглядеть как var contractId = data.id.
В конце присвоим внутренний ID "contractId" к соответствующему HTML-элементу и выведем его на странице в элементе h2.
Мы убедились что все работает, а значит можно получить нужные нам данные — балансы tez и tzBTC.
Сначала изучим ответ TzKT по нашему API-запросу. В нем есть поле balance в tez, значит мы можем получить его не изменяя запрос.
Присвоим переменной balanceInTez значение из полученного массива по ключу balance.
Теперь нужно получить количество tzBTC. Изучим хранилище контракта бейкинга ликвидности на TzKT — там указано количество tzBTC под ключом tokenPool. Его можно получить по запросу содержания хранилища.
Создадим еще один запрос AJAX. В url укажем API-запрос содержания хранилища, а переменной balanceInTZBTC присвоим значение соответствующей записи — tokenPool.
На странице выведем баланс в tzBTC.
Теперь посчитаем субсидии за год. В среднем год состоит из 31 556 926 секунд. Разделим это значение на время создания блока и умножим на размер субсидии.
Время создания блока и размер субсидии мы можем получить от TzKT по запросу https://api.tzkt.io/v1/protocols/current. В ответе они будут обозначены как timeBetweenBlocks и lbSubsidy.
Итак, нам нужно в одной функции получить данные из двух API-запросов и использовать их для расчетов. Но так как локальные переменные нельзя использовать в других функциях, нам нужно вложить их друг в друга. Сделаем это так:
- Получим количество tez.
- Запишем их в переменную.
- Вызовем функцию для расчета APY, передадим ей в аргументах количество tez.
- В функции APY получим нужные данные, произведем расчеты.
- Запишем результаты в переменные и присвоим ID.
- Вернемся в первую AJAX-функцию и добавим в конец присвоение ID переменной с количеством tez.
Сначала добавим вызов функции checkTimeAndSubsidy в функцию для получения баланса Sirius DEX в tez.
Ниже объявим ту же функцию, и добавим в нее вызов AJAX для запроса данных о протоколе от TzKT.
Присвоим три новых переменных:
- secondsInYear — количество секунд в году, по сути, константа;
- timeBetweenBlocks — время создания блока;
- lbSubsidy — субсидия пула Sirius DEX в mutez. Мы делим ее на миллион, чтобы получить значение в tez вместо mutez.
Теперь у нас есть все данные, чтобы посчитать годовой размер субсидии и APY бейкинга ликвидности.
Создадим переменные yearlySubsidy и APY, и в них посчитаем нужные нам значения.
Чтобы посчитать APY, необязательно получать цены активов. В каждый конкретный момент стоимость всех tez в пуле равна стоимости всех tzBTC. Чтобы упростить расчеты, мы предположим что пользователь добавляет в пул не tez и tzBTC равной стоимости, а в два раза больше tez. APY бейкинга ликвидности будет равна годовой сумме субсидий разделенной на ликвидность пула, то есть APY = yearlySubsidy / (balanceInTez × 2) × 100%.
Присвоим значениям годовой суммы субсидий и APY внутренние ID, и добавим их на страницу.
Домашнее задание
Попробуйте посчитать стоимость tez в пуле ликвидности Sirius DEX. Для этого:
- Найдите смарт-контракт любого пула ликвидности tez со стейблкоином: tez/USDt, tez/kUSD или tez/uUSD.
- Получите с помощью API-запроса количество токенов в пуле.
- Разделите количество tez на количество стейблкоинов, чтобы узнать курс tez.
- Умножьте количество tez в пуле Sirius DEX на полученный курс.
- Добавьте результат в соответствующую строку.
Решение
Сначала найдем контракт tez/kUSD биржи QuipuSwap на TzKT. Изучим хранилище, найдем нужные ключи: tez_pool — количество tez, token_pool — количество kUSD.
Нужно всегда помнить, что количество токенов в хранилище смарт-контракта — это всегда натуральное число. Чтобы узнать настоящее количество токенов, нужно разделить это nat на количество нулей после запятых, указанное в метаданных токена. Например, у токена kUSD 18 нулей после запятой, а значит баланс в kUSD нужно разделить на 10^18.
Так как для расчета стоимости всех tez надо знать количество tez в пуле, нам нужно использовать вложенные функции. После получения переменной balanceInTez вызовем функцию checkValueOfTez с аргументом balanceInTez. В этой функции используем AJAX, получим данные от пула tez/kUSD (не забудем разделить количество токенов на нужное количество нолей!).
Дальше посчитаем цену одного tez и стоимость всех tez в пуле. В конце добавим переменную readableValue — с помощью метода localeString() мы добавим разделение порядков в числе.
В итоге получим стоимость активов в пуле Sirius DEX, которую получаем полностью с ончейн-данных.