ప్రధాన కంటెంట్‌కి స్కిప్ చేయండి

ది గ్రాఫ్: వెబ్3 డేటా క్వేరింగ్ ను సరిచేయడం

దృఢత్వం
స్మార్ట్ కాంట్రాక్టులు
ప్రశ్నించడం
ది గ్రాఫ్
react
మధ్యస్థ
Markus Waas
6 సెప్టెంబర్, 2020
7 నిమిషం పఠనం

ఈసారి మనం ది గ్రాఫ్‌ను నిశితంగా పరిశీలిద్దాం, ఇది గత సంవత్సరంలో డాప్స్‌ను అభివృద్ధి చేయడానికి ప్రామాణిక స్టాక్‌లో ముఖ్యమైన భాగంగా మారింది. ముందుగా మనం సాంప్రదాయ పద్ధతిలో పనులను ఎలా చేస్తామో చూద్దాం...

ది గ్రాఫ్ లేకుండా...

కాబట్టి దృష్టాంత ప్రయోజనాల కోసం ఒక సాధారణ ఉదాహరణతో వెళ్దాం. మనందరికీ ఆటలు ఇష్టం, కాబట్టి వినియోగదారులు పందెం కాసే ఒక సాధారణ ఆటను ఊహించుకోండి:

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, "Transfer failed");
14 totalGamesPlayerWon++;
15 } else {
16 totalGamesPlayerLost++;
17 }
18
19 emit BetPlaced(msg.sender, msg.value, hasWon);
20 }
21}
అన్నీ చూపించు

ఇప్పుడు మన డాప్‌లో, మొత్తం పందాలను, ఓడిపోయిన/గెలిచిన మొత్తం ఆటలను ప్రదర్శించాలని మరియు ఎవరైనా మళ్లీ ఆడినప్పుడల్లా దాన్ని అప్‌డేట్ చేయాలని అనుకుందాం. విధానం ఇలా ఉంటుంది:

  1. totalGamesPlayerWonను పొందండి.
  2. totalGamesPlayerLostను పొందండి.
  3. BetPlaced ఈవెంట్‌లకు సబ్స్క్రయిబ్ అవ్వండి.

కుడి వైపు చూపిన విధంగా మనం వెబ్3లో ఈవెంట్opens in a new tab ను వినవచ్చు, కానీ దీనికి చాలా కేసులను నిర్వహించడం అవసరం.

1GameContract.events.BetPlaced({
2 fromBlock: 0
3}, function(error, event) { console.log(event); })
4.on('data', function(event) {
5 // ఈవెంట్ ఫైర్ చేయబడింది
6})
7.on('changed', function(event) {
8 // ఈవెంట్ మళ్ళీ తీసివేయబడింది
9})
10.on('error', function(error, receipt) {
11 // tx తిరస్కరించబడింది
12});
అన్నీ చూపించు

ఇప్పుడు ఇది మన సాధారణ ఉదాహరణకు కొంతవరకు బాగానే ఉంది. కానీ ఇప్పుడు మనం ప్రస్తుత ఆటగాడికి మాత్రమే ఓడిపోయిన/గెలిచిన పందాల మొత్తాలను ప్రదర్శించాలని అనుకుందాం. మనకు అదృష్టం లేదు, మీరు ఆ విలువలను నిల్వ చేసే కొత్త కాంట్రాక్ట్‌ను డిప్లాయ్ చేసి వాటిని పొందడం మంచిది. ఇప్పుడు చాలా సంక్లిష్టమైన స్మార్ట్ కాంట్రాక్ట్ మరియు డాప్‌ను ఊహించుకోండి, విషయాలు త్వరగా గందరగోళంగా మారవచ్చు.

కేవలం ప్రశ్నించడం సరిపోదు

ఇది ఎలా సరైనది కాదో మీరు చూడవచ్చు:

  • ఇప్పటికే డిప్లాయ్ చేసిన కాంట్రాక్టులకు పనిచేయదు.
  • ఆ విలువలను నిల్వ చేయడానికి అదనపు గ్యాస్ ఖర్చులు.
  • ఇతీరియము నోడ్ కోసం డేటాను పొందేందుకు మరొక కాల్ అవసరం.

అది సరిపోదు

ఇప్పుడు ఒక మంచి పరిష్కారాన్ని చూద్దాం.

మిమ్మల్ని GraphQLకు పరిచయం చేయనివ్వండి

ముందుగా మనం GraphQL గురించి మాట్లాడుకుందాం, ఇది మొదట ఫేస్బుక్ చే రూపొందించబడింది మరియు అమలు చేయబడింది. మీకు సాంప్రదాయ రెస్ట్ ఎపిఐ మోడల్ గురించి తెలిసి ఉండవచ్చు. ఇప్పుడు దానికి బదులుగా మీకు కావలసిన డేటా కోసం కచ్చితంగా మీరు ఒక క్వెరీ వ్రాయగలరని ఊహించుకోండి:

గ్రాఫ్ క్యూఎల్ ఎపిఐ వర్సెస్ రెస్ట్ ఎపిఐ

ఈ రెండు చిత్రాలు చాలా వరకు GraphQL సారాన్ని సంగ్రహిస్తాయి. కుడివైపున ఉన్న క్వెరీతో మనకు ఏ డేటా కావాలో కచ్చితంగా నిర్వచించవచ్చు, కాబట్టి అక్కడ మనం ఒకే అభ్యర్థనలో ప్రతిదీ పొందుతాము మరియు మనకు అవసరమైన దాని కంటే ఎక్కువ ఏమీ పొందము. ఒక GraphQL సర్వర్ అవసరమైన మొత్తం డేటాను పొందడాన్ని నిర్వహిస్తుంది, కాబట్టి ఫ్రంటెండ్ వినియోగదారు వైపు ఉపయోగించడం చాలా సులభం. ఇది ఒక మంచి వివరణopens in a new tab మీకు ఆసక్తి ఉంటే సర్వర్ ఒక క్వెరీని కచ్చితంగా ఎలా నిర్వహిస్తుందో వివరిస్తుంది.

ఇప్పుడు ఆ జ్ఞానంతో, చివరకు బ్లాక్ చైను స్పేస్ మరియు ది గ్రాఫ్‌లోకి ప్రవేశిద్దాం.

ది గ్రాఫ్ అంటే ఏమిటి?

బ్లాక్ చైను ఒక వికేంద్రీకృత డేటాబేస్, కానీ సాధారణంగా జరిగే దానికి భిన్నంగా, ఈ డేటాబేస్ కోసం మనకు క్వెరీ భాష లేదు. డేటాను తిరిగి పొందేందుకు పరిష్కారాలు బాధాకరంగా లేదా పూర్తిగా అసాధ్యంగా ఉంటాయి. ది గ్రాఫ్ అనేది బ్లాక్ చైను డేటాను ఇండెక్సింగ్ మరియు క్వెరీ చేయడం కోసం ఒక వికేంద్రీకృత ప్రోటోకాల్. మరియు మీరు ఊహించినట్లుగానే, ఇది క్వెరీ భాషగా GraphQLని ఉపయోగిస్తుంది.

ది గ్రాఫ్

ఏదైనా అర్థం చేసుకోవడానికి ఉదాహరణలు ఎల్లప్పుడూ ఉత్తమమైనవి, కాబట్టి మన GameContract ఉదాహరణ కోసం ది గ్రాఫ్‌ను ఉపయోగిద్దాం.

సబ్‌గ్రాఫ్‌ను ఎలా సృష్టించాలి

డేటాను ఎలా ఇండెక్స్ చేయాలో అనే నిర్వచనాన్ని సబ్‌గ్రాఫ్ అంటారు. దీనికి మూడు భాగాలు అవసరం:

  1. మ్యానిఫెస్ట్ (subgraph.yaml)
  2. స్కీమా (schema.graphql)
  3. మ్యాపింగ్ (mapping.ts)

మ్యానిఫెస్ట్ (subgraph.yaml)

మ్యానిఫెస్ట్ మన కాన్ఫిగరేషన్ ఫైల్ మరియు నిర్వచిస్తుంది:

  • ఏ స్మార్ట్ కాంట్రాక్ట్‌లను ఇండెక్స్ చేయాలి (చిరునామా, నెట్‌వర్క్, ఎబిఐ...)
  • ఏ ఈవెంట్‌లను వినాలి
  • ఫంక్షన్ కాల్స్ లేదా బ్లాక్‌ల వంటి ఇతర విషయాలను వినడం
  • కాల్ చేయబడుతున్న మ్యాపింగ్ ఫంక్షన్‌లు (క్రింద mapping.ts చూడండి)

మీరు ఇక్కడ బహుళ కాంట్రాక్టులను మరియు హ్యాండ్లర్లను నిర్వచించవచ్చు. ఒక సాధారణ సెటప్‌లో హార్డ్‌హాట్ ప్రాజెక్ట్ లోపల దాని స్వంత రిపోజిటరీతో ఒక సబ్‌గ్రాఫ్ ఫోల్డర్ ఉంటుంది. అప్పుడు మీరు ఎబిఐను సులభంగా సూచించవచ్చు.

సౌలభ్యం కోసం మీరు మస్టాచ్ వంటి టెంప్లేట్ సాధనాన్ని కూడా ఉపయోగించాలనుకోవచ్చు. అప్పుడు మీరు ఒక subgraph.template.yaml సృష్టించి, తాజా డిప్లాయ్‌మెంట్ల ఆధారంగా చిరునామాలను చేర్చండి. మరింత అధునాతన ఉదాహరణ సెటప్ కోసం, ఉదాహరణకు Aave సబ్ గ్రాఫ్ రెపోopens in a new tab చూడండి.

మరియు పూర్తి డాక్యుమెంటేషన్ ఇక్కడopens in a new tab చూడవచ్చు.

1specVersion: 0.0.1
2description: ఇతీరియముపై పందెం వేయడం
3repository: - GitHub లింక్ -
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
అన్నీ చూపించు

స్కీమా (schema.graphql)

స్కీమా అనేది GraphQL డేటా నిర్వచనం. ఇది ఏ ఎంటిటీలు ఉన్నాయి మరియు వాటి రకాలను నిర్వచించడానికి మిమ్మల్ని అనుమతిస్తుంది. ది గ్రాఫ్ నుండి మద్దతు ఉన్న రకాలు

  • బైట్‌లు
  • ID
  • స్ట్రింగ్
  • బూలియన్
  • ఇంట్
  • బిగ్ ఇంట్
  • బిగ్ డెసిమల్

సంబంధాలను నిర్వచించడానికి మీరు ఎంటిటీలను రకంగా కూడా ఉపయోగించవచ్చు. మా ఉదాహరణలో మేము ఆటగాడి నుండి పందాలకు 1-నుండి-చాలా సంబంధాన్ని నిర్వచిస్తాము. ! అంటే విలువ ఖాళీగా ఉండకూడదు. పూర్తి డాక్యుమెంటేషన్ ఇక్కడopens 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}
అన్నీ చూపించు

మ్యాపింగ్ (mapping.ts)

ది గ్రాఫ్‌లోని మ్యాపింగ్ ఫైల్ ఇన్‌కమింగ్ ఈవెంట్‌లను ఎంటిటీలుగా మార్చే మన ఫంక్షన్‌లను నిర్వచిస్తుంది. ఇది టైప్‌స్క్రిప్ట్ యొక్క ఉపసమితి అయిన అసెంబ్లీస్క్రిప్ట్‌లో వ్రాయబడింది. దీని అర్థం మ్యాపింగ్ యొక్క మరింత సమర్థవంతమైన మరియు పోర్టబుల్ అమలు కోసం దీనిని వాసం (వెబ్ అసెంబ్లీ) లోకి కంపైల్ చేయవచ్చు.

మీరు subgraph.yaml ఫైల్‌లో పేరు పెట్టబడిన ప్రతి ఫంక్షన్‌ను నిర్వచించవలసి ఉంటుంది, కాబట్టి మన విషయంలో మనకు ఒకటి మాత్రమే అవసరం: handleNewBet. మనం మొదట పంపినవారి చిరునామా నుండి ప్లేయర్ ఎంటిటీని ఐడిగా లోడ్ చేయడానికి ప్రయత్నిస్తాము. అది ఉనికిలో లేకపోతే, మేము ఒక కొత్త ఎంటిటీని సృష్టించి దానిని ప్రారంభ విలువలతో నింపుతాము.

అప్పుడు మనం ఒక కొత్త బెట్ ఎంటిటీని సృష్టిస్తాము. దీనికి ఐడి event.transaction.hash.toHex() + "-" + event.logIndex.toString()గా ఉంటుంది, ఇది ఎల్లప్పుడూ ప్రత్యేకమైన విలువను నిర్ధారిస్తుంది. ఒక స్మార్ట్ కాంట్రాక్ట్ ద్వారా ఒకే లావాదేవీలో ఎవరైనా ప్లేస్‌బెట్ ఫంక్షన్‌ను చాలాసార్లు కాల్ చేయవచ్చు కాబట్టి కేవలం హాష్‌ను ఉపయోగించడం సరిపోదు.

చివరగా మనం ప్లేయర్ ఎంటిటీని మొత్తం డేటాతో అప్‌డేట్ చేయవచ్చు. శ్రేణులను నేరుగా పుష్ చేయలేము, కానీ ఇక్కడ చూపిన విధంగా నవీకరించబడాలి. పందెంను సూచించడానికి మనం ఐడిని ఉపయోగిస్తాము. మరియు ఒక ఎంటిటీని నిల్వ చేయడానికి చివరలో .save() అవసరం.

పూర్తి డాక్యుమెంటేషన్ ఇక్కడ చూడవచ్చు: https://thegraph.com/docs/en/developing/creating-a-subgraph/#writing-mappingsopens in a new tab. మీరు మ్యాపింగ్ ఫైల్‌కు లాగింగ్ అవుట్‌పుట్‌ను కూడా జోడించవచ్చు, ఇక్కడopens 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 // ఇంకా లేకపోతే సృష్టించండి
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 // శ్రేణిని ఇలా నవీకరించండి
32 let bets = player.bets
33 bets.push(bet.id)
34 player.bets = bets
35
36 player.save()
37}
అన్నీ చూపించు

