Опубликован: 28.01.2018 | Доступ: свободный | Студентов: 924 / 142 | Длительность: 06:54:00
Лекция 5:

Использование возможностей библиотеки Web3 и среды разработки Truffle

< Лекция 4 || Лекция 5: 123456

Отображение транзакций пользователей

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

Откроем среду разработки. Перейдем к контракту SimpleWallet и перепишем его так, чтобы ассоциация isAllowedToSendFunds связывала не адреса и булевы значения, а адреса и структуры.


Нам потребуется определить эти структуры. Ассоциация будет связывать адреса и структуры с отправителями, в которых будет записано, авторизованы ли они распоряжаться эфиром. Другая ассоциация будет связываться со структурами, включающими снятия со счета. Приступим к определению структур.

Рассмотрим структуру отправителей Senders. В ней будет булево поле allowed, показывающее, что отправитель авторизован распоряжаться эфиром. Еще потребуется ключевое значение и связка со следующей структурой WithdrawlStruct, которую тоже нужно задать. Определяем эту структуру. Здесь пригодится адресное поле to и величина снятия amount. Теперь перенесем ассоциацию, связывающую адреса и отправителей.


Теперь нужно немного расширить спектр используемых функций. Начнем с функций allow и disallow. Для получения доступа к структуре пригодится булево расширение этих функций - в одном случае оно получит значение "true", в другом - "false".


Теперь допишем к этой функции allowed. Теперь обе функции получают доступ к структуре, а не просто к булеву значению из массива. Затем можно расширить следующую функцию, например, isAllowedToSend. Вместо того, чтобы просто создавать событие Withdrawl, описывающее снятие средств, можно расширить его для регистрации всех снятий. Получим доступ к структуре, добавим сюда ключ, который нужно увеличить для корректного получения доступа к структуре. Затем добавим параметров для доступа к структуре withdrawls. И, наконец, объявим, что в поле to будет записан получатель средств, receiver, а в поле amount - их объем.


Когда кто-либо отправляет средства со счета и имеет на это полномочия, а на счету достаточно средств и функция отправки успешно срабатывает, создается событие Withdrawl, записывающее снятие средств в ассоциацию isAllowedToSendFundsMapping.

Перейдем к коду JavaScript, который содержит три разных страницы. Одна из них - главная страница. На ней хотелось бы отображать баланс счета, а также все снятия с конкретного адреса. Страницу с событиями рассмотрим в следующей лекции. А на странице отправки средств должна быть возможность отправки средств на адрес контракта и их снятия в пользу заданного адреса.


Обратимся для начала к странице для отправки средств. Но перед этим добавим к нашему распределенному приложению загрузчик. Откроем index.html и выполним набор действий для включения загрузчика. Сначала скопируем файлы CSS, затем код JavaScript. Теперь при обработке веб-страницы будет задействован загрузчик, и можно будет воспользоваться всеми его функциями.


Настоятельно рекомендуется ознакомиться с документацией по getbootstrap (загрузчик Bootstrap).


Добавим к нашему приложению небольшое меню: кнопку SimpleWallet, бренд нашего приложения, кнопку для перехода к событиям и еще одну для отправки средств. Также добавим в контейнер якорь для отображения. Теперь все отцентрировано, а якорь для отображения находится в контейнере.


Перейдем к странице отправки средств. Будем использовать две функции. Одна будет отвечать за отправку средств контракту. Откроем список всех локальных счетов в клиенте Geth или другом узле APC. Выберем один из этих счетов, определим количество эфира для отправки и воспользуемся кнопкой для отправки средств.

Другой функцией станет отправка средств контракта на конкретный адрес. Форма Deposit начинается с простого заголовка, а затем идет раскрывающийся список из нескольких счетов и, конечно, поле для ввода объема средств для пересылки. И кнопка отправки команды.


Перейдем к контроллеру и посмотрим, как выглядит функция depositFunds изнутри. В контроллере SendfundsController удалим переменную myVar и начнем работу. Для начала создадим список доступных счетов. Объект Web3 привязан к активному окну, поэтому список счетов можно получить с помощью команды web3.eth.accounts. Еще одна функция - depositFunds, которая требует адреса (address) и объема средств (amount) в качестве входных параметров.

Далее получим доступ к контракту и запустим транзакцию. Поле from используется для задания адреса, откуда будут списываться средства, to - адрес нашего контракта, а value - это количество эфира, которое нужно конвертировать в веи. Затем идет функция обратного вызова, с помощью которой будем контролировать успешность операции. Если операция завершится с ошибкой, то ее классифицируем и выведем сообщение об ошибке, а если все пройдет хорошо, то отобразим короткое сообщение об успешности перевода средств. Поскольку работаем вне стандартных инструментов обнаружения ошибок Angular, потребуется внести в них изменения вручную.


Вернемся на веб-страницу отправки средств и добавим короткое оповещение в случае успешного перевода средств. Кроме того, если отправка была удачной, нет необходимости показывать форму для зачисления средств.


Перейдем в папку truffle2 и введем команду truffle serve.


Исправляем ошибки.



Код компилируется без проблем, но мы забыли разместить его в блокчейне с помощью команды truffle migrate. Теперь введем команду truffle serve.


Перейдем на адрес http://localhost:8080 и посмотрим на наш веб-кошелек. Здесь есть короткое меню, отображается секция для зачисления средств. Откроем консоль JavaScript. Вот список счетов из сети testrpc. Выберем первый счет и введем величину в одну единицу эфира.


Исправляем еще одну ошибку: simpleWallet, а не simpleContract.


Выполним сборку контракта еще раз.


Перезагрузим страницу. Теперь отправка средств прошла успешно. В консоли testrpc тоже показывается, что транзакция завершилась успешно.


Теперь перейдем на главную страницу и добавим код по запросу баланса. Добавим баланс в единицах эфира.


Переменной scope.balance соответствует web3.eth.getBalance. Конвертируем эту величину в число и задаем переменной scope.balanceInEther значение web3.fromWei, выраженное в единицах эфира.


Вернемся на адрес localhost:8080 . На счету контракта одна единица эфира.


Вернемся к механизму отправки средств и реализуем функцию снятия средств со счета. Добавим дополнительную форму с функцией снятия средств. Добавим функцию Withdraw. Команда withdrawFunds требует адреса и объема средств в качестве аргументов. Можно указать адрес, на который вы желаете перевести средства, объем в единицах эфира, и щелкнуть по кнопке Submit.


Перейдем к нашему контроллеру JavaScript и добавим эту функцию. Она требует один адрес и одно число - величину средств для перевода. Добавим контракт SimpleWallet и возможность вызова функции sendFunds из контракта SimpleWallet.


Если я перейду в контракт SimpleWallet, функция sendFunds будет требовать указания объема средств и адреса.


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


Далее опишем действия в случае возникновения ошибки.

Посмотрим, как вся эта логика выглядит со стороны веб-страницы. Вот функции пополнения и снятия средств.


Применим небольшую хитрость для получения одного из адресов: скопируем его из списка.


Вставим адрес в функцию перевода средств. Предположим, что необходимо перевести одну единицу эфира. Щелкаем по кнопке Submit. Получилось совсем не то, что ожидалось - возвращается не та величина.


Вот что нужно были сделать на самом деле.


Теперь добавим на счет одну единицу эфира. И теперь перешлем единицу эфира. Повторим эту транзакцию несколько раз.


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


Откроем MainController. Здесь нужно будет задать массив, который назовем withdrawls.


В нем можно будет перечислить все списания, упомянутые в ассоциации isAllowedToSendFunds. Для этого в первую очередь нужно вернуть количество списаний, произведенных с этого адреса. Давайте назовем эту функцию getAmountOfWithdrawls с параметром адресного типа. Это - постоянная функция, возвращающая число типа uint. В данном случае она возвращает isAllowedToSendFundsMapping[_address].amount_sends. Теперь зададим еще одну функцию, возвращающую информацию по конкретному списанию. Вернуть всю структуру нельзя, но можно вернуть несколько значений. Зададим функцию getWithdrawlForAddress с аргументами типов _address, uint и index. Эта функция возвращает адрес и объем переданного эфира. Настроим возврат процедуры. Важно отметить, что все эти значения инициализируются автоматически. Закончим задавать параметры для функции.


Теперь давайте попробуем удалить эту сборку и разместить наш контракт в блокчейне еще раз.


Затем подадим команду truffle serve, которая заново создаст HTTP-сервер и порт 8080.


