-
Notifications
You must be signed in to change notification settings - Fork 70
Description
Introducao a SmartContracts com Solidity
Tema: aplicação frontend consumindo um smartcontract
Pitch: Desenvolvimento de Aplicações Descentralizadas
Sumario
- Criar projeto Solidity com hardhat
- Testes automatizados de Solitidy com hardhat
- Deploy em testnet mumbai
- Integracao com frontent react
Atividade:
Seguir documentacao https://hardhat.org/tutorial/creating-a-new-hardhat-project
mkdir smartocntracts-tuto
cd smartocntracts-tuto
npm init # setup the way you prefer
npx hardhat # select create typescript projectSeguir documentacao https://www.npmjs.com/package/@typechain/hardhat
npm install --save-dev typechain @typechain/hardhat @typechain/ethers-v5Adicione no arquivo hardhat.config.ts
import '@typechain/hardhat'
import '@nomiclabs/hardhat-ethers'Delete Lock.sol na pasta contracts e tbm Lock.ts da pasta testes. Crie um contrato simples de greet.ts na pasta contracts:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
contract Greeter {
constructor() {}
function greet() public pure returns (string memory) {
return "Hello, World!";
}
}bash:
npx hardhat compile
Agora vamos integrar ao front!
O melhor caminho eh criar testes automatizados via typescript. Depois de criar as funcionalidades ja testadas, basta copiar o fluxo testado pro front e acoplar em algum botao.
Crie um arquivo na pasta test como greeter.ts
import { expect } from "chai";
import { ethers } from "hardhat";
import {Greeter__factory} from "../typechain-types";
import {Greeter} from "../typechain-types";
describe("Greeter", function () {
let greeter: Greeter;
async function deployGreeter() {
const Greeter: Greeter__factory = await ethers.getContractFactory("Greeter") as Greeter__factory;
const [owner, otherAccount] = await ethers.getSigners();
greeter = await Greeter.deploy();
return ;
}
beforeEach(async function () {
await deployGreeter();
});
describe("Hello Test", function () {
it("Should print \"Hello World!\"", async function () {
let response = await greeter.greet();
await expect(response).equal( "Hello, World!");
});
});
});Rode os testes:
hardhat testSe tudo tiver certo, faca deploy do contrato, recomendo testnet polygon. Edite o orquivo deploy.ts da pasta scripts. Para efetivamente fazer deploy do contrato.
import { ethers } from "hardhat";
import { Greeter__factory } from "../typechain-types";
import { Greeter } from "../typechain-types";
async function main() {
const Greeter: Greeter__factory = await ethers.getContractFactory("Greeter") as Greeter__factory;
const [owner, otherAccount] = await ethers.getSigners();
let greeter: Greeter = await Greeter.deploy();
await greeter.deployed();
console.log(`Greeter deployed to ${greeter.address}`);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});Pra que o contrato seja deployado em alguma chain, digamos polygon testnet, vc precisara das credenciais da wallet.
Pra isso crie um arquivo .env coloque ele no .gitignore e adicione o seu mnemonic phrase la. Se voce nao tiver uma wallet, recomendo criar uma apenas para este fim agora e salvar no arquivo .env. Como vamos usar .env nao esqueca de instalar o pacote dotenv com npm install --save-dev dotenv.
Para usar o contrato no navegador a forma mais simple eh adicionar a extensao metamask. Apos isto, importe suas chaves na metamask(criado no passo anterior) ou crie uma por la.
Use esse hardhat.config.ts que ele ja esta configurado para usar testnet da polygon e outras chains.
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import '@typechain/hardhat'
import '@nomiclabs/hardhat-ethers'
import * as dotenv from "dotenv";
import { resolve } from "path";
import { Wallet } from "ethers";
import * as fs from 'fs';
dotenv.config({ path: resolve(__dirname, "./.env") });
let mnemonic = process.env.MNEMONIC || "";
let wallet:Wallet;
if(mnemonic)
wallet = Wallet.fromMnemonic(mnemonic);
else {
mnemonic = Wallet.createRandom().mnemonic.phrase;
wallet = Wallet.fromMnemonic(mnemonic);
console.warn("RANDOM MNEMONIC used: " + mnemonic);
console.warn("PRIVATE KEY used: " + wallet.privateKey);
console.warn("WALLET ADDR used: " + wallet.address);
fs.writeFileSync(resolve(__dirname, "./.env"), `MNEMONIC="${mnemonic}"\nPRIVATEKEY="${wallet.privateKey}"\nWALLETADDRESS="${wallet.address}"\n`);
}
const config: HardhatUserConfig = {
solidity: {
compilers: [
{
version: "0.8.18",
settings: {
metadata: {
bytecodeHash: "none",
},
optimizer: {
enabled: true,
runs: 800,
},
},
}
],
},
networks: {
local: {
url: "http://localhost:8545",
accounts: { mnemonic },
},
bsctest: {
url: "https://data-seed-prebsc-1-s1.binance.org:8545",
chainId: 97,
accounts: { mnemonic },
},
bsc: {
url: "https://bsc-dataseed.binance.org/",
chainId: 56,
accounts: { mnemonic },
},
mumbai: {
url: "https://polygon-mumbai.blockpi.network/v1/rpc/public",
chainId: 80001,
accounts: { mnemonic },
},
hardhat: {
accounts: { mnemonic },
},
},
gasReporter: {
enabled: process.env.REPORT_GAS !== undefined,
currency: "USD",
},
typechain: {
outDir: "typechain-types",
target: "ethers-v5",
},
paths: {
artifacts: "./artifacts",
cache: "./cache",
sources: "./contracts",
tests: "./test",
},
};
export default config;Adicione a mumbai a sua wallet aqui https://chainlist.org/chain/80001
Se voce nao tiver tokens na wallet que vc estiver usando, precisamos adicionar fundos, no caso da polygon mumbai, adicione fundos aqui. https://faucet.polygon.technology/
Para deployar para a polygon testnet basta rodar agora com tudo configurado:
hardhat run --network mumbai scripts/deploy.tsGuarde o endereco do contrato pois vamos usar ele na integracao com o front. No meu caso o endereco do contrato gerado foi: "0xe720699f67778FBF021B3a5C6C5092ea4e5c3087"
Agora vamos integrar o contrato ao front.
Crie o projeto com a stack typescript que melhor lhe convir. Recomendo react. Copie toda a pasta typechain-types para o seu sources pois vamos usar ele.
Se voce estiver na pasta do smartcontracts-tuto acima, volte um nivel com cd ...
Para criar um esqueleto com react, vc pode usar:
npx create-react-app react-demo --template typescriptAgora copie o typechain-types da sua pasta smartcontracts-tuto para a nova pasta do react-demo recem criada dentro da subpasta src.
Na pasta do react-demo, instale @nomicfoundation/hardhat-toolbox via npm install --save @nomicfoundation/hardhat-toolbox.
Altere o App.tsx para chamar o greeter.
import React from 'react';
import logo from './logo.svg';
import './App.css';
import {Greeter, Greeter__factory} from './typechain-types';
import {ethers, Wallet} from 'ethers';
async function connect() {
console.log('clicked');
(window as any).ethereum.request({ method: 'eth_requestAccounts' });
}
async function callGreet(){
const provider = new ethers.providers.Web3Provider((window as any).ethereum);
const contract = Greeter__factory.connect('0xe720699f67778FBF021B3a5C6C5092ea4e5c3087', provider);
let ret = await contract.greet();
console.log(ret);
alert(ret);
}
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
<button onClick={() => connect()}>Connect to Metamask</button>
<button onClick={() => callGreet()}>Call Greet</button>
</header>
</div>
);
}
export default App;E pronto basta voce editar seu contrato e usar ele como achar melhor no seu frontend.
