Problem Statement / Feature Objective
The dashboard consumes state from multiple Soroban contracts deployed on testnet, futurenet, and (eventually) mainnet. Each chain produces events at different latencies and with different finality guarantees, leading to temporary UI inconsistencies when the same logical resource (e.g., a meter reading) is emitted by two chains. A CRDT-based synchronizer must merge concurrent updates deterministically so that the local Redux store always converges to a correct, consistent state without manual reconciliation.
Technical Invariants & Bounds
- CRDT type: Last-Writer-Wins Register for scalar readings; Observed-Remove Set for collections (e.g., connected device list).
- Lamport clock per chain: monotonic (chain_id, logical_timestamp) tuple; tie-breaking by chain priority (mainnet > testnet > futurenet).
- Maximum drift before forced reconciliation: 12 Soroban ledger closes (~60 seconds). Beyond that, a full state snapshot re-fetch is triggered.
- Event ingestion rate: peak 150 events/second during high-frequency meter polling. Merge worker must process each batch under 50 ms to avoid jank.
- Redux store schema must accommodate a vector clock per resource ID: .
Codebase Navigation Guide
- src/services/soroban.ts — Base contract interaction layer; , .
- src/hooks/useContractState.ts — Hook that subscribes to contract events and dispatches actions.
- src/store/slices/crdtSlice.ts — Redux slice maintaining CRDT state and vector clocks.
- src/workers/crdtMerge.worker.ts — Web Worker that performs the merge computation off the main thread.
- src/utils/lamportClock.ts — Lamport timestamp generation and comparison utilities.
- src/types/crdt.ts — TypeScript type definitions for CRDT registers, OR-Sets, vector clock structures.
Implementation Blueprint
- Define types in : , , , and an discriminated union.
- Implement class in : , , returning .
- Build the merge worker : receives batches of incoming CRDT events, groups by resource ID, applies LWW or OR-Set merge rules (tombstone-based for OR-Set), outputs patched state diff.
- Extend to stamp each dispatched event with the originating chain's Lamport clock before sending to the worker.
- In , create a reducer that accepts worker-posted diffs and applies them immutably. Also track a timestamp per chain.
- Implement a staleness watcher: every 12 ledger closes (~60s) without update from a chain, emit a action to re-fetch that chain's full state snapshot.
- Write unit tests in verifying concurrent merge cases with arbitrary interleavings.
Problem Statement / Feature Objective
The dashboard consumes state from multiple Soroban contracts deployed on testnet, futurenet, and (eventually) mainnet. Each chain produces events at different latencies and with different finality guarantees, leading to temporary UI inconsistencies when the same logical resource (e.g., a meter reading) is emitted by two chains. A CRDT-based synchronizer must merge concurrent updates deterministically so that the local Redux store always converges to a correct, consistent state without manual reconciliation.
Technical Invariants & Bounds
Codebase Navigation Guide
Implementation Blueprint