Como criar um rastreador de gas simples com Gas API e Next.js

Aprenda a criar um app simples de rastreamento de gas usando a API de gas do MetaMask, Next.js e ShadcnUI.

8 min de leitura
Como criar um rastreador de gas simples com Gas API e Next.js

'Gas' refere-se a uma unidade que mede a quantidade de esforço computacional necessário para executar operações, como realizar transações ou executar smart contracts. É semelhante ao combustível de um carro – necessário para que a rede processe e valide operações. Cada transação no Ethereum requer uma quantidade específica de gas, determinada pela sua complexidade. Os usuários definem um preço de gas em Gwei (1 Gwei = 1 bilionésimo de um Ether), representando a quantidade de Ether que estão dispostos a pagar por unidade de gas.

Entender os preços de gas é fundamental nas redes blockchain, pois ajuda os usuários a gerenciar o custo de suas transações. O conhecimento dos preços de gas atuais permite que os usuários escolham o momento mais econômico para iniciar uma transação e determinem sua velocidade. A consciência sobre os preços de gas também é essencial para evitar transações com falha, planejar orçamentos, compreender o congestionamento da rede e tomar decisões de investimento bem embasadas.

A Gas API do MetaMask

A Gas API do MetaMask, disponível por meio da Infura, é uma ferramenta especializada desenvolvida para fornecer informações em tempo real sobre preços de gas para redes compatíveis com a Ethereum Virtual Machine (EVM). Ela funciona como um oracle, oferecendo dados atualizados sobre os custos computacionais necessários para executar operações ou transações nessas redes. A API capacita desenvolvedores a criar recursos avançados de estimativa de gas, o que pode gerar economia de custos em operações de transação no back-end ou aprimorar a interface do usuário.

Neste tutorial, aprenderemos como construir um App de Rastreamento de Gas usando a Gas API, Next.js e ShadcnUI. Esta aplicação permitirá que usuários de dapps acessem preços de gas recomendados adaptados às suas prioridades de transação, auxiliando na inclusão eficiente dessas transações em um bloco da blockchain.

Pré-requisitos

Configurando Next.js + ShadcnUI

Primeiro, certifique-se de que o Node.js está instalado em sua máquina. Após configurar o Node.js, inicie uma nova aplicação Next.js abrindo seu terminal e executando o seguinte comando:

npx create-next-app@latest

Após executar o comando, além de vários prompts aparecerem, um novo diretório será criado com o nome do seu projeto – utilizei gastracker-app –, estabelecendo assim a estrutura base do Next.js e instalando as dependências essenciais. Agora, acesse o diretório do seu projeto:

npx create-next-app@latest
✔ What is your project named? … gastracker-app
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes
Copiar

Navegue até o diretório do seu novo projeto e ative a aplicação Next.js em modo de desenvolvimento. Em seguida, você pode explorar sua aplicação acessando http://localhost:3000 no seu navegador.

cd gastracker-app
npm run dev
Copiar

Criando a interface do usuário

Para nossa aplicação, utilizaremos uma biblioteca de componentes. Vamos começar instalando o ShadcnUI:

npx shadcn-ui@latest init

Durante a instalação, você será guiado pela configuração do arquivo components.json com os seguintes prompts:

Would you like to use TypeScript (recommended)? no / yes
Which style would you like to use? › Default
Which color would you like to use as base color? › Slate
Where is your global CSS file? › › app/globals.css
Do you want to use CSS variables for colors? › no / yes
Where is your tailwind.config.js located? › tailwind.config.js
Configure the import alias for components: › @/components
Configure the import alias for utils: › @/lib/utils
Are you using React Server Components? › no / yes
Copiar

Com isso resolvido, vamos também instalar o componente Card do Shadcn UI:

npx shadcn-ui@latest add card

Neste tutorial, vamos focar no uso do componente Card do Shadcn UI. Para saber mais sobre esses componentes, visite o site do Shadcn UI. Com o front end configurado, estamos prontos para começar a trabalhar com a Gas API.

No diretório raiz, crie um arquivo chamado .env, onde armazenaremos as seguintes credenciais:

INFURA_API_KEY=
INFURA_API_KEY_SECRET=
Copiar

Certifique-se de obter a API_KEY e a API_KEY_SECRET no seu painel da Infura. É fundamental evitar enviar a chave de API para o GitHub. No diretório raiz, verifique o arquivo .gitignore para confirmar que as linhas necessárias estão incluídas.

# Ignore environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
Copiar

Também precisaremos dos pacotes axios e dotenv:

npm install axios
npm install dotenv
Copiar

Agora, crie um arquivo chamado 'index.js' na raiz do nosso gastracker-app e copie o seguinte código nele:

const axios = require("axios");
require("dotenv").config();

const Auth = Buffer.from(
  process.env.INFURA_API_KEY + ":" + process.env.INFURA_API_KEY_SECRET,
).toString("base64");

// The chain ID of the supported network
const chainId = 1;

