Перейти до основного вмісту

Смарт-контракт Hello World для початківців — Fullstack

Solidity
Hardhat
Alchemy
смарт-контракти
розгортання
оглядач блоків
фронтенд
транзакції
фреймворк
Для початківців
nstrike2
25 жовтня 2021 р.
41 хвилин на читання

Цей посібник для вас, якщо ви новачок у розробці на блокчейні й не знаєте, з чого почати або як розгортати смарт-контракти та взаємодіяти з ними. Ми крок за кроком розглянемо створення та розгортання простого смарт-контракту в тестовій мережі Ґерлі за допомогою МетаМаск (відкривається в новій вкладці), Solidity (відкривається в новій вкладці), Hardhat (відкривається в новій вкладці) та Alchemy (відкривається в новій вкладці).

Для проходження цього посібника вам знадобиться акаунт Alchemy. Зареєструйте безкоштовний акаунт (відкривається в новій вкладці).

Якщо на будь-якому етапі у вас виникнуть запитання, не соромтеся звертатися до Discord Alchemy (відкривається в новій вкладці)!

Частина 1 — Створення та розгортання вашого смарт-контракту за допомогою Hardhat

Підключення до мережі Етеріум

Існує багато способів робити запити до ланцюга Етеріум. Для простоти ми використаємо безкоштовний акаунт на Alchemy — платформі для розробників блокчейну та API, яка дозволяє нам взаємодіяти з ланцюгом Етеріум без необхідності самостійно запускати вузол. Alchemy також має інструменти розробника для моніторингу та аналітики; ми скористаємося ними в цьому посібнику, щоб зрозуміти, як технічно відбувається розгортання нашого смарт-контракту.

Створення вашого застосунку та ключа API

Після створення акаунту Alchemy ви можете згенерувати ключ API, створивши застосунок. Це дозволить вам робити запити до тестової мережі Sepolia. Якщо ви не знайомі з тестовими мережами, ви можете прочитати посібник Alchemy щодо вибору мережі (відкривається в новій вкладці).

На панелі керування Alchemy знайдіть випадне меню Apps на панелі навігації та натисніть Create App.

Створення застосунку Hello world

Дайте своєму застосунку назву 'Hello World' і напишіть короткий опис. Виберіть Staging як середовище та Sepolia як мережу.

Перегляд створення застосунку Hello world

Примітка: обов'язково виберіть Sepolia, інакше цей посібник не працюватиме.

Натисніть Create app. Ваш застосунок з'явиться в таблиці нижче.

Створення акаунту Етеріум

Вам потрібен акаунт Етеріум, щоб надсилати та отримувати транзакції. Ми використаємо МетаМаск — віртуальний гаманець у браузері, який дозволяє користувачам керувати адресою свого акаунту Етеріум.

Ви можете безкоштовно завантажити та створити акаунт МетаМаск тут (відкривається в новій вкладці). Під час створення акаунту, або якщо він у вас уже є, обов'язково перемкніться на «Sepolia Test Network» у верхньому правому куті (щоб ми не мали справи з реальними грошима).

Крок 4: Додавання етеру з крана

Щоб розгорнути ваш смарт-контракт у тестовій мережі, вам знадобиться трохи несправжнього ETH. Щоб отримати ETH у мережі Sepolia, перейдіть до крана Sepolia та введіть адресу вашого акаунту Sepolia. Перегляньте сторінку тестових мереж, щоб знайти список доступних варіантів:

Примітка: через перевантаження мережі це може зайняти деякий час. ``

Крок 5: Перевірка вашого балансу

Щоб ще раз переконатися, що ETH є у вашому гаманці, давайте зробимо запит eth_getBalance (відкривається в новій вкладці) за допомогою інструменту пісочниці Alchemy (відкривається в новій вкладці). Це поверне кількість ETH у нашому гаманці. Щоб дізнатися більше, перегляньте короткий посібник Alchemy про те, як користуватися інструментом composer (відкривається в новій вкладці).

Введіть адресу вашого акаунту МетаМаск і натисніть Send Request. Ви побачите відповідь, схожу на фрагмент коду нижче.

{ "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" }

Примітка: Цей результат вказано у wei, а не в ETH. Wei використовується як найменша одиниця етеру.

Хух! Усі наші несправжні гроші на місці.

Крок 6: Ініціалізація нашого проєкту

Спочатку нам потрібно буде створити папку для нашого проєкту. Перейдіть до командного рядка та введіть наступне.

mkdir hello-world
cd hello-world

Тепер, коли ми знаходимося всередині папки нашого проєкту, ми використаємо npm init для ініціалізації проєкту.

Якщо у вас ще не встановлено npm, дотримуйтесь інструкцій зі встановлення Node.js (відкривається в новій вкладці), щоб встановити Node.js та npm.

Для цілей цього посібника не має значення, як ви відповідатимете на запитання щодо ініціалізації. Ось як ми це зробили для довідки:

Затвердьте package.json, і ми готові до роботи!

Крок 7: Завантаження Hardhat

Hardhat — це середовище розробки для компіляції, розгортання, тестування та налагодження вашого програмного забезпечення для Етеріум. Воно допомагає розробникам створювати смарт-контракти та децентралізовані застосунки (dapp) локально перед розгортанням у робочому ланцюзі.

Усередині нашого проєкту hello-world виконайте:

npm install --save-dev hardhat

Перегляньте цю сторінку для отримання додаткової інформації щодо інструкцій зі встановлення (відкривається в новій вкладці).

Крок 8: Створення проєкту Hardhat

Усередині папки нашого проєкту hello-world виконайте:

npx hardhat

Після цього ви побачите вітальне повідомлення та можливість вибрати, що ви хочете зробити. Виберіть «create an empty hardhat.config.js»:

Це згенерує файл hardhat.config.js у проєкті. Ми використаємо його пізніше в посібнику, щоб вказати налаштування для нашого проєкту.

Крок 9: Додавання папок проєкту

Щоб підтримувати порядок у проєкті, давайте створимо дві нові папки. У командному рядку перейдіть до кореневого каталогу вашого проєкту hello-world і введіть:

mkdir contracts
mkdir scripts
  • contracts/ — тут ми зберігатимемо файл коду нашого смарт-контракту hello world
  • scripts/ — тут ми зберігатимемо скрипти для розгортання та взаємодії з нашим контрактом

Крок 10: Написання нашого контракту

Ви можете запитати себе: коли ж ми будемо писати код? Час настав!

