Přejít na hlavní obsah

Jak napsat a nasadit NFT (Část 1/3 ze série tutoriálů o NFT)

ERC-721
Alchemy
Solidity
chytré kontrakty
Začátečník
Sumi Mudgil
22. dubna 2021
13 minut čtení

Vzhledem k tomu, že nezaměnitelné tokeny (NFT) dostávají blockchain do povědomí veřejnosti, je nyní skvělá příležitost pochopit tento humbuk na vlastní kůži tím, že publikujete svůj vlastní kontrakt pro NFT (token ERC-721) na blockchainu Ethereum!

V tomto tutoriálu si projdeme vytvoření a nasazení chytrého kontraktu ERC-721 na testnetu Sepolia pomocí nástrojů MetaMask (otevře se v nové záložce), Solidity (otevře se v nové záložce), Hardhat (otevře se v nové záložce), Pinata (otevře se v nové záložce) a Alchemy (otevře se v nové záložce) (nebojte se, pokud zatím nerozumíte, co to všechno znamená – vysvětlíme si to!).

Ve 2. části tohoto tutoriálu si projdeme, jak můžeme náš chytrý kontrakt použít k ražení NFT, a ve 3. části si vysvětlíme, jak si své NFT zobrazit v MetaMasku.

A samozřejmě, pokud budete mít kdykoli nějaké dotazy, neváhejte se ozvat na Discordu Alchemy (otevře se v nové záložce) nebo navštivte dokumentaci k rozhraní pro programování aplikací (API) pro NFT od Alchemy (otevře se v nové záložce)!

Krok 1: Připojení k síti Ethereum

Existuje spousta způsobů, jak zadávat požadavky na blockchain Ethereum, ale abychom si to usnadnili, použijeme bezplatný účet na Alchemy (otevře se v nové záložce), vývojářské platformě a API pro blockchain, která nám umožňuje komunikovat s řetězcem Ethereum, aniž bychom museli provozovat vlastní uzly.

V tomto tutoriálu také využijeme vývojářské nástroje Alchemy pro monitorování a analytiku, abychom pochopili, co se děje pod pokličkou při nasazení našeho chytrého kontraktu. Pokud ještě nemáte účet na Alchemy, můžete se zdarma zaregistrovat zde (otevře se v nové záložce).

Krok 2: Vytvoření aplikace (a klíče k API)

Jakmile si vytvoříte účet na Alchemy, můžete si vygenerovat klíč k rozhraní pro programování aplikací (API) vytvořením aplikace. To nám umožní zadávat požadavky na testnet Sepolia. Pokud se chcete o testnetech dozvědět více, podívejte se na tento průvodce (otevře se v nové záložce).

  1. Přejděte na stránku „Create new app“ (Vytvořit novou aplikaci) na svém panelu Alchemy tak, že v navigačním panelu vyberete „Select an app“ (Vybrat aplikaci) a kliknete na „Create new app“.

Vytvoření aplikace

  1. Pojmenujte svou aplikaci (my jsme zvolili „My First NFT!“), přidejte krátký popis a vyberte případ užití. Dále vyhledejte „Ethereum“ a vyberte síť. Použijeme Sepolia, doporučený testnet pro vývoj aplikací (viz Sítě Etherea).

  2. Pokračujte kliknutím na „Next“ (Další), poté na „Create app“ (Vytvořit aplikaci) a je to! Vaše aplikace by se měla objevit v rozbalovací nabídce navigačního panelu s klíčem k API, který si můžete zkopírovat.

Krok 3: Vytvoření účtu (adresy) na Ethereu

K odesílání a přijímání transakcí potřebujeme účet na Ethereu. Pro tento tutoriál 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 od Nadace Ethereum.

Účet na MetaMasku si můžete zdarma stáhnout a vytvořit zde (otevře se v nové záložce). Při vytváření účtu, nebo pokud již účet máte, se ujistěte, že jste pomocí nabídky pro výběr sítě přepnuli na testnet „Sepolia“ (abychom nepracovali se skutečnými penězi). Pokud v seznamu nevidíte síť Sepolia, otevřete nabídku v pravém horním rohu, vyberte „Networks“ (Sítě) a zapněte možnost „Show test networks“ (Zobrazit testovací sítě) (viz průvodce MetaMasku pro zobrazení testnetů (otevře se v nové záložce)).

Nastavení sítě Sepolia

Krok 4: Přidání etheru z faucetu

Abychom mohli nasadit náš chytrý kontrakt na testnet, budeme potřebovat nějaké falešné ETH. Chcete-li získat Sepolia ETH, vyberte si jeden z faucetů uvedených v podrobnostech o síti Sepolia a zadejte adresu svého účtu. Pokud jeden nefunguje, zkuste jiný, protože někdy mohou vyschnout a některé mají pravidla způsobilosti: například faucet Alchemy Sepolia (otevře se v nové záložce) vyžaduje, aby přijímající adresa měla alespoň 0,001 ETH na síti Ethereum Mainnet. Brzy poté byste měli vidět ETH na svém účtu v MetaMasku!

Krok 5: Kontrola zůstatku

Abychom si ověřili, že tam náš zůstatek je, vytvořme požadavek eth_getBalance (otevře se v nové záložce) pomocí nástroje sandbox od Alchemy (otevře se v nové záložce). To nám vrátí množství ETH v naší peněžence. Po zadání adresy vašeho účtu v MetaMasku a kliknutí na „Send Request“ byste měli vidět podobnou odpověď:

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

Poznámka Tento výsledek je ve Wei, nikoli v ETH. Wei se používá jako nejmenší nominální hodnota etheru. Převod z Wei na ETH je 1 eth = 1018 Wei. Pokud tedy převedeme 0xde0b6b3a7640000 do desítkové soustavy, dostaneme 1*1018 Wei, což se rovná 1 ETH.

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

Krok 6: Inicializace našeho projektu

Nejprve budeme muset vytvořit složku pro náš projekt. Přejděte do příkazového řádku a zadejte:

mkdir my-nft
cd my-nft

Nyní, když jsme ve složce našeho projektu, použijeme npm init k inicializaci projektu. Pokud ještě nemáte nainstalované npm, postupujte podle pokynů k instalaci Node.js (otevře se v nové záložce) (pro tento tutoriál budeme potřebovat Node.js a npm).

npm init

Nezáleží na tom, jak odpovíte na instalační otázky; zde je pro referenci ukázka, jak jsme to udělali my:

Schvalte soubor package.json. Hardhat 3, který nainstalujeme vzápětí, podporuje pouze projekty s moduly ES, takže projekt jako takový označte:

npm pkg set type=module

A můžeme začít!

Krok 7: Instalace nástroje Hardhat (otevře se v nové záložce)

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 vytváření chytrých kontraktů a decentralizovaných aplikací (dapp) před jejich nasazením do živého řetězce.

Hardhat 3 vyžaduje Node.js v22.13.0 nebo novější. Uvnitř našeho projektu my-nft spusťte:

npm install --save-dev hardhat

Další podrobnosti o pokynech k instalaci (otevře se v nové záložce) najdete na této stránce.

Krok 8: Vytvoření projektu Hardhat

Spuštění npx hardhat --init by vygenerovalo kompletní ukázkový projekt, ale pro tento tutoriál vše nastavíme ručně, abyste viděli každou část. V kořenovém adresáři složky vašeho projektu vytvořte soubor s názvem hardhat.config.js s následujícím obsahem:

import { defineConfig } from "hardhat/config"

export default defineConfig({
  solidity: "0.8.34",
})

Zde specifikujeme veškeré nastavení pro náš projekt (v kroku 13). Prozatím to jen říká nástroji Hardhat, kterou verzi kompilátoru Solidity má použít.

Krok 9: Přidání složek projektu

Abychom udrželi náš projekt organizovaný, vytvoříme dvě nové složky. Přejděte do kořenového adresáře vašeho projektu v příkazovém řádku a zadejte:

mkdir contracts
mkdir scripts
  • contracts/ je místo, kde budeme uchovávat kód našeho chytrého kontraktu pro NFT

  • scripts/ je místo, kde budeme uchovávat skripty pro nasazení a interakci s naším chytrým kontraktem

Krok 10: Napsání našeho kontraktu

Nyní, když je naše prostředí nastaveno, přejdeme k zajímavějším věcem: psaní kódu našeho chytrého kontraktu!

Otevřete projekt my-nft ve svém oblíbeném editoru (my máme rádi VSCode (otevře se v nové záložce)). Chytré kontrakty se píší v jazyce zvaném Solidity, který použijeme k napsání našeho chytrého kontraktu MyNFT.sol.‌

  1. Přejděte do složky contracts a vytvořte nový soubor s názvem MyNFT.sol

  2. Níže je kód našeho chytrého kontraktu pro NFT, který jsme založili na implementaci ERC-721 z knihovny OpenZeppelin (otevře se v nové záložce). Zkopírujte a vložte níže uvedený obsah do souboru MyNFT.sol.

  3. Protože dědíme třídy z knihovny kontraktů OpenZeppelin, spusťte v příkazovém řádku npm install @openzeppelin/contracts, abyste knihovnu nainstalovali do naší složky. Tento tutoriál používá OpenZeppelin Contracts 5.x, což vyžaduje Solidity 0.8.24 nebo novější.

Co tedy tento kód přesně dělá? Pojďme si to rozebrat řádek po řádku.

Na začátku našeho chytrého kontraktu importujeme tři třídy chytrých kontraktů OpenZeppelin (otevře se v nové záložce):

  • @openzeppelin/contracts/token/ERC721/ERC721.sol obsahuje implementaci standardu ERC-721, kterou náš chytrý kontrakt pro NFT zdědí. (Aby byl váš chytrý kontrakt platným NFT, musí implementovat všechny metody standardu ERC-721.) Chcete-li se dozvědět více o zděděných funkcích ERC-721, podívejte se na definici rozhraní zde (otevře se v nové záložce).

  • @openzeppelin/contracts/access/Ownable.sol nastavuje řízení přístupu (otevře se v nové záložce) k našemu chytrému kontraktu, takže pouze vlastník chytrého kontraktu (vy) může razit NFT. Vlastníkem je adresa initialOwner předaná konstruktoru. (Poznámka: zahrnutí řízení přístupu je čistě na vašich preferencích. Pokud byste chtěli, aby kdokoli mohl razit NFT pomocí vašeho chytrého kontraktu, odstraňte Ownable a Ownable(initialOwner) z definice kontraktu a konstruktoru a onlyOwner z funkce mintNFT.)

  • @openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol rozšiřuje ERC-721 tak, aby každý token mohl ukládat své vlastní URI pro metadata, které nastavíme při ražení.

Po našich příkazech pro import máme náš vlastní chytrý kontrakt pro NFT, který je překvapivě krátký – obsahuje pouze počítadlo, konstruktor a jedinou funkci! Je to díky našim zděděným kontraktům OpenZeppelin, které implementují většinu metod, které potřebujeme k vytvoření NFT, jako je ownerOf, která vrací vlastníka NFT, a transferFrom, která převádí vlastnictví NFT z jednoho účtu na druhý.

Počítadlo _nextTokenId sleduje celkový počet vyražených NFT a nastavuje jedinečné ID našeho nového NFT. (Každému NFT vyraženému pomocí chytrého kontraktu musí být přiřazeno jedinečné ID – zde je naše jedinečné ID určeno pouze celkovým počtem existujících NFT. ++_nextTokenId zvýší počítadlo před jeho použitím, takže první NFT, které vyrazíme pomocí našeho chytrého kontraktu, má ID „1“, naše druhé NFT má ID „2“ atd.)

V našem konstruktoru ERC-721 si všimnete, že předáváme 2 řetězce, „MyNFT“ a „NFT“. První proměnná je název chytrého kontraktu a druhá je jeho symbol. Každou z těchto proměnných můžete pojmenovat, jak chcete!

Nakonec tu máme naši funkci mintNFT(address recipient, string memory tokenURI), která nám umožňuje razit NFT! Všimnete si, že tato funkce přijímá dvě proměnné:

  • address recipient určuje adresu, která obdrží vaše čerstvě vyražené NFT

  • string memory tokenURI je řetězec, který by měl odkazovat na dokument JSON, který popisuje metadata NFT. Metadata NFT jsou tím, co mu skutečně vdechuje život a umožňuje mu mít konfigurovatelné vlastnosti, jako je název, popis, obrázek a další atributy. Ve 2. části tohoto tutoriálu popíšeme, jak tato metadata nakonfigurovat.

mintNFT volá některé metody ze zděděné knihovny ERC-721 a nakonec vrací číslo, které představuje ID čerstvě vyraženého NFT.

Krok 11: Připojení MetaMasku a Alchemy k vašemu projektu

Nyní, když jsme vytvořili peněženku MetaMask, účet na Alchemy a napsali náš chytrý kontrakt, je čas tyto tři věci propojit.

Každá transakce odeslaná z vaší virtuální peněženky vyžaduje podpis pomocí vašeho jedinečného soukromého klíče. Abychom našemu programu poskytli toto oprávnění, můžeme bezpečně uložit náš soukromý klíč (a klíč k API Alchemy) do souboru prostředí.

Chcete-li se dozvědět více o odesílání transakcí, podívejte se na dokumentaci k transakcím.

Vytvořte soubor .env v kořenovém adresáři našeho projektu a přidejte do něj svůj soukromý klíč z MetaMasku a URL adresu HTTP API Alchemy.

Váš soubor .env by nyní měl vypadat takto:

API_URL="https://eth-sepolia.g.alchemy.com/v2/your-api-key"
PRIVATE_KEY="your-metamask-private-key"

Abychom je skutečně propojili s naším kódem, odkážeme na tyto proměnné v našem souboru hardhat.config.js v kroku 13. Node.js dokáže číst soubory .env sám o sobě, takže není nutné instalovat žádný další balíček.

Necommitujte .env! Ujistěte se, že svůj soubor .env s nikým nesdílíte ani ho nevystavujete, protože tím ohrožujete své tajné údaje. Pokud používáte správu verzí, přidejte svůj .env do souboru gitignore (otevře se v nové záložce).

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-RPC uživatelsky přívětivějšími metodami.

Hardhat velmi usnadňuje integraci pluginů (otevře se v nové záložce) pro další nástroje a rozšířenou funkcionalitu. Využijeme plugin Ethers (otevře se v nové záložce) pro nasazení kontraktu (Ethers.js (otevře se v nové záložce) má několik velmi čistých metod pro nasazení kontraktu).

V adresáři vašeho projektu zadejte:

npm install --save-dev @nomicfoundation/hardhat-ethers ethers

V dalším kroku také přidáme plugin do našeho souboru hardhat.config.js.

Krok 13: Aktualizace 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 hardhat.config.js tak, aby vypadal takto:

configVariable říká nástroji Hardhat, aby četl každou hodnotu z proměnné prostředí pouze tehdy, když je to potřeba, takže příkazy jako compile fungují ještě před nastavením hodnot. Pokud byste raději neuchovávali svůj soukromý klíč v textovém souboru, Hardhat dokáže také číst konfigurační proměnné ze zašifrovaného úložiště klíčů (otevře se v nové záložce).

Krok 14: Kompilace našeho kontraktu

Abychom se ujistili, že zatím vše funguje, zkompilujeme náš kontrakt. Úloha kompilace je jednou z vestavěných úloh nástroje Hardhat.

Z příkazového řádku spusťte:

npx hardhat compile

Při první kompilaci si Hardhat stáhne kompilátor Solidity. Poté byste měli vidět něco jako Compiled 1 Solidity file with solc 0.8.34. Pokud ne, můžete vždy napsat na Discord Alchemy (otevře se v nové záložce).

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/ a vytvořte nový soubor s názvem deploy.js, do kterého přidejte následující obsah:

Pojďme si projít, co každý z těchto řádků kódu dělá.

const { ethers } = await network.create()

V Hardhat 3 skript otevírá připojení k síti explicitně. network.create() se připojí k síti, kterou vyberete pomocí volby --network při spuštění skriptu, a plugin hardhat-ethers přidá k tomuto připojení objekt ethers.

const [deployer] = await ethers.getSigners()

getSigners() vrací účty nakonfigurované pro danou síť. Na síti Sepolia je to účet, jehož soukromý klíč jste vložili do .env. Jeho adresu předáme konstruktoru, abyste se stali vlastníkem kontraktu.

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

ContractFactory v ethers.js je abstrakce používaná k nasazení nových chytrých kontraktů, takže MyNFT je zde továrnou pro instance našeho kontraktu pro NFT. 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.

const myNFT = await MyNFT.deploy(deployer.address)

Volání deploy() na ContractFactory zahájí nasazení a vrátí Promise, který se vyhodnotí jako Contract. Toto je objekt, který má metodu pro každou z funkcí našeho chytrého kontraktu. Argumenty, které předáte do deploy(), jdou do konstruktoru kontraktu, zde je to adresa initialOwner.

waitForDeployment() čeká, dokud není transakce nasazení zahrnuta do bloku, a getAddress() vrací adresu nového kontraktu. Další podrobnosti najdete v dokumentaci ke kontraktům ethers.js (otevře se v nové záložce).

Krok 16: Nasazení našeho kontraktu

Konečně jsme připraveni nasadit náš chytrý kontrakt! Přejděte zpět do kořenového adresáře vašeho projektu a v příkazovém řádku spusťte:

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

Poté byste měli vidět něco jako:

Contract deployed to address: 0x4C5266cCc4b3F426965d2f51b6D910325a0E7650

Pokud přejdeme na Etherscan sítě Sepolia (otevře se v nové záložce) a vyhledáme adresu našeho kontraktu, měli bychom vidět, že byl úspěšně nasazen. Pokud jej nevidíte okamžitě, chvíli počkejte, protože to může nějakou dobu trvat. Transakce bude vypadat nějak takto:

Zobrazení adresy vaší transakce na Etherscanu

Adresa „From“ (Od) by se měla shodovat s adresou vašeho účtu v MetaMasku a adresa „To“ (Komu) bude uvádět „Contract Creation“ (Vytvoření kontraktu). Pokud klikneme na transakci, uvidíme adresu našeho kontraktu v poli „To“:

Zobrazení adresy vašeho kontraktu na Etherscanu

Paráda! Právě jste nasadili svůj chytrý kontrakt pro NFT do řetězce Etherea (testnetu)!

Abyste pochopili, co se děje pod pokličkou, můžete se podívat na požadavky, které vaše aplikace obdržela, na vašem panelu Alchemy (otevře se v nové záložce).

Tam uvidíte hrstku volání JSON-RPC, která pro nás Hardhat/Ethers provedly pod pokličkou, když jsme zavolali funkci .deploy(). Dvě důležitá volání, která zde stojí za zmínku, jsou eth_sendRawTransaction, což je požadavek na skutečný zápis našeho chytrého kontraktu do řetězce Sepolia, a eth_getTransactionByHash, což je požadavek na přečtení informací o naší transakci na základě hashe (typický vzorec při odesílání transakcí). Chcete-li se dozvědět více o odesílání transakcí, podívejte se na dokumentaci k transakcím.

To je pro 1. část tohoto tutoriálu vše. Ve 2. části budeme s naším chytrým kontraktem skutečně interagovat ražením NFT a ve 3. části vám ukážeme, jak si své NFT zobrazit ve vaší peněžence na Ethereu!