NOUVEAU : Helius acquiert Light Protocol
Comment créer une visionneuse de portefeuille Solana avec Next.js et l’API DAS de Helius
Blog/Développement

Comment créer une visionneuse de portefeuille Solana avec Next.js et l’API DAS de Helius

Ingénieur en expérience développeurOwen Venter sur XOwen Venter sur LinkedIn
6 min de lecture

Objectifs

Dans ce tutoriel, nous allons créer une application front-end qui affiche le contenu d’un portefeuille Solana à l’aide de l’API DAS de Helius. Nous présenterons différents types de jetons ainsi que leurs informations détaillées, notamment leurs métadonnées, les informations sur leurs collections et le prix des jetons fongibles.

Ce tutoriel vous guidera à travers les étapes nécessaires pour créer une application similaire à Galleria.

Prérequis

  • Une clé API Helius.
  • Une bonne connaissance de React.
  • Une expérience avec Next.js.

Présentation des technologies utilisées

  • Next.js : un framework React permettant de créer des applications avec rendu côté serveur.
  • API DAS de Helius : une API complète permettant d’accéder aux données des jetons Solana.
  • Vercel : une plateforme d’hébergement pour les applications Next.js.
  • Tailwind CSS : un framework CSS privilégiant les classes utilitaires pour la mise en forme.

Configuration du projet

L’API DAS

L’API DAS est une spécification et un système open source proposés par Helius. Cette API fournit une interface simple pour interagir avec les actifs numériques sur la blockchain Solana. Elle prend en charge différents types de jetons, notamment les jetons fongibles, les NFT classiques et les NFT compressés, et offre des fonctionnalités telles que l’indexation des métadonnées hors chaîne.

Configuration de la clé API

Pour obtenir une clé API Helius, accédez au portail des développeurs Helius. Voici comment commencer :

  1. Créez un compte avec un portefeuille Solana, un compte Google ou un compte GitHub.
  2. Une fois connecté, vous serez invité à créer une clé API.
  3. Conservez cette clé en lieu sûr, car nous l’utiliserons pour effectuer nos appels API.

Création de l’application Next.js

Étape 1 : configurer votre projet Next.js

Créer une nouvelle application Next.js avec Tailwind

Code
npx create-next-app@latest helius-portfolio --typescript --eslint

Utilisez les configurations suivantes :

Cela nous permettra d’utiliser Tailwind CSS pour la mise en forme, ainsi que le nouveau routeur App.

Code
cd helius-portfolio

‍Étape 2 : créer les composants

Créez un dossier components dans le répertoire app afin de conserver une structure organisée.

Composant SearchBar (components/SearchBar.js) :

Ce composant gère la saisie des adresses de portefeuille. Il utilise le hook useState pour gérer l’état de l’adresse et useRouter pour la navigation après l’envoi du formulaire. Le formulaire est mis en forme avec des classes Tailwind CSS pour un rendu élégant.

Composant TokenCard (components/TokenCard.js) :

Ce composant est conçu pour afficher les informations des jetons. Il affiche conditionnellement différentes mises en page pour les jetons fongibles et non fongibles, et utilise les types Token et Attribute de ../types/Token.

Composant SearchBar :

components/searchBar.ts

Code
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
      
    
  );
}

Composant TokenCard :

Ce composant analyse les données des jetons provenant de l’API et affiche les informations pertinentes sur chaque carte de jeton.

Dans l’exemple ci-dessous, nous affichons des informations élémentaires telles que l’image, le symbole, la quantité et la valeur de chaque jeton fongible. Pour les jetons non fongibles, nous affichons l’image, le nom, la description et les attributs. Vous pouvez extraire n’importe quelle information fournie par l’API et l’afficher sur la carte.

Vous pourriez, par exemple, afficher les informations propres à la compression pour les cNFT ou les informations d’inscription pour les actifs inscrits. Pour en savoir plus sur les informations que vous pouvez exploiter, consultez la documentation de DAS.

Code
"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;

Étape 3 : récupérer les données depuis DAS

