Skip to content

feat: add GET /creators/:id/holders endpoint#428

Merged
Chucks1093 merged 2 commits into
accesslayerorg:mainfrom
Temi-suwa18:feat/creator-holders-endpoint-422
Jun 24, 2026
Merged

feat: add GET /creators/:id/holders endpoint#428
Chucks1093 merged 2 commits into
accesslayerorg:mainfrom
Temi-suwa18:feat/creator-holders-endpoint-422

Conversation

@Temi-suwa18

Copy link
Copy Markdown

Summary

Closes #422

Adds GET /api/v1/creators/:id/holders — a paginated endpoint that lets creators see which wallets hold their keys, the current balance for each holder, and when they first bought (for loyalty sorting).

  • Accepts creator cuid id or handle as the :id param
  • Returns 404 if the creator does not exist
  • Returns empty items: [] (not 404) if creator exists but has no holders
  • Default sort: key_balance descending (largest holders first)
  • ?sort=held_since returns earliest buyers first (KeyOwnership.createdAt ascending)
  • held_since is derived from KeyOwnership.createdAt — the timestamp when the ownership row is first created, which corresponds to the wallet's first buy for that creator
  • Standard offset pagination (limit / offset) with meta.hasMore
  • 5-minute public cache via existing cache preset infrastructure

Response shape

{
  "success": true,
  "data": {
    "items": [
      {
        "wallet_address": "GABC...",
        "key_balance": 5,
        "held_since": "2024-03-01T00:00:00.000Z"
      }
    ],
    "meta": { "limit": 20, "offset": 0, "total": 1, "hasMore": false }
  }
}

Files changed

File Change
src/modules/creators/creator-holders.schemas.ts Zod query schema (limit, offset, sort)
src/modules/creators/creator-holders.service.ts findCreatorByIdOrHandle + fetchCreatorHolders
src/modules/creators/creator-holders.controller.ts httpGetCreatorHolders handler
src/modules/creators/creator-holders.integration.test.ts 9 integration tests (mock-based, no DB)
src/modules/creators/creators.routes.ts Register GET /:id/holders + 405 handler
src/constants/creator-public-routes.constants.ts GET_HOLDERS route name constant
src/constants/creator-public-cache.constants.ts Cache preset for holders route

Test plan

  • Returns 404 when creator does not exist
  • Returns empty list (not 404) when creator exists but has no holders
  • Returns holders sorted by key_balance desc by default
  • ?sort=held_since passes correct sort to service
  • Pagination meta (hasMore, total, limit, offset) is correct
  • hasMore=false on the last page
  • Each item has wallet_address, key_balance, held_since
  • Returns 400 for unknown query params (strict schema)
  • Returns 400 for invalid sort value
  • next(error) is called on service exception

🤖 Generated with Claude Code

presidojay1 and others added 2 commits June 22, 2026 15:06
Adds a paginated key holder list endpoint so creators can see which
wallets hold their keys and how many.

## Endpoint

GET /api/v1/creators/:id/holders

Query params:
- limit  (default 20, max 100)
- offset (default 0)
- sort   "key_balance" (default) | "held_since"

Response body:
{
  "success": true,
  "data": {
    "items": [{ "wallet_address", "key_balance", "held_since" }],
    "meta":  { "limit", "offset", "total", "hasMore" }
  }
}

## Behaviour

- Default sort is key_balance desc (largest holders first)
- sort=held_since returns earliest buyers first (held_since asc)
- held_since is derived from KeyOwnership.createdAt — the timestamp
  when the ownership row was first created (wallet's first buy)
- Returns 404 when the creator id/handle does not exist
- Returns empty items [] (not 404) when creator exists but has no holders
- Accepts creator cuid id OR handle as the :id param

## Files added / changed

- src/modules/creators/creator-holders.schemas.ts    — Zod query schema
- src/modules/creators/creator-holders.service.ts    — DB queries
- src/modules/creators/creator-holders.controller.ts — HTTP handler
- src/modules/creators/creator-holders.integration.test.ts — Jest tests
- src/modules/creators/creators.routes.ts            — register route
- src/constants/creator-public-routes.constants.ts   — GET_HOLDERS constant
- src/constants/creator-public-cache.constants.ts    — 5-min cache preset

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add 'holders' to CreatorReadEndpoint union so createCreatorReadMetricsMiddleware
  accepts it; update registry, snapshot, and reset accordingly
- Narrow req.params['id'] from string | string[] to string before passing to
  findCreatorByIdOrHandle — Express v5 types route params as string | string[]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Chucks1093 Chucks1093 merged commit bf76870 into accesslayerorg:main Jun 24, 2026
1 check 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.

Add key holders list endpoint so creators can see who holds their keys

3 participants