diff --git a/59.md b/59.md index 032968aa..c831e10e 100644 --- a/59.md +++ b/59.md @@ -72,6 +72,28 @@ needed to route the event to its intended recipient, including the recipient's ` } ``` +### 4. Ephemeral Gift Wrap Event Kind + +An ephemeral gift wrap is a `kind:21059` event. It has the same structure as `kind:1059` but follows ephemeral event +semantics (relays MUST NOT store it). + +```json +{ + "id": "", + "pubkey": "", + "content": "", + "kind": 21059, + "created_at": 1686840217, + "tags": [["p", ""]], + "sig": "" +} +``` + +`kind:1059` is intended for regular direct messages and asynchronous communication where message persistence +and offline delivery are expected, such as in NIP-17. `kind:21059` is intended for real-time applications +that do not require asynchronous operations and where messages are only relevant to currently connected +recipients, such as live chat or real-time gaming. + ## Encrypting Payloads Encryption is done following [NIP-44](44.md) on the JSON-encoded event. Place the encryption payload in the `.content` @@ -103,7 +125,7 @@ AUTH, and refuse to serve wrapped events to non-recipients. When adding expiration tags to both `seal` and `gift wrap` layers, implementations SHOULD use independent random timestamps for each layer. Using different `created_at` values increases timing variance and helps protect against metadata correlation attacks. -Since signing keys are random, relays SHOULD delete `kind 1059` events whose p-tag matches the signer of +Since signing keys are random, relays SHOULD delete `kind:1059` events whose p-tag matches the signer of [NIP-09](09.md) deletions or [NIP-62](62.md) vanish requests. ## An Example @@ -171,7 +193,7 @@ Sign the `gift wrap` using the random key generated in the previous step. ### 4. Broadcast Selectively -Broadcast the `kind 1059` event to the recipient's relays only. Delete all the other events. +Broadcast the `kind:1059` or `kind:21059` event to the recipient's relays only. Delete all the other events. ## Code Samples @@ -238,6 +260,20 @@ const createWrap = (event: Event, recipientPublicKey: string) => { ) as Event } +const createEphemeralWrap = (event: Event, recipientPublicKey: string) => { + const randomKey = generateSecretKey() + + return finalizeEvent( + { + kind: 21059, + content: nip44Encrypt(event, randomKey, recipientPublicKey), + created_at: randomNow(), + tags: [["p", recipientPublicKey]], + }, + randomKey + ) as Event +} + // Test case using the above example const senderPrivateKey = nip19.decode(`nsec1p0ht6p3wepe47sjrgesyn4m50m6avk2waqudu9rl324cg2c4ufesyp6rdg`).data const recipientPrivateKey = nip19.decode(`nsec1uyyrnx7cgfp40fcskcr2urqnzekc20fj0er6de0q8qvhx34ahazsvs9p36`).data