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
- The Graph Studio — Hosted service (mainnet)
- graph-node — Self-hosted (development)
graph init→graph codegen→graph deploy