# Ekx Thegraph

> Indexing and querying onchain data with The Graph — subgraph development and deployment, GraphQL queries from a frontend, the Token API, and when a subgraph beats direct RPC log queries. Use when you need historical onchain data, an event feed, aggregations across many blocks, or when eth_getLogs is hitting range limits.

- Skill: `ekinoxis-evm/ekx-thegraph` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ekinoxis-evm/ekx-thegraph`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ekinoxis-evm/ekx-thegraph/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: Ekinoxis-evm (https://skillmd.com/u/ekinoxis-evm)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/ekinoxis-evm/ekx-thegraph

---


# The Graph

Onchain indexing for our lending work, via the `graph-subgraph` and `graph-token-api`
MCP servers.

---

## When you need it

Direct RPC reads answer *"what is the state now?"*. They are bad at
*"what happened over the last six months?"* — `eth_getLogs` caps at ~10k blocks per
call ([`../ekx-alchemy/SKILL.md`](../ekx-alchemy/SKILL.md)), and paging a year of blocks is
slow, expensive in compute units, and fragile.

Reach for a subgraph when you need: historical event feeds, aggregations (total
volume, per-user totals), sorting and filtering across many entities, or relations
between entities.

Do **not** build one for current state — a single `readContract` is faster and always fresh.

---

## Environment

```bash
GRAPH_GATEWAY_API_KEY=    # SECRET — querying the decentralised network
GRAPH_TOKEN_API_JWT=      # SECRET — the hosted Token API
```

---

## Subgraph shape

```yaml
# subgraph.yaml
dataSources:
  - kind: ethereum
    network: base-sepolia
    source:
      address: "0x…"
      abi: AuctionManager
      startBlock: 12345678        # ← the DEPLOY block, not 0
    mapping:
      eventHandlers:
        - event: BidPlaced(indexed address,uint256)
          handler: handleBidPlaced
```

**Set `startBlock` to the contract's deploy block.** Leaving it at 0 makes the
subgraph scan the entire chain history — hours of sync for zero extra data.

```graphql
# schema.graphql
type Bid @entity {
  id: ID!
  bidder: Bytes!
  amount: BigInt!
  timestamp: BigInt!
  auction: Auction!
}
```

```ts
// src/mapping.ts
export function handleBidPlaced(event: BidPlaced): void {
  const bid = new Bid(event.transaction.hash.concatI32(event.logIndex.toI32()));
  bid.bidder = event.params.bidder;
  bid.amount = event.params.amount;
  bid.timestamp = event.block.timestamp;
  bid.save();
}
```

Mappings are **AssemblyScript**, not TypeScript. No closures, no `try/catch`, no
`JSON.parse`, strict typing. It looks like TS and is not — most confusing errors come
from that gap.

```bash
graph codegen && graph build
graph deploy --studio <subgraph-name>
```

---

## Querying

```ts
const res = await fetch(SUBGRAPH_URL, {
  method: "POST",
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${process.env.GRAPH_GATEWAY_API_KEY}` },
  body: JSON.stringify({
    query: `{ bids(first: 20, orderBy: timestamp, orderDirection: desc, where: { auction: $id }) { bidder amount timestamp } }`,
  }),
});
```

Query **server-side** — the gateway key is billable. Proxy through a route handler.

Defaults that surprise: `first` defaults to 100 and caps at 1000. Page with
`skip`, or better, cursor on `id_gt` for stable pagination — `skip` degrades badly past a few thousand.

---

## Token API

`graph-token-api` gives balances and transfer history without writing a subgraph at
all. For "what tokens does this address hold", it is strictly less work than either a
subgraph or looping `balanceOf`.

---

## Gotchas

1. **`startBlock: 0`** → hours of pointless sync.
2. **AssemblyScript, not TypeScript.**
3. **Reindex on any schema or mapping change** — it is not a migration, it is a full resync. Budget the time.
4. **`BigInt` and `BigDecimal`** are Graph types with their own arithmetic (`.plus()`, `.times()`), not JS numbers.
5. **Indexing lag** of a few blocks. Never use a subgraph to confirm a transaction the user just sent — poll the receipt.
6. **Gateway key server-side only.**

