DApps или же децентрализованные приложения — это приложения, которые не полагаются на один сервер для своей работы и безопасности. Вместо этого они используют блокчейн и оракулы в качестве основы своей системы, что делает их более защищенными от вредоносных действий и взломов.
В этом руководстве показаны шаги по созданию базового сквозного децентрализованного приложения. С помощью этого приложения пользователи могут проверить текущую цену Ethereum и сохранить ее в смарт-контракте.
Изначально убедитесь, что у вас установлены NodeJS и MetaMask:
Что такое децентрализованное приложение (dApp)?
В dApp код бэкенда работает на блокчейне, в отличие от традиционного приложения, где код бэкенда работает на централизованных серверах. dApp может иметь внешний код и пользовательские интерфейсы, написанные на любом языке и развернутые на любом сервере или серверах для взаимодействия с внутренней логикой.
Благодаря тому, что логика бэкенда размещается в высокозащищенных, защищенных от взлома смарт-контрактах, dApp имеют множество преимуществ, недоступных для традиционных систем Web2:
- нулевое время простоя
- повышенная конфиденциальность
- устойчивость к цензуре
- выполнение логики с минимальным уровнем доверия
Однако эти преимущества имеют и некоторые недостатки. Обслуживание dApps требует больших усилий, поскольку код, развернутый на блокчейне, по умолчанию не подлежит изменению. Кроме того, из-за того, что логика выполняется в распределенной сети, а не на централизованном сервере, повышаются и эксплуатационные расходы. В дополнение к этому, пользовательский опыт может пострадать из-за того, что пользователю dApp необходимо пройти через сложности, связанные с созданием кошелька Web3 и пополнением его достаточным количеством криптовалюты для оплаты комиссий за транзакции.
Компоненты dApp
Компоненты dApp можно разделить на три различные категории: смарт-контракты, фронтенд-логика и пользовательский интерфейс, а также хранилище данных.
Смарт-контракты Умные контракты хранят бизнес-логику dApp, а также состояние приложения. Это самое большое отличие dApp от традиционного веб-приложения, и именно это дает dApp все преимущества, упомянутые выше.
Фронтенд/интерфейс пользователя В то время как логика бэкенда dApp требует от разработчика написания кода смарт-контракта для развертывания на блокчейне, фронтенд или клиентская часть dApp может использовать стандартные веб-технологии, такие как HTML и JavaScript. Это позволяет разработчикам использовать знакомые инструменты, библиотеки и фреймворки. Пользовательский интерфейс на стороне клиента обычно связан со смарт-контрактами через клиентские библиотеки, такие как Web3.js или Ethers.js
Они поставляются в комплекте с ресурсами фронтенда и отправляются в браузер вместе с пользовательским интерфейсом. Взаимодействие со смарт-контрактами, такое как подписание сообщений и отправка транзакций смарт-контрактам, обычно осуществляется через браузерный Web3-кошелек, например MetaMask.
Хранение данных Большинству приложений необходимо хранить данные, но из-за распределенной природы блокчейн хранение больших объемов данных на цепочке нецелесообразно и может оказаться очень дорогим. Поэтому многие dApp, которым необходимо хранить данные, используют офф-чейн сервисы хранения данных, такие как IPFS или Filecoin, оставляя блокчейн только для хранения важной бизнес-логики и состояния.
Можно также использовать традиционные облачные сервисы хранения данных. Однако многие разработчики выбирают децентрализованные варианты, чтобы сохранить и расширить свойства минимизации доверия, которые обеспечивает dApp на базе блокчейна.
Теперь, когда мы знаем компоненты dApp, давайте рассмотрим пример создания простого сквозного контракта.
Создание смарт-контракта
Смарт-контракт в нашем dApp будет простым примером, используемым для поиска данных и отражения изменений состояния на блокчейне. В данном случае мы будем искать стоимость ETH/USD, используя ETH/USD Data Feed, а затем постоянно сохранять результат в смарт-контракте.
Первым делом откройте документацию и перейдите на страницу Using Data Feeds:
Оттуда вы можете скопировать исходный код примера и вставить его в новый файл в выбранной вами IDE (например, Visual Code), либо нажать кнопку “Open In Remix” и работать из веб-версии Remix.
В этом примере мы будем работать с Visual Studio Code и Hardhat, фреймворком для разработки виртуальной машины Ethereum.
Сначала мы создадим новую структуру каталогов для нашего 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.
Если вы используете 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.
Следующим шагом будет изменение содержимого файла deploy.js в папке ‘scripts’, чтобы убедиться, что он развернет ваш новый контракт. Откройте файл и убедитесь, что следующий код заменяет уже имеющийся. Это просто возьмет ваш скомпилированный контракт PriceConsumerV3 и попытается развернуть его. Не забудьте сохранить изменения.
Теперь вы готовы составить и развернуть свой смарт-контракт в сети Rinkeby с помощью Hardhat:
npx hardhat compile
npx hardhat run --network rinkeby scripts/deploy.js
Вы должны увидеть сообщение, подобное приведенному ниже, в котором будет указан адрес на Rinkeby, на который был развернут ваш смарт-контракт. Запишите этот адрес, он понадобится нам для следующего шага.
Поздравляем, теперь вы готовы перейти к фронтенд-части вашего dApp!
Создание фронтенд-приложения
Логика фронтенда и пользовательский интерфейс вашего dApp могут быть построены с использованием широкого спектра различных фреймворков.
React – одна из самых популярных библиотек JavaScript для создания многофункциональных пользовательских веб-интерфейсов, поэтому она используется во многих Web3 dApp.
Кроме того, Ethers.js – это библиотека JavaScript для подключения и взаимодействия с блокчейнами и смарт-контрактами на базе EVM. Если объединить эти два компонента, вы получите разумную отправную точку для создания фронтенда вашего dApp.
В этом разделе мы создадим новое приложение React с помощью генератора шаблонов create-react-app.
Затем мы внедрим офф-чейн логику, использующую 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.
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. Вы можете использовать минификатор кода.
Это поможет отформатировать его в лучшем виде для хранения в вашем приложении.
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!
Вы также можете поработать с CSS приложения, чтобы изменить внешний вид пользовательского интерфейса.
Итог
Децентрализованные приложения – это приложения, которые заменяют традиционную обработку данных на внутреннем сервере технологиями Web3, такими как блокчейн и смарт-контракты, что дает им уникальные гарантии безопасности и устойчивости к цензуре, которые невозможны для традиционных веб-приложений.
В этой технической демонстрации мы создали простой dApp, содержащий смарт-контракт, который получает последнюю цену от ETH/USD Data Feed и сохраняет результат в смарт-контракте. Затем мы создали простой пользовательский интерфейс, использующий React и Ethers.js для подключения к развернутому смарт-контракту и взаимодействия с ним.
Подпишитесь на
Подпишитесь на наш Telegram:
CRYPTO-MINING.BLOG – Будьте в курсе последних новостей о криптовалютах и майнинге!
Подпишитесь на
Подпишитесь на наш Telegram:
CRYPTO-MINING.BLOG – Будьте в курсе последних новостей о криптовалютах и майнинге!
No Comments