Відкрийте проєкт hello-world у вашому улюбленому редакторі. Смарт-контракти найчастіше пишуться мовою Solidity, яку ми й використаємо для написання нашого смарт-контракту.‌

  1. Перейдіть до папки contracts і створіть новий файл під назвою HelloWorld.sol
  2. Нижче наведено приклад смарт-контракту Hello World, який ми будемо використовувати для цього посібника. Скопіюйте вміст нижче у файл HelloWorld.sol.

Примітка: Обов'язково прочитайте коментарі, щоб зрозуміти, що робить цей контракт.

Це базовий смарт-контракт, який зберігає повідомлення під час створення. Його можна оновити, викликавши функцію update.

Крок 11: Підключення МетаМаск та Alchemy до вашого проєкту

Ми створили гаманець МетаМаск, акаунт Alchemy та написали наш смарт-контракт, тепер настав час об'єднати їх.

Кожна транзакція, надіслана з вашого гаманця, потребує підпису за допомогою вашого унікального приватного ключа. Щоб надати нашій програмі цей дозвіл, ми можемо безпечно зберегти наш приватний ключ у файлі середовища. Тут ми також збережемо ключ API для Alchemy.

Щоб дізнатися більше про надсилання транзакцій, перегляньте цей посібник з надсилання транзакцій за допомогою Web3.

Спочатку встановіть пакет dotenv у каталозі вашого проєкту:

npm install dotenv --save

Потім створіть файл .env у кореневому каталозі проєкту. Додайте до нього свій приватний ключ МетаМаск та URL-адресу HTTP API Alchemy.

Ваш файл середовища має називатися .env, інакше він не буде розпізнаний як файл середовища.

Не називайте його process.env, .env-custom або якось інакше.

Ваш .env має виглядати так:

API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key"
PRIVATE_KEY = "your-metamask-private-key"

Щоб фактично підключити їх до нашого коду, ми пошлемося на ці змінні в нашому файлі hardhat.config.js на кроці 13.

Крок 12: Встановлення Ethers.js

Ethers.js — це бібліотека, яка полегшує взаємодію та виконання запитів до Етеріум, обгортаючи стандартні методи JSON-RPC більш зручними для користувача методами.

Hardhat дозволяє нам інтегрувати плагіни (відкривається в новій вкладці) для додаткових інструментів та розширеної функціональності. Ми скористаємося плагіном Ethers (відкривається в новій вкладці) для розгортання контракту.

У каталозі вашого проєкту введіть:

npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0"

Крок 13: Оновлення hardhat.config.js

Наразі ми додали кілька залежностей та плагінів, тепер нам потрібно оновити hardhat.config.js, щоб наш проєкт знав про них усі.

Оновіть ваш hardhat.config.js, щоб він виглядав так:

Крок 14: Компіляція нашого контракту

Щоб переконатися, що все працює, давайте скомпілюємо наш контракт. Завдання compile є одним із вбудованих завдань Hardhat.

З командного рядка виконайте:

npx hardhat compile

Ви можете отримати попередження про SPDX license identifier not provided in source file, але не варто про це турбуватися — сподіваємося, все інше виглядає добре! Якщо ні, ви завжди можете написати в Discord Alchemy (відкривається в новій вкладці).

Крок 15: Написання нашого скрипта розгортання

Тепер, коли наш контракт написано, а файл конфігурації готовий до роботи, настав час написати скрипт розгортання нашого контракту.

Перейдіть до папки scripts/ і створіть новий файл під назвою deploy.js, додавши до нього такий вміст:

Hardhat чудово пояснює, що робить кожен із цих рядків коду, у своєму посібнику з контрактів (відкривається в новій вкладці), ми запозичили їхні пояснення тут.

const HelloWorld = await ethers.getContractFactory("HelloWorld")

ContractFactory в ethers.js — це абстракція, яка використовується для розгортання нових смарт-контрактів, тому HelloWorld тут є фабрикою (відкривається в новій вкладці) для екземплярів нашого контракту hello world. Під час використання плагіна hardhat-ethers ContractFactory та Contract екземпляри за замовчуванням підключаються до першого підписанта (власника).

const hello_world = await HelloWorld.deploy()

Виклик deploy() на ContractFactory розпочне розгортання та поверне Promise, який перетворюється на об'єкт Contract. Це об'єкт, який має метод для кожної з функцій нашого смарт-контракту.

Крок 16: Розгортання нашого контракту

Ми нарешті готові розгорнути наш смарт-контракт! Перейдіть до командного рядка та виконайте:

npx hardhat run scripts/deploy.js --network sepolia

Після цього ви побачите щось схоже на:

Contract deployed to address: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570

Будь ласка, збережіть цю адресу. Ми будемо використовувати її пізніше в посібнику.

Якщо ми перейдемо на Sepolia Etherscan (відкривається в новій вкладці) і знайдемо адресу нашого контракту, ми зможемо побачити, що його було успішно розгорнуто. Транзакція виглядатиме приблизно так:

Адреса From має збігатися з адресою вашого акаунту МетаМаск, а в адресі To буде вказано Contract Creation. Якщо ми натиснемо на транзакцію, то побачимо адресу нашого контракту в полі To.

Вітаємо! Ви щойно розгорнули смарт-контракт у тестовій мережі Етеріум.

Щоб зрозуміти, як це працює технічно, давайте перейдемо на вкладку Explorer на нашій панелі керування Alchemy (відкривається в новій вкладці). Якщо у вас є кілька застосунків Alchemy, обов'язково відфільтруйте їх за застосунком і виберіть Hello World.

Тут ви побачите кілька методів JSON-RPC, які Hardhat/Ethers виконали для нас внутрішньо, коли ми викликали функцію .deploy(). Два важливі методи тут — це eth_sendRawTransaction (відкривається в новій вкладці), який є запитом на запис нашого контракту в ланцюг Sepolia, і eth_getTransactionByHash (відкривається в новій вкладці), який є запитом на читання інформації про нашу транзакцію за заданим хешем. Щоб дізнатися більше про надсилання транзакцій, перегляньте наш посібник із надсилання транзакцій за допомогою Web3.

Частина 2: Взаємодія з вашим смарт-контрактом

Тепер, коли ми успішно розгорнули смарт-контракт у мережі Ґерлі, давайте дізнаємося, як з ним взаємодіяти.

Створення файлу interact.js

Це файл, у якому ми напишемо наш скрипт для взаємодії. Ми будемо використовувати бібліотеку Ethers.js, яку ви раніше встановили в Частині 1.

