Přeskočit na hlavní obsah

Návod na minter pro NFT

solidity
NFT
alchemy
chytré kontrakty
frontend
Pinata
Středně pokročilý
smudgil
6. října 2021
26 minuta č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 pracovat s ním.

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

  • Připojit se k MetaMasku prostřednictvím vašeho frontendového projektu
  • Volat metody chytrého kontraktu z vašeho frontendu
  • Podepisovat transakce pomocí MetaMasku

V tomto návodu budeme jako náš frontendový framework používat Reactopens in a new tab. Protože se tento návod zaměřuje především na vývoj pro Web3, nebudeme trávit mnoho času rozebíráním základů Reactu. Místo toho se zaměříme na to, abychom našemu projektu dodali funkcionalitu.

Předpokladem je, že byste měli mít základní 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á se budete chtít podívat na tento návod Úvod do Reactuopens in a new tab. Těm, kteří se učí spíše vizuálně, vřele doporučujeme tuto vynikající sérii videí Kompletní moderní návod na Reactopens in a new tab od Net Ninja.

A pokud ho ještě nemáte, budete k dokončení tohoto návodu a k vytváření čehokoli na blockchainu určitě potřebovat účet Alchemy. Zaregistrujte si bezplatný účet zdeopens in a new tab.

Bez dalších okolků se do toho pusťme!

Tvorba NFT 101

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

Zveřejnění chytrého kontraktu NFT na blockchainu Ethereum

Největší rozdíl mezi dvěma standardy chytrých kontraktů pro NFT je ten, že ERC-1155 je standard pro více tokenů a zahrnuje dávkovou funkcionalitu, zatímco ERC-721 je standard pro jeden token, a proto podporuje pouze přenos jednoho tokenu najednou.

Volání funkce mintování

Obvykle tato funkce mintování vyžaduje, abyste jako parametry předali dvě proměnné: zaprvé recipient, která určuje adresu, jež obdrží vaše nově namintované NFT, a zadruhé tokenURI NFT, což je řetězec, který odkazuje na dokument JSON popisující metadata NFT.

Metadata NFT jsou to, co ho skutečně oživuje a umožňuje mu mít vlastnosti, jako je název, popis, obrázek (nebo jiné digitální aktivum) a další atributy. Zde je příklad tokenURIopens in a new tab, které obsahuje metadata NFT.

V tomto návodu se zaměříme na část 2, volání funkce mintování existujícího chytrého kontraktu NFT pomocí našeho uživatelského rozhraní React.

Zde je odkazopens in a new tab na chytrý kontrakt ERC-721 NFT, který budeme v tomto návodu volat. Pokud byste se chtěli dozvědět, jak jsme ho vytvořili, vřele doporučujeme podívat se na náš další návod, "Jak vytvořit NFT"opens in a new tab.

Super, teď když chápeme, jak funguje tvorba NFT, naklonujme si naše startovací soubory!

Naklonujte si startovací soubory

Nejprve přejděte do GitHub repozitáře nft-minter-tutorialopens in a new tab, abyste získali startovací soubory pro tento projekt. Naklonujte 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í React) pro tento projekt. V tomto návodu budeme pracovat v tomto adresáři, kde se naučíte, jak toto uživatelské rozhraní oživit připojením k vaší peněžence Ethereum a chytrému kontraktu NFT.
  • nft-minter obsahuje celý dokončený návod a je vám k dispozici jako reference, pokud se zaseknete.

Dále otevřete svou kopii minter-starter-files v 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ší javascriptové soubory, abychom našemu projektu dodali funkcionalitu Web3.

Krok 2: Prohlédněte si naše startovací soubory

Než začneme kódovat, je důležité si prohlédnout, co je pro nás již připraveno ve startovacích souborech.

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.

Chcete-li projekt spustit, přejděte do kořenového adresáře složky minter-starter-files a spusťte v terminálu příkaz npm install pro instalaci závislostí projektu:

