Здравствуйте! В статье я покажу, как написать и запустить на ноде Waves обычный dApp. Рассмотрим необходимые инструменты, методы и пример разработки.
Схема разработки 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:
Браузерное расширение 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:
Интерфейс 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. Увидите, как быстро строится пустая цепь локальной ноды.
Waves Explorer отображает экземпляр локальной ноды
Структура RIDE и инструмент Surfboard
Создайте пустую директорию и выполните в ней команду
surfboard init
Команда инициализирует директорию со структурой проекта, приложения типа «hello world» и тесты. Если откроете эту папку с VS Code, то увидите:
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()
, которое требует прикрепленного платежа в WAVESwithdraw(amount: Int)
, который возвращает токены
На протяжении всего жизненного цикла dApp, структура (address → amount) будет поддерживаться:
Action | Resulting state |
---|---|
initial | empty |
Alice deposits 5 WAVES | alice-address → 500000000 |
Bob deposits 2 WAVES |
alice-address → 500000000 bob-address → 200000000 |
Bob withdraws 7 WAVES | DENIED! |
Alice withdraws 4 WAVES | alice-address → 100000000 bob-address → 200000000 |
Вот код для полного понимания ситуации:
# 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.
Если хотите использовать другой текстовый редактор при компиляции файла, используйте
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, декомпилированный двоичный файл.
Waves Explorer. Приложение, которое только что развернули.
Несколько советов по Surfboard:
1. Чтобы тестировать в среде testnet, используйте:
surfboard test --env=testnet
2. Если хотите посмотреть JSON-версии транзакций и как они обрабатываются нодой, запустите тест с -v (означает ‘verbose’):
surfboard test -v
Использование приложений с Waves Keeper
1. Настройте Waves Keeper для работы: http://localhost:6869
Настройка 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» и нажмите кнопку:
Waves Keeper запрашивает разрешение, чтобы подписать InvokeScriptTransaction с платежом 10 WAVES.
6. Подтвердите транзакцию:
Транзакция создана и транслируется в сеть. Теперь видно ее ID
7. Наблюдайте за транзакцией с помощью Waves Explorer. Введите ID в поисковое поле
Выводы и дополнительная информация
Мы рассмотрели инструменты разработки, тестирования, развертывания и использования простых 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
Автор: ismagin