Nous utiliserons la méthode searchAssets de l’API DAS pour récupérer les données des jetons. Cette méthode est flexible et nous permet de préciser des critères tels que les adresses de portefeuille et les types de jetons.

Créer un dossier lib :

  1. Créez un dossier lib dans le répertoire app pour l’appel API.
  2. Créez-y un fichier searchAssets.ts.

Fonction d’appel API (lib/searchAssets.ts) :

  • Cette fonction récupère les jetons en fonction de l’adresse du portefeuille.
  • Elle gère les erreurs éventuelles et consigne les réponses à des fins de débogage
Code
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;

Configurer le type des jetons

  • Nous devons définir un type pour la réponse de l’API DAS. Il s’agit d’une bonne pratique lorsque vous travaillez avec Typescript. Vous pouvez créer un dossier appelé types, puis un fichier appelé token.ts
Code
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 {}

Étape 4 : afficher les informations des jetons

Nous classerons la réponse de l’API en jetons fongibles et non fongibles. Ces jetons seront affichés à l’aide du composant Token Card. Un bouton permettra aux utilisateurs de passer d’un type de jeton à l’autre.

Intégrer les composants à la page de recherche

  • Page de recherche (pages/index.ts)
  • La page d’accueil comporte une barre de recherche dans laquelle les utilisateurs peuvent saisir des adresses de portefeuille.
  • Elle est mise en forme avec Tailwind CSS pour offrir un design épuré et responsive.
Code
"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"}
        
        
          
        
      
    
  );
}

Configurer la page des jetons

Nous utiliserons les routes dynamiques de Next.js pour chaque adresse de portefeuille. Cela améliore l’expérience utilisateur en facilitant la navigation et le partage des URL.

Créez un répertoire appelé [wallet] ; les crochets activent le routage dynamique. Créez ensuite un fichier appelé page.tsx, qui contiendra toute la logique métier de l’ensemble des pages chargées dynamiquement.

Configuration de la page des jetons (pages/[wallet]/page.tsx) :

Cette page affiche les jetons associés à l’adresse de portefeuille figurant dans l’URL. Elle effectue un appel API pour récupérer les données des jetons et les affiche à l’aide du composant Token Card.

Code
"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...
      )}
    
  );
}

Une fois tous ces éléments configurés, le répertoire de votre projet devrait se présenter comme suit :

Étape 5 : mettre en forme l’application

Tailwind CSS sera notre framework de mise en forme. Son approche privilégiant les classes utilitaires nous permet de mettre rapidement en forme les composants, tout en garantissant un design cohérent et responsive. Vous pouvez utiliser Tailwind pour personnaliser votre application comme vous le souhaitez.

Étape 6 : tester l’application

Exécutez votre application Next.js pour la tester localement :

Code
npm run dev

Testez-la en saisissant différentes adresses de portefeuille et vérifiez que les données correctes s’affichent.

Déploiement

Nous déploierons notre application avec Vercel. Vercel propose un hébergement gratuit ainsi que de précieuses données d’analyse, ce qui en fait une solution idéale pour héberger des applications Next.js. Vous pouvez le configurer sur https://vercel.com/.

Conclusion

Félicitations, vous avez terminé ce tutoriel ! Nous espérons qu’il vous a été utile.

L’API DAS est un outil très puissant et rapide qui vous permet de récupérer les données des jetons depuis la blockchain.

Cette visionneuse de portefeuille illustre parfaitement les possibilités offertes par l’API.

Nous espérons que vous pourrez partir du site élémentaire que nous avons créé pour en faire un projet remarquable. Si vous avez des questions, n’hésitez pas à rejoindre notre Discord et à nous les poser directement !

Vous trouverez le code complet ici : https://github.com/helius-labs/galleria

Ressources pour approfondir vos connaissances

Pour approfondir votre compréhension de Next.js, de la blockchain Solana et de l’intégration des API, consultez les ressources suivantes :

Ce guide fournit une base solide pour créer des applications basées sur la blockchain avec Next.js et interagir avec la blockchain Solana à l’aide de l’API DAS.

‍

Abonnez-vous à Helius

Suivez les dernières actualités du développement sur Solana et recevez une notification à chaque publication

Image agrandie