Derde stappen

    Dus je hebt de basis onder de knie. In de vorige sectie heb je een slim contract ontwikkeld en dit geïmplementeerd met Truffle. In het vorige gedeelte werden uw slimme contracten echter geïmplementeerd in een lokaal ontwikkelingsnetwerk – en dat is niet leuk, aangezien alleen u dingen kunt implementeren en kunt communiceren met dat lokale testnetwerk! We willen vrienden! En toegang tot andere slimme contracten die andere mensen hebben ingezet!

    Daarom gaan we in dit gedeelte over op het gebruik van een openbaar Ethereum-testnet, zodat u kunt meedoen aan alle acties die plaatsvinden rond het Ethereum-ecosysteem.!

    Laten we beginnen!

    Eerst gaan we het hebben over hoe u toegang krijgt tot deze openbare Ethereum-netwerken.

    Om toegang te krijgen tot deze netwerken, moet u verbinding maken met een knooppunt dat is verbonden met het respectieve netwerk. Je kunt elk Ethereum-netwerk zien als zijn eigen kleine Ethereum-wereld, en je kunt een Ethereum-knooppunt zien als je gateway of toegangspunt tot elk van die werelden! Omdat Ethereum een ​​gedistribueerd netwerk is, slaat elk Ethereum-knooppunt de volledige status op van het netwerk waarmee het is verbonden (er zijn knooppunten die niet de volledige status hoeven op te slaan, maar maak je daar voorlopig geen zorgen over), en communiceert constant met de andere knooppunten in het netwerk om die toestand up-to-date te houden! Daarom hebben we toegang tot een van deze knooppunten nodig om te kunnen lezen van en schrijven naar deze status.


    Je zou heel goed je eigen node kunnen hosten met een van de vele Ethereum-clients die momenteel beschikbaar zijn (Hyperledger Besu (Java-client ontwikkeld door ConsenSys), Geth (Go-client), Parity (Rust-client), enz.) – maar er is nogal wat beetje DevOps-overhead die wordt geleverd bij het hosten en onderhouden van uw eigen Ethereum-knooppunt – vooral als u het betrouwbaar wilt doen! Als zodanig hebben we bij ConsenSys Infura gebouwd – een Ethereum-infrastructuuraanbod van wereldklasse. Infura zorgt voor het hele stuk ‘knooppuntbeheer’ voor u en biedt u directe, betrouwbare en schaalbare toegang tot clusters van Ethereum-knooppunten! U kunt Infura zien als “Ethereum-nodes-as-a-Service” &# 128578;

    Aan de slag met Infura

    Om aan de slag te gaan met Infura, wil je een account registreren bij infura.io. Maakt u zich geen zorgen: u kunt helemaal gratis aan de slag en u hoeft geen gevoelige informatie in te voeren!

    Na registratie wordt u doorgestuurd naar een pagina die er als volgt uitziet:

    infuraLogin

    Zoals deze pagina suggereert, selecteer je om te beginnen de eerste optie “Aan de slag en maak je eerste project om toegang te krijgen tot het Ethereum-netwerk!”

    U kunt uw project een naam geven zoals u maar wilt – we noemen het onze ‘testproject’.

    InfuraNP

    Nu krijgt u de inloggegevens te zien die u nodig heeft om toegang te krijgen tot de Infura-knooppunten!

    InfuraC

    Houd deze pagina open! We komen er later op terug &# 128578;

    Het volgende dat we gaan doen, is een nieuw truffelproject initialiseren. Als je hulp nodig hebt bij het installeren van Truffle, raadpleeg dan het vorige gedeelte van deze documentatie.

    Om een ​​nieuw Truffle-project te initialiseren, maakt u een nieuwe map aan en voert u het

    truffel init

    Vervolgens wilt u de Truffle HD Wallet-provider toevoegen aan uw nieuw geïnitialiseerde project, zodat u uw transacties kunt ondertekenen voordat ze naar de Infura-knooppunten worden verzonden. Elke statuswijziging die u in Ethereum aanbrengt, komt in de vorm van een transactie – of het nu gaat om het implementeren van een contract, het aanroepen van een functie binnen een contract of het verzenden van een token! Elke transactie moet worden ondertekend door een account – daarom moet onze applicatie de mogelijkheid hebben om transacties te ondertekenen, zodat deze statuswijzigingen in Ethereum kan aanbrengen!

    Elke transactie kost ook ether. Deze transactiekost wordt de “gaskost” genoemd. Om ervoor te zorgen dat onze ondertekende transacties door het netwerk worden verwerkt zodra ze naar de Infura-knooppunten zijn verzonden, moeten we daarom wat ether op onze rekening storten. We zullen dit wat later bespreken, maar dit is gewoon een andere belangrijke reden waarom u een portemonnee nodig heeft & wallet provider!

    Om de Truffle HD Wallet-provider toe te voegen aan uw nieuw geïnitialiseerde projecttype in uw terminal:

    npm install –save @ truffle / hdwallet-provider

    Dit kan enkele waarschuwingen opleveren, maar zolang het wordt geïnstalleerd, bent u klaar om te gaan!

    Nu kunnen we een Ethereum-account aanmaken zodat onze applicatie deze kan gebruiken! Omdat onze portemonnee-provider een HD-portemonnee (hiërarchisch deterministisch) is, kunnen we deterministisch accounts genereren met dezelfde seed-zin of geheugensteuntje.

    Om ons account aan te maken, moeten we eerst Ganache starten. Ganache is een truffelproduct waarmee we eenvoudig ons eigen lokale dev-netwerk kunnen creëren. Om ganache uit te voeren, typ je gewoon

    ganache-cli

    Als je stap 2 van deze handleiding hebt voltooid, zou je Ganache / ganache-cli al geïnstalleerd moeten hebben – als je dat niet doet, kun je het installeren met de opdracht npm:

    npm install -g ganache-cli

    Of als u garen gebruikt 

    garen globaal toevoegen ganache-cli

    Vervolgens moeten we onze app toestaan ​​om met Ganache te praten. Ga naar je projectdirectory en check het truffle-config.js-bestand uit, verwijder gewoon de commentaren (of voeg toe) de volgende regels onder netwerk:

    ontwikkeling: {host: "127.0.0.1", // Localhost (standaard: geen) poort: 8545, // Standaard Ethereum-poort (standaard: geen) netwerk_id: "​" // Elk netwerk (standaard: geen)},

    ongewoon

    Leuk! Nu kan onze app praten met ons Ganache-ontwikkelingsnetwerk dat draait op 127.0.0.1:8545! Voer nu de opdracht uit in een nieuw terminalvenster (maar nog steeds in uw projectmap)

    truffel console

     om verbinding te maken met uw Ganache-netwerk. Maakt u zich geen zorgen: we maken later verbinding met een openbaar netwerk! We hoeven nu alleen maar verbinding te maken met Ganache om onze sleutels te maken &# 128578;

    Opmerking: als u problemen ondervindt, zorg er dan voor dat in Ganache uw RPC Server-poortnummer overeenkomt met uw truffelconfiguratiebestand. In het standaardgeval zou 8545 moeten werken, anders verander je je configuratiebestand zodat het overeenkomt met Ganache.

    Voer nu de volgende opdrachten in de Truffel-console in om uw portemonnee aan te maken:

    const HDWalletProvider = vereisen (‘@ truffle / hdwallet-provider’);

    Dit zou moeten resulteren in een reactie van ‘ongedefinieerd’

    Voor je geheugensteuntje van 12 woorden kun je een geheugensteuntje-generator gebruiken, zoals deze als je het leuk vindt!

    ZORG ERVOOR DAT U UW MNEMONISCHE (ZAAD) UITDRUKKING BEWAART! We hebben het later nodig &# 128515;

    Voeg vervolgens de volgende opdracht toe aan uw terminal (terwijl u nog in truffelontwikkeling bent):

    const mnemonic = ’12 woorden hier ‘; const wallet = nieuwe HDWalletProvider (ezelsbruggetje, "http: // localhost: 8545"​

    Voer nu in je truffelconsole het commando in 

    portemonnee

    Als je omhoog scrolt, zou je een lijst met accounts moeten zien, zoals deze!

    addy

    Ondanks dat dat account wordt gegenereerd terwijl we verbonden waren met Ganache, kunnen we dezelfde Ethereum-account (s) gebruiken op elk Ethereum-netwerk (let op: hoewel hetzelfde account kan worden gebruikt in elk Ethereum-netwerk, activa / activiteiten die daarbij horen) account zijn netwerkspecifiek – als ik bijvoorbeeld een transactie doe op het Ethereum Mainnet, vindt die transactie alleen plaats op het Ethereum Mainnet en geen ander netwerk). We gaan nu stoppen met communiceren met Ganache (lokaal dev-netwerk) en beginnen dat account te gebruiken om te communiceren met sommige openbare netwerken!!

    Normaal gesproken is het eerste dat u moet doen bij interactie met een openbaar netwerk, een deel van de ether van dat netwerk verkrijgen. In ons geval maken we verbinding met het openbare testnetwerk van Ropsten, dus we hebben wat Ropsten-ether (ETH) nodig! Maak je geen zorgen – testnet ETH is gratis en overvloedig en supergemakkelijk te verkrijgen &# 128077;

    Tijd om test ETH te verwerven

    Om wat Ropsten ETH te krijgen, ga je naar de Ropsten kraan. Plak je accountadres en altviool! U heeft wat Ropsten ETH ontvangen en kunt beginnen met het verzenden van transacties (d.w.z. het aanbrengen van statuswijzigingen in) het Ropsten-netwerk!

    Ter referentie: het Ropsten-testnet is een openbaar Ethereum-testnetwerk, waar u uw code kunt testen in een omgeving die nauw aansluit bij die van het Ethereum-mainnet. Het belangrijkste verschil tussen het Ropsten-testnet (en de andere openbare Ethereum-testnetten) is dat de ETH in testnetland overvloedig is en geen echte waarde heeft! Wanneer u begint te communiceren met het Ethereum-mainnet, kost de Ether die u gebruikt om voor uw transacties te betalen (gaskosten) WERKELIJKE dollars – en daarom moeten we ervoor zorgen dat we de dingen van tevoren goed doen, zodat we onze harde -verdiend geld / onze kostbare mainnet ETH!

    Het Ropsten-testnet heeft, samen met de meeste andere openbare testnetwerken, veel blokverkenners waarmee u de activiteit in de keten kunt bekijken (https://ropsten.etherscan.io/​Om uw gefinancierde account te zien, plakt u het adres van uw account in de verkenner – en u kunt de hele geschiedenis bekijken die eraan is gekoppeld:

    Screen Shot 2020 09 01 om 4 34 21 uur

    Oké! Nu we onze portemonnee-provider hebben en een account gefinancierd met Ropsten ETH, kunnen we teruggaan naar ons project en het richten op de Infura-knooppunten die zijn verbonden met het Ropsten-testnet.

    Het eerste dat we willen doen, is een.env-bestand maken om onze kostbare GEHEIMEN in te bewaren! Deze geheimen omvatten onze Infura API-sleutel (gegenereerd toen we ons Infura-account maakten) en onze geheugenzin.

    Op het root-niveau van uw project maakt u eenvoudig een nieuw bestand “.env” aan. U moet ook het dotenv NPM-pakket installeren door de volgende opdracht in de terminal in te voeren

    npm install –save dotenv

    In dit new.env-bestand heb je twee dingen nodig:

    INFURA_API_KEY = VOEG JE API-SLEUTEL HIER IN (geen aanhalingstekens)

    MNEMONIC = “lens walvis waaier draad bubble online stoel bloot voorraad nummer zin winnaar”

    INFURA_API_KEY is de project-ID van het project dat u eerder in infura hebt gemaakt:

    Screen Shot 2020 09 01 om 4 37 12 uur

    En MNEMONIC is de seed-zin van 12 woorden die u eerder gebruikte om uw account te genereren.

    Uw bestand zou er nu als volgt uit moeten zien:

    Screen Shot 2020 09 01 om 4 41 53 uur

    Oké, we komen dichterbij!

    OPMERKING: Als je dit naar een Github-repository gaat pushen, of dit project op een of andere manier openbaar maakt, ZORG ER dan voor dat je.env-bestand in.gitignore staat, zodat je geheimen niet worden onthuld! 

    Nu moeten we naar het truffle-config.js-bestand gaan. Hier moeten we een paar dingen toevoegen om onze provider aan te duiden (die wordt gebruikt om te communiceren met de Infura (de Truffle HDWallet Provider die we eerder hebben geïnstalleerd), en onze app naar de Ropsten Infura-knooppunten richten.

    Voeg bovenaan het bestand toe:

    vereisen("dotenv") .config (); const HDWalletProvider = vereisen ("@ truffel / hdwallet-provider"​

    Vervolgens wilt u onder ‘netwerken’ het volgende netwerk toevoegen:

    ropsten: {provider: () => nieuwe HDWalletProvider (process.env.MNEMONIC, `https://ropsten.infura.io/v3/$ {process.env.INFURA_API_KEY}`), network_id: 3, // Ropsten’s id gas: 5500000, // Ropsten heeft een onderste bloklimiet dan mainnet-bevestigingen: 2, // # confs om te wachten tussen implementaties. (standaard: 0) timeoutBlocks: 200, // # blokken voordat een implementatie verloopt (minimum / standaard: 50) skipDryRun: true // Droogloop overslaan vóór migraties? (standaard: false voor openbare netten)}

     

    Nu zou je truffle-config.js-bestand er ongeveer zo uit moeten zien!

    Kanttekening:

    Als u Infura-eindpunten gebruikt, is de parameter ‘van’ vereist, aangezien deze geen portemonnee hebben. Als u Ganache- of Geth RPC-eindpunten gebruikt, is dit een optionele parameter.

    Screen Shot 2020 09 01 om 4 50 54 uur

    NU ZIJN WIJ KLAAR VOOR DE MAGIE! Het is tijd om een ​​slim contract in te zetten bij ROPSTEN!

    Een slim contract opzetten

    Solidity-opstelling

    Ten eerste willen we een slim contract maken om te implementeren! U kunt het slimme contract pakken dat u in het vorige gedeelte van deze handleiding hebt ontwikkeld, uw eigen slimme contract samenstellen of gewoon het volgende (uiterst eenvoudige) voorbeeldcontract gebruiken:

    pragma stevigheid >= 0,5,8; contract SimpleStorage {uint256 opgeslagenData; functieset (uint256 x) openbaar {opgeslagenData = x; } functie get () publieke weergave retourneert (uint256) {return opgeslagenData;​

    Dit contract moet worden aangemaakt als een “.sol” -bestand (Solidity) in de map “contracten” van uw project (in dit scenario hebben we het SimpleStorage.sol-bestand gemaakt, dat ons SimpleStorage-contract is:

    stellingen

    Migratie-instellingen

    Vervolgens moeten we ons migratiebestand instellen!

    Migraties zijn JavaScript-bestanden waarmee u contracten op het Ethereum-netwerk kunt implementeren. Deze bestanden zijn verantwoordelijk voor het opstellen van uw implementatietaken en ze zijn geschreven in de veronderstelling dat uw implementatiebehoeften in de loop van de tijd zullen veranderen. Naarmate uw project evolueert, zult u nieuwe migratiescripts maken om deze evolutie op de blockchain te bevorderen. Een geschiedenis van eerder uitgevoerde migraties wordt on-chain vastgelegd via een speciaal migratiecontract. U kunt er meer informatie over vinden hier.

    Ons migratiebestand om ons contract te implementeren ziet er als volgt uit:

    const SimpleStorage = artifacts.require ("SimpleStorage.sol"​module.exports = functie (implementator) {deployer.deploy (SimpleStorage);​

    Bewaar dit bestand in de map “migrations” onder de naam “2_deploy_contracts.js”.

    Uw eerste openbare contract implementeren

    Tijd om te migreren

    Nu ben je ECHT klaar voor de MAGIE DIE GEBEURT! Ga terug naar de console en typ

    truffel migreren –netwerk ropsten

    Boom!&# 128163; Uw code is geïmplementeerd op het openbare Ropsten Ethereum Test Net!!! 

    Wat er net gebeurde was:

    1. Uw slimme contract van Solidity (in de map “contracten”) is gecompileerd tot bytecode – de machineleesbare code voor de Ethereum Virtual Machine om te gebruiken.

    2. Deze bytecode, + enkele andere gegevens, werden gebundeld tot een transactie.

    3. Die transactie is ondertekend door uw account.

    4. Die transactie is verzonden naar het Infura-knooppunt dat is verbonden met Ropsten.

    5. De transactie werd door het hele netwerk verspreid, opgepikt door een Ropsten-mijnwerker en opgenomen in een Ropsten-blok.

    6. Je slimme contract is nu LIVE op de Ropsten-blockchain!

    U kunt uw contract bekijken met Etherscan: https://ropsten.etherscan.io/ – plak gewoon het adres van het contract (zou in uw terminal moeten staan) om het te bekijken!

    Screen Shot 2020 09 01 om 5 19 12 uur

    Verbazingwekkend! We hebben zojuist ons allereerste slimme contract geïmplementeerd in een PUBLIC Ethereum-netwerk! &# 129327;

    Het proces is exact hetzelfde voor implementatie op Ethereum-mainnet, behalve dat je het netwerk in het truffle-config.js-bestand vervangt voor het Ethereum-mainnet (en natuurlijk de mainnet Truffle-migratieopdracht uitvoeren in plaats van de Ropsten-opdracht) ! We zullen u hier niet door dit proces leiden, omdat implementatie op het Ethereum-mainnet u echte $ ’s kost – maar als u hierbij hulp wilt, ga dan naar de ConsenSys Discord en we helpen u graag verder!

    Een Web3-frontend bouwen 

    Nu we ons contract hebben geïmplementeerd bij Ropsten, gaan we een eenvoudige gebruikersinterface bouwen om ermee te communiceren!

    Opmerking: dApp “front-ends” zijn gewoon uw alledaagse, normale oude front-ends – als zodanig kunnen we al onze oude tools gebruiken waarmee we vertrouwd zijn (create-react-app, etc.) om onze front-end te laten draaien. , en voeg vervolgens een paar dingen toe zodat de frontend kan lezen van en schrijven naar Ethereum! Dit betekent dat al uw oude vaardigheden op het gebied van webontwikkeling direct kunnen worden overgedragen naar Ethereum-land / Web3!!

    Start ons React-project 

    Oké, laten we beginnen.

    Zorg er eerst voor dat u een directory heeft die alle informatie bevat die we zojuist hebben gemaakt voor ons opslagcontract. Ik heb mijn map “storage-back” genoemd en deze bevat het werk dat we zojuist hebben voltooid om ons contract op te zetten en te implementeren. 

    Screen Shot 2020 09 01 om 5 26 33 uur

    Nu gaan we beginnen met het opzetten van een react-project, laten we het onze noemen in dit voorbeeld “storage-lab”

    Laten we in onze terminal het volgende uitvoeren om ons project te starten 

    npx create-react-app storage-lab

    Nu we ons nieuwe standaardproject hebben, gaan we naar de projectdirectory

    cd-opslag-lab

    Nu we ons in ons project bevinden, zullen we nu het Web3-pakket toevoegen, waardoor ons project kan communiceren met Ethereum! Meer op web3 hier

    npm installeer web3

    Web3 is een van de twee hoofdpakketten die we kunnen gebruiken, de andere is ethers.js. Voor dit voorbeeld zullen we web3 gebruiken, maar als je meer wilt lezen over ethers.js, kijk dan eens hier 

    Bekijk dit artikel voor een gedetailleerde uitleg van de twee web3 versus ethers

    Super goed! We zijn nu bijna klaar om ons react-project te laten interageren met ons contract!

    Laten we eerst onze directory van eerder nemen (voor mij is het ‘storage-back’) die alleen het werk bevat dat we al hebben gedaan met betrekking tot onze slimme contracten, en laten we dat nu toevoegen aan ons nieuwe react-project. Dit zal op hetzelfde niveau leven als onze src, en nu zouden we alles wat we nodig hebben bij elkaar moeten hebben in onze reagerende REPO.

    Screen Shot 2020 09 01 om 5 31 38 uur

    Vervolgens moeten we ons bestand met onze ABI-informatie opzetten.

    “ABI?”

    Blij dat je het vraagt! 

    De Contract Application Binary Interface (ABI) is de standaardmanier om te communiceren met contracten binnen het Ethereum-ecosysteem, zowel van buiten de blockchain als voor contract-tot-contract-interactie. Toen we in een eerdere stap ons SimpleStorage-contract samenstelden, creëerde het een JSON-bestand voor ons. Kijk zelf maar, we hebben een SimpleStorage.json-bestand in onze build / contracten

    Screen Shot 2020 09 01 om 06 04 20 uur

    Een eerste blik op dit bestand zal veel informatie onthullen, op dit moment hoeven we ons alleen te concentreren op de ABI om ons contract te synchroniseren met de front-end die we aan het ontwikkelen zijn. Deze JSON bevat de informatie die we nodig hebben om ons contract met onze frontend te communiceren.

    Onze ABI is een array die objecten bevat. Als u het bestand van dichterbij bekijkt, kunt u zien dat elk van deze objecten in feite elke functie is die ons SimpleStorage-contract bevat.

    Screen Shot 2020 09 01 om 5 33 23 uur

    U kunt snel zien

    “Name”: “set”

    “Name”: “get”

    beide met een “type:” functie “beide functies die we hebben aangegeven bij het schrijven van ons slimme contract!

    Hoewel truffel de volgende paar stappen verdoezelt, gaan we door een veel meer ‘handmatige’ manier om dingen te doen, zodat je wordt blootgesteld aan alle basisprincipes &# 128578;

    Ga eerst uw gang en kopieer uw abi-informatie – we hebben deze zo dadelijk nodig. 

    Laten we een map maken in onze src met de naam “abi”.

    Laten we in onze vers gemaakte abi-map nu een bestand maken met de naam abi.js

    Opmerking: we hebben deze scheiding technisch niet nodig en kunnen gewoon onze abi.js toevoegen aan onze src, maar het behouden van onze abi.js-bestanden helpt bij de organisatie.

    Nu zullen we onze abi-array kopiëren die we eerder hebben gepakt uit het SimpleStorage.JSON-bestand en deze toevoegen aan ons nieuw gemaakte abi.js-bestand. We zullen het bestand een beetje wijzigen zodat ons project de informatie kan importeren in onze App.js. Vergeet niet, aangezien dit een.js-bestand is, we een export moeten toevoegen, zodat we het later in onze app.js kunnen ophalen. Laten we de const hetzelfde noemen als het contract, behalve met camelcase (zie onderstaande code):

    Dit is de code die we opslaan in ons abi.js-bestand

    export const simpleStorage = [{constante: false, invoer: [{naam: "X", type: "uint256", }, ], naam: "set", outputs: [], payable: false, stateMutability: "onbetaalbaar", type: "functie", }, {constante: waar, invoer: [], naam: "krijgen", uitgangen: [{naam: "", type: "uint256", },], payable: false, stateMutability: "visie", type: "functie", ​

    Tijd om naar onze App.js te gaan en zowel web3 als ons vers gemaakte abi.js-bestand te importeren.

    We gaan ook hooks gebruiken in dit voorbeeld (daarom importeren we ook {useState}, je kunt meer lezen over useState hier.

    De bovenkant van ons App.js-bestand zou er nu als volgt uit moeten zien:

    importeer React, {useState} van "Reageer"​importeer {simpleStorage} van "./ abi / abi"​importeer Web3 van "web3"​importeren "./App.css"​

    We moeten er nu voor zorgen dat willekeurige gebruikers de mogelijkheid hebben om verbinding te maken en onze dApp te gebruiken, zolang ze een wallet-provider hebben!

    De belangrijkste portemonnee die wordt gebruikt in de Ethereum-ruimte voor dApp-interactie is MetaMask, geïntroduceerd in stap 1.

    Als je geen MetaMask hebt, ga dan naar metamask.io

    Met MetaMask geïnstalleerd, hebben we toegang tot onze portemonnee in onze dapp met:

    const web3 = nieuwe Web3 (Web3.givenProvider);

    “Web3.givenProvider” wordt ingesteld in een door Ethereum ondersteunde browser.

    (u kunt meer lezen over waarom dit nodig is hier

    Dus nu zou onze code er als volgt uit moeten zien:

    importeer React, {useState} van "Reageer"​importeer {simpleStorage} van "./ abi / abi"​importeer Web3 van "web3"​importeren "./App.css"​const web3 = nieuwe Web3 (Web3.givenProvider);

    OK! Tot nu toe hebben we:

    • Start een React-project
    • Geïnstalleerde Web3
    • Onze map met onze build + contract + migratie toegevoegd aan ons React-project
    • Een abi.js-bestand gemaakt met de abi-gegevens die we uit SimpleStorage.json hebben gehaald
    • De gegevens geïmporteerd die we nodig hebben om te communiceren met ons contract
    • Een variabele gemaakt waarmee onze dApp kan communiceren met de portemonnee van de gebruiker

    Nogmaals, hoewel Truffle de volgende paar stappen overbodig maakt (we zullen je later door een veel eenvoudigere versie leiden), voegen we wat meer handmatige complexiteit toe aan onze dApp voor educatieve doeleinden.

    Wat we nu gaan doen, is twee nieuwe variabelen maken: een om het adres op te slaan van het contract dat we op Ropsten hebben geïmplementeerd en de andere om dat contract af te stemmen op onze ABI, zodat onze app weet hoe ermee te praten! 

    Om het contractadres te vinden, navigeert u naar het JSON-bestand waarin we ons eerder bevonden (dat de ABI (SimpleStorage.json) bevat) en scrolt u naar beneden. Het adres staat hier in het veld “adres”:

    "compiler"​ "naam"​ "solc", "versie"​ "0.5.8 + commit.23d335f2.Emscripten.clang" ​, "netwerken"​ "3"​ "evenementen"​, "links"​, "adres"​ "0x24164F46A62a73de326E55fe46D1239d136851d8", "transactionHash"​ "0x1f02006b451b9e85f70acdff15a01c6520e4beddfd93a20e88a9b702a607a7b0" ​, "schemaVersion"​ "3.0.16", "updatedAt"​ "2020-06-30T20: 45: 38.686Z", "devdoc"​ "methoden"​, "userdoc"​ "methoden"​

    Je kunt ook naar https://ropsten.etherscan.io/ en zoek het adres op van het account dat het contract heeft geïmplementeerd! Als u in Etherscan op “Contractaanmaak” klikt, wordt het contractadres zelf weergegeven.

    Screen Shot 2020 09 01 om 5 43 46 uur

    Nu nemen we de kopie van het adres van uw contract en maken we een nieuwe variabele om deze op te slaan. 

    Zonder dit kunnen we niet communiceren met het contract en werkt onze dApp niet zoals bedoeld.

    U voegt dit toe onder onze const web3 = new Web3 (Web3.givenProvider);

    const contractAddress = "uw contractadres hier"​

    Vervolgens maken we nog een nieuwe variabele met de naam ‘storageContract’ die zowel ons contractadres (zodat onze app weet waar het contract is) als de ABI (zodat onze app weet hoe hij met het contract moet omgaan) bevat..

    const storageContract = nieuwe web3.eth.Contract (simpleStorage, contractAddress);

    Onze App.js zou er nu zo uit moeten zien

    importeer React, {useState} van "Reageer"​importeer {simpleStorage} van "./ abi / abi"​importeer Web3 van "web3"​importeren "./App.css"​const web3 = nieuwe Web3 (Web3.givenProvider); const contractAddress = "uw contractadres hier"​const storageContract = nieuwe web3.eth.Contract (simpleStorage, contractAddress);

    We moeten nu onze hooks zover krijgen dat ze variabelen bevatten die in wisselwerking staan ​​met ons contract en frontend. We doen dit door het volgende binnen onze app-functie op te geven:

    importeer React, {useState} van "Reageer"​importeer {simpleStorage} van "./ abi / abi"​importeer Web3 van "web3"​importeren "./App.css"​const web3 = nieuwe Web3 (Web3.givenProvider); const contractAddress = "uw contractadres"​const storageContract = nieuwe web3.eth.Contract (simpleStorage, contractAddress); functie App () {const [nummer, setUint] = useState (0); const [getNumber, setGet] = useState ("0"​

    Ons eerste gebruik van useState (0) zal de uint256 bevatten die de gebruiker aangeeft.

    (de naamgevingsconventies van number, setUint, getNumber, setGet helpen hopelijk om te laten zien wat er gebeurt)

    useState (“0”) waarde fungeert als een tijdelijke aanduiding totdat we bevestiging hebben van onze ondertekende actie (onze gedeclareerde uint256)

    setUint we zullen binnenkort een beroep doen in onze terugkeer (hierover later meer)

    Tijd voor onze logica

    Vervolgens zullen we onze numberSet en NumberGet-logica toevoegen (we voegen numberSet toe in onze functie-app)

    const numberSet = async (t) => {t.preventDefault (); const accounts = wacht op window.ethereum.enable (); const account = accounts [0]; const gas = wachten storageContract.methods.set (nummer) .estimateGas (); const post = wachten storageContract.methods.set (nummer) .send ({van: account, gas,});​const numberGet = async (t) => {t.preventDefault (); const post = wachten storageContract.methods.get (). call (); setGet (plaatsen);​

    We hebben een preventDefault ingesteld (details over preventDefault gevonden hier

    We gebruiken ook een asynchrone oproep op Get voor het contract (details over async gevonden hier

    Onze hook setGet () slaat een standaardwaarde op die we aanvankelijk bekijken (“0”)

    const accounts = wacht op window.ethereum.enable ();

    zorgt ervoor dat we ons aangesloten adres bellen via MetaMask.

    const account = accounts [0];

    Trekt het connect-account binnen

    Je vraagt ​​je misschien af ​​wat er aan de hand is 

    const gas = wachten storageContract.methods.set (nummer) .estimateGas ();

    Onze app heeft toestemming nodig om toegang te krijgen tot gebruikersfondsen om gaskosten te betalen, alle functies die om ether vragen, ongeacht of deze zich op het testnet of het mainnet bevindt. Dit is waar onze verbinding met MetaMask van pas komt om voor dit gebruik te tekenen om onze uint256 in te stellen en ervoor te betalen (met test ETH).

    Dus voor elke functie die gas nodig heeft, moet u het potentiële gas dat wordt gebruikt berekenen.

    De “Set” -functie van ons contract vereist gas

    “Get” niet.

    (dit komt omdat ‘Get’ weergeeft wat al is gedeclareerd met ‘Set’)

    const post gaat de pas in uint256 aannemen, bevestig de transactie (na het betalen van gaskosten) vanuit uw MetaMask-portemonnee op het Ropsten-netwerk.

    Vervolgens geven we de functieparameters door via methods.set () en met ons gedeclareerde adres (gebruikersadres) behandelen we vervolgens de functie Set.

    We creëren onze slimme contracttransactie door onze functieparameters door te geven aan de slimme contractmethodes. Set (), en het geschatte gas- en gebruikersaccountadres to.send ().

    const post = wachten storageContract.methods.set (nummer) .send ({van: account, gas,});

    Dit zou alle logica moeten zijn die we nodig hebben om onze numberSet te dekken.

    Nu hebben we ons nummer nodig

    const numberGet = async (t) => {t.preventDefault (); const post = wachten storageContract.methods.get (). call (); setGet (plaatsen);​

    Onze const-post haalt ons setnummer op en setGet geeft de nieuwe waarde die we hebben aangegeven door

    Dus onze “0” zal onClick verwijzen naar ons numberGet en onze unint256 weergeven!

     Dus nu zou je app.js er als volgt uit moeten zien

    importeer React, {useState} van "Reageer"​importeer {simpleStorage} van "./ abi / abi"​importeer Web3 van "web3"​importeren "./App.css"​const web3 = nieuwe Web3 (Web3.givenProvider); const contractAddress = "uw contractadres"​const storageContract = nieuwe web3.eth.Contract (simpleStorage, contractAddress); functie App () {const [nummer, setUint] = useState (0); const [getNumber, setGet] = useState ("0"​const numberSet = async (t) => {t.preventDefault (); const accounts = wacht op window.ethereum.enable (); const account = accounts [0]; const gas = wachten storageContract.methods.set (nummer) .estimateGas (); const post = wachten storageContract.methods.set (nummer) .send ({van: account, gas,});​const numberGet = async (t) => {t.preventDefault (); const post = wachten storageContract.methods.get (). call (); setGet (plaatsen);​

    Laten we een heel eenvoudige weergave maken om te renderen, zodat we kunnen testen of we kunnen 

    • stel een unint256-waarde in,
    • Trek onze metamask-portemonnee omhoog en bevestig de transactie
    • Betaal de gaskosten
    • haal vervolgens de waarde (unint256) die we hebben opgeslagen zodra de transactie is voltooid.

    Ons rendement ziet er als volgt uit: 

    return (Stel uw uint256: setUint (t.target.value)} /> Bevestigen

    Haal uw uint256 {getNumber}); } export standaard app;

    Enkele snelle CSS

    Laten we nu naar het App.css-bestand gaan, de ketelplaatcode verwijderen en deze in plaats daarvan toevoegen

    .hoofd {text-align: center; weergave: flex; justify-content: center; achtergrondkleur: # f2f1f5; hoogte: 100vh; } .card {min-hoogte: 50vh; breedte: 50vw; weergave: flex; flex-richting: kolom; align-items: center; justify-content: center; } .form {hoogte: 20vh; breedte: 20vw; weergave: flex; justify-content: space-evenly; flex-richting: kolom; } .button {breedte: 20vw; hoogte: 5vh;​

    Nu zijn we klaar om te testen!

    In je terminale run

    garen start

    In onze localhost: 3000 zouden we er zo uit moeten zien

     

    Screen Shot 2020 09 01 om 6 12 49 uur

    We zouden nu een unint256-waarde in ons invoerveld moeten kunnen invoeren!

    Nadat we ons nummer in onze dApp hebben bevestigd, ondertekenen we via MetaMask (zorg ervoor dat uw portemonnee is ingesteld op het Ropsten-netwerk)

    confrim1

    We hebben het gedaan! &# 129303;

    We hebben nu ons slimme contract aangesloten op een front-end en hebben de mogelijkheid om de Set-functie te manipuleren (op voorwaarde dat we de test-ETH hebben om de gasvergoeding voor de transactie te betalen). Dan kunnen we de Get-functie aanroepen en de opgeslagen uint265-waarde ophalen.

    Best cool he!?!

    Extra styling 

    Nu is het tijd om te laten zien hoe gemakkelijk het kan zijn om nog meer populaire Web2-technologie in ons project te implementeren.

    We gaan MUI gebruiken om basisstyling toe te voegen, als je al met React ontwikkelt, ben je misschien bekend met material-ui. (Details gevonden hier) Material-UI of kortweg MUI is een erg populair React-framework waarmee je snel een project kunt starten met veel styling, op voorwaarde dat je de naamgevingsconventies volgt. Het is ook heel gemakkelijk te manipuleren als u alleen een foundation wilt gebruiken en van daaruit wilt aanpassen.

    * Dit is een heel kort voorbeeld van hoe u MUI aan een project kunt toevoegen met kleine toevoegingen om te laten zien hoe snel u ons project zoals het er nu uitziet, kunt integreren met een Web2-technologie. 

    MUI toevoegen

    We beginnen met het uitvoeren van de opdracht (terwijl u zich nog in onze projectdirectory in de terminal bevindt (als uw app nog steeds actief is, moet u deze sluiten (ctrl + c) of een nieuw tabblad openen)):

    Om te installeren met npm:

    npm install @ material-ui / core

    Of met garen:

    garen toevoegen @ materiaal-ui / kern

    Nu we MUI hebben geïnjecteerd, beginnen we met het veranderen van onze styling. Bovenaan ons app.js-bestand gaan we een paar nieuwe dingen importeren:

    importeer {simpleStorage} van "./ abi / abi"​knop importeren van "@ material-ui / core / Button"​importeer TextField van "@ material-ui / core / TextField"​importeer {makeStyles} van "@ material-ui / core / styles"​

    Het importeren van {makeStyles} stelt ons in staat om de opmaak (in dit geval) onze knoppen en tekstveld te manipuleren, samen met het importeren van de standaard MUI-opmaak. 

    We gaan nu een variabele maken (boven onze functie) die de boilerplate-styling van MUI binnenhaalt

    const useStyles = makeStyles ((theme) => ({root: { "& > ​": {margin: theme.spacing (1),},},}));

    Nu zullen we binnen onze App-functie ook een variabele met de naam “klassen” toevoegen, waarbij we de gedefinieerde stijlen binnenhalen die we zojuist hierboven hebben verklaard.

    functie App () {const klassen = useStyles (); const [nummer, setUint] = useState (0); const [getNumber, setGet] = useState ("0"​

    We zullen nu aanpassingen maken in onze aangifte om enkele van onze velden te vervangen door wat we zojuist hebben geïmporteerd.

    return (setUint (t.target.value)} variant ="geschetst" ​> Bevestigen

    Haal uw uint256 {getNumber}); } export standaard app;

    Uw code zou er nu als volgt uit moeten zien

    importeer React, {useState} van "Reageer"​importeer {simpleStorage} van "./ abi / abi"​importeer Web3 van "web3"​importeren "./App.css"​importeer {makeStyles} van "@ material-ui / core / styles"​knop importeren van "@ material-ui / core / Button"​importeer TextField van "@ material-ui / core / TextField"​const useStyles = makeStyles ((theme) => ({root: { "& > ​": {margin: theme.spacing (1),},},})); const web3 = nieuwe Web3 (Web3.givenProvider); const contractAddress = "uw contractadres hier"​const storageContract = nieuwe web3.eth.Contract (simpleStorage, contractAddress); functie App () {const klassen = useStyles (); const [nummer, setUint] = useState (0); const [getNumber, setGet] = useState ("0"​const numberSet = async (t) => {t.preventDefault (); const accounts = wacht op window.ethereum.enable (); const account = accounts [0]; const gas = wachten storageContract.methods.set (nummer) .estimateGas (); const post = wachten storageContract.methods.set (nummer) .send ({van: account, gas,});​const numberGet = async (t) => {t.preventDefault (); const post = wachten storageContract.methods.get (). call (); setGet (plaatsen);​return (setUint (t.target.value)} variant ="geschetst" ​> Bevestigen

    Haal uw uint256 {getNumber}); } export standaard app;

    Als we nu naar ons react-project kijken, zou het er zo uit moeten zien!

    Screen Shot 2020 09 01 om 6 48 55 uur

    Goed gedaan!

    We hebben nog steeds alle functionaliteit van vroeger en hebben nu een eenvoudig te gebruiken framework geïnjecteerd om ons project verder aan te passen zoals we willen. Bekijk de MUI documentatie om te experimenteren met uw eigen toevoegingen / wijzigingen!

    Bonusronde 

    Het zou leuk zijn om het verbindingsadres van de gebruikers in onze dApp te laten zien, nietwaar?

    Laten we een heel snel en eenvoudig onderdeel maken om precies dat te doen!

    We beginnen met het maken van een apart onderdeel dat we weer kunnen importeren in ons App.js-bestand. Het is een goed idee om onze logica te scheiden om niet alleen onze App.js gemakkelijk te navigeren te houden, maar ook de praktijk van een component te volgen die idealiter maar één ding doet. Als het uiteindelijk groeit, moet het worden afgebroken in kleinere subcomponenten.

    Component opgebouwd 

    We zullen een nieuwe map maken met de naam componenten op hetzelfde niveau als onze src en binnen die map zullen we een Nav.js-bestand maken. Onze projectsteiger zou er nu ongeveer zo uit moeten zien

    Screen Shot 2020 09 01 om 6 47 07 uur

    We zullen ook een Nav.css-bestand maken in onze componentenmap om alle stijlen te importeren die we specifiek op de Nav-component toepassen.

    Laten we onze Nav.js openen en ons React-, Web3- en ons empty.css-bestand importeren

    importeren Reageren van "Reageer"​importeer Web3 van "web3"​importeren "./Nav.css"

    Nu gaan we een klas maken met de naam Nav en we zullen er slechts een paar dingen aan toevoegen om ons verbonden adres weer te geven. We beginnen met het instellen van onze staat om het account te lezen

    class Nav breidt React.Component {state = {account: "" ​

    Nog steeds binnen onze klasse zullen we het account laden om van te lezen door onze async loadAccount-logica toe te voegen

    async loadAccount () {const web3 = nieuwe Web3 (Web3.givenProvider || "http: // localhost: 8080"​const network = wachten op web3.eth.net.getNetworkType (); const accounts = wachten op web3.eth.getAccounts (); this.setState ({account: accounts [0]});​

    We zullen vervolgens een componentDidMount maken (die onmiddellijk wordt aangeroepen nadat de component is aangekoppeld). In ons geval trekken we het geladen account binnen. Lees verder hier

    componentDidMount () {this.loadAccount ();​

    Kanttekening:

    Dit kan anders worden gedaan, in plaats van een klasse kunnen we een functie maken en hooks gebruiken in tegenstelling tot componentDidMount, maar omwille van dit voorbeeld zullen we vasthouden aan deze methode.

    We zullen dan een render maken boven onze return, render is een methode die vereist is als je een React-component schrijft met behulp van een class-methode. In onze retourzending voegen we een adresklasse toe aan onze div (om later een basisstijl te geven) samen met een p-tag om het verbonden adres te tonen dat we ophalen met {this.state.account}

    render () {return (uw verbonden adres: {this.state.account}); }} export standaard Nav;

    Ons Nav.js-bestand zou er nu als volgt uit moeten zien

    importeren Reageren van "Reageer"​importeer Web3 van "web3"​importeren "./Nav.css" class Nav breidt React.Component {state = {account: "" ​async loadAccount () {const web3 = nieuwe Web3 (Web3.givenProvider || "http: // localhost: 8080"​const network = wachten op web3.eth.net.getNetworkType (); const accounts = wachten op web3.eth.getAccounts (); this.setState ({account: accounts [0]}); } componentDidMount () {this.loadAccount (); } render () {return (uw verbonden adres: {this.state.account}); }} export standaard Nav;

     

    Laten we naar het Nav.css-bestand gaan en een heel eenvoudige stijl toevoegen

    .adres {display: flex; justify-content: center;​

    Je zou dit technisch gezien kunnen toevoegen aan het App.css-bestand, maar houd er rekening mee dat dit vrij snel rommelig kan worden. Componenten moeten herbruikbaar zijn en om zoveel mogelijk wrijving te voorkomen door uw werk in compartimenten op te delen, kan dit u onderweg hoofdpijn besparen.

    Laten we nu teruggaan naar onze App.js en ons nieuw gemaakte onderdeel importeren en ervoor zorgen dat we het aan onze terugkeer toevoegen om het weer te geven!

    Ons voltooide App.js-bestand zou er als volgt uit moeten zien

    importeer React, {useState} van "Reageer"​importeer {simpleStorage} van "./ abi / abi"​importeer Web3 van "web3"​ importeer Nav van "./components/Nav.js"​ importeren "./App.css"​importeer {makeStyles} van "@ material-ui / core / styles"​knop importeren van "@ material-ui / core / Button"​importeer TextField van "@ material-ui / core / TextField"​const useStyles = makeStyles ((theme) => ({root: { "& > ​": {margin: theme.spacing (1),},},})); const web3 = nieuwe Web3 (Web3.givenProvider); const contractAddress = "uw adres hier"​const storageContract = nieuwe web3.eth.Contract (simpleStorage, contractAddress); functie App () {const klassen = useStyles (); const [nummer, setUint] = useState (0); const [getNumber, setGet] = useState ("0"​const numberSet = async (t) => {t.preventDefault (); const accounts = wacht op window.ethereum.enable (); const account = accounts [0]; const gas = wachten storageContract.methods.set (nummer) .estimateGas (); const post = wachten storageContract.methods.set (nummer) .send ({van: account, gas,});​const numberGet = async (t) => {t.preventDefault (); const post = wachten storageContract.methods.get (). call (); setGet (plaatsen);​terugkeer ( setUint (t.target.value)} variant ="geschetst" ​> Bevestigen

    Haal uw uint256 {getNumber}); } export standaard app;

    We zouden nu ons verbonden adres bovenaan moeten zien en nog steeds al onze functionaliteit behouden!

    bonusV1

    &# 127881; We hebben het gedaan! &# 127881;

    We hebben nu een dApp die we vanaf de basis hebben opgebouwd. We hebben ons slimme contract opgenomen in een React-project, logica geschreven om ervoor te zorgen dat we gebruikersfunctionaliteit hebben, een component gemaakt om het verbonden adres weer te geven en we hebben zelfs een populair stylingraamwerk aan ons project toegevoegd.

    Goed gedaan! Dit is nog maar het begin van je Web3-ontwikkelingsavonturen en je hebt al iets om te laten zien dat je niet alleen hebt gemaakt, maar ook je hoofd eromheen hebt gewikkeld. Neem contact met ons op in de Discord en deel uw project (vooral als u wijzigingen of toevoegingen heeft aangebracht) met ons!

      Onboarding van ontwikkelaars: stap 1Stap 1 van de introductie van ontwikkelaars

      Onboarding van ontwikkelaars: stap 1

      Onboarding van ontwikkelaars: stap 2Stap 2 van de introductie van ontwikkelaars

      Onboarding van ontwikkelaars: stap 2

      10 minuten Ethereum-oriëntatie10 minuten Ethereum-oriëntatie

      10 minuten Ethereum-oriëntatie

    Mike Owergreen Administrator
    Sorry! The Author has not filled his profile.
    follow me