You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

2 Días
12 Hrs
8 Min
58 Seg

¿Qué es la metadata del ERC721?

16/24
Resources

What is the importance of metadata in NFTs?

In the exciting world of NFTs, understanding metadata is a key part of working efficiently with digital collections. Metadata defines essential attributes of an NFT such as its image, name, and rarity characteristics. Accepted standards, such as ERC-721, already incorporate systems for handling metadata, facilitating its inclusion in smart contracts. Understanding these fundamentals not only empowers your development, but ensures that you adhere to secure and recognized practices within the blockchain community.

How is metadata implemented in a smart contract?

Implementing metadata within a smart contract requires some level of familiarity with the OpenZeppelin functions already available. These functions are:

  1. Token Name: Defines the name of the entire NFT collection.
  2. Token symbol: Used for exchanges in marketplaces.
  3. Token URI: This is the function that connects an NFT with its metadata, pointing to a JSON file containing its full description.

Step by step to implement Token URI

To add the tokenURI function to your contract, follow these key steps:

function tokenURI(uint256 tokenId) public view override returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); // Build the JSON string in memory string memory jsonURI = string(abi.encodePacked( '{" name": "PlatziPunks #', uint2str(tokenId), '", "description": "A brief description of the PlatziPunk.", "image": "ImageURL"}' )); string memory base64Json = Base64.encode(bytes(jsonURI)); return string(abi.encodePacked("data:application/json;base64,", base64Json));}

Using base64 encoding for metadata

Base64 encoding is a common practice to keep all relevant NFT information on the blockchain without relying on third parties. This is critical as it avoids centralization risks where external servers could censor or manipulate content.

  1. Data URLs: Allow content to be included directly in the URI without making calls to the external server.
  2. Base64: Encodes the complete JSON, allowing it to be read even from recognized marketplaces.

What external libraries can be used?

For base64 encoding in Solidity, you can use libraries that are widely accepted and tested by the community. Be sure to include such libraries in your code:

import "./Base64.sol";

This library facilitates the transformation of data into base64 format, essential for constructing URLs that store content securely and efficiently.

Challenges and recommendations

It is important that you configure theURI token so that you can add additional attributes, depending on the specifications of the marketplace where your NFTs will be listed, such as OpenSea. Consult their documentation to take full advantage of the customization capabilities allowed and improve the visibility of your NFTs.

In summary, implementing metadata correctly and efficiently significantly increases the functionality and security of your NFTs, enabling a more secure and flexible integration into the blockchain ecosystem. Proper metadata management positions you better to develop robust projects aligned with industry standards.

Contributions 14

Questions 7

Sort by:

Want to see more contributions, questions and answers from the community?

Acá les dejo el string de la descripción para que no copien tanto 😉

"Platzi Punks are randomized Avataaars stored on chain to teach DApp development on Platzi", "image": "

OpenZeppelin ya tiene su propia implementación de Base64.sol.
Realizar el import simplemente con:

import "@openzeppelin/contracts/utils/Base64.sol";

Resolviendo reto:
Le agregue solo:

'"external_url": "ipfs://<hash>"',

A la metadata, un sitio donde estara alojado en IPFS todo el marketplace.
Aqui tambien se pudieran agregar los atributos para cada personaje, asi como la implementacion de Oracles para obtener numeros aleatorios y asi cada personaje garantizar que son unicos.

No sé hasta que punto pero siento que hacer test me ayuda a comprender mejor las cosas por eso les comparto los que voy logrando cualquier crítica es bienvenida.

const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("PlatziPunks", function () {
  let platzi_punks;
  beforeEach(async function(){
    const PlatziPunks = await ethers.getContractFactory("PlatziPunks");
    platzi_punks = await PlatziPunks.deploy(2);
    await platzi_punks.deployed();
  })

  describe("tokenURI", async function () {
    it("Should throw an error if tokenId don't exists", async function () {
      try {
        await platzi_punks.tokenURI(0)
        expect.fail('fail with an error');
      } catch (error) {
        expect(error.message).to.contains('ERC721Metadata: URI query for nonexistent token');
      }
    });
    
    it("Should return the correct tokenURI protocol mime type", async function () {
        await platzi_punks.mint()
        expect(await platzi_punks.tokenURI(0)).to.includes("data:application/json;base64,");
    });

    it("Should name token with correct number based on tokenId", async function () {
      await platzi_punks.mint()
      await platzi_punks.mint()
      
      expect(await platzi_punks.tokenURI(0)).to.includes(Buffer.from('{ "name": "PlatziPunks #0"').toString('base64').slice(0, -1));
      expect(await platzi_punks.tokenURI(1)).to.includes(Buffer.from('{ "name": "PlatziPunks #1"').toString('base64').slice(0, -1));
    });
  })
  
});

Excelente profesor pero explica muy rápido.

Documentacion del objeto abi en solidity que no vi en los recursos.

Importando con Contrato de OpenZeppelin Base64

Importamos la librería al principio del contrato

import "@openzeppelin/contracts/utils/Base64.sol";

Posteriormente solo se le hacen unos ajustes a la parte de jsonURI

bytes memory jsonURI = abi.encodePacked(
            '"name" : "Platzi Punks"', 
            tokenId,
            '", "description" : "Randomized Avatars", "image" : ", '
            "// TODO : calculate images URL",
            '"}'
        ); 

        return string (
            abi.encodePacked(
                "data:application/json;base64,",
                Base64.encode(jsonURI)
            )   
        );

Saludos

“el reto es construir una url que sea compliant para regresarnos un archivo de JSON”

… ¿eh?

Libreria de Base64 en OpenZeppeling. aunque no se puede importar es bueno tener el recurso a la mano.

Aqui esta la implementacion con open zeppelin

import "@openzeppelin/contracts/utils/Base64.sol";
function tokenURI(uint256 tokenId)
        public
        pure
        override
        returns (string memory)
    {
        bytes memory dataURI = abi.encodePacked(
            '{',
                '"name": "PlatziPunks #', tokenId.toString(), '"',
               	//Aqui colocan los datos de la metadata
            '}'
        );

        return string(
            abi.encodePacked(
                "data:application/json;base64,",
                Base64.encode(dataURI)
            )
        );

Ayuda con el reto del JSON …
No me quedo nada claro como avanzar con eso.

A Solidity le vendría bien los Backtick (``) de Javascript para concatenar.
Concatenar de esa forma es muy confuso realmente.

Algo que definitivamente no me ha gustado de Platzi es su variados cursos viejos y que los profesores solo grabaron y adios, no se puede obtener retroalimentacion de un experto. He realizado varias preguntas en distintos cursos y nunca he obtenido respuesta.

que significa hacer un override?