У папці scripts/ створіть новий файл з назвою interact.js та додайте наступний код:

// interact.js

const API_KEY = process.env.API_KEY
const PRIVATE_KEY = process.env.PRIVATE_KEY
const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS

Оновлення вашого файлу .env

Ми будемо використовувати нові змінні середовища, тому нам потрібно визначити їх у файлі .env, який ми створили раніше.

Нам потрібно буде додати визначення для нашого API_KEY від Alchemy та CONTRACT_ADDRESS, за якою був розгорнутий ваш смарт-контракт.

Ваш файл .env має виглядати приблизно так:

# .env

API_URL = "https://eth-goerli.alchemyapi.io/v2/<your-api-key>"
API_KEY = "<your-api-key>"
PRIVATE_KEY = "<your-metamask-private-key>"
CONTRACT_ADDRESS = "0x<your contract address>"

Отримання ABI вашого контракту

нашого контракту — це інтерфейс для взаємодії з нашим смарт-контрактом. Hardhat автоматично генерує ABI та зберігає його в HelloWorld.json. Щоб використовувати ABI, нам потрібно буде проаналізувати його вміст, додавши наступні рядки коду до нашого файлу interact.js:

// interact.js
const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")

Якщо ви хочете побачити ABI, ви можете вивести його в консоль:

console.log(JSON.stringify(contract.abi))

Щоб побачити ваш ABI, виведений у консоль, перейдіть до термінала та виконайте:

npx hardhat run scripts/interact.js

Створення екземпляра вашого контракту

Щоб взаємодіяти з нашим контрактом, нам потрібно створити екземпляр контракту в нашому коді. Щоб зробити це за допомогою Ethers.js, нам потрібно буде працювати з трьома концепціями:

  1. Провайдер (Провайдер) — провайдер вузла, який надає вам доступ для читання та запису до блокчейну
  2. Підписант (Підписант) — представляє акаунт Етеріуму, який може підписувати транзакції
  3. Контракт (Contract) — об'єкт Ethers.js, що представляє конкретний контракт, розгорнутий ончейн

Ми використаємо ABI контракту з попереднього кроку, щоб створити наш екземпляр контракту:

Дізнайтеся більше про провайдерів, підписантів та контракти в документації ethers.js (відкривається в новій вкладці).

Читання початкового повідомлення

Пам'ятаєте, коли ми розгортали наш контракт за допомогою initMessage = "Hello world!"? Тепер ми збираємося прочитати це повідомлення, збережене в нашому смарт-контракті, і вивести його в консоль.

У JavaScript асинхронні функції використовуються під час взаємодії з мережами. Щоб дізнатися більше про асинхронні функції, прочитайте цю статтю на Medium (відкривається в новій вкладці).

Використовуйте наведений нижче код, щоб викликати функцію message у нашому смарт-контракті та прочитати початкове повідомлення:

Після запуску файлу за допомогою npx hardhat run scripts/interact.js у терміналі ми повинні побачити таку відповідь:

The message is: Hello world!

Вітаємо! Ви щойно успішно прочитали дані смарт-контракту з блокчейну Етеріуму, так тримати!

Оновлення повідомлення

Замість того, щоб просто читати повідомлення, ми також можемо оновити повідомлення, збережене в нашому смарт-контракті, використовуючи функцію update! Досить круто, чи не так?

Щоб оновити повідомлення, ми можемо безпосередньо викликати функцію update на нашому створеному об'єкті Contract:

Зверніть увагу, що в рядку 11 ми викликаємо .wait() для повернутого об'єкта транзакції. Це гарантує, що наш скрипт дочекається, поки транзакція буде видобута в блокчейні, перш ніж вийти з функції. Якщо виклик .wait() не включено, скрипт може не побачити оновлене значення message у контракті.

Читання нового повідомлення

Ви можете повторити попередній крок, щоб прочитати оновлене значення message. Знайдіть хвилинку і спробуйте внести необхідні зміни, щоб вивести це нове значення!

Якщо вам потрібна підказка, ось як має виглядати ваш файл interact.js на цьому етапі:

Тепер просто запустіть скрипт, і ви зможете побачити старе повідомлення, статус оновлення та нове повідомлення, виведені у вашому терміналі!

npx hardhat run scripts/interact.js --network sepolia

The message is: Hello World!
Updating the message...
The new message is: This is the new message.

Під час виконання цього скрипта ви можете помітити, що крок Updating the message... займає деякий час перед завантаженням нового повідомлення. Це пов'язано з процесом майнінгу; якщо вам цікаво відстежувати транзакції під час їх майнінгу, відвідайте мемпул Alchemy (відкривається в новій вкладці), щоб побачити статус транзакції. Якщо транзакцію відхилено, також корисно перевірити Sepolia Etherscan (відкривається в новій вкладці) і знайти хеш вашої транзакції.

Частина 3: Опублікуйте свій смарт-контракт на Etherscan

Ви виконали всю важку роботу, щоб втілити свій смарт-контракт у життя; тепер настав час поділитися ним зі світом!

Верифікувавши свій смарт-контракт на Etherscan, будь-хто зможе переглядати ваш вихідний код і взаємодіяти з вашим смарт-контрактом. Почнімо!

Крок 1: Згенеруйте ключ API у своєму акаунті Etherscan

Ключ API Etherscan необхідний для підтвердження того, що ви є власником смарт-контракту, який намагаєтеся опублікувати.

Якщо у вас ще немає акаунта Etherscan, зареєструйтеся (відкривається в новій вкладці).

Після входу знайдіть своє ім'я користувача на панелі навігації, наведіть на нього курсор і виберіть кнопку My profile.

На сторінці вашого профілю ви побачите бічну панель навігації. На бічній панелі навігації виберіть API Keys. Далі натисніть кнопку «Add», щоб створити новий ключ API, назвіть свій застосунок hello-world і натисніть кнопку Create New API Key.

Ваш новий ключ API має з'явитися в таблиці ключів API. Скопіюйте ключ API в буфер обміну.

Далі нам потрібно додати ключ API Etherscan до нашого файлу .env.

Після його додавання ваш файл .env має виглядати так:

API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key"
PUBLIC_KEY = "your-public-account-address"
PRIVATE_KEY = "your-private-account-address"
CONTRACT_ADDRESS = "your-contract-address"
ETHERSCAN_API_KEY = "your-etherscan-key"

