Document and test share note events

This commit is contained in:
thePR0M3TH3AN committed 2026-01-22 22:50:00 -05:00
1 parent 6a0c1014b3
commit 5e389ab29b
3 files changed
+111 -4

No files matched your search

+16
View File
@@ -174,6 +174,22 @@ import { updateWatchHistoryListWithDefaultClient } from "./nostrWatchHistoryFaca
| Zap request (`NOTE_TYPES.ZAP_REQUEST`) | `9734` | `['p', <recipient pubkey>]` plus optional `['e', <event id>]`, `['a', <coordinate>]`, `['amount', <msats>]`, `['lnurl', <bech32>]`, and `['relays', ...]` for receipt publishing | Optional plaintext zap note |
| Zap receipt (`NOTE_TYPES.ZAP_RECEIPT`) | `9735` | `['bolt11', <invoice>]`, `['description', <zap request JSON>]`, `['p', <recipient pubkey>]` plus optional `['e', <event id>]` and `['a', <coordinate>]` | Empty content; receipts are published by the recipient's LNURL server |
### Share notes (kind `1`)
Share notes are plain text `kind:1` events generated by the Share modal. The
`content` field is preserved verbatim (after UTF-8 sanitization) and can contain
any short message or commentary accompanying the share.
The builder attaches the following tags:
* `['e', <event id>, '', 'mention']` — the shared video’s event id, normalized to
lowercase hex.
* `['p', <pubkey>, '', 'mention']` — the shared video’s author pubkey,
normalized to lowercase hex.
* `['r', <relay url>, <read/write?>]` — optional relay hints. Relay URLs are
trimmed, duplicates are removed, and the optional marker is normalized to
`read` or `write` when provided.
Subscription lists therefore match the
[NIP-51 follow-set specification](./nips/51.md#sets) by emitting kind `30000`
events with the shared `['d','subscriptions']` identifier. Builders continue to
+2 -4
View File
@@ -1010,14 +1010,12 @@ export function buildShareEvent(params) {
const readMarker = schema?.readMarker || "read";
const writeMarker = schema?.writeMarker || "write";
const normalizedVideoId =
typeof video?.id === "string" ? video.id.trim() : "";
const normalizedVideoId = normalizePointerIdentifier(video?.id);
if (normalizedVideoId) {
tags.push(["e", normalizedVideoId, "", "mention"]);
}
const normalizedVideoPubkey =
typeof video?.pubkey === "string" ? video.pubkey.trim() : "";
const normalizedVideoPubkey = normalizePointerIdentifier(video?.pubkey);
if (normalizedVideoPubkey) {
tags.push(["p", normalizedVideoPubkey, "", "mention"]);
}
+93
View File
@@ -0,0 +1,93 @@
import test from "node:test";
import assert from "node:assert/strict";
const SAMPLE_HEX = "deadbeef".repeat(8);
const SAMPLE_NPUB = "npub1shareeventfixture000000000000000000000";
if (typeof globalThis.window === "undefined") {
globalThis.window = {};
}
if (!globalThis.window.NostrTools) {
globalThis.window.NostrTools = {};
}
const existingNip19 =
typeof globalThis.window.NostrTools.nip19 === "object"
? globalThis.window.NostrTools.nip19
: {};
if (typeof existingNip19.decode !== "function") {
globalThis.window.NostrTools.nip19 = {
...existingNip19,
decode: () => ({ type: "npub", data: SAMPLE_HEX }),
};
}
const { buildShareEvent } = await import("../js/nostrEventSchemas.js");
test("buildShareEvent preserves share content", () => {
const event = buildShareEvent({
pubkey: "share-author",
created_at: 1700000800,
content: "Check this out!",
video: { id: "a".repeat(64), pubkey: "b".repeat(64) },
});
assert.equal(event.content, "Check this out!");
});
test("buildShareEvent normalizes hex identifiers for e and p tags", () => {
const event = buildShareEvent({
pubkey: "share-author",
created_at: 1700000801,
content: "Normalize IDs",
video: {
id: "ABCDEF".repeat(10) + "ABCD",
pubkey: SAMPLE_NPUB,
},
});
const eventTags = event.tags.filter((tag) => Array.isArray(tag) && tag[0] === "e");
const authorTags = event.tags.filter((tag) => Array.isArray(tag) && tag[0] === "p");
assert.deepEqual(eventTags, [["e", "abcdef".repeat(10) + "abcd", "", "mention"]]);
assert.deepEqual(authorTags, [["p", SAMPLE_HEX, "", "mention"]]);
});
test("buildShareEvent includes sanitized relay hints", () => {
const event = buildShareEvent({
pubkey: "share-author",
created_at: 1700000802,
content: "Relay hints",
video: { id: "c".repeat(64), pubkey: "d".repeat(64) },
relays: [
" wss://relay.one ",
{ url: " wss://relay.two ", mode: "READ" },
["r", "wss://relay.one", "write"],
{ relay: "wss://relay.three", write: true, read: false },
["wss://relay.four", "write"],
],
});
const relayTags = event.tags.filter((tag) => Array.isArray(tag) && tag[0] === "r");
assert.deepEqual(relayTags, [
["r", "wss://relay.one"],
["r", "wss://relay.two", "read"],
["r", "wss://relay.one", "write"],
["r", "wss://relay.three", "write"],
["r", "wss://relay.four", "write"],
]);
});
test("buildShareEvent tolerates missing optional fields", () => {
const event = buildShareEvent({
pubkey: "share-author",
created_at: 1700000803,
});
assert.equal(event.kind, 1);
assert.equal(event.content, "");
assert.deepEqual(event.tags, []);
});