Articolo originale: https://www.freecodecamp.org/news/how-to-make-an-nft-and-render-on-opensea-marketplace/

In questo articolo, ti mostrerò come realizzare un NFT senza competenze di ingegneria del software. Quindi impareremo come creare NFT personalizzabili illimitati con Brownie , Python e Chainlink . E vedremo come rendere e vendere la nostra creazione sul mercato NFT di OpenSea .

Se stai cercando un tutorial che utilizzi Truffle, JavaScript e divertenti personaggi medievali, dai un'occhiata a come costruire, distribuire e vendere il tuo NFT qui .

Cos'è un NFT?

Gli NFT (Non-Fungible Tokens) possono essere riassunti in una parola: "unico". Si tratta di contratti intelligenti distribuiti su una blockchain che rappresentano qualcosa di unico.

ERC20 vs ERC721

Gli NFT sono uno standard di token blockchain simile a ERC20 , come AAVE, SNX e LINK (tecnicamente un ERC677). Gli ERC20 sono token "fungibili", che significa "sostituibili" o "intercambiabili".

Ad esempio, la tua banconota da un dollaro varrà 1 $ indipendentemente dalla banconota da un dollaro che usi. Il numero di serie sulla banconota da un dollaro potrebbe essere diverso, ma le banconote sono intercambiabili e varranno sempre 1 $, qualunque cosa accada.

Gli NFT, d'altra parte, sono "non fungibili" e seguono il proprio standard di token, l'ERC721. Ad esempio, la Gioconda è "non fungibile". Anche se qualcuno può farne una copia, ci sarà sempre solo una Monna Lisa. Se la Gioconda fosse creata su una blockchain, sarebbe una NFT.

Crea un NFT
Immagine originale da Wikipedia

A cosa servono gli NFT?

Gli NFT forniscono valore a creatori, artisti, progettisti di giochi e altro avendo una cronologia permanente di distribuzione archiviata sulla chain.

Saprai sempre chi ha creato la NFT, chi possedeva la NFT, da dove proveniva e altro ancora, dando loro molto valore rispetto all'arte tradizionale. Nell'arte tradizionale, può essere difficile capire cosa sia un "falso", mentre sulla chain la storia è facilmente tracciabile.

E poiché i contratti intelligenti e gli NFT sono programmabili al 100%, gli NFT possono anche avere royalties integrate e qualsiasi altra funzionalità aggiunta. Ricompensare gli artisti è sempre stato un problema, poiché spesso il lavoro di un artista viene distribuito senza alcuna attribuzione.

Sempre più artisti e ingegneri stanno saltando su questo enorme valore aggiunto, perché è finalmente un ottimo modo per gli artisti di essere ricompensati per il loro lavoro. Oltre a questo, gli NFT sono un modo divertente per mostrare la tua creatività e diventare un collezionista in un mondo digitale.

Il valore degli NFT

Gli NFT hanno fatto molta strada e continuiamo a vedere vendite di NFT da record, come "Everydays: The First 5.000 Days" venduto per $ 69,3 milioni.

Crea un NFT
Immagine da Twitter

Quindi c'è molto valore qui, ed è anche un modo divertente, dinamico e coinvolgente di creare arte nel mondo digitale oltre che di a imparare la creazione di contratti intelligenti. Quindi ora ti insegnerò tutto ciò che devi sapere sulla creazione di NFT.

Come fare un NFT

Cosa non tratteremo

Ora, il modo più semplice per creare un NFT è semplicemente andare su una piattaforma come Opensea , Rarible o Mintible e seguire la loro guida passo passo per l'implementazione sulla loro piattaforma.

Puoi prendere questa strada al 100%, tuttavia potresti rimanere legato alla piattaforma e bloccato nelle sue funzionalità. Non puoi ottenere la personalizzazione illimitata o utilizzare davvero nessuno dei vantaggi offerti dagli NFT. Ma se sei un ingegnere del software alle prime armi, o non molto tecnico, questa è la strada che fa per te.

Invece se stai cercando di diventare un ingegnere del software più forte, imparare un po' di solidity e ottenere le capacità di creare qualcosa con creatività illimitata, continua a leggere!

Se sei nuovo nell'usare solidity, non ti preoccupare, parleremo delle basi anche in questo caso.

Come creare un NFT con personalizzazione illimitata

Ti farò fare un salto di qualità con questo Brownie Mix NFT . Questo è un repository funzionante con molto codice boilerplate.

