Этот пост предназначен для всех, кто ищет подробное руководство по разработке и развертыванию приложения на основе блокчейна (в данном случае Ethereum) с использованием Vue.js для создания интерфейса и Truffle. @ Drizzle / vue-plugin для добавления суперспособностей блокчейна.

Репозиторий готового проекта можно найти здесь.

Предпосылки

Для этого урока вам понадобится несколько основных инструментов, установленных в вашей системе. Примечание: эти инструкции были написаны для системы Mac / Linux, но также должны применяться к Windows.

Установить узел

Если на вашем компьютере нет Node.js, возможно, вы захотите вернуться назад. Рекомендуемая версия для этого руководства: 10.16.1.

Чтобы легко переключаться между версиями Node для каждого проекта, я бы рекомендовал nvm.

Установить Truffle

Truffle - это набор инструментов, предназначенных для создания, компиляции, тестирования и развертывания смарт-контрактов. Установить глобально.

npm install -g truffle

Установить Vue CLI

Vue CLI - это самый быстрый способ скаффолдинга приложения Vue.js с помощью некоторых распространенных пакетов и инструментов. Установите это также глобально.

npm install -g @vue/cli

А теперь приступим!

Инициализация приложения

Создайте новое приложение Vue с помощью Vue CLI.

vue create guestbook

Вам будет предложено выбрать дополнительные пакеты для включения в свое приложение. Выберите все, что вы хотите использовать в своем проекте, но не забудьте включить Vuex, поскольку он будет служить связующим звеном между интерфейсом Vue и вашими смарт-контрактами. Это достигается за счет использования Drizzle, еще одного продукта Truffle, который отслеживает состояние смарт-контрактов и обеспечивает легкий доступ к методам, данным и событиям.

После успешного создания приложения инициализируйте Truffle в корне проекта.

truffle init

Это создаст несколько файлов и папок. Ваша структура каталогов должна выглядеть так:

Откройте truffle-config.js и измените module.exports, чтобы Truffle поместил выходные данные сборки JSON в папку src, где интерфейсная программа может получить к ней доступ.

contracts_build_directory: "./src/contracts",

Теперь мы можем написать простой договор с гостевой книгой!

Написание контракта

Внутри папки contracts (в корне проекта, а не в src / контрактах) создайте новый файл с именем Guestbook.sol и создайте контракт.

pragma solidity >=0.4.21 <0.6.0;
contract Guestbook {
  event SignatureAdded(string message, bytes32 name);
  bytes32[] guests;
  function signBook(bytes32 name) public {
    guests.push(name);
    emit SignatureAdded("New guest signature!", name);
  }
  function getNames() public view returns (bytes32[] memory) {
    return guests;
  }
}

В первой строке объявляется, какую версию компилятора Solidity следует использовать в этом контракте. Для наших целей мы будем использовать тот же диапазон версий, что и контракт, созданный при запуске truffle init.

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

Контракт готов к развертыванию! Но сначала нам нужно создать миграцию, чтобы сообщить Truffle о нашем новом контракте. Внутри папки migrations создайте новый файл миграции с именем 2_deploy_guestbook.js. Добавьте следующее содержимое:

const Guestbook = artifacts.require("Guestbook");
module.exports = function(deployer) {
  deployer.deploy(Guestbook);
};

Вернувшись в консоль в корневом каталоге проекта, инициализируйте консоль Truffle dev.

truffle develop

Вы будете вознаграждены своим личным блокчейном! Есть список адресов и закрытых ключей, а также мнемоника, которая понадобится вам для подключения к этому кошельку в другом месте. Вы заметите, что ваша консоль изменилась на truffle(develop)>. Чтобы скомпилировать и перенести контракты одним махом, просто запустите:

migrate

Полезный совет - во время разработки вы можете вместо этого запустить:

migrate --reset

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

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

Создание приложения Vue

Откройте вторую консоль, так как нам нужно держать Truffle REPL под рукой для имитации нашей цепочки блоков Ethereum. Зайдите в корень вашего проекта и установите Drizzle Vue Plugin.

npm install @drizzle/vue-plugin

Затем перейдите в папкуsrc и создайте файл с именем drizzleOptions.js. Этот файл будет содержать конфигурацию для Drizzle. Добавьте следующий код:

import Guestbook from "@/contracts/Guestbook.json";
const options = {
  web3: {
    block: false,
    fallback: {
      type: "ws",
      url: "ws://127.0.0.1:9545"
    }
  },
// The contracts to monitor
  contracts: [Guestbook],
  events: {
    Guestbook: ["SignatureAdded"]
  },
  polls: {
    // check accounts ever 15 seconds
    accounts: 15000
  }
};
export default options;

Здесь мы сообщаем Drizzle, где расположены артефакты сборки контракта, регистрируем контракт гостевой книги и сообщаем Drizzle, какие события он должен прослушивать, которые могут быть сгенерированы контрактом.

Откройте main.js и сделайте так:

