Přejít na hlavní obsah

Výukový program: Ražení NFT

Solidity
NFT
Alchemy
chytré kontrakty
frontend
Pinata
erc-721
Středně pokročilý
smudgil
6. října 2021
26 minut čtení

Jednou z největších výzev pro vývojáře přicházející z prostředí Web2 je přijít na to, jak propojit chytrý kontrakt s frontendovým projektem a jak s ním interagovat.

Vytvořením aplikace pro ražení NFT – jednoduchého uživatelského rozhraní, kam můžete zadat odkaz na své digitální aktivum, název a popis – se naučíte, jak:

  • Připojit se k MetaMasku přes váš frontendový projekt
  • Volat metody chytrého kontraktu z vašeho frontendu
  • Podepisovat transakce pomocí MetaMasku

V tomto návodu budeme používat React (opens in a new tab) jako náš frontendový framework. Protože je tento návod primárně zaměřen na vývoj ve Web3, nebudeme trávit mnoho času rozebíráním základů Reactu. Místo toho se zaměříme na přidání funkcionality do našeho projektu.

Jako předpoklad byste měli mít začátečnické znalosti Reactu – vědět, jak fungují komponenty, props, useState/useEffect a základní volání funkcí. Pokud jste o žádném z těchto pojmů nikdy neslyšeli, možná byste se měli podívat na tento Úvod do Reactu (opens in a new tab). Pro ty, kteří se raději učí vizuálně, vřele doporučujeme tuto vynikající sérii videí Full Modern React Tutorial (opens in a new tab) od Net Ninja.

A pokud ho ještě nemáte, budete k dokončení tohoto návodu a k budování čehokoli na blockchainu rozhodně potřebovat účet na Alchemy. Zaregistrujte si bezplatný účet zde (opens in a new tab).

Bez dalších okolků, pojďme na to!

Základy tvorby NFT

Než se vůbec začneme dívat na nějaký kód, je důležité pochopit, jak tvorba NFT funguje. Zahrnuje to dva kroky:

Nasazení chytrého kontraktu pro NFT na blockchain Ethereum

Největší rozdíl mezi těmito dvěma standardy chytrých kontraktů pro NFT je ten, že ERC-1155 je multi-tokenový standard a zahrnuje dávkové funkce, zatímco ERC-721 je standard pro jeden token, a proto podporuje převod pouze jednoho tokenu najednou.

Volání funkce pro ražení

Obvykle tato funkce pro ražení vyžaduje, abyste předali dvě proměnné jako parametry: první je recipient, která specifikuje adresu, jež obdrží vaše čerstvě vyražené NFT, a druhou je tokenURI daného NFT, což je řetězec, který odkazuje na JSON dokument popisující metadata NFT.

Metadata NFT jsou tím, co mu skutečně vdechuje život, protože mu umožňují mít vlastnosti, jako je název, popis, obrázek (nebo jiné digitální aktivum) a další atributy. Zde je příklad tokenURI (opens in a new tab), který obsahuje metadata NFT.

V tomto návodu se zaměříme na část 2, volání funkce pro ražení chytrého kontraktu pro NFT pomocí našeho uživatelského rozhraní v Reactu.

Budete potřebovat chytrý kontrakt pro NFT standardu ERC-721 nasazený na podporovaném testnetu, jako je Sepolia. Pokud byste si chtěli nasadit vlastní, doporučujeme průvodce od Alchemy pro nasazení chytrého kontraktu na síť Sepolia (opens in a new tab).

Skvělé, teď když rozumíme tomu, jak tvorba NFT funguje, pojďme si naklonovat naše startovací soubory!

Klonování startovacích souborů

Nejprve přejděte do GitHub repozitáře nft-minter-tutorial (opens in a new tab), kde získáte startovací soubory pro tento projekt. Naklonujte si tento repozitář do svého lokálního prostředí.

Když otevřete tento naklonovaný repozitář nft-minter-tutorial, všimnete si, že obsahuje dvě složky: minter-starter-files a nft-minter.

  • minter-starter-files obsahuje startovací soubory (v podstatě uživatelské rozhraní v Reactu) pro tento projekt. V tomto návodu budeme pracovat v tomto adresáři, protože se naučíte, jak toto uživatelské rozhraní oživit jeho propojením s vaší peněženkou Ethereum a chytrým kontraktem pro NFT.
  • nft-minter obsahuje celý dokončený návod a slouží jako reference, pokud se zaseknete.

Dále otevřete svou kopii minter-starter-files ve své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 Minter.js a psát další soubory v JavaScriptu, abychom našemu projektu dodali funkcionalitu Web3.

Krok 2: Prozkoumání startovacích souborů

Než začneme programovat, je důležité se podívat, co už máme ve startovacích souborech připraveno.

Spuštění projektu v Reactu

Začněme spuštěním projektu v Reactu v našem prohlížeči. Krása Reactu spočívá v tom, že jakmile máme projekt spuštěný v prohlížeči, jakékoli změny, které uložíme, se v prohlížeči živě aktualizují.

Chcete-li projekt spustit, přejděte do kořenového adresáře složky minter-starter-files a ve svém terminálu spusťte npm install, abyste nainstalovali závislosti projektu:

cd minter-starter-files
npm install

Jakmile se instalace dokončí, spusťte ve svém terminálu npm start:

npm start

Tím by se mělo ve vašem prohlížeči otevřít http://localhost:3000/ (opens in a new tab), kde uvidíte frontend našeho projektu. Měl by se skládat ze 3 polí: místa pro zadání odkazu na aktivum vašeho NFT, zadání názvu vašeho NFT a poskytnutí popisu.

Pokud zkusíte kliknout na tlačítka „Connect Wallet“ nebo „Mint NFT“, všimnete si, že nefungují – to proto, že jejich funkcionalitu musíme teprve naprogramovat! :)

Komponenta Minter.js

POZNÁMKA: Ujistěte se, že jste ve složce minter-starter-files a ne ve složce nft-minter!

Vraťme se v našem editoru do složky src a otevřeme soubor Minter.js. Je nesmírně důležité, abychom všemu v tomto souboru rozuměli, protože se jedná o primární komponentu v Reactu, na které budeme pracovat.

Na začátku tohoto souboru máme naše stavové proměnné, které budeme aktualizovat po specifických událostech.

//Stavové proměnné
const [walletAddress, setWallet] = useState("")
const [status, setStatus] = useState("")
const [name, setName] = useState("")
const [description, setDescription] = useState("")
const [url, setURL] = useState("")

Nikdy jste neslyšeli o stavových proměnných nebo stavových hoocích v Reactu? Podívejte se na tuto (opens in a new tab) dokumentaci.

Zde je to, co jednotlivé proměnné představují:

  • walletAddress - řetězec, který ukládá adresu peněženky uživatele
  • status - řetězec, který obsahuje zprávu k zobrazení ve spodní části uživatelského rozhraní
  • name - řetězec, který ukládá název NFT
  • description - řetězec, který ukládá popis NFT
  • url - řetězec, který je odkazem na digitální aktivum NFT

Za stavovými proměnnými uvidíte tři neimplementované funkce: useEffect, connectWalletPressed a onMintPressed. Všimnete si, že všechny tyto funkce jsou async, to proto, že v nich budeme provádět asynchronní volání API! Jejich názvy odpovídají jejich funkcionalitě:

  • useEffect (opens in a new tab) - toto je hook v Reactu, který se volá po vykreslení vaší komponenty. Protože je do něj předáno prázdné pole [] (viz řádek 3), bude zavolán pouze při prvním vykreslení komponenty. Zde zavoláme náš posluchač peněženky a další funkci peněženky, abychom aktualizovali naše uživatelské rozhraní tak, aby odráželo, zda je peněženka již připojena.
  • connectWalletPressed - tato funkce bude zavolána pro připojení peněženky MetaMask uživatele k naší decentralizované aplikaci (dapp).
  • onMintPressed - tato funkce bude zavolána pro vyražení NFT uživatele.

Blízko konce tohoto souboru máme uživatelské rozhraní naší komponenty. Pokud si tento kód pečlivě prohlédnete, všimnete si, že aktualizujeme naše stavové proměnné url, name a description, když se změní vstup v jejich odpovídajících textových polích.

