Subgraph API
For reading historical data — assertions, votes, stake balances — query the subgraphs instead of the chain. They're indexed continuously and expose a GraphQL API.
Endpoints
All endpoints are served from https://subgraph.xtruth.xyz.
| Subgraph | Endpoint |
|---|---|
| OOv1 | /subgraphs/name/xtruth/xlayer-testnet-optimistic-oracle |
| OOv2 | /subgraphs/name/xtruth/xlayer-testnet-optimistic-oracle-v2 |
| OOv3 | /subgraphs/name/xtruth/xlayer-testnet-optimistic-oracle-v3 |
| SkinnyOO | /subgraphs/name/xtruth/xlayer-testnet-skinny-oo |
| VotingV2 | /subgraphs/name/xtruth/xlayer-testnet-voting-v2 |
CORS is open for browser dapps.
Health check
Every graph-node deployment exposes _meta, useful for verifying the
indexer is alive and how far behind chain head it is:
{
_meta {
block { number timestamp }
deployment
hasIndexingErrors
}
}
OOv3 — recent assertions
{
assertions(
first: 20
orderBy: assertionTimestamp
orderDirection: desc
) {
id
assertionId
claim
asserter
identifier
currency
bond
expirationTime
disputer
settlementResolution
assertionTimestamp
settlementTimestamp
}
}
OOv3 — single assertion by id
query Assertion($id: ID!) {
assertion(id: $id) {
assertionId
claim
asserter
bond
expirationTime
disputer
settlementResolution
settlementTimestamp
}
}
(id for an OOv3 assertion entity equals its assertionId.)
OOv3 — only currently disputed
{
assertions(
where: { disputer_not: null, settlementTimestamp: null }
orderBy: disputeTimestamp
orderDirection: desc
) {
assertionId
claim
disputer
disputeTimestamp
}
}
VotingV2 — global stats
{
globals(first: 1) {
cumulativeStake
emissionRate
annualVotingTokenEmission
annualPercentageReturn
countCorrectVotes
countWrongVotes
countNoVotes
}
}
VotingV2 — single voter position
query Voter($id: ID!) {
user(id: $id) {
address
voterStake
voterPendingUnstake
withdrawnRewards
cumulativeSlash
cumulativeSlashPercentage
countCorrectVotes
countWrongVotes
countNoVotes
annualPercentageReturn
}
}
(id is the voter's lowercase address.)
Polling cadence
The web console polls these endpoints with react-query, with intervals
ranging from 5 seconds (live status) to 60 seconds (slow-changing
aggregates). For your own UI you can use any GraphQL client; we use
graphql-request.
When to query the chain instead
Subgraph data is eventually consistent — typically a few seconds behind chain head, longer if the indexer is catching up after redeploy. For these you should hit RPC directly:
- The user's current allowance and balance (read-during-tx-construction).
- Whether their stake position has been slashed since last update tracker.
- Anything you're about to mutate in the same transaction batch.
For everything else (lists, history, dashboards), prefer the subgraph.