Files
bitvid/docs/nostr-client-overview.md
T
google-labs-jules[bot] d17045c431 chore(ai): doc js/nostr/client.js (agent)
- Added JSDoc comments to `js/nostr/client.js` for key methods (`sendDirectMessage`, `subscribeDirectMessages`, `ensurePool`, `saveLocalData`, `persistLocalData`).
- Created `docs/nostr-client-overview.md` to provide a high-level architectural overview of the `NostrClient` class.
2026-01-22 15:26:37 +00:00

66 lines
3.1 KiB
Markdown

# NostrClient Overview
`js/nostr/client.js` exports the `NostrClient` class, which serves as the central controller for all Nostr protocol interactions in the application. It acts as a bridge between the UI components, the local state (React/Redux/Listeners), and the decentralized Nostr network.
## Responsibilities
1. **Connection Management**:
* Maintains a persistent connection pool (`SimplePool` from `nostr-tools`) to multiple relays.
* Handles relay discovery, connection retries, and error reporting.
* Supports "Read" vs. "Write" relay splitting.
2. **Event Publishing (Write Path)**:
* Constructs spec-compliant Nostr events (Kind 1, 30078, etc.).
* Handles **signing**:
* NIP-07 (Browser Extensions like Alby/nos2x).
* NIP-46 (Remote Signers / Bunker).
* Local Private Keys (nsec).
* Broadcasts events to write relays and verifies acceptance.
* Implements **NIP-94** (File Metadata) and **NIP-71** (Video Categorization) mirroring.
3. **Data Fetching & Subscription (Read Path)**:
* **Live Feeds**: Uses persistent subscriptions (`sub`) to stream new events.
* **Buffering**: Implements a debounced buffer strategy (`subscribeVideos`) to handle relay floods without freezing the UI.
* **Caching**: Stores events in `allEvents` (memory) and persists to IndexedDB/LocalStorage for instant load ("Stale-While-Revalidate").
4. **State Management**:
* **`allEvents`**: Map of all raw video events fetched, keyed by Event ID.
* **`activeMap`**: A "materialized view" of the latest video state. It deduplicates multiple versions of the same video (edits) based on `videoRootId` or `d` tag, ensuring the UI only shows the most recent valid version.
* **`tombstones`**: Tracks deleted events to prevent "zombie" events from reappearing during partial syncs.
## Key Architectures
### 1. The "Active Map" & Deduplication
Nostr is immutable; "editing" a video means publishing a NEW event with the same identifier (`d` tag).
The client listens to *all* versions but only keeps the latest one in `activeMap`.
```javascript
// Simplified Logic
if (incomingEvent.createdAt > currentActiveEvent.createdAt) {
activeMap.set(videoRootId, incomingEvent);
notifyUI();
}
```
### 2. Buffering Strategy
When the app loads, relays might send 1000+ events in a second. Rendering React components 1000 times is too slow.
`subscribeVideos` pushes events to a buffer and flushes them every 75ms.
```javascript
sub.on("event", (evt) => {
buffer.push(evt);
debounce(flushBuffer, 75);
});
```
### 3. Tombstoning (Deletes)
Since relays are eventually consistent, a "delete" event (Kind 5) might arrive *before* the event it deletes, or *after*.
The client tracks `tombstones` (map of ID -> deletedAt timestamp). Any incoming event older than its tombstone is immediately discarded.
## Main Entry Points
* `init()`: Bootstraps the client, restores local cache, connects to relays.
* `subscribeVideos(callback)`: Main feed subscription.
* `publishVideo(payload)`: Complex flow to upload -> sign -> publish -> mirror.
* `connectRemoteSigner(uri)`: Handshake protocol for NIP-46.