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:
- 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>
}
- Two implementations:
MemoryCache — LRU in-memory (default for Node / RN / server).
IndexedDBCache — persistent browser cache (auto-selected in browser environment).
- 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.
- 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
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.
Labels:
Stellar Wave,stellar,perf,feature,drips,help-wantedTier: 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:MemoryCache— LRU in-memory (default for Node / RN / server).IndexedDBCache— persistent browser cache (auto-selected in browser environment).fetchAnnouncements:getLastSeen.fromLedgertolastSeen + 1and merge results with cache.lastSeenandputthe new announcements.bypassCache: trueoption for callers who need a fresh read (e.g., post-payment confirmation).Constraints
putcalls for a 1000-announcement page).Acceptance criteria
test/chains/stellar/cache.test.tscovering eviction, version migration, network isolation, and idempotency.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.