Skip to content

In-memory + IndexedDB cache layer for fetchAnnouncements #21

@truthixify

Description

@truthixify

Labels: Stellar Wave, stellar, perf, feature, drips, help-wanted
Tier: M (2–4 days)
Type: perf / feature

Context

Issue #11 adds cursor support so callers can fetch incrementally. But cursors don't persist across page reloads — the demo or any consumer re-fetches the whole window every time the user reopens the app. We can dramatically cut RPC traffic with a real cache layer.

This is the consumer-side companion to issue #11 and the contract-side companion to contracts/22 (event topic indexing).

Scope

Build a cache abstraction at sdk/src/chains/stellar/cache.ts:

  1. Interface:
    interface AnnouncementCache {
      get(network: Network, fromLedger: number, toLedger: number): Promise<Announcement[] | null>
      put(network: Network, announcements: Announcement[]): Promise<void>
      getLastSeen(network: Network): Promise<{ ledger: number; cursor: string } | null>
      setLastSeen(network: Network, ledger: number, cursor: string): Promise<void>
      clear(network: Network): Promise<void>
    }
  2. Two implementations:
    • MemoryCache — LRU in-memory (default for Node / RN / server).
    • IndexedDBCache — persistent browser cache (auto-selected in browser environment).
  3. Wire into fetchAnnouncements:
    • On first call, query the cache for getLastSeen.
    • If present, set fromLedger to lastSeen + 1 and merge results with cache.
    • On success, update lastSeen and put the new announcements.
  4. Support a bypassCache: true option for callers who need a fresh read (e.g., post-payment confirmation).

Constraints

  • Cache must NEVER store the user's viewing key or any derived material. It's announcement data only.
  • IndexedDB writes batched (don't issue 1000 individual put calls for a 1000-announcement page).
  • Cache key includes network — testnet/mainnet data never collide.
  • Cap the IndexedDB cache at 50 MB; LRU-evict beyond that.
  • Versioning: cache schema has a version constant; on mismatch the cache is dropped and rebuilt.

Acceptance criteria

  • Cache abstraction + both implementations.
  • Tests under test/chains/stellar/cache.test.ts covering eviction, version migration, network isolation, and idempotency.
  • Benchmarks showing the speedup for repeated scans (use #05's harness).
  • Documented integration pattern in the JSDoc / docs.

Why this matters

The Spectre TEE polls every 5 minutes. The demo polls every minute when on the receive page. The console will poll for analytics. Multiply this by every user × every chain × forever — caching is the difference between Wraith being a polite RPC citizen and being a noisy neighbor.

Metadata

Metadata

Assignees

Labels

Stellar WaveIssues in the Stellar wave programdripsFunded via Drips NetworkfeatureNew feature workhelp wantedExtra attention is neededperfPerformance / optimizationstellarTouches Stellar / Soroban code

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions