Cómo crear una app simple de seguimiento de gas con Gas API y Next.js

Aprende a crear una app sencilla de seguimiento de gas usando la API de gas de MetaMask, Next.js y ShadcnUI.

8 min de lectura
Cómo crear una app simple de seguimiento de gas con Gas API y Next.js

'Gas' se refiere a una unidad que mide la cantidad de esfuerzo computacional necesario para ejecutar operaciones, como realizar transacciones o ejecutar smart contracts. Es similar al combustible de un automóvil: necesario para que la red procese y valide las operaciones. Cada transacción en Ethereum requiere una cantidad específica de gas, determinada por su complejidad. Los usuarios establecen un precio de gas en Gwei (1 Gwei = 1 milmillonésima parte de un Ether), que representa la cantidad de Ether que están dispuestos a pagar por unidad de gas.

Comprender los precios del gas es fundamental en las redes blockchain, ya que ayuda a los usuarios a gestionar el costo de sus transacciones. Conocer los precios actuales del gas permite a los usuarios elegir el momento más económico para iniciar una transacción y determinar su velocidad. Estar al tanto de los precios del gas también es esencial para evitar transacciones fallidas, planificar presupuestos, entender la congestión de la red y tomar decisiones de inversión informadas.

La Gas API de MetaMask

La Gas API de MetaMask, disponible a través de Infura, es una herramienta especializada diseñada para proporcionar información en tiempo real sobre los precios del gas en redes compatibles con la Ethereum Virtual Machine (EVM). Funciona como un oráculo, ofreciendo datos actualizados sobre los costos computacionales necesarios para ejecutar operaciones o transacciones en estas redes. La API permite a los desarrolladores crear funciones avanzadas de estimación de gas, lo que puede generar ahorros en las operaciones de transacciones del back-end o mejorar la interfaz de usuario.

En este tutorial, aprenderemos a construir una aplicación Gas Tracker utilizando la Gas API, Next.js y ShadcnUI. Esta aplicación permitirá a los usuarios de dapps acceder a precios de gas recomendados adaptados a las prioridades de sus transacciones, ayudando a garantizar la inclusión eficiente de estas transacciones en un bloque de la blockchain.

Requisitos previos

Configuración de Next.js + ShadcnUI

Primero, asegúrate de tener Node.js instalado en tu máquina. Una vez configurado Node.js, inicia una nueva aplicación Next.js abriendo tu terminal y ejecutando el siguiente comando:

npx create-next-app@latest

Tras ejecutar el comando, no solo aparecerán varios mensajes de configuración, sino que también se generará un nuevo directorio con el nombre de tu proyecto (yo usé gastracker-app), estableciendo así la estructura base de Next.js e instalando las dependencias esenciales. Ahora, accede al directorio de tu proyecto:

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

Navega hasta el directorio de tu nuevo proyecto y activa la aplicación Next.js en modo de desarrollo. Luego puedes explorar tu aplicación accediendo a http://localhost:3000 en tu navegador.

cd gastracker-app
npm run dev
Copiar

Creación de la interfaz de usuario

Para nuestra aplicación, utilizaremos una biblioteca de componentes. Comencemos instalando ShadcnUI:

npx shadcn-ui@latest init

Durante la instalación, se te guiará para configurar el archivo components.json con los siguientes mensajes:

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

Con eso resuelto, instalemos también el componente Card de Shadcn UI:

npx shadcn-ui@latest add card

En este tutorial, nos centraremos en usar el componente Card de Shadcn UI. Para obtener más información sobre estos componentes, visita el sitio web de Shadcn UI. Con el frontend ya configurado, estamos listos para comenzar a trabajar con la Gas API.

En el directorio raíz, crea un archivo llamado .env, donde almacenaremos las siguientes credenciales:

INFURA_API_KEY=
INFURA_API_KEY_SECRET=
Copiar

Asegúrate de obtener el API_KEY y el API_KEY_SECRET desde tu panel de Infura. Es fundamental evitar subir la clave API a GitHub. En el directorio raíz, verifica el archivo .gitignore para confirmar que las líneas necesarias están incluidas.

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

También necesitaremos los paquetes axios y dotenv:

npm install axios
npm install dotenv
Copiar

Ahora, crea un archivo llamado 'index.js' en la raíz de nuestro gastracker-app y copia el siguiente código en él:

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

En otra ventana de terminal, ejecuta el siguiente comando.

node index.js

Deberías ver lo siguiente:

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

Si observas los datos mostrados en la terminal, significa que estamos recibiendo respuestas de la API correctamente. El siguiente paso es presentar estos datos en nuestro frontend. Ahora puedes eliminar el archivo index.js.

Visualización de los datos de gas en el frontend