cd minter-starter-files
npm install

Jakmile se dokončí instalace, spusťte v terminálu npm start:

npm start

Tím by se vám měl v 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ísto pro zadání odkazu na aktivum vašeho NFT, zadání názvu vašeho NFT a poskytnutí popisu.

Pokud se pokusíte kliknout na tlačítka „Připojit peněženku“ nebo „Mintovat NFT“, zjistíte, že nefungují – to proto, že jejich funkcionalitu musíme teprve naprogramovat! :)

Komponenta Minter.js

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

Vraťme se do složky src v našem editoru a otevřete 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 Reactu, na které budeme pracovat.

V horní části tohoto souboru máme naše stavové proměnné, které budeme aktualizovat po konkrétních událostech.

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

Nikdy jste neslyšeli o stavových proměnných Reactu nebo stavových hácích (hooks)? Podívejte se na tutoopens in a new tab dokumentaci.

Zde je přehled toho, 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í v dolní čá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

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

1useEffect(async () => {
2 //TODO: implementovat
3}, [])
4
5const connectWalletPressed = async () => {
6 //TODO: implementovat
7}
8
9const onMintPressed = async () => {
10 //TODO: implementovat
11}
Zobrazit vše
  • useEffectopens in a new tab – toto je React hook, který se volá po vykreslení vaší komponenty. Protože má předanou prázdnou rekvizitu pole [] (viz řádek 3), bude volána 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 volána pro připojení peněženky MetaMask uživatele k naší dapp.
  • onMintPressed – tato funkce bude volána pro mintování NFT uživatele.

Na konci tohoto souboru máme uživatelské rozhraní naší komponenty. Pokud si tento kód pečlivě projdete, všimnete si, že aktualizujeme naše stavové proměnné url, name a description při změně vstupu v jejich odpovídajících textových polích.

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

1//uživatelské rozhraní naší komponenty
2return (
3 <div className="Minter">
4 <button id="walletButton" onClick={connectWalletPressed}>
5 {walletAddress.length > 0 ? (
6 "Připojeno: " +
7 String(walletAddress).substring(0, 6) +
8 "..." +
9 String(walletAddress).substring(38)
10 ) : (
11 <span>Připojit peněženku</span>
12 )}
13 </button>
14
15 <br></br>
16 <h1 id="title">🧙‍♂️ Minter NFT od Alchemy</h1>
17 <p>
18 Jednoduše přidejte odkaz na své aktivum, název a popis a poté stiskněte „Mintovat“.
19 </p>
20 <form>
21 <h2>🖼 Odkaz na aktivum: </h2>
22 <input
23 type="text"
24 placeholder="např., https://gateway.pinata.cloud/ipfs/<hash>"
25 onChange={(event) => setURL(event.target.value)}
26 />
27 <h2>🤔 Název: </h2>
28 <input
29 type="text"
30 placeholder="např., Moje první NFT!"
31 onChange={(event) => setName(event.target.value)}
32 />
33 <h2>✍️ Popis: </h2>
34 <input
35 type="text"
36 placeholder="např., Ještě víc cool než cryptokitties ;)"
37 onChange={(event) => setDescription(event.target.value)}
38 />
39 </form>
40 <button id="mintButton" onClick={onMintPressed}>
41 Mintovat NFT
42 </button>
43 <p id="status">{status}</p>
44</div>
45)
Zobrazit vše

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

Pokud přejdete do souboru App.js, který je hlavní komponentou v Reactu a 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 soubor Minter.js a přidávat soubory do naší složky src.

Nyní, když chápeme, s čím pracujeme, nastavme si naši peněženku Ethereum!

Nastavte si svou peněženku Ethereum

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

Stáhněte si MetaMask

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

Úč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, se ujistěte, že jste vpravo nahoře přepnuli na „Ropsten Test Network“ (abychom nepracovali se skutečnými penězi).

Přidejte ether z Faucetu

Abychom mohli mintovat naše NFT (nebo podepisovat jakékoli transakce na blockchainu Ethereum), budeme potřebovat nějaké falešné Eth. Pro získání Eth můžete přejít na Ropsten faucetopens in a new tab, zadat adresu svého účtu Ropsten a kliknout na „Send Ropsten Eth“. 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!

Připojte MetaMask k vašemu UI

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

Protože se chceme držet paradigmatu MVCopens in a new tab, vytvoříme si 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

K tomu si vytvoříme novou složku s názvem utils ve vašem adresáři src a do ní přidáme 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 svého souboru interact.js přidejte následující

1export const connectWallet = async () => {
2 if (window.ethereum) {
3 try {
4 const addressArray = await window.ethereum.request({
5 method: "eth_requestAccounts",
6 })
7 const obj = {
8 status: "👆🏽 Napište zprávu do textového pole výše.",
9 address: addressArray[0],
10 }
11 return obj
12 } catch (err) {
13 return {
14 address: "",
15 status: "😥 " + err.message,
16 }
17 }
18 } else {
19 return {
20 address: "",
21 status: (
22 <span>
23 <p>
24 {" "}
25 🦊 <a target="_blank" href={`https://metamask.io/download`}>
26 Do prohlížeče si musíte nainstalovat MetaMask, virtuální peněženku pro Ethereum.
27 </a>
28 </p>
29 </span>
30 ),
31 }
32 }
33}
Zobrazit vše

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, 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.

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

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, které obsahuje všechny adresy účtů uživatele připojené k dapp. Celkově naše funkce connectWallet vrátí objekt JSON, který obsahuje první adresu v tomto poli (viz řádek 9) a zprávu status, 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 adresu a zprávu status, která odráží, že uživatel spojení odmítl.

Přidejte funkci connectWallet do své komponenty UI Minter.js

Nyní, když jsme napsali tuto funkci connectWallet, připojme ji 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ů souboru Minter.js by nyní mělo vypadat takto:

1import { useEffect, useState } from "react";
2import { connectWallet } from "./utils/interact.js";
3
4const Minter = (props) => {
5
6 //Stavové proměnné
7 const [walletAddress, setWallet] = useState("");
8 const [status, setStatus] = useState("");
9 const [name, setName] = useState("");
10 const [description, setDescription] = useState("");
11 const [url, setURL] = useState("");
Zobrazit vše

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

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

Všimněte si, jak je většina naší funkcionality abstrahována z naší komponenty Minter.js ze 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í uložme oba soubory Minter.js a interact.js a vyzkoušejme naše dosavadní uživatelské rozhraní.

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

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.

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 nebojte se! To můžeme snadno opravit implementací funkce nazvané getCurrentWalletConnected, která zkontroluje, zda je adresa již připojena k naší dapp, a podle toho aktualizuje naše uživatelské rozhraní!

Funkce getCurrentWalletConnected

Do svého souboru interact.js přidejte následující funkci getCurrentWalletConnected:

1export const getCurrentWalletConnected = async () => {
2 if (window.ethereum) {
3 try {
4 const addressArray = await window.ethereum.request({
5 method: "eth_accounts",
6 })
7 if (addressArray.length > 0) {
8 return {
9 address: addressArray[0],
10 status: "👆🏽 Napište zprávu do textového pole výše.",
11 }
12 } else {
13 return {
14 address: "",
15 status: "🦊 Připojte se k MetaMasku pomocí tlačítka vpravo nahoře.",
16 }
17 }
18 } catch (err) {
19 return {
20 address: "",
21 status: "😥 " + err.message,
22 }
23 }
24 } else {
25 return {
26 address: "",
27 status: (
28 <span>
29 <p>
30 {" "}
31 🦊 <a target="_blank" href={`https://metamask.io/download`}>
32 Do prohlížeče si musíte nainstalovat MetaMask, virtuální peněženku pro Ethereum.
33 </a>
34 </p>
35 </span>
36 ),
37 }
38 }
39}
Zobrazit vše

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 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 viděli tuto funkci v akci, zavoláme ji ve funkci useEffect naší komponenty Minter.js.

Stejně jako u connectWallet musíme tuto funkci naimportovat z našeho souboru interact.js do našeho souboru Minter.js takto:

1import { useEffect, useState } from "react"
2import {
3 connectWallet,
4 getCurrentWalletConnected, //importovat zde
5} from "./utils/interact.js"

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

1useEffect(async () => {
2 const { address, status } = await getCurrentWalletConnected()
3 setWallet(address)
4 setStatus(status)
5}, [])

Vš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.

Jakmile přidáte tento kód, zkuste obnovit okno prohlížeče. Tlačítko by mělo hlásit, že jste připojeni, a zobrazovat náhled adresy vaší připojené peněženky – i po obnovení!

Implementujte 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 svého souboru Minter.js přidejte funkci addWalletListener, která vypadá následovně:

1function addWalletListener() {
2 if (window.ethereum) {
3 window.ethereum.on("accountsChanged", (accounts) => {
4 if (accounts.length > 0) {
5 setWallet(accounts[0])
6 setStatus("👆🏽 Napište zprávu do textového pole výše.")
7 } else {
8 setWallet("")
9 setStatus("🦊 Připojte se k MetaMasku pomocí tlačítka vpravo nahoře.")
10 }
11 })
12 } else {
13 setStatus(
14 <p>
15 {" "}
16 🦊 <a target="_blank" href={`https://metamask.io/download`}>
17 Do prohlížeče si musíte nainstalovat MetaMask, virtuální peněženku pro Ethereum.
18 </a>
19 </p>
20 )
21 }
22}
Zobrazit vše

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

  • Nejprve naše funkce zkontroluje, zda je window.ethereum povoleno (tj. zda je MetaMask nainstalován).
    • Pokud není, jednoduše nastavíme naši stavovou proměnnou status na ř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á walletAddress se aktualizuje jako první účet v poli accounts vráceném posluchačem. V opačném případě je walletAddress nastaveno jako prázdný řetězec.

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

1useEffect(async () => {
2 const { address, status } = await getCurrentWalletConnected()
3 setWallet(address)
4 setStatus(status)
5
6 addWalletListener()
7}, [])

A je to! Dokončili jsme programování veškeré funkcionality naší peněženky! Nyní, když je naše peněženka nastavena, pojďme zjistit, jak mintovat naše NFT!

Metadata NFT 101

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

Tato metadata budeme muset nakonfigurovat jako objekt JSON 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 „Odkaz na aktivum“, „Název“ a „Popis“ bude tvořit různé vlastnosti metadat našeho NFT. Tato metadata naformátujeme jako objekt JSON, ale existuje několik možností, kde tento objekt JSON můžeme uložit:

  • Mohli bychom je uložit na blockchainu Ethereum, avšak to by bylo velmi drahé.
  • Mohli bychom je uložit na centralizovaném serveru, jako je AWS nebo Firebase. To by ale bylo v rozporu s naším decentralizačním étosem.
  • 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. Protože je tento protokol decentralizovaný a bezplatný, je to naše nejlepší volba!

K uložení našich metadat na IPFS použijeme Pinataopens 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žijte Pinata k připnutí vašich metadat na IPFS

Pokud nemáte účet Pinataopens in a new tab, zaregistrujte si bezplatný účet zdeopens in a new tab a dokončete kroky k ověření svého e-mailu a účtu.

Vytvořte si API klíč Pinata

Přejděte na stránku https://pinata.cloud/keysopens 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 vašimi informacemi o API. Ujistěte se, že si je uložíte na bezpečné místo.

Nyní, když máme náš klíč nastavený, přidejme ho do našeho projektu, abychom ho mohli používat.

Vytvořte soubor .env

Náš klíč Pinata a tajný klíč můžeme bezpečně uložit do souboru s proměnnými prostředí. Nainstalujme si do adresáře projektu balíček dotenvopens in a new tab.

Otevřete novou kartu v terminálu (jinou než tu, na které běží localhost), ujistěte se, že se nacházíte ve složce minter-starter-files a spusťte následující příkaz:

1npm install dotenv --save

Dále vytvořte soubor .env v kořenovém adresáři minter-starter-files zadáním následujícího příkazu:

1vim.env

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

Dále v editoru VSCode přejděte do souboru .env a přidejte do něj svůj API klíč Pinata a API secret takto:

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

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

Implementujte pinJSONToIPFS

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

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

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

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

1require("dotenv").config()
2const key = process.env.REACT_APP_PINATA_KEY
3const secret = process.env.REACT_APP_PINATA_SECRET
4
5const axios = require("axios")
6
7export const pinJSONToIPFS = async (JSONBody) => {
8 const url = `https://api.pinata.cloud/pinning/pinJSONToIPFS`
9 //odeslání POST požadavku pomocí axios na Pinata ⬇️
10 return axios
11 .post(url, JSONBody, {
12 headers: {
13 pinata_api_key: key,
14 pinata_secret_api_key: secret,
15 },
16 })
17 .then(function (response) {
18 return {
19 success: true,
20 pinataUrl:
21 "https://gateway.pinata.cloud/ipfs/" + response.data.IpfsHash,
22 }
23 })
24 .catch(function (error) {
25 console.log(error)
26 return {
27 success: false,
28 message: error.message,
29 }
30 })
31}
Zobrazit vše

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

Nejprve importuje axiosopens in a new tab, HTTP klienta založeného na promises pro prohlížeč a node.js, který použijeme k provedení požadavku na Pinata.

Poté máme naši asynchronní funkci pinJSONToIPFS, která jako vstup přijímá JSONBody a v hlavičce API klíč a secret Pinata, a to vše pro provedení POST požadavku na jejich API pinJSONToIPFS.

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

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

Načtěte svůj chytrý kontrakt

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 volat jeho funkci mintNFT.

Jak jsme již zmínili, v tomto návodu budeme používat tento existující chytrý kontrakt NFTopens in a new tab; nicméně, pokud byste se 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 si naše soubory pozorně prohlédli, jistě jste si všimli, že v našem adresáři src se nachází soubor contract-abi.json. ABI je nezbytné pro specifikaci, kterou funkci kontrakt vyvolá, a také pro zajištění, ž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řte si API klíč Alchemy

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

Jakmile si vytvoříte účet na Alchemy, můžete si vygenerovat klíč API vytvořením aplikace. To nám umožní provádět požadavky na testovací síť Ropsten.

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

Pojmenujte svou aplikaci – my jsme zvolili „My First NFT!“, nabídněte krátký popis, vyberte „Staging“ pro prostředí používané pro účetnictví vaší aplikace a jako síť zvolte „Ropsten“.

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 Alchemy API URL, zkopírujte si ji do schránky...

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

1REACT_APP_PINATA_KEY = <pinata-key>
2REACT_APP_PINATA_SECRET = <pinata-secret>
3REACT_APP_ALCHEMY_KEY = https://eth-ropsten.alchemyapi.io/v2/<alchemy-key>

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

Nastavte si svůj koncový bod Alchemy Web3 a kontrakt

Nejprve, pokud ho ještě nemáte, budete muset nainstalovat Alchemy Web3opens in a new tab tak, že přejdete do domovského adresáře: nft-minter-tutorial v terminálu:

1cd ..
2npm install @alch/alchemy-web3

Dále se vraťme do našeho souboru interact.js. Na začátek souboru přidejte následující kód, abyste naimportovali svůj klíč Alchemy ze souboru .env a nastavili si svůj koncový bod Alchemy Web3:

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

Alchemy 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ě!

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

1require("dotenv").config()
2const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY
3const { createAlchemyWeb3 } = require("@alch/alchemy-web3")
4const web3 = createAlchemyWeb3(alchemyKey)
5
6const contractABI = require("../contract-abi.json")
7const contractAddress = "0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE"

Jakmile máme obojí, jsme připraveni začít kódovat naši funkci mintování!

Implementujte funkci mintNFT

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

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

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

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

Zpracování chyb na vstupu

Je samozřejmě logické mít na začátku funkce nějaké zpracování chyb na vstupu, takže z této funkce odejdeme, pokud naše vstupní parametry nejsou správné. Do naší funkce přidejme následující kód:

1export const mintNFT = async (url, name, description) => {
2 //zpracování chyb
3 if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
4 return {
5 success: false,
6 status: "❗Před mintováním se prosím ujistěte, že jsou všechna pole vyplněna.",
7 }
8 }
9}
Zobrazit vše

