Přejít na hlavní obsah

The Graph: Oprava dotazování na data ve Web3

Solidity
chytré kontrakty
dotazování
the graph
React
Středně pokročilý
Markus Waas
6. září 2020
7 minut čtení

Tentokrát se podíváme blíže na The Graph, který se v posledním roce v podstatě stal součástí standardního stacku pro vývoj decentralizovaných aplikací (dapp). Pojďme se nejprve podívat, jak bychom to dělali tradičním způsobem...

Bez The Graph...

Pro ilustraci si tedy vezměme jednoduchý příklad. Všichni máme rádi hry, takže si představte jednoduchou hru, kde uživatelé uzavírají sázky:

Řekněme, že v naší decentralizované aplikaci (dapp) chceme zobrazit celkové sázky, celkový počet prohraných/vyhraných her a také to aktualizovat, kdykoli někdo hraje znovu. Postup by byl následující:

  1. Načíst totalGamesPlayerWon.
  2. Načíst totalGamesPlayerLost.
  3. Přihlásit se k odběru událostí BetPlaced.

Můžeme naslouchat události ve Web3 (opens in a new tab), jak je znázorněno vpravo, ale vyžaduje to ošetření poměrně velkého množství případů.

Pro náš jednoduchý příklad je to stále ještě docela v pořádku. Ale řekněme, že nyní chceme zobrazit částky prohraných/vyhraných sázek pouze pro aktuálního hráče. Máme smůlu, raději byste měli nasadit nový kontrakt, který tyto hodnoty ukládá, a načítat je z něj. A teď si představte mnohem složitější chytrý kontrakt a dapp, věci se mohou rychle zkomplikovat.

One Does Not Simply Query

Sami vidíte, že to není optimální:

  • Nefunguje pro již nasazené kontrakty.
  • Dodatečné náklady na gas za ukládání těchto hodnot.
  • Vyžaduje další volání pro načtení dat z uzlu Etherea.

Thats not good enough

Nyní se podívejme na lepší řešení.

Dovolte mi představit vám GraphQL

Nejprve si promluvme o GraphQL, které původně navrhl a implementoval Facebook. Možná znáte tradiční model REST API. Nyní si místo toho představte, že byste mohli napsat dotaz přesně na ta data, která chcete:

GraphQL API vs. REST API

Animated demonstration of a GraphQL query in The Graph playground

Tyto dva obrázky v podstatě vystihují podstatu GraphQL. Pomocí dotazu vpravo můžeme přesně definovat, jaká data chceme, takže získáme vše v jednom požadavku a nic víc než to, co přesně potřebujeme. Server GraphQL se stará o načtení všech požadovaných dat, takže je pro frontendového konzumenta neuvěřitelně snadné jej používat. Pokud vás to zajímá, zde je pěkné vysvětlení (opens in a new tab) toho, jak přesně server zpracovává dotaz.

S těmito znalostmi se konečně vrhněme do prostoru blockchainu a The Graph.

Co je The Graph?

Blockchain je decentralizovaná databáze, ale na rozdíl od toho, co je obvyklé, pro tuto databázi nemáme dotazovací jazyk. Řešení pro získávání dat jsou bolestivá nebo zcela nemožná. The Graph je decentralizovaný protokol pro indexování a dotazování na data z blockchainu. A jak jste už asi uhodli, jako dotazovací jazyk používá GraphQL.

The Graph

Příklady jsou vždy nejlepší pro pochopení čehokoli, takže použijme The Graph pro náš příklad s GameContract.

Jak vytvořit podgraf

Definice toho, jak indexovat data, se nazývá podgraf. Vyžaduje tři komponenty:

  1. Manifest (subgraph.yaml)
  2. Schéma (schema.graphql)
  3. Mapování (mapping.ts)

Manifest (subgraph.yaml)

Manifest je náš konfigurační soubor a definuje:

  • které chytré kontrakty se mají indexovat (adresa, síť, ABI...)
  • kterým událostem se má naslouchat
  • další věci k naslouchání, jako jsou volání funkcí nebo bloky
  • volané mapovací funkce (viz mapping.ts níže)

Zde můžete definovat více kontraktů a handlerů. Typické nastavení by mělo složku podgrafu uvnitř projektu Hardhat s vlastním repozitářem. Pak můžete snadno odkazovat na ABI.

Z důvodu pohodlí možná budete chtít použít také šablonovací nástroj, jako je mustache. Pak vytvoříte subgraph.template.yaml a vložíte adresy na základě nejnovějších nasazení. Pro pokročilejší příklad nastavení se podívejte například na repozitář podgrafu Aave (opens in a new tab).

A celou dokumentaci si můžete prohlédnout zde (opens in a new tab).

Schéma (schema.graphql)

Schéma je definice dat GraphQL. Umožní vám definovat, které entity existují a jaké jsou jejich typy. Podporované typy z The Graph jsou

  • Bytes
  • ID
  • String
  • Boolean
  • Int
  • BigInt
  • BigDecimal

Entity můžete také použít jako typ k definování vztahů. V našem příkladu definujeme vztah 1:N (jeden k mnoha) od hráče k sázkám. Znak ! znamená, že hodnota nesmí být prázdná. Celou dokumentaci si můžete prohlédnout zde (opens in a new tab).

Mapování (mapping.ts)

Soubor mapování v The Graph definuje naše funkce, které transformují příchozí události na entity. Je napsán v AssemblyScriptu, což je podmnožina TypeScriptu. To znamená, že jej lze zkompilovat do WASM (WebAssembly) pro efektivnější a přenositelnější provádění mapování.

Budete muset definovat každou funkci pojmenovanou v souboru subgraph.yaml, takže v našem případě potřebujeme pouze jednu: handleNewBet. Nejprve se pokusíme načíst entitu Player z adresy odesílatele jako id. Pokud neexistuje, vytvoříme novou entitu a naplníme ji počátečními hodnotami.

Poté vytvoříme novou entitu Bet. Její id bude event.transaction.hash.toHex() + "-" + event.logIndex.toString(), což zajistí vždy jedinečnou hodnotu. Použití pouze hashe nestačí, protože někdo může volat funkci placeBet několikrát v jedné transakci prostřednictvím chytrého kontraktu.

Nakonec můžeme aktualizovat entitu Player všemi daty. Do polí nelze přidávat prvky přímo (push), ale musí se aktualizovat tak, jak je ukázáno zde. K odkazování na sázku používáme id. A na konci je vyžadováno .save() pro uložení entity.

Celou dokumentaci si můžete prohlédnout zde: https://thegraph.com/docs/en/developing/creating-a-subgraph/#writing-mappings (opens in a new tab). Do souboru mapování můžete také přidat výstup protokolování (logging), viz zde (opens in a new tab).

Použití ve frontendu

Pomocí něčeho jako Apollo Boost můžete The Graph snadno integrovat do své decentralizované aplikace (dapp) v Reactu (nebo Apollo-Vue). Zejména při použití React hooks a Apolla je načítání dat tak jednoduché jako napsání jediného dotazu GraphQL ve vaší komponentě. Typické nastavení může vypadat takto:

A nyní můžeme napsat například takovýto dotaz. Ten nám načte

  • kolikrát aktuální uživatel vyhrál
  • kolikrát aktuální uživatel prohrál
  • seznam časových razítek se všemi jeho předchozími sázkami

Vše v jednom jediném požadavku na server GraphQL.

Magic

Chybí nám ale poslední kousek skládačky, a tím je server. Můžete jej buď provozovat sami, nebo využít hostovanou službu.

Server The Graph

Graph Explorer: Hostovaná služba

Nejjednodušší způsob je použít hostovanou službu. Pro nasazení podgrafu postupujte podle pokynů zde (opens in a new tab). Pro mnoho projektů můžete ve skutečnosti najít existující podgrafy v exploreru (opens in a new tab).

The Graph-Explorer

Provozování vlastního uzlu

Případně můžete provozovat svůj vlastní uzel. Dokumentace je zde (opens in a new tab). Jedním z důvodů, proč to udělat, může být použití sítě, která není podporována hostovanou službou. Aktuálně podporované sítě najdete zde (opens in a new tab).

Decentralizovaná budoucnost

GraphQL podporuje také streamy pro nově příchozí události. Ty jsou na The Graph podporovány prostřednictvím Substreams (opens in a new tab), které jsou v současné době v otevřené beta verzi.

V roce 2021 (opens in a new tab) zahájil The Graph přechod na decentralizovanou indexovací síť. Více o architektuře této decentralizované indexovací sítě si můžete přečíst zde (opens in a new tab).

Dva klíčové aspekty jsou:

  1. Uživatelé platí indexerům za dotazy.
  2. Indexeři stakují tokeny Graph (GRT).