WEB3DEV

Cover image for Como Usar o ChatGPT para Construir um Dapp Full Stack
Banana Labs
Banana Labs

Posted on

Como Usar o ChatGPT para Construir um Dapp Full Stack

capa

O ChatGPT não pode construir um dapp por si só, mas pode ajudar você a construir o seu! Aprenda como fazer isso com Infura, MetaMask e Truffle.

Nas partes um e dois da série Infura-ChatGPT, você aprendeu como o ChatGPT pode ajudar no desenvolvimento geral de contratos inteligentes, bem como usar essa útil ferramenta de IA para criar NFTs.

Na terceira e última parte desta série, vou mostrar como usar o ChatGPT, MetaMask, Infura e Truffle para criar e lançar um dapp na Ethereum. Vamos usar o ChatGPT para gerar a ideia do que nosso dapp deve ser – e, em seguida, realizar alguma engenharia de prompt para que o ChatGPT auxilie em todos os aspectos do desenvolvimento.

Usar a IA para o desenvolvimento de dapps é uma nova e empolgante oportunidade que o ChatGPT possibilitou, mas isso requer algumas precauções. Confira esse aviso legal da segunda parte.

Passo 1: Criar uma conta na OpenAI

Vamos começar criando nossa conta no ChatGPT. O ChatGPT é uma ferramenta gratuita oferecida pela OpenAI. Após criar sua conta, você pode acessar a interface aqui.

Deve parecer algo assim:

chatGPT interface
Usar o ChatGPT é simples. Você conversa com ele da mesma forma que conversaria com uma pessoa real.

Experimente fazer algumas perguntas, como: Qual é o maior país do mundo? Quais são os melhores hotéis em Londres? E Você pode sugerir alguns livros de psicologia não fictícios?

Digamos que você seja novo no mundo do desenvolvimento web3 e queira criar e implantar seu primeiro dapp na Ethereum. O ChatGPT é excelente para gerar ideias.

Experimente o seguinte prompt:

Eu sou um desenvolvedor iniciante de web3. Eu quero criar e implantar um dapp na Ethereum. Eu preferiria que o dapp fosse implementado como um único contrato inteligente. Você pode me dar algumas ideias?

O ChatGPT lhe dará uma resposta parecida com esta:

Claro! Aqui estão algumas ideias para um DApp que podem ser implementadas como um único contrato inteligente na Ethereum:

1.Exchange Descentralizada de Tokens: Crie um DApp que permita aos usuários negociar tokens ERC-20 diretamente entre si. O contrato inteligente atua como uma troca descentralizada, facilitando a troca de tokens entre compradores e vendedores.

2.Loteria Descentralizada: Crie um DApp de loteria onde os usuários podem comprar bilhetes enviando Ether para o contrato inteligente. O contrato pode lidar com a compra de bilhetes, seleção aleatória de vencedores e distribuição de prêmios.

3.Apostas Descentralizadas: Desenvolva um DApp que permita aos usuários fazer apostas em eventos ou resultados específicos. O contrato inteligente gerencia os valores das apostas, administra as apostas e distribui automaticamente os ganhos com base no resultado.

4.Mercado de NFTs: Crie um DApp que funcione como um mercado para tokens não fungíveis (NFTs). Os usuários podem listar seus NFTs para venda, e os compradores podem adquiri-los diretamente do contrato inteligente.

5.Financiamento Coletivo Descentralizado: Crie um DApp que permita financiamento coletivo para projetos ou iniciativas. Os usuários podem contribuir com Ether para o contrato inteligente, e se uma meta de financiamento predefinida for atingida dentro de um prazo especificado, os fundos são liberados para o proprietário do projeto.

6.Votação Descentralizada: Implemente um DApp de votação onde os usuários podem expressar seus votos sobre propostas ou decisões específicas. O contrato inteligente registra e conta os votos de forma segura, garantindo transparência e imutabilidade.

7.Serviço de Assinatura Descentralizada: Crie um DApp que ofereça um serviço baseado em assinatura, onde os usuários podem assinar para acessar conteúdo ou recursos premium. O contrato inteligente gerencia os detalhes da assinatura e lida com os pagamentos das assinaturas.

