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": "
Presentación del proyecto
Bienvenida al curso
PlatziPunks: marketplace de NFT
Arquitectura de DApps
¿Qué es una aplicación descentralizada?
Componentes descentralizables de una aplicación
Ejemplos de aplicaciones descentralizadas
¿Cómo interactuar con aplicaciones descentralizadas?
Setup del proyecto
JavaScript, Node y Webpack
Instalación y overview de Hardhat
Compilación, tests y despliegue
Actualización sobre testnet en Ethereum
Despliegue en Rinkeby
Manejo de llaves privadas
Alternativas a Hardhat y EIP
Desarrollo del contrato inteligente
Implementación del ERC721 de Open Zeppellin
Extendiendo la funcionalidad de PlatziPunks
¿Qué es la metadata del ERC721?
Diseñando el ADN de PlatziPunks
Implementando el ADN de PlatziPunks
Calculando el ADN de PlatziPunks
Usando el ADN para calcular la imagen del NFT
Probando nuestro Smart Contract
Probando nuestro Smart Contract
Despliegue en redes de prueba
¡Crea tu PlatziPunk y visualízalo en OpenSea!
Conclusión
Continúa con el proyecto PlatziPunks
You don't have access to this class
Keep learning! Join and start boosting your career
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.
Implementing metadata within a smart contract requires some level of familiarity with the OpenZeppelin functions already available. These functions are:
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));}
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.
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.
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
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.
que significa hacer un override?
Want to see more contributions, questions and answers from the community?