Para establecer tipos personalizados que se usarán en todo el proyecto, crea un archivo llamado 'index.d.ts' en el directorio raíz e incluye las siguientes líneas:

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

Estas declaraciones de interfaces TypeScript en un archivo global definen estructuras para las estimaciones de tarifas de gas y las respuestas de la API. Incluyen detalles como sugerencias de tarifas, tiempos de espera, congestión de la red y tendencias de tarifas para diferentes niveles de prioridad de transacciones en una red blockchain.

En la carpeta 'lib', crea un archivo llamado 'getData.ts' y añade el siguiente 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

Este código obtiene datos de tarifas de gas desde la Gas API:

  1. Configuración de autenticación: Crea un Buffer a partir de INFURA_API_KEY e INFURA_API_KEY_SECRET, que se establecen como variables de entorno. Este Buffer se convierte en una cadena base64 (llamada 'Auth') para la autenticación básica en las solicitudes a la API.

  2. Especificación del Chain ID: Establece la variable chainId en 1, que generalmente representa la red principal de Ethereum en contextos blockchain.

  3. Función getData: Una función asíncrona diseñada para obtener datos de tarifas de gas:

  • Utiliza fetch para realizar una solicitud GET al endpoint de la API de Infura, recuperando las tarifas de gas sugeridas para el chainId especificado.

  • Establece el encabezado de autorización en la solicitud utilizando el token Auth creado anteriormente.

  • Si tiene éxito, analiza la respuesta como JSON y la devuelve como GasFeesApiResponse, alineándose con la interfaz definida previamente.

  • Registra cualquier error, como problemas de red o errores del servidor, en la consola.

Variabilidad del Chain ID: El chainId puede ajustarse según la red para la que se construya la aplicación. La Gas API en Infura es compatible con la mayoría de las principales redes EVM. Para más información sobre las redes compatibles, visita la documentación.

Trabajando en la UI

Hemos llegado a la parte más emocionante, donde nos centraremos en la UI para mostrar los datos. Naveguemos a la carpeta de componentes y creemos un componente llamado '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

Veamos qué ocurrió aquí:

  1. Importaciones y obtención de datos:

  • El componente importa la función getData para obtener datos de tarifas de gas, junto con varios componentes de UI como Card, CardContent, CardHeader y CardTitle, que forman parte del Shadcn UI que instalamos anteriormente.

  • Dentro del componente GasCard, se invoca la función getData para recuperar los datos de tarifas de gas.

  1. Renderizado de estimaciones de tarifas de gas:

  • Se define una función llamada renderGasFeeEstimateCard, que renderiza una tarjeta de UI para una estimación de tarifa de gas específica (GasFeeEstimate) y un título (title).

  • Esta función construye un componente Card que muestra detalles como la tarifa de prioridad máxima, la tarifa máxima por gas y los tiempos de espera estimados.

  1. Estructura del componente:

  • La estructura JSX del componente GasCard se describe en la declaración return. Utiliza un diseño de cuadrícula para mostrar tarjetas con estimaciones de tarifas de gas bajas, medias y altas, que se muestran condicionalmente según la disponibilidad de los datos.

  • Una tarjeta adicional muestra más información, como la tarifa base estimada, la congestión de la red, los rangos de tarifas de prioridad (recientes e históricos) y las tendencias en las tarifas de prioridad y base.

Ahora, el único paso restante es importar GasCard.tsx en el archivo page.tsx. Tras esto, todos los datos deberían ser visibles en nuestro frontend.

Comienza a usar la Gas API

Utilizar la Gas API en Infura ofrece ventajas significativas para los desarrolladores que trabajan con redes compatibles con EVM. Proporciona información en tiempo real sobre el fluctuante mercado del gas, lo que permite a los usuarios tomar decisiones bien fundamentadas sobre sus tarifas de transacción. Esto es especialmente beneficioso para optimizar tanto la velocidad como la rentabilidad de las transacciones.

Este tutorial explica cómo comenzar con la GasAPI y crear una sencilla aplicación Gas Tracker. Puedes encontrar el código aquí: GasAPI-Template en GitHub.

Pero podemos hacer muchas más cosas interesantes con esto: podemos añadir formas de actualizar los datos de gas en intervalos de tiempo con una cuenta regresiva, y también podemos integrar la GasAPI en cualquier aplicación existente. Te recomiendo consultar los siguientes recursos:

Documentación de la Gas API: Documentación de la Gas API de Infura

EventSea: Una dapp de eventos full-stack que utiliza la GasAPI de forma creativa: EventSea en GitHub

¡Feliz construcción! 🚀

Traducido por IA. Puede contener errores. Por favor, verifique siempre la información.

Califica la traducción