Bienvenido a la semana 4 de la serie del camino hacia Web3. En este tutorial, aprenderás a desarrollar una galería de NFTs que muestre los NFTs por la dirección de billetera y dirección de contrato inteligente.
Tener datos públicos almacenados en el blockchain no hace que sean fácilmente accesibles. De hecho consultar la blockchain es una de las mayores dificultades para los desarrolladores, ya que tienen que empezar desde el origen de la cadena para reunir los datos que necesitan para conectar los puntos y responder a sus preguntas.
Digamos que un desarrollador quiere responder a la siguiente pregunta "¿Qué NFTs posee una billetera?".
Parece una pregunta sencilla, pero la respuesta no es nada fácil.
En este caso, el desarrollador tendría que encontrar todos los NFT minteados en una cadena determinada, luego, seguir todas las transferencias para entender quién es el propietario actual de los NFT.
Esta tarea podría llevar semanas. Por suerte, existe una solución: con una cuenta gratuita de Alchemy y la API de NFT de Alchemy, permite a los desarrolladores obtener información de los NFT en la cadena de bloques en milisegundos, no en semanas.
Dado que Alchemy ya ha consultado toda la cadena de bloques y ha indexado sus datos, la API de NFT te permite tener acceso completo a la información.
En este tutorial vas a aprender a utilizar la API de NFT de Alchemy para crear una galería de NFT capaz de obtener NFTs basándose en tres cosas:
- Dirección de la billetera
- Dirección de la colección
- Dirección de la billetera + Dirección de la colección
Utilizaremos las llamadas a la API de NFT de Alchemy para obtener NFTs, sus metadatos, mostrar imágenes, descripciones e IDs, en nuestra galería de NFT, utilizando lo siguiente:
- Next JS
- Tailwind CSS
- API de NFT de Alchemy
- Cuenta de Alchemy
¡Próximamente video en español!
Lo primero que tendrás que hacer es crear el paquete Next JS de desarrollo del proyecto e instalar TailwindCSS que se encargará de tus estilos.
Abre tu terminal y escribe el siguiente código:
npx create-next-app -e with-tailwindcss nameoftheproject
Dirigete a tu proyecto e inicia VSCode:
cd nameoftheproject
Ahora que se han creado los paquetes de desarrollo del proyecto, prueba que todo funciona.
Ejecuta el siguiente código en el directorio del proyecto:
npm run dev
Al navegar a localhost:3000 debería generar la siguiente página:
Pagina cargada luego de navegar a localhost:3000
Como no lo necesitaremos, puedes eliminar todo el código dentro de las etiquetas
Tú código dentro del archivo index.tsx debería tener ahora el siguiente aspecto
import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'
const Home: NextPage = () => {
return (
)
}
export default Home
Dado que este tutorial utilizará Javascript y no Typescript, antes de escribir su código, convierte los archivos index.tsx y _app.tsx de archivos .tsx
a archivos .jsx.
- Cambia las extensiones de ambos archivos a
.jsx
- Elimina las importaciones en la parte superior de ambos archivos
El primer paso para crear una galería de NFT con capacidad de búsqueda es crear las entradas de texto donde se añadirá la dirección del monedero y la dirección de la colección que se utiliza para buscar los NFT.
En la página index.jsx
, añade el siguiente código:
const Home = () => {
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
</div>
</div>
)
}
export default Home
Como puedes observar ya estamos implementando las clases CSS de Tailwind dentro de la propiedad className de nuestras entradas. No vamos a entrar en los detalles de cómo funciona TailwindCSS, si quieres saber más sobre él, puedes consultar la documentación oficial.
A continuación, tendremos que crear dos variables para almacenar tanto la dirección del monedero como la de la colección que insertaremos en los campos de entrada, utilizando el hook de react useState().
Importa el hook "useState" de "react" y añade el siguiente código, justo encima de la declaración de retorno del componente "Home":
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
</div>
</div>
)
}
export default Home
Para almacenar el valor de las entradas de texto dentro de las variables "wallet" y "collection", utilice el controlador de eventos "onChange".
El controlador de eventos "onChange" se activará cada vez que cambie el valor del campo de entrada, tomando las entradas y almacenándolas en las respectivas variables usando las funciones setWallet y setCollectionAddress
También querrás reflejar los cambios en tus variables "wallet" y "collection" asignando su valor mostrado en el input.
En las etiquetas de entrada de texto, añade el siguiente código:
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input onChange={(e)=>{setWalletAddress(e.target.value)}} value={wallet} type={"text"} placeholder="Add your wallet address"></input>
<input onChange={(e)=>{setCollectionAddress(e.target.value)}} value={collection} type={"text"} placeholder="Add the collection address"></input>
</div>
</div>
)
}
export default Home
Tus entradas ahora se almacenarán en sus respectivas variables (las direcciones que escribiremos dentro).
Vamos a realizar el proceso de instalación en Chrome, pero todo esto se aplica también a Mozilla Firefox.
- Ve a la tienda de extensiones del navegador
- Busca React developer tools
- Haz clic en "Añadir a Chrome".
Una vez descargada e instalada, podrás ver la pestaña de herramientas de desarrollo de React en la vista "inspeccionar" dentro de las herramientas de desarrollo de Chrome.
Vuelve a la terminal, dentro de la carpeta de tu aplicación, e inicia de nuevo tu aplicación escribiendo
npx run dev
- ve a la página de tu aplicación (localhost:3000)
- haz clic con el botón derecho en cualquier parte de la página
- haz clic en inspeccionar
- haga clic en el símbolo ">>".
- dirígete a "Components".
En la vista de "Componentes" podremos ver una lista de todos los componentes incluidos en nuestra página y, a la derecha, los diferentes estados guardados en los hooks y otra información sobre la aplicación:
Con las herramientas para desarrolladores de React instaladas, podemos probar los hooks useState()
escribiendo en sus entradas y comprobando si el valor de sus estados se actualiza:
Ahora que ya puedes almacenar la dirección de la billetera y de la colección, vamos a terminar la página de inicio.
A continuación, tendrás que añadir un botón que activará las funciones para obtener las información de la API de NFT de Alchemy, y un conmutador para decidir si quieres buscar por la dirección del monedero, la colección o ambas.
- debajo de la entrada de texto de la colección añade una nueva entrada de tipo "checkbox"
- envuélvelo en una etiqueta para añadir algo de texto
- crea el botón
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
<label className="text-gray-600 "><input type={"checkbox"} className="mr-2"></input>Fetch for collection</label>
<button className={"disabled:bg-slate-500 text-white bg-blue-400 px-4 py-2 mt-3 rounded-sm w-1/5"}>Let's go! </button>
</div>
</div>
)
}
export default Home
Ahora que tienes un botón, añade un controlador onClick()
que activará la función fetchNFTs()
para obtener los NFTs en función de la billetera que los posea:
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
<label className="text-gray-600 "><input type={"checkbox"} className="mr-2"></input>Fetch for collection</label>
<button className={"disabled:bg-slate-500 text-white bg-blue-400 px-4 py-2 mt-3 rounded-sm w-1/5"} onClick={
() => {
}
}>Let's go! </button>
</div>
</div>
)
}
export default Home
Ahora, crea la función fetchNFTs()
para añadirla dentro del controlador onClick
y obten tus NFTs.
Sin embargo, necesitas crear una nueva aplicación para obtener una clave de API de Alchemy.
Navega hasta Alchemy y haz clic en "Create App" para crear una nueva aplicación:
Crear una nueva aplicación en el panel de control de Alchemy.
Estos son los detalles que hay que añadir:
- Nombre de la aplicación
- Descripción
- Cadena (Ethereum)
- Red (Mainnet)
Seleccionar la red principal de Ethereum permitirá obtener NFTs sólo de Ethereum.
Si quieres obtener NFTs en Polygon u otras cadenas, tendrás que crear una nueva aplicación con la cadena respectiva y cambiar la URL base para reflejar la cadena que quieres usar, por ejemplo, la URL de Polygon sería:
https://polygon-mumbai.g.alchemy.com/v2/YOUR-API-KEY
Ahora que nuestra aplicación Alchemy está en marcha, vamos a crear la función fetchNFTs
para obtener todos los NFTs que posee una dirección.
Para obtener los NFTs que posee una dirección de monedero, utilice el EndPoint getNFTs de la API de NFT de Alchemy.
En el componente de inicio, declara una nueva variable useState()
, como hicimos antes con las direcciones de billetera y colección, para almacenar los NFT que obtendremos utilizando la API de NFT de Alchemy:
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
const [NFTs, setNFTs] = useState([])
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
<label className="text-gray-600 "><input type={"checkbox"} className="mr-2"></input>Fetch for collection</label>
<button className={"disabled:bg-slate-500 text-white bg-blue-400 px-4 py-2 mt-3 rounded-sm w-1/5"} onClick={
() => {
}
}>Let's go! </button>
</div>
</div>
)
}
export default Home
Ahora, añade la función fetchNFTs().
siempre dentro del componente de la página de inicio
const fetchNFTs = async() => {
let nfts;
console.log("fetching nfts");
const api_key = "A8A1Oo_UTB9IN5oNHfAc2tAxdR4UVwfM"
const baseURL = `https://eth-mainnet.g.alchemy.com/v2/${api_key}/getNFTs/`;
var requestOptions = {
method: 'GET'
};
if (!collection.length) {
const fetchURL = `${baseURL}?owner=${wallet}`;
nfts = await fetch(fetchURL, requestOptions).then(data => data.json())
} else {
console.log("fetching nfts for collection owned by address")
const fetchURL = `${baseURL}?owner=${wallet}&contractAddresses%5B%5D=${collection}`;
nfts= await fetch(fetchURL, requestOptions).then(data => data.json())
}
if (nfts) {
console.log("nfts:", nfts)
setNFTs(nfts.ownedNfts)
}
}
Lo primero que hay que notar en la función fetchNFTs()
, es la palabra clave async, que permitirá obtener datos sin bloquear toda la aplicación.
📘Lee más sobre el flujo de trabajo async await de JavaScript.
A continuación, declaramos una nueva variable para almacenar los NFTs que se obtienen, para luego crear la URL base que alimentará el fetch() para recuperar los nfts.
La URL base, según la documentación de la API de NFT de Alchemy, está compuesta por:
- URL base de la aplicación
- Tu clave de API
- Dirección del propietario
- Dirección de la colección - opcional
Si se proporciona la dirección de la colección, la API de NFT filtrará los NFT recuperados por colección, si no se proporciona, la API recuperará todos los NFT propiedad de la dirección de la billetera proporcionada.
Por ello, se necesitará una manera de saber si la dirección de la colección ha sido proporcionada o no, por lo tanto: quieres filtrar por colección.
Para ello, puede añadir una declaración "if" que compruebe si la variable "collection" está vacía o no:
Si está vacía, entonces sólo proporcionas los parámetros de la dirección de la cartera:
const fetchURL = `${baseURL}?owner=${wallet}`;
Si no lo está, entonces se obtienen todos los NFTs propiedad de una billetera y se filtran por colección:
const fetchURL = `${baseURL}?owner=${wallet}&contractAddresses%5B%5D=${collection}`;
La cadena "5B%5D" justo después de los parámetros "contractAddresses" especifica que el parámetro "contractAddresses" es un array y no una simple cadena. Esto se debe a que en realidad se puede filtrar por múltiples "contractAddresses", no sólo por uno.
En ambos casos, filtrando por colección o no, quieres introducir tu "baseURL" en una función fetch()
, esperar a que llegue el resultado y convertirlo en JSON usando la función .json().
Al imprimir los datos recuperados por nuestras funciones fetch()
, se registraría el siguiente objeto:
Dentro del objeto recuperado tienes más información de la que necesitas, ya que sólo necesitarás el array que contiene los NFTs que pertenecen a la dirección de la billetera que hemos proporcionado.
Esa es la razón por la que en la función setNFTs()
estás alimentando nfts.ownednfts y no sólo nfts, ya que sólo necesitarás el array ownednfts
para almacenarlo y usarlo después para mostrar tus NFTs.
Ahora que tu función fetchNFTs()
está lista, necesitarás implementar una nueva función para obtener los NFTs por colección sin un propietario de NFT.
Para obtener los NFT por colección, puede utilizar el EndPoint getNFTsForCollection de Alchemy.
El EndPoint getNFTsForCollection
requerirá dos parámetros:
contractAddress
- dirección del contrato de la colección de NFT [cadena]withMetadata
- (opcional) **** si se establece entrue
, devuelve los metadatos de NFT; en caso contrario, sólo devolverá los tokenIds. Por defecto afalse
[boolean]
El primer argumento es para especificar la dirección del contrato de la colección que se quiere recuperar.
El segundo argumento especifica a la API de NFT si también desea obtener los metadatos (por ejemplo, título, imagen, descripción, atributos) de las NFT contenidas en la colección o sólo sus ID.
Puedes leer más en la API de NFT de Alchemy.
Como hemos hecho antes, copiemos primero el código y entendamos lo que hace:
const fetchNFTsForCollection = async () => {
if (collection.length) {
var requestOptions = {
method: 'GET'
};
const api_key = "A8A1Oo_UTB9IN5oNHfAc2tAxdR4UVwfM"
const baseURL = `https://eth-mainnet.g.alchemy.com/v2/${api_key}/getNFTsForCollection/`;
const fetchURL = `${baseURL}?contractAddress=${collection}&withMetadata=${"true"}`;
const nfts = await fetch(fetchURL, requestOptions).then(data => data.json())
if (nfts) {
console.log("NFTs in collection:", nfts)
setNFTs(nfts.nfts)
}
}
}
Es muy similar a la función fetchNFTs()
que construimos antes, con dos diferencias importantes:
- El punto final utilizado
- El valor almacenado en la variable de estado NFTs
Esto es lo que ocurre:
- Primero estás verificando que la dirección de la colección no está vacía
- Luego has declarado
requestOptions
para decirle a fetch() que tu petición HTTP será una solicitud "GET" - Por último, construyes la
baseURL
pasando el valor de la dirección de la colección como parámetrocontractAddress
y el parámetrowithMetadata
a true.
Por último, conviertes los datos obtenidos a JSON, utilizando el flujo de trabajo async await + la función json().
Si registramos en la consola el objeto JSON que contiene los NFTs obtenidos, veremos que contiene 2 propiedades:
Ejemplo de registro en la consola
- Siguiente Token
- nfts
En este caso sólo necesitarás la propiedad "nfts" que contiene tu array (matriz) de NFTs pasando "nfts.nfts" en la función setNFTs().
Tu código en este punto debería ser el siguiente:
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
const [NFTs, setNFTs] = useState([])
const fetchNFTs = async() => {
let nfts;
console.log("fetching nfts");
const api_key = "A8A1Oo_UTB9IN5oNHfAc2tAxdR4UVwfM"
const baseURL = `https://eth-mainnet.g.alchemy.com/v2/${api_key}/getNFTs/`;
var requestOptions = {
method: 'GET'
};
if (!collection.length) {
const fetchURL = `${baseURL}?owner=${wallet}`;
nfts = await fetch(fetchURL, requestOptions).then(data => data.json())
} else {
console.log("fetching nfts for collection owned by address")
const fetchURL = `${baseURL}?owner=${wallet}&contractAddresses%5B%5D=${collection}`;
nfts= await fetch(fetchURL, requestOptions).then(data => data.json())
}
if (nfts) {
console.log("nfts:", nfts)
setNFTs(nfts.ownedNfts)
}
}
const fetchNFTsForCollection = async () => {
if (collection.length) {
var requestOptions = {
method: 'GET'
};
const api_key = "A8A1Oo_UTB9IN5oNHfAc2tAxdR4UVwfM"
const baseURL = `https://eth-mainnet.g.alchemy.com/v2/${api_key}/getNFTsForCollection/`;
const fetchURL = `${baseURL}?contractAddress=${collection}&withMetadata=${"true"}`;
const nfts = await fetch(fetchURL, requestOptions).then(data => data.json())
if (nfts) {
console.log("NFTs in collection:", nfts)
setNFTs(nfts.nfts)
}
}
}
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
<label className="text-gray-600 "><input type={"checkbox"} className="mr-2"></input>Fetch for collection</label>
<button className={"disabled:bg-slate-500 text-white bg-blue-400 px-4 py-2 mt-3 rounded-sm w-1/5"} onClick={
() => {
}
}>Let's go! </button>
</div>
</div>
)
}
export default Home
Ahora que tus funciones para obtener los NFTs están funcionando, tendrás que adjuntarlas al trigger "onClick" del botón que creaste hace unas secciones.
Lo primero que tendrás que hacer es añadir una nueva variable de estado llamada "fetchForCollection" que comprobará si quieres buscar por colección o por dirección de cartera:
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
const [NFTs, setNFTs] = useState([])
const [fetchForCollection, setFetchForCollection]=useState(false)
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
<label className="text-gray-600 "><input type={"checkbox"} className="mr-2"></input>Fetch for collection</label>
<button className={"disabled:bg-slate-500 text-white bg-blue-400 px-4 py-2 mt-3 rounded-sm w-1/5"} onClick={
() => {
}
}>Let's go! </button>
</div>
</div>
)
}
export default Home
Esta variable será manejada por el checkbox input que hemos creado, actualizando su valor en función de si el checkbox está marcado o desmarcado:
- Marcada: estamos buscando por colección - la variable de estado será verdadera
- Desmarcada: estamos buscando por la dirección de la billetera - la variable de estado será falsa
Para ello, tendrás que añadir otro controlador "onChange" a la entrada, pero esta vez utilizando el valor "e.target.checked", como valor de la entrada de estado, en lugar de e.target.value:
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
const [NFTs, setNFTs] = useState([])
const [fetchForCollection, setFetchForCollection]=useState(false)
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
<label className="text-gray-600 "><input onChange={(e)=>{setFetchForCollection(e.target.checked)}} type={"checkbox"} className="mr-2"></input>Fetch for collection</label>
<button className={"disabled:bg-slate-500 text-white bg-blue-400 px-4 py-2 mt-3 rounded-sm w-1/5"} onClick={
() => {
}
}>Let's go! </button>
</div>
</div>
)
}
export default Home
Podemos volver atrás y comprobar si la variable se actualiza correctamente utilizando las herramientas de desarrollo de React.
Ahora que sabes si estás buscando NFTs por cartera o por colección, asegúrate de que tu botón es capaz de disparar la función correcta basada en nuestra variable "fetchForCollection":
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
const [NFTs, setNFTs] = useState([])
const [fetchForCollection, setFetchForCollection]=useState(false)
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
<label className="text-gray-600 "><input onChange={(e)=>{setFetchForCollection(e.target.checked)}} type={"checkbox"} className="mr-2"></input>Fetch for collection</label>
<button className={"disabled:bg-slate-500 text-white bg-blue-400 px-4 py-2 mt-3 rounded-sm w-1/5"} onClick={
() => {
if (fetchForCollection) {
fetchNFTsForCollection()
}else fetchNFTs()
}
}>Let's go! </button>
</div>
</div>
)
}
export default Home
Aquí estamos esencialmente diciéndole a nuestro botón que:
- si "fetchForCollection" es verdadero
- entonces ejecuta la función fetchNFTsForCollection(), si no, simplemente fetchNFTs.
Para asegurarse de no añadir la dirección de la billetera en la entrada de la dirección del billetera cuando busques NFTs basados en la colección, puedes añadir la propiedad "disabled" a la entrada del monedero, y desactivarla siempre que fetchForCollection sea verdadero:
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
const [NFTs, setNFTs] = useState([])
const [fetchForCollection, setFetchForCollection]=useState(false)
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input disabled={fetchForCollection} type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
<label className="text-gray-600 "><input onChange={(e)=>{setFetchForCollection(e.target.checked)}} type={"checkbox"} className="mr-2"></input>Fetch for collection</label>
<button className={"disabled:bg-slate-500 text-white bg-blue-400 px-4 py-2 mt-3 rounded-sm w-1/5"} onClick={
() => {
if (fetchForCollection) {
fetchNFTsForCollection()
}else fetchNFTs()
}
}>Let's go! </button>
</div>
</div>
)
}
export default Home
Genial, el siguiente paso es visualizar los NFTs. Para ello necesitas crear el componente NFTCard.
En la carpeta raíz del proyecto, crea una nueva carpeta y llámala "components".
Dentro de esta carpeta crea un nuevo archivo y llámalo "nftCard.jsx".
Tu tarjeta NFT tomará un NFT como prop (aprende más sobre props en la documentación de ReactJS), obtendrás sus metadatos para mostrarlo en una tarjeta, que tendrá el siguiente aspecto:
Para ello, en el archivo que acabas de crear, añade el siguiente código:
export const NFTCard = ({ nft }) => {
return (
<div className="w-1/4 flex flex-col ">
<div className="rounded-md">
<img className="object-cover h-128 w-full rounded-t-md" src={nft.media[0].gateway} ></img>
</div>
<div className="flex flex-col y-gap-2 px-2 py-3 bg-slate-100 rounded-b-md h-110 ">
<div className="">
<h2 className="text-xl text-gray-800">{nft.title}</h2>
<p className="text-gray-600">Id: {nft.id.tokenId}</p>
<p className="text-gray-600" >{nft.contract.address}</p>
</div>
<div className="flex-grow mt-2">
<p className="text-gray-600">{nft.description}</p>
</div>
</div>
</div>
)
}
Como puedes observar, estamos mostrando 5 propiedades:
- Imagen
- Título
- TokenId
- Dirección del contrato
- Descripción
Para acceder a estas propiedades podemos mirar de nuevo el objeto NFT:
Así es como se obtiene la imagen NFT
- accede al primer índice del objeto multimedia
- accede a la propiedad gateway dentro de él para obtener la URL de la imagen
- asigna la URL de la imagen a la etiqueta img en el código anterior "media[0].gateway"
Para acceder al título de la NFT sólo tienes que acceder a la propiedad title dentro del propio objeto NFT.
Con la tarjeta NFT, dirigete al archivo home.jsx
e impórtalo para crear la Galería NFT.
En el archivo pages>index.js
, justo debajo de tu botón, importa el siguiente código:
import { NFTCard } from "../components/nftCard"
import { useState } from 'react'
const Home = () => {
const [wallet, setWalletAddress] = useState("");
const [collection, setCollectionAddress] = useState("");
const [NFTs, setNFTs] = useState([])
const [fetchForCollection, setFetchForCollection]=useState(false)
return (
<div className="flex flex-col items-center justify-center py-8 gap-y-3">
<div className="flex flex-col w-full justify-center items-center gap-y-2">
<input disabled={fetchForCollection} type={"text"} placeholder="Add your wallet address"></input>
<input type={"text"} placeholder="Add the collection address"></input>
<label className="text-gray-600 "><input onChange={(e)=>{setFetchForCollection(e.target.checked)}} type={"checkbox"} className="mr-2"></input>Fetch for collection</label>
<button className={"disabled:bg-slate-500 text-white bg-blue-400 px-4 py-2 mt-3 rounded-sm w-1/5"} onClick={
() => {
if (fetchForCollection) {
fetchNFTsForCollection()
}else fetchNFTs()
}
}>Let's go! </button>
</div>
<div className='flex flex-wrap gap-y-12 mt-4 w-5/6 gap-x-2 justify-center'>
{
NFTs.length && NFTs.map(nft => {
return (
<NFTCard nft={nft}></NFTCard>
)
})
}
</div>
</div>
)
}
export default Home
Esto es lo que ocurre en este código:
- La NFTCard fue importada en la parte superior del archivo.
- Dentro del componente de la página de inicio, se creó un nuevo div, abrimos las llaves, y comprobamos si hay NFTs en nuestra variable de estado usando la renderización condicional.
- Usamos la función map para iterar sobre el array de NFTs y devolver una NFTCard por cada NFT, pasando la propia NFT como prop de la NFTCard.
Cada vez que busquemos NFTs, y almacenemos un array en la variable de estado NFTs devolverá ahora una tarjeta NFT para cada NFT, mostrando su información.
Y ya está. Ya tienes una galería de NFTs que funciona :)
Ahora, vamos a añadir algunos retos divertidos para que los pruebes por ti mismo antes de enviar tu proyecto:
-
Añade un icono junto a las direcciones de NFT para que la gente que vea tu página pueda copiar fácilmente la dirección del contrato.
-
Añade un sistema de paginación para ver más de 100 NFTs, utilizando el parámetro pageKey del endpoint getNFTs.
Comparte tu proyecto en el discord de la Universidad de Alchemy para ganar una Prueba de Conocimiento (PoK) NFT
Para crear galerías de NFT como esta u otras aplicaciones web3 interesantes, regístrate hoy mismo para obtener una cuenta de desarrollador de Alchemy gratuita.