द ग्राफ: वेब3 डेटा क्वेरी को ठीक करना
इस बार हम द ग्राफ़ पर करीब से नज़र डालेंगे जो अनिवार्य रूप से पिछले साल डैप्स विकसित करने के लिए मानक स्टैक का हिस्सा बन गया। आइए पहले देखें कि हम पारंपरिक तरीके से चीजें कैसे करेंगे...
द ग्राफ़ के बिना...
तो चलिए उदाहरण के लिए एक सरल उदाहरण लेते हैं। हम सभी को गेम पसंद हैं, इसलिए यूज़र्स द्वारा दांव लगाने वाले एक सरल गेम की कल्पना करें:
1pragma solidity 0.7.1;23contract Game {4 uint256 totalGamesPlayerWon = 0;5 uint256 totalGamesPlayerLost = 0;6 event BetPlaced(address player, uint256 value, bool hasWon);78 function placeBet() external payable {9 bool hasWon = evaluateBetForPlayer(msg.sender);1011 if (hasWon) {12 (bool success, ) = msg.sender.call{ value: msg.value * 2 }('');13 require(success, "Transfer failed");14 totalGamesPlayerWon++;15 } else {16 totalGamesPlayerLost++;17 }1819 emit BetPlaced(msg.sender, msg.value, hasWon);20 }21}सभी दिखाएँअब मान लीजिए कि हमारे डैप में, हम कुल दांव, हारे/जीते गए कुल गेम दिखाना चाहते हैं और जब भी कोई फिर से खेलता है तो इसे अपडेट भी करना चाहते हैं। दृष्टिकोण यह होगा:
totalGamesPlayerWonफ़ेच करें।totalGamesPlayerLostफ़ेच करें।BetPlacedइवेंट्स के लिए सब्सक्राइब करें।
हम दाईं ओर दिखाए गए अनुसार वेब3 में इवेंट (opens in a new tab) को सुन सकते हैं, लेकिन इसके लिए कुछ मामलों को संभालने की आवश्यकता होती है।
1GameContract.events.BetPlaced({2 fromBlock: 03}, 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});सभी दिखाएँअब यह हमारे सरल उदाहरण के लिए कुछ हद तक ठीक है। लेकिन मान लीजिए कि हम अब केवल मौजूदा खिलाड़ी के लिए हारे/जीते गए दांव की राशि प्रदर्शित करना चाहते हैं। खैर, हमारी किस्मत खराब है, बेहतर होगा कि आप एक नया कॉन्ट्रैक्ट डिप्लॉय करें जो उन मानों को संग्रहीत करता है और उन्हें फ़ेच करता है। और अब एक बहुत अधिक जटिल स्मार्ट अनुबंध और डैप की कल्पना करें, चीजें जल्दी से गड़बड़ हो सकती हैं।
आप देख सकते हैं कि यह इष्टतम क्यों नहीं है:
- पहले से डिप्लॉय किए गए अनुबंधों के लिए काम नहीं करता।
- उन मानों को संग्रहीत करने के लिए अतिरिक्त गैस लागत।
- एथेरियम नोड के लिए डेटा फ़ेच करने के लिए एक और कॉल की आवश्यकता है।
अब आइए एक बेहतर समाधान देखें।
मैं आपको ग्राफक्यूएल से परिचित कराता हूँ
सबसे पहले ग्राफक्यूएल के बारे में बात करते हैं, जिसे मूल रूप से फेसबुक द्वारा डिज़ाइन और कार्यान्वित किया गया था। आप पारंपरिक REST API मॉडल से परिचित हो सकते हैं। अब कल्पना कीजिए कि इसके बजाय आप ठीक उसी डेटा के लिए एक क्वेरी लिख सकते हैं जो आप चाहते थे:
दो छवियां काफी हद तक ग्राफक्यूएल के सार को दर्शाती हैं। दाईं ओर की क्वेरी के साथ हम ठीक से परिभाषित कर सकते हैं कि हमें कौन सा डेटा चाहिए, इसलिए वहां हम एक ही अनुरोध में सब कुछ प्राप्त करते हैं और ठीक वही जो हमें चाहिए उससे ज्यादा कुछ नहीं। एक ग्राफक्यूएल सर्वर सभी आवश्यक डेटा को फ़ेच करने का काम करता है, इसलिए फ्रंटएंड उपभोक्ता पक्ष के लिए इसका उपयोग करना अविश्वसनीय रूप से आसान है। यह एक अच्छी व्याख्या है (opens in a new tab) कि यदि आप रुचि रखते हैं तो सर्वर वास्तव में क्वेरी को कैसे संभालता है।
अब उस ज्ञान के साथ, आइए अंत में ब्लॉकचेन स्पेस और द ग्राफ़ में कूदें।
द ग्राफ़ क्या है?
एक ब्लॉकचेन एक विकेन्द्रीकृत डेटाबेस है, लेकिन जो आमतौर पर होता है, उसके विपरीत, हमारे पास इस डेटाबेस के लिए कोई क्वेरी भाषा नहीं है। डेटा पुनर्प्राप्त करने के समाधान दर्दनाक या पूरी तरह से असंभव हैं। द ग्राफ़ ब्लॉकचेन डेटा को इंडेक्स करने और क्वेरी करने के लिए एक विकेन्द्रीकृत प्रोटोकॉल है। और आपने इसका अनुमान लगा लिया होगा, यह क्वेरी भाषा के रूप में ग्राफक्यूएल का उपयोग कर रहा है।
किसी चीज़ को समझने के लिए उदाहरण हमेशा सबसे अच्छे होते हैं, तो चलिए हमारे GameContract उदाहरण के लिए द ग्राफ़ का उपयोग करते हैं।
सबग्राफ़ कैसे बनाएं
डेटा को कैसे इंडेक्स किया जाए इसकी परिभाषा को सबग्राफ़ कहा जाता है। इसके लिए तीन घटकों की आवश्यकता है:
- मैनीफेस्ट (
subgraph.yaml) - स्कीमा (
schema.graphql) - मैपिंग (
mapping.ts)
मैनीफेस्ट (subgraph.yaml)
मैनीफेस्ट हमारी कॉन्फ़िगरेशन फ़ाइल है और परिभाषित करती है:
- किन स्मार्ट अनुबंधों को इंडेक्स करना है (पता, नेटवर्क, ABI...)
- कौन से इवेंट्स सुनने हैं
- सुनने के लिए अन्य चीजें जैसे फ़ंक्शन कॉल या ब्लॉक
- कॉल किए जा रहे मैपिंग फ़ंक्शन (नीचे
mapping.tsदेखें)
आप यहां कई अनुबंध और हैंडलर परिभाषित कर सकते हैं। एक विशिष्ट सेटअप में हार्डहैट प्रोजेक्ट के अंदर एक सबग्राफ़ फ़ोल्डर होगा जिसकी अपनी रिपॉजिटरी होगी। फिर आप आसानी से ABI को संदर्भित कर सकते हैं।
सुविधा के कारणों से आप मूंछ जैसे टेम्पलेट टूल का भी उपयोग करना चाह सकते हैं। फिर आप एक subgraph.template.yaml बनाते हैं और नवीनतम परिनियोजनों के आधार पर पते डालते हैं। एक अधिक उन्नत उदाहरण सेटअप के लिए, उदाहरण के लिए आवे सबग्राफ रेपो (opens in a new tab) देखें।
और पूरा प्रलेखन यहां (opens in a new tab) देखा जा सकता है।
1specVersion: 0.0.12description: एथेरियम पर दांव लगाना3repository: - GitHub लिंक -4schema:5 file: ./schema.graphql6dataSources:7 - kind: ethereum/contract8 name: GameContract9 network: mainnet10 source:11 address: '0x2E6454...cf77eC'12 abi: GameContract13 startBlock: 617524414 mapping:15 kind: ethereum/events16 apiVersion: 0.0.117 language: wasm/assemblyscript18 entities:19 - GameContract20 abis:21 - name: GameContract22 file: ../build/contracts/GameContract.json23 eventHandlers:24 - event: PlacedBet(address,uint256,bool)25 handler: handleNewBet26 file: ./src/mapping.tsसभी दिखाएँस्कीमा (schema.graphql)
स्कीमा ग्राफक्यूएल डेटा परिभाषा है। यह आपको यह परिभाषित करने की अनुमति देगा कि कौन सी इकाइयां मौजूद हैं और उनके प्रकार। द ग्राफ़ से समर्थित प्रकार हैं
- बाइट्स
- ID
- स्ट्रिंग
- बूलियन
- Int
- BigInt
- BigDecimal
आप संबंधों को परिभाषित करने के लिए प्रकार के रूप में संस्थाओं का भी उपयोग कर सकते हैं। हमारे उदाहरण में हम खिलाड़ी से दांव तक 1-से-कई संबंध परिभाषित करते हैं। ! का मतलब है कि मान खाली नहीं हो सकता। पूरा प्रलेखन यहां (opens in a new tab) देखा जा सकता है।
1type Bet @entity {2 id: ID!3 player: Player!4 playerHasWon: Boolean!5 time: Int!6}78type Player @entity {9 id: ID!10 totalPlayedCount: Int11 hasWonCount: Int12 hasLostCount: Int13 bets: [Bet]!14}सभी दिखाएँमैपिंग (mapping.ts)
द ग्राफ़ में मैपिंग फ़ाइल हमारे कार्यों को परिभाषित करती है जो आने वाले इवेंट्स को संस्थाओं में बदल देती है। यह AssemblyScript में लिखा गया है, जो Typescript का एक सबसेट है। इसका मतलब है कि मैपिंग के अधिक कुशल और पोर्टेबल निष्पादन के लिए इसे WASM (वेबअसेंबली) में संकलित किया जा सकता है।
आपको subgraph.yaml फ़ाइल में नामित प्रत्येक फ़ंक्शन को परिभाषित करने की आवश्यकता होगी, इसलिए हमारे मामले में हमें केवल एक की आवश्यकता है: handleNewBet। हम पहले आईडी के रूप में प्रेषक पते से प्लेयर इकाई को लोड करने का प्रयास करते हैं। यदि यह मौजूद नहीं है, तो हम एक नई इकाई बनाते हैं और इसे शुरुआती मानों से भरते हैं।
फिर हम एक नई दांव इकाई बनाते हैं। इसके लिए आईडी event.transaction.hash.toHex() + "-" + event.logIndex.toString() होगी जो हमेशा एक अद्वितीय मान सुनिश्चित करती है। केवल हैश का उपयोग करना पर्याप्त नहीं है क्योंकि कोई स्मार्ट अनुबंध के माध्यम से एक लेनदेन में कई बार placeBet फ़ंक्शन को कॉल कर सकता है।
अंत में हम सभी डेटा के साथ प्लेयर इकाई को अपडेट कर सकते हैं। एरे को सीधे पुश नहीं किया जा सकता है, लेकिन यहां दिखाए गए अनुसार अपडेट करने की आवश्यकता है। हम दांव को संदर्भित करने के लिए आईडी का उपयोग करते हैं। और एक इकाई को संग्रहीत करने के लिए अंत में .save() की आवश्यकता होती है।
पूरा प्रलेखन यहां देखा जा सकता है: https://thegraph.com/docs/en/developing/creating-a-subgraph/#writing-mappings। (opens in a new tab) आप मैपिंग फ़ाइल में लॉगिंग आउटपुट भी जोड़ सकते हैं, यहां (opens in a new tab) देखें।
1import { Bet, Player } from "../generated/schema"2import { PlacedBet } from "../generated/GameContract/GameContract"34export function handleNewBet(event: PlacedBet): void {5 let player = Player.load(event.transaction.from.toHex())67 if (player == null) {8 // यदि पहले से मौजूद नहीं है तो बनाएं9 player = new Player(event.transaction.from.toHex())10 player.bets = new Array<string>(0)11 player.totalPlayedCount = 012 player.hasWonCount = 013 player.hasLostCount = 014 }1516 let bet = new Bet(17 event.transaction.hash.toHex() + "-" + event.logIndex.toString()18 )19 bet.player = player.id20 bet.playerHasWon = event.params.hasWon21 bet.time = event.block.timestamp22 bet.save()2324 player.totalPlayedCount++25 if (event.params.hasWon) {26 player.hasWonCount++27 } else {28 player.hasLostCount++29 }3031 // इस तरह एरे को अपडेट करें32 let bets = player.bets33 bets.push(bet.id)34 player.bets = bets3536 player.save()37}सभी दिखाएँइसे फ्रंटएंड में उपयोग करना
Apollo Boost जैसी किसी चीज़ का उपयोग करके, आप आसानी से अपने रिएक्ट डैप (या Apollo-Vue) में द ग्राफ़ को एकीकृत कर सकते हैं। विशेष रूप से जब रिएक्ट हुक और Apollo का उपयोग करते हैं, तो डेटा फ़ेच करना उतना ही सरल है जितना कि आपके घटक में एक एकल ग्राफक्यूएल क्वेरी लिखना। एक विशिष्ट सेटअप इस तरह दिख सकता है:
1// सभी सबग्राफ देखें: https://thegraph.com/explorer/2const client = new ApolloClient({3 uri: "{{ subgraphUrl }}",4})56ReactDOM.render(7 <ApolloProvider client={client}>8 <App />9 </ApolloProvider>,10 document.getElementById("root")11)सभी दिखाएँऔर अब हम उदाहरण के लिए इस तरह की क्वेरी लिख सकते हैं। यह हमें फ़ेच करेगा
- वर्तमान यूज़र कितनी बार जीता है
- वर्तमान यूज़र कितनी बार हारा है
- उसके सभी पिछले दांव के साथ टाइमस्टैम्प की एक सूची
सभी एक ही अनुरोध में ग्राफक्यूएल सर्वर को।
1const myGraphQlQuery = gql`2 players(where: { id: $currentUser }) {3 totalPlayedCount4 hasWonCount5 hasLostCount6 bets {7 time8 }9 }10`1112const { loading, error, data } = useQuery(myGraphQlQuery)1314React.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)।
विकेंद्रीकृत भविष्य
ग्राफक्यूएल नए आने वाले इवेंट्स के लिए भी स्ट्रीम का समर्थन करता है। ये ग्राफ पर सबस्ट्रीम (opens in a new tab) के माध्यम से समर्थित हैं जो वर्तमान में ओपन बीटा में हैं।
2021 (opens in a new tab) में द ग्राफ़ ने एक विकेन्द्रीकृत इंडेक्सिंग नेटवर्क में अपना संक्रमण शुरू किया। आप इस विकेन्द्रीकृत इंडेक्सिंग नेटवर्क की वास्तुकला के बारे में यहां (opens in a new tab) और अधिक पढ़ सकते हैं।
दो प्रमुख पहलू हैं:
- यूज़र्स प्रश्नों के लिए इंडेक्सर्स को भुगतान करते हैं।
- इंडेक्सर्स ग्राफ़ टोकन (GRT) को स्टेक करते हैं।
पेज का अंतिम अपडेट: 26 फ़रवरी 2026






