> For the complete documentation index, see [llms.txt](https://docs.chiliz.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.chiliz.com/pt-br/desenvolver/avancado/trabalhar-com-nfts/mintar-com-thirdweb.md).

# Mintar com thirdweb

O [thirdweb](https://thirdweb.com/) é uma plataforma que oferece ferramentas e infraestrutura para criar aplicações descentralizadas em múltiplas redes blockchain. Simplifica a integração com blockchain via SDKs, APIs e componentes pré-construídos.

Para mintagem de NFTs, o thirdweb oferece um dashboard aprimorado e upload IPFS juntamente com seus contratos auditados e SDKs extensos.

## Mintando um único NFT manualmente

Se você simplesmente quer fazer upload de uma imagem única e mintá-la, o thirdweb oferece uma interface de implantação por clique.

Primeiro, crie uma conta thirdweb usando sua carteira Web3 como proprietário. Isso dá acesso ao seu dashboard thirdweb.

A partir daí, você pode escolher entre dois caminhos:

* Use a página [TokenERC721](https://thirdweb.com/thirdweb.eth/TokenERC721) e seu botão "Deploy Now".
* Ou use a interface "Create Token" do dashboard.

Vamos explorar cada um rapidamente nesta página.\
O [Portal do Desenvolvedor thirdweb](https://portal.thirdweb.com/) fornecerá mais informações caso necessite.

### Usando a página TokenERC721

1. Acesse a página [TokenERC721](https://thirdweb.com/thirdweb.eth/TokenERC721). Esta usa o contrato deles para criar uma Coleção NFT.
2. Clique em "Deploy Now" para acessar a página de implantação do contrato.

<figure><img src="/files/ZDFjhJl1eBLnmHgOEeoj" alt=""><figcaption></figcaption></figure>

3. Preencha a seção "Contract metadata":
   1. Faça upload da imagem que quer representar sua coleção NFT (ou apenas a imagem que quer mintar).
   2. Dê um nome único e um símbolo/ticker à sua coleção.
   3. Adicione uma descrição.
4. O thirdweb preenche automaticamente os endereços de destinatários para "Primary Sales" e "Royalties" — certifique-se de que os endereços Web3 são de fato os da sua carteira.
5. Em "Deploy Options", escolha a Chiliz Chain (ou Spicy Testnet se for apenas um teste) e clique em "Deploy Now":

<figure><img src="/files/u7wnJ0LDnh7Jh3PY9Wpt" alt=""><figcaption></figcaption></figure>

6. O thirdweb iniciará a implantação do contrato, acionando um modal de confirmação da sua carteira Web3. Confirme para concluir a implantação.\
   ![](/files/d78tPpwarp3WsEeIPQHr)
7. Após concluir, clique no botão "View Contract". Você será levado à página do contrato no seu dashboard thirdweb, com uma lista de verificação/barra de progresso:\
   ![](/files/svF3cznMdhTApvgEUZsU)
8. Como você pode ver na lista de verificação, por enquanto você apenas implantou um contrato, ainda precisa mintar o NFT de fato. Na coluna esquerda, clique no item de menu "NFTs" para abrir uma nova página, que por enquanto está vazia:\
   ![](/files/VxMAQjtcEFh85XKZ7pKj)
9. Clique no botão "Mint" e um painel lateral abre com campos para cada atributo do seu NFT. É aqui que você cria os metadados do seu NFT:\
   ![](/files/vgere1IZhVkrtrDUOkhZ)
10. Preencha os vários campos. Você pode criar campos específicos para sua coleção NFT, como "Artist\_name" ou "Type\_of\_work", e explorar opções avançadas, mas para este teste você pode manter o mínimo: nome, arquivo de mídia, descrição.
11. Clique no botão "Mint NFT" na parte inferior do painel lateral e aprove a transação na sua carteira.\
    ![](/files/mLyrmsmFcqe3fnIZOmJn)
12. O thirdweb exibirá a página "NFTs", com seu NFT agora visível, vinculado ao seu contrato NFT.

PRONTO! Você mintou seu NFT!

Para verificar se está de fato na Chiliz Chain, abra o [Chiliscan](https://www.chiliscan.com/) (ou sua [variante Testnet](https://testnet.chiliscan.com/) se estiver usando Spicy Testnet) e cole o hash do NFT no campo de pesquisa. Ele deve confirmar imediatamente que seu contrato está na rede, e a aba "Inventory" deve listar seu NFT com você (ou pelo menos o ID da sua carteira) como proprietário.

<figure><img src="/files/r01SDhs67AWpr5XGk7w7" alt=""><figcaption></figcaption></figure>

Se você mintou seu NFT na Chiliz Chain Mainnet, ele deverá aparecer na sua conta em marketplaces como [Rarible](https://rarible.com/) ou [OKX](https://www.okx.com/), e a partir daí você pode começar a vendê-lo!

### Usando o botão "Create Token"

Esta é na verdade uma forma mais direta do que a anterior, e é uma adição recente ao thirdweb.

1. Em qualquer pasta de projeto no seu dashboard thirdweb, clique na opção "Tokens" na barra lateral esquerda:\
   ![](/files/jYT5qSD3kxtRMUCidxqs)
2. Na página "Tokens" que abre, clique no botão "Create Token" no lado direito. Uma janela modal abre com 2 opções, escolha "Create NFT Collection".\
   ![](/files/ZW9trm1DbtoHxqgHCQkn)
3. Isso levará você a uma versão passo a passo da página de implantação do [TokenERC721](https://thirdweb.com/thirdweb.eth/TokenERC721) (na prática, implantará um contrato ERC-721 Drop). Preencha todos os campos necessários para este contrato, depois clique em "Next".
4. A próxima tela é sobre o próprio NFT: faça upload da imagem e preencha os campos que descrevem sua imagem, depois clique em "Next".
5. O thirdweb agora exibe um resumo da coleção NFT que você está prestes a lançar. Verifique se tudo está correto, depois clique em "Launch NFT Collection".
6. O thirdweb cuida de implantar o contrato, mintar o NFT e definir as condições, tudo de uma vez. Você precisará confirmar três transações pela sua carteira Web3.\
   ![](/files/i8RxRC8rjXqZMEBHeWza)
7. Após concluir, clique no botão "View NFT" e você será levado de volta ao seu dashboard thirdweb, exibindo a página específica deste contrato — e seus NFTs vinculados.

A partir daí, você pode verificar se está de fato na rede por meio de um block explorer, ou começar a vender seu NFT em um marketplace.

## Mintando um único NFT programaticamente

Aqui está um exemplo de código usando o [thirdweb v5 SDK](https://portal.thirdweb.com/references/typescript/v5), que faz upload do arquivo de mídia para o IPFS, gera o arquivo `metadata.json` e depois também o carrega para o IPFS.

Isso exigirá que você tenha:

* Um contrato ERC-721 já implantado na Chiliz Chain. Nesse caso, você deve fazê-lo usando o thirdweb em vez de outra ferramenta.
* Uma chave de API thirdweb, vinculada ao contrato ERC-721 que você implantou pelo thirdweb. Você pode encontrá-la na página do projeto do smart contract, com o nome "Client ID".
* Uma instalação local do SDK thirdweb. Você pode fazê-lo usando `npm`:

```bash
npm install thirdweb dotenv
```

O parâmetro `dotenv` gera um arquivo `.env`, necessário para armazenar valores privados:

```
THIRDWEB_SECRET_KEY=YOUR_TW_SECRET_KEY # From your thirdweb project's page.
PRIVATE_KEY=0xabc...                   # The Web3 wallet that will send the transaction.
CONTRACT_ADDRESS=0xYour721Address      # Your deployed TokenERC721 contract.
CHAIN_ID=88882                         # 88888=Mainnet, 88882=Spicy
IMAGE_PATH=./art/image.png             # The local path to your media file.
NAME=My Chiliz NFT
DESCRIPTION=Minted on Chiliz Chain
```

{% hint style="danger" %}
Nunca exponha sua `PRIVATE_KEY` nem `THIRDWEB_SECRET_KEY` em código do lado do cliente!\
Mantenha este arquivo em um servidor seguro/CI e não o carregue em um repositório público.
{% endhint %}

Com tudo pronto, você pode se inspirar neste script, que irá:

1. Fazer upload do arquivo de mídia para o IPFS
2. Construir e fazer upload do arquivo `metadata.json`
3. Mintar o NFT usando o método mintTo do contrato.
4. Exibir o `tokenId` e `tokenUrl` resultantes.

{% hint style="success" %}
Este é apenas um exemplo de código, você precisará adaptá-lo ao código do seu próprio projeto!
{% endhint %}

{% code overflow="wrap" lineNumbers="true" fullWidth="true" %}

```typescript
import 'dotenv/config';
import fs from 'fs';
import path from 'path';

import { createThirdwebClient, getContract, sendTransaction, waitForReceipt, parseEventLogs } from "thirdweb";
import { defineChain } from "thirdweb/chains";
import { privateKeyToAccount } from "thirdweb/wallets";
import { mintTo, transferEvent, getNFT } from "thirdweb/extensions/erc721";
import { upload } from "thirdweb/storage";

function guessMime(p: string) {
  const ext = path.extname(p).toLowerCase();
  if (ext === ".png") return "image/png";
  if (ext === ".jpg" || ext === ".jpeg") return "image/jpeg";
  if (ext === ".webp") return "image/webp";
  if (ext === ".gif") return "image/gif";
  if (ext === ".mp4") return "video/mp4";
  if (ext === ".webm") return "video/webm";
  return "application/octet-stream";
}

async function main() {
  const client = createThirdwebClient({ secretKey: process.env.THIRDWEB_SECRET_KEY! });
  const chain = defineChain(Number(process.env.CHAIN_ID)); // 88888 or 88882
  const account = privateKeyToAccount({ client, privateKey: process.env.PRIVATE_KEY! });

  const contract = getContract({
    client,
    chain,
    address: process.env.CONTRACT_ADDRESS as `0x${string}`,
  });

  // Upload media file to IPFS
  const filePath = process.env.IMAGE_PATH!;
  const buffer = fs.readFileSync(filePath);
  const file = new File([buffer], path.basename(filePath), { type: guessMime(filePath) });

  const [imageUri] = await upload({ client, files: [file] }); // returns ipfs://... 

  // Build & upload metadata.json referencing IPFS imageUri
  const metadata = {
    name: process.env.NAME!,
    description: process.env.DESCRIPTION!,
    image: imageUri
  };
  const metaBlob = new Blob([JSON.stringify(metadata, null, 2)], { type: "application/json" });
  const metaFile = new File([metaBlob], "metadata.json", { type: "application/json" });

  const [metadataUri] = await upload({ client, files: [metaFile] });

  // Prepare & send mintTo transaction using the metadata URI
  const tx = mintTo({
    contract,
    to: account.address,
    nft: metadataUri,
  });

  const { transactionHash } = await sendTransaction({ transaction: tx, account });

  const receipt = await waitForReceipt({ client, chain, transactionHash });

  const events = parseEventLogs({ logs: receipt.logs, events: [transferEvent()] });
  const minted = events.find(e => e.eventName === "Transfer" && e.args.from === "0x0000000000000000000000000000000000000000");
  const tokenId = minted ? (minted.args.tokenId as bigint) : undefined;

  if (tokenId !== undefined) {
    const nft = await getNFT({ contract, tokenId });
  }
}

main().catch((err) => (console.error(err), process.exit(1)));
```

{% endcode %}

As partes importantes para se inspirar são:

* `upload` armazena arquivos (e JSON) no IPFS e retorna URIs `ipfs://…`.
* `mintTo` aceita uma string para usar diretamente como `tokenURI`.
* Analisamos o evento padrão ERC-721 `Transfer` para ler o `tokenId` mintado.

## Mintando uma coleção de NFTs programaticamente

Mintar uma coleção de NFTs não é muito diferente de mintar um único. A diferença mais notável é que seu arquivo `.env` aponta para a pasta que contém todas as imagens usando `IMAGE_DIR`, em vez de uma única imagem com `IMAGE_PATH`.

```dotenv
THIRDWEB_SECRET_KEY=YOUR_TW_SECRET_KEY
PRIVATE_KEY=0xabc...
CONTRACT_ADDRESS=0xYour721Address
CHAIN_ID=88882
IMAGE_PATH=./art
NAME_PREFIX=My Chiliz NFT
DESCRIPTION=Minted on Chiliz Chain
```

O código de exemplo representa isso:

{% code overflow="wrap" lineNumbers="true" fullWidth="true" %}

```typescript
import 'dotenv/config';
import fs from 'fs';
import path from 'path';

import { createThirdwebClient, getContract, sendTransaction, waitForReceipt, parseEventLogs } from "thirdweb";
import { defineChain } from "thirdweb/chains";
import { privateKeyToAccount } from "thirdweb/wallets";
import { mintTo, transferEvent, getNFT } from "thirdweb/extensions/erc721";
import { upload } from "thirdweb/storage";

function guessMime(p: string) {
  const ext = path.extname(p).toLowerCase();
  if (ext === ".png") return "image/png";
  if (ext === ".jpg" || ext === ".jpeg") return "image/jpeg";
  if (ext === ".webp") return "image/webp";
  if (ext === ".gif") return "image/gif";
  if (ext === ".mp4") return "video/mp4";
  if (ext === ".webm") return "video/webm";
  return "application/octet-stream";
}

function listMediaFiles(dir: string) {
  const allow = new Set([".png", ".jpg", ".jpeg", ".webp", ".gif", ".mp4", ".webm", ".svg"]);
  return fs
    .readdirSync(dir)
    .filter((f) => allow.has(path.extname(f).toLowerCase()))
    .map((f) => path.join(dir, f));
}

async function main() {
  const client = createThirdwebClient({ secretKey: process.env.THIRDWEB_SECRET_KEY! });
  const chain = defineChain(Number(process.env.CHAIN_ID));
  const account = privateKeyToAccount({ client, privateKey: process.env.PRIVATE_KEY! }); 

  const contract = getContract({
    client,
    chain,
    address: process.env.CONTRACT_ADDRESS as `0x${string}`,
  });

  const dirPath = process.env.IMAGES_DIR!;
  const filePaths = listMediaFiles(dirPath);
  if (!filePaths.length) {
    throw new Error(`No media files found in ${dirPath}`);
  }

  const fileObjs = filePaths.map((p) => {
    const buffer = fs.readFileSync(p);
    return new File([buffer], path.basename(p), { type: guessMime(p) });
  });

  const imageUris = await upload({ client, files: fileObjs });

  const namePrefix = process.env.NAME!;
  const description = process.env.DESCRIPTION!;

  const metaFiles = imageUris.map((imageUri, i) => {
    const metadata = {
      name: `${namePrefix} #${i + 1}`,
      description,
      image: imageUri
    };
    const metaBlob = new Blob([JSON.stringify(metadata, null, 2)], { type: "application/json" });
    return new File([metaBlob], `metadata-${i + 1}.json`, { type: "application/json" });
  });

  const metadataUris = await upload({ client, files: metaFiles });

  const ZERO = "0x0000000000000000000000000000000000000000";

  for (let i = 0; i < metadataUris.length; i++) {
    const metadataUri = metadataUris[i];

    const tx = mintTo({
      contract,
      to: account.address,
      nft: metadataUri,
    });

    const { transactionHash } = await sendTransaction({ transaction: tx, account });
    console.log(`[${i + 1}/${metadataUris.length}] tx:`, transactionHash);

    const receipt = await waitForReceipt({ client, chain, transactionHash });

    const events = parseEventLogs({ logs: receipt.logs, events: [transferEvent()] });
    const minted = events.find(
      (e) => e.eventName === "Transfer" && typeof e.args.from === "string" && e.args.from.toLowerCase() === ZERO
    );
    const tokenId = minted ? (minted.args.tokenId as bigint) : undefined;

    if (tokenId !== undefined) {
      const nft = await getNFT({ contract, tokenId });
    }
  }
}

main().catch((err) => (console.error(err), process.exit(1)));
```

{% endcode %}

Novamente, use este código como inspiração para seu próprio projeto, não use como está!

Nota: Se você preferir fazer lazy minting, o contrato ERC-721 do thirdweb tem [um método `lazyMint`](https://portal.thirdweb.com/references/typescript/v5/erc721/lazyMint).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.chiliz.com/pt-br/desenvolver/avancado/trabalhar-com-nfts/mintar-com-thirdweb.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
