Как создать DApp на NodeJS для MetaMask

Как создать DApp на NodeJS для MetaMask

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

В этом руководстве показаны шаги по созданию базового сквозного децентрализованного приложения. С помощью этого приложения пользователи могут проверить текущую цену Ethereum и сохранить ее в смарт-контракте.

Изначально убедитесь, что у вас установлены NodeJS и MetaMask:

https://nodejs.org/en/

https://metamask.io/

Что такое децентрализованное приложение (dApp)?

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

Благодаря тому, что логика бэкенда размещается в высокозащищенных, защищенных от взлома смарт-контрактах, dApp имеют множество преимуществ, недоступных для традиционных систем Web2:

  • нулевое время простоя
  • повышенная конфиденциальность
  • устойчивость к цензуре
  • выполнение логики с минимальным уровнем доверия

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

Компоненты dApp

Компоненты dApp можно разделить на три различные категории: смарт-контракты, фронтенд-логика и пользовательский интерфейс, а также хранилище данных.

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

Фронтенд/интерфейс пользователя В то время как логика бэкенда dApp требует от разработчика написания кода смарт-контракта для развертывания на блокчейне, фронтенд или клиентская часть dApp может использовать стандартные веб-технологии, такие как HTML и JavaScript. Это позволяет разработчикам использовать знакомые инструменты, библиотеки и фреймворки. Пользовательский интерфейс на стороне клиента обычно связан со смарт-контрактами через клиентские библиотеки, такие как Web3.js или Ethers.js

https://web3js.readthedocs.io/en/v1.7.4/

https://docs.ethers.org/v5/

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

Хранение данных Большинству приложений необходимо хранить данные, но из-за распределенной природы блокчейн хранение больших объемов данных на цепочке нецелесообразно и может оказаться очень дорогим. Поэтому многие dApp, которым необходимо хранить данные, используют офф-чейн сервисы хранения данных, такие как IPFS или Filecoin, оставляя блокчейн только для хранения важной бизнес-логики и состояния.

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

Теперь, когда мы знаем компоненты dApp, давайте рассмотрим пример создания простого сквозного контракта.

Создание смарт-контракта

Смарт-контракт в нашем dApp будет простым примером, используемым для поиска данных и отражения изменений состояния на блокчейне. В данном случае мы будем искать стоимость ETH/USD, используя ETH/USD Data Feed, а затем постоянно сохранять результат в смарт-контракте.

https://data.chain.link/ethereum/mainnet/crypto-usd/eth-usd

Первым делом откройте документацию и перейдите на страницу Using Data Feeds:

https://docs.chain.link/data-feeds/price-feeds

Оттуда вы можете скопировать исходный код примера и вставить его в новый файл в выбранной вами IDE (например, Visual Code), либо нажать кнопку “Open In Remix” и работать из веб-версии Remix.

https://code.visualstudio.com/

В этом примере мы будем работать с Visual Studio Code и Hardhat, фреймворком для разработки виртуальной машины Ethereum.

https://hardhat.org/

Сначала мы создадим новую структуру каталогов для нашего dApp с папкой backend для кода смарт-контракта:

mkdir chainlink-dapp-example
cd chainlink-dapp-example
mkdir backend
cd backend

Далее мы откроем созданную директорию для нашего dApp в редакторе VS Code, а затем установим Hardhat:

npm init -y
npm install --save-dev hardhat
npx hardhat
(choose create javascript project, choose default parameters)

После этого удалите файл Touch.sol в папке “contracts”, создайте новый файл в этой папке под названием PriceConsumerV3.sol и сохраните. Здесь мы создадим наш смарт-контракт, поэтому скопируйте код из примера в документации Chainlink в этот файл и сохраните его.

В коде примера вы увидите, что в демо-контракте уже есть функция getLatestPrice для поиска текущей цены Ethereum на Rinkeby ETH/USD Data Feed.

