دی گراف: Web3 ڈیٹا کی دریافت کو درست کرنا
اس بار ہم دی گراف پر گہری نظر ڈالیں گے جو پچھلے سال میں dapps تیار کرنے کے لیے بنیادی طور پر معیاری اسٹیک کا حصہ بن گیا ہے۔ آئیے پہلے دیکھتے ہیں کہ ہم روایتی طریقے سے چیزیں کیسے کریں گے...
دی گراف کے بغیر...
تو آئیے مثال کے مقاصد کے لیے ایک سادہ مثال کے ساتھ چلتے ہیں۔ ہم سب کو گیمز پسند ہیں، تو ایک سادہ گیم کا تصور کریں جس میں صارفین شرط لگاتے ہیں:
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}سب دکھائیںاب فرض کریں کہ ہمارے dapp میں، ہم کل شرطیں، کل ہارے/جیتے ہوئے گیمز دکھانا چاہتے ہیں اور جب بھی کوئی دوبارہ کھیلتا ہے تو اسے اپ ڈیٹ بھی کرنا چاہتے ہیں۔ طریقہ کار یہ ہوگا:
totalGamesPlayerWonحاصل کریں۔totalGamesPlayerLostحاصل کریں۔BetPlacedایونٹس کو سبسکرائب کریں۔
ہم Web3 میں ایونٹopens in a new tab کو سن سکتے ہیں جیسا کہ دائیں طرف دکھایا گیا ہے، لیکن اس کے لیے کافی کچھ معاملات کو سنبھالنے کی ضرورت ہوتی ہے۔
1GameContract.events.BetPlaced({2 fromBlock: 03}, function(error, event) { console.log(event); })4.on('data', function(event) {5 // event fired6})7.on('changed', function(event) {8 // event was removed again9})10.on('error', function(error, receipt) {11 // tx rejected12});سب دکھائیںاب یہ ہماری سادہ مثال کے لیے اب بھی کسی حد تک ٹھیک ہے۔ لیکن فرض کریں کہ اب ہم صرف موجودہ کھلاڑی کے لیے ہاری/جیتی ہوئی شرطوں کی رقم دکھانا چاہتے ہیں۔ خیر ہماری قسمت خراب ہے، بہتر ہے کہ آپ ایک نیا کنٹریکٹ تعینات کریں جو ان اقدار کو ذخیرہ کرتا ہے اور انہیں حاصل کرتا ہے۔ اور اب ایک بہت زیادہ پیچیدہ سمارٹ کنٹریکٹ اور dapp کا تصور کریں، چیزیں جلدی سے گڑبڑ ہو سکتی ہیں۔
آپ دیکھ سکتے ہیں کہ یہ کس طرح بہترین نہیں ہے:
- پہلے سے تعینات کردہ کنٹریکٹس کے لیے کام نہیں کرتا۔
- ان اقدار کو ذخیرہ کرنے کے لیے اضافی گیس کی لاگت۔
- ایتھریم نوڈ کے لیے ڈیٹا حاصل کرنے کے لیے ایک اور کال کی ضرورت ہے۔
اب آئیے ایک بہتر حل پر نظر ڈالتے ہیں۔
میں آپ کو GraphQL سے متعارف کراتا ہوں
سب سے پہلے GraphQL کے بارے میں بات کرتے ہیں، جسے اصل میں فیس بک نے ڈیزائن اور نافذ کیا تھا۔ آپ روایتی REST API ماڈل سے واقف ہوں گے۔ اب اس کے بجائے تصور کریں کہ آپ بالکل اسی ڈیٹا کے لیے ایک استفسار لکھ سکتے ہیں جو آپ چاہتے تھے:
دو تصاویر GraphQL کے جوہر کو بہت حد تک بیان کرتی ہیں۔ دائیں طرف کے استفسار کے ساتھ ہم بالکل وہی بیان کر سکتے ہیں کہ ہم کیا ڈیٹا چاہتے ہیں، لہذا وہاں ہم ایک ہی درخواست میں سب کچھ حاصل کرتے ہیں اور اس سے زیادہ کچھ نہیں جو ہمیں درکار ہے۔ ایک GraphQL سرور تمام مطلوبہ ڈیٹا حاصل کرنے کو سنبھالتا ہے، لہذا فرنٹ اینڈ صارف کی طرف سے استعمال کرنا ناقابل یقین حد تک آسان ہے۔ اگر آپ دلچسپی رکھتے ہیں تو یہ ایک اچھی وضاحت ہےopens in a new tab کہ سرور بالکل ایک استفسار کو کیسے ہینڈل کرتا ہے۔
اب اس علم کے ساتھ، آئیے آخر کار بلاک چین کی دنیا اور دی گراف میں داخل ہوں۔
دی گراف کیا ہے؟
بلاک چین ایک غیر مرکزی ڈیٹا بیس ہے، لیکن عام طور پر جو ہوتا ہے اس کے برعکس، ہمارے پاس اس ڈیٹا بیس کے لیے کوئی استفسار کی زبان نہیں ہے۔ ڈیٹا کی بازیافت کے حل تکلیف دہ یا مکمل طور پر ناممکن ہیں۔ دی گراف بلاک چین ڈیٹا کو انڈیکس کرنے اور استفسار کرنے کے لیے ایک غیر مرکزی پروٹوکول ہے۔ اور آپ نے اندازہ لگا لیا ہوگا، یہ استفسار کی زبان کے طور پر GraphQL کا استعمال کر رہا ہے۔
مثالیں ہمیشہ کسی چیز کو سمجھنے کے لیے بہترین ہوتی ہیں، لہذا آئیے اپنی GameContract مثال کے لیے دی گراف کا استعمال کریں۔
سب گراف کیسے بنائیں
ڈیٹا کو انڈیکس کرنے کی تعریف کو سب گراف کہا جاتا ہے۔ اس کے لیے تین اجزاء کی ضرورت ہے:
- مینی فیسٹ (
subgraph.yaml) - اسکیما (
schema.graphql) - میپنگ (
mapping.ts)
مینی فیسٹ (subgraph.yaml)
مینی فیسٹ ہماری کنفیگریشن فائل ہے اور یہ بیان کرتی ہے:
- کون سے سمارٹ کنٹریکٹس کو انڈیکس کرنا ہے (ایڈریس، نیٹ ورک، ABI...)
- کون سے ایونٹس کو سننا ہے
- سننے کے لیے دیگر چیزیں جیسے فنکشن کالز یا بلاکس
- میپنگ فنکشنز کو کال کیا جا رہا ہے (نیچے
mapping.tsدیکھیں)
آپ یہاں متعدد کنٹریکٹس اور ہینڈلرز کی وضاحت کر سکتے ہیں۔ ایک عام سیٹ اپ میں Hardhat پروجیکٹ کے اندر اس کی اپنی ریپوزٹری کے ساتھ ایک سب گراف فولڈر ہوگا۔ پھر آپ آسانی سے ABI کا حوالہ دے سکتے ہیں۔
سہولت کے لیے آپ mustache جیسے ٹیمپلیٹ ٹول کا بھی استعمال کرنا چاہیں گے۔ پھر آپ ایک subgraph.template.yaml بناتے ہیں اور تازہ ترین تعیناتیوں کی بنیاد پر ایڈریسز داخل کرتے ہیں۔ مزید جدید مثال کے سیٹ اپ کے لیے، مثال کے طور پر Aave سب گراف ریپوopens in a new tab دیکھیں۔
اور مکمل دستاویزات یہاںopens in a new tab دیکھی جا سکتی ہیں۔
1specVersion: 0.0.12description: Placing Bets on Ethereum3repository: - GitHub link -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)
اسکیما 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 (WebAssembly) میں کمپائل کیا جا سکتا ہے۔
آپ کو subgraph.yaml فائل میں نامزد ہر فنکشن کی وضاحت کرنے کی ضرورت ہوگی، لہذا ہمارے معاملے میں ہمیں صرف ایک کی ضرورت ہے: handleNewBet۔ ہم پہلے بھیجنے والے کے ایڈریس سے پلیئر اینٹیٹی کو id کے طور پر لوڈ کرنے کی کوشش کرتے ہیں۔ اگر یہ موجود نہیں ہے، تو ہم ایک نئی اینٹیٹی بناتے ہیں اور اسے ابتدائی اقدار سے بھرتے ہیں۔
پھر ہم ایک نئی Bet اینٹیٹی بناتے ہیں۔ اس کے لیے id event.transaction.hash.toHex() + "-" + event.logIndex.toString() ہوگی جو ہمیشہ ایک منفرد قدر کو یقینی بناتی ہے۔ صرف ہیش کا استعمال کافی نہیں ہے کیونکہ کوئی شخص سمارٹ کنٹریکٹ کے ذریعے ایک ہی ٹرانزیکشن میں کئی بار placeBet فنکشن کو کال کر سکتا ہے۔
آخر میں ہم تمام ڈیٹا کے ساتھ پلیئر اینٹیٹی کو اپ ڈیٹ کر سکتے ہیں۔ ایریز کو براہ راست پش نہیں کیا جا سکتا، بلکہ انہیں یہاں دکھائے گئے طریقے سے اپ ڈیٹ کرنے کی ضرورت ہے۔ ہم شرط کا حوالہ دینے کے لیے id کا استعمال کرتے ہیں۔ اور ایک اینٹیٹی کو ذخیرہ کرنے کے لیے آخر میں .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 // create if doesn't exist yet9 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 // update array like this32 let bets = player.bets33 bets.push(bet.id)34 player.bets = bets3536 player.save()37}سب دکھائیںاسے فرنٹ اینڈ میں استعمال کرنا
Apollo Boost جیسی چیز کا استعمال کرتے ہوئے، آپ آسانی سے اپنے React dapp (یا Apollo-Vue) میں دی گراف کو ضم کر سکتے ہیں۔ خاص طور پر جب React hooks اور Apollo کا استعمال کرتے ہیں، تو ڈیٹا حاصل کرنا اتنا ہی آسان ہے جتنا کہ اپنے جزو میں ایک واحد GraphQL استفسار لکھنا۔ ایک عام سیٹ اپ کچھ اس طرح نظر آ سکتا ہے:
1// See all subgraphs: 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)سب دکھائیںاور اب ہم مثال کے طور پر اس طرح کا ایک استفسار لکھ سکتے ہیں۔ یہ ہمیں حاصل کرے گا
- موجودہ صارف کتنی بار جیتا ہے
- موجودہ صارف کتنی بار ہارا ہے
- اس کی تمام پچھلی شرطوں کے ساتھ ٹائم اسٹیمپس کی ایک فہرست
سب کچھ GraphQL سرور کو ایک ہی درخواست میں۔
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۔
غیر مرکزی مستقبل
GraphQL نئے آنے والے ایونٹس کے لیے اسٹریمز کو بھی سپورٹ کرتا ہے۔ یہ گراف پر سب اسٹریمزopens in a new tab کے ذریعے تعاون یافتہ ہیں جو فی الحال اوپن بیٹا میں ہیں۔
2021opens in a new tab میں دی گراف نے ایک غیر مرکزی انڈیکسنگ نیٹ ورک میں اپنی منتقلی شروع کی۔ آپ اس غیر مرکزی انڈیکسنگ نیٹ ورک کے فن تعمیر کے بارے میں مزید یہاںopens in a new tab پڑھ سکتے ہیں۔
دو اہم پہلو ہیں:
- صارفین استفسارات کے لیے انڈیکسرز کو ادائیگی کرتے ہیں۔
- انڈیکسرز گراف ٹوکنز (GRT) کو اسٹیک کرتے ہیں۔
صفحہ کی آخری تازہ کاری: 24 جون، 2025






