Como implementar o MetaMask SDK com Next.js

Aprenda a integrar um botão 'Connect Wallet' com MetaMask no Next.js. Este tutorial aborda configuração, uso do MetaMask SDK e criação de UI com ShadcnUI para ...

6 min de leitura
Como implementar o MetaMask SDK com Next.js

No web3, uma carteira (wallet) é um aplicativo digital que permite aos usuários interagir com redes blockchain. As carteiras funcionam como uma ponte entre os usuários e o mundo descentralizado do blockchain. Ao contrário dos aplicativos web tradicionais, que utilizam combinações de e-mail e senha ou serviços OAuth para autenticação, os apps web3 autenticam os usuários com base na propriedade de uma carteira e suas chaves privadas associadas. O botão "Connect Wallet" inicia esse processo de autenticação.

Neste tutorial, vamos implementar um botão "Connect Wallet" em um app Next.js que inicia o processo de autenticação com a carteira MetaMask.

Pré-requisitos:

  • Familiaridade com Next.js e React.

  • Node.js e npm/yarn instalados.

  • Extensão MetaMask instalada no seu navegador.

Embora esses sejam alguns pré-requisitos para este tutorial, a melhor forma de aprender é começando e aprendendo ao longo do caminho.

Configurando o projeto Next.js:

Para configurar um projeto Next.js, você precisa ter o Node.js instalado na sua máquina. Com o Node.js instalado, você pode criar um novo aplicativo Next.js abrindo o terminal e executando o seguinte comando:

npx create-next-app@latest

Veremos os seguintes prompts:

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

Esse comando cria uma nova pasta com o nome de projeto especificado, configura a estrutura inicial do Next.js e instala todas as dependências necessárias. Navegue até a sua pasta.

cd next-metamask-template

e execute o seguinte comando npm run dev. Esse comando inicia o aplicativo Next.js em modo de desenvolvimento, e você pode visualizar sua aplicação acessando http://localhost:3000 no seu navegador.

Criando a interface do usuário

Vamos adicionar uma biblioteca de componentes ao nosso app. Vamos instalar o ShadcnUI.

npx shadcn-ui@latest init

Veremos os seguintes prompts para configurar o 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

Da biblioteca de componentes ShadcnUI, utilizaremos dois componentes neste tutorial: Button e Popover.

Também utilizaremos o @metamask/sdk-react. Você pode saber mais sobre ele na documentação do MetaMask.

Vamos instalar o SDK:

npm i @metamask/sdk-react

Vamos criar um novo componente chamado NavBar.tsx e adicionar o botão "Connect Wallet" e o SDK. Inicialmente, nosso componente deve ter a seguinte aparência:

"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

Veja o que fizemos aqui:

1. Hook useSDK: Inicialmente, nosso foco está no hook useSDK, que permite acessar as funcionalidades do MetaMask SDK. Esse hook fornece um objeto SDK para interagir com o MetaMask, um booleano connected para verificar se a carteira está conectada, um booleano connecting para checar o status da conexão e um account para acessar o endereço da conta do usuário.

2. Funções connect e disconnect: A configuração inclui duas funções principais: connect e disconnect. A função connect é uma operação assíncrona que tenta estabelecer uma conexão com a carteira MetaMask usando o SDK. Após uma conexão bem-sucedida, ela atualiza os valores de connected e account do hook useSDK. A função disconnect, por sua vez, é usada para desconectar a carteira invocando sdk.terminate().

3. Elementos de UI: Nossa implementação incorpora dois elementos de UI — um botão e um popover. A renderização do componente muda com base no status da conexão. Quando conectado, exibe um componente Popover mostrando o endereço da conta formatado e uma opção para desconectar. Se não estiver conectado, exibe um botão "Connect Wallet", que fica desabilitado durante uma tentativa de conexão em andamento.

Agora vamos adicionar o código para a 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

Veja o que fizemos aqui:

  1. Variável host: Essa variável determina o endereço do host da janela atual para uso nas opções do SDK. Inclui uma verificação condicional para confirmar se está sendo executada em um ambiente de navegador.

  2. Opções do SDK: São as opções de configuração para o MetaMask SDK, definindo preferências de logging e verificações de instalação, além de incluir metadados sobre o dapp.

  3. Componente NavBar: A NavBar apresenta um link para a página inicial e incorpora o componente ConnectWalletButton. Para fornecer o contexto necessário do MetaMask SDK, ela envolve o ConnectWalletButton com o componente MetaMaskProvider, importado de @metamask/sdk-react.

  • Ícone de carteira: Para obter o ícone da carteira, utilizamos o SVGR, uma ferramenta que converte imagens SVG em componentes React.

Para evitar que o endereço completo da carteira ocupe muito espaço na NavBar, faremos ajustes no arquivo utils.ts dentro da pasta lib. Isso garante que o endereço seja exibido em um formato mais conciso.

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

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

Adicione as seguintes linhas:

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

As funções acima — formatBalance, formatChainAsNum e formatAddress — foram criadas para serem importadas e utilizadas em todo o dApp, garantindo a formatação e exibição consistente dos dados do blockchain para os usuários.

No componente NavBar, vamos importá-las assim:

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

E as utilizamos aqui no botão:

Agora, tudo que resta é importar o NavBar.tsx no nosso componente layout.tsx.

Se executarmos nosso servidor de desenvolvimento, veremos as alterações que fizemos no nosso app.

Conclusão

O MetaMask SDK é realmente conveniente e uma virada de jogo quando se trata de construir DApps. Ele permite que os usuários se conectem facilmente à extensão do navegador MetaMask e ao MetaMask Mobile.

Esta foi uma introdução a como começar com o MetaMask SDK, mas podemos fazer muito mais com ele e utilizá-lo também em aplicações fullstack. Você pode encontrar o código deste projeto neste repositório aqui.

Também recomendo conferir os seguintes recursos:

Bons projetos. 🚀

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

Avalie a tradução