@napplet/conformance-cli 0.2.19 → 0.3.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 napplet contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var NappletConformanceHostBundle = (() => {
3
3
  // ../core/dist/index.js
4
- var NAP_DOMAINS = ["relay", "identity", "storage", "inc", "theme", "keys", "media", "notify", "config", "resource", "cvm", "outbox", "upload", "intent", "ble", "webrtc", "link", "count", "lists", "serial", "fs", "common", "dm"];
4
+ var NAP_DOMAINS = ["shell", "relay", "identity", "storage", "inc", "theme", "keys", "media", "notify", "config", "resource", "cvm", "outbox", "upload", "intent", "ble", "webrtc", "link", "count", "lists", "serial", "fs", "common", "dm"];
5
5
  function createDispatch() {
6
6
  const handlers = /* @__PURE__ */ new Map();
7
7
  function registerNap2(domain, handler) {
@@ -32,6 +32,9 @@ var NappletConformanceHostBundle = (() => {
32
32
  // ../conformance/dist/index.js
33
33
  var ID = { id: "string" };
34
34
  var ENVELOPE_SPECS = {
35
+ // Optional NAP-SHELL environment, independent of other domains.
36
+ "shell.ready": { dir: "out" },
37
+ "shell.init": { dir: "in", fields: { capabilities: "object", services: "array" } },
35
38
  // ── relay ────────────────────────────────────────────────────────────────
36
39
  "relay.subscribe": { dir: "out", fields: { ...ID, subId: "string", filters: "array" } },
37
40
  "relay.close": { dir: "out", fields: { ...ID, subId: "string" } },
@@ -188,6 +191,7 @@ var NappletConformanceHostBundle = (() => {
188
191
  "intent.invoke.result": { dir: "in", fields: { ...ID, result: "object" } },
189
192
  "intent.available.result": { dir: "in" },
190
193
  "intent.handlers.result": { dir: "in" },
194
+ "intent.deliver": { dir: "in", fields: { delivery: "object" } },
191
195
  "intent.changed": { dir: "in" },
192
196
  // ── ble ──────────────────────────────────────────────────────────────────
193
197
  "ble.open": { dir: "out", fields: { ...ID, request: "object" } },
@@ -320,14 +324,25 @@ var NappletConformanceHostBundle = (() => {
320
324
  });
321
325
  }
322
326
  for (const field of ["action", "convention"]) {
323
- if (intent[field] !== void 0 && typeof intent[field] !== "string") {
327
+ if (typeof intent[field] !== "string") {
324
328
  errors.push({
325
- code: "wrong-type",
329
+ code: intent[field] === void 0 ? "missing-field" : "wrong-type",
326
330
  message: `Intent request field "${field}" must be a string`,
327
331
  field: `request.${field}`
328
332
  });
329
333
  }
330
334
  }
335
+ const match = typeof intent.convention === "string" ? /^napplet:([^/?#]+)\/([^/?#]+)$/.exec(intent.convention) : null;
336
+ if (!match || match[1] !== intent.archetype || match[2] !== intent.action) {
337
+ errors.push({ code: "wrong-type", message: "Intent convention must be stable and match archetype and action", field: "request.convention" });
338
+ }
339
+ if (intent.handler !== void 0 && typeof intent.handler !== "string") {
340
+ errors.push({ code: "wrong-type", message: 'Intent request field "handler" must be a string', field: "request.handler" });
341
+ }
342
+ if (intent.behavior !== void 0 && kindOf(intent.behavior) !== "object") {
343
+ errors.push({ code: "wrong-type", message: 'Intent request field "behavior" must be an object', field: "request.behavior" });
344
+ }
345
+ if (intent.handlerHint !== void 0) validateIntentHandlerHint(intent.handlerHint, errors);
331
346
  if ("sender" in intent) {
332
347
  errors.push({
333
348
  code: "forbidden-field",
@@ -336,6 +351,23 @@ var NappletConformanceHostBundle = (() => {
336
351
  });
337
352
  }
338
353
  }
354
+ function validateIntentHandlerHint(hint, errors) {
355
+ if (kindOf(hint) !== "object") {
356
+ errors.push({ code: "wrong-type", message: 'Intent request field "handlerHint" must be an object', field: "request.handlerHint" });
357
+ return;
358
+ }
359
+ const { address, relays } = hint;
360
+ if (typeof address !== "string" || !/^35129:[0-9a-f]{64}:.+$/s.test(address)) {
361
+ errors.push({
362
+ code: address === void 0 ? "missing-field" : "wrong-type",
363
+ message: 'Intent handler hint "address" must be a 35129:<pubkey>:<d> coordinate',
364
+ field: "request.handlerHint.address"
365
+ });
366
+ }
367
+ if (relays !== void 0 && !(Array.isArray(relays) && relays.every((relay) => typeof relay === "string"))) {
368
+ errors.push({ code: "wrong-type", message: 'Intent handler hint "relays" must be an array of strings', field: "request.handlerHint.relays" });
369
+ }
370
+ }
339
371
  function validateServerHints(value, field, errors) {
340
372
  if (Array.isArray(value) && value.every((server) => typeof server === "string")) return;
341
373
  errors.push({
@@ -461,14 +493,14 @@ var NappletConformanceHostBundle = (() => {
461
493
  return NAPPLET_MANIFEST_KINDS.includes(kind);
462
494
  }
463
495
  function isSha256Hex(value) {
464
- return typeof value === "string" && /^[0-9a-f]{64}$/i.test(value);
496
+ return typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
465
497
  }
466
498
  function manifestDTag(event) {
467
- const d = firstTag(event, "d")?.[1]?.trim();
499
+ const d = firstTag(event, "d")?.[1];
468
500
  return d || void 0;
469
501
  }
470
502
  function manifestRequires(event) {
471
- return event.tags.filter((tag) => tag[0] === "requires").map((tag) => tag[1]?.trim() ?? "").filter(Boolean);
503
+ return event.tags.filter((tag) => tag[0] === "R").map((tag) => tag[1]?.trim() ?? "").filter(Boolean);
472
504
  }
473
505
  function validateManifestEvent(event) {
474
506
  const errors = [];
@@ -477,6 +509,7 @@ var NappletConformanceHostBundle = (() => {
477
509
  return {
478
510
  ok: false,
479
511
  requires: [],
512
+ optional: [],
480
513
  errors: [{ code: "missing-manifest-event", message: "No NIP-5D manifest event was resolved" }],
481
514
  warnings
482
515
  };
@@ -489,57 +522,63 @@ var NappletConformanceHostBundle = (() => {
489
522
  message: `Manifest event kind ${event.kind} is not a NIP-5D napplet kind`
490
523
  });
491
524
  }
492
- if (event.kind === NAPPLET_KIND_NAMED && !dTag) {
493
- errors.push({
494
- code: "missing-d-tag",
495
- message: "Named napplet manifest kind 35129 must include a non-empty d tag"
496
- });
497
- } else if ((event.kind === NAPPLET_KIND_ROOT || event.kind === NAPPLET_KIND_SNAPSHOT) && dTag) {
498
- errors.push({
499
- code: "unexpected-d-tag",
500
- message: `Napplet manifest kind ${event.kind} must not include a d tag`
501
- });
525
+ const identifiers = event.tags.filter((tag) => tag[0] === "d");
526
+ if (event.kind === NAPPLET_KIND_NAMED && (identifiers.length !== 1 || !dTag)) {
527
+ errors.push({ code: "missing-d-tag", message: "Named manifests require exactly one non-empty d tag" });
528
+ } else if (event.kind !== NAPPLET_KIND_NAMED && identifiers.length > 0) {
529
+ errors.push({ code: "unexpected-d-tag", message: "Only named manifests carry a d tag" });
502
530
  }
503
- const indexPath = event.tags.find((tag) => tag[0] === "path" && tag[1] === "/index.html");
504
- if (!indexPath) {
505
- errors.push({
506
- code: "missing-index-html",
507
- message: "Napplet manifest must include a path tag for /index.html"
508
- });
509
- } else if (!isSha256Hex(indexPath[2])) {
510
- errors.push({
511
- code: "invalid-index-html-hash",
512
- message: "The /index.html path tag must carry a 64-character sha256 hash"
513
- });
531
+ const hashes = event.tags.filter((tag) => tag[0] === "x");
532
+ if (hashes.length !== 1 || hashes[0].length !== 2 || !isSha256Hex(hashes[0][1])) {
533
+ errors.push({ code: "invalid-artifact-hash", message: "Manifest requires exactly one x tag with the lowercase sha256 of /index.html" });
514
534
  }
515
- for (const req of requires) {
516
- if (req.startsWith("nap:") || req.startsWith("NAP-")) {
517
- errors.push({
518
- code: "invalid-required-nap",
519
- message: `requires tag "${req}" must be a bare NAP domain such as "relay"`
520
- });
521
- continue;
522
- }
523
- if (!NAP_DOMAINS.includes(req)) {
524
- errors.push({
525
- code: "unknown-required-nap",
526
- message: `requires tag "${req}" is not a known NAP domain`
527
- });
528
- }
535
+ if (typeof event.content !== "string" || !event.content.trim()) {
536
+ errors.push({ code: "missing-description", message: "Manifest content must contain a non-empty plain-text description" });
529
537
  }
538
+ validateCapabilities(event, errors, warnings);
539
+ validateMetadata(event, errors, warnings);
530
540
  return {
531
541
  ok: errors.length === 0,
532
542
  kind: event.kind,
533
543
  dTag,
534
544
  requires,
545
+ optional: event.tags.filter((tag) => tag[0] === "O").map((tag) => tag[1]).filter(Boolean),
535
546
  errors,
536
547
  warnings
537
548
  };
538
549
  }
550
+ function validateCapabilities(event, errors, warnings) {
551
+ for (const tag of event.tags.filter((tag2) => tag2[0] === "R" || tag2[0] === "O")) {
552
+ const domain = tag[1];
553
+ if (tag.length !== 2 || !domain || /[.:\s]/.test(domain) || domain.startsWith("NAP-")) {
554
+ errors.push({ code: tag[0] === "R" ? "invalid-required-nap" : "invalid-optional-nap", message: `${tag[0]} must name one bare NAP domain` });
555
+ } else if (!NAP_DOMAINS.includes(domain)) {
556
+ warnings.push({ code: "unknown-required-nap", message: `Domain "${domain}" is not in this tool's registry; check its NAP and runtime availability` });
557
+ }
558
+ }
559
+ }
560
+ function validateMetadata(event, errors, warnings) {
561
+ for (const name of ["title", "source", "a", "A"]) {
562
+ const tags = event.tags.filter((tag) => tag[0] === name);
563
+ if (tags.length > 1 || tags.length && (name === "a" || name === "A") && event.kind !== NAPPLET_KIND_SNAPSHOT) {
564
+ errors.push({ code: "invalid-metadata", message: `Invalid ${name} tag cardinality for kind ${event.kind}` });
565
+ }
566
+ }
567
+ for (const tag of event.tags.filter((tag2) => tag2[0] === "i")) {
568
+ if (!tag[1]?.trim() || tag[1].includes("?")) {
569
+ errors.push({ code: "invalid-metadata", message: "Intent advertisements must be non-empty queryless identities" });
570
+ }
571
+ }
572
+ const icons = event.tags.filter((tag) => tag[0] === "icon");
573
+ if (icons.length > 1 || icons.some((tag) => tag.length !== 3 || !isSha256Hex(tag[1]) || !["image/png", "image/jpeg", "image/webp"].includes(tag[2]))) {
574
+ warnings.push({ code: "invalid-icon", message: "Ignore invalid icon metadata and use generic artwork (NIP-5D \xA7Icon)" });
575
+ }
576
+ }
539
577
  var REFERENCE_PUBKEY = "f".repeat(64);
540
- var REFERENCE_ENDPOINT = { dTag: "reference-source" };
578
+ var REFERENCE_ENDPOINT = { id: "reference-source-endpoint", catalogId: "reference-source" };
541
579
  var REFERENCE_BLOB_URL = "https://reference.invalid/blob";
542
- var REFERENCE_HANDLER = "reference-handler";
580
+ var REFERENCE_HANDLER = `named:${REFERENCE_PUBKEY}:reference-handler`;
581
+ var REFERENCE_MANIFEST = { kind: 35129, pubkey: REFERENCE_PUBKEY, id: "0".repeat(64), tags: [["d", "reference-handler"], ["z", "note"], ["i", "napplet:note/open", "event"]] };
543
582
  var REFERENCE_SUBSCRIBER = "reference-subscriber";
544
583
  var REFERENCE_CONVENTION = "napplet:note/open";
545
584
  function pickResult(type, id, entry) {
@@ -601,7 +640,7 @@ var NappletConformanceHostBundle = (() => {
601
640
  "inc.channel.list": (e) => ok({ type: "inc.channel.list.result", id: e.id, channels: [] }),
602
641
  "inc.channel.close": none,
603
642
  // theme
604
- "theme.get": (e) => ok({ type: "theme.get.result", id: e.id, theme: { colors: {}, mode: "dark" } }),
643
+ "theme.get": (e) => ok({ type: "theme.get.result", id: e.id, theme: { colors: { background: "#000000", text: "#ffffff", primary: "#663399" } } }),
605
644
  // keys
606
645
  "keys.forward": none,
607
646
  "keys.registerAction": (e) => ok({ type: "keys.registerAction.result", id: e.id, actionId: `action-${String(e.id)}` }),
@@ -789,18 +828,26 @@ var NappletConformanceHostBundle = (() => {
789
828
  "fs.unwatch": (e) => ok({ type: "fs.unwatch.result", id: e.id })
790
829
  };
791
830
  function createReferenceHandler(options) {
831
+ const initialized = /* @__PURE__ */ new Set();
792
832
  return (endpoint, envelope) => {
793
833
  const type = getEnvelopeType(envelope);
794
834
  const verdict = validateEnvelope(envelope);
795
835
  options.records.push({ envelope, verdict, timestamp: options.now() });
796
836
  if (!type || !verdict.ok) return [];
837
+ const domains = endpoint.domains ?? NAP_DOMAINS;
838
+ if (!domains.includes(type.slice(0, type.indexOf(".")))) return [];
839
+ if (type === "shell.ready") {
840
+ if (initialized.has(endpoint.id)) return [];
841
+ initialized.add(endpoint.id);
842
+ return ok({ type: "shell.init", capabilities: { domains: [...domains] }, services: [] });
843
+ }
797
844
  const env = envelope;
798
845
  if (type === "intent.invoke") return options.intents.handleInvoke(endpoint, env);
799
846
  if (type === "intent.available") {
800
847
  return ok({ type: "intent.available.result", id: env.id, availability: options.intents.availability(env.archetype) });
801
848
  }
802
849
  if (type === "intent.handlers") {
803
- return ok({ type: "intent.handlers.result", id: env.id, handlers: [options.intents.availability("note")] });
850
+ return ok({ type: "intent.handlers.result", id: env.id, handlers: options.intents.handlers() });
804
851
  }
805
852
  if (type === "inc.emit") return handleIncEmit(endpoint, env, options.queueDelivery);
806
853
  const responder = RESPONDERS[type];
@@ -817,65 +864,70 @@ var NappletConformanceHostBundle = (() => {
817
864
  const event = {
818
865
  type: "inc.event",
819
866
  topic: env.topic,
820
- sender: endpoint.dTag
867
+ sender: endpoint.id
821
868
  };
822
869
  if ("payload" in env) event.payload = env.payload;
823
870
  queueDelivery(REFERENCE_SUBSCRIBER, event);
824
871
  return [];
825
872
  }
826
- function unavailableIntent(id, archetype, action, error) {
827
- return ok({
828
- type: "intent.invoke.result",
829
- id,
830
- result: { ok: false, archetype, action, handled: false, error }
831
- });
873
+ function catalogId(manifest) {
874
+ if (manifest.kind === 5129) return `snapshot:${manifest.id}`;
875
+ if (manifest.kind === 15129) return `root:${manifest.pubkey}`;
876
+ return `named:${manifest.pubkey}:${manifest.tags.find((tag) => tag[0] === "d")?.[1] ?? ""}`;
832
877
  }
833
- function createIntentHandlers() {
834
- return { handleInvoke, availability };
835
- }
836
- function handleInvoke(_endpoint, env) {
837
- const request = env.request;
838
- if (typeof request !== "object" || request === null || Array.isArray(request)) {
839
- return unavailableIntent(env.id, "", "open", "invalid intent request");
840
- }
841
- const intent = request;
842
- const archetype = typeof intent.archetype === "string" ? intent.archetype : "";
843
- const action = typeof intent.action === "string" ? intent.action : "open";
844
- if (!archetype) {
845
- return unavailableIntent(env.id, archetype, action, "intent request requires an archetype");
878
+ function contractsFor(manifest, archetype) {
879
+ if (!manifest.tags.some((tag) => tag[0] === "z" && tag[1] === archetype)) return [];
880
+ const contracts = [];
881
+ for (const tag of manifest.tags) {
882
+ if (tag[0] !== "i") continue;
883
+ const match = /^napplet:([^/?#]+)\/([^/?#]+)$/.exec(tag[1] ?? "");
884
+ if (match?.[1] !== archetype) continue;
885
+ contracts.push({ convention: tag[1], params: tag.slice(2) });
846
886
  }
847
- if (archetype !== "note") return unavailableIntent(env.id, archetype, action, "no handler");
848
- if (intent.convention !== void 0 && intent.convention !== REFERENCE_CONVENTION) {
849
- return unavailableIntent(env.id, archetype, action, "unsupported convention");
850
- }
851
- return ok({
852
- type: "intent.invoke.result",
853
- id: env.id,
854
- result: {
855
- ok: true,
856
- archetype,
857
- action,
858
- handled: true,
859
- handler: REFERENCE_HANDLER,
860
- windowId: "reference-window",
861
- convention: typeof intent.convention === "string" ? intent.convention : REFERENCE_CONVENTION
862
- }
863
- });
887
+ return contracts;
864
888
  }
865
- function availability(archetype) {
866
- if (archetype !== "note") {
867
- return { archetype, available: false, candidates: [], hasDefault: false };
889
+ function catalogAvailability(manifests, archetype, defaultId) {
890
+ const candidates = [];
891
+ for (const manifest of manifests) {
892
+ const contracts = contractsFor(manifest, archetype);
893
+ if (!contracts.length) continue;
894
+ const title = manifest.tags.find((tag) => tag[0] === "title")?.[1];
895
+ const id = catalogId(manifest);
896
+ candidates.push({
897
+ id,
898
+ ...title ? { title } : {},
899
+ actions: [...new Set(contracts.map(({ convention }) => convention.slice(convention.indexOf("/") + 1)))],
900
+ conventions: [...new Set(contracts.map(({ convention }) => convention))],
901
+ contracts,
902
+ ...id === defaultId ? { isDefault: true } : {}
903
+ });
868
904
  }
905
+ return { archetype, available: candidates.length > 0, candidates, hasDefault: candidates.some((item) => item.isDefault) };
906
+ }
907
+ function createIntentHandlers(queueDelivery, manifests = [REFERENCE_MANIFEST], defaults = { note: REFERENCE_HANDLER }) {
908
+ const availability = (archetype) => catalogAvailability(manifests, String(archetype), defaults[String(archetype)]);
869
909
  return {
870
- archetype,
871
- available: true,
872
- candidates: [{
873
- dTag: REFERENCE_HANDLER,
874
- actions: ["open"],
875
- conventions: [REFERENCE_CONVENTION],
876
- isDefault: true
877
- }],
878
- hasDefault: true
910
+ availability,
911
+ handlers: () => [...new Set(manifests.flatMap((manifest) => manifest.tags.filter((tag) => tag[0] === "z").map((tag) => tag[1])))].map(availability),
912
+ handleInvoke(endpoint, env) {
913
+ const request = env.request;
914
+ const candidates = availability(request.archetype).candidates.filter((candidate2) => candidate2.conventions.includes(request.convention));
915
+ const explicit = request.handler && !["default", "choose"].includes(request.handler);
916
+ const candidate = request.handler === "choose" ? void 0 : explicit ? candidates.find((item) => item.id === request.handler) : candidates.find((item) => item.isDefault) ?? candidates[0];
917
+ if (!candidate) return ok({ type: "intent.invoke.result", id: env.id, result: { ok: false, error: "no handler" } });
918
+ const { archetype, action, convention } = request;
919
+ queueDelivery(candidate.id, structuredClone({
920
+ type: "intent.deliver",
921
+ delivery: {
922
+ sender: endpoint.catalogId,
923
+ archetype,
924
+ action,
925
+ convention,
926
+ ..."payload" in request ? { payload: request.payload } : {}
927
+ }
928
+ }));
929
+ return ok({ type: "intent.invoke.result", id: env.id, result: { ok: true, archetype, action, convention, handler: candidate.id } });
930
+ }
879
931
  };
880
932
  }
881
933
  function createReferenceShell(options = {}) {
@@ -885,7 +937,7 @@ var NappletConformanceHostBundle = (() => {
885
937
  now: options.now ?? Date.now,
886
938
  records,
887
939
  queueDelivery: deliveries.queue,
888
- intents: createIntentHandlers()
940
+ intents: createIntentHandlers(deliveries.queue, options.manifests, options.defaults)
889
941
  });
890
942
  return {
891
943
  get records() {
@@ -1112,13 +1164,14 @@ var NappletConformanceHostBundle = (() => {
1112
1164
  var skip = (detail) => ({ status: "skip", detail });
1113
1165
  var result = { pass, fail, skip };
1114
1166
  function manifestErrors(ctx, codes) {
1115
- return validateManifestEvent(ctx.manifestEvent).errors.filter((e) => codes.includes(e.code));
1167
+ const verdict = validateManifestEvent(ctx.manifestEvent);
1168
+ return [...verdict.errors, ...verdict.warnings].filter((e) => codes.includes(e.code));
1116
1169
  }
1117
- function manifestCheck(id, title, codes) {
1170
+ function manifestCheck(id, title, codes, severity = "error") {
1118
1171
  return {
1119
1172
  id,
1120
1173
  area: "manifest",
1121
- severity: "error",
1174
+ severity,
1122
1175
  title,
1123
1176
  run: (ctx) => {
1124
1177
  if (!ctx.manifestEvent) return result.skip("No NIP-5D manifest event was resolved");
@@ -1135,13 +1188,18 @@ var NappletConformanceHostBundle = (() => {
1135
1188
  "unexpected-d-tag"
1136
1189
  ]),
1137
1190
  manifestCheck("manifest/index-html", "Manifest declares a hashed /index.html", [
1138
- "missing-index-html",
1139
- "invalid-index-html-hash"
1191
+ "invalid-artifact-hash",
1192
+ "missing-description",
1193
+ "invalid-metadata"
1140
1194
  ]),
1141
- manifestCheck("manifest/requires", "requires tags are bare known NAP domains", [
1195
+ manifestCheck("manifest/requires", "R/O tags name bare NAP domains", [
1142
1196
  "invalid-required-nap",
1143
- "unknown-required-nap"
1197
+ "invalid-optional-nap"
1144
1198
  ]),
1199
+ // Registry coverage is a tooling advisory, not a protocol requirement.
1200
+ manifestCheck("manifest/requires-known", "R/O domains are in this toolchain registry (advisory)", [
1201
+ "unknown-required-nap"
1202
+ ], "warning"),
1145
1203
  // ── boot ─────────────────────────────────────────────────────────────────────
1146
1204
  {
1147
1205
  id: "boot/sandbox-allow-scripts",
@@ -0,0 +1,109 @@
1
+ (function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))n(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&n(o)}).observe(document,{childList:!0,subtree:!0});function r(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function n(i){if(i.ep)return;i.ep=!0;const s=r(i);fetch(i.href,s)}})();var _e=["shell","relay","identity","storage","inc","theme","keys","media","notify","config","resource","cvm","outbox","upload","intent","ble","webrtc","link","count","lists","serial","fs","common","dm"],d={id:"string"},Rn={"shell.ready":{dir:"out"},"shell.init":{dir:"in",fields:{capabilities:"object",services:"array"}},"relay.subscribe":{dir:"out",fields:{...d,subId:"string",filters:"array"}},"relay.close":{dir:"out",fields:{...d,subId:"string"}},"relay.publish":{dir:"out",fields:{...d,event:"object"}},"relay.publishEncrypted":{dir:"out",fields:{...d,event:"object",recipient:"string"}},"relay.query":{dir:"out",fields:{...d,filters:"array"}},"relay.event":{dir:"in"},"relay.eose":{dir:"in"},"relay.closed":{dir:"in"},"relay.publish.result":{dir:"in"},"relay.publishEncrypted.result":{dir:"in"},"relay.query.result":{dir:"in"},"identity.getPublicKey":{dir:"out",fields:{...d}},"identity.getRelays":{dir:"out",fields:{...d}},"identity.getProfile":{dir:"out",fields:{...d}},"identity.getFollows":{dir:"out",fields:{...d}},"identity.getList":{dir:"out",fields:{...d,listType:"string"}},"identity.getZaps":{dir:"out",fields:{...d}},"identity.getMutes":{dir:"out",fields:{...d}},"identity.getBlocked":{dir:"out",fields:{...d}},"identity.getBadges":{dir:"out",fields:{...d}},"identity.changed":{dir:"in"},"identity.getPublicKey.result":{dir:"in"},"identity.getRelays.result":{dir:"in"},"identity.getProfile.result":{dir:"in"},"identity.getFollows.result":{dir:"in"},"identity.getList.result":{dir:"in"},"identity.getZaps.result":{dir:"in"},"identity.getMutes.result":{dir:"in"},"identity.getBlocked.result":{dir:"in"},"identity.getBadges.result":{dir:"in"},"storage.get":{dir:"out",fields:{...d,key:"string"}},"storage.set":{dir:"out",fields:{...d,key:"string",value:"string"}},"storage.remove":{dir:"out",fields:{...d,key:"string"}},"storage.keys":{dir:"out",fields:{...d}},"storage.get.result":{dir:"in"},"storage.set.result":{dir:"in"},"storage.remove.result":{dir:"in"},"storage.keys.result":{dir:"in"},"inc.emit":{dir:"out",fields:{topic:"string"},forbiddenFields:["sender"]},"inc.subscribe":{dir:"out",fields:{...d,topic:"string"}},"inc.unsubscribe":{dir:"out",fields:{topic:"string"}},"inc.channel.open":{dir:"out",fields:{...d,target:"string"}},"inc.channel.emit":{dir:"out",fields:{channelId:"string"}},"inc.channel.broadcast":{dir:"out"},"inc.channel.list":{dir:"out",fields:{...d}},"inc.channel.close":{dir:"out",fields:{channelId:"string"}},"inc.subscribe.result":{dir:"in"},"inc.event":{dir:"in",fields:{topic:"string",sender:"string"}},"inc.channel.open.result":{dir:"in"},"inc.channel.opened":{dir:"in",fields:{channelId:"string",peer:"string"}},"inc.channel.event":{dir:"in"},"inc.channel.list.result":{dir:"in"},"inc.channel.closed":{dir:"in"},"theme.get":{dir:"out",fields:{...d}},"theme.get.result":{dir:"in"},"theme.changed":{dir:"in"},"keys.forward":{dir:"out",fields:{key:"string",code:"string",ctrl:"boolean",alt:"boolean",shift:"boolean",meta:"boolean"}},"keys.registerAction":{dir:"out",fields:{...d,action:"object"}},"keys.unregisterAction":{dir:"out",fields:{actionId:"string"}},"keys.registerAction.result":{dir:"in"},"keys.bindings":{dir:"in"},"keys.action":{dir:"in"},"media.session.create":{dir:"out",fields:{...d,owner:"object"}},"media.session.update":{dir:"out",fields:{sessionId:"string",metadata:"object"}},"media.session.destroy":{dir:"out",fields:{sessionId:"string"}},"media.state":{dir:"out",fields:{sessionId:"string",status:"string"}},"media.capabilities":{dir:"out",fields:{sessionId:"string",actions:"array"}},"media.session.create.result":{dir:"in"},"media.command":{dir:"in"},"media.controls":{dir:"in"},"notify.send":{dir:"out",fields:{...d,title:"string"}},"notify.dismiss":{dir:"out",fields:{notificationId:"string"}},"notify.badge":{dir:"out",fields:{count:"number"}},"notify.channel.register":{dir:"out",fields:{channelId:"string",label:"string"}},"notify.permission.request":{dir:"out",fields:{...d}},"notify.send.result":{dir:"in"},"notify.permission.result":{dir:"in"},"notify.action":{dir:"in"},"notify.clicked":{dir:"in"},"notify.dismissed":{dir:"in"},"notify.controls":{dir:"in"},"config.registerSchema":{dir:"out",fields:{...d,schema:"object"}},"config.get":{dir:"out",fields:{...d}},"config.subscribe":{dir:"out"},"config.unsubscribe":{dir:"out"},"config.openSettings":{dir:"out"},"config.registerSchema.result":{dir:"in"},"config.values":{dir:"in"},"config.schemaError":{dir:"in"},"resource.info":{dir:"out",fields:{...d}},"resource.bytes":{dir:"out",fields:{...d,url:"string"}},"resource.bytesMany":{dir:"out",fields:{...d,requests:"array"}},"resource.cancel":{dir:"out",fields:{...d}},"resource.info.result":{dir:"in"},"resource.info.error":{dir:"in"},"resource.bytes.result":{dir:"in"},"resource.bytes.error":{dir:"in"},"resource.bytesMany.result":{dir:"in"},"resource.bytesMany.error":{dir:"in"},"cvm.discover":{dir:"out",fields:{...d}},"cvm.request":{dir:"out",fields:{...d,server:"object",message:"object"}},"cvm.close":{dir:"out",fields:{...d,server:"object"}},"cvm.registry.list":{dir:"out",fields:{...d}},"cvm.registry.has":{dir:"out",fields:{...d,family:"string"}},"cvm.registry.describe":{dir:"out",fields:{...d,family:"string"}},"cvm.registry.call":{dir:"out",fields:{...d,family:"string",tool:"string"}},"cvm.discover.result":{dir:"in"},"cvm.request.result":{dir:"in"},"cvm.close.result":{dir:"in"},"cvm.event":{dir:"in"},"cvm.registry.list.result":{dir:"in"},"cvm.registry.has.result":{dir:"in"},"cvm.registry.describe.result":{dir:"in"},"cvm.registry.call.result":{dir:"in"},"outbox.getEvent":{dir:"out",fields:{...d,eventId:"string"}},"outbox.query":{dir:"out",fields:{...d,filters:"present"}},"outbox.subscribe":{dir:"out",fields:{...d,subId:"string",filters:"present"}},"outbox.close":{dir:"out",fields:{...d,subId:"string"}},"outbox.publish":{dir:"out",fields:{...d,event:"object"}},"outbox.resolveRelays":{dir:"out",fields:{...d,target:"present"}},"outbox.getEvent.result":{dir:"in"},"outbox.query.result":{dir:"in"},"outbox.event":{dir:"in"},"outbox.closed":{dir:"in"},"outbox.publish.result":{dir:"in"},"outbox.resolveRelays.result":{dir:"in"},"upload.info":{dir:"out",fields:{...d}},"upload.upload":{dir:"out",fields:{...d,request:"object"}},"upload.status":{dir:"out",fields:{...d,uploadId:"string"}},"upload.info.result":{dir:"in"},"upload.upload.result":{dir:"in"},"upload.status.result":{dir:"in"},"upload.status.changed":{dir:"in"},"intent.invoke":{dir:"out",fields:{...d,request:"object"}},"intent.available":{dir:"out",fields:{...d,archetype:"string"}},"intent.handlers":{dir:"out",fields:{...d}},"intent.invoke.result":{dir:"in",fields:{...d,result:"object"}},"intent.available.result":{dir:"in"},"intent.handlers.result":{dir:"in"},"intent.deliver":{dir:"in",fields:{delivery:"object"}},"intent.changed":{dir:"in"},"ble.open":{dir:"out",fields:{...d,request:"object"}},"ble.services":{dir:"out",fields:{...d,sessionId:"string"}},"ble.read":{dir:"out",fields:{...d,sessionId:"string",target:"object"}},"ble.write":{dir:"out",fields:{...d,sessionId:"string",target:"object",data:"array"}},"ble.subscribe":{dir:"out",fields:{...d,sessionId:"string",target:"object"}},"ble.unsubscribe":{dir:"out",fields:{...d,sessionId:"string",target:"object"}},"ble.close":{dir:"out",fields:{...d,sessionId:"string"}},"ble.open.result":{dir:"in"},"ble.services.result":{dir:"in"},"ble.read.result":{dir:"in"},"ble.write.result":{dir:"in"},"ble.subscribe.result":{dir:"in"},"ble.unsubscribe.result":{dir:"in"},"ble.close.result":{dir:"in"},"ble.event":{dir:"in"},"common.encodeNip19":{dir:"out",fields:{...d,input:"object"}},"common.decodeNip19":{dir:"out",fields:{...d,value:"string"}},"common.getProfile":{dir:"out",fields:{...d,target:"string"}},"common.follows":{dir:"out",fields:{...d}},"common.follow":{dir:"out",fields:{...d,pubkeys:"array"}},"common.unfollow":{dir:"out",fields:{...d,pubkeys:"array"}},"common.react":{dir:"out",fields:{...d,targetEventId:"string",reaction:"string"}},"common.report":{dir:"out",fields:{...d,target:"object",reason:"string",text:"string"}},"common.encodeNip19.result":{dir:"in"},"common.decodeNip19.result":{dir:"in"},"common.getProfile.result":{dir:"in"},"common.follows.result":{dir:"in"},"common.follow.result":{dir:"in"},"common.unfollow.result":{dir:"in"},"common.react.result":{dir:"in"},"common.report.result":{dir:"in"},"webrtc.open":{dir:"out",fields:{...d,request:"object"}},"webrtc.send":{dir:"out",fields:{...d,sessionId:"string",payload:"present"}},"webrtc.close":{dir:"out",fields:{...d,sessionId:"string"}},"webrtc.open.result":{dir:"in"},"webrtc.send.result":{dir:"in"},"webrtc.close.result":{dir:"in"},"webrtc.event":{dir:"in"},"link.open":{dir:"out",fields:{...d,url:"string"}},"link.open.result":{dir:"in"},"count.query":{dir:"out",fields:{...d,filters:"array"}},"count.query.result":{dir:"in"},"lists.supported":{dir:"out",fields:{...d}},"lists.add":{dir:"out",fields:{...d,list:"object",items:"array"}},"lists.remove":{dir:"out",fields:{...d,list:"object",items:"array"}},"lists.supported.result":{dir:"in"},"lists.add.result":{dir:"in"},"lists.remove.result":{dir:"in"},"serial.open":{dir:"out",fields:{...d,request:"object"}},"serial.write":{dir:"out",fields:{...d,sessionId:"string",data:"array"}},"serial.close":{dir:"out",fields:{...d,sessionId:"string"}},"serial.open.result":{dir:"in"},"serial.write.result":{dir:"in"},"serial.close.result":{dir:"in"},"serial.event":{dir:"in"},"fs.info":{dir:"out",fields:{...d}},"fs.pickFile":{dir:"out",fields:{...d}},"fs.pickFiles":{dir:"out",fields:{...d}},"fs.pickDirectory":{dir:"out",fields:{...d}},"fs.pickSaveFile":{dir:"out",fields:{...d}},"fs.stat":{dir:"out",fields:{...d,path:"string"}},"fs.list":{dir:"out",fields:{...d,path:"string"}},"fs.read":{dir:"out",fields:{...d,path:"string"}},"fs.write":{dir:"out",fields:{...d,path:"string",data:"string"}},"fs.mkdir":{dir:"out",fields:{...d,path:"string"}},"fs.remove":{dir:"out",fields:{...d,path:"string"}},"fs.move":{dir:"out",fields:{...d,fromPath:"string",toPath:"string"}},"fs.watch":{dir:"out",fields:{...d,path:"string"}},"fs.unwatch":{dir:"out",fields:{...d,watchId:"string"}},"fs.info.result":{dir:"in"},"fs.pickFile.result":{dir:"in"},"fs.pickFiles.result":{dir:"in"},"fs.pickDirectory.result":{dir:"in"},"fs.pickSaveFile.result":{dir:"in"},"fs.stat.result":{dir:"in"},"fs.list.result":{dir:"in"},"fs.read.result":{dir:"in"},"fs.write.result":{dir:"in"},"fs.mkdir.result":{dir:"in"},"fs.remove.result":{dir:"in"},"fs.move.result":{dir:"in"},"fs.watch.result":{dir:"in"},"fs.unwatch.result":{dir:"in"},"fs.changed":{dir:"in"},"dm.status":{dir:"out",fields:{...d}},"dm.conversations":{dir:"out",fields:{...d}},"dm.messages":{dir:"out",fields:{...d,conversationId:"string"}},"dm.send":{dir:"out",fields:{...d,recipients:"array",content:"string"}},"dm.subscribe":{dir:"out",fields:{...d}},"dm.unsubscribe":{dir:"out",fields:{...d,subscriptionId:"string"}},"dm.status.result":{dir:"in"},"dm.conversations.result":{dir:"in"},"dm.messages.result":{dir:"in"},"dm.send.result":{dir:"in"},"dm.subscribe.result":{dir:"in"},"dm.unsubscribe.result":{dir:"in"},"dm.message":{dir:"in"}};function Ce(e){if(e===void 0)return"undefined";if(e===null)return"null";if(Array.isArray(e))return"array";const t=typeof e;return t==="string"||t==="number"||t==="boolean"?t:t==="object"?"object":"present"}function Sn(e,t){return t==="present"?e!=null:Ce(e)===t}function In(e,t){if(typeof e!="object"||e===null||Array.isArray(e))return;const r=e;typeof r.archetype!="string"&&t.push({code:r.archetype===void 0?"missing-field":"wrong-type",message:'Intent request requires a string "archetype" field',field:"request.archetype"});for(const i of["action","convention"])typeof r[i]!="string"&&t.push({code:r[i]===void 0?"missing-field":"wrong-type",message:`Intent request field "${i}" must be a string`,field:`request.${i}`});const n=typeof r.convention=="string"?/^napplet:([^/?#]+)\/([^/?#]+)$/.exec(r.convention):null;(!n||n[1]!==r.archetype||n[2]!==r.action)&&t.push({code:"wrong-type",message:"Intent convention must be stable and match archetype and action",field:"request.convention"}),r.handler!==void 0&&typeof r.handler!="string"&&t.push({code:"wrong-type",message:'Intent request field "handler" must be a string',field:"request.handler"}),r.behavior!==void 0&&Ce(r.behavior)!=="object"&&t.push({code:"wrong-type",message:'Intent request field "behavior" must be an object',field:"request.behavior"}),r.handlerHint!==void 0&&$n(r.handlerHint,t),"sender"in r&&t.push({code:"forbidden-field",message:"Intent request does not define a caller-supplied sender field",field:"request.sender"})}function $n(e,t){if(Ce(e)!=="object"){t.push({code:"wrong-type",message:'Intent request field "handlerHint" must be an object',field:"request.handlerHint"});return}const{address:r,relays:n}=e;(typeof r!="string"||!/^35129:[0-9a-f]{64}:.+$/s.test(r))&&t.push({code:r===void 0?"missing-field":"wrong-type",message:'Intent handler hint "address" must be a 35129:<pubkey>:<d> coordinate',field:"request.handlerHint.address"}),n!==void 0&&!(Array.isArray(n)&&n.every(i=>typeof i=="string"))&&t.push({code:"wrong-type",message:'Intent handler hint "relays" must be an array of strings',field:"request.handlerHint.relays"})}function Ht(e,t,r){Array.isArray(e)&&e.every(n=>typeof n=="string")||r.push({code:"wrong-type",message:`Field "${t}" must be an array of strings`,field:t})}function An(e,t){e.servers!==void 0&&Ht(e.servers,"servers",t)}function Bn(e,t){if(Array.isArray(e)){if(e.length===0){t.push({code:"invalid-resource-request",message:'Field "requests" must contain at least one resource request',field:"requests"});return}for(const[r,n]of e.entries()){const i=`requests[${r}]`;if(typeof n!="object"||n===null||Array.isArray(n)){t.push({code:"invalid-resource-request",message:`Field "${i}" must be a resource request object`,field:i});continue}const s=n;typeof s.url!="string"&&t.push({code:s.url===void 0?"missing-field":"wrong-type",message:`Field "${i}.url" must be a string`,field:`${i}.url`}),s.servers!==void 0&&Ht(s.servers,`${i}.servers`,t)}}}function On(e){const t=[];if(typeof e!="object"||e===null||Array.isArray(e))return{ok:!1,errors:[{code:"not-an-object",message:"Envelope must be a non-null object"}]};const r=e,n=r.type;if(typeof n!="string")return{ok:!1,errors:[{code:"missing-type",message:"Envelope is missing a string `type` field"}]};const i=n.indexOf(".");if(i<=0)return{ok:!1,type:n,errors:[{code:"malformed-type",message:`Envelope type "${n}" is not in domain.action form`}]};const s=n.slice(0,i);if(!_e.includes(s))return{ok:!1,type:n,domain:s,errors:[{code:"unknown-domain",message:`"${s}" is not a known NAP domain`}]};const c=Rn[n];if(!c)return{ok:!1,type:n,domain:s,errors:[{code:"unknown-type",message:`"${n}" is not a known ${s} message type`}]};for(const[a,l]of Object.entries(c.fields??{})){if(!(a in r)||r[a]===void 0){t.push({code:"missing-field",message:`Required field "${a}" is missing`,field:a});continue}Sn(r[a],l)||t.push({code:"wrong-type",message:`Field "${a}" should be ${l} but is ${Ce(r[a])}`,field:a})}if(c.dir==="in")return{ok:!1,type:n,domain:s,direction:"in",errors:[{code:"inbound-type-emitted",message:`"${n}" is a shell→napplet message; a napplet must not emit it`},...t]};for(const a of c.forbiddenFields??[])a in r&&t.push({code:"forbidden-field",message:`Field "${a}" must be runtime-derived and cannot be emitted by a napplet`,field:a});return n==="intent.invoke"&&In(r.request,t),n==="resource.bytes"&&An(r,t),n==="resource.bytesMany"&&Bn(r.requests,t),{ok:t.length===0,type:n,domain:s,direction:"out",errors:t}}var Ut=5129,Tn=15129,de=35129,ct=[Ut,Tn,de];function jt(e,t){return e.tags.find(r=>r[0]===t)}function qn(e){return ct.includes(e)}function Dt(e){return typeof e=="string"&&/^[0-9a-f]{64}$/.test(e)}function Mt(e){return jt(e,"d")?.[1]||void 0}function Nn(e){return e.tags.filter(t=>t[0]==="R").map(t=>t[1]?.trim()??"").filter(Boolean)}function Ft(e){return Mt(e)??jt(e,"title")?.[1]??e.id}function He(e){const t=[],r=[];if(!e)return{ok:!1,requires:[],optional:[],errors:[{code:"missing-manifest-event",message:"No NIP-5D manifest event was resolved"}],warnings:r};const n=Mt(e),i=Nn(e);qn(e.kind)||t.push({code:"invalid-napplet-kind",message:`Manifest event kind ${e.kind} is not a NIP-5D napplet kind`});const s=e.tags.filter(c=>c[0]==="d");e.kind===de&&(s.length!==1||!n)?t.push({code:"missing-d-tag",message:"Named manifests require exactly one non-empty d tag"}):e.kind!==de&&s.length>0&&t.push({code:"unexpected-d-tag",message:"Only named manifests carry a d tag"});const o=e.tags.filter(c=>c[0]==="x");return(o.length!==1||o[0].length!==2||!Dt(o[0][1]))&&t.push({code:"invalid-artifact-hash",message:"Manifest requires exactly one x tag with the lowercase sha256 of /index.html"}),(typeof e.content!="string"||!e.content.trim())&&t.push({code:"missing-description",message:"Manifest content must contain a non-empty plain-text description"}),Ln(e,t,r),Pn(e,t,r),{ok:t.length===0,kind:e.kind,dTag:n,requires:i,optional:e.tags.filter(c=>c[0]==="O").map(c=>c[1]).filter(Boolean),errors:t,warnings:r}}function Ln(e,t,r){for(const n of e.tags.filter(i=>i[0]==="R"||i[0]==="O")){const i=n[1];n.length!==2||!i||/[.:\s]/.test(i)||i.startsWith("NAP-")?t.push({code:n[0]==="R"?"invalid-required-nap":"invalid-optional-nap",message:`${n[0]} must name one bare NAP domain`}):_e.includes(i)||r.push({code:"unknown-required-nap",message:`Domain "${i}" is not in this tool's registry; check its NAP and runtime availability`})}}function Pn(e,t,r){for(const i of["title","source","a","A"]){const s=e.tags.filter(o=>o[0]===i);(s.length>1||s.length&&(i==="a"||i==="A")&&e.kind!==Ut)&&t.push({code:"invalid-metadata",message:`Invalid ${i} tag cardinality for kind ${e.kind}`})}for(const i of e.tags.filter(s=>s[0]==="i"))(!i[1]?.trim()||i[1].includes("?"))&&t.push({code:"invalid-metadata",message:"Intent advertisements must be non-empty queryless identities"});const n=e.tags.filter(i=>i[0]==="icon");(n.length>1||n.some(i=>i.length!==3||!Dt(i[1])||!["image/png","image/jpeg","image/webp"].includes(i[2])))&&r.push({code:"invalid-icon",message:"Ignore invalid icon metadata and use generic artwork (NIP-5D §Icon)"})}var le="f".repeat(64),_n={id:"reference-source-endpoint",catalogId:"reference-source"},Cn="https://reference.invalid/blob",Hn=`named:${le}:reference-handler`,Un={kind:35129,pubkey:le,id:"0".repeat(64),tags:[["d","reference-handler"],["z","note"],["i","napplet:note/open","event"]]},jn="reference-subscriber",Dn="napplet:note/open";function ke(e,t,r){return u({type:e,id:t,result:{entries:[r]}})}var u=e=>[e],N=()=>[];function bt(e){if(typeof e!="string"||!e.startsWith("data:"))return null;const t=e.indexOf(",");if(t<0)return{blob:new Blob([],{type:"text/plain"}),mime:"text/plain"};const r=e.slice(5,t),n=e.slice(t+1),i=r.split(";").filter(Boolean),s=i.includes("base64"),o=i.find(c=>c.includes("/"))??"text/plain";try{if(s){const c=globalThis.atob(n),a=Uint8Array.from(c,l=>l.charCodeAt(0));return{blob:new Blob([a],{type:o}),mime:o}}return{blob:new Blob([decodeURIComponent(n)],{type:o}),mime:o}}catch{return null}}var Mn={"relay.subscribe":e=>u({type:"relay.eose",subId:e.subId}),"relay.close":N,"relay.publish":e=>u({type:"relay.publish.result",id:e.id,ok:!0,event:e.event}),"relay.publishEncrypted":e=>u({type:"relay.publishEncrypted.result",id:e.id,ok:!0,event:e.event}),"relay.query":e=>u({type:"relay.query.result",id:e.id,events:[]}),"identity.getPublicKey":e=>u({type:"identity.getPublicKey.result",id:e.id,pubkey:le}),"identity.getRelays":e=>u({type:"identity.getRelays.result",id:e.id,relays:{}}),"identity.getProfile":e=>u({type:"identity.getProfile.result",id:e.id,profile:null}),"identity.getFollows":e=>u({type:"identity.getFollows.result",id:e.id,pubkeys:[]}),"identity.getList":e=>u({type:"identity.getList.result",id:e.id,entries:[]}),"identity.getZaps":e=>u({type:"identity.getZaps.result",id:e.id,zaps:[]}),"identity.getMutes":e=>u({type:"identity.getMutes.result",id:e.id,pubkeys:[]}),"identity.getBlocked":e=>u({type:"identity.getBlocked.result",id:e.id,pubkeys:[]}),"identity.getBadges":e=>u({type:"identity.getBadges.result",id:e.id,badges:[]}),"storage.get":e=>u({type:"storage.get.result",id:e.id,value:null}),"storage.set":e=>u({type:"storage.set.result",id:e.id}),"storage.remove":e=>u({type:"storage.remove.result",id:e.id}),"storage.keys":e=>u({type:"storage.keys.result",id:e.id,keys:[]}),"inc.emit":N,"inc.subscribe":e=>u({type:"inc.subscribe.result",id:e.id}),"inc.unsubscribe":N,"inc.channel.open":e=>u({type:"inc.channel.open.result",id:e.id,channelId:`chan-${String(e.id)}`,peer:"reference-peer"}),"inc.channel.emit":N,"inc.channel.broadcast":N,"inc.channel.list":e=>u({type:"inc.channel.list.result",id:e.id,channels:[]}),"inc.channel.close":N,"theme.get":e=>u({type:"theme.get.result",id:e.id,theme:{colors:{background:"#000000",text:"#ffffff",primary:"#663399"}}}),"keys.forward":N,"keys.registerAction":e=>u({type:"keys.registerAction.result",id:e.id,actionId:`action-${String(e.id)}`}),"keys.unregisterAction":N,"media.session.create":e=>u({type:"media.session.create.result",id:e.id,sessionId:`session-${String(e.id)}`,owner:e.owner}),"media.session.update":N,"media.session.destroy":N,"media.state":N,"media.capabilities":N,"notify.send":e=>u({type:"notify.send.result",id:e.id,notificationId:`notif-${String(e.id)}`}),"notify.dismiss":N,"notify.badge":N,"notify.channel.register":N,"notify.permission.request":e=>u({type:"notify.permission.result",id:e.id,granted:!0}),"config.registerSchema":e=>u({type:"config.registerSchema.result",id:e.id,ok:!0}),"config.get":e=>u({type:"config.values",id:e.id,values:{}}),"config.subscribe":()=>u({type:"config.values",values:{}}),"config.unsubscribe":N,"config.openSettings":N,"resource.bytes":e=>{const t=bt(e.url);return u(t?{type:"resource.bytes.result",id:e.id,blob:t.blob,mime:t.mime}:{type:"resource.bytes.result",id:e.id,blob:new Blob([]),mime:"application/octet-stream"})},"resource.bytesMany":e=>u({type:"resource.bytesMany.result",id:e.id,items:Array.isArray(e.requests)?e.requests.map(t=>{const r=typeof t=="object"&&t!==null&&!Array.isArray(t)?t.url:void 0,n=bt(r);return{url:typeof r=="string"?r:"",ok:!0,blob:n?.blob??new Blob([]),mime:n?.mime??"application/octet-stream"}}):[]}),"resource.info":e=>u({type:"resource.info.result",id:e.id,info:{schemes:[{scheme:"data",enabled:!0},{scheme:"https",enabled:!0}],maxServers:8}}),"resource.cancel":N,"cvm.discover":e=>u({type:"cvm.discover.result",id:e.id,servers:[]}),"cvm.request":e=>u({type:"cvm.request.result",id:e.id,message:{}}),"cvm.close":e=>u({type:"cvm.close.result",id:e.id}),"outbox.getEvent":e=>u({type:"outbox.getEvent.result",id:e.id}),"outbox.query":e=>u({type:"outbox.query.result",id:e.id,events:[]}),"outbox.subscribe":e=>u({type:"outbox.closed",subId:e.subId,reason:"reference shell complete"}),"outbox.close":N,"outbox.publish":e=>u({type:"outbox.publish.result",id:e.id,ok:!0}),"outbox.resolveRelays":e=>u({type:"outbox.resolveRelays.result",id:e.id,plan:{}}),"upload.info":e=>u({type:"upload.info.result",id:e.id,info:{rails:[{rail:"nip96",enabled:!0,returns:["https"]},{rail:"blossom",enabled:!0,returns:["https","blossom"]}]}}),"upload.upload":e=>u({type:"upload.upload.result",id:e.id,result:{url:Cn}}),"upload.status":e=>u({type:"upload.status.result",id:e.id,status:{}}),"ble.open":e=>u({type:"ble.open.result",id:e.id,session:{id:"ble-reference",state:"open",device:{id:"reference-device",name:"Reference BLE"}}}),"ble.services":e=>u({type:"ble.services.result",id:e.id,services:[]}),"ble.read":e=>u({type:"ble.read.result",id:e.id,data:[]}),"ble.write":e=>u({type:"ble.write.result",id:e.id}),"ble.subscribe":e=>u({type:"ble.subscribe.result",id:e.id}),"ble.unsubscribe":e=>u({type:"ble.unsubscribe.result",id:e.id}),"ble.close":e=>u({type:"ble.close.result",id:e.id}),"common.encodeNip19":e=>u({type:"common.encodeNip19.result",id:e.id,ok:!0,value:"npub1reference",nip19Type:"npub"}),"common.decodeNip19":e=>u({type:"common.decodeNip19.result",id:e.id,ok:!0,nip19Type:"npub",hex:le}),"common.getProfile":e=>u({type:"common.getProfile.result",id:e.id,ok:!0,pubkey:le,profile:null}),"common.follows":e=>u({type:"common.follows.result",id:e.id,ok:!0,pubkeys:[]}),"common.follow":e=>u({type:"common.follow.result",id:e.id,ok:!0}),"common.unfollow":e=>u({type:"common.unfollow.result",id:e.id,ok:!0}),"common.react":e=>u({type:"common.react.result",id:e.id,ok:!0,eventId:"0".repeat(64)}),"common.report":e=>u({type:"common.report.result",id:e.id,ok:!0,eventId:"1".repeat(64)}),"webrtc.open":e=>u({type:"webrtc.open.result",id:e.id,session:{id:"webrtc-reference",scope:{type:"direct",pubkey:le},channel:"default",state:"connecting"}}),"webrtc.send":e=>u({type:"webrtc.send.result",id:e.id}),"webrtc.close":e=>u({type:"webrtc.close.result",id:e.id}),"link.open":e=>u({type:"link.open.result",id:e.id,status:"opened"}),"count.query":e=>u({type:"count.query.result",id:e.id,ok:!0,count:0}),"lists.supported":e=>u({type:"lists.supported.result",id:e.id,lists:[]}),"lists.add":e=>u({type:"lists.add.result",id:e.id,ok:!0,added:0,skipped:0}),"lists.remove":e=>u({type:"lists.remove.result",id:e.id,ok:!0,removed:0,skipped:0}),"serial.open":e=>u({type:"serial.open.result",id:e.id,session:{id:`serial-${String(e.id)}`,state:"open"}}),"serial.write":e=>u({type:"serial.write.result",id:e.id}),"serial.close":e=>u({type:"serial.close.result",id:e.id}),"fs.info":e=>u({type:"fs.info.result",id:e.id,info:{roots:[{path:"/shared",name:"Shared files",permissions:["read","list","write","create","delete","watch"]}],limits:{maxReadBytes:1048576,maxWriteBytes:1048576,maxWatchCount:16}}}),"fs.pickFile":e=>ke("fs.pickFile.result",e.id,{path:"/picked/file.txt",kind:"file",name:"file.txt",permissions:["read"]}),"fs.pickFiles":e=>ke("fs.pickFiles.result",e.id,{path:"/picked/file.txt",kind:"file",name:"file.txt",permissions:["read"]}),"fs.pickDirectory":e=>ke("fs.pickDirectory.result",e.id,{path:"/picked",kind:"directory",name:"picked",permissions:["read","list"]}),"fs.pickSaveFile":e=>ke("fs.pickSaveFile.result",e.id,{path:"/picked/export.json",kind:"file",name:"export.json",permissions:["write","create"]}),"fs.stat":e=>u({type:"fs.stat.result",id:e.id,metadata:{path:e.path,kind:"file",size:0}}),"fs.list":e=>u({type:"fs.list.result",id:e.id,entries:[]}),"fs.read":e=>u({type:"fs.read.result",id:e.id,result:{data:"",offset:0,bytesRead:0,eof:!0,size:0}}),"fs.write":e=>u({type:"fs.write.result",id:e.id,result:{bytesWritten:0,size:0}}),"fs.mkdir":e=>u({type:"fs.mkdir.result",id:e.id}),"fs.remove":e=>u({type:"fs.remove.result",id:e.id}),"fs.move":e=>u({type:"fs.move.result",id:e.id}),"fs.watch":e=>u({type:"fs.watch.result",id:e.id,watchId:`watch-${String(e.id)}`}),"fs.unwatch":e=>u({type:"fs.unwatch.result",id:e.id})};function Fn(e){const t=new Set;return(r,n)=>{const i=Zn(n),s=On(n);if(e.records.push({envelope:n,verdict:s,timestamp:e.now()}),!i||!s.ok)return[];const o=r.domains??_e;if(!o.includes(i.slice(0,i.indexOf("."))))return[];if(i==="shell.ready")return t.has(r.id)?[]:(t.add(r.id),u({type:"shell.init",capabilities:{domains:[...o]},services:[]}));const c=n;if(i==="intent.invoke")return e.intents.handleInvoke(r,c);if(i==="intent.available")return u({type:"intent.available.result",id:c.id,availability:e.intents.availability(c.archetype)});if(i==="intent.handlers")return u({type:"intent.handlers.result",id:c.id,handlers:e.intents.handlers()});if(i==="inc.emit")return Wn(r,c,e.queueDelivery);const a=Mn[i];return a?a(c):[]}}function Zn(e){if(!e||typeof e!="object")return;const t=e.type;return typeof t=="string"?t:void 0}function Wn(e,t,r){if(t.topic!==Dn)return[];const n={type:"inc.event",topic:t.topic,sender:e.id};return"payload"in t&&(n.payload=t.payload),r(jn,n),[]}function Vn(e){return e.kind===5129?`snapshot:${e.id}`:e.kind===15129?`root:${e.pubkey}`:`named:${e.pubkey}:${e.tags.find(t=>t[0]==="d")?.[1]??""}`}function Kn(e,t){if(!e.tags.some(n=>n[0]==="z"&&n[1]===t))return[];const r=[];for(const n of e.tags)n[0]!=="i"||/^napplet:([^/?#]+)\/([^/?#]+)$/.exec(n[1]??"")?.[1]!==t||r.push({convention:n[1],params:n.slice(2)});return r}function zn(e,t,r){const n=[];for(const i of e){const s=Kn(i,t);if(!s.length)continue;const o=i.tags.find(a=>a[0]==="title")?.[1],c=Vn(i);n.push({id:c,...o?{title:o}:{},actions:[...new Set(s.map(({convention:a})=>a.slice(a.indexOf("/")+1)))],conventions:[...new Set(s.map(({convention:a})=>a))],contracts:s,...c===r?{isDefault:!0}:{}})}return{archetype:t,available:n.length>0,candidates:n,hasDefault:n.some(i=>i.isDefault)}}function Yn(e,t=[Un],r={note:Hn}){const n=i=>zn(t,String(i),r[String(i)]);return{availability:n,handlers:()=>[...new Set(t.flatMap(i=>i.tags.filter(s=>s[0]==="z").map(s=>s[1])))].map(n),handleInvoke(i,s){const o=s.request,c=n(o.archetype).candidates.filter(m=>m.conventions.includes(o.convention)),a=o.handler&&!["default","choose"].includes(o.handler),l=o.handler==="choose"?void 0:a?c.find(m=>m.id===o.handler):c.find(m=>m.isDefault)??c[0];if(!l)return u({type:"intent.invoke.result",id:s.id,result:{ok:!1,error:"no handler"}});const{archetype:f,action:h,convention:g}=o;return e(l.id,structuredClone({type:"intent.deliver",delivery:{sender:i.catalogId,archetype:f,action:h,convention:g,..."payload"in o?{payload:o.payload}:{}}})),u({type:"intent.invoke.result",id:s.id,result:{ok:!0,archetype:f,action:h,convention:g,handler:l.id}})}}}function Gn(e={}){const t=[],r=Xn(),n=Fn({now:e.now??Date.now,records:t,queueDelivery:r.queue,intents:Yn(r.queue,e.manifests,e.defaults)});return{get records(){return t},handle:i=>n(_n,i),handleFrom:n,takeDeliveries:r.take,reset(){t.length=0,r.clear()}}}function Xn(){const e=new Map;return{queue(t,r){const n=e.get(t);n?n.push(r):e.set(t,[r])},take(t){const r=e.get(t)??[];return e.delete(t),r},clear(){e.clear()}}}function Jn(e){return{manifestHtml:e.manifestHtml,manifestEvent:e.manifestEvent??null,sandbox:e.sandbox??{allowScripts:!0,allowSameOrigin:!1},installedGlobal:e.boot.installedGlobal,bootError:e.boot.bootError,emitted:e.boot.emitted,forbiddenGlobals:e.forbiddenGlobals??[],degraded:e.boot.degraded,lifecycle:e.lifecycle??null}}var Zt="__nappletConformance.error";function wt(e){return new Promise(t=>setTimeout(t,e))}function Qn(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function er(e){return`
2
+ (() => {
3
+ const domains = ${JSON.stringify(e)};
4
+ const napplet = {};
5
+ for (const domain of domains) napplet[domain] = {};
6
+ const pending = new Map();
7
+ let seq = 0;
8
+ const nextId = () => {
9
+ try {
10
+ if (window.crypto && typeof window.crypto.randomUUID === 'function') return window.crypto.randomUUID();
11
+ } catch {}
12
+ seq += 1;
13
+ return 'conformance-' + Date.now().toString(36) + '-' + seq.toString(36);
14
+ };
15
+ const request = (message, resultType, errorType) => new Promise((resolve, reject) => {
16
+ const id = message.id || nextId();
17
+ const timeout = window.setTimeout(() => {
18
+ pending.delete(id);
19
+ reject(new Error(message.type + ' timed out'));
20
+ }, 5000);
21
+ pending.set(id, { resolve, reject, resultType, errorType, timeout });
22
+ window.parent.postMessage({ ...message, id }, '*');
23
+ });
24
+ window.addEventListener('message', (event) => {
25
+ const msg = event.data;
26
+ if (!msg || typeof msg !== 'object' || typeof msg.id !== 'string') return;
27
+ const slot = pending.get(msg.id);
28
+ if (!slot) return;
29
+ if (msg.type !== slot.resultType && msg.type !== slot.errorType) return;
30
+ pending.delete(msg.id);
31
+ window.clearTimeout(slot.timeout);
32
+ if (msg.type === slot.errorType) {
33
+ slot.reject(new Error(msg.message ? msg.error + ': ' + msg.message : String(msg.error || 'request failed')));
34
+ return;
35
+ }
36
+ slot.resolve(msg);
37
+ });
38
+ if (napplet.resource) {
39
+ napplet.resource.info = () =>
40
+ request({ type: 'resource.info' }, 'resource.info.result', 'resource.info.error')
41
+ .then((msg) => msg.info);
42
+ napplet.resource.bytes = (url, options) => {
43
+ const message = { type: 'resource.bytes', url: String(url) };
44
+ if (options && options.servers !== undefined) message.servers = options.servers;
45
+ return request(message, 'resource.bytes.result', 'resource.bytes.error')
46
+ .then((msg) => msg.blob);
47
+ };
48
+ napplet.resource.bytesMany = (requests) =>
49
+ request({ type: 'resource.bytesMany', requests: Array.from(requests || []) }, 'resource.bytesMany.result', 'resource.bytesMany.error')
50
+ .then((msg) => msg.items);
51
+ napplet.resource.bytesAsObjectURL = (url) => {
52
+ const handle = { url: '', revoke: () => {} };
53
+ let objectUrl = '';
54
+ let revoked = false;
55
+ const ready = napplet.resource.bytes(url).then((blob) => {
56
+ if (revoked) return;
57
+ objectUrl = URL.createObjectURL(blob);
58
+ handle.url = objectUrl;
59
+ return objectUrl;
60
+ });
61
+ handle.revoke = () => {
62
+ if (revoked) return;
63
+ revoked = true;
64
+ if (objectUrl) URL.revokeObjectURL(objectUrl);
65
+ };
66
+ Object.defineProperty(handle, 'ready', { value: ready, enumerable: false });
67
+ return handle;
68
+ };
69
+ }
70
+ window.napplet = napplet;
71
+ const report = (reason) => {
72
+ try {
73
+ window.parent.postMessage({ type: '${Zt}', reason: String(reason && reason.message || reason) }, '*');
74
+ } catch {}
75
+ };
76
+ window.addEventListener('error', (event) => report(event.error || event.message));
77
+ window.addEventListener('unhandledrejection', (event) => report(event.reason));
78
+ })();
79
+ `}function tr(e,t,r){const n=`<base href="${Qn(t)}">`,i=`<script>${er(r)}<\/script>`,s=/<head(?:\s[^>]*)?>/i.exec(e);if(s){const o=s.index+s[0].length;return`${e.slice(0,o)}${n}${i}${e.slice(o)}`}return`${n}${i}${e}`}function nr(e){if(!e.startsWith("data:"))return null;const t=e.indexOf(",");if(t<0)return"";const r=e.slice(0,t),n=e.slice(t+1);return r.endsWith(";base64")?atob(n):decodeURIComponent(n)}async function rr(e){if(e==="about:blank")return"<!doctype html><html><head></head><body></body></html>";const t=nr(e);if(t!==null)return t;const r=await fetch(e);if(!r.ok)throw new Error(`Failed to fetch napplet HTML: ${r.status} ${r.statusText}`);return r.text()}async function vt(e,t,r,n){const i=Gn(),s=r.createElement("iframe");s.setAttribute("sandbox",t.allowSameOrigin?"allow-scripts allow-same-origin":"allow-scripts"),s.setAttribute("aria-hidden","true"),s.style.position="absolute",s.style.width="1px",s.style.height="1px",s.style.left="-9999px";let o=null;const c=f=>{if(f.source!==s.contentWindow)return;const h=f.data;if(h&&typeof h=="object"&&h.type===Zt){o=`napplet boot error: ${String(h.reason??"unknown error")}`;return}const g=i.handle(f.data),m=f.source;for(const b of g)m?.postMessage(b,"*")};let a=!1;const l=new Promise(f=>{s.addEventListener("load",()=>{a=!0,f()},{once:!0})});n.addEventListener("message",c),(r.body??r.documentElement).appendChild(s);try{const f=await rr(t.url);s.srcdoc=tr(f,t.url,e)}catch(f){o=f instanceof Error?f.message:String(f)}if(!o){const f=Symbol("timeout");await Promise.race([l.then(()=>"loaded"),wt(t.readyTimeoutMs).then(()=>f)])===f||!a?o=`napplet did not boot (iframe did not load within ${t.readyTimeoutMs}ms; a conformant napplet must run under sandbox="allow-scripts" without allow-same-origin)`:await wt(t.settleMs)}n.removeEventListener("message",c);try{s.remove()}catch{}return{installedGlobal:o===null,bootError:o,emitted:[...i.records]}}async function ir(e){const t=e.document??document,r=e.window??window,n={url:e.url,readyTimeoutMs:e.readyTimeoutMs??5e3,settleMs:e.settleMs,allowSameOrigin:e.allowSameOrigin??!1},i=await vt(_e,n,t,r);let s=null;{const o=await vt([],n,t,r);s={bootError:o.bootError,emitted:o.emitted}}return{installedGlobal:i.installedGlobal,bootError:i.bootError,emitted:i.emitted,degraded:s}}var sr=e=>({status:"pass",detail:e}),or=(e,t)=>({status:"fail",detail:e,diagnostics:t}),ar=e=>({status:"skip",detail:e}),T={pass:sr,fail:or,skip:ar};function cr(e,t){const r=He(e.manifestEvent);return[...r.errors,...r.warnings].filter(n=>t.includes(n.code))}function Re(e,t,r,n="error"){return{id:e,area:"manifest",severity:n,title:t,run:i=>{if(!i.manifestEvent)return T.skip("No NIP-5D manifest event was resolved");const s=cr(i,r);return s.length?T.fail(s[0].message,s):T.pass()}}}var lr=[Re("manifest/event-kind","Resolved event is a NIP-5D napplet manifest",["invalid-napplet-kind","missing-d-tag","unexpected-d-tag"]),Re("manifest/index-html","Manifest declares a hashed /index.html",["invalid-artifact-hash","missing-description","invalid-metadata"]),Re("manifest/requires","R/O tags name bare NAP domains",["invalid-required-nap","invalid-optional-nap"]),Re("manifest/requires-known","R/O domains are in this toolchain registry (advisory)",["unknown-required-nap"],"warning"),{id:"boot/sandbox-allow-scripts",area:"boot",severity:"error",title:"Runs under allow-scripts without allow-same-origin",run:e=>e.sandbox.allowScripts?e.sandbox.allowSameOrigin?T.fail("Napplet relied on allow-same-origin, which a shell must not grant"):T.pass():T.fail("Napplet was not loaded with allow-scripts")},{id:"boot/installs-global",area:"boot",severity:"error",title:"Runs after runtime-injected window.napplet is installed",run:e=>e.installedGlobal?T.pass():T.fail("runtime did not inject window.napplet before load")},{id:"boot/no-boot-error",area:"boot",severity:"error",title:"Boots without an uncaught error",run:e=>e.bootError?T.fail(e.bootError):T.pass()},{id:"boot/no-forbidden-globals",area:"boot",severity:"error",title:"Does not access forbidden browser authority surfaces",run:e=>e.forbiddenGlobals.length?T.fail(`Accessed forbidden surface(s): ${e.forbiddenGlobals.join(", ")}`,e.forbiddenGlobals):T.pass()},{id:"wire/envelope-well-formed",area:"wire",severity:"error",title:"Every emitted envelope is well-formed",run:e=>{if(e.emitted.length===0)return T.skip("Napplet emitted no envelopes");const t=e.emitted.filter(n=>!n.verdict.ok);if(t.length===0)return T.pass(`${e.emitted.length} envelope(s) valid`);const r=t.map(n=>({envelope:n.envelope,errors:n.verdict.errors}));return T.fail(`${t.length}/${e.emitted.length} emitted envelope(s) invalid`,r)}},{id:"degrade/domain-absence",area:"degradation",severity:"error",title:"Does not crash when no NAP domains are injected",run:e=>e.degraded?e.degraded.bootError?T.fail(`Crashed with no injected domains: ${e.degraded.bootError}`):T.pass():T.skip("Host did not run the degraded (no-capabilities) pass")},{id:"lifecycle/clean-teardown",area:"lifecycle",severity:"warning",title:"Tears down listeners on unload",run:e=>e.lifecycle?e.lifecycle.listenerLeak?T.fail("Message listeners remained after unload"):T.pass():T.skip("Lifecycle not measured")}];function dr(e,t={}){const r=t.now??(()=>Date.now()),n=t.checks??lr,i=r(),s=n.map(a=>{const l=a.run(e);return{id:a.id,area:a.area,severity:a.severity,title:a.title,status:l.status,detail:l.detail,diagnostics:l.diagnostics}}),o={total:s.length,passed:s.filter(a=>a.status==="pass").length,failed:s.filter(a=>a.status==="fail").length,skipped:s.filter(a=>a.status==="skip").length,errors:s.filter(a=>a.status==="fail"&&a.severity==="error").length,warnings:s.filter(a=>a.status==="fail"&&a.severity==="warning").length};return{napplet:e.manifestEvent?Ft(e.manifestEvent):void 0,startedAt:i,finishedAt:r(),checks:s,summary:o,ok:o.errors===0}}function ur(e,t){const r=i=>e.tags.find(s=>s[0]===i)?.[1],n=e.tags.filter(i=>i[0]==="server").map(i=>i[1]).filter(Boolean);return[["event",e.id],["kind",e.kind],["d",r("d")],["name",Ft(e)],["requires",t.requires.join(", ")],["optional",t.optional.join(", ")],["artifact hash (x)",r("x")],["servers",n.join(", ")]]}/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */function fr(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function lt(e,t=""){if(!Number.isSafeInteger(e)||e<0){const r=t&&`"${t}" `;throw new Error(`${r}expected integer >= 0, got ${e}`)}}function D(e,t,r=""){const n=fr(e),i=e?.length,s=t!==void 0;if(!n||s&&i!==t){const o=r&&`"${r}" `,c=s?` of length ${t}`:"",a=n?`length=${i}`:`type=${typeof e}`;throw new Error(o+"expected Uint8Array"+c+", got "+a)}return e}function Et(e,t=!0){if(e.destroyed)throw new Error("Hash instance has been destroyed");if(t&&e.finished)throw new Error("Hash#digest() has already been called")}function hr(e,t){D(e,void 0,"digestInto() output");const r=t.outputLen;if(e.length<r)throw new Error('"digestInto() output" expected to be of length >='+r)}function Qe(...e){for(let t=0;t<e.length;t++)e[t].fill(0)}function Ze(e){return new DataView(e.buffer,e.byteOffset,e.byteLength)}function Y(e,t){return e<<32-t|e>>>t}const Wt=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",pr=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function _(e){if(D(e),Wt)return e.toHex();let t="";for(let r=0;r<e.length;r++)t+=pr[e[r]];return t}const J={_0:48,_9:57,A:65,F:70,a:97,f:102};function xt(e){if(e>=J._0&&e<=J._9)return e-J._0;if(e>=J.A&&e<=J.F)return e-(J.A-10);if(e>=J.a&&e<=J.f)return e-(J.a-10)}function X(e){if(typeof e!="string")throw new Error("hex string expected, got "+typeof e);if(Wt)return Uint8Array.fromHex(e);const t=e.length,r=t/2;if(t%2)throw new Error("hex string expected, got unpadded hex of length "+t);const n=new Uint8Array(r);for(let i=0,s=0;i<r;i++,s+=2){const o=xt(e.charCodeAt(s)),c=xt(e.charCodeAt(s+1));if(o===void 0||c===void 0){const a=e[s]+e[s+1];throw new Error('hex string expected, got non-hex character "'+a+'" at index '+s)}n[i]=o*16+c}return n}function Oe(...e){let t=0;for(let n=0;n<e.length;n++){const i=e[n];D(i),t+=i.length}const r=new Uint8Array(t);for(let n=0,i=0;n<e.length;n++){const s=e[n];r.set(s,i),i+=s.length}return r}function gr(e,t={}){const r=(i,s)=>e(s).update(i).digest(),n=e(void 0);return r.outputLen=n.outputLen,r.blockLen=n.blockLen,r.create=i=>e(i),Object.assign(r,t),Object.freeze(r)}function Vt(e=32){const t=typeof globalThis=="object"?globalThis.crypto:null;if(typeof t?.getRandomValues!="function")throw new Error("crypto.getRandomValues must be defined");return t.getRandomValues(new Uint8Array(e))}const mr=e=>({oid:Uint8Array.from([6,9,96,134,72,1,101,3,4,2,e])});/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */function Kt(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function zt(e,t){return Array.isArray(t)?t.length===0?!0:e?t.every(r=>typeof r=="string"):t.every(r=>Number.isSafeInteger(r)):!1}function yr(e){if(typeof e!="function")throw new Error("function expected");return!0}function be(e,t){if(typeof t!="string")throw new Error(`${e}: string expected`);return!0}function Yt(e){if(!Number.isSafeInteger(e))throw new Error(`invalid integer: ${e}`)}function et(e){if(!Array.isArray(e))throw new Error("array expected")}function Gt(e,t){if(!zt(!0,t))throw new Error(`${e}: array of strings expected`)}function Xt(e,t){if(!zt(!1,t))throw new Error(`${e}: array of numbers expected`)}function br(...e){const t=s=>s,r=(s,o)=>c=>s(o(c)),n=e.map(s=>s.encode).reduceRight(r,t),i=e.map(s=>s.decode).reduce(r,t);return{encode:n,decode:i}}function wr(e){const t=typeof e=="string"?e.split(""):e,r=t.length;Gt("alphabet",t);const n=new Map(t.map((i,s)=>[i,s]));return{encode:i=>(et(i),i.map(s=>{if(!Number.isSafeInteger(s)||s<0||s>=r)throw new Error(`alphabet.encode: digit index outside alphabet "${s}". Allowed: ${e}`);return t[s]})),decode:i=>(et(i),i.map(s=>{be("alphabet.decode",s);const o=n.get(s);if(o===void 0)throw new Error(`Unknown letter: "${s}". Allowed: ${e}`);return o}))}}function vr(e=""){return be("join",e),{encode:t=>(Gt("join.decode",t),t.join(e)),decode:t=>(be("join.decode",t),t.split(e))}}const Jt=(e,t)=>t===0?e:Jt(t,e%t),Te=(e,t)=>e+(t-Jt(e,t)),Ae=(()=>{let e=[];for(let t=0;t<40;t++)e.push(2**t);return e})();function tt(e,t,r,n){if(et(e),t<=0||t>32)throw new Error(`convertRadix2: wrong from=${t}`);if(r<=0||r>32)throw new Error(`convertRadix2: wrong to=${r}`);if(Te(t,r)>32)throw new Error(`convertRadix2: carry overflow from=${t} to=${r} carryBits=${Te(t,r)}`);let i=0,s=0;const o=Ae[t],c=Ae[r]-1,a=[];for(const l of e){if(Yt(l),l>=o)throw new Error(`convertRadix2: invalid data word=${l} from=${t}`);if(i=i<<t|l,s+t>32)throw new Error(`convertRadix2: carry overflow pos=${s} from=${t}`);for(s+=t;s>=r;s-=r)a.push((i>>s-r&c)>>>0);const f=Ae[s];if(f===void 0)throw new Error("invalid carry");i&=f-1}if(i=i<<r-s&c,!n&&s>=t)throw new Error("Excess padding");if(!n&&i>0)throw new Error(`Non-zero padding: ${i}`);return n&&s>0&&a.push(i>>>0),a}function Er(e,t=!1){if(Yt(e),e<=0||e>32)throw new Error("radix2: bits should be in (0..32]");if(Te(8,e)>32||Te(e,8)>32)throw new Error("radix2: carry overflow");return{encode:r=>{if(!Kt(r))throw new Error("radix2.encode input should be Uint8Array");return tt(Array.from(r),8,e,!t)},decode:r=>(Xt("radix2.decode",r),Uint8Array.from(tt(r,e,8,t)))}}function kt(e){return yr(e),function(...t){try{return e.apply(null,t)}catch{}}}const nt=br(wr("qpzry9x8gf2tvdw0s3jn54khce6mua7l"),vr("")),Rt=[996825010,642813549,513874426,1027748829,705979059];function pe(e){const t=e>>25;let r=(e&33554431)<<5;for(let n=0;n<Rt.length;n++)(t>>n&1)===1&&(r^=Rt[n]);return r}function St(e,t,r=1){const n=e.length;let i=1;for(let s=0;s<n;s++){const o=e.charCodeAt(s);if(o<33||o>126)throw new Error(`Invalid prefix (${e})`);i=pe(i)^o>>5}i=pe(i);for(let s=0;s<n;s++)i=pe(i)^e.charCodeAt(s)&31;for(let s of t)i=pe(i)^s;for(let s=0;s<6;s++)i=pe(i);return i^=r,nt.encode(tt([i%Ae[30]],30,5,!1))}function xr(e){const t=e==="bech32"?1:734539939,r=Er(5),n=r.decode,i=r.encode,s=kt(n);function o(h,g,m=90){be("bech32.encode prefix",h),Kt(g)&&(g=Array.from(g)),Xt("bech32.encode",g);const b=h.length;if(b===0)throw new TypeError(`Invalid prefix length ${b}`);const E=b+7+g.length;if(m!==!1&&E>m)throw new TypeError(`Length ${E} exceeds limit ${m}`);const q=h.toLowerCase(),L=St(q,g,t);return`${q}1${nt.encode(g)}${L}`}function c(h,g=90){be("bech32.decode input",h);const m=h.length;if(m<8||g!==!1&&m>g)throw new TypeError(`invalid string length: ${m} (${h}). Expected (8..${g})`);const b=h.toLowerCase();if(h!==b&&h!==h.toUpperCase())throw new Error("String must be lowercase or uppercase");const E=b.lastIndexOf("1");if(E===0||E===-1)throw new Error('Letter "1" must be present between prefix and data only');const q=b.slice(0,E),L=b.slice(E+1);if(L.length<6)throw new Error("Data must be at least 6 characters long");const K=nt.decode(L).slice(0,-6),Q=St(q,K,t);if(!L.endsWith(Q))throw new Error(`Invalid checksum in ${h}: expected "${Q}"`);return{prefix:q,words:K}}const a=kt(c);function l(h){const{prefix:g,words:m}=c(h,!1);return{prefix:g,words:m,bytes:n(m)}}function f(h,g){return o(h,i(g))}return{encode:o,decode:c,encodeFromBytes:f,decodeToBytes:l,decodeUnsafe:a,fromWords:n,fromWordsUnsafe:s,toWords:i}}const It=xr("bech32");var Se=new TextDecoder("utf-8");new TextEncoder;var kr=5e3;function Rr(e){try{return e.startsWith("nostr:")&&(e=e.substring(6)),Sr(e)}catch{return{type:"invalid",data:null}}}function Sr(e){let{prefix:t,words:r}=It.decode(e,kr),n=new Uint8Array(It.fromWords(r));switch(t){case"nprofile":{let i=We(n);if(!i[0]?.[0])throw new Error("missing TLV 0 for nprofile");if(i[0][0].length!==32)throw new Error("TLV 0 should be 32 bytes");return{type:"nprofile",data:{pubkey:_(i[0][0]),relays:i[1]?i[1].map(s=>Se.decode(s)):[]}}}case"nevent":{let i=We(n);if(!i[0]?.[0])throw new Error("missing TLV 0 for nevent");if(i[0][0].length!==32)throw new Error("TLV 0 should be 32 bytes");if(i[2]&&i[2][0].length!==32)throw new Error("TLV 2 should be 32 bytes");if(i[3]&&i[3][0].length!==4)throw new Error("TLV 3 should be 4 bytes");return{type:"nevent",data:{id:_(i[0][0]),relays:i[1]?i[1].map(s=>Se.decode(s)):[],author:i[2]?.[0]?_(i[2][0]):void 0,kind:i[3]?.[0]?parseInt(_(i[3][0]),16):void 0}}}case"naddr":{let i=We(n);if(!i[0]?.[0])throw new Error("missing TLV 0 for naddr");if(!i[2]?.[0])throw new Error("missing TLV 2 for naddr");if(i[2][0].length!==32)throw new Error("TLV 2 should be 32 bytes");if(!i[3]?.[0])throw new Error("missing TLV 3 for naddr");if(i[3][0].length!==4)throw new Error("TLV 3 should be 4 bytes");return{type:"naddr",data:{identifier:Se.decode(i[0][0]),pubkey:_(i[2][0]),kind:parseInt(_(i[3][0]),16),relays:i[1]?i[1].map(s=>Se.decode(s)):[]}}}case"nsec":return{type:t,data:n};case"npub":case"note":return{type:t,data:_(n)};default:throw new Error(`unknown prefix ${t}`)}}function We(e){let t={},r=e;for(;r.length>0;){let n=r[0],i=r[1],s=r.slice(2,2+i);if(r=r.slice(2+i),s.length<i)throw new Error(`not enough data to read on TLV ${n}`);t[n]=t[n]||[],t[n].push(s)}return t}function Ir(e,t,r){return e&t^~e&r}function $r(e,t,r){return e&t^e&r^t&r}class Ar{blockLen;outputLen;padOffset;isLE;buffer;view;finished=!1;length=0;pos=0;destroyed=!1;constructor(t,r,n,i){this.blockLen=t,this.outputLen=r,this.padOffset=n,this.isLE=i,this.buffer=new Uint8Array(t),this.view=Ze(this.buffer)}update(t){Et(this),D(t);const{view:r,buffer:n,blockLen:i}=this,s=t.length;for(let o=0;o<s;){const c=Math.min(i-this.pos,s-o);if(c===i){const a=Ze(t);for(;i<=s-o;o+=i)this.process(a,o);continue}n.set(t.subarray(o,o+c),this.pos),this.pos+=c,o+=c,this.pos===i&&(this.process(r,0),this.pos=0)}return this.length+=t.length,this.roundClean(),this}digestInto(t){Et(this),hr(t,this),this.finished=!0;const{buffer:r,view:n,blockLen:i,isLE:s}=this;let{pos:o}=this;r[o++]=128,Qe(this.buffer.subarray(o)),this.padOffset>i-o&&(this.process(n,0),o=0);for(let h=o;h<i;h++)r[h]=0;n.setBigUint64(i-8,BigInt(this.length*8),s),this.process(n,0);const c=Ze(t),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen must be aligned to 32bit");const l=a/4,f=this.get();if(l>f.length)throw new Error("_sha2: outputLen bigger than state");for(let h=0;h<l;h++)c.setUint32(4*h,f[h],s)}digest(){const{buffer:t,outputLen:r}=this;this.digestInto(t);const n=t.slice(0,r);return this.destroy(),n}_cloneInto(t){t||=new this.constructor,t.set(...this.get());const{blockLen:r,buffer:n,length:i,finished:s,destroyed:o,pos:c}=this;return t.destroyed=o,t.finished=s,t.length=i,t.pos=c,i%r&&t.buffer.set(n),t}clone(){return this._cloneInto()}}const ee=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),Br=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),te=new Uint32Array(64);class Or extends Ar{constructor(t){super(64,t,8,!1)}get(){const{A:t,B:r,C:n,D:i,E:s,F:o,G:c,H:a}=this;return[t,r,n,i,s,o,c,a]}set(t,r,n,i,s,o,c,a){this.A=t|0,this.B=r|0,this.C=n|0,this.D=i|0,this.E=s|0,this.F=o|0,this.G=c|0,this.H=a|0}process(t,r){for(let h=0;h<16;h++,r+=4)te[h]=t.getUint32(r,!1);for(let h=16;h<64;h++){const g=te[h-15],m=te[h-2],b=Y(g,7)^Y(g,18)^g>>>3,E=Y(m,17)^Y(m,19)^m>>>10;te[h]=E+te[h-7]+b+te[h-16]|0}let{A:n,B:i,C:s,D:o,E:c,F:a,G:l,H:f}=this;for(let h=0;h<64;h++){const g=Y(c,6)^Y(c,11)^Y(c,25),m=f+g+Ir(c,a,l)+Br[h]+te[h]|0,E=(Y(n,2)^Y(n,13)^Y(n,22))+$r(n,i,s)|0;f=l,l=a,a=c,c=o+m|0,o=s,s=i,i=n,n=m+E|0}n=n+this.A|0,i=i+this.B|0,s=s+this.C|0,o=o+this.D|0,c=c+this.E|0,a=a+this.F|0,l=l+this.G|0,f=f+this.H|0,this.set(n,i,s,o,c,a,l,f)}roundClean(){Qe(te)}destroy(){this.set(0,0,0,0,0,0,0,0),Qe(this.buffer)}}class Tr extends Or{A=ee[0]|0;B=ee[1]|0;C=ee[2]|0;D=ee[3]|0;E=ee[4]|0;F=ee[5]|0;G=ee[6]|0;H=ee[7]|0;constructor(){super(32)}}const qe=gr(()=>new Tr,mr(1));/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const dt=BigInt(0),rt=BigInt(1);function $t(e,t=""){if(typeof e!="boolean"){const r=t&&`"${t}" `;throw new Error(r+"expected boolean, got type="+typeof e)}return e}function qr(e){if(typeof e=="bigint"){if(!Pr(e))throw new Error("positive bigint expected, got "+e)}else lt(e);return e}function Qt(e){if(typeof e!="string")throw new Error("hex string expected, got "+typeof e);return e===""?dt:BigInt("0x"+e)}function ut(e){return Qt(_(e))}function en(e){return Qt(_(Nr(D(e)).reverse()))}function ft(e,t){lt(t),e=qr(e);const r=X(e.toString(16).padStart(t*2,"0"));if(r.length!==t)throw new Error("number too large");return r}function tn(e,t){return ft(e,t).reverse()}function Nr(e){return Uint8Array.from(e)}function Lr(e){return Uint8Array.from(e,(t,r)=>{const n=t.charCodeAt(0);if(t.length!==1||n>127)throw new Error(`string contains non-ASCII character "${e[r]}" with code ${n} at position ${r}`);return n})}const Pr=e=>typeof e=="bigint"&&dt<=e;function _r(e){let t;for(t=0;e>dt;e>>=rt,t+=1);return t}const nn=e=>(rt<<BigInt(e))-rt;function rn(e,t={},r={}){if(!e||typeof e!="object")throw new Error("expected valid options object");function n(s,o,c){const a=e[s];if(c&&a===void 0)return;const l=typeof a;if(l!==o||a===null)throw new Error(`param "${s}" is invalid: expected ${o}, got ${l}`)}const i=(s,o)=>Object.entries(s).forEach(([c,a])=>n(c,a,o));i(t,!1),i(r,!0)}function At(e){const t=new WeakMap;return(r,...n)=>{const i=t.get(r);if(i!==void 0)return i;const s=e(r,...n);return t.set(r,s),s}}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const j=BigInt(0),U=BigInt(1),se=BigInt(2),sn=BigInt(3),on=BigInt(4),an=BigInt(5),Cr=BigInt(7),cn=BigInt(8),Hr=BigInt(9),ln=BigInt(16);function V(e,t){const r=e%t;return r>=j?r:t+r}function F(e,t,r){let n=e;for(;t-- >j;)n*=n,n%=r;return n}function Bt(e,t){if(e===j)throw new Error("invert: expected non-zero number");if(t<=j)throw new Error("invert: expected positive modulus, got "+t);let r=V(e,t),n=t,i=j,s=U;for(;r!==j;){const c=n/r,a=n%r,l=i-s*c;n=r,r=a,i=s,s=l}if(n!==U)throw new Error("invert: does not exist");return V(i,t)}function ht(e,t,r){if(!e.eql(e.sqr(t),r))throw new Error("Cannot find square root")}function dn(e,t){const r=(e.ORDER+U)/on,n=e.pow(t,r);return ht(e,n,t),n}function Ur(e,t){const r=(e.ORDER-an)/cn,n=e.mul(t,se),i=e.pow(n,r),s=e.mul(t,i),o=e.mul(e.mul(s,se),i),c=e.mul(s,e.sub(o,e.ONE));return ht(e,c,t),c}function jr(e){const t=Ue(e),r=un(e),n=r(t,t.neg(t.ONE)),i=r(t,n),s=r(t,t.neg(n)),o=(e+Cr)/ln;return(c,a)=>{let l=c.pow(a,o),f=c.mul(l,n);const h=c.mul(l,i),g=c.mul(l,s),m=c.eql(c.sqr(f),a),b=c.eql(c.sqr(h),a);l=c.cmov(l,f,m),f=c.cmov(g,h,b);const E=c.eql(c.sqr(f),a),q=c.cmov(l,f,E);return ht(c,q,a),q}}function un(e){if(e<sn)throw new Error("sqrt is not defined for small field");let t=e-U,r=0;for(;t%se===j;)t/=se,r++;let n=se;const i=Ue(e);for(;Ot(i,n)===1;)if(n++>1e3)throw new Error("Cannot find square root: probably non-prime P");if(r===1)return dn;let s=i.pow(n,t);const o=(t+U)/se;return function(a,l){if(a.is0(l))return l;if(Ot(a,l)!==1)throw new Error("Cannot find square root");let f=r,h=a.mul(a.ONE,s),g=a.pow(l,t),m=a.pow(l,o);for(;!a.eql(g,a.ONE);){if(a.is0(g))return a.ZERO;let b=1,E=a.sqr(g);for(;!a.eql(E,a.ONE);)if(b++,E=a.sqr(E),b===f)throw new Error("Cannot find square root");const q=U<<BigInt(f-b-1),L=a.pow(h,q);f=b,h=a.sqr(L),g=a.mul(g,h),m=a.mul(m,L)}return m}}function Dr(e){return e%on===sn?dn:e%cn===an?Ur:e%ln===Hr?jr(e):un(e)}const Mr=["create","isValid","is0","neg","inv","sqrt","sqr","eql","add","sub","mul","pow","div","addN","subN","mulN","sqrN"];function Fr(e){const t={ORDER:"bigint",BYTES:"number",BITS:"number"},r=Mr.reduce((n,i)=>(n[i]="function",n),t);return rn(e,r),e}function Zr(e,t,r){if(r<j)throw new Error("invalid exponent, negatives unsupported");if(r===j)return e.ONE;if(r===U)return t;let n=e.ONE,i=t;for(;r>j;)r&U&&(n=e.mul(n,i)),i=e.sqr(i),r>>=U;return n}function fn(e,t,r=!1){const n=new Array(t.length).fill(r?e.ZERO:void 0),i=t.reduce((o,c,a)=>e.is0(c)?o:(n[a]=o,e.mul(o,c)),e.ONE),s=e.inv(i);return t.reduceRight((o,c,a)=>e.is0(c)?o:(n[a]=e.mul(o,n[a]),e.mul(o,c)),s),n}function Ot(e,t){const r=(e.ORDER-U)/se,n=e.pow(t,r),i=e.eql(n,e.ONE),s=e.eql(n,e.ZERO),o=e.eql(n,e.neg(e.ONE));if(!i&&!s&&!o)throw new Error("invalid Legendre symbol result");return i?1:s?0:-1}function Wr(e,t){t!==void 0&&lt(t);const r=t!==void 0?t:e.toString(2).length,n=Math.ceil(r/8);return{nBitLength:r,nByteLength:n}}class Vr{ORDER;BITS;BYTES;isLE;ZERO=j;ONE=U;_lengths;_sqrt;_mod;constructor(t,r={}){if(t<=j)throw new Error("invalid field: expected ORDER > 0, got "+t);let n;this.isLE=!1,r!=null&&typeof r=="object"&&(typeof r.BITS=="number"&&(n=r.BITS),typeof r.sqrt=="function"&&(this.sqrt=r.sqrt),typeof r.isLE=="boolean"&&(this.isLE=r.isLE),r.allowedLengths&&(this._lengths=r.allowedLengths?.slice()),typeof r.modFromBytes=="boolean"&&(this._mod=r.modFromBytes));const{nBitLength:i,nByteLength:s}=Wr(t,n);if(s>2048)throw new Error("invalid field: expected ORDER of <= 2048 bytes");this.ORDER=t,this.BITS=i,this.BYTES=s,this._sqrt=void 0,Object.preventExtensions(this)}create(t){return V(t,this.ORDER)}isValid(t){if(typeof t!="bigint")throw new Error("invalid field element: expected bigint, got "+typeof t);return j<=t&&t<this.ORDER}is0(t){return t===j}isValidNot0(t){return!this.is0(t)&&this.isValid(t)}isOdd(t){return(t&U)===U}neg(t){return V(-t,this.ORDER)}eql(t,r){return t===r}sqr(t){return V(t*t,this.ORDER)}add(t,r){return V(t+r,this.ORDER)}sub(t,r){return V(t-r,this.ORDER)}mul(t,r){return V(t*r,this.ORDER)}pow(t,r){return Zr(this,t,r)}div(t,r){return V(t*Bt(r,this.ORDER),this.ORDER)}sqrN(t){return t*t}addN(t,r){return t+r}subN(t,r){return t-r}mulN(t,r){return t*r}inv(t){return Bt(t,this.ORDER)}sqrt(t){return this._sqrt||(this._sqrt=Dr(this.ORDER)),this._sqrt(this,t)}toBytes(t){return this.isLE?tn(t,this.BYTES):ft(t,this.BYTES)}fromBytes(t,r=!1){D(t);const{_lengths:n,BYTES:i,isLE:s,ORDER:o,_mod:c}=this;if(n){if(!n.includes(t.length)||t.length>i)throw new Error("Field.fromBytes: expected "+n+" bytes, got "+t.length);const l=new Uint8Array(i);l.set(t,s?0:l.length-t.length),t=l}if(t.length!==i)throw new Error("Field.fromBytes: expected "+i+" bytes, got "+t.length);let a=s?en(t):ut(t);if(c&&(a=V(a,o)),!r&&!this.isValid(a))throw new Error("invalid field element: outside of range 0..ORDER");return a}invertBatch(t){return fn(this,t)}cmov(t,r,n){return n?r:t}}function Ue(e,t={}){return new Vr(e,t)}function hn(e){if(typeof e!="bigint")throw new Error("field order must be bigint");const t=e.toString(2).length;return Math.ceil(t/8)}function Kr(e){const t=hn(e);return t+Math.ceil(t/2)}function zr(e,t,r=!1){D(e);const n=e.length,i=hn(t),s=Kr(t);if(n<16||n<s||n>1024)throw new Error("expected "+s+"-1024 bytes of input, got "+n);const o=r?en(e):ut(e),c=V(o,t-U)+U;return r?tn(c,i):ft(c,i)}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const ue=BigInt(0),oe=BigInt(1);function Ne(e,t){const r=t.negate();return e?r:t}function Tt(e,t){const r=fn(e.Fp,t.map(n=>n.Z));return t.map((n,i)=>e.fromAffine(n.toAffine(r[i])))}function pn(e,t){if(!Number.isSafeInteger(e)||e<=0||e>t)throw new Error("invalid window size, expected [1.."+t+"], got W="+e)}function Ve(e,t){pn(e,t);const r=Math.ceil(t/e)+1,n=2**(e-1),i=2**e,s=nn(e),o=BigInt(e);return{windows:r,windowSize:n,mask:s,maxNumber:i,shiftBy:o}}function qt(e,t,r){const{windowSize:n,mask:i,maxNumber:s,shiftBy:o}=r;let c=Number(e&i),a=e>>o;c>n&&(c-=s,a+=oe);const l=t*n,f=l+Math.abs(c)-1,h=c===0,g=c<0,m=t%2!==0;return{nextN:a,offset:f,isZero:h,isNeg:g,isNegF:m,offsetF:l}}const Ke=new WeakMap,gn=new WeakMap;function ze(e){return gn.get(e)||1}function Nt(e){if(e!==ue)throw new Error("invalid wNAF")}class Yr{BASE;ZERO;Fn;bits;constructor(t,r){this.BASE=t.BASE,this.ZERO=t.ZERO,this.Fn=t.Fn,this.bits=r}_unsafeLadder(t,r,n=this.ZERO){let i=t;for(;r>ue;)r&oe&&(n=n.add(i)),i=i.double(),r>>=oe;return n}precomputeWindow(t,r){const{windows:n,windowSize:i}=Ve(r,this.bits),s=[];let o=t,c=o;for(let a=0;a<n;a++){c=o,s.push(c);for(let l=1;l<i;l++)c=c.add(o),s.push(c);o=c.double()}return s}wNAF(t,r,n){if(!this.Fn.isValid(n))throw new Error("invalid scalar");let i=this.ZERO,s=this.BASE;const o=Ve(t,this.bits);for(let c=0;c<o.windows;c++){const{nextN:a,offset:l,isZero:f,isNeg:h,isNegF:g,offsetF:m}=qt(n,c,o);n=a,f?s=s.add(Ne(g,r[m])):i=i.add(Ne(h,r[l]))}return Nt(n),{p:i,f:s}}wNAFUnsafe(t,r,n,i=this.ZERO){const s=Ve(t,this.bits);for(let o=0;o<s.windows&&n!==ue;o++){const{nextN:c,offset:a,isZero:l,isNeg:f}=qt(n,o,s);if(n=c,!l){const h=r[a];i=i.add(f?h.negate():h)}}return Nt(n),i}getPrecomputes(t,r,n){let i=Ke.get(r);return i||(i=this.precomputeWindow(r,t),t!==1&&(typeof n=="function"&&(i=n(i)),Ke.set(r,i))),i}cached(t,r,n){const i=ze(t);return this.wNAF(i,this.getPrecomputes(i,t,n),r)}unsafe(t,r,n,i){const s=ze(t);return s===1?this._unsafeLadder(t,r,i):this.wNAFUnsafe(s,this.getPrecomputes(s,t,n),r,i)}createCache(t,r){pn(r,this.bits),gn.set(t,r),Ke.delete(t)}hasCache(t){return ze(t)!==1}}function Gr(e,t,r,n){let i=t,s=e.ZERO,o=e.ZERO;for(;r>ue||n>ue;)r&oe&&(s=s.add(i)),n&oe&&(o=o.add(i)),i=i.double(),r>>=oe,n>>=oe;return{p1:s,p2:o}}function Lt(e,t,r){if(t){if(t.ORDER!==e)throw new Error("Field.ORDER must match order: Fp == p, Fn == n");return Fr(t),t}else return Ue(e,{isLE:r})}function Xr(e,t,r={},n){if(n===void 0&&(n=e==="edwards"),!t||typeof t!="object")throw new Error(`expected valid ${e} CURVE object`);for(const a of["p","n","h"]){const l=t[a];if(!(typeof l=="bigint"&&l>ue))throw new Error(`CURVE.${a} must be positive bigint`)}const i=Lt(t.p,r.Fp,n),s=Lt(t.n,r.Fn,n),c=["Gx","Gy","a","b"];for(const a of c)if(!i.isValid(t[a]))throw new Error(`CURVE.${a} must be valid field element of CURVE.Fp`);return t=Object.freeze(Object.assign({},t)),{CURVE:t,Fp:i,Fn:s}}function Jr(e,t){return function(n){const i=e(n);return{secretKey:i,publicKey:t(i)}}}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const Pt=(e,t)=>(e+(e>=0?t:-t)/ei)/t;function Qr(e,t,r){const[[n,i],[s,o]]=t,c=Pt(o*e,r),a=Pt(-i*e,r);let l=e-c*n-a*s,f=-c*i-a*o;const h=l<ge,g=f<ge;h&&(l=-l),g&&(f=-f);const m=nn(Math.ceil(_r(r)/2))+Be;if(l<ge||l>=m||f<ge||f>=m)throw new Error("splitScalar (endomorphism): failed, k="+e);return{k1neg:h,k1:l,k2neg:g,k2:f}}const ge=BigInt(0),Be=BigInt(1),ei=BigInt(2),Ie=BigInt(3),ti=BigInt(4);function ni(e,t={}){const r=Xr("weierstrass",e,t),{Fp:n,Fn:i}=r;let s=r.CURVE;const{h:o,n:c}=s;rn(t,{},{allowInfinityPoint:"boolean",clearCofactor:"function",isTorsionFree:"function",fromBytes:"function",toBytes:"function",endo:"object"});const{endo:a}=t;if(a&&(!n.is0(s.a)||typeof a.beta!="bigint"||!Array.isArray(a.basises)))throw new Error('invalid endo: expected "beta": bigint and "basises": array');const l=ii(n,i);function f(){if(!n.isOdd)throw new Error("compression is not supported: Field does not have .isOdd()")}function h($,p,y){const{x:v,y:x}=p.toAffine(),A=n.toBytes(v);if($t(y,"isCompressed"),y){f();const S=!n.isOdd(x);return Oe(ri(S),A)}else return Oe(Uint8Array.of(4),A,n.toBytes(x))}function g($){D($,void 0,"Point");const{publicKey:p,publicKeyUncompressed:y}=l,v=$.length,x=$[0],A=$.subarray(1);if(v===p&&(x===2||x===3)){const S=n.fromBytes(A);if(!n.isValid(S))throw new Error("bad point: is not on curve, wrong x");const k=E(S);let w;try{w=n.sqrt(k)}catch(M){const P=M instanceof Error?": "+M.message:"";throw new Error("bad point: is not on curve, sqrt error"+P)}f();const R=n.isOdd(w);return(x&1)===1!==R&&(w=n.neg(w)),{x:S,y:w}}else if(v===y&&x===4){const S=n.BYTES,k=n.fromBytes(A.subarray(0,S)),w=n.fromBytes(A.subarray(S,S*2));if(!q(k,w))throw new Error("bad point: is not on curve");return{x:k,y:w}}else throw new Error(`bad point: got length ${v}, expected compressed=${p} or uncompressed=${y}`)}const m=t.toBytes||h,b=t.fromBytes||g;function E($){const p=n.sqr($),y=n.mul(p,$);return n.add(n.add(y,n.mul($,s.a)),s.b)}function q($,p){const y=n.sqr(p),v=E($);return n.eql(y,v)}if(!q(s.Gx,s.Gy))throw new Error("bad curve params: generator point");const L=n.mul(n.pow(s.a,Ie),ti),K=n.mul(n.sqr(s.b),BigInt(27));if(n.is0(n.add(L,K)))throw new Error("bad curve params: a or b");function Q($,p,y=!1){if(!n.isValid(p)||y&&n.is0(p))throw new Error(`bad point coordinate ${$}`);return p}function ve($){if(!($ instanceof O))throw new Error("Weierstrass Point expected")}function Ee($){if(!a||!a.basises)throw new Error("no endo");return Qr($,a.basises,i.ORDER)}const xe=At(($,p)=>{const{X:y,Y:v,Z:x}=$;if(n.eql(x,n.ONE))return{x:y,y:v};const A=$.is0();p==null&&(p=A?n.ONE:n.inv(x));const S=n.mul(y,p),k=n.mul(v,p),w=n.mul(x,p);if(A)return{x:n.ZERO,y:n.ZERO};if(!n.eql(w,n.ONE))throw new Error("invZ was invalid");return{x:S,y:k}}),kn=At($=>{if($.is0()){if(t.allowInfinityPoint&&!n.is0($.Y))return;throw new Error("bad point: ZERO")}const{x:p,y}=$.toAffine();if(!n.isValid(p)||!n.isValid(y))throw new Error("bad point: x or y not field elements");if(!q(p,y))throw new Error("bad point: equation left != right");if(!$.isTorsionFree())throw new Error("bad point: not in prime-order subgroup");return!0});function mt($,p,y,v,x){return y=new O(n.mul(y.X,$),y.Y,y.Z),p=Ne(v,p),y=Ne(x,y),p.add(y)}class O{static BASE=new O(s.Gx,s.Gy,n.ONE);static ZERO=new O(n.ZERO,n.ONE,n.ZERO);static Fp=n;static Fn=i;X;Y;Z;constructor(p,y,v){this.X=Q("x",p),this.Y=Q("y",y,!0),this.Z=Q("z",v),Object.freeze(this)}static CURVE(){return s}static fromAffine(p){const{x:y,y:v}=p||{};if(!p||!n.isValid(y)||!n.isValid(v))throw new Error("invalid affine point");if(p instanceof O)throw new Error("projective point not allowed");return n.is0(y)&&n.is0(v)?O.ZERO:new O(y,v,n.ONE)}static fromBytes(p){const y=O.fromAffine(b(D(p,void 0,"point")));return y.assertValidity(),y}static fromHex(p){return O.fromBytes(X(p))}get x(){return this.toAffine().x}get y(){return this.toAffine().y}precompute(p=8,y=!0){return he.createCache(this,p),y||this.multiply(Ie),this}assertValidity(){kn(this)}hasEvenY(){const{y:p}=this.toAffine();if(!n.isOdd)throw new Error("Field doesn't support isOdd");return!n.isOdd(p)}equals(p){ve(p);const{X:y,Y:v,Z:x}=this,{X:A,Y:S,Z:k}=p,w=n.eql(n.mul(y,k),n.mul(A,x)),R=n.eql(n.mul(v,k),n.mul(S,x));return w&&R}negate(){return new O(this.X,n.neg(this.Y),this.Z)}double(){const{a:p,b:y}=s,v=n.mul(y,Ie),{X:x,Y:A,Z:S}=this;let k=n.ZERO,w=n.ZERO,R=n.ZERO,I=n.mul(x,x),M=n.mul(A,A),P=n.mul(S,S),B=n.mul(x,A);return B=n.add(B,B),R=n.mul(x,S),R=n.add(R,R),k=n.mul(p,R),w=n.mul(v,P),w=n.add(k,w),k=n.sub(M,w),w=n.add(M,w),w=n.mul(k,w),k=n.mul(B,k),R=n.mul(v,R),P=n.mul(p,P),B=n.sub(I,P),B=n.mul(p,B),B=n.add(B,R),R=n.add(I,I),I=n.add(R,I),I=n.add(I,P),I=n.mul(I,B),w=n.add(w,I),P=n.mul(A,S),P=n.add(P,P),I=n.mul(P,B),k=n.sub(k,I),R=n.mul(P,M),R=n.add(R,R),R=n.add(R,R),new O(k,w,R)}add(p){ve(p);const{X:y,Y:v,Z:x}=this,{X:A,Y:S,Z:k}=p;let w=n.ZERO,R=n.ZERO,I=n.ZERO;const M=s.a,P=n.mul(s.b,Ie);let B=n.mul(y,A),Z=n.mul(v,S),W=n.mul(x,k),ae=n.add(y,v),H=n.add(A,S);ae=n.mul(ae,H),H=n.add(B,Z),ae=n.sub(ae,H),H=n.add(y,x);let z=n.add(A,k);return H=n.mul(H,z),z=n.add(B,W),H=n.sub(H,z),z=n.add(v,x),w=n.add(S,k),z=n.mul(z,w),w=n.add(Z,W),z=n.sub(z,w),I=n.mul(M,H),w=n.mul(P,W),I=n.add(w,I),w=n.sub(Z,I),I=n.add(Z,I),R=n.mul(w,I),Z=n.add(B,B),Z=n.add(Z,B),W=n.mul(M,W),H=n.mul(P,H),Z=n.add(Z,W),W=n.sub(B,W),W=n.mul(M,W),H=n.add(H,W),B=n.mul(Z,H),R=n.add(R,B),B=n.mul(z,H),w=n.mul(ae,w),w=n.sub(w,B),B=n.mul(ae,Z),I=n.mul(z,I),I=n.add(I,B),new O(w,R,I)}subtract(p){return this.add(p.negate())}is0(){return this.equals(O.ZERO)}multiply(p){const{endo:y}=t;if(!i.isValidNot0(p))throw new Error("invalid scalar: out of range");let v,x;const A=S=>he.cached(this,S,k=>Tt(O,k));if(y){const{k1neg:S,k1:k,k2neg:w,k2:R}=Ee(p),{p:I,f:M}=A(k),{p:P,f:B}=A(R);x=M.add(B),v=mt(y.beta,I,P,S,w)}else{const{p:S,f:k}=A(p);v=S,x=k}return Tt(O,[v,x])[0]}multiplyUnsafe(p){const{endo:y}=t,v=this;if(!i.isValid(p))throw new Error("invalid scalar: out of range");if(p===ge||v.is0())return O.ZERO;if(p===Be)return v;if(he.hasCache(this))return this.multiply(p);if(y){const{k1neg:x,k1:A,k2neg:S,k2:k}=Ee(p),{p1:w,p2:R}=Gr(O,v,A,k);return mt(y.beta,w,R,x,S)}else return he.unsafe(v,p)}toAffine(p){return xe(this,p)}isTorsionFree(){const{isTorsionFree:p}=t;return o===Be?!0:p?p(O,this):he.unsafe(this,c).is0()}clearCofactor(){const{clearCofactor:p}=t;return o===Be?this:p?p(O,this):this.multiplyUnsafe(o)}isSmallOrder(){return this.multiplyUnsafe(o).is0()}toBytes(p=!0){return $t(p,"isCompressed"),this.assertValidity(),m(O,this,p)}toHex(p=!0){return _(this.toBytes(p))}toString(){return`<Point ${this.is0()?"ZERO":this.toHex()}>`}}const yt=i.BITS,he=new Yr(O,t.endo?Math.ceil(yt/2):yt);return O.BASE.precompute(8),O}function ri(e){return Uint8Array.of(e?2:3)}function ii(e,t){return{secretKey:t.BYTES,publicKey:1+e.BYTES,publicKeyUncompressed:1+2*e.BYTES,publicKeyHasPrefix:!0,signature:2*t.BYTES}}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const je={p:BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"),n:BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),h:BigInt(1),a:BigInt(0),b:BigInt(7),Gx:BigInt("0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"),Gy:BigInt("0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8")},si={beta:BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"),basises:[[BigInt("0x3086d221a7d46bcde86c90e49284eb15"),-BigInt("0xe4437ed6010e88286f547fa90abfe4c3")],[BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8"),BigInt("0x3086d221a7d46bcde86c90e49284eb15")]]},oi=BigInt(0),it=BigInt(2);function ai(e){const t=je.p,r=BigInt(3),n=BigInt(6),i=BigInt(11),s=BigInt(22),o=BigInt(23),c=BigInt(44),a=BigInt(88),l=e*e*e%t,f=l*l*e%t,h=F(f,r,t)*f%t,g=F(h,r,t)*f%t,m=F(g,it,t)*l%t,b=F(m,i,t)*m%t,E=F(b,s,t)*b%t,q=F(E,c,t)*E%t,L=F(q,a,t)*q%t,K=F(L,c,t)*E%t,Q=F(K,r,t)*f%t,ve=F(Q,o,t)*b%t,Ee=F(ve,n,t)*l%t,xe=F(Ee,it,t);if(!Le.eql(Le.sqr(xe),e))throw new Error("Cannot find square root");return xe}const Le=Ue(je.p,{sqrt:ai}),fe=ni(je,{Fp:Le,endo:si}),_t={};function Pe(e,...t){let r=_t[e];if(r===void 0){const n=qe(Lr(e));r=Oe(n,n),_t[e]=r}return qe(Oe(r,...t))}const pt=e=>e.toBytes(!0).slice(1),gt=e=>e%it===oi;function st(e){const{Fn:t,BASE:r}=fe,n=t.fromBytes(e),i=r.multiply(n);return{scalar:gt(i.y)?n:t.neg(n),bytes:pt(i)}}function mn(e){const t=Le;if(!t.isValidNot0(e))throw new Error("invalid x: Fail if x ≥ p");const r=t.create(e*e),n=t.create(r*e+BigInt(7));let i=t.sqrt(n);gt(i)||(i=t.neg(i));const s=fe.fromAffine({x:e,y:i});return s.assertValidity(),s}const ye=ut;function yn(...e){return fe.Fn.create(ye(Pe("BIP0340/challenge",...e)))}function Ct(e){return st(e).bytes}function ci(e,t,r=Vt(32)){const{Fn:n}=fe,i=D(e,void 0,"message"),{bytes:s,scalar:o}=st(t),c=D(r,32,"auxRand"),a=n.toBytes(o^ye(Pe("BIP0340/aux",c))),l=Pe("BIP0340/nonce",a,s,i),{bytes:f,scalar:h}=st(l),g=yn(f,s,i),m=new Uint8Array(64);if(m.set(f,0),m.set(n.toBytes(n.create(h+g*o)),32),!bn(m,i,s))throw new Error("sign: Invalid signature produced");return m}function bn(e,t,r){const{Fp:n,Fn:i,BASE:s}=fe,o=D(e,64,"signature"),c=D(t,void 0,"message"),a=D(r,32,"publicKey");try{const l=mn(ye(a)),f=ye(o.subarray(0,32));if(!n.isValidNot0(f))return!1;const h=ye(o.subarray(32,64));if(!i.isValidNot0(h))return!1;const g=yn(i.toBytes(f),pt(l),c),m=s.multiplyUnsafe(h).add(l.multiplyUnsafe(i.neg(g))),{x:b,y:E}=m.toAffine();return!(m.is0()||!gt(E)||b!==f)}catch{return!1}}const G=(()=>{const r=(n=Vt(48))=>zr(n,je.n);return{keygen:Jr(r,Ct),getPublicKey:Ct,sign:ci,verify:bn,Point:fe,utils:{randomSecretKey:r,taggedHash:Pe,lift_x:mn,pointToBytes:pt},lengths:{secretKey:32,publicKey:32,publicKeyHasPrefix:!1,signature:64,seed:48}}})();var ie=Symbol("verified"),li=e=>e instanceof Object;function di(e){if(!li(e)||typeof e.kind!="number"||typeof e.content!="string"||typeof e.created_at!="number"||typeof e.pubkey!="string"||!e.pubkey.match(/^[a-f0-9]{64}$/)||!Array.isArray(e.tags))return!1;for(let t=0;t<e.tags.length;t++){let r=e.tags[t];if(!Array.isArray(r))return!1;for(let n=0;n<r.length;n++)if(typeof r[n]!="string")return!1}return!0}new TextDecoder("utf-8");var ui=new TextEncoder;function me(e){try{e.indexOf("://")===-1&&(e="wss://"+e);let t=new URL(e);return t.protocol==="http:"?t.protocol="ws:":t.protocol==="https:"&&(t.protocol="wss:"),t.pathname=t.pathname.replace(/\/+/g,"/"),t.pathname.endsWith("/")&&(t.pathname=t.pathname.slice(0,-1)),(t.port==="80"&&t.protocol==="ws:"||t.port==="443"&&t.protocol==="wss:")&&(t.port=""),t.searchParams.sort(),t.hash="",t.toString()}catch{throw new Error(`Invalid URL: ${e}`)}}var fi=class{generateSecretKey(){return G.utils.randomSecretKey()}getPublicKey(t){return _(G.getPublicKey(t))}finalizeEvent(t,r){const n=t;return n.pubkey=_(G.getPublicKey(r)),n.id=Ye(n),n.sig=_(G.sign(X(Ye(n)),r)),n[ie]=!0,n}verifyEvent(t){if(typeof t[ie]=="boolean")return t[ie];try{const r=Ye(t);if(r!==t.id)return t[ie]=!1,!1;const n=G.verify(X(t.sig),X(r),X(t.pubkey));return t[ie]=n,n}catch{return t[ie]=!1,!1}}};function hi(e){if(!di(e))throw new Error("can't serialize event with wrong or missing properties");return JSON.stringify([0,e.pubkey,e.created_at,e.kind,e.tags,e.content])}function Ye(e){let t=qe(ui.encode(hi(e)));return _(t)}var De=new fi;De.generateSecretKey;De.getPublicKey;De.finalizeEvent;var pi=De.verifyEvent,gi=22242;function mi(e,t){if(e.ids&&e.ids.indexOf(t.id)===-1||e.kinds&&e.kinds.indexOf(t.kind)===-1||e.authors&&e.authors.indexOf(t.pubkey)===-1)return!1;for(let r in e)if(r[0]==="#"){let n=r.slice(1),i=e[`#${n}`];if(i&&!t.tags.find(([s,o])=>s===r.slice(1)&&i.indexOf(o)!==-1))return!1}return!(e.since&&t.created_at<e.since||e.until&&t.created_at>e.until)}function yi(e,t){for(let r=0;r<e.length;r++)if(mi(e[r],t))return!0;return!1}function bi(e,t){let r=t.length+3,n=e.indexOf(`"${t}":`)+r,i=e.slice(n).indexOf('"')+n+1;return e.slice(i,i+64)}function wi(e){let t=e.slice(0,22).indexOf('"EVENT"');if(t===-1)return null;let r=e.slice(t+7+1).indexOf('"');if(r===-1)return null;let n=t+7+1+r,i=e.slice(n+1,80).indexOf('"');if(i===-1)return null;let s=n+1+i;return e.slice(n+1,s)}function vi(e,t){return{kind:gi,created_at:Math.floor(Date.now()/1e3),tags:[["relay",e],["challenge",t]],content:""}}var wn=class extends Error{constructor(e,t){super(`Tried to send message '${e} on a closed connection to ${t}.`),this.name="SendingOnClosedConnection"}},vn=class{url;_connected=!1;onclose=null;onnotice=e=>console.debug(`NOTICE from ${this.url}: ${e}`);onauth;baseEoseTimeout=4400;publishTimeout=4400;pingFrequency=29e3;pingTimeout=2e4;resubscribeBackoff=[1e4,1e4,1e4,2e4,2e4,3e4,6e4];openSubs=new Map;enablePing;enableReconnect;idleSince=Date.now();ongoingOperations=0;reconnectTimeoutHandle;pingIntervalHandle;reconnectAttempts=0;skipReconnection=!1;connectionPromise;openCountRequests=new Map;openEventPublishes=new Map;ws;challenge;authPromise;serial=0;verifyEvent;_WebSocket;constructor(e,t){this.url=me(e),this.verifyEvent=t.verifyEvent,this._WebSocket=t.websocketImplementation||WebSocket,this.enablePing=t.enablePing,this.enableReconnect=t.enableReconnect||!1}static async connect(e,t){const r=new vn(e,t);return await r.connect(t),r}closeAllSubscriptions(e){for(let[t,r]of this.openSubs)r.close(e);this.openSubs.clear();for(let[t,r]of this.openEventPublishes)r.reject(new Error(e));this.openEventPublishes.clear();for(let[t,r]of this.openCountRequests)r.reject(new Error(e));this.openCountRequests.clear()}get connected(){return this._connected}async reconnect(){const e=this.resubscribeBackoff[Math.min(this.reconnectAttempts,this.resubscribeBackoff.length-1)];this.reconnectAttempts++,this.reconnectTimeoutHandle=setTimeout(async()=>{try{await this.connect()}catch{}},e)}handleHardClose(e){this.pingIntervalHandle&&(clearInterval(this.pingIntervalHandle),this.pingIntervalHandle=void 0),this._connected=!1,this.connectionPromise=void 0,this.idleSince=void 0,this.enableReconnect&&!this.skipReconnection?this.reconnect():(this.onclose?.(),this.closeAllSubscriptions(e))}async connect(e){let t;return this.connectionPromise?this.connectionPromise:(this.challenge=void 0,this.authPromise=void 0,this.skipReconnection=!1,this.connectionPromise=new Promise((r,n)=>{e?.timeout&&(t=setTimeout(()=>{n("connection timed out"),this.connectionPromise=void 0,this.skipReconnection=!0,this.onclose?.(),this.handleHardClose("relay connection timed out")},e.timeout)),e?.abort&&(e.abort.onabort=n);try{this.ws=new this._WebSocket(this.url)}catch(i){clearTimeout(t),n(i);return}this.ws.onopen=()=>{this.reconnectTimeoutHandle&&(clearTimeout(this.reconnectTimeoutHandle),this.reconnectTimeoutHandle=void 0),clearTimeout(t),this._connected=!0;const i=this.reconnectAttempts>0;this.reconnectAttempts=0;for(const s of this.openSubs.values()){if(s.eosed=!1,i)for(let o=0;o<s.filters.length;o++)s.lastEmitted&&(s.filters[o].since=s.lastEmitted+1);s.fire()}this.enablePing&&(this.pingIntervalHandle=setInterval(()=>this.pingpong(),this.pingFrequency)),r()},this.ws.onerror=()=>{clearTimeout(t),n("connection failed"),this.connectionPromise=void 0,this.skipReconnection=!0,this.onclose?.(),this.handleHardClose("relay connection failed")},this.ws.onclose=i=>{clearTimeout(t),n(i.message||"websocket closed"),this.handleHardClose("relay connection closed")},this.ws.onmessage=this._onmessage.bind(this)}),this.connectionPromise)}waitForPingPong(){return new Promise(e=>{this.ws.once("pong",()=>e(!0)),this.ws.ping()})}waitForDummyReq(){return new Promise((e,t)=>{if(!this.connectionPromise)return t(new Error(`no connection to ${this.url}, can't ping`));try{const r=this.subscribe([{ids:["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"],limit:0}],{label:"<forced-ping>",oneose:()=>{e(!0),r.close()},onclose(){e(!0)},eoseTimeout:this.pingTimeout+1e3})}catch(r){t(r)}})}async pingpong(){this.ws?.readyState===1&&(await Promise.any([this.ws&&this.ws.ping&&this.ws.once?this.waitForPingPong():this.waitForDummyReq(),new Promise(t=>setTimeout(()=>t(!1),this.pingTimeout))])||this.ws?.readyState===this._WebSocket.OPEN&&this.ws?.close())}async send(e){if(!this.connectionPromise)throw new wn(e,this.url);this.connectionPromise.then(()=>{this.ws?.send(e)})}async auth(e){const t=this.challenge;if(!t)throw new Error("can't perform auth, no challenge was received");return this.authPromise?this.authPromise:(this.authPromise=new Promise(async(r,n)=>{try{let i=await e(vi(this.url,t)),s=setTimeout(()=>{let o=this.openEventPublishes.get(i.id);o&&(o.reject(new Error("auth timed out")),this.openEventPublishes.delete(i.id))},this.publishTimeout);this.openEventPublishes.set(i.id,{resolve:r,reject:n,timeout:s}),this.send('["AUTH",'+JSON.stringify(i)+"]")}catch(i){console.warn("subscribe auth function failed:",i)}}),this.authPromise)}async publish(e){this.idleSince=void 0,this.ongoingOperations++;const t=new Promise((r,n)=>{const i=setTimeout(()=>{const s=this.openEventPublishes.get(e.id);s&&(s.reject(new Error("publish timed out")),this.openEventPublishes.delete(e.id))},this.publishTimeout);this.openEventPublishes.set(e.id,{resolve:r,reject:n,timeout:i})});return this.send('["EVENT",'+JSON.stringify(e)+"]"),this.ongoingOperations--,this.ongoingOperations===0&&(this.idleSince=Date.now()),t}async count(e,t){this.serial++;const r=t?.id||"count:"+this.serial,n=new Promise((i,s)=>{this.openCountRequests.set(r,{resolve:i,reject:s})});return this.send('["COUNT","'+r+'",'+JSON.stringify(e).substring(1)),n}subscribe(e,t){t.label!=="<forced-ping>"&&(this.idleSince=void 0,this.ongoingOperations++);const r=this.prepareSubscription(e,t);return r.fire(),t.abort&&(t.abort.onabort=()=>r.close(String(t.abort.reason||"<aborted>"))),r}prepareSubscription(e,t){this.serial++;const r=t.id||(t.label?t.label+":":"sub:")+this.serial,n=new Ei(this,r,e,t);return this.openSubs.set(r,n),n}close(){this.skipReconnection=!0,this.reconnectTimeoutHandle&&(clearTimeout(this.reconnectTimeoutHandle),this.reconnectTimeoutHandle=void 0),this.pingIntervalHandle&&(clearInterval(this.pingIntervalHandle),this.pingIntervalHandle=void 0),this.closeAllSubscriptions("relay connection closed by us"),this._connected=!1,this.idleSince=void 0,this.onclose?.(),this.ws?.readyState===this._WebSocket.OPEN&&this.ws?.close()}_onmessage(e){const t=e.data;if(!t)return;const r=wi(t);if(r){const n=this.openSubs.get(r);if(!n)return;const i=bi(t,"id"),s=n.alreadyHaveEvent?.(i);if(n.receivedEvent?.(this,i),s)return}try{let n=JSON.parse(t);switch(n[0]){case"EVENT":{const i=this.openSubs.get(n[1]),s=n[2];this.verifyEvent(s)&&yi(i.filters,s)?i.onevent(s):i.oninvalidevent?.(s),(!i.lastEmitted||i.lastEmitted<s.created_at)&&(i.lastEmitted=s.created_at);return}case"COUNT":{const i=n[1],s=n[2],o=this.openCountRequests.get(i);o&&(o.resolve(s.count),this.openCountRequests.delete(i));return}case"EOSE":{const i=this.openSubs.get(n[1]);if(!i)return;i.receivedEose();return}case"OK":{const i=n[1],s=n[2],o=n[3],c=this.openEventPublishes.get(i);c&&(clearTimeout(c.timeout),s?c.resolve(o):c.reject(new Error(o)),this.openEventPublishes.delete(i));return}case"CLOSED":{const i=n[1],s=this.openSubs.get(i);if(!s)return;s.closed=!0,s.close(n[2]);return}case"NOTICE":{this.onnotice(n[1]);return}case"AUTH":{this.challenge=n[1],this.onauth&&this.auth(this.onauth);return}default:{this.openSubs.get(n[1])?.oncustom?.(n);return}}}catch(n){try{const[i,s,o]=JSON.parse(t);console.warn(`[nostr] relay ${this.url} error processing message:`,n,o)}catch{console.warn(`[nostr] relay ${this.url} error processing message:`,n)}return}}},Ei=class{relay;id;lastEmitted;closed=!1;eosed=!1;filters;alreadyHaveEvent;receivedEvent;onevent;oninvalidevent;oneose;onclose;oncustom;eoseTimeout;eoseTimeoutHandle;constructor(e,t,r,n){if(r.length===0)throw new Error("subscription can't be created with zero filters");this.relay=e,this.filters=r,this.id=t,this.alreadyHaveEvent=n.alreadyHaveEvent,this.receivedEvent=n.receivedEvent,this.eoseTimeout=n.eoseTimeout||e.baseEoseTimeout,this.oneose=n.oneose,this.onclose=n.onclose,this.oninvalidevent=n.oninvalidevent,this.onevent=n.onevent||(i=>{console.warn(`onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`,i)})}fire(){this.relay.send('["REQ","'+this.id+'",'+JSON.stringify(this.filters).substring(1)),this.eoseTimeoutHandle=setTimeout(this.receivedEose.bind(this),this.eoseTimeout)}receivedEose(){this.eosed||(clearTimeout(this.eoseTimeoutHandle),this.eosed=!0,this.oneose?.())}close(e="closed by caller"){if(!this.closed&&this.relay.connected){try{this.relay.send('["CLOSE",'+JSON.stringify(this.id)+"]")}catch(t){if(!(t instanceof wn))throw t}this.closed=!0}this.relay.openSubs.delete(this.id),this.relay.ongoingOperations--,this.relay.ongoingOperations===0&&(this.relay.idleSince=Date.now()),this.onclose?.(e)}},xi=e=>(e[ie]=!0,!0),ki=class{relays=new Map;seenOn=new Map;trackRelays=!1;verifyEvent;enablePing;enableReconnect;automaticallyAuth;trustedRelayURLs=new Set;onRelayConnectionFailure;onRelayConnectionSuccess;allowConnectingToRelay;maxWaitForConnection;_WebSocket;constructor(e){this.verifyEvent=e.verifyEvent,this._WebSocket=e.websocketImplementation,this.enablePing=e.enablePing,this.enableReconnect=e.enableReconnect||!1,this.automaticallyAuth=e.automaticallyAuth,this.onRelayConnectionFailure=e.onRelayConnectionFailure,this.onRelayConnectionSuccess=e.onRelayConnectionSuccess,this.allowConnectingToRelay=e.allowConnectingToRelay,this.maxWaitForConnection=e.maxWaitForConnection||3e3}async ensureRelay(e,t){e=me(e);let r=this.relays.get(e);if(r||(r=new vn(e,{verifyEvent:this.trustedRelayURLs.has(e)?xi:this.verifyEvent,websocketImplementation:this._WebSocket,enablePing:this.enablePing,enableReconnect:this.enableReconnect}),r.onclose=()=>{this.relays.delete(e)},this.relays.set(e,r)),this.automaticallyAuth){const n=this.automaticallyAuth(e);n&&(r.onauth=n)}try{await r.connect({timeout:t?.connectionTimeout,abort:t?.abort})}catch(n){throw this.relays.delete(e),n}return r}close(e){e.map(me).forEach(t=>{this.relays.get(t)?.close(),this.relays.delete(t)})}subscribe(e,t,r){const n=[],i=[];for(let s=0;s<e.length;s++){const o=me(e[s]);n.find(c=>c.url===o)||i.indexOf(o)===-1&&(i.push(o),n.push({url:o,filter:t}))}return this.subscribeMap(n,r)}subscribeMany(e,t,r){return this.subscribe(e,t,r)}subscribeMap(e,t){const r=new Map;for(const g of e){const{url:m,filter:b}=g;r.has(m)||r.set(m,[]),r.get(m).push(b)}const n=Array.from(r.entries()).map(([g,m])=>({url:g,filters:m}));this.trackRelays&&(t.receivedEvent=(g,m)=>{let b=this.seenOn.get(m);b||(b=new Set,this.seenOn.set(m,b)),b.add(g)});const i=new Set,s=[],o=[];let c=g=>{o[g]||(o[g]=!0,o.filter(m=>m).length===n.length&&(t.oneose?.(),c=()=>{}))};const a=[];let l=(g,m)=>{a[g]||(c(g),a[g]=m,a.filter(b=>b).length===n.length&&(t.onclose?.(a),l=()=>{}))};const f=g=>{if(t.alreadyHaveEvent?.(g))return!0;const m=i.has(g);return i.add(g),m},h=Promise.all(n.map(async({url:g,filters:m},b)=>{if(this.allowConnectingToRelay?.(g,["read",m])===!1){l(b,"connection skipped by allowConnectingToRelay");return}let E;try{E=await this.ensureRelay(g,{connectionTimeout:this.maxWaitForConnection<(t.maxWait||0)?Math.max(t.maxWait*.8,t.maxWait-1e3):this.maxWaitForConnection,abort:t.abort})}catch(L){this.onRelayConnectionFailure?.(g),l(b,L?.message||String(L));return}this.onRelayConnectionSuccess?.(g);let q=E.subscribe(m,{...t,oneose:()=>c(b),onclose:L=>{L.startsWith("auth-required: ")&&t.onauth?E.auth(t.onauth).then(()=>{E.subscribe(m,{...t,oneose:()=>c(b),onclose:K=>{l(b,K)},alreadyHaveEvent:f,eoseTimeout:t.maxWait,abort:t.abort})}).catch(K=>{l(b,`auth was required and attempted, but failed with: ${K}`)}):l(b,L)},alreadyHaveEvent:f,eoseTimeout:t.maxWait,abort:t.abort});s.push(q)}));return{async close(g){await h,s.forEach(m=>{m.close(g)})}}}subscribeEose(e,t,r){let n;return n=this.subscribe(e,t,{...r,oneose(){const i="closed automatically on eose";n?n.close(i):r.onclose?.(e.map(s=>i))}}),n}subscribeManyEose(e,t,r){return this.subscribeEose(e,t,r)}async querySync(e,t,r){return new Promise(async n=>{const i=[];this.subscribeEose(e,t,{...r,onevent(s){i.push(s)},onclose(s){n(i)}})})}async get(e,t,r){t.limit=1;const n=await this.querySync(e,t,r);return n.sort((i,s)=>s.created_at-i.created_at),n[0]||null}publish(e,t,r){return e.map(me).map(async(n,i,s)=>{if(s.indexOf(n)!==i)return Promise.reject("duplicate url");if(this.allowConnectingToRelay?.(n,["write",t])===!1)return Promise.reject("connection skipped by allowConnectingToRelay");let o;try{o=await this.ensureRelay(n,{connectionTimeout:this.maxWaitForConnection<(r?.maxWait||0)?Math.max(r.maxWait*.8,r.maxWait-1e3):this.maxWaitForConnection,abort:r?.abort})}catch(c){return this.onRelayConnectionFailure?.(n),"connection failure: "+String(c)}return o.publish(t).catch(async c=>{if(c instanceof Error&&c.message.startsWith("auth-required: ")&&r?.onauth)return await o.auth(r.onauth),o.publish(t);throw c}).then(c=>{if(this.trackRelays){let a=this.seenOn.get(t.id);a||(a=new Set,this.seenOn.set(t.id,a)),a.add(o)}return c})})}listConnectionStatus(){const e=new Map;return this.relays.forEach((t,r)=>e.set(r,t.connected)),e}destroy(){this.relays.forEach(e=>e.close()),this.relays=new Map}pruneIdleRelays(e=1e4){const t=[];for(const[r,n]of this.relays)n.idleSince&&Date.now()-n.idleSince>=e&&(this.relays.delete(r),t.push(r),n.close());return t}},En;try{En=WebSocket}catch{}var Ri=class extends ki{constructor(e){super({verifyEvent:pi,websocketImplementation:En,maxWaitForConnection:3e3,...e})}},ce=Symbol("verified"),Si=e=>e instanceof Object;function Ii(e){if(!Si(e)||typeof e.kind!="number"||typeof e.content!="string"||typeof e.created_at!="number"||typeof e.pubkey!="string"||!e.pubkey.match(/^[a-f0-9]{64}$/)||!Array.isArray(e.tags))return!1;for(let t=0;t<e.tags.length;t++){let r=e.tags[t];if(!Array.isArray(r))return!1;for(let n=0;n<r.length;n++)if(typeof r[n]!="string")return!1}return!0}new TextDecoder("utf-8");var $i=new TextEncoder,Ai=class{generateSecretKey(){return G.utils.randomSecretKey()}getPublicKey(e){return _(G.getPublicKey(e))}finalizeEvent(e,t){const r=e;return r.pubkey=_(G.getPublicKey(t)),r.id=Ge(r),r.sig=_(G.sign(X(Ge(r)),t)),r[ce]=!0,r}verifyEvent(e){if(typeof e[ce]=="boolean")return e[ce];try{const t=Ge(e);if(t!==e.id)return e[ce]=!1,!1;const r=G.verify(X(e.sig),X(t),X(e.pubkey));return e[ce]=r,r}catch{return e[ce]=!1,!1}}};function Bi(e){if(!Ii(e))throw new Error("can't serialize event with wrong or missing properties");return JSON.stringify([0,e.pubkey,e.created_at,e.kind,e.tags,e.content])}function Ge(e){let t=qe($i.encode(Bi(e)));return _(t)}var Me=new Ai;Me.generateSecretKey;Me.getPublicKey;Me.finalizeEvent;var Oi=Me.verifyEvent;const Ti=8e3;function qi(e){return typeof e=="number"&&ct.includes(e)}function Ni(e){try{const t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function Li(e){const t=[];for(const r of e??[])try{const n=new URL(r);if(n.protocol!=="ws:"&&n.protocol!=="wss:")continue;t.push(n.href)}catch{}return[...new Set(t)]}function Pi(e){const t=Rr(e.trim());if(t.type!=="nevent"&&t.type!=="naddr")throw new Error("Enter a NIP-19 nevent or naddr for a NIP-5D napplet manifest event");const r=Li(t.data.relays);if(r.length===0)throw new Error("The pointer does not include relay hints; include at least one relay in the nevent/naddr");if(t.type==="nevent"){if(t.data.kind!==void 0&&!qi(t.data.kind))throw new Error(`nevent points at kind ${t.data.kind}, not a NIP-5D napplet manifest kind`);return{type:"nevent",relays:r,filter:{ids:[t.data.id],kinds:t.data.kind===void 0?[...ct]:[t.data.kind],authors:t.data.author?[t.data.author]:void 0,limit:1}}}if(t.data.kind!==de)throw new Error(`naddr kind ${t.data.kind} is not the named napplet kind ${de}`);return{type:"naddr",relays:r,filter:{kinds:[de],authors:[t.data.pubkey],"#d":[t.data.identifier],limit:1}}}function _i(e){return{id:e.id,pubkey:e.pubkey,kind:e.kind,tags:e.tags,content:e.content}}async function Ci(e){const t=typeof e=="string"?new TextEncoder().encode(e):e,r=new Uint8Array(t.byteLength);r.set(t);const n=await crypto.subtle.digest("SHA-256",r.buffer);return[...new Uint8Array(n)].map(i=>i.toString(16).padStart(2,"0")).join("")}function Hi(e){const t=[];for(const r of e.tags)if(!(r[0]!=="server"||!r[1]))try{const n=new URL(r[1]);(n.protocol==="http:"||n.protocol==="https:")&&t.push(n.href)}catch{}return[...new Set(t)]}function Ui(e,t){const r=e.endsWith("/")?e:`${e}/`;return new URL(t,r).href}async function ji(e,t=fetch){const r=He(e);if(!r.ok)throw new Error(r.errors.map(o=>o.message).join("; "));const n=e.tags.find(o=>o[0]==="x")[1],i=Hi(e);if(i.length===0)throw new Error("Manifest does not include any usable Blossom server hints");const s=[];for(const o of i){const c=Ui(o,n);try{const a=await t(c,{mode:"cors"});if(!a.ok){s.push(`${c}: HTTP ${a.status}`);continue}const l=new Uint8Array(await a.arrayBuffer()),f=await Ci(l);if(f!==n){s.push(`${c}: sha256 ${f} did not match manifest ${n}`);continue}return new TextDecoder().decode(l)}catch(a){s.push(`${c}: ${a instanceof Error?a.message:String(a)}`)}}throw new Error(`Unable to fetch verified /index.html from Blossom servers: ${s.join("; ")}`)}async function Di(e,t){try{const n=await(await t(e,{mode:"cors"})).text();return{source:"url",input:e,label:e,bootUrl:e,html:n,fetched:!0,manifestEvent:null}}catch{return{source:"url",input:e,label:e,bootUrl:e,html:"",fetched:!1,manifestEvent:null}}}async function Mi(e,t){const r=Pi(e),n=!t.pool,i=t.pool??new Ri;try{const s=await i.get(r.relays,{...r.filter},{maxWait:t.maxRelayWaitMs??Ti});if(!s)throw new Error("No matching napplet manifest event was found on the pointer relay hints");if(!Oi(s))throw new Error("Resolved manifest event signature is invalid");const o=_i(s),c=He(o);if(!c.ok)throw new Error(`Resolved event is not a valid NIP-5D napplet manifest: ${c.errors[0]?.message}`);const a=await ji(o,t.fetcher??fetch),l=(t.createObjectUrl??URL.createObjectURL)(new Blob([a],{type:"text/html;charset=utf-8"})),f=()=>(t.revokeObjectUrl??URL.revokeObjectURL)(l);return{source:"nostr",input:e,label:o.id??e,bootUrl:l,html:a,fetched:!0,manifestEvent:o,revoke:f}}finally{n&&i.destroy()}}async function Fi(e,t={}){const r=e.trim();if(!r)throw new Error("Enter a NIP-19 nevent/naddr, or an HTTP URL for local dev");return Ni(r)?Di(r,t.fetcher??fetch):Mi(r,t)}const Zi=/\bwindow\s*\.\s*nostr\b|\bglobalThis\s*\.\s*nostr\b/,Wi="/__conformance__/events",ot=new URLSearchParams(location.search),xn=ot.get("live")==="1";function ne(e){return String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}const re=document.getElementById("app");function Vi(){return re.innerHTML=`
80
+ <header class="masthead">
81
+ <h1>napplet conformance ${xn?'<span class="live-badge" id="live-badge">● live</span>':""}</h1>
82
+ <p>Load a napplet by <code>nevent</code> or <code>naddr</code> and run NAP protocol conformance live. Same engine as <code>napplet-conformance</code> CI.</p>
83
+ </header>
84
+ <form id="run-form" class="runbar">
85
+ <input id="target" type="text" placeholder="naddr1… or nevent1… for a NIP-5D napplet manifest" autocomplete="off" spellcheck="false" />
86
+ <button id="run" type="submit">Run conformance</button>
87
+ <button id="rerun" type="button" class="secondary" hidden>Re-run</button>
88
+ </form>
89
+ <p id="status" class="status" role="status"></p>
90
+ <section id="output" class="output"></section>
91
+ `,{targetInput:re.querySelector("#target"),runButton:re.querySelector("#run"),rerunButton:re.querySelector("#rerun"),liveBadge:re.querySelector("#live-badge")??document.createElement("span"),status:re.querySelector("#status"),output:re.querySelector("#output")}}const C=Vi();let we="",at=0;function $e(e,t="info"){C.status.textContent=e,C.status.dataset.kind=t}function Xe(e){return String(e).padStart(2,"0")}function Ki(e){const t=new Date(e);return`${Xe(t.getHours())}:${Xe(t.getMinutes())}:${Xe(t.getSeconds())}`}function zi(e){const t=e.ok?"conformant":"non-conformant",n=[...new Set(e.checks.map(o=>o.area))].map(o=>{const c=e.checks.filter(a=>a.area===o).map(a=>{const l=a.severity==="warning"&&a.status==="fail"?' <span class="tag warn">warning</span>':"",f=a.detail?`<span class="detail">${ne(a.detail)}</span>`:"";return`<li class="check ${a.status}"><span class="badge ${a.status}">${a.status}</span><span class="id">${ne(a.id)}</span>${l}${f}</li>`}).join("");return`<div class="area"><h3>${ne(o)}</h3><ul>${c}</ul></div>`}).join(""),i=e.summary,s=at>1?`<span class="run-stamp">run #${at} · ${Ki(e.finishedAt)}</span>`:"";return`
92
+ <div class="verdict ${t}">
93
+ <span class="result">${e.ok?"CONFORMANT":"NON-CONFORMANT"}</span>
94
+ <span class="counts">${i.passed} passed · ${i.failed} failed · ${i.skipped} skipped${i.warnings?` · ${i.warnings} warning(s)`:""}</span>
95
+ ${s}
96
+ </div>
97
+ <div class="checks">${n}</div>
98
+ `}function Yi(e){return e.length===0?'<p class="empty">No envelopes were emitted.</p>':`<ul class="envlog">${e.map(r=>{const n=r.verdict.ok?"ok":"bad",i=r.verdict.ok?"":`<div class="errs">${r.verdict.errors.map(s=>ne(`${s.code}: ${s.message}`)).join("<br>")}</div>`;return`<li class="env ${n}"><code>${ne(JSON.stringify(r.envelope))}</code>${i}</li>`}).join("")}</ul>`}function Gi(e){const t=(r,n)=>`<tr><th>${ne(r)}</th><td>${n?ne(String(n)):"<em>—</em>"}</td></tr>`;if(e.manifestEvent){const r=e.manifestEvent,n=He(r);return`
99
+ <table class="manifest">
100
+ ${ur(r,n).map(([i,s])=>t(i,s)).join("")}
101
+ </table>
102
+ ${n.errors.length?`<div class="errs">${n.errors.map(i=>ne(`${i.code}: ${i.message}`)).join("<br>")}</div>`:""}
103
+ `}return e.fetched?'<p class="empty">Local URL mode booted raw HTML. It does not include a signed NIP-5D manifest event, so manifest-event checks are skipped.</p>':`<p class="empty">Couldn't fetch the local URL HTML, likely because of CORS. Use a NIP-19 <code>nevent</code>/<code>naddr</code> for authoritative manifest checks, or use the CLI for local URL runs.</p>`}function Xi(e,t,r){C.output.innerHTML=`
104
+ ${zi(e)}
105
+ <div class="panels">
106
+ <section class="panel"><h2>Emitted envelopes (${t.length})</h2>${Yi(t)}</section>
107
+ <section class="panel"><h2>Manifest</h2>${Gi(r)}</section>
108
+ </div>
109
+ `}async function Fe(e){we=e,C.runButton.disabled=!0,C.rerunButton.disabled=!0;let t=null;try{$e(`Resolving ${e} …`),t=await Fi(e);const r=Zi.test(t.html)?["window.nostr"]:[];$e("Booting napplet in a sandboxed iframe …");const n=await ir({url:t.bootUrl,readyTimeoutMs:5e3,settleMs:800,runDegraded:!0}),i=Jn({manifestHtml:t.html,manifestEvent:t.manifestEvent,boot:n,forbiddenGlobals:r}),s=dr(i);at+=1,$e(s.ok?"Done — conformant.":"Done — non-conformant.",s.ok?"info":"error"),Xi(s,n.emitted,t),C.rerunButton.hidden=!1}catch(r){$e(`Error: ${r instanceof Error?r.message:String(r)}`,"error")}finally{t?.revoke?.(),C.runButton.disabled=!1,C.rerunButton.disabled=!1}}function Ji(){if(!xn||typeof EventSource>"u")return;let e=!1;const t=new EventSource(Wi);t.addEventListener("rerun",()=>{!we||e||(e=!0,setTimeout(()=>{e=!1,Fe(we)},50))}),t.addEventListener("open",()=>{C.liveBadge&&(C.liveBadge.dataset.state="connected")}),t.addEventListener("error",()=>{C.liveBadge&&(C.liveBadge.dataset.state="disconnected")})}C.runButton.parentElement.addEventListener("submit",e=>{e.preventDefault();const t=C.targetInput.value.trim();if(t){const r=new URL(location.href);r.searchParams.set("target",t),r.searchParams.delete("url"),history.replaceState(null,"",r),Fe(t)}});C.rerunButton.addEventListener("click",()=>{we&&Fe(we)});Ji();const Je=ot.get("target")??ot.get("url");Je&&(C.targetInput.value=Je,Fe(Je));
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>napplet conformance runtime</title>
7
7
  <meta name="description" content="Load a napplet and run NAP protocol conformance checks live in your browser." />
8
- <script type="module" crossorigin src="/assets/index-DV1wZ-SF.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-CS2zxBsY.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-D4WUxbBl.css">
10
10
  </head>
11
11
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@napplet/conformance-cli",
3
- "version": "0.2.19",
3
+ "version": "0.3.1",
4
4
  "description": "Headless CLI that runs @napplet/conformance against a napplet in real Chromium via Playwright — the `test:conformance` runner",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,14 +15,14 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "playwright": "^1.59.1",
18
- "@napplet/conformance": "^0.17.0"
18
+ "@napplet/conformance": "^0.19.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^22.15.0",
22
22
  "tsup": "^8.5.0",
23
23
  "typescript": "^5.9.3",
24
- "vitest": "^4.1.2",
25
- "@napplet/conformance-web": "0.0.18"
24
+ "vitest": "^4.1.11",
25
+ "@napplet/conformance-web": "0.0.19"
26
26
  },
27
27
  "license": "MIT",
28
28
  "repository": {
@@ -1,116 +0,0 @@
1
- (function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))n(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&n(o)}).observe(document,{childList:!0,subtree:!0});function r(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function n(i){if(i.ep)return;i.ep=!0;const s=r(i);fetch(i.href,s)}})();var at=["relay","identity","storage","inc","theme","keys","media","notify","config","resource","cvm","outbox","upload","intent","ble","webrtc","link","count","lists","serial","fs","common","dm"],l={id:"string"},An={"relay.subscribe":{dir:"out",fields:{...l,subId:"string",filters:"array"}},"relay.close":{dir:"out",fields:{...l,subId:"string"}},"relay.publish":{dir:"out",fields:{...l,event:"object"}},"relay.publishEncrypted":{dir:"out",fields:{...l,event:"object",recipient:"string"}},"relay.query":{dir:"out",fields:{...l,filters:"array"}},"relay.event":{dir:"in"},"relay.eose":{dir:"in"},"relay.closed":{dir:"in"},"relay.publish.result":{dir:"in"},"relay.publishEncrypted.result":{dir:"in"},"relay.query.result":{dir:"in"},"identity.getPublicKey":{dir:"out",fields:{...l}},"identity.getRelays":{dir:"out",fields:{...l}},"identity.getProfile":{dir:"out",fields:{...l}},"identity.getFollows":{dir:"out",fields:{...l}},"identity.getList":{dir:"out",fields:{...l,listType:"string"}},"identity.getZaps":{dir:"out",fields:{...l}},"identity.getMutes":{dir:"out",fields:{...l}},"identity.getBlocked":{dir:"out",fields:{...l}},"identity.getBadges":{dir:"out",fields:{...l}},"identity.changed":{dir:"in"},"identity.getPublicKey.result":{dir:"in"},"identity.getRelays.result":{dir:"in"},"identity.getProfile.result":{dir:"in"},"identity.getFollows.result":{dir:"in"},"identity.getList.result":{dir:"in"},"identity.getZaps.result":{dir:"in"},"identity.getMutes.result":{dir:"in"},"identity.getBlocked.result":{dir:"in"},"identity.getBadges.result":{dir:"in"},"storage.get":{dir:"out",fields:{...l,key:"string"}},"storage.set":{dir:"out",fields:{...l,key:"string",value:"string"}},"storage.remove":{dir:"out",fields:{...l,key:"string"}},"storage.keys":{dir:"out",fields:{...l}},"storage.get.result":{dir:"in"},"storage.set.result":{dir:"in"},"storage.remove.result":{dir:"in"},"storage.keys.result":{dir:"in"},"inc.emit":{dir:"out",fields:{topic:"string"},forbiddenFields:["sender"]},"inc.subscribe":{dir:"out",fields:{...l,topic:"string"}},"inc.unsubscribe":{dir:"out",fields:{topic:"string"}},"inc.channel.open":{dir:"out",fields:{...l,target:"string"}},"inc.channel.emit":{dir:"out",fields:{channelId:"string"}},"inc.channel.broadcast":{dir:"out"},"inc.channel.list":{dir:"out",fields:{...l}},"inc.channel.close":{dir:"out",fields:{channelId:"string"}},"inc.subscribe.result":{dir:"in"},"inc.event":{dir:"in",fields:{topic:"string",sender:"string"}},"inc.channel.open.result":{dir:"in"},"inc.channel.opened":{dir:"in",fields:{channelId:"string",peer:"string"}},"inc.channel.event":{dir:"in"},"inc.channel.list.result":{dir:"in"},"inc.channel.closed":{dir:"in"},"theme.get":{dir:"out",fields:{...l}},"theme.get.result":{dir:"in"},"theme.changed":{dir:"in"},"keys.forward":{dir:"out",fields:{key:"string",code:"string",ctrl:"boolean",alt:"boolean",shift:"boolean",meta:"boolean"}},"keys.registerAction":{dir:"out",fields:{...l,action:"object"}},"keys.unregisterAction":{dir:"out",fields:{actionId:"string"}},"keys.registerAction.result":{dir:"in"},"keys.bindings":{dir:"in"},"keys.action":{dir:"in"},"media.session.create":{dir:"out",fields:{...l,owner:"object"}},"media.session.update":{dir:"out",fields:{sessionId:"string",metadata:"object"}},"media.session.destroy":{dir:"out",fields:{sessionId:"string"}},"media.state":{dir:"out",fields:{sessionId:"string",status:"string"}},"media.capabilities":{dir:"out",fields:{sessionId:"string",actions:"array"}},"media.session.create.result":{dir:"in"},"media.command":{dir:"in"},"media.controls":{dir:"in"},"notify.send":{dir:"out",fields:{...l,title:"string"}},"notify.dismiss":{dir:"out",fields:{notificationId:"string"}},"notify.badge":{dir:"out",fields:{count:"number"}},"notify.channel.register":{dir:"out",fields:{channelId:"string",label:"string"}},"notify.permission.request":{dir:"out",fields:{...l}},"notify.send.result":{dir:"in"},"notify.permission.result":{dir:"in"},"notify.action":{dir:"in"},"notify.clicked":{dir:"in"},"notify.dismissed":{dir:"in"},"notify.controls":{dir:"in"},"config.registerSchema":{dir:"out",fields:{...l,schema:"object"}},"config.get":{dir:"out",fields:{...l}},"config.subscribe":{dir:"out"},"config.unsubscribe":{dir:"out"},"config.openSettings":{dir:"out"},"config.registerSchema.result":{dir:"in"},"config.values":{dir:"in"},"config.schemaError":{dir:"in"},"resource.info":{dir:"out",fields:{...l}},"resource.bytes":{dir:"out",fields:{...l,url:"string"}},"resource.bytesMany":{dir:"out",fields:{...l,requests:"array"}},"resource.cancel":{dir:"out",fields:{...l}},"resource.info.result":{dir:"in"},"resource.info.error":{dir:"in"},"resource.bytes.result":{dir:"in"},"resource.bytes.error":{dir:"in"},"resource.bytesMany.result":{dir:"in"},"resource.bytesMany.error":{dir:"in"},"cvm.discover":{dir:"out",fields:{...l}},"cvm.request":{dir:"out",fields:{...l,server:"object",message:"object"}},"cvm.close":{dir:"out",fields:{...l,server:"object"}},"cvm.registry.list":{dir:"out",fields:{...l}},"cvm.registry.has":{dir:"out",fields:{...l,family:"string"}},"cvm.registry.describe":{dir:"out",fields:{...l,family:"string"}},"cvm.registry.call":{dir:"out",fields:{...l,family:"string",tool:"string"}},"cvm.discover.result":{dir:"in"},"cvm.request.result":{dir:"in"},"cvm.close.result":{dir:"in"},"cvm.event":{dir:"in"},"cvm.registry.list.result":{dir:"in"},"cvm.registry.has.result":{dir:"in"},"cvm.registry.describe.result":{dir:"in"},"cvm.registry.call.result":{dir:"in"},"outbox.getEvent":{dir:"out",fields:{...l,eventId:"string"}},"outbox.query":{dir:"out",fields:{...l,filters:"present"}},"outbox.subscribe":{dir:"out",fields:{...l,subId:"string",filters:"present"}},"outbox.close":{dir:"out",fields:{...l,subId:"string"}},"outbox.publish":{dir:"out",fields:{...l,event:"object"}},"outbox.resolveRelays":{dir:"out",fields:{...l,target:"present"}},"outbox.getEvent.result":{dir:"in"},"outbox.query.result":{dir:"in"},"outbox.event":{dir:"in"},"outbox.closed":{dir:"in"},"outbox.publish.result":{dir:"in"},"outbox.resolveRelays.result":{dir:"in"},"upload.info":{dir:"out",fields:{...l}},"upload.upload":{dir:"out",fields:{...l,request:"object"}},"upload.status":{dir:"out",fields:{...l,uploadId:"string"}},"upload.info.result":{dir:"in"},"upload.upload.result":{dir:"in"},"upload.status.result":{dir:"in"},"upload.status.changed":{dir:"in"},"intent.invoke":{dir:"out",fields:{...l,request:"object"}},"intent.available":{dir:"out",fields:{...l,archetype:"string"}},"intent.handlers":{dir:"out",fields:{...l}},"intent.invoke.result":{dir:"in",fields:{...l,result:"object"}},"intent.available.result":{dir:"in"},"intent.handlers.result":{dir:"in"},"intent.changed":{dir:"in"},"ble.open":{dir:"out",fields:{...l,request:"object"}},"ble.services":{dir:"out",fields:{...l,sessionId:"string"}},"ble.read":{dir:"out",fields:{...l,sessionId:"string",target:"object"}},"ble.write":{dir:"out",fields:{...l,sessionId:"string",target:"object",data:"array"}},"ble.subscribe":{dir:"out",fields:{...l,sessionId:"string",target:"object"}},"ble.unsubscribe":{dir:"out",fields:{...l,sessionId:"string",target:"object"}},"ble.close":{dir:"out",fields:{...l,sessionId:"string"}},"ble.open.result":{dir:"in"},"ble.services.result":{dir:"in"},"ble.read.result":{dir:"in"},"ble.write.result":{dir:"in"},"ble.subscribe.result":{dir:"in"},"ble.unsubscribe.result":{dir:"in"},"ble.close.result":{dir:"in"},"ble.event":{dir:"in"},"common.encodeNip19":{dir:"out",fields:{...l,input:"object"}},"common.decodeNip19":{dir:"out",fields:{...l,value:"string"}},"common.getProfile":{dir:"out",fields:{...l,target:"string"}},"common.follows":{dir:"out",fields:{...l}},"common.follow":{dir:"out",fields:{...l,pubkeys:"array"}},"common.unfollow":{dir:"out",fields:{...l,pubkeys:"array"}},"common.react":{dir:"out",fields:{...l,targetEventId:"string",reaction:"string"}},"common.report":{dir:"out",fields:{...l,target:"object",reason:"string",text:"string"}},"common.encodeNip19.result":{dir:"in"},"common.decodeNip19.result":{dir:"in"},"common.getProfile.result":{dir:"in"},"common.follows.result":{dir:"in"},"common.follow.result":{dir:"in"},"common.unfollow.result":{dir:"in"},"common.react.result":{dir:"in"},"common.report.result":{dir:"in"},"webrtc.open":{dir:"out",fields:{...l,request:"object"}},"webrtc.send":{dir:"out",fields:{...l,sessionId:"string",payload:"present"}},"webrtc.close":{dir:"out",fields:{...l,sessionId:"string"}},"webrtc.open.result":{dir:"in"},"webrtc.send.result":{dir:"in"},"webrtc.close.result":{dir:"in"},"webrtc.event":{dir:"in"},"link.open":{dir:"out",fields:{...l,url:"string"}},"link.open.result":{dir:"in"},"count.query":{dir:"out",fields:{...l,filters:"array"}},"count.query.result":{dir:"in"},"lists.supported":{dir:"out",fields:{...l}},"lists.add":{dir:"out",fields:{...l,list:"object",items:"array"}},"lists.remove":{dir:"out",fields:{...l,list:"object",items:"array"}},"lists.supported.result":{dir:"in"},"lists.add.result":{dir:"in"},"lists.remove.result":{dir:"in"},"serial.open":{dir:"out",fields:{...l,request:"object"}},"serial.write":{dir:"out",fields:{...l,sessionId:"string",data:"array"}},"serial.close":{dir:"out",fields:{...l,sessionId:"string"}},"serial.open.result":{dir:"in"},"serial.write.result":{dir:"in"},"serial.close.result":{dir:"in"},"serial.event":{dir:"in"},"fs.info":{dir:"out",fields:{...l}},"fs.pickFile":{dir:"out",fields:{...l}},"fs.pickFiles":{dir:"out",fields:{...l}},"fs.pickDirectory":{dir:"out",fields:{...l}},"fs.pickSaveFile":{dir:"out",fields:{...l}},"fs.stat":{dir:"out",fields:{...l,path:"string"}},"fs.list":{dir:"out",fields:{...l,path:"string"}},"fs.read":{dir:"out",fields:{...l,path:"string"}},"fs.write":{dir:"out",fields:{...l,path:"string",data:"string"}},"fs.mkdir":{dir:"out",fields:{...l,path:"string"}},"fs.remove":{dir:"out",fields:{...l,path:"string"}},"fs.move":{dir:"out",fields:{...l,fromPath:"string",toPath:"string"}},"fs.watch":{dir:"out",fields:{...l,path:"string"}},"fs.unwatch":{dir:"out",fields:{...l,watchId:"string"}},"fs.info.result":{dir:"in"},"fs.pickFile.result":{dir:"in"},"fs.pickFiles.result":{dir:"in"},"fs.pickDirectory.result":{dir:"in"},"fs.pickSaveFile.result":{dir:"in"},"fs.stat.result":{dir:"in"},"fs.list.result":{dir:"in"},"fs.read.result":{dir:"in"},"fs.write.result":{dir:"in"},"fs.mkdir.result":{dir:"in"},"fs.remove.result":{dir:"in"},"fs.move.result":{dir:"in"},"fs.watch.result":{dir:"in"},"fs.unwatch.result":{dir:"in"},"fs.changed":{dir:"in"},"dm.status":{dir:"out",fields:{...l}},"dm.conversations":{dir:"out",fields:{...l}},"dm.messages":{dir:"out",fields:{...l,conversationId:"string"}},"dm.send":{dir:"out",fields:{...l,recipients:"array",content:"string"}},"dm.subscribe":{dir:"out",fields:{...l}},"dm.unsubscribe":{dir:"out",fields:{...l,subscriptionId:"string"}},"dm.status.result":{dir:"in"},"dm.conversations.result":{dir:"in"},"dm.messages.result":{dir:"in"},"dm.send.result":{dir:"in"},"dm.subscribe.result":{dir:"in"},"dm.unsubscribe.result":{dir:"in"},"dm.message":{dir:"in"}};function Ht(e){if(e===void 0)return"undefined";if(e===null)return"null";if(Array.isArray(e))return"array";const t=typeof e;return t==="string"||t==="number"||t==="boolean"?t:t==="object"?"object":"present"}function Tn(e,t){return t==="present"?e!=null:Ht(e)===t}function Bn(e,t){if(typeof e!="object"||e===null||Array.isArray(e))return;const r=e;typeof r.archetype!="string"&&t.push({code:r.archetype===void 0?"missing-field":"wrong-type",message:'Intent request requires a string "archetype" field',field:"request.archetype"});for(const n of["action","convention"])r[n]!==void 0&&typeof r[n]!="string"&&t.push({code:"wrong-type",message:`Intent request field "${n}" must be a string`,field:`request.${n}`});"sender"in r&&t.push({code:"forbidden-field",message:"Intent request does not define a caller-supplied sender field",field:"request.sender"})}function jt(e,t,r){Array.isArray(e)&&e.every(n=>typeof n=="string")||r.push({code:"wrong-type",message:`Field "${t}" must be an array of strings`,field:t})}function On(e,t){e.servers!==void 0&&jt(e.servers,"servers",t)}function qn(e,t){if(Array.isArray(e)){if(e.length===0){t.push({code:"invalid-resource-request",message:'Field "requests" must contain at least one resource request',field:"requests"});return}for(const[r,n]of e.entries()){const i=`requests[${r}]`;if(typeof n!="object"||n===null||Array.isArray(n)){t.push({code:"invalid-resource-request",message:`Field "${i}" must be a resource request object`,field:i});continue}const s=n;typeof s.url!="string"&&t.push({code:s.url===void 0?"missing-field":"wrong-type",message:`Field "${i}.url" must be a string`,field:`${i}.url`}),s.servers!==void 0&&jt(s.servers,`${i}.servers`,t)}}}function Nn(e){const t=[];if(typeof e!="object"||e===null||Array.isArray(e))return{ok:!1,errors:[{code:"not-an-object",message:"Envelope must be a non-null object"}]};const r=e,n=r.type;if(typeof n!="string")return{ok:!1,errors:[{code:"missing-type",message:"Envelope is missing a string `type` field"}]};const i=n.indexOf(".");if(i<=0)return{ok:!1,type:n,errors:[{code:"malformed-type",message:`Envelope type "${n}" is not in domain.action form`}]};const s=n.slice(0,i);if(!at.includes(s))return{ok:!1,type:n,domain:s,errors:[{code:"unknown-domain",message:`"${s}" is not a known NAP domain`}]};const c=An[n];if(!c)return{ok:!1,type:n,domain:s,errors:[{code:"unknown-type",message:`"${n}" is not a known ${s} message type`}]};for(const[a,d]of Object.entries(c.fields??{})){if(!(a in r)||r[a]===void 0){t.push({code:"missing-field",message:`Required field "${a}" is missing`,field:a});continue}Tn(r[a],d)||t.push({code:"wrong-type",message:`Field "${a}" should be ${d} but is ${Ht(r[a])}`,field:a})}if(c.dir==="in")return{ok:!1,type:n,domain:s,direction:"in",errors:[{code:"inbound-type-emitted",message:`"${n}" is a shell→napplet message; a napplet must not emit it`},...t]};for(const a of c.forbiddenFields??[])a in r&&t.push({code:"forbidden-field",message:`Field "${a}" must be runtime-derived and cannot be emitted by a napplet`,field:a});return n==="intent.invoke"&&Bn(r.request,t),n==="resource.bytes"&&On(r,t),n==="resource.bytesMany"&&qn(r.requests,t),{ok:t.length===0,type:n,domain:s,direction:"out",errors:t}}var Dt=5129,Mt=15129,ge=35129,ct=[Dt,Mt,ge];function Ft(e,t){return e.tags.find(r=>r[0]===t)}function Ln(e){return ct.includes(e)}function Pn(e){return typeof e=="string"&&/^[0-9a-f]{64}$/i.test(e)}function Wt(e){return Ft(e,"d")?.[1]?.trim()||void 0}function _n(e){return e.tags.filter(t=>t[0]==="requires").map(t=>t[1]?.trim()??"").filter(Boolean)}function Zt(e){return Wt(e)??Ft(e,"title")?.[1]??e.id}function lt(e){const t=[],r=[];if(!e)return{ok:!1,requires:[],errors:[{code:"missing-manifest-event",message:"No NIP-5D manifest event was resolved"}],warnings:r};const n=Wt(e),i=_n(e);Ln(e.kind)||t.push({code:"invalid-napplet-kind",message:`Manifest event kind ${e.kind} is not a NIP-5D napplet kind`}),e.kind===ge&&!n?t.push({code:"missing-d-tag",message:"Named napplet manifest kind 35129 must include a non-empty d tag"}):(e.kind===Mt||e.kind===Dt)&&n&&t.push({code:"unexpected-d-tag",message:`Napplet manifest kind ${e.kind} must not include a d tag`});const s=e.tags.find(o=>o[0]==="path"&&o[1]==="/index.html");s?Pn(s[2])||t.push({code:"invalid-index-html-hash",message:"The /index.html path tag must carry a 64-character sha256 hash"}):t.push({code:"missing-index-html",message:"Napplet manifest must include a path tag for /index.html"});for(const o of i){if(o.startsWith("nap:")||o.startsWith("NAP-")){t.push({code:"invalid-required-nap",message:`requires tag "${o}" must be a bare NAP domain such as "relay"`});continue}at.includes(o)||t.push({code:"unknown-required-nap",message:`requires tag "${o}" is not a known NAP domain`})}return{ok:t.length===0,kind:e.kind,dTag:n,requires:i,errors:t,warnings:r}}var xe="f".repeat(64),Cn={dTag:"reference-source"},Un="https://reference.invalid/blob",Vt="reference-handler",Hn="reference-subscriber",Be="napplet:note/open";function ke(e,t,r){return u({type:e,id:t,result:{entries:[r]}})}var u=e=>[e],N=()=>[];function wt(e){if(typeof e!="string"||!e.startsWith("data:"))return null;const t=e.indexOf(",");if(t<0)return{blob:new Blob([],{type:"text/plain"}),mime:"text/plain"};const r=e.slice(5,t),n=e.slice(t+1),i=r.split(";").filter(Boolean),s=i.includes("base64"),o=i.find(c=>c.includes("/"))??"text/plain";try{if(s){const c=globalThis.atob(n),a=Uint8Array.from(c,d=>d.charCodeAt(0));return{blob:new Blob([a],{type:o}),mime:o}}return{blob:new Blob([decodeURIComponent(n)],{type:o}),mime:o}}catch{return null}}var jn={"relay.subscribe":e=>u({type:"relay.eose",subId:e.subId}),"relay.close":N,"relay.publish":e=>u({type:"relay.publish.result",id:e.id,ok:!0,event:e.event}),"relay.publishEncrypted":e=>u({type:"relay.publishEncrypted.result",id:e.id,ok:!0,event:e.event}),"relay.query":e=>u({type:"relay.query.result",id:e.id,events:[]}),"identity.getPublicKey":e=>u({type:"identity.getPublicKey.result",id:e.id,pubkey:xe}),"identity.getRelays":e=>u({type:"identity.getRelays.result",id:e.id,relays:{}}),"identity.getProfile":e=>u({type:"identity.getProfile.result",id:e.id,profile:null}),"identity.getFollows":e=>u({type:"identity.getFollows.result",id:e.id,pubkeys:[]}),"identity.getList":e=>u({type:"identity.getList.result",id:e.id,entries:[]}),"identity.getZaps":e=>u({type:"identity.getZaps.result",id:e.id,zaps:[]}),"identity.getMutes":e=>u({type:"identity.getMutes.result",id:e.id,pubkeys:[]}),"identity.getBlocked":e=>u({type:"identity.getBlocked.result",id:e.id,pubkeys:[]}),"identity.getBadges":e=>u({type:"identity.getBadges.result",id:e.id,badges:[]}),"storage.get":e=>u({type:"storage.get.result",id:e.id,value:null}),"storage.set":e=>u({type:"storage.set.result",id:e.id}),"storage.remove":e=>u({type:"storage.remove.result",id:e.id}),"storage.keys":e=>u({type:"storage.keys.result",id:e.id,keys:[]}),"inc.emit":N,"inc.subscribe":e=>u({type:"inc.subscribe.result",id:e.id}),"inc.unsubscribe":N,"inc.channel.open":e=>u({type:"inc.channel.open.result",id:e.id,channelId:`chan-${String(e.id)}`,peer:"reference-peer"}),"inc.channel.emit":N,"inc.channel.broadcast":N,"inc.channel.list":e=>u({type:"inc.channel.list.result",id:e.id,channels:[]}),"inc.channel.close":N,"theme.get":e=>u({type:"theme.get.result",id:e.id,theme:{colors:{},mode:"dark"}}),"keys.forward":N,"keys.registerAction":e=>u({type:"keys.registerAction.result",id:e.id,actionId:`action-${String(e.id)}`}),"keys.unregisterAction":N,"media.session.create":e=>u({type:"media.session.create.result",id:e.id,sessionId:`session-${String(e.id)}`,owner:e.owner}),"media.session.update":N,"media.session.destroy":N,"media.state":N,"media.capabilities":N,"notify.send":e=>u({type:"notify.send.result",id:e.id,notificationId:`notif-${String(e.id)}`}),"notify.dismiss":N,"notify.badge":N,"notify.channel.register":N,"notify.permission.request":e=>u({type:"notify.permission.result",id:e.id,granted:!0}),"config.registerSchema":e=>u({type:"config.registerSchema.result",id:e.id,ok:!0}),"config.get":e=>u({type:"config.values",id:e.id,values:{}}),"config.subscribe":()=>u({type:"config.values",values:{}}),"config.unsubscribe":N,"config.openSettings":N,"resource.bytes":e=>{const t=wt(e.url);return u(t?{type:"resource.bytes.result",id:e.id,blob:t.blob,mime:t.mime}:{type:"resource.bytes.result",id:e.id,blob:new Blob([]),mime:"application/octet-stream"})},"resource.bytesMany":e=>u({type:"resource.bytesMany.result",id:e.id,items:Array.isArray(e.requests)?e.requests.map(t=>{const r=typeof t=="object"&&t!==null&&!Array.isArray(t)?t.url:void 0,n=wt(r);return{url:typeof r=="string"?r:"",ok:!0,blob:n?.blob??new Blob([]),mime:n?.mime??"application/octet-stream"}}):[]}),"resource.info":e=>u({type:"resource.info.result",id:e.id,info:{schemes:[{scheme:"data",enabled:!0},{scheme:"https",enabled:!0}],maxServers:8}}),"resource.cancel":N,"cvm.discover":e=>u({type:"cvm.discover.result",id:e.id,servers:[]}),"cvm.request":e=>u({type:"cvm.request.result",id:e.id,message:{}}),"cvm.close":e=>u({type:"cvm.close.result",id:e.id}),"outbox.getEvent":e=>u({type:"outbox.getEvent.result",id:e.id}),"outbox.query":e=>u({type:"outbox.query.result",id:e.id,events:[]}),"outbox.subscribe":e=>u({type:"outbox.closed",subId:e.subId,reason:"reference shell complete"}),"outbox.close":N,"outbox.publish":e=>u({type:"outbox.publish.result",id:e.id,ok:!0}),"outbox.resolveRelays":e=>u({type:"outbox.resolveRelays.result",id:e.id,plan:{}}),"upload.info":e=>u({type:"upload.info.result",id:e.id,info:{rails:[{rail:"nip96",enabled:!0,returns:["https"]},{rail:"blossom",enabled:!0,returns:["https","blossom"]}]}}),"upload.upload":e=>u({type:"upload.upload.result",id:e.id,result:{url:Un}}),"upload.status":e=>u({type:"upload.status.result",id:e.id,status:{}}),"ble.open":e=>u({type:"ble.open.result",id:e.id,session:{id:"ble-reference",state:"open",device:{id:"reference-device",name:"Reference BLE"}}}),"ble.services":e=>u({type:"ble.services.result",id:e.id,services:[]}),"ble.read":e=>u({type:"ble.read.result",id:e.id,data:[]}),"ble.write":e=>u({type:"ble.write.result",id:e.id}),"ble.subscribe":e=>u({type:"ble.subscribe.result",id:e.id}),"ble.unsubscribe":e=>u({type:"ble.unsubscribe.result",id:e.id}),"ble.close":e=>u({type:"ble.close.result",id:e.id}),"common.encodeNip19":e=>u({type:"common.encodeNip19.result",id:e.id,ok:!0,value:"npub1reference",nip19Type:"npub"}),"common.decodeNip19":e=>u({type:"common.decodeNip19.result",id:e.id,ok:!0,nip19Type:"npub",hex:xe}),"common.getProfile":e=>u({type:"common.getProfile.result",id:e.id,ok:!0,pubkey:xe,profile:null}),"common.follows":e=>u({type:"common.follows.result",id:e.id,ok:!0,pubkeys:[]}),"common.follow":e=>u({type:"common.follow.result",id:e.id,ok:!0}),"common.unfollow":e=>u({type:"common.unfollow.result",id:e.id,ok:!0}),"common.react":e=>u({type:"common.react.result",id:e.id,ok:!0,eventId:"0".repeat(64)}),"common.report":e=>u({type:"common.report.result",id:e.id,ok:!0,eventId:"1".repeat(64)}),"webrtc.open":e=>u({type:"webrtc.open.result",id:e.id,session:{id:"webrtc-reference",scope:{type:"direct",pubkey:xe},channel:"default",state:"connecting"}}),"webrtc.send":e=>u({type:"webrtc.send.result",id:e.id}),"webrtc.close":e=>u({type:"webrtc.close.result",id:e.id}),"link.open":e=>u({type:"link.open.result",id:e.id,status:"opened"}),"count.query":e=>u({type:"count.query.result",id:e.id,ok:!0,count:0}),"lists.supported":e=>u({type:"lists.supported.result",id:e.id,lists:[]}),"lists.add":e=>u({type:"lists.add.result",id:e.id,ok:!0,added:0,skipped:0}),"lists.remove":e=>u({type:"lists.remove.result",id:e.id,ok:!0,removed:0,skipped:0}),"serial.open":e=>u({type:"serial.open.result",id:e.id,session:{id:`serial-${String(e.id)}`,state:"open"}}),"serial.write":e=>u({type:"serial.write.result",id:e.id}),"serial.close":e=>u({type:"serial.close.result",id:e.id}),"fs.info":e=>u({type:"fs.info.result",id:e.id,info:{roots:[{path:"/shared",name:"Shared files",permissions:["read","list","write","create","delete","watch"]}],limits:{maxReadBytes:1048576,maxWriteBytes:1048576,maxWatchCount:16}}}),"fs.pickFile":e=>ke("fs.pickFile.result",e.id,{path:"/picked/file.txt",kind:"file",name:"file.txt",permissions:["read"]}),"fs.pickFiles":e=>ke("fs.pickFiles.result",e.id,{path:"/picked/file.txt",kind:"file",name:"file.txt",permissions:["read"]}),"fs.pickDirectory":e=>ke("fs.pickDirectory.result",e.id,{path:"/picked",kind:"directory",name:"picked",permissions:["read","list"]}),"fs.pickSaveFile":e=>ke("fs.pickSaveFile.result",e.id,{path:"/picked/export.json",kind:"file",name:"export.json",permissions:["write","create"]}),"fs.stat":e=>u({type:"fs.stat.result",id:e.id,metadata:{path:e.path,kind:"file",size:0}}),"fs.list":e=>u({type:"fs.list.result",id:e.id,entries:[]}),"fs.read":e=>u({type:"fs.read.result",id:e.id,result:{data:"",offset:0,bytesRead:0,eof:!0,size:0}}),"fs.write":e=>u({type:"fs.write.result",id:e.id,result:{bytesWritten:0,size:0}}),"fs.mkdir":e=>u({type:"fs.mkdir.result",id:e.id}),"fs.remove":e=>u({type:"fs.remove.result",id:e.id}),"fs.move":e=>u({type:"fs.move.result",id:e.id}),"fs.watch":e=>u({type:"fs.watch.result",id:e.id,watchId:`watch-${String(e.id)}`}),"fs.unwatch":e=>u({type:"fs.unwatch.result",id:e.id})};function Dn(e){return(t,r)=>{const n=Mn(r),i=Nn(r);if(e.records.push({envelope:r,verdict:i,timestamp:e.now()}),!n||!i.ok)return[];const s=r;if(n==="intent.invoke")return e.intents.handleInvoke(t,s);if(n==="intent.available")return u({type:"intent.available.result",id:s.id,availability:e.intents.availability(s.archetype)});if(n==="intent.handlers")return u({type:"intent.handlers.result",id:s.id,handlers:[e.intents.availability("note")]});if(n==="inc.emit")return Fn(t,s,e.queueDelivery);const o=jn[n];return o?o(s):[]}}function Mn(e){if(!e||typeof e!="object")return;const t=e.type;return typeof t=="string"?t:void 0}function Fn(e,t,r){if(t.topic!==Be)return[];const n={type:"inc.event",topic:t.topic,sender:e.dTag};return"payload"in t&&(n.payload=t.payload),r(Hn,n),[]}function Se(e,t,r,n){return u({type:"intent.invoke.result",id:e,result:{ok:!1,archetype:t,action:r,handled:!1,error:n}})}function Wn(){return{handleInvoke:Zn,availability:Vn}}function Zn(e,t){const r=t.request;if(typeof r!="object"||r===null||Array.isArray(r))return Se(t.id,"","open","invalid intent request");const n=r,i=typeof n.archetype=="string"?n.archetype:"",s=typeof n.action=="string"?n.action:"open";return i?i!=="note"?Se(t.id,i,s,"no handler"):n.convention!==void 0&&n.convention!==Be?Se(t.id,i,s,"unsupported convention"):u({type:"intent.invoke.result",id:t.id,result:{ok:!0,archetype:i,action:s,handled:!0,handler:Vt,windowId:"reference-window",convention:typeof n.convention=="string"?n.convention:Be}}):Se(t.id,i,s,"intent request requires an archetype")}function Vn(e){return e!=="note"?{archetype:e,available:!1,candidates:[],hasDefault:!1}:{archetype:e,available:!0,candidates:[{dTag:Vt,actions:["open"],conventions:[Be],isDefault:!0}],hasDefault:!0}}function Kn(e={}){const t=[],r=Yn(),n=Dn({now:e.now??Date.now,records:t,queueDelivery:r.queue,intents:Wn()});return{get records(){return t},handle:i=>n(Cn,i),handleFrom:n,takeDeliveries:r.take,reset(){t.length=0,r.clear()}}}function Yn(){const e=new Map;return{queue(t,r){const n=e.get(t);n?n.push(r):e.set(t,[r])},take(t){const r=e.get(t)??[];return e.delete(t),r},clear(){e.clear()}}}function zn(e){return{manifestHtml:e.manifestHtml,manifestEvent:e.manifestEvent??null,sandbox:e.sandbox??{allowScripts:!0,allowSameOrigin:!1},installedGlobal:e.boot.installedGlobal,bootError:e.boot.bootError,emitted:e.boot.emitted,forbiddenGlobals:e.forbiddenGlobals??[],degraded:e.boot.degraded,lifecycle:e.lifecycle??null}}var Kt="__nappletConformance.error";function vt(e){return new Promise(t=>setTimeout(t,e))}function Gn(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Xn(e){return`
2
- (() => {
3
- const domains = ${JSON.stringify(e)};
4
- const napplet = {};
5
- for (const domain of domains) napplet[domain] = {};
6
- const pending = new Map();
7
- let seq = 0;
8
- const nextId = () => {
9
- try {
10
- if (window.crypto && typeof window.crypto.randomUUID === 'function') return window.crypto.randomUUID();
11
- } catch {}
12
- seq += 1;
13
- return 'conformance-' + Date.now().toString(36) + '-' + seq.toString(36);
14
- };
15
- const request = (message, resultType, errorType) => new Promise((resolve, reject) => {
16
- const id = message.id || nextId();
17
- const timeout = window.setTimeout(() => {
18
- pending.delete(id);
19
- reject(new Error(message.type + ' timed out'));
20
- }, 5000);
21
- pending.set(id, { resolve, reject, resultType, errorType, timeout });
22
- window.parent.postMessage({ ...message, id }, '*');
23
- });
24
- window.addEventListener('message', (event) => {
25
- const msg = event.data;
26
- if (!msg || typeof msg !== 'object' || typeof msg.id !== 'string') return;
27
- const slot = pending.get(msg.id);
28
- if (!slot) return;
29
- if (msg.type !== slot.resultType && msg.type !== slot.errorType) return;
30
- pending.delete(msg.id);
31
- window.clearTimeout(slot.timeout);
32
- if (msg.type === slot.errorType) {
33
- slot.reject(new Error(msg.message ? msg.error + ': ' + msg.message : String(msg.error || 'request failed')));
34
- return;
35
- }
36
- slot.resolve(msg);
37
- });
38
- if (napplet.resource) {
39
- napplet.resource.info = () =>
40
- request({ type: 'resource.info' }, 'resource.info.result', 'resource.info.error')
41
- .then((msg) => msg.info);
42
- napplet.resource.bytes = (url, options) => {
43
- const message = { type: 'resource.bytes', url: String(url) };
44
- if (options && options.servers !== undefined) message.servers = options.servers;
45
- return request(message, 'resource.bytes.result', 'resource.bytes.error')
46
- .then((msg) => msg.blob);
47
- };
48
- napplet.resource.bytesMany = (requests) =>
49
- request({ type: 'resource.bytesMany', requests: Array.from(requests || []) }, 'resource.bytesMany.result', 'resource.bytesMany.error')
50
- .then((msg) => msg.items);
51
- napplet.resource.bytesAsObjectURL = (url) => {
52
- const handle = { url: '', revoke: () => {} };
53
- let objectUrl = '';
54
- let revoked = false;
55
- const ready = napplet.resource.bytes(url).then((blob) => {
56
- if (revoked) return;
57
- objectUrl = URL.createObjectURL(blob);
58
- handle.url = objectUrl;
59
- return objectUrl;
60
- });
61
- handle.revoke = () => {
62
- if (revoked) return;
63
- revoked = true;
64
- if (objectUrl) URL.revokeObjectURL(objectUrl);
65
- };
66
- Object.defineProperty(handle, 'ready', { value: ready, enumerable: false });
67
- return handle;
68
- };
69
- }
70
- window.napplet = napplet;
71
- const report = (reason) => {
72
- try {
73
- window.parent.postMessage({ type: '${Kt}', reason: String(reason && reason.message || reason) }, '*');
74
- } catch {}
75
- };
76
- window.addEventListener('error', (event) => report(event.error || event.message));
77
- window.addEventListener('unhandledrejection', (event) => report(event.reason));
78
- })();
79
- `}function Jn(e,t,r){const n=`<base href="${Gn(t)}">`,i=`<script>${Xn(r)}<\/script>`,s=/<head(?:\s[^>]*)?>/i.exec(e);if(s){const o=s.index+s[0].length;return`${e.slice(0,o)}${n}${i}${e.slice(o)}`}return`${n}${i}${e}`}function Qn(e){if(!e.startsWith("data:"))return null;const t=e.indexOf(",");if(t<0)return"";const r=e.slice(0,t),n=e.slice(t+1);return r.endsWith(";base64")?atob(n):decodeURIComponent(n)}async function er(e){if(e==="about:blank")return"<!doctype html><html><head></head><body></body></html>";const t=Qn(e);if(t!==null)return t;const r=await fetch(e);if(!r.ok)throw new Error(`Failed to fetch napplet HTML: ${r.status} ${r.statusText}`);return r.text()}async function Et(e,t,r,n){const i=Kn(),s=r.createElement("iframe");s.setAttribute("sandbox",t.allowSameOrigin?"allow-scripts allow-same-origin":"allow-scripts"),s.setAttribute("aria-hidden","true"),s.style.position="absolute",s.style.width="1px",s.style.height="1px",s.style.left="-9999px";let o=null;const c=f=>{if(f.source!==s.contentWindow)return;const h=f.data;if(h&&typeof h=="object"&&h.type===Kt){o=`napplet boot error: ${String(h.reason??"unknown error")}`;return}const g=i.handle(f.data),y=f.source;for(const b of g)y?.postMessage(b,"*")};let a=!1;const d=new Promise(f=>{s.addEventListener("load",()=>{a=!0,f()},{once:!0})});n.addEventListener("message",c),(r.body??r.documentElement).appendChild(s);try{const f=await er(t.url);s.srcdoc=Jn(f,t.url,e)}catch(f){o=f instanceof Error?f.message:String(f)}if(!o){const f=Symbol("timeout");await Promise.race([d.then(()=>"loaded"),vt(t.readyTimeoutMs).then(()=>f)])===f||!a?o=`napplet did not boot (iframe did not load within ${t.readyTimeoutMs}ms; a conformant napplet must run under sandbox="allow-scripts" without allow-same-origin)`:await vt(t.settleMs)}n.removeEventListener("message",c);try{s.remove()}catch{}return{installedGlobal:o===null,bootError:o,emitted:[...i.records]}}async function tr(e){const t=e.document??document,r=e.window??window,n={url:e.url,readyTimeoutMs:e.readyTimeoutMs??5e3,settleMs:e.settleMs,allowSameOrigin:e.allowSameOrigin??!1},i=await Et(at,n,t,r);let s=null;{const o=await Et([],n,t,r);s={bootError:o.bootError,emitted:o.emitted}}return{installedGlobal:i.installedGlobal,bootError:i.bootError,emitted:i.emitted,degraded:s}}var nr=e=>({status:"pass",detail:e}),rr=(e,t)=>({status:"fail",detail:e,diagnostics:t}),ir=e=>({status:"skip",detail:e}),O={pass:nr,fail:rr,skip:ir};function sr(e,t){return lt(e.manifestEvent).errors.filter(r=>t.includes(r.code))}function Me(e,t,r){return{id:e,area:"manifest",severity:"error",title:t,run:n=>{if(!n.manifestEvent)return O.skip("No NIP-5D manifest event was resolved");const i=sr(n,r);return i.length?O.fail(i[0].message,i):O.pass()}}}var or=[Me("manifest/event-kind","Resolved event is a NIP-5D napplet manifest",["invalid-napplet-kind","missing-d-tag","unexpected-d-tag"]),Me("manifest/index-html","Manifest declares a hashed /index.html",["missing-index-html","invalid-index-html-hash"]),Me("manifest/requires","requires tags are bare known NAP domains",["invalid-required-nap","unknown-required-nap"]),{id:"boot/sandbox-allow-scripts",area:"boot",severity:"error",title:"Runs under allow-scripts without allow-same-origin",run:e=>e.sandbox.allowScripts?e.sandbox.allowSameOrigin?O.fail("Napplet relied on allow-same-origin, which a shell must not grant"):O.pass():O.fail("Napplet was not loaded with allow-scripts")},{id:"boot/installs-global",area:"boot",severity:"error",title:"Runs after runtime-injected window.napplet is installed",run:e=>e.installedGlobal?O.pass():O.fail("runtime did not inject window.napplet before load")},{id:"boot/no-boot-error",area:"boot",severity:"error",title:"Boots without an uncaught error",run:e=>e.bootError?O.fail(e.bootError):O.pass()},{id:"boot/no-forbidden-globals",area:"boot",severity:"error",title:"Does not access forbidden browser authority surfaces",run:e=>e.forbiddenGlobals.length?O.fail(`Accessed forbidden surface(s): ${e.forbiddenGlobals.join(", ")}`,e.forbiddenGlobals):O.pass()},{id:"wire/envelope-well-formed",area:"wire",severity:"error",title:"Every emitted envelope is well-formed",run:e=>{if(e.emitted.length===0)return O.skip("Napplet emitted no envelopes");const t=e.emitted.filter(n=>!n.verdict.ok);if(t.length===0)return O.pass(`${e.emitted.length} envelope(s) valid`);const r=t.map(n=>({envelope:n.envelope,errors:n.verdict.errors}));return O.fail(`${t.length}/${e.emitted.length} emitted envelope(s) invalid`,r)}},{id:"degrade/domain-absence",area:"degradation",severity:"error",title:"Does not crash when no NAP domains are injected",run:e=>e.degraded?e.degraded.bootError?O.fail(`Crashed with no injected domains: ${e.degraded.bootError}`):O.pass():O.skip("Host did not run the degraded (no-capabilities) pass")},{id:"lifecycle/clean-teardown",area:"lifecycle",severity:"warning",title:"Tears down listeners on unload",run:e=>e.lifecycle?e.lifecycle.listenerLeak?O.fail("Message listeners remained after unload"):O.pass():O.skip("Lifecycle not measured")}];function ar(e,t={}){const r=t.now??(()=>Date.now()),n=t.checks??or,i=r(),s=n.map(a=>{const d=a.run(e);return{id:a.id,area:a.area,severity:a.severity,title:a.title,status:d.status,detail:d.detail,diagnostics:d.diagnostics}}),o={total:s.length,passed:s.filter(a=>a.status==="pass").length,failed:s.filter(a=>a.status==="fail").length,skipped:s.filter(a=>a.status==="skip").length,errors:s.filter(a=>a.status==="fail"&&a.severity==="error").length,warnings:s.filter(a=>a.status==="fail"&&a.severity==="warning").length};return{napplet:e.manifestEvent?Zt(e.manifestEvent):void 0,startedAt:i,finishedAt:r(),checks:s,summary:o,ok:o.errors===0}}/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */function cr(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function dt(e,t=""){if(!Number.isSafeInteger(e)||e<0){const r=t&&`"${t}" `;throw new Error(`${r}expected integer >= 0, got ${e}`)}}function D(e,t,r=""){const n=cr(e),i=e?.length,s=t!==void 0;if(!n||s&&i!==t){const o=r&&`"${r}" `,c=s?` of length ${t}`:"",a=n?`length=${i}`:`type=${typeof e}`;throw new Error(o+"expected Uint8Array"+c+", got "+a)}return e}function xt(e,t=!0){if(e.destroyed)throw new Error("Hash instance has been destroyed");if(t&&e.finished)throw new Error("Hash#digest() has already been called")}function lr(e,t){D(e,void 0,"digestInto() output");const r=t.outputLen;if(e.length<r)throw new Error('"digestInto() output" expected to be of length >='+r)}function Je(...e){for(let t=0;t<e.length;t++)e[t].fill(0)}function Fe(e){return new DataView(e.buffer,e.byteOffset,e.byteLength)}function z(e,t){return e<<32-t|e>>>t}const Yt=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",dr=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function _(e){if(D(e),Yt)return e.toHex();let t="";for(let r=0;r<e.length;r++)t+=dr[e[r]];return t}const J={_0:48,_9:57,A:65,F:70,a:97,f:102};function kt(e){if(e>=J._0&&e<=J._9)return e-J._0;if(e>=J.A&&e<=J.F)return e-(J.A-10);if(e>=J.a&&e<=J.f)return e-(J.a-10)}function X(e){if(typeof e!="string")throw new Error("hex string expected, got "+typeof e);if(Yt)return Uint8Array.fromHex(e);const t=e.length,r=t/2;if(t%2)throw new Error("hex string expected, got unpadded hex of length "+t);const n=new Uint8Array(r);for(let i=0,s=0;i<r;i++,s+=2){const o=kt(e.charCodeAt(s)),c=kt(e.charCodeAt(s+1));if(o===void 0||c===void 0){const a=e[s]+e[s+1];throw new Error('hex string expected, got non-hex character "'+a+'" at index '+s)}n[i]=o*16+c}return n}function Oe(...e){let t=0;for(let n=0;n<e.length;n++){const i=e[n];D(i),t+=i.length}const r=new Uint8Array(t);for(let n=0,i=0;n<e.length;n++){const s=e[n];r.set(s,i),i+=s.length}return r}function ur(e,t={}){const r=(i,s)=>e(s).update(i).digest(),n=e(void 0);return r.outputLen=n.outputLen,r.blockLen=n.blockLen,r.create=i=>e(i),Object.assign(r,t),Object.freeze(r)}function zt(e=32){const t=typeof globalThis=="object"?globalThis.crypto:null;if(typeof t?.getRandomValues!="function")throw new Error("crypto.getRandomValues must be defined");return t.getRandomValues(new Uint8Array(e))}const fr=e=>({oid:Uint8Array.from([6,9,96,134,72,1,101,3,4,2,e])});/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */function Gt(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function Xt(e,t){return Array.isArray(t)?t.length===0?!0:e?t.every(r=>typeof r=="string"):t.every(r=>Number.isSafeInteger(r)):!1}function hr(e){if(typeof e!="function")throw new Error("function expected");return!0}function me(e,t){if(typeof t!="string")throw new Error(`${e}: string expected`);return!0}function Jt(e){if(!Number.isSafeInteger(e))throw new Error(`invalid integer: ${e}`)}function Qe(e){if(!Array.isArray(e))throw new Error("array expected")}function Qt(e,t){if(!Xt(!0,t))throw new Error(`${e}: array of strings expected`)}function en(e,t){if(!Xt(!1,t))throw new Error(`${e}: array of numbers expected`)}function pr(...e){const t=s=>s,r=(s,o)=>c=>s(o(c)),n=e.map(s=>s.encode).reduceRight(r,t),i=e.map(s=>s.decode).reduce(r,t);return{encode:n,decode:i}}function gr(e){const t=typeof e=="string"?e.split(""):e,r=t.length;Qt("alphabet",t);const n=new Map(t.map((i,s)=>[i,s]));return{encode:i=>(Qe(i),i.map(s=>{if(!Number.isSafeInteger(s)||s<0||s>=r)throw new Error(`alphabet.encode: digit index outside alphabet "${s}". Allowed: ${e}`);return t[s]})),decode:i=>(Qe(i),i.map(s=>{me("alphabet.decode",s);const o=n.get(s);if(o===void 0)throw new Error(`Unknown letter: "${s}". Allowed: ${e}`);return o}))}}function yr(e=""){return me("join",e),{encode:t=>(Qt("join.decode",t),t.join(e)),decode:t=>(me("join.decode",t),t.split(e))}}const tn=(e,t)=>t===0?e:tn(t,e%t),qe=(e,t)=>e+(t-tn(e,t)),Ae=(()=>{let e=[];for(let t=0;t<40;t++)e.push(2**t);return e})();function et(e,t,r,n){if(Qe(e),t<=0||t>32)throw new Error(`convertRadix2: wrong from=${t}`);if(r<=0||r>32)throw new Error(`convertRadix2: wrong to=${r}`);if(qe(t,r)>32)throw new Error(`convertRadix2: carry overflow from=${t} to=${r} carryBits=${qe(t,r)}`);let i=0,s=0;const o=Ae[t],c=Ae[r]-1,a=[];for(const d of e){if(Jt(d),d>=o)throw new Error(`convertRadix2: invalid data word=${d} from=${t}`);if(i=i<<t|d,s+t>32)throw new Error(`convertRadix2: carry overflow pos=${s} from=${t}`);for(s+=t;s>=r;s-=r)a.push((i>>s-r&c)>>>0);const f=Ae[s];if(f===void 0)throw new Error("invalid carry");i&=f-1}if(i=i<<r-s&c,!n&&s>=t)throw new Error("Excess padding");if(!n&&i>0)throw new Error(`Non-zero padding: ${i}`);return n&&s>0&&a.push(i>>>0),a}function mr(e,t=!1){if(Jt(e),e<=0||e>32)throw new Error("radix2: bits should be in (0..32]");if(qe(8,e)>32||qe(e,8)>32)throw new Error("radix2: carry overflow");return{encode:r=>{if(!Gt(r))throw new Error("radix2.encode input should be Uint8Array");return et(Array.from(r),8,e,!t)},decode:r=>(en("radix2.decode",r),Uint8Array.from(et(r,e,8,t)))}}function St(e){return hr(e),function(...t){try{return e.apply(null,t)}catch{}}}const tt=pr(gr("qpzry9x8gf2tvdw0s3jn54khce6mua7l"),yr("")),Rt=[996825010,642813549,513874426,1027748829,705979059];function fe(e){const t=e>>25;let r=(e&33554431)<<5;for(let n=0;n<Rt.length;n++)(t>>n&1)===1&&(r^=Rt[n]);return r}function $t(e,t,r=1){const n=e.length;let i=1;for(let s=0;s<n;s++){const o=e.charCodeAt(s);if(o<33||o>126)throw new Error(`Invalid prefix (${e})`);i=fe(i)^o>>5}i=fe(i);for(let s=0;s<n;s++)i=fe(i)^e.charCodeAt(s)&31;for(let s of t)i=fe(i)^s;for(let s=0;s<6;s++)i=fe(i);return i^=r,tt.encode(et([i%Ae[30]],30,5,!1))}function br(e){const t=e==="bech32"?1:734539939,r=mr(5),n=r.decode,i=r.encode,s=St(n);function o(h,g,y=90){me("bech32.encode prefix",h),Gt(g)&&(g=Array.from(g)),en("bech32.encode",g);const b=h.length;if(b===0)throw new TypeError(`Invalid prefix length ${b}`);const E=b+7+g.length;if(y!==!1&&E>y)throw new TypeError(`Length ${E} exceeds limit ${y}`);const q=h.toLowerCase(),L=$t(q,g,t);return`${q}1${tt.encode(g)}${L}`}function c(h,g=90){me("bech32.decode input",h);const y=h.length;if(y<8||g!==!1&&y>g)throw new TypeError(`invalid string length: ${y} (${h}). Expected (8..${g})`);const b=h.toLowerCase();if(h!==b&&h!==h.toUpperCase())throw new Error("String must be lowercase or uppercase");const E=b.lastIndexOf("1");if(E===0||E===-1)throw new Error('Letter "1" must be present between prefix and data only');const q=b.slice(0,E),L=b.slice(E+1);if(L.length<6)throw new Error("Data must be at least 6 characters long");const K=tt.decode(L).slice(0,-6),Q=$t(q,K,t);if(!L.endsWith(Q))throw new Error(`Invalid checksum in ${h}: expected "${Q}"`);return{prefix:q,words:K}}const a=St(c);function d(h){const{prefix:g,words:y}=c(h,!1);return{prefix:g,words:y,bytes:n(y)}}function f(h,g){return o(h,i(g))}return{encode:o,decode:c,encodeFromBytes:f,decodeToBytes:d,decodeUnsafe:a,fromWords:n,fromWordsUnsafe:s,toWords:i}}const It=br("bech32");var Re=new TextDecoder("utf-8");new TextEncoder;var wr=5e3;function vr(e){try{return e.startsWith("nostr:")&&(e=e.substring(6)),Er(e)}catch{return{type:"invalid",data:null}}}function Er(e){let{prefix:t,words:r}=It.decode(e,wr),n=new Uint8Array(It.fromWords(r));switch(t){case"nprofile":{let i=We(n);if(!i[0]?.[0])throw new Error("missing TLV 0 for nprofile");if(i[0][0].length!==32)throw new Error("TLV 0 should be 32 bytes");return{type:"nprofile",data:{pubkey:_(i[0][0]),relays:i[1]?i[1].map(s=>Re.decode(s)):[]}}}case"nevent":{let i=We(n);if(!i[0]?.[0])throw new Error("missing TLV 0 for nevent");if(i[0][0].length!==32)throw new Error("TLV 0 should be 32 bytes");if(i[2]&&i[2][0].length!==32)throw new Error("TLV 2 should be 32 bytes");if(i[3]&&i[3][0].length!==4)throw new Error("TLV 3 should be 4 bytes");return{type:"nevent",data:{id:_(i[0][0]),relays:i[1]?i[1].map(s=>Re.decode(s)):[],author:i[2]?.[0]?_(i[2][0]):void 0,kind:i[3]?.[0]?parseInt(_(i[3][0]),16):void 0}}}case"naddr":{let i=We(n);if(!i[0]?.[0])throw new Error("missing TLV 0 for naddr");if(!i[2]?.[0])throw new Error("missing TLV 2 for naddr");if(i[2][0].length!==32)throw new Error("TLV 2 should be 32 bytes");if(!i[3]?.[0])throw new Error("missing TLV 3 for naddr");if(i[3][0].length!==4)throw new Error("TLV 3 should be 4 bytes");return{type:"naddr",data:{identifier:Re.decode(i[0][0]),pubkey:_(i[2][0]),kind:parseInt(_(i[3][0]),16),relays:i[1]?i[1].map(s=>Re.decode(s)):[]}}}case"nsec":return{type:t,data:n};case"npub":case"note":return{type:t,data:_(n)};default:throw new Error(`unknown prefix ${t}`)}}function We(e){let t={},r=e;for(;r.length>0;){let n=r[0],i=r[1],s=r.slice(2,2+i);if(r=r.slice(2+i),s.length<i)throw new Error(`not enough data to read on TLV ${n}`);t[n]=t[n]||[],t[n].push(s)}return t}function xr(e,t,r){return e&t^~e&r}function kr(e,t,r){return e&t^e&r^t&r}class Sr{blockLen;outputLen;padOffset;isLE;buffer;view;finished=!1;length=0;pos=0;destroyed=!1;constructor(t,r,n,i){this.blockLen=t,this.outputLen=r,this.padOffset=n,this.isLE=i,this.buffer=new Uint8Array(t),this.view=Fe(this.buffer)}update(t){xt(this),D(t);const{view:r,buffer:n,blockLen:i}=this,s=t.length;for(let o=0;o<s;){const c=Math.min(i-this.pos,s-o);if(c===i){const a=Fe(t);for(;i<=s-o;o+=i)this.process(a,o);continue}n.set(t.subarray(o,o+c),this.pos),this.pos+=c,o+=c,this.pos===i&&(this.process(r,0),this.pos=0)}return this.length+=t.length,this.roundClean(),this}digestInto(t){xt(this),lr(t,this),this.finished=!0;const{buffer:r,view:n,blockLen:i,isLE:s}=this;let{pos:o}=this;r[o++]=128,Je(this.buffer.subarray(o)),this.padOffset>i-o&&(this.process(n,0),o=0);for(let h=o;h<i;h++)r[h]=0;n.setBigUint64(i-8,BigInt(this.length*8),s),this.process(n,0);const c=Fe(t),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen must be aligned to 32bit");const d=a/4,f=this.get();if(d>f.length)throw new Error("_sha2: outputLen bigger than state");for(let h=0;h<d;h++)c.setUint32(4*h,f[h],s)}digest(){const{buffer:t,outputLen:r}=this;this.digestInto(t);const n=t.slice(0,r);return this.destroy(),n}_cloneInto(t){t||=new this.constructor,t.set(...this.get());const{blockLen:r,buffer:n,length:i,finished:s,destroyed:o,pos:c}=this;return t.destroyed=o,t.finished=s,t.length=i,t.pos=c,i%r&&t.buffer.set(n),t}clone(){return this._cloneInto()}}const ee=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),Rr=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),te=new Uint32Array(64);class $r extends Sr{constructor(t){super(64,t,8,!1)}get(){const{A:t,B:r,C:n,D:i,E:s,F:o,G:c,H:a}=this;return[t,r,n,i,s,o,c,a]}set(t,r,n,i,s,o,c,a){this.A=t|0,this.B=r|0,this.C=n|0,this.D=i|0,this.E=s|0,this.F=o|0,this.G=c|0,this.H=a|0}process(t,r){for(let h=0;h<16;h++,r+=4)te[h]=t.getUint32(r,!1);for(let h=16;h<64;h++){const g=te[h-15],y=te[h-2],b=z(g,7)^z(g,18)^g>>>3,E=z(y,17)^z(y,19)^y>>>10;te[h]=E+te[h-7]+b+te[h-16]|0}let{A:n,B:i,C:s,D:o,E:c,F:a,G:d,H:f}=this;for(let h=0;h<64;h++){const g=z(c,6)^z(c,11)^z(c,25),y=f+g+xr(c,a,d)+Rr[h]+te[h]|0,E=(z(n,2)^z(n,13)^z(n,22))+kr(n,i,s)|0;f=d,d=a,a=c,c=o+y|0,o=s,s=i,i=n,n=y+E|0}n=n+this.A|0,i=i+this.B|0,s=s+this.C|0,o=o+this.D|0,c=c+this.E|0,a=a+this.F|0,d=d+this.G|0,f=f+this.H|0,this.set(n,i,s,o,c,a,d,f)}roundClean(){Je(te)}destroy(){this.set(0,0,0,0,0,0,0,0),Je(this.buffer)}}class Ir extends $r{A=ee[0]|0;B=ee[1]|0;C=ee[2]|0;D=ee[3]|0;E=ee[4]|0;F=ee[5]|0;G=ee[6]|0;H=ee[7]|0;constructor(){super(32)}}const Ne=ur(()=>new Ir,fr(1));/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const ut=BigInt(0),nt=BigInt(1);function At(e,t=""){if(typeof e!="boolean"){const r=t&&`"${t}" `;throw new Error(r+"expected boolean, got type="+typeof e)}return e}function Ar(e){if(typeof e=="bigint"){if(!Or(e))throw new Error("positive bigint expected, got "+e)}else dt(e);return e}function nn(e){if(typeof e!="string")throw new Error("hex string expected, got "+typeof e);return e===""?ut:BigInt("0x"+e)}function ft(e){return nn(_(e))}function rn(e){return nn(_(Tr(D(e)).reverse()))}function ht(e,t){dt(t),e=Ar(e);const r=X(e.toString(16).padStart(t*2,"0"));if(r.length!==t)throw new Error("number too large");return r}function sn(e,t){return ht(e,t).reverse()}function Tr(e){return Uint8Array.from(e)}function Br(e){return Uint8Array.from(e,(t,r)=>{const n=t.charCodeAt(0);if(t.length!==1||n>127)throw new Error(`string contains non-ASCII character "${e[r]}" with code ${n} at position ${r}`);return n})}const Or=e=>typeof e=="bigint"&&ut<=e;function qr(e){let t;for(t=0;e>ut;e>>=nt,t+=1);return t}const on=e=>(nt<<BigInt(e))-nt;function an(e,t={},r={}){if(!e||typeof e!="object")throw new Error("expected valid options object");function n(s,o,c){const a=e[s];if(c&&a===void 0)return;const d=typeof a;if(d!==o||a===null)throw new Error(`param "${s}" is invalid: expected ${o}, got ${d}`)}const i=(s,o)=>Object.entries(s).forEach(([c,a])=>n(c,a,o));i(t,!1),i(r,!0)}function Tt(e){const t=new WeakMap;return(r,...n)=>{const i=t.get(r);if(i!==void 0)return i;const s=e(r,...n);return t.set(r,s),s}}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const j=BigInt(0),H=BigInt(1),se=BigInt(2),cn=BigInt(3),ln=BigInt(4),dn=BigInt(5),Nr=BigInt(7),un=BigInt(8),Lr=BigInt(9),fn=BigInt(16);function V(e,t){const r=e%t;return r>=j?r:t+r}function F(e,t,r){let n=e;for(;t-- >j;)n*=n,n%=r;return n}function Bt(e,t){if(e===j)throw new Error("invert: expected non-zero number");if(t<=j)throw new Error("invert: expected positive modulus, got "+t);let r=V(e,t),n=t,i=j,s=H;for(;r!==j;){const c=n/r,a=n%r,d=i-s*c;n=r,r=a,i=s,s=d}if(n!==H)throw new Error("invert: does not exist");return V(i,t)}function pt(e,t,r){if(!e.eql(e.sqr(t),r))throw new Error("Cannot find square root")}function hn(e,t){const r=(e.ORDER+H)/ln,n=e.pow(t,r);return pt(e,n,t),n}function Pr(e,t){const r=(e.ORDER-dn)/un,n=e.mul(t,se),i=e.pow(n,r),s=e.mul(t,i),o=e.mul(e.mul(s,se),i),c=e.mul(s,e.sub(o,e.ONE));return pt(e,c,t),c}function _r(e){const t=Ce(e),r=pn(e),n=r(t,t.neg(t.ONE)),i=r(t,n),s=r(t,t.neg(n)),o=(e+Nr)/fn;return(c,a)=>{let d=c.pow(a,o),f=c.mul(d,n);const h=c.mul(d,i),g=c.mul(d,s),y=c.eql(c.sqr(f),a),b=c.eql(c.sqr(h),a);d=c.cmov(d,f,y),f=c.cmov(g,h,b);const E=c.eql(c.sqr(f),a),q=c.cmov(d,f,E);return pt(c,q,a),q}}function pn(e){if(e<cn)throw new Error("sqrt is not defined for small field");let t=e-H,r=0;for(;t%se===j;)t/=se,r++;let n=se;const i=Ce(e);for(;Ot(i,n)===1;)if(n++>1e3)throw new Error("Cannot find square root: probably non-prime P");if(r===1)return hn;let s=i.pow(n,t);const o=(t+H)/se;return function(a,d){if(a.is0(d))return d;if(Ot(a,d)!==1)throw new Error("Cannot find square root");let f=r,h=a.mul(a.ONE,s),g=a.pow(d,t),y=a.pow(d,o);for(;!a.eql(g,a.ONE);){if(a.is0(g))return a.ZERO;let b=1,E=a.sqr(g);for(;!a.eql(E,a.ONE);)if(b++,E=a.sqr(E),b===f)throw new Error("Cannot find square root");const q=H<<BigInt(f-b-1),L=a.pow(h,q);f=b,h=a.sqr(L),g=a.mul(g,h),y=a.mul(y,L)}return y}}function Cr(e){return e%ln===cn?hn:e%un===dn?Pr:e%fn===Lr?_r(e):pn(e)}const Ur=["create","isValid","is0","neg","inv","sqrt","sqr","eql","add","sub","mul","pow","div","addN","subN","mulN","sqrN"];function Hr(e){const t={ORDER:"bigint",BYTES:"number",BITS:"number"},r=Ur.reduce((n,i)=>(n[i]="function",n),t);return an(e,r),e}function jr(e,t,r){if(r<j)throw new Error("invalid exponent, negatives unsupported");if(r===j)return e.ONE;if(r===H)return t;let n=e.ONE,i=t;for(;r>j;)r&H&&(n=e.mul(n,i)),i=e.sqr(i),r>>=H;return n}function gn(e,t,r=!1){const n=new Array(t.length).fill(r?e.ZERO:void 0),i=t.reduce((o,c,a)=>e.is0(c)?o:(n[a]=o,e.mul(o,c)),e.ONE),s=e.inv(i);return t.reduceRight((o,c,a)=>e.is0(c)?o:(n[a]=e.mul(o,n[a]),e.mul(o,c)),s),n}function Ot(e,t){const r=(e.ORDER-H)/se,n=e.pow(t,r),i=e.eql(n,e.ONE),s=e.eql(n,e.ZERO),o=e.eql(n,e.neg(e.ONE));if(!i&&!s&&!o)throw new Error("invalid Legendre symbol result");return i?1:s?0:-1}function Dr(e,t){t!==void 0&&dt(t);const r=t!==void 0?t:e.toString(2).length,n=Math.ceil(r/8);return{nBitLength:r,nByteLength:n}}class Mr{ORDER;BITS;BYTES;isLE;ZERO=j;ONE=H;_lengths;_sqrt;_mod;constructor(t,r={}){if(t<=j)throw new Error("invalid field: expected ORDER > 0, got "+t);let n;this.isLE=!1,r!=null&&typeof r=="object"&&(typeof r.BITS=="number"&&(n=r.BITS),typeof r.sqrt=="function"&&(this.sqrt=r.sqrt),typeof r.isLE=="boolean"&&(this.isLE=r.isLE),r.allowedLengths&&(this._lengths=r.allowedLengths?.slice()),typeof r.modFromBytes=="boolean"&&(this._mod=r.modFromBytes));const{nBitLength:i,nByteLength:s}=Dr(t,n);if(s>2048)throw new Error("invalid field: expected ORDER of <= 2048 bytes");this.ORDER=t,this.BITS=i,this.BYTES=s,this._sqrt=void 0,Object.preventExtensions(this)}create(t){return V(t,this.ORDER)}isValid(t){if(typeof t!="bigint")throw new Error("invalid field element: expected bigint, got "+typeof t);return j<=t&&t<this.ORDER}is0(t){return t===j}isValidNot0(t){return!this.is0(t)&&this.isValid(t)}isOdd(t){return(t&H)===H}neg(t){return V(-t,this.ORDER)}eql(t,r){return t===r}sqr(t){return V(t*t,this.ORDER)}add(t,r){return V(t+r,this.ORDER)}sub(t,r){return V(t-r,this.ORDER)}mul(t,r){return V(t*r,this.ORDER)}pow(t,r){return jr(this,t,r)}div(t,r){return V(t*Bt(r,this.ORDER),this.ORDER)}sqrN(t){return t*t}addN(t,r){return t+r}subN(t,r){return t-r}mulN(t,r){return t*r}inv(t){return Bt(t,this.ORDER)}sqrt(t){return this._sqrt||(this._sqrt=Cr(this.ORDER)),this._sqrt(this,t)}toBytes(t){return this.isLE?sn(t,this.BYTES):ht(t,this.BYTES)}fromBytes(t,r=!1){D(t);const{_lengths:n,BYTES:i,isLE:s,ORDER:o,_mod:c}=this;if(n){if(!n.includes(t.length)||t.length>i)throw new Error("Field.fromBytes: expected "+n+" bytes, got "+t.length);const d=new Uint8Array(i);d.set(t,s?0:d.length-t.length),t=d}if(t.length!==i)throw new Error("Field.fromBytes: expected "+i+" bytes, got "+t.length);let a=s?rn(t):ft(t);if(c&&(a=V(a,o)),!r&&!this.isValid(a))throw new Error("invalid field element: outside of range 0..ORDER");return a}invertBatch(t){return gn(this,t)}cmov(t,r,n){return n?r:t}}function Ce(e,t={}){return new Mr(e,t)}function yn(e){if(typeof e!="bigint")throw new Error("field order must be bigint");const t=e.toString(2).length;return Math.ceil(t/8)}function Fr(e){const t=yn(e);return t+Math.ceil(t/2)}function Wr(e,t,r=!1){D(e);const n=e.length,i=yn(t),s=Fr(t);if(n<16||n<s||n>1024)throw new Error("expected "+s+"-1024 bytes of input, got "+n);const o=r?rn(e):ft(e),c=V(o,t-H)+H;return r?sn(c,i):ht(c,i)}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const le=BigInt(0),oe=BigInt(1);function Le(e,t){const r=t.negate();return e?r:t}function qt(e,t){const r=gn(e.Fp,t.map(n=>n.Z));return t.map((n,i)=>e.fromAffine(n.toAffine(r[i])))}function mn(e,t){if(!Number.isSafeInteger(e)||e<=0||e>t)throw new Error("invalid window size, expected [1.."+t+"], got W="+e)}function Ze(e,t){mn(e,t);const r=Math.ceil(t/e)+1,n=2**(e-1),i=2**e,s=on(e),o=BigInt(e);return{windows:r,windowSize:n,mask:s,maxNumber:i,shiftBy:o}}function Nt(e,t,r){const{windowSize:n,mask:i,maxNumber:s,shiftBy:o}=r;let c=Number(e&i),a=e>>o;c>n&&(c-=s,a+=oe);const d=t*n,f=d+Math.abs(c)-1,h=c===0,g=c<0,y=t%2!==0;return{nextN:a,offset:f,isZero:h,isNeg:g,isNegF:y,offsetF:d}}const Ve=new WeakMap,bn=new WeakMap;function Ke(e){return bn.get(e)||1}function Lt(e){if(e!==le)throw new Error("invalid wNAF")}class Zr{BASE;ZERO;Fn;bits;constructor(t,r){this.BASE=t.BASE,this.ZERO=t.ZERO,this.Fn=t.Fn,this.bits=r}_unsafeLadder(t,r,n=this.ZERO){let i=t;for(;r>le;)r&oe&&(n=n.add(i)),i=i.double(),r>>=oe;return n}precomputeWindow(t,r){const{windows:n,windowSize:i}=Ze(r,this.bits),s=[];let o=t,c=o;for(let a=0;a<n;a++){c=o,s.push(c);for(let d=1;d<i;d++)c=c.add(o),s.push(c);o=c.double()}return s}wNAF(t,r,n){if(!this.Fn.isValid(n))throw new Error("invalid scalar");let i=this.ZERO,s=this.BASE;const o=Ze(t,this.bits);for(let c=0;c<o.windows;c++){const{nextN:a,offset:d,isZero:f,isNeg:h,isNegF:g,offsetF:y}=Nt(n,c,o);n=a,f?s=s.add(Le(g,r[y])):i=i.add(Le(h,r[d]))}return Lt(n),{p:i,f:s}}wNAFUnsafe(t,r,n,i=this.ZERO){const s=Ze(t,this.bits);for(let o=0;o<s.windows&&n!==le;o++){const{nextN:c,offset:a,isZero:d,isNeg:f}=Nt(n,o,s);if(n=c,!d){const h=r[a];i=i.add(f?h.negate():h)}}return Lt(n),i}getPrecomputes(t,r,n){let i=Ve.get(r);return i||(i=this.precomputeWindow(r,t),t!==1&&(typeof n=="function"&&(i=n(i)),Ve.set(r,i))),i}cached(t,r,n){const i=Ke(t);return this.wNAF(i,this.getPrecomputes(i,t,n),r)}unsafe(t,r,n,i){const s=Ke(t);return s===1?this._unsafeLadder(t,r,i):this.wNAFUnsafe(s,this.getPrecomputes(s,t,n),r,i)}createCache(t,r){mn(r,this.bits),bn.set(t,r),Ve.delete(t)}hasCache(t){return Ke(t)!==1}}function Vr(e,t,r,n){let i=t,s=e.ZERO,o=e.ZERO;for(;r>le||n>le;)r&oe&&(s=s.add(i)),n&oe&&(o=o.add(i)),i=i.double(),r>>=oe,n>>=oe;return{p1:s,p2:o}}function Pt(e,t,r){if(t){if(t.ORDER!==e)throw new Error("Field.ORDER must match order: Fp == p, Fn == n");return Hr(t),t}else return Ce(e,{isLE:r})}function Kr(e,t,r={},n){if(n===void 0&&(n=e==="edwards"),!t||typeof t!="object")throw new Error(`expected valid ${e} CURVE object`);for(const a of["p","n","h"]){const d=t[a];if(!(typeof d=="bigint"&&d>le))throw new Error(`CURVE.${a} must be positive bigint`)}const i=Pt(t.p,r.Fp,n),s=Pt(t.n,r.Fn,n),c=["Gx","Gy","a","b"];for(const a of c)if(!i.isValid(t[a]))throw new Error(`CURVE.${a} must be valid field element of CURVE.Fp`);return t=Object.freeze(Object.assign({},t)),{CURVE:t,Fp:i,Fn:s}}function Yr(e,t){return function(n){const i=e(n);return{secretKey:i,publicKey:t(i)}}}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const _t=(e,t)=>(e+(e>=0?t:-t)/Gr)/t;function zr(e,t,r){const[[n,i],[s,o]]=t,c=_t(o*e,r),a=_t(-i*e,r);let d=e-c*n-a*s,f=-c*i-a*o;const h=d<he,g=f<he;h&&(d=-d),g&&(f=-f);const y=on(Math.ceil(qr(r)/2))+Te;if(d<he||d>=y||f<he||f>=y)throw new Error("splitScalar (endomorphism): failed, k="+e);return{k1neg:h,k1:d,k2neg:g,k2:f}}const he=BigInt(0),Te=BigInt(1),Gr=BigInt(2),$e=BigInt(3),Xr=BigInt(4);function Jr(e,t={}){const r=Kr("weierstrass",e,t),{Fp:n,Fn:i}=r;let s=r.CURVE;const{h:o,n:c}=s;an(t,{},{allowInfinityPoint:"boolean",clearCofactor:"function",isTorsionFree:"function",fromBytes:"function",toBytes:"function",endo:"object"});const{endo:a}=t;if(a&&(!n.is0(s.a)||typeof a.beta!="bigint"||!Array.isArray(a.basises)))throw new Error('invalid endo: expected "beta": bigint and "basises": array');const d=ei(n,i);function f(){if(!n.isOdd)throw new Error("compression is not supported: Field does not have .isOdd()")}function h(I,p,m){const{x:v,y:x}=p.toAffine(),A=n.toBytes(v);if(At(m,"isCompressed"),m){f();const R=!n.isOdd(x);return Oe(Qr(R),A)}else return Oe(Uint8Array.of(4),A,n.toBytes(x))}function g(I){D(I,void 0,"Point");const{publicKey:p,publicKeyUncompressed:m}=d,v=I.length,x=I[0],A=I.subarray(1);if(v===p&&(x===2||x===3)){const R=n.fromBytes(A);if(!n.isValid(R))throw new Error("bad point: is not on curve, wrong x");const k=E(R);let w;try{w=n.sqrt(k)}catch(M){const P=M instanceof Error?": "+M.message:"";throw new Error("bad point: is not on curve, sqrt error"+P)}f();const S=n.isOdd(w);return(x&1)===1!==S&&(w=n.neg(w)),{x:R,y:w}}else if(v===m&&x===4){const R=n.BYTES,k=n.fromBytes(A.subarray(0,R)),w=n.fromBytes(A.subarray(R,R*2));if(!q(k,w))throw new Error("bad point: is not on curve");return{x:k,y:w}}else throw new Error(`bad point: got length ${v}, expected compressed=${p} or uncompressed=${m}`)}const y=t.toBytes||h,b=t.fromBytes||g;function E(I){const p=n.sqr(I),m=n.mul(p,I);return n.add(n.add(m,n.mul(I,s.a)),s.b)}function q(I,p){const m=n.sqr(p),v=E(I);return n.eql(m,v)}if(!q(s.Gx,s.Gy))throw new Error("bad curve params: generator point");const L=n.mul(n.pow(s.a,$e),Xr),K=n.mul(n.sqr(s.b),BigInt(27));if(n.is0(n.add(L,K)))throw new Error("bad curve params: a or b");function Q(I,p,m=!1){if(!n.isValid(p)||m&&n.is0(p))throw new Error(`bad point coordinate ${I}`);return p}function we(I){if(!(I instanceof B))throw new Error("Weierstrass Point expected")}function ve(I){if(!a||!a.basises)throw new Error("no endo");return zr(I,a.basises,i.ORDER)}const Ee=Tt((I,p)=>{const{X:m,Y:v,Z:x}=I;if(n.eql(x,n.ONE))return{x:m,y:v};const A=I.is0();p==null&&(p=A?n.ONE:n.inv(x));const R=n.mul(m,p),k=n.mul(v,p),w=n.mul(x,p);if(A)return{x:n.ZERO,y:n.ZERO};if(!n.eql(w,n.ONE))throw new Error("invZ was invalid");return{x:R,y:k}}),In=Tt(I=>{if(I.is0()){if(t.allowInfinityPoint&&!n.is0(I.Y))return;throw new Error("bad point: ZERO")}const{x:p,y:m}=I.toAffine();if(!n.isValid(p)||!n.isValid(m))throw new Error("bad point: x or y not field elements");if(!q(p,m))throw new Error("bad point: equation left != right");if(!I.isTorsionFree())throw new Error("bad point: not in prime-order subgroup");return!0});function mt(I,p,m,v,x){return m=new B(n.mul(m.X,I),m.Y,m.Z),p=Le(v,p),m=Le(x,m),p.add(m)}class B{static BASE=new B(s.Gx,s.Gy,n.ONE);static ZERO=new B(n.ZERO,n.ONE,n.ZERO);static Fp=n;static Fn=i;X;Y;Z;constructor(p,m,v){this.X=Q("x",p),this.Y=Q("y",m,!0),this.Z=Q("z",v),Object.freeze(this)}static CURVE(){return s}static fromAffine(p){const{x:m,y:v}=p||{};if(!p||!n.isValid(m)||!n.isValid(v))throw new Error("invalid affine point");if(p instanceof B)throw new Error("projective point not allowed");return n.is0(m)&&n.is0(v)?B.ZERO:new B(m,v,n.ONE)}static fromBytes(p){const m=B.fromAffine(b(D(p,void 0,"point")));return m.assertValidity(),m}static fromHex(p){return B.fromBytes(X(p))}get x(){return this.toAffine().x}get y(){return this.toAffine().y}precompute(p=8,m=!0){return ue.createCache(this,p),m||this.multiply($e),this}assertValidity(){In(this)}hasEvenY(){const{y:p}=this.toAffine();if(!n.isOdd)throw new Error("Field doesn't support isOdd");return!n.isOdd(p)}equals(p){we(p);const{X:m,Y:v,Z:x}=this,{X:A,Y:R,Z:k}=p,w=n.eql(n.mul(m,k),n.mul(A,x)),S=n.eql(n.mul(v,k),n.mul(R,x));return w&&S}negate(){return new B(this.X,n.neg(this.Y),this.Z)}double(){const{a:p,b:m}=s,v=n.mul(m,$e),{X:x,Y:A,Z:R}=this;let k=n.ZERO,w=n.ZERO,S=n.ZERO,$=n.mul(x,x),M=n.mul(A,A),P=n.mul(R,R),T=n.mul(x,A);return T=n.add(T,T),S=n.mul(x,R),S=n.add(S,S),k=n.mul(p,S),w=n.mul(v,P),w=n.add(k,w),k=n.sub(M,w),w=n.add(M,w),w=n.mul(k,w),k=n.mul(T,k),S=n.mul(v,S),P=n.mul(p,P),T=n.sub($,P),T=n.mul(p,T),T=n.add(T,S),S=n.add($,$),$=n.add(S,$),$=n.add($,P),$=n.mul($,T),w=n.add(w,$),P=n.mul(A,R),P=n.add(P,P),$=n.mul(P,T),k=n.sub(k,$),S=n.mul(P,M),S=n.add(S,S),S=n.add(S,S),new B(k,w,S)}add(p){we(p);const{X:m,Y:v,Z:x}=this,{X:A,Y:R,Z:k}=p;let w=n.ZERO,S=n.ZERO,$=n.ZERO;const M=s.a,P=n.mul(s.b,$e);let T=n.mul(m,A),W=n.mul(v,R),Z=n.mul(x,k),ae=n.add(m,v),U=n.add(A,R);ae=n.mul(ae,U),U=n.add(T,W),ae=n.sub(ae,U),U=n.add(m,x);let Y=n.add(A,k);return U=n.mul(U,Y),Y=n.add(T,Z),U=n.sub(U,Y),Y=n.add(v,x),w=n.add(R,k),Y=n.mul(Y,w),w=n.add(W,Z),Y=n.sub(Y,w),$=n.mul(M,U),w=n.mul(P,Z),$=n.add(w,$),w=n.sub(W,$),$=n.add(W,$),S=n.mul(w,$),W=n.add(T,T),W=n.add(W,T),Z=n.mul(M,Z),U=n.mul(P,U),W=n.add(W,Z),Z=n.sub(T,Z),Z=n.mul(M,Z),U=n.add(U,Z),T=n.mul(W,U),S=n.add(S,T),T=n.mul(Y,U),w=n.mul(ae,w),w=n.sub(w,T),T=n.mul(ae,W),$=n.mul(Y,$),$=n.add($,T),new B(w,S,$)}subtract(p){return this.add(p.negate())}is0(){return this.equals(B.ZERO)}multiply(p){const{endo:m}=t;if(!i.isValidNot0(p))throw new Error("invalid scalar: out of range");let v,x;const A=R=>ue.cached(this,R,k=>qt(B,k));if(m){const{k1neg:R,k1:k,k2neg:w,k2:S}=ve(p),{p:$,f:M}=A(k),{p:P,f:T}=A(S);x=M.add(T),v=mt(m.beta,$,P,R,w)}else{const{p:R,f:k}=A(p);v=R,x=k}return qt(B,[v,x])[0]}multiplyUnsafe(p){const{endo:m}=t,v=this;if(!i.isValid(p))throw new Error("invalid scalar: out of range");if(p===he||v.is0())return B.ZERO;if(p===Te)return v;if(ue.hasCache(this))return this.multiply(p);if(m){const{k1neg:x,k1:A,k2neg:R,k2:k}=ve(p),{p1:w,p2:S}=Vr(B,v,A,k);return mt(m.beta,w,S,x,R)}else return ue.unsafe(v,p)}toAffine(p){return Ee(this,p)}isTorsionFree(){const{isTorsionFree:p}=t;return o===Te?!0:p?p(B,this):ue.unsafe(this,c).is0()}clearCofactor(){const{clearCofactor:p}=t;return o===Te?this:p?p(B,this):this.multiplyUnsafe(o)}isSmallOrder(){return this.multiplyUnsafe(o).is0()}toBytes(p=!0){return At(p,"isCompressed"),this.assertValidity(),y(B,this,p)}toHex(p=!0){return _(this.toBytes(p))}toString(){return`<Point ${this.is0()?"ZERO":this.toHex()}>`}}const bt=i.BITS,ue=new Zr(B,t.endo?Math.ceil(bt/2):bt);return B.BASE.precompute(8),B}function Qr(e){return Uint8Array.of(e?2:3)}function ei(e,t){return{secretKey:t.BYTES,publicKey:1+e.BYTES,publicKeyUncompressed:1+2*e.BYTES,publicKeyHasPrefix:!0,signature:2*t.BYTES}}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const Ue={p:BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"),n:BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),h:BigInt(1),a:BigInt(0),b:BigInt(7),Gx:BigInt("0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"),Gy:BigInt("0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8")},ti={beta:BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"),basises:[[BigInt("0x3086d221a7d46bcde86c90e49284eb15"),-BigInt("0xe4437ed6010e88286f547fa90abfe4c3")],[BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8"),BigInt("0x3086d221a7d46bcde86c90e49284eb15")]]},ni=BigInt(0),rt=BigInt(2);function ri(e){const t=Ue.p,r=BigInt(3),n=BigInt(6),i=BigInt(11),s=BigInt(22),o=BigInt(23),c=BigInt(44),a=BigInt(88),d=e*e*e%t,f=d*d*e%t,h=F(f,r,t)*f%t,g=F(h,r,t)*f%t,y=F(g,rt,t)*d%t,b=F(y,i,t)*y%t,E=F(b,s,t)*b%t,q=F(E,c,t)*E%t,L=F(q,a,t)*q%t,K=F(L,c,t)*E%t,Q=F(K,r,t)*f%t,we=F(Q,o,t)*b%t,ve=F(we,n,t)*d%t,Ee=F(ve,rt,t);if(!Pe.eql(Pe.sqr(Ee),e))throw new Error("Cannot find square root");return Ee}const Pe=Ce(Ue.p,{sqrt:ri}),de=Jr(Ue,{Fp:Pe,endo:ti}),Ct={};function _e(e,...t){let r=Ct[e];if(r===void 0){const n=Ne(Br(e));r=Oe(n,n),Ct[e]=r}return Ne(Oe(r,...t))}const gt=e=>e.toBytes(!0).slice(1),yt=e=>e%rt===ni;function it(e){const{Fn:t,BASE:r}=de,n=t.fromBytes(e),i=r.multiply(n);return{scalar:yt(i.y)?n:t.neg(n),bytes:gt(i)}}function wn(e){const t=Pe;if(!t.isValidNot0(e))throw new Error("invalid x: Fail if x ≥ p");const r=t.create(e*e),n=t.create(r*e+BigInt(7));let i=t.sqrt(n);yt(i)||(i=t.neg(i));const s=de.fromAffine({x:e,y:i});return s.assertValidity(),s}const ye=ft;function vn(...e){return de.Fn.create(ye(_e("BIP0340/challenge",...e)))}function Ut(e){return it(e).bytes}function ii(e,t,r=zt(32)){const{Fn:n}=de,i=D(e,void 0,"message"),{bytes:s,scalar:o}=it(t),c=D(r,32,"auxRand"),a=n.toBytes(o^ye(_e("BIP0340/aux",c))),d=_e("BIP0340/nonce",a,s,i),{bytes:f,scalar:h}=it(d),g=vn(f,s,i),y=new Uint8Array(64);if(y.set(f,0),y.set(n.toBytes(n.create(h+g*o)),32),!En(y,i,s))throw new Error("sign: Invalid signature produced");return y}function En(e,t,r){const{Fp:n,Fn:i,BASE:s}=de,o=D(e,64,"signature"),c=D(t,void 0,"message"),a=D(r,32,"publicKey");try{const d=wn(ye(a)),f=ye(o.subarray(0,32));if(!n.isValidNot0(f))return!1;const h=ye(o.subarray(32,64));if(!i.isValidNot0(h))return!1;const g=vn(i.toBytes(f),gt(d),c),y=s.multiplyUnsafe(h).add(d.multiplyUnsafe(i.neg(g))),{x:b,y:E}=y.toAffine();return!(y.is0()||!yt(E)||b!==f)}catch{return!1}}const G=(()=>{const r=(n=zt(48))=>Wr(n,Ue.n);return{keygen:Yr(r,Ut),getPublicKey:Ut,sign:ii,verify:En,Point:de,utils:{randomSecretKey:r,taggedHash:_e,lift_x:wn,pointToBytes:gt},lengths:{secretKey:32,publicKey:32,publicKeyHasPrefix:!1,signature:64,seed:48}}})();var ie=Symbol("verified"),si=e=>e instanceof Object;function oi(e){if(!si(e)||typeof e.kind!="number"||typeof e.content!="string"||typeof e.created_at!="number"||typeof e.pubkey!="string"||!e.pubkey.match(/^[a-f0-9]{64}$/)||!Array.isArray(e.tags))return!1;for(let t=0;t<e.tags.length;t++){let r=e.tags[t];if(!Array.isArray(r))return!1;for(let n=0;n<r.length;n++)if(typeof r[n]!="string")return!1}return!0}new TextDecoder("utf-8");var ai=new TextEncoder;function pe(e){try{e.indexOf("://")===-1&&(e="wss://"+e);let t=new URL(e);return t.protocol==="http:"?t.protocol="ws:":t.protocol==="https:"&&(t.protocol="wss:"),t.pathname=t.pathname.replace(/\/+/g,"/"),t.pathname.endsWith("/")&&(t.pathname=t.pathname.slice(0,-1)),(t.port==="80"&&t.protocol==="ws:"||t.port==="443"&&t.protocol==="wss:")&&(t.port=""),t.searchParams.sort(),t.hash="",t.toString()}catch{throw new Error(`Invalid URL: ${e}`)}}var ci=class{generateSecretKey(){return G.utils.randomSecretKey()}getPublicKey(t){return _(G.getPublicKey(t))}finalizeEvent(t,r){const n=t;return n.pubkey=_(G.getPublicKey(r)),n.id=Ye(n),n.sig=_(G.sign(X(Ye(n)),r)),n[ie]=!0,n}verifyEvent(t){if(typeof t[ie]=="boolean")return t[ie];try{const r=Ye(t);if(r!==t.id)return t[ie]=!1,!1;const n=G.verify(X(t.sig),X(r),X(t.pubkey));return t[ie]=n,n}catch{return t[ie]=!1,!1}}};function li(e){if(!oi(e))throw new Error("can't serialize event with wrong or missing properties");return JSON.stringify([0,e.pubkey,e.created_at,e.kind,e.tags,e.content])}function Ye(e){let t=Ne(ai.encode(li(e)));return _(t)}var He=new ci;He.generateSecretKey;He.getPublicKey;He.finalizeEvent;var di=He.verifyEvent,ui=22242;function fi(e,t){if(e.ids&&e.ids.indexOf(t.id)===-1||e.kinds&&e.kinds.indexOf(t.kind)===-1||e.authors&&e.authors.indexOf(t.pubkey)===-1)return!1;for(let r in e)if(r[0]==="#"){let n=r.slice(1),i=e[`#${n}`];if(i&&!t.tags.find(([s,o])=>s===r.slice(1)&&i.indexOf(o)!==-1))return!1}return!(e.since&&t.created_at<e.since||e.until&&t.created_at>e.until)}function hi(e,t){for(let r=0;r<e.length;r++)if(fi(e[r],t))return!0;return!1}function pi(e,t){let r=t.length+3,n=e.indexOf(`"${t}":`)+r,i=e.slice(n).indexOf('"')+n+1;return e.slice(i,i+64)}function gi(e){let t=e.slice(0,22).indexOf('"EVENT"');if(t===-1)return null;let r=e.slice(t+7+1).indexOf('"');if(r===-1)return null;let n=t+7+1+r,i=e.slice(n+1,80).indexOf('"');if(i===-1)return null;let s=n+1+i;return e.slice(n+1,s)}function yi(e,t){return{kind:ui,created_at:Math.floor(Date.now()/1e3),tags:[["relay",e],["challenge",t]],content:""}}var xn=class extends Error{constructor(e,t){super(`Tried to send message '${e} on a closed connection to ${t}.`),this.name="SendingOnClosedConnection"}},kn=class{url;_connected=!1;onclose=null;onnotice=e=>console.debug(`NOTICE from ${this.url}: ${e}`);onauth;baseEoseTimeout=4400;publishTimeout=4400;pingFrequency=29e3;pingTimeout=2e4;resubscribeBackoff=[1e4,1e4,1e4,2e4,2e4,3e4,6e4];openSubs=new Map;enablePing;enableReconnect;idleSince=Date.now();ongoingOperations=0;reconnectTimeoutHandle;pingIntervalHandle;reconnectAttempts=0;skipReconnection=!1;connectionPromise;openCountRequests=new Map;openEventPublishes=new Map;ws;challenge;authPromise;serial=0;verifyEvent;_WebSocket;constructor(e,t){this.url=pe(e),this.verifyEvent=t.verifyEvent,this._WebSocket=t.websocketImplementation||WebSocket,this.enablePing=t.enablePing,this.enableReconnect=t.enableReconnect||!1}static async connect(e,t){const r=new kn(e,t);return await r.connect(t),r}closeAllSubscriptions(e){for(let[t,r]of this.openSubs)r.close(e);this.openSubs.clear();for(let[t,r]of this.openEventPublishes)r.reject(new Error(e));this.openEventPublishes.clear();for(let[t,r]of this.openCountRequests)r.reject(new Error(e));this.openCountRequests.clear()}get connected(){return this._connected}async reconnect(){const e=this.resubscribeBackoff[Math.min(this.reconnectAttempts,this.resubscribeBackoff.length-1)];this.reconnectAttempts++,this.reconnectTimeoutHandle=setTimeout(async()=>{try{await this.connect()}catch{}},e)}handleHardClose(e){this.pingIntervalHandle&&(clearInterval(this.pingIntervalHandle),this.pingIntervalHandle=void 0),this._connected=!1,this.connectionPromise=void 0,this.idleSince=void 0,this.enableReconnect&&!this.skipReconnection?this.reconnect():(this.onclose?.(),this.closeAllSubscriptions(e))}async connect(e){let t;return this.connectionPromise?this.connectionPromise:(this.challenge=void 0,this.authPromise=void 0,this.skipReconnection=!1,this.connectionPromise=new Promise((r,n)=>{e?.timeout&&(t=setTimeout(()=>{n("connection timed out"),this.connectionPromise=void 0,this.skipReconnection=!0,this.onclose?.(),this.handleHardClose("relay connection timed out")},e.timeout)),e?.abort&&(e.abort.onabort=n);try{this.ws=new this._WebSocket(this.url)}catch(i){clearTimeout(t),n(i);return}this.ws.onopen=()=>{this.reconnectTimeoutHandle&&(clearTimeout(this.reconnectTimeoutHandle),this.reconnectTimeoutHandle=void 0),clearTimeout(t),this._connected=!0;const i=this.reconnectAttempts>0;this.reconnectAttempts=0;for(const s of this.openSubs.values()){if(s.eosed=!1,i)for(let o=0;o<s.filters.length;o++)s.lastEmitted&&(s.filters[o].since=s.lastEmitted+1);s.fire()}this.enablePing&&(this.pingIntervalHandle=setInterval(()=>this.pingpong(),this.pingFrequency)),r()},this.ws.onerror=()=>{clearTimeout(t),n("connection failed"),this.connectionPromise=void 0,this.skipReconnection=!0,this.onclose?.(),this.handleHardClose("relay connection failed")},this.ws.onclose=i=>{clearTimeout(t),n(i.message||"websocket closed"),this.handleHardClose("relay connection closed")},this.ws.onmessage=this._onmessage.bind(this)}),this.connectionPromise)}waitForPingPong(){return new Promise(e=>{this.ws.once("pong",()=>e(!0)),this.ws.ping()})}waitForDummyReq(){return new Promise((e,t)=>{if(!this.connectionPromise)return t(new Error(`no connection to ${this.url}, can't ping`));try{const r=this.subscribe([{ids:["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"],limit:0}],{label:"<forced-ping>",oneose:()=>{e(!0),r.close()},onclose(){e(!0)},eoseTimeout:this.pingTimeout+1e3})}catch(r){t(r)}})}async pingpong(){this.ws?.readyState===1&&(await Promise.any([this.ws&&this.ws.ping&&this.ws.once?this.waitForPingPong():this.waitForDummyReq(),new Promise(t=>setTimeout(()=>t(!1),this.pingTimeout))])||this.ws?.readyState===this._WebSocket.OPEN&&this.ws?.close())}async send(e){if(!this.connectionPromise)throw new xn(e,this.url);this.connectionPromise.then(()=>{this.ws?.send(e)})}async auth(e){const t=this.challenge;if(!t)throw new Error("can't perform auth, no challenge was received");return this.authPromise?this.authPromise:(this.authPromise=new Promise(async(r,n)=>{try{let i=await e(yi(this.url,t)),s=setTimeout(()=>{let o=this.openEventPublishes.get(i.id);o&&(o.reject(new Error("auth timed out")),this.openEventPublishes.delete(i.id))},this.publishTimeout);this.openEventPublishes.set(i.id,{resolve:r,reject:n,timeout:s}),this.send('["AUTH",'+JSON.stringify(i)+"]")}catch(i){console.warn("subscribe auth function failed:",i)}}),this.authPromise)}async publish(e){this.idleSince=void 0,this.ongoingOperations++;const t=new Promise((r,n)=>{const i=setTimeout(()=>{const s=this.openEventPublishes.get(e.id);s&&(s.reject(new Error("publish timed out")),this.openEventPublishes.delete(e.id))},this.publishTimeout);this.openEventPublishes.set(e.id,{resolve:r,reject:n,timeout:i})});return this.send('["EVENT",'+JSON.stringify(e)+"]"),this.ongoingOperations--,this.ongoingOperations===0&&(this.idleSince=Date.now()),t}async count(e,t){this.serial++;const r=t?.id||"count:"+this.serial,n=new Promise((i,s)=>{this.openCountRequests.set(r,{resolve:i,reject:s})});return this.send('["COUNT","'+r+'",'+JSON.stringify(e).substring(1)),n}subscribe(e,t){t.label!=="<forced-ping>"&&(this.idleSince=void 0,this.ongoingOperations++);const r=this.prepareSubscription(e,t);return r.fire(),t.abort&&(t.abort.onabort=()=>r.close(String(t.abort.reason||"<aborted>"))),r}prepareSubscription(e,t){this.serial++;const r=t.id||(t.label?t.label+":":"sub:")+this.serial,n=new mi(this,r,e,t);return this.openSubs.set(r,n),n}close(){this.skipReconnection=!0,this.reconnectTimeoutHandle&&(clearTimeout(this.reconnectTimeoutHandle),this.reconnectTimeoutHandle=void 0),this.pingIntervalHandle&&(clearInterval(this.pingIntervalHandle),this.pingIntervalHandle=void 0),this.closeAllSubscriptions("relay connection closed by us"),this._connected=!1,this.idleSince=void 0,this.onclose?.(),this.ws?.readyState===this._WebSocket.OPEN&&this.ws?.close()}_onmessage(e){const t=e.data;if(!t)return;const r=gi(t);if(r){const n=this.openSubs.get(r);if(!n)return;const i=pi(t,"id"),s=n.alreadyHaveEvent?.(i);if(n.receivedEvent?.(this,i),s)return}try{let n=JSON.parse(t);switch(n[0]){case"EVENT":{const i=this.openSubs.get(n[1]),s=n[2];this.verifyEvent(s)&&hi(i.filters,s)?i.onevent(s):i.oninvalidevent?.(s),(!i.lastEmitted||i.lastEmitted<s.created_at)&&(i.lastEmitted=s.created_at);return}case"COUNT":{const i=n[1],s=n[2],o=this.openCountRequests.get(i);o&&(o.resolve(s.count),this.openCountRequests.delete(i));return}case"EOSE":{const i=this.openSubs.get(n[1]);if(!i)return;i.receivedEose();return}case"OK":{const i=n[1],s=n[2],o=n[3],c=this.openEventPublishes.get(i);c&&(clearTimeout(c.timeout),s?c.resolve(o):c.reject(new Error(o)),this.openEventPublishes.delete(i));return}case"CLOSED":{const i=n[1],s=this.openSubs.get(i);if(!s)return;s.closed=!0,s.close(n[2]);return}case"NOTICE":{this.onnotice(n[1]);return}case"AUTH":{this.challenge=n[1],this.onauth&&this.auth(this.onauth);return}default:{this.openSubs.get(n[1])?.oncustom?.(n);return}}}catch(n){try{const[i,s,o]=JSON.parse(t);console.warn(`[nostr] relay ${this.url} error processing message:`,n,o)}catch{console.warn(`[nostr] relay ${this.url} error processing message:`,n)}return}}},mi=class{relay;id;lastEmitted;closed=!1;eosed=!1;filters;alreadyHaveEvent;receivedEvent;onevent;oninvalidevent;oneose;onclose;oncustom;eoseTimeout;eoseTimeoutHandle;constructor(e,t,r,n){if(r.length===0)throw new Error("subscription can't be created with zero filters");this.relay=e,this.filters=r,this.id=t,this.alreadyHaveEvent=n.alreadyHaveEvent,this.receivedEvent=n.receivedEvent,this.eoseTimeout=n.eoseTimeout||e.baseEoseTimeout,this.oneose=n.oneose,this.onclose=n.onclose,this.oninvalidevent=n.oninvalidevent,this.onevent=n.onevent||(i=>{console.warn(`onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`,i)})}fire(){this.relay.send('["REQ","'+this.id+'",'+JSON.stringify(this.filters).substring(1)),this.eoseTimeoutHandle=setTimeout(this.receivedEose.bind(this),this.eoseTimeout)}receivedEose(){this.eosed||(clearTimeout(this.eoseTimeoutHandle),this.eosed=!0,this.oneose?.())}close(e="closed by caller"){if(!this.closed&&this.relay.connected){try{this.relay.send('["CLOSE",'+JSON.stringify(this.id)+"]")}catch(t){if(!(t instanceof xn))throw t}this.closed=!0}this.relay.openSubs.delete(this.id),this.relay.ongoingOperations--,this.relay.ongoingOperations===0&&(this.relay.idleSince=Date.now()),this.onclose?.(e)}},bi=e=>(e[ie]=!0,!0),wi=class{relays=new Map;seenOn=new Map;trackRelays=!1;verifyEvent;enablePing;enableReconnect;automaticallyAuth;trustedRelayURLs=new Set;onRelayConnectionFailure;onRelayConnectionSuccess;allowConnectingToRelay;maxWaitForConnection;_WebSocket;constructor(e){this.verifyEvent=e.verifyEvent,this._WebSocket=e.websocketImplementation,this.enablePing=e.enablePing,this.enableReconnect=e.enableReconnect||!1,this.automaticallyAuth=e.automaticallyAuth,this.onRelayConnectionFailure=e.onRelayConnectionFailure,this.onRelayConnectionSuccess=e.onRelayConnectionSuccess,this.allowConnectingToRelay=e.allowConnectingToRelay,this.maxWaitForConnection=e.maxWaitForConnection||3e3}async ensureRelay(e,t){e=pe(e);let r=this.relays.get(e);if(r||(r=new kn(e,{verifyEvent:this.trustedRelayURLs.has(e)?bi:this.verifyEvent,websocketImplementation:this._WebSocket,enablePing:this.enablePing,enableReconnect:this.enableReconnect}),r.onclose=()=>{this.relays.delete(e)},this.relays.set(e,r)),this.automaticallyAuth){const n=this.automaticallyAuth(e);n&&(r.onauth=n)}try{await r.connect({timeout:t?.connectionTimeout,abort:t?.abort})}catch(n){throw this.relays.delete(e),n}return r}close(e){e.map(pe).forEach(t=>{this.relays.get(t)?.close(),this.relays.delete(t)})}subscribe(e,t,r){const n=[],i=[];for(let s=0;s<e.length;s++){const o=pe(e[s]);n.find(c=>c.url===o)||i.indexOf(o)===-1&&(i.push(o),n.push({url:o,filter:t}))}return this.subscribeMap(n,r)}subscribeMany(e,t,r){return this.subscribe(e,t,r)}subscribeMap(e,t){const r=new Map;for(const g of e){const{url:y,filter:b}=g;r.has(y)||r.set(y,[]),r.get(y).push(b)}const n=Array.from(r.entries()).map(([g,y])=>({url:g,filters:y}));this.trackRelays&&(t.receivedEvent=(g,y)=>{let b=this.seenOn.get(y);b||(b=new Set,this.seenOn.set(y,b)),b.add(g)});const i=new Set,s=[],o=[];let c=g=>{o[g]||(o[g]=!0,o.filter(y=>y).length===n.length&&(t.oneose?.(),c=()=>{}))};const a=[];let d=(g,y)=>{a[g]||(c(g),a[g]=y,a.filter(b=>b).length===n.length&&(t.onclose?.(a),d=()=>{}))};const f=g=>{if(t.alreadyHaveEvent?.(g))return!0;const y=i.has(g);return i.add(g),y},h=Promise.all(n.map(async({url:g,filters:y},b)=>{if(this.allowConnectingToRelay?.(g,["read",y])===!1){d(b,"connection skipped by allowConnectingToRelay");return}let E;try{E=await this.ensureRelay(g,{connectionTimeout:this.maxWaitForConnection<(t.maxWait||0)?Math.max(t.maxWait*.8,t.maxWait-1e3):this.maxWaitForConnection,abort:t.abort})}catch(L){this.onRelayConnectionFailure?.(g),d(b,L?.message||String(L));return}this.onRelayConnectionSuccess?.(g);let q=E.subscribe(y,{...t,oneose:()=>c(b),onclose:L=>{L.startsWith("auth-required: ")&&t.onauth?E.auth(t.onauth).then(()=>{E.subscribe(y,{...t,oneose:()=>c(b),onclose:K=>{d(b,K)},alreadyHaveEvent:f,eoseTimeout:t.maxWait,abort:t.abort})}).catch(K=>{d(b,`auth was required and attempted, but failed with: ${K}`)}):d(b,L)},alreadyHaveEvent:f,eoseTimeout:t.maxWait,abort:t.abort});s.push(q)}));return{async close(g){await h,s.forEach(y=>{y.close(g)})}}}subscribeEose(e,t,r){let n;return n=this.subscribe(e,t,{...r,oneose(){const i="closed automatically on eose";n?n.close(i):r.onclose?.(e.map(s=>i))}}),n}subscribeManyEose(e,t,r){return this.subscribeEose(e,t,r)}async querySync(e,t,r){return new Promise(async n=>{const i=[];this.subscribeEose(e,t,{...r,onevent(s){i.push(s)},onclose(s){n(i)}})})}async get(e,t,r){t.limit=1;const n=await this.querySync(e,t,r);return n.sort((i,s)=>s.created_at-i.created_at),n[0]||null}publish(e,t,r){return e.map(pe).map(async(n,i,s)=>{if(s.indexOf(n)!==i)return Promise.reject("duplicate url");if(this.allowConnectingToRelay?.(n,["write",t])===!1)return Promise.reject("connection skipped by allowConnectingToRelay");let o;try{o=await this.ensureRelay(n,{connectionTimeout:this.maxWaitForConnection<(r?.maxWait||0)?Math.max(r.maxWait*.8,r.maxWait-1e3):this.maxWaitForConnection,abort:r?.abort})}catch(c){return this.onRelayConnectionFailure?.(n),"connection failure: "+String(c)}return o.publish(t).catch(async c=>{if(c instanceof Error&&c.message.startsWith("auth-required: ")&&r?.onauth)return await o.auth(r.onauth),o.publish(t);throw c}).then(c=>{if(this.trackRelays){let a=this.seenOn.get(t.id);a||(a=new Set,this.seenOn.set(t.id,a)),a.add(o)}return c})})}listConnectionStatus(){const e=new Map;return this.relays.forEach((t,r)=>e.set(r,t.connected)),e}destroy(){this.relays.forEach(e=>e.close()),this.relays=new Map}pruneIdleRelays(e=1e4){const t=[];for(const[r,n]of this.relays)n.idleSince&&Date.now()-n.idleSince>=e&&(this.relays.delete(r),t.push(r),n.close());return t}},Sn;try{Sn=WebSocket}catch{}var vi=class extends wi{constructor(e){super({verifyEvent:di,websocketImplementation:Sn,maxWaitForConnection:3e3,...e})}},ce=Symbol("verified"),Ei=e=>e instanceof Object;function xi(e){if(!Ei(e)||typeof e.kind!="number"||typeof e.content!="string"||typeof e.created_at!="number"||typeof e.pubkey!="string"||!e.pubkey.match(/^[a-f0-9]{64}$/)||!Array.isArray(e.tags))return!1;for(let t=0;t<e.tags.length;t++){let r=e.tags[t];if(!Array.isArray(r))return!1;for(let n=0;n<r.length;n++)if(typeof r[n]!="string")return!1}return!0}new TextDecoder("utf-8");var ki=new TextEncoder,Si=class{generateSecretKey(){return G.utils.randomSecretKey()}getPublicKey(e){return _(G.getPublicKey(e))}finalizeEvent(e,t){const r=e;return r.pubkey=_(G.getPublicKey(t)),r.id=ze(r),r.sig=_(G.sign(X(ze(r)),t)),r[ce]=!0,r}verifyEvent(e){if(typeof e[ce]=="boolean")return e[ce];try{const t=ze(e);if(t!==e.id)return e[ce]=!1,!1;const r=G.verify(X(e.sig),X(t),X(e.pubkey));return e[ce]=r,r}catch{return e[ce]=!1,!1}}};function Ri(e){if(!xi(e))throw new Error("can't serialize event with wrong or missing properties");return JSON.stringify([0,e.pubkey,e.created_at,e.kind,e.tags,e.content])}function ze(e){let t=Ne(ki.encode(Ri(e)));return _(t)}var je=new Si;je.generateSecretKey;je.getPublicKey;je.finalizeEvent;var $i=je.verifyEvent;const Ii=8e3;function Ai(e){return typeof e=="number"&&ct.includes(e)}function Ti(e){try{const t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function Bi(e){const t=[];for(const r of e??[])try{const n=new URL(r);if(n.protocol!=="ws:"&&n.protocol!=="wss:")continue;t.push(n.href)}catch{}return[...new Set(t)]}function Oi(e){const t=vr(e.trim());if(t.type!=="nevent"&&t.type!=="naddr")throw new Error("Enter a NIP-19 nevent or naddr for a NIP-5D napplet manifest event");const r=Bi(t.data.relays);if(r.length===0)throw new Error("The pointer does not include relay hints; include at least one relay in the nevent/naddr");if(t.type==="nevent"){if(t.data.kind!==void 0&&!Ai(t.data.kind))throw new Error(`nevent points at kind ${t.data.kind}, not a NIP-5D napplet manifest kind`);return{type:"nevent",relays:r,filter:{ids:[t.data.id],kinds:t.data.kind===void 0?[...ct]:[t.data.kind],authors:t.data.author?[t.data.author]:void 0,limit:1}}}if(t.data.kind!==ge)throw new Error(`naddr kind ${t.data.kind} is not the named napplet kind ${ge}`);return{type:"naddr",relays:r,filter:{kinds:[ge],authors:[t.data.pubkey],"#d":[t.data.identifier],limit:1}}}function qi(e){return{id:e.id,pubkey:e.pubkey,kind:e.kind,tags:e.tags}}async function Rn(e){const t=typeof e=="string"?new TextEncoder().encode(e):e,r=new Uint8Array(t.byteLength);r.set(t);const n=await crypto.subtle.digest("SHA-256",r.buffer);return[...new Uint8Array(n)].map(i=>i.toString(16).padStart(2,"0")).join("")}function Ni(e){return e.tags.filter(t=>t[0]==="path"&&typeof t[1]=="string"&&typeof t[2]=="string")}async function Li(e){const t=Ni(e).map(r=>`${r[2]} ${r[1]}
80
- `).sort().join("");return Rn(t)}async function Pi(e){const t=await Li(e);for(const r of e.tags.filter(n=>n[0]==="x"))if(r[2]!==t)throw new Error(`Manifest x tag does not match recomputed aggregate hash ${t}`)}function _i(e){return e.tags.find(t=>t[0]==="path"&&t[1]==="/index.html")}function Ci(e){const t=[];for(const r of e.tags)if(!(r[0]!=="server"||!r[1]))try{const n=new URL(r[1]);(n.protocol==="http:"||n.protocol==="https:")&&t.push(n.href)}catch{}return[...new Set(t)]}function Ui(e,t){const r=e.endsWith("/")?e:`${e}/`;return new URL(t,r).href}async function Hi(e,t=fetch){const n=_i(e)?.[2];if(!n)throw new Error("Manifest does not include a /index.html path hash");const i=Ci(e);if(i.length===0)throw new Error("Manifest does not include any usable Blossom server hints");const s=[];for(const o of i){const c=Ui(o,n);try{const a=await t(c,{mode:"cors"});if(!a.ok){s.push(`${c}: HTTP ${a.status}`);continue}const d=new Uint8Array(await a.arrayBuffer()),f=await Rn(d);if(f!==n){s.push(`${c}: sha256 ${f} did not match manifest ${n}`);continue}return new TextDecoder().decode(d)}catch(a){s.push(`${c}: ${a instanceof Error?a.message:String(a)}`)}}throw new Error(`Unable to fetch verified /index.html from Blossom servers: ${s.join("; ")}`)}async function ji(e,t){try{const n=await(await t(e,{mode:"cors"})).text();return{source:"url",input:e,label:e,bootUrl:e,html:n,fetched:!0,manifestEvent:null}}catch{return{source:"url",input:e,label:e,bootUrl:e,html:"",fetched:!1,manifestEvent:null}}}async function Di(e,t){const r=Oi(e),n=!t.pool,i=t.pool??new vi;try{const s=await i.get(r.relays,{...r.filter},{maxWait:t.maxRelayWaitMs??Ii});if(!s)throw new Error("No matching napplet manifest event was found on the pointer relay hints");if(!$i(s))throw new Error("Resolved manifest event signature is invalid");const o=qi(s),c=lt(o);if(!c.ok)throw new Error(`Resolved event is not a valid NIP-5D napplet manifest: ${c.errors[0]?.message}`);await Pi(o);const a=await Hi(o,t.fetcher??fetch),d=(t.createObjectUrl??URL.createObjectURL)(new Blob([a],{type:"text/html;charset=utf-8"})),f=()=>(t.revokeObjectUrl??URL.revokeObjectURL)(d);return{source:"nostr",input:e,label:o.id??e,bootUrl:d,html:a,fetched:!0,manifestEvent:o,revoke:f}}finally{n&&i.destroy()}}async function Mi(e,t={}){const r=e.trim();if(!r)throw new Error("Enter a NIP-19 nevent/naddr, or an HTTP URL for local dev");return Ti(r)?ji(r,t.fetcher??fetch):Di(r,t)}const Fi=/\bwindow\s*\.\s*nostr\b|\bglobalThis\s*\.\s*nostr\b/,Wi="/__conformance__/events",st=new URLSearchParams(location.search),$n=st.get("live")==="1";function ne(e){return String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}const re=document.getElementById("app");function Zi(){return re.innerHTML=`
81
- <header class="masthead">
82
- <h1>napplet conformance ${$n?'<span class="live-badge" id="live-badge">● live</span>':""}</h1>
83
- <p>Load a napplet by <code>nevent</code> or <code>naddr</code> and run NAP protocol conformance live. Same engine as <code>napplet-conformance</code> CI.</p>
84
- </header>
85
- <form id="run-form" class="runbar">
86
- <input id="target" type="text" placeholder="naddr1… or nevent1… for a NIP-5D napplet manifest" autocomplete="off" spellcheck="false" />
87
- <button id="run" type="submit">Run conformance</button>
88
- <button id="rerun" type="button" class="secondary" hidden>Re-run</button>
89
- </form>
90
- <p id="status" class="status" role="status"></p>
91
- <section id="output" class="output"></section>
92
- `,{targetInput:re.querySelector("#target"),runButton:re.querySelector("#run"),rerunButton:re.querySelector("#rerun"),liveBadge:re.querySelector("#live-badge")??document.createElement("span"),status:re.querySelector("#status"),output:re.querySelector("#output")}}const C=Zi();let be="",ot=0;function Ie(e,t="info"){C.status.textContent=e,C.status.dataset.kind=t}function Ge(e){return String(e).padStart(2,"0")}function Vi(e){const t=new Date(e);return`${Ge(t.getHours())}:${Ge(t.getMinutes())}:${Ge(t.getSeconds())}`}function Ki(e){const t=e.ok?"conformant":"non-conformant",n=[...new Set(e.checks.map(o=>o.area))].map(o=>{const c=e.checks.filter(a=>a.area===o).map(a=>{const d=a.severity==="warning"&&a.status==="fail"?' <span class="tag warn">warning</span>':"",f=a.detail?`<span class="detail">${ne(a.detail)}</span>`:"";return`<li class="check ${a.status}"><span class="badge ${a.status}">${a.status}</span><span class="id">${ne(a.id)}</span>${d}${f}</li>`}).join("");return`<div class="area"><h3>${ne(o)}</h3><ul>${c}</ul></div>`}).join(""),i=e.summary,s=ot>1?`<span class="run-stamp">run #${ot} · ${Vi(e.finishedAt)}</span>`:"";return`
93
- <div class="verdict ${t}">
94
- <span class="result">${e.ok?"CONFORMANT":"NON-CONFORMANT"}</span>
95
- <span class="counts">${i.passed} passed · ${i.failed} failed · ${i.skipped} skipped${i.warnings?` · ${i.warnings} warning(s)`:""}</span>
96
- ${s}
97
- </div>
98
- <div class="checks">${n}</div>
99
- `}function Yi(e){return e.length===0?'<p class="empty">No envelopes were emitted.</p>':`<ul class="envlog">${e.map(r=>{const n=r.verdict.ok?"ok":"bad",i=r.verdict.ok?"":`<div class="errs">${r.verdict.errors.map(s=>ne(`${s.code}: ${s.message}`)).join("<br>")}</div>`;return`<li class="env ${n}"><code>${ne(JSON.stringify(r.envelope))}</code>${i}</li>`}).join("")}</ul>`}function zi(e){const t=(r,n)=>`<tr><th>${ne(r)}</th><td>${n?ne(String(n)):"<em>—</em>"}</td></tr>`;if(e.manifestEvent){const r=e.manifestEvent,n=lt(r),i=r.tags.find(c=>c[0]==="d")?.[1],s=r.tags.find(c=>c[0]==="path"&&c[1]==="/index.html"),o=r.tags.filter(c=>c[0]==="server").map(c=>c[1]).filter(Boolean);return`
100
- <table class="manifest">
101
- ${t("event",r.id)}
102
- ${t("kind",r.kind)}
103
- ${t("d",i)}
104
- ${t("name",Zt(r))}
105
- ${t("requires",n.requires.join(", "))}
106
- ${t("/index.html",s?.[2])}
107
- ${t("servers",o.join(", "))}
108
- </table>
109
- ${n.errors.length?`<div class="errs">${n.errors.map(c=>ne(`${c.code}: ${c.message}`)).join("<br>")}</div>`:""}
110
- `}return e.fetched?'<p class="empty">Local URL mode booted raw HTML. It does not include a signed NIP-5D manifest event, so manifest-event checks are skipped.</p>':`<p class="empty">Couldn't fetch the local URL HTML, likely because of CORS. Use a NIP-19 <code>nevent</code>/<code>naddr</code> for authoritative manifest checks, or use the CLI for local URL runs.</p>`}function Gi(e,t,r){C.output.innerHTML=`
111
- ${Ki(e)}
112
- <div class="panels">
113
- <section class="panel"><h2>Emitted envelopes (${t.length})</h2>${Yi(t)}</section>
114
- <section class="panel"><h2>Manifest</h2>${zi(r)}</section>
115
- </div>
116
- `}async function De(e){be=e,C.runButton.disabled=!0,C.rerunButton.disabled=!0;let t=null;try{Ie(`Resolving ${e} …`),t=await Mi(e);const r=Fi.test(t.html)?["window.nostr"]:[];Ie("Booting napplet in a sandboxed iframe …");const n=await tr({url:t.bootUrl,readyTimeoutMs:5e3,settleMs:800,runDegraded:!0}),i=zn({manifestHtml:t.html,manifestEvent:t.manifestEvent,boot:n,forbiddenGlobals:r}),s=ar(i);ot+=1,Ie(s.ok?"Done — conformant.":"Done — non-conformant.",s.ok?"info":"error"),Gi(s,n.emitted,t),C.rerunButton.hidden=!1}catch(r){Ie(`Error: ${r instanceof Error?r.message:String(r)}`,"error")}finally{t?.revoke?.(),C.runButton.disabled=!1,C.rerunButton.disabled=!1}}function Xi(){if(!$n||typeof EventSource>"u")return;let e=!1;const t=new EventSource(Wi);t.addEventListener("rerun",()=>{!be||e||(e=!0,setTimeout(()=>{e=!1,De(be)},50))}),t.addEventListener("open",()=>{C.liveBadge&&(C.liveBadge.dataset.state="connected")}),t.addEventListener("error",()=>{C.liveBadge&&(C.liveBadge.dataset.state="disconnected")})}C.runButton.parentElement.addEventListener("submit",e=>{e.preventDefault();const t=C.targetInput.value.trim();if(t){const r=new URL(location.href);r.searchParams.set("target",t),r.searchParams.delete("url"),history.replaceState(null,"",r),De(t)}});C.rerunButton.addEventListener("click",()=>{be&&De(be)});Xi();const Xe=st.get("target")??st.get("url");Xe&&(C.targetInput.value=Xe,De(Xe));