Przejdź do głównej zawartości

Inteligentny kontrakt „Witaj świecie” dla początkujących – Fullstack

Solidity
Hardhat
Alchemy
smart kontrakty
wdrażanie
eksplorator bloków
frontend
transakcje
Początkujący
nstrike2
25 października 2021
40 minuta czytania

Ten przewodnik jest dla Ciebie, jeśli jesteś nowy w tworzeniu blockchaina i nie wiesz, od czego zacząć lub jak wdrażać i wchodzić w interakcję z inteligentnymi kontraktami. Przeprowadzimy Cię przez proces tworzenia i wdrażania prostego inteligentnego kontraktu w sieci testowej Goerli przy użyciu MetaMask (opens in a new tab), Solidity (opens in a new tab), Hardhat (opens in a new tab) i Alchemy (opens in a new tab).

Do ukończenia tego samouczka potrzebne będzie konto Alchemy. Zarejestruj się, aby założyć darmowe konto (opens in a new tab).

Jeśli masz jakieś pytania, skontaktuj się z nami na Discordzie Alchemy (opens in a new tab)!

Część 1 – Utwórz i wdróż swój inteligentny kontrakt za pomocą Hardhat

Połącz się z siecią Ethereum

Istnieje wiele sposobów na wysyłanie żądań do łańcucha Ethereum. Dla uproszczenia, użyjemy darmowego konta na Alchemy, platformie deweloperskiej i interfejsie API blockchaina, które pozwalają nam komunikować się z łańcuchem Ethereum bez konieczności samodzielnego uruchamiania węzła. Alchemy posiada również narzędzia deweloperskie do monitorowania i analityki. Skorzystamy z nich w tym samouczku, aby zrozumieć, co dzieje się pod maską podczas wdrażania naszego inteligentnego kontraktu.

Utwórz swoją aplikację i klucz API

Po utworzeniu konta Alchemy, można wygenerować klucz API, tworząc aplikację. Umożliwi to wysyłanie żądań do sieci testowej Goerli. Jeśli nie znasz sieci testowych, możesz przeczytać przewodnik Alchemy dotyczący wyboru sieci (opens in a new tab).

Na pulpicie nawigacyjnym Alchemy znajdź menu rozwijane Aplikacje w pasku nawigacyjnym i kliknij Utwórz aplikację.

Utwórz aplikację Hello world

Nadaj swojej aplikacji nazwę „Hello World” i wpisz krótki opis. Wybierz Staging jako środowisko i Goerli jako sieć.

widok tworzenia aplikacji hello world

Uwaga: upewnij się, że wybrałeś Goerli, w przeciwnym razie ten samouczek nie zadziała.

Kliknij Utwórz aplikację. Twoja aplikacja pojawi się w poniższej tabeli.

Utwórz konto Ethereum

Aby wysyłać i odbierać transakcje, potrzebujesz konta Ethereum. Użyjemy MetaMask, wirtualnego portfela w przeglądarce, który pozwala użytkownikom zarządzać adresem konta Ethereum.

Możesz pobrać i utworzyć konto MetaMask za darmo tutaj (opens in a new tab). Podczas tworzenia konta, lub jeśli już je posiadasz, upewnij się, że przełączyłeś się na „Sieć testową Goerli” w prawym górnym rogu (aby nie mieć do czynienia z prawdziwymi pieniędzmi).

Krok 4: Dodaj ether z Faucet

Aby wdrożyć swój inteligentny kontrakt w sieci testowej, będziesz potrzebować trochę fałszywych ETH. Aby uzyskać ETH w sieci Goerli, przejdź do Faucet Goerli i wprowadź adres swojego konta Goerli. Należy pamiętać, że krany Goerli mogą być ostatnio nieco zawodne - sprawdź stronę sieci testowych, aby uzyskać listę opcji do wypróbowania:

Uwaga: ze względu na przeciążenie sieci może to trochę potrwać.

Krok 5: Sprawdź swoje saldo

Aby dwukrotnie sprawdzić, czy ETH znajduje się w Twoim portfelu, wykonaj żądanie eth_getBalance (opens in a new tab) za pomocą narzędzia kompozytora Alchemy (opens in a new tab). Zwróci to ilość ETH w naszym portfelu. Aby dowiedzieć się więcej, sprawdź krótki samouczek Alchemy na temat korzystania z narzędzia kompozytora (opens in a new tab).

Wprowadź swój adres konta MetaMask i kliknij Wyślij żądanie. Zobaczysz odpowiedź, która wygląda jak poniższy fragment kodu.

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

Uwaga: Ten wynik jest w wei, nie w ETH. Wei jest używane jako najmniejsza jednostka etheru.

Uff! Wszystkie nasze fałszywe pieniądze są na miejscu.

Krok 6: Zainicjuj nasz projekt

Najpierw musimy utworzyć folder dla naszego projektu. Przejdź do wiersza poleceń i wprowadź następujące informacje.

1mkdir hello-world
2cd hello-world

Teraz, gdy jesteśmy w folderze naszego projektu, użyjemy npm init, aby zainicjować projekt.

Jeśli nie masz jeszcze zainstalowanego npm, postępuj zgodnie z tymi instrukcjami, aby zainstalować Node.js i npm (opens in a new tab).

Dla celów tego samouczka nie ma znaczenia, jak odpowiesz na pytania inicjujące. Oto, jak zrobiliśmy to dla odniesienia:

1package name: (hello-world)
2version: (1.0.0)
3description: hello world smart contract
4entry point: (index.js)
5test command:
6git repository:
7keywords:
8author:
9license: (ISC)
10
11About to write to /Users/.../.../.../hello-world/package.json:
12
13{
14 "name": "hello-world",
15 "version": "1.0.0",
16 "description": "hello world smart contract",
17 "main": "index.js",
18 "scripts": {
19 "test": "echo \"Error: no test specified\" && exit 1"
20 },
21 "author": "",
22 "license": "ISC"
23}
Pokaż wszystko

Zatwierdź plik package.json i gotowe!

Krok 7: Pobierz Hardhat

Hardhat to środowisko programistyczne do kompilacji, wdrażania, testowania i debugowania oprogramowania Ethereum. Pomaga deweloperom w tworzeniu inteligentnych kontraktów i dapek lokalnie przed wdrożeniem ich na żywym łańcuchu.

W naszym projekcie hello-world uruchom:

1npm install --save-dev hardhat

Sprawdź tę stronę, aby uzyskać więcej szczegółów na temat instrukcji instalacji (opens in a new tab).

Krok 8: Utwórz projekt Hardhat

W naszym folderze projektu hello-world uruchom:

1npx hardhat

Powinieneś wtedy zobaczyć wiadomość powitalną i opcję wyboru tego, co chcesz zrobić. Wybierz „utwórz pusty hardhat.config.js”:

1888 888 888 888 888
2888 888 888 888 888
3888 888 888 888 888
48888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888
5888 888 "88b 888P" d88" 888 888 "88b "88b 888
6888 888 .d888888 888 888 888 888 888 .d888888 888
7888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.
8888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888
9
10👷 Witamy w Hardhat v2.0.11 👷‍
11
12Co chcesz zrobić? …
13Utwórz przykładowy projekt
14❯ Utwórz pusty plik hardhat.config.js
15Zamknij
Pokaż wszystko

Spowoduje to wygenerowanie pliku hardhat.config.js w projekcie. Użyjemy tego później w samouczku, aby określić konfigurację naszego projektu.

Krok 9: Dodaj foldery projektu

Aby utrzymać porządek w projekcie, utwórzmy dwa nowe foldery. W wierszu poleceń przejdź do katalogu głównego projektu hello-world i wpisz:

1mkdir contracts
2mkdir scripts
  • w contracts/ będziemy przechowywać plik z kodem naszego inteligentnego kontraktu hello world
  • w scripts/ będziemy przechowywać skrypty do wdrażania naszego kontraktu i interakcji z nim

Krok 10: Napisz nasz kontrakt

Możesz zadać sobie pytanie, kiedy napiszemy kod? Nadszedł czas!

Otwórz projekt hello-world w swoim ulubionym edytorze. Inteligentne kontrakty najczęściej pisane są w Solidity, którego użyjemy do napisania naszego inteligentnego kontraktu.

  1. Przejdź do folderu contracts i utwórz nowy plik o nazwie HelloWorld.sol
  2. Poniżej znajduje się przykładowy inteligentny kontrakt Witaj Świecie, którego będziemy używać w tym samouczku. Skopiuj poniższą zawartość do pliku HelloWorld.sol.

Uwaga: Pamiętaj, aby przeczytać komentarze, aby zrozumieć, co robi ten kontrakt.

1// Określa wersję Solidity, używając semantycznego wersjonowania.
2// Dowiedz się więcej: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
3pragma solidity >=0.7.3;
4
5// Definiuje kontrakt o nazwie `HelloWorld`.
6// Kontrakt jest zbiorem funkcji i danych (jego stanu). Po wdrożeniu kontrakt znajduje się pod określonym adresem w blockchainie Ethereum. Dowiedz się więcej: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
7contract HelloWorld {
8
9 // Emitowane, gdy wywoływana jest funkcja aktualizacji
10 // Zdarzenia inteligentnych kontraktów to sposób, w jaki kontrakt komunikuje, że coś wydarzyło się na blockchainie do front-endu aplikacji, który może „nasłuchiwać” określonych zdarzeń i podejmować działania, gdy one wystąpią.
11 event UpdatedMessages(string oldStr, string newStr);
12
13 // Deklaruje zmienną stanu `message` typu `string`.
14 // Zmienne stanu to zmienne, których wartości są trwale przechowywane w pamięci kontraktu. Słowo kluczowe `public` udostępnia zmienne spoza kontraktu i tworzy funkcję, którą inne kontrakty lub klienci mogą wywołać w celu uzyskania dostępu do wartości.
15 string public message;
16
17 // Podobnie jak w wielu językach obiektowych opartych na klasach, konstruktor jest specjalną funkcją, która jest wykonywana tylko podczas tworzenia kontraktu.
18 // Konstruktory służą do inicjalizacji danych kontraktu. Dowiedz się więcej: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
19 constructor(string memory initMessage) {
20
21 // Akceptuje argument ciągu znaków `initMessage` i ustawia wartość w zmiennej pamięci kontraktu `message`).
22 message = initMessage;
23 }
24
25 // Funkcja publiczna, która akceptuje argument w postaci ciągu znaków i aktualizuje zmienną pamięci masowej `message`.
26 function update(string memory newMessage) public {
27 string memory oldMsg = message;
28 message = newMessage;
29 emit UpdatedMessages(oldMsg, newMessage);
30 }
31}
Pokaż wszystko

Jest to podstawowy inteligentny kontrakt, który przechowuje wiadomość po utworzeniu. Można go zaktualizować, wywołując funkcję update.

Krok 11: Podłącz MetaMask i Alchemy do swojego projektu

Stworzyliśmy portfel MetaMask, konto Alchemy i napisaliśmy nasz inteligentny kontrakt, teraz nadszedł czas, aby połączyć te trzy elementy.

Każda transakcja wysłana z Twojego portfela wymaga podpisu za pomocą Twojego unikalnego klucza prywatnego. Aby zapewnić naszemu programowi to uprawnienie, możemy bezpiecznie przechowywać nasz klucz prywatny w pliku środowiskowym. Będziemy tutaj również przechowywać klucz API dla Alchemy.

Aby dowiedzieć się więcej o wysyłaniu transakcji, sprawdź ten samouczek (opens in a new tab) na temat wysyłania transakcji za pomocą web3.

Najpierw zainstaluj pakiet dotenv w katalogu swojego projektu:

1npm install dotenv --save

Następnie utwórz plik .env w głównym katalogu projektu. Dodaj do niego swój klucz prywatny MetaMask i adres URL HTTP Alchemy API.

Twój plik środowiskowy musi mieć nazwę .env, w przeciwnym razie nie zostanie rozpoznany jako plik środowiskowy.

Nie nazywaj go process.env lub .env-custom ani w żaden inny sposób.

Twój plik .env powinien wyglądać następująco:

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

Aby faktycznie połączyć je z naszym kodem, odwołamy się do tych zmiennych w naszym pliku hardhat.config.js w kroku 13.

Krok 12: Zainstaluj Ethers.js

Ethers.js to biblioteka, która ułatwia interakcję i wysyłanie żądań do Ethereum poprzez opakowanie standardowych metod JSON-RPC (opens in a new tab) w bardziej przyjazne dla użytkownika metody.

Hardhat pozwala nam na integrację wtyczek (opens in a new tab) w celu uzyskania dodatkowych narzędzi i rozszerzonej funkcjonalności. Skorzystamy z wtyczki Ethers (opens in a new tab) do wdrażania kontraktów.

W katalogu projektu wpisz:

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

Krok 13: Zaktualizuj hardhat.config.js

Do tej pory dodaliśmy kilka zależności i wtyczek, teraz musimy zaktualizować hardhat.config.js, aby nasz projekt wiedział o wszystkich.

Zaktualizuj swój hardhat.config.js, aby wyglądał następująco:

1/**
2 * @type import('hardhat/config').HardhatUserConfig
3 */
4
5require("dotenv").config()
6require("@nomiclabs/hardhat-ethers")
7
8const { API_URL, PRIVATE_KEY } = process.env
9
10module.exports = {
11 solidity: "0.7.3",
12 defaultNetwork: "goerli",
13 networks: {
14 hardhat: {},
15 goerli: {
16 url: API_URL,
17 accounts: [`0x${PRIVATE_KEY}`],
18 },
19 },
20}
Pokaż wszystko

Krok 14: Skompiluj nasz kontrakt

Aby upewnić się, że wszystko do tej pory działa, skompilujmy nasz kontrakt. Zadanie compile jest jednym z wbudowanych zadań hardhat.

Z wiersza poleceń uruchom:

npx hardhat compile

Możesz otrzymać ostrzeżenie o SPDX license identifier not provided in source file, ale nie musisz się tym martwić - miejmy nadzieję, że wszystko inne wygląda dobrze! Jeśli nie, zawsze możesz napisać wiadomość na discordzie Alchemy (opens in a new tab).

Krok 15: Napisz nasz skrypt wdrożeniowy

Teraz, gdy nasz kontrakt jest napisany, a nasz plik konfiguracyjny jest gotowy, nadszedł czas, aby napisać nasz skrypt wdrażający kontrakt.

Przejdź do folderu scripts/ i utwórz nowy plik o nazwie deploy.js, dodając do niego następującą zawartość:

1async function main() {
2 const HelloWorld = await ethers.getContractFactory("HelloWorld")
3
4 // Rozpocznij wdrażanie, zwracając obietnicę, która rozwiązuje się do obiektu kontraktu
5 const hello_world = await HelloWorld.deploy("Hello World!")
6 console.log("Contract deployed to address:", hello_world.address)
7}
8
9main()
10 .then(() => process.exit(0))
11 .catch((error) => {
12 console.error(error)
13 process.exit(1)
14 })
Pokaż wszystko

Hardhat wykonuje niesamowitą robotę, wyjaśniając, co robi każda z tych linii kodu w swoim samouczku dotyczącym kontraktów (opens in a new tab), a my przyjęliśmy ich wyjaśnienia tutaj.

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

ContractFactory w ethers.js jest abstrakcją używaną do wdrażania nowych inteligentnych kontraktów, więc HelloWorld jest tutaj fabryką (opens in a new tab) dla instancji naszego kontraktu witaj świecie. Podczas korzystania z wtyczki hardhat-ethers, instancje ContractFactory i Contract są domyślnie połączone z pierwszym sygnatariuszem (właścicielem).

1const hello_world = await HelloWorld.deploy()

Wywołanie deploy() w ContractFactory rozpocznie wdrażanie i zwróci Promise, które rozwiąże się do obiektu Contract. Jest to obiekt, który ma metodę dla każdej z naszych funkcji inteligentnego kontraktu.

Krok 16: Wdróż nasz kontrakt

Jesteśmy wreszcie gotowi do wdrożenia naszego inteligentnego kontraktu! Przejdź do wiersza poleceń i uruchom:

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

Powinieneś wtedy zobaczyć coś takiego:

Kontrakt wdrożony pod adresem: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570

Proszę zapisać ten adres. Będziemy go używać w dalszej części samouczka.

Jeśli przejdziemy do Goerli etherscan (opens in a new tab) i wyszukamy adres naszego kontraktu, powinniśmy zobaczyć, że został on pomyślnie wdrożony. Transakcja będzie wyglądać mniej więcej tak:

Adres From powinien pasować do adresu konta MetaMask, a adres To będzie zawierał informację Contract Creation. Jeśli klikniemy w transakcję, zobaczymy adres naszego kontraktu w polu Do.

Gratulacje! Właśnie wdrożyłeś inteligentny kontrakt w sieci testowej Ethereum.

Aby zrozumieć, co dzieje się pod maską, przejdź do zakładki Eksplorator w naszym pulpicie nawigacyjnym Alchemy (opens in a new tab). Jeśli masz wiele aplikacji Alchemy, upewnij się, że filtrujesz według aplikacji i wybierz Hello World.

Tutaj zobaczysz kilka metod JSON-RPC, które Hardhat/Ethers stworzył dla nas pod maską, gdy wywołaliśmy funkcję .deploy(). Dwie ważne metody to eth_sendRawTransaction (opens in a new tab), czyli żądanie zapisu naszego kontraktu w łańcuchu Goerli, oraz eth_getTransactionByHash (opens in a new tab), czyli żądanie odczytania informacji o naszej transakcji na podstawie jej hasza. Aby dowiedzieć się więcej o wysyłaniu transakcji, sprawdź nasz samouczek na temat wysyłania transakcji za pomocą Web3.

Część 2: Interakcja z Twoim inteligentnym kontraktem

Teraz, gdy pomyślnie wdrożyliśmy inteligentny kontrakt w sieci Goerli, nauczmy się, jak wchodzić z nim w interakcję.

Utwórz plik interact.js

To jest plik, w którym napiszemy nasz skrypt interakcji. Będziemy używać biblioteki Ethers.js, którą zainstalowałeś wcześniej w części 1.

W folderze scripts/ utwórz nowy plik o nazwie interact.js i dodaj następujący kod:

1// interact.js
2
3const API_KEY = process.env.API_KEY
4const PRIVATE_KEY = process.env.PRIVATE_KEY
5const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS

Zaktualizuj swój plik .env

Będziemy używać nowych zmiennych środowiskowych, więc musimy je zdefiniować w pliku .env, który utworzyliśmy wcześniej.

