diff --git a/src/components/ChatViewer.tsx b/src/components/ChatViewer.tsx
index ef3b89b..f65019b 100644
--- a/src/components/ChatViewer.tsx
+++ b/src/components/ChatViewer.tsx
@@ -940,6 +940,28 @@ export function ChatViewer({
{conversation.metadata.description}
)}
+ {/* Participants for NIP-17 group DMs */}
+ {protocol === "nip-17" &&
+ conversation.participants.length > 2 && (
+
+
+ Participants:
+
+
+ {[
+ ...new Set(
+ conversation.participants.map((p) => p.pubkey),
+ ),
+ ].map((participantPubkey) => (
+
+ ))}
+
+
+ )}
{/* Protocol Type - Clickable */}
{(conversation.type === "group" ||
diff --git a/src/lib/chat/adapters/nip-17-adapter.ts b/src/lib/chat/adapters/nip-17-adapter.ts
index d7af0a5..711812f 100644
--- a/src/lib/chat/adapters/nip-17-adapter.ts
+++ b/src/lib/chat/adapters/nip-17-adapter.ts
@@ -462,8 +462,9 @@ export class Nip17Adapter extends ChatProtocolAdapter {
* Helper: Get conversation key from conversation
*/
private getConversationKey(conversation: Conversation): string {
- const pubkeys = conversation.participants.map((p) => p.pubkey).sort();
- return pubkeys.join(":");
+ const pubkeys = conversation.participants.map((p) => p.pubkey);
+ // Deduplicate and sort for consistency with gift wrap storage
+ return [...new Set(pubkeys)].sort().join(":");
}
/**
diff --git a/src/services/gift-wrap.ts b/src/services/gift-wrap.ts
index 5d93238..434dd36 100644
--- a/src/services/gift-wrap.ts
+++ b/src/services/gift-wrap.ts
@@ -775,9 +775,22 @@ class GiftWrapManager {
throw new Error(`Failed to unlock gift wrap: ${error}`);
}
- // Use applesauce helper to get the conversation identifier
- // This properly handles all participants including group DMs
- const conversationKey = getConversationIdentifierFromMessage(rumor);
+ // Generate conversation key based on rumor kind
+ // For kind 14 (DMs), use applesauce helper which handles groups properly
+ // For other kinds (reactions, etc.), extract participants from p-tags
+ let conversationKey: string;
+ if (rumor.kind === 14) {
+ // Use applesauce helper for DMs - it properly handles group DMs
+ conversationKey = getConversationIdentifierFromMessage(rumor);
+ } else {
+ // For non-DM events (reactions, private relays, etc.),
+ // create conversation key from sender + all p-tags
+ const recipientPubkeys = rumor.tags
+ .filter((t: string[]) => t[0] === "p" && t[1])
+ .map((t: string[]) => t[1]);
+ const allParticipants = [rumor.pubkey, ...recipientPubkeys];
+ conversationKey = [...new Set(allParticipants)].sort().join(":");
+ }
// Get seal ID from gift wrap tags (applesauce stores it there)
const sealId = rumor.id.split(":")[1] || giftWrap.id;