ఫ్రంటెండ్‌లో దీనిని ఉపయోగించడం

అపోలో బూస్ట్ వంటి వాటిని ఉపయోగించి, మీరు మీ రియాక్ట్ డాప్‌లో (లేదా అపోలో-వ్యూ) ది గ్రాఫ్‌ను సులభంగా ఇంటిగ్రేట్ చేయవచ్చు. ముఖ్యంగా రియాక్ట్ హుక్స్ మరియు అపోలోను ఉపయోగిస్తున్నప్పుడు, మీ కాంపోనెంట్‌లో ఒకే GraphQL క్వెరీని వ్రాయడం అంత సులభం డేటాను పొందడం. ఒక సాధారణ సెటప్ ఇలా ఉండవచ్చు:

1// అన్ని సబ్‌గ్రాఫ్‌లను చూడండి: 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)
అన్నీ చూపించు

మరియు ఇప్పుడు మనం ఉదాహరణకు ఇలాంటి క్వెరీని వ్రాయవచ్చు. ఇది మనకు అందిస్తుంది

  • ప్రస్తుత వినియోగదారు ఎన్నిసార్లు గెలిచారు
  • ప్రస్తుత వినియోగదారు ఎన్నిసార్లు ఓడిపోయారు
  • వారి మునుపటి అన్ని పందాలతో కూడిన టైమ్‌స్టాంప్‌ల జాబితా

అన్నీ 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])
అన్నీ చూపించు

మాయ

కానీ మనం ఈ పజిల్ యొక్క చివరి భాగాన్ని కోల్పోతున్నాము మరియు అది సర్వర్. మీరు దానిని మీరే అమలు చేయవచ్చు లేదా హోస్ట్ చేసిన సేవను ఉపయోగించవచ్చు.

ది గ్రాఫ్ సర్వర్

గ్రాఫ్ ఎక్స్‌ప్లోరర్: హోస్ట్ చేసిన సేవ

సులభమైన మార్గం హోస్ట్ చేసిన సేవను ఉపయోగించడం. సబ్‌గ్రాఫ్‌ను డిప్లాయ్ చేయడానికి ఇక్కడopens in a new tab సూచనలను అనుసరించండి. అనేక ప్రాజెక్టుల కోసం మీరు వాస్తవానికి ఎక్స్‌ప్లోరర్‌లోopens in a new tab ఇప్పటికే ఉన్న సబ్‌గ్రాఫ్‌లను కనుగొనవచ్చు.

ది గ్రాఫ్-ఎక్స్‌ప్లోరర్

మీ స్వంత నోడ్‌ను నడపడం

ప్రత్యామ్నాయంగా మీరు మీ స్వంత నోడ్‌ను అమలు చేయవచ్చు. డాక్స్ ఇక్కడopens in a new tab. దీనిని చేయడానికి ఒక కారణం హోస్ట్ చేసిన సేవ మద్దతు ఇవ్వని నెట్‌వర్క్‌ను ఉపయోగించడం కావచ్చు. ప్రస్తుతం మద్దతు ఉన్న నెట్‌వర్క్‌లను ఇక్కడ కనుగొనవచ్చుopens in a new tab.

వికేంద్రీకృత భవిష్యత్తు

GraphQL కొత్తగా వచ్చే ఈవెంట్‌ల కోసం స్ట్రీమ్‌లకు కూడా మద్దతు ఇస్తుంది. ఇవి గ్రాఫ్‌లో సబ్‌స్ట్రీమ్‌లopens in a new tab ద్వారా మద్దతివ్వబడతాయి, ఇవి ప్రస్తుతం ఓపెన్ బీటాలో ఉన్నాయి.

2021opens in a new tabలో ది గ్రాఫ్ వికేంద్రీకృత ఇండెక్సింగ్ నెట్‌వర్క్‌కు తన పరివర్తనను ప్రారంభించింది. ఈ వికేంద్రీకృత ఇండెక్సింగ్ నెట్‌వర్క్ యొక్క ఆర్కిటెక్చర్ గురించి మీరు మరింతగా ఇక్కడopens in a new tab చదవవచ్చు.

రెండు ముఖ్యమైన అంశాలు:

  1. వినియోగదారులు క్వెరీల కోసం ఇండెక్సర్లకు చెల్లిస్తారు.
  2. ఇండెక్సర్లు గ్రాఫ్ టోకెన్లను (జిఆర్టి) స్టేక్ చేస్తారు.

పేజీ చివరి అప్‌డేట్: 24 జూన్, 2025

ఈ ట్యుటోరియల్ ఉపయోగపడిందా?