Také uvidíte, že connectWalletPressed a onMintPressed jsou volány při kliknutí na tlačítka s ID mintButton a walletButton.

Nakonec se podívejme, kam je tato komponenta Minter přidána.

Pokud přejdete do souboru App.js, což je hlavní komponenta v Reactu, která funguje jako kontejner pro všechny ostatní komponenty, uvidíte, že naše komponenta Minter je vložena na řádku 7.

V tomto návodu budeme upravovat pouze Minter.js file a přidávat soubory do naší složky src.

Nyní, když rozumíme tomu, s čím pracujeme, pojďme si nastavit naši peněženku Ethereum!

Nastavení vaší peněženky Ethereum

Aby uživatelé mohli interagovat s vaším chytrým kontraktem, budou muset připojit svou peněženku Ethereum k vaší dapp.

Stažení MetaMasku

Pro tento návod použijeme MetaMask, virtuální peněženku v prohlížeči, která se používá ke správě adresy vašeho účtu na Ethereu. Pokud chcete lépe porozumět tomu, jak fungují transakce na Ethereu, podívejte se na tuto stránku.

MetaMask si můžete stáhnout a vytvořit si účet zdarma zde (opens in a new tab). Při vytváření účtu, nebo pokud již účet máte, se ujistěte, že jste přepnuli na podporovaný testnet, jako je Sepolia (abychom nepracovali se skutečnými penězi).

Přidání etheru z faucetu

Abychom mohli razit naše NFT (nebo podepisovat jakékoli transakce na blockchainu Etherea), budeme potřebovat nějaké testovací ETH. Chcete-li získat testnet ETH, použijte udržovaný faucet, jako je faucet Alchemy Sepolia (opens in a new tab), a zadejte adresu svého účtu na síti Sepolia. Brzy poté byste měli vidět ETH na svém účtu MetaMask! Abychom si ověřili, že tam náš zůstatek je, vytvořme požadavek eth_getBalance (opens in a new tab) pomocí nástroje sandbox od Alchemy (opens in a new tab). To vrátí množství ETH v naší peněžence. Poté, co zadáte adresu svého účtu MetaMask a kliknete na „Send Request“, měli byste vidět podobnou odpověď:

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

POZNÁMKA: Tento výsledek je ve Wei, ne v ETH. Wei se používá jako nejmenší jednotka etheru. Převod z Wei na ETH je: 1 ETH = 10¹⁸ Wei. Pokud tedy převedeme 0xde0b6b3a7640000 do desítkové soustavy, dostaneme 1*10¹⁸, což se rovná 1 ETH.

Uf! Naše falešné peníze tam všechny jsou!

Připojení MetaMasku k vašemu uživatelskému rozhraní

Nyní, když je naše peněženka MetaMask nastavena, pojďme k ní připojit naši dapp!

Protože se chceme držet paradigmatu MVC (opens in a new tab), vytvoříme samostatný soubor, který bude obsahovat naše funkce pro správu logiky, dat a pravidel naší dapp, a poté tyto funkce předáme našemu frontendu (naší komponentě Minter.js).

Funkce connectWallet

Za tímto účelem vytvořme novou složku s názvem utils ve vašem adresáři src a přidejme do ní soubor s názvem interact.js, který bude obsahovat všechny naše funkce pro interakci s peněženkou a chytrým kontraktem.

V našem souboru interact.js napíšeme funkci connectWallet, kterou pak naimportujeme a zavoláme v naší komponentě Minter.js.

Do vašeho souboru interact.js přidejte následující:

Pojďme si rozebrat, co tento kód dělá:

Nejprve naše funkce zkontroluje, zda je ve vašem prohlížeči povoleno window.ethereum.

window.ethereum je globální API vkládané MetaMaskem a dalšími poskytovateli peněženek, které umožňuje webovým stránkám vyžadovat účty uživatelů na Ethereu. Pokud je to 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 MetaMasku (opens in a new tab)!

Pokud window.ethereum není přítomno, znamená to, že MetaMask není nainstalován. Výsledkem je vrácení JSON objektu, kde vrácená address je prázdný řetězec a JSX objekt status sděluje, že si uživatel musí nainstalovat MetaMask.

Většina funkcí, které napíšeme, bude vracet JSON objekty, které můžeme použít k aktualizaci našich stavových proměnných a uživatelského rozhraní.

Pokud je window.ethereum přítomno, pak začíná být situace zajímavá.

Pomocí bloku try/catch se pokusíme připojit k MetaMasku zavoláním window.ethereum.request({ method: "eth_requestAccounts" }); (opens in a new tab). Zavolání této funkce otevře MetaMask v prohlížeči, čímž 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, které obsahuje všechny adresy účtů uživatele, které jsou připojeny k dapp. Celkově naše funkce connectWallet vrátí JSON objekt, který obsahuje první address v tomto poli (viz řádek 9) a zprávu status, která vyzývá uživatele k napsání zprávy do chytrého kontraktu.
  • Pokud uživatel připojení odmítne, pak JSON objekt bude obsahovat prázdný řetězec pro vrácenou address a zprávu status, která odráží, že uživatel připojení odmítl.

Přidání funkce connectWallet do vaší UI komponenty Minter.js

Nyní, když jsme napsali tuto funkci connectWallet, pojďme ji připojit k naší komponentě Minter.js..

Nejprve budeme muset naimportovat naši funkci do našeho souboru Minter.js přidáním import { connectWallet } from "./utils/interact.js"; na začátek souboru Minter.js. Vašich prvních 11 řádků v Minter.js by nyní mělo vypadat takto:

Poté uvnitř naší funkce connectWalletPressed zavoláme naši naimportovanou funkci connectWallet takto:

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

Všimli jste si, jak je většina naší funkcionality abstrahována od naší komponenty Minter.js do souboru interact.js? To proto, abychom dodrželi paradigma M-V-C!

V connectWalletPressed jednoduše provedeme volání s await na naši naimportovanou funkci connectWallet a pomocí její odpovědi aktualizujeme naše proměnné status a walletAddress prostřednictvím jejich stavových hooků.

Nyní uložme oba soubory Minter.js a interact.js a otestujme naše dosavadní uživatelské rozhraní.

Otevřete svůj prohlížeč na localhost:3000 a stiskněte tlačítko „Connect Wallet“ vpravo nahoře na stránce.

Pokud máte nainstalovaný MetaMask, měli byste být vyzváni k připojení vaší peněženky k vaší dapp. Přijměte výzvu k připojení.

Měli byste vidět, že tlačítko peněženky nyní odráží, že je vaše adresa připojena.

Dále zkuste obnovit stránku... to je zvláštní. Naše tlačítko peněženky nás vyzývá k připojení MetaMasku, i když už je připojen...

Ale nebojte se! Můžeme to snadno opravit implementací funkce zvané getCurrentWalletConnected, která zkontroluje, zda je adresa již připojena k naší dapp, a podle toho aktualizuje naše uživatelské rozhraní!

Funkce getCurrentWalletConnected

Do vašeho souboru interact.js přidejte následující funkci getCurrentWalletConnected:

Tento kód je velmi podobný funkci connectWallet, kterou jsme napsali dříve.

Hlavní rozdíl je v tom, že místo volání metody eth_requestAccounts, která otevře MetaMask, aby uživatel mohl připojit svou peněženku, zde voláme metodu eth_accounts, která jednoduše vrátí pole obsahující adresy MetaMasku aktuálně připojené k naší dapp.

Abychom viděli tuto funkci v akci, zavolejme ji ve funkci useEffect naší komponenty Minter.js.

Stejně jako jsme to udělali pro connectWallet, musíme tuto funkci naimportovat z našeho souboru interact.js do našeho souboru Minter.js takto:

import { useEffect, useState } from "react"
import {
  connectWallet,
  getCurrentWalletConnected, //importujte zde
} from "./utils/interact.js"

Nyní ji jednoduše zavoláme v naší funkci useEffect:

useEffect(async () => {
  const { address, status } = await getCurrentWalletConnected()
  setWallet(address)
  setStatus(status)
}, [])

Všimněte si, že používáme odpověď našeho volání getCurrentWalletConnected k aktualizaci našich stavových proměnných walletAddress a status.

Jakmile tento kód přidáte, zkuste obnovit okno prohlížeče. Tlačítko by mělo říkat, že jste připojeni, a zobrazovat náhled adresy vaší připojené peněženky – a to 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.

Do vašeho souboru Minter.js přidejte funkci addWalletListener, která vypadá následovně:

Pojďme si v rychlosti rozebrat, co se zde děje:

  • Nejprve naše funkce zkontroluje, zda je povoleno window.ethereum (tj. zda je nainstalován MetaMask).
    • Pokud není, jednoduše nastavíme naši stavovou proměnnou status na JSX řetězec, který vyzývá uživatele k instalaci MetaMasku.
    • Pokud je povoleno, nastavíme na řádku 3 posluchač window.ethereum.on("accountsChanged"), který naslouchá změnám stavu v peněžence MetaMask, což zahrnuje situace, kdy uživatel připojí k dapp další účet, přepne účty nebo účet odpojí. Pokud je připojen alespoň jeden účet, stavová proměnná walletAddress se aktualizuje jako první účet v poli accounts vráceném posluchačem. V opačném případě je walletAddress nastavena jako prázdný řetězec.

Nakonec ji musíme zavolat v naší funkci useEffect:

useEffect(async () => {
  const { address, status } = await getCurrentWalletConnected()
  setWallet(address)
  setStatus(status)

  addWalletListener()
}, [])

A voilà! Dokončili jsme programování veškeré funkcionality naší peněženky! Nyní, když je naše peněženka nastavena, pojďme přijít na to, jak vyrazit naše NFT!

Základy metadat NFT

Vzpomeňte si na metadata NFT, o kterých jsme právě mluvili v Kroku 0 tohoto návodu – vdechují NFT život a umožňují mu mít vlastnosti, jako je digitální aktivum, název, popis a další atributy.

Tato metadata budeme muset nakonfigurovat jako JSON objekt a uložit je, abychom je mohli předat jako parametr tokenURI při volání funkce mintNFT našeho chytrého kontraktu.

Text v polích „Link to Asset“ (Odkaz na aktivum), „Name“ (Název) a „Description“ (Popis) bude tvořit různé vlastnosti metadat našeho NFT. Tato metadata naformátujeme jako JSON objekt, ale existuje několik možností, kam můžeme tento JSON objekt uložit:

  • Mohli bychom ho uložit na blockchain Ethereum; to by však bylo velmi drahé.
  • Mohli bychom ho uložit na centralizovaný server, jako je AWS nebo Firebase. To by ale popřelo náš étos decentralizace.
  • Mohli bychom použít IPFS, decentralizovaný protokol a peer-to-peer síť pro ukládání a sdílení dat v distribuovaném souborovém systému. Vzhledem k tomu, že je tento protokol decentralizovaný a zdarma, je to naše nejlepší možnost!

K uložení našich metadat na IPFS použijeme Pinata (opens in a new tab), pohodlné API a sadu nástrojů pro IPFS. V dalším kroku si přesně vysvětlíme, jak na to!

Použití Pinata k připnutí vašich metadat na IPFS

Pokud nemáte účet na Pinata (opens in a new tab), zaregistrujte si bezplatný účet zde (opens in a new tab) a dokončete kroky k ověření vašeho e-mailu a účtu.

Vytvoření vašeho API klíče Pinata

Přejděte na stránku https://pinata.cloud/keys (opens in a new tab), poté vyberte tlačítko „New Key“ nahoře, nastavte widget Admin jako povolený a pojmenujte svůj klíč.

Poté se vám zobrazí vyskakovací okno s informacemi o vašem API. Ujistěte se, že si je uložíte na bezpečné místo.

Nyní, když je náš klíč nastaven, pojďme ho přidat do našeho projektu, abychom ho mohli používat.

Vytvoření souboru .env

Náš klíč a tajný klíč (secret) pro Pinata můžeme bezpečně uložit do souboru s proměnnými prostředí. Pojďme si do adresáře vašeho projektu nainstalovat balíček dotenv (opens in a new tab).

