Skip to main content
Loading market data…
SoccerverseSoccerverse

Public GraphQL Subgraphs

Public Soccerverse GraphQL subgraphs for SVC/Democrit trading, Xaya chain stats, and shop, referral and pricing data.

Purpose: document the read-only GraphQL subgraphs used by Soccerverse clients and tooling. These subgraphs index public Polygon/Xaya events and expose query-only GraphQL endpoints.

Scope

Covered here:

  • Democrit/SVC GraphQL for Soccerverse exchange trades, orders, vaults, pools, and deposits.
  • Xaya account/name stats used for wallet/name lookup and generic public chain stats.
  • Soccerverse-specific Polygon subgraph data for referrals, pack/shop sales, sale pricing, club sale status, and WCHI/USDC/WETH price observations.

Access model

Protocol: HTTP POST with JSON body.

Header:

Content-Type: application/json

No authentication is required for the public endpoints. If these endpoints are later put behind Cloudflare or a gateway bypass, examples should use placeholders only, for example:

-H "X-Cloudflare-Bypass-Secret: $CLOUDFLARE_BYPASS_SECRET"

Do not put real secret values in docs, logs, curl history, or committed test fixtures.

Endpoint catalogue

FamilyPublic alias URLDeployment hash / direct Graph Node pathSource references
Democrit/SVC productionhttps://graph.soccerverse.com/democrit-sv/subgraphs/id/QmeNciuwUvmGmUMsW9AMujc46fZKuByU3JzUdBQPUWzDXsaws-soccerverse/clusters/prod/graph/ingress-democrit-sv.yaml; soccerverse_nextjs/lib/api/svc-exchange.ts; soccerverse_mcp/democrit_api.py
Democrit/SVC testhttps://graph.soccerverse.com/democrit-svt/subgraphs/id/QmeXoguDWYrNDH7FBiZrAXnbwPGrtawCTcViCJ1Na199NDaws-soccerverse/clusters/prod/graph/ingress-democrit-svt.yaml; test overlay references
Xaya statshttps://graph.soccerverse.com/xaya-stats/subgraphs/id/QmagTKHVncUvDTzycyqcB8zzmBFcAoAUYpEgtAjijoHLhCaws-soccerverse/clusters/prod/graph/ingress-xaya-stats.yaml; soccerverse_nextjs/lib/api/xaya-graphql.ts
Soccerverse shop/referrals/pricinghttps://graph.soccerverse.com/sv-subgraph/subgraphs/id/QmSx3oQyKzn9674LhMPu2sep978SjxJAr6DqmzseHiGNLAaws-soccerverse/clusters/prod/graph/ingress-sv-subgraph.yaml; sv-full-stack/graph-admin/sv-subgraph/*; soccerverse_mcp/shop_api.py

Notes:

  • The public alias URLs are friendlier and stable behind Nginx ingress rewrite rules. The deployment hash paths are useful for diagnostics and provenance.
  • Frontend production currently sets NEXT_PUBLIC_DEMOCRIT_GRAPHQL_URL to the Democrit deployment-hash URL and NEXT_PUBLIC_XAYA_GRAPHQL_URL to the Xaya stats deployment-hash URL in argocd-deployments/frontend/base/deployment.yaml.
  • The MCP shop client reads SHOP_GRAPHQL_URL; source code shows it expects the Soccerverse shop/referrals/pricing schema exposed by sv-subgraph.

Common GraphQL patterns

Minimal curl template

curl -sS 'https://graph.soccerverse.com/sv-subgraph' \
  -H 'Content-Type: application/json' \
  --data '{"query":"query { saleClubs(first: 1) { clubId minted remainingInTranche } }"}'

Python standard-library template

import json
import urllib.request

url = "https://graph.soccerverse.com/democrit-sv"
query = """
query RecentTrades {
  trades(first: 3, orderBy: timestamp, orderDirection: desc) {
    id
    timestamp
    asset
    amount
    sats
    price
    seller
    buyer
  }
}
"""

