Fatskills
Practice. Master. Repeat.
Study Guide: Blockchain and Web3 Development: Decentralized Applications dApps Indexing and Querying Blockchain Data The Graph Subgraphs
Source: https://www.fatskills.com/cryptocurrency-bitcoin-blockchain-and-more/chapter/blockchain-and-web3-development-blockchain-and-web3-development-decentralized-applications-dapps-indexing-and-querying-blockchain-data-the-graph-subgraphs

Blockchain and Web3 Development: Decentralized Applications dApps Indexing and Querying Blockchain Data The Graph Subgraphs

By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.

⏱️ ~6 min read

Study Guide – Indexing and Querying Blockchain Data (The Graph, Subgraphs)


What This Is

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.


Key Terms & Code Snippets

  • The Graph – A decentralized indexing protocol (similar to Google for blockchain) that lets developers publish subgraphs and query them with GraphQL.
  • Subgraph – A declarative description (schema + mapping) of how to index contract events and entities.
  • GraphQL – A query language for APIs; you ask for exactly the fields you need, and the server returns only those fields.
  • Entity – A table‑like object defined in the subgraph schema (e.g., Swap, User, NFT).
  • Mapping (AssemblyScript) – A TypeScript‑like function that runs on The Graph node, transforms raw event data into entity rows.

```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 – The GraphQL schema that defines entities and their fields.

graphql type Swap @entity {
id: ID!
pair: Bytes!
sender: Bytes!
amount0In: BigInt!
amount1Out: BigInt!
timestamp: BigInt! }


  • subgraph.yaml – Manifest that tells The Graph which contracts to watch, which events to map, and where the mapping code lives.

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 – Command‑line tool (graph init, graph codegen, graph deploy) that scaffolds, compiles, and publishes subgraphs.
  • graph-node – The open‑source indexing node you can run locally (or rely on hosted services like The Graph Hosted Service or The Graph Council).
  • indexed – Event parameters marked indexed in Solidity become searchable topics; The Graph can filter on them without scanning the whole log.

solidity event Swap(
address indexed sender,
address indexed to,
uint256 amount0In,
uint256 amount1Out,
uint256 amount0Out,
uint256 amount1In );


  • blockHandler – Optional mapping that runs on every new block (useful for time‑based aggregates).


Step‑by‑Step / Process Flow

  1. Write & Deploy the Smart Contract
    bash
    npx hardhat compile
    npx hardhat run scripts/deploy.ts --network goerli
  2. Generate the Subgraph Scaffold
    bash
    npx graph init --from-contract 0xYourContractAddress \
    --network goerli my-uniswap-subgraph
  3. Define the GraphQL Schema (schema.graphql) and write the mapping (src/mapping.ts) that converts emitted events into entities.
  4. Code‑gen & Build
    bash
    npx graph codegen # creates TypeScript bindings
    npx graph build # compiles AssemblyScript to WASM
  5. Deploy the Subgraph (hosted service or self‑hosted node)
    bash
    npx graph deploy --node https://api.thegraph.com/deploy/ \
    --ipfs https://api.thegraph.com/ipfs/ \
    my-uniswap-subgraph
  6. Query from Your dApp (Ethers.js + Apollo/urql)

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)


Common Mistakes

  • 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.

  • 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.

  • 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.


Blockchain Developer Interview / Practical Insights

  1. “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.

  2. “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.

  3. “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.

  4. “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.


Quick Check Questions

  1. 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.

  2. 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.

  3. 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.


Last‑Minute Cram Sheet (10 one‑liners)

  1. ⚠️ Never trust off‑chain data for settlement – always verify critical values on‑chain.
  2. indexed = searchable topic; up to 3 indexed params per event.
  3. GraphQL query cost = number of entities returned × field count – keep pagination tight.
  4. AssemblyScript → WASM; the mapping runs in a sandbox with no external I/O.
  5. entity.save() is mandatory; without it the entity never persists.
  6. graph-node default DB = PostgreSQL; you can swap for SQLite for local testing.
  7. Subgraph versioning – bump specVersion when you change the schema or mapping API.
  8. Gas tip: Use event.params.amount.toString() only when needed; avoid heavy string ops in mappings.
  9. Deploy to The Graph Hosted Service → free tier up to 100k entities; beyond that use The Graph Council or self‑host.
  10. Rollup compatibility: The Graph currently indexes L1 data; for L2 (Arbitrum, Optimism) use the respective subgraph endpoints.


ADVERTISEMENT