NUEVO: Helius adquiere Light Protocol
Cómo crear un visor de portafolio de Solana con Next.js y la API DAS de Helius
Blog/Desarrollo

Cómo crear un visor de portafolio de Solana con Next.js y la API DAS de Helius

Ingeniero de experiencia del desarrolladorOwen Venter en XOwen Venter en LinkedIn
6 min de lectura

Objetivos

En este tutorial, crearemos una aplicación frontend para mostrar el contenido de una billetera de Solana mediante la API DAS de Helius. Mostraremos varios tipos de tokens y su información detallada, incluidos los metadatos, la información de la colección y los precios de los tokens fungibles.

Este tutorial te guiará por los pasos necesarios para crear algo similar a Galleria.

Requisitos previos

  • Clave de API de Helius.
  • Familiaridad con React.
  • Experiencia con Next.js.

Resumen de las tecnologías utilizadas

  • Next.js: Un framework de React para crear aplicaciones renderizadas del lado del servidor.
  • API DAS de Helius: Una API integral para acceder a datos de tokens de Solana.
  • Vercel: Una plataforma para alojar aplicaciones de Next.js.
  • Tailwind CSS: Un framework CSS basado en utilidades para aplicar estilos.

Configuración del proyecto

La API DAS

La API DAS es una especificación y un sistema de código abierto que ofrece Helius. La API proporciona una interfaz sencilla para interactuar con activos digitales en la blockchain de Solana. Admite varios tipos de tokens, incluidos tokens fungibles, NFT normales y NFT comprimidos, y ofrece funciones como la indexación de metadatos fuera de la cadena.

Configuración de la clave de API

Para obtener una clave de API de Helius, visita el Portal para desarrolladores de Helius. Sigue estos pasos para comenzar:

  1. Crea una cuenta con una billetera de Solana, una cuenta de Google o una cuenta de GitHub.
  2. Cuando inicies sesión, se te pedirá que crees una clave de API.
  3. Guarda esta clave de forma segura, ya que la usaremos para realizar llamadas a la API.

Creación de la aplicación de Next.js

Paso 1: Configura tu proyecto de Next.js

Crea una nueva aplicación de Next.js con Tailwind

Código
npx create-next-app@latest helius-portfolio --typescript --eslint

Usa las siguientes configuraciones:

Esto nos permitirá usar Tailwind CSS para aplicar estilos, así como el nuevo enrutador de aplicaciones.

Código
cd helius-portfolio

‍Paso 2: Crea los componentes

Crea una carpeta components en el directorio de la aplicación para mantener una estructura organizada.

Componente SearchBar (components/SearchBar.js):

Este componente gestiona las direcciones de billetera que ingresan los usuarios. Utiliza el hook useState para gestionar el estado de la dirección y useRouter para la navegación al enviar el formulario. El formulario utiliza clases de Tailwind CSS para lograr un aspecto elegante.

Componente TokenCard (components/TokenCard.js):

Este componente está diseñado para mostrar información de los tokens. Renderiza de forma condicional distintos diseños para tokens fungibles y no fungibles, y utiliza los tipos Token y Attribute de ../types/Token.

Componente SearchBar:

components/searchBar.ts

Código
import { useRouter } from "next/navigation";
import React, { useState } from "react";

export default function SearchBar() {
  const router = useRouter();
  const [address, setAddress] = useState("");

  function handleSubmit(event: React.FormEvent) {
    event.preventDefault();
    router.push(`/${address}`);
  }

  return (
    
       setAddress(e.target.value)}
        className="border-2 border-gray-300 rounded-md w-full text-center px-4 py-2 mb-4 flex-grow text-black"
      />
      
        Search
      
    
  );
}

Componente TokenCard:

Este componente procesa los datos de los tokens provenientes de la API y muestra información relevante en cada tarjeta de token.

En el siguiente ejemplo, mostramos información básica como la imagen, el símbolo, la cantidad y el valor de cada token fungible. Para los tokens no fungibles, mostramos la imagen, el nombre, la descripción y los atributos. Puedes extraer cualquier información proporcionada por la API y mostrarla en la tarjeta.

Por ejemplo, podrías mostrar información específica sobre la compresión de los cNFT o información sobre las inscripciones de los activos inscritos. Para obtener más información sobre los datos específicos con los que puedes trabajar, consulta la documentación de DAS.

Código
"use client";

import React from "react";
import { Token, Attribute } from "../types/Token";

interface TokenCardProps {
  token: Token;
  tokenType: string;
}

