waves_logo Docs
  • Обзор
    Обзор
  • Практические руководства
    • Получение данных из блокчейна
      Получение данных из блокчейна
    • Создание и отправка транзакций
      Создание и отправка транзакций
    • Токенизация
      Токенизация
    • Распространение токена (airdrop)
      Распространение токена (airdrop)
    • Прием платежей
      Прием платежей
    • Обмен токенов
      Обмен токенов
    • Простое голосование
      Простое голосование
    • Список как аргумент
      Список как аргумент
    Практические руководства
  • Смарт-контракты Waves
    Смарт-контракты Waves
  • dApp
    • Создание и запуск dApp
      Создание и запуск dApp
    dApp
  • Cмарт-аккаунт
    • Создание смарт-аккаунта
      Создание смарт-аккаунта
    • [en] Creating and deploying a script manually
      [en] Creating and deploying a script manually
    • [en] Video tutorials
      [en] Video tutorials
    Cмарт-аккаунт
  • Cмарт-ассет
    Cмарт-ассет
  • Инструменты разработчика
    • Waves IDE
      Waves IDE
    • Расширение для VS Code
      Расширение для VS Code
    • Surfboard
      Surfboard
    • Ride REPL
      Ride REPL
    Инструменты разработчика
  • Signer ◆
    Signer ◆
  • Waves API
    • Data Service API
      Data Service API
    • Node REST API 🡥
      Node REST API 🡥
    • Node gRPC Server 🡥
      Node gRPC Server 🡥
    • Blockchain Updates 🡥
      Blockchain Updates 🡥
    Waves API
  • Клиентские библиотеки
    • Waves C#
      • Установка SDK
        Установка SDK
      • Запуск кода
        • Отправка транзакций
          Отправка транзакций
        • Использование криптографических утилит
          Использование криптографических утилит
        • Взаимодействие с нодой
          Взаимодействие с нодой
        • Развертывание смарт-контрактов
          Развертывание смарт-контрактов
        Запуск кода
      Waves C#
    • Gowaves
      • Установка SDK
        Установка SDK
      • Запуск кода
        • Отправка транзакций
          Отправка транзакций
        • Использование криптографических утилит
          Использование криптографических утилит
        • Взаимодействие с нодой
          Взаимодействие с нодой
        • Развертывание смарт-контрактов
          Развертывание смарт-контрактов
        Запуск кода
      Gowaves
    • WavesJ
      • Установка SDK
        Установка SDK
      • Запуск кода
        • Отправка транзакций
          Отправка транзакций
        • Использование криптографических утилит
          Использование криптографических утилит
        • Взаимодействие с нодой
          Взаимодействие с нодой
        • Развертывание смарт-контрактов
          Развертывание смарт-контрактов
        Запуск кода
      WavesJ
    • Ts-lib-crypto
      • Установка SDK
        Установка SDK
      Ts-lib-crypto
    • Waves-PHP
      • Установка SDK
        Установка SDK
      Waves-PHP
    • PyWaves-CE
      • Установка SDK
        Установка SDK
      PyWaves-CE
    • Waves-rust
      • Установка SDK
        Установка SDK
      Waves-rust
    Клиентские библиотеки
      • English
      • Русский
      On this page
        • План действий
        • Шаг 1. Создание аккаунта dApp
        • Шаг 2. Написание dApp-скрипта
        • Шаг 3. Установка скрипта
        • Шаг 4. Тестирование скрипта
        • Шаг 5. Выход в реальный мир
        • Что дальше
      waves_logo Docs

          # Как создать и запустить dApp: полное пошаговое руководство

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

          Для создания и тестирования dApp мы используем Waves IDE . Для создания веб-приложения, которое вызывает функции dApp, мы используем JavaScript.

          Процесс разработки dApp состоит из пяти простых шагов. Мы пройдем их один за другим. В результате должно получиться простое приложение Waves Magic 8 Ball — генератор превдослучайных ответов. В дальнейшем, повторяя эти шаги, вы сможете создать приложение любой сложности.

          О возможностях dApp читайте в разделе Что такое dApp.

          # План действий

          1. Создание аккаунта dApp.
          2. Написание dApp-скрипта.
          3. Установка скрипта на аккаунт dApp.
          4. Тестирование скрипта.
          5. Выход в реальный мир.

          # Шаг 1. Создание аккаунта dApp

          1. Откройте Waves IDE .

          2. Нажмите и убедитесь, что вы работаете с Testnet.

          3. Нажмите Add account → Generate new account.

          4. Нажмите Show seed and private key и сохраните секретную фразу в укромном месте — она потребуется для восстановления доступа к аккаунту.

          5. Пополните баланс аккаунта: в Testnet это бесплатно. Для этого:

            • Скопируйте адрес аккаунта: нажмите на название аккаунта, затем нажмите кнопку .

            • В Кране Waves вставьте адрес и нажмите Запросить WAVES.

          # Шаг 2. Написание dApp-скрипта

          1. Нажмите кнопку и выберите dApp script.
          2. Замените автоматически сгенерированный код на текст вашего скрипта.

          Файл скрипта сохраняется в Waves IDE автоматически.

          Код скрипта Waves Magic 8 Ball можно скопировать из библиотеки: Library → ride4dapps → 8ball → ride → 8ball.ride.

          Код скрипта
          {-# STDLIB_VERSION 8 #-}
          {-# CONTENT_TYPE DAPP #-}
          {-# SCRIPT_TYPE ACCOUNT #-}
          
          # Определяем количество и список ответов
          let answersCount = 20
          let answers = 
            ["It is certain.",
            "It is decidedly so.",
            "Without a doubt.",
            "Yes - definitely.",
            "You may rely on it.",
            "As I see it, yes.",
            "Most likely.",
            "Outlook good.",
            "Yes.",
            "Signs point to yes.",
            "Reply hazy, try again.",
            "Ask again later.",
            "Better not tell you now.",
            "Cannot predict now.",
            "Concentrate and ask again.",
            "Don't count on it.",
            "My reply is no.",
            "My sources say no.",
            "Outlook not so good.",
            "Very doubtful."]
          
          # Функция-генератор псевдослучайных ответов
          func getAnswer(question: String, previousAnswer: String) = {
            let hash = sha256(toBytes(question + previousAnswer))
            let index = toInt(hash)
            answers[index % answersCount]
          }
          
          # Функция получения предыдущего ответа из хранилища
          func getPreviousAnswer(address: String) = {
            match getString(this, address + "_a") {
              case a: String => a
              case _ => address
            }
          }
          
          # Функция ответа 
          @Callable(i)
          func tellme(question: String) = {
            # Получаем адрес пользователя, который вызывает контракт
            let callerAddress = i.caller.toString()
            # Получаем псевдослучайный ответ
            let answer = getAnswer(question, getPreviousAnswer(callerAddress))
            # Записываем данные в хранилище
            [
              StringEntry(callerAddress + "_q", question),
              StringEntry(callerAddress + "_a", answer)
            ]
          }
          
          Пояснения к коду

          dApp-скрипт должен начинаться с директив:

          {-# STDLIB_VERSION 8 #-}
          {-# CONTENT_TYPE DAPP #-}
          {-# SCRIPT_TYPE ACCOUNT #-}
          

          Между директивами и вызываемой функцией можно объявить переменные и вспомогательные функции.

          Перед объявлением вызываемой функции нужно указать аннотацию @Callable(i). Объект i содержит поля транзакции вызова скрипта, которые может использовать вызываемая функция. В нашем примере используется поле i.caller — адрес аккаунта, вызвавшего функцию.

          Результат вызываемой функции — набор действий скрипта. В нашем примере функция выполняет два действия StringEntry, которые добавляют или изменяют запись строкового типа в хранилище данных dApp.

          Подробнее о структуре dApp-скрипта читайте в разделе Структура dApp-скрипта.

          # Шаг 3. Установка скрипта

          Для установки dApp-скрипта на аккаунт нужно отправить с этого аккаунта транзакцию установки скрипта. Комиссия за установку скрипта составляет 0,01 WAVES.

          Отправить транзакцию можно прямо из Waves IDE:

          1. Откройте dApp-скрипт и нажмите Deploy.
          2. Нажмите Add sign, чтобы добавить подпись к транзакции. Нажмите Publish.

          Вы можете проверить установленный dApp-скрипт в Waves Explorer:

          1. Откройте https://wavesexplorer.com/ru .
          2. В правом верхнем углу переключитесь на Testnet.
          3. Выполните поиск по адресу аккаунта dApp.
          4. Перейдите на вкладку Скрипт.

          dApp готов к использованию — его функции можно вызывать с помощью транзакции вызова скрипта.

          # Шаг 4. Тестирование скрипта

          Для тестирования dApp-скрипта нужно отправить транзакцию вызова скрипта. Комиссия за вызов скрипта составляет от 0,005 WAVES и зависит от количества смарт-ассетов, используемых в вызове (в нашем примере они не используются). Формула расчета комиссии приведена в разделе Комиссия за транзакцию.

          Для ручного тестирования удобно использовать Waves Dapp Ui :

          1. Создайте аккаунт тестового пользователя в рекомендуемом приложении-кошельке, например:

            • в WX Network для Testnet ,

            • или в расширении для браузера Keeper Wallet , переключив сеть на Testnet перед созданием аккаунта.

          2. Пополните баланс аккаунта с помощью Крана Waves .

          3. В Waves Dapp Ui вставьте адрес dApp.

          4. Нажмите Sign In и подключите кошелек тестового пользователя.

          5. Задайте параметры вызываемой функции и приложите платежи, если требуется.

          Waves Dapp UI

          Выполнить тесты можно прямо из Waves IDE. В тестах поддерживаются функции:

          • describe и it из библиотеки mocha ;
          • expect из библиотеки chai .
          1. Создайте аккаунт тестового пользователя и пополните баланс — для этого повторите шаг 1.

          2. Нажмите кнопку и выберите Test.

          3. Замените автоматически сгенерированный код на ваш тест.

            Код теста для скрипта Waves Magic 8 Ball можно скопировать из библиотеки: Library → ride4dapps → 8ball → tests → 8ball_test.js. Не забудьте заменить значение ballAddress на адрес своего dApp.

          4. Нажмите кнопку Run full test.

          Код теста

          describe('8 ball', () => {
              const ballAddress = "3MxBZbnN8Z8sbYjjL5N3oG5C8nWq9NMeCEm"
              const question = "Test" + Date.now()
              const tx = invokeScript({fee: 500000, dApp: ballAddress, call:{function:"tellme", args:[{"type": "string", "value": question}]}, payment: null})

              it('Tx is mined in block', async function(){
                  await broadcast(tx)
                  await waitForTx(tx.id)
              })

              it('Question is in ball', async function(){
                  await accountDataByKey(address()+"_q", ballAddress)
                      .then(reslove => expect(reslove.value).to.equal(question))
              })
          })

          Вы можете проверить результат выполнения dApp-скрипта в Waves Explorer:

          1. Откройте https://wavesexplorer.com/ru .
          2. В меню справа вверху переключитесь на Testnet.
          3. Выполните поиск по адресу аккаунта dApp.
          4. Перейдите на вкладку Данные.

          # Шаг 5. Выход в реальный мир

          Для выхода в реальный мир:

          • Создайте веб-приложение, в котором пользователь сможет, нажав кнопку, подписать и отправить транзакцию вызова скрипта.
          • Добавьте ваш dApp на Mainnet.
          • Зарегистрируйте приложение в каталогах dApp, чтобы как можно больше пользователей узнали о нем!

          # 5.1. Создание веб-приложения

          Чтобы вызывать функции dApp от имени реального пользователя, подключите TypeScript/JavaScript-библиотеку Signer. Signer позволяет вашему веб-приложению подписать и отправить транзакцию вызова скрипта, не запрашивая у пользователя его секретную фразу (seed) или закрытый ключ.

          Код вызова скрипта

          await signer.invoke({
              dApp: ballAddress,
              call: {
                  function: "tellme",
                  args:[{"type": "string", "value": question}]
              }
          }).broadcast();

          Полный код приложения на Github

          # 5.2. Добавление dApp на Mainnet

          1. В Waves IDE нажмите и переключитесь на Mainnet.
          2. Создайте аккаунт dApp на Mainnet — аналогично шагу 1.
          3. Пополните баланс аккаунта, чтобы оплатить комиссию за установку скрипта. См. раздел Как получить WAVES.
          4. Установите dApp-скрипт на аккаунт — аналогично шагу 3.

          dApp на Mainnet получит другой адрес — не забудьте поменять его в веб-приложении. Кроме того, адрес ноды для отправки транзакции вызова скрипта нужно заменить на https://nodes.wavesnodes.com.

          💡 Если вы хотите сделать приложение бесплатным для пользователей и оплачивать вместо них комиссию за вызов скрипта, включите спонсирование.

          # 5.3. Регистрация на DappRadar

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

          Отправить заявку

          # Что дальше

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

          dApp
          Cмарт-аккаунт
          dApp
          Cмарт-аккаунт