Chytrý kontrakt Hello World pro začátečníky – Fullstack
Tento průvodce je pro vás, pokud jste v blockchainovém vývoji nováčkem a nevíte, kde začít nebo jak nasadit chytré kontrakty a interagovat s nimi. Projdeme si vytvoření a nasazení jednoduchého chytrého kontraktu v testovací síti Goerli pomocí MetaMaskopens in a new tab, Solidityopens in a new tab, Hardhatopens in a new tab a Alchemyopens in a new tab.
K dokončení tohoto tutoriálu budete potřebovat účet Alchemy. Zaregistrujte si bezplatný účetopens in a new tab.
Pokud budete mít kdykoli nějaké otázky, neváhejte se na nás obrátit na Discordu Alchemyopens in a new tab!
Část 1 – Vytvoření a nasazení chytrého kontraktu pomocí Hardhat
Připojení k síti Ethereum
Existuje mnoho způsobů, jak posílat požadavky na blockchain Etherea. Pro zjednodušení použijeme bezplatný účet na Alchemy, vývojářské platformě a API pro blockchain, která nám umožňuje komunikovat s ethereovým chainem, aniž bychom museli sami provozovat uzel. Alchemy má také vývojářské nástroje pro monitorování a analýzu; v tomto tutoriálu je využijeme, abychom pochopili, co se děje pod pokličkou při nasazení našeho chytrého kontraktu.
Vytvoření aplikace a klíče API
Jakmile si vytvoříte účet Alchemy, můžete si vygenerovat API klíč vytvořením aplikace. To vám umožní zadávat požadavky do testovací sítě Goerli. Pokud testovací sítě neznáte, můžete si přečíst průvodce Alchemy výběrem sítěopens in a new tab.
Na řídicím panelu Alchemy najděte v navigační liště rozevírací seznam Aplikace a klikněte na Vytvořit aplikaci.
Pojmenujte svou aplikaci „Hello World“ a napište krátký popis. Jako prostředí vyberte Staging a jako síť Goerli.
Poznámka: Nezapomeňte vybrat Goerli, jinak tento tutoriál nebude fungovat.
Klikněte na Vytvořit aplikaci. Vaše aplikace se objeví v tabulce níže.
Vytvoření účtu Ethereum
Potřebujete účet Ethereum pro odesílání a přijímání transakcí. Použijeme MetaMask, virtuální peněženku v prohlížeči, která umožňuje uživatelům spravovat adresu svého ethereového účtu.
Účet MetaMask si můžete zdarma stáhnout a vytvořit zdeopens in a new tab. Při vytváření účtu nebo pokud již účet máte, nezapomeňte se vpravo nahoře přepnout na „testovací síť Goerli“ (abychom nepracovali se skutečnými penězi).
Krok 4: Přidejte ether z Faucetu
Chcete-li nasadit chytrý kontrakt do testovací sítě, budete potřebovat nějaké falešné ETH. Chcete-li získat ETH v síti Goerli, přejděte na faucet Goerli a zadejte adresu svého účtu Goerli. Upozorňujeme, že faucety Goerli mohou být v poslední době trochu nespolehlivé – podívejte se na stránku testovacích sítí, kde najdete seznam možností k vyzkoušení:
Poznámka: Kvůli přetížení sítě to může chvíli trvat. ``
Krok 5: Zkontrolujte si zůstatek
Chcete-li si dvakrát ověřit, že máte ETH v peněžence, zadejte požadavek eth_getBalanceopens in a new tab pomocí nástroje Alchemy Composeropens in a new tab. Tím se vrátí množství ETH v naší peněžence. Chcete-li se dozvědět více, podívejte se na krátký tutoriál od Alchemy o tom, jak používat nástroj Composeropens in a new tab.
Zadejte adresu svého účtu MetaMask a klikněte na Odeslat požadavek. Zobrazí se odpověď, která vypadá jako úryvek kódu níže.
1{ "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" }Poznámka: Tento výsledek je ve wei, nikoliv v ETH. Wei je nejmenší jednotkou etheru.
Uf! Naše falešné peníze jsou všechny tam.
Krok 6: Inicializace našeho projektu
Nejprve musíme pro náš projekt vytvořit složku. Přejděte na příkazový řádek a zadejte následující.
1mkdir hello-world2cd hello-worldNyní, když jsme uvnitř složky našeho projektu, použijeme npm init k inicializaci projektu.
Pokud ještě nemáte nainstalovaný npm, postupujte podle těchto pokynů k instalaci Node.js a npmopens in a new tab.
Pro účely tohoto tutoriálu nezáleží na tom, jak na inicializační otázky odpovíte. Zde je pro referenci, jak jsme to udělali my:
1název balíčku: (hello-world)2verze: (1.0.0)3popis: chytrý kontrakt hello world4vstupní bod: (index.js)5příkaz k testování:6repositář git:7klíčová slova:8autor:9licence: (ISC)1011Chystá se zápis do /Users/.../.../.../hello-world/package.json:1213{14 "name": "hello-world",15 "version": "1.0.0",16 "description": "chytrý kontrakt hello world",17 "main": "index.js",18 "scripts": {19 "test": "echo \"Chyba: není zadán žádný test\" && exit 1"20 },21 "author": "",22 "license": "ISC"23}Zobrazit všeSchvalte package.json a můžeme pokračovat!
Krok 7: Stažení nástroje Hardhat
Hardhat je vývojové prostředí pro kompilaci, nasazení, testování a ladění vašeho softwaru pro Ethereum. Pomáhá vývojářům při lokálním budování chytrých kontraktů a dapps před jejich nasazením na živý řetězec.
Uvnitř našeho projektu hello-world spusťte:
1npm install --save-dev hardhatDalší podrobnosti o instalačních pokynechopens in a new tab naleznete na této stránce.
Krok 8: Vytvoření projektu Hardhat
Uvnitř složky projektu hello-world spusťte:
1npx hardhatPoté by se vám měla zobrazit uvítací zpráva a možnost vybrat si, co chcete dělat. Vyberte „create an empty hardhat.config.js“:
1888 888 888 888 8882888 888 888 888 8883888 888 888 888 88848888888888 8888b. 888d888 .d88888 88888b. 8888b. 8888885888 888 "88b 888P" d88" 888 888 "88b "88b 8886888 888 .d888888 888 888 888 888 888 .d888888 8887888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.8888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888910👷 Vítejte v Hardhat v2.0.11 👷1112Co chcete udělat? …13Vytvořit vzorový projekt14❯ Vytvořit prázdný soubor hardhat.config.js15UkončitZobrazit všeTím se v projektu vygeneruje soubor hardhat.config.js. Ten použijeme později v tomto tutoriálu k určení nastavení našeho projektu.
Krok 9: Přidání složek projektu
Aby byl projekt přehledný, vytvoříme dvě nové složky. V příkazovém řádku přejděte do kořenového adresáře projektu hello-world a zadejte:
1mkdir contracts2mkdir scriptscontracts/je místo, kam uložíme soubor s kódem našeho chytrého kontraktu Hello Worldscripts/je místo, kam uložíme skripty pro nasazení našeho kontraktu a interakci s ním
Krok 10: Napsání našeho kontraktu
Možná si říkáte, kdy budeme psát kód? Je čas!
Otevřete si projekt hello-world ve svém oblíbeném editoru. Chytré kontrakty se nejčastěji píší v Solidity, který použijeme i my.
- Přejděte do složky
contractsa vytvořte nový soubor s názvemHelloWorld.sol - Níže je ukázka chytrého kontraktu Hello World, který budeme v tomto tutoriálu používat. Zkopírujte níže uvedený obsah do souboru
HelloWorld.sol.
Poznámka: Nezapomeňte si přečíst komentáře, abyste pochopili, co tento kontrakt dělá.
1// Určuje verzi Solidity pomocí sémantického verzování.2// Více informací: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma3pragma solidity >=0.7.3;45// Definuje kontrakt s názvem `HelloWorld`.6// Kontrakt je soubor funkcí a dat (jeho stav). Po nasazení se kontrakt nachází na určité adrese na blockchainu Ethereum. Více informací: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html7contract HelloWorld {89 // Emituje se při zavolání funkce update10 // Události chytrého kontraktu jsou způsob, jakým může váš kontrakt sdělit vašemu front-endu, že se na blockchainu něco stalo, což může „naslouchat“ určitým událostem a při jejich výskytu provést akci.11 event UpdatedMessages(string oldStr, string newStr);1213 // Deklaruje stavovou proměnnou `message` typu `string`.14 // Stavové proměnné jsou proměnné, jejichž hodnoty jsou trvale uloženy v úložišti kontraktu. Klíčové slovo `public` zpřístupňuje proměnné zvenčí kontraktu a vytváří funkci, kterou mohou volat jiné kontrakty nebo klienti pro přístup k hodnotě.15 string public message;1617 // Podobně jako v mnoha třídních objektově orientovaných jazycích je konstruktor speciální funkce, která se provádí pouze při vytvoření kontraktu.18 // Konstruktory se používají k inicializaci dat kontraktu. Více informací:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors19 constructor(string memory initMessage) {2021 // Přijímá řetězcový argument `initMessage` a nastavuje hodnotu do úložné proměnné kontraktu `message`).22 message = initMessage;23 }2425 // Veřejná funkce, která přijímá řetězcový argument a aktualizuje úložnou proměnnou `message`.26 function update(string memory newMessage) public {27 string memory oldMsg = message;28 message = newMessage;29 emit UpdatedMessages(oldMsg, newMessage);30 }31}Zobrazit všeJedná se o základní chytrý kontrakt, který při vytvoření ukládá zprávu. Lze jej aktualizovat voláním funkce update.
Krok 11: Připojení MetaMask a Alchemy k vašemu projektu
Vytvořili jsme si peněženku MetaMask, účet Alchemy a napsali jsme náš chytrý kontrakt, nyní je čas je všechny tři propojit.
Každá transakce odeslaná z vaší peněženky vyžaduje podpis s použitím vašeho jedinečného privátního klíče. Abychom programu toto oprávnění poskytli, můžeme náš privátní klíč bezpečně uložit do souboru prostředí. Zde také uložíme API klíč pro Alchemy.
Chcete-li se dozvědět více o odesílání transakcí, podívejte se na tento tutoriálopens in a new tab o odesílání transakcí pomocí Web3.
Nejprve nainstalujte balíček dotenv do adresáře vašeho projektu:
1npm install dotenv --savePoté vytvořte v kořenovém adresáři projektu soubor .env. Přidejte do něj svůj privátní klíč MetaMask a URL adresa Alchemy API pro HTTP.
Váš soubor prostředí se musí jmenovat .env, jinak nebude rozpoznán jako soubor prostředí.
Nenazývejte jej process.env ani .env-custom ani nijak jinak.
- Postupujte podle těchto pokynůopens in a new tab a exportujte svůj privátní klíč
- Níže naleznete postup, jak získat URL pro HTTP API Alchemy
Váš soubor .env by měl vypadat takto:
1API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key"2PRIVATE_KEY = "your-metamask-private-key"Abychom je skutečně propojili s naším kódem, budeme na tyto proměnné odkazovat v našem souboru hardhat.config.js v kroku 13.
Krok 12: Instalace Ethers.js
Ethers.js je knihovna, která usnadňuje interakci a zadávání požadavků na Ethereum tím, že obaluje standardní metody JSON-RPCopens in a new tab uživatelsky přívětivějšími metodami.
Hardhat umožňuje integrovat pluginyopens in a new tab pro další nástroje a rozšířenou funkčnost. Pro nasazení kontraktu využijeme plugin Ethersopens in a new tab.
V adresáři projektu zadejte:
npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0"Krok 13: Aktualizace souboru hardhat.config.js
Zatím jsme přidali několik závislostí a pluginů, nyní musíme aktualizovat hardhat.config.js, aby o nich náš projekt věděl.
Aktualizujte svůj soubor hardhat.config.js, aby vypadal takto:
1/**2 * @type import('hardhat/config').HardhatUserConfig3 */45require("dotenv").config()6require("@nomiclabs/hardhat-ethers")78const { API_URL, PRIVATE_KEY } = process.env910module.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}Zobrazit všeKrok 14: Kompilace našeho kontraktu
Abychom se ujistili, že zatím vše funguje, zkompilujeme si náš kontrakt. Úkol compile je jedním z vestavěných úkolů Hardhatu.
Z příkazového řádku spusťte:
npx hardhat compileMůže se zobrazit varování o SPDX license identifier not provided in source file, ale nemusíte se tím znepokojovat – doufejme, že vše ostatní vypadá dobře! Pokud ne, vždy můžete napsat zprávu na discordu Alchemyopens in a new tab.
Krok 15: Napsání našeho skriptu pro nasazení
Nyní, když je náš kontrakt napsán a náš konfigurační soubor je připraven, je čas napsat náš skript pro nasazení kontraktu.
Přejděte do složky scripts/, vytvořte nový soubor s názvem deploy.js a přidejte do něj následující obsah:
1async function main() {2 const HelloWorld = await ethers.getContractFactory("HelloWorld")34 // Spusťte nasazení, vrátí se promise, která se vyřeší na objekt kontraktu5 const hello_world = await HelloWorld.deploy("Hello World!")6 console.log("Contract deployed to address:", hello_world.address)7}89main()10 .then(() => process.exit(0))11 .catch((error) => {12 console.error(error)13 process.exit(1)14 })Zobrazit všeHardhat skvěle vysvětluje, co každý z těchto řádků kódu dělá ve svém výukovém programu Kontraktyopens in a new tab, a my jsme zde jejich vysvětlení převzali.
1const HelloWorld = await ethers.getContractFactory("HelloWorld")ContractFactory v ethers.js je abstrakce používaná k nasazení nových chytrých kontraktů, takže HelloWorld je zde továrnaopens in a new tab pro instance našeho kontraktu hello world. Při použití pluginu hardhat-ethers jsou instance ContractFactory a Contract ve výchozím nastavení připojeny k prvnímu podepisujícímu (vlastníkovi).
1const hello_world = await HelloWorld.deploy()Volání deploy() na ContractFactory spustí nasazení a vrátí Promise, která se vyřeší na objekt Contract. Toto je objekt, který má metodu pro každou z funkcí našeho chytrého kontraktu.
Krok 16: Nasazení našeho kontraktu
Konečně jsme připraveni nasadit náš chytrý kontrakt! Přejděte na příkazový řádek a spusťte:
npx hardhat run scripts/deploy.js --network goerliMěli byste pak vidět něco takového:
Kontrakt nasazen na adresu: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570Tuto adresu si prosím uložte. Budeme ji používat později v tomto tutoriálu.
Pokud přejdeme na Goerli Etherscanopens in a new tab a vyhledáme adresu našeho kontraktu, měli bychom vidět, že byl úspěšně nasazen. Transakce bude vypadat nějak takto:
Adresa From by se měla shodovat s adresou vašeho účtu MetaMask a v adrese To bude uvedeno Vytvoření kontraktu. Pokud klikneme na transakci, uvidíme v poli To adresu našeho kontraktu.
Výborně! Právě jste nasadili chytrý kontrakt do testovací sítě Ethereum.
Abyste pochopili, co se děje pod pokličkou, přejděte na kartu Průzkumník v našem řídicím panelu Alchemyopens in a new tab. Pokud máte více aplikací Alchemy, nezapomeňte filtrovat podle aplikace a vybrat Hello World.
Zde uvidíte několik metod JSON-RPC, které pro nás Hardhat/Ethers vytvořil pod pokličkou, když jsme volali funkci .deploy(). Dvě důležité metody jsou zde eth_sendRawTransactionopens in a new tab, což je požadavek na zapsání našeho kontraktu do chainu Goerli, a eth_getTransactionByHashopens in a new tab, což je požadavek na přečtení informací o naší transakci na základě daného haše. Chcete-li se dozvědět více o odesílání transakcí, podívejte se na náš tutoriál o odesílání transakcí pomocí Web3.
Část 2: Interakce s vaším chytrým kontraktem
Nyní, když jsme úspěšně nasadili chytrý kontrakt do sítě Goerli, se naučíme, jak s ním interagovat.
Vytvoření souboru interact.js
Toto je soubor, do kterého napíšeme náš interakční skript. Budeme používat knihovnu Ethers.js, kterou jste si nainstalovali v části 1.
Uvnitř složky scripts/ vytvořte nový soubor s názvem interact.js a přidejte následující kód:
1// interact.js23const API_KEY = process.env.API_KEY4const PRIVATE_KEY = process.env.PRIVATE_KEY5const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESSAktualizujte svůj soubor .env
Budeme používat nové proměnné prostředí, takže je musíme definovat v souboru .env, který jsme vytvořili dříve.
Budeme muset přidat definici pro náš Alchemy API_KEY a CONTRACT_ADDRESS, kde byl váš chytrý kontrakt nasazen.
Váš soubor .env by měl vypadat nějak takto:
# .envAPI_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>"Získání ABI kontraktu
Naše kontraktu je rozhraní pro interakci s naším chytrým kontraktem. Hardhat automaticky generuje ABI a ukládá ho do HelloWorld.json. Pro použití ABI budeme muset analyzovat obsah přidáním následujících řádků kódu do našeho souboru interact.js:
1// interact.js2const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")Pokud chcete vidět ABI, můžete si ho vytisknout do konzole:
1console.log(JSON.stringify(contract.abi))Abyste viděli své ABI vytištěné v konzoli, přejděte do terminálu a spusťte:
npx hardhat run scripts/interact.jsVytvoření instance vašeho kontraktu
Pro interakci s naším kontraktem musíme v našem kódu vytvořit instanci kontraktu. Abychom tak učinili s Ethers.js, budeme muset pracovat se třemi koncepty:
- Provider - poskytovatel uzlu, který vám dává přístup ke čtení a zápisu do blockchainu
- Signer - představuje účet Ethereum, který může podepisovat transakce
- Contract - objekt Ethers.js představující konkrétní kontrakt nasazený na blockchainu
K vytvoření naší instance kontraktu použijeme ABI kontraktu z předchozího kroku:
1// interact.js23// Provider4const alchemyProvider = new ethers.providers.AlchemyProvider(5 (network = "goerli"),6 API_KEY7)89// Signer10const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider)1112// Contract13const helloWorldContract = new ethers.Contract(14 CONTRACT_ADDRESS,15 contract.abi,16 signer17)Zobrazit všeVíce se o Providerech, Signerech a Kontraktech dozvíte v dokumentaci ethers.jsopens in a new tab.
Přečtěte si úvodní zprávu
Pamatujete si, když jsme nasadili náš kontrakt s initMessage = "Hello world!"? Nyní se chystáme přečíst zprávu uloženou v našem chytrém kontraktu a vytisknout ji do konzole.
V JavaScriptu se při interakci se sítěmi používají asynchronní funkce. Chcete-li se dozvědět více o asynchronních funkcích, přečtěte si tento článek na Mediumopens in a new tab.
Použijte níže uvedený kód pro volání funkce message v našem chytrém kontraktu a přečtení úvodní zprávy:
1// interact.js23// ...45async function main() {6 const message = await helloWorldContract.message()7 console.log("Zpráva zní: " + message)8}9main()Zobrazit všePo spuštění souboru pomocí npx hardhat run scripts/interact.js v terminálu bychom měli vidět tuto odpověď:
1Zpráva zní: Hello world!Výborně! Právě jste úspěšně přečetli data chytrého kontraktu z blockchainu Ethereum, skvělá práce!
Aktualizovat zprávu
Místo pouhého čtení zprávy můžeme také aktualizovat zprávu uloženou v našem chytrém kontraktu pomocí funkce update! Docela super, že?
Pro aktualizaci zprávy můžeme přímo zavolat funkci update na našem instancovaném objektu Contract:
1// interact.js23// ...45async function main() {6 const message = await helloWorldContract.message()7 console.log("Zpráva zní: " + message)89 console.log("Aktualizace zprávy...")10 const tx = await helloWorldContract.update("Toto je nová zpráva.")11 await tx.wait()12}13main()Zobrazit všeVšimněte si, že na řádku 11 voláme .wait() na vráceném objektu transakce. To zajišťuje, že náš skript počká, až se transakce vytěží na blockchainu, než opustí funkci. Pokud není zahrnuto volání .wait(), skript nemusí vidět aktualizovanou hodnotu message v kontraktu.
Přečtěte si novou zprávu
Měli byste být schopni zopakovat předchozí krok a přečíst aktualizovanou hodnotu message. Chvilku se zamyslete a zkuste provést změny potřebné k vytištění této nové hodnoty!
Pokud potřebujete nápovědu, takto by měl v tuto chvíli vypadat váš soubor interact.js:
1// interact.js23const API_KEY = process.env.API_KEY4const PRIVATE_KEY = process.env.PRIVATE_KEY5const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS67const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")89// provider - Alchemy10const alchemyProvider = new ethers.providers.AlchemyProvider(11 (network = "goerli"),12 API_KEY13)1415// signer - you16const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider)1718// instance kontraktu19const helloWorldContract = new ethers.Contract(20 CONTRACT_ADDRESS,21 contract.abi,22 signer23)2425async function main() {26 const message = await helloWorldContract.message()27 console.log("Zpráva zní: " + message)2829 console.log("Aktualizace zprávy...")30 const tx = await helloWorldContract.update("toto je nová zpráva")31 await tx.wait()3233 const newMessage = await helloWorldContract.message()34 console.log("Nová zpráva zní: " + newMessage)35}3637main()Zobrazit všeNyní stačí spustit skript a měli byste vidět starou zprávu, stav aktualizace a novou zprávu vytištěnou ve vašem terminálu!
npx hardhat run scripts/interact.js --network goerli
1Zpráva zní: Hello World!2Aktualizace zprávy...3Nová zpráva zní: Toto je nová zpráva.Při spouštění tohoto skriptu si můžete všimnout, že krok Updating the message... (Aktualizace zprávy...) chvíli trvá, než se načte nová zpráva. Je to kvůli procesu těžby; pokud jste zvědaví na sledování transakcí během jejich těžby, navštivte mempool Alchemyopens in a new tab a podívejte se na stav transakce. Pokud je transakce zrušena, je také užitečné zkontrolovat Goerli Etherscanopens in a new tab a vyhledat haš vaší transakce.
Část 3: Zveřejnění vašeho chytrého kontraktu na Etherscanu
Odvedli jste veškerou těžkou práci, abyste svůj chytrý kontrakt přivedli k životu; nyní je čas podělit se o něj se světem!
Ověřením vašeho chytrého kontraktu na Etherscanu si může kdokoli prohlédnout váš zdrojový kód a interagovat s vaším chytrým kontraktem. Začínáme!
Krok 1: Vygenerování API klíče na vašem účtu Etherscan
Klíč Etherscan API je nezbytný k ověření, že vlastníte chytrý kontrakt, který se pokoušíte publikovat.
Pokud ještě nemáte účet Etherscan, zaregistrujte si jejopens in a new tab.
Po přihlášení najděte své uživatelské jméno v navigační liště, najeďte na něj a vyberte tlačítko Můj profil.
Na stránce vašeho profilu byste měli vidět boční navigační lištu. Z boční navigační lišty vyberte API klíče. Dále stiskněte tlačítko „Přidat“ pro vytvoření nového API klíče, pojmenujte svou aplikaci hello-world a stiskněte tlačítko Vytvořit nový API klíč.
Váš nový API klíč by se měl objevit v tabulce API klíčů. Zkopírujte API klíč do schránky.
Dále musíme přidat Etherscan API klíč do našeho souboru .env.
Po jeho přidání by měl váš soubor .env vypadat takto:
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"Chytré kontrakty nasazené pomocí Hardhat
Instalace hardhat-etherscan
Publikování vašeho kontraktu na Etherscan pomocí Hardhat je jednoduché. Nejprve budete muset nainstalovat plugin hardhat-etherscan, abyste mohli začít. hardhat-etherscan automaticky ověří zdrojový kód a ABI chytrého kontraktu na Etherscanu. Pro jeho přidání spusťte v adresáři hello-world:
1npm install --save-dev @nomiclabs/hardhat-etherscanPo instalaci vložte následující příkaz na začátek souboru hardhat.config.js a přidejte možnosti konfigurace Etherscanu:
1// hardhat.config.js23require("dotenv").config()4require("@nomiclabs/hardhat-ethers")5require("@nomiclabs/hardhat-etherscan")67const { API_URL, PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env89module.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 // Váš API klíč pro Etherscan21 // Získejte jej na https://etherscan.io/22 apiKey: ETHERSCAN_API_KEY,23 },24}Zobrazit všeOvěření vašeho chytrého kontraktu na Etherscanu
Ujistěte se, že jsou všechny soubory uloženy a všechny proměnné v souboru .env jsou správně nakonfigurovány.
Spusťte úlohu verify, předejte adresu kontraktu a síť, kde je nasazen:
1npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS 'Hello World!'Ujistěte se, že DEPLOYED_CONTRACT_ADDRESS je adresa vašeho nasazeného chytrého kontraktu v testovací síti Goerli. Také poslední argument ('Hello World!') musí být stejná řetězcová hodnota, která byla použita během kroku nasazení v části 1.
Pokud vše půjde dobře, uvidíte ve svém terminálu následující zprávu:
1Zdrojový kód pro kontrakt byl úspěšně odeslán2contracts/HelloWorld.sol:HelloWorld na 0xdeployed-contract-address3k ověření na Etherscanu. Čekání na výsledek ověření...456Kontrakt HelloWorld byl úspěšně ověřen na Etherscanu.7https://goerli.etherscan.io/address/<contract-address>#contractsVýborně! Kód vašeho chytrého kontraktu je na Etherscanu!
Podívejte se na svůj chytrý kontrakt na Etherscanu!
Když přejdete na odkaz uvedený ve vašem terminálu, měli byste vidět svůj kód chytrého kontraktu a ABI publikované na Etherscanu!
Paráda – dokázali jste to, šampione! Nyní může kdokoli volat nebo zapisovat do vašeho chytrého kontraktu! Těšíme se, co postavíte příště!
Část 4 – Integrace vašeho chytrého kontraktu s frontendem
Na konci tohoto tutoriálu budete vědět, jak:
- Připojit peněženku MetaMask k vaší dapp
- Číst data z vašeho chytrého kontraktu pomocí Alchemy Web3opens in a new tab API
- Podepisovat transakce Ethereum pomocí MetaMask
Pro tuto dapp budeme jako frontendový framework používat Reactopens in a new tab; je však důležité si uvědomit, že nebudeme trávit mnoho času rozebíráním jeho základů, protože se budeme soustředit hlavně na přenesení funkčnosti Web3 do našeho projektu.
Jako předpoklad byste měli mít základní znalosti Reactu. Pokud ne, doporučujeme dokončit oficiální tutoriál Úvod do Reactuopens in a new tab.
Naklonujte si startovací soubory
Nejprve přejděte do GitHub repozitáře hello-world-part-fouropens in a new tab, abyste získali startovací soubory pro tento projekt, a naklonujte tento repozitář na váš lokální počítač.
Otevřete si naklonovaný repozitář lokálně. Všimněte si, že obsahuje dvě složky: starter-files a completed.
starter-files- budeme pracovat v tomto adresáři, propojíme UI s vaší peněženkou Ethereum a s chytrým kontraktem, který jsme publikovali na Etherscanu v Části 3.completedobsahuje celý dokončený tutoriál a měl by být použit pouze jako reference, pokud se zaseknete.
Dále si otevřete vaši kopii starter-files ve vašem oblíbeném editoru kódu a poté přejděte do složky src.
Veškerý kód, který napíšeme, bude umístěn ve složce src. Budeme upravovat komponentu HelloWorld.js a javascriptové soubory util/interact.js, abychom našemu projektu dodali funkčnost Web3.
Prozkoumejte startovací soubory
Než začneme kódovat, prozkoumejme, co nám startovací soubory poskytují.
Spusťte svůj projekt v Reactu
Začněme spuštěním projektu React v našem prohlížeči. Krása Reactu spočívá v tom, že jakmile náš projekt běží v prohlížeči, veškeré uložené změny se v prohlížeči projeví v reálném čase.
Aby projekt fungoval, přejděte do kořenového adresáře složky starter-files a spusťte v terminálu npm install pro instalaci závislostí projektu:
cd starter-filesnpm installJakmile se dokončí instalace, spusťte v terminálu npm start:
npm startTím by se měla ve vašem prohlížeči otevřít adresa http://localhost:3000/opens in a new tab, kde uvidíte frontend našeho projektu. Měl by se skládat z jednoho pole (místo pro aktualizaci zprávy uložené ve vašem chytrém kontraktu), tlačítka „Připojit peněženku“ a tlačítka „Aktualizovat“.
Pokud zkusíte kliknout na kterékoli tlačítko, zjistíte, že nefungují – je to proto, že jejich funkčnost musíme teprve naprogramovat.
Komponenta HelloWorld.js
Vraťme se zpět do složky src v našem editoru a otevřeme si soubor HelloWorld.js. Je nesmírně důležité, abychom všemu v tomto souboru rozuměli, protože se jedná o primární komponentu Reactu, na které budeme pracovat.
Na začátku tohoto souboru si všimnete, že máme několik importních příkazů, které jsou nezbytné pro spuštění našeho projektu, včetně knihovny React, hooků useEffect a useState, některých položek z ./util/interact.js (popíšeme je podrobněji brzy!) a loga Alchemy.
1// HelloWorld.js23import React from "react"4import { useEffect, useState } from "react"5import {6 helloWorldContract,7 connectWallet,8 updateMessage,9 loadCurrentMessage,10 getCurrentWalletConnected,11} from "./util/interact.js"1213import alchemylogo from "./alchemylogo.svg"Zobrazit všeDále máme naše stavové proměnné, které budeme aktualizovat po konkrétních událostech.
1// HelloWorld.js23//Stavové proměnné4const [walletAddress, setWallet] = useState("")5const [status, setStatus] = useState("")6const [message, setMessage] = useState("Žádné spojení se sítí.")7const [newMessage, setNewMessage] = useState("")Zde je, co každá proměnná představuje:
walletAddress– řetězec, který ukládá adresu peněženky uživatelestatus– řetězec, který uchovává užitečnou zprávu, jež uživatele navádí, jak s dapp interagovatmessage- řetězec, který ukládá aktuální zprávu v chytrém kontraktunewMessage- řetězec, který ukládá novou zprávu, která bude zapsána do chytrého kontraktu
Po stavových proměnných uvidíte pět neimplementovaných funkcí: useEffect ,addSmartContractListener, addWalletListener , connectWalletPressed a onUpdatePressed. Níže vysvětlíme, co dělají:
1// HelloWorld.js23//voláno pouze jednou4useEffect(async () => {5 //TODO: implement6}, [])78function addSmartContractListener() {9 //TODO: implement10}1112function addWalletListener() {13 //TODO: implement14}1516const connectWalletPressed = async () => {17 //TODO: implement18}1920const onUpdatePressed = async () => {21 //TODO: implement22}Zobrazit všeuseEffectopens in a new tab- toto je React hook, který se volá po vykreslení vaší komponenty. Protože má prázdné pole[]jako prop (viz řádek 4), bude volán pouze při prvním vykreslení komponenty. Zde načteme aktuální zprávu uloženou v našem chytrém kontraktu, zavoláme naše posluchače chytrého kontraktu a peněženky a aktualizujeme naše UI tak, aby odráželo, zda je peněženka již připojena.addSmartContractListener- tato funkce nastaví posluchače, který bude sledovat událostUpdatedMessagesnašeho kontraktu HelloWorld a aktualizuje naše UI, když se zpráva v našem chytrém kontraktu změní.addWalletListener- tato funkce nastaví posluchače, který detekuje změny ve stavu peněženky MetaMask uživatele, například když uživatel odpojí svou peněženku nebo přepne adresy.connectWalletPressed- tato funkce bude volána pro připojení peněženky MetaMask uživatele k naší dapp.onUpdatePressed– tato funkce bude volána, když uživatel bude chtít aktualizovat zprávu uloženou v chytrém kontraktu.
Na konci tohoto souboru máme uživatelské rozhraní naší komponenty.
1// HelloWorld.js23//UI naší komponenty4return (5 <div id="container">6 <img id="logo" src={alchemylogo}></img>7 <button id="walletButton" onClick={connectWalletPressed}>8 {walletAddress.length > 0 ? (9 "Připojeno: " +10 String(walletAddress).substring(0, 6) +11 "..." +12 String(walletAddress).substring(38)13 ) : (14 <span>Připojit peněženku</span>15 )}16 </button>1718 <h2 style={{ paddingTop: "50px" }}>Aktuální zpráva:</h2>19 <p>{message}</p>2021 <h2 style={{ paddingTop: "18px" }}>Nová zpráva:</h2>2223 <div>24 <input25 type="text"26 placeholder="Aktualizujte zprávu ve svém chytrém kontraktu."27 onChange={(e) => setNewMessage(e.target.value)}28 value={newMessage}29 />30 <p id="status">{status}</p>3132 <button id="publishButton" onClick={onUpdatePressed}>33 Aktualizovat34 </button>35</div>36 37</div>38)Zobrazit všePokud si tento kód pozorně prostudujete, zjistíte, kde v našem UI používáme naše různé stavové proměnné:
- Na řádcích 6-12, pokud je peněženka uživatele připojena (tj.
walletAddress.length > 0), zobrazíme zkrácenou verzi adresy uživatelewalletAddressv tlačítku s ID „walletButton;“ jinak se jednoduše zobrazí „Připojit peněženku“. - Na řádku 17 zobrazujeme aktuální zprávu uloženou v chytrém kontraktu, která je zachycena v řetězci
message. - Na řádcích 23-26 používáme řízenou komponentuopens in a new tab k aktualizaci naší stavové proměnné
newMessage, když se změní vstup v textovém poli.
Kromě našich stavových proměnných také uvidíte, že funkce connectWalletPressed a onUpdatePressed jsou volány při kliknutí na tlačítka s ID publishButton a walletButton.
Nakonec se podívejme, kam se tato komponenta HelloWorld.js přidává.
Pokud přejdete do souboru App.js, který je hlavní komponentou v Reactu a slouží jako kontejner pro všechny ostatní komponenty, uvidíte, že naše komponenta HelloWorld.js je vložena na řádku 7.
V neposlední řadě se podívejme na ještě jeden soubor, který máte k dispozici, a to interact.js.
Soubor interact.js
Protože se chceme řídit paradigmatem M-V-Copens in a new tab, budeme chtít samostatný soubor, který bude obsahovat všechny naše funkce pro správu logiky, dat a pravidel naší dapp, a poté budeme moci tyto funkce exportovat do našeho frontendu (naší komponenty HelloWorld.js).
👆🏽Toto je přesně účel našeho souboru interact.js!
Přejděte do složky util ve vašem adresáři src a všimnete si, že jsme zahrnuli soubor s názvem interact.js, který bude obsahovat všechny naše funkce a proměnné pro interakci s chytrým kontraktem a peněženkou.
1// interact.js23//export const helloWorldContract;45export const loadCurrentMessage = async () => {}67export const connectWallet = async () => {}89const getCurrentWalletConnected = async () => {}1011export const updateMessage = async (message) => {}Zobrazit všeNa začátku souboru si všimnete, že jsme zakomentovali objekt helloWorldContract. Později v tomto tutoriálu tento objekt odkomentujeme a instancujeme náš chytrý kontrakt do této proměnné, kterou pak exportujeme do naší komponenty HelloWorld.js.
Čtyři neimplementované funkce za naším objektem helloWorldContract dělají následující:
loadCurrentMessage– tato funkce se stará o logiku načítání aktuální zprávy uložené v chytrém kontraktu. Provede volání čtení na chytrý kontrakt Hello World pomocí Alchemy Web3 APIopens in a new tab.connectWallet- tato funkce připojí peněženku MetaMask uživatele k naší dapp.getCurrentWalletConnected– tato funkce zkontroluje, zda je účet Ethereum již připojen k naší dapp při načítání stránky a podle toho aktualizuje naše UI.updateMessage– tato funkce aktualizuje zprávu uloženou v chytrém kontraktu. Provede zápisové volání na chytrý kontrakt Hello World, takže peněženka MetaMask uživatele bude muset podepsat transakci Ethereum k aktualizaci zprávy.
Nyní, když rozumíme tomu, s čím pracujeme, pojďme zjistit, jak číst z našeho chytrého kontraktu!
Krok 3: Čtení z vašeho chytrého kontraktu
Chcete-li číst ze svého chytrého kontraktu, musíte úspěšně nastavit:
- API připojení k řetězci Ethereum
- Načtenou instanci vašeho chytrého kontraktu
- Funkci pro volání funkce vašeho chytrého kontraktu
- Posluchače pro sledování aktualizací, když se změní data, která čtete z chytrého kontraktu
To může znít jako mnoho kroků, ale nebojte se! Provedeme vás každým z nich krok za krokem! :)
Vytvoření API spojení s Ethereum chainem
Vzpomínáte si, jak jsme v části 2 tohoto tutoriálu použili náš Alchemy Web3 klíč k čtení z našeho chytrého kontraktuopens in a new tab? Ve své dapp budete také potřebovat klíč Alchemy Web3, abyste mohli číst z chainu.
Pokud jej ještě nemáte, nejprve si nainstalujte Alchemy Web3opens in a new tab tak, že přejdete do kořenového adresáře vašich starter-files a spustíte v terminálu následující příkaz:
1npm install @alch/alchemy-web3Alchemy Web3opens in a new tab je nadstavba nad Web3.jsopens in a new tab, která poskytuje vylepšené metody API a další klíčové výhody, které vám usnadní život vývojáře web3. Je navržen tak, aby vyžadoval minimální konfiguraci, takže jej můžete ve své aplikaci začít používat okamžitě!
Poté nainstalujte balíček dotenvopens in a new tab do adresáře svého projektu, abychom měli bezpečné místo pro uložení našeho API klíče po jeho získání.
1npm install dotenv --savePro naši dapp budeme používat náš API klíč pro Websockets namísto našeho API klíče pro HTTP, protože nám to umožní nastavit posluchače, který detekuje, kdy se změní zpráva uložená v chytrém kontraktu.
Jakmile budete mít svůj API klíč, vytvořte v kořenovém adresáři soubor .env a přidejte do něj svou Alchemy Websockets URL. Poté by měl váš soubor .env vypadat takto:
1REACT_APP_ALCHEMY_KEY = wss://eth-goerli.ws.alchemyapi.io/v2/<key>Nyní jsme připraveni nastavit náš Alchemy Web3 endpoint v naší dapp! Vraťme se k našemu souboru interact.js, který je vnořený do naší složky util a přidejme následující kód na začátek souboru:
1// interact.js23require("dotenv").config()4const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY5const { createAlchemyWeb3 } = require("@alch/alchemy-web3")6const web3 = createAlchemyWeb3(alchemyKey)78//export const helloWorldContract;Výše jsme nejprve importovali klíč Alchemy z našeho souboru .env a poté jsme předali náš alchemyKey do createAlchemyWeb3, abychom vytvořili náš Alchemy Web3 endpoint.
S tímto připraveným koncovým bodem je čas načíst náš chytrý kontrakt!
Načítání vašeho chytrého kontraktu Hello World
K načtení vašeho chytrého kontraktu Hello World budete potřebovat jeho adresu kontraktu a ABI, obojí lze najít na Etherscanu, pokud jste dokončili Část 3 tohoto tutoriálu.
Jak získat ABI kontraktu z Etherscanu
Pokud jste přeskočili Část 3 tohoto tutoriálu, můžete použít kontrakt HelloWorld s adresou 0x6f3f635A9762B47954229Ea479b4541eAF402A6Aopens in a new tab. Jeho ABI lze nalézt zdeopens in a new tab.
ABI kontraktu je nezbytné pro určení, kterou funkci bude kontrakt volat, a také pro zajištění, že funkce vrátí data ve formátu, který očekáváte. Jakmile jsme zkopírovali naše ABI kontraktu, uložme ho jako JSON soubor s názvem contract-abi.json do vašeho adresáře src.
Váš contract-abi.json by měl být uložen ve složce src.
Vyzbrojeni adresou kontraktu, ABI a Alchemy Web3 koncovým bodem můžeme použít metodu kontraktuopens in a new tab k načtení instance našeho chytrého kontraktu. Importujte ABI vašeho kontraktu do souboru interact.js a přidejte adresu svého kontraktu.
1// interact.js23const contractABI = require("../contract-abi.json")4const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A"Nyní můžeme konečně odkomentovat naši proměnnou helloWorldContract a načíst chytrý kontrakt pomocí našeho koncového bodu AlchemyWeb3:
1// interact.js2export const helloWorldContract = new web3.eth.Contract(3 contractABI,4 contractAddress5)Abychom to shrnuli, prvních 12 řádků vašeho souboru interact.js by nyní mělo vypadat takto:
1// interact.js23require("dotenv").config()4const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY5const { createAlchemyWeb3 } = require("@alch/alchemy-web3")6const web3 = createAlchemyWeb3(alchemyKey)78const contractABI = require("../contract-abi.json")9const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A"1011export const helloWorldContract = new web3.eth.Contract(12 contractABI,13 contractAddress14)Zobrazit všeNyní, když máme náš kontrakt načtený, můžeme implementovat naši funkci loadCurrentMessage!
Implementace loadCurrentMessage ve vašem souboru interact.js
Tato funkce je super jednoduchá. Provedeme jednoduché asynchronní volání web3 pro čtení z našeho kontraktu. Naše funkce vrátí zprávu uloženou v chytrém kontraktu:
Aktualizujte loadCurrentMessage ve vašem souboru interact.js na následující:
1// interact.js23export const loadCurrentMessage = async () => {4 const message = await helloWorldContract.methods.message().call()5 return message6}Protože chceme zobrazit tento chytrý kontrakt v našem UI, aktualizujme funkci useEffect v naší komponentě HelloWorld.js na následující:
1// HelloWorld.js23//voláno pouze jednou4useEffect(async () => {5 const message = await loadCurrentMessage()6 setMessage(message)7}, [])Všimněte si, že chceme, aby byla naše funkce loadCurrentMessage volána pouze jednou během prvního vykreslení komponenty. Brzy implementujeme addSmartContractListener pro automatickou aktualizaci UI po změně zprávy v chytrém kontraktu.
Než se pustíme do našeho posluchače, podívejme se, co jsme zatím dokázali! Uložte si soubory HelloWorld.js a interact.js a přejděte na http://localhost:3000/opens in a new tab
Všimnete si, že aktuální zpráva již neříká „Žádné spojení se sítí“. Místo toho odráží zprávu uloženou v chytrém kontraktu. Super!
Vaše UI by nyní mělo odrážet zprávu uloženou v chytrém kontraktu
A teď k tomu posluchači...
Implementace addSmartContractListener
Pokud si vzpomenete na soubor HelloWorld.sol, který jsme napsali v části 1 této série tutoriálůopens in a new tab, vzpomenete si, že existuje událost chytrého kontraktu s názvem UpdatedMessages, která je emitována po vyvolání funkce update našeho chytrého kontraktu (viz řádky 9 a 27):
1// HelloWorld.sol23// Určuje verzi Solidity pomocí sémantického verzování.4// Více informací: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma5pragma solidity ^0.7.3;67// Definuje kontrakt s názvem `HelloWorld`.8// Kontrakt je soubor funkcí a dat (jeho stav). Po nasazení se kontrakt nachází na určité adrese na blockchainu Ethereum. Více informací: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html9contract HelloWorld {1011 // Emituje se při zavolání funkce update12 // Události chytrého kontraktu jsou způsob, jakým může váš kontrakt sdělit vašemu front-endu, že se na blockchainu něco stalo, což může „naslouchat“ určitým událostem a při jejich výskytu provést akci.13 event UpdatedMessages(string oldStr, string newStr);1415 // Deklaruje stavovou proměnnou `message` typu `string`.16 // Stavové proměnné jsou proměnné, jejichž hodnoty jsou trvale uloženy v úložišti kontraktu. Klíčové slovo `public` zpřístupňuje proměnné zvenčí kontraktu a vytváří funkci, kterou mohou volat jiné kontrakty nebo klienti pro přístup k hodnotě.17 string public message;1819 // Podobně jako v mnoha třídních objektově orientovaných jazycích je konstruktor speciální funkce, která se provádí pouze při vytvoření kontraktu.20 // Konstruktory se používají k inicializaci dat kontraktu. Více informací:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors21 constructor(string memory initMessage) {2223 // Přijímá řetězcový argument `initMessage` a nastavuje hodnotu do úložné proměnné kontraktu `message`).24 message = initMessage;25 }2627 // Veřejná funkce, která přijímá řetězcový argument a aktualizuje úložnou proměnnou `message`.28 function update(string memory newMessage) public {29 string memory oldMsg = message;30 message = newMessage;31 emit UpdatedMessages(oldMsg, newMessage);32 }33}Zobrazit všeUdálosti chytrého kontraktu jsou způsob, jakým může váš kontrakt komunikovat, že se na blockchainu něco stalo (tj. došlo k události) vaší front-endové aplikaci, která může „naslouchat“ konkrétním událostem a při jejich výskytu provádět akce.
Funkce addSmartContractListener bude specificky naslouchat události UpdatedMessages našeho chytrého kontraktu Hello World a aktualizovat naše UI, aby zobrazilo novou zprávu.
Upravte addSmartContractListener na následující:
1// HelloWorld.js23function 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("🎉 Vaše zpráva byla aktualizována!")11 }12 })13}Zobrazit všePojďme si rozebrat, co se stane, když posluchač detekuje událost:
- Pokud dojde k chybě při emisi události, projeví se to v UI prostřednictvím naší stavové proměnné
status. - V opačném případě použijeme vrácený objekt
data.data.returnValuesje pole indexované od nuly, kde první prvek pole ukládá předchozí zprávu a druhý prvek ukládá aktualizovanou. Celkově při úspěšné události nastavíme náš řetězecmessagena aktualizovanou zprávu, vymažeme řetězecnewMessagea aktualizujeme naši stavovou proměnnoustatus, aby odrážela, že byla na našem chytrém kontraktu publikována nová zpráva.
Nakonec zavoláme našeho posluchače ve funkci useEffect, aby byl inicializován při prvním vykreslení komponenty HelloWorld.js. Celkově by vaše funkce useEffect měla vypadat takto:
1// HelloWorld.js23useEffect(async () => {4 const message = await loadCurrentMessage()5 setMessage(message)6 addSmartContractListener()7}, [])Nyní, když umíme číst z našeho chytrého kontraktu, bylo by skvělé zjistit, jak do něj také zapisovat! Abychom však mohli do naší dapp zapisovat, musíme k ní mít nejprve připojenou peněženku Ethereum.
Takže dále se budeme zabývat nastavením naší peněženky Ethereum (MetaMask) a jejím připojením k naší dapp!
Krok 4: Nastavení vaší peněženky Ethereum
Aby mohli uživatelé cokoliv zapsat na Ethereum chain, musí podepisovat transakce pomocí privátních klíčů své virtuální peněženky. Pro tento tutoriál použijeme MetaMaskopens in a new tab, virtuální peněženku v prohlížeči, která slouží ke správě vaší adresy účtu Ethereum, protože to pro koncového uživatele velmi usnadňuje podepisování transakcí.
Pokud chcete lépe porozumět tomu, jak fungují transakce na Ethereu, podívejte se na tuto stránku od Nadace Ethereum.
Stáhněte si MetaMask
Účet MetaMask si můžete zdarma stáhnout a vytvořit zdeopens in a new tab. Při vytváření účtu nebo pokud již účet máte, nezapomeňte se vpravo nahoře přepnout na „testovací síť Goerli“ (abychom nepracovali se skutečnými penězi).
Přidání etheru z faucetu
K podepsání transakce na blockchainu Ethereum budeme potřebovat nějaký falešný ETH. Pro získání ETH můžete jít na FaucETHopens in a new tab a zadat adresu svého účtu Goerli, kliknout na „Požádat o prostředky“, poté v rozevíracím seznamu vybrat „Ethereum Testnet Goerli“ a nakonec znovu kliknout na tlačítko „Požádat o prostředky“. Krátce poté byste měli vidět Eth ve svém účtu MetaMask!
Zkontrolujte si zůstatek
Abychom si ověřili, že náš zůstatek je k dispozici, proveďte požadavek eth_getBalanceopens in a new tab pomocí nástroje Composer od Alchemyopens in a new tab. Tím získáte množství Eth ve vaší peněžence. Po zadání adresy vašeho účtu MetaMask a kliknutí na „Send Request“ byste měli vidět takovouto odpověď:
1{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}POZNÁMKA: Tento výsledek je ve wei, nikoli v eth. Wei se používá jako nejmenší denominace etheru. Převod z wei na eth je: 1 eth = 10¹⁸ wei. Takže pokud převedeme 0xde0b6b3a7640000 na desetinné číslo, dostaneme 1*10¹⁸, což se rovná 1 eth.
Uf! Naše falešné peníze jsou všechny tam! 🤑
Krok 5: Připojení MetaMask k vašemu UI
Nyní, když je naše peněženka MetaMask nastavena, připojme k ní naši dapp!
Funkce connectWallet
V našem souboru interact.js implementujeme funkci connectWallet, kterou pak můžeme zavolat v naší komponentě HelloWorld.js.
Upravme connectWallet na následující:
1// interact.js23export 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: "👆🏽 Napište zprávu do textového pole výše.",11 address: addressArray[0],12 }13 return obj14 } 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 Musíte si do prohlížeče nainstalovat MetaMask, virtuální peněženku Ethereum.2930 </p>3132 ),33 }34 }35}Zobrazit všeCo přesně tedy tento obrovský blok kódu dělá?
Nejprve zkontroluje, zda je ve vašem prohlížeči povoleno window.ethereum.
window.ethereum je globální API, které vkládá MetaMask a další poskytovatelé peněženek a které webovým stránkám umožňuje žádat o účty uživatelů Etherea. Pokud je schváleno, může číst data z blockchainů, ke kterým je uživatel připojen, a navrhovat uživateli podepisování zpráv a transakcí. Pro více informací se podívejte do dokumentace MetaMaskuopens in a new tab!
Pokud window.ethereum není přítomno, znamená to, že MetaMask není nainstalován. Výsledkem je vrácení objektu JSON, kde vrácená adresa je prázdný řetězec a objekt JSX status sděluje, že uživatel si musí nainstalovat MetaMask.
Pokud window.ethereum je přítomno, pak to začne být zajímavé.
Pomocí smyčky try/catch se pokusíme připojit k MetaMasku voláním window.ethereum.request({ method: \"eth_requestAccounts\" });opens in a new tab. Volání této funkce otevře MetaMask v prohlížeči, kde bude uživatel vyzván k připojení své peněženky k vaší dapp.
- Pokud se uživatel rozhodne připojit,
method: "eth_requestAccounts"vrátí pole obsahující všechny adresy účtů uživatele, které se k dapp připojily. Celkově naše funkceconnectWalletvrátí objekt JSON, který obsahuje prvníadresuv tomto poli (viz řádek 9) a zprávustatus, která vyzve uživatele k napsání zprávy do chytrého kontraktu. - Pokud uživatel spojení odmítne, objekt JSON bude obsahovat prázdný řetězec pro vrácenou
adresua zprávustatus, která odráží, že uživatel spojení odmítl.
Nyní, když jsme napsali tuto funkci connectWallet, je dalším krokem její zavolání v naší komponentě HelloWorld.js.
Přidání funkce connectWallet do vaší UI komponenty HelloWorld.js
Přejděte na funkci connectWalletPressed v HelloWorld.js a aktualizujte ji na následující:
1// HelloWorld.js23const connectWalletPressed = async () => {4 const walletResponse = await connectWallet()5 setStatus(walletResponse.status)6 setWallet(walletResponse.address)7}Všimli jste si, jak je většina naší funkčnosti abstrahována od naší komponenty HelloWorld.js do souboru interact.js? To proto, abychom dodrželi paradigma M-V-C!
V connectWalletPressed jednoduše provedeme await volání naší importované funkce connectWallet a pomocí její odpovědi aktualizujeme naše proměnné status a walletAddress prostřednictvím jejich stavových háků (hooks).
Nyní si oba soubory (HelloWorld.js a interact.js) uložme a otestujme naše UI.
Otevřete si prohlížeč na stránce http://localhost:3000/opens in a new tab a stiskněte tlačítko „Připojit peněženku“ vpravo nahoře.
Pokud máte nainstalovaný MetaMask, měli byste být vyzváni k připojení své peněženky k vaší dapp. Přijměte výzvu k připojení.
Měli byste vidět, že tlačítko peněženky nyní ukazuje, že je vaše adresa připojena! Super! 🔥
Dále zkuste obnovit stránku... to je divné. Naše tlačítko peněženky nás vyzývá k připojení MetaMasku, i když už je připojen...
Ale žádný strach! To snadno vyřešíme (chápete?). implementací getCurrentWalletConnected, která zkontroluje, zda je adresa již připojena k naší dapp, a podle toho aktualizuje naše UI!
Funkce getCurrentWalletConnected
Aktualizujte svou funkci getCurrentWalletConnected v souboru interact.js na následující:
1// interact.js23export 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: "👆🏽 Napište zprávu do textového pole výše.",13 }14 } else {15 return {16 address: "",17 status: "🦊 Připojte se k MetaMask pomocí tlačítka vpravo nahoře.",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 Musíte si do prohlížeče nainstalovat MetaMask, virtuální peněženku Ethereum.3536 </p>3738 ),39 }40 }41}Zobrazit všeTento kód je velmi podobný funkci connectWallet, kterou jsme právě napsali v předchozím kroku.
Hlavní rozdíl je v tom, že místo volání metody eth_requestAccounts, která otevře MetaMask, aby si uživatel mohl připojit svou peněženku, zde voláme metodu eth_accounts, která jednoduše vrací pole obsahující adresy MetaMask aktuálně připojené k naší dapp.
Abychom tuto funkci viděli v akci, zavoláme ji ve funkci useEffect naší komponenty HelloWorld.js:
1// HelloWorld.js23useEffect(async () => {4 const message = await loadCurrentMessage()5 setMessage(message)6 addSmartContractListener()78 const { address, status } = await getCurrentWalletConnected()9 setWallet(address)10 setStatus(status)11}, [])Zobrazit všeVšimněte si, že odpověď z našeho volání getCurrentWalletConnected používáme k aktualizaci našich stavových proměnných walletAddress a status.
Nyní, když jste přidali tento kód, zkusme obnovit okno našeho prohlížeče.
Paráda! Tlačítko by mělo hlásit, že jste připojeni, a zobrazovat náhled adresy vaší připojené peněženky – i po obnovení!
Implementace addWalletListener
Posledním krokem v nastavení peněženky naší dapp je implementace posluchače peněženky, aby se naše uživatelské rozhraní aktualizovalo, když se změní stav naší peněženky, například když se uživatel odpojí nebo přepne účty.
Ve vašem souboru HelloWorld.js upravte svou funkci addWalletListener na následující:
1// HelloWorld.js23function addWalletListener() {4 if (window.ethereum) {5 window.ethereum.on("accountsChanged", (accounts) => {6 if (accounts.length > 0) {7 setWallet(accounts[0])8 setStatus("👆🏽 Napište zprávu do textového pole výše.")9 } else {10 setWallet("")11 setStatus("🦊 Připojte se k MetaMask pomocí tlačítka vpravo nahoře.")12 }13 })14 } else {15 setStatus(16 <p>17 {" "}18 🦊 <a target="_blank" href={`https://metamask.io/download`}>19 Musíte si do prohlížeče nainstalovat MetaMask, virtuální peněženku Ethereum.2021 </p>22 )23 }24}Zobrazit všeVsadím se, že už ani nepotřebujete naši pomoc, abyste pochopili, co se zde děje, ale pro úplnost si to rychle rozebereme:
- Nejprve naše funkce zkontroluje, zda je
window.ethereumpovoleno (tj. zda je MetaMask nainstalován).- Pokud není, jednoduše nastavíme naši stavovou proměnnou
statusna řetězec JSX, který uživatele vyzve k instalaci MetaMasku. - Pokud je povoleno, nastavíme na řádku 3 posluchače
window.ethereum.on(\"accountsChanged\"), který naslouchá změnám stavu v peněžence MetaMask, což zahrnuje případy, kdy uživatel připojí další účet k dapp, přepne účty nebo odpojí účet. Pokud je připojen alespoň jeden účet, stavová proměnnáwalletAddressse aktualizuje jako první účet v poliaccountsvráceném posluchačem. V opačném případě jewalletAddressnastaveno jako prázdný řetězec.
- Pokud není, jednoduše nastavíme naši stavovou proměnnou
V neposlední řadě ji musíme zavolat v naší funkci useEffect:
1// HelloWorld.js23useEffect(async () => {4 const message = await loadCurrentMessage()5 setMessage(message)6 addSmartContractListener()78 const { address, status } = await getCurrentWalletConnected()9 setWallet(address)10 setStatus(status)1112 addWalletListener()13}, [])Zobrazit všeA to je vše! Úspěšně jsme dokončili programování veškeré funkčnosti naší peněženky! Nyní k našemu poslednímu úkolu: aktualizaci zprávy uložené v našem chytrém kontraktu!
Krok 6: Implementace funkce updateMessage
Tak jo, lidi, jsme v cílové rovince! Ve funkci updateMessage vašeho souboru interact.js uděláme následující:
- Ujistěte se, že zpráva, kterou chceme publikovat v našem chytrém kontraktu, je platná
- Podepište naši transakci pomocí MetaMask
- Zavolejte tuto funkci z naší frontendové komponenty
HelloWorld.js
Nebude to trvat dlouho; pojďme tuto dapp dokončit!
Zpracování chyb na vstupu
Je přirozené, že na začátku funkce je nějaké zpracování chyb vstupů.
Budeme chtít, aby se naše funkce vrátila dříve, pokud není nainstalováno rozšíření MetaMask, není připojena žádná peněženka (tj. předaná adresa je prázdný řetězec) nebo je zpráva prázdný řetězec. Přidejme následující zpracování chyb do updateMessage:
1// interact.js23export const updateMessage = async (address, message) => {4 if (!window.ethereum || address === null) {5 return {6 status:7 "💡 Připojte svou peněženku MetaMask pro aktualizaci zprávy na blockchainu.",8 }9 }1011 if (message.trim() === "") {12 return {13 status: "❌ Vaše zpráva nemůže být prázdný řetězec.",14 }15 }16}Zobrazit všeNyní, když máme správné zpracování chyb vstupů, je čas podepsat transakci přes MetaMask!
Podepisování naší transakce
Pokud jste již obeznámeni s tradičními web3 Ethereum transakcemi, kód, který napíšeme dále, vám bude velmi povědomý. Pod kód pro zpracování chyb vstupů přidejte do updateMessage následující:
1// interact.js23//nastavení parametrů transakce4const transactionParameters = {5 to: contractAddress, // Vyžadováno kromě publikací kontraktů.6 from: address, // musí se shodovat s aktivní adresou uživatele.7 data: helloWorldContract.methods.update(message).encodeABI(),8}910//podepsání transakce11try {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 Zobrazte stav své transakce na Etherscanu!2223 <br />24 ℹ️ Jakmile bude transakce ověřena sítí, zpráva bude25 aktualizována automaticky.2627 ),28 }29} catch (error) {30 return {31 status: "😥 " + error.message,32 }33}Zobrazit všeRozeberme si, co se děje. Nejprve nastavíme parametry naší transakce, kde:
tourčuje adresu příjemce (náš chytrý kontrakt)fromurčuje podepisujícího transakce, proměnnouaddress, kterou jsme předali do naší funkcedataobsahuje volání metodyupdatenašeho chytrého kontraktu Hello World, která přijímá naši řetězcovou proměnnoumessagejako vstup
Poté provedeme await volání window.ethereum.request, kde požádáme MetaMask o podepsání transakce. Všimněte si, že na řádcích 11 a 12 určujeme naši metodu eth, eth_sendTransaction, a předáváme naše transactionParameters.
V tomto okamžiku se v prohlížeči otevře MetaMask a vyzve uživatele k podepsání nebo zamítnutí transakce.
- Pokud je transakce úspěšná, funkce vrátí JSON objekt, kde
statusJSX řetězec vyzve uživatele, aby se podíval na Etherscan pro více informací o své transakci. - Pokud transakce selže, funkce vrátí JSON objekt, kde řetězec
statuspředá chybovou zprávu.
Celkově by naše funkce updateMessage měla vypadat takto:
1// interact.js23export const updateMessage = async (address, message) => {4 //zpracování chyb vstupů5 if (!window.ethereum || address === null) {6 return {7 status:8 "💡 Připojte svou peněženku MetaMask pro aktualizaci zprávy na blockchainu.",9 }10 }1112 if (message.trim() === "") {13 return {14 status: "❌ Vaše zpráva nemůže být prázdný řetězec.",15 }16 }1718 //nastavení parametrů transakce19 const transactionParameters = {20 to: contractAddress, // Vyžadováno kromě publikací kontraktů.21 from: address, // musí se shodovat s aktivní adresou uživatele.22 data: helloWorldContract.methods.update(message).encodeABI(),23 }2425 //podepsání transakce26 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 Zobrazte stav své transakce na Etherscanu!3738 <br />39 ℹ️ Jakmile bude transakce ověřena sítí, zpráva bude40 aktualizována automaticky.4142 ),43 }44 } catch (error) {45 return {46 status: "😥 " + error.message,47 }48 }49}Zobrazit všeV neposlední řadě musíme naši funkci updateMessage propojit s naší komponentou HelloWorld.js.
Propojení updateMessage s frontendem HelloWorld.js
Naše funkce onUpdatePressed by měla provést await volání na importovanou funkci updateMessage a upravit stavovou proměnnou status, aby odrážela, zda naše transakce uspěla nebo selhala:
1// HelloWorld.js23const onUpdatePressed = async () => {4 const { status } = await updateMessage(walletAddress, newMessage)5 setStatus(status)6}Je to super čisté a jednoduché. A hádejte co... VAŠE DAPP JE HOTOVÁ!!!
Jděte do toho a otestujte tlačítko Aktualizovat!
Vytvořte si vlastní dapp
Skvělé, dostali jste se až na konec tutoriálu! Abychom to shrnuli, naučili jste se:
- Připojit peněženku MetaMask k vašemu projektu dapp
- Číst data z vašeho chytrého kontraktu pomocí Alchemy Web3opens in a new tab API
- Podepisovat transakce Ethereum pomocí MetaMask
Nyní jste plně vybaveni k tomu, abyste dovednosti z tohoto tutoriálu uplatnili při vytváření vlastního projektu dapp! Jako vždy, pokud máte nějaké otázky, neváhejte se na nás obrátit s žádostí o pomoc na Discordu Alchemyopens in a new tab. 🧙♂️
Jakmile dokončíte tento tutoriál, dejte nám vědět, jaké byly vaše zkušenosti, nebo pokud máte nějakou zpětnou vazbu, tak nás označte na Twitteru @alchemyplatformopens in a new tab!
Stránka naposledy aktualizována: 25. února 2026