request = urllib.request.Request(
    url,
    data=json.dumps({"query": query}).encode("utf-8"),
    headers={
        "Content-Type": "application/json",
        "User-Agent": "soccerverse-docs-readonly/1.0",
    },
    method="POST",
)

with urllib.request.urlopen(request, timeout=30) as response:
    payload = json.loads(response.read().decode("utf-8"))

if "errors" in payload:
    raise RuntimeError(payload["errors"])

print(payload["data"])

Note: some non-browser/stdlib clients may receive HTTP 403 without a standard User-Agent; always send a descriptive User-Agent header as shown above.

Introspection query

Use this lightweight introspection query to verify entity names and fields before writing examples:

query IntrospectionLite {
  __schema {
    queryType {
      name
    }
    types {
      name
      kind
      fields {
        name
        type {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
            }
          }
        }
        args {
          name
          type {
            kind
            name
            ofType {
              kind
              name
            }
          }
        }
      }
    }
  }
}

Pagination, ordering, and filtering

These subgraphs use The Graph query conventions:

  • first: N limits results. Keep docs/examples small (first: 1 to first: 5) and avoid large pages unless explicitly needed.
  • skip: N paginates by offset. For large scans, prefer deterministic ordering and page in batches.
  • orderBy: field and orderDirection: asc|desc sort results.
  • where: { ... } filters results. Nested filters use the underscore form, for example primaryClub_: { clubId: 50 }.
  • Entity IDs are often bytes/hex strings or stringified numeric IDs depending on the schema. Do not assume all id fields are decimal.

Example pagination query:

query SaleClubPage {
  saleClubs(first: 5, skip: 0, orderBy: clubId, orderDirection: asc) {
    clubId
    minted
    remainingInTranche
    trancheIndex
  }
}

Democrit/SVC subgraph

Production base URL:

https://graph.soccerverse.com/democrit-sv

Deployment hash:

QmeNciuwUvmGmUMsW9AMujc46fZKuByU3JzUdBQPUWzDXs

Test/staging alias:

https://graph.soccerverse.com/democrit-svt

Test deployment hash:

QmeXoguDWYrNDH7FBiZrAXnbwPGrtawCTcViCJ1Na199ND

Purpose: index Democrit exchange data for Soccerverse currency/assets, including trades, active sell/buy orders, vaults, pools, and deposits.

Source references:

  • sv-full-stack/graph-admin/sv-smart-contracts/lib/democrit-evm/subgraph/schema.graphql
  • sv-full-stack/graph-admin/sv-smart-contracts/lib/democrit-evm/subgraph/subgraph.yaml
  • soccerverse_nextjs/lib/api/svc-exchange.ts
  • soccerverse_nextjs/lib/trading/vault-checkpoint.ts
  • soccerverse_mcp/democrit_api.py
  • soccerverse_mcp/handlers/democrit_trades.py
  • aws-soccerverse/clusters/prod/graph/ingress-democrit-sv.yaml

Democrit entity table

EntityRoot fieldsPurposeImportant fields
Tradetrade, tradesCompleted Democrit tradesid, timestamp, asset, amount, sats, price, seller, buyer
SellOrdersellOrder, sellOrdersActive limit sell ordersid, vault, creator, seller, asset, amount, totalSats, price
BuyOrderbuyOrder, buyOrdersActive limit buy ordersid, tradingPool, creator, buyer, asset, amount, totalSats, price
Vaultvault, vaultsExisting non-empty vaults controlled by the contractid, founder, asset, balance, linked order/pool/deposit fields
TradingPooltradingPool, tradingPoolsActive trading poolsid, vault, operator, endpoint, asset, balance, relFee
SellDepositsellDeposit, sellDepositsActive sell depositsid, vault, owner, asset, balance
AutoIdautoId, autoIdsInternal sequence helperid, next