import Vue from "vue"
import App from "./App.vue"
import store from "./store"
import drizzleVuePlugin from "@drizzle/vue-plugin"
import drizzleOptions from "./drizzleOptions"
Vue.config.productionTip = false
Vue.use(drizzleVuePlugin, { store, drizzleOptions })
new Vue({
  store,
  render: h => h(App)
}).$mount("#app")

Здесь мы импортируем магазин Vuex, плагин Drizzle и только что созданный файл параметров. Затем мы говорим нашему приложению использовать плагин и передаем файл store и options в качестве параметров плагину.

Откройте App.vue и отредактируйте раздел шаблона. Обязательно удалите любой шаблонный код, сгенерированный Vue CLI, например компоненты HelloWorld или нежелательные стили:

<template>
  <div v-if="isDrizzleInitialized" id="app">
    <h1>Sign the Guestbook</h1>
    <drizzle-contract-form
      contractName="Guestbook"
      method="signBook"
      :placeholders="['Name']"
    />
    <h2>Guests:</h2>
    <ul v-if="getNames">
      <li v-for="(name, i) in getNames" :key="i">{{ utils.toUtf8(name) }}</li>
    </ul>
  </div>
  <div v-else>
    Loading application...
  </div>
</template>

Во-первых, шаблон содержит v-if/else в корне. Если Drizzle еще не инициализирован, данные вашего смарт-контракта не будут доступны, и вы тем временем захотите отобразить что-нибудь еще.

Существует специальный компонент под названием drizzle-contract-form, который регистрируется при установке подключаемого модуля Drizzle. Учитывая имя контракта и метод, он будет генерировать входные данные, соответствующие входным параметрам, ожидаемым контрактом. Вы также можете установить массив заполнителей, которые отображаются в порядке значений параметров.

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

Вот раздел файла the<script>:

<script>
import { mapGetters } from "vuex"
export default {
  name: "app",
  computed: {
    ...mapGetters("drizzle", ["drizzleInstance", "isDrizzleInitialized"]),
    ...mapGetters("contracts", ["getContractData"]),
    getNames() {
      let data = this.getContractData({
        contract: "Guestbook",
        method: "getNames"
      });
      if (data === "loading") return false;
      return data
    },
    utils() {
      return this.drizzleInstance.web3.utils
    }
  },
  created() {
    this.$store.dispatch("drizzle/REGISTER_CONTRACT", {
      contractName: "Guestbook",
      method: "getNames",
      methodArgs: []
    })
  }
}
</script>

Вот разбивка:

  • Импортируйте mapGetters из Vuex, чтобы разрешить доступ к модулям хранилища Vuex, созданным плагином как вычисляемые свойства в нашем компоненте. См. Их документацию для получения дополнительной информации о том, как работает mapGetters.
  • Используйте mapGetters, чтобы импортировать несколько функций дождя из магазина. Нам нужен drizzleInstance для его утилит для преобразования текста. isDrizzleInitialized возвращает логическое значение, которое мы можем использовать для условного рендеринга приложения и показывать какой-то индикатор «загрузки», когда оно еще не совсем готово. Наконец, getContractData позволяет нам передавать имя и метод контракта и получать данные о его состоянии в реактивном режиме. Аккуратный!
  • Получите список имен гостевых книг с помощью getContractData. Проверьте возвращаемое значение, чтобы ничего не сломать в макете.
  • Импортируйте утилиты из drizzleInstance для преобразования шестнадцатеричного кода в читаемый текст. Экземпляр Drizzle расширяет web3.utils - ознакомьтесь с документацией, чтобы лучше понять типы доступных операций.
  • Когда компонент создан, зарегистрируйте контракт, метод и аргументы, используя действие REGISTER_CONTRACT из плагина. Это устанавливает контракт в Drizzle и делает его данные и функции доступными для вашего приложения, включая метод getContractData.

Мы готовы запустить приложение!

Запуск приложения!

В вашем терминале:

npm run serve

Вы также можете использовать yarn serve, если вам нравится такой вкус. После успешного построения сервер разработки должен запуститься.

Перейдите к одному из URL-адресов. Мы собираемся использовать Metamask в этом примере, но вы можете использовать любой другой браузер web3, если вы можете импортировать учетную запись и настроить URL-адрес RPC.

Если вы используете Metamask и не хотите терять текущий кошелек, убедитесь, что вы экспортировали исходную фразу (Настройки - ›Безопасность и конфиденциальность).

Выйдите из Metamask, затем на экране входа нажмите Импортировать с использованием начальной фразы учетной записи. Используйте начальную фразу, предоставленную truffle develop, и ваш кошелек должен заполниться учетными записями, отображаемыми в консоли Truffle. Теперь в вашем приложении вы должны увидеть поле ввода, в котором вы можете добавить имя в список и отправить его в список. Попробуй! Через несколько секунд вы должны увидеть имя, которое появится в списке ниже.

Вы сделали это! В следующей части этой серии мы развернем смарт-контракты в тестовой сети Ropsten Ethereum. Следите за обновлениями!