function getLatestPrice() public view returns (int) {
        (
            /*uint80 roundID*/,
            int price,
            /*uint startedAt*/,
            /*uint timeStamp*/,
            /*uint80 answeredInRound*/
        ) = priceFeed.latestRoundData();
        return price;

Нам нужно создать новую переменную и новую функцию для хранения этого значения в смарт-контракте. Первым шагом будет создание новой переменной под существующей priceFeedone для хранения цены Ethereum:

int public storedPrice;

Далее нам нужно создать новую функцию, которая будет вызываться фронтендом dApp. Эта функция должна искать последнюю цену Ethereum, вызывая существующую функцию getLatestPrice. Затем она должна сохранить это значение в новом параметре storedPrice:

function storeLatestPrice() external {
        storedPrice = getLatestPrice();
    }

Ваш новый контракт должен выглядеть следующим образом:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract PriceConsumerV3 {

    AggregatorV3Interface internal priceFeed;
    int public storedPrice;

    /**
     * Network: Rinkeby
     * Aggregator: ETH/USD
     * Address: 0x8A753747A1Fa494EC906cE90E9f37563A8AF630e
     */
    constructor() {
        priceFeed =
AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
    }

    /**
     * Returns the latest price
     */
    function getLatestPrice() public view returns (int) {
        (
            /*uint80 roundID*/,
            int price,
            /*uint startedAt*/,
            /*uint timeStamp*/,
            /*uint80 answeredInRound*/
        ) = priceFeed.latestRoundData();
        return price;
    }

    function storeLatestPrice() external {
        storedPrice = getLatestPrice();
    }
}

Развертывание смарт-контракта

Теперь вы готовы скомпилировать и развернуть свой контракт в тестовой сети Rinkeby. Не забудьте сначала пополнить свой кошелек MetaMask некоторым количеством Rinkeby ETH.

https://faucets.chain.link/

Если вы используете Remix, вы можете скомпилировать и развернуть свой контракт, используя стандартный процесс Remix. Если вы используете IDE, например Visual Studio Code, мы рекомендуем использовать Hardhat для управления контрактами.

Первым шагом к компиляции и развертыванию вашего контракта является установка библиотеки инструментов Hardhat, библиотеки контрактов Chainlink и библиотеки dotenv для хранения паролей и секретных ключей в отдельном файле .env:

npm install --save-dev @nomicfoundation/hardhat-toolbox
npm install @chainlink/contracts --save
npm install dotenv

Затем замените содержимое файла hardhat-config.js на следующее:

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

После этого вам необходимо получить конечную точку RPC для доступа к сети Rinkeby. Это можно сделать, вставив URL RPC в поле RINKEBY_RPC_URL в файле .env. Мы рекомендуем подписаться на бесплатную учетную запись Infura или Alchemy, чтобы получить URL RPC.

https://www.infura.io/

https://www.alchemy.com/

Следующим шагом будет изменение содержимого файла deploy.js в папке ‘scripts’, чтобы убедиться, что он развернет ваш новый контракт. Откройте файл и убедитесь, что следующий код заменяет уже имеющийся. Это просто возьмет ваш скомпилированный контракт PriceConsumerV3 и попытается развернуть его. Не забудьте сохранить изменения.

Теперь вы готовы составить и развернуть свой смарт-контракт в сети Rinkeby с помощью Hardhat:

npx hardhat compile
npx hardhat run --network rinkeby scripts/deploy.js

Вы должны увидеть сообщение, подобное приведенному ниже, в котором будет указан адрес на Rinkeby, на который был развернут ваш смарт-контракт. Запишите этот адрес, он понадобится нам для следующего шага.

Поздравляем, теперь вы готовы перейти к фронтенд-части вашего dApp!

 Создание фронтенд-приложения

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

React – одна из самых популярных библиотек JavaScript для создания многофункциональных пользовательских веб-интерфейсов, поэтому она используется во многих Web3 dApp.

https://reactjs.org/

Кроме того, Ethers.js – это библиотека JavaScript для подключения и взаимодействия с блокчейнами и смарт-контрактами на базе EVM. Если объединить эти два компонента, вы получите разумную отправную точку для создания фронтенда вашего dApp.

В этом разделе мы создадим новое приложение React с помощью генератора шаблонов create-react-app. 

https://create-react-app.dev/

Затем мы внедрим офф-чейн логику, использующую Ethers.js для связи пользовательского интерфейса с развернутым смарт-контрактом, что позволит нам создать полноценный сквозной dApp.

Создание React-приложения Первым шагом для создания фронтенда является установка и реализация проекта create-react-app boilerplate, а затем его модификация для нашего dApp. Первым шагом будет установка библиотеки в новую папку “frontend”:

cd ..
npx create-react-app frontend

После этого в вашем проекте должна появиться новая папка “frontend” со всем связанным с ней кодом React. Раскройте папку “frontend” и выполните следующие действия:

  • Удалить /src/setupTests.js
  • Удалить /src/ReportWebVitals.js
  • Удалить /src/logo.svg
  • Удалить /src/App.test.js
  • Удалить /src/App.css

Структура папок должна выглядеть следующим образом:

Теперь мы почти готовы приступить к изменению кода приложения React. Но сначала не забудьте установить библиотеки для Bootstrap и Ethers.js.

https://getbootstrap.com/

 Bootstrap – это популярный CSS-фреймворк для фронтенда, который поставляется с удобными для React виджетами пользовательского интерфейса с наложенной стилизацией CSS, а Ethers.js позволяет нам подключить наш фронтенд к развернутым смарт-контрактам на блокчейне. Убедитесь, что эти команды выполняются из папки “frontend”.

cd frontend
npm install bootstrap
npm install ethers

Теперь мы готовы к изменению кода приложения React. Откройте файл App.js в папке /src/ и удалите его содержимое. Мы начнем создавать его с нуля.

Первый шаг – сообщить приложению, что мы хотим использовать React (включая библиотеки useEffect и useState) и Ethers.js:

import React, { useEffect, useState } from 'react';
import { ethers } from "ethers";

Затем создайте функцию под названием “App” и экспортируйте ее:

Теперь мы начнем заполнять содержимое функции “App”. Добавьте в нее следующий код. Этот код делает следующее:

Устанавливает реактивные хуки storedPrice и setStoresPrice. Создает соединение с вашим кошельком MetaMask Web3. Устанавливает адрес развернутого смарт-контракта и ABI. Оба эти параметра необходимы Ethers.js для взаимодействия с развернутым смарт-контрактом. Адрес смарт-контракта можно получить из шага развертывания, описанного ранее в этом руководстве. Вставьте это значение вместо строки REPLACE_WITH_DEPLOYED_CONTRACT_ADDRESS. ABI смарт-контракта можно получить из файла /backend/artifacts/contracts/PriceConsumerV3.json, в элементе abi. Вы можете использовать минификатор кода.

https://codebeautify.org/jsonminifier

Это поможет отформатировать его в лучшем виде для хранения в вашем приложении.

const [storedPrice, setStoredPrice] = useState('');
  const provider = new ethers.providers.Web3Provider(window.ethereum)
  const signer = provider.getSigner()
  const contractAddress = <REPLACE_WITH_DEPLOYED_CONTRACT_ADDRESS>’';
  const ABI =
'[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"getLatestPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"storeLatestPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"storedPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"}]'
  const contract = new ethers.Contract(contractAddress, ABI, signer);

Теперь мы создадим две функции, которые будут использоваться в нашем приложении:

getStoredPrice подключится к развернутому смарт-контракту и получит текущее значение геттер-функции storedPrice(). Функция setNewPrice будет вызывать функцию storeLatestPrice развернутого смарт-контракта, ждать завершения транзакции, а затем вызывать функцию getStoredPrice для получения сохраненной в смарт-контракте цены. Мы также добавим вызов getStoredPrice в нашу функцию App, чтобы она первоначально вызывала функцию getter при загрузке страницы:

Последним шагом в создании фронтенда является возврат JSX-кода для рендеринга браузером. Вставьте следующий код в нижней части функции App, под вызовом getStorePrice(). Этот код делает следующее:

Возвращает простой двухколоночный макет сетки. Первый столбец содержит текущую хранимую цену ETH/USD в смарт-контракте. Второй столбец содержит кнопку, которую пользователь может использовать для взаимодействия с умным контрактом и обновления сохраненной цены. Нажатие кнопки вызывает функцию setNewPrice, описанную выше.

Ваше приложение готово. Теперь вы готовы к запуску вашего dApp. Запуск приложения dApp Убедившись, что все файлы сохранены, запустите свой dApp локально, выполнив следующую команду из папки frontend:

npm run start

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

После того как вы убедитесь, что пополнили свой счет в MetaMask некоторым количеством Rinkeby ETH, нажмите кнопку “Обновить” в пользовательском интерфейсе dApp, чтобы взаимодействовать с развернутым смарт-контрактом в сети Rinkeby. Вы должны получить уведомление от MetaMask с просьбой подтвердить транзакцию. После этого в течение нескольких секунд ваш dApp должен автоматически обновиться, а в разделе “Сохраненная цена” появится текущая цена Ethereum:

Поздравляем, теперь вы успешно создали, развернули и взаимодействовали с простым dApp! В этом руководстве вы просто запустите фронтенд локально на своем компьютере, но при желании вы можете развернуть его на облачном сервере или даже децентрализовать фронтенд и развернуть его на IPFS! 

https://ipfs.tech/

Вы также можете поработать с CSS приложения, чтобы изменить внешний вид пользовательского интерфейса.

https://www.w3schools.com/css/

Итог

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

В этой технической демонстрации мы создали простой dApp, содержащий смарт-контракт, который получает последнюю цену от ETH/USD Data Feed и сохраняет результат в смарт-контракте. Затем мы создали простой пользовательский интерфейс, использующий React и Ethers.js для подключения к развернутому смарт-контракту и взаимодействия с ним.


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

Подпишитесь на наш Telegram: CRYPTO WIKIES | Bitcoin & Altcoins Mining

CRYPTO-MINING.BLOG – Будьте в курсе последних новостей о криптовалютах и майнинге!


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

Подпишитесь на наш Telegram: CRYPTO WIKIES | Bitcoin & Altcoins Mining

CRYPTO-MINING.BLOG – Будьте в курсе последних новостей о криптовалютах и майнинге!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *