The Graph Integration (Data Indexing)

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
The Graph Integration (Data Indexing)
Medium
~2-3 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1217
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1046
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

The Graph Integration (Data Indexing)

A typical problem that comes up: the frontend makes dozens of eth_call and getLogs on every page load. On mainnet this is slow, on public RPC nodes—unreliable, and when you need aggregation or historical data—simply impossible through direct calls. The Graph solves this correctly: you write a subgraph once that indexes contract events, and get a GraphQL API with arbitrary queries.

Subgraph Architecture

A subgraph consists of three components:

subgraph.yaml — the manifest. Describes data sources: which contracts to listen to, from which block (startBlock), which events and functions to process. Critical: startBlock should be the contract deployment block, not zero—otherwise indexing takes days.

schema.graphql — entity types. This is what will be available through GraphQL. Designed based on frontend needs, not contract event structure—these are different things.

mappings.ts — AssemblyScript handlers. Transform raw events into schema entities.

Schema Design

The most common mistake is making the schema a mirror of contract events. If the event is Transfer(address from, address to, uint256 amount)—don't need a TransferEvent entity. Think about queries: "what's the user's current balance", "top holders", "volume in 24h".

type Token @entity {
  id: ID!
  totalSupply: BigInt!
  holderCount: Int!
}

type Account @entity {
  id: Bytes!
  balance: BigInt!
  transfersIn: [Transfer!]! @derivedFrom(field: "to")
  transfersOut: [Transfer!]! @derivedFrom(field: "from")
}

type Transfer @entity(immutable: true) {
  id: Bytes!
  from: Account!
  to: Account!
  amount: BigInt!
  blockNumber: BigInt!
  timestamp: BigInt!
}

@entity(immutable: true) for Transfer—important optimization. Immutable entities aren't stored in the undo buffer, indexing is 30–40% faster.

Handlers: Nuances

AssemblyScript isn't full TypeScript—no null via ?., no Array.from(), no standard JS methods. This is a frequent source of errors for developers coming from frontend.

// Correct entity loading or creation
function getOrCreateAccount(address: Address): Account {
  let account = Account.load(address)
  if (account == null) {
    account = new Account(address)
    account.balance = BigInt.fromI32(0)
  }
  return account as Account
}

export function handleTransfer(event: TransferEvent): void {
  let from = getOrCreateAccount(event.params.from)
  let to = getOrCreateAccount(event.params.to)

  from.balance = from.balance.minus(event.params.value)
  to.balance = to.balance.plus(event.params.value)

  from.save()
  to.save()

  // Immutable — create once, don't load
  let transfer = new Transfer(
    event.transaction.hash.concatI32(event.logIndex.toI32())
  )
  transfer.from = from.id
  transfer.to = to.id
  transfer.amount = event.params.value
  transfer.blockNumber = event.block.number
  transfer.timestamp = event.block.timestamp
  transfer.save()
}

Call handlers and block handlers

Besides events, The Graph can process function calls (callHandlers) and each block (blockHandlers). Call handlers are needed when a contract doesn't emit events for needed operations—legacy contracts suffer from this. Block handlers—for periodic snapshots (e.g., daily stats). Both types significantly slow down indexing, especially block handlers—use only if you can't do without them.

Deployment and Exploitation

Hosted Service vs Decentralized Network

Hosted Service (The Graph Network hosted)—centralized, free, suitable for development and MVP. No SLA guarantees, can be unavailable.

Decentralized Network—indexers receive GRT for queries, curation signal affects priority. For production with uptime requirements—the right choice, but need to understand the economics: query costs depend on volume.

Self-hosted Graph Node—full control, no GRT costs, but infrastructure load. Requires: PostgreSQL 14+, IPFS node, Ethereum archive node (or Firehose). Minimum requirements for production: 16 CPU, 64GB RAM, NVMe SSD.

Typical Indexing Problems

Subgraph fails with "store error"—usually an attempt to save an entity with a null field declared non-nullable in the schema. Check all fields before save().

Indexing stalls on a specific block—usually a call handler on a reverted transaction. Need to add handling via receipt.status.

Data divergence from on-chain—subgraph doesn't account for reorgs. For critical data, need minEthereumBlockConfirmations in the manifest or additional logic on the client.

Frontend Integration

Standard stack: Apollo Client or urql for React apps. The Graph supports subscriptions via WebSocket—for realtime updates without polling.

const POSITIONS_QUERY = gql`
  query UserPositions($account: Bytes!, $skip: Int!) {
    positions(
      where: { owner: $account, liquidity_gt: "0" }
      orderBy: createdAt
      orderDirection: desc
      first: 100
      skip: $skip
    ) {
      id
      pool { token0 { symbol } token1 { symbol } feeTier }
      liquidity
      depositedToken0
      depositedToken1
    }
  }
`

Pagination via first/skip works until skip: 5000—beyond that The Graph returns an error. For large datasets, need keyset pagination via id_gt.

Timelines and What's Included

In 2–3 days: schema design for client tasks, writing mappings for all events and calls, fork testing, deployment on Hosted Service or self-hosted node setup, basic frontend integration or GraphQL endpoint provision.