Смарт-контракти, розгорнуті за допомогою Hardhat

Встановіть hardhat-etherscan

Опублікувати ваш контракт на Etherscan за допомогою Hardhat дуже просто. Для початку вам потрібно буде встановити плагін hardhat-etherscan. hardhat-etherscan автоматично верифікує вихідний код смарт-контракту та ABI на Etherscan. Щоб додати його, у каталозі hello-world виконайте:

npm install --save-dev @nomiclabs/hardhat-etherscan

Після встановлення додайте наступний вираз у верхній частині вашого hardhat.config.js та додайте параметри конфігурації Etherscan:

Верифікуйте свій смарт-контракт на Etherscan

Переконайтеся, що всі файли збережено, а всі змінні .env налаштовано правильно.

Запустіть завдання verify, передавши адресу контракту та мережу, у якій його розгорнуто:

npx hardhat verify --network sepolia DEPLOYED_CONTRACT_ADDRESS 'Hello World!'

Переконайтеся, що DEPLOYED_CONTRACT_ADDRESS — це адреса вашого розгорнутого смарт-контракту в тестовій мережі Sepolia. Крім того, останній аргумент ('Hello World!') має бути тим самим рядковим значенням, яке використовувалося під час кроку розгортання в частині 1.

Якщо все пройде добре, ви побачите таке повідомлення у своєму терміналі:

Successfully submitted source code for contract
contracts/HelloWorld.sol:HelloWorld at 0xdeployed-contract-address
for verification on Etherscan. Waiting for verification result...


Successfully verified contract HelloWorld on Etherscan.
https://sepolia.etherscan.io/address/<contract-address>#contracts

Вітаємо! Код вашого смарт-контракту тепер на Etherscan!

Перегляньте свій смарт-контракт на Etherscan!

Перейшовши за посиланням, наданим у вашому терміналі, ви зможете побачити код свого смарт-контракту та ABI, опубліковані на Etherscan!

Ура — ви зробили це, чемпіоне! Тепер будь-хто може викликати ваш смарт-контракт або записувати в нього дані! З нетерпінням чекаємо на те, що ви створите далі!

Частина 4 — Інтеграція вашого смарт-контракту з фронтендом

До кінця цього посібника ви дізнаєтеся, як:

  • Підключити гаманець МетаМаск до вашого децентралізованого застосунку (dapp)
  • Зчитувати дані з вашого смарт-контракту за допомогою API Alchemy Web3 (відкривається в новій вкладці)
  • Підписувати транзакції Етеріуму за допомогою МетаМаск

Для цього dapp ми будемо використовувати React (відкривається в новій вкладці) як наш фронтенд-фреймворк; однак важливо зазначити, що ми не будемо витрачати багато часу на розбір його основ, оскільки здебільшого зосередимося на додаванні функціональності Web3 до нашого проєкту.

Як передумова, ви повинні мати розуміння React на рівні початківця. Якщо ні, ми рекомендуємо пройти офіційний посібник Вступ до React (відкривається в новій вкладці).

Клонування початкових файлів

Спочатку перейдіть до репозиторію hello-world-part-four на GitHub (відкривається в новій вкладці), щоб отримати початкові файли для цього проєкту, і клонуйте цей репозиторій на свій локальний комп'ютер.

Відкрийте клонований репозиторій локально. Зверніть увагу, що він містить дві папки: starter-files та completed.

  • starter-filesми будемо працювати в цій директорії, ми підключимо інтерфейс користувача до вашого гаманця Етеріуму та смарт-контракту, який ми опублікували на Etherscan у Частині 3.
  • completed містить повністю завершений посібник і має використовуватися лише як довідник, якщо ви застрягнете.

Далі відкрийте вашу копію starter-files у вашому улюбленому редакторі коду, а потім перейдіть до папки src.

Увесь код, який ми напишемо, буде знаходитися в папці src. Ми будемо редагувати компонент HelloWorld.js та файли JavaScript util/interact.js, щоб надати нашому проєкту функціональність Web3.

Огляд початкових файлів

Перш ніж почати писати код, давайте розглянемо, що надається нам у початкових файлах.

Запуск вашого проєкту React

Давайте почнемо із запуску проєкту React у нашому браузері. Краса React полягає в тому, що як тільки наш проєкт буде запущено в браузері, будь-які збережені нами зміни будуть оновлюватися в браузері в реальному часі.

Щоб запустити проєкт, перейдіть до кореневої директорії папки starter-files і виконайте npm install у вашому терміналі, щоб встановити залежності проєкту:

cd starter-files
npm install

Після завершення їх встановлення виконайте npm start у вашому терміналі:

npm start

Це має відкрити http://localhost:3000/ (відкривається в новій вкладці) у вашому браузері, де ви побачите фронтенд нашого проєкту. Він має складатися з одного поля (місце для оновлення повідомлення, що зберігається у вашому смарт-контракті), кнопки «Connect Wallet» (Підключити гаманець) та кнопки «Update» (Оновити).

Якщо ви спробуєте натиснути будь-яку з кнопок, ви помітите, що вони не працюють — це тому, що нам ще потрібно запрограмувати їхню функціональність.

Компонент HelloWorld.js

Давайте повернемося до папки src у нашому редакторі та відкриємо файл HelloWorld.js. Надзвичайно важливо, щоб ми розуміли все в цьому файлі, оскільки це основний компонент React, з яким ми будемо працювати.

У верхній частині цього файлу ви помітите кілька інструкцій імпорту, які необхідні для запуску нашого проєкту, включаючи бібліотеку React, хуки useEffect та useState, деякі елементи з ./util/interact.js (ми опишемо їх детальніше незабаром!) та логотип Alchemy.

Далі у нас є змінні стану, які ми будемо оновлювати після певних подій.

// HelloWorld.js

//Змінні стану
const [walletAddress, setWallet] = useState("")
const [status, setStatus] = useState("")
const [message, setMessage] = useState("No connection to the network.")
const [newMessage, setNewMessage] = useState("")

Ось що представляє кожна зі змінних:

  • walletAddress — рядок, який зберігає адресу гаманця користувача
  • status — рядок, який зберігає корисне повідомлення, що підказує користувачеві, як взаємодіяти з dapp
  • message — рядок, який зберігає поточне повідомлення в смарт-контракті
  • newMessage — рядок, який зберігає нове повідомлення, що буде записано в смарт-контракт

Після змінних стану ви побачите п'ять нереалізованих функцій: useEffect, addSmartContractListener, addWalletListener, connectWalletPressed та onUpdatePressed. Нижче ми пояснимо, що вони роблять:

  • useEffect (відкривається в новій вкладці) — це хук React, який викликається після рендерингу вашого компонента. Оскільки в нього передається порожній масив [] (див. рядок 4), він буде викликаний лише під час першого рендерингу компонента. Тут ми завантажимо поточне повідомлення, що зберігається в нашому смарт-контракті, викличемо слухачів нашого смарт-контракту та гаманця, а також оновимо наш інтерфейс користувача, щоб відобразити, чи вже підключено гаманець.
  • addSmartContractListener — ця функція налаштовує слухача, який буде стежити за подією UpdatedMessages нашого контракту HelloWorld і оновлювати наш інтерфейс користувача, коли повідомлення в нашому смарт-контракті змінюється.
  • addWalletListener — ця функція налаштовує слухача, який виявляє зміни в стані гаманця МетаМаск користувача, наприклад, коли користувач відключає свій гаманець або змінює адреси.
  • connectWalletPressed — ця функція буде викликана для підключення гаманця МетаМаск користувача до нашого dapp.
  • onUpdatePressed — ця функція буде викликана, коли користувач захоче оновити повідомлення, що зберігається в смарт-контракті.

Ближче до кінця цього файлу у нас є інтерфейс користувача нашого компонента.

Якщо ви уважно переглянете цей код, то помітите, де ми використовуємо наші різні змінні стану в нашому інтерфейсі користувача:

  • У рядках 6-12, якщо гаманець користувача підключено (тобто walletAddress.length > 0), ми відображаємо скорочену версію walletAddress користувача на кнопці з ідентифікатором "walletButton"; інакше там просто написано "Connect Wallet".
  • У рядку 17 ми відображаємо поточне повідомлення, що зберігається в смарт-контракті, яке зафіксовано в рядку message.
  • У рядках 23-26 ми використовуємо керований компонент (відкривається в новій вкладці) для оновлення нашої змінної стану newMessage, коли змінюється введення в текстовому полі.

Окрім наших змінних стану, ви також побачите, що функції connectWalletPressed та onUpdatePressed викликаються при натисканні кнопок з ідентифікаторами publishButton та walletButton відповідно.

Нарешті, давайте з'ясуємо, куди додається цей компонент HelloWorld.js.

Якщо ви перейдете до файлу App.js, який є основним компонентом у React і діє як контейнер для всіх інших компонентів, ви побачите, що наш компонент HelloWorld.js впроваджується в рядку 7.

І останнє, але не менш важливе: давайте перевіримо ще один наданий вам файл — файл interact.js.

Файл interact.js

Оскільки ми хочемо дотримуватися парадигми M-V-C (відкривається в новій вкладці), нам знадобиться окремий файл, який містить усі наші функції для управління логікою, даними та правилами нашого dapp, щоб потім мати можливість експортувати ці функції до нашого фронтенду (нашого компонента HelloWorld.js).

👆🏽Саме для цього і призначений наш файл interact.js!

Перейдіть до папки util у вашій директорії src, і ви помітите, що ми включили файл під назвою interact.js, який міститиме всі наші функції та змінні для взаємодії зі смарт-контрактом і гаманцем.

Ви помітите у верхній частині файлу, що ми закоментували об'єкт helloWorldContract. Пізніше в цьому посібнику ми розкоментуємо цей об'єкт і створимо екземпляр нашого смарт-контракту в цій змінній, яку потім експортуємо в наш компонент HelloWorld.js.

Чотири нереалізовані функції після нашого об'єкта helloWorldContract виконують наступне:

  • loadCurrentMessage — ця функція обробляє логіку завантаження поточного повідомлення, що зберігається в смарт-контракті. Вона зробить виклик читання до смарт-контракту Hello World за допомогою API Alchemy Web3 (відкривається в новій вкладці).
  • connectWallet — ця функція підключить МетаМаск користувача до нашого dapp.
  • getCurrentWalletConnected — ця функція перевірить, чи вже підключено акаунт Етеріуму до нашого dapp під час завантаження сторінки, і відповідно оновить наш інтерфейс користувача.
  • updateMessage — ця функція оновить повідомлення, що зберігається в смарт-контракті. Вона зробить виклик запису до смарт-контракту Hello World, тому гаманцю МетаМаск користувача доведеться підписати транзакцію Етеріуму, щоб оновити повідомлення.

Тепер, коли ми розуміємо, з чим працюємо, давайте з'ясуємо, як зчитувати дані з нашого смарт-контракту!

Крок 3: Зчитування з вашого смарт-контракту

Щоб зчитувати дані з вашого смарт-контракту, вам потрібно буде успішно налаштувати:

  • Підключення API до ланцюга Етеріуму
  • Завантажений екземпляр вашого смарт-контракту
  • Функцію для виклику функції вашого смарт-контракту
  • Слухача для відстеження оновлень, коли дані, які ви зчитуєте зі смарт-контракту, змінюються

Це може здатися великою кількістю кроків, але не хвилюйтеся! Ми крок за кроком покажемо вам, як виконати кожен із них! :)

Встановлення підключення API до ланцюга Етеріум

Пам'ятаєте, як у Частині 2 цього посібника ми використовували наш ключ Alchemy Web3 для зчитування з нашого смарт-контракту? Вам також знадобиться ключ Alchemy Web3 у вашому децентралізованому застосунку (dapp), щоб зчитувати дані з ланцюга.

Якщо у вас його ще немає, спочатку встановіть Alchemy Web3 (відкривається в новій вкладці), перейшовши до кореневого каталогу ваших starter-files і виконавши наступну команду у вашому терміналі:

npm install @alch/alchemy-web3

Alchemy Web3 (відкривається в новій вкладці) — це обгортка навколо Web3.js (відкривається в новій вкладці), яка надає розширені методи API та інші важливі переваги, щоб полегшити ваше життя як розробника Web3. Вона розроблена так, щоб вимагати мінімальної конфігурації, тому ви можете почати використовувати її у своєму застосунку відразу!

Потім встановіть пакет dotenv (відкривається в новій вкладці) у каталозі вашого проєкту, щоб ми мали безпечне місце для зберігання нашого ключа API після його отримання.

npm install dotenv --save

Для нашого dapp ми будемо використовувати наш ключ API Websockets замість нашого ключа API HTTP, оскільки це дозволить нам налаштувати слухача, який виявляє, коли повідомлення, що зберігається в смарт-контракті, змінюється.

Отримавши ключ API, створіть файл .env у вашому кореневому каталозі та додайте до нього вашу URL-адресу Alchemy Websockets. Після цього ваш файл .env має виглядати так:

REACT_APP_ALCHEMY_KEY = wss://eth-goerli.ws.alchemyapi.io/v2/<key>

Тепер ми готові налаштувати нашу кінцеву точку Alchemy Web3 у нашому dapp! Давайте повернемося до нашого interact.js, який знаходиться у папці util, і додамо наступний код у верхній частині файлу:

// interact.js

require("dotenv").config()
const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY
const { createAlchemyWeb3 } = require("@alch/alchemy-web3")
const web3 = createAlchemyWeb3(alchemyKey)

//export const helloWorldContract;

Вище ми спочатку імпортували ключ Alchemy з нашого файлу .env, а потім передали наш alchemyKey до createAlchemyWeb3, щоб встановити нашу кінцеву точку Alchemy Web3.

Коли ця кінцева точка готова, настав час завантажити наш смарт-контракт!

Завантаження вашого смарт-контракту Hello World

Щоб завантажити ваш смарт-контракт Hello World, вам знадобиться адреса контракту та його ABI, які можна знайти на Etherscan, якщо ви завершили Частину 3 цього посібника.

Як отримати ABI вашого контракту з Etherscan

Якщо ви пропустили Частину 3 цього посібника, спочатку розгорніть та верифікуйте власний контракт HelloWorld. Потім відкрийте сторінку вашого контракту на Sepolia Etherscan (відкривається в новій вкладці), щоб скопіювати його ABI.

ABI контракту необхідний для вказівки того, яку функцію викликатиме контракт, а також для забезпечення того, що функція повертатиме дані в очікуваному вами форматі. Після того, як ми скопіювали ABI нашого контракту, давайте збережемо його як файл JSON під назвою contract-abi.json у вашому каталозі src.

Ваш contract-abi.json має зберігатися у вашій папці src.

Озброївшись адресою нашого контракту, ABI та кінцевою точкою Alchemy Web3, ми можемо використати метод контракту (відкривається в новій вкладці), щоб завантажити екземпляр нашого смарт-контракту. Імпортуйте ABI вашого контракту у файл interact.js та додайте адресу вашого контракту.

// interact.js

const contractABI = require("../contract-abi.json")
// Використовуйте адресу вашого контракту тут
const contractAddress = "0x..."

Тепер ми нарешті можемо розкоментувати нашу змінну helloWorldContract і завантажити смарт-контракт за допомогою нашої кінцевої точки AlchemyWeb3:

// interact.js
export const helloWorldContract = new web3.eth.Contract(
  contractABI,
  contractAddress
)

Підсумовуючи, перші 12 рядків вашого interact.js тепер мають виглядати так:

Тепер, коли наш контракт завантажено, ми можемо реалізувати нашу функцію loadCurrentMessage!

Реалізація loadCurrentMessage у вашому файлі interact.js

Ця функція надзвичайно проста. Ми збираємося зробити простий асинхронний виклик Web3 для зчитування з нашого контракту. Наша функція поверне повідомлення, що зберігається в смарт-контракті:

Оновіть loadCurrentMessage у вашому файлі interact.js на наступне:

// interact.js

export const loadCurrentMessage = async () => {
  const message = await helloWorldContract.methods.message().call()
  return message
}

Оскільки ми хочемо відобразити цей смарт-контракт у нашому інтерфейсі користувача, давайте оновимо функцію useEffect у нашому компоненті HelloWorld.js на наступне:

// HelloWorld.js

//викликається лише один раз
useEffect(async () => {
  const message = await loadCurrentMessage()
  setMessage(message)
}, [])

Зверніть увагу, ми хочемо, щоб наша loadCurrentMessage викликалася лише один раз під час першого рендерингу компонента. Незабаром ми реалізуємо addSmartContractListener для автоматичного оновлення інтерфейсу користувача після зміни повідомлення в смарт-контракті.

Перш ніж ми зануримося в нашого слухача, давайте перевіримо, що ми маємо на даний момент! Збережіть ваші файли HelloWorld.js та interact.js, а потім перейдіть на http://localhost:3000/ (відкривається в новій вкладці)

Ви помітите, що поточне повідомлення більше не говорить «No connection to the network» (Немає підключення до мережі). Натомість воно відображає повідомлення, що зберігається в смарт-контракті. Круто!

Ваш інтерфейс користувача тепер має відображати повідомлення, що зберігається в смарт-контракті

Тепер, говорячи про цього слухача...

Реалізація addSmartContractListener

Якщо ви згадаєте файл HelloWorld.sol, який ми написали в Частині 1 цієї серії посібників, ви пригадаєте, що існує подія смарт-контракту під назвою UpdatedMessages, яка генерується після виклику функції update нашого смарт-контракту (див. рядки 9 і 27):

Події смарт-контракту — це спосіб для вашого контракту повідомити вашому фронтенд-застосунку, що щось сталося (тобто відбулася подія) у блокчейні, який може «слухати» певні події та вживати заходів, коли вони відбуваються.

Функція addSmartContractListener буде спеціально слухати подію UpdatedMessages нашого смарт-контракту Hello World і оновлювати наш інтерфейс користувача для відображення нового повідомлення.

Змініть addSmartContractListener на наступне:

Давайте розберемо, що відбувається, коли слухач виявляє подію:

  • Якщо під час генерації події виникає помилка, це буде відображено в інтерфейсі користувача через нашу змінну стану status.
  • В іншому випадку ми використаємо повернутий об'єкт data. data.returnValues — це масив з індексацією від нуля, де перший елемент у масиві зберігає попереднє повідомлення, а другий елемент зберігає оновлене. Загалом, у разі успішної події ми встановимо наш рядок message на оновлене повідомлення, очистимо рядок newMessage та оновимо нашу змінну стану status, щоб відобразити, що нове повідомлення було опубліковано в нашому смарт-контракті.

Нарешті, давайте викличемо нашого слухача в нашій функції useEffect, щоб він ініціалізувався під час першого рендерингу компонента HelloWorld.js. Загалом, ваша функція useEffect має виглядати так:

// HelloWorld.js

useEffect(async () => {
  const message = await loadCurrentMessage()
  setMessage(message)
  addSmartContractListener()
}, [])

