· Nacho Coll · Guides · 9 min de leitura
Armazenamento de Metadados NFT: O Guia Completo de IPFS para Criadores de NFT
Guia passo a passo para armazenar metadados NFT no IPFS. Inclui padrões tokenURI ERC-721, exemplos em Python e JavaScript.

Criar NFTs requer mais do que apenas a implantação de smart contracts — você precisa de armazenamento descentralizado e confiável para seus metadados e ativos. Este guia abrangente leva você passo a passo pelo armazenamento de metadados NFT no IPFS usando as melhores práticas do setor, com exemplos de código para desenvolvedores Python e JavaScript.

Por que IPFS para armazenamento de metadados NFT?
A hospedagem web tradicional cria riscos de centralização para projetos NFT. Quando os metadados ficam em servidores convencionais, os NFTs podem ficar “quebrados” se o serviço de hospedagem cair ou alterar URLs. O IPFS (InterPlanetary File System) resolve isso fornecendo:
- Endereçamento de conteúdo imutável: Cada arquivo recebe um Content Identifier (CID) único que nunca muda
- Armazenamento descentralizado: O conteúdo existe em vários nós no mundo todo
- Verificação criptográfica: A integridade do arquivo é garantida por hashing de conteúdo
- URLs à prova do futuro: Links IPFS funcionam indefinidamente, protegendo o valor a longo prazo
Para uma compreensão mais profunda dos fundamentos do IPFS, confira nosso guia sobre o que é IPFS pinning.
Entendendo a estrutura de metadados ERC-721
O padrão ERC-721 define como os metadados NFT devem ser estruturados. A função tokenURI do seu smart contract retorna uma URL apontando para metadados JSON seguindo este padrão:
{
"name": "My Amazing NFT #1",
"description": "A unique digital artwork showcasing...",
"image": "ipfs://QmYourImageCIDHere",
"attributes": [
{
"trait_type": "Background",
"value": "Blue"
},
{
"trait_type": "Rarity",
"value": "Common"
}
],
"external_url": "https://yourproject.com/token/1"
}Campos de metadados principais
- name: O título do NFT exibido em wallets e marketplaces
- description: Informações detalhadas sobre o NFT
- image: URL IPFS para o ativo visual principal
- attributes: Propriedades baseadas em traços para filtragem e cálculos de raridade
- external_url: Link opcional para conteúdo adicional ou para o site do seu projeto
Processo passo a passo de armazenamento NFT no IPFS
Etapa 1: Preparar seus ativos e metadados
Antes de enviar qualquer coisa, organize seus arquivos:
- Ativos principais: Imagens, vídeos ou outro conteúdo primário
- Arquivos de metadados: Arquivos JSON descrevendo cada NFT
- Metadados da coleção: Informações opcionais ao nível da coleção
Etapa 2: Fazer upload de ativos no IPFS
Comece fazendo upload dos seus ativos NFT principais (imagens, vídeos, etc.) para obter seus CIDs IPFS. Você referenciará esses CIDs nos seus arquivos JSON de metadados.
Aqui está como fazer upload de uma imagem usando Python:
import requests
import base64
import json
def upload_image_to_ipfs(image_path, api_key):
"""Upload an image file to IPFS and return its CID"""
# Read and encode image
with open(image_path, 'rb') as f:
image_data = base64.b64encode(f.read()).decode('utf-8')
# Prepare upload payload
payload = {
"content": image_data,
"description": f"NFT Asset: {image_path}"
}
headers = {
"Content-Type": "application/json",
"X-Api-Key": api_key
}
# Upload to IPFS.NINJA
response = requests.post(
"https://api.ipfs.ninja/upload/new",
headers=headers,
json=payload
)
if response.status_code == 200:
result = response.json()
print(f"✅ Image uploaded successfully!")
print(f"CID: {result['cid']}")
print(f"IPFS URL: {result['uris']['ipfs']}")
print(f"Gateway URL: {result['uris']['url']}")
return result['cid']
else:
print(f"❌ Upload failed: {response.text}")
return None
# Example usage
API_KEY = "bws_1234567890abcdef1234567890abcdef" # Replace with your actual key
image_cid = upload_image_to_ipfs("my-nft-artwork.png", API_KEY)Etapa 3: Criar e fazer upload do JSON de metadados
Uma vez que você tenha os CIDs dos seus ativos, crie arquivos JSON de metadados e faça upload deles:
def create_and_upload_metadata(name, description, image_cid, attributes, api_key):
"""Create NFT metadata JSON and upload to IPFS"""
# Create metadata object
metadata = {
"name": name,
"description": description,
"image": f"ipfs://{image_cid}",
"attributes": attributes
}
# Convert to JSON string and encode
metadata_json = json.dumps(metadata, indent=2)
metadata_b64 = base64.b64encode(metadata_json.encode('utf-8')).decode('utf-8')
# Upload metadata
payload = {
"content": metadata_b64,
"description": f"NFT Metadata: {name}",
"metadata": {
"contentType": "application/json",
"nftTokenId": name.split('#')[1] if '#' in name else "1"
}
}
headers = {
"Content-Type": "application/json",
"X-Api-Key": api_key
}
response = requests.post(
"https://api.ipfs.ninja/upload/new",
headers=headers,
json=payload
)
if response.status_code == 200:
result = response.json()
print(f"✅ Metadata uploaded successfully!")
print(f"Metadata CID: {result['cid']}")
return result['cid']
else:
print(f"❌ Metadata upload failed: {response.text}")
return None
# Example usage
attributes = [
{"trait_type": "Background", "value": "Cosmic Blue"},
{"trait_type": "Eyes", "value": "Laser"},
{"trait_type": "Rarity", "value": "Epic"}
]
metadata_cid = create_and_upload_metadata(
name="Cosmic Warrior #001",
description="A fierce warrior from the distant galaxies, wielding the power of stars.",
image_cid=image_cid,
attributes=attributes,
api_key=API_KEY
)Etapa 4: Implementação JavaScript
Para aplicações web ou projetos Node.js, aqui está o equivalente em JavaScript:
class NFTStorage {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.ipfs.ninja';
}
async uploadFile(fileContent, description) {
const payload = {
content: fileContent, // base64 encoded
description: description
};
const response = await fetch(`${this.baseUrl}/upload/new`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': this.apiKey
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`Upload failed: ${response.statusText}`);
}
return await response.json();
}
async uploadImageFromFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async (e) => {
try {
const base64Content = e.target.result.split(',')[1]; // Remove data:image/...;base64, prefix
const result = await this.uploadFile(base64Content, `NFT Image: ${file.name}`);
resolve(result.cid);
} catch (error) {
reject(error);
}
};
reader.readAsDataURL(file);
});
}
async uploadMetadata(name, description, imageCid, attributes = []) {
const metadata = {
name,
description,
image: `ipfs://${imageCid}`,
attributes
};
const metadataJson = JSON.stringify(metadata, null, 2);
const base64Metadata = btoa(metadataJson);
const result = await this.uploadFile(base64Metadata, `NFT Metadata: ${name}`);
return result.cid;
}
}
// Usage example
const storage = new NFTStorage('bws_1234567890abcdef1234567890abcdef'); // Replace with your key
// Upload process
async function createNFT() {
try {
// Assuming you have a file input element
const fileInput = document.getElementById('nft-image');
const imageFile = fileInput.files[0];
console.log('Uploading image...');
const imageCid = await storage.uploadImageFromFile(imageFile);
console.log(`Image uploaded: ${imageCid}`);
console.log('Uploading metadata...');
const metadataCid = await storage.uploadMetadata(
'Galaxy Explorer #042',
'A mysterious explorer traversing the cosmic void.',
imageCid,
[
{ trait_type: 'Class', value: 'Explorer' },
{ trait_type: 'Galaxy', value: 'Andromeda' },
{ trait_type: 'Rarity', value: 'Legendary' }
]
);
console.log(`Metadata uploaded: ${metadataCid}`);
console.log(`Token URI: ipfs://${metadataCid}`);
} catch (error) {
console.error('Upload failed:', error);
}
}Implementando tokenURI no seu smart contract
Uma vez que seus metadados estejam carregados no IPFS, implemente a função tokenURI no seu contrato ERC-721:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyNFTCollection is ERC721, Ownable {
mapping(uint256 => string) private _tokenURIs;
string private _baseTokenURI;
constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
function setTokenURI(uint256 tokenId, string memory uri) external onlyOwner {
require(_exists(tokenId), "Token does not exist");
_tokenURIs[tokenId] = uri;
}
function setBaseURI(string memory baseURI) external onlyOwner {
_baseTokenURI = baseURI;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string) {
require(_exists(tokenId), "Token does not exist");
string memory _tokenURI = _tokenURIs[tokenId];
// Return specific token URI if set
if (bytes(_tokenURI).length > 0) {
return _tokenURI;
}
// Fall back to base URI + token ID pattern
if (bytes(_baseTokenURI).length > 0) {
return string(abi.encodePacked(_baseTokenURI, tokenId.toString()));
}
return "";
}
function mintWithURI(address to, uint256 tokenId, string memory uri) external onlyOwner {
_mint(to, tokenId);
_tokenURIs[tokenId] = uri;
}
}Operações em lote para grandes coleções
Para grandes coleções NFT, operações em lote economizam tempo e custos de gas:
def batch_upload_collection(collection_data, api_key):
"""Upload an entire NFT collection in batches"""
print(f"Starting batch upload of {len(collection_data)} NFTs...")
results = []
for i, nft_data in enumerate(collection_data):
print(f"Processing NFT {i+1}/{len(collection_data)}: {nft_data['name']}")
try:
# Upload image
image_cid = upload_image_to_ipfs(nft_data['image_path'], api_key)
if image_cid:
# Upload metadata
metadata_cid = create_and_upload_metadata(
name=nft_data['name'],
description=nft_data['description'],
image_cid=image_cid,
attributes=nft_data['attributes'],
api_key=api_key
)
if metadata_cid:
results.append({
'token_id': i + 1,
'name': nft_data['name'],
'image_cid': image_cid,
'metadata_cid': metadata_cid,
'token_uri': f"ipfs://{metadata_cid}"
})
except Exception as e:
print(f"❌ Error processing {nft_data['name']}: {e}")
print(f"✅ Batch upload complete! {len(results)} NFTs processed successfully.")
return results
# Example collection data
collection_data = [
{
'name': 'Cosmic Warrior #001',
'description': 'A fierce warrior from distant galaxies.',
'image_path': 'images/warrior_001.png',
'attributes': [
{'trait_type': 'Class', 'value': 'Warrior'},
{'trait_type': 'Rarity', 'value': 'Epic'}
]
},
# Add more NFTs...
]
results = batch_upload_collection(collection_data, API_KEY)Melhores práticas para armazenamento de metadados NFT
1. Use nomes de arquivos descritivos
Ao fazer upload no IPFS, use descrições significativas para ajudar na organização:
payload = {
"content": base64_content,
"description": f"Collection: {collection_name} | Token: {token_id} | Type: {file_type}"
}2. Implemente tratamento adequado de erros
Sempre trate falhas de upload de forma elegante:
import time
def upload_with_retry(upload_function, max_retries=3, delay=2):
"""Upload with exponential backoff retry logic"""
for attempt in range(max_retries):
try:
return upload_function()
except Exception as e:
if attempt == max_retries - 1:
raise e
print(f"Attempt {attempt + 1} failed: {e}. Retrying in {delay} seconds...")
time.sleep(delay)
delay *= 2 # Exponential backoff3. Valide a estrutura dos metadados
Certifique-se de que seus metadados sigam os padrões:
def validate_metadata(metadata):
"""Validate NFT metadata structure"""
required_fields = ['name', 'description', 'image']
for field in required_fields:
if field not in metadata:
raise ValueError(f"Missing required field: {field}")
if not metadata['image'].startswith('ipfs://'):
raise ValueError("Image must be an IPFS URL")
if 'attributes' in metadata:
for attr in metadata['attributes']:
if 'trait_type' not in attr or 'value' not in attr:
raise ValueError("Invalid attribute structure")
return TrueEscolhendo o serviço de pinning IPFS certo
Ao selecionar um serviço de pinning IPFS para seu projeto NFT, considere:
- Confiabilidade: Tempo de atividade garantido para armazenamento de longo prazo
- Desempenho: Velocidades de recuperação rápidas em todo o mundo
- Preço: Custo-benefício para o tamanho da sua coleção
- Recursos: Capacidades de API, analytics e ferramentas para desenvolvedores
Para uma comparação detalhada dos serviços de pinning, leia nossa comparação IPFS Ninja vs Pinata e nosso guia dos melhores serviços de pinning IPFS.
Recursos avançados: Gateways customizados e analytics
O IPFS Ninja oferece recursos adicionais para projetos NFT profissionais:
Configuração de gateway customizado
Crie gateways IPFS com a sua marca para sua coleção:
// Access your NFT through a custom gateway
const customGateway = 'https://my-collection.gw.ipfs.ninja';
const nftUrl = `${customGateway}/ipfs/${metadataCid}`;Analytics de upload
Monitore o uso de armazenamento e padrões de acesso dos seus NFTs através da analítica do dashboard, ajudando você a entender o desempenho da coleção e otimizar custos de armazenamento.
Solucionando problemas comuns
Metadados não carregam
- Verifique se as URLs IPFS usam o protocolo
ipfs:// - Verifique se o JSON dos metadados é válido
- Certifique-se de que o serviço de pinning está mantendo o conteúdo
Imagens não são exibidas
- Confirme que os CIDs das imagens estão corretos nos metadados
- Teste as URLs das imagens em gateways IPFS
- Verifique se os formatos de arquivo de imagem são compatíveis com a web
Erros de estimativa de gas
- Certifique-se de que a função
tokenURIretorne strings válidas - Verifique referências circulares nos metadados
- Valide todos os CIDs IPFS antes do minting
Monitorando e mantendo seu armazenamento NFT
Após implantar sua coleção:
- Verificações regulares de saúde: Verifique se os metadados e imagens permanecem acessíveis
- Faça backup de CIDs importantes: Mantenha registros de todos os identificadores de conteúdo carregados
- Monitore analytics: Acompanhe padrões de acesso e uso de armazenamento
- Planeje para escala: Considere atualizar seu serviço de pinning conforme sua coleção cresce
Para mais detalhes sobre o gerenciamento de uploads programaticamente, consulte nosso tutorial da API de upload IPFS.
Conclusão
Armazenar metadados NFT no IPFS garante que seus ativos digitais permaneçam acessíveis e valiosos a longo prazo. Seguindo este guia, você aprendeu a:
- Estruturar metadados compatíveis com ERC-721
- Fazer upload de ativos e metadados usando Python e JavaScript
- Implementar funções
tokenURIadequadas - Lidar com operações em lote para grandes coleções
- Aplicar as melhores práticas para implantações em produção
A combinação da arquitetura descentralizada do IPFS e serviços de pinning confiáveis cria a base para projetos NFT bem-sucedidos que resistem ao teste do tempo.
Pronto para começar a fazer pinning? Crie uma conta gratuita — 50 arquivos, 1 GB de armazenamento, 2 GB de largura de banda/mês. Não é necessário cartão de crédito.
