Главная
предыдущий
пятый урок

Как использовать DipDup и Dappetizer на Tezos

DipDup и Dappetizer — фреймворки для создания кастомных селективных индексеров для работы со сложными контрактами и децентрализованными приложениями, подключения аналитики, получения данных из IPFS и многого другого. Главное отличие между ними — в используемых языках. При работе с DipDup нужно писать код на Python, при работе с Dappetizer — на JavaScript или TypeScript.

Селективные индексеры — это программы, которые собирают и сохраняют запрашиваемые ончейн-данные в локальной базе данных. Их намного сложнее использовать, чем публичные индексеры, потому что разработчик должен самостоятельно написать логику индексирования: какие данные собирать, как их обрабатывать, как хранить, и все такое.

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

Что мы будем делать

Так как DipDup и Dappetizer достаточно сложны в настройке, мы будем индексировать простой контракт и выполнять простые запросы. Для примера мы выбрали tzBTC — обернутый Bitcoin на Tezos в виде токена стандарта FA1.2.

Сначала мы установим каждый индексер и создадим пустые проекты. Затем настроим индексер и правила индексирования балансов держателей tzBTC из хранилища или объем транзакций tzBTC по точке входа "transfer". Затем мы отобразим сохраненные в базе данных значения на простой веб-странице.

Установка и настройка DipDup

DipDup работает только на Unix системах: macOS и дистрибутивах Linux. Если у вас Windows, используйте WSL или Linux в дуалбуте.

Сначала нужно установить среду Python любым удобным способом. Затем открыть терминал и установить DipDup с помощью команды:

python -c "$(curl -sSL https://dipdup.io/install.py)"

Если у вас установлена macOS 12 или выше, замените python на python3.

1

Создание проекта в DipDup

Теперь начнем настраивать DipDup. Сначала создадим папку dipdup_smartlink, в которой будем создавать проект, и перейдем в нее в терминале. Затем выполним команду dipdup new, чтобы создать новый проект.

Для примера проиндексируем контракт токена tzBTC, так как он устроен просто и создание индексера не займет много времени. Для этого при выборе шаблона конфигурации возьмем вариант tzBTC.

2

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

3

Конфигурация индексера

В папке с проектом появится файл dipdup.yml — конфигурация индексера для проекта. Его структура следующая:

  • spec и package — данные о самом DipDup;
  • database — настройки используемой базы данных. По-умолчанию — sqlite, но можно подключить PostgreSQL;
  • contracts — название контракта, его адрес и typename для дальнейшего использования в коде;
  • datasources — источники данных для индексирования. По-умолчанию — TzKT, но можно добавить сторонние API и брать данные из других сайтов, например получать цены от бирж, или IPFS для получения метаданных NFT;
  • indexes — список индексов, которые создаст и будет использовать DipDup. В нашем случае мы будем собирать информацию о держателях tzBTC;
  • templates — схемы операций, которые нужно индексировать. Внутри есть handlers, которые по сути являются инструкциями как DipDup должен обработать вызовы точек входа: какие данные взять и как их записать в базу. Кстати, и указывают на ключи "datasource" и "contract" внутри словаря "indexes".

Самое важное — это templates. В этих модулях мы указываем точки входа, которые нужно индексировать: для данных on_transfer нужно проверять операции с точкой входой transfer, для on_mint — операции с mint. Это важно, так как в коде обработчиков не будет прямых ссылок на точки входа или на контракт, и эта особенность может вызвать вопросы вроде «А откуда вообще берутся данные?».

В этом примере мы будем собирать балансы держателей tzBTC. Они меняются при вызовах точек входа "transfer" и "mint", поэтому мы добавили два обработчика по названиям точек входа в контракте — on_mint и on_transfer.

4

Посмотрите документацию DipDup Config, если вы хотите узнать больше о возможных конфигурациях индексера.

Модели и обработчики данных

Затем нужно инициировать создание индексов, схем, моделей и обработчиков. Для этого в терминале перейти в папку tzbtc и выполнить команду:

dipdup init

5

DipDup создаст несколько файлов — модели и обработчики, которые описывают работу с базой данных и индексирование ончейн-данных, и нам нужно их модифицировать для настройки процесса индексирования.

Первый файл — models.py. В нем хранятся модели данных, грубо говоря — описания таблиц и столбцов в базе данных. В модели Holder мы объявим несколько типов столбцов:

  • адрес длиной 36 символов;
  • баланс и оборот в числовом формате, при этом укажем 8 знаков после запятых (decimal_places);
  • количество транзакций;
  • время последней активности.

6

Обработчики (handlers) — это инструкции, которые говорят DipDup как обработать ончейн-данные, когда он найдет в блоке вызов нужных точек входа tzBTC. В папке handlers хранятся обработчики хранилища и вызовов точек входа контракта tzBTC.

Первый обработчик — on_balance_update. Мы будем вызывать его при появлении операции, которая изменит балансы держателей tzBTC, то есть при минтинге и передаче токенов, и будем обновлять соответствующие балансы в базе данных.

В нем мы объявили функцию on_balance_update, которой передадим три параметра:

  • address — адрес держателя;
  • balance_update — сумму изменения баланса держателя;
  • timestamp — время операции.

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

7

Второй обработчик — on_mint — будет считывать параметры вызова точки входа mint, а затем вызывать функцию on_balance_update для обновления записей в базе данных.

8

Обратите внимание: в переменную amount мы сохраняем значение mint.parameter.value, которое берем из параметров вызова точки входа mint.

9

Аналогично берем адрес получателя свежих токенов: address = mint.parameter.to;

Третий обработчик — on_transfer — разбирается с транзакциями, то есть операциями с точкой входа transfer. Он устроен сложнее. Во-первых, нужно сравнить адреса отправителя и получателя. Если они совпадают, значит балансы держателей не изменились и базу данных можно не обновлять. Во-вторых, перевод токенов означает изменение балансов отправителя и получателя. Поэтому функцию on_balance_update нужно вызвать дважы для каждого адреса, при этом от баланса отправителя отнять сумму транзакции, а к балансу получателя — добавить.

10

Как и в обработчике onmint, мы получаем ончейн-данные из параметров вызова точки входа transfer: адрес отправителя from, адрес получателя to, сумму перевода value.

Запуск индексера

В терминале выполните команду:

dipdup run

DipDup начнет загружать нужные данные из публичного API TzKT. По завершению он начнет обрабатывать новые блоки.

11

Подключение базы данных к проекту

Сделаем похожий проект, как в прошлом уроке, в котором мы отображали предложения о займах под залог NFT и генерировали ссылки на заложенные токены.

Создадим в папке ttzbtc_dipdup файл tzbtc_dipdup.php. Сначала подключимся к базе данных. DipDup по-умолчанию записывает проиндексированные данные в базу данных SQLite. Подключение к ней немного отличается от Postgres: нужно указать полный путь к файлу с базой данных, но при этом не нужно указывать имя пользователя, пароль и порт.

Чтобы изучить структуру базы данных SQLite и точно знать что запрашивать, можно установить графический интерфейс SQLite Browser.

12

В переменной $db_dir укажем путь к базе данных на жестком диске, а в $db_handle — метод подключения к базе данных new PDO($db_dir). Затем напишем sql запрос, в котором выберем все адреса и балансы держателей tzBTC с ненулевым балансом и сортировкой по возрастанию.

13

С помощью функции перебора массива foreach выведем на страницу адреса и балансы пользователей из массива $row.

Затем закроем соединение к базе данных командой $db_handle = null.

В терминале перейдем в папку с tzbtc_dipdup.php и запустим PHP-сервер командой:

php -S localhost:8000

14

В браузере откроем страницу по адресу http://localhost:8000/tzbtc_dipdup.php

15

Так как при написании обработчиков транзакций и минтинга tzBTC мы уже делили баланс на 10^8, то в базе данных они отображаются с правильным количеством знаков после запятой.