Prerequisiti

Per iniziare abbiamo bisogno di alcune cose installate:

Se non hai familiarità con Metamask, puoi seguire questo tutorial per configurarlo.

Lavoreremo anche sul testnet Rinkeby di Ethereum, quindi implementeremo i nostri contratti su una vera blockchain, gratuitamente!

I testnet sono ottimi modi per testare come si comportano i nostri contratti intelligenti nel mondo reale. Abbiamo bisogno di Rinkeby ETH e Rinkeby LINK, che possiamo ottenere gratuitamente dai link agli ultimi faucet dalla documentazione di Chainlink .

Dovremo anche aggiungere il token LINK rinkeby al nostro metamask, cosa che possiamo fare seguendo la documentazione di acquisizione LINK .

Se sei ancora confuso, puoi seguire questo video , assicurati di usare Rinkeby invece di Ropsten.

Quando lavoriamo con una piattaforma di smart contract come Ethereum, dobbiamo pagare un po' di ETH e quando riceviamo dati da off-chain, dobbiamo pagare un po' di LINK. Questo è il motivo per cui abbiamo bisogno di testnet LINK ed ETH.

Fantastico, iniziamo. Questa è l'NFT che implementeremo su OpenSea.

Screen-Shot-31-03-2021-at-10.58.35-AM

Avvio rapido

git clone https://github.com/PatrickAlphaC/nft-mix
cd nft-mix

Stupendo! Ora dobbiamo installare ganache-cli e eth-brownie.

pip install eth-brownie
npm install -g ganache-cli

Ora possiamo impostare le nostre variabili d'ambiente . Se non hai familiarità con le variabili di ambiente, puoi semplicemente aggiungerle al tuo file .env e quindi eseguire:

source .env

Un esempio di file .env dovrebbe essere nel repository che hai appena clonato con le variabili di ambiente commentate. Decommentale per usarle!

Avrai bisogno di un WEB3_INFURA_PROJECT_ID e un PRIVATE_KEY. WEB3_INFURA_PROJECT_ID puoi trovarlo registrando gratuitamente un account Infura. Questo ci darà un modo per inviare transazioni alla blockchain.

Avremo anche bisogno di una chiave privata, che puoi ottenere dal tuo Metamask. Premi i 3 puntini e fai clic su Account Details ed Export Private Key. Per favore NON condividere questa chiave con nessuno se ci metti soldi veri!

export PRIVATE_KEY=YOUR_KEY_HERE
export WEB3_INFURA_PROJECT_ID=YOUR_PROJECT_ID_HERE
.env

Ora possiamo distribuire il nostro contratto NFT e creare il nostro primo oggetto da collezione con i seguenti due comandi.

brownie run scripts/simple_collectible/deploy_simple.py --network rinkeby
brownie run scripts/simple_collectible/create_collectible.py --network rinkeby

Il primo script distribuisce il nostro contratto NFT sulla blockchain di Rinkeby e il secondo crea il nostro primo oggetto da collezione.

Hai appena implementato il tuo primo contratto intelligente!

Non fa molto, ma non preoccuparti: ti mostrerò come renderizzarlo su OpenSea nella parte avanzata di questo tutorial. Ma prima, diamo un'occhiata allo standard del token ERC721.

Lo standard del token ERC721

Diamo un'occhiata al contratto che abbiamo appena distribuito, nel file SimpleCollectible.sol.

// SPDX-License-Identifier: MIT
pragma solidity 0.6.6;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract SimpleCollectible is ERC721 {
    uint256 public tokenCounter;
    constructor () public ERC721 ("Dogie", "DOG"){
        tokenCounter = 0;
    }

    function createCollectible(string memory tokenURI) public returns (uint256) {
        uint256 newItemId = tokenCounter;
        _safeMint(msg.sender, newItemId);
        _setTokenURI(newItemId, tokenURI);
        tokenCounter = tokenCounter + 1;
        return newItemId;
    }

}

Stiamo usando il pacchetto OpenZepplin per il token ERC721. Questo pacchetto che abbiamo importato ci consente di utilizzare tutte le funzioni di un tipico token ERC721. Questo definisce tutte le funzionalità che avranno i nostri token, come transfer che sposta i token a nuovi utenti, safeMint che crea nuovi token e altro ancora.