Otevřete si novou kartu ve svém terminálu (oddělenou od té, kde běží localhost) a ujistěte se, že jste ve složce minter-starter-files, poté ve svém terminálu spusťte následující příkaz:

npm install dotenv --save

Dále vytvořte soubor .env v kořenovém adresáři vaší složky minter-starter-files zadáním následujícího příkazu do příkazového řádku:

vim.env

Tím se otevře váš soubor .env ve vimu (textovém editoru). Chcete-li jej uložit, stiskněte na klávesnici v tomto pořadí „esc“ + „:“ + „q“.

Dále ve VSCode přejděte do svého souboru .env a přidejte do něj svůj API klíč a tajný klíč pro Pinata takto:

REACT_APP_PINATA_KEY = <pinata-api-key>
REACT_APP_PINATA_SECRET = <pinata-api-secret>

Uložte soubor a pak jste připraveni začít psát funkci pro nahrání vašich JSON metadat na IPFS!

Implementace pinJSONToIPFS

Naštěstí pro nás má Pinata API speciálně pro nahrávání JSON dat na IPFS (opens in a new tab) a praktický příklad v JavaScriptu s axios, který můžeme s drobnými úpravami použít.

Ve vaší složce utils vytvořme další soubor s názvem pinata.js a poté naimportujme náš tajný klíč a klíč pro Pinata ze souboru .env takto:

require("dotenv").config()
const key = process.env.REACT_APP_PINATA_KEY
const secret = process.env.REACT_APP_PINATA_SECRET

Dále vložte do svého souboru pinata.js další kód z níže uvedeného příkladu. Nebojte se, rozebereme si, co všechno znamená!

Co tedy tento kód přesně dělá?

Nejprve importuje axios (opens in a new tab), HTTP klienta založeného na promises pro prohlížeč a Node.js, kterého použijeme k vytvoření požadavku na Pinata.

Pak tu máme naši asynchronní funkci pinJSONToIPFS, která jako svůj vstup přijímá JSONBody a v hlavičce má API klíč a tajný klíč pro Pinata, to vše za účelem vytvoření POST požadavku na jejich API pinJSONToIPFS.

  • Pokud je tento POST požadavek úspěšný, pak naše funkce vrátí JSON objekt s booleovskou hodnotou success jako true a pinataUrl, kam byla naše metadata připnuta. Tuto vrácenou pinataUrl použijeme jako vstup tokenURI pro funkci ražení našeho chytrého kontraktu.
  • Pokud tento POST požadavek selže, pak naše funkce vrátí JSON objekt s booleovskou hodnotou success jako false a řetězcem message, který předává naši chybu.

Stejně jako u návratových typů naší funkce connectWallet vracíme JSON objekty, abychom mohli použít jejich parametry k aktualizaci našich stavových proměnných a uživatelského rozhraní.

Načtení vašeho chytrého kontraktu

Nyní, když máme způsob, jak nahrát naše metadata NFT na IPFS prostřednictvím naší funkce pinJSONToIPFS, budeme potřebovat způsob, jak načíst instanci našeho chytrého kontraktu, abychom mohli zavolat jeho funkci mintNFT.

Jak jsme zmínili dříve, v tomto návodu budeme používat tento existující chytrý kontrakt pro NFT (opens in a new tab); pokud byste se však chtěli dozvědět, jak jsme ho vytvořili, nebo si vytvořit vlastní, vřele doporučujeme podívat se na náš další návod „Jak vytvořit NFT“ (opens in a new tab).

ABI kontraktu

Pokud jste naše soubory prozkoumali podrobně, všimli jste si, že v našem adresáři src je soubor contract-abi.json. ABI je nezbytné pro specifikaci toho, kterou funkci kontrakt vyvolá, a také pro zajištění toho, že funkce vrátí data ve formátu, který očekáváte.

Budeme také potřebovat API klíč Alchemy a Alchemy Web3 API, abychom se připojili k blockchainu Ethereum a načetli náš chytrý kontrakt.

Vytvoření vašeho API klíče Alchemy

Pokud ještě nemáte účet na Alchemy, zaregistrujte se zdarma zde. (opens in a new tab)