Lembre-se de testar minuciosamente o contrato inteligente e revisar o código em busca de possíveis vulnerabilidades de segurança antes de implantá-lo na rede Ethereum. Também é uma boa prática buscar feedback da comunidade de desenvolvedores e realizar auditorias para garantir a integridade do contrato. Bom Desenvolvimento!

Observe que o ChatGPT não lhe dará a mesma resposta mesmo em prompts idênticos, então o que você obtiver não será exatamente igual ao acima.

A lista de ideias que ele gerou é bastante impressionante! Para este tutorial, vamos escolher a ideia de Loteria Descentralizada. Sinta-se à vontade para escolher uma das outras ideias para trabalhar como alternativa. Os passos que seguiremos para criar nosso contrato inteligente e lançar nosso dapp serão na maioria os mesmos.

Passo 2: Crie uma carteira MetaMask e adquira ETH de teste

Para criar, implantar e interagir com contratos inteligentes na Ethereum, precisaremos de uma carteira criptográfica e tokens de gás.

Para a carteira, vamos usar a MetaMask. A MetaMask é uma carteira descentralizada, autocustodial que é segura, confiável e fácil de usar. Baixe e instale a MetaMask como uma extensão de navegador. Após a instalação, a MetaMask solicitará que você siga uma série de etapas para criar sua primeira carteira. No processo, você receberá uma frase secreta. Tenha um cuidado especial para armazenar sua frase-semente (seed) com segurança. Se você a perder, perderá o acesso à sua carteira.

Depois que sua carteira estiver configurada, clique na guia Rede (Network) no canto superior direito da extensão e depois em Mostrar redes de teste (testnet).

Após habilitar as redes de teste, selecione Sepolia no menu suspenso de rede. Usaremos essa rede de teste para implantar nosso dapp. Implantar (e interagir com) um contrato inteligente requer gás – que pode ser caro na rede principal (mainnet). Em uma rede de teste como a Sepolia, no entanto, podemos usar o SepoliaETH, que está disponível gratuitamente na torneira (faucet) da Sepolia. Após usar a torneira, você deve ver um pouco de ETH de teste em sua carteira.

ETH de test

Passo 3: Crie uma conta na Infura

O último passo da preparação é se inscrever para uma conta na Infura. A Infura é um endpoint RPC gratuito, rápido e confiável que nos permite conectar à Ethereum (e Sepolia). É por meio desses endpoints RPC que podemos interagir com as blockchains da Sepolia (e eventualmente à rede principal).

Crie sua conta gratuita na Infura e depois acesse seu painel e crie uma nova chave de API.

criar nova chave

Use a rede padrão da API Web3. Você pode nomear a chave da maneira que quiser.

Essa chave dá acesso a endpoints para muitas blockchains principais, incluindo Ethereum, Polygon, Optimism, Starknet, Near e outras. Para o nosso projeto, estamos interessados na rede de testes Sepolia. O endpoint RPC que usaremos posteriormente no código terá o formato https://sepolia.infura.io/v3/.

Passo 4: Crie um projeto Truffle

Agora estamos prontos para começar a programar. Vamos configurar nosso projeto Truffle.

O Truffle é um ambiente de desenvolvimento para criar, testar e implantar contratos inteligentes Ethereum e baseados em EVM. Vamos usá-lo para praticamente tudo o que precisamos para escrever, testar e implantar nosso código neste projeto.

Antes de instalarmos o Truffle, certifique-se de ter o node e o npm instalados em sua máquina local. Verifique novamente certificando-se de que você pode ver os números das versões ao executar os seguintes comandos.

$ node -v
$ npm -v
Enter fullscreen mode Exit fullscreen mode

Com o node instalado, configurar nosso ambiente de desenvolvimento requer apenas alguns comandos.

$ mkdir lottery && cd lottery
$ npm init -y
$ npm install -save truffle
$ npx truffle init && npx truffle test
$ npm install @openzeppelin/contracts @truffle/hdwallet-provider dotenv
Enter fullscreen mode Exit fullscreen mode

Aqui está o que estamos fazendo acima:

1.Criando um repositório vazio e configurando um projeto node

2.Instalando o Truffle

3.Criando um projeto básico do Truffle

4.Instalando pacotes úteis como OpenZeppelin (para implementações ERC), HD Wallet

5.Provider (para gerenciamento de carteira) e Dotenv (para gerenciamento de segredos).

Passo 5: Crie um contrato de loteria com o ChatGPT

Agora a parte divertida - estamos prontos para pedir ao ChatGPT para escrever nosso contrato inteligente.

Lembre-se de que o ChatGPT nem sempre fornecerá uma solução que seja 100% correta. Portanto, ainda queremos ser diligentes com o código gerado. A maneira mais fácil de obter o melhor código possível é ser o mais detalhado possível em nossa solicitação.

Vamos escrever um prompt interativo para criar o contrato de loteria.

Escreva um contrato inteligente que implementa uma loteria descentralizada.

O contrato inteligente deve ter uma função em que o público possa enviar uma certa quantia de dinheiro para ser considerada na loteria.

Após isso, o proprietário do contrato pode invocar uma função que escolhe aleatoriamente um vencedor e envia todos os fundos no contrato para o vencedor.

O ChatGPT vai gerar uma resposta parecida com esta:

Claro! Aqui está um exemplo de implementação de um contrato inteligente de loteria descentralizada no Ethereum:


// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;


contract DecentralizedLottery {

    address public owner;

    uint256 public ticketPrice;

    mapping(uint256 => address) public participants;

    uint256 public participantCount;

    bool public lotteryClosed;

    uint256 private randomSeed;


    event LotteryClosed(address winner, uint256 amount);

    event TicketPurchased(address participant);


    constructor(uint256 _ticketPrice) {

        owner = msg.sender;

        ticketPrice = _ticketPrice;

        participantCount = 0;

        lotteryClosed = false;

        randomSeed = 0;

    }


    function purchaseTicket() public payable {

        require(!lotteryClosed, "Lottery is closed");

        require(msg.value == ticketPrice, "Incorrect ticket price");


        participants[participantCount] = msg.sender;

        participantCount++;


        emit TicketPurchased(msg.sender);

    }


    function closeLottery() public {

        require(msg.sender == owner, "Only the owner can close the lottery");

        require(!lotteryClosed, "Lottery is already closed");


        lotteryClosed = true;


        uint256 winnerIndex = _generateRandomNumber() % participantCount;

        address payable winner = payable(participants[winnerIndex]);

        uint256 contractBalance = address(this).balance;


        emit LotteryClosed(winner, contractBalance);


        winner.transfer(contractBalance);

    }


    function _generateRandomNumber() private returns (uint256) {

        randomSeed = uint256(keccak256(abi.encodePacked(randomSeed, block.timestamp, block.difficulty)));

        return randomSeed;

    }

}
Enter fullscreen mode Exit fullscreen mode

Neste contrato inteligente, o contrato DecentralizedLottery é inicializado com ticketPrice, sendo a quantia que os participantes precisam enviar para comprar um bilhete da loteria.

O proprietário do contrato pode invocar a função closeLottery para selecionar aleatoriamente um vencedor e transferir todos os fundos no contrato para o endereço do vencedor.

Os participantes podem comprar um bilhete chamando a função purchaseTicket e enviando a quantia ticketPrice em Ether. O contrato mantém o controle dos participantes e da contagem total.

A função closeLottery só pode ser chamada pelo proprietário do contrato, garantindo que somente o proprietário possa iniciar o processo de fechamento da loteria.

A geração de números aleatórios é feita através da função _generateRandomNumber, que combina diversos parâmetros como o carimbo de data/hora atual e a dificuldade do bloco para produzir um número pseudo-aleatório.

Lembrando que este é um exemplo simplificado e não deve ser usado em um ambiente de produção sem auditoria e testes de segurança adequados. Além disso, é crucial considerar os custos de gas, casos excepcionais e possíveis vulnerabilidades de segurança ao implementar uma loteria descentralizada no mundo real.

O contrato que o ChatGPT cria é em grande parte correto. Como o próprio ChatGPT aponta corretamente, provavelmente não é apropriado implantá-lo em um ambiente de produção. Mas para este exemplo, funciona muito bem.

Você também pode solicitar ao GPT para melhorar o contrato (por exemplo, usando a funcionalidade Ownable oferecida pelo OpenZeppelin em vez de implementá-la por nós mesmos).

Então, vamos criar um contrato chamado DecentralizedLottery.sol na pasta contracts e adicionar o seguinte código ligeiramente modificado.

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

contract DecentralizedLottery {
    address public owner;
    uint256 public ticketPrice;
    mapping(uint256 => address) public participants;
    uint256 public participantCount;
    bool public lotteryClosed;
    uint256 private randomSeed;

    event LotteryClosed(address winner, uint256 amount);
    event TicketPurchased(address participant);

    constructor(uint256 _ticketPrice) {
        owner = msg.sender;
        ticketPrice = _ticketPrice;
        participantCount = 0;
        lotteryClosed = false;
        randomSeed = 0;
    }

    function purchaseTicket() public payable {
        require(!lotteryClosed, "Lottery is closed");
        require(msg.value == ticketPrice, "Incorrect ticket price");

        participants[participantCount] = msg.sender;
        participantCount++;

        emit TicketPurchased(msg.sender);
    }

    function closeLottery() public {
        require(msg.sender == owner, "Only the owner can close the lottery");
        require(!lotteryClosed, "Lottery is already closed");

        lotteryClosed = true;

        uint256 winnerIndex = _generateRandomNumber() % participantCount;
        address payable winner = payable(participants[winnerIndex]);
        uint256 contractBalance = address(this).balance;

        emit LotteryClosed(winner, contractBalance);

        winner.transfer(contractBalance);
    }

    function _generateRandomNumber() private returns (uint256) {
        randomSeed = uint256(keccak256(abi.encodePacked(randomSeed, block.timestamp, block.prevrandao)));
        return randomSeed;
    }
}

Enter fullscreen mode Exit fullscreen mode

Passo 6: Configurar Dotenv e Truffle

Agora vamos configurar nosso projeto para funcionar com nossa carteira e nosso ponto de extremidade RPC.

No diretório raiz do nosso projeto, crie um arquivo chamado .env e adicione as seguintes informações:

INFURA_API_KEY = "https://sepolia.infura.io/v3/<Sua-Chave-API>"
MNEMONIC = "<Sua-Frase-Secreta-de-Recuperação-da-Metamask>"
Enter fullscreen mode Exit fullscreen mode

Este arquivo garante que nossas informações sensíveis não sejam enviadas para locais públicos, como o GitHub.

A seguir, substitua o conteúdo do arquivo truffle.config.js para funcionar com a carteira MetaMask e o ponto de extremidade RPC da Infura:

require('dotenv').config();
const HDWalletProvider = require('@truffle/hdwallet-provider');
const { INFURA_API_KEY, MNEMONIC } = process.env;

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*"
    },
    sepolia: {
      provider: () => new HDWalletProvider(MNEMONIC, INFURA_API_KEY),
      network_id: '11155111',
    },
  },
  compilers: {
    solc: {
      version: "0.8.19",
    }
  }
};

Enter fullscreen mode Exit fullscreen mode

Compile o contrato executando:

$ npx truffle compile
Enter fullscreen mode Exit fullscreen mode

Passo 7: Implante o dapp na rede de testes Sepolia

Vamos voltar ao ChatGPT novamente e desta vez pedir sua ajuda para implantar nosso contrato na rede de testes Ethereum.

Use o seguinte prompt:

Estou criando este contrato no Truffle. Você pode me fornecer um script que o implante em uma rede de testes Ethereum?

ChatGPT dá uma resposta parecida com isto:

Claro! Aqui está um exemplo de script que você pode usar para implantar o contrato inteligente de loteria descentralizada em uma rede de testes Ethereum usando o Truffle.

Este exemplo pressupõe que você está usando o framework Truffle e configurou o projeto Truffle com uma configuração de rede adequada para a rede de testes desejada.