Puoi trovare tutte le funzioni che vengono fornite al nostro contratto controllando il contratto token OpenZepplin ERC721 . Il nostro contratto eredita queste funzioni su questa riga:

contract SimpleCollectible is ERC721 {

È così che solidity fa eredità. Quando distribuiamo un contratto, il  constructor viene chiamato automaticamente e richiede alcuni parametri.

constructor () public ERC721 ("Dogie", "DOG"){
        tokenCounter = 0;
    }

Usiamo anche il costruttore di ERC721, nel nostro costruttore, e dobbiamo solo dargli un nome e un simbolo. Nel nostro caso, sono "Dogie" e "DOG". Ciò significa che ogni NFT che creiamo sarà di tipo Dogie/DOG.

Questo è come il caso delle carte di Pokemon in cui ognuna di essa è ancora un pokemon, o ogni giocatore di baseball su una carta collezionabile è ancora un giocatore di baseball. Ogni giocatore di baseball è unico, ma rimangono comunque tutti giocatori di baseball. Stiamo solo usando il tipo DOG.

Abbiamo tokenCounter in alto che conta quanti NFT abbiamo creato di questo tipo. Ogni nuovo token ottiene un tokenId basato sul tokenCounter corrente .

Possiamo effettivamente creare un NFT con la funzione createCollectible. Questo è ciò che chiamiamo nel nostro script create_collectible.py.

function createCollectible(string memory tokenURI) public returns (uint256) {
        uint256 newItemId = tokenCounter;
        _safeMint(msg.sender, newItemId);
        _setTokenURI(newItemId, tokenURI);
        tokenCounter = tokenCounter + 1;
        return newItemId;
    }

La funzione _safeMint crea il nuovo NFT e lo assegna a chi ha chiamato createdCollectible, alias the msg.sender, con un newItemId derivato da tokenCounter. In questo modo possiamo tenere traccia di chi possiede cosa, controllando il proprietario del tokenId.

Noterai che chiamiamo anche _setTokenURI. Parliamo di questo.

Cosa sono i metadati NFT e TokenURI?

Quando vennero creati i contratti intelligenti e quindi creati gli NFT, le persone si sono subito rese conto che è davvero costoso distribuire molti dati sulla blockchain. Immagini di appena un KB possono facilmente costare oltre 1 milione di dollari per l'archiviazione .

Questo è chiaramente un problema per gli NFT, poiché avere un'arte creativa significa che devi archiviare queste informazioni da qualche parte. Volevano anche un modo leggero per archiviare gli attributi su un NFT, ed è qui che entrano in gioco tokenURI e metadati.

TokenURI

Il tokenURI su un NFT è un identificatore univoco di come "sembra" il token. Un URI potrebbe essere una chiamata API su HTTPS, un hash IPFS o qualsiasi altra cosa univoca.

Seguono uno standard di visualizzazione dei metadati simile a questo:

{
    "name": "name",
    "description": "description",
    "image": "https://ipfs.io/ipfs/QmTgqnhFBMkfT9s8PHKcdXBn1f5bG3Q5hmBaR4U6hoTvb1?filename=Chainlink_Elf.png",
    "attributes": [
        {
            "trait_type": "trait",
            "value": 100
        }
    ]
}

Questi mostrano l'aspetto di un NFT e i suoi attributi. La sezione image punta a un altro URI di come appare l'NFT. Ciò rende facile per le piattaforme NFT come Opensea, Rarible e Mintable eseguire il rendering di NFT sulle loro piattaforme, poiché sono tutti alla ricerca di questi metadati.

Metadati off-chain vs metadati on-chain

Ora potresti pensare "aspetta... se i metadati non sono on-chain, significa che il mio NFT potrebbe andare via a un certo punto"? E avresti ragione.

Avresti anche ragione nel pensare che avere i metadati off-chain significa che non puoi utilizzare quei metadati per far interagire i tuoi contratti intelligenti tra loro.

Questo è il motivo per cui vogliamo concentrarci sui metadati on-chain, in modo da poter programmare i nostri NFT per interagire tra loro.

Tuttavia, abbiamo ancora bisogno della parte image dei metadati off-chain, poiché non abbiamo un ottimo modo per archiviare immagini di grandi dimensioni on-chain. Ma non preoccuparti, possiamo farlo gratuitamente su una rete decentralizzata usando ancora IPFS .

Ecco un esempio di imageURI di IPFS che mostra l' Elfo Chainlink creato nel tutorial di Dungeons and Dragons.

image-3
L'elfo Chainlink

Non abbiamo impostato un tokenURI per il semplice NFT perché volevamo mostrare solo un esempio di base.

Passiamo ora all'NFT avanzato, così possiamo vedere alcune delle straordinarie funzionalità che possiamo ottenere con i metadati on-chain, avere il rendering NFT su opensea e creare Dogie!

Se vuoi un video di ripasso sulla sezione che abbiamo appena esaminato, segui la distribuzione di un semplice video NFT.

NFT dinamici e avanzati

Gli NFT dinamici sono NFT che possono cambiare nel tempo o avere funzionalità a catena che possiamo utilizzare per farli interagire tra loro. Questi sono gli NFT che nel nostro caso, hanno la personalizzazione illimitata per creare interi giochi, mondi o opere d'arte interattive di qualche tipo. Passiamo alla sezione avanzata.

Avvio rapido avanzato

Assicurati di avere abbastanza testnet ETH e LINK nel tuo metamask, quindi esegui quanto segue:

brownie run scripts/advanced_collectible/deploy_advanced.py --network rinkeby
brownie run scripts/advanced_collectible/create_collectible.py --network rinkeby

Il nostro oggetto da collezione qui è una razza di cane casuale restituita dal Chainlink VRF. Chainlink VRF è un modo per ottenere numeri casuali dimostrabili e quindi una vera rarità nei nostri NFT. Quindi vogliamo creare i suoi metadati.

brownie run scripts/advanced_collectible/create_metadata.py --network rinkeby

Possiamo quindi caricare facoltativamente questi dati su IPFS in modo da poter avere un tokenURI. Ti mostrerò come farlo più tardi. Per ora, useremo solo il tokenURI di esempio di:

https://ipfs.io/ipfs/Qmd9MCGtdVz2miNumBHDbvj8bigSgTwnr4SbyH6DNnpWdt?filename=1-PUG.json

Se scarichi IPFS Companion nel tuo browser, puoi utilizzare quell'URL per vedere cosa restituisce l'URI. Assomiglierà  a qualcosa del genere:

{
    "name": "PUG",
    "description": "An adorable PUG pup!",
    "image": "https://ipfs.io/ipfs/QmSsYRx3LpDAb1GZQm7zZ1AuHZjfbPkD6J7s9r41xu1mf8?filename=pug.png",
    "attributes": [
        {
            "trait_type": "cuteness",
            "value": 100
        }
    ]
}

Quindi possiamo eseguire il nostro script  set_tokenuri.py:

brownie run scripts/advanced_collectible/set_tokenuri.py --network rinkeby

E otterremo un output come questo:

Running 'scripts/advanced_collectible/set_tokenuri.py::main'...
Working on rinkeby
Transaction sent: 0x8a83a446c306d6255952880c0ca35fa420248a84ba7484c3798d8bbad421f88e
  Gas price: 1.0 gwei   Gas limit: 44601   Nonce: 354
  AdvancedCollectible.setTokenURI confirmed - Block: 8331653   Gas used: 40547 (90.91%)

Awesome! You can view your NFT at https://testnets.opensea.io/assets/0x679c5f9adC630663a6e63Fa27153B215fe021b34/0
Please give up to 20 minutes, and hit the "refresh metadata" button

E possiamo premere il link fornito per vedere come appare su Opensea! Potrebbe essere necessario premere il pulsante refresh metadata e attendere qualche minuto.

Crea un NFT
Aggiorna metadati

La razza casuale

Parliamo di quello che abbiamo appena fatto. Ecco il nostro AdvancedCollectible.sol:

pragma solidity 0.6.6;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";

contract AdvancedCollectible is ERC721, VRFConsumerBase {
    uint256 public tokenCounter;
    enum Breed{PUG, SHIBA_INU, BRENARD}
    // add other things
    mapping(bytes32 => address) public requestIdToSender;
    mapping(bytes32 => string) public requestIdToTokenURI;
    mapping(uint256 => Breed) public tokenIdToBreed;
    mapping(bytes32 => uint256) public requestIdToTokenId;
    event requestedCollectible(bytes32 indexed requestId); 


    bytes32 internal keyHash;
    uint256 internal fee;
    uint256 public randomResult;
    constructor(address _VRFCoordinator, address _LinkToken, bytes32 _keyhash)
    public 
    VRFConsumerBase(_VRFCoordinator, _LinkToken)
    ERC721("Dogie", "DOG")
    {
        tokenCounter = 0;
        keyHash = _keyhash;
        fee = 0.1 * 10 ** 18;
    }

    function createCollectible(string memory tokenURI, uint256 userProvidedSeed) 
        public returns (bytes32){
            bytes32 requestId = requestRandomness(keyHash, fee, userProvidedSeed);
            requestIdToSender[requestId] = msg.sender;
            requestIdToTokenURI[requestId] = tokenURI;
            emit requestedCollectible(requestId);
    }

    function fulfillRandomness(bytes32 requestId, uint256 randomNumber) internal override {
        address dogOwner = requestIdToSender[requestId];
        string memory tokenURI = requestIdToTokenURI[requestId];
        uint256 newItemId = tokenCounter;
        _safeMint(dogOwner, newItemId);
        _setTokenURI(newItemId, tokenURI);
        Breed breed = Breed(randomNumber % 3); 
        tokenIdToBreed[newItemId] = breed;
        requestIdToTokenId[requestId] = newItemId;
        tokenCounter = tokenCounter + 1;
    }

    function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: transfer caller is not owner nor approved"
        );
        _setTokenURI(tokenId, _tokenURI);
    }
}