(async () => {
  try {
    const { data } = await axios.get(
      `https://gas.api.infura.io/networks/${chainId}/suggestedGasFees`,
      {
        headers: {
          Authorization: `Basic ${Auth}`,
        },
      },
    );
    console.log("Suggested gas fees:", data);
  } catch (error) {
    console.log("Server responded with:", error);
  }
})();
Copiar

Em outra janela do terminal, execute o seguinte comando.

node index.js

Você deverá ver o seguinte:

Suggested gas fees: {
  low: {
    suggestedMaxPriorityFeePerGas: '0.05',
    suggestedMaxFeePerGas: '28.501086221',
    minWaitTimeEstimate: 15000,
    maxWaitTimeEstimate: 30000
  },
  medium: {
    suggestedMaxPriorityFeePerGas: '0.1',
    suggestedMaxFeePerGas: '38.508966399',
    minWaitTimeEstimate: 15000,
    maxWaitTimeEstimate: 45000
  },
  high: {
    suggestedMaxPriorityFeePerGas: '0.3',
    suggestedMaxFeePerGas: '48.666846576',
    minWaitTimeEstimate: 15000,
    maxWaitTimeEstimate: 60000
  },
  estimatedBaseFee: '28.451086221',
  networkCongestion: 0.7718,
  latestPriorityFeeRange: [ '0.05', '9.249760902' ],
  historicalPriorityFeeRange: [ '0.023435712', '56.009283908' ],
  historicalBaseFeeRange: [ '19.277073248', '31.361941035' ],
  priorityFeeTrend: 'down',
  baseFeeTrend: 'up'
}
Copiar

Se você observar os dados exibidos no terminal, isso indica que estamos recebendo respostas da API com sucesso. O próximo passo é apresentar esses dados no nosso frontend. Você pode excluir o arquivo index.js agora.

Exibindo dados de gas no frontend

Para estabelecer tipos personalizados para uso em todo o projeto, crie um arquivo chamado 'index.d.ts' no diretório raiz e inclua as seguintes linhas:

interface GasFeeEstimate {
    suggestedMaxPriorityFeePerGas: string;
    suggestedMaxFeePerGas: string;
    minWaitTimeEstimate: number;
    maxWaitTimeEstimate: number;
  }

  interface GasFeesApiResponse {
    low: GasFeeEstimate;
    medium: GasFeeEstimate;
    high: GasFeeEstimate;
    estimatedBaseFee: string;
    networkCongestion: number;
    latestPriorityFeeRange: string[];
    historicalPriorityFeeRange: string[];
    historicalBaseFeeRange: string[];
    priorityFeeTrend: 'up' | 'down';
    baseFeeTrend: 'up' | 'down';
  }
Copiar

Essas declarações de interface TypeScript em um arquivo global definem estruturas para estimativas de taxas de gas e respostas da API. Elas abrangem detalhes como sugestões de taxas, tempos de espera, congestionamento da rede e tendências de taxas para diferentes níveis de prioridade de transação em uma rede blockchain.

Na pasta 'lib', crie um arquivo chamado 'getData.ts' e adicione o seguinte código:

const Auth = Buffer.from(
  process.env["INFURA_API_KEY"] + ":" + process.env["INFURA_API_KEY_SECRET"]
).toString("base64");

// The chain ID of the supported network
const chainId = 1;

export const getData = async () => {
  try {
    const res = await fetch(
      `https://gas.api.infura.io/networks/${chainId}/suggestedGasFees`,
      {
        headers: {
          Authorization: `Basic ${Auth}`,
        },
      }
    );

    const data = await res.json();

    return data as GasFeesApiResponse;
  } catch (error) {
    console.log("Server responded with:", error);
  }
};
Copiar

Esses códigos buscam dados de taxas de gas da Gas API:

  1. Configuração de Autenticação: Cria um Buffer a partir de INFURA_API_KEY e INFURA_API_KEY_SECRET, que são definidos como variáveis de ambiente. Esse Buffer é então convertido em uma string base64 (chamada 'Auth') para autenticação básica nas requisições à API.

  2. Especificação do Chain ID: Define a variável chainId como 1, representando tipicamente a mainnet do Ethereum em contextos de blockchain.

  3. Função getData: Uma função assíncrona projetada para buscar dados de taxas de gas:

  • Utiliza fetch para fazer uma requisição GET ao endpoint da API da Infura, recuperando as taxas de gas sugeridas para o chainId especificado.

  • Define o cabeçalho Authorization na requisição usando o token Auth criado anteriormente.

  • Se bem-sucedida, analisa a resposta como JSON e a retorna como GasFeesApiResponse, alinhando-se à interface previamente definida.

  • Registra quaisquer erros, como problemas de rede ou erros de servidor, no console.

Variabilidade do Chain ID: O chainId pode ser ajustado com base na rede para a qual o app é construído. A Gas API na Infura suporta a maioria das principais redes EVM. Para mais informações sobre redes suportadas, visite a documentação.

