@napplet/conformance-cli 0.2.15 → 0.2.16

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/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # @napplet/conformance-cli
2
2
 
3
- The headless `napplet-conformance` runner. It drives the
4
- [`@napplet/conformance`](../conformance) engine against a napplet in real headless
5
- Chromium (via Playwright), so a napplet can prove it conforms to the NAP protocol
6
- **before** publishing — locally and in CI.
3
+ The headless `napplet-conformance` runner. It drives the [`@napplet/conformance`](../conformance) engine against a napplet in real headless Chromium (via Playwright), so a napplet can prove it conforms to the NAP protocol **before** publishing — locally and in CI.
4
+
5
+ The runner validates NIP-5D/NAP envelope and manifest carriers. It does not define payload schemas or matching behavior for an archetype convention. Intent acceptance and target delivery are distinct: the reference shell uses an authenticated endpoint fixture for sender provenance, returns acceptance first, and queues a separate no-ID target delivery. Payloads remain untrusted.
6
+
7
+ Archetype metadata is one queryless convention per tag with optional trailing same-tag `kind:<number>` discovery fields; kinds are not inferred from payloads. This non-normative description follows the adopted [NAP-INC #89 `4593ce9`](https://github.com/napplet/naps/blob/4593ce9e301ce098fd3dad64206fcd6f144fa7af/naps/NAP-INC.md), [URI terminology #90 `896c32c`](https://github.com/napplet/naps/commit/896c32c92deee68dc4d10fc1132b62df20cccb6f), and [NAP-INTENT #91 `a718915`](https://github.com/napplet/naps/blob/a718915ddefa2f03a0126579601f59d8bd86f7c4/naps/NAP-INTENT.md).
7
8
 
8
9
  ```bash
9
10
  # Build your napplet first, then:
@@ -35,25 +36,13 @@ pnpm test:conformance # npm / yarn / bun all work — the bin is PM-agnostic
35
36
  napplet-conformance --ui . --exec "vite build --watch"
36
37
  ```
37
38
 
38
- `--ui` serves the standalone conformance web runtime (bundled with this package) plus
39
- the napplet, opens your browser, and **re-runs conformance live every time the napplet
40
- changes**. The optional `--exec` runs your build in watch mode so source edits rebuild
41
- the served `./dist`; the CLI's file watcher then triggers a fresh run — edit, save, see
42
- the verdict update. Useful flags: `--port <n>`, `--no-open`. (Headless mode is
43
- unchanged — `--ui` is purely additive.)
39
+ `--ui` serves the standalone conformance web runtime (bundled with this package) plus the napplet, opens your browser, and **re-runs conformance live every time the napplet changes**. The optional `--exec` runs your build in watch mode so source edits rebuild the served `./dist`; the CLI's file watcher then triggers a fresh run — edit, save, see the verdict update. Useful flags: `--port <n>`, `--no-open`. (Headless mode is unchanged — `--ui` is purely additive.)
44
40
 
45
41
  ## How it works
46
42
 
47
- 1. Serves your built napplet on loopback alongside a host harness page and the
48
- bundled engine. Every response sends `Access-Control-Allow-Origin: *` so the
49
- sandboxed napplet's module scripts load across its opaque origin.
50
- 2. Launches headless Chromium, loads the napplet into a `sandbox="allow-scripts"`
51
- iframe (no `allow-same-origin`), attaches a reference shell, and records every
52
- envelope the napplet emits — plus a second no-capability pass to prove graceful
53
- degradation.
54
- 3. Assembles the conformance context (manifest + static `window.nostr` scan), runs
55
- the check catalog, prints the report, and exits non-zero on any error-severity
56
- failure.
43
+ 1. Serves your built napplet on loopback alongside a host harness page and the bundled engine. Every response sends `Access-Control-Allow-Origin: *` so the sandboxed napplet's module scripts load across its opaque origin.
44
+ 2. Launches headless Chromium, loads the napplet into a `sandbox="allow-scripts"` iframe (no `allow-same-origin`), attaches a reference shell, and records every envelope the napplet emits — plus a second no-capability pass to prove graceful degradation.
45
+ 3. Assembles the conformance context (manifest + static `window.nostr` scan), runs the check catalog, prints the report, and exits non-zero on any error-severity failure.
57
46
 
58
47
  ## Options
59
48
 
@@ -74,7 +74,7 @@ var NappletConformanceHostBundle = (() => {
74
74
  "storage.remove.result": { dir: "in" },
75
75
  "storage.keys.result": { dir: "in" },
76
76
  // ── inc (inter-napplet communication) ─────────────────────────────────────
77
- "inc.emit": { dir: "out", fields: { topic: "string" } },
77
+ "inc.emit": { dir: "out", fields: { topic: "string" }, forbiddenFields: ["sender"] },
78
78
  "inc.subscribe": { dir: "out", fields: { ...ID, topic: "string" } },
79
79
  "inc.unsubscribe": { dir: "out", fields: { topic: "string" } },
80
80
  "inc.channel.open": { dir: "out", fields: { ...ID, target: "string" } },
@@ -83,7 +83,7 @@ var NappletConformanceHostBundle = (() => {
83
83
  "inc.channel.list": { dir: "out", fields: { ...ID } },
84
84
  "inc.channel.close": { dir: "out", fields: { channelId: "string" } },
85
85
  "inc.subscribe.result": { dir: "in" },
86
- "inc.event": { dir: "in" },
86
+ "inc.event": { dir: "in", fields: { topic: "string", sender: "string" } },
87
87
  "inc.channel.open.result": { dir: "in" },
88
88
  "inc.channel.event": { dir: "in" },
89
89
  "inc.channel.list.result": { dir: "in" },
@@ -188,6 +188,7 @@ var NappletConformanceHostBundle = (() => {
188
188
  "intent.available.result": { dir: "in" },
189
189
  "intent.handlers.result": { dir: "in" },
190
190
  "intent.changed": { dir: "in" },
191
+ "intent.deliver": { dir: "in", fields: { delivery: "object" } },
191
192
  // ── ble ──────────────────────────────────────────────────────────────────
192
193
  "ble.open": { dir: "out", fields: { ...ID, request: "object" } },
193
194
  "ble.services": { dir: "out", fields: { ...ID, sessionId: "string" } },
@@ -278,6 +279,43 @@ var NappletConformanceHostBundle = (() => {
278
279
  if (kind === "present") return value !== void 0 && value !== null;
279
280
  return kindOf(value) === kind;
280
281
  }
282
+ function validateIntentInvokeRequest(request, errors) {
283
+ if (typeof request !== "object" || request === null || Array.isArray(request)) return;
284
+ const normalized = request;
285
+ for (const field of ["archetype", "action", "convention"]) {
286
+ const value = normalized[field];
287
+ if (value === void 0) {
288
+ errors.push({
289
+ code: "missing-field",
290
+ message: `Intent request requires a string "${field}" field`,
291
+ field: `request.${field}`
292
+ });
293
+ } else if (typeof value !== "string") {
294
+ errors.push({
295
+ code: "wrong-type",
296
+ message: `Intent request field "${field}" must be a string`,
297
+ field: `request.${field}`
298
+ });
299
+ }
300
+ }
301
+ if ("sender" in normalized) {
302
+ errors.push({
303
+ code: "forbidden-field",
304
+ message: "Intent request sender is runtime-derived and cannot be emitted by a napplet",
305
+ field: "request.sender"
306
+ });
307
+ }
308
+ const { archetype, action, convention } = normalized;
309
+ if (typeof archetype !== "string" || typeof action !== "string" || typeof convention !== "string") return;
310
+ const parsed = /^napplet:([^/?#\s]+)\/([^/?#\s]+)$/.exec(convention);
311
+ if (!parsed || parsed[1] !== archetype || parsed[2] !== action) {
312
+ errors.push({
313
+ code: "invalid-intent-request",
314
+ message: "Intent convention must be queryless and match request archetype and action",
315
+ field: "request.convention"
316
+ });
317
+ }
318
+ }
281
319
  function validateEnvelope(message) {
282
320
  const errors = [];
283
321
  if (typeof message !== "object" || message === null || Array.isArray(message)) {
@@ -301,15 +339,6 @@ var NappletConformanceHostBundle = (() => {
301
339
  if (!spec) {
302
340
  return { ok: false, type, domain, errors: [{ code: "unknown-type", message: `"${type}" is not a known ${domain} message type` }] };
303
341
  }
304
- if (spec.dir === "in") {
305
- return {
306
- ok: false,
307
- type,
308
- domain,
309
- direction: "in",
310
- errors: [{ code: "inbound-type-emitted", message: `"${type}" is a shell\u2192napplet message; a napplet must not emit it` }]
311
- };
312
- }
313
342
  for (const [field, kind] of Object.entries(spec.fields ?? {})) {
314
343
  if (!(field in record) || record[field] === void 0) {
315
344
  errors.push({ code: "missing-field", message: `Required field "${field}" is missing`, field });
@@ -323,6 +352,30 @@ var NappletConformanceHostBundle = (() => {
323
352
  });
324
353
  }
325
354
  }
355
+ if (spec.dir === "in") {
356
+ return {
357
+ ok: false,
358
+ type,
359
+ domain,
360
+ direction: "in",
361
+ errors: [
362
+ { code: "inbound-type-emitted", message: `"${type}" is a shell\u2192napplet message; a napplet must not emit it` },
363
+ ...errors
364
+ ]
365
+ };
366
+ }
367
+ for (const field of spec.forbiddenFields ?? []) {
368
+ if (field in record) {
369
+ errors.push({
370
+ code: "forbidden-field",
371
+ message: `Field "${field}" must be runtime-derived and cannot be emitted by a napplet`,
372
+ field
373
+ });
374
+ }
375
+ }
376
+ if (type === "intent.invoke") {
377
+ validateIntentInvokeRequest(record.request, errors);
378
+ }
326
379
  return { ok: errors.length === 0, type, domain, direction: "out", errors };
327
380
  }
328
381
  var NAPPLET_KIND_SNAPSHOT = 5129;
@@ -410,14 +463,18 @@ var NappletConformanceHostBundle = (() => {
410
463
  ok: errors.length === 0,
411
464
  kind: event.kind,
412
465
  dTag,
413
- nappletType: dTag,
414
466
  requires,
415
467
  errors,
416
468
  warnings
417
469
  };
418
470
  }
419
471
  var REFERENCE_PUBKEY = "f".repeat(64);
472
+ var REFERENCE_ENDPOINT = { dTag: "reference-source" };
420
473
  var REFERENCE_BLOB_URL = "https://reference.invalid/blob";
474
+ var REFERENCE_HANDLER = "reference-handler";
475
+ var REFERENCE_SUBSCRIBER = "reference-subscriber";
476
+ var REFERENCE_CONVENTION = "napplet:note/open";
477
+ var REFERENCE_CONTRACT = { convention: REFERENCE_CONVENTION, eventKinds: [1, 30023] };
421
478
  var ok = (v) => [v];
422
479
  var none = () => [];
423
480
  function dataUrlToBlob(url) {
@@ -553,27 +610,6 @@ var NappletConformanceHostBundle = (() => {
553
610
  }),
554
611
  "upload.upload": (e) => ok({ type: "upload.upload.result", id: e.id, result: { url: REFERENCE_BLOB_URL } }),
555
612
  "upload.status": (e) => ok({ type: "upload.status.result", id: e.id, status: {} }),
556
- // intent
557
- "intent.invoke": (e) => ok({ type: "intent.invoke.result", id: e.id, result: { ok: true, archetype: "reference", action: "open", handled: true } }),
558
- "intent.available": (e) => ok({
559
- type: "intent.available.result",
560
- id: e.id,
561
- availability: {
562
- archetype: e.archetype,
563
- available: true,
564
- candidates: [
565
- {
566
- dTag: "reference-handler",
567
- actions: ["open"],
568
- protocols: ["NAP-4"],
569
- contracts: [{ action: "open", protocol: "NAP-4", eventKinds: [1] }],
570
- isDefault: true
571
- }
572
- ],
573
- hasDefault: true
574
- }
575
- }),
576
- "intent.handlers": (e) => ok({ type: "intent.handlers.result", id: e.id, handlers: [] }),
577
613
  // ble
578
614
  "ble.open": (e) => ok({
579
615
  type: "ble.open.result",
@@ -628,20 +664,112 @@ var NappletConformanceHostBundle = (() => {
628
664
  function createReferenceShell(options = {}) {
629
665
  const now = options.now ?? (() => Date.now());
630
666
  const records = [];
631
- function handle(envelope) {
667
+ const targetQueues = /* @__PURE__ */ new Map();
668
+ function queueDelivery(target, delivery) {
669
+ const queue = targetQueues.get(target);
670
+ if (queue) {
671
+ queue.push(delivery);
672
+ return;
673
+ }
674
+ targetQueues.set(target, [delivery]);
675
+ }
676
+ function takeDeliveries(target) {
677
+ const queue = targetQueues.get(target) ?? [];
678
+ targetQueues.delete(target);
679
+ return queue;
680
+ }
681
+ function unavailableIntent(id, error) {
682
+ return ok({ type: "intent.invoke.result", id, result: { ok: false, error } });
683
+ }
684
+ function handleIntentInvoke(endpoint, env) {
685
+ const request = env.request;
686
+ if (typeof request !== "object" || request === null || Array.isArray(request)) {
687
+ return unavailableIntent(env.id, "invalid intent request");
688
+ }
689
+ const normalized = request;
690
+ const { archetype, action, convention } = normalized;
691
+ if (typeof archetype !== "string" || typeof action !== "string" || typeof convention !== "string") {
692
+ return unavailableIntent(env.id, "intent request must carry normalized identity");
693
+ }
694
+ const parsed = /^napplet:([^/?#\s]+)\/([^/?#\s]+)$/.exec(convention);
695
+ if (!parsed || parsed[1] !== archetype || parsed[2] !== action) {
696
+ return unavailableIntent(env.id, "intent request conflicts with its convention");
697
+ }
698
+ if (convention !== REFERENCE_CONVENTION) {
699
+ return unavailableIntent(env.id, "no reference handler for convention");
700
+ }
701
+ const delivery = {
702
+ sender: endpoint.dTag,
703
+ archetype,
704
+ action,
705
+ convention
706
+ };
707
+ if ("payload" in normalized) delivery.payload = normalized.payload;
708
+ queueDelivery(REFERENCE_HANDLER, { type: "intent.deliver", delivery });
709
+ return ok({
710
+ type: "intent.invoke.result",
711
+ id: env.id,
712
+ result: { ok: true, archetype, action, convention, handler: REFERENCE_HANDLER }
713
+ });
714
+ }
715
+ function intentAvailability(archetype) {
716
+ if (archetype !== "note") {
717
+ return { archetype, available: false, candidates: [], hasDefault: false };
718
+ }
719
+ return {
720
+ archetype,
721
+ available: true,
722
+ candidates: [{
723
+ dTag: REFERENCE_HANDLER,
724
+ actions: ["open"],
725
+ conventions: [REFERENCE_CONVENTION],
726
+ contracts: [REFERENCE_CONTRACT],
727
+ isDefault: true
728
+ }],
729
+ hasDefault: true
730
+ };
731
+ }
732
+ function handleFrom(endpoint, envelope) {
632
733
  const type = envelope && typeof envelope === "object" && typeof envelope.type === "string" ? envelope.type : void 0;
633
- records.push({ envelope, verdict: validateEnvelope(envelope), timestamp: now() });
634
- if (!type) return [];
734
+ const verdict = validateEnvelope(envelope);
735
+ records.push({ envelope, verdict, timestamp: now() });
736
+ if (!type || !verdict.ok) return [];
737
+ const env = envelope;
738
+ if (type === "intent.invoke") return handleIntentInvoke(endpoint, env);
739
+ if (type === "intent.available") {
740
+ return ok({ type: "intent.available.result", id: env.id, availability: intentAvailability(env.archetype) });
741
+ }
742
+ if (type === "intent.handlers") {
743
+ return ok({ type: "intent.handlers.result", id: env.id, handlers: [intentAvailability("note")] });
744
+ }
745
+ if (type === "inc.emit") {
746
+ if (env.topic === REFERENCE_CONVENTION) {
747
+ const event = {
748
+ type: "inc.event",
749
+ topic: env.topic,
750
+ sender: endpoint.dTag
751
+ };
752
+ if ("payload" in env) event.payload = env.payload;
753
+ queueDelivery(REFERENCE_SUBSCRIBER, event);
754
+ }
755
+ return [];
756
+ }
635
757
  const responder = RESPONDERS[type];
636
- return responder ? responder(envelope) : [];
758
+ return responder ? responder(env) : [];
759
+ }
760
+ function handle(envelope) {
761
+ return handleFrom(REFERENCE_ENDPOINT, envelope);
637
762
  }
638
763
  return {
639
764
  get records() {
640
765
  return records;
641
766
  },
642
767
  handle,
768
+ handleFrom,
769
+ takeDeliveries,
643
770
  reset() {
644
771
  records.length = 0;
772
+ targetQueues.clear();
645
773
  }
646
774
  };
647
775
  }
@@ -0,0 +1,113 @@
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 ot=["relay","identity","storage","inc","theme","keys","media","notify","config","resource","cvm","outbox","upload","intent","ble","webrtc","link","count","lists","serial","common","dm"],f={id:"string"},Sn={"relay.subscribe":{dir:"out",fields:{...f,subId:"string",filters:"array"}},"relay.close":{dir:"out",fields:{...f,subId:"string"}},"relay.publish":{dir:"out",fields:{...f,event:"object"}},"relay.publishEncrypted":{dir:"out",fields:{...f,event:"object",recipient:"string"}},"relay.query":{dir:"out",fields:{...f,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:{...f}},"identity.getRelays":{dir:"out",fields:{...f}},"identity.getProfile":{dir:"out",fields:{...f}},"identity.getFollows":{dir:"out",fields:{...f}},"identity.getList":{dir:"out",fields:{...f,listType:"string"}},"identity.getZaps":{dir:"out",fields:{...f}},"identity.getMutes":{dir:"out",fields:{...f}},"identity.getBlocked":{dir:"out",fields:{...f}},"identity.getBadges":{dir:"out",fields:{...f}},"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:{...f,key:"string"}},"storage.set":{dir:"out",fields:{...f,key:"string",value:"string"}},"storage.remove":{dir:"out",fields:{...f,key:"string"}},"storage.keys":{dir:"out",fields:{...f}},"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:{...f,topic:"string"}},"inc.unsubscribe":{dir:"out",fields:{topic:"string"}},"inc.channel.open":{dir:"out",fields:{...f,target:"string"}},"inc.channel.emit":{dir:"out",fields:{channelId:"string"}},"inc.channel.broadcast":{dir:"out"},"inc.channel.list":{dir:"out",fields:{...f}},"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.event":{dir:"in"},"inc.channel.list.result":{dir:"in"},"inc.channel.closed":{dir:"in"},"theme.get":{dir:"out",fields:{...f}},"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:{...f,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:{...f,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:{...f,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:{...f}},"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:{...f,schema:"object"}},"config.get":{dir:"out",fields:{...f}},"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:{...f}},"resource.bytes":{dir:"out",fields:{...f,url:"string"}},"resource.bytesMany":{dir:"out",fields:{...f,urls:"array"}},"resource.cancel":{dir:"out",fields:{...f}},"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:{...f}},"cvm.request":{dir:"out",fields:{...f,server:"object",message:"object"}},"cvm.close":{dir:"out",fields:{...f,server:"object"}},"cvm.registry.list":{dir:"out",fields:{...f}},"cvm.registry.has":{dir:"out",fields:{...f,family:"string"}},"cvm.registry.describe":{dir:"out",fields:{...f,family:"string"}},"cvm.registry.call":{dir:"out",fields:{...f,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:{...f,eventId:"string"}},"outbox.query":{dir:"out",fields:{...f,filters:"present"}},"outbox.subscribe":{dir:"out",fields:{...f,subId:"string",filters:"present"}},"outbox.close":{dir:"out",fields:{...f,subId:"string"}},"outbox.publish":{dir:"out",fields:{...f,event:"object"}},"outbox.resolveRelays":{dir:"out",fields:{...f,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:{...f}},"upload.upload":{dir:"out",fields:{...f,request:"object"}},"upload.status":{dir:"out",fields:{...f,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:{...f,request:"object"}},"intent.available":{dir:"out",fields:{...f,archetype:"string"}},"intent.handlers":{dir:"out",fields:{...f}},"intent.invoke.result":{dir:"in"},"intent.available.result":{dir:"in"},"intent.handlers.result":{dir:"in"},"intent.changed":{dir:"in"},"intent.deliver":{dir:"in",fields:{delivery:"object"}},"ble.open":{dir:"out",fields:{...f,request:"object"}},"ble.services":{dir:"out",fields:{...f,sessionId:"string"}},"ble.read":{dir:"out",fields:{...f,sessionId:"string",target:"object"}},"ble.write":{dir:"out",fields:{...f,sessionId:"string",target:"object",data:"array"}},"ble.subscribe":{dir:"out",fields:{...f,sessionId:"string",target:"object"}},"ble.unsubscribe":{dir:"out",fields:{...f,sessionId:"string",target:"object"}},"ble.close":{dir:"out",fields:{...f,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:{...f,input:"object"}},"common.decodeNip19":{dir:"out",fields:{...f,value:"string"}},"common.getProfile":{dir:"out",fields:{...f,target:"string"}},"common.follows":{dir:"out",fields:{...f}},"common.follow":{dir:"out",fields:{...f,pubkeys:"array"}},"common.unfollow":{dir:"out",fields:{...f,pubkeys:"array"}},"common.react":{dir:"out",fields:{...f,targetEventId:"string",reaction:"string"}},"common.report":{dir:"out",fields:{...f,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:{...f,request:"object"}},"webrtc.send":{dir:"out",fields:{...f,sessionId:"string",payload:"present"}},"webrtc.close":{dir:"out",fields:{...f,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:{...f,url:"string"}},"link.open.result":{dir:"in"},"count.query":{dir:"out",fields:{...f,filters:"array"}},"count.query.result":{dir:"in"},"lists.supported":{dir:"out",fields:{...f}},"lists.add":{dir:"out",fields:{...f,list:"object",items:"array"}},"lists.remove":{dir:"out",fields:{...f,list:"object",items:"array"}},"lists.supported.result":{dir:"in"},"lists.add.result":{dir:"in"},"lists.remove.result":{dir:"in"},"serial.open":{dir:"out",fields:{...f,request:"object"}},"serial.write":{dir:"out",fields:{...f,sessionId:"string",data:"array"}},"serial.close":{dir:"out",fields:{...f,sessionId:"string"}},"serial.open.result":{dir:"in"},"serial.write.result":{dir:"in"},"serial.close.result":{dir:"in"},"serial.event":{dir:"in"},"dm.status":{dir:"out",fields:{...f}},"dm.conversations":{dir:"out",fields:{...f}},"dm.messages":{dir:"out",fields:{...f,conversationId:"string"}},"dm.send":{dir:"out",fields:{...f,recipients:"array",content:"string"}},"dm.subscribe":{dir:"out",fields:{...f}},"dm.unsubscribe":{dir:"out",fields:{...f,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 Ut(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 $n(e,t){return t==="present"?e!=null:Ut(e)===t}function In(e,t){if(typeof e!="object"||e===null||Array.isArray(e))return;const r=e;for(const c of["archetype","action","convention"]){const a=r[c];a===void 0?t.push({code:"missing-field",message:`Intent request requires a string "${c}" field`,field:`request.${c}`}):typeof a!="string"&&t.push({code:"wrong-type",message:`Intent request field "${c}" must be a string`,field:`request.${c}`})}"sender"in r&&t.push({code:"forbidden-field",message:"Intent request sender is runtime-derived and cannot be emitted by a napplet",field:"request.sender"});const{archetype:n,action:i,convention:s}=r;if(typeof n!="string"||typeof i!="string"||typeof s!="string")return;const o=/^napplet:([^/?#\s]+)\/([^/?#\s]+)$/.exec(s);(!o||o[1]!==n||o[2]!==i)&&t.push({code:"invalid-intent-request",message:"Intent convention must be queryless and match request archetype and action",field:"request.convention"})}function Tn(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(!ot.includes(s))return{ok:!1,type:n,domain:s,errors:[{code:"unknown-domain",message:`"${s}" is not a known NAP domain`}]};const c=Sn[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}$n(r[a],l)||t.push({code:"wrong-type",message:`Field "${a}" should be ${l} but is ${Ut(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),{ok:t.length===0,type:n,domain:s,direction:"out",errors:t}}var Ht=5129,jt=15129,ge=35129,at=[Ht,jt,ge];function Dt(e,t){return e.tags.find(r=>r[0]===t)}function An(e){return at.includes(e)}function Bn(e){return typeof e=="string"&&/^[0-9a-f]{64}$/i.test(e)}function Mt(e){return Dt(e,"d")?.[1]?.trim()||void 0}function On(e){return e.tags.filter(t=>t[0]==="requires").map(t=>t[1]?.trim()??"").filter(Boolean)}function Zt(e){return Mt(e)??Dt(e,"title")?.[1]??e.id}function ct(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=Mt(e),i=On(e);An(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===jt||e.kind===Ht)&&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?Bn(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}ot.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),Nn={dTag:"reference-source"},qn="https://reference.invalid/blob",je="reference-handler",Ln="reference-subscriber",$e="napplet:note/open",Pn={convention:$e,eventKinds:[1,30023]},m=e=>[e],L=()=>[];function yt(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 _n={"relay.subscribe":e=>m({type:"relay.eose",subId:e.subId}),"relay.close":L,"relay.publish":e=>m({type:"relay.publish.result",id:e.id,ok:!0,event:e.event}),"relay.publishEncrypted":e=>m({type:"relay.publishEncrypted.result",id:e.id,ok:!0,event:e.event}),"relay.query":e=>m({type:"relay.query.result",id:e.id,events:[]}),"identity.getPublicKey":e=>m({type:"identity.getPublicKey.result",id:e.id,pubkey:xe}),"identity.getRelays":e=>m({type:"identity.getRelays.result",id:e.id,relays:{}}),"identity.getProfile":e=>m({type:"identity.getProfile.result",id:e.id,profile:null}),"identity.getFollows":e=>m({type:"identity.getFollows.result",id:e.id,pubkeys:[]}),"identity.getList":e=>m({type:"identity.getList.result",id:e.id,entries:[]}),"identity.getZaps":e=>m({type:"identity.getZaps.result",id:e.id,zaps:[]}),"identity.getMutes":e=>m({type:"identity.getMutes.result",id:e.id,pubkeys:[]}),"identity.getBlocked":e=>m({type:"identity.getBlocked.result",id:e.id,pubkeys:[]}),"identity.getBadges":e=>m({type:"identity.getBadges.result",id:e.id,badges:[]}),"storage.get":e=>m({type:"storage.get.result",id:e.id,value:null}),"storage.set":e=>m({type:"storage.set.result",id:e.id}),"storage.remove":e=>m({type:"storage.remove.result",id:e.id}),"storage.keys":e=>m({type:"storage.keys.result",id:e.id,keys:[]}),"inc.emit":L,"inc.subscribe":e=>m({type:"inc.subscribe.result",id:e.id}),"inc.unsubscribe":L,"inc.channel.open":e=>m({type:"inc.channel.open.result",id:e.id,channelId:`chan-${String(e.id)}`,peer:"reference-peer"}),"inc.channel.emit":L,"inc.channel.broadcast":L,"inc.channel.list":e=>m({type:"inc.channel.list.result",id:e.id,channels:[]}),"inc.channel.close":L,"theme.get":e=>m({type:"theme.get.result",id:e.id,theme:{colors:{},mode:"dark"}}),"keys.forward":L,"keys.registerAction":e=>m({type:"keys.registerAction.result",id:e.id,actionId:`action-${String(e.id)}`}),"keys.unregisterAction":L,"media.session.create":e=>m({type:"media.session.create.result",id:e.id,sessionId:`session-${String(e.id)}`,owner:e.owner}),"media.session.update":L,"media.session.destroy":L,"media.state":L,"media.capabilities":L,"notify.send":e=>m({type:"notify.send.result",id:e.id,notificationId:`notif-${String(e.id)}`}),"notify.dismiss":L,"notify.badge":L,"notify.channel.register":L,"notify.permission.request":e=>m({type:"notify.permission.result",id:e.id,granted:!0}),"config.registerSchema":e=>m({type:"config.registerSchema.result",id:e.id,ok:!0}),"config.get":e=>m({type:"config.values",id:e.id,values:{}}),"config.subscribe":()=>m({type:"config.values",values:{}}),"config.unsubscribe":L,"config.openSettings":L,"resource.bytes":e=>{const t=yt(e.url);return m(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=>m({type:"resource.bytesMany.result",id:e.id,items:Array.isArray(e.urls)?e.urls.map(t=>{const r=yt(t);return{url:t,ok:!0,blob:r?.blob??new Blob([]),mime:r?.mime??"application/octet-stream"}}):[]}),"resource.info":e=>m({type:"resource.info.result",id:e.id,info:{schemes:[{scheme:"data",enabled:!0},{scheme:"https",enabled:!0}]}}),"resource.cancel":L,"cvm.discover":e=>m({type:"cvm.discover.result",id:e.id,servers:[]}),"cvm.request":e=>m({type:"cvm.request.result",id:e.id,message:{}}),"cvm.close":e=>m({type:"cvm.close.result",id:e.id}),"outbox.getEvent":e=>m({type:"outbox.getEvent.result",id:e.id}),"outbox.query":e=>m({type:"outbox.query.result",id:e.id,events:[]}),"outbox.subscribe":e=>m({type:"outbox.closed",subId:e.subId,reason:"reference shell complete"}),"outbox.close":L,"outbox.publish":e=>m({type:"outbox.publish.result",id:e.id,ok:!0}),"outbox.resolveRelays":e=>m({type:"outbox.resolveRelays.result",id:e.id,plan:{}}),"upload.info":e=>m({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=>m({type:"upload.upload.result",id:e.id,result:{url:qn}}),"upload.status":e=>m({type:"upload.status.result",id:e.id,status:{}}),"ble.open":e=>m({type:"ble.open.result",id:e.id,session:{id:"ble-reference",state:"open",device:{id:"reference-device",name:"Reference BLE"}}}),"ble.services":e=>m({type:"ble.services.result",id:e.id,services:[]}),"ble.read":e=>m({type:"ble.read.result",id:e.id,data:[]}),"ble.write":e=>m({type:"ble.write.result",id:e.id}),"ble.subscribe":e=>m({type:"ble.subscribe.result",id:e.id}),"ble.unsubscribe":e=>m({type:"ble.unsubscribe.result",id:e.id}),"ble.close":e=>m({type:"ble.close.result",id:e.id}),"common.encodeNip19":e=>m({type:"common.encodeNip19.result",id:e.id,ok:!0,value:"npub1reference",nip19Type:"npub"}),"common.decodeNip19":e=>m({type:"common.decodeNip19.result",id:e.id,ok:!0,nip19Type:"npub",hex:xe}),"common.getProfile":e=>m({type:"common.getProfile.result",id:e.id,ok:!0,pubkey:xe,profile:null}),"common.follows":e=>m({type:"common.follows.result",id:e.id,ok:!0,pubkeys:[]}),"common.follow":e=>m({type:"common.follow.result",id:e.id,ok:!0}),"common.unfollow":e=>m({type:"common.unfollow.result",id:e.id,ok:!0}),"common.react":e=>m({type:"common.react.result",id:e.id,ok:!0,eventId:"0".repeat(64)}),"common.report":e=>m({type:"common.report.result",id:e.id,ok:!0,eventId:"1".repeat(64)}),"webrtc.open":e=>m({type:"webrtc.open.result",id:e.id,session:{id:"webrtc-reference",scope:{type:"direct",pubkey:xe},channel:"default",state:"connecting"}}),"webrtc.send":e=>m({type:"webrtc.send.result",id:e.id}),"webrtc.close":e=>m({type:"webrtc.close.result",id:e.id}),"link.open":e=>m({type:"link.open.result",id:e.id,status:"opened"}),"count.query":e=>m({type:"count.query.result",id:e.id,ok:!0,count:0}),"lists.supported":e=>m({type:"lists.supported.result",id:e.id,lists:[]}),"lists.add":e=>m({type:"lists.add.result",id:e.id,ok:!0,added:0,skipped:0}),"lists.remove":e=>m({type:"lists.remove.result",id:e.id,ok:!0,removed:0,skipped:0}),"serial.open":e=>m({type:"serial.open.result",id:e.id,session:{id:`serial-${String(e.id)}`,state:"open"}}),"serial.write":e=>m({type:"serial.write.result",id:e.id}),"serial.close":e=>m({type:"serial.close.result",id:e.id})};function Cn(e={}){const t=e.now??(()=>Date.now()),r=[],n=new Map;function i(d,u){const h=n.get(d);if(h){h.push(u);return}n.set(d,[u])}function s(d){const u=n.get(d)??[];return n.delete(d),u}function o(d,u){return m({type:"intent.invoke.result",id:d,result:{ok:!1,error:u}})}function c(d,u){const h=u.request;if(typeof h!="object"||h===null||Array.isArray(h))return o(u.id,"invalid intent request");const b=h,{archetype:w,action:I,convention:T}=b;if(typeof w!="string"||typeof I!="string"||typeof T!="string")return o(u.id,"intent request must carry normalized identity");const j=/^napplet:([^/?#\s]+)\/([^/?#\s]+)$/.exec(T);if(!j||j[1]!==w||j[2]!==I)return o(u.id,"intent request conflicts with its convention");if(T!==$e)return o(u.id,"no reference handler for convention");const W={sender:d.dTag,archetype:w,action:I,convention:T};return"payload"in b&&(W.payload=b.payload),i(je,{type:"intent.deliver",delivery:W}),m({type:"intent.invoke.result",id:u.id,result:{ok:!0,archetype:w,action:I,convention:T,handler:je}})}function a(d){return d!=="note"?{archetype:d,available:!1,candidates:[],hasDefault:!1}:{archetype:d,available:!0,candidates:[{dTag:je,actions:["open"],conventions:[$e],contracts:[Pn],isDefault:!0}],hasDefault:!0}}function l(d,u){const h=u&&typeof u=="object"&&typeof u.type=="string"?u.type:void 0,b=Tn(u);if(r.push({envelope:u,verdict:b,timestamp:t()}),!h||!b.ok)return[];const w=u;if(h==="intent.invoke")return c(d,w);if(h==="intent.available")return m({type:"intent.available.result",id:w.id,availability:a(w.archetype)});if(h==="intent.handlers")return m({type:"intent.handlers.result",id:w.id,handlers:[a("note")]});if(h==="inc.emit"){if(w.topic===$e){const T={type:"inc.event",topic:w.topic,sender:d.dTag};"payload"in w&&(T.payload=w.payload),i(Ln,T)}return[]}const I=_n[h];return I?I(w):[]}function p(d){return l(Nn,d)}return{get records(){return r},handle:p,handleFrom:l,takeDeliveries:s,reset(){r.length=0,n.clear()}}}function Un(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 Vt="__nappletConformance.error";function wt(e){return new Promise(t=>setTimeout(t,e))}function Hn(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function jn(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) =>
43
+ request({ type: 'resource.bytes', url: String(url) }, 'resource.bytes.result', 'resource.bytes.error')
44
+ .then((msg) => msg.blob);
45
+ napplet.resource.bytesMany = (urls) =>
46
+ request({ type: 'resource.bytesMany', urls: Array.from(urls || []) }, 'resource.bytesMany.result', 'resource.bytesMany.error')
47
+ .then((msg) => msg.items);
48
+ napplet.resource.bytesAsObjectURL = (url) => {
49
+ const handle = { url: '', revoke: () => {} };
50
+ let objectUrl = '';
51
+ let revoked = false;
52
+ const ready = napplet.resource.bytes(url).then((blob) => {
53
+ if (revoked) return;
54
+ objectUrl = URL.createObjectURL(blob);
55
+ handle.url = objectUrl;
56
+ return objectUrl;
57
+ });
58
+ handle.revoke = () => {
59
+ if (revoked) return;
60
+ revoked = true;
61
+ if (objectUrl) URL.revokeObjectURL(objectUrl);
62
+ };
63
+ Object.defineProperty(handle, 'ready', { value: ready, enumerable: false });
64
+ return handle;
65
+ };
66
+ }
67
+ window.napplet = napplet;
68
+ const report = (reason) => {
69
+ try {
70
+ window.parent.postMessage({ type: '${Vt}', reason: String(reason && reason.message || reason) }, '*');
71
+ } catch {}
72
+ };
73
+ window.addEventListener('error', (event) => report(event.error || event.message));
74
+ window.addEventListener('unhandledrejection', (event) => report(event.reason));
75
+ })();
76
+ `}function Dn(e,t,r){const n=`<base href="${Hn(t)}">`,i=`<script>${jn(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 Mn(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 Zn(e){if(e==="about:blank")return"<!doctype html><html><head></head><body></body></html>";const t=Mn(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=Cn(),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=p=>{if(p.source!==s.contentWindow)return;const d=p.data;if(d&&typeof d=="object"&&d.type===Vt){o=`napplet boot error: ${String(d.reason??"unknown error")}`;return}const u=i.handle(p.data),h=p.source;for(const b of u)h?.postMessage(b,"*")};let a=!1;const l=new Promise(p=>{s.addEventListener("load",()=>{a=!0,p()},{once:!0})});n.addEventListener("message",c),(r.body??r.documentElement).appendChild(s);try{const p=await Zn(t.url);s.srcdoc=Dn(p,t.url,e)}catch(p){o=p instanceof Error?p.message:String(p)}if(!o){const p=Symbol("timeout");await Promise.race([l.then(()=>"loaded"),wt(t.readyTimeoutMs).then(()=>p)])===p||!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 Vn(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(ot,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 Wn=e=>({status:"pass",detail:e}),Fn=(e,t)=>({status:"fail",detail:e,diagnostics:t}),Kn=e=>({status:"skip",detail:e}),q={pass:Wn,fail:Fn,skip:Kn};function Yn(e,t){return ct(e.manifestEvent).errors.filter(r=>t.includes(r.code))}function De(e,t,r){return{id:e,area:"manifest",severity:"error",title:t,run:n=>{if(!n.manifestEvent)return q.skip("No NIP-5D manifest event was resolved");const i=Yn(n,r);return i.length?q.fail(i[0].message,i):q.pass()}}}var zn=[De("manifest/event-kind","Resolved event is a NIP-5D napplet manifest",["invalid-napplet-kind","missing-d-tag","unexpected-d-tag"]),De("manifest/index-html","Manifest declares a hashed /index.html",["missing-index-html","invalid-index-html-hash"]),De("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?q.fail("Napplet relied on allow-same-origin, which a shell must not grant"):q.pass():q.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?q.pass():q.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?q.fail(e.bootError):q.pass()},{id:"boot/no-forbidden-globals",area:"boot",severity:"error",title:"Does not access forbidden browser authority surfaces",run:e=>e.forbiddenGlobals.length?q.fail(`Accessed forbidden surface(s): ${e.forbiddenGlobals.join(", ")}`,e.forbiddenGlobals):q.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 q.skip("Napplet emitted no envelopes");const t=e.emitted.filter(n=>!n.verdict.ok);if(t.length===0)return q.pass(`${e.emitted.length} envelope(s) valid`);const r=t.map(n=>({envelope:n.envelope,errors:n.verdict.errors}));return q.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?q.fail(`Crashed with no injected domains: ${e.degraded.bootError}`):q.pass():q.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?q.fail("Message listeners remained after unload"):q.pass():q.skip("Lifecycle not measured")}];function Gn(e,t={}){const r=t.now??(()=>Date.now()),n=t.checks??zn,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?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 Xn(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 M(e,t,r=""){const n=Xn(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 Jn(e,t){M(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 Xe(...e){for(let t=0;t<e.length;t++)e[t].fill(0)}function Me(e){return new DataView(e.buffer,e.byteOffset,e.byteLength)}function G(e,t){return e<<32-t|e>>>t}const Wt=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",Qn=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function _(e){if(M(e),Wt)return e.toHex();let t="";for(let r=0;r<e.length;r++)t+=Qn[e[r]];return t}const Q={_0:48,_9:57,A:65,F:70,a:97,f:102};function xt(e){if(e>=Q._0&&e<=Q._9)return e-Q._0;if(e>=Q.A&&e<=Q.F)return e-(Q.A-10);if(e>=Q.a&&e<=Q.f)return e-(Q.a-10)}function J(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 Ae(...e){let t=0;for(let n=0;n<e.length;n++){const i=e[n];M(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 er(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 Ft(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 tr=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 Yt(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 nr(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 zt(e){if(!Number.isSafeInteger(e))throw new Error(`invalid integer: ${e}`)}function Je(e){if(!Array.isArray(e))throw new Error("array expected")}function Gt(e,t){if(!Yt(!0,t))throw new Error(`${e}: array of strings expected`)}function Xt(e,t){if(!Yt(!1,t))throw new Error(`${e}: array of numbers expected`)}function rr(...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 ir(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=>(Je(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=>(Je(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 sr(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),Be=(e,t)=>e+(t-Jt(e,t)),Ie=(()=>{let e=[];for(let t=0;t<40;t++)e.push(2**t);return e})();function Qe(e,t,r,n){if(Je(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(Be(t,r)>32)throw new Error(`convertRadix2: carry overflow from=${t} to=${r} carryBits=${Be(t,r)}`);let i=0,s=0;const o=Ie[t],c=Ie[r]-1,a=[];for(const l of e){if(zt(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 p=Ie[s];if(p===void 0)throw new Error("invalid carry");i&=p-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 or(e,t=!1){if(zt(e),e<=0||e>32)throw new Error("radix2: bits should be in (0..32]");if(Be(8,e)>32||Be(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 Qe(Array.from(r),8,e,!t)},decode:r=>(Xt("radix2.decode",r),Uint8Array.from(Qe(r,e,8,t)))}}function kt(e){return nr(e),function(...t){try{return e.apply(null,t)}catch{}}}const et=rr(ir("qpzry9x8gf2tvdw0s3jn54khce6mua7l"),sr("")),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 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=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,et.encode(Qe([i%Ie[30]],30,5,!1))}function ar(e){const t=e==="bech32"?1:734539939,r=or(5),n=r.decode,i=r.encode,s=kt(n);function o(d,u,h=90){be("bech32.encode prefix",d),Kt(u)&&(u=Array.from(u)),Xt("bech32.encode",u);const b=d.length;if(b===0)throw new TypeError(`Invalid prefix length ${b}`);const w=b+7+u.length;if(h!==!1&&w>h)throw new TypeError(`Length ${w} exceeds limit ${h}`);const I=d.toLowerCase(),T=St(I,u,t);return`${I}1${et.encode(u)}${T}`}function c(d,u=90){be("bech32.decode input",d);const h=d.length;if(h<8||u!==!1&&h>u)throw new TypeError(`invalid string length: ${h} (${d}). Expected (8..${u})`);const b=d.toLowerCase();if(d!==b&&d!==d.toUpperCase())throw new Error("String must be lowercase or uppercase");const w=b.lastIndexOf("1");if(w===0||w===-1)throw new Error('Letter "1" must be present between prefix and data only');const I=b.slice(0,w),T=b.slice(w+1);if(T.length<6)throw new Error("Data must be at least 6 characters long");const j=et.decode(T).slice(0,-6),W=St(I,j,t);if(!T.endsWith(W))throw new Error(`Invalid checksum in ${d}: expected "${W}"`);return{prefix:I,words:j}}const a=kt(c);function l(d){const{prefix:u,words:h}=c(d,!1);return{prefix:u,words:h,bytes:n(h)}}function p(d,u){return o(d,i(u))}return{encode:o,decode:c,encodeFromBytes:p,decodeToBytes:l,decodeUnsafe:a,fromWords:n,fromWordsUnsafe:s,toWords:i}}const $t=ar("bech32");var ke=new TextDecoder("utf-8");new TextEncoder;var cr=5e3;function lr(e){try{return e.startsWith("nostr:")&&(e=e.substring(6)),dr(e)}catch{return{type:"invalid",data:null}}}function dr(e){let{prefix:t,words:r}=$t.decode(e,cr),n=new Uint8Array($t.fromWords(r));switch(t){case"nprofile":{let i=Ze(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=>ke.decode(s)):[]}}}case"nevent":{let i=Ze(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=>ke.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=Ze(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:ke.decode(i[0][0]),pubkey:_(i[2][0]),kind:parseInt(_(i[3][0]),16),relays:i[1]?i[1].map(s=>ke.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 Ze(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 ur(e,t,r){return e&t^~e&r}function fr(e,t,r){return e&t^e&r^t&r}class hr{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=Me(this.buffer)}update(t){Et(this),M(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=Me(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),Jn(t,this),this.finished=!0;const{buffer:r,view:n,blockLen:i,isLE:s}=this;let{pos:o}=this;r[o++]=128,Xe(this.buffer.subarray(o)),this.padOffset>i-o&&(this.process(n,0),o=0);for(let d=o;d<i;d++)r[d]=0;n.setBigUint64(i-8,BigInt(this.length*8),s),this.process(n,0);const c=Me(t),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen must be aligned to 32bit");const l=a/4,p=this.get();if(l>p.length)throw new Error("_sha2: outputLen bigger than state");for(let d=0;d<l;d++)c.setUint32(4*d,p[d],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]),pr=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 gr extends hr{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 d=0;d<16;d++,r+=4)te[d]=t.getUint32(r,!1);for(let d=16;d<64;d++){const u=te[d-15],h=te[d-2],b=G(u,7)^G(u,18)^u>>>3,w=G(h,17)^G(h,19)^h>>>10;te[d]=w+te[d-7]+b+te[d-16]|0}let{A:n,B:i,C:s,D:o,E:c,F:a,G:l,H:p}=this;for(let d=0;d<64;d++){const u=G(c,6)^G(c,11)^G(c,25),h=p+u+ur(c,a,l)+pr[d]+te[d]|0,w=(G(n,2)^G(n,13)^G(n,22))+fr(n,i,s)|0;p=l,l=a,a=c,c=o+h|0,o=s,s=i,i=n,n=h+w|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,p=p+this.H|0,this.set(n,i,s,o,c,a,l,p)}roundClean(){Xe(te)}destroy(){this.set(0,0,0,0,0,0,0,0),Xe(this.buffer)}}class mr extends gr{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 Oe=er(()=>new mr,tr(1));/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const dt=BigInt(0),tt=BigInt(1);function It(e,t=""){if(typeof e!="boolean"){const r=t&&`"${t}" `;throw new Error(r+"expected boolean, got type="+typeof e)}return e}function br(e){if(typeof e=="bigint"){if(!vr(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(_(yr(M(e)).reverse()))}function ft(e,t){lt(t),e=br(e);const r=J(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 yr(e){return Uint8Array.from(e)}function wr(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 vr=e=>typeof e=="bigint"&&dt<=e;function Er(e){let t;for(t=0;e>dt;e>>=tt,t+=1);return t}const nn=e=>(tt<<BigInt(e))-tt;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 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 D=BigInt(0),H=BigInt(1),se=BigInt(2),sn=BigInt(3),on=BigInt(4),an=BigInt(5),xr=BigInt(7),cn=BigInt(8),kr=BigInt(9),ln=BigInt(16);function Y(e,t){const r=e%t;return r>=D?r:t+r}function V(e,t,r){let n=e;for(;t-- >D;)n*=n,n%=r;return n}function At(e,t){if(e===D)throw new Error("invert: expected non-zero number");if(t<=D)throw new Error("invert: expected positive modulus, got "+t);let r=Y(e,t),n=t,i=D,s=H;for(;r!==D;){const c=n/r,a=n%r,l=i-s*c;n=r,r=a,i=s,s=l}if(n!==H)throw new Error("invert: does not exist");return Y(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+H)/on,n=e.pow(t,r);return ht(e,n,t),n}function Rr(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 Sr(e){const t=Pe(e),r=un(e),n=r(t,t.neg(t.ONE)),i=r(t,n),s=r(t,t.neg(n)),o=(e+xr)/ln;return(c,a)=>{let l=c.pow(a,o),p=c.mul(l,n);const d=c.mul(l,i),u=c.mul(l,s),h=c.eql(c.sqr(p),a),b=c.eql(c.sqr(d),a);l=c.cmov(l,p,h),p=c.cmov(u,d,b);const w=c.eql(c.sqr(p),a),I=c.cmov(l,p,w);return ht(c,I,a),I}}function un(e){if(e<sn)throw new Error("sqrt is not defined for small field");let t=e-H,r=0;for(;t%se===D;)t/=se,r++;let n=se;const i=Pe(e);for(;Bt(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+H)/se;return function(a,l){if(a.is0(l))return l;if(Bt(a,l)!==1)throw new Error("Cannot find square root");let p=r,d=a.mul(a.ONE,s),u=a.pow(l,t),h=a.pow(l,o);for(;!a.eql(u,a.ONE);){if(a.is0(u))return a.ZERO;let b=1,w=a.sqr(u);for(;!a.eql(w,a.ONE);)if(b++,w=a.sqr(w),b===p)throw new Error("Cannot find square root");const I=H<<BigInt(p-b-1),T=a.pow(d,I);p=b,d=a.sqr(T),u=a.mul(u,d),h=a.mul(h,T)}return h}}function $r(e){return e%on===sn?dn:e%cn===an?Rr:e%ln===kr?Sr(e):un(e)}const Ir=["create","isValid","is0","neg","inv","sqrt","sqr","eql","add","sub","mul","pow","div","addN","subN","mulN","sqrN"];function Tr(e){const t={ORDER:"bigint",BYTES:"number",BITS:"number"},r=Ir.reduce((n,i)=>(n[i]="function",n),t);return rn(e,r),e}function Ar(e,t,r){if(r<D)throw new Error("invalid exponent, negatives unsupported");if(r===D)return e.ONE;if(r===H)return t;let n=e.ONE,i=t;for(;r>D;)r&H&&(n=e.mul(n,i)),i=e.sqr(i),r>>=H;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 Bt(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 Br(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 Or{ORDER;BITS;BYTES;isLE;ZERO=D;ONE=H;_lengths;_sqrt;_mod;constructor(t,r={}){if(t<=D)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}=Br(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 Y(t,this.ORDER)}isValid(t){if(typeof t!="bigint")throw new Error("invalid field element: expected bigint, got "+typeof t);return D<=t&&t<this.ORDER}is0(t){return t===D}isValidNot0(t){return!this.is0(t)&&this.isValid(t)}isOdd(t){return(t&H)===H}neg(t){return Y(-t,this.ORDER)}eql(t,r){return t===r}sqr(t){return Y(t*t,this.ORDER)}add(t,r){return Y(t+r,this.ORDER)}sub(t,r){return Y(t-r,this.ORDER)}mul(t,r){return Y(t*r,this.ORDER)}pow(t,r){return Ar(this,t,r)}div(t,r){return Y(t*At(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 At(t,this.ORDER)}sqrt(t){return this._sqrt||(this._sqrt=$r(this.ORDER)),this._sqrt(this,t)}toBytes(t){return this.isLE?tn(t,this.BYTES):ft(t,this.BYTES)}fromBytes(t,r=!1){M(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=Y(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 Pe(e,t={}){return new Or(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 Nr(e){const t=hn(e);return t+Math.ceil(t/2)}function qr(e,t,r=!1){M(e);const n=e.length,i=hn(t),s=Nr(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=Y(o,t-H)+H;return r?tn(c,i):ft(c,i)}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const le=BigInt(0),oe=BigInt(1);function Ne(e,t){const r=t.negate();return e?r:t}function Ot(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 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 l=t*n,p=l+Math.abs(c)-1,d=c===0,u=c<0,h=t%2!==0;return{nextN:a,offset:p,isZero:d,isNeg:u,isNegF:h,offsetF:l}}const We=new WeakMap,gn=new WeakMap;function Fe(e){return gn.get(e)||1}function qt(e){if(e!==le)throw new Error("invalid wNAF")}class Lr{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}=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:p,isNeg:d,isNegF:u,offsetF:h}=Nt(n,c,o);n=a,p?s=s.add(Ne(u,r[h])):i=i.add(Ne(d,r[l]))}return qt(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!==le;o++){const{nextN:c,offset:a,isZero:l,isNeg:p}=Nt(n,o,s);if(n=c,!l){const d=r[a];i=i.add(p?d.negate():d)}}return qt(n),i}getPrecomputes(t,r,n){let i=We.get(r);return i||(i=this.precomputeWindow(r,t),t!==1&&(typeof n=="function"&&(i=n(i)),We.set(r,i))),i}cached(t,r,n){const i=Fe(t);return this.wNAF(i,this.getPrecomputes(i,t,n),r)}unsafe(t,r,n,i){const s=Fe(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),We.delete(t)}hasCache(t){return Fe(t)!==1}}function Pr(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 Lt(e,t,r){if(t){if(t.ORDER!==e)throw new Error("Field.ORDER must match order: Fp == p, Fn == n");return Tr(t),t}else return Pe(e,{isLE:r})}function _r(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>le))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 Cr(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)/Hr)/t;function Ur(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,p=-c*i-a*o;const d=l<he,u=p<he;d&&(l=-l),u&&(p=-p);const h=nn(Math.ceil(Er(r)/2))+Te;if(l<he||l>=h||p<he||p>=h)throw new Error("splitScalar (endomorphism): failed, k="+e);return{k1neg:d,k1:l,k2neg:u,k2:p}}const he=BigInt(0),Te=BigInt(1),Hr=BigInt(2),Re=BigInt(3),jr=BigInt(4);function Dr(e,t={}){const r=_r("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=Zr(n,i);function p(){if(!n.isOdd)throw new Error("compression is not supported: Field does not have .isOdd()")}function d(A,g,y){const{x:E,y:x}=g.toAffine(),B=n.toBytes(E);if(It(y,"isCompressed"),y){p();const S=!n.isOdd(x);return Ae(Mr(S),B)}else return Ae(Uint8Array.of(4),B,n.toBytes(x))}function u(A){M(A,void 0,"Point");const{publicKey:g,publicKeyUncompressed:y}=l,E=A.length,x=A[0],B=A.subarray(1);if(E===g&&(x===2||x===3)){const S=n.fromBytes(B);if(!n.isValid(S))throw new Error("bad point: is not on curve, wrong x");const k=w(S);let v;try{v=n.sqrt(k)}catch(Z){const P=Z instanceof Error?": "+Z.message:"";throw new Error("bad point: is not on curve, sqrt error"+P)}p();const R=n.isOdd(v);return(x&1)===1!==R&&(v=n.neg(v)),{x:S,y:v}}else if(E===y&&x===4){const S=n.BYTES,k=n.fromBytes(B.subarray(0,S)),v=n.fromBytes(B.subarray(S,S*2));if(!I(k,v))throw new Error("bad point: is not on curve");return{x:k,y:v}}else throw new Error(`bad point: got length ${E}, expected compressed=${g} or uncompressed=${y}`)}const h=t.toBytes||d,b=t.fromBytes||u;function w(A){const g=n.sqr(A),y=n.mul(g,A);return n.add(n.add(y,n.mul(A,s.a)),s.b)}function I(A,g){const y=n.sqr(g),E=w(A);return n.eql(y,E)}if(!I(s.Gx,s.Gy))throw new Error("bad curve params: generator point");const T=n.mul(n.pow(s.a,Re),jr),j=n.mul(n.sqr(s.b),BigInt(27));if(n.is0(n.add(T,j)))throw new Error("bad curve params: a or b");function W(A,g,y=!1){if(!n.isValid(g)||y&&n.is0(g))throw new Error(`bad point coordinate ${A}`);return g}function we(A){if(!(A instanceof N))throw new Error("Weierstrass Point expected")}function ve(A){if(!a||!a.basises)throw new Error("no endo");return Ur(A,a.basises,i.ORDER)}const Ee=Tt((A,g)=>{const{X:y,Y:E,Z:x}=A;if(n.eql(x,n.ONE))return{x:y,y:E};const B=A.is0();g==null&&(g=B?n.ONE:n.inv(x));const S=n.mul(y,g),k=n.mul(E,g),v=n.mul(x,g);if(B)return{x:n.ZERO,y:n.ZERO};if(!n.eql(v,n.ONE))throw new Error("invZ was invalid");return{x:S,y:k}}),Rn=Tt(A=>{if(A.is0()){if(t.allowInfinityPoint&&!n.is0(A.Y))return;throw new Error("bad point: ZERO")}const{x:g,y}=A.toAffine();if(!n.isValid(g)||!n.isValid(y))throw new Error("bad point: x or y not field elements");if(!I(g,y))throw new Error("bad point: equation left != right");if(!A.isTorsionFree())throw new Error("bad point: not in prime-order subgroup");return!0});function mt(A,g,y,E,x){return y=new N(n.mul(y.X,A),y.Y,y.Z),g=Ne(E,g),y=Ne(x,y),g.add(y)}class N{static BASE=new N(s.Gx,s.Gy,n.ONE);static ZERO=new N(n.ZERO,n.ONE,n.ZERO);static Fp=n;static Fn=i;X;Y;Z;constructor(g,y,E){this.X=W("x",g),this.Y=W("y",y,!0),this.Z=W("z",E),Object.freeze(this)}static CURVE(){return s}static fromAffine(g){const{x:y,y:E}=g||{};if(!g||!n.isValid(y)||!n.isValid(E))throw new Error("invalid affine point");if(g instanceof N)throw new Error("projective point not allowed");return n.is0(y)&&n.is0(E)?N.ZERO:new N(y,E,n.ONE)}static fromBytes(g){const y=N.fromAffine(b(M(g,void 0,"point")));return y.assertValidity(),y}static fromHex(g){return N.fromBytes(J(g))}get x(){return this.toAffine().x}get y(){return this.toAffine().y}precompute(g=8,y=!0){return ue.createCache(this,g),y||this.multiply(Re),this}assertValidity(){Rn(this)}hasEvenY(){const{y:g}=this.toAffine();if(!n.isOdd)throw new Error("Field doesn't support isOdd");return!n.isOdd(g)}equals(g){we(g);const{X:y,Y:E,Z:x}=this,{X:B,Y:S,Z:k}=g,v=n.eql(n.mul(y,k),n.mul(B,x)),R=n.eql(n.mul(E,k),n.mul(S,x));return v&&R}negate(){return new N(this.X,n.neg(this.Y),this.Z)}double(){const{a:g,b:y}=s,E=n.mul(y,Re),{X:x,Y:B,Z:S}=this;let k=n.ZERO,v=n.ZERO,R=n.ZERO,$=n.mul(x,x),Z=n.mul(B,B),P=n.mul(S,S),O=n.mul(x,B);return O=n.add(O,O),R=n.mul(x,S),R=n.add(R,R),k=n.mul(g,R),v=n.mul(E,P),v=n.add(k,v),k=n.sub(Z,v),v=n.add(Z,v),v=n.mul(k,v),k=n.mul(O,k),R=n.mul(E,R),P=n.mul(g,P),O=n.sub($,P),O=n.mul(g,O),O=n.add(O,R),R=n.add($,$),$=n.add(R,$),$=n.add($,P),$=n.mul($,O),v=n.add(v,$),P=n.mul(B,S),P=n.add(P,P),$=n.mul(P,O),k=n.sub(k,$),R=n.mul(P,Z),R=n.add(R,R),R=n.add(R,R),new N(k,v,R)}add(g){we(g);const{X:y,Y:E,Z:x}=this,{X:B,Y:S,Z:k}=g;let v=n.ZERO,R=n.ZERO,$=n.ZERO;const Z=s.a,P=n.mul(s.b,Re);let O=n.mul(y,B),F=n.mul(E,S),K=n.mul(x,k),ae=n.add(y,E),U=n.add(B,S);ae=n.mul(ae,U),U=n.add(O,F),ae=n.sub(ae,U),U=n.add(y,x);let z=n.add(B,k);return U=n.mul(U,z),z=n.add(O,K),U=n.sub(U,z),z=n.add(E,x),v=n.add(S,k),z=n.mul(z,v),v=n.add(F,K),z=n.sub(z,v),$=n.mul(Z,U),v=n.mul(P,K),$=n.add(v,$),v=n.sub(F,$),$=n.add(F,$),R=n.mul(v,$),F=n.add(O,O),F=n.add(F,O),K=n.mul(Z,K),U=n.mul(P,U),F=n.add(F,K),K=n.sub(O,K),K=n.mul(Z,K),U=n.add(U,K),O=n.mul(F,U),R=n.add(R,O),O=n.mul(z,U),v=n.mul(ae,v),v=n.sub(v,O),O=n.mul(ae,F),$=n.mul(z,$),$=n.add($,O),new N(v,R,$)}subtract(g){return this.add(g.negate())}is0(){return this.equals(N.ZERO)}multiply(g){const{endo:y}=t;if(!i.isValidNot0(g))throw new Error("invalid scalar: out of range");let E,x;const B=S=>ue.cached(this,S,k=>Ot(N,k));if(y){const{k1neg:S,k1:k,k2neg:v,k2:R}=ve(g),{p:$,f:Z}=B(k),{p:P,f:O}=B(R);x=Z.add(O),E=mt(y.beta,$,P,S,v)}else{const{p:S,f:k}=B(g);E=S,x=k}return Ot(N,[E,x])[0]}multiplyUnsafe(g){const{endo:y}=t,E=this;if(!i.isValid(g))throw new Error("invalid scalar: out of range");if(g===he||E.is0())return N.ZERO;if(g===Te)return E;if(ue.hasCache(this))return this.multiply(g);if(y){const{k1neg:x,k1:B,k2neg:S,k2:k}=ve(g),{p1:v,p2:R}=Pr(N,E,B,k);return mt(y.beta,v,R,x,S)}else return ue.unsafe(E,g)}toAffine(g){return Ee(this,g)}isTorsionFree(){const{isTorsionFree:g}=t;return o===Te?!0:g?g(N,this):ue.unsafe(this,c).is0()}clearCofactor(){const{clearCofactor:g}=t;return o===Te?this:g?g(N,this):this.multiplyUnsafe(o)}isSmallOrder(){return this.multiplyUnsafe(o).is0()}toBytes(g=!0){return It(g,"isCompressed"),this.assertValidity(),h(N,this,g)}toHex(g=!0){return _(this.toBytes(g))}toString(){return`<Point ${this.is0()?"ZERO":this.toHex()}>`}}const bt=i.BITS,ue=new Lr(N,t.endo?Math.ceil(bt/2):bt);return N.BASE.precompute(8),N}function Mr(e){return Uint8Array.of(e?2:3)}function Zr(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 _e={p:BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"),n:BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),h:BigInt(1),a:BigInt(0),b:BigInt(7),Gx:BigInt("0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"),Gy:BigInt("0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8")},Vr={beta:BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"),basises:[[BigInt("0x3086d221a7d46bcde86c90e49284eb15"),-BigInt("0xe4437ed6010e88286f547fa90abfe4c3")],[BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8"),BigInt("0x3086d221a7d46bcde86c90e49284eb15")]]},Wr=BigInt(0),nt=BigInt(2);function Fr(e){const t=_e.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,p=l*l*e%t,d=V(p,r,t)*p%t,u=V(d,r,t)*p%t,h=V(u,nt,t)*l%t,b=V(h,i,t)*h%t,w=V(b,s,t)*b%t,I=V(w,c,t)*w%t,T=V(I,a,t)*I%t,j=V(T,c,t)*w%t,W=V(j,r,t)*p%t,we=V(W,o,t)*b%t,ve=V(we,n,t)*l%t,Ee=V(ve,nt,t);if(!qe.eql(qe.sqr(Ee),e))throw new Error("Cannot find square root");return Ee}const qe=Pe(_e.p,{sqrt:Fr}),de=Dr(_e,{Fp:qe,endo:Vr}),_t={};function Le(e,...t){let r=_t[e];if(r===void 0){const n=Oe(wr(e));r=Ae(n,n),_t[e]=r}return Oe(Ae(r,...t))}const pt=e=>e.toBytes(!0).slice(1),gt=e=>e%nt===Wr;function rt(e){const{Fn:t,BASE:r}=de,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=qe;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=de.fromAffine({x:e,y:i});return s.assertValidity(),s}const me=ut;function bn(...e){return de.Fn.create(me(Le("BIP0340/challenge",...e)))}function Ct(e){return rt(e).bytes}function Kr(e,t,r=Ft(32)){const{Fn:n}=de,i=M(e,void 0,"message"),{bytes:s,scalar:o}=rt(t),c=M(r,32,"auxRand"),a=n.toBytes(o^me(Le("BIP0340/aux",c))),l=Le("BIP0340/nonce",a,s,i),{bytes:p,scalar:d}=rt(l),u=bn(p,s,i),h=new Uint8Array(64);if(h.set(p,0),h.set(n.toBytes(n.create(d+u*o)),32),!yn(h,i,s))throw new Error("sign: Invalid signature produced");return h}function yn(e,t,r){const{Fp:n,Fn:i,BASE:s}=de,o=M(e,64,"signature"),c=M(t,void 0,"message"),a=M(r,32,"publicKey");try{const l=mn(me(a)),p=me(o.subarray(0,32));if(!n.isValidNot0(p))return!1;const d=me(o.subarray(32,64));if(!i.isValidNot0(d))return!1;const u=bn(i.toBytes(p),pt(l),c),h=s.multiplyUnsafe(d).add(l.multiplyUnsafe(i.neg(u))),{x:b,y:w}=h.toAffine();return!(h.is0()||!gt(w)||b!==p)}catch{return!1}}const X=(()=>{const r=(n=Ft(48))=>qr(n,_e.n);return{keygen:Cr(r,Ct),getPublicKey:Ct,sign:Kr,verify:yn,Point:de,utils:{randomSecretKey:r,taggedHash:Le,lift_x:mn,pointToBytes:pt},lengths:{secretKey:32,publicKey:32,publicKeyHasPrefix:!1,signature:64,seed:48}}})();var ie=Symbol("verified"),Yr=e=>e instanceof Object;function zr(e){if(!Yr(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 Gr=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 Xr=class{generateSecretKey(){return X.utils.randomSecretKey()}getPublicKey(t){return _(X.getPublicKey(t))}finalizeEvent(t,r){const n=t;return n.pubkey=_(X.getPublicKey(r)),n.id=Ke(n),n.sig=_(X.sign(J(Ke(n)),r)),n[ie]=!0,n}verifyEvent(t){if(typeof t[ie]=="boolean")return t[ie];try{const r=Ke(t);if(r!==t.id)return t[ie]=!1,!1;const n=X.verify(J(t.sig),J(r),J(t.pubkey));return t[ie]=n,n}catch{return t[ie]=!1,!1}}};function Jr(e){if(!zr(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 Ke(e){let t=Oe(Gr.encode(Jr(e)));return _(t)}var Ce=new Xr;Ce.generateSecretKey;Ce.getPublicKey;Ce.finalizeEvent;var Qr=Ce.verifyEvent,ei=22242;function ti(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 ni(e,t){for(let r=0;r<e.length;r++)if(ti(e[r],t))return!0;return!1}function ri(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 ii(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 si(e,t){return{kind:ei,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=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 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(si(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 oi(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=ii(t);if(r){const n=this.openSubs.get(r);if(!n)return;const i=ri(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)&&ni(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}}},oi=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)}},ai=e=>(e[ie]=!0,!0),ci=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 vn(e,{verifyEvent:this.trustedRelayURLs.has(e)?ai: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 u of e){const{url:h,filter:b}=u;r.has(h)||r.set(h,[]),r.get(h).push(b)}const n=Array.from(r.entries()).map(([u,h])=>({url:u,filters:h}));this.trackRelays&&(t.receivedEvent=(u,h)=>{let b=this.seenOn.get(h);b||(b=new Set,this.seenOn.set(h,b)),b.add(u)});const i=new Set,s=[],o=[];let c=u=>{o[u]||(o[u]=!0,o.filter(h=>h).length===n.length&&(t.oneose?.(),c=()=>{}))};const a=[];let l=(u,h)=>{a[u]||(c(u),a[u]=h,a.filter(b=>b).length===n.length&&(t.onclose?.(a),l=()=>{}))};const p=u=>{if(t.alreadyHaveEvent?.(u))return!0;const h=i.has(u);return i.add(u),h},d=Promise.all(n.map(async({url:u,filters:h},b)=>{if(this.allowConnectingToRelay?.(u,["read",h])===!1){l(b,"connection skipped by allowConnectingToRelay");return}let w;try{w=await this.ensureRelay(u,{connectionTimeout:this.maxWaitForConnection<(t.maxWait||0)?Math.max(t.maxWait*.8,t.maxWait-1e3):this.maxWaitForConnection,abort:t.abort})}catch(T){this.onRelayConnectionFailure?.(u),l(b,T?.message||String(T));return}this.onRelayConnectionSuccess?.(u);let I=w.subscribe(h,{...t,oneose:()=>c(b),onclose:T=>{T.startsWith("auth-required: ")&&t.onauth?w.auth(t.onauth).then(()=>{w.subscribe(h,{...t,oneose:()=>c(b),onclose:j=>{l(b,j)},alreadyHaveEvent:p,eoseTimeout:t.maxWait,abort:t.abort})}).catch(j=>{l(b,`auth was required and attempted, but failed with: ${j}`)}):l(b,T)},alreadyHaveEvent:p,eoseTimeout:t.maxWait,abort:t.abort});s.push(I)}));return{async close(u){await d,s.forEach(h=>{h.close(u)})}}}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}},En;try{En=WebSocket}catch{}var li=class extends ci{constructor(e){super({verifyEvent:Qr,websocketImplementation:En,maxWaitForConnection:3e3,...e})}},ce=Symbol("verified"),di=e=>e instanceof Object;function ui(e){if(!di(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 fi=new TextEncoder,hi=class{generateSecretKey(){return X.utils.randomSecretKey()}getPublicKey(e){return _(X.getPublicKey(e))}finalizeEvent(e,t){const r=e;return r.pubkey=_(X.getPublicKey(t)),r.id=Ye(r),r.sig=_(X.sign(J(Ye(r)),t)),r[ce]=!0,r}verifyEvent(e){if(typeof e[ce]=="boolean")return e[ce];try{const t=Ye(e);if(t!==e.id)return e[ce]=!1,!1;const r=X.verify(J(e.sig),J(t),J(e.pubkey));return e[ce]=r,r}catch{return e[ce]=!1,!1}}};function pi(e){if(!ui(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=Oe(fi.encode(pi(e)));return _(t)}var Ue=new hi;Ue.generateSecretKey;Ue.getPublicKey;Ue.finalizeEvent;var gi=Ue.verifyEvent;const mi=8e3;function bi(e){return typeof e=="number"&&at.includes(e)}function yi(e){try{const t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function wi(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 vi(e){const t=lr(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=wi(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&&!bi(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?[...at]:[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 Ei(e){return{id:e.id,pubkey:e.pubkey,kind:e.kind,tags:e.tags}}async function xn(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 xi(e){return e.tags.filter(t=>t[0]==="path"&&typeof t[1]=="string"&&typeof t[2]=="string")}async function ki(e){const t=xi(e).map(r=>`${r[2]} ${r[1]}
77
+ `).sort().join("");return xn(t)}async function Ri(e){const t=await ki(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 Si(e){return e.tags.find(t=>t[0]==="path"&&t[1]==="/index.html")}function $i(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 Ii(e,t){const r=e.endsWith("/")?e:`${e}/`;return new URL(t,r).href}async function Ti(e,t=fetch){const n=Si(e)?.[2];if(!n)throw new Error("Manifest does not include a /index.html path hash");const i=$i(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=Ii(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()),p=await xn(l);if(p!==n){s.push(`${c}: sha256 ${p} 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 Ai(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 Bi(e,t){const r=vi(e),n=!t.pool,i=t.pool??new li;try{const s=await i.get(r.relays,{...r.filter},{maxWait:t.maxRelayWaitMs??mi});if(!s)throw new Error("No matching napplet manifest event was found on the pointer relay hints");if(!gi(s))throw new Error("Resolved manifest event signature is invalid");const o=Ei(s),c=ct(o);if(!c.ok)throw new Error(`Resolved event is not a valid NIP-5D napplet manifest: ${c.errors[0]?.message}`);await Ri(o);const a=await Ti(o,t.fetcher??fetch),l=(t.createObjectUrl??URL.createObjectURL)(new Blob([a],{type:"text/html;charset=utf-8"})),p=()=>(t.revokeObjectUrl??URL.revokeObjectURL)(l);return{source:"nostr",input:e,label:o.id??e,bootUrl:l,html:a,fetched:!0,manifestEvent:o,revoke:p}}finally{n&&i.destroy()}}async function Oi(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 yi(r)?Ai(r,t.fetcher??fetch):Bi(r,t)}const Ni=/\bwindow\s*\.\s*nostr\b|\bglobalThis\s*\.\s*nostr\b/,qi="/__conformance__/events",it=new URLSearchParams(location.search),kn=it.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 Li(){return re.innerHTML=`
78
+ <header class="masthead">
79
+ <h1>napplet conformance ${kn?'<span class="live-badge" id="live-badge">● live</span>':""}</h1>
80
+ <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>
81
+ </header>
82
+ <form id="run-form" class="runbar">
83
+ <input id="target" type="text" placeholder="naddr1… or nevent1… for a NIP-5D napplet manifest" autocomplete="off" spellcheck="false" />
84
+ <button id="run" type="submit">Run conformance</button>
85
+ <button id="rerun" type="button" class="secondary" hidden>Re-run</button>
86
+ </form>
87
+ <p id="status" class="status" role="status"></p>
88
+ <section id="output" class="output"></section>
89
+ `,{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=Li();let ye="",st=0;function Se(e,t="info"){C.status.textContent=e,C.status.dataset.kind=t}function ze(e){return String(e).padStart(2,"0")}function Pi(e){const t=new Date(e);return`${ze(t.getHours())}:${ze(t.getMinutes())}:${ze(t.getSeconds())}`}function _i(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>':"",p=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}${p}</li>`}).join("");return`<div class="area"><h3>${ne(o)}</h3><ul>${c}</ul></div>`}).join(""),i=e.summary,s=st>1?`<span class="run-stamp">run #${st} · ${Pi(e.finishedAt)}</span>`:"";return`
90
+ <div class="verdict ${t}">
91
+ <span class="result">${e.ok?"CONFORMANT":"NON-CONFORMANT"}</span>
92
+ <span class="counts">${i.passed} passed · ${i.failed} failed · ${i.skipped} skipped${i.warnings?` · ${i.warnings} warning(s)`:""}</span>
93
+ ${s}
94
+ </div>
95
+ <div class="checks">${n}</div>
96
+ `}function Ci(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 Ui(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=ct(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`
97
+ <table class="manifest">
98
+ ${t("event",r.id)}
99
+ ${t("kind",r.kind)}
100
+ ${t("d",i)}
101
+ ${t("name",Zt(r))}
102
+ ${t("requires",n.requires.join(", "))}
103
+ ${t("/index.html",s?.[2])}
104
+ ${t("servers",o.join(", "))}
105
+ </table>
106
+ ${n.errors.length?`<div class="errs">${n.errors.map(c=>ne(`${c.code}: ${c.message}`)).join("<br>")}</div>`:""}
107
+ `}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 Hi(e,t,r){C.output.innerHTML=`
108
+ ${_i(e)}
109
+ <div class="panels">
110
+ <section class="panel"><h2>Emitted envelopes (${t.length})</h2>${Ci(t)}</section>
111
+ <section class="panel"><h2>Manifest</h2>${Ui(r)}</section>
112
+ </div>
113
+ `}async function He(e){ye=e,C.runButton.disabled=!0,C.rerunButton.disabled=!0;let t=null;try{Se(`Resolving ${e} …`),t=await Oi(e);const r=Ni.test(t.html)?["window.nostr"]:[];Se("Booting napplet in a sandboxed iframe …");const n=await Vn({url:t.bootUrl,readyTimeoutMs:5e3,settleMs:800,runDegraded:!0}),i=Un({manifestHtml:t.html,manifestEvent:t.manifestEvent,boot:n,forbiddenGlobals:r}),s=Gn(i);st+=1,Se(s.ok?"Done — conformant.":"Done — non-conformant.",s.ok?"info":"error"),Hi(s,n.emitted,t),C.rerunButton.hidden=!1}catch(r){Se(`Error: ${r instanceof Error?r.message:String(r)}`,"error")}finally{t?.revoke?.(),C.runButton.disabled=!1,C.rerunButton.disabled=!1}}function ji(){if(!kn||typeof EventSource>"u")return;let e=!1;const t=new EventSource(qi);t.addEventListener("rerun",()=>{!ye||e||(e=!0,setTimeout(()=>{e=!1,He(ye)},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),He(t)}});C.rerunButton.addEventListener("click",()=>{ye&&He(ye)});ji();const Ge=it.get("target")??it.get("url");Ge&&(C.targetInput.value=Ge,He(Ge));
@@ -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-j_MRjiMC.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-ugli4mLk.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.15",
3
+ "version": "0.2.16",
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.13.0"
18
+ "@napplet/conformance": "^0.14.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
24
  "vitest": "^4.1.2",
25
- "@napplet/conformance-web": "0.0.14"
25
+ "@napplet/conformance-web": "0.0.15"
26
26
  },
27
27
  "license": "MIT",
28
28
  "repository": {
@@ -1,113 +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 it=["relay","identity","storage","inc","theme","keys","media","notify","config","resource","cvm","outbox","upload","intent","ble","webrtc","link","count","lists","serial","common","dm"],d={id:"string"},kn={"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"}},"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"},"inc.channel.open.result":{dir:"in"},"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,urls:"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"},"intent.available.result":{dir:"in"},"intent.handlers.result":{dir:"in"},"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"},"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 _t(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:_t(e)===t}function Rn(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(!it.includes(s))return{ok:!1,type:n,domain:s,errors:[{code:"unknown-domain",message:`"${s}" is not a known NAP domain`}]};const c=kn[n];if(!c)return{ok:!1,type:n,domain:s,errors:[{code:"unknown-type",message:`"${n}" is not a known ${s} message type`}]};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`}]};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 ${_t(r[a])}`,field:a})}return{ok:t.length===0,type:n,domain:s,direction:"out",errors:t}}var Ct=5129,Ut=15129,ge=35129,st=[Ct,Ut,ge];function Ht(e,t){return e.tags.find(r=>r[0]===t)}function $n(e){return st.includes(e)}function Tn(e){return typeof e=="string"&&/^[0-9a-f]{64}$/i.test(e)}function jt(e){return Ht(e,"d")?.[1]?.trim()||void 0}function Bn(e){return e.tags.filter(t=>t[0]==="requires").map(t=>t[1]?.trim()??"").filter(Boolean)}function Mt(e){return jt(e)??Ht(e,"title")?.[1]??e.id}function ot(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=jt(e),i=Bn(e);$n(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===Ut||e.kind===Ct)&&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?Tn(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}it.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,nappletType:n,requires:i,errors:t,warnings:r}}var xe="f".repeat(64),In="https://reference.invalid/blob",p=e=>[e],q=()=>[];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 An={"relay.subscribe":e=>p({type:"relay.eose",subId:e.subId}),"relay.close":q,"relay.publish":e=>p({type:"relay.publish.result",id:e.id,ok:!0,event:e.event}),"relay.publishEncrypted":e=>p({type:"relay.publishEncrypted.result",id:e.id,ok:!0,event:e.event}),"relay.query":e=>p({type:"relay.query.result",id:e.id,events:[]}),"identity.getPublicKey":e=>p({type:"identity.getPublicKey.result",id:e.id,pubkey:xe}),"identity.getRelays":e=>p({type:"identity.getRelays.result",id:e.id,relays:{}}),"identity.getProfile":e=>p({type:"identity.getProfile.result",id:e.id,profile:null}),"identity.getFollows":e=>p({type:"identity.getFollows.result",id:e.id,pubkeys:[]}),"identity.getList":e=>p({type:"identity.getList.result",id:e.id,entries:[]}),"identity.getZaps":e=>p({type:"identity.getZaps.result",id:e.id,zaps:[]}),"identity.getMutes":e=>p({type:"identity.getMutes.result",id:e.id,pubkeys:[]}),"identity.getBlocked":e=>p({type:"identity.getBlocked.result",id:e.id,pubkeys:[]}),"identity.getBadges":e=>p({type:"identity.getBadges.result",id:e.id,badges:[]}),"storage.get":e=>p({type:"storage.get.result",id:e.id,value:null}),"storage.set":e=>p({type:"storage.set.result",id:e.id}),"storage.remove":e=>p({type:"storage.remove.result",id:e.id}),"storage.keys":e=>p({type:"storage.keys.result",id:e.id,keys:[]}),"inc.emit":q,"inc.subscribe":e=>p({type:"inc.subscribe.result",id:e.id}),"inc.unsubscribe":q,"inc.channel.open":e=>p({type:"inc.channel.open.result",id:e.id,channelId:`chan-${String(e.id)}`,peer:"reference-peer"}),"inc.channel.emit":q,"inc.channel.broadcast":q,"inc.channel.list":e=>p({type:"inc.channel.list.result",id:e.id,channels:[]}),"inc.channel.close":q,"theme.get":e=>p({type:"theme.get.result",id:e.id,theme:{colors:{},mode:"dark"}}),"keys.forward":q,"keys.registerAction":e=>p({type:"keys.registerAction.result",id:e.id,actionId:`action-${String(e.id)}`}),"keys.unregisterAction":q,"media.session.create":e=>p({type:"media.session.create.result",id:e.id,sessionId:`session-${String(e.id)}`,owner:e.owner}),"media.session.update":q,"media.session.destroy":q,"media.state":q,"media.capabilities":q,"notify.send":e=>p({type:"notify.send.result",id:e.id,notificationId:`notif-${String(e.id)}`}),"notify.dismiss":q,"notify.badge":q,"notify.channel.register":q,"notify.permission.request":e=>p({type:"notify.permission.result",id:e.id,granted:!0}),"config.registerSchema":e=>p({type:"config.registerSchema.result",id:e.id,ok:!0}),"config.get":e=>p({type:"config.values",id:e.id,values:{}}),"config.subscribe":()=>p({type:"config.values",values:{}}),"config.unsubscribe":q,"config.openSettings":q,"resource.bytes":e=>{const t=bt(e.url);return p(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=>p({type:"resource.bytesMany.result",id:e.id,items:Array.isArray(e.urls)?e.urls.map(t=>{const r=bt(t);return{url:t,ok:!0,blob:r?.blob??new Blob([]),mime:r?.mime??"application/octet-stream"}}):[]}),"resource.info":e=>p({type:"resource.info.result",id:e.id,info:{schemes:[{scheme:"data",enabled:!0},{scheme:"https",enabled:!0}]}}),"resource.cancel":q,"cvm.discover":e=>p({type:"cvm.discover.result",id:e.id,servers:[]}),"cvm.request":e=>p({type:"cvm.request.result",id:e.id,message:{}}),"cvm.close":e=>p({type:"cvm.close.result",id:e.id}),"outbox.getEvent":e=>p({type:"outbox.getEvent.result",id:e.id}),"outbox.query":e=>p({type:"outbox.query.result",id:e.id,events:[]}),"outbox.subscribe":e=>p({type:"outbox.closed",subId:e.subId,reason:"reference shell complete"}),"outbox.close":q,"outbox.publish":e=>p({type:"outbox.publish.result",id:e.id,ok:!0}),"outbox.resolveRelays":e=>p({type:"outbox.resolveRelays.result",id:e.id,plan:{}}),"upload.info":e=>p({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=>p({type:"upload.upload.result",id:e.id,result:{url:In}}),"upload.status":e=>p({type:"upload.status.result",id:e.id,status:{}}),"intent.invoke":e=>p({type:"intent.invoke.result",id:e.id,result:{ok:!0,archetype:"reference",action:"open",handled:!0}}),"intent.available":e=>p({type:"intent.available.result",id:e.id,availability:{archetype:e.archetype,available:!0,candidates:[{dTag:"reference-handler",actions:["open"],protocols:["NAP-4"],contracts:[{action:"open",protocol:"NAP-4",eventKinds:[1]}],isDefault:!0}],hasDefault:!0}}),"intent.handlers":e=>p({type:"intent.handlers.result",id:e.id,handlers:[]}),"ble.open":e=>p({type:"ble.open.result",id:e.id,session:{id:"ble-reference",state:"open",device:{id:"reference-device",name:"Reference BLE"}}}),"ble.services":e=>p({type:"ble.services.result",id:e.id,services:[]}),"ble.read":e=>p({type:"ble.read.result",id:e.id,data:[]}),"ble.write":e=>p({type:"ble.write.result",id:e.id}),"ble.subscribe":e=>p({type:"ble.subscribe.result",id:e.id}),"ble.unsubscribe":e=>p({type:"ble.unsubscribe.result",id:e.id}),"ble.close":e=>p({type:"ble.close.result",id:e.id}),"common.encodeNip19":e=>p({type:"common.encodeNip19.result",id:e.id,ok:!0,value:"npub1reference",nip19Type:"npub"}),"common.decodeNip19":e=>p({type:"common.decodeNip19.result",id:e.id,ok:!0,nip19Type:"npub",hex:xe}),"common.getProfile":e=>p({type:"common.getProfile.result",id:e.id,ok:!0,pubkey:xe,profile:null}),"common.follows":e=>p({type:"common.follows.result",id:e.id,ok:!0,pubkeys:[]}),"common.follow":e=>p({type:"common.follow.result",id:e.id,ok:!0}),"common.unfollow":e=>p({type:"common.unfollow.result",id:e.id,ok:!0}),"common.react":e=>p({type:"common.react.result",id:e.id,ok:!0,eventId:"0".repeat(64)}),"common.report":e=>p({type:"common.report.result",id:e.id,ok:!0,eventId:"1".repeat(64)}),"webrtc.open":e=>p({type:"webrtc.open.result",id:e.id,session:{id:"webrtc-reference",scope:{type:"direct",pubkey:xe},channel:"default",state:"connecting"}}),"webrtc.send":e=>p({type:"webrtc.send.result",id:e.id}),"webrtc.close":e=>p({type:"webrtc.close.result",id:e.id}),"link.open":e=>p({type:"link.open.result",id:e.id,status:"opened"}),"count.query":e=>p({type:"count.query.result",id:e.id,ok:!0,count:0}),"lists.supported":e=>p({type:"lists.supported.result",id:e.id,lists:[]}),"lists.add":e=>p({type:"lists.add.result",id:e.id,ok:!0,added:0,skipped:0}),"lists.remove":e=>p({type:"lists.remove.result",id:e.id,ok:!0,removed:0,skipped:0}),"serial.open":e=>p({type:"serial.open.result",id:e.id,session:{id:`serial-${String(e.id)}`,state:"open"}}),"serial.write":e=>p({type:"serial.write.result",id:e.id}),"serial.close":e=>p({type:"serial.close.result",id:e.id})};function On(e={}){const t=e.now??(()=>Date.now()),r=[];function n(i){const s=i&&typeof i=="object"&&typeof i.type=="string"?i.type:void 0;if(r.push({envelope:i,verdict:Rn(i),timestamp:t()}),!s)return[];const o=An[s];return o?o(i):[]}return{get records(){return r},handle:n,reset(){r.length=0}}}function Nn(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 Dt="__nappletConformance.error";function mt(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 Ln(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) =>
43
- request({ type: 'resource.bytes', url: String(url) }, 'resource.bytes.result', 'resource.bytes.error')
44
- .then((msg) => msg.blob);
45
- napplet.resource.bytesMany = (urls) =>
46
- request({ type: 'resource.bytesMany', urls: Array.from(urls || []) }, 'resource.bytesMany.result', 'resource.bytesMany.error')
47
- .then((msg) => msg.items);
48
- napplet.resource.bytesAsObjectURL = (url) => {
49
- const handle = { url: '', revoke: () => {} };
50
- let objectUrl = '';
51
- let revoked = false;
52
- const ready = napplet.resource.bytes(url).then((blob) => {
53
- if (revoked) return;
54
- objectUrl = URL.createObjectURL(blob);
55
- handle.url = objectUrl;
56
- return objectUrl;
57
- });
58
- handle.revoke = () => {
59
- if (revoked) return;
60
- revoked = true;
61
- if (objectUrl) URL.revokeObjectURL(objectUrl);
62
- };
63
- Object.defineProperty(handle, 'ready', { value: ready, enumerable: false });
64
- return handle;
65
- };
66
- }
67
- window.napplet = napplet;
68
- const report = (reason) => {
69
- try {
70
- window.parent.postMessage({ type: '${Dt}', reason: String(reason && reason.message || reason) }, '*');
71
- } catch {}
72
- };
73
- window.addEventListener('error', (event) => report(event.error || event.message));
74
- window.addEventListener('unhandledrejection', (event) => report(event.reason));
75
- })();
76
- `}function Pn(e,t,r){const n=`<base href="${qn(t)}">`,i=`<script>${Ln(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 _n(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 Cn(e){if(e==="about:blank")return"<!doctype html><html><head></head><body></body></html>";const t=_n(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 yt(e,t,r,n){const i=On(),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=u=>{if(u.source!==s.contentWindow)return;const f=u.data;if(f&&typeof f=="object"&&f.type===Dt){o=`napplet boot error: ${String(f.reason??"unknown error")}`;return}const g=i.handle(u.data),b=u.source;for(const y of g)b?.postMessage(y,"*")};let a=!1;const l=new Promise(u=>{s.addEventListener("load",()=>{a=!0,u()},{once:!0})});n.addEventListener("message",c),(r.body??r.documentElement).appendChild(s);try{const u=await Cn(t.url);s.srcdoc=Pn(u,t.url,e)}catch(u){o=u instanceof Error?u.message:String(u)}if(!o){const u=Symbol("timeout");await Promise.race([l.then(()=>"loaded"),mt(t.readyTimeoutMs).then(()=>u)])===u||!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 mt(t.settleMs)}n.removeEventListener("message",c);try{s.remove()}catch{}return{installedGlobal:o===null,bootError:o,emitted:[...i.records]}}async function Un(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 yt(it,n,t,r);let s=null;{const o=await yt([],n,t,r);s={bootError:o.bootError,emitted:o.emitted}}return{installedGlobal:i.installedGlobal,bootError:i.bootError,emitted:i.emitted,degraded:s}}var Hn=e=>({status:"pass",detail:e}),jn=(e,t)=>({status:"fail",detail:e,diagnostics:t}),Mn=e=>({status:"skip",detail:e}),O={pass:Hn,fail:jn,skip:Mn};function Dn(e,t){return ot(e.manifestEvent).errors.filter(r=>t.includes(r.code))}function He(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=Dn(n,r);return i.length?O.fail(i[0].message,i):O.pass()}}}var Zn=[He("manifest/event-kind","Resolved event is a NIP-5D napplet manifest",["invalid-napplet-kind","missing-d-tag","unexpected-d-tag"]),He("manifest/index-html","Manifest declares a hashed /index.html",["missing-index-html","invalid-index-html-hash"]),He("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 Wn(e,t={}){const r=t.now??(()=>Date.now()),n=t.checks??Zn,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?Mt(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 Vn(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function at(e,t=""){if(!Number.isSafeInteger(e)||e<0){const r=t&&`"${t}" `;throw new Error(`${r}expected integer >= 0, got ${e}`)}}function M(e,t,r=""){const n=Vn(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 wt(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 Kn(e,t){M(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 ze(...e){for(let t=0;t<e.length;t++)e[t].fill(0)}function je(e){return new DataView(e.buffer,e.byteOffset,e.byteLength)}function z(e,t){return e<<32-t|e>>>t}const Zt=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",Fn=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function _(e){if(M(e),Zt)return e.toHex();let t="";for(let r=0;r<e.length;r++)t+=Fn[e[r]];return t}const J={_0:48,_9:57,A:65,F:70,a:97,f:102};function vt(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(Zt)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=vt(e.charCodeAt(s)),c=vt(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 Be(...e){let t=0;for(let n=0;n<e.length;n++){const i=e[n];M(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 Yn(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 Wt(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 zn=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 Vt(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function Kt(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 Gn(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 Ft(e){if(!Number.isSafeInteger(e))throw new Error(`invalid integer: ${e}`)}function Ge(e){if(!Array.isArray(e))throw new Error("array expected")}function Yt(e,t){if(!Kt(!0,t))throw new Error(`${e}: array of strings expected`)}function zt(e,t){if(!Kt(!1,t))throw new Error(`${e}: array of numbers expected`)}function Xn(...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 Jn(e){const t=typeof e=="string"?e.split(""):e,r=t.length;Yt("alphabet",t);const n=new Map(t.map((i,s)=>[i,s]));return{encode:i=>(Ge(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=>(Ge(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 Qn(e=""){return me("join",e),{encode:t=>(Yt("join.decode",t),t.join(e)),decode:t=>(me("join.decode",t),t.split(e))}}const Gt=(e,t)=>t===0?e:Gt(t,e%t),Ie=(e,t)=>e+(t-Gt(e,t)),$e=(()=>{let e=[];for(let t=0;t<40;t++)e.push(2**t);return e})();function Xe(e,t,r,n){if(Ge(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(Ie(t,r)>32)throw new Error(`convertRadix2: carry overflow from=${t} to=${r} carryBits=${Ie(t,r)}`);let i=0,s=0;const o=$e[t],c=$e[r]-1,a=[];for(const l of e){if(Ft(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 u=$e[s];if(u===void 0)throw new Error("invalid carry");i&=u-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(Ft(e),e<=0||e>32)throw new Error("radix2: bits should be in (0..32]");if(Ie(8,e)>32||Ie(e,8)>32)throw new Error("radix2: carry overflow");return{encode:r=>{if(!Vt(r))throw new Error("radix2.encode input should be Uint8Array");return Xe(Array.from(r),8,e,!t)},decode:r=>(zt("radix2.decode",r),Uint8Array.from(Xe(r,e,8,t)))}}function Et(e){return Gn(e),function(...t){try{return e.apply(null,t)}catch{}}}const Je=Xn(Jn("qpzry9x8gf2tvdw0s3jn54khce6mua7l"),Qn("")),xt=[996825010,642813549,513874426,1027748829,705979059];function fe(e){const t=e>>25;let r=(e&33554431)<<5;for(let n=0;n<xt.length;n++)(t>>n&1)===1&&(r^=xt[n]);return r}function kt(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,Je.encode(Xe([i%$e[30]],30,5,!1))}function tr(e){const t=e==="bech32"?1:734539939,r=er(5),n=r.decode,i=r.encode,s=Et(n);function o(f,g,b=90){me("bech32.encode prefix",f),Vt(g)&&(g=Array.from(g)),zt("bech32.encode",g);const y=f.length;if(y===0)throw new TypeError(`Invalid prefix length ${y}`);const E=y+7+g.length;if(b!==!1&&E>b)throw new TypeError(`Length ${E} exceeds limit ${b}`);const N=f.toLowerCase(),L=kt(N,g,t);return`${N}1${Je.encode(g)}${L}`}function c(f,g=90){me("bech32.decode input",f);const b=f.length;if(b<8||g!==!1&&b>g)throw new TypeError(`invalid string length: ${b} (${f}). Expected (8..${g})`);const y=f.toLowerCase();if(f!==y&&f!==f.toUpperCase())throw new Error("String must be lowercase or uppercase");const E=y.lastIndexOf("1");if(E===0||E===-1)throw new Error('Letter "1" must be present between prefix and data only');const N=y.slice(0,E),L=y.slice(E+1);if(L.length<6)throw new Error("Data must be at least 6 characters long");const F=Je.decode(L).slice(0,-6),Q=kt(N,F,t);if(!L.endsWith(Q))throw new Error(`Invalid checksum in ${f}: expected "${Q}"`);return{prefix:N,words:F}}const a=Et(c);function l(f){const{prefix:g,words:b}=c(f,!1);return{prefix:g,words:b,bytes:n(b)}}function u(f,g){return o(f,i(g))}return{encode:o,decode:c,encodeFromBytes:u,decodeToBytes:l,decodeUnsafe:a,fromWords:n,fromWordsUnsafe:s,toWords:i}}const St=tr("bech32");var ke=new TextDecoder("utf-8");new TextEncoder;var nr=5e3;function rr(e){try{return e.startsWith("nostr:")&&(e=e.substring(6)),ir(e)}catch{return{type:"invalid",data:null}}}function ir(e){let{prefix:t,words:r}=St.decode(e,nr),n=new Uint8Array(St.fromWords(r));switch(t){case"nprofile":{let i=Me(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=>ke.decode(s)):[]}}}case"nevent":{let i=Me(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=>ke.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=Me(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:ke.decode(i[0][0]),pubkey:_(i[2][0]),kind:parseInt(_(i[3][0]),16),relays:i[1]?i[1].map(s=>ke.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 Me(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 sr(e,t,r){return e&t^~e&r}function or(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=je(this.buffer)}update(t){wt(this),M(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=je(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){wt(this),Kn(t,this),this.finished=!0;const{buffer:r,view:n,blockLen:i,isLE:s}=this;let{pos:o}=this;r[o++]=128,ze(this.buffer.subarray(o)),this.padOffset>i-o&&(this.process(n,0),o=0);for(let f=o;f<i;f++)r[f]=0;n.setBigUint64(i-8,BigInt(this.length*8),s),this.process(n,0);const c=je(t),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen must be aligned to 32bit");const l=a/4,u=this.get();if(l>u.length)throw new Error("_sha2: outputLen bigger than state");for(let f=0;f<l;f++)c.setUint32(4*f,u[f],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]),cr=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 lr 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 f=0;f<16;f++,r+=4)te[f]=t.getUint32(r,!1);for(let f=16;f<64;f++){const g=te[f-15],b=te[f-2],y=z(g,7)^z(g,18)^g>>>3,E=z(b,17)^z(b,19)^b>>>10;te[f]=E+te[f-7]+y+te[f-16]|0}let{A:n,B:i,C:s,D:o,E:c,F:a,G:l,H:u}=this;for(let f=0;f<64;f++){const g=z(c,6)^z(c,11)^z(c,25),b=u+g+sr(c,a,l)+cr[f]+te[f]|0,E=(z(n,2)^z(n,13)^z(n,22))+or(n,i,s)|0;u=l,l=a,a=c,c=o+b|0,o=s,s=i,i=n,n=b+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,u=u+this.H|0,this.set(n,i,s,o,c,a,l,u)}roundClean(){ze(te)}destroy(){this.set(0,0,0,0,0,0,0,0),ze(this.buffer)}}class dr extends lr{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 Ae=Yn(()=>new dr,zn(1));/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const ct=BigInt(0),Qe=BigInt(1);function Rt(e,t=""){if(typeof e!="boolean"){const r=t&&`"${t}" `;throw new Error(r+"expected boolean, got type="+typeof e)}return e}function ur(e){if(typeof e=="bigint"){if(!pr(e))throw new Error("positive bigint expected, got "+e)}else at(e);return e}function Xt(e){if(typeof e!="string")throw new Error("hex string expected, got "+typeof e);return e===""?ct:BigInt("0x"+e)}function lt(e){return Xt(_(e))}function Jt(e){return Xt(_(fr(M(e)).reverse()))}function dt(e,t){at(t),e=ur(e);const r=X(e.toString(16).padStart(t*2,"0"));if(r.length!==t)throw new Error("number too large");return r}function Qt(e,t){return dt(e,t).reverse()}function fr(e){return Uint8Array.from(e)}function hr(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"&&ct<=e;function gr(e){let t;for(t=0;e>ct;e>>=Qe,t+=1);return t}const en=e=>(Qe<<BigInt(e))-Qe;function tn(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 $t(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),nn=BigInt(3),rn=BigInt(4),sn=BigInt(5),br=BigInt(7),on=BigInt(8),mr=BigInt(9),an=BigInt(16);function K(e,t){const r=e%t;return r>=j?r:t+r}function Z(e,t,r){let n=e;for(;t-- >j;)n*=n,n%=r;return n}function Tt(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=K(e,t),n=t,i=j,s=H;for(;r!==j;){const c=n/r,a=n%r,l=i-s*c;n=r,r=a,i=s,s=l}if(n!==H)throw new Error("invert: does not exist");return K(i,t)}function ut(e,t,r){if(!e.eql(e.sqr(t),r))throw new Error("Cannot find square root")}function cn(e,t){const r=(e.ORDER+H)/rn,n=e.pow(t,r);return ut(e,n,t),n}function yr(e,t){const r=(e.ORDER-sn)/on,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 ut(e,c,t),c}function wr(e){const t=Le(e),r=ln(e),n=r(t,t.neg(t.ONE)),i=r(t,n),s=r(t,t.neg(n)),o=(e+br)/an;return(c,a)=>{let l=c.pow(a,o),u=c.mul(l,n);const f=c.mul(l,i),g=c.mul(l,s),b=c.eql(c.sqr(u),a),y=c.eql(c.sqr(f),a);l=c.cmov(l,u,b),u=c.cmov(g,f,y);const E=c.eql(c.sqr(u),a),N=c.cmov(l,u,E);return ut(c,N,a),N}}function ln(e){if(e<nn)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=Le(e);for(;Bt(i,n)===1;)if(n++>1e3)throw new Error("Cannot find square root: probably non-prime P");if(r===1)return cn;let s=i.pow(n,t);const o=(t+H)/se;return function(a,l){if(a.is0(l))return l;if(Bt(a,l)!==1)throw new Error("Cannot find square root");let u=r,f=a.mul(a.ONE,s),g=a.pow(l,t),b=a.pow(l,o);for(;!a.eql(g,a.ONE);){if(a.is0(g))return a.ZERO;let y=1,E=a.sqr(g);for(;!a.eql(E,a.ONE);)if(y++,E=a.sqr(E),y===u)throw new Error("Cannot find square root");const N=H<<BigInt(u-y-1),L=a.pow(f,N);u=y,f=a.sqr(L),g=a.mul(g,f),b=a.mul(b,L)}return b}}function vr(e){return e%rn===nn?cn:e%on===sn?yr:e%an===mr?wr(e):ln(e)}const Er=["create","isValid","is0","neg","inv","sqrt","sqr","eql","add","sub","mul","pow","div","addN","subN","mulN","sqrN"];function xr(e){const t={ORDER:"bigint",BYTES:"number",BITS:"number"},r=Er.reduce((n,i)=>(n[i]="function",n),t);return tn(e,r),e}function kr(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 dn(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 Bt(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 Sr(e,t){t!==void 0&&at(t);const r=t!==void 0?t:e.toString(2).length,n=Math.ceil(r/8);return{nBitLength:r,nByteLength:n}}class Rr{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}=Sr(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 K(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 K(-t,this.ORDER)}eql(t,r){return t===r}sqr(t){return K(t*t,this.ORDER)}add(t,r){return K(t+r,this.ORDER)}sub(t,r){return K(t-r,this.ORDER)}mul(t,r){return K(t*r,this.ORDER)}pow(t,r){return kr(this,t,r)}div(t,r){return K(t*Tt(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 Tt(t,this.ORDER)}sqrt(t){return this._sqrt||(this._sqrt=vr(this.ORDER)),this._sqrt(this,t)}toBytes(t){return this.isLE?Qt(t,this.BYTES):dt(t,this.BYTES)}fromBytes(t,r=!1){M(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?Jt(t):lt(t);if(c&&(a=K(a,o)),!r&&!this.isValid(a))throw new Error("invalid field element: outside of range 0..ORDER");return a}invertBatch(t){return dn(this,t)}cmov(t,r,n){return n?r:t}}function Le(e,t={}){return new Rr(e,t)}function un(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 $r(e){const t=un(e);return t+Math.ceil(t/2)}function Tr(e,t,r=!1){M(e);const n=e.length,i=un(t),s=$r(t);if(n<16||n<s||n>1024)throw new Error("expected "+s+"-1024 bytes of input, got "+n);const o=r?Jt(e):lt(e),c=K(o,t-H)+H;return r?Qt(c,i):dt(c,i)}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const le=BigInt(0),oe=BigInt(1);function Oe(e,t){const r=t.negate();return e?r:t}function It(e,t){const r=dn(e.Fp,t.map(n=>n.Z));return t.map((n,i)=>e.fromAffine(n.toAffine(r[i])))}function fn(e,t){if(!Number.isSafeInteger(e)||e<=0||e>t)throw new Error("invalid window size, expected [1.."+t+"], got W="+e)}function De(e,t){fn(e,t);const r=Math.ceil(t/e)+1,n=2**(e-1),i=2**e,s=en(e),o=BigInt(e);return{windows:r,windowSize:n,mask:s,maxNumber:i,shiftBy:o}}function At(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,u=l+Math.abs(c)-1,f=c===0,g=c<0,b=t%2!==0;return{nextN:a,offset:u,isZero:f,isNeg:g,isNegF:b,offsetF:l}}const Ze=new WeakMap,hn=new WeakMap;function We(e){return hn.get(e)||1}function Ot(e){if(e!==le)throw new Error("invalid wNAF")}class Br{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}=De(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=De(t,this.bits);for(let c=0;c<o.windows;c++){const{nextN:a,offset:l,isZero:u,isNeg:f,isNegF:g,offsetF:b}=At(n,c,o);n=a,u?s=s.add(Oe(g,r[b])):i=i.add(Oe(f,r[l]))}return Ot(n),{p:i,f:s}}wNAFUnsafe(t,r,n,i=this.ZERO){const s=De(t,this.bits);for(let o=0;o<s.windows&&n!==le;o++){const{nextN:c,offset:a,isZero:l,isNeg:u}=At(n,o,s);if(n=c,!l){const f=r[a];i=i.add(u?f.negate():f)}}return Ot(n),i}getPrecomputes(t,r,n){let i=Ze.get(r);return i||(i=this.precomputeWindow(r,t),t!==1&&(typeof n=="function"&&(i=n(i)),Ze.set(r,i))),i}cached(t,r,n){const i=We(t);return this.wNAF(i,this.getPrecomputes(i,t,n),r)}unsafe(t,r,n,i){const s=We(t);return s===1?this._unsafeLadder(t,r,i):this.wNAFUnsafe(s,this.getPrecomputes(s,t,n),r,i)}createCache(t,r){fn(r,this.bits),hn.set(t,r),Ze.delete(t)}hasCache(t){return We(t)!==1}}function Ir(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 Nt(e,t,r){if(t){if(t.ORDER!==e)throw new Error("Field.ORDER must match order: Fp == p, Fn == n");return xr(t),t}else return Le(e,{isLE:r})}function Ar(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>le))throw new Error(`CURVE.${a} must be positive bigint`)}const i=Nt(t.p,r.Fp,n),s=Nt(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 Or(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 qt=(e,t)=>(e+(e>=0?t:-t)/qr)/t;function Nr(e,t,r){const[[n,i],[s,o]]=t,c=qt(o*e,r),a=qt(-i*e,r);let l=e-c*n-a*s,u=-c*i-a*o;const f=l<he,g=u<he;f&&(l=-l),g&&(u=-u);const b=en(Math.ceil(gr(r)/2))+Te;if(l<he||l>=b||u<he||u>=b)throw new Error("splitScalar (endomorphism): failed, k="+e);return{k1neg:f,k1:l,k2neg:g,k2:u}}const he=BigInt(0),Te=BigInt(1),qr=BigInt(2),Se=BigInt(3),Lr=BigInt(4);function Pr(e,t={}){const r=Ar("weierstrass",e,t),{Fp:n,Fn:i}=r;let s=r.CURVE;const{h:o,n:c}=s;tn(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=Cr(n,i);function u(){if(!n.isOdd)throw new Error("compression is not supported: Field does not have .isOdd()")}function f(T,h,m){const{x:v,y:x}=h.toAffine(),B=n.toBytes(v);if(Rt(m,"isCompressed"),m){u();const R=!n.isOdd(x);return Be(_r(R),B)}else return Be(Uint8Array.of(4),B,n.toBytes(x))}function g(T){M(T,void 0,"Point");const{publicKey:h,publicKeyUncompressed:m}=l,v=T.length,x=T[0],B=T.subarray(1);if(v===h&&(x===2||x===3)){const R=n.fromBytes(B);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(D){const P=D instanceof Error?": "+D.message:"";throw new Error("bad point: is not on curve, sqrt error"+P)}u();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(B.subarray(0,R)),w=n.fromBytes(B.subarray(R,R*2));if(!N(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=${h} or uncompressed=${m}`)}const b=t.toBytes||f,y=t.fromBytes||g;function E(T){const h=n.sqr(T),m=n.mul(h,T);return n.add(n.add(m,n.mul(T,s.a)),s.b)}function N(T,h){const m=n.sqr(h),v=E(T);return n.eql(m,v)}if(!N(s.Gx,s.Gy))throw new Error("bad curve params: generator point");const L=n.mul(n.pow(s.a,Se),Lr),F=n.mul(n.sqr(s.b),BigInt(27));if(n.is0(n.add(L,F)))throw new Error("bad curve params: a or b");function Q(T,h,m=!1){if(!n.isValid(h)||m&&n.is0(h))throw new Error(`bad point coordinate ${T}`);return h}function we(T){if(!(T instanceof A))throw new Error("Weierstrass Point expected")}function ve(T){if(!a||!a.basises)throw new Error("no endo");return Nr(T,a.basises,i.ORDER)}const Ee=$t((T,h)=>{const{X:m,Y:v,Z:x}=T;if(n.eql(x,n.ONE))return{x:m,y:v};const B=T.is0();h==null&&(h=B?n.ONE:n.inv(x));const R=n.mul(m,h),k=n.mul(v,h),w=n.mul(x,h);if(B)return{x:n.ZERO,y:n.ZERO};if(!n.eql(w,n.ONE))throw new Error("invZ was invalid");return{x:R,y:k}}),xn=$t(T=>{if(T.is0()){if(t.allowInfinityPoint&&!n.is0(T.Y))return;throw new Error("bad point: ZERO")}const{x:h,y:m}=T.toAffine();if(!n.isValid(h)||!n.isValid(m))throw new Error("bad point: x or y not field elements");if(!N(h,m))throw new Error("bad point: equation left != right");if(!T.isTorsionFree())throw new Error("bad point: not in prime-order subgroup");return!0});function pt(T,h,m,v,x){return m=new A(n.mul(m.X,T),m.Y,m.Z),h=Oe(v,h),m=Oe(x,m),h.add(m)}class A{static BASE=new A(s.Gx,s.Gy,n.ONE);static ZERO=new A(n.ZERO,n.ONE,n.ZERO);static Fp=n;static Fn=i;X;Y;Z;constructor(h,m,v){this.X=Q("x",h),this.Y=Q("y",m,!0),this.Z=Q("z",v),Object.freeze(this)}static CURVE(){return s}static fromAffine(h){const{x:m,y:v}=h||{};if(!h||!n.isValid(m)||!n.isValid(v))throw new Error("invalid affine point");if(h instanceof A)throw new Error("projective point not allowed");return n.is0(m)&&n.is0(v)?A.ZERO:new A(m,v,n.ONE)}static fromBytes(h){const m=A.fromAffine(y(M(h,void 0,"point")));return m.assertValidity(),m}static fromHex(h){return A.fromBytes(X(h))}get x(){return this.toAffine().x}get y(){return this.toAffine().y}precompute(h=8,m=!0){return ue.createCache(this,h),m||this.multiply(Se),this}assertValidity(){xn(this)}hasEvenY(){const{y:h}=this.toAffine();if(!n.isOdd)throw new Error("Field doesn't support isOdd");return!n.isOdd(h)}equals(h){we(h);const{X:m,Y:v,Z:x}=this,{X:B,Y:R,Z:k}=h,w=n.eql(n.mul(m,k),n.mul(B,x)),S=n.eql(n.mul(v,k),n.mul(R,x));return w&&S}negate(){return new A(this.X,n.neg(this.Y),this.Z)}double(){const{a:h,b:m}=s,v=n.mul(m,Se),{X:x,Y:B,Z:R}=this;let k=n.ZERO,w=n.ZERO,S=n.ZERO,$=n.mul(x,x),D=n.mul(B,B),P=n.mul(R,R),I=n.mul(x,B);return I=n.add(I,I),S=n.mul(x,R),S=n.add(S,S),k=n.mul(h,S),w=n.mul(v,P),w=n.add(k,w),k=n.sub(D,w),w=n.add(D,w),w=n.mul(k,w),k=n.mul(I,k),S=n.mul(v,S),P=n.mul(h,P),I=n.sub($,P),I=n.mul(h,I),I=n.add(I,S),S=n.add($,$),$=n.add(S,$),$=n.add($,P),$=n.mul($,I),w=n.add(w,$),P=n.mul(B,R),P=n.add(P,P),$=n.mul(P,I),k=n.sub(k,$),S=n.mul(P,D),S=n.add(S,S),S=n.add(S,S),new A(k,w,S)}add(h){we(h);const{X:m,Y:v,Z:x}=this,{X:B,Y:R,Z:k}=h;let w=n.ZERO,S=n.ZERO,$=n.ZERO;const D=s.a,P=n.mul(s.b,Se);let I=n.mul(m,B),W=n.mul(v,R),V=n.mul(x,k),ae=n.add(m,v),U=n.add(B,R);ae=n.mul(ae,U),U=n.add(I,W),ae=n.sub(ae,U),U=n.add(m,x);let Y=n.add(B,k);return U=n.mul(U,Y),Y=n.add(I,V),U=n.sub(U,Y),Y=n.add(v,x),w=n.add(R,k),Y=n.mul(Y,w),w=n.add(W,V),Y=n.sub(Y,w),$=n.mul(D,U),w=n.mul(P,V),$=n.add(w,$),w=n.sub(W,$),$=n.add(W,$),S=n.mul(w,$),W=n.add(I,I),W=n.add(W,I),V=n.mul(D,V),U=n.mul(P,U),W=n.add(W,V),V=n.sub(I,V),V=n.mul(D,V),U=n.add(U,V),I=n.mul(W,U),S=n.add(S,I),I=n.mul(Y,U),w=n.mul(ae,w),w=n.sub(w,I),I=n.mul(ae,W),$=n.mul(Y,$),$=n.add($,I),new A(w,S,$)}subtract(h){return this.add(h.negate())}is0(){return this.equals(A.ZERO)}multiply(h){const{endo:m}=t;if(!i.isValidNot0(h))throw new Error("invalid scalar: out of range");let v,x;const B=R=>ue.cached(this,R,k=>It(A,k));if(m){const{k1neg:R,k1:k,k2neg:w,k2:S}=ve(h),{p:$,f:D}=B(k),{p:P,f:I}=B(S);x=D.add(I),v=pt(m.beta,$,P,R,w)}else{const{p:R,f:k}=B(h);v=R,x=k}return It(A,[v,x])[0]}multiplyUnsafe(h){const{endo:m}=t,v=this;if(!i.isValid(h))throw new Error("invalid scalar: out of range");if(h===he||v.is0())return A.ZERO;if(h===Te)return v;if(ue.hasCache(this))return this.multiply(h);if(m){const{k1neg:x,k1:B,k2neg:R,k2:k}=ve(h),{p1:w,p2:S}=Ir(A,v,B,k);return pt(m.beta,w,S,x,R)}else return ue.unsafe(v,h)}toAffine(h){return Ee(this,h)}isTorsionFree(){const{isTorsionFree:h}=t;return o===Te?!0:h?h(A,this):ue.unsafe(this,c).is0()}clearCofactor(){const{clearCofactor:h}=t;return o===Te?this:h?h(A,this):this.multiplyUnsafe(o)}isSmallOrder(){return this.multiplyUnsafe(o).is0()}toBytes(h=!0){return Rt(h,"isCompressed"),this.assertValidity(),b(A,this,h)}toHex(h=!0){return _(this.toBytes(h))}toString(){return`<Point ${this.is0()?"ZERO":this.toHex()}>`}}const gt=i.BITS,ue=new Br(A,t.endo?Math.ceil(gt/2):gt);return A.BASE.precompute(8),A}function _r(e){return Uint8Array.of(e?2:3)}function Cr(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 Pe={p:BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"),n:BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),h:BigInt(1),a:BigInt(0),b:BigInt(7),Gx:BigInt("0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"),Gy:BigInt("0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8")},Ur={beta:BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"),basises:[[BigInt("0x3086d221a7d46bcde86c90e49284eb15"),-BigInt("0xe4437ed6010e88286f547fa90abfe4c3")],[BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8"),BigInt("0x3086d221a7d46bcde86c90e49284eb15")]]},Hr=BigInt(0),et=BigInt(2);function jr(e){const t=Pe.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,u=l*l*e%t,f=Z(u,r,t)*u%t,g=Z(f,r,t)*u%t,b=Z(g,et,t)*l%t,y=Z(b,i,t)*b%t,E=Z(y,s,t)*y%t,N=Z(E,c,t)*E%t,L=Z(N,a,t)*N%t,F=Z(L,c,t)*E%t,Q=Z(F,r,t)*u%t,we=Z(Q,o,t)*y%t,ve=Z(we,n,t)*l%t,Ee=Z(ve,et,t);if(!Ne.eql(Ne.sqr(Ee),e))throw new Error("Cannot find square root");return Ee}const Ne=Le(Pe.p,{sqrt:jr}),de=Pr(Pe,{Fp:Ne,endo:Ur}),Lt={};function qe(e,...t){let r=Lt[e];if(r===void 0){const n=Ae(hr(e));r=Be(n,n),Lt[e]=r}return Ae(Be(r,...t))}const ft=e=>e.toBytes(!0).slice(1),ht=e=>e%et===Hr;function tt(e){const{Fn:t,BASE:r}=de,n=t.fromBytes(e),i=r.multiply(n);return{scalar:ht(i.y)?n:t.neg(n),bytes:ft(i)}}function pn(e){const t=Ne;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);ht(i)||(i=t.neg(i));const s=de.fromAffine({x:e,y:i});return s.assertValidity(),s}const be=lt;function gn(...e){return de.Fn.create(be(qe("BIP0340/challenge",...e)))}function Pt(e){return tt(e).bytes}function Mr(e,t,r=Wt(32)){const{Fn:n}=de,i=M(e,void 0,"message"),{bytes:s,scalar:o}=tt(t),c=M(r,32,"auxRand"),a=n.toBytes(o^be(qe("BIP0340/aux",c))),l=qe("BIP0340/nonce",a,s,i),{bytes:u,scalar:f}=tt(l),g=gn(u,s,i),b=new Uint8Array(64);if(b.set(u,0),b.set(n.toBytes(n.create(f+g*o)),32),!bn(b,i,s))throw new Error("sign: Invalid signature produced");return b}function bn(e,t,r){const{Fp:n,Fn:i,BASE:s}=de,o=M(e,64,"signature"),c=M(t,void 0,"message"),a=M(r,32,"publicKey");try{const l=pn(be(a)),u=be(o.subarray(0,32));if(!n.isValidNot0(u))return!1;const f=be(o.subarray(32,64));if(!i.isValidNot0(f))return!1;const g=gn(i.toBytes(u),ft(l),c),b=s.multiplyUnsafe(f).add(l.multiplyUnsafe(i.neg(g))),{x:y,y:E}=b.toAffine();return!(b.is0()||!ht(E)||y!==u)}catch{return!1}}const G=(()=>{const r=(n=Wt(48))=>Tr(n,Pe.n);return{keygen:Or(r,Pt),getPublicKey:Pt,sign:Mr,verify:bn,Point:de,utils:{randomSecretKey:r,taggedHash:qe,lift_x:pn,pointToBytes:ft},lengths:{secretKey:32,publicKey:32,publicKeyHasPrefix:!1,signature:64,seed:48}}})();var ie=Symbol("verified"),Dr=e=>e instanceof Object;function Zr(e){if(!Dr(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 Wr=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 Vr=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=Ve(n),n.sig=_(G.sign(X(Ve(n)),r)),n[ie]=!0,n}verifyEvent(t){if(typeof t[ie]=="boolean")return t[ie];try{const r=Ve(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 Kr(e){if(!Zr(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 Ve(e){let t=Ae(Wr.encode(Kr(e)));return _(t)}var _e=new Vr;_e.generateSecretKey;_e.getPublicKey;_e.finalizeEvent;var Fr=_e.verifyEvent,Yr=22242;function zr(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 Gr(e,t){for(let r=0;r<e.length;r++)if(zr(e[r],t))return!0;return!1}function Xr(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 Jr(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 Qr(e,t){return{kind:Yr,created_at:Math.floor(Date.now()/1e3),tags:[["relay",e],["challenge",t]],content:""}}var mn=class extends Error{constructor(e,t){super(`Tried to send message '${e} on a closed connection to ${t}.`),this.name="SendingOnClosedConnection"}},yn=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 yn(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 mn(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(Qr(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=Jr(t);if(r){const n=this.openSubs.get(r);if(!n)return;const i=Xr(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)&&Gr(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 mn))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)}},ti=e=>(e[ie]=!0,!0),ni=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 yn(e,{verifyEvent:this.trustedRelayURLs.has(e)?ti: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:b,filter:y}=g;r.has(b)||r.set(b,[]),r.get(b).push(y)}const n=Array.from(r.entries()).map(([g,b])=>({url:g,filters:b}));this.trackRelays&&(t.receivedEvent=(g,b)=>{let y=this.seenOn.get(b);y||(y=new Set,this.seenOn.set(b,y)),y.add(g)});const i=new Set,s=[],o=[];let c=g=>{o[g]||(o[g]=!0,o.filter(b=>b).length===n.length&&(t.oneose?.(),c=()=>{}))};const a=[];let l=(g,b)=>{a[g]||(c(g),a[g]=b,a.filter(y=>y).length===n.length&&(t.onclose?.(a),l=()=>{}))};const u=g=>{if(t.alreadyHaveEvent?.(g))return!0;const b=i.has(g);return i.add(g),b},f=Promise.all(n.map(async({url:g,filters:b},y)=>{if(this.allowConnectingToRelay?.(g,["read",b])===!1){l(y,"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(y,L?.message||String(L));return}this.onRelayConnectionSuccess?.(g);let N=E.subscribe(b,{...t,oneose:()=>c(y),onclose:L=>{L.startsWith("auth-required: ")&&t.onauth?E.auth(t.onauth).then(()=>{E.subscribe(b,{...t,oneose:()=>c(y),onclose:F=>{l(y,F)},alreadyHaveEvent:u,eoseTimeout:t.maxWait,abort:t.abort})}).catch(F=>{l(y,`auth was required and attempted, but failed with: ${F}`)}):l(y,L)},alreadyHaveEvent:u,eoseTimeout:t.maxWait,abort:t.abort});s.push(N)}));return{async close(g){await f,s.forEach(b=>{b.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}},wn;try{wn=WebSocket}catch{}var ri=class extends ni{constructor(e){super({verifyEvent:Fr,websocketImplementation:wn,maxWaitForConnection:3e3,...e})}},ce=Symbol("verified"),ii=e=>e instanceof Object;function si(e){if(!ii(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 oi=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=Ke(r),r.sig=_(G.sign(X(Ke(r)),t)),r[ce]=!0,r}verifyEvent(e){if(typeof e[ce]=="boolean")return e[ce];try{const t=Ke(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 ci(e){if(!si(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 Ke(e){let t=Ae(oi.encode(ci(e)));return _(t)}var Ce=new ai;Ce.generateSecretKey;Ce.getPublicKey;Ce.finalizeEvent;var li=Ce.verifyEvent;const di=8e3;function ui(e){return typeof e=="number"&&st.includes(e)}function fi(e){try{const t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function hi(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=hi(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&&!ui(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?[...st]:[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 gi(e){return{id:e.id,pubkey:e.pubkey,kind:e.kind,tags:e.tags}}async function vn(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 bi(e){return e.tags.filter(t=>t[0]==="path"&&typeof t[1]=="string"&&typeof t[2]=="string")}async function mi(e){const t=bi(e).map(r=>`${r[2]} ${r[1]}
77
- `).sort().join("");return vn(t)}async function yi(e){const t=await mi(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 wi(e){return e.tags.find(t=>t[0]==="path"&&t[1]==="/index.html")}function vi(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 Ei(e,t){const r=e.endsWith("/")?e:`${e}/`;return new URL(t,r).href}async function xi(e,t=fetch){const n=wi(e)?.[2];if(!n)throw new Error("Manifest does not include a /index.html path hash");const i=vi(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=Ei(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()),u=await vn(l);if(u!==n){s.push(`${c}: sha256 ${u} 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 ki(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 Si(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??di});if(!s)throw new Error("No matching napplet manifest event was found on the pointer relay hints");if(!li(s))throw new Error("Resolved manifest event signature is invalid");const o=gi(s),c=ot(o);if(!c.ok)throw new Error(`Resolved event is not a valid NIP-5D napplet manifest: ${c.errors[0]?.message}`);await yi(o);const a=await xi(o,t.fetcher??fetch),l=(t.createObjectUrl??URL.createObjectURL)(new Blob([a],{type:"text/html;charset=utf-8"})),u=()=>(t.revokeObjectUrl??URL.revokeObjectURL)(l);return{source:"nostr",input:e,label:o.id??e,bootUrl:l,html:a,fetched:!0,manifestEvent:o,revoke:u}}finally{n&&i.destroy()}}async function Ri(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 fi(r)?ki(r,t.fetcher??fetch):Si(r,t)}const $i=/\bwindow\s*\.\s*nostr\b|\bglobalThis\s*\.\s*nostr\b/,Ti="/__conformance__/events",nt=new URLSearchParams(location.search),En=nt.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 Bi(){return re.innerHTML=`
78
- <header class="masthead">
79
- <h1>napplet conformance ${En?'<span class="live-badge" id="live-badge">● live</span>':""}</h1>
80
- <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>
81
- </header>
82
- <form id="run-form" class="runbar">
83
- <input id="target" type="text" placeholder="naddr1… or nevent1… for a NIP-5D napplet manifest" autocomplete="off" spellcheck="false" />
84
- <button id="run" type="submit">Run conformance</button>
85
- <button id="rerun" type="button" class="secondary" hidden>Re-run</button>
86
- </form>
87
- <p id="status" class="status" role="status"></p>
88
- <section id="output" class="output"></section>
89
- `,{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=Bi();let ye="",rt=0;function Re(e,t="info"){C.status.textContent=e,C.status.dataset.kind=t}function Fe(e){return String(e).padStart(2,"0")}function Ii(e){const t=new Date(e);return`${Fe(t.getHours())}:${Fe(t.getMinutes())}:${Fe(t.getSeconds())}`}function Ai(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>':"",u=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}${u}</li>`}).join("");return`<div class="area"><h3>${ne(o)}</h3><ul>${c}</ul></div>`}).join(""),i=e.summary,s=rt>1?`<span class="run-stamp">run #${rt} · ${Ii(e.finishedAt)}</span>`:"";return`
90
- <div class="verdict ${t}">
91
- <span class="result">${e.ok?"CONFORMANT":"NON-CONFORMANT"}</span>
92
- <span class="counts">${i.passed} passed · ${i.failed} failed · ${i.skipped} skipped${i.warnings?` · ${i.warnings} warning(s)`:""}</span>
93
- ${s}
94
- </div>
95
- <div class="checks">${n}</div>
96
- `}function Oi(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 Ni(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=ot(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`
97
- <table class="manifest">
98
- ${t("event",r.id)}
99
- ${t("kind",r.kind)}
100
- ${t("d",i)}
101
- ${t("name",Mt(r))}
102
- ${t("requires",n.requires.join(", "))}
103
- ${t("/index.html",s?.[2])}
104
- ${t("servers",o.join(", "))}
105
- </table>
106
- ${n.errors.length?`<div class="errs">${n.errors.map(c=>ne(`${c.code}: ${c.message}`)).join("<br>")}</div>`:""}
107
- `}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 qi(e,t,r){C.output.innerHTML=`
108
- ${Ai(e)}
109
- <div class="panels">
110
- <section class="panel"><h2>Emitted envelopes (${t.length})</h2>${Oi(t)}</section>
111
- <section class="panel"><h2>Manifest</h2>${Ni(r)}</section>
112
- </div>
113
- `}async function Ue(e){ye=e,C.runButton.disabled=!0,C.rerunButton.disabled=!0;let t=null;try{Re(`Resolving ${e} …`),t=await Ri(e);const r=$i.test(t.html)?["window.nostr"]:[];Re("Booting napplet in a sandboxed iframe …");const n=await Un({url:t.bootUrl,readyTimeoutMs:5e3,settleMs:800,runDegraded:!0}),i=Nn({manifestHtml:t.html,manifestEvent:t.manifestEvent,boot:n,forbiddenGlobals:r}),s=Wn(i);rt+=1,Re(s.ok?"Done — conformant.":"Done — non-conformant.",s.ok?"info":"error"),qi(s,n.emitted,t),C.rerunButton.hidden=!1}catch(r){Re(`Error: ${r instanceof Error?r.message:String(r)}`,"error")}finally{t?.revoke?.(),C.runButton.disabled=!1,C.rerunButton.disabled=!1}}function Li(){if(!En||typeof EventSource>"u")return;let e=!1;const t=new EventSource(Ti);t.addEventListener("rerun",()=>{!ye||e||(e=!0,setTimeout(()=>{e=!1,Ue(ye)},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),Ue(t)}});C.rerunButton.addEventListener("click",()=>{ye&&Ue(ye)});Li();const Ye=nt.get("target")??nt.get("url");Ye&&(C.targetInput.value=Ye,Ue(Ye));