
Como criar um visualizador de portfólio da Solana com Next.js e a DAS API da Helius
Objetivos
Neste tutorial, criaremos uma aplicação front-end para exibir o conteúdo de uma carteira Solana usando a DAS API da Helius. Mostraremos diferentes tipos de token e suas informações detalhadas, incluindo metadados, dados de coleções e preços de tokens fungíveis.
Este tutorial mostrará como criar algo semelhante à Galleria, detalhando as etapas necessárias.
Pré-requisitos
- Chave de API da Helius.
- Familiaridade com React.
- Experiência com Next.js.
Visão geral das tecnologias utilizadas
- Next.js: um framework React para criar aplicações renderizadas no servidor.
- DAS API da Helius: uma API abrangente para acessar dados de tokens da Solana.
- Vercel: uma plataforma para hospedar aplicações Next.js.
- Tailwind CSS: um framework CSS utility-first para estilização.
Configurando o projeto
A DAS API
A DAS API é uma especificação e um sistema de código aberto oferecidos pela Helius. A API fornece uma interface simples para interagir com ativos digitais na blockchain Solana. Ela oferece suporte a vários tipos de token, incluindo tokens fungíveis, NFTs tradicionais e NFTs compactados, além de recursos como indexação de metadados off-chain.
Configuração da chave de API
Para obter uma chave de API da Helius, acesse o Portal do Desenvolvedor da Helius. Veja como começar:
- Crie uma conta usando uma carteira Solana ou uma conta do Google ou GitHub.
- Após entrar, você verá uma solicitação para criar uma chave de API.
- Armazene essa chave com segurança, pois ela será usada para fazer nossas chamadas de API.
Criando a aplicação Next.js
Etapa 1: configurar seu projeto Next.js
Crie uma nova aplicação Next.js com Tailwind
npx create-next-app@latest helius-portfolio --typescript --eslintUse as seguintes configurações:
Isso permitirá usar o Tailwind CSS para estilização, além do novo App Router.
cd helius-portfolioEtapa 2: criar componentes
Crie uma pasta components no diretório app para manter uma estrutura organizada.
Componente SearchBar (components/SearchBar.js):
Esse componente processa os dados inseridos pelo usuário para endereços de carteira. Ele utiliza o hook useState para gerenciar o estado do endereço e useRouter para navegar após o envio do formulário. O formulário é estilizado com classes do Tailwind CSS para oferecer uma aparência elegante.
Componente TokenCard (components/TokenCard.js):
Esse componente foi desenvolvido para exibir informações de tokens. Ele renderiza condicionalmente diferentes layouts para tokens fungíveis e não fungíveis e utiliza os tipos Token e Attribute de ../types/Token.
Componente SearchBar:
components/searchBar.ts
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:
Esse componente analisa os dados de tokens recebidos da API e mostra as informações relevantes em cada cartão de token.
No exemplo abaixo, mostramos algumas informações básicas, como imagem, símbolo, quantidade e valor de cada token fungível. Para tokens não fungíveis, mostramos a imagem, o nome, a descrição e os atributos. Você pode extrair qualquer informação fornecida pela API e exibi-la no cartão.
Um exemplo seria mostrar informações específicas de compactação para cNFTs ou informações de inscrição para ativos inscritos. Para saber mais sobre as informações específicas com as quais você pode trabalhar, consulte a documentação da DAS.
"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;Etapa 3: buscar dados da DAS
Usaremos o método searchAssets da DAS API para buscar dados de tokens. Esse método é flexível e permite especificar critérios como endereços de carteira e tipos de token.
Criando uma pasta lib:
- Crie uma pasta
libno diretório app para a chamada de API. - Dentro dela, crie um arquivo
searchAssets.ts.
Função de chamada da API (lib/searchAssets.ts):
- Essa função busca tokens com base no endereço da carteira.
- Ela processa possíveis erros e registra respostas para depuração
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;Configure o tipo de token
- Precisaremos configurar um tipo para a resposta da DAS API. Essa é uma boa prática ao trabalhar com Typescript. Você pode criar uma pasta chamada types e um arquivo chamado
token.ts
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 {}Etapa 4: exibir informações dos tokens
Categorizaremos a resposta da API em tokens fungíveis e não fungíveis. Esses tokens serão exibidos usando o componente Token Card. Um botão de alternância permite que os usuários troquem entre os dois tipos de token.
Integrando os componentes à página de busca
- Página de busca (pages/index.ts)
- A página inicial apresenta uma barra de busca na qual os usuários podem inserir endereços de carteira.
- Ela é estilizada com Tailwind CSS para oferecer um design limpo e responsivo.
"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"}
);
}Configurando a página de tokens
Usaremos rotas dinâmicas do Next.js para endereços de carteira individuais. Isso melhora a experiência do usuário, facilitando a navegação e o compartilhamento de URLs.
Configure um diretório chamado [wallet]. Os colchetes habilitam o roteamento dinâmico. Depois disso, crie um arquivo chamado page.tsx, que conterá toda a lógica de negócios de todas as páginas carregadas dinamicamente.
Configuração da página de tokens (pages/[wallet]/page.tsx):
Essa página exibe os tokens associados ao endereço da carteira presente na URL. Ela faz uma chamada de API para buscar os dados dos tokens e os exibe usando o componente Token Card.
"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...
)}
);
}Depois de configurar tudo isso, o diretório do seu projeto deverá ter esta aparência:
Etapa 5: estilizar a aplicação
O Tailwind CSS será nosso framework de estilização. Sua abordagem utility-first permite estilizar componentes rapidamente, mantendo um design consistente e responsivo. Você pode usar o Tailwind para personalizar sua aplicação como quiser.
Etapa 6: testar a aplicação
Execute sua aplicação Next.js para testá-la localmente:
npm run devFaça testes inserindo diferentes endereços de carteira e verifique se os dados corretos são exibidos.
Implantação
Implantaremos nossa aplicação usando a Vercel. A Vercel oferece hospedagem gratuita, além de análises e insights valiosos, o que a torna uma opção ideal para hospedar aplicações Next.js. Você pode fazer a configuração em https://vercel.com/.
Conclusão
Parabéns por concluir este tutorial! Esperamos que ele tenha sido útil.
A DAS API é uma ferramenta muito rápida e poderosa que permite recuperar dados de tokens da blockchain.
Este visualizador de portfólio é um excelente exemplo do que a API pode fazer.
Esperamos que você possa usar o site básico criado aqui e transformá-lo em algo incrível. Se tiver alguma dúvida, entre no nosso Discord e fale diretamente conosco!
Você encontra o código completo aqui: https://github.com/helius-labs/galleria
Outros recursos de aprendizagem
Para aprofundar seu conhecimento sobre Next.js, a blockchain Solana e a integração de APIs, confira estes recursos:
- Documentação do Next.js
- Biblioteca Solana Web3.js
- Site oficial do Tailwind CSS
- Documentação da Helius
Este guia oferece uma base sólida para criar aplicações baseadas em blockchain com Next.js e interagir com a blockchain Solana usando a DAS API.
Artigos relacionados
Assine a Helius
Acompanhe as novidades mais recentes do desenvolvimento Solana e receba atualizações quando publicarmos


