By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
Study Guide – Indexing and Querying Blockchain Data (The Graph, Subgraphs)
Indexing and querying blockchain data is the process of turning the raw, ever‑growing ledger of transactions into fast, searchable tables that dApps can read without scanning every block. The Graph provides a decentralized protocol for building subgraphs—custom APIs that listen to events emitted by smart contracts, transform them into a relational schema, and expose the result via GraphQL.
Real‑world example: A DeFi dashboard shows the latest Uniswap V3 swap price, the total volume of the pool, and each user’s position. Instead of pulling every Swap event from the Ethereum archive node, the dashboard queries a subgraph that already indexed those events, delivering results in milliseconds.
Swap
User
NFT
```ts // src/mapping.ts import { Swap } from '../generated/schema' import { Pair, Sync } from '../generated/UniswapV2Pair/UniswapV2Pair'
export function handleSync(event: Sync): void { let pair = Pair.load(event.address.toHex()) if (!pair) { pair = new Pair(event.address.toHex()) } pair.reserve0 = event.params.reserve0 pair.reserve1 = event.params.reserve1 pair.save() } ```
schema.graphql
graphql type Swap @entity { id: ID! pair: Bytes! sender: Bytes! amount0In: BigInt! amount1Out: BigInt! timestamp: BigInt! }
subgraph.yaml
yaml specVersion: 0.0.4 description: Index Uniswap V2 swaps dataSources: - kind: ethereum/contract name: UniswapV2Pair network: mainnet source: address: "0xB4e16d..." abi: UniswapV2Pair mapping: kind: ethereum/events apiVersion: 0.0.5 language: wasm/assemblyscript entities: - Swap abis: - name: UniswapV2Pair file: ./abis/UniswapV2Pair.json eventHandlers: - event: Swap(indexed address,indexed address,uint256,uint256,uint256,uint256) handler: handleSwap file: ./src/mapping.ts
graph-cli
graph init
graph codegen
graph deploy
graph-node
indexed
solidity event Swap( address indexed sender, address indexed to, uint256 amount0In, uint256 amount1Out, uint256 amount0Out, uint256 amount1In );
blockHandler
bash npx hardhat compile npx hardhat run scripts/deploy.ts --network goerli
bash npx graph init --from-contract 0xYourContractAddress \ --network goerli my-uniswap-subgraph
src/mapping.ts
bash npx graph codegen # creates TypeScript bindings npx graph build # compiles AssemblyScript to WASM
bash npx graph deploy --node https://api.thegraph.com/deploy/ \ --ipfs https://api.thegraph.com/ipfs/ \ my-uniswap-subgraph
js const query = ` query { swaps(first: 5, orderBy: timestamp, orderDirection: desc) { id sender amount0In amount1Out } } ` const result = await fetch('https://api.thegraph.com/subgraphs/name/your/name', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query }) }).then(r => r.json()) console.log(result.data.swaps)
Mistake: Indexing every event from a high‑frequency contract. Correction: Filter only the events you need (indexed topics) and use eventHandler for specific signatures; otherwise the node will run out of memory and sync will stall.
eventHandler
Mistake: Hard‑coding contract addresses in subgraph.yaml for multiple networks. Correction: Use environment variables or separate subgraph manifests per network; this avoids accidental mainnet queries while testing on testnets.
Mistake: Neglecting to save() the entity at the end of a handler. Correction: The Graph only persists changes when you call entity.save(). Missing it results in empty tables and silent bugs.
save()
entity.save()
Mistake: Assuming the subgraph updates instantly after a transaction. Correction: Indexing latency is typically 1‑2 blocks; design UI with loading states or fallback to direct RPC calls for real‑time data.
Mistake: Using BigInt from JavaScript directly in the mapping. Correction: AssemblyScript’s BigInt is a wrapper around i128; use event.params.amount0.toString() if you need a string, or the provided BigInt type for arithmetic.
BigInt
i128
event.params.amount0.toString()
“Explain the difference between an on‑chain event and an off‑chain indexer.” Interviewers expect you to say that events are cheap logs stored in the receipt, while an indexer (The Graph) processes those logs off‑chain to provide fast, filtered queries.
“When would you prefer a custom subgraph over directly reading logs with eth_getLogs?” Answer: when you need complex joins, aggregations, or pagination—tasks that would be prohibitively expensive or impossible with raw RPC calls.
eth_getLogs
“What are the security implications of relying on a decentralized indexer?” A good answer mentions data availability (multiple indexers, fallback to archive nodes), the need to verify critical data on‑chain, and the trust model of The Graph’s Delegated Indexers.
“How does The Graph’s indexed keyword affect query performance?” Explain that indexed parameters become topics, enabling the node to filter logs at the Ethereum level rather than scanning every log, dramatically reducing CPU and storage costs.
Scenario: Your dApp shows the latest NFT mint events. You query the subgraph and see a mint you didn’t expect. Answer: Verify the mint on‑chain (e.g., ownerOf(tokenId)) because subgraphs can be out‑of‑sync or maliciously altered; always treat off‑chain data as cached not canonical.
ownerOf(tokenId)
Scenario: You need to display the total USD value of a liquidity pool. The subgraph stores token balances but not price data. Answer: Pull price feeds (Chainlink oracles) on‑chain or via a separate subgraph and combine them in your UI; subgraphs only index what contracts emit.
Scenario: A user reports that a swap they performed isn’t appearing in the UI for 5 minutes. Answer: The Graph typically indexes within 1‑2 blocks; a 5‑minute delay suggests either a network congestion or that the subgraph’s syncing status is lagging—check the subgraph’s health endpoint.
syncing
specVersion
event.params.amount.toString()
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.