blog 1AktualnościDevelopersEnterpriseBlockchain ExplainedWydarzenia i konferencjePrasaBiuletyny

Zapisz się do naszego newslettera.

Adres e-mail

Szanujemy twoją prywatność

HomeBlogBlockchain Development

Jak pobierać i aktualizować dane z Ethereum za pomocą React i SWR

Oto jak skonfigurować frontend swojego dapp, aby salda tokenów i transfery środków aktualizowały się w portfelach Ethereum użytkowników. Autor: Lorenzo Sicilia 18 czerwca 2020 Opublikowane 18 czerwca 2020

pobierz dane za pomocą ethereum hero


Ethereum pozwala nam budować zdecentralizowane aplikacje (dapps). Główna różnica między typową aplikacją a dappem polega na tym, że nie musisz wdrażać zaplecza – przynajmniej tak długo, jak korzystasz z innych inteligentnych kontraktów wdrożonych w sieci głównej Ethereum.

Z tego powodu frontend odgrywa główną rolę. Odpowiada za organizowanie i wycofywanie danych z inteligentnych kontraktów, obsługę interakcji z portfelem (sprzętem lub oprogramowaniem) i, jak zwykle, zarządzanie UX. Co więcej, zgodnie z projektem dapp używa wywołań JSON-RPC i może otwierać połączenie przez gniazdo, aby otrzymywać aktualizacje.

Jak widać, jest kilka rzeczy do zaaranżowania, ale nie martw się, ekosystem dość mocno dojrzał w ciągu ostatnich kilku miesięcy.

Wymagania wstępne

Podczas tego samouczka zakładam, że masz już następujące elementy:

Portfel do połączenia z węzłem Geth

Najprostsze podejście to instalowanie MetaMask abyś mógł użyć Infura infrastruktura po wyjęciu z pudełka.

Trochę Ether na twoim koncie

Kiedy programujesz z Ethereum, zdecydowanie radzę przełączyć się na testnet i użyć testowego Ether. Jeśli potrzebujesz środków na testowanie, możesz skorzystać z kranu np. https://faucet.rinkeby.io/

Podstawowe rozumienie React

Poprowadzę Cię krok po kroku, ale założę, że wiesz, jak działa React (w tym hooki). Jeśli coś wydaje się nieznane, skonsultuj się z Reaguj dokumentację.

Działający plac zabaw dla React

Napisałem ten samouczek za pomocą Typescript, ale wpisano tylko kilka rzeczy, więc przy minimalnych zmianach możesz go używać tak samo, jak w Javascript. użyłem Parcel.js ale zachęcamy do korzystania Utwórz aplikację React też lub inny pakiet aplikacji internetowych.

Połącz się z Ethereum Mainnet

Po przygotowaniu MetaMask będziemy używać web3-reaguj do obsługi interakcji z siecią. Daje ci to całkiem poręczny hook useWeb3React, który zawiera wiele przydatnych narzędzi do zabawy z Ethereum.

yarn add @ web3 -active / core @ web3 -active / injected-connectorJęzyk kodu: CSS (css)

W takim razie potrzebujesz dostawcy. Dostawca wyodrębnia połączenie z łańcuchem bloków Ethereum w celu wysyłania zapytań i wysyłania podpisanych transakcji zmieniających stan.

Będziemy używać Web3Provider z Ether.js.

Wygląda na to, że ma już kilka bibliotek, ale podczas interakcji z Ethereum musisz przetłumaczyć typy danych Javascript na Solidity. Musisz także podpisać transakcje, gdy chcesz wykonać akcję. Ether.js elegancko zapewnia te funkcje.

przędza dodaj @ ethersproject / providerJęzyk kodu: CSS (css)

uwaga: powyższy pakiet Ether.js jest obecnie w wersji v5 beta.

Następnie możemy zanotować minimalny świat powitania, aby sprawdzić, czy mamy wszystko, czego potrzebujemy:

importuj React z „reaguj” importuj {Web3ReactProvider} z „@ web3-react / core” importuj {Web3Provider} z „@ ethersproject / dostawców” importuj {useWeb3React} z „@ web3-reag / core” importuj {InjectedConnector} z „@ web3 -active / injected-connector ‘export const injectedConnector = new InjectedConnector ({supportedChainIds: [1, // Mainet 3, // Ropsten 4, // Rinkeby 5, // Goerli 42, // Kovan],}) function getLibrary (dostawca: dowolny): Web3Provider {const biblioteka = nowa biblioteka Web3Provider (dostawca ).pollingInterval = 12000 zwracana biblioteka} eksportuj const Wallet = () => {const {chainId, account, activ, active} = useWeb3React () const onClick = () => {uaktywnij (injectedConnector)} return ( <div> <div>ChainId: {chainId} div> <div>Konto: {konto} div> {aktywny? ( <div>✅ div> ): ( <typ przycisku ="przycisk" onClick = {onClick}> Przycisk Połącz> )} div> )} eksportuj const App = () => { powrót ( <Web3ReactProvider getLibrary = {getLibrary}> <Portfel /> Web3ReactProvider> )} Język kodu: JavaScript (javascript)

Jeśli odrobiłeś pracę domową, powinieneś mieć coś takiego:

Złącze wtryskowe.

Oto co zrobiliśmy do tej pory: GIT – krok 1

Jak pobrać dane z sieci głównej

Użyję SWR do zarządzania pobieraniem danych.

To jest to, co chcę osiągnąć.

const {data: balance} = useSWR (["getBalance", konto, "najnowszy"]) Język kodu: JavaScript (javascript)

Całkiem fajne &# 128578;

Odsłońmy sztuczkę! SWR oznacza Stale-While-Revalidate, strategię unieważniania pamięci podręcznej HTTP spopularyzowaną przez RFC 5861.

SWR najpierw zwraca dane z pamięci podręcznej (nieaktualne), następnie wysyła żądanie pobrania (rewalidacja), a na koniec ponownie dostarcza aktualne dane.

SWR akceptuje klucz i za kulisami zdoła rozwiązać

Aby to zrobić, SWR umożliwia przekazanie modułu pobierającego zdolnego do rozpoznania klucza poprzez zwrócenie obietnicy. Hello world SWR opiera się na żądaniach REST API z fetcherem opartym na fetch API lub Axios.

Wspaniałe w SWR jest to, że jedynym wymaganiem do stworzenia modułu pobierającego jest zwrot obietnicy.

Oto moja pierwsza implementacja modułu pobierania dla Ethereum:

const fetcher = (biblioteka) => (… argumenty) => {const [metoda, … params] = args console.log (metoda, parametry) return biblioteka [metoda] (… params)} Język kodu: JavaScript (javascript)

Jak widać, jest to funkcja częściowo zastosowana. W ten sposób mogę wstrzyknąć bibliotekę (mój Web3Provider) podczas konfigurowania modułu pobierającego. Później, za każdym razem, gdy klucz się zmieni, funkcję można rozwiązać, zwracając wymaganą obietnicę.

Teraz mogę stworzyć swój komponent

eksport const Balance = () => {const {account, library} = useWeb3React () const {data: balance} = useSWR ([‘getBalance’, account, ‘latest’], {fetcher: fetcher (library),}) if (! balance) {return <div>…div> } powrót <div>Saldo: {balance.toString ()} div> } Język kodu: JavaScript (javascript)

Zwrócony obiekt salda to BigNumber.

Komponent równowagi.

Jak widać, liczba nie jest sformatowana i jest bardzo duża. Dzieje się tak, ponieważ Solidity używa liczby całkowitej do 256 bitów.

Aby wyświetlić liczbę w formacie czytelnym dla człowieka, rozwiązaniem jest użycie jednego z wyżej wymienionych narzędzi z narzędzi Ether.js: formatEther (balance)

yarn install @ ethersproject / units Język kodu: CSS (css)

Teraz, gdy mogę przerobić mój komponent, aby obsługiwał i formatował BitInt w czytelnej dla człowieka formie:

eksport const Balance = () => {const {account, library} = useWeb3React () const {data: balance} = useSWR ([‘getBalance’, account, ‘latest’], {fetcher: fetcher (library),}) if (! balance) {return <div>…div> } powrót <div>Ξ {parseFloat (formatEther (balance)). ToPrecision (4)} div> } Język kodu: JavaScript (javascript) BitInt w czytelnej dla człowieka formie.

to, co zrobiliśmy do tej pory: Krok 2 GIT

Jak aktualizować dane w czasie rzeczywistym

SWR ujawnia funkcję mutacji w celu zaktualizowania swojej wewnętrznej pamięci podręcznej.

const {data: balance, mutate} = useSWR ([‘getBalance’, account, ‘latest’], {fetcher: fetcher (library),}) const onClick = () => {mutate (new BigNumber (10), false)} Język kodu: JavaScript (javascript)

Funkcja mutate jest automatycznie przypisywana do klucza (np. [„GetBalance”, konto, „najnowsze”], z którego została wygenerowana. Akceptuje dwa parametry. Nowe dane i czy ma zostać uruchomiona walidacja. Jeśli tak, SWR automatycznie użyje modułu pobierającego do zaktualizowania pamięci podręcznej &# 128165;

Zgodnie z przewidywaniami zdarzenia Solidity zapewniają niewielką abstrakcję w dodatku do funkcji rejestrowania EVM. Aplikacje mogą subskrybować i słuchać tych zdarzeń za pośrednictwem interfejsu RPC klienta Ethereum.

Ether.js ma proste API do subskrybowania wydarzenia:

const {konto, biblioteka} = useWeb3React () library.on ("zablokuj numer", (numer_bloku) => {console.log ({blockNumber})}) Język kodu: JavaScript (javascript)

Teraz połączmy oba podejścia w nowym komponencie

eksport const Balance = () => {const {konto, biblioteka} = useWeb3React () const {data: balance, mutate} = useSWR ([‘getBalance’, account, ‘latest’], {fetcher: fetcher (library),}) useEffect (() => {// nasłuchuj zmian na adresie Ethereum console.log (`nasłuchiwanie bloków …`) library.on (‘block’, () => {console.log (‘update balance …’) mutate (undefined, true)}) // usuń detektor, gdy komponent jest odłączony return () => {library.removeAllListeners (‘block’)} // wywołaj efekt tylko przy zamontowaniu komponentu}, []) if (! balance) {return <div>…div> } powrót <div>Ξ {parseFloat (formatEther (balance)). ToPrecision (4)} div> } Język kodu: JavaScript (javascript)

Początkowo SWR pobierze saldo konta, a następnie za każdym razem, gdy otrzyma zdarzenie blokowe, użyje mutacji, aby wywołać ponowne pobranie.

uwaga: użyliśmy mutate (undefined, true), ponieważ nie możemy pobrać z bieżącego zdarzenia rzeczywistego salda, po prostu uruchamiamy ponowne pobranie salda.

Poniżej znajduje się szybkie demo z dwoma portfelami Ethereum, które wymieniają część ETH.

Demo dwóch portfeli Ethereum wymieniających ETH.

Oto co zrobiliśmy do tej pory: Krok 3 GIT

Jak współdziałać z inteligentną umową

Do tej pory zilustrowaliśmy podstawy korzystania z SWR i jak wykonać podstawowe wywołanie za pośrednictwem Web3Provider. Zobaczmy teraz, jak współdziałać z inteligentną umową.

Ether.js obsługuje inteligentną interakcję kontraktową za pomocą interfejsu binarnego aplikacji kontraktu (ABI) ABI generowanego przez Solidity Compiler.

Interfejs binarny aplikacji kontraktowej (ABI) to standardowy sposób interakcji z kontraktami w ekosystemie Ethereum, zarówno spoza łańcucha bloków, jak i dla interakcji kontrakt-kontrakt.

Na przykład, biorąc pod uwagę poniższą prostą inteligentną umowę:

solidność pragmy ^ 0,5,0; kontrakt Test {constructor () public {b = hex"12345678901234567890123456789012"; } zdarzenie Zdarzenie (indeksowane uint a, bytes32 b); zdarzenie Event2 (indeksowane uint a, bytes32 b); function foo (uint a) public {emituj Zdarzenie (a, b); } bytes32 b; } Język kodu: JavaScript (javascript)

to jest wygenerowany przez ABI

[{ "rodzaj": "zdarzenie", "wejścia": [{ "Nazwa": "za", "rodzaj": "uint256", "zindeksowane": prawdziwe }, { "Nazwa": "b", "rodzaj": "bytes32", "zindeksowane": fałszywy } ], "Nazwa": "Zdarzenie" }, { "rodzaj": "zdarzenie", "wejścia": [{ "Nazwa": "za", "rodzaj": "uint256", "zindeksowane": prawdziwe }, { "Nazwa": "b", "rodzaj": "bytes32", "zindeksowane": fałszywy } ], "Nazwa": "Wydarzenie2" }, { "rodzaj": "funkcjonować", "wejścia": [{ "Nazwa": "za", "rodzaj": "uint256" }], "Nazwa": "bla", "wyjścia": []}] Język kodu: JSON / JSON z komentarzami (json)

Aby użyć ABI, możemy po prostu skopiować je bezpośrednio do twojego kodu i zaimportować je tam, gdzie jest to wymagane. W tym demo użyjemy standardu ERC20 ABI, ponieważ chcemy odzyskać salda dwóch tokenów: DAI i MKR.

Kolejnym krokiem jest utworzenie komponentu

export const TokenBalance = ({symbol, adres, dziesiętne}) => {const {konto, biblioteka} = useWeb3React () const {data: balance, mutate} = useSWR ([adres, ‘balanceOf’, konto], {fetcher: fetcher (biblioteka, ERC20ABI),}) useEffect (() => {// nasłuchuj zmian na adresie Ethereum console.log (`nasłuchiwanie transferu …`) const contract = new Contract (address, ERC20ABI, library.getSigner ()) const fromMe = contract.filters.Transfer (account, null) biblioteka.on (fromMe, (od, do, kwota, zdarzenie) => {console.log (‘Transfer | sent’, {from, to, amount, event}) mutate (undefined, true)}) const toMe = contract.filters.Transfer (null, account) library.on (toMe, (from , do, kwota, zdarzenie) => {console.log (‘Transfer | received’, {from, to, amount, event}) mutate (undefined, true)}) // usuń detektor, gdy komponent jest odłączony return () => {library.removeAllListeners (toMe) library.removeAllListeners (fromMe)} // wywołaj efekt tylko przy montażu komponentu}, []) if (! balance) {return <div>…div> } powrót ( <div> {parseFloat (formatUnits (saldo, dziesiętne)). toPrecision (4)} {symbol} div> )} Język kodu: JavaScript (javascript)

Przybliżmy. Są dwie główne różnice:

Kluczowa definicja

Klucz używany przez useSWR ([adres, „balanceOf”, konto])) musi zaczynać się od adresu Ethereum, a nie od metody. Dzięki temu fetcher może rozpoznać, co chcemy osiągnąć i użyć ABI.

Zmieńmy odpowiednio moduł pobierania:

const fetcher = (biblioteka: Web3Provider, abi ?: any) => (… argumenty) => {const [arg1, arg2, … params] = args // to jest kontrakt if (isAddress (arg1)) {const adres = arg1 const metoda = arg2 const kontrakt = nowy kontrakt (adres, abi, biblioteka.getSigner () ) return kontrakt [metoda] (… params)} // to jest et wywołanie const metoda = arg1 zwracana biblioteka [metoda] (arg2, … params)} Język kodu: JavaScript (javascript)

Teraz mamy moduł pobierania ogólnego przeznaczenia, który może współdziałać z wywołaniami JSON-RPC Ethereum. &# 128588;

Filtry dziennika

Innym aspektem jest to, jak nasłuchiwać wydarzeń ERC20. Ether.js zapewnia wygodny sposób konfigurowania filtru na podstawie tematów i nazwy wydarzenia. Więcej informacji na temat tego, co jest tematem, można znaleźć w Solidity docs.

const kontrakt = new Contract (address, ERC20ABI, library.getSigner ()) const fromMe = contract.filters.Transfer (account, null) Język kodu: JavaScript (javascript)

Po utworzeniu instancji kontraktu z ABI możesz przekazać filtr do instancji biblioteki.

Ostrzeżenie:

Możesz ulec pokusie, aby bezpośrednio wykorzystać kwotę z imprezy ERC20, aby zwiększyć lub zmniejszyć saldo.

Uważaj na smoka. Podczas konfigurowania modułu pobierającego przekazałeś clojure jako wywołanie zwrotne do funkcji on, która zawierała aktualną wartość salda.

Można to naprawić za pomocą useRef, ale ze względu na prostotę ponownie zweryfikujmy pamięć podręczną, aby upewnić się, że salda są świeże: mutate (undefined, true)

Mamy teraz wszystkie potrzebne elementy. Ostatni kawałek to trochę kleju.

Skonfigurowałem kilka stałych, aby mieć przyjemny sposób mapowania mojego komponentu TokenBalance na listę tokenów w zależności od sieci, w której pracujemy:

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: {[klucz: numer]: IERC20 []} = {[Networks.Rinkeby]: [{adres: "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa", symbol: "DAI", Nazwa: "Dai", dziesiętne: 18,}, {adres: "0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85", symbol: "MKR", Nazwa: "Producent", dziesiętne: 18,},],} Język kodu: JavaScript (javascript)

Gdy mamy już stałe, łatwo jest zmapować skonfigurowane tokeny na mój komponent:

eksportuj const TokenList = ({chainId}) => { powrót ( <> {TOKENS_BY_NETWORK [identyfikator łańcucha] .map ((token) => ( <TokenBalance key = {token.address} {… token} /> ))})} Język kodu: JavaScript (javascript)

Wszystko gotowe! Teraz mamy portfel Ethereum, który ładuje salda eteru i tokenów. A jeśli użytkownik wysyła lub odbiera środki, interfejs portfela jest aktualizowany.

Portfel Ethereum, który ładuje salda eteru i tokenów.

Oto, co zrobiliśmy do tej pory: Krok 4 GIT

Refaktoryzacja

Przenieśmy każdy komponent w oddzielnym pliku i sprawmy, aby moduł pobierania był globalnie dostępny przy użyciu dostawcy SWRConfig.

<Wartość SWRConfig = {{fetcher: fetcher (biblioteka, ERC20ABI)}}> <EthBalance /> <TokenList chainId = {chainId} /> <SWRConfig />Język kodu: HTML, XML (xml)

Dzięki SWRConfig możemy skonfigurować niektóre opcje tak, jak zawsze są dostępne, abyśmy mogli wygodniej korzystać z SWR.

const {data: balance, mutate} = useSWR ([adres, ‘balanceOf’, konto]) Język kodu: JavaScript (javascript)

Oto wszystko po refaktoryzacji: Krok 5 GIT

Zakończyć

SWR i Ether.js to dwie fajne biblioteki do pracy, jeśli chcesz usprawnić strategię pobierania danych za pomocą Ethereum dapp.

Kluczowe zalety
  • Podejście deklaratywne
  • Dane zawsze świeże za pośrednictwem gniazd sieciowych lub opcji SWR
  • Unikaj ponownego wymyślania koła zarządzania stanem z niestandardowym kontekstem React

Jeśli używasz wielu inteligentnych kontraktów w swoim dapp i podobał Ci się ten samouczek, uogólniłem pobieranie web3 na małe narzędzie: swr-eth (Gwiazdy są doceniane &# 128123;)

I na koniec, oto pełne repozytorium GIT: (https://github.com/aboutlo/swr-eth-tutorial).

Uzyskaj więcej samouczków Ethereum prosto do swojej skrzynki odbiorczej

Zapisz się do naszego biuletynu, aby otrzymywać najnowsze kursy dla programistów Ethereum, narzędzia, profesjonalne porady i nie tylko. InfuraMetaMaskNewsletterZapisz się do naszego newslettera, aby otrzymywać najnowsze wiadomości o Ethereum, rozwiązania dla przedsiębiorstw, zasoby dla programistów i nie tylko.Jak zbudować udany produkt BlockchainWebinar

Jak zbudować udany produkt Blockchain

Jak skonfigurować i uruchomić węzeł EthereumWebinar

Jak skonfigurować i uruchomić węzeł Ethereum

Jak zbudować własny interfejs API EthereumWebinar

Jak zbudować własny interfejs API Ethereum

Jak stworzyć token społecznościowyWebinar

Jak stworzyć token społecznościowy

Korzystanie z narzędzi bezpieczeństwa w tworzeniu inteligentnych kontraktówWebinar

Korzystanie z narzędzi bezpieczeństwa w tworzeniu inteligentnych kontraktów

Przyszłość finansów, aktywów cyfrowych i DeFiWebinar

Przyszłość finansów: aktywa cyfrowe i DeFi

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