mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-29 08:52:25 +00:00
- Added JSDoc comments to `NostrClient` class and methods. - Added JSDoc comments to `EventsCacheStore`. - Created `docs/nostr-client-overview.md` with high-level documentation. - Fixed a race condition in `tests/nostr-delete-flow.test.mjs`.
80 lines
4.1 KiB
Markdown
80 lines
4.1 KiB
Markdown
# NostrClient Overview
|
|
|
|
`NostrClient` (`js/nostr/client.js`) is the central controller for all Nostr network interactions and state management in the application. It acts as a facade over `nostr-tools`, managing connections to multiple relays, signing events, and maintaining the local application state.
|
|
|
|
## Responsibilities
|
|
|
|
1. **Connection Management**: Maintains a pool of connections to configured Nostr relays. It handles initialization, reconnection, and error logging.
|
|
2. **Event Publishing**: Handles the creation, signing, and broadcasting of various Nostr event kinds (Video Post: 30078, Reaction: 7, Comment: 1, etc.). It supports NIP-07 (Extension), NIP-46 (Remote/Bunker), and NIP-01 (Local nsec) signers.
|
|
3. **State Management**:
|
|
* `allEvents`: A raw map of all fetched video events (Kind 30078), preserving history.
|
|
* `activeMap`: A derived map containing only the *latest* version of each video, deduplicated by `videoRootId` or `d` tag. This is the source of truth for the UI.
|
|
* `rawEvents`: A cache of the exact raw JSON events from relays, used for signature verification and republishing.
|
|
* `tombstones`: Tracks deletion timestamps to prevent deleted events from reappearing.
|
|
4. **Caching**: Implements a dual-layer cache (`IndexedDB` + `localStorage`) to persist `activeMap`, `allEvents`, and `tombstones`. This allows the app to restore its state instantly on load ("stale-while-revalidate").
|
|
5. **Video Lifecycle**: Manages the full lifecycle of a video post: Publish -> Edit (new event with same `d` tag) -> Revert (new event, same `d`, deleted flag) -> Delete (Kind 5).
|
|
|
|
## Key Concepts
|
|
|
|
### Active Video Logic
|
|
Nostr is an append-only protocol. Edits are new events. `NostrClient` implements "latest-wins" logic to present a coherent view:
|
|
- **Identifier**: Videos are identified by a `videoRootId` (in the content) or a NIP-33 `d` tag.
|
|
- **Resolution**: When a new event arrives, the client checks if it's newer than the current active version in `activeMap`. If so, it replaces the entry.
|
|
- **Deletions**: If an event has `deleted: true` or is a Kind 5 deletion, it is removed from `activeMap`, and a tombstone is recorded.
|
|
|
|
### Buffering & Debouncing
|
|
To handle high volumes of events (e.g., during initial relay dump), `subscribeVideos` uses a buffering strategy:
|
|
1. Incoming events are pushed to `eventBuffer`.
|
|
2. A flush is scheduled with a short debounce (e.g., 75ms).
|
|
3. On flush, the batch is processed: validation, state updates, and UI notification.
|
|
This prevents UI thrashing.
|
|
|
|
### Tombstones
|
|
Because relays are eventually consistent, a deleted event might arrive *after* a deletion command.
|
|
- `tombstones` map `activeKey` -> `timestamp`.
|
|
- If an incoming event is older than the tombstone for its key, it is ignored (`applyTombstoneGuard`).
|
|
|
|
## Example Flow: `subscribeVideos`
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant UI
|
|
participant Client as NostrClient
|
|
participant Buffer as EventBuffer
|
|
participant State as activeMap
|
|
participant Relays
|
|
|
|
UI->>Client: subscribeVideos(onVideo)
|
|
Client->>Relays: REQ Kind 30078
|
|
Relays-->>Client: EVENT (Video A, v1)
|
|
Client->>Buffer: Push Event
|
|
Client->>Buffer: Schedule Flush (75ms)
|
|
Relays-->>Client: EVENT (Video B, v1)
|
|
Client->>Buffer: Push Event
|
|
|
|
Note over Client, Buffer: 75ms passes...
|
|
|
|
Client->>Buffer: Flush()
|
|
loop For each event
|
|
Buffer->>State: Is newer?
|
|
alt Yes
|
|
State->>State: Update Entry
|
|
State->>UI: onVideo(Video)
|
|
else No
|
|
State->>State: Ignore
|
|
end
|
|
end
|
|
```
|
|
|
|
## When to Modify
|
|
|
|
- **Adding a new Event Kind**: If the app needs to support a new type of interaction (e.g., playlists), add the handling logic here and in `js/nostrEventSchemas.js`.
|
|
- **Changing Caching Strategy**: Modify `EventsCacheStore` or `persistLocalData` if the caching requirements change.
|
|
- **Updating Signing Logic**: Changes to NIP-07 or NIP-46 integration should be carefully reviewed here.
|
|
|
|
## Related Files
|
|
|
|
- `js/nostrEventSchemas.js`: Definitions of event structures.
|
|
- `js/nostr/nip71.js`: Helper logic for video categorization (NIP-71).
|
|
- `js/nostr/watchHistory.js`: Manages user watch history state.
|