Gegevens uit Ethereum ophalen en bijwerken met React en SWR

blog 1NieuwsOntwikkelaarsEnterpriseBlockchain ExplainedEvenementen en conferentiesPersNieuwsbrieven

Abonneer op onze nieuwsbrief.

E-mailadres

Wij respecteren uw privacy

HomeBlogBlockchain-ontwikkeling

Gegevens uit Ethereum ophalen en bijwerken met React en SWR

Hier leest u hoe u de frontend van uw dapp configureert, zodat tokensaldi en geldoverboekingen worden bijgewerkt in de Ethereum-portefeuilles van uw gebruikers. Door Lorenzo Sicilia 18 juni 2020 Geplaatst op 18 juni 2020

gegevens ophalen met ethereum hero

Ethereum stelt ons in staat om gedecentraliseerde applicaties (dapps) te bouwen. Het belangrijkste verschil tussen een typische applicatie en een dapp is dat u geen backend hoeft te implementeren, tenminste zolang u profiteert van de andere slimme contracten die op het Ethereum-mainnet zijn geïmplementeerd.

Daardoor speelt de frontend een grote rol. Het is verantwoordelijk voor het rangschikken en unmarshalen van de gegevens van de slimme contracten, het afhandelen van de interacties met de portemonnee (hardware of software) en, zoals gewoonlijk, het beheren van de UX. Niet alleen dat, door het ontwerp, een dapp JSON-RPC-oproepen gebruikt en een socketverbinding kan openen om updates te ontvangen.

Zoals je kunt zien, zijn er een paar dingen om te orkestreren, maar maak je geen zorgen, het ecosysteem is de afgelopen maanden behoorlijk volwassen geworden.

Vereisten

Tijdens deze tutorial ga ik ervan uit dat je het volgende al hebt:

Een portemonnee om verbinding te maken met een Geth-knooppunt

De eenvoudigste benadering is MetaMask installeren zodat u kunt gebruiken Infura infrastructuur uit de doos.

Wat Ether in je account

Wanneer je ontwikkelt met Ethereum, raad ik je ten zeerste aan om over te schakelen naar een testnet en test Ether te gebruiken. Als u geld nodig heeft voor testdoeleinden, kunt u een kraan gebruiken, bijv. https://faucet.rinkeby.io/


Basiskennis van React

Ik zal je stap voor stap begeleiden, maar ik ga ervan uit dat je weet hoe React werkt (inclusief hooks). Raadpleeg het Reageer documentatie.

Een werkende React-speeltuin

Ik heb deze tutorial met Typescript geschreven, maar er zijn maar een paar dingen getypt, dus met minimale wijzigingen kun je het ook gebruiken zoals het in Javascript is. ik gebruikte Parcel.js maar voel je vrij om te gebruiken Maak een React-app too of een andere bundler voor webtoepassingen.

Maak verbinding met Ethereum Mainnet

Zodra je MetaMask klaar hebt, gaan we gebruiken web3-react om de interactie met het netwerk af te handelen. Het geeft je een behoorlijk handig hook useWeb3React, dat veel handige hulpprogramma’s bevat om met Ethereum te spelen.

garen toevoegen @ web3-react / core @ web3-react / injected-connector Code taal: CSS (css)

Dan heeft u een aanbieder nodig. Een provider abstraheert een verbinding met de Ethereum-blockchain, voor het geven van vragen en het verzenden van ondertekende statusveranderende transacties.

We zullen Web3Provider gebruiken van Ether.js.

Het lijkt al een paar bibliotheken te hebben, maar wanneer u met Ethereum communiceert, moet u Javascript-gegevenstypen vertalen naar Solidity-typen. En u moet de transacties ook ondertekenen als u een actie wilt uitvoeren. Ether.js biedt deze functionaliteiten op elegante wijze.

garen toevoegen @ ethersproject / providers Code taal: CSS (css)

opmerking: het bovenstaande Ether.js-pakket is de v5 die momenteel in bèta.

Daarna zijn we klaar om een ​​minimale hallo-wereld te noteren om te controleren of we alles hebben wat we nodig hebben:

import Reageer vanuit ‘react’ importeer {Web3ReactProvider} vanuit ‘@ web3-react / core’ importeer {Web3Provider} vanuit ‘@ ethersproject / providers’ importeer {useWeb3React} vanuit ‘@ web3-react / core’ importeer {InjectedConnector} vanuit ‘@ web3-react / injected-connector ‘export const injectedConnector = new InjectedConnector ({supportedChainIds: [1, // Mainet 3, // Ropsten 4, // Rinkeby 5, // Goerli 42, // Kovan],}) functie getLibrary (provider: elke): Web3Provider {const library = nieuwe Web3Provider (provider) library.pollingInterval = 12000 return library} export const Wallet = () => {const {chainId, account, activated, active} = useWeb3React () const onClick = () => {activeren (injectedConnector)} retour ( <div> <div>ChainId: {chainId} div> <div>Account: {account} div> {actief ?​ <div>✅ div> ​ <knoptype ="knop" onClick = {onClick}> Connect-knop> )} div> )} export const App = () => {terugkeer ( <Web3ReactProvider getLibrary = {getLibrary}> <Portemonnee /> Web3ReactProvider> )} Codetaal: JavaScript (javascript)

Als je je huiswerk hebt gedaan, zou je zoiets als dit moeten hebben:

Geïnjecteerde connector.

Hier wat we tot nu toe hebben gedaan: GIT – stap-1

Gegevens ophalen van het mainnet

ik zal gebruiken SWR om het ophalen van gegevens te beheren.

Dit is wat ik wil bereiken.

const {data: balance} = useSWR (["getBalance", account, "laatste"]) Codetaal: JavaScript (javascript)

Best stoer &# 128578;

Laten we de truc onthullen! SWR staat voor Stale-While-Revalidate, een HTTP-cache-invalidatiestrategie die populair is door RFC 5861.

SWR retourneert eerst de gegevens uit de cache (oud), verzendt vervolgens het ophaalverzoek (opnieuw valideren) en komt uiteindelijk weer met de bijgewerkte gegevens.

SWR accepteert een sleutel en achter de schermen zal het oplossen

Om dat te doen, staat SWR het passeren van een fetcher toe die de sleutel kan oplossen door een belofte te retourneren. De hallo wereld van SWR is gebaseerd op REST API-verzoeken met een fetcher gebaseerd op fetch API of Axios.

Wat briljant is aan SWR, is dat de enige vereiste om een ​​fetcher te maken, is dat het een belofte moet teruggeven.

Dus hier is mijn eerste implementatie van een fetcher voor Ethereum:

const fetcher = (bibliotheek) => (… args) => {const [method, … params] = args console.log (method, params) return library [method] (… params)} Code taal: JavaScript (javascript)

Zoals u kunt zien, is het een gedeeltelijk toegepaste functie. Op die manier kan ik de bibliotheek (mijn Web3Provider) injecteren wanneer ik de fetcher configureer. Later, elke keer dat een sleutel verandert, kan de functie worden opgelost door de vereiste belofte te retourneren.

Nu kan ik mijn component maken

export const Balance = () => {const {account, bibliotheek} = useWeb3React () const {data: balans} = useSWR ([‘getBalance’, account, ‘laatste’], {fetcher: fetcher (bibliotheek),}) if (! saldo) {return <div>…div> } terug <div>Saldo: {balance.toString ()} div> } Codetaal: JavaScript (javascript)

Het teruggezonden saldo-object is een BigNumber.

Evenwichtscomponent.

Zoals u kunt zien, is het nummer niet opgemaakt en extreem groot. Dit komt omdat Solidity Integer tot 256 bits gebruikt.

Om het nummer in een voor mensen leesbaar formaat weer te geven, gebruikt de oplossing een van de bovengenoemde hulpprogramma’s van Ether.js-hulpprogramma’s: formatEther (balans)

yarn install @ ethersproject / units Code taal: CSS (css)

Nu ik mijn component kan herwerken om de BitInt in een door mensen leesbare vorm te verwerken en op te maken:

export const Balance = () => {const {account, bibliotheek} = useWeb3React () const {data: balans} = useSWR ([‘getBalance’, account, ‘laatste’], {fetcher: fetcher (bibliotheek),}) if (! saldo) {return <div>…div> } terug <div>Ξ {parseFloat (formatEther (balans)). ToPrecision (4)} div> } Codetaal: JavaScript (javascript) BitInt in een door mensen leesbare vorm.

dit hebben we tot nu toe gedaan: GIT stap-2

Hoe u de gegevens in realtime kunt bijwerken

SWR stelt een mutatiefunctie beschikbaar om de interne cache bij te werken.

const {data: balans, muteren} = useSWR ([‘getBalance’, account, ‘laatste’], {fetcher: fetcher (bibliotheek),}) const onClick = () => {mutate (new BigNumber (10), false)} Codetaal: JavaScript (javascript)

De mutatiefunctie is automatisch gebonden aan de sleutel (bijv. [‘GetBalance’, account, ‘latest’] waaruit het is gegenereerd. Het accepteert twee parameters. De nieuwe gegevens en of er een validatie moet worden geactiveerd. Indien nodig, SWR zal automatisch de fetcher gebruiken om de cache bij te werken &# 128165;

Zoals verwacht, geven Solidity-evenementen een kleine abstractie bovenop de logfunctie van de EVM. Applicaties kunnen zich abonneren op deze evenementen en ernaar luisteren via de RPC-interface van een Ethereum-client.

Ether.js heeft een eenvoudige API om je op een evenement te abonneren:

const {account, bibliotheek} = useWeb3React () bibliotheek.on ("blokkeer nummer", (blockNumber) => {console.log ({blockNumber})}) Codetaal: JavaScript (javascript)

Laten we nu beide benaderingen combineren in de nieuwe component

export const Balance = () => {const {account, bibliotheek} = useWeb3React () const {data: balans, mutate} = useSWR ([‘getBalance’, account, ‘laatste’], {fetcher: fetcher (bibliotheek),}) useEffect (() => {// luister naar wijzigingen op een Ethereum-adres console.log (`listening for blocks …`) library.on (‘block’, () => {console.log (‘update balance …’) mutate (undefined, true)}) // verwijder listener wanneer de component niet is gemonteerd return () => {library.removeAllListeners (‘block’)} // activeer het effect alleen op component mount}, []) if (! balance) {return <div>…div> } terug <div>Ξ {parseFloat (formatEther (balans)). ToPrecision (4)} div> } Codetaal: JavaScript (javascript)

In eerste instantie zal SWR het rekeningsaldo ophalen en vervolgens elke keer dat het een blokgebeurtenis ontvangt, zal het muteren gebruiken om een ​​opnieuw ophalen te activeren.

opmerking: we hebben muteren (ongedefinieerd, waar) gebruikt omdat we het werkelijke saldo niet kunnen achterhalen uit de huidige gebeurtenis, we activeren alleen het opnieuw ophalen van het saldo.

Hieronder vindt u een korte demo met twee Ethereum-portefeuilles die wat ETH uitwisselen.

Demo van twee Ethereum-portefeuilles die ETH uitwisselen.

Hier wat we tot nu toe hebben gedaan: GIT stap-3

Hoe om te gaan met een slim contract

Tot dusverre hebben we de basisprincipes van het gebruik van SWR geïllustreerd en hoe u een basisgesprek kunt voeren via een Web3Provider. Laten we nu eens kijken hoe we kunnen omgaan met een slim contract.

Ether.js verwerkt slimme contractinteractie met behulp van de Contract Application Binary Interface (ABI) ABI gegenereerd door de Solidity Compiler.

De Contract Application Binary Interface (ABI) is de standaardmanier om te communiceren met contracten in het Ethereum-ecosysteem, zowel van buiten de blockchain als voor contract-tot-contract-interactie.

Gezien het onderstaande eenvoudige slimme contract bijvoorbeeld:

pragma stevigheid ^ 0,5,0; contract Test {constructor () openbaar {b = hex"12345678901234567890123456789012"​} event Event (uint geïndexeerd a, bytes32 b); event Event2 (uint geïndexeerd a, bytes32 b); functie foo (uint a) public {emit Event (a, b); } bytes32 b; } Codetaal: JavaScript (javascript)

dit is de gegenereerde ABI

​ "type"​ "evenement", "ingangen"​ "naam"​ "een", "type"​ "uint256", "geïndexeerd": true}, { "naam"​ "b", "type"​ "bytes32", "geïndexeerd": false}], "naam"​ "Evenement" ​ "type"​ "evenement", "ingangen"​ "naam"​ "een", "type"​ "uint256", "geïndexeerd": true}, { "naam"​ "b", "type"​ "bytes32", "geïndexeerd": false}], "naam"​ "Evenement2" ​ "type"​ "functie", "ingangen"​ "naam"​ "een", "type"​ "uint256" ​, "naam"​ "foo", "uitgangen": []}] Codetaal: JSON / JSON met opmerkingen (json)

Om de ABI’s te gebruiken, kunnen we ze eenvoudig rechtstreeks in uw code kopiëren en ze waar nodig importeren. In deze demo gebruiken we een standaard ERC20 ABI omdat we de saldi van twee tokens willen ophalen: DAI en MKR.

De volgende stap is het maken van de component

export const TokenBalance = ({symbool, adres, decimalen}) => {const {account, bibliotheek} = useWeb3React () const {data: balans, muteren} = useSWR ([adres, ‘balanceOf’, account], {fetcher: fetcher (bibliotheek, ERC20ABI),}) useEffect (() => {// luister naar wijzigingen op een Ethereum-adres console.log (`listening for Transfer …`) const contract = new Contract (address, ERC20ABI, library.getSigner ()) const fromMe = contract.filters.Transfer (account, null) library.on (fromMe, (from, to, amount, event) => {console.log (‘Transfer | sent’, {from, to, amount, event}) mutate (undefined, true)}) const toMe = contract.filters.Transfer (null, account) library.on (toMe, (from , to, amount, event) => {console.log (‘Overdracht | ontvangen’, {van, naar, bedrag, gebeurtenis}) muteren (ongedefinieerd, waar)}) // verwijder luisteraar wanneer de component niet is gekoppeld return () => {library.removeAllListeners (toMe) library.removeAllListeners (fromMe)} // activeer het effect alleen op component mount}, []) if (! balance) {return <div>…div> } terugkeer ( <div> {parseFloat (formatUnits (balans, decimalen)). toPrecision (4)} {symbol} div> )} Codetaal: JavaScript (javascript)

Laten we eens inzoomen. Er zijn twee belangrijke verschillen:

Sleutel definitie

De sleutel, gebruikt door useSWR ([adres, ‘balanceOf’, account])), moet beginnen met een Ethereum-adres in plaats van een methode. Hierdoor kan de fetcher herkennen wat we willen bereiken en de ABI gebruiken.

Laten we de fetcher dienovereenkomstig refactoren:

const fetcher = (bibliotheek: Web3Provider, abi ?: any) => (… args) => {const [arg1, arg2, … params] = args // het is een contract if (isAddress (arg1)) {const adres = arg1 const methode = arg2 const contract = nieuw contract (adres, abi, library.getSigner () ) retour contract [methode] (… params)} // het is een aanroep eth const methode = arg1 terugkeer bibliotheek [methode] (arg2, … params)} Code taal: JavaScript (javascript)

Nu hebben we een fetcher voor algemeen gebruik die in staat is om te communiceren met de JSON-RPC-aanroepen van Ethereum. &# 128588;

Logboekfilters

Het andere aspect is hoe te luisteren naar de ERC20-evenementen. Ether.js biedt een handige manier om een ​​filter te configureren op basis van de onderwerpen en de naam van de gebeurtenis. Meer informatie over wat een onderwerp is, is te vinden in het Solidity docs.

const contract = nieuw contract (adres, ERC20ABI, library.getSigner ()) const fromMe = contract.filters.Transfer (account, null) Codetaal: JavaScript (javascript)

Nadat u een contractinstantie heeft gebouwd met de ABI, kunt u het filter doorgeven aan de bibliotheekinstantie.

Waarschuwing:

U zou in de verleiding kunnen komen om het bedrag in het ERC20-evenement rechtstreeks te gebruiken om het saldo te verhogen of te verlagen.

Pas op voor de draak. Toen je de fetcher instelde, gaf je een clojure door als callback naar de on-functie, die de balanswaarde op dat moment bevatte.

Dit kan worden opgelost met een useRef, maar laten we voor de eenvoud de cache opnieuw valideren om er zeker van te zijn dat de saldi vers zijn: mutate (undefined, true)

We hebben nu alle benodigde stukken. Het laatste stukje is een beetje lijm.

Ik heb een paar constanten geconfigureerd om een ​​leuke manier te hebben om mijn TokenBalance-component toe te wijzen aan een lijst met tokens, afhankelijk van het netwerk waarin we werken:

export const Networks = {MainNet: 1, Rinkeby: 4, Ropsten: 3, Kovan: 42,} export interface IERC20 {symbol: string adres: string decimalen: nummer naam: string} export const TOKENS_BY_NETWORK: {[key: number]: IERC20 []} = {[Networks.Rinkeby]: [{adres: "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa", symbool: "DAI", naam: "Dai", decimalen: 18,}, {adres: "0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85", symbool: "MKR", naam: "Maker", decimalen: 18,},],} Codetaal: JavaScript (javascript)

Zodra we de constanten hebben, is het gemakkelijk om de geconfigureerde tokens toe te wijzen aan mijn component:

export const TokenList = ({chainId}) => {terugkeer ( <> {TOKENS_BY_NETWORK [chainId] .map ((token) => ​ <TokenBalance-sleutel = {token.address} {… token} /> ))})} Codetaal: JavaScript (javascript)

Helemaal klaar! Nu hebben we een Ethereum-portemonnee die ether- en tokensaldi laadt. En als de gebruiker geld verstuurt of ontvangt, wordt de gebruikersinterface van de portemonnee bijgewerkt.

Een Ethereum-portemonnee die ether- en token-saldi laadt.

Dit is wat we tot nu toe hebben gedaan: GIT stap-4

Refactoring

Laten we elke component in een apart bestand verplaatsen en de fetcher wereldwijd beschikbaar maken met behulp van de SWRConfig-provider.

<SWRConfig-waarde = {{fetcher: fetcher (bibliotheek, ERC20ABI)}}> <EthBalance /> <TokenList chainId = {chainId} /> <SWRConfig />Codetaal: HTML, XML (xml)

Met SWRConfig kunnen we sommige opties configureren zoals altijd beschikbaar, zodat we gemakkelijker gebruik kunnen maken van SWR.

const {data: balance, mutate} = useSWR ([adres, ‘balanceOf’, account]) Code taal: JavaScript (javascript)

Hier is alles na de refactoring: GIT stap-5

Afronden

SWR en Ether.js zijn twee leuke bibliotheken om mee te werken als u uw strategie voor het ophalen van gegevens wilt stroomlijnen met Ethereum dapp.

Belangrijkste voordelen
  • Declaratieve benadering
  • Gegevens altijd vers via websockets of SWR-opties
  • Voorkom dat u het wiel voor statusbeheer opnieuw uitvindt met aangepaste React-context

Als je meerdere slimme contracten in je dapp gebruikt en je deze tutorial leuk vond, heb ik de web3-fetcher gegeneraliseerd tot een kleine util: swr-eth (Sterren worden gewaardeerd &# 128123;)

En tot slot, hier is de volledige GIT-repo: (https://github.com/aboutlo/swr-eth-tutorial​.

Haal meer Ethereum-zelfstudies rechtstreeks in uw inbox

Abonneer u op onze nieuwsbrief voor de nieuwste Ethereum-ontwikkelaarscursussen, tools, professionele tips en meer. Meld u aan voor onze nieuwsbrief voor het laatste Ethereum-nieuws, bedrijfsoplossingen, bronnen voor ontwikkelaars en meer.Hoe u een succesvol blockchain-product bouwtWebinar

Hoe u een succesvol blockchain-product bouwt

Hoe u een Ethereum-knooppunt instelt en uitvoertWebinar

Hoe u een Ethereum-knooppunt instelt en uitvoert

Hoe u uw eigen Ethereum-API kunt bouwenWebinar

Hoe u uw eigen Ethereum-API kunt bouwen

Hoe u een sociaal token maaktWebinar

Hoe u een sociaal token maakt

Beveiligingshulpmiddelen gebruiken bij slimme contractontwikkelingWebinar

Beveiligingshulpmiddelen gebruiken bij slimme contractontwikkeling

De toekomst van digitale activa en defiWebinar

De toekomst van financiën: digitale activa en deFi

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me
Like this post? Please share to your friends:
Adblock
detector
map