Теперь, когда кошелек полностью обновлен и подключен к блокчейну, попробуем отправить средства со счета. На счету у нас три единицы эфира. Скопируем второй адрес и отправим одну единицу эфира, а потом повторим процедуру. Теперь посмотрим, как отобразить все процедуры списания. Для начала нам потребуется функция contract.getAmountOfWithdrawls.call, вызовем ее с указанием параметра web3.eth.accounts[0] , то есть запросим отображение всех списаний по первому счету. Запишем результат в переменную numberOfWithdrawls, и последовательно пройдем по списку всех списаний эфира с этого адреса с помощью цикла for. Установим счетчик i, равный единице, и будем выполнять функцию contract.getWithdrawlForAddress.call, пока i не станет равен числу всех списаний, numberOfWithdrawls, увеличивая i на единицу на каждом шаге и отображая это на веб-странице с помощью команды $scope.withdrawls.push(result_withdrawl) . Добавим команды для корректной работы Angular и Ether-Padding - $scope.$apply() и return this.


Перейдем на главную страницу. Будем разбираться со снятиями со счета. Опишем заголовок поля, зададим адрес с помощью ключевого слова to: , это снятие будет первым элементом соответствующего массива. Затем укажем величину снятия, для удобства ее лучше выразить в единицах эфира, поэтому потребуется конвертация с помощью функции fromWei.


Посмотрим, успешно ли это работает. Нет, разумеется, доступ запрещен.


Нужно откорректировать способ отображения суммы для списания, так, чтобы она отображалась в единицах эфира.


Проверим. Теперь объем средств для списания отображается в единицах эфира, и остается только убедиться, что данные поступают в численном формате.


Подведем краткие итоги этой лекции. Главной задачей было обеспечить корректную работу модуля списания эфира со счета. Во-первых, включили загрузчик Bootstrap в приложение и разобрались, как настроить его базовую конфигурацию путем копирования общедоступных участков кода. Данный загрузчик устанавливает тему страницы, поддерживает таблицы стилей CSS, библиотеку jQuery и bootstrap.jsВо-вторых, включили меню. Можно найти разные варианты реализации меню в свободном доступе, например, на сайте, посвященном загрузчику Bootstrap, на странице Components в разделе Navbar. Для данной лекции просто скопировали с сайта часть кода и удалили ненужные участки. В-третьих, установили якорь для отображения в контейнер, чтобы контент веб-кошелька не занимал всю ширину страницы, а был отцентрирован и умещался в 960 пикселов.

Вторая часть лекции представляла собой подготовку к настройке модуля снятия средств. Добавили на веб-страницу sendfunds.html две формы: для зачисления (Deposit) и снятия (Withdrawal) средств. По щелчку по кнопке Submit эти формы вызывают из контроллера функции зачисления или списания средств. Адреса для зачисления и списания также берутся из этих модулей путем предоставления выбора из списка адресов, доступных в нашей тестовой сети testrpc. Список счетов можно всегда получить с помощью функции web3.eth.accounts. Разумеется, результат будет различаться в зависимости от того, к какому узлу вы подключены. Например, если у вас запущен кошелек Mist или работает узел Geth, допускающий RPC-подключения по протоколу HTTP, вы увидите доступные в этих сетях счета в веб-кошельке. В данном случае приложение подключено к сетиtestrpc, и можно видеть существующие в ней счета. Если вернуться к файлу app.js и контроллеру SendFundsController, можно увидеть, в каком участке кода получаем список счетов и можем проходиться по их списку с помощью функции Withdraw, требующей указания целевого адреса и объема средств для передачи. Функция зачисления средств создает транзакцию для перевода средств со счета, находящегося в кошельке, на адрес контракта, также на заданную величину единиц эфира. В функции отправки вызываем функцию sendFunds из контракта, и она так же требует указания объема средств и адреса получателя, после чего пересылает средства из контракта получателю.

Кроме того, функция отправки средств создает событие и добавляет информацию о факте перечисления средств в структуру данных и соответствующую ассоциацию. Никакой чрезмерно сложной логики здесь нет, все процедуры работают довольно прозрачным образом.

Списания будем отображать в контроллере MainController. Вызываем функцию getAmountOfWithdrawls из нашего контракта, которая возвращает нам объем произведенных списаний, а именно число записей в отображении, хранящем информацию о списаниях. Поскольку каждый раз при списании средств общий объем отправленных средств увеличивается, отражаем это в соответствующей переменной, а также увеличиваем число операций списания на единицу. Все это нужно для отображения числа операций списания средств. Каждая из них имеет свой номер, последняя операция будет иметь самый большой номер. Затем просто проходимся со счетчиком i, начиная с единицы, по всем операциям списания, и берем из каждой из них объем списанных средств, после чего конвертируем сумму в единицы эфира и размещаем информацию в массив данных о списаниях.

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

< Лекция 4 || Лекция 5: 123456
Алексей Миронов
Алексей Миронов

Здравствуйте, сколько стоит курс Работа с Ethereum?