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
    • Waves-python
      • Установка SDK
        Установка SDK
      Waves-python
    • Waves-rust
      • Установка SDK
        Установка SDK
      Waves-rust
    Клиентские библиотеки
      • English
      • Русский
      On this page
        • План действий
        • 1. Создание аккаунта главы ТСЖ
        • 2. Создание аккаунтов жильцов дома
        • 3. Создание dApp-скрипта
        • 4. Привязка dApp-скрипта к аккаунту главы ТСЖ
        • 5. Голосование
        • 6. Просмотр результатов голосования
      waves_logo Docs

          # Простое голосование на блокчейне Waves

          Глава ТСЖ (товарищества собственников жилья) задает вопрос жильцам дома: "Уважаемые жильцы, согласны ли вы со строительством детской площадки во дворе вашего дома?".

          На блокчейне Waves необходимо реализовать голосование жильцов дома за строительство детской площадки.

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

          1. Создадим аккаунт главы ТСЖ.
          2. Создадим аккаунты жильцов дома.
          3. Создадим dApp-скрипт с методом vote.
          4. Привяжем dApp-скрипт к аккаунту главы ТСЖ, создав таким образом dApp.
          5. Проголосуем с аккаунтов жильцов дома, вызвав метод vote dApp.
          6. Узнаем результаты голосования.

          # 1. Создание аккаунта главы ТСЖ

          Зайдите в настройки Waves IDE .

          Убедитесь, что выбрана тестовая сеть.

          Создайте аккаунт главы ТСЖ, выбрав Generate new account.

          Переименуйте созданный аккаунт в "Глава ТСЖ".

          Скопируйте адрес главы ТСЖ и с помощью Faucet пополните его баланс на 10 WAVES. Токены понадобятся главе ТСЖ для оплаты комиссии за транзакцию установки скрипта, когда он будет привязывать dApp-скрипт к своему аккаунту.

          # 2. Создание аккаунтов жильцов дома

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

          # 3. Создание dApp-скрипта

          Создайте dApp-скрипт, выбрав в выпадающем списке DApp.

          Переименуйте скрипт в "Голосование главы ТСЖ".

          Замените автоматически сгенерированный код на следующий:

          {-# STDLIB_VERSION 8 #-}
          {-# CONTENT_TYPE DAPP #-}
          {-# SCRIPT_TYPE ACCOUNT #-}
          
          func voterIsAllowedToVote(voterPublicKey: ByteVector) = {
          
              let alekseiPubKey = base58'8QvKvspfNF6cUv2DFMCfvT8SrbraERqXpNMEMqBfJZ3e'
              let annaPubKey = base58'AtYwJTqWNfwYrPnWVvfmnPTSTEioiLFzUTcZVttgDj1x'
          
              if (voterPublicKey != alekseiPubKey && voterPublicKey != annaPubKey)
              then
                  false
              else
                  true
          
          }
          
          @Callable(i)
          func vote(theVote: Int) = {
          
              if (!voterIsAllowedToVote(i.callerPublicKey))
              then
                  throw("Вы не можете голосовать, так как вас нет в списке голосующих!")
              else
                  let dataFromStorage = this.getInteger(i.callerPublicKey.toBase58String())
          
                  if (dataFromStorage.isDefined())
                  then
                      throw("Вы уже голосовали! Повтороное голосование запрещено.")
                  else
                      (
                          [
                              IntegerEntry(i.callerPublicKey.toBase58String(), theVote)
                          ],
                          unit
                      )
          }
          

          # Пояснения к коду dApp-скрипта

          # Функция vote

          Функция vote выполняет действие IntegerEntry, которое записывает голос в хранилище данных аккаунта главы ТСЖ.

          Перед функцией vote указана аннотация @Callable, которая делает данную функцию вызываемой у dApp. У данной аннотации i — переменная, содержащая информацию о вызове функции vote. Мы используем переменную i в коде для получения открытого ключа аккаунта i.callerPublicKey, который вызвал функцию.

          Для простоты в функции vote нет никаких проверок значения переменной theVote.

          # Функция voterIsAllowedToVote

          Функция voterIsAllowedToVote проверяет, что аккаунт, вызывающий скрипт, имеет право голосовать.

          В данном примере значения открытых ключей жестко прописаны в коде скрипта. В реальном примере можно было бы считывать открытые ключи, например, из хранилища данных аккаунта главы ТСЖ (предварительно записав их туда).

          Значения открытых ключей alekseiPubKey и annaPubKey возьмите из карточек аккаунтов Алексея и Анны.

          # Функция getInteger

          Функция getInteger получает значения из хранилища данных аккаунта по ключу:

          let dataFromStorage = this.getInteger(i.callerPublicKey.toBase58String())
          

          Размер и сложность скрипта отображаются в панели под редактором скрипта.

          # 4. Привязка dApp-скрипта к аккаунту главы ТСЖ

          Нажмите на кнопку Deploy dAppscript.

          В открывшемся окне, в комбинированном списке Account, выберите значение "Глава ТСЖ". Подпишите транзакцию, нажав Add sign.

          Отметим, что подписать транзакцию можно также секретной фразой или с помощью Keeper Wallet .

          Отправьте с аккаунта главы ТСЖ транзакцию установки скрипта, нажав Publish.

          Таким образом, вы только что создали dApp.

          В Waves Explorer для Testnet найдите информацию об активности на адресе главы ТСЖ. Для этого введите адрес главы ТСЖ в строку поиска и нажмите Enter.

          По адресу главы ТСЖ отображаются две транзакции: транзакция перевода (пополнение баланса на 10 WAVES с помощью faucet) и отправка транзакции установки скрипта. Отметим, что с баланса аккаунта главы ТСЖ списали комиссию за транзакцию установки скрипта в 0,01 WAVES.

          # 5. Голосование

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

          Отправьте транзакцию вызова скрипта с аккаунта Алексея с помощью консоли. Для этого в Waves IDE выберите аккаунт Алексея.

          Далее на вкладке Console выполните следующую команду:

          broadcast(invokeScript({dApp: "3Mz2X8c4Gpf8uporPrkEHA5TH73pYDYg6vL", call: {function: "vote", args: [{type: "integer", value: 7}]} }))
          

          Здесь 3Mz2X8c4Gpf8uporPrkEHA5TH73pYDYg6vL — адрес аккаунта главы ТСЖ.

          Если все прошло успешно, то вы увидите следующий результат (разверните объект Promise в консоли):

          Аналогично проголосуйте с аккаунта Анны, предварительно выбрав аккаунт Анны в Waves IDE:

          broadcast(invokeScript({dApp: "3Mz2X8c4Gpf8uporPrkEHA5TH73pYDYg6vL", call: {function: "vote", args: [{type: "integer", value: 25}]} }))
          

          Если вы попробуете повторно проголосовать с аккаунтов Алексея или Анны, то вы увидите ошибку:

          Если вы попробуете проголосовать с аккаунта главы ТСЖ, то вы увидите ошибку:

          # 6. Просмотр результатов голосования

          На вкладке Data в Waves Explorer просмотрите содержимое хранилища данных аккаунта главы ТСЖ — в хранилище данных содержатся две записи.

          Обмен токенов
          Список как аргумент
          Обмен токенов
          Список как аргумент