O primeiro passo que você dará para construir um Dapp de cunhagem NFT é preparar a arte. Sem a arte, você não pode ter seu projeto NFT atualizado.
Outro motivo para pré-processar suas artes é gerar metadados para cada uma das imagens. Sem esses metadados, seu NFT não pode ser vendido em nenhum dos grandes mercados secundários, como o Opensea.
Por exemplo, a imagem abaixo é um NFT no mercado Opensea com alguns metadados que também podem ser vistos abaixo.
As informações acima, incluindo a obra de arte, seus detalhes e características, podem ser vistas na imagem IPFS abaixo.
Abra seu terminal e navegue até o diretório do projeto ou crie uma pasta de projeto em um local específico. Por exemplo, executar **mkdir preprocessor**
no terminal criará uma pasta chamada “ pré-processador” no local especificado.
Em seguida, execute os seguintes comandos no terminal.
cd preprocessor npm init -y npm install sharp @faker.js/faker --save-dev
Os comandos acima instalarão as bibliotecas sharp e faker em seu projeto. A biblioteca faker nos ajudará a gerar informações aleatórias. Visto que a biblioteca nítida nos ajudará a processar a imagem em uma determinada dimensão, qualidade e formato.
Em seguida, crie uma pasta em seu projeto chamada arts
e outra chamada outputs
. Na pasta “arts”, coloque todas as imagens para processamento dentro dela.
Com os passos acima realizados, abra o projeto em “código VS”. A estrutura do projeto deve se parecer com a abaixo.
- preprocessor/ - arts/ - node_modules/ - outputs/ - package.json - package-lock.json
Ótimo, vamos passar para a codificação do mecanismo responsável pelo processamento das imagens.
Você precisará do seguinte instalado em seu computador para concluir este tutorial.
Crie um arquivo na raiz do seu projeto chamado **imagify.js**
e cole o seguinte código
const fs = require('fs') const path = require('path') const sharp = require('sharp') const { faker } = require('@faker-js/faker') const input = './arts' const output = './outputs' let img_counter = 1 const imgSize = { width: 500, height: 500 } const desired_ext = '.webp' const base_url = 'https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/' const attributes = { weapon: [ 'Stick', 'Knife', 'Blade', 'Clube', 'Ax', 'Sword', 'Spear', 'Gun', 'Craft', ], environment: [ 'Space', 'Sky', 'Desert', 'Forest', 'Grassland', 'Moiuntains', 'Oceans', 'Rainforest', ], rarity: Array.from(Array(10).keys()), } fs.readdirSync(input).forEach((file) => { const orginal_ext = path.extname(file) const orginal_file_name = path.basename(file).split('.')[0] if (['.jpg', '.jpeg', '.png', '.gif', '.webp'].includes(orginal_ext)) { const id = img_counter const metadata = { id, name: `Adulam NFT #${id}`, description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: base_url + id + desired_ext, demand: faker.random.numeric({ min: 10, max: 100 }), attributes: [ { trait_type: 'Environment', value: attributes.environment.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Weapon', value: attributes.weapon.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Rarity', value: attributes.rarity.sort(() => 0.5 - Math.random())[0], max_value: 10, }, { display_type: 'date', trait_type: 'Created', value: Date.now(), }, { display_type: 'number', trait_type: 'generation', value: 1, }, ], } if (fs.existsSync(`${input}/${orginal_file_name + orginal_ext}`)) { sharp(`${input}/${orginal_file_name + orginal_ext}`) .resize(imgSize.height, imgSize.width) .toFile(`${output}/images/${id + desired_ext}`, (err, info) => console.log(err), ) fs.writeFileSync(`${output}/metadata/${id}.json`, JSON.stringify(metadata), { encoding: 'utf-8', flag: 'w', }) } console.log(metadata) img_counter++ } })
As etapas a seguir ajudarão você a entender como esse mecanismo de processamento de metadados funciona.
Importando Bibliotecas Essenciais
const fs = require('fs') const path = require('path') const sharp = require('sharp') const { faker } = require('@faker-js/faker') const input = './arts' const output = './outputs'
O fs
representa o sistema de arquivos, é um módulo embutido que acompanha o NodeJs. Ele tem a responsabilidade de gerenciar as atividades de leitura e gravação de arquivos em sua máquina.
O path
é outro módulo de nó que o ajuda a navegar pelas estruturas de diretório em sua máquina. Isso será fundamental para localizar onde nossas imagens são mantidas.
Sharp é o módulo que usamos para processar a imagem, como redimensionar e transformar em um tipo de arquivo diferente.
Usaremos o falsificador para gerar um número aleatório.
Por fim, a variável de input
contém o local onde estão localizadas as imagens a serem processadas e a output
aponta para o local onde as imagens processadas serão salvas.
Definindo Variáveis Essenciais
let img_counter = 1 const imgSize = { width: 500, height: 500 } const desired_ext = '.webp' const base_url = 'https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/' const attributes = { weapon: [ 'Stick', 'Knife', 'Blade', 'Clube', 'Ax', 'Sword', 'Spear', 'Gun', 'Craft', ], environment: [ 'Space', 'Sky', 'Desert', 'Forest', 'Grassland', 'Moiuntains', 'Oceans', 'Rainforest', ], rarity: Array.from(Array(10).keys()), }
Os códigos acima contêm variáveis importantes a serem usadas durante a geração de nossos metadados.
**Image_counter**
nos ajuda a numerar as imagens de forma consistente com a iteração atual.**ImgSize**
define a dimensão da largura e altura de cada imagem a ser processada.**Desired_ext**
fala do formato de arquivo que você deseja que suas imagens processadas suportem.**Base_url**
especifica o local onde as imagens devem ser armazenadas no IPFS.**Attributes**
contém mais informações sobre os metadados de cada imagem.
Executando Tarefa Recursiva
fs.readdirSync(input).forEach((file) => { if(['.jpg', '.jpeg', '.png', '.gif', '.webp'].includes(orginal_ext)) { // Images and metadata tasks are recursively performed here... } })
No bloco de código acima, usamos a biblioteca do sistema de arquivos (fs) para percorrer todas as imagens no local **input**
(arts). E para cada uma das imagens, garantimos que nosso mecanismo selecione apenas imagens de uma lista aprovada de extensões.
Executando a tarefa de metadados
const id = img_counter const metadata = { id, name: `Adulam NFT #${id}`, description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: base_url + id + desired_ext, demand: faker.random.numeric({ min: 10, max: 100 }), attributes: [ { trait_type: 'Environment', value: attributes.environment.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Weapon', value: attributes.weapon.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Rarity', value: attributes.rarity.sort(() => 0.5 - Math.random())[0], max_value: 10, }, { display_type: 'date', trait_type: 'Created', value: Date.now(), }, { display_type: 'number', trait_type: 'generation', value: 1, }, ], }
No bloco de código acima, fornecemos valores para cada espaço de metadados. Por exemplo, ambientes, armas e todos os valores de características são fornecidos aleatoriamente e dinamicamente.
Executando a tarefa de transformação de imagem
if (fs.existsSync(`${input}/${orginal_file_name + orginal_ext}`)) { sharp(`${input}/${orginal_file_name + orginal_ext}`) .resize(imgSize.height, imgSize.width) .toFile(`${output}/images/${id + desired_ext}`, (err, info) => console.log(err), ) fs.writeFileSync(`${output}/metadata/${id}.json`, JSON.stringify(metadata), { encoding: 'utf-8', flag: 'w', }) } console.log(metadata) img_counter++
No trecho acima, usamos o módulo do sistema de arquivos novamente para primeiro localizar cada uma de nossas artes e redimensioná-las para a dimensão especificada (500 x 500). Além disso, fornecemos um novo nome de acordo com a iteração atual e demos a extensão desejada (webp).
Redimensionar e transformar as imagens em webp
otimizou muito nossas obras de arte a uma altura surpreendente.
Por exemplo, onde submeti este motor de pré-processamento de imagem a 99
imagens totalizando um tamanho de 111MB
. O tamanho caiu para 62MB
para a extensão .png
e surpreendentes .webp
4.5MB
Essa enorme redução de tamanho representa um grande salto no tempo de carregamento de um site da Minting construído com minhas imagens.
Por fim, a partir do bloco de código acima, criamos metadados JSON
para cada imagem processada, contendo um nome idêntico e uma URL apontando para o local da imagem. Esses metadados são os que implantaremos no IPFS após o processamento das imagens.
Agora, execute o comando abaixo para ter sua imagem transformada. Certifique-se de estar na pasta do seu projeto.
node imagify.js
Neste ponto, terminamos nosso mecanismo de imagem, nossa pasta de saída deve ter a seguinte estrutura de arquivo como resultado.
- output/ - images - 1.webp - 2.webp - ...... - metadata - 1.json - 2.json - ......
IPFS significa o sistema de arquivos interplanetário, é ponto a ponto e descentralizado. Não há uma maneira fácil de extrair dados armazenados no IPFS e, como tal, é um par quase perfeito para usar junto com seus aplicativos blockchain para armazenar conteúdo de mídia.
Para usar a maneira mais fácil e menos confusa, vá para a página de instalação do aplicativo IPFS Desktop e siga as instruções especificadas lá.
Depois que a instalação for bem-sucedida, abra o aplicativo IPFS e carregue PRIMEIRO, e repito, PRIMEIRO carregue a pasta de imagens.
Uma string CID (identificação de conteúdo) exclusiva será gerada como parte do nome da pasta, veja a imagem abaixo.
Agora, copie o CID da pasta de imagens como pode ser visto na imagem acima e substitua-o em seu código **imagify.js**
. Veja o código abaixo.
const base_url = "https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/" //old string const base_url = "https://ipfs.io/ipfs/QmY1zrFibpdHQ7qcqZqq7THsqTremZYepXNWR5Au3MF1ST/" //new string
Agora, execute o **node imagify.js**
novamente para incluir a localização exata de cada imagem em seus metadados JSON . Veja um exemplo dos metadados JSON gerados antes e depois da substituição do CID.
Você pode assistir a este vídeo para entender como usei essas imagens e metadados em um projeto de cunhagem NFT completo.
Antes da substituição do CID
{ id: 97, name: 'Adulam NFT #97', description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: 'https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/97.webp', demand: '4', attributes: [ { trait_type: 'Environment', value: 'Forest' }, { trait_type: 'Weapon', value: 'Craft' }, { trait_type: 'Rarity', value: 4, max_value: 10 }, { display_type: 'date', trait_type: 'Created', value: 1664478034024 }, { display_type: 'number', trait_type: 'generation', value: 1 } ] }
Após a substituição do CID
{ id: 97, name: 'Adulam NFT #97', description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: 'https://ipfs.io/ipfs/QmY1zrFibpdHQ7qcqZqq7THsqTremZYepXNWR5Au3MF1ST/97.webp', demand: '7', attributes: [ { trait_type: 'Environment', value: 'Moiuntains' }, { trait_type: 'Weapon', value: 'Clube' }, { trait_type: 'Rarity', value: 2, max_value: 10 }, { display_type: 'date', trait_type: 'Created', value: 1664478110287 }, { display_type: 'number', trait_type: 'generation', value: 1 } ] }
Por fim, conforme mostrado na imagem abaixo, carregue a pasta de metadados no IPFS junto com a pasta de imagens.
Fantástico, agora vamos colocá-lo na web para o mundo ver. Atualmente, ambas as pastas estão localizadas em seu nó IPFS local (seu computador), para que seja acessível em todo o mundo, você precisa usar um serviço de fixação como o Pinata .
Primeiro, vá para o Pinata Pin Manager e inscreva-se, caso ainda não tenha feito isso. Em seguida, clique no ícone da conta e selecione Chaves de API. Veja a imagem abaixo.
Na página de criação de chaves, clique em criar uma nova chave e insira o nome da chave. Observe a imagem abaixo.
Agora copie a chave JWT na área de transferência. Isso é o que usaremos para vincular nosso IPFS Desktop à nossa conta Pinata. Veja a imagem abaixo.
Em seguida, abra seu aplicativo de desktop IPFS, vá para a guia de configurações e adicione um novo serviço, selecione Pinata e cole seu token JWT no espaço fornecido. Consulte a imagem abaixo.
A última coisa a fazer é fixar suas pastas no Pinata usando as instruções abaixo.
Vá para a guia de arquivos, clique na linha pontilhada tripla e selecione definir fixação. Isso aparecerá na imagem abaixo.
Selecione Pinata e aplique, ao fazer isso, sua pasta de imagens estará acessível globalmente.
Vá para este site, copie e cole seu CID no campo de entrada IPFS e clique no botão de cache. Isso verifica todo o conjunto de gateways IPFS disponíveis publicamente em busca de suas imagens. Veja a imagem abaixo.
Os resultados da imagem acima mostram que muitos nós IPFS agora têm cópias da pasta de imagens disponíveis e acessíveis globalmente, mesmo que você exclua a cópia original em seu nó local.
Com as etapas claramente descritas para você, fixe também a pasta de metadados para torná-los publicamente disponíveis online.
Agora você pode usar qualquer um dos links na imagem acima como URL base para tokens ERC721 . Veja a imagem abaixo.
E aí está, é como preparar e fazer upload de suas obras de arte no IPFS.
Você sempre encontrará a necessidade de entender como pré-processar e fazer upload de obras de arte no IPFS em escala de lote.
Depois de entender como trabalhar e processar imagens para o IPFS, você pode começar a usá-lo em seus projetos web3 especiais.
Até a próxima vez, continue esmagando!
Veja o uso de demonstração ao vivo no meu projeto NFT no testnet Goerli aqui . Veja aqui a localização da Opensea. Você pode assistir a versão em vídeo no meu canal do YouTube.
Sou um desenvolvedor full-stack blockchain com mais de 6+
anos de experiência na indústria de desenvolvimento de software.
Ao combinar desenvolvimento de software, redação e ensino, demonstro como criar aplicativos descentralizados em redes blockchain compatíveis com EVM.
Minhas pilhas incluem JavaScript
, React
, Vue
, Angular
, Node
, React Native
, NextJs
, Solidity
e muito mais.
Inscreva-se no meu canal do YouTube para aprender como criar um aplicativo Web3 do zero. Também ofereço aulas particulares e especializadas para pessoas sérias que desejam aprender individualmente com um mentor.
Marque aqui as suas aulas de Web3 .
Agora, deixe-me mostrar como representar a imagem e os metadados acima em seu código.