Jakmile si vytvoříte účet na Alchemy, můžete si vygenerovat API klíč vytvořením aplikace. To nám umožní odesílat požadavky do testnetu Sepolia.

Přejděte na stránku „Create App“ na vašem řídicím panelu Alchemy tak, že najedete myší na „Apps“ v navigačním panelu a kliknete na „Create App“.

Pojmenujte svou aplikaci (my jsme zvolili „My First NFT!“), přidejte krátký popis, vyberte „Staging“ pro prostředí (Environment) používané pro evidenci vaší aplikace a jako vaši síť zvolte „Sepolia“.

Klikněte na „Create app“ a to je vše! Vaše aplikace by se měla objevit v tabulce níže.

Skvělé, takže teď, když jsme vytvořili naši HTTP URL adresu pro Alchemy API, zkopírujte si ji do schránky...

…a pak ji přidejme do našeho souboru .env. Celkově by váš soubor .env měl vypadat takto:

REACT_APP_PINATA_KEY = <pinata-key>
REACT_APP_PINATA_SECRET = <pinata-secret>
REACT_APP_ALCHEMY_KEY = https://eth-sepolia.g.alchemy.com/v2/<alchemy-key>

Nyní, když máme ABI našeho kontraktu a náš API klíč Alchemy, jsme připraveni načíst náš chytrý kontrakt pomocí Alchemy Web3 (opens in a new tab).

Nastavení vašeho endpointu Alchemy Web3 a kontraktu

Nejprve, pokud ho ještě nemáte, budete si muset nainstalovat Alchemy Web3 (opens in a new tab) přechodem do domovského adresáře: nft-minter-tutorial v terminálu:

cd ..
npm install @alch/alchemy-web3

Dále se vraťme k našemu souboru interact.js. Na začátek souboru přidejte následující kód pro import vašeho klíče Alchemy ze souboru .env a nastavení vašeho endpointu Alchemy Web3:

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

Alchemy Web3 (opens in a new tab) je wrapper kolem Web3.js (opens in a new tab), který poskytuje vylepšené metody API a další klíčové výhody, které vám usnadní život jako vývojáři ve Web3. Je navržen tak, aby vyžadoval minimální konfiguraci, takže jej můžete začít používat ve své aplikaci hned!

Dále přidejme do našeho souboru ABI kontraktu a adresu kontraktu.

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

const contractABI = require("../contract-abi.json")
const contractAddress = "0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE"

Jakmile máme obojí, jsme připraveni začít programovat naši funkci pro ražení!

Implementace funkce mintNFT

Uvnitř vašeho souboru interact.js definujme naši funkci mintNFT, která, jak název napovídá, vyrazí naše NFT.

Protože budeme provádět četná asynchronní volání (na Pinata pro připnutí našich metadat na IPFS, na Alchemy Web3 pro načtení našeho chytrého kontraktu a na MetaMask pro podepsání našich transakcí), bude naše funkce také asynchronní.

Třemi vstupy do naší funkce budou url našeho digitálního aktiva, name a description. Přidejte následující signaturu funkce pod funkci connectWallet:

export const mintNFT = async (url, name, description) => {}

Zpracování chyb vstupu

Přirozeně dává smysl mít na začátku funkce nějaké zpracování chyb vstupu, abychom tuto funkci opustili, pokud naše vstupní parametry nejsou správné. Uvnitř naší funkce přidejme následující kód:

V podstatě, pokud je některý ze vstupních parametrů prázdný řetězec, pak vrátíme JSON objekt, kde je booleovská hodnota success false a řetězec status sděluje, že všechna pole v našem uživatelském rozhraní musí být vyplněna.

Nahrání metadat na IPFS

Jakmile víme, že jsou naše metadata správně naformátována, dalším krokem je zabalit je do JSON objektu a nahrát je na IPFS prostřednictvím funkce pinJSONToIPFS, kterou jsme napsali!

K tomu musíme nejprve naimportovat funkci pinJSONToIPFS do našeho souboru interact.js. Úplně na začátek souboru interact.js přidejme:

import { pinJSONToIPFS } from "./pinata.js"

