Como escrever e implantar um NFT (Primeira parte da série de tutoriais sobre NFT)
Com os NFTs levando a blockchain aos olhos do público, agora é uma excelente oportunidade para você mesmo entender todo esse interesse, publicando seu próprio NFT (ERC-721 Token) na blockchain Ethereum!
A Alchemy tem muito orgulho por estar no espaço NFT com os maiores nomes incluindo Makersplace (recentemente atingiu a marca de 69 milhões de doláres em vendas de artes digitais), Dapper Labs (criadores do NBA Top Shot e Crypto Kitties), OpenSea (o maior mercado de NFT do mundo), Zora, Super Rare, NFTfi, Foundation, Enjin, Origin Protocol, Immutable e muito mais.
Neste tutorial, vamos ver a criação e implantação de um contrato inteligente ERC-721 na rede de testes de Ropsten usando o MetaMask, Solidity, Hardhat,, Pinhata e Alchemy (não importa se você não entender o que isso significa ainda — vamos explicar!).
Na parte 2 deste tutorial, veremos como podemos usar nosso contrato inteligente para gerar NFT, e na Parte 3, explicaremos como ver seu NFT no MetaMask.
And of course, if you have questions at any point, don’t hesitate to reach out in the Alchemy Discord or visit Alchemy's NFT API docs!
Etapa 1: Se conectar à rede Ethereum
Existem várias maneiras de fazer solicitações para a blockchain Ethereum, mas para facilitar as coisas, usaremos uma conta gratuita na Alchemy, uma plataforma e API de desenvolvedores blockchain que nos permite nos comunicar com a cadeia Ethereum sem ter que executar os nossos próprios nós.
Neste tutorial, também aproveitaremos as ferramentas de desenvolvedor da Alchemy para fins de monitoramento e análise, para entender o que está acontecendo nos bastidores da nossa implantação de contrato inteligente. Se você ainda não tiver uma conta da Alchemy, inscreva-se gratuitamente aqui.
Etapa 2: Criar seu aplicativo (e chave de API)
Assim que criar uma conta na Alchemy, você pode gerar uma chave de API criando um "app". Isso nos permitirá fazer solicitações à rede de testes Ropsten. Confira este guia se você está curioso para aprender mais sobre as redes de teste.
- Vá até a página "Create App" no painel da Alchemy, passe o mouse sobre a palavra "Apps" na barra de navegação e clique em "Create App"
- Nomeie seu aplicativo (nós escolhemos "My First NFT!"), faça uma breve descrição, selecione "Staging" para o ambiente (usado para a contabilidade do seu ‘app’) e escolha "Ropsten" para sua rede.
- Clique em "Create App", e é isso e tudo! Seu app deveria aparecer na tabela abaixo.
Etapa 3: Criar uma conta Ethereum (endereço)
Precisamos de uma conta Ethereum para enviar e receber transações. Para este tutorial, usaremos uma carteira virtual no navegador, a MetaMask, para gerenciar o endereço da sua conta Ethereum. Se você quiser entender mais sobre como as transações no Ethereum funcionam, confira esta página na Fundação Ethereum.
Você pode baixar e criar uma conta MetaMask gratuitamente neste link. Quando estiver criando uma conta, ou se já tiver uma, certifique-se de mudar para a "Ropsten Test Network", no canto superior direito (para não precisar lidar com dinheiro de verdade).
Etapa 4: Adicionar ether de um faucet
Para implementar nosso contrato inteligente na rede de teste, precisaremos de alguns ETHs de imitação. To get ETH you can go to the FaucETH and enter your Ropsten account address, click “Request funds”, then select “Ethereum Testnet Ropsten” in the dropdown and finally click “Request funds” button again. Você deveria ver o ETH na sua conta MetaMask logo depois!
Etapa 5: Verificar seu saldo
Para verificar novamente que temos saldo, vamos fazer uma solicitação através da ferramenta eth_getBalance fornecida pelo compositor da Alchemy. Ele mostrará a quantidade de ETH em nossa carteira. Depois de inserir o endereço da sua conta da MetaMask e clicar em "Send Request", você verá uma resposta como esta:
1`{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}`2
OBSERVAÇÃO: este resultado é em wei não em ETH. Lembre-se de que "Wei" é a menor unidade de ether. A conversão de Wei para ETH é 1 eth = 1018 Wei. Então, se convertemos 0xde0b6b3a7640000 para decimal, temos 1*1018 wei, que é igual a 1 ETH.
Ufa! O nosso dinheiro falso está todo lá.
Etapa 6: Dar início a nosso projeto
Primeiro, precisamos criar uma pasta para o nosso projeto. Navegue até sua linha de comando e digite:
1mkdir my-nft2cd my-nft3
Agora que estamos dentro da pasta do nosso projeto, vamos usar npm init para inicializá-lo. Se você ainda não tiver o npm instalado, siga estas instruções (nós também vamos precisar do Node.js, então baixe isso também!).
1npm init2
Não importa realmente como você responde às questões de instalação; aqui está o que utilizamos de referência:
1package name: (my-nft)2version: (1.0.0)3description: My first NFT!4entry point: (index.js)5test command:6git repository:7keywords:8author:9license: (ISC)10About to write to /Users/thesuperb1/Desktop/my-nft/package.json:1112{13 "name": "my-nft",14 "version": "1.0.0",15 "description": "My first NFT!",16 "main": "index.js",17 "scripts": {18 "test": "echo \"Error: no test specified\" && exit 1"19 },20 "author": "",21 "license": "ISC"22}23Exibir tudo
Aprove o package.json e estamos prontos para começar!
Etapa 7: Instalar o Hardhat
Hardhat é um ambiente de desenvolvimento para compilar, implantar, testar e depurar seu software de Ethereum. Ele ajuda os desenvolvedores na criação de contratos inteligentes e dApps localmente antes de implantar na cadeia online.
Dentro do nosso projeto my-nft execute:
1npm install --save-dev hardhat2
Para mais detalhes, confira esta página sobre as instruções de instalação.
Etapa 8: Criar o projeto Hardhat
Dentro da nossa pasta de projeto, execute:
1npx hardhat2
Você deve ver uma mensagem de boas-vindas e a opção de selecionar o que você quer fazer. Selecione "create an empty hardhat.config.js":
1888 888 888 888 8882888 888 888 888 8883888 888 888 888 88848888888888 8888b. 888d888 .d88888 88888b. 8888b. 8888885888 888 "88b 888P" d88" 888 888 "88b "88b 8886888 888 .d888888 888 888 888 888 888 .d888888 8887888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.8888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y8889👷 Welcome to Hardhat v2.0.11 👷10? O que você deseja fazer? …11Create a sample project12❯ Create an empty hardhat.config.js13Quit14Exibir tudo
Isso vai gerar um arquivo hardhat.config.js onde especificaremos todas as configurações para o nosso projeto (no passo 13).
Etapa 9: Adicionar as pastas do projeto
Para manter a organização do nosso projeto, vamos criar duas novas pastas. Navegue até o diretório raiz do seu projeto na linha de comando e digite:
1mkdir contracts2mkdir scripts3
contracts/ é onde manteremos o nosso código de contrato inteligente para o NFT
scripts/ é onde manteremos scripts para implantar e interagir com nosso contrato inteligente
Etapa 10: Escrever nosso contrato
Agora que nosso ambiente de trabalho está configurado, iremos para a parte mais emocionante: escrever nosso contrato de código inteligente!
Abra o projeto my-nft no seu editor favorito (nós gostamos do VSCode). Os contratos inteligentes são escritos em uma linguagem chamada Solidity, que usaremos para escrever nosso contrato inteligente MyNFT.sol.
Navegue até a pasta de
contracts
e crie um novo arquivo chamado MyNFT.solAbaixo está o nosso código de contrato inteligente NFT, nossa base para a implementação do ERC-721 da biblioteca OpenZeppelin. Copie e cole o conteúdo abaixo no seu arquivo MyNFT.sol.
1//Contract based on [https://docs.openzeppelin.com/contracts/3.x/erc721](https://docs.openzeppelin.com/contracts/3.x/erc721)2// SPDX-License-Identifier: MIT3pragma solidity ^0.8.0;45import "@openzeppelin/contracts/token/ERC721/ERC721.sol";6import "@openzeppelin/contracts/utils/Counters.sol";7import "@openzeppelin/contracts/access/Ownable.sol";8import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";910contract MyNFT is ERC721URIStorage, Ownable {11 using Counters for Counters.Counter;12 Counters.Counter private _tokenIds;1314 constructor() ERC721("MyNFT", "NFT") {}1516 function mintNFT(address recipient, string memory tokenURI)17 public onlyOwner18 returns (uint256)19 {20 _tokenIds.increment();2122 uint256 newItemId = _tokenIds.current();23 _mint(recipient, newItemId);24 _setTokenURI(newItemId, tokenURI);2526 return newItemId;27 }28}29Exibir tudoCopiar
Como estamos herdando classes da biblioteca de contratos OpenZeppelin, na linha de comando execute
npm install @openzeppelin/contracts
para instalar a biblioteca em nossa pasta.
Então, o que esse código faz exatamente? Vamos por partes, linha por linha.
No topo do nosso contrato inteligente, importamos três classes de contrato inteligente OpenZeppelin:
@openzeppelin/contracts/token/ERC721/ERC721.sol contém a implementação do padrão ERC-721, que nosso contrato inteligente NFT herdará. (Para ser um NFT válido, seu contrato inteligente deve implementar todos os métodos do padrão ERC-721.) Para saber mais sobre as funções herdadas do ERC-721, confira a definição da interface aqui.
@openzeppelin/contracts/utils/Counters.sol fornece contadores que só podem ser incrementados ou diminuídos por um. Nosso contrato inteligente usa um contador para acompanhar o número total de NFTs impressos e definir o ID exclusivo em nosso novo NFT. (Cada NFT cunhado usando um contrato inteligente deve ter um ID único – aqui nosso ID exclusivo é determinado pelo número total de NFTs existentes. Por exemplo, o primeiro NFT que cunhamos com o nosso contrato inteligente tem um ID igual a "1," nosso segundo NFT tem um ID igual a "2," etc.)
@openzeppelin/contratos/access/Ownable.sol configura controle de acesso em nosso contrato inteligente, então apenas o proprietário do contrato inteligente (você) pode 'cunhar' NFTs. (Observação, incluir controle de acesso é inteiramente uma preferência. Se você quer que qualquer pessoa consiga gerar um NFT usando seu contrato inteligente, remove a palavra "Ownable" na linha 10 e "onlyOwner" na linha 17.)
Depois de seguir nossas instruções de importação, temos o nosso contrato inteligente de NFT, que é surpreendentemente curto – contém apenas um contador, um construtor e uma única função! Isto é graças aos nossos contratos OpenZeppelin herdados, que implementam a maioria dos métodos de que precisamos para criar um NFT, tal como ownerOf
, que retorna o proprietário do NFT, e transferFrom
, que transfere a propriedade do NFT de uma conta para outra.
No nosso construtor ERC-721, você notará que transmitimos 2 ‘strings’: "MyNFT" e "NFT" A primeira variável é o nome do contrato inteligente e a segunda é símbolo dele. Você pode nomear cada uma dessas variáveis como quiser!
Finally, we have our function mintNFT(address recipient, string memory tokenURI)
that allows us to mint an NFT! Você vai notar que essa função recebe duas variáveis:
address recipient
especifica o endereço que receberá o seu NFT recém-cunhadostring memory tokenURI
é uma string que deve ser resolvida em um documento JSON que descreve os metadados do NFT. Os metadados de um NFT são o que realmente o torna realidade, permitindo que tenha propriedades configuráveis, como um nome, descrição, imagem e outros atributos. Na parte 2 deste tutorial, descreveremos como configurar este metadado.
mintNFT
chama alguns métodos da biblioteca ERC-721 herdada, e retorna um número que representa o ID do NFT recém-cunhada.
Etapa 11: Vincular as contas MetaMask e Alchemy a seu projeto
Agora que criamos uma carteira MetaMask, uma conta Alchemy e escrevemos o nosso contrato inteligente, é hora de vinculá-las.
Toda transação enviada da sua carteira virtual requer uma assinatura, usando sua chave privada única. Para fornecer esta permissão a nosso programa, podemos armazenar nossa chave privada (e a chave Alchemy API) em um arquivo de ambiente.
Para saber mais sobre o envio de transações, confira este tutorial sobre como enviar transações usando a web3.
Primeiro, instale o pacote dotenv no diretório do seu projeto:
1npm install dotenv --save2
Then, create a .env
file in the root directory of our project, and add your MetaMask private key and HTTP Alchemy API URL to it.
Siga estas instruções para exportar sua chave privada do MetaMask
Veja abaixo como obter o URL da API HTTP Alchemy e copiá-la para a área de transferência
Your .env
should now look like this:
1API_URL="https://eth-ropsten.alchemyapi.io/v2/your-api-key"2PRIVATE_KEY="your-metamask-private-key"3
Para realmente vinculá-los a nosso código, vamos fazer referência a essas variáveis em nosso arquivo hardhat.config.js no passo 13.
.env
! Please make sure never to share or expose your .env
file with anyone, as you are compromising your secrets in doing so. If you are using version control, add your .env
to a gitignore file.Etapa 12: Instalar o Ethers.js
Ethers.js é uma biblioteca que facilita a interação e o envio de solicitações ao Ethereum ao incorporar métodos padrões JSON-RPC a outros métodos mais amigáveis ao usuário.
Hardhat torna muito fácil a integração de plugins, para ferramentas adicionais e funcionalidades extendidas. Aproveitaremos o plugin Ethers para implantação de contratos. (Ethers.js tem alguns métodos de implantação de contratos bastante claros).
No diretório do seu projeto, digite:
1npm install --save-dev @nomiclabs/hardhat-ethers ethers@^5.0.02
Também precisaremos de ethers em nosso hardhat.config.js na próxima etapa.
Etapa 13: Atualizar hardhat.config.js
Até aqui, já adicionamos diversas dependências e plugins. Agora precisamos atualizar o hardhat.config.js para que nosso projeto reconheça todos eles.
Atualize seu hardhat.config.js para ficar assim:
1/**2* @type import('hardhat/config').HardhatUserConfig3*/4require('dotenv').config();5require("@nomiclabs/hardhat-ethers");6const { API_URL, PRIVATE_KEY } = process.env;7module.exports = {8 solidity: "0.8.1",9 defaultNetwork: "ropsten",10 networks: {11 hardhat: {},12 ropsten: {13 url: API_URL,14 accounts: [`0x${PRIVATE_KEY}`]15 }16 },17}18Exibir tudo
Etapa 14: Compilar nosso contrato
Para ter certeza de que tudo está funcionando, vamos compilar nosso contrato. A tarefa de compilação é uma das tarefas integradas do Hardhat.
Execute na linha de comando:
1npx hardhat compile2
Você pode receber o aviso SPDX license identifier not provided in source file, mas não há necessidade de se preocupar com isso. Esperemos que tudo mais esteja bem! Se não, você sempre pode enviar uma mensagem no discord Alchemy.
Etapa 15: Escrever nosso script de implantação
Agora que nosso contrato está escrito e nosso arquivo de configuração está pronto, é hora de escrever o script de implantação do contrato.
Navegue até a pasta scripts/
e crie um novo arquivo chamado deploy.js
, adicionando o seguinte conteúdo:
1async function main() {2 const MyNFT = await ethers.getContractFactory("MyNFT")34 // Start deployment, returning a promise that resolves to a contract object5 const myNFT = await MyNFT.deploy()6 await myNFT.deployed()7 console.log("Contract deployed to address:", myNFT.address)8}910main()11 .then(() => process.exit(0))12 .catch((error) => {13 console.error(error)14 process.exit(1)15 })16Exibir tudoCopiar
A Hardhat fez um trabalho incrível ao explicar o que cada uma dessas linhas de código faz em seu Tutorial sobre contratos. Adotamos aqui as explicações deles.
1const MyNFT = await ethers.getContractFactory("MyNFT");2
Uma ContractFactory em ethers.js é uma abstração usada para implantar novos contratos inteligentes, então MyNFT aqui representa uma fábrica para instâncias do nosso contrato NFT. Ao usar o plug-in hardhat-ethers, as instâncias ContractFactory e Contract são conectadas ao primeiro signatário por padrão.
1const myNFT = await MyNFT.deploy();2
Ao chamar deploy() em uma ContractFactory, a implantação se iniciará e retornará uma Promise que se resolve em um Contract. Este é o objeto que tem um método para cada uma de nossas funções de contrato inteligente.
Etapa 16: Implantar nosso contrato
Finalmente estamos prontos para implantar o nosso contrato inteligente! Navegue de volta para a raiz do diretório do seu projeto e, na linha de comando, execute:
1npx hardhat --network ropsten run scripts/deploy.js2
Você deverá ver algo assim:
1Contract deployed to address: 0x81c587EB0fE773404c42c1d2666b5f557C470eED2
If we go to the Ropsten etherscan and search for our contract address we should be able to see that it has been deployed successfully. If you can't see it immediately, please wait a while as it can take some time. A transação ficará parecida com isto:
O endereço do remetente (From) deve corresponder ao seu endereço da conta MetaMask e o endereço do destinatário (To) deve dizer "Contract Creation". Se clicarmos na transação, veremos o nosso endereço de contrato no campo "To":
Sim! Você acabou de implantar o seu contrato inteligente NFT para a cadeia Ethereum!
Para entender o que está acontecendo nos bastidores, vamos navegar até a guia Explorer no painel do Alchemy. Se você tem vários aplicativos Alchemy certifique-se de filtrar por app e selecionar "MyNFT".
Aqui você verá um punhado de chamadas JSON-RPC que Hardhat/Ethers fizeram em segundo plano para nós quando chamamos a função .deploy() . Duas importantes chamadas aqui são eth_sendRawTransaction, que é o pedido para realmente escrever nosso contrato inteligente na cadeia de Ropsten, e eth_getTransactionByHash, que é um pedido para ler informações sobre nossa transação, dado o hash (um padrão típico ao enviar transações). Para saber mais sobre o envio de transações, confira este tutorial sobre como enviar transações usando a web3.
Isso é tudo para a Parte 1 deste tutorial. Na Parte 2, interagiremos com o nosso contrato inteligente cunhando um NFT, e na Parte 3, mostraremos como ver o seu NFT na sua carteira Ethereum!