Как строить, развертывать и тестировать Waves RIDE dApp

Здравствуйте! В статье я покажу, как написать и запустить на ноде Waves обычный dApp. Рассмотрим необходимые инструменты, методы и пример разработки.

ctez2oksuspqfa_irunreiyiqt8.png

Схема разработки dApps и обычных приложений почти не отличается:

  • Пишем код
  • Пишем автоматизированное тестирование
  • Запускаем приложение
  • Тестируем


Инструменты


1. docker для запуска ноды и Waves Explorer

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

  • Вам постоянно будут нужны новые аккаунты с тестовыми токенами. Кран тестовой сети переводит по 10 WAVES каждые 10 минут.
  • Среднее время блоков в тестовой сети — 1 минута, в ноде — 15 секунд. Это особенно ощутимо, когда транзакция требует нескольких подтверждений.
  • В общедоступных тестовых нодах возможно агрессивное кэширование.
  • Еще они могут быть временно недоступны из-за технического обслуживания.


Далее буду считать, что вы работаете со своей нодой.

2. Инструмент командной строки Surfboard

  • Скачайте и установите Node.js с помощью ppa, homebrew или exe здесь: https://nodejs.org/en/download/.
  • Установите Surfboard — инструмент, который позволит запустить тесты на существующей ноде.
npm install -g @waves/surfboard


3. Плагин Visual Studio Code

Шаг необязателен, если вы — не фанат IDE и предпочитаете текстовые редакторы. Все необходимые инструменты — это утилиты командной строки. Если используете vim, обратите внимание на плагин vim-ride.
Скачайте и установите Visual Studio Code: https://code.visualstudio.com/

Откройте VS Code и установите плагин waves-ride:

9lcbf8wgqnwljbv_ays4zitiqs4.png

Браузерное расширение Waves Keeper: https://wavesplatform.com/products-keeper

Готово!

Запустите ноду и Waves Explorer


1. Запустите ноду:

docker run -d -p 6869:6869 wavesplatform/waves-private-node


Проследите, чтобы нода запускалась через REST API в http://localhost:6869:

moynkn4-ttspn4enqevslyahzwa.png
Интерфейс Swagger REST API для ноды

2. Запустите экземпляр Waves Explorer:

docker run -d -e API_NODE_URL=http://localhost:6869 -e NODE_LIST=http://localhost:6869 -p 3000:8080 wavesplatform/explorer


Откройте браузер и перейдите в http://localhost:3000. Увидите, как быстро строится пустая цепь локальной ноды.

e9ijtba7cv70_9yp0nmaplzqaum.png
Waves Explorer отображает экземпляр локальной ноды

Структура RIDE и инструмент Surfboard

Создайте пустую директорию и выполните в ней команду

surfboard init


Команда инициализирует директорию со структурой проекта, приложения типа «hello world» и тесты. Если откроете эту папку с VS Code, то увидите:

hlpsftkbcerslkoonncswxylvva.png
Surfboard.config.json

  • Под папкой ./ride/ найдете одиночный файл wallet.ride — директорию, где расположен код dApp. Мы кратко проанализируем dApp в следующем блоке.
  • Под папкой ./test/ найдете файл *.js. Здесь хранятся тесты.
  • ./surfboard.config.json — конфигурационный файл для запуска тестов.


Envs — важная секция. Каждая среда настраивается так:

  • Конечная точка REST API ноды, которая будет использоваться для запуска dApp и CHAIN_ID сети.
  • Секретная фраза для аккаунта с токенами, которые будут источниками токенов вашего теста.


Как видите, surfboard.config.json по умолчанию поддерживает несколько сред. По умолчанию выставлена локальная среда (ключ defaultEnv — изменяемый параметр).

Приложение Wallet-demo


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

Рассмотрим простое приложение Wallet-demo. Каждый может отправить на адрес dApp токены. Вывести можно только свои WAVES. Две @Callable функции доступны через InvokeScriptTransaction:

  • deposit(), которое требует прикрепленного платежа в WAVES
  • withdraw(amount: Int), который возвращает токены


На протяжении всего жизненного цикла dApp, структура (address → amount) будет поддерживаться:
Вот код для полного понимания ситуации:

# In this example multiple accounts can deposit their funds and safely take them back. No one can interfere with this.
# An inner state is maintained as mapping `address=>waves`.
{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
@Callable(i)
func deposit() = {
 let pmt = extract(i.payment)
 if (isDefined(pmt.assetId))
    then throw("works with waves only")
    else {
     let currentKey = toBase58String(i.caller.bytes)
     let currentAmount = match getInteger(this, currentKey) {
       case a:Int => a
       case _ => 0
     }
     let newAmount = currentAmount + pmt.amount
     WriteSet([DataEntry(currentKey, newAmount)]) 
   }
 }
@Callable(i)
func withdraw(amount: Int) = {
 let currentKey = toBase58String(i.caller.bytes)
 let currentAmount = match getInteger(this, currentKey) {
   case a:Int => a
   case _ => 0
 }
 let newAmount = currentAmount - amount
 if (amount < 0)
   then throw("Can't withdraw negative amount")
   else if (newAmount < 0)
     then throw("Not enough balance")
     else ScriptResult(
       WriteSet([DataEntry(currentKey, newAmount)]),
       TransferSet([ScriptTransfer(i.caller, amount, unit)])
      )
 }
@Verifier(tx)
func verify() = false


Пример кода можно также найти на GitHub.

Плагин VSCode поддерживает непрерывную компиляцию при редактировании файла. Поэтому вы всегда можете следить за ошибками во вкладке PROBLEMS.

e2n989kg7fhgcgkr_krnpwqfdlk.png
Если хотите использовать другой текстовый редактор при компиляции файла, используйте

surfboard compile ride/wallet.ride


Это выведет ряд base64 скомпилированного кода RIDE.

Тестовый сценарий для «wallet.ride»


Посмотрим на тестовый файл. Работает на фреймворке JavaScript«s Mocha. Есть функция «Before» и три теста:

  • «Before» финансирует несколько аккаунтов через MassTransferTransaction, компилирует скрипт и развертывает его в блокчейне.
  • «Can deposit» отправляет в сеть InvokeScriptTransaction, активируя функцию deposit () для каждого из двух аккаунтов.
  • «Can’t withdraw more than was deposited» тестирует, что никто не сможет украсть чужие токены.
  • «Can deposit» проверяет, что выводы обрабатываются корректно.


Запуск тестов с Surfboard и анализ результатов в Waves Explorer


Для запуска теста выполните

surfboard test


Если у вас есть несколько сценариев (например, нужен отдельный скрипт развертывания), можете запустить

surfboard test my-scenario.js


Surfboard соберет тестовые файлы в папке ./test/ и запустит сценарий в ноде, которая настроена в surfboard.config.json. Спустя несколько секунд вы будете наблюдать что-то подобное:

wallet test suite
Generating accounts with nonce: ce8d86ee
Account generated: foofoofoofoofoofoofoofoofoofoofoo#ce8d86ee - 3M763WgwDhmry95XzafZedf7WoBf5ixMwhX
Account generated: barbarbarbarbarbarbarbarbarbar#ce8d86ee - 3MAi9KhwnaAk5HSHmYPjLRdpCAnsSFpoY2v
Account generated: wallet#ce8d86ee - 3M5r6XYMZPUsRhxbwYf1ypaTB6MNs2Yo1Gb
Accounts successfully funded
Script has been set
   √ Can deposit (4385ms)
   √ Cannot withdraw more than was deposited
   √ Can withdraw (108ms)
3 passing (15s)


Ура! Тесты пройдены. Теперь взглянем на то, что происходит при использовании Waves Explorer: просмотрим блоки или вставим один из указанных выше адресов в поиск (например, соответствующий wallet#. Там можно найти историю транзакций, состояние dApp, декомпилированный двоичный файл.

b7gjhoibtnpaotigfcmycucnpje.png
Waves Explorer. Приложение, которое только что развернули.

Несколько советов по Surfboard:

1. Чтобы тестировать в среде testnet, используйте:

surfboard test --env=testnet


Получить тестовые токены

2. Если хотите посмотреть JSON-версии транзакций и как они обрабатываются нодой, запустите тест с -v (означает «verbose»):

surfboard test -v


Использование приложений с Waves Keeper


1. Настройте Waves Keeper для работы: http://localhost:6869

su4i35dyfs6e8zzsk54g8i-foow.png
Настройка Waves Keeper для работы с локальной нодой

2. Импортируйте секретную фразу с токенами для сети? Для простоты используйте начальное seed вашей ноды: waves private node seed with waves tokens. Адрес: 3M4qwDomRabJKLZxuXhwfqLApQkU592nWxF.

3. Вы можете запустить одностраничное безсерверное приложение самостоятельно, используя npm. Или перейдите к существующему: chrome-ext.wvservices.com/dapp-wallet.html

4. Введите адрес кошелька из тестового запуска (подчеркнут выше) в текстовое поле адреса dApp

5. Впишите небольшую сумму в поле «Deposit» и нажмите кнопку:

19wkkfmlyuu5uhthjkjzax77b5e.png
Waves Keeper запрашивает разрешение, чтобы подписать InvokeScriptTransaction с платежом 10 WAVES.

6. Подтвердите транзакцию:

fpepl_tgwmruhltgggwflpmaezu.png
Транзакция создана и транслируется в сеть. Теперь видно ее ID

7. Наблюдайте за транзакцией с помощью Waves Explorer. Введите ID в поисковое поле

1udz5fiiqj-zbkpjybdvs0hzjyw.png

Выводы и дополнительная информация


Мы рассмотрели инструменты разработки, тестирования, развертывания и использования простых dApps на Waves Platform:

  • Язык RIDE
  • Редактор VS Code
  • Waves Explorer
  • Surfboard
  • Waves Keeper


Ссылки для тех, кто хочет продолжить изучать RIDE:

Больше примеров
Онлайн IDE с примерами
Документация Waves
Чат разработчиков в Телеграме
Waves и RIDE на stackoverflow
NEW! Онлайн-курсы по созданию dApps на Waves Platform

Продолжайте углубляться в тему RIDE и создайте свой первый dApp!

TL; DR: bit.ly/2YCFnwY

© Habrahabr.ru