Skip to content

nostr: add NIP-40 expiration to gift wrap and private DM builders#1384

Merged
yukibtc merged 1 commit into
nostrdevkit:masterfrom
unsaltedbutter-ai:feat/nip17-expiration
Jul 1, 2026
Merged

nostr: add NIP-40 expiration to gift wrap and private DM builders#1384
yukibtc merged 1 commit into
nostrdevkit:masterfrom
unsaltedbutter-ai:feat/nip17-expiration

Conversation

@unsaltedbutter-ai

Copy link
Copy Markdown
Contributor

Description

Add an expiration option to GiftWrapBuilder and PrivateDirectMessageBuilder. The NIP-40 expiration tag is anchored to the gift wrap's randomized created_at (created_at + duration) instead of the real send time, so it doesn't leak when the message was actually sent.

Closes #1381

Notes to the reviewers

One design decision:
expiration is a builder method taking a Duration rather than something you pass through extra_tags.
It has to be anchored to the gift wrap's created_at, which is randomized internally and not exposed to the caller.

Setting an absolute timestamp from outside would leak the real send time (subtract the duration and you've got it).

So by setting Duration, the library does created_at + duration and nothing leaks.

NIP-17 just hands the same value down to the gift wrap builder. The tag goes on the gift wrap, not the kind:13 seal, which NIP-59 requires to be empty.

Checklist

@unsaltedbutter-ai

Copy link
Copy Markdown
Contributor Author

I know the bindings live in nostr-sdk-ffi and this only touches the core crate.
Do you mind if I submit the matching ffi change once this lands? Unless you'd rather fold that in on your side.

@yukibtc yukibtc force-pushed the feat/nip17-expiration branch from 22bc4ba to 3508765 Compare July 1, 2026 09:21
Add an expiration option to GiftWrapBuilder and PrivateDirectMessageBuilder.
The NIP-40 expiration tag is anchored to the gift wrap's randomized created_at
(created_at + duration) instead of the real send time,
so it doesn't leak when the message was actually sent.

Closes nostrdevkit#1381

Pull-Request: nostrdevkit#1384
Signed-off-by: Info <info@unsaltedbutter.ai>
Signed-off-by: Yuki Kishimoto <yukikishimoto@protonmail.com>
@yukibtc yukibtc force-pushed the feat/nip17-expiration branch from 3508765 to 9df86d4 Compare July 1, 2026 09:22
@yukibtc yukibtc merged commit 9df86d4 into nostrdevkit:master Jul 1, 2026
@yukibtc

yukibtc commented Jul 1, 2026

Copy link
Copy Markdown
Member

Thanks! Squashed and merged at 9df86d4

I know the bindings live in nostr-sdk-ffi and this only touches the core crate.
Do you mind if I submit the matching ffi change once this lands? Unless you'd rather fold that in on your side.

Sure, feel free to open a PR also for FFI, thanks!

@unsaltedbutter-ai

Copy link
Copy Markdown
Contributor Author

@yukibtc — for this NIP-40 change, it's a small change in the FFI:

  • an optional expiration: Option on nip17_make_private_msg and nip59_make_gift_wrap (+ async).

However, nostr-sdk-ffi still pins nostr at alpha.2 (83fa932), and this change is only reachable at alpha.3+ (9df86d4). Moving the pin also crosses the NIP‑03/15/31/90 removal, which breaks the current bindings (nip90.rs, EventBuilder::job_*, Tag::alt, some Kind variants).
So the dependency bump isn't clean.

Are you working on bumping the FFI to alpha.3, or do you want me to include that bump & migration as a part of a NIP-40 PR?

@yukibtc

yukibtc commented Jul 2, 2026

Copy link
Copy Markdown
Member

@unsaltedbutter-ai, I've updated it at nostrdevkit/nostr-sdk-ffi@96ecfad and exposed expiration for NIP-17 and NIP-59 at nostrdevkit/nostr-sdk-ffi@09c0f7f

@unsaltedbutter-ai

unsaltedbutter-ai commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Thank you. I have a project ready to use this — will keep an eye out for the next nostr-sdk release that includes it.

@yukibtc

yukibtc commented Jul 3, 2026

Copy link
Copy Markdown
Member

Thank you. I have a project ready to use this — will keep an eye out for the next nostr-sdk release that includes it.

I'll probably release the alpha.4 in the next few weeks. You can also use the nostr-sdk directly from git:

nostr-sdk = { git = "https://github.com/rust-nostr/nostr", rev = "<commit>" }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

nip17: add NIP-40 expiration to private DM builders

2 participants