Cómo implementar MetaMask SDK con Next.js

Aprende a integrar un botón 'Connect Wallet' con MetaMask en Next.js. Este tutorial cubre la configuración, el uso del SDK de MetaMask y la creación de UI con ShadcnUI para ...

6 min de lectura
Cómo implementar MetaMask SDK con Next.js

En web3, una wallet (billetera) es una aplicación digital que permite a los usuarios interactuar con redes blockchain. Las wallets actúan como puente entre los usuarios y el mundo descentralizado de la blockchain. A diferencia de las aplicaciones web tradicionales que utilizan combinaciones de correo electrónico y contraseña o servicios OAuth para la autenticación, las aplicaciones web3 autentican a los usuarios basándose en la titularidad de una wallet y sus claves privadas asociadas. El botón "Connect Wallet" inicia este proceso de autenticación.

En este tutorial, implementaremos un botón "Connect Wallet" en una aplicación Next.js que inicia el proceso de autenticación con la wallet de MetaMask.

Requisitos previos:

  • Familiaridad con Next.js y React.

  • Node.js y npm/yarn instalados.

  • Extensión de MetaMask instalada en tu navegador.

Aunque estos son algunos requisitos previos para este tutorial, la mejor manera de aprender es comenzar y aprender en el camino.

Configuración del proyecto Next.js:

Para configurar un proyecto Next.js, necesitas tener Node.js instalado en tu máquina. Una vez instalado Node.js, puedes crear una nueva aplicación Next.js abriendo tu terminal y ejecutando el siguiente comando:

npx create-next-app@latest

Veremos los siguientes mensajes:

npx create-next-app@latest
✔ What is your project named? … next-metamask-template
✔ 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

Este comando crea una nueva carpeta con el nombre de proyecto especificado, configura la estructura inicial de Next.js e instala todas las dependencias necesarias. Navega hasta tu carpeta.

cd next-metamask-template

y ejecuta el siguiente comando npm run dev. Este comando inicia la aplicación Next.js en modo de desarrollo y puedes ver tu aplicación accediendo a http://localhost:3000 en tu navegador web.

Creación de la interfaz de usuario

Añadiremos una biblioteca de componentes a nuestra aplicación. Procedamos a instalar ShadcnUI.

npx shadcn-ui@latest init

Veremos los siguientes mensajes para configurar components.json:

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

De la biblioteca de componentes de ShadcnUI, utilizaremos dos componentes para este tutorial: Button y Popover.

También utilizaremos @metamask/sdk-react. Puedes obtener más información en la documentación de MetaMask.

Instalemos el SDK:

npm i @metamask/sdk-react

Crearemos un nuevo componente llamado NavBar.tsx y añadiremos el botón "Connect Wallet" y el SDK. Nuestro componente debería verse así en un principio:

"use client";

import Link from "next/link";

import WalletIcon from "../public/icons/WalletIcon";

import { Button } from "./ui/button";

import { useSDK, MetaMaskProvider } from "@metamask/sdk-react";
import { formatAddress } from "../lib/utils";
import {
  Popover,
  PopoverTrigger,
  PopoverContent,
} from "@/components/ui/popover";

export const ConnectWalletButton = () => {
  const { sdk, connected, connecting, account } = useSDK();

  const connect = async () => {
    try {
      await sdk?.connect();
    } catch (err) {
      console.warn(`No accounts found`, err);
    }
  };

  const disconnect = () => {
    if (sdk) {
      sdk.terminate();
    }
  };

  return (
    <div className="relative">
      {connected ? (
        <Popover>
          <PopoverTrigger>
            <Button>{formatAddress(account)}</Button>
          </PopoverTrigger>
          <PopoverContent className="mt-2 w-44 bg-gray-100 border rounded-md shadow-lg right-0 z-10 top-10">
            
              Disconnect
            
          </PopoverContent>
        </Popover>
      ) : (
        <Button disabled={connecting} onClick={connect}>
          <WalletIcon className="mr-2 h-4 w-4" /> Connect Wallet
        </Button>
      )}
    </div>
  );
};
Copiar

Veamos qué hicimos aquí:

1. Hook useSDK: Inicialmente, nos centramos en el hook useSDK, que permite acceder a las funcionalidades del SDK de MetaMask. Este hook proporciona un objeto SDK para interactuar con MetaMask, un booleano connected para verificar si la wallet está conectada, un booleano connecting para comprobar el estado de la conexión y un account para acceder a la dirección de la cuenta del usuario.

2. Funciones de conexión y desconexión: La configuración incluye dos funciones clave: connect y disconnect. La función connect es una operación asíncrona que intenta establecer una conexión con la wallet de MetaMask mediante el SDK. Tras una conexión exitosa, actualiza los valores de connected y account del hook useSDK. La función disconnect, por su parte, se utiliza para desconectar la wallet invocando sdk.terminate().

3. Elementos de la interfaz: Nuestra implementación incorpora dos elementos de interfaz: un botón y un popover. El renderizado del componente cambia según el estado de la conexión. Cuando está conectado, muestra un componente Popover con la dirección de cuenta formateada y una opción para desconectarse. Si no está conectado, muestra un botón "Connect Wallet" que se deshabilita durante un intento de conexión en curso.

Ahora añadamos el código para el NavBar:

export const NavBar = () => {
  const host =
    typeof window !== "undefined" ? window.location.host : "defaultHost";

  const sdkOptions = {
    logging: { developerMode: false },
    checkInstallationImmediately: false,
    dappMetadata: {
      name: "Next-Metamask-Boilerplate",
      url: host, // using the host constant defined above
    },
  };

  return (
    <nav className="flex items-center justify-between max-w-screen-xl px-6 mx-auto py-7 rounded-xl">
      <Link href="/" className="flex gap-1 px-6">
        <span className="hidden text-2xl font-bold sm:block">
          <span className="text-gray-900">Template</span>
        </span>
      </Link>
      <div className="flex gap-4 px-6">
        <MetaMaskProvider debug={false} sdkOptions={sdkOptions}>
          <ConnectWalletButton />
        </MetaMaskProvider>
      </div>
    </nav>
  );
};

export default NavBar;
Copiar

Veamos qué hicimos aquí:

  1. Variable host: Esta variable determina la dirección del host de la ventana actual para su uso en las opciones del SDK. Incluye una verificación condicional para comprobar si se está ejecutando en un entorno de navegador.

  2. Opciones del SDK: Son las opciones de configuración del SDK de MetaMask, que establecen preferencias para el registro y las comprobaciones de instalación, e incluyen metadatos sobre la dapp.

  3. Componente NavBar: El NavBar incluye un enlace a la página de inicio e incorpora el componente ConnectWalletButton. Para proporcionar el contexto necesario del SDK de MetaMask, envuelve el ConnectWalletButton con el componente MetaMaskProvider, que se importa desde @metamask/sdk-react.

  • Ícono de wallet: Para obtener el ícono de la wallet, utilizamos SVGR, una herramienta que convierte imágenes SVG en componentes de React.

Para evitar que la dirección completa de la wallet ocupe demasiado espacio en el NavBar, realizaremos ajustes en el archivo utils.ts dentro de la carpeta lib. Esto garantiza que la dirección se muestre en un formato más conciso.

import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
Copiar

Añade las siguientes líneas:

export const formatBalance = (rawBalance: string) => {
  const balance = (parseInt(rawBalance) / 1000000000000000000).toFixed(2);
  return balance;
};

export const formatChainAsNum = (chainIdHex: string) => {
  const chainIdNum = parseInt(chainIdHex);
  return chainIdNum;
};

export const formatAddress = (addr: string | undefined) => {
  return `${addr?.substring(0, 8)}...`;
};
Copiar

Las funciones anteriores — formatBalance, formatChainAsNum y formatAddress — están diseñadas para ser importadas y utilizadas en toda una dApp con el fin de formatear y mostrar datos de blockchain a los usuarios de manera consistente.

En el componente NavBar lo importaremos así:

import { formatAddress } from "../lib/utils";

Y lo utilizamos aquí en el botón:

Ahora solo queda importar NavBar.tsx en nuestro componente layout.tsx.

Si ejecutamos nuestro servidor de desarrollo, veremos los cambios que hemos realizado en nuestra aplicación.

Conclusión

El SDK de MetaMask es verdaderamente conveniente y un cambio de paradigma a la hora de construir DApps. Permite a los usuarios conectarse fácilmente a la extensión de navegador de MetaMask y a MetaMask Mobile.

Esta fue una introducción a cómo comenzar con el SDK de MetaMask, pero podemos hacer mucho más con él y también utilizarlo en aplicaciones fullstack. Puedes encontrar el código de este proyecto en este repositorio aquí.

También recomiendo consultar los siguientes recursos:

¡Feliz construcción! 🚀

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

Califica la traducción