Установка и настройка Dappetizer

Сначала установить Node.js, чтобы можно было работать с пакетным менеджером npm. Затем создадим папку для проекта и установим туда Dappetizer. Проще всего сделать все из терминала:

    mkdir dappetizer
	cd dappetizer
	npm install @tezos-dappetizer/cli

Проверим, прошла ли установка успешно коммандой проверки версии:

	npx dappetizer --version

16

Теперь инициализируем новый проект с указанием названия tzBTC и адреса контракта:

npx dappetizer init --contractName=tzBTC KT1PWx2mnDueood7fEmfbBDKx1D9BAnnXitn

17

Конфигурация индексера

Dappetizer создаст в папке проекта необходимые для работы файлы. Среди них четыре главных:

  • dappetizer.config.ts — параметры для подключения к базе данных;
  • index.ts — основной модуль, в него мы импортируем конфигурацию индексирования;
  • tz-btc-indexer.ts — логика индексирования контракта tzBTC. Dappetizer генерирует список с шаблонами для всех точек входа контракта, и нужно лишь удалить неиспользуемые и дописать логику обработчика точки входа "on_transfer";
  • entities.ts — его нужно создать самому и описать в нем структуру таблиц и столбцов, в которые Dappetizer будет записывать данные.

В dappetizer.config.ts записаны параметры для подключения к базе данных. По умолчанию Dappetizer использует SQLite, но можно подключить Postgres.

18

entities.ts нужно создать самому, и в нем указать класс (таблицу) и столбцы базы данных. Мы будем записывать транзакции с токеном tzBTC, поэтому создадим класс transaction со столбцами id (внутренний id в базе данных), sender, receiver и amount.

19

В папке src находится tz-btc-indexer.ts, в котором Dappetizer сгенерирует функции для индексирования всех точек входа указанного контракта. В коде соответствующей точки входа нужно описать логику индексирования: какой параметр вызова точки входа записать в базу данных.

20

В tzBTC точка входа для отправки токенов называется transfer. Соответственно, найдем код этой точки входа и добавим в него логику:

  • в начале импортируем класс Transaction, чтобы использовать его для записи данных;
  • в функции indexTransfer опишем логику индексирования: создадим константу tzBTCtransfer, в которой запишем адреса отправителя и получателя, а также объем транзакции;
  • в конце функции indexTranfer вызовем функцию insert, чтобы записать содержание tzBTCtransfer в базу данных.

21

Теперь нужно добавить модель Transaction в модуль index.ts. для этого импортируем Transaction из файла entities.ts и добавим Transaction в массив dbEntities.

22

Запуск индексера

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

npm run build

Затем запустите индексирование:

npx dappetizer start

Dappetizer начнет индексировать блоки:

23

Подключение базы данных к проекту

Сделаем похожую страницу, как в проекте с DipDup. Создадим файл tzbtc_dappetizer.php и опишем в нем структуру страницы. Так как мы используем ту же базу данных SQLite, можем напрямую скопировать код из проекта с DipDup. Нужно изменить только путь к базе данных, SQL-запрос и функцию для вывода данных.

24

Запустим PHP-сервер в папке Dappetizer и откроем страницу в браузере:

25

Домашнее задание

Подсчитайте общий объем транзакций tzBTC за проиндексированный период. Подсказка: лучше работать с готовыми данными, а не с теми, что вы добавляете.

Решение

Работа с индексерами тесно связана с базами данных и SQL-запросами. Для разработки приложения обязательно нужно изучить SQL!

Если в примере с DipDup мы считали объем (turnover) через добавление объема проиндексированной транзакции к прежнему значению turnover, то сейчас проще воспользоваться SQL-командой SUM().

Откройте файл tzbtc_dappetizer и создайте SQL-запрос $sql_sum с командой SELECT SUM(amount) FROM "transaction":

26

Затем добавьте функцию query($sql_sum) для запроса к базе данных и выведите значение на страницу.

27

Поделиться в соцсетях: