Maintenant pour les métadonnées. Nous allons créer un fichier de métadonnées par tokenId et nommer simplement le fichier comme tokenId (sans extension). Pour les besoins de cette démo, nous allons simplement créer et télécharger des métadonnées pour le jeton 0 (en fin de compte, vous voudrez des CID uniques dans les métadonnées de chaque jeton qui font référence à l’art unique associé à chaque jeton).
mkdir metadata
touch metadata/0
Dans ce fichier, collez ce qui suit (en remplaçant <CID>
avec celui de votre tableau de bord Pinata) :
{
"name": "Crypto Art #0",
"description": "Crypto Art is a collection of 1 PNG file, which I took from some Medium article",
"image": "ipfs://<CID>"
}
Maintenant, via Pinata, téléchargez tout ce dossier de métadonnées sur IPFS.
Chaque fichier de métadonnées peut maintenant être trouvé à ipfs://<METADATA-FOLDER-CID>/<TOKEN-ID>.
Par défaut, le contrat intelligent ERC721 d’OpenZeppelin, que nous avons importé dans notre CryptoArt.sol fichier, a une fonction appelée tokenURI
. Cela prend un tokenId
, l’annexe au contrat currentBaseURI
(auquel il accède en appelant _baseURI
) et renvoie le résultat.
Si nous définissons le contrat intelligentcurrentBASEURI
comme lien IPFS du dossier de métadonnées (se terminant par un ‘/’), puis le tokenURI
La fonction renverra un lien vers les métadonnées du jeton. Notez que cette fonction est marquée comme onlyOwner
, ce qui signifie que seul le propriétaire du contrat (vous) pouvez l’appeler !
Par exemple, si le lien IPFS du dossier de métadonnées est ipfs://0123456789/
, et nous sommes intéressés par tokenId
0, puis appel tokenURI(0)
reviendra ipfs://0123456789/0.
Cela signifie que n’importe qui peut appeler le contrat intelligent et, en ouvrant des liens IPFS, récupérer l’œuvre d’art associée !
Il ne reste plus qu’à dire au contrat ce que c’est currentBaseURI
devrait être en appelant setBaseURI(ipfs://0123456789/)
(nous le ferons via Etherscan après le déploiement – voir ci-dessous).
Bien sûr, nous ne voulons généralement pas que les collectionneurs puissent frapper un nombre infini de NFT du contrat, en particulier lorsqu’ils peuvent le faire gratuitement !
L’ajout d’une offre et d’un prix maximum au contrat est très simple, il suffit de mettre à jour le contrat comme suit :
Qu’est-ce qui a changé ?
- Nous avons défini un mintPrice de 0,1 éther. C’est
public
etconstant
, ce qui signifie que sa valeur peut être vérifiée en dehors du contrat et qu’elle ne peut pas changer. - Le maxSupply est défini sur 1024.
- À l’intérieur de
mint
fonction, il y a deuxrequire
déclarations. Un pour vérifier qu’il reste encore assez de jetons pour satisfaire la demandequantity
, et un autre pour vérifier que suffisamment d’éther est payé. - Enfin, un
withdrawEth
la fonction est ajoutée. Lorsque quelqu’un frappe un NFT, l’éther envoyé dans la transaction est simplement détenu par le contrat. Dans cette fonction, nous transférons cet éther au titulaire du contrat, vous ! En savoir plus sur la syntaxe particulière utilisée ici (c’est pour des raisons de sécurité).
C’est ça! Bien que de nombreuses autres fonctionnalités puissent être ajoutées, ce contrat intelligent vous permet de vendre une quantité fixe de NFT à un prix donné, de fournir des métadonnées et des illustrations uniques pour chaque jeton et de retirer tout l’éther créé. Pas mal!
S’ouvrir test/index.ts et collez ce qui suit :
En haut, nous effectuons deux importations.
- Chai est une excellente bibliothèque que hardhat utilise pour exécuter des tests de contrats intelligents. Ici, nous utilisons son
expect
fonction, qui nous permet de tester les valeurs des choses. - Ethers.js est une bibliothèque extrêmement importante que nous utiliserons dans tous les éléments de notre projet NFT (y compris l’interface React, que nous construirons dans la partie 3 de cette série).
Structurellement, nous avons créé deux groupes de tests, avec un test dans chacun. Dans chacun nous utilisons Ethers.js à déployer le contrat sur un réseau Ethereum local (le réseau Hardhat). A noter qu’un tout nouveau contrat est établi à chaque déploiement (l’état du contrat persiste entre les tests).
- Le premier test appelle le
mint
fonction avec une quantité de 1, puis vérifie que le contrat a une offre totale de 1. - Le deuxième test vérifie que le tokenURI (qui pointe vers nos métadonnées sur IPFS) peut être défini et renvoyé, avec une adresse unique pour le jeton 0.
Si ceux-ci étaient exécutés sur le réseau principal, nous aurions besoin d’attendre que les appels soient extraits en tant que transaction, mais sur le réseau Hardhat, cela se fait immédiatement – c’est bien !
Exécutez les tests :
npx hardhat test
Bien sûr, ce contrat n’est pas entièrement testé. En réalité, nous devons tester que le contrat se comporte correctement dans toutes les circonstances prévisibles (par exemple, si pas assez d’éther est fourni, si l’offre maximale est atteinte, etc.). Essayez le plugin de couverture de solidité pour vous aider à déterminer quelles parties du contrat ne sont pas exécutées dans les tests afin que vous puissiez créer une couverture jusqu’à 100 %.
Déployons sur le réseau de test Rinkeby.
Pour vous aider, nous utiliserons le plugin hardhat-deploy. Installez-le:
npm install hardhat-deploy
Créez maintenant un nouveau fichier et remplissez-le comme suit :
mkdir deploy
touch deploy/001_deploy_token.ts
Pour déployer, nous devons nous connecter à un réseau, ce qui peut être fait via un nœud Ethereum. Nous utiliserons le service fourni par les excellents employés d’Alchemy.io, qui offrent un accès généreux aux nœuds dans le niveau gratuit. Inscrivez-vous et créez une application sur le réseau Rinkeby. Vous recevrez une URL qui se termine par une clé, quelque chose comme : https://eth-rinkeby.alchemyapi.io/v2/<YOUR-KEY>
Tout d’abord, renommez .exemple.env à .env, puis collez votre clé dans ce fichier sous ALCHEMY_KEY
.
Enfin, mettez à jour le casque.config.ts fichier à ressembler: