NEU: Helius übernimmt Light Protocol
So baust du einen Solana-Portfolio-Viewer mit Next.js und der DAS API von Helius
Blog/Entwicklung

So baust du einen Solana-Portfolio-Viewer mit Next.js und der DAS API von Helius

Developer Experience EngineerOwen Venter auf XOwen Venter auf LinkedIn
6 Min. Lesezeit

Ziele

In diesem Tutorial erstellen wir mit der DAS API von Helius eine Frontend-Anwendung, die den Inhalt einer Solana-Wallet anzeigt. Wir präsentieren verschiedene Token-Typen und ihre Details, darunter Metadaten, Informationen zu Collections und Preise fungibler Token.

Dieses Tutorial führt dich Schritt für Schritt durch die Entwicklung einer Anwendung, die Galleria ähnelt.

Voraussetzungen

  • Helius API-Key.
  • Vertrautheit mit React.
  • Erfahrung mit Next.js.

Überblick über die verwendeten Technologien

  • Next.js: Ein React-Framework zum Erstellen serverseitig gerenderter Anwendungen.
  • DAS API von Helius: Eine umfassende API für den Zugriff auf Solana-Token-Daten.
  • Vercel: Eine Plattform zum Hosten von Next.js-Anwendungen.
  • Tailwind CSS: Ein Utility-First-CSS-Framework für das Styling.

Projekt einrichten

Die DAS API

Die DAS API ist eine Open-Source-Spezifikation und ein von Helius angebotenes System. Die API bietet eine einfache Schnittstelle für die Interaktion mit digitalen Assets auf der Solana-Blockchain. Sie unterstützt verschiedene Token-Typen, darunter fungible Token, reguläre NFTs und komprimierte NFTs. Außerdem bietet sie Funktionen wie die Indizierung von Off-Chain-Metadaten.

API-Key einrichten

Um einen Helius API-Key zu erhalten, besuche das Helius-Entwicklerportal. So legst du los:

  1. Erstelle mit einer Solana-Wallet, einem Google-Konto oder einem GitHub-Konto einen Account.
  2. Nach der Anmeldung wirst du aufgefordert, einen API-Key zu erstellen.
  3. Bewahre diesen Key sicher auf, da wir ihn für unsere API-Aufrufe verwenden.

Next.js-Anwendung erstellen

Schritt 1: Next.js-Projekt einrichten

Neue Next.js-App mit Tailwind erstellen

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

Verwende die folgenden Konfigurationen:

Damit können wir Tailwind CSS für das Styling und den neuen App Router verwenden.

Code
cd helius-portfolio

‍Schritt 2: Komponenten erstellen

Erstelle im app-Verzeichnis einen Ordner namens components, um die Struktur übersichtlich zu halten.

SearchBar-Komponente (components/SearchBar.js):

Diese Komponente verarbeitet die Eingabe von Wallet-Adressen. Sie verwendet den Hook useState, um den Zustand der Adresse zu verwalten, und useRouter, um nach dem Absenden des Formulars zu navigieren. Tailwind-CSS-Klassen verleihen dem Formular ein modernes Design.

TokenCard-Komponente (components/TokenCard.js):

Diese Komponente zeigt Token-Informationen an. Sie rendert abhängig vom Token-Typ unterschiedliche Layouts für fungible und nicht fungible Token und verwendet die Typen Token und Attribute aus ../types/Token.

SearchBar-Komponente:

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

TokenCard-Komponente:

Diese Komponente verarbeitet die Token-Daten aus der API und zeigt die relevanten Informationen auf jeder Token-Karte an.

Im folgenden Beispiel zeigen wir für jeden fungiblen Token grundlegende Informationen wie Bild, Symbol, Menge und Wert. Für nicht fungible Token zeigen wir Bild, Name, Beschreibung und Attribute. Du kannst beliebige Informationen aus der API extrahieren und auf der Karte anzeigen.

Du könntest beispielsweise komprimierungsspezifische Informationen für cNFTs oder Inschriftinformationen für Assets mit Inschriften anzeigen. Weitere Details zu den verfügbaren Informationen findest du in der DAS-Dokumentation.

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;

Schritt 3: Daten aus DAS abrufen

Wir verwenden die Methode searchAssets der DAS API, um Token-Daten abzurufen. Diese Methode ist flexibel und erlaubt es uns, Kriterien wie Wallet-Adressen und Token-Typen anzugeben.

Ordner lib erstellen:

  1. Erstelle im app-Verzeichnis einen Ordner namens lib für den API-Aufruf.
  2. Erstelle darin eine Datei namens searchAssets.ts.

Funktion für den API-Aufruf (lib/searchAssets.ts):

  • Diese Funktion ruft Token anhand der Wallet-Adresse ab.
  • Sie behandelt mögliche Fehler und protokolliert Antworten für das Debugging
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;

Token-Typ einrichten

  • Wir müssen einen Typ für die Antwort der DAS API definieren. Das ist bei der Arbeit mit Typescript eine bewährte Vorgehensweise. Du kannst einen Ordner namens types und darin eine Datei namens token.ts erstellen
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 {}

Schritt 4: Token-Informationen anzeigen

Wir unterteilen die API-Antwort in fungible und nicht fungible Token. Anschließend zeigt die TokenCard-Komponente diese Token an. Über eine Umschalttaste können Nutzer zwischen den beiden Token-Typen wechseln.

Komponenten in die Suchseite integrieren

  • Suchseite (pages/index.ts)
  • Die Startseite enthält eine Suchleiste, in die Nutzer Wallet-Adressen eingeben können.
  • Tailwind CSS sorgt für ein klares, responsives Design.
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"}
        
        
          
        
      
    
  );
}

Token-Seite einrichten

Wir verwenden dynamische Routen in Next.js für einzelne Wallet-Adressen. Das verbessert die Nutzererfahrung, da Nutzer einfach navigieren und URLs teilen können.

Erstelle ein Verzeichnis namens [wallet]. Die Klammern ermöglichen dynamisches Routing. Erstelle anschließend eine Datei namens page.tsx, die die gesamte Geschäftslogik für alle dynamisch geladenen Seiten enthält.

Token-Seite einrichten (pages/[wallet]/page.tsx):

Diese Seite zeigt die Token an, die mit der Wallet-Adresse in der URL verknüpft sind. Sie ruft die Token-Daten über die API ab und zeigt sie mit der TokenCard-Komponente an.

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

Nachdem du alles eingerichtet hast, sollte dein Projektverzeichnis so aussehen:

Schritt 5: Anwendung gestalten

Wir verwenden Tailwind CSS als Styling-Framework. Der Utility-First-Ansatz ermöglicht es uns, Komponenten schnell zu gestalten und gleichzeitig ein konsistentes, responsives Design sicherzustellen. Mit Tailwind kannst du deine Anwendung beliebig anpassen.

Schritt 6: Anwendung testen

Starte deine Next.js-App, um sie lokal zu testen:

Code
npm run dev

Gib zum Testen verschiedene Wallet-Adressen ein und prüfe, ob die richtigen Daten angezeigt werden.

Deployment

Wir stellen unsere Anwendung mit Vercel bereit. Vercel bietet kostenloses Hosting sowie nützliche Analysen und Einblicke. Damit eignet sich die Plattform ideal für Next.js-Anwendungen. Du kannst die Einrichtung unter https://vercel.com/ vornehmen.

Fazit

Glückwunsch, du hast das Tutorial abgeschlossen! Wir hoffen, dass es dir weitergeholfen hat.

Die DAS API ist ein sehr leistungsstarkes und schnelles Werkzeug, mit dem du Token-Daten aus der Blockchain abrufen kannst.

Dieser Portfolio-Viewer zeigt hervorragend, was mit der API möglich ist.

Wir hoffen, dass du die erstellte Basis-Website weiterentwickelst und etwas Großartiges daraus machst. Falls du Fragen hast, tritt unserem Discord bei und frag uns direkt!

Den vollständigen Code findest du hier: https://github.com/helius-labs/galleria

Weitere Lernressourcen

Mit diesen Ressourcen kannst du dein Wissen über Next.js, die Solana-Blockchain und die API-Integration vertiefen:

Dieser Leitfaden bietet dir eine solide Grundlage, um Blockchain-basierte Anwendungen mit Next.js zu erstellen und über die DAS API mit der Solana-Blockchain zu interagieren.

‍

Helius abonnieren

Bleib bei der Solana-Entwicklung auf dem Laufenden und erhalte Updates, wenn wir neue Beiträge veröffentlichen

Vergrößertes Bild