@@ -159,6 +159,43 @@ async fn create_private_dm_event(
159159 )
160160}
161161
162+ /// Builds the published NIP-59 **Gift Wrap** (kind 1059) from a signed **Seal** event.
163+ ///
164+ /// Rust-nostr’s `EventBuilder::gift_wrap` seals and wraps but does not apply NIP-13 PoW to the
165+ /// outer Gift Wrap; Mostro may require that difficulty on the relay-visible event. This helper
166+ /// mirrors the SDK’s seal→wrap steps: reject non-seal inputs, encrypt the seal JSON to `receiver`
167+ /// with NIP-44 using an **ephemeral** key pair, attach `p` and optional tags, set
168+ /// [`nip59::RANGE_RANDOM_TIMESTAMP_TWEAK`]-style `created_at`, mine with [`EventBuilder::pow`],
169+ /// then sign the wrap with the ephemeral keys.
170+ fn gift_wrap_from_seal_with_pow (
171+ receiver : & PublicKey ,
172+ seal : & Event ,
173+ extra_tags : impl IntoIterator < Item = Tag > ,
174+ pow : u8 ,
175+ ) -> Result < Event > {
176+ if seal. kind != nostr_sdk:: Kind :: Seal {
177+ return Err ( anyhow:: anyhow!( "Invalid kind" ) ) ;
178+ }
179+
180+ let ephem = Keys :: generate ( ) ;
181+ let content = nip44:: encrypt (
182+ ephem. secret_key ( ) ,
183+ receiver,
184+ seal. as_json ( ) ,
185+ nip44:: Version :: default ( ) ,
186+ ) ?;
187+
188+ let mut tags: Vec < Tag > = extra_tags. into_iter ( ) . collect ( ) ;
189+ tags. push ( Tag :: public_key ( * receiver) ) ;
190+
191+ EventBuilder :: new ( nostr_sdk:: Kind :: GiftWrap , content)
192+ . tags ( tags)
193+ . custom_created_at ( Timestamp :: tweaked ( nip59:: RANGE_RANDOM_TIMESTAMP_TWEAK ) )
194+ . pow ( pow)
195+ . sign_with_keys ( & ephem)
196+ . map_err ( |e| anyhow:: anyhow!( "Failed to sign gift wrap: {e}" ) )
197+ }
198+
162199async fn create_gift_wrap_event (
163200 trade_keys : & Keys ,
164201 identity_keys : Option < & Keys > ,
@@ -183,9 +220,7 @@ async fn create_gift_wrap_event(
183220 . map_err ( |e| anyhow:: anyhow!( "Failed to serialize message: {e}" ) ) ?
184221 } ;
185222
186- let rumor = EventBuilder :: text_note ( content)
187- . pow ( pow)
188- . build ( trade_keys. public_key ( ) ) ;
223+ let rumor = EventBuilder :: text_note ( content) . build ( trade_keys. public_key ( ) ) ;
189224
190225 let tags = create_expiration_tags ( expiration) ;
191226
@@ -195,7 +230,12 @@ async fn create_gift_wrap_event(
195230 trade_keys
196231 } ;
197232
198- Ok ( EventBuilder :: gift_wrap ( signer_keys, receiver_pubkey, rumor, tags) . await ?)
233+ let seal: Event = EventBuilder :: seal ( signer_keys, receiver_pubkey, rumor)
234+ . await ?
235+ . sign ( signer_keys)
236+ . await ?;
237+
238+ gift_wrap_from_seal_with_pow ( receiver_pubkey, & seal, tags, pow)
199239}
200240
201241pub async fn send_dm (
0 commit comments