feat: Add NIP-17/59 gift-wrapped DM support with caching

Implements encrypted private messaging using gift wraps:

- Add event cache service (Dexie) for offline access
- Add rumor storage for caching decrypted gift wrap content
- Wire persistEventsToCache and persistEncryptedContent to EventStore
- Create NIP-17 adapter for gift-wrapped DMs
- Add InboxViewer component for DM conversation list
- Add `inbox` command to open private message inbox
- Register NIP-17 adapter in ChatViewer

Features:
- Decrypt once, cache forever - no re-decryption needed
- Explicit decrypt button (user-initiated)
- Conversation list derived from decrypted gift wraps
- Private inbox relay discovery (kind 10050)
- Send not yet implemented (TODO: use SendWrappedMessage action)
This commit is contained in:
Claude
2026-01-14 11:39:08 +00:00
parent 998944fdf7
commit cd052d657f
10 changed files with 1443 additions and 2 deletions

View File

@@ -23,6 +23,7 @@ import type {
// import { NipC7Adapter } from "@/lib/chat/adapters/nip-c7-adapter"; // Coming soon
import { Nip29Adapter } from "@/lib/chat/adapters/nip-29-adapter";
import { Nip53Adapter } from "@/lib/chat/adapters/nip-53-adapter";
import { Nip17Adapter } from "@/lib/chat/adapters/nip-17-adapter";
import type { ChatProtocolAdapter } from "@/lib/chat/adapters/base-adapter";
import type { Message } from "@/types/chat";
import type { ChatAction } from "@/types/chat-actions";
@@ -630,6 +631,8 @@ export function ChatViewer({
addWindow("nip", { number: 29 });
} else if (conversation?.protocol === "nip-53") {
addWindow("nip", { number: 53 });
} else if (conversation?.protocol === "nip-17") {
addWindow("nip", { number: 17 });
}
}, [conversation?.protocol, addWindow]);
@@ -955,8 +958,8 @@ function getAdapter(protocol: ChatProtocol): ChatProtocolAdapter {
// return new NipC7Adapter();
case "nip-29":
return new Nip29Adapter();
// case "nip-17": // Phase 2 - Encrypted DMs (coming soon)
// return new Nip17Adapter();
case "nip-17":
return new Nip17Adapter();
// case "nip-28": // Phase 3 - Public channels (coming soon)
// return new Nip28Adapter();
case "nip-53":