Usiamo il Chainlink VRF per creare una razza casuale da un elenco di PUG, SHIBA_INU, BRENARD. Questa volta chiamando createCollectible, abbiamo effettivamente avviato una richiesta al nodo Chainlink VRF off-chain e siamo tornati con un numero casuale per creare l'NFT con una di quelle 3 razze.

L'uso della vera casualità nei tuoi NFT è un ottimo modo per creare una vera rarità e l'uso di un numero casuale di un oracolo Chainlink significa che il tuo numero è probabilmente casuale e non può essere influenzato dai minatori.

Puoi saperne di più su Chainlink VRF nella documentazione .

Il nodo Chainlink risponde chiamando la funzione fulfillRandomness e crea l'oggetto da collezione in base al numero casuale. Quindi dobbiamo ancora chiamare _setTokenURI per dare al nostro NFT l'aspetto di cui ha bisogno.

Qui non abbiamo fornito i nostri attributi NFT, ma gli attributi sono un ottimo modo per far combattere e interagire i nostri NFT. Puoi vedere un ottimo esempio di NFT con attributi in questo esempio di Dungeons and Dragons .

Metadati da IPFS

Stiamo usando IPFS per memorizzare due file:

  1. L'immagine dell'NFT (l'immagine del carlino)
  2. Il file tokenURI (il file JSON che include anche il collegamento dell'immagine)

Usiamo IPFS perché è una piattaforma decentralizzata gratuita. Possiamo aggiungere i nostri tokenURI e immagini a IPFS scaricando IPFS desktop e premendo il pulsante import.

Crea un NFT
IPFS aggiunge un file

Quindi, possiamo condividere l'URI premendo i 3 punti accanto al file che vogliamo condividere, premendo share link e copiando il collegamento fornito. Possiamo quindi aggiungere questo collegamento nel nostro file  set_tokenuri.py per modificare l'URI del token che vogliamo utilizzare.

Persistenza

Tuttavia, se il tokenURI è solo sul nostro nodo, significa che quando il nostro nodo è inattivo, nessun altro può visualizzarlo. Quindi vogliamo che altri pin siano nel nostro NFT. Possiamo utilizzare un servizio di pinning come Pinata per mantenere in vita i nostri dati anche quando il nostro nodo IPFS è inattivo.

Immagino che in futuro sempre più metadati verranno archiviati su IPFS e altre piattaforme di archiviazione decentralizzate. I server centralizzati possono non funzionare e significherebbe che l'arte di quegli NFT è persa per sempre. Assicurati di controllare dove si trova il tokenURI dell'NFT che usi!

Mi aspetto anche che più persone utilizzeranno piattaforme dStorage come Filecoin, poiché anche l'utilizzo di un servizio di pinning non è decentralizzato come dovrebbe essere.

Andando avanti

Se desideri una video guida sull'NFT avanzato, puoi guardare il video NFT avanzato .

Ora hai le capacità per creare NFT divertenti, personalizzabili e interattivi e renderli su un mercato.

Gli NFT sono modi divertenti e potenti per avere artisti accuratamente compensati per tutto il duro lavoro che fanno. Buona fortuna e ricordati di divertirti!