Připomeňme si, že pinJSONToIPFS přijímá tělo ve formátu JSON. Takže předtím, než ji zavoláme, budeme muset naformátovat naše parametry url, name a description do JSON objektu.

Aktualizujme náš kód tak, abychom vytvořili JSON objekt s názvem metadata a poté zavolali pinJSONToIPFS s tímto parametrem metadata:

Všimněte si, že odpověď našeho volání pinJSONToIPFS(metadata) ukládáme do objektu pinataResponse. Poté tento objekt analyzujeme na případné chyby.

Pokud dojde k chybě, vrátíme JSON objekt, kde je booleovská hodnota success false a náš řetězec status sděluje, že naše volání selhalo. V opačném případě extrahujeme pinataURL z pinataResponse a uložíme ji jako naši proměnnou tokenURI.

Nyní je čas načíst náš chytrý kontrakt pomocí Alchemy Web3 API, které jsme inicializovali na začátku našeho souboru. Přidejte následující řádek kódu na konec funkce mintNFT, abyste nastavili kontrakt do globální proměnné window.contract:

window.contract = await new web3.eth.Contract(contractABI, contractAddress)

Poslední věc, kterou musíme přidat do naší funkce mintNFT, je naše transakce na Ethereu:

Pokud jste již obeznámeni s transakcemi na Ethereu, všimnete si, že struktura je docela podobná tomu, co jste už viděli.

  • Nejprve nastavíme parametry naší transakce.
    • to specifikuje adresu příjemce (náš chytrý kontrakt)
    • from specifikuje podepisujícího transakce (připojenou adresu uživatele k MetaMasku: window.ethereum.selectedAddress)
    • data obsahuje volání metody mintNFT našeho chytrého kontraktu, která jako vstupy přijímá naši tokenURI a adresu peněženky uživatele, window.ethereum.selectedAddress
  • Poté provedeme volání s await, window.ethereum.request,, kde požádáme MetaMask o podepsání transakce. Všimněte si, že v tomto požadavku specifikujeme naši eth metodu (eth_SentTransaction) 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 odmítnutí transakce.
    • Pokud je transakce úspěšná, funkce vrátí JSON objekt, kde je booleovská hodnota success nastavena na true a řetězec status vyzývá 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 je booleovská hodnota success nastavena na false a řetězec status předává chybovou zprávu.

Celkově by naše funkce mintNFT měla vypadat takto:

To je ale obrovská funkce! Nyní už jen musíme připojit naši funkci mintNFT k naší komponentě Minter.js...

Připojení mintNFT k našemu frontendu Minter.js

Otevřete svůj soubor Minter.js a aktualizujte řádek import { connectWallet, getCurrentWalletConnected } from "./utils/interact.js"; nahoře takto:

import {
  connectWallet,
  getCurrentWalletConnected,
  mintNFT,
} from "./utils/interact.js"

Nakonec implementujte funkci onMintPressed, abyste provedli volání s await na vaši naimportovanou funkci mintNFT a aktualizovali stavovou proměnnou status tak, aby odrážela, zda naše transakce byla úspěšná nebo selhala:

const onMintPressed = async () => {
  const { status } = await mintNFT(url, name, description)
  setStatus(status)
}

Vezměte blockchainový svět útokem

Dělám si legraci, dostali jste se na konec návodu!

Abychom to shrnuli, vytvořením aplikace pro ražení NFT jste se úspěšně naučili, jak:

  • Připojit se k MetaMasku přes váš frontendový projekt
  • Volat metody chytrého kontraktu z vašeho frontendu
  • Podepisovat transakce pomocí MetaMasku

Pravděpodobně byste se chtěli pochlubit NFT vyraženými prostřednictvím vaší dapp ve vaší peněžence – takže se určitě podívejte na náš rychlý návod Jak si zobrazit NFT ve vaší peněžence!

A jako vždy, pokud máte nějaké dotazy, jsme tu, abychom vám pomohli na Discordu Alchemy (opens in a new tab). Nemůžeme se dočkat, až uvidíme, jak koncepty z tohoto návodu uplatníte ve svých budoucích projektech!