WEB3DEV

Cover image for Um Guia Abrangente para o Desenvolvimento de dApps com ethers.js e web3.js
Fatima Lima
Fatima Lima

Posted on

Um Guia Abrangente para o Desenvolvimento de dApps com ethers.js e web3.js

Image description

Os aplicativos descentralizados (dApps) revolucionaram a forma como interagimos com redes blockchain e contratos inteligentes. Para permitir uma comunicação perfeita com a blockchain Ethereum, os desenvolvedores contam com bibliotecas especializadas como ethers.js e web3.js. Neste artigo, explorarei as funcionalidades, as diferenças e o uso prático dessas duas bibliotecas JavaScript populares para o desenvolvimento de dApps. Seja você um desenvolvedor experiente ou um novato no espaço blockchain, este guia tem como objetivo fornecer a você uma compreensão abrangente do ethers.js e do web3.js e como aproveitar o poder deles para seu próximo projeto de dApp.

Compreendendo o ethers.js

O Ethers.js surgiu como uma biblioteca avançada projetada para interagir com a blockchain Ethereum. Seus principais recursos incluem simplicidade, velocidade e _type safety _(nunca converte valores explicitamente ou implicitamente de um tipo para outro). Criado com TypeScript, o ethers.js oferece uma API intuitiva para gerenciar contas, lidar com transações e interagir com contratos inteligentes. Vamos nos aprofundar em algumas das principais funcionalidades:

Image description

Como Ethers.js vai ser usado

Gerenciamento da Conta

O Ethers.js facilita a geração de carteiras Ethereum, o acesso aos detalhes da conta e a assinatura de transações com segurança. Veja abaixo um exemplo de como criar uma carteira Ethereum usando o ethers.js:

    const { ethers } = require("ethers");

    const wallet = ethers.Wallet.createRandom();
    console.log("Address:", wallet.address);
    console.log("Private Key:", wallet.privateKey);
Enter fullscreen mode Exit fullscreen mode

Processamento de Transações

O envio e o recebimento de transações é um aspecto fundamental do desenvolvimento de dApps. O Ethers.js simplifica esse processo, fornecendo aos desenvolvedores as ferramentas para criar e transmitir transações sem problemas. Veja a seguir como enviar ether de uma conta para outra:

    const { ethers } = require("ethers");

    const privateKey = "YOUR_PRIVATE_KEY";
    const provider = ethers.getDefaultProvider("rinkeby");
    const wallet = new ethers.Wallet(privateKey, provider);

    const recipientAddress = "RECIPIENT_ADDRESS";
    const transaction = {
     to: recipientAddress,
     value: ethers.utils.parseEther("1.0"), // Sending 1 ether
    };

    (async () => {
     const tx = await wallet.sendTransaction(transaction);
     console.log("Transaction hash:", tx.hash);
    })();
Enter fullscreen mode Exit fullscreen mode

Interação de Contratos Inteligentes

O Ethers.js aproveita as interfaces binárias de aplicativos (ABIs) de contratos inteligentes para interagir com os contratos inteligentes Ethereum. Abaixo está um exemplo de implantação de um contrato de token ERC20 simples e de interação com ele usando o ethers.js:

    const { ethers } = require("ethers");
    const erc20ABI = require("./path/to/erc20ABI.json");

    const privateKey = "YOUR_PRIVATE_KEY";
    const provider = ethers.getDefaultProvider("rinkeby");
    const wallet = new ethers.Wallet(privateKey, provider);

    const contractAddress = "CONTRACT_ADDRESS";
    const erc20Contract = new ethers.Contract(contractAddress, erc20ABI, wallet);

    // Obtém o saldo de uma conta
    (async () => {
     const accountAddress = "ACCOUNT_ADDRESS";
     const balance = await erc20Contract.balanceOf(accountAddress);
     console.log("Balance:", balance.toString());
    })();
Enter fullscreen mode Exit fullscreen mode

Compreendendo o web3.js

A Web3.js é outra biblioteca amplamente usada para o desenvolvimento de dApp Ethereum, endossada pela própria Fundação Ethereum. Sua versatilidade e o amplo suporte da comunidade fazem dela uma escolha popular entre os desenvolvedores. Vamos nos aprofundar em suas principais funcionalidades:

Image description

Como o web3.js vai usar<>/center

Gerenciamento da Conta

Semelhante ao ethers.js, o web3.js facilita a criação de contas, o acesso e a assinatura de transações. Veja abaixo um exemplo de como criar uma conta Ethereum usando o web3.js:

    const Web3 = require("web3");

    const providerUrl = "https://rinkeby.infura.io/v3/YOUR_INFURA_API_KEY";
    const web3 = new Web3(providerUrl);

    const account = web3.eth.accounts.create();
    console.log("Address:", account.address);
    console.log("Private Key:", account.privateKey);
Enter fullscreen mode Exit fullscreen mode

Processamento de Transações

O Web3.js fornece uma interface JSON-RPC para o processamento de transações, permitindo que os desenvolvedores criem e executem transações com facilidade. Veja abaixo um exemplo de envio de ether de uma conta para outra usando o web3.js:

    const Web3 = require("web3");

    const providerUrl = "https://rinkeby.infura.io/v3/YOUR_INFURA_API_KEY";
    const web3 = new Web3(providerUrl);

    const privateKey = "YOUR_PRIVATE_KEY";
    const senderAddress = "SENDER_ADDRESS";
    const recipientAddress = "RECIPIENT_ADDRESS";

    web3.eth.accounts.wallet.add(privateKey);
    const tx = {
     from: senderAddress,
     to: recipientAddress,
     value: web3.utils.toWei("1", "ether"),
    };

    web3.eth.sendTransaction(tx)
     .on("transactionHash", (hash) => {
       console.log("Transaction hash:", hash);
     })
     .on("receipt", (receipt) => {
       console.log("Transaction receipt:", receipt);
     });
Enter fullscreen mode Exit fullscreen mode

Interação de Contratos Inteligentes

A interação com os contratos inteligentes da Ethereum é muito fácil com o web3.js. Abaixo está um exemplo de configuração de um objeto de contrato, chamando métodos de contrato e recebendo eventos emitidos pelo contrato:

    const Web3 = require("web3");
    const contractABI = require("./path/to/contractABI.json");

    const providerUrl = "https://rinkeby.infura.io/v3/YOUR_INFURA_API_KEY";
    const web3 = new Web3(providerUrl);

    const contractAddress = "CONTRACT_ADDRESS";
    const contractInstance = new web3.eth.Contract(contractABI, contractAddress);

    // Chama um método de contrato
    (async () => {
     const result = await contractInstance.methods.someMethod().call();
     console.log("Result:", result);
    })();

    // Ouve os eventos do contrato
    contractInstance.events.SomeEvent()
     .on("data", (event) => {
       console.log("Event data:", event.returnValues);
     })
     .on("error", (error) => {
       console.error("Error:", error);
     });
Enter fullscreen mode Exit fullscreen mode

Comparando o ethers.js e o web3.js

Tanto o ethers.js quanto o web3.js têm seus pontos fortes e casos de uso, o que os torna ferramentas valiosas para o desenvolvimento de dApps. Vamos explorar os principais fatores a serem considerados ao comparar as duas bibliotecas.

Type Safety e Projeto API:

O Ethers.js se destaca com seu suporte ao TypeScript, oferecendo type safety aprimorado e integridade de código melhorada. Para os desenvolvedores familiarizados com o TypeScript, o ethers.js oferece uma experiência de desenvolvimento mais estruturada e robusta. Por outro lado, o web3.js não oferece suporte ao TypeScript, mas sua API baseada em JavaScript permanece mais familiar para os desenvolvedores sem experiência prévia com o TypeScript.

Suporte da Comunidade e Documentação:

O web3.js conta com amplo apoio da comunidade devido ao seu endosso pela Fundação Ethereum e à sua ampla adoção. Como resultado, o web3.js tem uma abundância de recursos, tutoriais e projetos orientados pela comunidade. No entanto, o ethers.js está ganhando popularidade e tem uma comunidade ativa, com uma documentação oficial bem mantida e um crescente conteúdo contribuído pela comunidade.

Tamanho e Performance:

O Ethers.js é conhecido por seu tamanho pequeno e performance eficiente, o que o torna uma excelente opção para aplicativos em que o mínimo de espaço ocupado e o desempenho otimizado são cruciais. Em contrapartida, o web3.js é uma biblioteca mais substancial com funcionalidades adicionais, o que pode afetar a performance em determinados cenários. Os desenvolvedores precisam pesar as compensações entre os recursos e o desempenho ao fazer sua escolha.

Escolhendo a Biblioteca Certa para o dApp

A escolha da biblioteca certa para seu dApp depende de vários fatores. Considere os seguintes aspectos para tomar uma decisão fundamentada:

Complexidade do Projeto:

Para dApps relativamente simples, o ethers.js ou o web3.js podem ser adequados. No entanto, para projetos mais complexos que exigem verificação robusta de tipos e uma abordagem de desenvolvimento estruturada, o ethers.js pode ser a escolha mais adequada. Por outro lado, a vasta comunidade e os diversos casos de uso do web3.js podem ser benéficos para dApps ambiciosos e voltados para a comunidade.

Familiaridade do Desenvolvedor:

Considere o conjunto de habilidades e a familiaridade do seu time de desenvolvimento. Se a sua equipe já for proficiente em TypeScript e valorizar a type safety, o ethers.js poderá se alinhar bem à sua experiência. Por outro lado, o web3.js pode ser preferido se o seu time estiver mais confortável com o JavaScript tradicional e tiver experiência anterior com a biblioteca.

Requisitos de Desempenho:

Para aplicativos em que o desempenho é uma prioridade máxima, o tamanho pequeno e o desempenho otimizado do ethers.js podem ser a melhor opção. Por outro lado, os recursos adicionais e o ecossistema maior do web3.js podem ser vantajosos para projetos em que a performance não é a principal preocupação.

Exemplo Prático: Construindo um dApp Simples

Vamos criar um dApp de votação simplificado usando ethers.js ou web3.js. O dApp permitirá que os usuários votem em sua opção favorita e os votos serão registrados na blockchain Ethereum usando um contrato inteligente.

Pilha (stack) de Código Front-end:

▪️ HTML: O arquivo HTML para criar a estrutura básica da interface de votação.

▪️ CSS: O arquivo CSS para estilizar a interface de votação.

▪️ JavaScript: O arquivo JavaScript para interagir com o contrato inteligente Ethereum usando ou o either ethers.js ou o web3.js.

HTML (index.html):

    <!DOCTYPE html>
    <html>
    <head>
     <title>Simple Voting dApp</title>
     <link rel="stylesheet" href="styles.css">
    </head>
    <body>
     <div class="container">
       <h1>Vote for Your Favorite Option</h1>
       <div class="options">
         <button id="option1">Option 1</button>
         <button id="option2">Option 2</button>
       </div>
       <div class="result">
         <p>Option 1 Votes: <span id="votesOption1">0</span></p>
         <p>Option 2 Votes: <span id="votesOption2">0</span></p>
       </div>
     </div>
     <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/web3.min.js"></script>
     <script src="app.js"></script>
    </body>
    </html>
Enter fullscreen mode Exit fullscreen mode

CSS (styles.css):

    body {
     font-family: Arial, sans-serif;
     background-color: #f7f7f7;
     margin: 0;
     padding: 0;
    }

    .container {
     max-width: 600px;
     margin: 0 auto;
     padding: 20px;
     background-color: #ffffff;
     box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    }

    h1 {
     text-align: center;
    }

    .options {
     display: flex;
     justify-content: center;
     gap: 20px;
    }

    button {
     padding: 10px 20px;
     font-size: 16px;
     cursor: pointer;
    }

    .result {
     margin-top: 20px;
    }

    .result p {
     margin: 0;
    }

    span {
     font-weight: bold;
    }
Enter fullscreen mode Exit fullscreen mode

JavaScript (app.js):

    const providerUrl = "https://rinkeby.infura.io/v3/YOUR_INFURA_API_KEY";
    const web3 = new Web3(providerUrl);

    const contractABI = [...]; // Substituir pela ABI de seu contrato inteligente implantado
    const contractAddress = "CONTRACT_ADDRESS"; // Substitui pelo endereço de seu contrato inteligente
    const votingContract = new web3.eth.Contract(contractABI, contractAddress);

    const option1Button = document.getElementById("option1");
    const option2Button = document.getElementById("option2");
    const votesOption1Element = document.getElementById("votesOption1");
    const votesOption2Element = document.getElementById("votesOption2");

    option1Button.addEventListener("click", async () => {
     await vote(1);
    });

    option2Button.addEventListener("click", async () => {
     await vote(2);
    });

    async function vote(option) {
     const accounts = await web3.eth.getAccounts();
     const sender = accounts[0];

     try {
       const result = await votingContract.methods.vote(option).send({ from: sender });
       console.log("Transaction hash:", result.transactionHash);
       updateVoteCounts();
     } catch (error) {
       console.error("Vote error:", error);
     }
    }

    async function updateVoteCounts() {
     const option1Votes = await votingContract.methods.getVoteCount(1).call();
     const option2Votes = await votingContract.methods.getVoteCount(2).call();

     votesOption1Element.textContent = option1Votes;
     votesOption2Element.textContent = option2Votes;
    }
Enter fullscreen mode Exit fullscreen mode

Pilha de Código Backend:

▪️ Solidity: O código do contrato inteligente Solidity para o mecanismo de votação.

Solidity (Voting.sol):

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;

    contract Voting {
       mapping(uint256 => uint256) public voteCounts;

       function vote(uint256 option) public {
           require(option == 1 || option == 2, "Invalid option");
           voteCounts[option]++;
       }

       function getVoteCount(uint256 option) public view returns (uint256) {
           require(option == 1 || option == 2, "Invalid option");
           return voteCounts[option];
       }
    }
Enter fullscreen mode Exit fullscreen mode

Implantar o Contrato Inteligente:

👣 Compile o contrato inteligente do Solidity (Voting.sol) usando o compilador Solidity.

👣 Implante o contrato inteligente compilado na rede de teste Rinkeby usando Remix, Truffle ou Hardhat.

👣 Obtenha o endereço do contrato e a ABI após a implantação.

Substitua "YOUR_INFURA_API_KEY" por sua chave de API Infura real e "[...]" no código JavaScript pela ABI real de seu contrato inteligente implantado.

Ethers.js e web3.js são ferramentas valiosas para o desenvolvimento de dApps Ethereum, cada uma com seus pontos fortes e vantagens. Ao compreender suas funcionalidades e comparar seus recursos, você pode tomar uma decisão fundamentada ao selecionar a biblioteca que melhor atende às necessidades específicas do seu dApp. Quer você priorize a type safety, o suporte da comunidade ou o desempenho, ambas as bibliotecas oferecem soluções poderosas para a criação de aplicativos descentralizados interessantes e inovadores.

Esse artigo foi escrito por Harith D. Jayawardhane e traduzido por Fátima Lima. O original pode ser lido aqui.

Latest comments (0)