V podstatě, pokud je některý ze vstupních parametrů prázdný řetězec, vrátíme objekt JSON, 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.

Nahrajte metadata na IPFS

Jakmile víme, že jsou naše metadata správně naformátována, dalším krokem je zabalit je do objektu JSON 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. Na samý začátek interact.js přidejme:

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

Vzpomeňte si, že pinJSONToIPFS přijímá jako vstup tělo JSON. Takže než ji zavoláme, budeme muset naformátovat naše parametry url, name a description do objektu JSON.

Aktualizujme náš kód tak, aby vytvořil objekt JSON nazvaný metadata a poté proveďme volání pinJSONToIPFS s tímto parametrem metadata:

1export const mintNFT = async (url, name, description) => {
2 //zpracování chyb
3 if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
4 return {
5 success: false,
6 status: "❗Před mintováním se prosím ujistěte, že jsou všechna pole vyplněna.",
7 }
8 }
9
10 //vytvořit metadata
11 const metadata = new Object()
12 metadata.name = name
13 metadata.image = url
14 metadata.description = description
15
16 //volání pinata
17 const pinataResponse = await pinJSONToIPFS(metadata)
18 if (!pinataResponse.success) {
19 return {
20 success: false,
21 status: "😢 Něco se pokazilo při nahrávání vašeho tokenURI.",
22 }
23 }
24 const tokenURI = pinataResponse.pinataUrl
25}
Zobrazit vše