Crie um novo arquivo JavaScript (por exemplo, deploy.js) no seu projeto Truffle e cole o seguinte script:


const DecentralizedLottery = artifacts.require("DecentralizedLottery");


module.exports = async function (deployer) {

  try {

    // Implante o contrato DecentralizedLottery

    await deployer.deploy(DecentralizedLottery, /* ticketPrice */ 0.1); // Set the ticketPrice here


    // Obtenha a instância implantada

    const lotteryInstance = await DecentralizedLottery.deployed();


    console.log("DecentralizedLottery contract deployed at:", lotteryInstance.address);

  } catch (error) {

    console.error("Error deploying the contract:", error);

  }

};
Enter fullscreen mode Exit fullscreen mode

Certifique-se de substituir /* ticketPrice */ 0.1 pelo preço do bilhete desejado em Ether que os participantes devem enviar para comprar um bilhete.

Para implantar o contrato, execute o seguinte comando no seu terminal:

truffle migrate --network <nome_da_rede>
Enter fullscreen mode Exit fullscreen mode

Substitua <nome_da_rede> pelo nome da rede para a qual você deseja implantar (por exemplo, ropsten, rinkeby, etc.). Certifique-se de ter configurado corretamente a rede no arquivo truffle-config.js.

O Truffle irá compilar seus contratos e implantar o contrato DecentralizedLottery na testnet especificada. Uma vez que a implantação seja bem-sucedida, o endereço do contrato será exibido no console.

Lembre-se de conectar sua carteira à testnet e ter Ether suficiente para a implantação e taxas de transação.

Por favor, observe que este é um exemplo simplificado, e você pode precisar modificar o script com base na configuração específica do seu projeto e na configuração da rede.

Como é típico, a resposta fornecida pelo ChatGPT está quase correta. A única peça que está claramente faltando é definir o preço do bilhete corretamente e a convenção de nomenclatura adotada pelo Truffle.

Crie um arquivo chamado 1_deploy_contract.js e adicione o código criado pelo ChatGPT.

const DecentralizedLottery = artifacts.require("DecentralizedLottery");

module.exports = async function (deployer) {
    try {
        // Implante o contrato DecentralizedLottery
        const ticketPrice = web3.utils.toWei('0.001', 'ether');
        await deployer.deploy(DecentralizedLottery, ticketPrice); // Set the ticketPrice here

        // Obtenha a instância implantada
        const lotteryInstance = await DecentralizedLottery.deployed();

        console.log("DecentralizedLottery contract deployed at:", lotteryInstance.address);
    } catch (error) {
        console.error("Error deploying the contract:", error);
    }
};
Enter fullscreen mode Exit fullscreen mode

Conforme recomendado pelo ChatGPT, implante o contrato usando o seguinte comando:

$ npx truffle migrate -network sepolia
Enter fullscreen mode Exit fullscreen mode

Se tudo correr bem, você deverá ver uma saída parecida com esta:

Compiling your contracts...

===========================

> Everything is up to date, there is nothing to compile.



Migrations dry-run (simulation)

===============================

> Network name:    'sepolia-fork'

> Network id:      11155111

> Block gas limit: 30000000 (0x1c9c380)



1_deploy_contract.js

====================


   Deploying 'DecentralizedLottery'

   --------------------------------

   > block number:        3498893

   > block timestamp:     1684259757

   > account:             0xc361Fc33b99F88612257ac8cC2d852A5CEe0E217

   > balance:             0.498960474971217066

   > gas used:            672264 (0xa4208)

   > gas price:           2.500000008 gwei

   > value sent:          0 ETH

   > total cost:          0.001680660005378112 ETH


DecentralizedLottery contract deployed at: 0xA4766Ceb9E84a71D282A4CED9fB8Fe93C49b2Ff7

   -------------------------------------

   > Total cost:     0.001680660005378112 ETH


Summary

=======

> Total deployments:   1

> Final cost:          0.001680660005378112 ETH



Starting migrations...

======================

> Network name:    'sepolia'

> Network id:      11155111

> Block gas limit: 30000000 (0x1c9c380)



1_deploy_contract.js

====================


   Deploying 'DecentralizedLottery'

   --------------------------------

   > transaction hash:    0x2a4b6eeaa354d2a4d156f0d562ca6ac7212b22a2131a54426178ec5a82a660d0

   > Blocks: 2            Seconds: 22

   > contract address:    0xA4766Ceb9E84a71D282A4CED9fB8Fe93C49b2Ff7

   > block number:        3498900

   > block timestamp:     1684259784

   > account:             0xc361Fc33b99F88612257ac8cC2d852A5CEe0E217

   > balance:             0.498960474970544802

   > gas used:            672264 (0xa4208)

   > gas price:           2.500000009 gwei

   > value sent:          0 ETH

   > total cost:          0.001680660006050376 ETH


DecentralizedLottery contract deployed at: 0xA4766Ceb9E84a71D282A4CED9fB8Fe93C49b2Ff7

   > Saving artifacts

   -------------------------------------

   > Total cost:     0.001680660006050376 ETH


Summary

=======

> Total deployments:   1

> Final cost:          0.001680660006050376 ETH
Enter fullscreen mode Exit fullscreen mode

Parabéns! Seu contrato agora está ativo. Você pode procurá-lo no Sepolia Etherscan.
etherscan

Passo 8: Criar um frontend React

Agora que nosso contrato foi implantado, vamos criar um frontend web3 em React que permitirá que qualquer pessoa no mundo compre nossos bilhetes de loteria.

Crie um novo repositório de projeto para isso usando os seguintes comandos:

$ npx create-react-app lottery-frontend
$ npm install [email protected]
$ cd lottery-frontend
Enter fullscreen mode Exit fullscreen mode

Para que nosso frontend possa interagir com nosso contrato, precisamos do ABI do contrato. Felizmente, o Truffle já gerou isso para nós quando compilamos nossos contratos.

Você pode encontrar o arquivo JSON do ABI na pasta build do seu projeto Truffle. Crie uma nova pasta contracts na pasta src do projeto React e cole o arquivo ABI lá.

Em seguida, crie uma pasta data na pasta src do projeto React e adicione o seguinte código:

const contractAddress = "<- SEU ENDEREÇO DO CONTRATO ->";
const walletAddress = "<- SEU ENDEREÇO DA CARTEIRA ->";

export { contractAddress, walletAddress }
Enter fullscreen mode Exit fullscreen mode

Passo 9: Escreva o código principal do aplicativo

Agora vamos escrever a lógica principal do aplicativo. Nosso aplicativo fará o seguinte:

1.Permitirá que os usuários conectem sua carteira MetaMask ao nosso site.
2.Permitirá que os usuários conectados comprem um bilhete.

Embora este seja um aplicativo muito simples, ele é mais complexo (tanto em termos de lógica quanto de número de linhas de código) do que o contrato inteligente que geramos anteriormente.

No entanto, o ChatGPT ainda é uma excelente ferramenta para obter um "primeiro rascunho" do nosso código. Lembre-se de que os resultados produzidos serão melhores se você for mais preciso e detalhado em suas instruções - e é exatamente isso que vamos fazer.

Não vamos pedir algo vago como Criar um aplicativo React que se conecta ao nosso contrato. Em vez disso, vamos usar o seguinte prompt:

Quero criar um aplicativo React que se conecte com o contrato inteligente da loteria.

Este contrato inteligente possui uma função purchaseTicket que é pública e pode ser invocada por qualquer pessoa que envie uma certa quantia de dinheiro (o ticketPrice) para ele.

Quero que você escreva o código para o arquivo App.js. O código deve ser escrito em JavaScript usando as bibliotecas ethers e a API do MetaMask.

No arquivo App.js, o seguinte deve ser implementado:

1.Funcionalidade de conexão da carteira.
2.Funcionalidade que permite aos usuários comprar bilhetes do contrato.

O ChatGPT produz uma resposta parecida com esta:

Certamente! Aqui está um exemplo de como você pode implementar o arquivo App.js para criar um aplicativo React que faz interface com um contrato inteligente de loteria usando ethers.js e a API MetaMask:

