From e488e7d723f4aa86e71fdb1a6e699dfcb5fa779f Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 16 Jan 2026 07:34:52 +0000 Subject: [PATCH] fix: Ensure gift wrap is in event store before unlocking CRITICAL FIX: Applesauce caches seal/rumor on gift wrap event objects via symbols. These cached values must be stored in the event store to persist properly. Changes: - Import eventStore in gift-wrap.ts - Call eventStore.add(giftWrap) before unlocking in processGiftWrap() - Updated comments to explain the requirement - This ensures pending gift wraps (from Dexie) are re-added to event store before decryption Why this matters: - When processing pending gift wraps from database, those events are NOT in event store - unlockGiftWrap caches results on the event object using symbols - Without event store presence, caching doesn't work correctly - This fixes serialization errors from missing cached data Follows applesauce pattern from their gift wrap example. --- src/services/gift-wrap.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/services/gift-wrap.ts b/src/services/gift-wrap.ts index 1a7a135..7566e32 100644 --- a/src/services/gift-wrap.ts +++ b/src/services/gift-wrap.ts @@ -15,6 +15,7 @@ import type { NostrEvent } from "@/types/nostr"; import type { ISigner } from "applesauce-signers"; import { unlockGiftWrap, getGiftWrapSeal } from "applesauce-common/helpers"; +import eventStore from "./event-store"; import db, { GiftWrapEnvelope, DecryptedRumor, @@ -46,9 +47,12 @@ export class GiftWrapError extends Error { * Uses applesauce-common unlockGiftWrap helper * * Note: Rumors are unsigned events (no sig field) - this is by design in NIP-59. - * Applesauce handles all validation internally. + * Applesauce caches the rumor on the gift wrap event object using symbols. * - * @param giftWrap - Kind 1059 gift wrap event + * IMPORTANT: The gift wrap event MUST be in the event store before calling this, + * as applesauce uses the event store to cache and retrieve seals/rumors. + * + * @param giftWrap - Kind 1059 gift wrap event (must be in event store) * @param signer - Signer for recipient (to decrypt) * @returns Object with seal and rumor */ @@ -57,7 +61,7 @@ export async function unwrapAndUnseal( signer: ISigner, ): Promise<{ seal: NostrEvent; rumor: NostrEvent }> { // Use applesauce helper to unlock the gift wrap - // This handles all validation internally + // This caches the seal and rumor on the gift wrap event object via symbols const rumor = await unlockGiftWrap(giftWrap, signer); // Get the seal from the unlocked gift wrap @@ -102,6 +106,10 @@ export async function processGiftWrap( } } + // CRITICAL: Ensure gift wrap is in event store before unlocking + // Applesauce caches seal/rumor on the event object via symbols + eventStore.add(giftWrap); + // Store gift wrap envelope const envelope: GiftWrapEnvelope = { id: giftWrap.id,