blogul 1NewsDevelopersEnterpriseBlockchain Explained Evenimente și conferințe ApăsațiBuletine informative

Aboneaza-te la newsletter-ul nostru.

Adresa de email

Vă respectăm confidențialitatea

AcasăBlogDezvoltare blockchain

Cum să extrageți și să actualizați datele din Ethereum cu React și SWR

Iată cum să configurați frontend-ul Dapp, astfel încât soldurile simbolice și transferurile de fonduri să fie actualizate în portofelele Ethereum ale utilizatorilor dvs. de Lorenzo Sicilia 18 iunie 2020 Postat pe 18 iunie 2020

obțineți date cu eroul ethereum

Ethereum ne permite să construim aplicații descentralizate (dapps). Principala diferență între o aplicație tipică și un dapp este că nu este nevoie să implementați un backend – cel puțin atâta timp cât profitați de celelalte contracte inteligente desfășurate pe rețeaua principală Ethereum.

Din acest motiv, frontendul joacă un rol major. Este însărcinat să organizeze și să elimine datele din contractele inteligente, să gestioneze interacțiunile cu portofelul (hardware sau software) și, ca de obicei, să gestioneze UX. Nu numai că, prin design, un dapp folosește apeluri JSON-RPC și poate deschide o conexiune socket pentru a primi actualizări.

După cum puteți vedea, există câteva lucruri de orchestrat, dar nu vă faceți griji, ecosistemul s-a maturizat destul de mult în ultimele luni.

Condiții prealabile

În timpul acestui tutorial, voi presupune că aveți deja următoarele:

Un portofel pentru conectarea la un nod Geth

Cea mai simplă abordare este instalarea MetaMask astfel încât să puteți folosi Infura infrastructură scoasă din cutie.

Câteva etere din contul tău

Când vă dezvoltați cu Ethereum, vă sfătuiesc cu tărie să treceți la un testnet și să utilizați testul Ether. Dacă aveți nevoie de fonduri pentru testare, puteți folosi un robinet de ex. https://faucet.rinkeby.io/

Înțelegerea de bază a React

Vă voi ghida pas cu pas, dar voi presupune că știți cum funcționează React (inclusiv cârlige). Dacă ceva pare necunoscut consultați Reacționează documentația.

Un loc de joacă React care funcționează

Am scris acest tutorial cu Typescript, dar doar câteva lucruri sunt tastate, astfel încât, cu modificări minime, îl puteți folosi așa cum este și în Javascript. obisnuiam Parcel.js dar nu ezitați să utilizați Creați aplicația React sau alt pachet de aplicații web.

Conectați-vă la Ethereum Mainnet

Odată ce ați pregătit MetaMask, vom folosi web3-reacționează pentru a gestiona interacțiunea cu rețeaua. Vă va oferi un cârlig destul de la îndemână să folosiți Web3React, care conține multe utilități utile pentru a vă juca cu Ethereum.

fire add @ web3-react / core @ web3-react / injected-connector Limbaj cod: CSS (css)

Atunci ai nevoie de un furnizor. Un furnizor abstractizează o conexiune la blockchain-ul Ethereum, pentru emiterea de interogări și trimiterea de tranzacții semnate care schimbă starea.

Vom folosi Web3Provider de la Ether.js.

Se pare că are deja câteva biblioteci, dar când interacționați cu Ethereum, trebuie să traduceți tipurile de date Javascript în cele Solidity. De asemenea, vi se cere să semnați tranzacțiile atunci când doriți să executați o acțiune. Ether.js oferă elegant aceste funcționalități.

fire add @ ethersproject / provider Limba codului: CSS (css)

notă: pachetul Ether.js de mai sus este v5 în prezent beta.

După aceea, suntem gata să notăm o lume minunată de salut pentru a verifica dacă avem tot ce ne trebuie:

import React from ‘react’ import {Web3ReactProvider} from ‘@ web3-react / core’ import {Web3Provider} from ‘@ ethersproject / providers’ import {useWeb3React} from ‘@ web3-react / core’ import {InjectedConnector} from ‘@ web3-react / injected-connector ‘export const injectedConnector = new InjectedConnector ({supportedChainIds: [1, // Mainet 3, // Ropsten 4, // Rinkeby 5, // Goerli 42, // Kovan],}) funcție getLibrary (furnizor: orice): Web3Provider {const library = new Web3Provider (provider) library.pollingInterval = 12000 return library} export const Wallet = () => {const {chainId, account, activate, active} = useWeb3React () const onClick = () => {activate (injectedConnector)} returnează ( <div> <div>ChainId: {chainId} div> <div>Cont: {account} div> {activ? ( <div>✅ div> ): ( <tip buton ="buton" onClick = {onClick}> Butonul Conectare> )} div> )} export const App = () => { întoarcere ( <Web3ReactProvider getLibrary = {getLibrary}> <Portofel /> Web3ReactProvider> )} Limba codului: JavaScript (javascript)

Dacă ți-ai făcut temele ar trebui să ai așa ceva:

Conector injectat.

Iată ce am făcut până acum: GIT – pasul 1

Cum să preluați date de pe Mainnet

voi folosi SWR pentru a gestiona preluarea datelor.

Asta vreau să realizez.

const {data: balance} = useSWR (["getBalance", cont, "cele mai recente"]) Limba codului: JavaScript (javascript)

Destul de mișto &# 128578;

Să dezvăluim trucul! SWR înseamnă Stale-While-Revalidate, o strategie de invalidare a cache-ului HTTP popularizată de RFC 5861.

SWR returnează mai întâi datele din memorie cache (învechite), apoi trimite cererea de preluare (revalidează) și, în cele din urmă, vine din nou cu datele actualizate.

SWR acceptă o cheie și în culise va reuși să se rezolve

Pentru a face acest lucru SWR permite trecerea unui căpătător capabil să rezolve cheia prin returnarea unei promisiuni. Bună ziua lumea SWR se bazează pe cererile API REST cu un preluator bazat pe preluarea API sau Axios.

Ceea ce este strălucit la SWR este că singura cerință pentru a crea un fetcher este că trebuie să returneze o promisiune.

Așadar, iată prima mea implementare a unui fetcher pentru Ethereum:

const fetcher = (biblioteca) => (… args) => {const [method, … params] = args console.log (method, params) returnează biblioteca [method] (… params)} Limbajul codului: JavaScript (javascript)

După cum puteți vedea, este o funcție parțial aplicată. În acest fel, pot injecta biblioteca (Web3Provider-ul meu) când configurez recuperatorul. Mai târziu, de fiecare dată când se schimbă o cheie, funcția poate fi rezolvată prin returnarea promisiunii solicitate.

Acum îmi pot crea componenta

export const Sold = () => {const {account, library} = useWeb3React () const {data: balance} = useSWR ([‘getBalance’, account, ‘latest’], {fetcher: fetcher (library),}) if (! balance) {return <div>…div> } întoarcere <div>Sold: {balance.toString ()} div> } Limba codului: JavaScript (javascript)

Obiectul de sold returnat este un număr mare.

Componenta echilibrului.

După cum puteți vedea, numărul nu este formatat și extrem de mare. Acest lucru se datorează faptului că Solidity folosește întregul până la 256 de biți.

Pentru a afișa numărul într-un format lizibil de către om, soluția utilizează unul dintre utilitarele menționate mai sus din utilitarele Ether.js: formatEther (echilibru)

yarn install @ ethersproject / units Limba codului: CSS (css)

Acum, că îmi pot reface componenta pentru a gestiona și a forma BitInt într-o formă lizibilă de către om:

export const Sold = () => {const {account, library} = useWeb3React () const {data: balance} = useSWR ([‘getBalance’, account, ‘latest’], {fetcher: fetcher (library),}) if (! balance) {return <div>…div> } întoarcere <div>Ξ {parseFloat (formatEther (sold)). ToPrecision (4)} div> } Limba codului: JavaScript (javascript) BitInt într-o formă lizibilă de om.

asta am făcut până acum: GIT pasul 2

Cum se actualizează datele în timp real

SWR expune o funcție de mutare pentru a-și actualiza memoria cache internă.

const {data: balance, mutate} = useSWR ([‘getBalance’, account, ‘latest’], {fetcher: fetcher (library),}) const onClick = () => {mutare (nou BigNumber (10), fals)} Limbajul codului: JavaScript (javascript)

Funcția de mutare este legată automat de cheie (de exemplu [„getBalance”, cont, „latest”] din care a fost generată. Acceptă doi parametri. Noile date și dacă ar trebui declanșată o validare. Dacă ar trebui, SWR va folosi automat recuperatorul pentru a actualiza memoria cache &# 128165;

Așa cum era de așteptat, evenimentele Solidity oferă o mică abstracție pe lângă funcționalitatea de înregistrare a EVM. Aplicațiile se pot abona și asculta aceste evenimente prin interfața RPC a unui client Ethereum.

Ether.js are un API simplu pentru a vă abona la un eveniment:

const {account, library} = useWeb3React () library.on ("blockNumber", (Număr bloc) => {console.log ({blockNumber})}) Limba codului: JavaScript (javascript)

Acum să combinăm ambele abordări în noua componentă

export const Sold = () => {const {account, library} = useWeb3React () const {data: balance, mutate} = useSWR ([‘getBalance’, account, ‘latest’], {fetcher: fetcher (library),}) useEffect (() => {// ascultați modificările pe o adresă Ethereum console.log (`ascultarea blocurilor …`) library.on (‘bloc’, () => {console.log (‘actualizați soldul …’) mutați (nedefinit, adevărat)}) // eliminați ascultătorul atunci când componenta este nemontată return () => {library.removeAllListeners (‘bloc’)} // declanșează efectul numai pe montarea componentelor}, []) dacă (! sold) {return <div>…div> } întoarcere <div>Ξ {parseFloat (formatEther (sold)). ToPrecision (4)} div> } Limba codului: JavaScript (javascript)

Inițial, SWR va prelua soldul contului și apoi, de fiecare dată când primește un eveniment de blocare, va folosi mutarea pentru a declanșa o recuperare.

notă: am folosit mutare (nedefinit, adevărat) deoarece nu putem extrage din evenimentul curent soldul real, ci doar declanșăm o recuperare a soldului.

Mai jos este o demonstrație rapidă cu două portofele Ethereum care schimbă niște ETH.

Demo-ul a două portofele Ethereum care schimbă ETH.

Iată ce am făcut până acum: GIT pasul 3

Cum să interacționați cu un contract inteligent

Până în prezent am ilustrat elementele de bază ale utilizării SWR și modul de efectuare a unui apel de bază prin intermediul unui Web3Provider. Să descoperim acum cum să interacționăm cu un contract inteligent.

Ether.js gestionează interacțiunea contractelor inteligente utilizând ABI (Contract Application Binary Interface) ABI generată de Solidity Compiler.

Interfața binară de aplicare a contractului (ABI) este modalitatea standard de a interacționa cu contractele din ecosistemul Ethereum, atât din afara blockchain-ului, cât și pentru interacțiunea contract-la-contract.

De exemplu, având în vedere contractul inteligent simplu de mai jos:

soliditatea pragmei ^ 0,5,0; contract Test {constructor () public {b = hex"12345678901234567890123456789012"; } eveniment Eveniment (uint indexat a, bytes32 b); eveniment Event2 (uint indexat a, bytes32 b); function foo (uint a) public {emit Eveniment (a, b); } octeți32 b; } Limba codului: JavaScript (javascript)

acesta este ABI generat

[{ "tip": "eveniment", "intrări": [{ "Nume": "A", "tip": "uint256", "indexat": Adevărat }, { "Nume": "b", "tip": "octeți32", "indexat": fals } ], "Nume": "Eveniment" }, { "tip": "eveniment", "intrări": [{ "Nume": "A", "tip": "uint256", "indexat": Adevărat }, { "Nume": "b", "tip": "octeți32", "indexat": fals } ], "Nume": "Eveniment2" }, { "tip": "funcţie", "intrări": [{ "Nume": "A", "tip": "uint256" }], "Nume": "foo", "ieșiri": []}] Limbajul codului: JSON / JSON cu Comentarii (json)

Pentru a utiliza ABI-urile, le putem copia pur și simplu direct în codul dvs. și le putem importa acolo unde este necesar. În această demonstrație, vom folosi un standard ERC20 ABI pentru că vrem să recuperăm soldurile a două jetoane: DAI și MKR.

Următorul pas este crearea componentei

export const TokenBalance = ({simbol, adresă, zecimale}) => {const {account, library} = useWeb3React () const {data: balance, mutate} = useSWR ([adresa, ‘balanceOf’, cont], {fetcher: fetcher (biblioteca, ERC20ABI),}) useEffect (() => {// ascultați modificările unei adrese Ethereum console.log (`ascultând Transfer …`) const contract = contract nou (adresa, ERC20ABI, library.getSigner ()) const fromMe = contract.filters.Transfer (cont, null) library.on (fromMe, (from, to, amount, event) => {console.log (‘Transfer | trimis’, {din, către, suma, eveniment}) mutare (nedefinit, adevărat)}) const toMe = contract.filters.Transfer (nul, cont) library.on (toMe, (din , la, suma, eveniment) => {console.log (‘Transfer | primit’, {de la, la, suma, eveniment}) mutați (nedefinit, adevărat)}) // eliminați ascultătorul atunci când componenta este nemontată return () => {library.removeAllListeners (toMe) library.removeAllListeners (fromMe)} // declanșează efectul doar pe montarea componentelor}, []) dacă (! balance) {return <div>…div> } întoarcere ( <div> {parseFloat (formatUnități (sold, zecimale)). toPrecision (4)} {simbol} div> )} Limba codului: JavaScript (javascript)

Să mărim. Există două diferențe principale:

Definiție cheie

Cheia, utilizată de useSWR ([address, ‘balanceOf’, account])), trebuie să înceapă mai degrabă cu o adresă Ethereum decât cu o metodă. Din această cauză, căutătorul poate recunoaște ceea ce vrem să realizăm și să folosim ABI.

Să refacturăm căutătorul în consecință:

const fetcher = (biblioteca: Web3Provider, abi ?: any) => (… args) => {const [arg1, arg2, … params] = args // este un contract if (isAddress (arg1)) {const address = arg1 const method = arg2 const contract = new Contract (address, abi, library.getSigner () ) return return [method] (… params)} // este o metodă eth call const = arg1 return bibliotecă [method] (arg2, … params)} Limbajul codului: JavaScript (javascript)

Acum avem un recuperator cu scop general capabil să interacționeze cu apelurile JSON-RPC ale Ethereum. &# 128588;

Filtre jurnal

Celălalt aspect este cum să ascultați evenimentele ERC20. Ether.js oferă o modalitate utilă de a configura un filtru bazat pe subiectele și numele evenimentului. Mai multe informații despre ceea ce este un subiect pot fi găsite în Documente de soliditate.

contract contract = contract nou (adresa, ERC20ABI, library.getSigner ()) const fromMe = contract.filters.Transfer (cont, nul) Limba codului: JavaScript (javascript)

Odată ce ați creat o instanță contractuală cu ABI, puteți transmite filtrul instanței bibliotecii.

Avertizare:

Ați putea fi tentați să utilizați suma din evenimentul ERC20 direct pentru a mări sau micșora soldul.

Fii conștient de dragon. Când configurați recuperatorul, ați trecut un clojure ca apel invers la funcția on, care conținea valoarea soldului la momentul respectiv.

Acest lucru ar putea fi remediat folosind un useRef, dar, din motive de simplitate, să revalidăm memoria cache pentru a ne asigura că soldurile sunt noi: mutare (nedefinit, adevărat)

Acum avem toate piesele necesare. Ultimul bit este un pic de lipici.

Am configurat câteva constante pentru a avea un mod frumos de a mapa componenta mea TokenBalance la o listă de jetoane în funcție de rețeaua în care lucrăm:

export const Networks = {MainNet: 1, Rinkeby: 4, Ropsten: 3, Kovan: 42,} export interface IERC20 {symbol: string address: string decimals: number name: string} export const TOKENS_BY_NETWORK: {[key: number]: IERC20 []} = {[Networks.Rinkeby]: [{adresa: "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa", simbol: "DAI", Nume: "Dai", zecimale: 18,}, {adresa: "0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85", simbol: "MKR", Nume: "Producător", zecimale: 18,},],} Limbajul codului: JavaScript (javascript)

Odată ce avem constantele, este ușor să mapez jetoanele configurate la componenta mea:

export const TokenList = ({chainId}) => { întoarcere ( <> {TOKENS_BY_NETWORK [chainId] .map ((token) => ( <TokenBalance cheie = {token.address} {… token} /> ))})} Limba codului: JavaScript (javascript)

Gata! Acum avem un portofel Ethereum care încarcă eter și solduri simbolice. Și dacă utilizatorul trimite sau primește fonduri, interfața de utilizare a portofelului este actualizată.

Un portofel Ethereum care încarcă eter și solduri simbolice.

Iată ce am făcut până acum: GIT pasul 4

Refactorizare

Să mutăm fiecare componentă dintr-un fișier separat și să facem căutarea să fie disponibilă la nivel global utilizând furnizorul SWRConfig.

<SWRConfig value = {{fetcher: fetcher (biblioteca, ERC20ABI)}}> <EthBalance /> <TokenList chainId = {chainId} /> <SWRConfig />Limbaj cod: HTML, XML (xml)

Cu SWRConfig putem configura unele opțiuni ca întotdeauna disponibile, astfel încât să putem avea o utilizare mai convenabilă a SWR.

const {data: balance, mutate} = useSWR ([adresa, „balanceOf”, cont]) Limba codului: JavaScript (javascript)

Iată totul după refactorizare: GIT pasul 5

Învelire

SWR și Ether.js sunt două biblioteci frumoase cu care puteți lucra dacă doriți să vă simplificați strategia de preluare a datelor cu Ethereum dapp.

Avantaje cheie
  • Abordare declarativă
  • Date mereu noi prin socketuri web sau opțiuni SWR
  • Evitați să reinventați roata pentru gestionarea stării cu context personalizat React

Dacă utilizați mai multe contracte inteligente în dapp și v-a plăcut acest tutorial, am generalizat căutătorul web3 într-o mică utilizare: swr-eth (Stelele sunt apreciate &# 128123;)

Și, în sfârșit, iată repo GIT complet: (https://github.com/aboutlo/swr-eth-tutorial).

Obțineți mai multe tutoriale Ethereum direct în Mesaje primite

Abonați-vă la newsletter-ul nostru pentru cele mai recente cursuri, instrumente, sfaturi profesionale și multe altele pentru dezvoltatori Ethereum. InfuraMetaMaskNewsletter Abonați-vă la newsletter-ul nostru pentru cele mai recente știri Ethereum, soluții pentru întreprinderi, resurse pentru dezvoltatori și multe altele. Adresa de e-mail Conținut exclusivCum să construiți un produs Blockchain de succesWebinar

Cum să construiți un produs Blockchain de succes

Cum se configurează și se execută un nod EthereumWebinar

Cum se configurează și se execută un nod Ethereum

Cum să vă construiți propriul API EthereumWebinar

Cum să vă construiți propriul API Ethereum

Cum să creați un simbol socialWebinar

Cum să creați un simbol social

Utilizarea instrumentelor de securitate în dezvoltarea contractelor inteligenteWebinar

Utilizarea instrumentelor de securitate în dezvoltarea contractelor inteligente

Viitorul activelor digitale și al DeFi-ului financiarWebinar

Viitorul finanțelor: active digitale și DeFi

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