Democrit queries

Recent SVC/Democrit trades:

query RecentTrades {
  trades(first: 3, orderBy: timestamp, orderDirection: desc) {
    id
    timestamp
    asset
    amount
    sats
    price
    seller
    buyer
  }
}

Response-field notes:

  • timestamp is a Unix timestamp in seconds, returned as a string-like GraphQL BigInt in JSON.
  • amount is raw asset amount. Frontend source divides by API_VALUE_DIVISOR (10000) for SVC-style display.
  • sats is WCHI satoshis; divide by 100000000 for WCHI decimal display.
  • price in live JSON is returned as a string. Source comments call it sats per asset unit; frontend code divides by 10000 for WCHI per SVC display.
  • asset was observed as smc in live results.

Cheapest current sell orders:

query CheapestSellOrders {
  sellOrders(first: 3, orderBy: price, orderDirection: asc) {
    id
    vault {
      id
    }
    seller
    asset
    amount
    totalSats
    price
  }
}

Vault sample:

query VaultSample {
  vaults(first: 3) {
    id
    founder
    asset
    balance
  }
}

Democrit pitfalls

  • GraphQL order data is not the only validation step for trading actions. Frontend source validates active sell orders on-chain with checkSellOrders and validates vaults with GSP get_vaults before using them for trading operations. GraphQL provides read/index data only, not sufficient proof that an order can be filled.
  • Seller strings are case-sensitive in source comments (fetchUserSellOrders deliberately avoids lowercasing the username).
  • democrit-svt contains test-looking data and should not be described as production SVC liquidity.
  • Keep example pages small. The app fetches up to 1000 sell orders for its own UI, but public docs should not encourage heavy queries.

Xaya stats subgraph

Base URL:

https://graph.soccerverse.com/xaya-stats

Deployment hash:

QmagTKHVncUvDTzycyqcB8zzmBFcAoAUYpEgtAjijoHLhC

Purpose: index public Xaya Accounts contract data on Polygon. Soccerverse frontend uses it for fast wallet/name lookup instead of many RPC calls.

Source references:

  • sv-full-stack/graph-admin/stats-subgraph/schema.graphql
  • sv-full-stack/graph-admin/stats-subgraph/subgraph.yaml
  • soccerverse_nextjs/lib/api/xaya-graphql.ts
  • argocd-deployments/frontend/base/deployment.yaml
  • aws-soccerverse/clusters/prod/graph/ingress-xaya-stats.yaml

Xaya entity table

EntityRoot fieldsPurposeImportant fields
Addressaddress, addressesWallet/address currently holding or historically related to namesid, names
Namename, namesXaya names, including p/ player namesid, ns, name, owner, profile/move relations
Namespacenamespace, namespacesXaya namespacesid, ns, names
Gamegame, gamesGame IDs observed in movesid, game, moves
Movemove, movesRaw name movesid, tx, name, move, payment, games
GameMovegameMove, gameMovesGame-specific move recordsid, move, tx, game, gamemove
Paymentpayment, paymentsWCHI payment attached to a moveid, move, receiver, amount
ProfileDataintrospected on Name.profileData; source schema entityPublic profile key/value dataaccount, admin, key, value
Transactiontransaction, transactionsChain transaction metadataid, height, timestamp

Xaya queries

Lookup the sample username snailbrain:

query NameByAccount {
  names(first: 5, where: { name: "snailbrain" }) {
    id
    name
    ns {
      ns
    }
    owner {
      id
    }
  }
}

Lookup names owned by a wallet:

query NamesByOwner {
  addresses(where: { id: "0x59f5f46dc284e3414f67eda31ee90126bc48bf95" }) {
    id
    names(first: 100, orderBy: name, orderDirection: asc) {
      id
      name
      ns {
        ns
      }
    }
  }
}

This is the shape used by frontend source (addresses(where: { id: ... }) { names(...) { id name ns { ns } } }).

Recent generic game move stats:

query RecentGameMoves {
  gameMoves(first: 3, orderBy: tx__timestamp, orderDirection: desc) {
    id
    game {
      game
    }
    tx {
      height
      timestamp
    }
  }
}

Xaya pitfalls

  • Frontend source normalizes wallet addresses to lowercase before querying addresses(where: { id: ... }).
  • The frontend filters names to namespace p after fetching; Name.ns.ns == "p" is the Soccerverse player-name namespace used by the app.
  • Some names can be blank or whitespace; do not assume every Name.name is display-safe without validation.

Soccerverse shop/referrals/pricing subgraph

Base URL:

https://graph.soccerverse.com/sv-subgraph

Deployment hash:

QmSx3oQyKzn9674LhMPu2sep978SjxJAr6DqmzseHiGNLA

Purpose: index Soccerverse-specific Polygon contracts for referral leaderboards, shop pack purchases, club sale status, sale pricing tiers, pack composition, and Uniswap-derived price observations.

Source references:

  • sv-full-stack/graph-admin/sv-subgraph/schema.graphql
  • sv-full-stack/graph-admin/sv-subgraph/subgraph.yaml
  • soccerverse_mcp/shop_api.py
  • soccerverse_mcp/handlers/shop.py
  • soccerverse_mcp/handlers/soccerverse_market.py
  • aws-soccerverse/clusters/prod/graph/ingress-sv-subgraph.yaml

Indexed contracts from subgraph.yaml:

Data sourceNetworkAddressStart blockMain indexed events/entities
ReferralTrackermatic0x329612BB11Eea1Ea5065993DC32b41C86D6068c262773319Referrer, Referral, ReferrerTotal, ReferrerBonus
ClubMintermatic0xeEE0d855112b71Dc68d72053594Af03F92C586Ae66056325SaleClub
UniswapV2Factorymatic0x9e5A52f57b3038F1B8EeE45F28b3C1967e22799C66056324Token, TokenPair, PriceObservation
PackSaleForReferrals templatematicdynamic sale contractsn/aReferrerBonus, ReferrerTotal
PackSaleForShop templatematicdynamic sale contractsn/aPacksBought, PriceStep, SaleClub, SaleTier, pack contents

Soccerverse entity table

EntityRoot fieldsPurposeImportant fields
Referrerreferrer, referrersA user that has referred othersaccount, referrals, bonuses, totals, currentTotal
Referralreferral, referralsA referred accountaccount, referrer, timestamp
ReferrerBonusreferrerBonus, referrerBonusesReferral bonus from pack purchasetimestamp, clubId, packsBought, usdSpent, bonusShares
ReferrerTotalreferrerTotal, referrerTotalsRunning referral totals snapshotstimestamp, index, referrals, bonusShares, usdSpent
SaleTiersaleTier, saleTiersShop sale tier / sale contractname, active, related clubs/pricing/purchases
PricingSteppricingStep, pricingStepsPrice tranche data inside a tierindex, numShares, price, fromTotal, toTotal, tier
SaleClubsaleClub, saleClubsClub sale stateclubId, tier, pausedInTier, minted, trancheIndex, remainingInTranche
Packpack, packsPack for a primary clubprimaryClub, shares, maxPacks, cost
PackShareContentpackShareContent, packShareContentsClubs/shares contained in a packpack, club, num
PacksBoughtpacksBought, packsBoughtsIndividual pack purchase eventtimestamp, buyer, receiver, primaryClub, tier, numPacks, usdSpent
Tokentoken, tokensTracked token metadataid, decimals, symbol
TokenPairtokenPair, tokenPairsTracked Uniswap pairtradedToken, baseToken, uniswapPair, prices
PriceObservationpriceObservation, priceObservationsPeriodic Uniswap moving-average observationsvirtualTimestamp, exactTimestamp, cumulativePrice, average24h, pair

Soccerverse queries

Club sale status for sample club_id=50:

query ClubSaleStatus {
  saleClubs(first: 5, where: { clubId: 50 }) {
    id
    clubId
    minted
    remainingInTranche
    trancheIndex
    tier {
      name
      active
    }
    pausedInTier {
      name
      active
    }
  }
}

Pack composition for sample club_id=50:

query PackForClub50 {
  packs(first: 5, where: { primaryClub_: { clubId: 50 } }) {
    id
    maxPacks
    cost
    primaryClub {
      clubId
      minted
      remainingInTranche
      tier {
        name
      }
    }
    shares(first: 3) {
      club {
        clubId
      }
      num
    }
  }
}

Recent pack purchases:

query RecentPackPurchases {
  packsBoughts(first: 3, orderBy: timestamp, orderDirection: desc) {
    id
    timestamp
    receiver
    numPacks
    usdSpent
    primaryClub {
      clubId
      minted
      remainingInTranche
    }
    tier {
      name
      active
    }
  }
}

Current referral leaderboard:

query CurrentReferralLeaders {
  referrers(first: 5, orderBy: currentTotal__referrals, orderDirection: desc) {
    account
    currentTotal {
      timestamp
      referrals
      bonusShares
      usdSpent
    }
  }
}

Prefer this over ordering referrerTotals directly when you want one row per referrer; referrerTotals is a historical snapshot table and can contain many rows for the same account.

Pricing tier steps:

query PricingSteps {
  pricingSteps(first: 5, orderBy: fromTotal, orderDirection: asc) {
    id
    index
    numShares
    price
    fromTotal
    toTotal
    tier {
      name
      active
    }
  }
}

Price observations:

query PriceObservations {
  priceObservations(first: 3, orderBy: exactTimestamp, orderDirection: desc) {
    id
    virtualTimestamp
    exactTimestamp
    average24h
    pair {
      tradedToken {
        symbol
        decimals
      }
      baseToken {
        symbol
        decimals
      }
    }
  }
}

Live results include WCHI/WETH and WETH/USDC pairs.

Soccerverse response-field notes

  • usdSpent, cost, and price are raw integer units from indexed contracts. Do not assume human decimals without checking the token/contract unit. For MCP/shop docs, keep raw values labelled as raw unless another source explicitly converts them.
  • minted, remainingInTranche, numPacks, maxPacks, and numShares are plain integer counts.
  • ReferrerTotal is append-only snapshot history. Use Referrer.currentTotal for current leaderboard views.
  • PriceObservation.average24h is a large fixed-point integer. Source schema says prices use a 2**112 denominator and already account for token decimals.

Soccerverse pitfalls

  • Nested filtering is useful but easy to get wrong. For club pack lookup, use packs(where: { primaryClub_: { clubId: 50 } }), not packs(where: { clubId: 50 }).
  • Historical snapshot tables (referrerTotals, priceObservations) produce multiple rows per logical object. Explain whether an example is fetching current state or history.
  • The MCP shop_api.py sanitises GraphQL string/int interpolation; docs should show variables or carefully quoted literals, not encourage raw string concatenation from user input.
  • Pack/shop subgraph data is public chain-derived data, not the Datacentre REST /shop/* API. Cross-link them in final docs but keep responsibilities separate.

Operational notes

  • The public ingress sets proxy-body-size: 200m and CORS * for the subgraph aliases, but clients should still keep query bodies and pages small.
  • The Graph's first: 1000 is used by app code for some market views; public examples should use small first values and document pagination instead of recommending max-size queries.
  • Sorting on nested fields is supported (tx__timestamp, currentTotal__referrals), but nested sort fields should be verified against introspection when added to docs.
  • Endpoint aliases rewrite to specific deployment hashes; when schemas change, update both the hash and the generated entity table.
  • Some non-browser/stdlib clients can receive HTTP 403 without a standard User-Agent; always send a descriptive User-Agent header as shown in the Python template above.

Our Partners