Category: Performance
Repository location: apps/web/hooks/useTxHistory.ts (fetchPage, lines ~124-128); indexer already persists parsed events (indexer/listener/handlers.go)
Problem
For every page of up to 10 transactions, the hook fires up to 10 concurrent Horizon operations().forTransaction(...).limit(200) requests just to find the matching contract op, with no caching keyed by transaction hash. Paging back and forth (goPrev/goNext) beyond react-query's cache window re-issues all sub-requests, and Horizon rate-limit (429) responses are silently dropped by Promise.allSettled rather than surfaced.
Evidence
const opsResults = await Promise.allSettled(
txPage.records.map((tx) =>
server.operations().forTransaction(tx.hash).limit(200).call(),
),
);
Suggested implementation
Prefer using the indexer's already-persisted, parsed transaction/event history (it listens to and stores these events server-side) instead of re-deriving them client-side via N Horizon calls per page; alternatively, cache per-tx-hash operation lookups independently and handle 429s distinctly.
Acceptance criteria
- Paging through transaction history issues at most one request per newly-seen transaction, not per page-view.
- A 429 from Horizon surfaces as a distinguishable rate-limit error rather than silently omitting the transaction.
Difficulty: Medium
Expected impact: Meaningfully reduces client-side RPC load and improves resilience to Horizon rate limiting.
Filed as part of the second repository-wide audit (deeper refinements following the first cleanup pass).
Category: Performance
Repository location: apps/web/hooks/useTxHistory.ts (fetchPage, lines ~124-128); indexer already persists parsed events (indexer/listener/handlers.go)
Problem
For every page of up to 10 transactions, the hook fires up to 10 concurrent Horizon
operations().forTransaction(...).limit(200)requests just to find the matching contract op, with no caching keyed by transaction hash. Paging back and forth (goPrev/goNext) beyond react-query's cache window re-issues all sub-requests, and Horizon rate-limit (429) responses are silently dropped byPromise.allSettledrather than surfaced.Evidence
Suggested implementation
Prefer using the indexer's already-persisted, parsed transaction/event history (it listens to and stores these events server-side) instead of re-deriving them client-side via N Horizon calls per page; alternatively, cache per-tx-hash operation lookups independently and handle 429s distinctly.
Acceptance criteria
Difficulty: Medium
Expected impact: Meaningfully reduces client-side RPC load and improves resilience to Horizon rate limiting.
Filed as part of the second repository-wide audit (deeper refinements following the first cleanup pass).