Skip to content

Add key discovery, leaderboard and global search endpoints - #991

Merged
Chucks1093 merged 4 commits into
accesslayerorg:mainfrom
samjay8:feat/keys-marketplace-endpoints
Sep 30, 2026
Merged

Chucks1093 merged 4 commits into
accesslayerorg:mainfrom
samjay8:feat/keys-marketplace-endpoints

Conversation

@samjay8

@samjay8 samjay8 commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

Closes #901
Closes #896
Closes #895

Summary

Three marketplace read endpoints over the existing Trade and CreatorPriceSnapshot read models, in one PR because they share the volume-aggregation and cache infrastructure:

Scope

New src/modules/keys/ module (service, controller, routes) + two-line wiring in src/modules/index.ts. Caching follows the creators module's in-process TTL pattern (no Redis in this deployment), keyed by a generation counter. No changes to existing modules.

Testing

  • Jest unit tests (keys.service.test.ts) cover volume aggregation, snapshot merge, ranking order, type filtering, cache hit/invalidation lifecycle, and the governance-outage degradation path.
  • prisma and logger mocked at module boundary; no database needed.

Files changed

  • src/modules/keys/keys-discovery.service.ts (new)
  • src/modules/keys/keys.controller.ts (new)
  • src/modules/keys/keys.routes.ts (new)
  • src/modules/keys/keys.service.test.ts (new)
  • src/modules/index.ts (router wiring)

Three marketplace read endpoints over the existing Trade and
CreatorPriceSnapshot read models (issues accesslayerorg#895, accesslayerorg#896, accesslayerorg#901):

- GET /api/v1/keys/discovery: trending top-5 keys by 24h volume plus the
  10 newest listings, cached 60s, invalidated on new key creation, both
  sections always return data even when volume is zero.
- GET /api/v1/keys/leaderboard: per-key volume over ?window=24h|7d|30d,
  ranked descending, ?limit= capped at 50, cached with window-sized TTL.
- GET /api/v1/search: unified search across keys, creators and governance
  proposals ranked by text-match relevance, ?type= filter, empty query
  returns 400 with usage guidance, governance-table outage degrades to
  empty proposals.

Caching follows the creators module's in-process TTL pattern, keyed by a
generation counter so key creation invalidates immediately. Jest tests
cover aggregation, snapshot merge, ranking, type filtering and caching.
@drips-wave

drips-wave Bot commented Sep 27, 2026

Copy link
Copy Markdown

@samjay8 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

Remove the unused snapshots destructuring element (creators is the only
half consumed by buildMarketEntries), the unused ErrorCode import, and
rename the unused request arg to _req in httpGetKeyDiscovery; clears 3
@typescript-eslint/no-unused-vars errors from the verify job.
Prisma cannot sum a String column server-side, so the groupBy(_sum: price)
in aggregateVolumeByCreator was invalid TypeScript. Fetch creatorId/price
rows within the window and sum them as BigInt client-side instead; the
Map<string, bigint> contract and cache behavior are unchanged.

Also drop the vestigial Promise.all wrapper in buildMarketEntries and fix
the zero-volume test mock, which returned no creator for the
buildMarketEntries id lookup. TS casts keep the rank-leak assertion valid.
@Chucks1093
Chucks1093 merged commit dd7dc57 into accesslayerorg:main Sep 30, 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

2 participants