Indexer: materialize 24h volume, fix block timestamps, cap pagination (M4, M8) #243
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#243
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Reference
Gap analysis:
gaps/GAP_1780200149.md— findings M4, M8 (both parts).Current codebase
M4 — Per-request 24h volume aggregation:
list_pairs_filteredinindexer/src/db/queries/pairs.rs:145-150LEFT JOINs a subquery scanningswap_eventsfor the last 24 hours on every pair-list request when sorting/filtering by volume. No materialized rollup or cache.M8 (p1) — Block timestamp fallback:
parse_block_timeinindexer/src/indexer/poller.rs:155-173usesUtc::now()when LCD timestamp is missing or invalid → candles aligned to ingestion time, not chain time.M8 (p2) — Uncapped pagination:
offsetinapi/pairs.rs:162—.max(0)only; no upper cap (deep offset = full table scan).tokens/ CG pairs endpoints — unbounded or weakly bounded list sizes (seeapi/tokens.rs,api/cg.rs).Related: trader tier sync O(traders) every 10 min (
indexer/src/indexer/trader_tracker.rs) — note for future but out of scope unless trivial cache hook.Why this is needed
Pair list with
sort=volume_24his hot path for frontend Pool/Charts/Swap token discovery. O(pairs × swaps) per request does not scale. Uncapped offsets enable expensive scan DoS. Timestamp skew corrupts candle charts and CG/CMC historical data. Unbounded token lists increase memory and response times.Constraints / guardrails
Utc::now(); if fallback retained, metric + exclude from candle close.PAIR_LIST_LIMIT_MAX(100) — e.g. max offset 10_000 or max page index.limit/offsetcaps consistent with existing API patterns.indexer/migrations/.Relevant files
indexer/src/db/queries/pairs.rsindexer/src/api/pairs.rsindexer/src/indexer/poller.rsparse_block_timeindexer/src/indexer/candle_builder.rsindexer/src/api/tokens.rsindexer/src/api/cg.rs,api/cmc.rsindexer/migrations/Recommended direction
pair_volume_24hmaterialized table or PG materialized view refreshed every 1–5 min; or incremental rollup on swap insert. Index(pair_id, block_timestamp)onswap_eventsif missing.offset≤ e.g. 10_000; return 400 if exceeded. Add pagination defaults/max to tokens/CG pairs.Acceptance criteria
volume_24hdoes not full-scan 24h swaps per request (explain refresh lag in docs).Test plan — all paths
Run: indexer integration tests + EXPLAIN on pair list query.
Test plan — attack / abuse vectors
Verification criteria
Utc::now().mentioned in commit
d4e4698d81mentioned in commit
9aca628794Implementation complete (pushed to
main—d4e4698)Addressed GitLab #243 / gap analysis M4 and M8 (both parts).
What changed
M4 — Materialized 24h pair volume
pair_volume_24htable + migration20260531143000_pair_volume_24h_rollup.sqlvolume_aggregator(+ initial refresh on indexer startup)GET /api/v1/pairs?sort=volume_24hnow JOINs the rollup table instead of scanning 24hswap_eventsper requestM8 (p1) — Block timestamp fallback
resolve_block_time: valid tx RFC3339 → use it; missing/invalid tx → LCD block headertime; noUtc::now()fallbackM8 (p2) — Pagination caps
offset> 10_000 → 400GET /api/v1/tokens:limit(default 200, max 500) +offsetcap 10_000GET /cg/pairs:limit(default 500, max 1000) +offsetcap 10_000Documentation
docs/indexer-invariants.md— invariants V1–V4, block time + rollup sectionsskills/AGENTS_INDEXER_VOLUME_PAGINATION.mdTests run (docker network — host
127.0.0.1:5432unreachable in this env)indexer_pair_volume_pagination— rollup matches live sum; volume sort OKindexer_ingestion_hardening— header fallback; invalid tx+header fails without cursor advanceapi_pairs— offset=99999 → 400api_tokens— offset capapi_cg— offset cap + existing CG testsVerification checklist (QA)
\d pair_volume_24hshows table; indexer starts cleanlyGET /api/v1/pairs?sort=volume_24h&order=descreturns sensible order (note up to ~5 min lag vs live swaps)EXPLAIN ANALYZEon pair list query: no seq scan aggregating full 24hswap_eventsGET /api/v1/pairs?offset=99999→ 400GET /api/v1/tokens?offset=99999→ 400GET /cg/pairs?offset=99999→ 400Requesting verification from @qa agent team — please run the checklist above on QA/localnet after deploy and confirm volume sort lag + pagination behavior.
Issue left open pending QA sign-off.
mentioned in commit
fe4cacc922mentioned in commit
4a68a1fe24QA verification complete (@verify/issue-243 →
main4a68a1f)Verified GitLab #243 / gap M4 + M8 on LocalTerra stack (indexer
:3001, Postgresdex_indexer,dex_indexer_test). Implementation fromd4e4698meets all acceptance and verification criteria in the issue body.What was verified
sort=volume_24husespair_volume_24hrollup (not live 24hswap_eventsscan)EXPLAINon prod DB: joinspair_volume_24honly; noswap_eventsin planupdated_atrecent (~5 min loop)invalid_tx_and_header_timestamp_fails_block; cursor unchanged;resolve_block_timehas noUtc::now()missing_tx_timestamp_uses_block_header_timeoffset=99999→ 400api_pairs)api_tokens,api_cg)20260531143000_pair_volume_24h_rollup.sqlappliedindexer_pair_volume_pagination(3),indexer_ingestion_hardening(6),api_pairs/api_tokens/api_cgFollow-up on
maingaps/GAP_1780200149.md: M4 / M8 marked Fixed (#243).pair_list_volume_sort_plan_does_not_touch_swap_events(EXPLAIN guard).Manual re-check checklist (optional)
GET /api/v1/pairs?sort=volume_24h&order=desc— sensible order (expect up to ~5 min lag vs live swaps)GET /api/v1/tokensdefault page size ≤ 500Closing — all issue acceptance + verification criteria satisfied. @brouie — ping if you see volume-sort lag or pagination regressions in prod.
mentioned in issue #335
mentioned in issue #337
mentioned in issue #361
mentioned in issue #544
mentioned in issue #576
mentioned in issue #655
mentioned in issue #692