Będziemy musieli dodać definicję dla naszego API_KEY Alchemy i CONTRACT_ADDRESS, gdzie został wdrożony nasz inteligentny kontrakt.

Plik .env powinien wyglądać następująco:

# .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>"

Pobierz swoje ABI kontraktu

Nasze kontraktu to interfejs do interakcji z naszym inteligentnym kontraktem. Hardhat automatycznie generuje ABI i zapisuje go w HelloWorld.json. Aby użyć ABI, będziemy musieli przeanalizować zawartość, dodając następujące wiersze kodu do naszego pliku interact.js:

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

Jeśli chcesz zobaczyć ABI, możesz je wydrukować w swojej konsoli:

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

Aby zobaczyć swoje ABI wydrukowane na konsoli, przejdź do terminala i uruchom:

npx hardhat run scripts/interact.js

Utwórz instancję swojego kontraktu

Aby wejść w interakcję z naszym kontraktem, musimy stworzyć jego instancję w naszym kodzie. Aby to zrobić za pomocą Ethers.js, będziemy musieli pracować z trzema koncepcjami:

  1. Dostawca - dostawca węzła, który daje Ci dostęp do odczytu i zapisu do blockchaina
  2. Sygnatariusz - reprezentuje konto Ethereum, które może podpisywać transakcje
  3. Kontrakt - obiekt Ethers.js reprezentujący określony kontrakt wdrożony w łańcuchu

Użyjemy ABI kontraktu z poprzedniego kroku, aby stworzyć instancję naszego kontraktu:

1// interact.js
2
3// Dostawca
4const alchemyProvider = new ethers.providers.AlchemyProvider(
5 (network = "goerli"),
6 API_KEY
7)
8
9// Sygnatariusz
10const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider)
11
12// Kontrakt
13const helloWorldContract = new ethers.Contract(
14 CONTRACT_ADDRESS,
15 contract.abi,
16 signer
17)
Pokaż wszystko

Dowiedz się więcej o Dostawcach, Sygnatariuszach i Kontraktach w dokumentacji ethers.js (opens in a new tab).

Przeczytaj wiadomość init

Pamiętasz, jak wdrożyliśmy nasz kontrakt z initMessage = "Hello world!"? Teraz odczytamy tę wiadomość zapisaną w naszym inteligentnym kontrakcie i wydrukujemy ją na konsoli.

W języku JavaScript funkcje asynchroniczne są używane podczas interakcji z sieciami. Aby dowiedzieć się więcej o funkcjach asynchronicznych, przeczytaj ten artykuł (opens in a new tab).

Użyj poniższego kodu, aby wywołać funkcję message w naszym inteligentnym kontrakcie i odczytać wiadomość init:

1// interact.js
2
3// ...
4
5asynchroniczna funkcja main() {
6 const message = await helloWorldContract.message()
7 console.log("Wiadomość to: " + message)
8}
9main()
Pokaż wszystko

Po uruchomieniu pliku za pomocą npx hardhat run scripts/interact.js w terminalu powinniśmy zobaczyć taką odpowiedź:

1Wiadomość to: Witaj świecie!

Gratulacje! Właśnie pomyślnie odczytałeś dane inteligentnego kontraktu z blockchaina Ethereum, brawo!

Zaktualizuj wiadomość

Zamiast tylko odczytywać wiadomość, możemy również zaktualizować wiadomość zapisaną w naszym inteligentnym kontrakcie za pomocą funkcji update! Całkiem fajne, prawda?

Aby zaktualizować wiadomość, możemy bezpośrednio wywołać funkcję update na naszym obiekcie Contract:

1// interact.js
2
3// ...
4
5asynchroniczna funkcja main() {
6 const message = await helloWorldContract.message()
7 console.log("Wiadomość to: " + message)
8
9 console.log("Aktualizowanie wiadomości...")
10 const tx = await helloWorldContract.update("To jest nowa wiadomość.")
11 await tx.wait()
12}
13main()
Pokaż wszystko

Zauważ, że w linii 11, wywołujemy .wait() na zwróconym obiekcie transakcji. To zapewnia, że nasz skrypt czeka na wydobycie transakcji na blockchainie przed zakończeniem funkcji. Jeśli wywołanie .wait() nie zostanie uwzględnione, skrypt może nie zobaczyć zaktualizowanej wartości message w kontrakcie.

Przeczytaj nową wiadomość

Powinieneś być w stanie powtórzyć poprzedni krok, aby odczytać zaktualizowaną wartość message. Poświęć chwilę i sprawdź, czy możesz dokonać niezbędnych zmian, aby wydrukować tę nową wartość!

Jeśli potrzebujesz podpowiedzi, oto jak powinien wyglądać twój plik interact.js w tym momencie:

1// interact.js
2
3const API_KEY = process.env.API_KEY
4const PRIVATE_KEY = process.env.PRIVATE_KEY
5const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS
6
7const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")
8
9// dostawca - Alchemy
10const alchemyProvider = new ethers.providers.AlchemyProvider(
11 (network = "goerli"),
12 API_KEY
13)
14
15// podpisujący - ty
16const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider)
17
18// instancja kontraktu
19const helloWorldContract = new ethers.Contract(
20 CONTRACT_ADDRESS,
21 contract.abi,
22 signer
23)
24
25asynchroniczna funkcja main() {
26 const message = await helloWorldContract.message()
27 console.log("Wiadomość to: " + message)
28
29 console.log("Aktualizowanie wiadomości...")
30 const tx = await helloWorldContract.update("this is the new message")
31 await tx.wait()
32
33 const newMessage = await helloWorldContract.message()
34 console.log("Nowa wiadomość to: " + newMessage)
35}
36
37main()
Pokaż wszystko

Teraz po prostu uruchom skrypt, a powinieneś zobaczyć starą wiadomość, status aktualizacji i nową wiadomość wydrukowaną w terminalu!

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

1Wiadomość to: Witaj świecie!
2Aktualizowanie wiadomości...
3Nowa wiadomość to: To jest nowa wiadomość.

Podczas uruchamiania tego skryptu możesz zauważyć, że krok Aktualizowanie wiadomości... zajmuje chwilę, zanim załaduje się nowa wiadomość. Jest to spowodowane procesem wydobycia. Jeśli jesteś ciekaw śledzenia transakcji podczas ich wydobywania, odwiedź mempool Alchemy (opens in a new tab), aby zobaczyć status transakcji. Jeśli transakcja zostanie odrzucona, warto również sprawdzić Goerli Etherscan (opens in a new tab) i wyszukać swój hasz transakcji.

Część 3: Opublikuj swój inteligentny kontrakt w Etherscan

Wykonałeś całą ciężką pracę, aby ożywić swój inteligentny kontrakt, teraz nadszedł czas, aby podzielić się nim ze światem!

Weryfikując swój inteligentny kontrakt w Etherscan, każdy może zobaczyć jego kod źródłowy i wejść z nim w interakcję. Zaczynajmy!

Krok 1: Wygeneruj klucz API na swoim koncie Etherscan

Klucz API Etherscan jest niezbędny do zweryfikowania, czy jesteś właścicielem inteligentnego kontraktu, który próbujesz opublikować.

Jeśli nie masz jeszcze konta Etherscan, załóż konto (opens in a new tab).

Po zalogowaniu znajdź swoją nazwę użytkownika w pasku nawigacyjnym, najedź na nią i wybierz przycisk Mój profil.

Na stronie profilu powinieneś zobaczyć boczny pasek nawigacyjny. Z bocznego paska nawigacyjnego wybierz Klucze API. Następnie naciśnij przycisk „Dodaj”, aby utworzyć nowy klucz API, nazwij swoją aplikację hello-world i naciśnij przycisk Utwórz nowy klucz API.

Nowy klucz API powinien pojawić się w tabeli kluczy API. Skopiuj klucz API do schowka.

Następnie musimy dodać klucz API Etherscan do naszego pliku .env.

Po dodaniu, twój plik .env powinien wyglądać tak:

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

Inteligentne kontrakty wdrożone za pomocą Hardhat

Zainstaluj hardhat-etherscan

Publikowanie kontraktu w Etherscan za pomocą Hardhat jest proste. Na początek musisz zainstalować wtyczkę hardhat-etherscan. hardhat-etherscan automatycznie zweryfikuje kod źródłowy inteligentnego kontraktu i ABI w Etherscan. Aby to dodać, w katalogu hello-world uruchom:

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

Po zainstalowaniu, dołącz następującą instrukcję na początku pliku hardhat.config.js i dodaj opcje konfiguracyjne Etherscan:

1// hardhat.config.js
2
3require("dotenv").config()
4require("@nomiclabs/hardhat-ethers")
5require("@nomiclabs/hardhat-etherscan")
6
7const { API_URL, PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env
8
9module.exports = {
10 solidity: "0.7.3",
11 defaultNetwork: "goerli",
12 networks: {
13 hardhat: {},
14 goerli: {
15 url: API_URL,
16 accounts: [`0x${PRIVATE_KEY}`],
17 },
18 },
19 etherscan: {
20 // Twój klucz API dla Etherscan
21 // Uzyskaj go na https://etherscan.io/
22 apiKey: ETHERSCAN_API_KEY,
23 },
24}
Pokaż wszystko

Zweryfikuj swój inteligentny kontrakt na Etherscan

Upewnij się, że wszystkie pliki są zapisane, a wszystkie zmienne .env są poprawnie skonfigurowane.

Uruchom zadanie verify, podając adres kontraktu i sieć, w której jest wdrożony:

1npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS 'Hello World!'

Upewnij się, że DEPLOYED_CONTRACT_ADDRESS to adres Twojego wdrożonego inteligentnego kontraktu w sieci testowej Goerli. Ponadto ostatni argument ('Hello World!') musi być tą samą wartością ciągu znaków, która została użyta podczas kroku wdrażania w części 1.

Jeśli wszystko pójdzie dobrze, zobaczysz następujący komunikat w terminalu:

1Pomyślnie przesłano kod źródłowy dla kontraktu
2contracts/HelloWorld.sol:HelloWorld at 0xdeployed-contract-address
3do weryfikacji na Etherscan. Oczekiwanie na wynik weryfikacji...
4
5
6Pomyślnie zweryfikowano kontrakt HelloWorld na Etherscan.
7https://goerli.etherscan.io/address/<contract-address>#contracts

Gratulacje! Twój kod inteligentnego kontraktu jest w Etherscan!

Sprawdź swój inteligentny kontrakt w Etherscan!

Po przejściu do linku podanego w terminalu, powinieneś być w stanie zobaczyć kod inteligentnego kontraktu i ABI opublikowane na Etherscan!

Hura - udało Ci się, mistrzu! Teraz każdy może wywołać lub zapisać do Twojego inteligentnego kontraktu! Nie możemy się doczekać, co zbudujesz dalej!

Część 4 – Integracja inteligentnego kontraktu z frontendem

Po ukończeniu tego samouczka dowiesz się, jak:

  • Połącz portfel MetaMask z Twoją dappką
  • Odczytaj dane ze swojego inteligentnego kontraktu za pomocą interfejsu API Alchemy Web3 (opens in a new tab)
  • Podpisz transakcje Ethereum za pomocą MetaMask

Dla tej dapki użyjemy React (opens in a new tab) jako naszego frameworka frontendowego. Należy jednak zauważyć, że nie będziemy spędzać dużo czasu na omawianiu jego podstaw, ponieważ skupimy się głównie na wprowadzaniu funkcjonalności Web3 do naszego projektu.

Jako warunek wstępny, powinieneś mieć podstawową wiedzę na temat React. Jeśli nie, polecamy ukończenie oficjalnego samouczka Wprowadzenie do React (opens in a new tab).

Klonowanie plików startowych

Najpierw przejdź do repozytorium GitHub hello-world-part-four (opens in a new tab), aby pobrać pliki startowe dla tego projektu i sklonować to repozytorium na swój komputer lokalny.

Otwórz sklonowane repozytorium lokalnie. Zauważ, że zawiera on dwa foldery: starter-files i completed.

  • starter-files- będziemy pracować w tym katalogu, połączymy interfejs użytkownika z Twoim portfelem Ethereum i inteligentnym kontraktem, który opublikowaliśmy w Etherscan w części 3.
  • completed zawiera cały ukończony samouczek i powinien być używany tylko jako odniesienie, jeśli utkniesz.

Następnie otwórz swoją kopię starter-files w ulubionym edytorze kodu, a następnie przejdź do folderu src.

Cały kod, który napiszemy, będzie znajdować się w folderze src. Będziemy edytować komponent HelloWorld.js i pliki JavaScript util/interact.js, aby nadać naszemu projektowi funkcjonalność Web3.

Sprawdź pliki startowe

Zanim zaczniemy kodować, przeanalizujmy, co jest dla nas dostępne w plikach startowych.

Uruchomienie projektu React

Zacznijmy od uruchomienia projektu React w naszej przeglądarce. Piękno React polega na tym, że gdy nasz projekt jest już uruchomiony w przeglądarce, wszelkie zapisane przez nas zmiany będą na bieżąco aktualizowane w przeglądarce.

Aby uruchomić projekt, przejdź do katalogu głównego folderu starter-files i uruchom npm install w terminalu, aby zainstalować zależności projektu:

cd starter-files
npm install

Po zakończeniu instalacji uruchom npm start w terminalu:

npm start

Spowoduje to otwarcie http://localhost:3000/ (opens in a new tab) w przeglądarce, gdzie zobaczysz frontend naszego projektu. Powinien on składać się z jednego pola (miejsce do aktualizacji wiadomości przechowywanej w inteligentnym kontrakcie), przycisku „Połącz portfel” i przycisku „Aktualizuj”.

Jeśli spróbujesz kliknąć którykolwiek z przycisków, zauważysz, że nie działają – to dlatego, że wciąż musimy zaprogramować ich funkcjonalność.

Komponent HelloWorld.js

Wróćmy do folderu src w naszym edytorze i otwórzmy plik HelloWorld.js. Jest bardzo ważne, abyśmy zrozumieli wszystko w tym pliku, ponieważ jest to główny komponent React, nad którym będziemy pracować.

Na górze tego pliku zauważysz, że mamy kilka instrukcji importu, które są niezbędne do uruchomienia naszego projektu, w tym bibliotekę React, hooki useEffect i useState, niektóre elementy z ./util/interact.js (opiszemy je bardziej szczegółowo wkrótce!) i logo Alchemy.

1// HelloWorld.js
2
3import React from "react"
4import { useEffect, useState } from "react"
5import {
6 helloWorldContract,
7 connectWallet,
8 updateMessage,
9 loadCurrentMessage,
10 getCurrentWalletConnected,
11} from "./util/interact.js"
12
13import alchemylogo from "./alchemylogo.svg"
Pokaż wszystko

Następnie mamy nasze zmienne stanu, które będziemy aktualizować po określonych zdarzeniach.

1// HelloWorld.js
2
3// Zmienne stanu
4const [walletAddress, setWallet] = useState("")
5const [status, setStatus] = useState("")
6const [message, setMessage] = useState("Brak połączenia z siecią.")
7const [newMessage, setNewMessage] = useState("")

Oto, co reprezentuje każda ze zmiennych:

  • walletAddress - ciąg znaków, który przechowuje adres portfela użytkownika
  • status - ciąg znaków, który przechowuje pomocną wiadomość, która prowadzi użytkownika, jak wchodzić w interakcję z dapp
  • message - ciąg znaków, który przechowuje bieżącą wiadomość w inteligentnym kontrakcie
  • newMessage - ciąg znaków, który przechowuje nową wiadomość, która zostanie zapisana w inteligentnym kontrakcie

Po zmiennych stanu zobaczysz pięć niezaimplementowanych funkcji: useEffect, addSmartContractListener, addWalletListener, connectWalletPressed i onUpdatePressed. Poniżej wyjaśnimy, co robią:

1// HelloWorld.js
2
3// wywoływane tylko raz
4useEffect(async () => {
5 // TODO: zaimplementuj
6}, [])
7
8function addSmartContractListener() {
9 // TODO: zaimplementuj
10}
11
12function addWalletListener() {
13 // TODO: zaimplementuj
14}
15
16const connectWalletPressed = async () => {
17 // TODO: zaimplementuj
18}
19
20const onUpdatePressed = async () => {
21 // TODO: zaimplementuj
22}
Pokaż wszystko
  • useEffect (opens in a new tab) - to hook React, który jest wywoływany po wyrenderowaniu komponentu. Ponieważ ma przekazaną pustą tablicę [] jako właściwość (patrz linia 4), będzie wywoływany tylko podczas pierwszego renderowania komponentu. Tutaj załadujemy bieżącą wiadomość zapisaną w naszym inteligentnym kontrakcie, wywołamy nasze inteligentne kontrakty i nasłuchiwacze portfela, a także zaktualizujemy nasz interfejs użytkownika, aby odzwierciedlić, czy portfel jest już podłączony.
  • addSmartContractListener - ta funkcja konfiguruje nasłuchiwacza, który będzie obserwował zdarzenie UpdatedMessages naszego kontraktu HelloWorld i aktualizował nasz interfejs użytkownika, gdy wiadomość w naszym inteligentnym kontrakcie ulegnie zmianie.
  • addWalletListener - ta funkcja konfiguruje nasłuchiwacza, który wykrywa zmiany w stanie portfela MetaMask użytkownika, np. gdy użytkownik odłącza portfel lub zmienia adresy.
  • connectWalletPressed - ta funkcja zostanie wywołana w celu połączenia portfela MetaMask użytkownika z naszą dapp.
  • onUpdatePressed - ta funkcja zostanie wywołana, gdy użytkownik będzie chciał zaktualizować wiadomość zapisaną w inteligentnym kontrakcie.

Pod koniec tego pliku mamy interfejs użytkownika naszego komponentu.

1// HelloWorld.js
2
3// interfejs użytkownika naszego komponentu
4return (
5 <div id="container">
6 <img id="logo" src={alchemylogo}></img>
7 <button id="walletButton" onClick={connectWalletPressed}>
8 {walletAddress.length > 0 ? (
9 "Połączono: " +
10 String(walletAddress).substring(0, 6) +
11 "..." +
12 String(walletAddress).substring(38)
13 ) : (
14 <span>Połącz portfel</span>
15 )}
16 </button>
17
18 <h2 style={{ paddingTop: "50px" }}>Bieżąca wiadomość:</h2>
19 <p>{message}</p>
20
21 <h2 style={{ paddingTop: "18px" }}>Nowa wiadomość:</h2>
22
23 <div>
24 <input
25 type="text"
26 placeholder="Zaktualizuj wiadomość w swoim inteligentnym kontrakcie."
27 onChange={(e) => setNewMessage(e.target.value)}
28 value={newMessage}
29 />
30 <p id="status">{status}</p>
31
32 <button id="publishButton" onClick={onUpdatePressed}>
33 Zaktualizuj
34 </button>
35</div>
36
37</div>
38)
Pokaż wszystko

Jeśli dokładnie przeanalizujesz ten kod, zauważysz, gdzie używamy naszych różnych zmiennych stanu w naszym interfejsie użytkownika:

  • W liniach 6-12, jeśli portfel użytkownika jest podłączony (tj. walletAddress.length > 0), wyświetlamy skróconą wersję walletAddress użytkownika w przycisku o identyfikatorze „walletButton”; w przeciwnym razie jest tam po prostu napis „Połącz portfel”.
  • W linii 17 wyświetlamy bieżącą wiadomość zapisaną w inteligentnym kontrakcie, która jest przechwytywana w ciągu znaków message.
  • W liniach 23-26 używamy komponentu kontrolowanego (opens in a new tab), aby zaktualizować naszą zmienną stanu newMessage, gdy zmienia się wpis w polu tekstowym.

Oprócz naszych zmiennych stanu, zobaczysz również, że funkcje connectWalletPressed i onUpdatePressed są wywoływane, gdy odpowiednio klikane są przyciski o identyfikatorach publishButton i walletButton.

Na koniec zajmijmy się tym, gdzie ten komponent HelloWorld.js jest dodawany.

Jeśli przejdziesz do pliku App.js, który jest głównym komponentem w React, który działa jako kontener dla wszystkich innych komponentów, zobaczysz, że nasz komponent HelloWorld.js jest wstrzykiwany w linii 7.

Na koniec sprawdźmy jeszcze jeden plik, który został dla Ciebie przygotowany, plik interact.js.

Plik interact.js

Ponieważ chcemy trzymać się paradygmatu M-V-C (opens in a new tab), będziemy chcieli mieć osobny plik, który zawiera wszystkie nasze funkcje do zarządzania logiką, danymi i regułami naszej dapki, a następnie będziemy mogli wyeksportować te funkcje do naszego frontendu (naszego komponentu HelloWorld.js).

👆🏽 To jest dokładny cel naszego pliku interact.js!

Przejdź do folderu util w swoim katalogu src, a zauważysz, że dołączyliśmy plik o nazwie interact.js, który będzie zawierał wszystkie nasze funkcje i zmienne interakcji z inteligentnym kontraktem i portfelem.

1// interact.js
2
3//export const helloWorldContract;
4
5export const loadCurrentMessage = async () => {}
6
7export const connectWallet = async () => {}
8
9const getCurrentWalletConnected = async () => {}
10
11export const updateMessage = async (message) => {}
Pokaż wszystko

Na początku pliku zauważysz, że skomentowaliśmy obiekt helloWorldContract. Później w tym samouczku odkomentujemy ten obiekt i utworzymy instancję naszego inteligentnego kontraktu w tej zmiennej, którą następnie wyeksportujemy do naszego komponentu HelloWorld.js.

Cztery niezaimplementowane funkcje po naszym obiekcie helloWorldContract robią następujące rzeczy:

  • loadCurrentMessage - ta funkcja obsługuje logikę ładowania bieżącej wiadomości zapisanej w inteligentnym kontrakcie. Wywoła ona żądanie odczytu do inteligentnego kontraktu Witaj Świecie za pomocą interfejsu API Alchemy Web3 (opens in a new tab).
  • connectWallet - ta funkcja połączy MetaMask użytkownika z naszą dappką.
  • getCurrentWalletConnected - ta funkcja sprawdzi, czy konto Ethereum jest już połączone z naszą dappką podczas ładowania strony i odpowiednio zaktualizuje nasz interfejs użytkownika.
  • updateMessage - ta funkcja zaktualizuje wiadomość zapisaną w inteligentnym kontrakcie. Wykona ona żądanie zapisu do inteligentnego kontraktu Witaj Świecie, więc portfel MetaMask użytkownika będzie musiał podpisać transakcję Ethereum, aby zaktualizować wiadomość.

Teraz, gdy rozumiemy, z czym pracujemy, dowiedzmy się, jak czytać z naszego inteligentnego kontraktu!

Krok 3: Odczyt z Twojego inteligentnego kontraktu

Aby odczytać dane z inteligentnego kontraktu, musisz pomyślnie skonfigurować:

  • Połączenie API z łańcuchem Ethereum
  • Załadowana instancja Twojego inteligentnego kontraktu
  • Funkcja do wywołania funkcji inteligentnego kontraktu
  • Nasłuchiwacz do obserwowania aktualizacji, gdy zmieniają się dane, które odczytujesz z inteligentnego kontraktu

To może brzmieć jak wiele kroków, ale nie martw się! Przeprowadzimy Cię przez każdy z nich krok po kroku! :)