Všimněte si, že odpověď na naše 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 objekt JSON, 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. Na konec funkce mintNFT přidejte následující řádek kódu, který nastaví kontrakt na globální proměnnou window.contract:

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

Poslední věc, kterou je třeba přidat do naší funkce mintNFT, je naše transakce Ethereum:

1//nastavte si svou transakci Ethereum
2const transactionParameters = {
3 to: contractAddress, // Povinné s výjimkou zveřejnění kontraktu.
4 from: window.ethereum.selectedAddress, // musí odpovídat aktivní adrese uživatele.
5 data: window.contract.methods
6 .mintNFT(window.ethereum.selectedAddress, tokenURI)
7 .encodeABI(), //provést volání chytrého kontraktu NFT
8}
9
10//podepsat transakci přes MetaMask
11try {
12 const txHash = await window.ethereum.request({
13 method: "eth_sendTransaction",
14 params: [transactionParameters],
15 })
16 return {
17 success: true,
18 status:
19 "✅ Podívejte se na svou transakci na Etherscanu: https://ropsten.etherscan.io/tx/" +
20 txHash,
21 }
22} catch (error) {
23 return {
24 success: false,
25 status: "😥 Něco se pokazilo: " + error.message,
26 }
27}
Zobrazit vše

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

  • Nejprve nastavíme naše parametry transakce.
    • to určuje adresu příjemce (náš chytrý kontrakt)
    • from určuje podepisujícího transakce (připojená adresa uživatele k MetaMasku: window.ethereum.selectedAddress)
    • data obsahuje volání metody mintNFT našeho chytrého kontraktu, která jako vstup přijímá náš tokenURI a adresu peněženky uživatele, window.ethereum.selectedAddress
  • Poté provedeme await volání 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 zamítnutí transakce.
    • Pokud je transakce úspěšná, funkce vrátí objekt JSON, kde je booleovská hodnota success nastavena na true a řetězec status vyzve uživatele, aby se podíval na Etherscan pro více informací o své transakci.
    • Pokud transakce selže, funkce vrátí objekt JSON, kde je booleovská hodnota success nastavena na false a řetězec status sděluje chybovou zprávu.

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

1export const mintNFT = async (url, name, description) => {
2 //zpracování chyb
3 if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
4 return {
5 success: false,
6 status: "❗Před mintováním se prosím ujistěte, že jsou všechna pole vyplněna.",
7 }
8 }
9
10 //vytvořit metadata
11 const metadata = new Object()
12 metadata.name = name
13 metadata.image = url
14 metadata.description = description
15
16 //žádost o připnutí pinata
17 const pinataResponse = await pinJSONToIPFS(metadata)
18 if (!pinataResponse.success) {
19 return {
20 success: false,
21 status: "😢 Něco se pokazilo při nahrávání vašeho tokenURI.",
22 }
23 }
24 const tokenURI = pinataResponse.pinataUrl
25
26 //načíst chytrý kontrakt
27 window.contract = await new web3.eth.Contract(contractABI, contractAddress) //loadContract();
28
29 //nastavte si svou transakci Ethereum
30 const transactionParameters = {
31 to: contractAddress, // Povinné s výjimkou zveřejnění kontraktu.
32 from: window.ethereum.selectedAddress, // musí odpovídat aktivní adrese uživatele.
33 data: window.contract.methods
34 .mintNFT(window.ethereum.selectedAddress, tokenURI)
35 .encodeABI(), //provést volání chytrého kontraktu NFT
36 }
37
38 //podepsat transakci přes MetaMask
39 try {
40 const txHash = await window.ethereum.request({
41 method: "eth_sendTransaction",
42 params: [transactionParameters],
43 })
44 return {
45 success: true,
46 status:
47 "✅ Podívejte se na svou transakci na Etherscanu: https://ropsten.etherscan.io/tx/" +
48 txHash,
49 }
50 } catch (error) {
51 return {
52 success: false,
53 status: "😥 Něco se pokazilo: " + error.message,
54 }
55 }
56}
Zobrazit vše

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

Připojte mintNFT k našemu frontendu Minter.js

Otevřete svůj soubor Minter.js a aktualizujte řádek import { connectWallet, getCurrentWalletConnected } from \"./utils/interact.js\"; na začátku na:

1import {
2 connectWallet,
3 getCurrentWalletConnected,
4 mintNFT,
5} from "./utils/interact.js"

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

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

Nasaďte své NFT na živou webovou stránku

Jste připraveni uvést svůj projekt do provozu, aby s ním uživatelé mohli interagovat? Podívejte se na tento návodopens in a new tab pro nasazení vašeho Minteru na živou webovou stránku.

Ještě poslední krok...

Dobijte svět blockchainu

Děláme si legraci, dostali jste se až na konec návodu!

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

  • Připojit se k MetaMasku prostřednictvím vašeho frontendového projektu
  • Volat metody chytrého kontraktu z vašeho frontendu
  • Podepisovat transakce pomocí MetaMasku

Pravděpodobně se budete chtít pochlubit NFT vyraženými prostřednictvím vaší dapp ve své peněžence – proto se určitě podívejte na náš rychlý návod Jak si zobrazit NFT ve vaší peněženceopens in a new tab!

A jako vždy, pokud máte nějaké dotazy, jsme tu, abychom vám pomohli na Alchemy Discorduopens 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!

Stránka naposledy aktualizována: 25. února 2026

Byl tento tutoriál užitečný?