Тепер, коли ми можемо зчитувати дані з нашого смарт-контракту, було б чудово з'ясувати, як також записувати в нього! Однак, щоб записувати в наш dapp, ми повинні спочатку підключити до нього гаманець Етеріуму.

Отже, далі ми займемося налаштуванням нашого гаманця Етеріуму (МетаМаск), а потім підключенням його до нашого dapp!

Крок 4: Налаштування вашого гаманця Етеріуму

Щоб записати будь-що в ланцюг Етеріуму, користувачі повинні підписувати транзакції за допомогою приватних ключів свого віртуального гаманця. Для цього посібника ми будемо використовувати МетаМаск (відкривається в новій вкладці), віртуальний гаманець у браузері, який використовується для управління адресою вашого акаунта Етеріуму, оскільки він робить підписання транзакцій надзвичайно простим для кінцевого користувача.

Якщо ви хочете дізнатися більше про те, як працюють транзакції в Етеріумі, перегляньте цю сторінку від Ethereum Foundation.

Завантаження МетаМаск

Ви можете безкоштовно завантажити та створити акаунт МетаМаск тут (відкривається в новій вкладці). Під час створення акаунта, або якщо він у вас уже є, обов'язково перемкніться на тестову мережу Sepolia у верхньому правому куті (щоб ми не мали справи з реальними грошима).

Додавання етеру з крана

Щоб підписати транзакцію в блокчейні Етеріум, нам знадобиться трохи несправжнього ETH. Щоб отримати ETH, ви можете перейти до крана Sepolia, вказаного на сторінці тестових мереж, і ввести адресу свого акаунту Sepolia. Незабаром після цього ви побачите ETH у своєму акаунті МетаМаск!

Перевірте свій баланс

Щоб ще раз переконатися, що наш баланс на місці, зробімо запит eth_getBalance (відкривається в новій вкладці) за допомогою інструмента пісочниці Alchemy (відкривається в новій вкладці). Це поверне кількість ETH у нашому гаманці. Після того, як ви введете адресу свого акаунту МетаМаск і натиснете «Send Request» (Надіслати запит), ви побачите таку відповідь:

{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}

ПРИМІТКА: Цей результат вказано у wei, а не в ETH. Wei використовується як найменша одиниця етеру. Конвертація з wei в ETH така: 1 ETH = 10¹⁸ wei. Отже, якщо ми переведемо 0xde0b6b3a7640000 у десяткову систему, ми отримаємо 1*10¹⁸, що дорівнює 1 ETH.

Хух! Усі наші несправжні гроші на місці! 🤑

Крок 5: Підключення МетаМаск до вашого інтерфейсу користувача

Тепер, коли наш гаманець МетаМаск налаштовано, давайте підключимо до нього наш dapp!

Функція connectWallet

У нашому файлі interact.js давайте реалізуємо функцію connectWallet, яку ми потім зможемо викликати в нашому компоненті HelloWorld.js.

Давайте змінимо connectWallet на наступне:

Отже, що саме робить цей гігантський блок коду?

Ну, по-перше, він перевіряє, чи увімкнено window.ethereum у вашому браузері.

window.ethereum — це глобальний API, який впроваджується МетаМаск та іншими провайдерами гаманців, що дозволяє вебсайтам запитувати акаунти Етеріуму користувачів. У разі схвалення він може зчитувати дані з блокчейнів, до яких підключений користувач, і пропонувати користувачеві підписувати повідомлення та транзакції. Перегляньте документацію МетаМаск (відкривається в новій вкладці) для отримання додаткової інформації!

Якщо window.ethereum не присутній, це означає, що МетаМаск не встановлено. Це призводить до повернення об'єкта JSON, де повернута address є порожнім рядком, а об'єкт JSX status повідомляє, що користувач повинен встановити МетаМаск.

Тепер, якщо window.ethereum присутній, тоді починається найцікавіше.

Використовуючи блок try/catch, ми спробуємо підключитися до МетаМаск, викликавши window.ethereum.request({ method: "eth_requestAccounts" }); (відкривається в новій вкладці). Виклик цієї функції відкриє МетаМаск у браузері, після чого користувачеві буде запропоновано підключити свій гаманець до вашого dapp.

  • Якщо користувач вирішить підключитися, method: "eth_requestAccounts" поверне масив, який містить усі адреси акаунтів користувача, підключених до dapp. Загалом, наша функція connectWallet поверне об'єкт JSON, який містить першу address у цьому масиві (див. рядок 9) та повідомлення status, яке пропонує користувачеві написати повідомлення до смарт-контракту.
  • Якщо користувач відхиляє підключення, тоді об'єкт JSON міститиме порожній рядок для повернутої address та повідомлення status, яке відображає, що користувач відхилив підключення.

Тепер, коли ми написали цю функцію connectWallet, наступним кроком є її виклик у нашому компоненті HelloWorld.js.

Додавання функції connectWallet до вашого компонента інтерфейсу користувача HelloWorld.js

Перейдіть до функції connectWalletPressed у HelloWorld.js та оновіть її на наступне:

// HelloWorld.js

const connectWalletPressed = async () => {
  const walletResponse = await connectWallet()
  setStatus(walletResponse.status)
  setWallet(walletResponse.address)
}

Помітили, як більша частина нашої функціональності абстрагована від нашого компонента HelloWorld.js у файлі interact.js? Це зроблено для того, щоб ми дотримувалися парадигми M-V-C!

У connectWalletPressed ми просто робимо виклик await до нашої імпортованої функції connectWallet і, використовуючи її відповідь, оновлюємо наші змінні status та walletAddress через їхні хуки стану.

Тепер давайте збережемо обидва файли (HelloWorld.js та interact.js) і протестуємо наш інтерфейс користувача на даний момент.

Відкрийте свій браузер на сторінці http://localhost:3000/ (відкривається в новій вкладці) і натисніть кнопку «Connect Wallet» у верхньому правому куті сторінки.

Якщо у вас встановлено МетаМаск, вам буде запропоновано підключити свій гаманець до вашого dapp. Прийміть запрошення на підключення.

Ви повинні побачити, що кнопка гаманця тепер відображає, що вашу адресу підключено! Такккк 🔥

Далі спробуйте оновити сторінку... це дивно. Наша кнопка гаманця пропонує нам підключити МетаМаск, хоча він уже підключений...

Однак не бійтеся! Ми легко можемо вирішити це, реалізувавши getCurrentWalletConnected, яка перевірить, чи адреса вже підключена до нашого dapp, і відповідно оновить наш інтерфейс користувача!

