# Простое голосование на блокчейне Waves
Глава ТСЖ (товарищества собственников жилья) задает вопрос жильцам дома: "Уважаемые жильцы, согласны ли вы со строительством детской площадки во дворе вашего дома?".
На блокчейне Waves необходимо реализовать голосование жильцов дома за строительство детской площадки.
# План действий
- Создадим аккаунт главы ТСЖ.
 - Создадим аккаунты жильцов дома.
 - Создадим dApp-скрипт с методом 
vote. - Привяжем dApp-скрипт к аккаунту главы ТСЖ, создав таким образом dApp.
 - Проголосуем с аккаунтов жильцов дома, вызвав метод 
votedApp. - Узнаем результаты голосования.
 
# 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 просмотрите содержимое хранилища данных аккаунта главы ТСЖ — в хранилище данных содержатся две записи.