Ustanów połączenie API z łańcuchem Ethereum

Pamiętasz, jak w części 2 tego samouczka użyliśmy naszego klucza Alchemy Web3 do odczytu z naszego inteligentnego kontraktu (https://docs.alchemy.com/alchemy/tutorials/hello-world-smart-contract/interacting-with-a-smart-contract#step-1-install-web3-library (opens in a new tab))? Będziesz również potrzebować klucza Alchemy Web3 w swojej dapce, aby czytać z łańcucha.

Jeśli go jeszcze nie masz, najpierw zainstaluj Alchemy Web3 (opens in a new tab), przechodząc do katalogu głównego starter-files i uruchamiając następujące polecenie w terminalu:

1npm install @alch/alchemy-web3

Alchemy Web3 (opens in a new tab) to nakładka na Web3.js (opens in a new tab), zapewniająca ulepszone metody API i inne kluczowe korzyści, które ułatwiają życie dewelopera web3. Został zaprojektowany tak, aby wymagał minimalnej konfiguracji, dzięki czemu możesz od razu zacząć go używać w swojej aplikacji!

Następnie zainstaluj pakiet dotenv (opens in a new tab) w katalogu projektu, abyśmy mieli bezpieczne miejsce do przechowywania naszego klucza API po jego pobraniu.

1npm install dotenv --save

Dla naszej dapki będziemy używać naszego klucza API Websockets zamiast klucza API HTTP, ponieważ pozwoli nam to skonfigurować nasłuchiwacza, który wykrywa, kiedy zmienia się wiadomość zapisana w inteligentnym kontrakcie.

Po uzyskaniu klucza API, utwórz plik .env w swoim katalogu głównym i dodaj do niego adres URL Alchemy Websockets. Następnie plik .env powinien wyglądać następująco:

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

Teraz jesteśmy gotowi do skonfigurowania naszego punktu końcowego Alchemy Web3 w naszej dapce! Wróćmy do naszego pliku interact.js, który jest zagnieżdżony w naszym folderze util i dodajmy następujący kod na początku pliku:

1// interact.js
2
3require("dotenv").config()
4const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY
5const { createAlchemyWeb3 } = require("@alch/alchemy-web3")
6const web3 = createAlchemyWeb3(alchemyKey)
7
8//export const helloWorldContract;

Powyżej najpierw zaimportowaliśmy klucz Alchemy z naszego pliku .env, a następnie przekazaliśmy nasz alchemyKey do createAlchemyWeb3, aby ustanowić nasz punkt końcowy Alchemy Web3.

Gdy ten punkt końcowy jest gotowy, nadszedł czas, aby załadować nasz inteligentny kontrakt!

Ładowanie Twojego inteligentnego kontraktu Witaj Świecie

Aby załadować swój inteligentny kontrakt Witaj Świecie, będziesz potrzebować jego adresu kontraktu i ABI, które można znaleźć w Etherscan, jeśli ukończyłeś część 3 tego samouczka.

Jak uzyskać ABI kontraktu z Etherscan

Jeśli pominąłeś część 3 tego samouczka, możesz użyć kontraktu HelloWorld z adresem 0x6f3f635A9762B47954229Ea479b4541eAF402A6A (opens in a new tab). Jego ABI można znaleźć tutaj (opens in a new tab).

ABI kontraktu jest niezbędne do określenia, którą funkcję kontrakt wywoła, a także do zapewnienia, że funkcja zwróci dane w oczekiwanym formacie. Po skopiowaniu naszego ABI kontraktu, zapiszmy go jako plik JSON o nazwie contract-abi.json w swoim katalogu src.

Twój plik contract-abi.json powinien być przechowywany w folderze src.

Mając do dyspozycji adres kontraktu, ABI i punkt końcowy Alchemy Web3, możemy użyć metody kontraktu (opens in a new tab), aby załadować instancję naszego inteligentnego kontraktu. Zaimportuj ABI kontraktu do pliku interact.js i dodaj adres kontraktu.

1// interact.js
2
3const contractABI = require("../contract-abi.json")
4const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A"

Możemy teraz wreszcie odkomentować naszą zmienną helloWorldContract i załadować inteligentny kontrakt za pomocą naszego punktu końcowego AlchemyWeb3:

1// interact.js
2export const helloWorldContract = new web3.eth.Contract(
3 contractABI,
4 contractAddress
5)

Podsumowując, pierwsze 12 linii pliku interact.js powinno teraz wyglądać tak:

1// interact.js
2
3require("dotenv").config()
4const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY
5const { createAlchemyWeb3 } = require("@alch/alchemy-web3")
6const web3 = createAlchemyWeb3(alchemyKey)
7
8const contractABI = require("../contract-abi.json")
9const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A"
10
11export const helloWorldContract = new web3.eth.Contract(
12 contractABI,
13 contractAddress
14)
Pokaż wszystko

Teraz, gdy nasz kontrakt jest załadowany, możemy zaimplementować naszą funkcję loadCurrentMessage!

Implementacja loadCurrentMessage w pliku interact.js

Ta funkcja jest super prosta. Zrobimy proste asynchroniczne wywołanie web3, aby odczytać z naszego kontraktu. Nasza funkcja zwróci wiadomość zapisaną w inteligentnym kontrakcie:

Zaktualizuj loadCurrentMessage w swoim pliku interact.js do następującej postaci:

1// interact.js
2
3export const loadCurrentMessage = async () => {
4 const message = await helloWorldContract.methods.message().call()
5 return message
6}

Ponieważ chcemy wyświetlić ten inteligentny kontrakt w naszym interfejsie użytkownika, zaktualizujmy funkcję useEffect w naszym komponencie HelloWorld.js do następującej postaci:

1// HelloWorld.js
2
3// wywoływane tylko raz
4useEffect(async () => {
5 const message = await loadCurrentMessage()
6 setMessage(message)
7}, [])

Zauważ, że chcemy, aby nasza funkcja loadCurrentMessage była wywoływana tylko raz podczas pierwszego renderowania komponentu. Wkrótce zaimplementujemy addSmartContractListener, aby automatycznie aktualizować interfejs użytkownika po zmianie wiadomości w inteligentnym kontrakcie.

Zanim przejdziemy do naszego nasłuchiwacza, sprawdźmy, co mamy do tej pory! Zapisz pliki HelloWorld.js i interact.js, a następnie przejdź do http://localhost:3000/ (opens in a new tab)

Zauważysz, że bieżąca wiadomość nie brzmi już „Brak połączenia z siecią”. Zamiast tego odzwierciedla ona wiadomość zapisaną w inteligentnym kontrakcie. Super!

Twój interfejs użytkownika powinien teraz odzwierciedlać wiadomość zapisaną w inteligentnym kontrakcie

A propos tego nasłuchiwacza...

Zaimplementuj addSmartContractListener

Jeśli przypomnisz sobie plik HelloWorld.sol, który napisaliśmy w części 1 tej serii samouczków (opens in a new tab), przypomnisz sobie, że istnieje zdarzenie inteligentnego kontraktu o nazwie UpdatedMessages, które jest emitowane po wywołaniu funkcji update naszego inteligentnego kontraktu (patrz linie 9 i 27):

1// HelloWorld.sol
2
3// Określa wersję Solidity, używając semantycznego wersjonowania.
4// Dowiedz się więcej: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
5pragma solidity ^0.7.3;
6
7// Definiuje kontrakt o nazwie `HelloWorld`.
8// Kontrakt jest zbiorem funkcji i danych (jego stanu). Po wdrożeniu kontrakt znajduje się pod określonym adresem w blockchainie Ethereum. Dowiedz się więcej: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
9contract HelloWorld {
10
11 // Emitowane, gdy wywoływana jest funkcja aktualizacji
12 // Zdarzenia inteligentnych kontraktów to sposób, w jaki kontrakt komunikuje, że coś wydarzyło się na blockchainie do front-endu aplikacji, który może „nasłuchiwać” określonych zdarzeń i podejmować działania, gdy one wystąpią.
13 event UpdatedMessages(string oldStr, string newStr);
14
15 // Deklaruje zmienną stanu `message` typu `string`.
16 // Zmienne stanu to zmienne, których wartości są trwale przechowywane w pamięci kontraktu. Słowo kluczowe `public` udostępnia zmienne spoza kontraktu i tworzy funkcję, którą inne kontrakty lub klienci mogą wywołać w celu uzyskania dostępu do wartości.
17 string public message;
18
19 // Podobnie jak w wielu językach obiektowych opartych na klasach, konstruktor jest specjalną funkcją, która jest wykonywana tylko podczas tworzenia kontraktu.
20 // Konstruktory służą do inicjalizacji danych kontraktu. Dowiedz się więcej: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
21 constructor(string memory initMessage) {
22
23 // Akceptuje argument ciągu znaków `initMessage` i ustawia wartość w zmiennej pamięci kontraktu `message`).
24 message = initMessage;
25 }
26
27 // Funkcja publiczna, która akceptuje argument w postaci ciągu znaków i aktualizuje zmienną pamięci masowej `message`.
28 function update(string memory newMessage) public {
29 string memory oldMsg = message;
30 message = newMessage;
31 emit UpdatedMessages(oldMsg, newMessage);
32 }
33}
Pokaż wszystko

Zdarzenia inteligentnych kontraktów to sposób, w jaki kontrakt komunikuje, że coś się stało (tj. miało miejsce zdarzenie) na blockchainie do Twojej aplikacji front-endowej, która może „nasłuchiwać” określonych zdarzeń i podejmować działania, gdy one wystąpią.

Funkcja addSmartContractListener będzie konkretnie nasłuchiwać zdarzenia UpdatedMessages naszego inteligentnego kontraktu Witaj Świecie i aktualizować nasz interfejs użytkownika, aby wyświetlić nową wiadomość.

Zmodyfikuj addSmartContractListener do następującej postaci:

1// HelloWorld.js
2
3function addSmartContractListener() {
4 helloWorldContract.events.UpdatedMessages({}, (error, data) => {
5 if (error) {
6 setStatus("😥 " + error.message)
7 } else {
8 setMessage(data.returnValues[1])
9 setNewMessage("")
10 setStatus("🎉 Twoja wiadomość została zaktualizowana!")
11 }
12 })
13}
Pokaż wszystko

Przeanalizujmy, co się dzieje, gdy nasłuchiwacz wykryje zdarzenie:

  • Jeśli wystąpi błąd podczas emitowania zdarzenia, zostanie on odzwierciedlony w interfejsie użytkownika za pośrednictwem naszej zmiennej stanu status.
  • W przeciwnym razie użyjemy zwróconego obiektu data. data.returnValues to tablica indeksowana od zera, w której pierwszy element tablicy przechowuje poprzednią wiadomość, a drugi element przechowuje zaktualizowaną. W sumie, w przypadku pomyślnego zdarzenia, ustawimy nasz ciąg znaków message na zaktualizowaną wiadomość, wyczyścimy ciąg znaków newMessage i zaktualizujemy naszą zmienną stanu status, aby odzwierciedlić, że nowa wiadomość została opublikowana w naszym inteligentnym kontrakcie.

Na koniec wywołajmy naszego nasłuchiwacza w naszej funkcji useEffect, aby został zainicjowany podczas pierwszego renderowania komponentu HelloWorld.js. W sumie Twoja funkcja useEffect powinna wyglądać tak:

1// HelloWorld.js
2
3useEffect(async () => {
4 const message = await loadCurrentMessage()
5 setMessage(message)
6 addSmartContractListener()
7}, [])

Teraz, gdy jesteśmy w stanie czytać z naszego inteligentnego kontraktu, byłoby wspaniale dowiedzieć się, jak do niego pisać! Jednak, aby pisać do naszej dapki, musimy najpierw mieć do niej podłączony portfel Ethereum.

Więc następnie zajmiemy się konfiguracją naszego portfela Ethereum (MetaMask), a następnie podłączeniem go do naszej dapki!

Krok 4: Skonfiguruj swój portfel Ethereum

Aby cokolwiek zapisać w łańcuchu Ethereum, użytkownicy muszą podpisywać transakcje za pomocą kluczy prywatnych swojego wirtualnego portfela. W tym samouczku użyjemy MetaMask (opens in a new tab), wirtualnego portfela w przeglądarce używanego do zarządzania adresem konta Ethereum, ponieważ znacznie ułatwia to podpisywanie transakcji dla użytkownika końcowego.

Jeśli chcesz dowiedzieć się więcej o tym, jak działają transakcje w Ethereum, sprawdź tę stronę od Ethereum Foundation.

Pobierz MetaMask

Możesz pobrać i utworzyć konto MetaMask za darmo tutaj (opens in a new tab). Podczas tworzenia konta, lub jeśli już je posiadasz, upewnij się, że przełączyłeś się na „Sieć testową Goerli” w prawym górnym rogu (aby nie mieć do czynienia z prawdziwymi pieniędzmi).

Dodaj ether z Faucet

Aby podpisać transakcję na blockchainie Ethereum, będziemy potrzebować trochę fałszywego Eth. Aby uzyskać Eth, możesz przejść do FaucETH (opens in a new tab) i wprowadzić swój adres konta Goerli, kliknąć „Poproś o fundusze”, następnie wybrać „Ethereum Testnet Goerli” w menu rozwijanym i na koniec ponownie kliknąć przycisk „Poproś o fundusze”. Wkrótce powinieneś zobaczyć Eth na swoim koncie MetaMask!

Sprawdź swoje saldo

Aby sprawdzić, czy nasze saldo jest na miejscu, wykonajmy żądanie eth_getBalance (opens in a new tab) za pomocą narzędzia kompozytora Alchemy (opens in a new tab). Zwróci to ilość Eth w naszym portfelu. Po wprowadzeniu adresu konta MetaMask i kliknięciu „Wyślij żądanie” powinieneś zobaczyć następującą odpowiedź:

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

UWAGA: ten wynik jest w wei, a nie w eth. Wei jest używany jako najmniejsza jednostka etheru. Konwersja z wei na eth to: 1 eth = 10¹⁸ wei. Więc jeśli przekonwertujemy 0xde0b6b3a7640000 na system dziesiętny, otrzymamy 1*10¹⁸, co równa się 1 eth.

Uff! Nasze fałszywe pieniądze są na miejscu! 🤑

Krok 5: Podłącz MetaMask do swojego interfejsu użytkownika

Teraz, gdy nasz portfel MetaMask jest skonfigurowany, połączmy z nim naszą dapką!

Funkcja connectWallet

W naszym pliku interact.js zaimplementujmy funkcję connectWallet, którą następnie możemy wywołać w naszym komponencie HelloWorld.js.

Zmodyfikujmy connectWallet do następującej postaci:

1// interact.js
2
3export const connectWallet = async () => {
4 if (window.ethereum) {
5 try {
6 const addressArray = await window.ethereum.request({
7 method: "eth_requestAccounts",
8 })
9 const obj = {
10 status: "👆🏽 Wpisz wiadomość w polu tekstowym powyżej.",
11 address: addressArray[0],
12 }
13 return obj
14 } catch (err) {
15 return {
16 address: "",
17 status: "😥 " + err.message,
18 }
19 }
20 } else {
21 return {
22 address: "",
23 status: (
24 <span>
25 <p>
26 {" "}
27 🦊 <a target="_blank" href={`https://metamask.io/download`}>
28 Musisz zainstalować MetaMask, wirtualny portfel Ethereum, w swojej
29 przeglądarce.
30 </a>
31 </p>
32 </span>
33 ),
34 }
35 }
36}
Pokaż wszystko

Więc co dokładnie robi ten gigantyczny blok kodu?

Po pierwsze, sprawdza, czy window.ethereum jest włączone w przeglądarce.

window.ethereum to globalny interfejs API wstrzykiwany przez MetaMask i innych dostawców portfeli, który pozwala stronom internetowym na żądanie dostępu do kont Ethereum użytkowników. Jeśli zostanie zatwierdzony, może odczytywać dane z blockchainów, z którymi użytkownik jest połączony, i sugerować, aby użytkownik podpisywał wiadomości i transakcje. Sprawdź dokumentację MetaMask (opens in a new tab), aby uzyskać więcej informacji!

Jeśli window.ethereum nie jest obecne, oznacza to, że MetaMask nie jest zainstalowany. Powoduje to zwrócenie obiektu JSON, w którym zwrócony adres jest pustym ciągiem, a obiekt status JSX informuje, że użytkownik musi zainstalować MetaMask.

Teraz, jeśli window.ethereum jest obecne, to wtedy robi się ciekawie.

Używając pętli try/catch, spróbujemy połączyć się z MetaMask, wywołując window.ethereum.request({ method: "eth_requestAccounts" }); (opens in a new tab). Wywołanie tej funkcji otworzy MetaMask w przeglądarce, gdzie użytkownik zostanie poproszony o podłączenie swojego portfela do Twojej dapki.

  • Jeśli użytkownik zdecyduje się połączyć, method: "eth_requestAccounts" zwróci tablicę zawierającą wszystkie adresy kont użytkownika, które połączyły się z dappką. W sumie nasza funkcja connectWallet zwróci obiekt JSON, który zawiera pierwszy adres w tej tablicy (patrz linia 9) oraz wiadomość status, która prosi użytkownika o napisanie wiadomości do inteligentnego kontraktu.
  • Jeśli użytkownik odrzuci połączenie, obiekt JSON będzie zawierał pusty ciąg dla zwróconego adresu oraz komunikat status, który odzwierciedla, że użytkownik odrzucił połączenie.

Teraz, gdy napisaliśmy tę funkcję connectWallet, następnym krokiem jest wywołanie jej w naszym komponencie HelloWorld.js.

Dodaj funkcję connectWallet do swojego komponentu interfejsu użytkownika HelloWorld.js

Przejdź do funkcji connectWalletPressed w HelloWorld.js i zaktualizuj ją do następującej postaci:

1// HelloWorld.js
2
3const connectWalletPressed = async () => {
4 const walletResponse = await connectWallet()
5 setStatus(walletResponse.status)
6 setWallet(walletResponse.address)
7}

Zauważ, jak większość naszej funkcjonalności jest abstrahowana od naszego komponentu HelloWorld.js z pliku interact.js? Robimy tak, aby zachować zgodność z paradygmatem M-V-C!

W connectWalletPressed po prostu wykonujemy wywołanie await do naszej zaimportowanej funkcji connectWallet, a za pomocą jej odpowiedzi aktualizujemy nasze zmienne status i walletAddress za pomocą ich hooków stanu.

Teraz zapiszmy oba pliki (HelloWorld.js i interact.js) i przetestujmy nasz dotychczasowy interfejs użytkownika.

Otwórz przeglądarkę na stronie http://localhost:3000/ (opens in a new tab) i naciśnij przycisk „Połącz portfel” w prawym górnym rogu strony.

Jeśli masz zainstalowany MetaMask, powinieneś zostać poproszony o podłączenie swojego portfela do Twojej dapki. Zaakceptuj zaproszenie do połączenia.

Powinieneś zobaczyć, że przycisk portfela odzwierciedla teraz, że Twój adres jest połączony! Jeeee 🔥

Następnie spróbuj odświeżyć stronę... to jest dziwne. Nasz przycisk portfela prosi nas o podłączenie MetaMask, mimo że jest już podłączony...

Jednak nie ma się czego bać! Możemy łatwo to rozwiązać (zaadresować?) implementując getCurrentWalletConnected, który sprawdzi, czy adres jest już połączony z naszą dappką i odpowiednio zaktualizuje nasz interfejs użytkownika!

Funkcja getCurrentWalletConnected

Zaktualizuj swoją funkcję getCurrentWalletConnected w pliku interact.js do następującej postaci:

1// interact.js
2
3export const getCurrentWalletConnected = async () => {
4 if (window.ethereum) {
5 try {
6 const addressArray = await window.ethereum.request({
7 method: "eth_accounts",
8 })
9 if (addressArray.length > 0) {
10 return {
11 address: addressArray[0],
12 status: "👆🏽 Wpisz wiadomość w polu tekstowym powyżej.",
13 }
14 } else {
15 return {
16 address: "",
17 status: "🦊 Połącz się z MetaMask za pomocą przycisku w prawym górnym rogu.",
18 }
19 }
20 } catch (err) {
21 return {
22 address: "",
23 status: "😥 " + err.message,
24 }
25 }
26 } else {
27 return {
28 address: "",
29 status: (
30 <span>
31 <p>
32 {" "}
33 🦊 <a target="_blank" href={`https://metamask.io/download`}>
34 Musisz zainstalować MetaMask, wirtualny portfel Ethereum, w swojej
35 przeglądarce.
36 </a>
37 </p>
38 </span>
39 ),
40 }
41 }
42}
Pokaż wszystko

Ten kod jest bardzo podobny do funkcji connectWallet, którą właśnie napisaliśmy w poprzednim kroku.

Główna różnica polega na tym, że zamiast wywoływać metodę eth_requestAccounts, która otwiera MetaMask, aby użytkownik mógł połączyć swój portfel, tutaj wywołujemy metodę eth_accounts, która po prostu zwraca tablicę zawierającą adresy MetaMask aktualnie połączone z naszą dapką.

Aby zobaczyć tę funkcję w działaniu, wywołajmy ją w naszej funkcji useEffect naszego komponentu HelloWorld.js:

1// HelloWorld.js
2
3useEffect(async () => {
4 const message = await loadCurrentMessage()
5 setMessage(message)
6 addSmartContractListener()
7
8 const { address, status } = await getCurrentWalletConnected()
9 setWallet(address)
10 setStatus(status)
11}, [])
Pokaż wszystko

Zauważ, że używamy odpowiedzi z naszego wywołania getCurrentWalletConnected, aby zaktualizować nasze zmienne stanu walletAddress i status.

Teraz, gdy dodałeś ten kod, spróbujmy odświeżyć okno przeglądarki.

Fajnieee! Przycisk powinien informować, że jesteś połączony i pokazywać podgląd adresu podłączonego portfela - nawet po odświeżeniu!

Zaimplementuj addWalletListener

Ostatnim krokiem w konfiguracji portfela naszej dapki jest zaimplementowanie nasłuchiwacza portfela, aby nasz interfejs użytkownika aktualizował się, gdy zmieni się stan naszego portfela, na przykład gdy użytkownik się rozłączy lub zmieni konto.

W pliku HelloWorld.js zmodyfikuj swoją funkcję addWalletListener w następujący sposób:

1// HelloWorld.js
2
3function addWalletListener() {
4 if (window.ethereum) {
5 window.ethereum.on("accountsChanged", (accounts) => {
6 if (accounts.length > 0) {
7 setWallet(accounts[0])
8 setStatus("👆🏽 Wpisz wiadomość w polu tekstowym powyżej.")
9 } else {
10 setWallet("")
11 setStatus("🦊 Połącz się z MetaMask za pomocą przycisku w prawym górnym rogu.")
12 }
13 })
14 } else {
15 setStatus(
16 <p>
17 {" "}
18 🦊 <a target="_blank" href={`https://metamask.io/download`}>
19 Musisz zainstalować MetaMask, wirtualny portfel Ethereum, w swojej przeglądarce.
20 </a>
21 </p>
22 )
23 }
24}
Pokaż wszystko

Założę się, że w tym momencie nie potrzebujesz nawet naszej pomocy, aby zrozumieć, co się tutaj dzieje, ale dla porządku szybko to omówmy:

  • Najpierw nasza funkcja sprawdza, czy window.ethereum jest włączone (tj. MetaMask jest zainstalowany).
    • Jeśli nie jest, po prostu ustawiamy naszą zmienną stanu status na ciąg JSX, który prosi użytkownika o zainstalowanie MetaMask.
    • Jeśli jest włączone, ustawiamy nasłuchiwacz window.ethereum.on("accountsChanged") w linii 3, który nasłuchuje zmian stanu w portfelu MetaMask, co obejmuje sytuacje, gdy użytkownik podłącza dodatkowe konto do dapki, zmienia konta lub odłącza konto. Jeśli co najmniej jedno konto jest połączone, zmienna stanu walletAddress jest aktualizowana jako pierwsze konto w tablicy konta zwróconej przez nasłuchiwacz. W przeciwnym razie walletAddress jest ustawiany jako pusty ciąg.

Na koniec musimy wywołać ją w naszej funkcji useEffect:

1// HelloWorld.js
2
3useEffect(async () => {
4 const message = await loadCurrentMessage()
5 setMessage(message)
6 addSmartContractListener()
7
8 const { address, status } = await getCurrentWalletConnected()
9 setWallet(address)
10 setStatus(status)
11
12 addWalletListener()
13}, [])
Pokaż wszystko

I to wszystko! Pomyślnie ukończyliśmy programowanie całej naszej funkcjonalności portfela! Teraz przejdźmy do naszego ostatniego zadania: aktualizacji wiadomości zapisanej w naszym inteligentnym kontrakcie!

Krok 6: Zaimplementuj funkcję updateMessage

Dobra, ekipa, dotarliśmy do ostatniej prostej! W updateMessage w swoim pliku interact.js, zrobimy następujące rzeczy:

  1. Upewnij się, że wiadomość, którą chcemy opublikować w naszym inteligentnym kontakcie, jest ważna
  2. Podpisz naszą transakcję za pomocą MetaMask
  3. Wywołaj tę funkcję z naszego komponentu frontendowego HelloWorld.js

To nie potrwa długo; dokończmy tę dappkę!

Obsługa błędów wejściowych

Naturalnie, sensowne jest posiadanie jakiejś formy obsługi błędów wejściowych na początku funkcji.

Będziemy chcieli, aby nasza funkcja zakończyła się wcześniej, jeśli nie ma zainstalowanego rozszerzenia MetaMask, nie jest podłączony portfel (tj. przekazany address jest pustym ciągiem znaków) lub message jest pustym ciągiem znaków. Dodajmy następującą obsługę błędów do updateMessage:

1// interact.js
2
3export const updateMessage = async (address, message) => {
4 if (!window.ethereum || address === null) {
5 return {
6 status:
7 "💡 Połącz swój portfel MetaMask, aby zaktualizować wiadomość na blockchainie.",
8 }
9 }
10
11 if (message.trim() === "") {
12 return {
13 status: "❌ Twoja wiadomość nie może być pustym ciągiem znaków.",
14 }
15 }
16}
Pokaż wszystko

Teraz, gdy mamy właściwą obsługę błędów wejściowych, nadszedł czas, aby podpisać transakcję za pomocą MetaMask!

Podpisywanie naszej transakcji

Jeśli jesteś już zaznajomiony z tradycyjnymi transakcjami Ethereum web3, kod, który napiszemy dalej, będzie bardzo znajomy. Poniżej kodu obsługi błędów wejściowych dodaj następujący kod do updateMessage:

1// interact.js
2
3// ustaw parametry transakcji
4const transactionParameters = {
5 to: contractAddress, // Wymagane z wyjątkiem publikacji kontraktów.
6 from: address, // musi pasować do aktywnego adresu użytkownika.
7 data: helloWorldContract.methods.update(message).encodeABI(),
8}
9
10// podpisz transakcję
11try {
12 const txHash = await window.ethereum.request({
13 method: "eth_sendTransaction",
14 params: [transactionParameters],
15 })
16 return {
17 status: (
18 <span>
19{" "}
20 <a target="_blank" href={`https://goerli.etherscan.io/tx/${txHash}`}>
21 Zobacz status swojej transakcji na Etherscan!
22 </a>
23 <br />
24 ℹ️ Gdy transakcja zostanie zweryfikowana przez sieć, wiadomość zostanie
25 zaktualizowana automatycznie.
26 </span>
27 ),
28 }
29} catch (error) {
30 return {
31 status: "😥 " + error.message,
32 }
33}
Pokaż wszystko

Przeanalizujmy, co się dzieje. Najpierw ustawiamy parametry naszej transakcji, gdzie:

  • to określa adres odbiorcy (nasz inteligentny kontrakt)
  • from określa sygnatariusza transakcji, zmienną address, którą przekazaliśmy do naszej funkcji
  • data zawiera wywołanie metody update naszego inteligentnego kontraktu Witaj Świecie, otrzymując jako dane wejściowe naszą zmienną ciągu znaków message

Następnie wykonujemy wywołanie await, window.ethereum.request, w którym prosimy MetaMask o podpisanie transakcji. Zauważ, że w liniach 11 i 12 określamy naszą metodę eth, eth_sendTransaction i przekazujemy nasze transactionParameters.

W tym momencie w przeglądarce otworzy się MetaMask i poprosi użytkownika o podpisanie lub odrzucenie transakcji.

  • Jeśli transakcja się powiedzie, funkcja zwróci obiekt JSON, w którym ciąg JSX status prosi użytkownika o sprawdzenie Etherscan w celu uzyskania dalszych informacji o transakcji.
  • Jeśli transakcja się nie powiedzie, funkcja zwróci obiekt JSON, w którym ciąg znaków status przekaże komunikat o błędzie.

W sumie nasza funkcja updateMessage powinna wyglądać tak:

1// interact.js
2
3export const updateMessage = async (address, message) => {
4 // obsługa błędów wejściowych
5 if (!window.ethereum || address === null) {
6 return {
7 status:
8 "💡 Połącz swój portfel MetaMask, aby zaktualizować wiadomość na blockchainie.",
9 }
10 }
11
12 if (message.trim() === "") {
13 return {
14 status: "❌ Twoja wiadomość nie może być pustym ciągiem znaków.",
15 }
16 }
17
18 // ustaw parametry transakcji
19 const transactionParameters = {
20 to: contractAddress, // Wymagane z wyjątkiem publikacji kontraktów.
21 from: address, // musi pasować do aktywnego adresu użytkownika.
22 data: helloWorldContract.methods.update(message).encodeABI(),
23 }
24
25 // podpisz transakcję
26 try {
27 const txHash = await window.ethereum.request({
28 method: "eth_sendTransaction",
29 params: [transactionParameters],
30 })
31 return {
32 status: (
33 <span>
34{" "}
35 <a target="_blank" href={`https://goerli.etherscan.io/tx/${txHash}`}>
36 Zobacz status swojej transakcji na Etherscan!
37 </a>
38 <br />
39 ℹ️ Gdy transakcja zostanie zweryfikowana przez sieć, wiadomość zostanie
40 zaktualizowana automatycznie.
41 </span>
42 ),
43 }
44 } catch (error) {
45 return {
46 status: "😥 " + error.message,
47 }
48 }
49}
Pokaż wszystko

Na koniec musimy połączyć naszą funkcję updateMessage z naszym komponentem HelloWorld.js.

Połącz updateMessage z frontendem HelloWorld.js

Nasza funkcja onUpdatePressed powinna wykonać wywołanie await do zaimportowanej funkcji updateMessage i zmodyfikować zmienną stanu status, aby odzwierciedlić, czy nasza transakcja się powiodła, czy nie:

1// HelloWorld.js
2
3const onUpdatePressed = async () => {
4 const { status } = await updateMessage(walletAddress, newMessage)
5 setStatus(status)
6}

To super czyste i proste. I zgadnij co... TWOJA DAPPKA JEST UKOŃCZONA!!!

Śmiało przetestuj przycisk Aktualizuj!

Stwórz swoją własną dappkę

Hura, dotarłeś do końca samouczka! Podsumowując, nauczyłeś się, jak:

  • Podłącz portfel MetaMask do swojego projektu dapp
  • Odczytaj dane ze swojego inteligentnego kontraktu za pomocą interfejsu API Alchemy Web3 (opens in a new tab)
  • Podpisz transakcje Ethereum za pomocą MetaMask

Teraz jesteś w pełni wyposażony, aby zastosować umiejętności z tego samouczka do zbudowania własnego, niestandardowego projektu dapp! Jak zawsze, jeśli masz jakieś pytania, nie wahaj się skontaktować z nami w celu uzyskania pomocy na Discordzie Alchemy (opens in a new tab). 🧙‍♂️

Po ukończeniu tego samouczka daj nam znać, jak Ci poszło lub czy masz jakieś uwagi, oznaczając nas na Twitterze @alchemyplatform (opens in a new tab)!

Strona ostatnio zaktualizowana: 26 lutego 2026

Czy ten samouczek był pomocny?