import React, { useState, useEffect } from "react";

import { ethers } from "ethers";


// Importe o endereço do contrato e a ABI

import { contractAddress } from "./contractConfig";

import { contractABI } from "./contractABI";


function App() {

  const [provider, setProvider] = useState(null);

  const [signer, setSigner] = useState(null);

  const [contract, setContract] = useState(null);

  const [account, setAccount] = useState(null);

  const [ticketPrice, setTicketPrice] = useState(null);


  useEffect(() => {

    const initialize = async () => {

      try {

        // Verifique se a MetaMask está instalada

        if (window.ethereum) {

          await window.ethereum.request({ method: "eth_requestAccounts" });

          const ethereumProvider = new ethers.providers.Web3Provider(window.ethereum);

          const selectedAccount = ethereumProvider.getSigner();


          setProvider(ethereumProvider);

          setSigner(selectedAccount);

          setAccount(await selectedAccount.getAddress());

          setContract(new ethers.Contract(contractAddress, contractABI, selectedAccount));


          const price = await contract.ticketPrice();

          setTicketPrice(ethers.utils.formatEther(price));

        } else {

          console.log("MetaMask is not installed");

        }

      } catch (error) {

        console.error(error);

      }

    };


    initialize();

  }, []);


  const connectWallet = async () => {

    try {

      await window.ethereum.request({ method: "eth_requestAccounts" });

      const ethereumProvider = new ethers.providers.Web3Provider(window.ethereum);

      const selectedAccount = ethereumProvider.getSigner();


      setProvider(ethereumProvider);

      setSigner(selectedAccount);

      setAccount(await selectedAccount.getAddress());

      setContract(new ethers.Contract(contractAddress, contractABI, selectedAccount));

    } catch (error) {

      console.error(error);

    }

  };


  const purchaseTicket = async () => {

    try {

      const transaction = await contract.purchaseTicket({ value: ethers.utils.parseEther(ticketPrice) });

      await transaction.wait();

      alert("Ticket purchased successfully!");

    } catch (error) {

      console.error(error);

      alert("Failed to purchase ticket");

    }

  };


  return (

    <div className="App">

      <h1>Decentralized Lottery</h1>

      {provider && (

        <>

          <p>Connected Account: {account}</p>

          <p>Ticket Price: {ticketPrice} ETH</p>

          <button onClick={purchaseTicket}>Purchase Ticket</button>

        </>

      )}

      {!provider && <button onClick={connectWallet}>Connect Wallet</button>}

    </div>

  );

}


export default App;
Enter fullscreen mode Exit fullscreen mode

Neste exemplo:

- O endereço e a ABI do contrato são importados de arquivos separados (contractConfig.js e contractABI.js), que devem ser criados por você. Ajuste os caminhos de importação e nomes de arquivo conforme necessário.

- Os estados provider, signer, contract, account e ticketPrice são definidos usando o hook useState.

- A função initialize é chamada no momento da montagem do componente, verificando se o MetaMask está instalado e definindo os valores do provedor, assinante, contrato, conta e preço do bilhete adequadamente.

- A função connectWallet é chamada quando o botão "Conectar Carteira" é clicado. Ela solicita ao usuário que conecte sua carteira MetaMask e define os valores do provedor, assinante, contrato e conta.

- A função purchaseTicket é chamada quando o botão "Comprar" é clicado. Ela tenta comprar um bilhete chamando a função do contrato e manipula os erros, se ocorrerem.

O código que ele fornece, embora não seja perfeito, é um ótimo ponto de partida.

Começando com o código que o ChatGPT forneceu, faremos algumas alterações para que o seu arquivo App.js fique parecido com isso:

import React, { useState, useEffect } from "react";
import { ethers } from "ethers";

// Importe o endereço do contrato e a ABI
import { contractAddress } from "./data/constants";
import contract from "./contracts/DecentralizedLottery.json";

const contractABI = contract.abi;
const ticketPrice = "0.001";

function App() {

  const [provider, setProvider] = useState(null);
  const [contract, setContract] = useState(null);
  const [account, setAccount] = useState(null);

  useEffect(() => {
    const initialize = async () => {
      try {
        // Verifique se a MetaMask está instalada
        if (window.ethereum) {
          await window.ethereum.request({ method: "eth_requestAccounts" });
          const ethereumProvider = new ethers.providers.Web3Provider(window.ethereum);
          const selectedAccount = ethereumProvider.getSigner();

          setProvider(ethereumProvider);
          setAccount(await selectedAccount.getAddress());
          setContract(new ethers.Contract(contractAddress, contractABI, selectedAccount));
        } else {
          console.log("MetaMask is not installed");
        }
      } catch (error) {
        console.error(error);
      }
    };

    initialize();
  }, []);

  const connectWallet = async () => {
    try {
      await window.ethereum.request({ method: "eth_requestAccounts" });
      const ethereumProvider = new ethers.providers.Web3Provider(window.ethereum);
      const selectedAccount = ethereumProvider.getSigner();

      setProvider(ethereumProvider);
      setAccount(await selectedAccount.getAddress());
      setContract(new ethers.Contract(contractAddress, contractABI, selectedAccount));
    } catch (error) {
      console.error(error);
    }
  };

  const purchaseTicket = async () => {
    try {
      const transaction = await contract.purchaseTicket({ value: ethers.utils.parseEther(ticketPrice) });
      await transaction.wait();
      alert("Ticket purchased successfully!");
    } catch (error) {
      console.error(error);
      alert("Failed to purchase ticket");
    }
  };

  return (
    <div className="App">
      <h1>Decentralized Lottery</h1>
      {provider && (
        <>
          <p>Connected Account: {account}</p>
          <p>Ticket Price: {ticketPrice} ETH</p>
          <button onClick={purchaseTicket}>Purchase Ticket</button>
        </>
      )}
      {!provider && <button onClick={connectWallet}>Connect Wallet</button>}
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Mudando menos de 10 linhas de código, agora temos um dapp completo em nossas mãos. Tivemos que:

1.Corrigir as importações do endereço do contrato e do ABI do contrato.

2.Remover variáveis que não estavam sendo usadas (signer).

3.Converter certas variáveis em constantes (ticketPrice).

Vamos ver isso em ação executando o seguinte comando:

$ npm start
Enter fullscreen mode Exit fullscreen mode

Isso deve abrir uma janela do navegador apontando para https://localhost:3000. Se você vir um botão Conectar Carteira, clique nele e conecte sua MetaMask. (Alternativamente, você pode ser solicitado a conectar a MetaMask assim que a página for carregada.)

Depois de conectar sua carteira, você deve ver uma página que se parece com isso:

página

Clicar no botão Comprar Ingresso irá solicitar outra transação na MetaMask, onde você será solicitado a pagar o preço do ingresso + gás.

Depois de fazer isso, você deve ser capaz de verificar o status da sua transação na MetaMask.

metamask

Assim que a transação for concluída, um pop-up irá informá-lo sobre a mesma.

pop-up

E aí está! Você comprou com sucesso um bilhete do contrato. Você pode verificar se a transação realmente ocorreu visitando a página Etherscan do seu contrato.

etherscan

Com o ChatGPT gerando a lógica central do aplicativo para você, agora você pode prosseguir e fazer coisas como adicionar estilos CSS à sua página e torná-la mais amigável para o usuário (por exemplo, fornecendo um status ao vivo da transação na própria página).

Experimente pedir ao ChatGPT para fazer isso por você, em vez de criar dapps do zero. Você produzirá resultados mais rapidamente e sua saída provavelmente será melhor do que se tivesse feito sozinho.

Continue construindo com ChatGPT, MetaMask e Infura

Parabéns! Você construiu e implantou com sucesso um dapp de loteria na rede de testes Sepolia. Esperamos que este tutorial tenha sido útil e que você entenda como o ChatGPT pode ser um assistente útil para o desenvolvimento futuro de contratos inteligentes. Para saber mais sobre as ferramentas MetaMask para desenvolvedores, visite https://metamask.io/news/developers/.



Esse artigo é uma tradução feita por @bananlabs. Você pode encontrar o artigo original aqui

Top comments (0)