Ruka kwenda kwenye maudhui makuu

The Graph: Kurekebisha uulizaji wa data wa Web3

uimara
mikataba erevu
kuuliza
the graph
react
Intermediate
Markus Waas
6 Septemba 2020
7 minute read

Wakati huu tutaangalia kwa undani zaidi The Graph ambayo kimsingi imekuwa sehemu ya rundo la kawaida la kuendeleza mfumo mtawanyo wa kimamlaka katika mwaka uliopita. Hebu kwanza tuone jinsi tungefanya mambo kwa njia ya jadi...

Bila The Graph...

Kwa hivyo, hebu tuchukue mfano rahisi kwa madhumuni ya kielelezo. Sote tunapenda michezo, kwa hivyo fikiria mchezo rahisi ambapo watumiaji wanaweka dau:

1pragma solidity 0.7.1;
2
3contract Game {
4 uint256 totalGamesPlayerWon = 0;
5 uint256 totalGamesPlayerLost = 0;
6 event BetPlaced(address player, uint256 value, bool hasWon);
7
8 function placeBet() external payable {
9 bool hasWon = evaluateBetForPlayer(msg.sender);
10
11 if (hasWon) {
12 (bool success, ) = msg.sender.call{ value: msg.value * 2 }('');
13 require(success, "Uhamisho umeshindikana");
14 totalGamesPlayerWon++;
15 } else {
16 totalGamesPlayerLost++;
17 }
18
19 emit BetPlaced(msg.sender, msg.value, hasWon);
20 }
21}
Onyesha yote

Sasa tuseme katika mfumo wetu uliotawanywa, tunataka kuonyesha jumla ya dau, jumla ya michezo iliyopotea/kushinda na pia kuisasisha kila wakati mtu anapocheza tena. Njia itakuwa:

  1. Leta totalGamesPlayerWon.
  2. Leta totalGamesPlayerLost.
  3. Jisajili kwa matukio ya BetPlaced.

Tunaweza kusikiliza tukio katika Web3opens in a new tab kama inavyoonyeshwa upande wa kulia, lakini inahitaji kushughulikia visa kadhaa.

1GameContract.events.BetPlaced({
2 fromBlock: 0
3}, function(error, event) { console.log(event); })
4.on('data', function(event) {
5 // tukio limetokea
6})
7.on('changed', function(event) {
8 // tukio limeondolewa tena
9})
10.on('error', function(error, receipt) {
11 // tx imekataliwa
12});
Onyesha yote

Sasa hii bado ni sawa kwa mfano wetu rahisi. Lakini tuseme sasa tunataka kuonyesha kiasi cha dau zilizopotea/kushinda kwa mchezaji wa sasa pekee. Basi hatuna bahati, ni bora upeleke mkataba mpya unaohifadhi thamani hizo na kuzileta. Na sasa fikiria mkataba-erevu na mfumo uliotawanywa ulio mgumu zaidi, mambo yanaweza kuwa magumu haraka.

Mtu Haulizi Hivi Hivi

Unaweza kuona jinsi hii si bora zaidi:

  • Haifanyi kazi kwa mikataba iliyokwisha pelekwa.
  • Gharama za ziada za gesi kwa kuhifadhi thamani hizo.
  • Inahitaji wito mwingine ili kuleta data kwa nodi ya Ethereum.

Hiyo haitoshi

Sasa hebu tuangalie suluhisho bora zaidi.

Acha nikutambulishe kwa GraphQL

Kwanza hebu tuzungumzie GraphQL, iliyobuniwa na kutekelezwa awali na Facebook. Huenda unaifahamu muundo wa jadi wa REST API. Sasa fikiria badala yake unaweza kuandika hoja ya kuulizia data unayoitaka hasa:

GraphQL API dhidi ya REST API

Picha hizi mbili zinaonyesha kiini cha GraphQL. Kwa hoja ya kuulizia upande wa kulia tunaweza kufafanua hasa data tunayoitaka, kwa hivyo hapo tunapata kila kitu katika ombi moja na si zaidi ya kile tunachohitaji hasa. Seva ya GraphQL hushughulikia upataji wa data yote inayohitajika, kwa hivyo ni rahisi sana kwa upande wa mtumiaji wa frontend kutumia. Haya ni maelezo mazuriopens in a new tab ya jinsi seva inavyoshughulikia hoja ya kuulizia ikiwa una nia.

Sasa tukiwa na maarifa hayo, hatimaye tuingie katika ulimwengu wa mnyororo wa bloku na The Graph.

The Graph ni nini?

Mnyororo wa bloku ni hifadhidata iliyogatuliwa, lakini kinyume na ilivyo kawaida, hatuna lugha ya kuulizia kwa hifadhidata hii. Mbinu za kupata data ni ngumu au haziwezekani kabisa. The Graph ni itifaki iliyogatuliwa ya kuorodhesha na kuuliza data ya mnyororo wa bloku. Na huenda umekisia, inatumia GraphQL kama lugha ya kuulizia.

The Graph

Mifano daima ndiyo njia bora ya kuelewa kitu, kwa hivyo hebu tutumie The Graph kwa mfano wetu wa GameContract.

Jinsi ya kuunda Subgraph

Ufafanuzi wa jinsi ya kuorodhesha data unaitwa subgraph. Inahitaji vipengele vitatu:

  1. Manifest (subgraph.yaml)
  2. Schema (schema.graphql)
  3. Mapping (mapping.ts)

Manifest (subgraph.yaml)

Manifest ni faili letu la usanidi na linafafanua:

  • ni mikataba-erevu ipi ya kuorodhesha (anwani, mtandao, ABI...)
  • ni matukio yapi ya kusikiliza
  • mambo mengine ya kusikiliza kama miito ya kukokotoa au bloku
  • kazi za ramani zinazoitwa (tazama mapping.ts hapa chini)

Unaweza kufafanua mikataba na vidhibiti vingi hapa. Mpangilio wa kawaida ungekuwa na folda ya subgraph ndani ya mradi wa Hardhat na hifadhi yake yenyewe. Kisha unaweza kurejelea ABI kwa urahisi.

Kwa sababu za urahisi unaweza pia kutaka kutumia zana ya violezo kama mustache. Kisha unaunda subgraph.template.yaml na kuingiza anwani kulingana na upekuzi wa hivi karibuni. Kwa mfano wa usanidi wa hali ya juu zaidi, angalia kwa mfano repo ya Aave subgraphopens in a new tab.

Na nyaraka kamili zinaweza kuonekana hapaopens in a new tab.

1specVersion: 0.0.1
2description: Kuweka Dau kwenye Ethereum
3repository: - GitHub link -
4schema:
5 file: ./schema.graphql
6dataSources:
7 - kind: ethereum/contract
8 name: GameContract
9 network: mainnet
10 source:
11 address: '0x2E6454...cf77eC'
12 abi: GameContract
13 startBlock: 6175244
14 mapping:
15 kind: ethereum/events
16 apiVersion: 0.0.1
17 language: wasm/assemblyscript
18 entities:
19 - GameContract
20 abis:
21 - name: GameContract
22 file: ../build/contracts/GameContract.json
23 eventHandlers:
24 - event: PlacedBet(address,uint256,bool)
25 handler: handleNewBet
26 file: ./src/mapping.ts
Onyesha yote

Schema (schema.graphql)

Schema ni ufafanuzi wa data wa GraphQL. Itakuruhusu kufafanua ni vyombo vipi vipo na aina zake. Aina zinazotumika kutoka kwa The Graph ni

  • Baiti
  • ID
  • String
  • Boolean
  • Int
  • BigInt
  • BigDecimal

Unaweza pia kutumia vyombo kama aina kufafanua mahusiano. Katika mfano wetu tunafafanua uhusiano wa 1-kwa-wengi kutoka kwa mchezaji kwenda kwa dau. ! inamaanisha thamani haiwezi kuwa tupu. Nyaraka kamili zinaweza kuonekana hapaopens in a new tab.

1type Bet @entity {
2 id: ID!
3 player: Player!
4 playerHasWon: Boolean!
5 time: Int!
6}
7
8type Player @entity {
9 id: ID!
10 totalPlayedCount: Int
11 hasWonCount: Int
12 hasLostCount: Int
13 bets: [Bet]!
14}
Onyesha yote

Mapping (mapping.ts)

Faili la ramani katika The Graph linafafanua kazi zetu zinazobadilisha matukio yanayoingia kuwa vyombo. Imeandikwa katika AssemblyScript, ambayo ni sehemu ndogo ya Typescript. Hii inamaanisha inaweza kuandaliwa kuwa WASM (WebAssembly) kwa utekelezaji bora zaidi na unaobebeka wa ramani.

Utahihaji kufafanua kila kazi iliyotajwa kwenye faili ya subgraph.yaml, kwa hivyo kwa upande wetu tunahitaji moja tu: handleNewBet. Kwanza tunajaribu kupakia chombo cha Mchezaji kutoka kwa anwani ya mtumaji kama kitambulisho. Ikiwa haipo, tunaunda chombo kipya na kukijaza na thamani za kuanzia.

Kisha tunaunda chombo kipya cha Dau. Kitambulisho cha hili kitakuwa event.transaction.hash.toHex() + "-" + event.logIndex.toString() kuhakikisha daima kuna thamani ya kipekee. Kutumia hashi pekee haitoshi kwani mtu anaweza kuwa anaita kazi ya placeBet mara kadhaa katika muamala mmoja kupitia mkataba-erevu.

Mwisho, tunaweza kusasisha chombo cha Mchezaji na data yote. Safu haziwezi kusukumwa moja kwa moja, lakini zinahitaji kusasishwa kama inavyoonyeshwa hapa. Tunatumia kitambulisho kurejelea dau. Na .save() inahitajika mwishoni kuhifadhi chombo.

Nyaraka kamili zinaweza kuonekana hapa: https://thegraph.com/docs/en/developing/creating-a-subgraph/#writing-mappingsopens in a new tab. Unaweza pia kuongeza matokeo ya kumbukumbu kwenye faili la ramani, tazama hapaopens in a new tab.

1import { Bet, Player } from "../generated/schema"
2import { PlacedBet } from "../generated/GameContract/GameContract"
3
4export function handleNewBet(event: PlacedBet): void {
5 let player = Player.load(event.transaction.from.toHex())
6
7 if (player == null) {
8 // unda ikiwa bado haipo
9 player = new Player(event.transaction.from.toHex())
10 player.bets = new Array<string>(0)
11 player.totalPlayedCount = 0
12 player.hasWonCount = 0
13 player.hasLostCount = 0
14 }
15
16 let bet = new Bet(
17 event.transaction.hash.toHex() + "-" + event.logIndex.toString()
18 )
19 bet.player = player.id
20 bet.playerHasWon = event.params.hasWon
21 bet.time = event.block.timestamp
22 bet.save()
23
24 player.totalPlayedCount++
25 if (event.params.hasWon) {
26 player.hasWonCount++
27 } else {
28 player.hasLostCount++
29 }
30
31 // sasisha safu kama hivi
32 let bets = player.bets
33 bets.push(bet.id)
34 player.bets = bets
35
36 player.save()
37}
Onyesha yote

Kuitumia katika Frontend

Kwa kutumia kitu kama Apollo Boost, unaweza kuunganisha kwa urahisi The Graph katika mfumo wako uliotawanywa wa React (au Apollo-Vue). Hasa unapotumia React hooks na Apollo, kupata data ni rahisi kama kuandika hoja moja ya GraphQL katika kijenzi chako. Mpangilio wa kawaida unaweza kuonekana hivi:

1// Tazama subgraphs zote: https://thegraph.com/explorer/
2const client = new ApolloClient({
3 uri: "{{ subgraphUrl }}",
4})
5
6ReactDOM.render(
7 <ApolloProvider client={client}>
8 <App />
9 </ApolloProvider>,
10 document.getElementById("root")
11)
Onyesha yote

Na sasa tunaweza kuandika kwa mfano hoja ya kuulizia kama hii. Hii itatuletea

  • mtumiaji wa sasa ameshinda mara ngapi
  • mtumiaji wa sasa amepoteza mara ngapi
  • orodha ya mihuri ya muda na dau zake zote za awali

Yote katika ombi moja kwa seva ya GraphQL.

1const myGraphQlQuery = gql`
2 players(where: { id: $currentUser }) {
3 totalPlayedCount
4 hasWonCount
5 hasLostCount
6 bets {
7 time
8 }
9 }
10`
11
12const { loading, error, data } = useQuery(myGraphQlQuery)
13
14React.useEffect(() => {
15 if (!loading && !error && data) {
16 console.log({ data })
17 }
18}, [loading, error, data])
Onyesha yote

Uchawi

Lakini tunakosa kipande kimoja cha mwisho cha fumbo na hiyo ni seva. Unaweza kuiendesha mwenyewe au kutumia huduma iliyohifadhiwa.

Seva ya The Graph

Graph Explorer: Huduma iliyohifadhiwa

Njia rahisi zaidi ni kutumia huduma iliyohifadhiwa. Fuata maagizo hapaopens in a new tab ili kupeleka subgraph. Kwa miradi mingi unaweza kupata subgraphs zilizopo kwenye exploreropens in a new tab.

The Graph-Explorer

Kuendesha nodi yako mwenyewe

Vinginevyo unaweza kuendesha nodi yako mwenyewe. Nyaraka hapaopens in a new tab. Sababu moja ya kufanya hivi inaweza kuwa ni kutumia mtandao ambao hautumiki na huduma iliyohifadhiwa. Mitandao inayotumika sasa hivi inaweza kupatikana hapaopens in a new tab.

Mustakabali uliogatuliwa

GraphQL inasaidia mitiririko pia kwa matukio mapya yanayoingia. Hizi zinatumika kwenye grafu kupitia Substreamsopens in a new tab ambazo kwa sasa ziko katika beta ya wazi.

Mnamo 2021opens in a new tab The Graph ilianza mabadiliko yake kuelekea mtandao wa uorodheshaji uliogatuliwa. Unaweza kusoma zaidi kuhusu usanifu wa mtandao huu wa uorodheshaji uliogatuliwa hapaopens in a new tab.

Vipengele viwili muhimu ni:

  1. Watumiaji huwalipa waorodheshaji kwa ajili ya hoja za kuulizia.
  2. Waorodheshaji huweka dau Tokeni za Grafu (GRT).

Ukurasa ulihaririwa mwisho: 24 Juni 2025

Umesaidika na mafunzo haya?