Skip to content

feat(api): GraphQL surface at /graphql via mercurius#48

Merged
github-actions[bot] merged 1 commit into
mainfrom
feat/indexer-graphql
May 10, 2026
Merged

feat(api): GraphQL surface at /graphql via mercurius#48
github-actions[bot] merged 1 commit into
mainfrom
feat/indexer-graphql

Conversation

@satyakwok
Copy link
Copy Markdown
Member

Summary

Tier 3 deferred item from the indexer audit — GraphQL surface lands. Schema mirrors the REST shape with proper typed bindings. dApp devs that prefer GraphQL (subgraph muscle memory, join-heavy queries that would otherwise be 3+ REST round-trips) hit `/graphql` instead of stitching routes client-side.

Resolvers delegate to the same Drizzle queries the REST routes use, so behaviour stays in lock-step across both surfaces — adding a column to the schema only needs SDL update + one resolver line, not divergent maintenance.

What lands

`apps/api/src/graphql.ts` — Mercurius plugin registered at `/graphql`.

Initial query coverage:

Query Returns Notes
`block(height: BigInt!)` `Block` (with `.transactions` sub-resolver)
`blocks(limit: Int, before: BigInt)` `[Block]` Cursor-paginated, default limit 25, max 100
`tx(hash: String!)` `Tx` (with `.logs` sub-resolver) Lowercases hash for the WHERE
`address(address: String!)` `Address` (with `.txs` and `.transfers` sub-resolvers)

`Address.txs` uses the `(from_addr|to_addr, block_height)` composite indexes from migration 0004 — filter + sort served in one index scan.

Custom BigInt scalar

Block heights, fees, u256 values overflow JavaScript Number. Serialiser emits a string; parser accepts string or numeric literals. Same convention every modern EVM client follows (Etherscan API, Alchemy, Infura).

GraphiQL playground

Enabled when `NODE_ENV !== 'production'`. Production deploys flip it off via env.

Out of scope

  • Subscriptions — push surface lives in chain node's gRPC `StreamEvents`; adding GraphQL subscriptions here would duplicate state and risk drift. Revisit when `sdk-ts` demand surfaces.
  • Etherscan-compat shape under GraphQL — the `?module=` REST endpoints stay REST-only; GraphQL clients should use the typed schema.
  • Validators / Tokens / Coinblast queries — easy follow-up; the resolver pattern is established.

Test plan

  • `pnpm turbo build` passes
  • After deploy, `curl 'https://api.sentrixchain.com/graphql' -H 'content-type: application/json' -d '{"query":"{ blocks(limit: 3) { height hash txCount } }"}'` returns three latest blocks
  • GraphiQL playground at `/graphiql` renders schema introspection (non-prod)
  • `address(address:"0x…").txs(limit: 5)` runs against the composite index — verify via `EXPLAIN ANALYZE` on the underlying query

Tier 3 deferred item lands. Schema mirrors the REST shape with proper
typed bindings — dApp devs that prefer GraphQL (subgraph muscle memory,
join-heavy queries that would otherwise be 3+ REST round-trips) hit
/graphql instead of stitching routes client-side. Resolvers delegate to
the same Drizzle queries the REST routes use, so behaviour stays in
lock-step across both surfaces.

Custom BigInt scalar — block heights, fees, u256 values overflow
JavaScript Number. Serialiser emits a string; parser accepts string or
numeric literals. Same convention every modern EVM client follows
(Etherscan, Alchemy, Infura).

Initial query coverage:
  - block(height): Block (with .transactions sub-resolver)
  - blocks(limit, before): cursor-paginated [Block]
  - tx(hash): Tx (with .logs sub-resolver)
  - address(address): Address (with .txs and .transfers sub-resolvers)

Address.txs uses the (from_addr|to_addr, block_height) composite
indexes from migration 0004 — filter + sort served in one index scan.

GraphiQL playground enabled in non-production for self-serve schema
exploration. Production deploys flip it off via NODE_ENV.

No subscriptions yet — push surface lives in chain node's gRPC
StreamEvents; adding GraphQL subscriptions here would duplicate state
and risk drift. Revisit when sdk-ts demand surfaces.
@github-actions github-actions Bot enabled auto-merge (squash) May 10, 2026 20:49
@github-actions github-actions Bot merged commit f8dee8e into main May 10, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant