A web3 está aí e cada vez mais as empresas estão querendo criar funcionalidades e até sistemas inteiros baseados na blockchain. Desta forma, para acompanhar esta tendência é importante que os programadores aprendam como implementar isto e felizmente a esta altura já existem muitas formas de fazer este tipo de integração, em especial com as blockchains baseadas em Ethereum ou EVM-compatible.
No tutorial de hoje eu vou ensinar como escrever aplicações descentralizadas (dapps) com ReactJS que se conectam à blockchain e fazem consultas e transações nela utilizando a biblioteca Wagmi e a carteira MetaMask.
Se preferir, pode assistir ao vídeo abaixo ao invés de ler.
Então vamos lá!
#1 – Setup
Neste tutorial vamos usar ReactJS e ele não é indicado para quem nunca programou React na vida. Neste tutorial ensino como dar os primeiros passos com esta tecnologia, caso precise de uma introdução. Vamos criar o projeto juntos à seguir, então não se preocupe em fazê-lo sozinho. É necessário conhecimento básico de blockchain também, para entender o que vamos fazer aqui, algo que você pode conseguir nas primeiras aulas dessa playlist.
Além de ter alguma experiência com React, o próximo passo é ter uma carteira de criptomoedas, já que para se comunicar com a blockchain é obrigatório ter uma. Como vamos programar para blockchains EVM, tem de ser uma carteira compatível com a mesma e eu recomendo a MetaMask. O vídeo abaixo ensina o que é e como criar a sua, gratuitamente.

A MetaMask vem por padrão configurada para a rede Mainnet da Ethereum, o que não é muito indicado para desenvolvimento. Indo no menu no topo dela você pode ir em Redes e usar a opção “mostrar redes de teste” para habilitar o aparecimento da rede testnet Sepolia, que é a que vamos usar aqui.
Mesmo sendo uma rede de testes você vai precisar de saldo em ETH para poder fazer transações para ela, então recomendo que use este Faucet PoW para ganhar algumas moedas. Basta conectar a sua carteira, colocar a minerar e em minutos terá saldo para usar na rede Sepolia.
Agora sim, temos todo o necessário para começar a programar, então vamos criar nosso projeto. O Wagmi pode ser instalado em qualquer projeto React, mas é muito mais fácil quando criamos um projeto do zero usar o utilitário deles com o comando abaixo.
|
1 2 3 |
npm create wagmi@latest |
O nome do meu projeto será wagmi-react e o template será com Vite. Todo o restante do setup de dependências, TypeScript e estrutura inicial fica por conta do utilitário. A biblioteca Wagmi fornece uma série de hooks React que facilitam enormemente nossa vida quando o assunto é criar o frontend de dapps web3. Ela usa o @wagmi/connectors para se conectar às carteiras mais populares do mercado e o Viem como biblioteca para comunicação com a blockchain, tudo isso com o mais alto nível de suporte a TypeScript e os recursos de fetch/caching/refetch/etc do React Query, se tornando a solução mais profissional atualmente para front web3.
O Wagmi adota uma abordagem baseada em componentes por padrão. Então a primeira coisa que recomendo é a criação de um componente com o código inicial de conexão que ele criou pra gente. Crie um arquivo Connection.tsx e mova pra ele TODO o conteúdo do App.tsx, apenas trocando o nome da função App() para Connection(). Já no App.tsx, subtitua pelo seguinte código, que apenas usa o referido componente.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import Connection from "./Connection" function App() { return ( <> <Connection /> </> ) } export default App |
Quando terminar esse setup, pode seguir as instruções do terminal para colocar o projeto para rodar, que já contará com o context provider do Wagmi no seu main.tsx configurado para as redes Sepolia e Ethereum Mainnet e uma interface com a funcionalidade de conectar na MetaMask. É interessante gastar alguns minutos dando uma olhada em tudo que foi criado para entender principalmente as configurações. Por exemplo, os RPC Nodes configurados no wagmi.ts são públicos, logo não são ideais para dapps profissionais, situação em que recomendo a Infura.

Agora que terminamos o setup podemos começar a programar.
#2 – Gerenciando Conexão
O exemplo inicial do Wagmi é de conexão e desconexão de carteira. Antes de fazer funcionalidades autorais, vou propor alguns ajustes pontuais no Connection.tsx, para ele ter duas aparências distintas (conectado/não conectado) e menos informações na página também. Essas alterações vão servir como gancho também para eu explicar alguns conceitos importantes.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
import { useConnect, useConnection, useConnectors, useDisconnect } from 'wagmi' function Connection() { const connection = useConnection() const { connect, status, error } = useConnect() const connectors = useConnectors() const { disconnect } = useDisconnect() return ( <> <div> <h2>Connection</h2> { connection.status === 'connected' ? ( <div> <strong>Address:</strong> {JSON.stringify(connection.addresses)} <button type="button" onClick={() => disconnect()}> Disconnect </button> </div> ) : <div> {connectors.map((connector) => ( <button key={connector.uid} onClick={() => connect({ connector })} type="button" > {connector.name} </button> ))} </div> } <div>{error?.message}</div> </div> </> ) } export default Connection |
O Wagmi é todo baseado em React Hooks, então temos nesse exemplo:
- useConnection: hook que traz um objeto com informações da conexão com a carteira, como o status (“connected”);
- useConnect: hook que traz um objeto com função para conectar, status e error de conexão;
- useConnectors: hook que traz o array de conectores configurados no seu projeto (wagmi.ts);
- useDisconnect: hook que traz objeto com função para desconectar;
Dito isso, neste componente acima eu me baseio no connection.status para exibir endereço e botão de desconectar ou então o botão de conexão. Em ambos os casos, fica sempre exposto uma possível mensagem de erro. Sobre as ações de conexão e desconexão em si, a disconnect() não exige parâmetro algum, já a connect precisa que seja passado o connector para que a solicitação de permissão seja feita corretamente para a carteira.
Recomendo que teste tanto a conexão quanto a desconexão, para entender o fluxo e garantir que esteja funcionando.
#3 – Saldo ETH
Após garantir a funcionalidade de gestão da conexão, as primeiras coisas que você deve aprender é como ver o saldo da sua carteira e como transferir fundos dela para outra carteira. Crie um arquivo Balance.tsx para programarmos mais este componente. Considerando que estamos programando para redes ETH, tanto o saldo quanto a transferência dizem respeito a essa moeda pois é a nativa da rede. Futuramente quero trazer aqui pro site tutoriais ensinando a interagir com smart contracts.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import { useAccount, useBalance } from 'wagmi' import { formatUnits } from 'viem' export function Balance() { const { address, isConnected } = useAccount() const { data, status } = useBalance({ address }) if (!isConnected) return <div>Wallet not connected</div> if (status === 'pending') return <div>Loading balance...</div> return ( <div> <strong>Balance:</strong> {data ? formatUnits(data.value, data.decimals) : "0"} {data?.symbol} </div> ) } |
Aqui usamos mais dois hooks novos do Wagmi:
- useAccount: retorna o endereço da carteira conectado e se ela está atualmente conectada ou não;
- useBalance: retorna o saldo do endereço fornecido, na moeda nativa da rede e o status dessa query de saldo;
Com essas informações podemos exibir o estado da consulta no componente e, quando tudo estiver ok, o saldo formatado com a ajuda do formatUnits do Viem. O componente em si é bem tranquilo, incorpore ele no App.tsx e terá como resultado algo parecido com abaixo.

Agora vamos fazer algo mais elaborado, uma transferência!
#4 – Transferência ETH
Além de ver saldo, outra tarefa muito recorrente é a transferência de fundos. Como estamos em uma rede ETH, a transferência é realizada sobre a moeda nativa, ou seja, ETH na rede Ethereum/Sepolia. Para que uma transferência ocorra é necessário enviar uma transação para a rede, assinada pela carteira que vai enviar os fundos.
Antes de fazer esta transferência é importante que você tenha uma segunda conta configurada para a mesma blockchain para poder fazer o teste. Você pode fazer isso facilmente na própria interface da MetaMask indo na sua conta no canto superior direito e escolhendo a opção “Add Account” como mostrado na imagem abaixo.

Agora vamos criar mais um componente, o Transfer.tsx, onde aprenderemos sobre uma série de outros hooks do Wagmi. Primeiro os imports, que explicarei mais à frente, quando usarmos eles.
|
1 2 3 4 5 |
import { useState } from 'react' import { useAccount, useSendTransaction, useWaitForTransactionReceipt } from 'wagmi' import { parseEther, isAddress } from 'viem' |
Dentro da função do componente (Transfer), vamos inicializar os hooks como abaixo.
|
1 2 3 4 5 6 7 8 9 |
const { isConnected } = useAccount() const [to, setTo] = useState('') const [amount, setAmount] = useState('') const { data: hash, isPending, sendTransaction, error } = useSendTransaction() const { isLoading, isSuccess } = useWaitForTransactionReceipt({ hash }) |
- useAccount: já usamos antes, aqui quero apenas saber se o usuário já está conectado com sua carteira ou não;
- useState: para armazenarmos as informações do to (destinatário da transferência) e da amount (quantia a ser transferida);
- useSendTransaction: hook que inicializa um objeto com o hash da transação (data), função de envio da transação (sendTransaction) e informações de status (isPending e error);
- useWaitForTransactionReceipt: hook para monitorar o progresso de uma transação informada (hash) através de variáveis de status;
Com esses hooks configurados, vamos criar o TSX do componente, onde teremos um formulário simples com os campos para destinatário e quantia, além do botão para envio da transação e campos para dar informações sobre o progresso.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
return ( <div style={{ display: 'flex', flexDirection: 'column', gap: 8, maxWidth: 300 }}> <h2>Transfer ETH</h2> {!isConnected && <div>First connect your wallet.</div>} <input type="text" placeholder="0xTarget..." value={to} onChange={(e) => setTo(e.target.value)} /> <input type="number" placeholder="ETH Value" value={amount} onChange={(e) => setAmount(e.target.value)} /> <button onClick={btnTransferClick} disabled={isPending || !isConnected}> {isPending ? 'Sending...' : 'Send ETH'} </button> {error && <div style={{ color: 'red' }}>Error: {error.message}</div>} {isLoading && <div>Confirming transaction...</div>} {isSuccess && <div>Transaction confirmed! 🎉 Hash: {hash}</div>} </div> ) |
A construção da interface não tem grandes novidades para quem já está acostumado com ReactJS. Os inputs são controlados pelos states, enquanto que o click do botão vai dispara a função abaixo.
|
1 2 3 4 5 6 7 8 9 10 11 12 |
function btnTransferClick() { if (!isConnected) return alert('Wallet not connected.') if (!isAddress(to)) return alert('Invalid address.') if (!amount || Number(amount) <= 0) return alert('Invalid amount.') sendTransaction({ to, value: parseEther(amount), }) } |
Os mesmos objetos de status que populam alguns campos de informação no front servem como validação no click do botão, incluindo uma validação específica no endereço do destinatário com com a função isAddress do Viem. Tudo estando certo, basta chamar a função sendTransaction passando o to e o value (convertido para wei com o parseEther do Viem) que a MetaMask irá disparar a janela pedindo autorização e efetuando a mesma.
O resultado final você confere abaixo.

A seguir, recomendo estudar como conectar seu front a smart contracts, o que ensino neste tutorial.
Até a próxima!
Olá, tudo bem?
O que você achou deste conteúdo? Conte nos comentários.



