The Graph & Indexing — Web3

The Graph & Indexing Blockchain menyimpan data, tapi querying data itu lambat dan terbatas. The Graph adalah protocol indexing yang memungkinkan kamu query…

The Graph & Indexing

Blockchain menyimpan data, tapi querying data itu lambat dan terbatas. The Graph adalah protocol indexing yang memungkinkan kamu query blockchain data secepat query database biasa, menggunakan GraphQL.

Mengapa Butuh Indexing?

// Tanpa indexing, untuk mendapatkan semua Transfer events:
// → Scan SEMUA block dari awal (jutaan blocks)
// → Lambat, mahal, tidak practical

// Dengan The Graph:
// → Data sudah di-index dan siap query
// → Response dalam milliseconds

// Query langsung ke subgraph:
const query = `{
  transfers(first: 10, orderBy: timestamp, orderDirection: desc) {
    from
    to
    value
    timestamp
    transactionHash
  }
}`;

const response = await fetch(SUBGRAPH_URL, {
  method: "POST",
  body: JSON.stringify({ query }),
});
const data = await response.json();

Subgraph — Definisi Index

Subgraph mendefinisikan data apa yang di-index dan bagaimana:

# schema.graphql — Definisi entity (seperti database schema)
type Transfer @entity {
  id: ID!
  from: Bytes!
  to: Bytes!
  value: BigInt!
  timestamp: BigInt!
  blockNumber: BigInt!
  transactionHash: Bytes!
}

type Token @entity {
  id: ID!
  name: String!
  symbol: String!
  totalSupply: BigInt!
  transfers: [Transfer!]! @derivedFrom(field: "token")
}

Mapping — Event Handler

// src/mapping.ts — Logika indexing
import { Transfer as TransferEvent } from "../generated/MyToken/MyToken";
import { Transfer } from "../generated/schema";

export function handleTransfer(event: TransferEvent): void {
  // Buat entity baru setiap ada Transfer event
  let transfer = new Transfer(
    event.transaction.hash.concatI32(event.logIndex.toI32())
  );

  transfer.from = event.params.from;
  transfer.to = event.params.to;
  transfer.value = event.params.value;
  transfer.timestamp = event.block.timestamp;
  transfer.blockNumber = event.block.number;
  transfer.transactionHash = event.transaction.hash;

  transfer.save(); // Simpan ke indexed store
}

subgraph.yaml — Konfigurasi

specVersion: 0.0.5
schema:
  file: ./schema.graphql
dataSources:
  - kind: ethereum
    name: MyToken
    network: mainnet
    source:
      address: "0xContractAddress..."
      abi: MyToken
      startBlock: 18000000  # Block saat contract di-deploy
    mapping:
      kind: ethereum/events
      apiVersion: 0.0.7
      language: wasm/assemblyscript
      entities:
        - Transfer
      abis:
        - name: MyToken
          file: ./abis/MyToken.json
      eventHandlers:
        - event: Transfer(indexed address,indexed address,uint256)
          handler: handleTransfer

Query dari Frontend

// Menggunakan urql atau Apollo Client
const TRANSFERS_QUERY = gql`
  query GetTransfers($first: Int!, $skip: Int!) {
    transfers(
      first: $first
      skip: $skip
      orderBy: timestamp
      orderDirection: desc
      where: { value_gt: "1000000000000000000" }
    ) {
      from
      to
      value
      timestamp
    }
  }
`;

// Aggregate queries
const STATS_QUERY = gql`
  query {
    token(id: "0x...") {
      totalSupply
      transfers(first: 0) { id }
    }
  }
`;

Deploy Subgraph

Yang akan kamu pelajari