Функція getCurrentWalletConnected

Оновіть вашу функцію getCurrentWalletConnected у файлі interact.js на наступне:

Цей код дуже схожий на функцію connectWallet, яку ми щойно написали на попередньому кроці.

Головна відмінність полягає в тому, що замість виклику методу eth_requestAccounts, який відкриває МетаМаск для підключення гаманця користувачем, тут ми викликаємо метод eth_accounts, який просто повертає масив, що містить адреси МетаМаск, наразі підключені до нашого dapp.

Щоб побачити цю функцію в дії, давайте викличемо її в нашій функції useEffect нашого компонента HelloWorld.js:

Зверніть увагу, ми використовуємо відповідь нашого виклику до getCurrentWalletConnected для оновлення наших змінних стану walletAddress та status.

Тепер, коли ви додали цей код, давайте спробуємо оновити вікно нашого браузера.

Чудовоооо! Кнопка має повідомляти, що ви підключені, і показувати попередній перегляд адреси вашого підключеного гаманця — навіть після оновлення!

Реалізація addWalletListener

Останнім кроком у налаштуванні гаманця нашого dapp є реалізація слухача гаманця, щоб наш інтерфейс користувача оновлювався, коли стан нашого гаманця змінюється, наприклад, коли користувач відключається або змінює акаунти.

У вашому файлі HelloWorld.js змініть вашу функцію addWalletListener на наступне:

Б'юся об заклад, вам навіть не потрібна наша допомога, щоб зрозуміти, що тут відбувається на цьому етапі, але для повноти картини давайте швидко розберемо це:

  • По-перше, наша функція перевіряє, чи увімкнено window.ethereum (тобто чи встановлено МетаМаск).
    • Якщо ні, ми просто встановлюємо нашу змінну стану status на рядок JSX, який пропонує користувачеві встановити МетаМаск.
    • Якщо він увімкнений, ми налаштовуємо слухача window.ethereum.on("accountsChanged") у рядку 3, який відстежує зміни стану в гаманці МетаМаск, що включають підключення користувачем додаткового акаунта до dapp, зміну акаунтів або відключення акаунта. Якщо підключено принаймні один акаунт, змінна стану walletAddress оновлюється як перший акаунт у масиві accounts, повернутому слухачем. Інакше walletAddress встановлюється як порожній рядок.

І останнє, але не менш важливе: ми повинні викликати її в нашій функції useEffect:

І це все! Ми успішно завершили програмування всієї функціональності нашого гаманця! Тепер переходимо до нашого останнього завдання: оновлення повідомлення, що зберігається в нашому смарт-контракті!

Крок 6: Реалізація функції updateMessage

Гаразд, друзі, ми вийшли на фінішну пряму! У updateMessage вашого файлу interact.js ми збираємося зробити наступне:

  1. Переконатися, що повідомлення, яке ми хочемо опублікувати в нашому смарт-контракті, є дійсним
  2. Підписати нашу транзакцію за допомогою МетаМаск
  3. Викликати цю функцію з нашого фронтенд-компонента HelloWorld.js

Це не займе багато часу; давайте закінчимо цей dapp!

Обробка помилок введення

Звісно, має сенс мати певну обробку помилок введення на початку функції.

Ми хочемо, щоб наша функція поверталася достроково, якщо розширення МетаМаск не встановлено, гаманець не підключено (тобто передана address є порожнім рядком) або message є порожнім рядком. Давайте додамо наступну обробку помилок до updateMessage:

Тепер, коли є належна обробка помилок введення, настав час підписати транзакцію через МетаМаск!

Підписання нашої транзакції

Якщо ви вже знайомі з традиційними транзакціями Етеріуму у Web3, код, який ми напишемо далі, буде вам дуже знайомим. Нижче вашого коду обробки помилок введення додайте наступне до updateMessage:

Давайте розберемо, що відбувається. Спочатку ми налаштовуємо параметри нашої транзакції, де:

  • to вказує адресу одержувача (наш смарт-контракт)
  • from вказує підписанта транзакції, змінну address, яку ми передали в нашу функцію
  • data містить виклик методу update нашого смарт-контракту Hello World, отримуючи нашу рядкову змінну message як вхідні дані

Потім ми робимо виклик await, window.ethereum.request, де ми просимо МетаМаск підписати транзакцію. Зверніть увагу, у рядках 11 і 12 ми вказуємо наш метод eth, eth_sendTransaction, і передаємо наші transactionParameters.

На цьому етапі МетаМаск відкриється в браузері та запропонує користувачеві підписати або відхилити транзакцію.

  • Якщо транзакція успішна, функція поверне об'єкт JSON, де рядок JSX status пропонує користувачеві перевірити Etherscan для отримання додаткової інформації про свою транзакцію.
  • Якщо транзакція не вдається, функція поверне об'єкт JSON, де рядок status передає повідомлення про помилку.

Загалом, наша функція updateMessage має виглядати так:

І останнє, але не менш важливе: нам потрібно підключити нашу функцію updateMessage до нашого компонента HelloWorld.js.

Підключення updateMessage до фронтенду HelloWorld.js

Наша функція onUpdatePressed має зробити виклик await до імпортованої функції updateMessage та змінити змінну стану status, щоб відобразити, чи була наша транзакція успішною, чи ні:

// HelloWorld.js

const onUpdatePressed = async () => {
  const { status } = await updateMessage(walletAddress, newMessage)
  setStatus(status)
}

Це надзвичайно чисто і просто. І знаєте що... ВАШ DAPP ЗАВЕРШЕНО!!!

Сміливо тестуйте кнопку Update!

Створення власного кастомного dapp

Ураааа, ви дійшли до кінця посібника! Підсумовуючи, ви дізналися, як:

  • Підключити гаманець МетаМаск до вашого проєкту dapp
  • Зчитувати дані з вашого смарт-контракту за допомогою API Alchemy Web3 (відкривається в новій вкладці)
  • Підписувати транзакції Етеріуму за допомогою МетаМаск

Тепер ви повністю готові застосувати навички з цього посібника для створення власного кастомного проєкту dapp! Як завжди, якщо у вас виникнуть запитання, не соромтеся звертатися до нас за допомогою в Discord Alchemy (відкривається в новій вкладці). 🧙‍♂️

Після завершення цього посібника повідомте нам про свої враження або залиште відгук, позначивши нас у Twitter @alchemyplatform (відкривається в новій вкладці)!