Skip to content

Pull Request: Add GraphQL query limiting, public TVL, and portfolio analytics endpoints - #904

Merged
Jayy4rl merged 5 commits into
StellarYield:mainfrom
Maxwell316:main
Jul 27, 2026
Merged

Pull Request: Add GraphQL query limiting, public TVL, and portfolio analytics endpoints#904
Jayy4rl merged 5 commits into
StellarYield:mainfrom
Maxwell316:main

Conversation

@Maxwell316

Copy link
Copy Markdown
Contributor

This PR adds GraphQL query depth/complexity limiting and three new analytics endpoints.

Closes #774
Closes #775
Closes #776
Closes #777

Issues Fixed

1. GraphQL query depth and complexity limiting (#774)

Deep or complex GraphQL queries can cause excessive DB load. This adds validation-level
limits to the existing Apollo Server:

  • Installed graphql-depth-limit and graphql-query-complexity.
  • New src/graphql/queryLimits.ts exports depthLimitRule and complexityLimitRule,
    wired into ApolloServer's validationRules.
  • Max depth: 7. Exceeding it returns Query depth {n} exceeds maximum of 7.
  • Max complexity: 200, via a custom estimator where every field costs 1 and any
    field whose type resolves to a list costs 10. Exceeding it returns
    Query complexity {n} exceeds maximum of 200.

2. Public cross-vault TVL aggregate (#775)

GET /api/v1/admin/stats includes platform-wide TVL but is admin-gated. Dashboards need
a public equivalent:

  • GET /api/v1/analytics/tvl returns { totalValueLocked, activeVaultCount, fundingVaultCount }.
  • totalValueLocked sums total_assets across all non-archived vaults; the two counts
    are vaults in the Active and Funding states respectively.
  • No authentication required — mounted on the existing public analyticsRouter.
  • Response includes Cache-Control: max-age=30.

3. Portfolio asset allocation breakdown (#776)

  • GET /api/v1/users/:address/portfolio/allocation returns
    { allocations: [{ category, deposited, percentage }] }.
  • Groups a user's positions by vaults.rwa_category (falling back to "Uncategorized"),
    summing deposited per category.
  • percentage is left unrounded (categoryDeposited / totalDeposited * 100) so that
    percentages across categories sum to 100 within floating-point precision.
  • Returns { allocations: [] } for a user with no positions.

4. Portfolio diversification score (#777)

  • GET /api/v1/users/:address/portfolio/diversification returns
    { score, vaultCount, categoryCount, herfindahlIndex }.
  • herfindahlIndex is the sum of squared per-vault deposit shares — lower means more
    diversified.
  • score = (1 - herfindahlIndex) * 100, rounded to one decimal place.
  • A user with a single position gets score: 0; a user with equal deposits across
    four vaults gets score: 75.

Verification

  • npx tsc --noEmit — clean
  • New tests added: src/graphql/queryLimits.test.ts, src/api/controllers/analytics.test.ts,
    src/services/user.portfolio-analytics.test.ts
  • npx vitest run — all tests pass except two pre-existing, unrelated flakes
    (src/services/indexer.test.ts, src/api/controllers/admin.test.ts), both confirmed
    present on main prior to this change and passing when run in isolation

…arYield#774)

Deeply nested or overly broad GraphQL queries can drive excessive DB
load. Enforce a max depth of 7 and a max complexity of 200 (each field
costs 1, list-returning fields cost 10) via validation rules wired
into Apollo Server, returning a descriptive error when either limit is
exceeded.
…Yield#775)

GET /api/v1/analytics/tvl returns total value locked plus active and
funding vault counts across all non-archived vaults, with no
authentication required and a 30s Cache-Control header, so dashboards
no longer need admin credentials just to read platform TVL.

Also adds the response types for the portfolio allocation and
diversification endpoints (StellarYield#776, StellarYield#777) to types/index.ts.
…StellarYield#776, StellarYield#777)

GET /api/v1/users/:address/portfolio/allocation groups a user's
positions by vaults.rwa_category and returns each category's deposited
total and share of the portfolio (percentages sum to 100).

GET /api/v1/users/:address/portfolio/diversification scores
concentration via the Herfindahl-Hirschman Index over per-vault
deposits: score = (1 - HHI) * 100, so a single position scores 0 and
four equally-weighted vaults score ~75.
@drips-wave

drips-wave Bot commented Jul 27, 2026

Copy link
Copy Markdown

@Maxwell316 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Jayy4rl
Jayy4rl merged commit 252a9bb into StellarYield:main Jul 27, 2026
5 of 6 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

3 participants