@qntx/nostr 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +25 -0
  3. package/dist/builder-BphJa-Y-.d.mts +67 -0
  4. package/dist/builder-q0VsvnYE.mjs +158 -0
  5. package/dist/builder-q0VsvnYE.mjs.map +1 -0
  6. package/dist/client-Bd8B1mYm.mjs +835 -0
  7. package/dist/client-Bd8B1mYm.mjs.map +1 -0
  8. package/dist/client.d.mts +2 -0
  9. package/dist/client.mjs +2 -0
  10. package/dist/core.d.mts +8 -0
  11. package/dist/core.mjs +9 -0
  12. package/dist/error-B49rbDzT.d.mts +7 -0
  13. package/dist/error-CwBxle6N.mjs +13 -0
  14. package/dist/error-CwBxle6N.mjs.map +1 -0
  15. package/dist/error-DZEs5OuZ.mjs +24 -0
  16. package/dist/error-DZEs5OuZ.mjs.map +1 -0
  17. package/dist/error-WEFS-R-4.d.mts +20 -0
  18. package/dist/event-B5D2jxt_.d.mts +108 -0
  19. package/dist/event-CzoQEFMF.mjs +188 -0
  20. package/dist/event-CzoQEFMF.mjs.map +1 -0
  21. package/dist/filter-BxwjEkZp.mjs +113 -0
  22. package/dist/filter-BxwjEkZp.mjs.map +1 -0
  23. package/dist/filter-DUEKP3q1.d.mts +40 -0
  24. package/dist/gossip-3xkRRCm_.mjs +220 -0
  25. package/dist/gossip-3xkRRCm_.mjs.map +1 -0
  26. package/dist/gossip-C5RVB1UB.d.mts +71 -0
  27. package/dist/gossip.d.mts +3 -0
  28. package/dist/gossip.mjs +2 -0
  29. package/dist/http-6vevbBlu.d.mts +22 -0
  30. package/dist/http-D2rhokZo.mjs +24 -0
  31. package/dist/http-D2rhokZo.mjs.map +1 -0
  32. package/dist/index-BYMnhRIC.d.mts +161 -0
  33. package/dist/index-C0C4e-Gn.d.mts +55 -0
  34. package/dist/index-CaxrMD1A.d.mts +1 -0
  35. package/dist/index-DaRyjo7O.d.mts +77 -0
  36. package/dist/index-DgOugrpF.d.mts +275 -0
  37. package/dist/index-EwL6fHLo.d.mts +267 -0
  38. package/dist/index-k2YhCgsh.d.mts +57 -0
  39. package/dist/index.d.mts +22 -0
  40. package/dist/index.mjs +23 -0
  41. package/dist/key-BiGxGLhg.d.mts +37 -0
  42. package/dist/key-Dn-aX4x4.mjs +130 -0
  43. package/dist/key-Dn-aX4x4.mjs.map +1 -0
  44. package/dist/kind-BLl4cLOc.mjs +59 -0
  45. package/dist/kind-BLl4cLOc.mjs.map +1 -0
  46. package/dist/loaders-BNQszDAn.mjs +767 -0
  47. package/dist/loaders-BNQszDAn.mjs.map +1 -0
  48. package/dist/loaders.d.mts +3 -0
  49. package/dist/loaders.mjs +2 -0
  50. package/dist/memory-BCmhZPek.mjs +461 -0
  51. package/dist/memory-BCmhZPek.mjs.map +1 -0
  52. package/dist/message-C_Uj-Y-c.mjs +179 -0
  53. package/dist/message-C_Uj-Y-c.mjs.map +1 -0
  54. package/dist/message-DJC-Jz6T.d.mts +32 -0
  55. package/dist/nip17-BWq-Kfq5.d.mts +38 -0
  56. package/dist/nip19-D7905oIv.d.mts +63 -0
  57. package/dist/nip46-C_DoxiS_.d.mts +51 -0
  58. package/dist/nip59-DljW_sYh.d.mts +76 -0
  59. package/dist/nip65-Di5hZRuV.d.mts +21 -0
  60. package/dist/nip77-ByxlgoQO.d.mts +55 -0
  61. package/dist/nips/blossom.d.mts +93 -0
  62. package/dist/nips/blossom.mjs +325 -0
  63. package/dist/nips/blossom.mjs.map +1 -0
  64. package/dist/nips/nip04.d.mts +8 -0
  65. package/dist/nips/nip04.mjs +41 -0
  66. package/dist/nips/nip04.mjs.map +1 -0
  67. package/dist/nips/nip05.d.mts +89 -0
  68. package/dist/nips/nip05.mjs +147 -0
  69. package/dist/nips/nip05.mjs.map +1 -0
  70. package/dist/nips/nip10.d.mts +43 -0
  71. package/dist/nips/nip10.mjs +194 -0
  72. package/dist/nips/nip10.mjs.map +1 -0
  73. package/dist/nips/nip11.d.mts +43 -0
  74. package/dist/nips/nip11.mjs +99 -0
  75. package/dist/nips/nip11.mjs.map +1 -0
  76. package/dist/nips/nip13.d.mts +23 -0
  77. package/dist/nips/nip13.mjs +88 -0
  78. package/dist/nips/nip13.mjs.map +1 -0
  79. package/dist/nips/nip17.d.mts +2 -0
  80. package/dist/nips/nip17.mjs +138 -0
  81. package/dist/nips/nip17.mjs.map +1 -0
  82. package/dist/nips/nip19.d.mts +2 -0
  83. package/dist/nips/nip19.mjs +174 -0
  84. package/dist/nips/nip19.mjs.map +1 -0
  85. package/dist/nips/nip21.d.mts +17 -0
  86. package/dist/nips/nip21.mjs +29 -0
  87. package/dist/nips/nip21.mjs.map +1 -0
  88. package/dist/nips/nip27.d.mts +42 -0
  89. package/dist/nips/nip27.mjs +175 -0
  90. package/dist/nips/nip27.mjs.map +1 -0
  91. package/dist/nips/nip42.d.mts +12 -0
  92. package/dist/nips/nip42.mjs +22 -0
  93. package/dist/nips/nip42.mjs.map +1 -0
  94. package/dist/nips/nip44.d.mts +12 -0
  95. package/dist/nips/nip44.mjs +125 -0
  96. package/dist/nips/nip44.mjs.map +1 -0
  97. package/dist/nips/nip46.d.mts +2 -0
  98. package/dist/nips/nip46.mjs +132 -0
  99. package/dist/nips/nip46.mjs.map +1 -0
  100. package/dist/nips/nip49.d.mts +12 -0
  101. package/dist/nips/nip49.mjs +80 -0
  102. package/dist/nips/nip49.mjs.map +1 -0
  103. package/dist/nips/nip51.d.mts +88 -0
  104. package/dist/nips/nip51.mjs +246 -0
  105. package/dist/nips/nip51.mjs.map +1 -0
  106. package/dist/nips/nip57.d.mts +43 -0
  107. package/dist/nips/nip57.mjs +230 -0
  108. package/dist/nips/nip57.mjs.map +1 -0
  109. package/dist/nips/nip59.d.mts +2 -0
  110. package/dist/nips/nip59.mjs +171 -0
  111. package/dist/nips/nip59.mjs.map +1 -0
  112. package/dist/nips/nip65.d.mts +2 -0
  113. package/dist/nips/nip65.mjs +76 -0
  114. package/dist/nips/nip65.mjs.map +1 -0
  115. package/dist/nips/nip77.d.mts +2 -0
  116. package/dist/nips/nip77.mjs +421 -0
  117. package/dist/nips/nip77.mjs.map +1 -0
  118. package/dist/nips/nip96.d.mts +31 -0
  119. package/dist/nips/nip96.mjs +95 -0
  120. package/dist/nips/nip96.mjs.map +1 -0
  121. package/dist/nips/nip98.d.mts +28 -0
  122. package/dist/nips/nip98.mjs +91 -0
  123. package/dist/nips/nip98.mjs.map +1 -0
  124. package/dist/nostr_crypto_wasm_bg-hi5aXi5P.mjs +4 -0
  125. package/dist/nostr_crypto_wasm_bg.wasm +0 -0
  126. package/dist/pool-C_j1OmBB.mjs +1881 -0
  127. package/dist/pool-C_j1OmBB.mjs.map +1 -0
  128. package/dist/pool-DhRi7l-b.d.mts +297 -0
  129. package/dist/relay.d.mts +4 -0
  130. package/dist/relay.mjs +2 -0
  131. package/dist/signer-CZ6K6FUc.mjs +473 -0
  132. package/dist/signer-CZ6K6FUc.mjs.map +1 -0
  133. package/dist/signer.d.mts +3 -0
  134. package/dist/signer.mjs +2 -0
  135. package/dist/storage-DOy0iLRE.mjs +870 -0
  136. package/dist/storage-DOy0iLRE.mjs.map +1 -0
  137. package/dist/storage.d.mts +4 -0
  138. package/dist/storage.mjs +4 -0
  139. package/dist/types-BzyADqnw.d.mts +19 -0
  140. package/dist/types-Dn24TPFs.d.mts +43 -0
  141. package/dist/util-6tfLQ9JF.mjs +73 -0
  142. package/dist/util-6tfLQ9JF.mjs.map +1 -0
  143. package/dist/wasm.d.mts +19 -0
  144. package/dist/wasm.mjs +237 -0
  145. package/dist/wasm.mjs.map +1 -0
  146. package/package.json +204 -0
@@ -0,0 +1,147 @@
1
+ import { a as isHex32 } from "../util-6tfLQ9JF.mjs";
2
+ import { a as NostrError } from "../error-DZEs5OuZ.mjs";
3
+ import { n as requireGlobalFetch, t as fetchManual } from "../http-D2rhokZo.mjs";
4
+ //#region src/nips/nip05.ts
5
+ /**
6
+ * NIP-05: Mapping Nostr keys to DNS-based internet identifiers
7
+ * @see https://github.com/nostr-protocol/nips/blob/master/05.md
8
+ */
9
+ /** Root local-part (`_@domain` rendered as just the domain). */
10
+ const NIP05_ROOT_LOCAL = "_";
11
+ const WELL_KNOWN_PATH = "/.well-known/nostr.json";
12
+ var Nip05Error = class extends NostrError {
13
+ constructor(message, options) {
14
+ super(message, options);
15
+ }
16
+ };
17
+ /**
18
+ * Matches optional local@domain.
19
+ * Groups: 1=local (optional), 2=domain.
20
+ */
21
+ const NIP05_REGEX = /^(?:([\w.+-]+)@)?([\w-]+(?:\.[\w-]+)+)$/;
22
+ function isNip05(value) {
23
+ return typeof value === "string" && NIP05_REGEX.test(value);
24
+ }
25
+ /**
26
+ * Parse an identifier into local + domain.
27
+ * Accepts `name@domain`, `_@domain`, or bare `domain` (local becomes `_`).
28
+ */
29
+ function parseNip05(input) {
30
+ const match = input.trim().match(NIP05_REGEX);
31
+ if (!match?.[2]) throw new Nip05Error(`invalid NIP-05 identifier: ${input}`);
32
+ const localRaw = match[1] ?? "_";
33
+ const local = localRaw.toLowerCase();
34
+ const domain = match[2].toLowerCase();
35
+ if (!/^[a-z0-9._-]+$/.test(local)) throw new Nip05Error(`invalid NIP-05 local-part: ${localRaw}`);
36
+ if (!domain) throw new Nip05Error("NIP-05 domain must not be empty");
37
+ return {
38
+ local,
39
+ domain
40
+ };
41
+ }
42
+ /** Build the well-known HTTPS URL for an address. */
43
+ function wellKnownUrl(address) {
44
+ const url = new URL(`https://${address.domain}${WELL_KNOWN_PATH}`);
45
+ url.searchParams.set("name", address.local);
46
+ return url.toString();
47
+ }
48
+ function stringUrls(list) {
49
+ if (!Array.isArray(list)) return void 0;
50
+ return list.filter((u) => typeof u === "string" && u.length > 0);
51
+ }
52
+ /**
53
+ * Parse nostr.json `nip46`: 46.md appendix `{relays, nostrconnect_url}`.
54
+ * Hex-pubkey maps and other keys are ignored.
55
+ */
56
+ function parseNip05Nip46(raw) {
57
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
58
+ const obj = raw;
59
+ const result = {};
60
+ if (Array.isArray(obj.relays)) result.relays = stringUrls(obj.relays) ?? [];
61
+ if (typeof obj.nostrconnect_url === "string" && obj.nostrconnect_url.length > 0) result.nostrconnectUrl = obj.nostrconnect_url;
62
+ if (result.relays === void 0 && result.nostrconnectUrl === void 0) return;
63
+ return result;
64
+ }
65
+ /** Parse and validate a nostr.json document body. */
66
+ function parseNip05Document(json) {
67
+ if (!json || typeof json !== "object") throw new Nip05Error("NIP-05 document must be a JSON object");
68
+ const raw = json;
69
+ if (!raw.names || typeof raw.names !== "object" || Array.isArray(raw.names)) throw new Nip05Error("NIP-05 document missing names map");
70
+ const names = {};
71
+ for (const [k, v] of Object.entries(raw.names)) {
72
+ if (typeof v !== "string" || !isHex32(v)) continue;
73
+ names[k.toLowerCase()] = v.toLowerCase();
74
+ }
75
+ let relays;
76
+ if (raw.relays && typeof raw.relays === "object" && !Array.isArray(raw.relays)) {
77
+ relays = {};
78
+ for (const [pk, list] of Object.entries(raw.relays)) {
79
+ if (!isHex32(pk)) continue;
80
+ const urls = stringUrls(list);
81
+ if (urls?.length) relays[pk.toLowerCase()] = urls;
82
+ }
83
+ }
84
+ return {
85
+ names,
86
+ relays,
87
+ nip46: parseNip05Nip46(raw.nip46)
88
+ };
89
+ }
90
+ /** Resolve local name from an already-parsed document. */
91
+ function lookupFromDocument(doc, address) {
92
+ const pubkey = doc.names[address.local];
93
+ if (!pubkey) return void 0;
94
+ const relays = doc.relays?.[pubkey];
95
+ return relays?.length ? {
96
+ pubkey,
97
+ relays: [...relays]
98
+ } : { pubkey };
99
+ }
100
+ /**
101
+ * Fetch and parse `/.well-known/nostr.json`.
102
+ * Returns `null` on network/parse failure (does not throw for those).
103
+ * Rejects HTTP redirects (non-200) per NIP-05 security constraints.
104
+ * AbortError rethrows; it is not mapped to `null`.
105
+ */
106
+ async function queryNip05Document(identifier, opts) {
107
+ let address;
108
+ try {
109
+ address = parseNip05(identifier);
110
+ } catch {
111
+ return null;
112
+ }
113
+ const url = wellKnownUrl(address);
114
+ const fetchImpl = opts?.fetch ?? requireGlobalFetch(() => new Nip05Error("no fetch implementation available; pass opts.fetch"));
115
+ try {
116
+ const res = await fetchManual(fetchImpl, url, { signal: opts?.signal }, (err) => err instanceof Error ? err : /* @__PURE__ */ new Error("NIP-05 request failed"));
117
+ if (res.status !== 200) return null;
118
+ const json = await res.json();
119
+ return {
120
+ address,
121
+ doc: parseNip05Document(json)
122
+ };
123
+ } catch (err) {
124
+ if (err instanceof Error && err.name === "AbortError") throw err;
125
+ return null;
126
+ }
127
+ }
128
+ /**
129
+ * Query `/.well-known/nostr.json` for an identifier.
130
+ * Returns `null` on network/parse/lookup failure (does not throw for those).
131
+ * Profile `relays` only. `nip46` is discovery metadata, not a bunker pointer.
132
+ */
133
+ async function queryProfile(identifier, opts) {
134
+ const fetched = await queryNip05Document(identifier, opts);
135
+ if (!fetched) return null;
136
+ return lookupFromDocument(fetched.doc, fetched.address) ?? null;
137
+ }
138
+ /** True when the identifier resolves to exactly `pubkey`. */
139
+ async function verifyNip05(pubkey, identifier, opts) {
140
+ if (!isHex32(pubkey)) return false;
141
+ const profile = await queryProfile(identifier, opts);
142
+ return profile !== null && profile.pubkey === pubkey.toLowerCase();
143
+ }
144
+ //#endregion
145
+ export { NIP05_REGEX, NIP05_ROOT_LOCAL, Nip05Error, WELL_KNOWN_PATH, isNip05, lookupFromDocument, parseNip05, parseNip05Document, parseNip05Nip46, queryNip05Document, queryProfile, verifyNip05, wellKnownUrl };
146
+
147
+ //# sourceMappingURL=nip05.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip05.mjs","names":[],"sources":["../../src/nips/nip05.ts"],"sourcesContent":["/**\n * NIP-05: Mapping Nostr keys to DNS-based internet identifiers\n * @see https://github.com/nostr-protocol/nips/blob/master/05.md\n */\nimport { NostrError } from \"../core/error.ts\";\nimport { isHex32 } from \"../core/util.ts\";\nimport { fetchManual, requireGlobalFetch, type ManualFetch } from \"./http.ts\";\nimport type { ProfilePointer } from \"./nip19.ts\";\n\n/** Root local-part (`_@domain` rendered as just the domain). */\nexport const NIP05_ROOT_LOCAL = \"_\";\n\nexport const WELL_KNOWN_PATH = \"/.well-known/nostr.json\";\n\n/**\n * NIP-05 identifier string.\n * - Full: `name@domain`\n * - Root: `domain` or `_@domain`\n */\nexport type Nip05 = string;\n\nexport type Nip05Address = {\n /** Local part (lowercased). `_` for domain-only identifiers. */\n local: string;\n /** Domain (lowercased). */\n domain: string;\n};\n\n/**\n * 46.md appendix discovery metadata (`{relays, nostrconnect_url}`).\n * Not a bunker pointer.\n */\nexport type Nip05Nip46 = {\n relays?: string[];\n nostrconnectUrl?: string;\n};\n\nexport type Nip05Document = {\n names: Record<string, string>;\n /** NIP-05 profile relay hints */\n relays?: Record<string, string[]>;\n nip46?: Nip05Nip46;\n};\n\nexport type Nip05Fetch = ManualFetch;\n\nexport class Nip05Error extends NostrError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n }\n}\n\n/**\n * Matches optional local@domain.\n * Groups: 1=local (optional), 2=domain.\n */\nexport const NIP05_REGEX = /^(?:([\\w.+-]+)@)?([\\w-]+(?:\\.[\\w-]+)+)$/;\n\nexport function isNip05(value: unknown): value is string {\n return typeof value === \"string\" && NIP05_REGEX.test(value);\n}\n\n/**\n * Parse an identifier into local + domain.\n * Accepts `name@domain`, `_@domain`, or bare `domain` (local becomes `_`).\n */\nexport function parseNip05(input: string): Nip05Address {\n const match = input.trim().match(NIP05_REGEX);\n if (!match?.[2]) {\n throw new Nip05Error(`invalid NIP-05 identifier: ${input}`);\n }\n const localRaw = match[1] ?? NIP05_ROOT_LOCAL;\n const local = localRaw.toLowerCase();\n const domain = match[2].toLowerCase();\n\n // NIP-05 local-part: a-z0-9-_.\n if (!/^[a-z0-9._-]+$/.test(local)) {\n throw new Nip05Error(`invalid NIP-05 local-part: ${localRaw}`);\n }\n if (!domain) {\n throw new Nip05Error(\"NIP-05 domain must not be empty\");\n }\n\n return { local, domain };\n}\n\n/** Build the well-known HTTPS URL for an address. */\nexport function wellKnownUrl(address: Nip05Address): string {\n const url = new URL(`https://${address.domain}${WELL_KNOWN_PATH}`);\n url.searchParams.set(\"name\", address.local);\n return url.toString();\n}\n\nfunction stringUrls(list: unknown): string[] | undefined {\n if (!Array.isArray(list)) return undefined;\n return list.filter((u): u is string => typeof u === \"string\" && u.length > 0);\n}\n\n/**\n * Parse nostr.json `nip46`: 46.md appendix `{relays, nostrconnect_url}`.\n * Hex-pubkey maps and other keys are ignored.\n */\nexport function parseNip05Nip46(raw: unknown): Nip05Nip46 | undefined {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n const obj = raw as Record<string, unknown>;\n const result: Nip05Nip46 = {};\n\n if (Array.isArray(obj.relays)) {\n result.relays = stringUrls(obj.relays) ?? [];\n }\n\n if (typeof obj.nostrconnect_url === \"string\" && obj.nostrconnect_url.length > 0) {\n result.nostrconnectUrl = obj.nostrconnect_url;\n }\n\n if (result.relays === undefined && result.nostrconnectUrl === undefined) {\n return undefined;\n }\n return result;\n}\n\n/** Parse and validate a nostr.json document body. */\nexport function parseNip05Document(json: unknown): Nip05Document {\n if (!json || typeof json !== \"object\") {\n throw new Nip05Error(\"NIP-05 document must be a JSON object\");\n }\n const raw = json as { names?: unknown; relays?: unknown; nip46?: unknown };\n if (!raw.names || typeof raw.names !== \"object\" || Array.isArray(raw.names)) {\n throw new Nip05Error(\"NIP-05 document missing names map\");\n }\n\n const names: Record<string, string> = {};\n for (const [k, v] of Object.entries(raw.names as Record<string, unknown>)) {\n if (typeof v !== \"string\" || !isHex32(v)) continue;\n names[k.toLowerCase()] = v.toLowerCase();\n }\n\n let relays: Record<string, string[]> | undefined;\n if (raw.relays && typeof raw.relays === \"object\" && !Array.isArray(raw.relays)) {\n relays = {};\n for (const [pk, list] of Object.entries(raw.relays as Record<string, unknown>)) {\n if (!isHex32(pk)) continue;\n const urls = stringUrls(list);\n if (urls?.length) relays[pk.toLowerCase()] = urls;\n }\n }\n\n return { names, relays, nip46: parseNip05Nip46(raw.nip46) };\n}\n\n/** Resolve local name from an already-parsed document. */\nexport function lookupFromDocument(\n doc: Nip05Document,\n address: Nip05Address,\n): ProfilePointer | undefined {\n const pubkey = doc.names[address.local];\n if (!pubkey) return undefined;\n const relays = doc.relays?.[pubkey];\n return relays?.length ? { pubkey, relays: [...relays] } : { pubkey };\n}\n\n/**\n * Fetch and parse `/.well-known/nostr.json`.\n * Returns `null` on network/parse failure (does not throw for those).\n * Rejects HTTP redirects (non-200) per NIP-05 security constraints.\n * AbortError rethrows; it is not mapped to `null`.\n */\nexport async function queryNip05Document(\n identifier: string,\n opts?: { fetch?: Nip05Fetch; signal?: AbortSignal },\n): Promise<{ address: Nip05Address; doc: Nip05Document } | null> {\n let address: Nip05Address;\n try {\n address = parseNip05(identifier);\n } catch {\n return null;\n }\n\n const url = wellKnownUrl(address);\n const fetchImpl =\n opts?.fetch ??\n requireGlobalFetch(() => new Nip05Error(\"no fetch implementation available; pass opts.fetch\"));\n\n try {\n const res = await fetchManual(fetchImpl, url, { signal: opts?.signal }, (err) =>\n err instanceof Error ? err : new Error(\"NIP-05 request failed\"),\n );\n // Redirects and errors must not be trusted (NIP-05 security).\n if (res.status !== 200) return null;\n const json = await res.json();\n return { address, doc: parseNip05Document(json) };\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") throw err;\n return null;\n }\n}\n\n/**\n * Query `/.well-known/nostr.json` for an identifier.\n * Returns `null` on network/parse/lookup failure (does not throw for those).\n * Profile `relays` only. `nip46` is discovery metadata, not a bunker pointer.\n */\nexport async function queryProfile(\n identifier: string,\n opts?: { fetch?: Nip05Fetch; signal?: AbortSignal },\n): Promise<ProfilePointer | null> {\n const fetched = await queryNip05Document(identifier, opts);\n if (!fetched) return null;\n return lookupFromDocument(fetched.doc, fetched.address) ?? null;\n}\n\n/** True when the identifier resolves to exactly `pubkey`. */\nexport async function verifyNip05(\n pubkey: string,\n identifier: string,\n opts?: { fetch?: Nip05Fetch; signal?: AbortSignal },\n): Promise<boolean> {\n if (!isHex32(pubkey)) return false;\n const profile = await queryProfile(identifier, opts);\n return profile !== null && profile.pubkey === pubkey.toLowerCase();\n}\n"],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { t as Event, v as Tag } from "../event-B5D2jxt_.mjs";
2
+ import { t as EventBuilder } from "../builder-BphJa-Y-.mjs";
3
+ import { f as ProfilePointer, i as EventPointer, t as AddressPointer } from "../nip19-D7905oIv.mjs";
4
+ //#region src/nips/nip10.d.ts
5
+ type ThreadReferences = {
6
+ /** Pointer to the root of the thread. */
7
+ root: EventPointer | undefined;
8
+ /** Pointer to the parent event this note replies to. */
9
+ reply: EventPointer | undefined;
10
+ /** Other e-tagged events (not root/reply). */
11
+ mentions: EventPointer[];
12
+ /** Quoted events (`q` tags): event ids or addresses. Discriminate with `"id" in q`. */
13
+ quotes: Array<EventPointer | AddressPointer>;
14
+ /** p-tagged profiles involved in the thread. */
15
+ profiles: ProfilePointer[];
16
+ };
17
+ type ReplyParent = Pick<Event, "id" | "pubkey" | "tags" | "kind">;
18
+ type QuoteInput = string | EventPointer | AddressPointer;
19
+ /**
20
+ * Parse NIP-10 thread markers and legacy positional e-tags from an event.
21
+ */
22
+ declare function parseThreadTags(event: Pick<Event, "tags">): ThreadReferences;
23
+ type ReplyTagsOptions = {
24
+ /** Parent event being replied to. */
25
+ parent: ReplyParent;
26
+ /** Optional relay hint for the parent e-tag. */
27
+ relayHint?: string;
28
+ /** Quoted events (`q` tags): hex ids, `kind:pubkey:d` coords, or pointers. */
29
+ quotes?: QuoteInput[];
30
+ };
31
+ /**
32
+ * Build NIP-10 e/p tags for a reply to `parent`.
33
+ * Uses marked tags (`root` / `reply`) per preferred modern style.
34
+ */
35
+ declare function buildReplyTags(opts: ReplyTagsOptions): Tag[];
36
+ /**
37
+ * Build an {@link EventBuilder} reply with NIP-10 tags.
38
+ * Lives here (not on EventBuilder) so core does not depend on nips.
39
+ */
40
+ declare function replyTo(parent: ReplyParent, content: string, opts?: Pick<ReplyTagsOptions, "relayHint" | "quotes">): EventBuilder;
41
+ //#endregion
42
+ export { ReplyTagsOptions, ThreadReferences, buildReplyTags, parseThreadTags, replyTo };
43
+ //# sourceMappingURL=nip10.d.mts.map
@@ -0,0 +1,194 @@
1
+ import { a as isHex32 } from "../util-6tfLQ9JF.mjs";
2
+ import { n as EventValidationError } from "../error-DZEs5OuZ.mjs";
3
+ import { t as Kind } from "../kind-BLl4cLOc.mjs";
4
+ import { g as formatEventAddress, m as Tag, y as parseEventAddress } from "../event-CzoQEFMF.mjs";
5
+ import { t as EventBuilder } from "../builder-q0VsvnYE.mjs";
6
+ //#region src/nips/nip10.ts
7
+ /**
8
+ * NIP-10: Text Notes and Threads
9
+ * @see https://github.com/nostr-protocol/nips/blob/master/10.md
10
+ */
11
+ function eventPointerFromETag(tag) {
12
+ if (tag[0] !== "e" || !tag[1] || !isHex32(tag[1])) return void 0;
13
+ const author = tag[4] && isHex32(tag[4]) ? tag[4].toLowerCase() : tag[3] && isHex32(tag[3]) ? tag[3].toLowerCase() : void 0;
14
+ return {
15
+ id: tag[1].toLowerCase(),
16
+ relays: tag[2] ? [tag[2]] : [],
17
+ author
18
+ };
19
+ }
20
+ function quoteFromQTag(tag) {
21
+ if (tag[0] !== "q" || !tag[1]) return void 0;
22
+ if (isHex32(tag[1])) {
23
+ const pointer = {
24
+ id: tag[1].toLowerCase(),
25
+ relays: tag[2] ? [tag[2]] : []
26
+ };
27
+ if (tag[3] && isHex32(tag[3])) pointer.author = tag[3].toLowerCase();
28
+ return pointer;
29
+ }
30
+ const addr = parseEventAddress(tag[1]);
31
+ if (!addr) return void 0;
32
+ return {
33
+ identifier: addr.identifier,
34
+ pubkey: addr.pubkey,
35
+ kind: addr.kind,
36
+ relays: tag[2] ? [tag[2]] : []
37
+ };
38
+ }
39
+ function quoteToTag(quote) {
40
+ if (typeof quote === "string") {
41
+ if (isHex32(quote)) return { tag: ["q", quote.toLowerCase()] };
42
+ const addr = parseEventAddress(quote);
43
+ if (!addr) return void 0;
44
+ return { tag: ["q", formatEventAddress(addr.kind, addr.pubkey, addr.identifier)] };
45
+ }
46
+ if ("id" in quote) {
47
+ const id = quote.id.toLowerCase();
48
+ const relay = quote.relays?.[0];
49
+ const author = quote.author && isHex32(quote.author) ? quote.author.toLowerCase() : void 0;
50
+ return {
51
+ tag: author !== void 0 ? [
52
+ "q",
53
+ id,
54
+ relay ?? "",
55
+ author
56
+ ] : relay ? [
57
+ "q",
58
+ id,
59
+ relay
60
+ ] : ["q", id],
61
+ author,
62
+ relay: relay || void 0
63
+ };
64
+ }
65
+ const coord = formatEventAddress(quote.kind, quote.pubkey, quote.identifier);
66
+ const relay = quote.relays?.[0];
67
+ return {
68
+ tag: relay ? [
69
+ "q",
70
+ coord,
71
+ relay
72
+ ] : ["q", coord],
73
+ author: quote.pubkey,
74
+ relay: relay || void 0
75
+ };
76
+ }
77
+ function assertKind1Parent(parent) {
78
+ if (parent.kind !== Kind.TextNote) throw new EventValidationError("NIP-10 replyTo is for kind 1");
79
+ }
80
+ /**
81
+ * Parse NIP-10 thread markers and legacy positional e-tags from an event.
82
+ */
83
+ function parseThreadTags(event) {
84
+ const result = {
85
+ root: void 0,
86
+ reply: void 0,
87
+ mentions: [],
88
+ quotes: [],
89
+ profiles: []
90
+ };
91
+ let maybeParent;
92
+ let maybeRoot;
93
+ for (let i = event.tags.length - 1; i >= 0; i--) {
94
+ const tag = event.tags[i];
95
+ if (tag[0] === "e" && tag[1] && isHex32(tag[1])) {
96
+ const pointer = eventPointerFromETag(tag);
97
+ const marker = tag[3];
98
+ if (marker === "root") {
99
+ result.root = pointer;
100
+ continue;
101
+ }
102
+ if (marker === "reply") {
103
+ result.reply = pointer;
104
+ continue;
105
+ }
106
+ if (marker && !isHex32(marker)) {
107
+ result.mentions.push(pointer);
108
+ continue;
109
+ }
110
+ if (!maybeParent) maybeParent = pointer;
111
+ else maybeRoot = pointer;
112
+ result.mentions.push(pointer);
113
+ continue;
114
+ }
115
+ if (tag[0] === "q") {
116
+ const quote = quoteFromQTag(tag);
117
+ if (quote) result.quotes.push(quote);
118
+ continue;
119
+ }
120
+ if (tag[0] === "p" && tag[1] && isHex32(tag[1])) result.profiles.push({
121
+ pubkey: tag[1].toLowerCase(),
122
+ relays: tag[2] ? [tag[2]] : []
123
+ });
124
+ }
125
+ if (!result.root) result.root = maybeRoot ?? maybeParent ?? result.reply;
126
+ if (!result.reply) result.reply = maybeParent ?? result.root;
127
+ const drop = new Set([result.root?.id, result.reply?.id].filter((id) => Boolean(id)));
128
+ result.mentions = result.mentions.filter((m) => !drop.has(m.id));
129
+ for (const ref of [
130
+ result.reply,
131
+ result.root,
132
+ ...result.mentions
133
+ ]) {
134
+ if (!ref?.author) continue;
135
+ const author = result.profiles.find((p) => p.pubkey === ref.author);
136
+ if (!author?.relays?.length) continue;
137
+ const relays = [...ref.relays ?? []];
138
+ for (const url of author.relays) if (!relays.includes(url)) relays.push(url);
139
+ ref.relays = relays;
140
+ }
141
+ return result;
142
+ }
143
+ /**
144
+ * Build NIP-10 e/p tags for a reply to `parent`.
145
+ * Uses marked tags (`root` / `reply`) per preferred modern style.
146
+ */
147
+ function buildReplyTags(opts) {
148
+ assertKind1Parent(opts.parent);
149
+ const thread = parseThreadTags(opts.parent);
150
+ const root = thread.root ?? {
151
+ id: opts.parent.id,
152
+ relays: [],
153
+ author: opts.parent.pubkey
154
+ };
155
+ const parentIsRoot = root.id.toLowerCase() === opts.parent.id.toLowerCase();
156
+ const tags = [];
157
+ const rootRelay = root.relays?.[0] ?? opts.relayHint ?? "";
158
+ tags.push(Tag.e(root.id, rootRelay, "root", root.author ?? opts.parent.pubkey));
159
+ if (!parentIsRoot) tags.push(Tag.e(opts.parent.id, opts.relayHint ?? "", "reply", opts.parent.pubkey));
160
+ const pSeen = /* @__PURE__ */ new Set();
161
+ const addP = (pk, relay) => {
162
+ const key = pk.toLowerCase();
163
+ if (pSeen.has(key)) return;
164
+ pSeen.add(key);
165
+ tags.push(Tag.p(pk, relay || void 0));
166
+ };
167
+ if (root.author) addP(root.author, root.relays?.[0]);
168
+ addP(opts.parent.pubkey, opts.relayHint);
169
+ for (const p of thread.profiles) addP(p.pubkey, p.relays?.[0]);
170
+ const qTags = [];
171
+ for (const quote of opts.quotes ?? []) {
172
+ const built = quoteToTag(quote);
173
+ if (!built) continue;
174
+ if (built.author) addP(built.author, built.relay);
175
+ qTags.push(built.tag);
176
+ }
177
+ tags.push(...qTags);
178
+ return tags;
179
+ }
180
+ /**
181
+ * Build an {@link EventBuilder} reply with NIP-10 tags.
182
+ * Lives here (not on EventBuilder) so core does not depend on nips.
183
+ */
184
+ function replyTo(parent, content, opts) {
185
+ return EventBuilder.textNote(content).tags(buildReplyTags({
186
+ parent,
187
+ relayHint: opts?.relayHint,
188
+ quotes: opts?.quotes
189
+ }));
190
+ }
191
+ //#endregion
192
+ export { buildReplyTags, parseThreadTags, replyTo };
193
+
194
+ //# sourceMappingURL=nip10.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip10.mjs","names":[],"sources":["../../src/nips/nip10.ts"],"sourcesContent":["/**\n * NIP-10: Text Notes and Threads\n * @see https://github.com/nostr-protocol/nips/blob/master/10.md\n */\nimport { EventBuilder } from \"../core/builder.ts\";\nimport { EventValidationError } from \"../core/error.ts\";\nimport type { Event } from \"../core/event.ts\";\nimport { Kind } from \"../core/kind.ts\";\nimport { formatEventAddress, parseEventAddress, Tag } from \"../core/tag.ts\";\nimport { isHex32 } from \"../core/util.ts\";\nimport type { AddressPointer, EventPointer, ProfilePointer } from \"./nip19.ts\";\n\nexport type ThreadReferences = {\n /** Pointer to the root of the thread. */\n root: EventPointer | undefined;\n /** Pointer to the parent event this note replies to. */\n reply: EventPointer | undefined;\n /** Other e-tagged events (not root/reply). */\n mentions: EventPointer[];\n /** Quoted events (`q` tags): event ids or addresses. Discriminate with `\"id\" in q`. */\n quotes: Array<EventPointer | AddressPointer>;\n /** p-tagged profiles involved in the thread. */\n profiles: ProfilePointer[];\n};\n\ntype ReplyParent = Pick<Event, \"id\" | \"pubkey\" | \"tags\" | \"kind\">;\ntype QuoteInput = string | EventPointer | AddressPointer;\n\nfunction eventPointerFromETag(tag: readonly string[]): EventPointer | undefined {\n if (tag[0] !== \"e\" || !tag[1] || !isHex32(tag[1])) return undefined;\n // NIP-10 5-tuple pubkey is index 4; NIP-01 4-tuple pubkey is index 3.\n const author =\n tag[4] && isHex32(tag[4])\n ? tag[4].toLowerCase()\n : tag[3] && isHex32(tag[3])\n ? tag[3].toLowerCase()\n : undefined;\n return {\n id: tag[1].toLowerCase(),\n relays: tag[2] ? [tag[2]] : [],\n author,\n };\n}\n\nfunction quoteFromQTag(tag: readonly string[]): EventPointer | AddressPointer | undefined {\n if (tag[0] !== \"q\" || !tag[1]) return undefined;\n if (isHex32(tag[1])) {\n const pointer: EventPointer = {\n id: tag[1].toLowerCase(),\n relays: tag[2] ? [tag[2]] : [],\n };\n if (tag[3] && isHex32(tag[3])) pointer.author = tag[3].toLowerCase();\n return pointer;\n }\n const addr = parseEventAddress(tag[1]);\n if (!addr) return undefined;\n // Address q tags do not use the event-id pubkey slot (index 3).\n return {\n identifier: addr.identifier,\n pubkey: addr.pubkey,\n kind: addr.kind,\n relays: tag[2] ? [tag[2]] : [],\n };\n}\n\nfunction quoteToTag(quote: QuoteInput): { tag: Tag; author?: string; relay?: string } | undefined {\n if (typeof quote === \"string\") {\n if (isHex32(quote)) return { tag: [\"q\", quote.toLowerCase()] };\n const addr = parseEventAddress(quote);\n if (!addr) return undefined;\n return { tag: [\"q\", formatEventAddress(addr.kind, addr.pubkey, addr.identifier)] };\n }\n if (\"id\" in quote) {\n const id = quote.id.toLowerCase();\n const relay = quote.relays?.[0];\n const author = quote.author && isHex32(quote.author) ? quote.author.toLowerCase() : undefined;\n const tag: Tag =\n author !== undefined ? [\"q\", id, relay ?? \"\", author] : relay ? [\"q\", id, relay] : [\"q\", id];\n return { tag, author, relay: relay || undefined };\n }\n const coord = formatEventAddress(quote.kind, quote.pubkey, quote.identifier);\n const relay = quote.relays?.[0];\n const tag: Tag = relay ? [\"q\", coord, relay] : [\"q\", coord];\n return { tag, author: quote.pubkey, relay: relay || undefined };\n}\n\nfunction assertKind1Parent(parent: ReplyParent): void {\n // NIP-10 is kind 1 only; comments are NIP-22.\n if (parent.kind !== Kind.TextNote) {\n throw new EventValidationError(\"NIP-10 replyTo is for kind 1\");\n }\n}\n\n/**\n * Parse NIP-10 thread markers and legacy positional e-tags from an event.\n */\nexport function parseThreadTags(event: Pick<Event, \"tags\">): ThreadReferences {\n const result: ThreadReferences = {\n root: undefined,\n reply: undefined,\n mentions: [],\n quotes: [],\n profiles: [],\n };\n\n let maybeParent: EventPointer | undefined;\n let maybeRoot: EventPointer | undefined;\n\n for (let i = event.tags.length - 1; i >= 0; i--) {\n const tag = event.tags[i]!;\n\n if (tag[0] === \"e\" && tag[1] && isHex32(tag[1])) {\n const pointer = eventPointerFromETag(tag)!;\n const marker = tag[3];\n\n if (marker === \"root\") {\n result.root = pointer;\n continue;\n }\n if (marker === \"reply\") {\n result.reply = pointer;\n continue;\n }\n // Preferred markers are root/reply only. A hex32 at index 3 is NIP-01 pubkey, not a marker.\n if (marker && !isHex32(marker)) {\n result.mentions.push(pointer);\n continue;\n }\n\n // Legacy positional: last unmarked is parent, second-to-last is root.\n if (!maybeParent) maybeParent = pointer;\n else maybeRoot = pointer;\n result.mentions.push(pointer);\n continue;\n }\n\n if (tag[0] === \"q\") {\n const quote = quoteFromQTag(tag);\n if (quote) result.quotes.push(quote);\n continue;\n }\n\n if (tag[0] === \"p\" && tag[1] && isHex32(tag[1])) {\n result.profiles.push({\n pubkey: tag[1].toLowerCase(),\n relays: tag[2] ? [tag[2]] : [],\n });\n }\n }\n\n if (!result.root) {\n result.root = maybeRoot ?? maybeParent ?? result.reply;\n }\n if (!result.reply) {\n result.reply = maybeParent ?? result.root;\n }\n\n // Drop root/reply from mentions (by id).\n const drop = new Set(\n [result.root?.id, result.reply?.id].filter((id): id is string => Boolean(id)),\n );\n result.mentions = result.mentions.filter((m) => !drop.has(m.id));\n\n // Inherit relay hints from matching p-tags.\n for (const ref of [result.reply, result.root, ...result.mentions]) {\n if (!ref?.author) continue;\n const author = result.profiles.find((p) => p.pubkey === ref.author);\n if (!author?.relays?.length) continue;\n const relays = [...(ref.relays ?? [])];\n for (const url of author.relays) {\n if (!relays.includes(url)) relays.push(url);\n }\n ref.relays = relays;\n }\n\n return result;\n}\n\nexport type ReplyTagsOptions = {\n /** Parent event being replied to. */\n parent: ReplyParent;\n /** Optional relay hint for the parent e-tag. */\n relayHint?: string;\n /** Quoted events (`q` tags): hex ids, `kind:pubkey:d` coords, or pointers. */\n quotes?: QuoteInput[];\n};\n\n/**\n * Build NIP-10 e/p tags for a reply to `parent`.\n * Uses marked tags (`root` / `reply`) per preferred modern style.\n */\nexport function buildReplyTags(opts: ReplyTagsOptions): Tag[] {\n assertKind1Parent(opts.parent);\n const thread = parseThreadTags(opts.parent);\n const root = thread.root ?? { id: opts.parent.id, relays: [], author: opts.parent.pubkey };\n const parentIsRoot = root.id.toLowerCase() === opts.parent.id.toLowerCase();\n\n const tags: Tag[] = [];\n const rootRelay = root.relays?.[0] ?? opts.relayHint ?? \"\";\n tags.push(Tag.e(root.id, rootRelay, \"root\", root.author ?? opts.parent.pubkey));\n\n if (!parentIsRoot) {\n tags.push(Tag.e(opts.parent.id, opts.relayHint ?? \"\", \"reply\", opts.parent.pubkey));\n }\n\n // Ensure root + parent authors are p-tagged.\n const pSeen = new Set<string>();\n const addP = (pk: string, relay?: string) => {\n const key = pk.toLowerCase();\n if (pSeen.has(key)) return;\n pSeen.add(key);\n tags.push(Tag.p(pk, relay || undefined));\n };\n if (root.author) addP(root.author, root.relays?.[0]);\n addP(opts.parent.pubkey, opts.relayHint);\n for (const p of thread.profiles) addP(p.pubkey, p.relays?.[0]);\n\n const qTags: Tag[] = [];\n for (const quote of opts.quotes ?? []) {\n const built = quoteToTag(quote);\n if (!built) continue;\n if (built.author) addP(built.author, built.relay);\n qTags.push(built.tag);\n }\n tags.push(...qTags);\n\n return tags;\n}\n\n/**\n * Build an {@link EventBuilder} reply with NIP-10 tags.\n * Lives here (not on EventBuilder) so core does not depend on nips.\n */\nexport function replyTo(\n parent: ReplyParent,\n content: string,\n opts?: Pick<ReplyTagsOptions, \"relayHint\" | \"quotes\">,\n): EventBuilder {\n return EventBuilder.textNote(content).tags(\n buildReplyTags({\n parent,\n relayHint: opts?.relayHint,\n quotes: opts?.quotes,\n }),\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { a as NostrError } from "../error-WEFS-R-4.mjs";
2
+ import { t as ManualFetch } from "../http-6vevbBlu.mjs";
3
+ //#region src/nips/nip11.d.ts
4
+ type Nip11Fetch = ManualFetch;
5
+ type RelayInformation = {
6
+ name?: string;
7
+ description?: string;
8
+ banner?: string;
9
+ icon?: string;
10
+ pubkey?: string;
11
+ self?: string;
12
+ contact?: string;
13
+ supported_nips?: number[];
14
+ software?: string;
15
+ version?: string;
16
+ limitation?: {
17
+ max_message_length?: number;
18
+ max_subscriptions?: number;
19
+ max_limit?: number;
20
+ max_subid_length?: number;
21
+ max_event_tags?: number;
22
+ max_content_length?: number;
23
+ default_limit?: number;
24
+ auth_required?: boolean;
25
+ payment_required?: boolean;
26
+ restricted_writes?: boolean;
27
+ min_pow_difficulty?: number;
28
+ created_at_lower_limit?: number;
29
+ created_at_upper_limit?: number;
30
+ };
31
+ payments_url?: string;
32
+ terms_of_service?: string;
33
+ };
34
+ declare class Nip11Error extends NostrError {}
35
+ /** Convert a relay websocket URL to the HTTP URL that serves the NIP-11 document. */
36
+ declare function relayInfoHttpUrl(wsUrl: string): string;
37
+ declare function fetchRelayInformation(wsUrl: string, opts?: {
38
+ fetch?: Nip11Fetch;
39
+ signal?: AbortSignal;
40
+ }): Promise<RelayInformation>;
41
+ //#endregion
42
+ export { Nip11Error, Nip11Fetch, RelayInformation, fetchRelayInformation, relayInfoHttpUrl };
43
+ //# sourceMappingURL=nip11.d.mts.map
@@ -0,0 +1,99 @@
1
+ import { a as NostrError } from "../error-DZEs5OuZ.mjs";
2
+ import { n as requireGlobalFetch, t as fetchManual } from "../http-D2rhokZo.mjs";
3
+ //#region src/nips/nip11.ts
4
+ /**
5
+ * NIP-11: Relay Information Document
6
+ * @see https://github.com/nostr-protocol/nips/blob/master/11.md
7
+ */
8
+ const ACCEPT = "application/nostr+json";
9
+ const STRING_FIELDS = [
10
+ "name",
11
+ "description",
12
+ "banner",
13
+ "icon",
14
+ "pubkey",
15
+ "self",
16
+ "contact",
17
+ "software",
18
+ "version",
19
+ "payments_url",
20
+ "terms_of_service"
21
+ ];
22
+ const LIMITATION_NUMBERS = [
23
+ "max_message_length",
24
+ "max_subscriptions",
25
+ "max_limit",
26
+ "max_subid_length",
27
+ "max_event_tags",
28
+ "max_content_length",
29
+ "min_pow_difficulty",
30
+ "created_at_lower_limit",
31
+ "created_at_upper_limit",
32
+ "default_limit"
33
+ ];
34
+ const LIMITATION_BOOLEANS = [
35
+ "auth_required",
36
+ "payment_required",
37
+ "restricted_writes"
38
+ ];
39
+ var Nip11Error = class extends NostrError {};
40
+ /** Convert a relay websocket URL to the HTTP URL that serves the NIP-11 document. */
41
+ function relayInfoHttpUrl(wsUrl) {
42
+ let url;
43
+ try {
44
+ url = new URL(wsUrl);
45
+ } catch (cause) {
46
+ throw new Nip11Error(`invalid relay URL: ${wsUrl}`, { cause: cause instanceof Error ? cause : void 0 });
47
+ }
48
+ if (url.protocol === "wss:") url.protocol = "https:";
49
+ else if (url.protocol === "ws:") url.protocol = "http:";
50
+ else if (url.protocol !== "https:" && url.protocol !== "http:") throw new Nip11Error(`unsupported relay URL scheme: ${url.protocol}`);
51
+ return url.toString();
52
+ }
53
+ function isNonNegativeInteger(value) {
54
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
55
+ }
56
+ function parseRelayInformation(json) {
57
+ if (json === null || typeof json !== "object" || Array.isArray(json)) throw new Nip11Error("relay information document must be a JSON object");
58
+ const raw = json;
59
+ const info = {};
60
+ for (const key of STRING_FIELDS) {
61
+ const value = raw[key];
62
+ if (typeof value === "string") info[key] = value;
63
+ }
64
+ if (Array.isArray(raw.supported_nips)) info.supported_nips = raw.supported_nips.filter(isNonNegativeInteger);
65
+ if (raw.limitation && typeof raw.limitation === "object" && !Array.isArray(raw.limitation)) {
66
+ const rawLim = raw.limitation;
67
+ const limitation = {};
68
+ for (const key of LIMITATION_NUMBERS) {
69
+ const value = rawLim[key];
70
+ if (isNonNegativeInteger(value)) limitation[key] = value;
71
+ }
72
+ for (const key of LIMITATION_BOOLEANS) {
73
+ const value = rawLim[key];
74
+ if (typeof value === "boolean") limitation[key] = value;
75
+ }
76
+ if (Object.keys(limitation).length > 0) info.limitation = limitation;
77
+ }
78
+ return info;
79
+ }
80
+ async function fetchRelayInformation(wsUrl, opts) {
81
+ const httpUrl = relayInfoHttpUrl(wsUrl);
82
+ const fetchImpl = opts?.fetch ?? requireGlobalFetch(() => new Nip11Error("no fetch implementation available; pass opts.fetch"));
83
+ const res = await fetchManual(fetchImpl, httpUrl, {
84
+ headers: { Accept: ACCEPT },
85
+ signal: opts?.signal
86
+ }, (cause) => new Nip11Error(`relay information request failed: ${httpUrl}`, { cause: cause instanceof Error ? cause : void 0 }));
87
+ if (!res.ok) throw new Nip11Error(`relay information request failed: HTTP ${res.status}`);
88
+ let json;
89
+ try {
90
+ json = await res.json();
91
+ } catch (cause) {
92
+ throw new Nip11Error("relay information document is not valid JSON", { cause: cause instanceof Error ? cause : void 0 });
93
+ }
94
+ return parseRelayInformation(json);
95
+ }
96
+ //#endregion
97
+ export { Nip11Error, fetchRelayInformation, relayInfoHttpUrl };
98
+
99
+ //# sourceMappingURL=nip11.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip11.mjs","names":[],"sources":["../../src/nips/nip11.ts"],"sourcesContent":["/**\n * NIP-11: Relay Information Document\n * @see https://github.com/nostr-protocol/nips/blob/master/11.md\n */\nimport { NostrError } from \"../core/error.ts\";\nimport { fetchManual, requireGlobalFetch, type ManualFetch } from \"./http.ts\";\n\nconst ACCEPT = \"application/nostr+json\";\n\nconst STRING_FIELDS = [\n \"name\",\n \"description\",\n \"banner\",\n \"icon\",\n \"pubkey\",\n \"self\",\n \"contact\",\n \"software\",\n \"version\",\n \"payments_url\",\n \"terms_of_service\",\n] as const;\n\nconst LIMITATION_NUMBERS = [\n \"max_message_length\",\n \"max_subscriptions\",\n \"max_limit\",\n \"max_subid_length\",\n \"max_event_tags\",\n \"max_content_length\",\n \"min_pow_difficulty\",\n \"created_at_lower_limit\",\n \"created_at_upper_limit\",\n \"default_limit\",\n] as const;\n\nconst LIMITATION_BOOLEANS = [\"auth_required\", \"payment_required\", \"restricted_writes\"] as const;\n\nexport type Nip11Fetch = ManualFetch;\n\nexport type RelayInformation = {\n name?: string;\n description?: string;\n banner?: string;\n icon?: string;\n pubkey?: string;\n self?: string;\n contact?: string;\n supported_nips?: number[];\n software?: string;\n version?: string;\n limitation?: {\n max_message_length?: number;\n max_subscriptions?: number;\n max_limit?: number;\n max_subid_length?: number;\n max_event_tags?: number;\n max_content_length?: number;\n default_limit?: number;\n auth_required?: boolean;\n payment_required?: boolean;\n restricted_writes?: boolean;\n min_pow_difficulty?: number;\n created_at_lower_limit?: number;\n created_at_upper_limit?: number;\n };\n payments_url?: string;\n terms_of_service?: string;\n};\n\nexport class Nip11Error extends NostrError {}\n\n/** Convert a relay websocket URL to the HTTP URL that serves the NIP-11 document. */\nexport function relayInfoHttpUrl(wsUrl: string): string {\n let url: URL;\n try {\n url = new URL(wsUrl);\n } catch (cause) {\n throw new Nip11Error(`invalid relay URL: ${wsUrl}`, {\n cause: cause instanceof Error ? cause : undefined,\n });\n }\n\n if (url.protocol === \"wss:\") url.protocol = \"https:\";\n else if (url.protocol === \"ws:\") url.protocol = \"http:\";\n else if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n throw new Nip11Error(`unsupported relay URL scheme: ${url.protocol}`);\n }\n\n return url.toString();\n}\n\nfunction isNonNegativeInteger(value: unknown): value is number {\n return typeof value === \"number\" && Number.isInteger(value) && value >= 0;\n}\n\nfunction parseRelayInformation(json: unknown): RelayInformation {\n if (json === null || typeof json !== \"object\" || Array.isArray(json)) {\n throw new Nip11Error(\"relay information document must be a JSON object\");\n }\n const raw = json as Record<string, unknown>;\n const info: RelayInformation = {};\n\n for (const key of STRING_FIELDS) {\n const value = raw[key];\n if (typeof value === \"string\") info[key] = value;\n }\n\n if (Array.isArray(raw.supported_nips)) {\n info.supported_nips = raw.supported_nips.filter(isNonNegativeInteger);\n }\n\n if (raw.limitation && typeof raw.limitation === \"object\" && !Array.isArray(raw.limitation)) {\n const rawLim = raw.limitation as Record<string, unknown>;\n const limitation: NonNullable<RelayInformation[\"limitation\"]> = {};\n for (const key of LIMITATION_NUMBERS) {\n const value = rawLim[key];\n if (isNonNegativeInteger(value)) limitation[key] = value;\n }\n for (const key of LIMITATION_BOOLEANS) {\n const value = rawLim[key];\n if (typeof value === \"boolean\") limitation[key] = value;\n }\n if (Object.keys(limitation).length > 0) info.limitation = limitation;\n }\n\n return info;\n}\n\nexport async function fetchRelayInformation(\n wsUrl: string,\n opts?: { fetch?: Nip11Fetch; signal?: AbortSignal },\n): Promise<RelayInformation> {\n const httpUrl = relayInfoHttpUrl(wsUrl);\n const fetchImpl =\n opts?.fetch ??\n requireGlobalFetch(() => new Nip11Error(\"no fetch implementation available; pass opts.fetch\"));\n\n const res = await fetchManual(\n fetchImpl,\n httpUrl,\n { headers: { Accept: ACCEPT }, signal: opts?.signal },\n (cause) =>\n new Nip11Error(`relay information request failed: ${httpUrl}`, {\n cause: cause instanceof Error ? cause : undefined,\n }),\n );\n\n if (!res.ok) {\n throw new Nip11Error(`relay information request failed: HTTP ${res.status}`);\n }\n\n let json: unknown;\n try {\n json = await res.json();\n } catch (cause) {\n throw new Nip11Error(\"relay information document is not valid JSON\", {\n cause: cause instanceof Error ? cause : undefined,\n });\n }\n\n return parseRelayInformation(json);\n}\n"],"mappings":";;;;;;;AAOA,MAAM,SAAS;AAEf,MAAM,gBAAgB;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,qBAAqB;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,sBAAsB;CAAC;CAAiB;CAAoB;AAAmB;AAkCrF,IAAa,aAAb,cAAgC,WAAW,CAAC;;AAG5C,SAAgB,iBAAiB,OAAuB;CACtD,IAAI;CACJ,IAAI;EACF,MAAM,IAAI,IAAI,KAAK;CACrB,SAAS,OAAO;EACd,MAAM,IAAI,WAAW,sBAAsB,SAAS,EAClD,OAAO,iBAAiB,QAAQ,QAAQ,KAAA,EAC1C,CAAC;CACH;CAEA,IAAI,IAAI,aAAa,QAAQ,IAAI,WAAW;MACvC,IAAI,IAAI,aAAa,OAAO,IAAI,WAAW;MAC3C,IAAI,IAAI,aAAa,YAAY,IAAI,aAAa,SACrD,MAAM,IAAI,WAAW,iCAAiC,IAAI,UAAU;CAGtE,OAAO,IAAI,SAAS;AACtB;AAEA,SAAS,qBAAqB,OAAiC;CAC7D,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,SAAS;AAC1E;AAEA,SAAS,sBAAsB,MAAiC;CAC9D,IAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GACjE,MAAM,IAAI,WAAW,kDAAkD;CAEzE,MAAM,MAAM;CACZ,MAAM,OAAyB,CAAC;CAEhC,KAAK,MAAM,OAAO,eAAe;EAC/B,MAAM,QAAQ,IAAI;EAClB,IAAI,OAAO,UAAU,UAAU,KAAK,OAAO;CAC7C;CAEA,IAAI,MAAM,QAAQ,IAAI,cAAc,GAClC,KAAK,iBAAiB,IAAI,eAAe,OAAO,oBAAoB;CAGtE,IAAI,IAAI,cAAc,OAAO,IAAI,eAAe,YAAY,CAAC,MAAM,QAAQ,IAAI,UAAU,GAAG;EAC1F,MAAM,SAAS,IAAI;EACnB,MAAM,aAA0D,CAAC;EACjE,KAAK,MAAM,OAAO,oBAAoB;GACpC,MAAM,QAAQ,OAAO;GACrB,IAAI,qBAAqB,KAAK,GAAG,WAAW,OAAO;EACrD;EACA,KAAK,MAAM,OAAO,qBAAqB;GACrC,MAAM,QAAQ,OAAO;GACrB,IAAI,OAAO,UAAU,WAAW,WAAW,OAAO;EACpD;EACA,IAAI,OAAO,KAAK,UAAU,CAAC,CAAC,SAAS,GAAG,KAAK,aAAa;CAC5D;CAEA,OAAO;AACT;AAEA,eAAsB,sBACpB,OACA,MAC2B;CAC3B,MAAM,UAAU,iBAAiB,KAAK;CACtC,MAAM,YACJ,MAAM,SACN,yBAAyB,IAAI,WAAW,oDAAoD,CAAC;CAE/F,MAAM,MAAM,MAAM,YAChB,WACA,SACA;EAAE,SAAS,EAAE,QAAQ,OAAO;EAAG,QAAQ,MAAM;CAAO,IACnD,UACC,IAAI,WAAW,qCAAqC,WAAW,EAC7D,OAAO,iBAAiB,QAAQ,QAAQ,KAAA,EAC1C,CAAC,CACL;CAEA,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,WAAW,0CAA0C,IAAI,QAAQ;CAG7E,IAAI;CACJ,IAAI;EACF,OAAO,MAAM,IAAI,KAAK;CACxB,SAAS,OAAO;EACd,MAAM,IAAI,WAAW,gDAAgD,EACnE,OAAO,iBAAiB,QAAQ,QAAQ,KAAA,EAC1C,CAAC;CACH;CAEA,OAAO,sBAAsB,IAAI;AACnC"}
@@ -0,0 +1,23 @@
1
+ import { r as UnsignedEvent } from "../event-B5D2jxt_.mjs";
2
+ import { a as NostrError } from "../error-WEFS-R-4.mjs";
3
+ //#region src/nips/nip13.d.ts
4
+ declare class Nip13Error extends NostrError {
5
+ constructor(message: string, options?: ErrorOptions);
6
+ }
7
+ type MinePowOptions = {
8
+ /** Yield to the event loop after this many hashes. Default 1000. */
9
+ yieldEvery?: number;
10
+ signal?: AbortSignal;
11
+ };
12
+ /** Leading zero bits of a hex event id or raw sha256 bytes. */
13
+ declare function getPow(idOrHash: string | Uint8Array): number;
14
+ /**
15
+ * Returns a new unsigned event with nonce tag and computed id.
16
+ * Does not mutate input. Yields every `yieldEvery` hashes.
17
+ */
18
+ declare function minePow(unsigned: UnsignedEvent, difficulty: number, opts?: MinePowOptions): Promise<UnsignedEvent & {
19
+ id: string;
20
+ }>;
21
+ //#endregion
22
+ export { MinePowOptions, Nip13Error, getPow, minePow };
23
+ //# sourceMappingURL=nip13.d.mts.map