Este guia mostrará como criar um aplicativo descentralizado onde os usuários finais podem escolher qual NFT desejam cunhar.
Vamos percorrer o seguinte:
- Criando um Contrato de Coleção de NFTs
- Mostrando os NFTs disponíveis para os usuários cunharem
- Cunhando os NFTs usando a assinatura mint
Vamos começar!
Implantando um contrato ERC721
Primeiro, implantaremos um Contrato de Coleção de NFTs que usaremos para assinar os NFTs.
Para começar, vá para a página de Contratos em seu Painel da Thirdweb e clique em "Implantar novo contrato" (Deploy new contract):
Você será levado para nossa página Explore (Exploração) - onde você pode navegar pelos contratos inteligentes construídos pelos principais protocolos web3 e implantá-los com apenas alguns cliques!
Observação: Você também pode usar a CLI da Thirdweb para configurar um ambiente de contrato inteligente executando o comando abaixo a partir do seu terminal:
npx thirdweb create contract
Isso o levará por uma sequência de etapas fáceis de seguir para criar seu contrato. Saiba mais sobre isso em nosso guia CLI.
Caso contrário, vamos voltar para a página de exploração:
Aqui, selecione o contrato inteligente de sua escolha. Para este guia, vamos usar o contrato de Coleção de NFTs para criar nossa coleção de NFTs:
Configure seu contrato inteligente com uma imagem, nome, descrição, etc., e defina qual endereço de carteira receberá os fundos das vendas primárias e secundárias:
Você pode selecionar qualquer rede que desejar; para este guia, estou escolhendo a Goerli. Saiba mais sobre as diferentes redes disponíveis abaixo:
https://blog.thirdweb.com/guides/which-network-should-you-use/
Assim que o contrato for implantado, estamos prontos para prosseguir. Não precisamos fazer nada com o contrato por enquanto.
Criando o Aplicativo Full Stack do Next.js
Agora, vamos criar um aplicativo da web de staking de NFTs em que os usuários podem conectar suas carteiras, escolher o NFT que desejam criar e criar o NFT.
Antes de começarmos, você pode acessar o código-fonte completo deste modelo no GitHub.
Usando a CLI da Thirdweb, crie um novo projeto Next.js em TypeScript com o SDK do React já pré-configurado usando o seguinte comando:
npx thirdweb create app --next --ts
Por padrão, a rede é a Rede Principal (mainnet). Você precisará alterá-la para a rede em que implantou seus contratos inteligentes dentro do arquivo _app.tsx
.
// Este é o chainId em que seu dApp funcionará.
const activeChainId = ChainId.Mumbai;
Agora, adicione as variáveis de ambiente em um novo arquivo .env.local
assim:
PRIVATE_KEY=<sua-chave-privada>
IMPORTANTE: O uso de chaves privadas como variáveis de ambiente é vulnerável a ataques e não é a melhor prática. Estamos fazendo isso neste guia por brevidade, mas recomendamos fortemente usar um gerenciador de segredos para armazenar sua chave privada.
IMPORTANTE: Chaves Privadas.
Se você estiver usando variáveis de ambiente para armazenar sua chave privada (não recomendado), nunca comprometa sua chave privada com o Git.
Se você enviar sua chave privada para o GitHub, sua carteira será esvaziada!
Crie um novo arquivo chamado data/address.ts
e adicione seu endereço assim, porque vamos precisar dele em alguns lugares:
export const nftCollectionAddress =
"0x02Fe95daB242625924B03819FB4Ab25d533EDdCA";
Mostrando os NFTs
Agora vamos adicionar os NFTs que queremos disponibilizar. Para isso, crie um arquivo data/nfts.ts
e adicione seus NFTs no seguinte formato:
import { NFT } from "../types/NFT";
export const nfts: NFT[] = [
{
id: 0,
name: "NFT 1",
description: "Este é o nosso primeiro NFT incrível.",
url: "https://bafybeihgfxd5f5sqili34vyjyfai6kezlagrya43e6bkgw6hnxucxug5ya.ipfs.nftstorage.link/",
price: 0.01,
},
{
id: 1,
name: "NFT 2",
description: "Este é o nosso segundo NFT incrível.",
url: "https://bafybeida2kkclur4345iihiqb6pepfnwse7ko7pvrft4duxwxxwo2jqqjq.ipfs.nftstorage.link/",
price: 0.02,
},
{
id: 2,
name: "NFT 3",
description: "Este é o nosso terceiro NFT incrível.",
url: "https://bafybeidegtxcfpr43d6vbrippnm2csxqst7stxaxl3rp5vd27ss6yd3s5e.ipfs.nftstorage.link/",
price: 0.03,
},
{
id: 3,
name: "NFT 4",
description: "Este é o nosso quarto NFT incrível.",
url: "https://bafybeieicywyvnaher24isrxoagjxbro6qr6kbzcz2feldbquoqeag7ivm.ipfs.nftstorage.link/",
price: 0.01,
},
{
id: 4,
name: "NFT 5",
description: "Este é o nosso quinto NFT incrível.",
url: "https://bafybeieufjiaqny6q6kis2ehv2w6epwqzkeoscfc3ltck67dunrbvseczq.ipfs.nftstorage.link/",
price: 0.02,
},
{
id: 5,
name: "NFT 6",
description: "Este é o nosso sexto NFT incrível.",
url: "https://bafybeiftcf7xruf4gmlbme6bos5tznlrvz46xfxdnofp3auibvzbizysoy.ipfs.nftstorage.link/",
price: 0.03,
},
];
Você pode adicionar mais propriedades se desejar, mas estou adicionando apenas essas. Você pode ver que também adicionamos o tipo para cada NFT, portanto, crie um arquivo types/NFT.ts
e adicione este tipo:
export interface NFT {
id: number;
name: string;
description: string;
url: string;
price: number;
minted?: boolean;
}
Vamos criar uma rota de API para verificar se algum NFT já foi criado e retornar os dados com base nisso. Então, crie um arquivo dentro de pages/api
chamado get-nfts.ts
e adicione o seguinte:
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import type { NextApiRequest, NextApiResponse } from "next";
import { nftCollectionAddress } from "../../data/address";
import { nfts } from "../../data/nfts";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method === "GET") {
const sdk = ThirdwebSDK.fromPrivateKey(process.env.PRIVATE_KEY!, "goerli");
const nftCollection = await sdk.getContract(
nftCollectionAddress,
"nft-collection"
);
try {
const mintedNfts = await nftCollection?.erc721.getAll();
if (!mintedNfts) {
return res.status(200).json(nfts);
}
mintedNfts.forEach((nft) => {
const nftIndex = nfts.findIndex(
// @ts-ignore
(nftItem) => nftItem.id === nft.metadata.attributes[0].id
);
if (nftIndex !== -1) {
nfts[nftIndex].minted = true;
}
});
return res.status(200).json(nfts);
} catch (error) {
return res.status(500).json({ error });
}
}
return res.status(405).json({ error: "Método não permitido" });
}
Aqui, primeiro verificamos se a solicitação é uma solicitação get
e, se não for, retornamos um erro, mas se for uma solicitação get
, avançamos. Primeiramente, inicializamos o sdk da thirdweb, em seguida, obtemos a coleção de NFTs usando o endereço que adicionamos anteriormente. Finalmente, obtemos todos os NFTs da coleção e, se algum dos NFTs tiver sido cunhado, definimos como "minted" e retornamos os NFTs.
Agora vamos renderizar os NFTs para os usuários. Para isso, vamos buscar os NFTs da seguinte forma:
const [nftMetadata, setNftMetadata] = useState<NFT[] | []>([]);
const fetchNfts = async () => {
try {
const response = await fetch("/api/get-nfts");
const data = await response.json();
setNftMetadata(data);
} catch (error) {
console.error(error);
}
};
useEffect(() => {
fetchNfts();
}, []);
Então, vamos verificar se o usuário conectou sua carteira e mapear os NFTs da seguinte forma:
<div className={styles.container}>
{address ? (
<>
<h1> Selecione um NFT para cunhar</h1>
<div className={styles.NFTs}>
{nftMetadata &&
nftMetadata.map((nft) => <Nft key={nft.id} nft={nft} />)}
</div>
</>
) : (
<ConnectWallet />
)}
</div>
Aqui, criamos um novo componente para o NFT. Então crie um novo arquivo components/Nft.tsx
e adicione o seguinte:
import { MediaRenderer, Web3Button } from "@thirdweb-dev/react";
import { nftCollectionAddress } from "../data/address";
import styles from "../styles/Home.module.css";
import { NFT } from "../types/NFT";
const Nft = ({ nft }: { nft: NFT }) => {
return (
<div className={styles.NFT}>
{nft?.url && <MediaRenderer src={nft.url} className={styles.NFTImage} />}
<div>
<h2>{nft?.name}</h2>
<p>{nft?.description}</p>
<p>{nft?.price} ETH</p>
</div>
{nft?.minted ? (
<b>Este NFT já foi cunhado</b>
) : (
<Web3Button contractAddress={nftCollectionAddress} action={() => {}}>
Cunhar
</Web3Button>
)}
</div>
);
};
export default Nft;
Isso cria cartões de NFT simples como estes:
Mas uma coisa a acrescentar aqui é a funcionalidade de cunhagem! Então vamos adicionar isso. Precisamos criar outra API para gerar a assinatura, então crie um novo arquivo, generate-signature.ts
e adicione o seguinte:
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import type { NextApiRequest, NextApiResponse } from "next";
import { nftCollectionAddress } from "../../data/address";
import { nfts } from "../../data/nfts";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const { id, address } = JSON.parse(req.body);
try {
const sdk = ThirdwebSDK.fromPrivateKey(process.env.PRIVATE_KEY!, "goerli");
const nftCollection = await sdk.getContract(
nftCollectionAddress,
"nft-collection"
);
const mintedNfts = await nftCollection?.erc721.getAll();
if (mintedNfts) {
const mintedNft = mintedNfts.find(
// @ts-ignore
(nft) => nft.metadata.attributes[0].id === id
);
if (mintedNft) {
return res.status(400).json({ error: "NFT já cunhado" });
}
}
const { name, description, url, price } = nfts[id];
const metadata = {
metadata: {
name,
description,
image: url,
attributes: [{ id }],
},
price,
to: address,
};
const signature = await nftCollection?.signature.generate(metadata);
return res.status(200).json({ signature });
} catch (error) {
return res.status(500).json({ error });
}
};
export default handler;
Aqui, obtemos o tokenID do request body (corpo da requisição). Primeiro, usamos para verificar se o NFT já foi cunhado, caso contrário, usamos para obter os metadados do NFT. Também obtemos o preço do corpo que está sendo usado no parâmetro to
. Finalmente, usando esses metadados, geramos a assinatura e a passamos para o frontend.
No componente Nft
, adicione estes ganchos (hooks) e esta função mintNft
:
const { data: nftCollection } = useContract(
nftCollectionAddress,
"nft-collection"
);
const address = useAddress();
const [loading, setLoading] = useState(false);
const mintNft = async (id: number) => {
setLoading(true);
try {
const response = await fetch("/api/generate-signature", {
method: "POST",
body: JSON.stringify({ id, address }),
});
if (response) {
const data = await response.json();
await nftCollection?.signature.mint(data.signature);
alert("NFT cunhado com sucesso!");
}
} catch (error) {
alert("Falha ao cunhar NFT!");
} finally {
setLoading(false);
}
};
Este código está adquirindo a Coleção de NFTs usando o gancho useContract
. Em seguida, na função real, obtemos o id dos parâmetros e fazemos uma requisição de post
para api/generate-signature
com o id e endereço. Por fim, ela recebe a assinatura e cria o NFT. Agora, anexe-a ao web3Button:
<Web3Button
action={() => mintNft(nft?.id)}
contractAddress={nftCollectionAddress}>
Cunhar
</Web3Button>
Também vamos usar o estado de carregamento para mostrar um texto de carregamento:
{loading ? (
<p
style={{
textAlign: "center",
}}
>
Cunhando...
</p>
) : nft?.minted ? (
<b>Este NFT já foi cunhado</b>
) : (
<Web3Button
action={() => mintNft(nft?.id)}
contractAddress={nftCollectionAddress}
>
Cunhar
</Web3Button>
)}
Agora podemos cunhar o NFT.
Conclusão
Este guia nos ensinou como criar um aplicativo descentralizado onde os usuários podem escolher quais NFTs cunhar usando a assinatura mint.
Você aprendeu muito! Agora dê um tapinha nas costas e compartilhe seus aplicativos incríveis conosco no discord da thirdweb! Se você quiser ver o código, confira nosso Repositório do GitHub.
Artigo original publicado por Thirdweb. Traduzido por Paulinho Giovannini.
Top comments (0)