const TokenCard = ({ token, tokenType }: TokenCardProps) => {
  return (
    
      {/* Other token information */}
      {tokenType === "fungible" ? (
        
          
          
            
              {token.content.metadata.symbol}
            
            {/* {token.content.metadata.description} */}
            Amount:{token.token_info.balance}
            {token.token_info.price_info?.total_price ? (
              Value: ${token.token_info.price_info.total_price}
            ) : null}
          
        
      ) : (
        
          
          
            
              {token.content.metadata.name}
            
            {token.content.metadata.description}
            
              {token.content.metadata?.attributes?.map(
                (attribute: Attribute, index: number) => (
                  
                    {attribute.trait_type}: {attribute.value}
                  
                )
              )}
            
          
        
      )}
    
  );
}

export default TokenCard;

Paso 3: Obtén datos de DAS

Usaremos el método searchAssets de la API DAS para obtener datos de los tokens. Este método es flexible y nos permite especificar criterios como direcciones de billeteras y tipos de tokens.

Crea una carpeta lib:

  1. Crea una carpeta lib en el directorio de la aplicación para la llamada a la API.
  2. Crea dentro de ella un archivo searchAssets.ts.

Función de llamada a la API (lib/searchAssets.ts):

  • Esta función obtiene tokens según la dirección de la billetera.
  • Gestiona posibles errores y registra las respuestas para facilitar la depuración
Código
interface Tokens {
  items: any[];
}

const fetchTokens = async (walletAddress: string): Promise => {
  const url = `https://mainnet.helius-rpc.com/?api-key=`;
  console.log(
    `Starting search for tokens for wallet address: ${walletAddress}`
  );
  try {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: "my-id",
        method: "searchAssets",
        params: {
          ownerAddress: walletAddress,
          tokenType: "all",
          displayOptions: {
            showCollectionMetadata: true,
          },
        },
      }),
    });
    const data = await response.json();
    console.log(
      `Data returned for wallet address ${walletAddress}:`,
      data.result
    );
    return { items: data.result };
  } catch (error) {
    console.error("Error fetching tokens:", error);
    return { items: [] };
  }
};

export default fetchTokens;

Configura el tipo de token

  • Tendremos que configurar un tipo para la respuesta de la API DAS. Esta es una buena práctica al trabajar con TypeScript. Puedes crear una carpeta llamada types y un archivo llamado token.ts
Código
export interface ApiResponse {
  total: number;
  limit: number;
  cursor?: string;
  items: Token[];
}

export interface Token {
  interface: string;
  id: string;
  content: Content;
  authorities: Authority[];
  compression: Compression;
  grouping: Grouping[]; // or any[]
  royalty: Royalty;
  creators: Creator[]; // or any[]
  ownership: Ownership;
  supply: Supply | null | number;
  mutable: boolean;
  burnt: boolean;
  token_info: TokenInfo;
  mint_extensions: MintExtensions;
  inscription: Inscription;
  spl20?: Spl20;
}

export interface Content {
  $schema: string;
  json_uri: string;
  files: any[];
  metadata: Record;
  links: Record;
}

export interface Authority {
  address: string;
  scopes: string[];
}

export interface Compression {
  eligible: boolean;
  compressed: boolean;
  data_hash: string;
  creator_hash: string;
  asset_hash: string;
  tree: string;
  seq: number;
  leaf_id: number;
}

export interface Grouping {
  group_key: string;
  group_value: string;
  collection_metadata: CollectionMetadata;
}

export interface Royalty {
  royalty_model: string;
  target: string | null;
  percent: number;
  basis_points: number;
  primary_sale_happened: boolean;
  locked: boolean;
}

export interface Creator {
  address: string;
  share: number;
  verified: boolean;
}

export interface Ownership {
  frozen: boolean;
  delegated: boolean;
  delegate: null | string;
  ownership_model: string;
  owner: string;
}

export interface Supply {
  print_max_supply: number;
  print_current_supply: number;
  edition_nonce: number;
}

export interface TokenInfo {
  symbol: string;
  balance: number;
  supply: number;
  decimals: number;
  token_program: string;
  associated_token_address: string;
  price_info: PriceInfo;
}

export interface Inscription {
  order: number;
  size: number;
  contentType: string;
  encoding: string;
  validationHash: string;
  inscriptionDataAccount: string;
}

export interface Spl20 {
  p: string;
  op: string;
  tick: string;
  amt: string;
}

export interface File {
  uri: string;
  cdn_uri: string;
  mime: string;
}

export interface Metadata {
  attributes: Attribute[];
  description: string;
  name: string;
  symbol: string;
}

export interface Attribute {
  value: string;
  trait_type: string;
}

export interface CollectionMetadata {
  name: string;
  symbol: string;
  image: string;
  description: string;
  external_url: string;
}

export interface PriceInfo {
  price_per_token: number;
  total_price: number;
  currency: string;
}

export interface MintExtensions {}

Paso 4: Muestra la información de los tokens

Clasificaremos la respuesta de la API en tokens fungibles y no fungibles. Mostraremos estos tokens mediante el componente Token Card. Un botón permite alternar entre ambos tipos de tokens.

Integra los componentes en la página de búsqueda

  • Página de búsqueda (pages/index.ts)
  • La página de inicio incluye una barra de búsqueda donde los usuarios pueden ingresar direcciones de billeteras.
  • Utiliza Tailwind CSS para ofrecer un diseño limpio y adaptable.
Código
"use client";

import React from "react";
import SearchBar from "./components/searchBar";

export default function Home() {
  return (
    
      
        
          Solana Portfolio Viewer
        
        
          {"Built with Helius's DAS API"}
        
        
          
        
      
    
  );
}

Configura la página de tokens

Usaremos rutas dinámicas de Next.js para cada dirección de billetera. Esto mejora la experiencia del usuario, ya que permite navegar y compartir URL fácilmente.

Configura un directorio llamado [wallet]; los corchetes habilitan el enrutamiento dinámico. Después, crea un archivo llamado page.tsx que contendrá toda la lógica de negocio de las páginas cargadas dinámicamente.

Configuración de la página de tokens (pages/[wallet]/page.tsx):

Esta página muestra los tokens asociados con la dirección de billetera de la URL. Realiza una llamada a la API para obtener los datos de los tokens y los muestra mediante el componente Token Card.

Código
"use client";

import React, { useState, useEffect } from "react";
import fetchTokens from "../lib/searchAssets";
import TokenCard from "../components/tokenCard";
import { Token, Attribute } from "../types/Token";

interface Tokens {
  items: Token[];
}

interface PageProps {
  params: {
    wallet: string;
  };
}

export default function Page({ params }: PageProps) {
  const [tokens, setTokens] = useState(null);
  const [tokenType, setTokenType] = useState("fungible");

  useEffect(() => {
    fetchTokens(params.wallet).then(setTokens).catch(console.error);
  }, [params.wallet]);

  console.log("tokens", tokens);

  const fungibleTokens = tokens
    ? tokens.items.filter(
        (token) =>
          token.interface === "FungibleToken" ||
          token.interface === "FungibleAsset"
      )
    : [];

  const nonFungibleTokens = tokens
    ? tokens.items.filter(
        (token) =>
          token.interface !== "FungibleToken" &&
          token.interface !== "FungibleAsset"
      )
    : [];

  const displayedTokens =
    tokenType === "fungible" ? fungibleTokens : nonFungibleTokens;

  return (
    
      
        Portfolio Viewer
      
      {params.wallet}
      
         setTokenType("fungible")}
        >
          Fungible Tokens
        
         setTokenType("nonFungible")}
        >
          Non-Fungible Tokens
        
      
      {displayedTokens.length > 0 ? (
        
          {displayedTokens.map((token) => (
            
          ))}
        
      ) : (
        Loading...
      )}
    
  );
}

Después de configurar todo, el directorio de tu proyecto debería verse así:

Paso 5: Aplica estilos a la aplicación

Tailwind CSS será nuestro framework de estilos. Su enfoque basado en utilidades nos permite aplicar estilos rápidamente a los componentes y mantener un diseño coherente y adaptable. Puedes usar Tailwind para personalizar tu aplicación como quieras.

Paso 6: Prueba la aplicación

Ejecuta tu aplicación de Next.js para probarla de forma local:

Código
npm run dev

Ingresa distintas direcciones de billeteras para hacer pruebas y verifica que se muestren los datos correctos.

Despliegue

Desplegaremos nuestra aplicación mediante Vercel. Vercel ofrece alojamiento gratuito y proporciona análisis e información valiosa, por lo que es una opción ideal para alojar aplicaciones de Next.js. Puedes configurarlo en https://vercel.com/.

Conclusión

¡Felicitaciones por completar este tutorial! Esperamos que te haya resultado útil.

La API DAS es una herramienta muy potente y rápida que te permite obtener datos de tokens desde la cadena.

Este visor de portafolio es un excelente ejemplo de las capacidades de la API.

Esperamos que puedas tomar el sitio básico que creamos y convertirlo en algo increíble. Si tienes alguna pregunta, únete a nuestro Discord y pregúntanos directamente.

Puedes encontrar el código completo aquí: https://github.com/helius-labs/galleria

Recursos de aprendizaje adicionales

Para profundizar tus conocimientos sobre Next.js, la blockchain de Solana y la integración de API, explora estos recursos:

Esta guía proporciona una base sólida para crear aplicaciones basadas en blockchain con Next.js e interactuar con la blockchain de Solana mediante la API DAS.

‍

Suscríbete a Helius

Mantente al día con las novedades del desarrollo en Solana y recibe actualizaciones cuando publiquemos

Imagen ampliada