Trabalhando na UI

Chegamos agora à parte mais interessante, onde vamos focar na UI para exibir os dados. Vamos navegar até a pasta de componentes e criar um componente chamado 'GasCard.tsx'.

import { getData } from "@/lib/getData";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";

export const GasCard = async () => {
  const data = await getData();

  const renderGasFeeEstimateCard = (
    estimate: GasFeeEstimate,
    title: string
  ) => (
    <Card>
      <CardHeader>
        <CardTitle>{title}</CardTitle>
      </CardHeader>
      <CardContent>
        <p>Max Priority Fee: {estimate.suggestedMaxPriorityFeePerGas}</p>
        <p>Max Fee Per Gas: {estimate.suggestedMaxFeePerGas}</p>
        <p>Min Wait Time: {estimate.minWaitTimeEstimate} seconds</p>
        <p>Max Wait Time: {estimate.maxWaitTimeEstimate} seconds</p>
      </CardContent>
    </Card>
  );

  return (
    <div className="space-y-4">
      <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
        {data?.low &&
          renderGasFeeEstimateCard(data.low, "Low Gas Fee Estimate")}
        {data?.medium &&
          renderGasFeeEstimateCard(data.medium, "Medium Gas Fee Estimate")}
        {data?.high &&
          renderGasFeeEstimateCard(data.high, "High Gas Fee Estimate")}
      </div>
      <Card>
        <CardContent>
          <h2 className="font-semibold">Estimated Base Fee</h2>
          <p>Gas Price: {data?.estimatedBaseFee}</p>
          <h2 className="font-semibold">Network Congestion</h2>
          <p>{data?.networkCongestion}</p>
          <h2 className="font-semibold">Latest Priority Fee Range</h2>
          <p>{data?.latestPriorityFeeRange.join(" - ")}</p>
          <h2 className="font-semibold">Historical Priority Fee Range</h2>
          <p>{data?.historicalPriorityFeeRange.join(" - ")}</p>
          <h2 className="font-semibold">Historical Base Fee Range</h2>
          <p>{data?.historicalBaseFeeRange.join(" - ")}</p>
          <h2 className="font-semibold">Priority Fee Trend</h2>
          <p>{data?.priorityFeeTrend}</p>
          <h2 className="font-semibold">Base Fee Trend</h2>
          <p>{data?.baseFeeTrend}</p>
        </CardContent>
      </Card>
    </div>
  );
};
Copiar

Veja o que aconteceu aqui:

  1. Importações e Busca de Dados:

  • O componente importa a função getData para buscar dados de taxas de gas, juntamente com vários componentes de UI como Card, CardContent, CardHeader e CardTitle, que fazem parte do Shadcn UI que instalamos anteriormente.

  • Dentro do componente GasCard, a função getData é invocada para recuperar os dados de taxas de gas.

  1. Renderização das Estimativas de Taxas de Gas:

  • Uma função chamada renderGasFeeEstimateCard é definida, que renderiza um card de UI para uma estimativa de taxa de gas específica (GasFeeEstimate) e título (title).

  • Essa função constrói um componente Card exibindo detalhes como a taxa de prioridade máxima, taxa máxima por gas e tempos de espera estimados.

  1. Estrutura do Componente:

  • A estrutura JSX do componente GasCard é delineada na instrução return. Ela utiliza um layout de grade para exibir cards para estimativas de taxas de gas baixas, médias e altas, que são exibidas condicionalmente dependendo da disponibilidade dos dados.

  • Um card adicional mostra mais informações como a taxa base estimada, congestionamento da rede, faixas de taxa de prioridade (recentes e históricas) e tendências nas taxas de prioridade e base.

Agora, o único passo restante é importar o GasCard.tsx no arquivo page.tsx. Após isso, todos os dados deverão estar visíveis no nosso frontend.

Comece a usar a Gas API

Utilizar a Gas API na Infura oferece vantagens significativas para desenvolvedores que trabalham com redes compatíveis com EVM. Ela fornece insights em tempo real sobre o mercado de gas em constante variação, permitindo que os usuários tomem decisões bem embasadas sobre suas taxas de transação. Isso é particularmente benéfico para otimizar tanto a velocidade quanto a eficiência de custos das transações.

Este tutorial aborda como começar a usar a GasAPI e criar um App simples de Rastreamento de Gas. Você pode encontrar o código aqui: GasAPI-Template no GitHub.

Mas podemos fazer muito mais coisas interessantes com isso; podemos adicionar formas de atualizar o GasData em determinados intervalos com uma contagem regressiva, e também podemos integrar a GasAPI em qualquer aplicação existente. Recomendo conferir os seguintes recursos:

Documentação da Gas API: Documentação da Gas API da Infura

EventSea: Um Dapp de Eventos full-stack que utiliza a GasAPI de forma criativa: EventSea no GitHub

Bons projetos! 🚀

Traduzido por IA. Pode conter erros. Por favor, verifique sempre as informações.

Avalie a tradução