diff --git a/app-catalog/catalog.json b/app-catalog/catalog.json
index b37c4146..74f16fa2 100644
--- a/app-catalog/catalog.json
+++ b/app-catalog/catalog.json
@@ -673,6 +673,18 @@
"tier": "optional",
"icon": "/assets/img/app-icons/angor-green.png",
"repoUrl": "https://github.com/hoytech/strfry"
+ },
+ {
+ "id": "justworks",
+ "title": "Just Works",
+ "version": "0.1.0",
+ "description": "Turn your existing business links into a website with Just Works. Open your website editor and business tools from one lightweight launcher. Uses the hosted Just Works services; an internet connection is required.",
+ "icon": "/assets/img/app-icons/justworks.svg",
+ "author": "Just Works contributors",
+ "category": "business",
+ "tier": "optional",
+ "repoUrl": "https://github.com/bencoin21/justworks.cash",
+ "dockerImage": "localhost/archipelago-justworks:0.1.0"
}
]
}
diff --git a/apps/justworks/manifest.yml b/apps/justworks/manifest.yml
new file mode 100644
index 00000000..0b98c85d
--- /dev/null
+++ b/apps/justworks/manifest.yml
@@ -0,0 +1,62 @@
+app:
+ id: justworks
+ name: Just Works
+ version: 0.1.0
+ description: >-
+ Turn your existing business links into a website with Just Works.
+ Open your website editor and business tools from one lightweight launcher.
+ Uses the hosted Just Works services; an internet connection is required.
+ category: business
+ upstream:
+ kind: manual
+ url: https://github.com/bencoin21/justworks-business
+ container:
+ build:
+ context: /opt/archipelago/docker/justworks
+ dockerfile: Dockerfile
+ tag: localhost/archipelago-justworks:0.1.0
+ network: archy-net
+ resources:
+ cpu_limit: 1
+ memory_limit: 256Mi
+ disk_limit: 128Mi
+ security:
+ capabilities: []
+ readonly_root: true
+ no_new_privileges: true
+ network_policy: isolated
+ ports:
+ - host: 8340
+ container: 8340
+ protocol: tcp
+ bind: 127.0.0.1
+ auth: gated
+ session_passthrough: true
+ volumes:
+ - type: bind
+ source: /var/lib/archipelago/justworks
+ target: /data
+ environment: []
+ health_check:
+ type: http
+ endpoint: http://127.0.0.1:8340
+ path: /healthz
+ interval: 30s
+ timeout: 5s
+ retries: 3
+ interfaces:
+ main:
+ name: Just Works
+ description: Website and business tools
+ type: ui
+ port: 8340
+ protocol: http
+ path: /
+ metadata:
+ icon: /assets/img/app-icons/justworks.svg
+ author: Just Works contributors
+ repo: https://github.com/bencoin21/justworks.cash
+ tier: optional
+ launch:
+ requires_host_frame: true
+ open_in_new_tab: false
diff --git a/core/archipelago/src/fips/app_ports.rs b/core/archipelago/src/fips/app_ports.rs
index 21b122eb..1647a33b 100644
--- a/core/archipelago/src/fips/app_ports.rs
+++ b/core/archipelago/src/fips/app_ports.rs
@@ -33,6 +33,7 @@ pub const APP_LAUNCH_PORTS: &[u16] = &[
8334,
8336,
8337,
+ 8340,
8888,
8998,
8999,
diff --git a/docker/justworks/.dockerignore b/docker/justworks/.dockerignore
new file mode 100644
index 00000000..d89fc386
--- /dev/null
+++ b/docker/justworks/.dockerignore
@@ -0,0 +1,2 @@
+__pycache__
+test_*.py
diff --git a/docker/justworks/Dockerfile b/docker/justworks/Dockerfile
new file mode 100644
index 00000000..1bb63b3b
--- /dev/null
+++ b/docker/justworks/Dockerfile
@@ -0,0 +1,11 @@
+FROM docker.io/library/python:3.13-alpine@sha256:2d9aefe2fef018a7eb2c13064c89c71929800fd2e5dccdbf52ea5da5bb8d929a
+RUN apk add --no-cache nodejs
+WORKDIR /app
+COPY server.py payments.py boot.py ./
+COPY business ./business
+COPY public ./public
+COPY UPSTREAM-LICENSE /usr/share/licenses/justworks/LICENSE
+ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
+USER 65534:65534
+EXPOSE 8340
+CMD ["python3", "boot.py"]
diff --git a/docker/justworks/README.txt b/docker/justworks/README.txt
new file mode 100644
index 00000000..77365853
--- /dev/null
+++ b/docker/justworks/README.txt
@@ -0,0 +1,113 @@
+Just Works for Archipelago — app and demo
+
+Scope
+ One optional Archipelago app. First launch embeds the original Just Works home.
+ After a published website is connected, show Website and Business tools.
+ Dashboard > Setup > Instant business site contains the native OS guided flow.
+ The split launcher appears after the first connected website. A small Business
+ tools switch is always available at bottom-left, with a Website return path.
+ It uses the shared ring-button style, building/person icons, and icon-only
+ layout on phones to leave room for the upstream menu at bottom-right.
+ No changes to, publication in, or deployment of the existing Just Works repos.
+ Native wallet keys never leave the node. Website owner keys can be imported
+ into a separate native business identity. Reuse requires the node password and
+ explicit key-sharing approval; only its nsec is forwarded to Just Works for
+ the selected login/payment action. No secrets are saved in browser storage.
+
+Real-service mode
+ The original hosted creator/editor and an isolated Business copy load inside
+ the app iframe. Business data persists in /var/lib/archipelago/justworks.
+ The same wrapper is used when Archipelago opens the app in its own tab.
+ Owner authorization is verified by Just Works. Connecting a public link is not
+ ownership proof.
+ The app's GET /api/site checks the existing Core public API for published status.
+ It returns only a bounded display name, public identity and fixed-origin links.
+ Outbound reads reject redirects and are bounded in size/time; there is no generic
+ proxy or client-controlled upstream host. Only the page slug is saved in browser
+ storage. Another browser must connect its own link. Removing the app/link does
+ not delete the hosted business or its data. Internet access is required.
+ Isolated Business discovery resolves published sites directly through Core.
+ It uses the connected npub automatically and preserves the upstream UI.
+ No demo recipient fallback is enabled; legacy hardcoded order checkout is
+ blocked. The website payment page and merchant-address quick-pay are separate.
+ The local proxy has a fixed loopback destination and requires same-origin writes.
+
+Demo mode
+ The dashboard demo shows the native guide and embeds the original hosted site.
+ It does not simulate a replacement website editor or Business interface.
+ Connecting a published page requires the installed adapter on a real node.
+
+Setup completion
+ The native guide checks the published page through a hidden app-origin bridge.
+ Requests are correlated by random IDs; replies require the exact iframe window
+ and origin. Merely opening the app never completes the guide. The bridge saves
+ only the public slug; storage failure does not mark setup complete.
+ The launcher rechecks publication before revealing Business tools.
+
+Native wallet connection
+ The third OS guide step calls existing wallet.ecash-lnaddress; no LND/Bitcoin
+ dependency, additional wallet app or custom mint is installed. The native
+ @minibits.cash address is displayed automatically, not typed by the merchant.
+ Owner login/key authorization is entered for Connect wallet & publish. Core
+ verifies it; the adapter changes only the payment field using existing APIs.
+ POST /api/payment-connect requires exact same-origin JSON and a bounded body;
+ fixed-origin requests refuse redirects. No credentials are logged or stored.
+ Success requires Core's verified artifact, published status and a fresh public
+ record whose lud16 exactly matches the native address. Partial save/publish
+ failures remain incomplete and offer retry. No payment is sent by setup.
+ Hosted website tip flow reads this public record. Legacy Business order flows
+ with hardcoded destinations are not changed or certified by this integration.
+ Wallet Receive > Ecash uses the existing claim/retry flow. Node ecash still
+ depends on its existing hosted address/mint service; this is not self-hosting
+ the mint or receiving into LND. Existing Business merchant discovery applies.
+
+Runtime
+ Python adapter and isolated Business service, non-root, read-only root, no
+ capabilities, 256 MiB limit.
+ Port 8340 is loopback-bound behind Archipelago's app gate. The manifest carries
+ the icon, UI classification, build context and host-frame integration.
+ Run locally: JW_HOST=127.0.0.1 JW_PORT=18340 python3 server.py
+ Build: docker build -t localhost/archipelago-justworks:0.1.0 docker/justworks
+
+Design-system provenance
+ Vendored from bencoin21/justworks-business at
+ 0aec5c44fb90f8642afab8f2e9d4c13364af1ae0 (2026-09-20), MIT.
+ The original tokens, design-system.css imports, logo renderer, base/components,
+ layout presets and mobile chrome are retained. The only vendor adaptation is
+ ds/frame.js configureNavigation(): local launcher destinations replace
+ the upstream customer menu. launcher.css owns the new page composition.
+ The dashboard SVG uses the official portal paths in white,
+ normalized with scripts/normalize-app-icon.py (12% margin). Archipelago adds
+ its tile plate. No replacement brand glyph or external artwork is used.
+ Just Works MIT notice: UPSTREAM-LICENSE and public/licenses/JustWorks-LICENSE.
+ Syne and Geist font licenses: public/fonts/*-LICENSE.
+
+Verification
+ python3 -m unittest discover -s docker/justworks -p 'test_*.py'
+ From neode-ui: npm test -- src/views/goals/__tests__/justworksCompletion.test.ts
+ src/views/goals/__tests__/goalStepActions.test.ts src/stores/__tests__/goals.test.ts
+ From neode-ui: npm run build
+ bash scripts/validate-app-manifest.sh apps/justworks/manifest.yml
+ python3 scripts/check-app-catalog-drift.py --release --strict
+ Local shared browser scenarios/reports live outside the repository, under
+ ~/.local/share/browser-check/projects/archy-justworks/ and /tmp/justworks-*.
+ Browser fixture tests perform no production writes. A container read-only check
+ used the existing public barreirinha-bar-cafe-3 site; no credentials were used.
+
+Deployment boundary
+ Deployed and verified as an Archipelago demo on yaya. Not an OTA, catalog
+ publication or change to the hosted Just Works deployment. Shared-platform release/integration remains with the
+ existing platform owner; preserve their concurrent work when integrating.
+
+Native key rollout
+ Backend additions: identity.capabilities and password-protected identity.import-nostr.
+ Import verifies the expected npub, creates a separate business identity, reuses
+ an existing matching business identity, and never replaces another identity.
+ The native guide checks capabilities before collecting an import key. Nodes
+ without the new RPC retain direct owner-key/login access and a clear update note.
+ Export uses existing identity.export-keys after node-password verification;
+ other exported secret fields are never forwarded to the app.
+ The original hosted CMS has no session injection mechanism. Its own sign-in
+ remains separate. Saved credentials support payment setup and local Business.
+ Source: isolated justworks-business-archipelago worktree, upstream 0aec5c4.
+ Business LICENSE and bundled upstream assets retained in business/.
diff --git a/docker/justworks/UPSTREAM-LICENSE b/docker/justworks/UPSTREAM-LICENSE
new file mode 100644
index 00000000..02fe5437
--- /dev/null
+++ b/docker/justworks/UPSTREAM-LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Napplet contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/docker/justworks/boot.py b/docker/justworks/boot.py
new file mode 100644
index 00000000..6881356d
--- /dev/null
+++ b/docker/justworks/boot.py
@@ -0,0 +1,17 @@
+"""Run the app adapter and isolated Business service with shared lifecycle."""
+import os
+import subprocess
+import time
+children = []
+try:
+ children.append(subprocess.Popen(['python3', 'business/server.py'], env={**os.environ,
+ 'JWB_HOST':'127.0.0.1', 'JWB_PORT':'4310', 'JWB_BASE_PATH':'/business-demo',
+ 'JWB_DATA_DIR':'/data/business', 'JWB_AUTH_MODE':'enforce',
+ 'JWB_COOKIE_SECURE':'0', 'JWB_ARCHIPELAGO':'1'}))
+ children.append(subprocess.Popen(['python3', 'server.py']))
+ while all(child.poll() is None for child in children): time.sleep(0.5)
+finally:
+ for child in children:
+ if child.poll() is None: child.terminate()
+ for child in children: child.wait()
+raise SystemExit(1)
diff --git a/docker/justworks/business/LICENSE b/docker/justworks/business/LICENSE
new file mode 100644
index 00000000..02fe5437
--- /dev/null
+++ b/docker/justworks/business/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Napplet contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/docker/justworks/business/business_rollout.py b/docker/justworks/business/business_rollout.py
new file mode 100644
index 00000000..72638c5c
--- /dev/null
+++ b/docker/justworks/business/business_rollout.py
@@ -0,0 +1,275 @@
+"""Operational rollout and browser-bound Business SSO, not a new identity provider."""
+import hashlib
+import json
+import os
+import re
+import secrets
+import time
+from http.cookies import SimpleCookie
+from urllib.parse import urlsplit, urlencode
+
+import business_security as security
+
+GROUPS = ("merchant_config", "staff_reads", "staff_mutations")
+DEFAULT_ORIGINS = ("https://business.justworks.cash", "https://pos.justworks.cash")
+SSO_COOKIE = "__Host-jwb_exchange"
+TABLES = ("products", "tables", "orders", "payments", "quick_payments", "bookings", "merchant_modules")
+
+
+def migrate(conn):
+ conn.executescript("""
+ CREATE TABLE IF NOT EXISTS business_session_audiences (
+ token_hash TEXT PRIMARY KEY, audience TEXT NOT NULL);
+ CREATE TABLE IF NOT EXISTS business_identity_verifications (
+ npub TEXT PRIMARY KEY, slug TEXT NOT NULL, verified_at INTEGER NOT NULL);
+ CREATE TABLE IF NOT EXISTS business_merchant_aliases (
+ alias TEXT PRIMARY KEY, npub TEXT NOT NULL UNIQUE, verified_slug TEXT NOT NULL,
+ migrated_at INTEGER NOT NULL);
+ CREATE TABLE IF NOT EXISTS business_rollout_approvals (
+ route_group TEXT NOT NULL, npub TEXT NOT NULL, approved_at INTEGER NOT NULL,
+ PRIMARY KEY(route_group,npub));
+ CREATE TABLE IF NOT EXISTS business_exchanges (
+ request_hash TEXT PRIMARY KEY, binder_hash TEXT NOT NULL, npub TEXT NOT NULL,
+ audience TEXT NOT NULL, return_path TEXT NOT NULL, expires_at INTEGER NOT NULL,
+ code_hash TEXT UNIQUE, source_session TEXT, consumed INTEGER NOT NULL DEFAULT 0);
+ CREATE INDEX IF NOT EXISTS business_exchanges_expiry ON business_exchanges(expires_at);
+ """)
+
+
+def legacy_merchant(conn):
+ row = conn.execute("SELECT npub FROM business_merchant_aliases WHERE alias='localpub-demo'").fetchone()
+ return row[0] if row else "localpub-demo"
+
+
+def group_for(method, path):
+ if method == "GET" and path in security.PRIVILEGED_GET | {"/api/business"}:
+ return "staff_reads"
+ if method == "POST" and path in security.PRIVILEGED_POST:
+ return "merchant_config"
+ if method == "POST" and re.fullmatch(r"/api/(orders|payments|bookings)/[^/]+/(status|acknowledge)", path):
+ return "staff_mutations"
+ return None
+
+
+def policy():
+ groups = json.loads(os.environ.get("JWB_AUTH_GROUPS", "{}"))
+ if not isinstance(groups, dict) or any(k not in GROUPS or v not in ("shadow", "enforce") for k, v in groups.items()):
+ raise ValueError("invalid JWB_AUTH_GROUPS")
+ canaries = set(filter(None, (x.strip() for x in os.environ.get("JWB_AUTH_CANARIES", "").split(","))))
+ for merchant in canaries:
+ security.canonical_npub(merchant)
+ return groups, canaries
+
+
+def effective_mode(conn, method, path, merchant):
+ global_mode = security.mode()
+ # Existing global enforce is retained for regression/local tests only.
+ # Operators use shadow + groups; force-shadow overrides all group settings.
+ if global_mode == "off" or os.environ.get("JWB_AUTH_FORCE_SHADOW", "0") == "1":
+ return "off" if global_mode == "off" else "shadow"
+ if global_mode == "enforce":
+ return "enforce"
+ groups, canaries = policy()
+ group = group_for(method, path)
+ if groups.get(group) != "enforce" or merchant not in canaries:
+ return "shadow"
+ approved = conn.execute("SELECT 1 FROM business_rollout_approvals WHERE route_group=? AND npub=?", (group, merchant)).fetchone()
+ return "enforce" if approved else "shadow"
+
+
+def verification(conn, npub, slug):
+ conn.execute("INSERT OR REPLACE INTO business_identity_verifications VALUES (?,?,?)", (security.canonical_npub(npub), slug, int(time.time())))
+ conn.commit()
+
+
+def migration_plan(conn, npub, slug):
+ npub = security.canonical_npub(npub)
+ existing = conn.execute("SELECT * FROM business_merchant_aliases WHERE alias='localpub-demo'").fetchone()
+ if existing:
+ if existing["npub"] != npub or existing["verified_slug"] != slug:
+ raise ValueError("legacy merchant already mapped to a different identity")
+ return {"already_applied": True, "source": "localpub-demo", "target": npub, "counts": {}}
+ verified = conn.execute("SELECT slug,verified_at FROM business_identity_verifications WHERE npub=?", (npub,)).fetchone()
+ if not verified or verified[0] != slug or verified[1] < int(time.time()) - 86400:
+ raise ValueError("recent Core-verified owner login and matching slug required")
+ if not conn.execute("SELECT 1 FROM merchant WHERE id='localpub-demo'").fetchone():
+ raise ValueError("legacy merchant missing")
+ counts = {table: conn.execute(f"SELECT COUNT(*) FROM {table} WHERE merchant_id='localpub-demo'").fetchone()[0] for table in TABLES}
+ # Never merge unrelated tenant records or choose which configuration wins.
+ if conn.execute("SELECT 1 FROM merchant WHERE id=?", (npub,)).fetchone() or any(
+ conn.execute(f"SELECT 1 FROM {table} WHERE merchant_id=? LIMIT 1", (npub,)).fetchone() for table in TABLES
+ ):
+ raise ValueError("target has existing data; explicit reconciliation required before migration")
+ return {"already_applied": False, "source": "localpub-demo", "target": npub, "counts": counts}
+
+
+def migrate_legacy(conn, npub, slug, apply=False):
+ conn.execute("BEGIN IMMEDIATE")
+ try:
+ report = migration_plan(conn, npub, slug)
+ if apply and not report["already_applied"]:
+ conn.execute("UPDATE merchant SET id=? WHERE id='localpub-demo'", (npub,))
+ for table in TABLES:
+ conn.execute(f"UPDATE {table} SET merchant_id=? WHERE merchant_id='localpub-demo'", (npub,))
+ conn.execute("INSERT INTO business_merchant_aliases VALUES ('localpub-demo',?,?,?)", (npub, slug, int(time.time())))
+ conn.execute("INSERT INTO business_audit(occurred_at,event,route,merchant,actor,reason) VALUES (?,'merchant_migrated','operator',?,?,'explicit_verified_mapping')", (int(time.time()), npub, npub))
+ conn.commit()
+ else:
+ conn.rollback()
+ return {**report, "applied": apply}
+ except Exception:
+ conn.rollback()
+ raise
+
+
+def origins():
+ values = tuple(x.strip() for x in os.environ.get("JWB_SSO_ORIGINS", ",".join(DEFAULT_ORIGINS)).split(",") if x.strip())
+ for value in values:
+ p = urlsplit(value)
+ if p.scheme != "https" or not p.hostname or p.username or p.password or p.port or p.path or p.query or p.fragment or value != f"https://{p.hostname}" or not p.hostname.endswith(".justworks.cash"):
+ raise ValueError("SSO origins must be exact HTTPS JustWorks subdomains")
+ if DEFAULT_ORIGINS[0] not in values:
+ raise ValueError("business.justworks.cash must remain the Business session hub")
+ return values
+
+
+def request_origin(headers):
+ host = headers.get("Host", "").lower()
+ origin = "https://" + host
+ if origin not in origins():
+ raise ValueError("SSO host not allowed")
+ if headers.get("Origin") != origin or headers.get("Sec-Fetch-Site") == "cross-site":
+ raise ValueError("explicit same-origin request required")
+ return origin
+
+
+def enabled():
+ return os.environ.get("JWB_SSO_ENABLED", "0") == "1"
+
+
+def safe_return(value):
+ if not isinstance(value, str) or len(value) > 2000 or not value.startswith("/") or value.startswith("//") or "\\" in value or any(ord(c) < 32 for c in value):
+ raise ValueError("invalid return path")
+ p = urlsplit(value)
+ if p.scheme or p.netloc or p.fragment or "%" in p.path:
+ raise ValueError("invalid return path")
+ return value
+
+
+def opaque(value):
+ if not isinstance(value, str) or not re.fullmatch(r"[A-Za-z0-9_-]{43}", value):
+ raise ValueError("invalid exchange")
+ return value
+
+
+def exchange_cookie(token="", ttl=0):
+ return f"{SSO_COOKIE}={token}; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age={ttl}"
+
+
+def start(conn, values, headers):
+ audience = request_origin(headers)
+ npub = security.canonical_npub(values.get("npub"))
+ target = safe_return(values.get("return_path", "/"))
+ request_id, binder = secrets.token_urlsafe(32), secrets.token_urlsafe(32)
+ timestamp = int(time.time())
+ conn.execute("DELETE FROM business_exchanges WHERE expires_at<=? OR consumed=1", (timestamp,))
+ if conn.execute("SELECT COUNT(*) FROM business_exchanges").fetchone()[0] >= 1000:
+ raise ValueError("exchange capacity reached")
+ conn.execute("INSERT INTO business_exchanges(request_hash,binder_hash,npub,audience,return_path,expires_at) VALUES (?,?,?,?,?,?)", (security.token_hash(request_id), security.token_hash(binder), npub, audience, target, timestamp + 180))
+ conn.commit()
+ return {"request_id": request_id, "authorize_url": DEFAULT_ORIGINS[0] + "/business-sso?" + urlencode({"npub": npub}) + "#" + request_id, "source_origin": DEFAULT_ORIGINS[0]}, exchange_cookie(binder, 180)
+
+
+def pending(conn, request_id):
+ row = conn.execute("SELECT * FROM business_exchanges WHERE request_hash=? AND expires_at>? AND consumed=0", (security.token_hash(opaque(request_id)), int(time.time()))).fetchone()
+ if not row:
+ raise ValueError("exchange expired or used")
+ return row
+
+
+def source_details(conn, values, headers, approve=False):
+ if request_origin(headers) != DEFAULT_ORIGINS[0]:
+ raise ValueError("only Business session hub may approve")
+ row = pending(conn, values.get("request_id"))
+ current = security.session(conn, headers)
+ if not current or current["npub"] != row["npub"]:
+ raise ValueError("matching verified Business login required")
+ if row["audience"] not in origins():
+ raise ValueError("audience no longer allowed")
+ result = {"audience": row["audience"], "npub": row["npub"]}
+ if approve:
+ if row["code_hash"]:
+ raise ValueError("exchange already approved")
+ code = secrets.token_urlsafe(32)
+ cookie = SimpleCookie(); cookie.load(headers.get("Cookie", ""))
+ source_hash = security.token_hash(cookie[security.COOKIE].value)
+ conn.execute("UPDATE business_exchanges SET code_hash=?,source_session=?,expires_at=? WHERE request_hash=?", (security.token_hash(code), source_hash, min(row["expires_at"], int(time.time()) + 60), row["request_hash"]))
+ conn.commit()
+ result["code"] = code
+ security.audit(conn, "exchange_approved", "/api/business-sso/approve", row["npub"], current["npub"])
+ return result
+
+
+def complete(conn, values, headers):
+ audience = request_origin(headers)
+ row = pending(conn, values.get("request_id"))
+ cookie = SimpleCookie(); cookie.load(headers.get("Cookie", ""))
+ binder = cookie[SSO_COOKIE].value if SSO_COOKIE in cookie else ""
+ code_hash = security.token_hash(opaque(values.get("code")))
+ source = conn.execute("SELECT s.npub FROM business_sessions s JOIN business_session_audiences a ON a.token_hash=s.token_hash WHERE s.token_hash=? AND s.expires_at>? AND a.audience=?", (row["source_session"], int(time.time()), DEFAULT_ORIGINS[0][8:])).fetchone()
+ if row["audience"] != audience or not secrets.compare_digest(row["binder_hash"], security.token_hash(binder)) or not secrets.compare_digest(row["code_hash"] or "", code_hash) or not source or source[0] != row["npub"]:
+ raise ValueError("exchange binding mismatch")
+ # The caller serializes HTTP operations with the application lock. This UPDATE
+ # also makes consumption conditional for other operator/SQLite clients.
+ updated = conn.execute("UPDATE business_exchanges SET consumed=1 WHERE request_hash=? AND consumed=0", (row["request_hash"],))
+ if updated.rowcount != 1:
+ raise ValueError("exchange already used")
+ conn.commit()
+ session_cookie, expires = security.issue(conn, row["npub"], headers)
+ security.audit(conn, "exchange_completed", "/api/business-sso/complete", row["npub"], row["npub"])
+ return {"ok": True, "npub": row["npub"], "expires_at": expires, "return_path": row["return_path"]}, session_cookie
+
+
+def readiness(conn, npub, group):
+ npub = security.canonical_npub(npub)
+ if group not in GROUPS:
+ raise ValueError("unknown route group")
+ blockers = []
+ if not conn.execute("SELECT 1 FROM business_identity_verifications WHERE npub=?", (npub,)).fetchone():
+ blockers.append("no_verified_owner_login")
+ hosts = {row[0] for row in conn.execute("SELECT DISTINCT a.audience FROM business_sessions s JOIN business_session_audiences a ON a.token_hash=s.token_hash WHERE s.npub=? AND s.expires_at>?", (npub, int(time.time())))}
+ if not all(urlsplit(origin).hostname in hosts for origin in origins()):
+ blockers.append("missing_verified_session_on_configured_hosts")
+ if not enabled() or not conn.execute("SELECT 1 FROM business_audit WHERE event='exchange_completed' AND merchant=?", (npub,)).fetchone():
+ blockers.append("subdomain_exchange_not_verified")
+ if legacy_merchant(conn) == "localpub-demo":
+ blockers.append("legacy_owner_mapping_unresolved")
+ return blockers
+
+
+def approve_group(conn, npub, group):
+ blockers = readiness(conn, npub, group)
+ if blockers:
+ raise ValueError("readiness blocked: " + ", ".join(blockers))
+ conn.execute("INSERT OR REPLACE INTO business_rollout_approvals VALUES (?,?,?)", (group, npub, int(time.time())))
+ conn.commit()
+ security.audit(conn, "rollout_approved", "operator", npub, npub, group)
+
+
+def audit_report(conn, since=0, reveal=False):
+ def identity(value):
+ return value if reveal or value == "localpub-demo" else "merchant:" + hashlib.sha256(value.encode()).hexdigest()[:12] if value else "unknown"
+ rows = conn.execute("SELECT event,route,merchant,reason,COUNT(*) AS events,MIN(occurred_at) AS first_seen,MAX(occurred_at) AS last_seen FROM business_audit WHERE occurred_at>=? AND event IN ('would_deny','denied') GROUP BY event,route,merchant,reason ORDER BY events DESC", (since,))
+ observations = [{**dict(row), "merchant": identity(row["merchant"]), "group": group_for("GET" if row["route"] in security.PRIVILEGED_GET else "POST", row["route"])} for row in rows]
+ groups, canaries = policy()
+ active_sessions = conn.execute("SELECT COUNT(*) FROM business_sessions WHERE expires_at>?", (int(time.time()),)).fetchone()[0]
+ blockers = []
+ if not active_sessions: blockers.append("no_active_business_sessions")
+ if legacy_merchant(conn) == 'localpub-demo': blockers.append("legacy_owner_mapping_unresolved")
+ if not enabled(): blockers.append("subdomain_exchange_disabled")
+ if not canaries: blockers.append("no_explicit_canary_merchants")
+ return {"mode": security.mode(), "force_shadow": os.environ.get("JWB_AUTH_FORCE_SHADOW") == "1", "groups": groups,
+ "canaries": [identity(x) for x in sorted(canaries)], "legacy_mapping": identity(legacy_merchant(conn)),
+ "active_sessions": active_sessions, "blockers": blockers,
+ "observations": observations, "coalesced_events_not_request_counts": True,
+ "canary_readiness": [{"merchant": identity(x), "group": group, "blockers": readiness(conn, x, group), "approved": bool(conn.execute("SELECT 1 FROM business_rollout_approvals WHERE route_group=? AND npub=?", (group, x)).fetchone())} for x in sorted(canaries) for group in GROUPS]}
diff --git a/docker/justworks/business/business_security.py b/docker/justworks/business/business_security.py
new file mode 100644
index 00000000..5a4fc0a0
--- /dev/null
+++ b/docker/justworks/business/business_security.py
@@ -0,0 +1,226 @@
+"""Additive Business authorization; never an identity provider or key store."""
+import hashlib
+import ipaddress
+import os
+import re
+import secrets
+import time
+from http.cookies import SimpleCookie, CookieError
+from collections import OrderedDict
+
+COOKIE = "jwb_session"
+PRIVILEGED_GET = {"/api/dashboard", "/api/pos"}
+PRIVILEGED_POST = {"/api/config", "/api/business-config", "/api/business-profile"}
+RATE_BUCKETS = OrderedDict()
+
+
+def canonical_npub(value):
+ """Validate NIP-19 bech32 checksum and the 32-byte public key length."""
+ alphabet = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+ if not isinstance(value, str) or len(value) != 63 or not value.startswith("npub1"):
+ raise ValueError("invalid npub")
+ try:
+ data = [alphabet.index(char) for char in value[5:]]
+ except ValueError:
+ raise ValueError("invalid npub") from None
+ checksum = 1
+ expanded = [ord(c) >> 5 for c in "npub"] + [0] + [ord(c) & 31 for c in "npub"]
+ for item in expanded + data:
+ high = checksum >> 25
+ checksum = ((checksum & 0x1ffffff) << 5) ^ item
+ for bit, generator in enumerate((0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3)):
+ if (high >> bit) & 1: checksum ^= generator
+ if checksum != 1 or data[-7] & 15:
+ raise ValueError("invalid npub")
+ return value
+
+
+def client_ip(remote, headers):
+ """Trust one Nginx-overwritten X-Real-IP only from explicitly enabled loopback."""
+ def normalize(value):
+ if not isinstance(value, str) or '%' in value:
+ raise ValueError("invalid address")
+ address = ipaddress.ip_address(value.strip())
+ if isinstance(address, ipaddress.IPv6Address) and address.ipv4_mapped:
+ return address.ipv4_mapped
+ return address
+
+ try:
+ peer = normalize(remote)
+ except ValueError:
+ return "unknown"
+ if os.environ.get("JWB_TRUST_PROXY", "0") != "1" or not peer.is_loopback:
+ return str(peer)
+ # HTTPMessage permits duplicate headers; a normal dict is used by unit tests.
+ values = headers.get_all("X-Real-IP", []) if hasattr(headers, "get_all") else [headers.get("X-Real-IP", "")]
+ if len(values) == 1:
+ try:
+ return str(normalize(values[0]))
+ except ValueError:
+ pass
+ return str(peer)
+
+
+def rate_scope(path, values):
+ # Table flows ignore caller-supplied npub; opaque tokens never enter bucket keys.
+ if path in {"/api/orders", "/api/payments"}:
+ for field in ("token", "order_id", "payment_id"):
+ value = values.get(field)
+ if isinstance(value, str) and value:
+ return field + ":" + token_hash(value)
+ return "unscoped"
+ try:
+ return "merchant:" + canonical_npub(values.get("npub", ""))
+ except ValueError:
+ return "unscoped"
+
+
+def rate_allowed(remote, path, values=None, headers=None):
+ # Caller holds the process lock. Keep only a digest of the normalized peer.
+ timestamp = int(time.time()) // 60
+ peer = client_ip(remote, headers or {})
+ key = (token_hash(peer), path, rate_scope(path, values or {}))
+ prior_window, count = RATE_BUCKETS.pop(key, (timestamp, 0))
+ count = count + 1 if prior_window == timestamp else 1
+ RATE_BUCKETS[key] = (timestamp, count)
+ while len(RATE_BUCKETS) > 2048: RATE_BUCKETS.popitem(last=False)
+ return count <= (20 if path == "/api/business-owner-login" else 120)
+
+
+def mode():
+ value = os.environ.get("JWB_AUTH_MODE", "shadow")
+ if value not in {"off", "shadow", "enforce"}:
+ raise RuntimeError("JWB_AUTH_MODE must be off, shadow or enforce")
+ return value
+
+
+def migrate(conn):
+ conn.executescript("""
+ CREATE TABLE IF NOT EXISTS business_sessions (
+ token_hash TEXT PRIMARY KEY, npub TEXT NOT NULL, created_at INTEGER NOT NULL,
+ expires_at INTEGER NOT NULL);
+ CREATE INDEX IF NOT EXISTS business_sessions_expiry ON business_sessions(expires_at);
+ CREATE TABLE IF NOT EXISTS business_audit (
+ id INTEGER PRIMARY KEY AUTOINCREMENT, occurred_at INTEGER NOT NULL,
+ event TEXT NOT NULL, route TEXT NOT NULL, merchant TEXT NOT NULL,
+ actor TEXT NOT NULL, reason TEXT NOT NULL);
+ """)
+ import business_rollout
+ business_rollout.migrate(conn)
+
+
+def audit(conn, event, route="", merchant="", actor="", reason=""):
+ # Only fixed event/reason codes and public identities; never bodies, cookies or exceptions.
+ timestamp = int(time.time())
+ route = re.sub(r"/api/(orders|payments|bookings)/[^/]+/", r"/api/\1/:id/", route)
+ merchant = merchant if re.fullmatch(r"npub1[023456789acdefghjklmnpqrstuvwxyz]{58}|localpub-demo", merchant) else ""
+ actor = actor if re.fullmatch(r"npub1[023456789acdefghjklmnpqrstuvwxyz]{58}", actor) else ""
+ if event == "would_deny" and conn.execute(
+ "SELECT 1 FROM business_audit WHERE event=? AND route=? AND merchant=? AND reason=? AND occurred_at>? LIMIT 1",
+ (event, route, merchant, reason, timestamp - 60)).fetchone():
+ return
+ conn.execute("INSERT INTO business_audit(occurred_at,event,route,merchant,actor,reason) VALUES (?,?,?,?,?,?)",
+ (timestamp, event, route, merchant, actor, reason))
+ conn.execute("DELETE FROM business_audit WHERE id NOT IN (SELECT id FROM business_audit ORDER BY id DESC LIMIT 10000)")
+ conn.execute("DELETE FROM business_sessions WHERE expires_at<=?", (timestamp,))
+ conn.execute("DELETE FROM business_session_audiences WHERE token_hash NOT IN (SELECT token_hash FROM business_sessions)")
+ conn.commit()
+
+
+def token_hash(token):
+ return hashlib.sha256(token.encode()).hexdigest()
+
+
+def session(conn, headers):
+ try:
+ cookie = SimpleCookie()
+ cookie.load(headers.get("Cookie", ""))
+ token = cookie[COOKIE].value
+ if not re.fullmatch(r"[A-Za-z0-9_-]{43}", token):
+ return None
+ row = conn.execute("SELECT s.npub,s.expires_at FROM business_sessions s LEFT JOIN business_session_audiences a ON a.token_hash=s.token_hash WHERE s.token_hash=? AND s.expires_at>? AND (a.audience=? OR a.audience IS NULL)",
+ (token_hash(token), int(time.time()), headers.get("Host", "").lower())).fetchone()
+ return dict(row) if row else None
+ except (KeyError, ValueError, CookieError):
+ return None
+
+
+def revoke(conn, headers, all_sessions=False):
+ current = session(conn, headers)
+ if all_sessions and current:
+ conn.execute("DELETE FROM business_sessions WHERE npub=?", (current["npub"],))
+ else:
+ cookie = SimpleCookie()
+ try:
+ cookie.load(headers.get("Cookie", ""))
+ conn.execute("DELETE FROM business_sessions WHERE token_hash=?", (token_hash(cookie[COOKIE].value),))
+ except (KeyError, ValueError, CookieError):
+ pass
+ conn.execute("DELETE FROM business_session_audiences WHERE token_hash NOT IN (SELECT token_hash FROM business_sessions)")
+ conn.commit()
+ return current
+
+
+def cookie_header(token="", max_age=0):
+ # Local HTTP opt-out is operator configuration, never inferred from attacker-controlled Host.
+ secure = "" if os.environ.get("JWB_COOKIE_SECURE", "1") == "0" else "; Secure"
+ return f"{COOKIE}={token}; Path=/; HttpOnly; SameSite=Lax; Max-Age={max_age}{secure}"
+
+
+def issue(conn, npub, headers):
+ npub = canonical_npub(npub)
+ revoke(conn, headers)
+ token = secrets.token_urlsafe(32)
+ ttl = max(60, min(86400, int(os.environ.get("JWB_SESSION_TTL", "28800"))))
+ expires = int(time.time()) + ttl
+ conn.execute("INSERT INTO business_sessions(token_hash,npub,created_at,expires_at) VALUES (?,?,?,?)", (token_hash(token), npub, int(time.time()), expires))
+ conn.execute("INSERT INTO business_session_audiences VALUES (?,?)", (token_hash(token), headers.get("Host", "").lower()))
+ conn.execute("DELETE FROM business_sessions WHERE npub=? AND token_hash NOT IN (SELECT token_hash FROM business_sessions WHERE npub=? ORDER BY created_at DESC,rowid DESC LIMIT 10)", (npub, npub))
+ conn.execute("DELETE FROM business_session_audiences WHERE token_hash NOT IN (SELECT token_hash FROM business_sessions)")
+ conn.commit()
+ return cookie_header(token, ttl), expires
+
+
+def target(conn, method, path, values):
+ from business_rollout import legacy_merchant
+ if method == "GET" and path in PRIVILEGED_GET:
+ return legacy_merchant(conn) if path == "/api/dashboard" else str(values.get("npub", "")).strip()
+ if method == "POST" and path in PRIVILEGED_POST:
+ return legacy_merchant(conn) if path == "/api/config" else str(values.get("npub", "")).strip()
+ match = re.fullmatch(r"/api/(orders|payments|bookings)/([^/]+)/(status|acknowledge)", path)
+ if method == "POST" and match:
+ table, identity, _ = match.groups()
+ row = conn.execute(f"SELECT merchant_id FROM {table} WHERE id=?", (identity,)).fetchone()
+ return row[0] if row else ""
+ return None
+
+
+def same_origin(headers):
+ from urllib.parse import urlparse
+ origin = headers.get("Origin")
+ if headers.get("Sec-Fetch-Site") == "cross-site":
+ return False
+ if not origin:
+ return True # non-browser clients; browser JSON requests require CORS preflight
+ parsed = urlparse(origin)
+ return parsed.scheme in {"http", "https"} and parsed.netloc.lower() == headers.get("Host", "").lower()
+
+
+def authorize(conn, method, path, values, headers):
+ merchant = target(conn, method, path, values)
+ if merchant is None:
+ return True, None
+ current = session(conn, headers)
+ reason = ""
+ if not current:
+ reason = "missing_session"
+ elif current["npub"] != merchant:
+ reason = "tenant_mismatch"
+ elif method != "GET" and not same_origin(headers):
+ reason = "cross_origin"
+ from business_rollout import effective_mode
+ selected = effective_mode(conn, method, path, merchant)
+ if reason and selected != "off":
+ audit(conn, "denied" if selected == "enforce" else "would_deny", path, merchant,
+ current["npub"] if current else "", reason)
+ return not reason or selected != "enforce", (merchant, current["npub"] if current else "")
diff --git a/docker/justworks/business/payment-helper.cjs b/docker/justworks/business/payment-helper.cjs
new file mode 100644
index 00000000..fe8cb3fe
--- /dev/null
+++ b/docker/justworks/business/payment-helper.cjs
@@ -0,0 +1,15351 @@
+var __create = Object.create;
+var __defProp = Object.defineProperty;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __getProtoOf = Object.getPrototypeOf;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __commonJS = (cb, mod2) => function __require() {
+ return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
+};
+var __export = (target, all) => {
+ for (var name in all)
+ __defProp(target, name, { get: all[name], enumerable: true });
+};
+var __copyProps = (to, from, except, desc) => {
+ if (from && typeof from === "object" || typeof from === "function") {
+ for (let key of __getOwnPropNames(from))
+ if (!__hasOwnProp.call(to, key) && key !== except)
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
+ }
+ return to;
+};
+var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
+ // If the importer is in node compatibility mode or this is not an ESM
+ // file that has been converted to a CommonJS file using a Babel-
+ // compatible transform (i.e. "__esModule" has not been set), then set
+ // "default" to the CommonJS "module.exports" for node compatibility.
+ isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target,
+ mod2
+));
+
+// node_modules/bech32/dist/index.js
+var require_dist = __commonJS({
+ "node_modules/bech32/dist/index.js"(exports2) {
+ "use strict";
+ Object.defineProperty(exports2, "__esModule", { value: true });
+ exports2.bech32m = exports2.bech32 = void 0;
+ var ALPHABET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
+ var ALPHABET_MAP = {};
+ for (let z = 0; z < ALPHABET.length; z++) {
+ const x = ALPHABET.charAt(z);
+ ALPHABET_MAP[x] = z;
+ }
+ function polymodStep(pre) {
+ const b = pre >> 25;
+ return (pre & 33554431) << 5 ^ -(b >> 0 & 1) & 996825010 ^ -(b >> 1 & 1) & 642813549 ^ -(b >> 2 & 1) & 513874426 ^ -(b >> 3 & 1) & 1027748829 ^ -(b >> 4 & 1) & 705979059;
+ }
+ function prefixChk(prefix) {
+ let chk = 1;
+ for (let i3 = 0; i3 < prefix.length; ++i3) {
+ const c = prefix.charCodeAt(i3);
+ if (c < 33 || c > 126)
+ return "Invalid prefix (" + prefix + ")";
+ chk = polymodStep(chk) ^ c >> 5;
+ }
+ chk = polymodStep(chk);
+ for (let i3 = 0; i3 < prefix.length; ++i3) {
+ const v = prefix.charCodeAt(i3);
+ chk = polymodStep(chk) ^ v & 31;
+ }
+ return chk;
+ }
+ function convert(data, inBits, outBits, pad2) {
+ let value = 0;
+ let bits = 0;
+ const maxV = (1 << outBits) - 1;
+ const result = [];
+ for (let i3 = 0; i3 < data.length; ++i3) {
+ value = value << inBits | data[i3];
+ bits += inBits;
+ while (bits >= outBits) {
+ bits -= outBits;
+ result.push(value >> bits & maxV);
+ }
+ }
+ if (pad2) {
+ if (bits > 0) {
+ result.push(value << outBits - bits & maxV);
+ }
+ } else {
+ if (bits >= inBits)
+ return "Excess padding";
+ if (value << outBits - bits & maxV)
+ return "Non-zero padding";
+ }
+ return result;
+ }
+ function toWords(bytes4) {
+ return convert(bytes4, 8, 5, true);
+ }
+ function fromWordsUnsafe(words) {
+ const res = convert(words, 5, 8, false);
+ if (Array.isArray(res))
+ return res;
+ }
+ function fromWords(words) {
+ const res = convert(words, 5, 8, false);
+ if (Array.isArray(res))
+ return res;
+ throw new Error(res);
+ }
+ function getLibraryFromEncoding(encoding) {
+ let ENCODING_CONST;
+ if (encoding === "bech32") {
+ ENCODING_CONST = 1;
+ } else {
+ ENCODING_CONST = 734539939;
+ }
+ function encode(prefix, words, LIMIT) {
+ LIMIT = LIMIT || 90;
+ if (prefix.length + 7 + words.length > LIMIT)
+ throw new TypeError("Exceeds length limit");
+ prefix = prefix.toLowerCase();
+ let chk = prefixChk(prefix);
+ if (typeof chk === "string")
+ throw new Error(chk);
+ let result = prefix + "1";
+ for (let i3 = 0; i3 < words.length; ++i3) {
+ const x = words[i3];
+ if (x >> 5 !== 0)
+ throw new Error("Non 5-bit word");
+ chk = polymodStep(chk) ^ x;
+ result += ALPHABET.charAt(x);
+ }
+ for (let i3 = 0; i3 < 6; ++i3) {
+ chk = polymodStep(chk);
+ }
+ chk ^= ENCODING_CONST;
+ for (let i3 = 0; i3 < 6; ++i3) {
+ const v = chk >> (5 - i3) * 5 & 31;
+ result += ALPHABET.charAt(v);
+ }
+ return result;
+ }
+ function __decode(str, LIMIT) {
+ LIMIT = LIMIT || 90;
+ if (str.length < 8)
+ return str + " too short";
+ if (str.length > LIMIT)
+ return "Exceeds length limit";
+ const lowered = str.toLowerCase();
+ const uppered = str.toUpperCase();
+ if (str !== lowered && str !== uppered)
+ return "Mixed-case string " + str;
+ str = lowered;
+ const split = str.lastIndexOf("1");
+ if (split === -1)
+ return "No separator character for " + str;
+ if (split === 0)
+ return "Missing prefix for " + str;
+ const prefix = str.slice(0, split);
+ const wordChars = str.slice(split + 1);
+ if (wordChars.length < 6)
+ return "Data too short";
+ let chk = prefixChk(prefix);
+ if (typeof chk === "string")
+ return chk;
+ const words = [];
+ for (let i3 = 0; i3 < wordChars.length; ++i3) {
+ const c = wordChars.charAt(i3);
+ const v = ALPHABET_MAP[c];
+ if (v === void 0)
+ return "Unknown character " + c;
+ chk = polymodStep(chk) ^ v;
+ if (i3 + 6 >= wordChars.length)
+ continue;
+ words.push(v);
+ }
+ if (chk !== ENCODING_CONST)
+ return "Invalid checksum for " + str;
+ return { prefix, words };
+ }
+ function decodeUnsafe(str, LIMIT) {
+ const res = __decode(str, LIMIT);
+ if (typeof res === "object")
+ return res;
+ }
+ function decode2(str, LIMIT) {
+ const res = __decode(str, LIMIT);
+ if (typeof res === "object")
+ return res;
+ throw new Error(res);
+ }
+ return {
+ decodeUnsafe,
+ decode: decode2,
+ encode,
+ toWords,
+ fromWordsUnsafe,
+ fromWords
+ };
+ }
+ exports2.bech32 = getLibraryFromEncoding("bech32");
+ exports2.bech32m = getLibraryFromEncoding("bech32m");
+ }
+});
+
+// node_modules/ws/lib/constants.js
+var require_constants = __commonJS({
+ "node_modules/ws/lib/constants.js"(exports2, module2) {
+ "use strict";
+ var BINARY_TYPES = ["nodebuffer", "arraybuffer", "fragments"];
+ var hasBlob = typeof Blob !== "undefined";
+ if (hasBlob) BINARY_TYPES.push("blob");
+ module2.exports = {
+ BINARY_TYPES,
+ EMPTY_BUFFER: Buffer.alloc(0),
+ GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
+ hasBlob,
+ kForOnEventAttribute: Symbol("kIsForOnEventAttribute"),
+ kListener: Symbol("kListener"),
+ kStatusCode: Symbol("status-code"),
+ kWebSocket: Symbol("websocket"),
+ NOOP: () => {
+ }
+ };
+ }
+});
+
+// node_modules/ws/lib/buffer-util.js
+var require_buffer_util = __commonJS({
+ "node_modules/ws/lib/buffer-util.js"(exports2, module2) {
+ "use strict";
+ var { EMPTY_BUFFER: EMPTY_BUFFER2 } = require_constants();
+ var FastBuffer = Buffer[Symbol.species];
+ function concat(list, totalLength) {
+ if (list.length === 0) return EMPTY_BUFFER2;
+ if (list.length === 1) return list[0];
+ const target = Buffer.allocUnsafe(totalLength);
+ let offset = 0;
+ for (let i3 = 0; i3 < list.length; i3++) {
+ const buf = list[i3];
+ target.set(buf, offset);
+ offset += buf.length;
+ }
+ if (offset < totalLength) {
+ return new FastBuffer(target.buffer, target.byteOffset, offset);
+ }
+ return target;
+ }
+ function _mask(source, mask, output4, offset, length) {
+ for (let i3 = 0; i3 < length; i3++) {
+ output4[offset + i3] = source[i3] ^ mask[i3 & 3];
+ }
+ }
+ function _unmask(buffer, mask) {
+ for (let i3 = 0; i3 < buffer.length; i3++) {
+ buffer[i3] ^= mask[i3 & 3];
+ }
+ }
+ function toArrayBuffer(buf) {
+ if (buf.length === buf.buffer.byteLength) {
+ return buf.buffer;
+ }
+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
+ }
+ function toBuffer(data) {
+ toBuffer.readOnly = true;
+ if (Buffer.isBuffer(data)) return data;
+ let buf;
+ if (data instanceof ArrayBuffer) {
+ buf = new FastBuffer(data);
+ } else if (ArrayBuffer.isView(data)) {
+ buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);
+ } else {
+ buf = Buffer.from(data);
+ toBuffer.readOnly = false;
+ }
+ return buf;
+ }
+ module2.exports = {
+ concat,
+ mask: _mask,
+ toArrayBuffer,
+ toBuffer,
+ unmask: _unmask
+ };
+ if (!process.env.WS_NO_BUFFER_UTIL) {
+ try {
+ const bufferUtil = require("bufferutil");
+ module2.exports.mask = function(source, mask, output4, offset, length) {
+ if (length < 48) _mask(source, mask, output4, offset, length);
+ else bufferUtil.mask(source, mask, output4, offset, length);
+ };
+ module2.exports.unmask = function(buffer, mask) {
+ if (buffer.length < 32) _unmask(buffer, mask);
+ else bufferUtil.unmask(buffer, mask);
+ };
+ } catch (e) {
+ }
+ }
+ }
+});
+
+// node_modules/ws/lib/limiter.js
+var require_limiter = __commonJS({
+ "node_modules/ws/lib/limiter.js"(exports2, module2) {
+ "use strict";
+ var kDone = Symbol("kDone");
+ var kRun = Symbol("kRun");
+ var Limiter = class {
+ /**
+ * Creates a new `Limiter`.
+ *
+ * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
+ * to run concurrently
+ */
+ constructor(concurrency) {
+ this[kDone] = () => {
+ this.pending--;
+ this[kRun]();
+ };
+ this.concurrency = concurrency || Infinity;
+ this.jobs = [];
+ this.pending = 0;
+ }
+ /**
+ * Adds a job to the queue.
+ *
+ * @param {Function} job The job to run
+ * @public
+ */
+ add(job) {
+ this.jobs.push(job);
+ this[kRun]();
+ }
+ /**
+ * Removes a job from the queue and runs it if possible.
+ *
+ * @private
+ */
+ [kRun]() {
+ if (this.pending === this.concurrency) return;
+ if (this.jobs.length) {
+ const job = this.jobs.shift();
+ this.pending++;
+ job(this[kDone]);
+ }
+ }
+ };
+ module2.exports = Limiter;
+ }
+});
+
+// node_modules/ws/lib/permessage-deflate.js
+var require_permessage_deflate = __commonJS({
+ "node_modules/ws/lib/permessage-deflate.js"(exports2, module2) {
+ "use strict";
+ var zlib = require("zlib");
+ var bufferUtil = require_buffer_util();
+ var Limiter = require_limiter();
+ var { kStatusCode } = require_constants();
+ var FastBuffer = Buffer[Symbol.species];
+ var TRAILER = Buffer.from([0, 0, 255, 255]);
+ var kPerMessageDeflate = Symbol("permessage-deflate");
+ var kTotalLength = Symbol("total-length");
+ var kCallback = Symbol("callback");
+ var kBuffers = Symbol("buffers");
+ var kError = Symbol("error");
+ var zlibLimiter;
+ var PerMessageDeflate = class {
+ /**
+ * Creates a PerMessageDeflate instance.
+ *
+ * @param {Object} [options] Configuration options
+ * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
+ * for, or request, a custom client window size
+ * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/
+ * acknowledge disabling of client context takeover
+ * @param {Number} [options.concurrencyLimit=10] The number of concurrent
+ * calls to zlib
+ * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
+ * use of a custom server window size
+ * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
+ * disabling of server context takeover
+ * @param {Number} [options.threshold=1024] Size (in bytes) below which
+ * messages should not be compressed if context takeover is disabled
+ * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on
+ * deflate
+ * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
+ * inflate
+ * @param {Boolean} [isServer=false] Create the instance in either server or
+ * client mode
+ * @param {Number} [maxPayload=0] The maximum allowed message length
+ */
+ constructor(options, isServer, maxPayload) {
+ this._maxPayload = maxPayload | 0;
+ this._options = options || {};
+ this._threshold = this._options.threshold !== void 0 ? this._options.threshold : 1024;
+ this._isServer = !!isServer;
+ this._deflate = null;
+ this._inflate = null;
+ this.params = null;
+ if (!zlibLimiter) {
+ const concurrency = this._options.concurrencyLimit !== void 0 ? this._options.concurrencyLimit : 10;
+ zlibLimiter = new Limiter(concurrency);
+ }
+ }
+ /**
+ * @type {String}
+ */
+ static get extensionName() {
+ return "permessage-deflate";
+ }
+ /**
+ * Create an extension negotiation offer.
+ *
+ * @return {Object} Extension parameters
+ * @public
+ */
+ offer() {
+ const params = {};
+ if (this._options.serverNoContextTakeover) {
+ params.server_no_context_takeover = true;
+ }
+ if (this._options.clientNoContextTakeover) {
+ params.client_no_context_takeover = true;
+ }
+ if (this._options.serverMaxWindowBits) {
+ params.server_max_window_bits = this._options.serverMaxWindowBits;
+ }
+ if (this._options.clientMaxWindowBits) {
+ params.client_max_window_bits = this._options.clientMaxWindowBits;
+ } else if (this._options.clientMaxWindowBits == null) {
+ params.client_max_window_bits = true;
+ }
+ return params;
+ }
+ /**
+ * Accept an extension negotiation offer/response.
+ *
+ * @param {Array} configurations The extension negotiation offers/reponse
+ * @return {Object} Accepted configuration
+ * @public
+ */
+ accept(configurations) {
+ configurations = this.normalizeParams(configurations);
+ this.params = this._isServer ? this.acceptAsServer(configurations) : this.acceptAsClient(configurations);
+ return this.params;
+ }
+ /**
+ * Releases all resources used by the extension.
+ *
+ * @public
+ */
+ cleanup() {
+ if (this._inflate) {
+ this._inflate.close();
+ this._inflate = null;
+ }
+ if (this._deflate) {
+ const callback = this._deflate[kCallback];
+ this._deflate.close();
+ this._deflate = null;
+ if (callback) {
+ callback(
+ new Error(
+ "The deflate stream was closed while data was being processed"
+ )
+ );
+ }
+ }
+ }
+ /**
+ * Accept an extension negotiation offer.
+ *
+ * @param {Array} offers The extension negotiation offers
+ * @return {Object} Accepted configuration
+ * @private
+ */
+ acceptAsServer(offers) {
+ const opts = this._options;
+ const accepted = offers.find((params) => {
+ if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && !params.client_max_window_bits) {
+ return false;
+ }
+ return true;
+ });
+ if (!accepted) {
+ throw new Error("None of the extension offers can be accepted");
+ }
+ if (opts.serverNoContextTakeover) {
+ accepted.server_no_context_takeover = true;
+ }
+ if (opts.clientNoContextTakeover) {
+ accepted.client_no_context_takeover = true;
+ }
+ if (typeof opts.serverMaxWindowBits === "number") {
+ accepted.server_max_window_bits = opts.serverMaxWindowBits;
+ }
+ if (typeof opts.clientMaxWindowBits === "number") {
+ accepted.client_max_window_bits = opts.clientMaxWindowBits;
+ } else if (accepted.client_max_window_bits === true || opts.clientMaxWindowBits === false) {
+ delete accepted.client_max_window_bits;
+ }
+ return accepted;
+ }
+ /**
+ * Accept the extension negotiation response.
+ *
+ * @param {Array} response The extension negotiation response
+ * @return {Object} Accepted configuration
+ * @private
+ */
+ acceptAsClient(response) {
+ const params = response[0];
+ if (this._options.clientNoContextTakeover === false && params.client_no_context_takeover) {
+ throw new Error('Unexpected parameter "client_no_context_takeover"');
+ }
+ if (!params.client_max_window_bits) {
+ if (typeof this._options.clientMaxWindowBits === "number") {
+ params.client_max_window_bits = this._options.clientMaxWindowBits;
+ }
+ } else if (this._options.clientMaxWindowBits === false || typeof this._options.clientMaxWindowBits === "number" && params.client_max_window_bits > this._options.clientMaxWindowBits) {
+ throw new Error(
+ 'Unexpected or invalid parameter "client_max_window_bits"'
+ );
+ }
+ return params;
+ }
+ /**
+ * Normalize parameters.
+ *
+ * @param {Array} configurations The extension negotiation offers/reponse
+ * @return {Array} The offers/response with normalized parameters
+ * @private
+ */
+ normalizeParams(configurations) {
+ configurations.forEach((params) => {
+ Object.keys(params).forEach((key) => {
+ let value = params[key];
+ if (value.length > 1) {
+ throw new Error(`Parameter "${key}" must have only a single value`);
+ }
+ value = value[0];
+ if (key === "client_max_window_bits") {
+ if (value !== true) {
+ const num = +value;
+ if (!Number.isInteger(num) || num < 8 || num > 15) {
+ throw new TypeError(
+ `Invalid value for parameter "${key}": ${value}`
+ );
+ }
+ value = num;
+ } else if (!this._isServer) {
+ throw new TypeError(
+ `Invalid value for parameter "${key}": ${value}`
+ );
+ }
+ } else if (key === "server_max_window_bits") {
+ const num = +value;
+ if (!Number.isInteger(num) || num < 8 || num > 15) {
+ throw new TypeError(
+ `Invalid value for parameter "${key}": ${value}`
+ );
+ }
+ value = num;
+ } else if (key === "client_no_context_takeover" || key === "server_no_context_takeover") {
+ if (value !== true) {
+ throw new TypeError(
+ `Invalid value for parameter "${key}": ${value}`
+ );
+ }
+ } else {
+ throw new Error(`Unknown parameter "${key}"`);
+ }
+ params[key] = value;
+ });
+ });
+ return configurations;
+ }
+ /**
+ * Decompress data. Concurrency limited.
+ *
+ * @param {Buffer} data Compressed data
+ * @param {Boolean} fin Specifies whether or not this is the last fragment
+ * @param {Function} callback Callback
+ * @public
+ */
+ decompress(data, fin, callback) {
+ zlibLimiter.add((done) => {
+ this._decompress(data, fin, (err, result) => {
+ done();
+ callback(err, result);
+ });
+ });
+ }
+ /**
+ * Compress data. Concurrency limited.
+ *
+ * @param {(Buffer|String)} data Data to compress
+ * @param {Boolean} fin Specifies whether or not this is the last fragment
+ * @param {Function} callback Callback
+ * @public
+ */
+ compress(data, fin, callback) {
+ zlibLimiter.add((done) => {
+ this._compress(data, fin, (err, result) => {
+ done();
+ callback(err, result);
+ });
+ });
+ }
+ /**
+ * Decompress data.
+ *
+ * @param {Buffer} data Compressed data
+ * @param {Boolean} fin Specifies whether or not this is the last fragment
+ * @param {Function} callback Callback
+ * @private
+ */
+ _decompress(data, fin, callback) {
+ const endpoint = this._isServer ? "client" : "server";
+ if (!this._inflate) {
+ const key = `${endpoint}_max_window_bits`;
+ const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
+ this._inflate = zlib.createInflateRaw({
+ ...this._options.zlibInflateOptions,
+ windowBits
+ });
+ this._inflate[kPerMessageDeflate] = this;
+ this._inflate[kTotalLength] = 0;
+ this._inflate[kBuffers] = [];
+ this._inflate.on("error", inflateOnError);
+ this._inflate.on("data", inflateOnData);
+ }
+ this._inflate[kCallback] = callback;
+ this._inflate.write(data);
+ if (fin) this._inflate.write(TRAILER);
+ this._inflate.flush(() => {
+ const err = this._inflate[kError];
+ if (err) {
+ this._inflate.close();
+ this._inflate = null;
+ callback(err);
+ return;
+ }
+ const data2 = bufferUtil.concat(
+ this._inflate[kBuffers],
+ this._inflate[kTotalLength]
+ );
+ if (this._inflate._readableState.endEmitted) {
+ this._inflate.close();
+ this._inflate = null;
+ } else {
+ this._inflate[kTotalLength] = 0;
+ this._inflate[kBuffers] = [];
+ if (fin && this.params[`${endpoint}_no_context_takeover`]) {
+ this._inflate.reset();
+ }
+ }
+ callback(null, data2);
+ });
+ }
+ /**
+ * Compress data.
+ *
+ * @param {(Buffer|String)} data Data to compress
+ * @param {Boolean} fin Specifies whether or not this is the last fragment
+ * @param {Function} callback Callback
+ * @private
+ */
+ _compress(data, fin, callback) {
+ const endpoint = this._isServer ? "server" : "client";
+ if (!this._deflate) {
+ const key = `${endpoint}_max_window_bits`;
+ const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
+ this._deflate = zlib.createDeflateRaw({
+ ...this._options.zlibDeflateOptions,
+ windowBits
+ });
+ this._deflate[kTotalLength] = 0;
+ this._deflate[kBuffers] = [];
+ this._deflate.on("data", deflateOnData);
+ }
+ this._deflate[kCallback] = callback;
+ this._deflate.write(data);
+ this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {
+ if (!this._deflate) {
+ return;
+ }
+ let data2 = bufferUtil.concat(
+ this._deflate[kBuffers],
+ this._deflate[kTotalLength]
+ );
+ if (fin) {
+ data2 = new FastBuffer(data2.buffer, data2.byteOffset, data2.length - 4);
+ }
+ this._deflate[kCallback] = null;
+ this._deflate[kTotalLength] = 0;
+ this._deflate[kBuffers] = [];
+ if (fin && this.params[`${endpoint}_no_context_takeover`]) {
+ this._deflate.reset();
+ }
+ callback(null, data2);
+ });
+ }
+ };
+ module2.exports = PerMessageDeflate;
+ function deflateOnData(chunk) {
+ this[kBuffers].push(chunk);
+ this[kTotalLength] += chunk.length;
+ }
+ function inflateOnData(chunk) {
+ this[kTotalLength] += chunk.length;
+ if (this[kPerMessageDeflate]._maxPayload < 1 || this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload) {
+ this[kBuffers].push(chunk);
+ return;
+ }
+ this[kError] = new RangeError("Max payload size exceeded");
+ this[kError].code = "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH";
+ this[kError][kStatusCode] = 1009;
+ this.removeListener("data", inflateOnData);
+ this.reset();
+ }
+ function inflateOnError(err) {
+ this[kPerMessageDeflate]._inflate = null;
+ if (this[kError]) {
+ this[kCallback](this[kError]);
+ return;
+ }
+ err[kStatusCode] = 1007;
+ this[kCallback](err);
+ }
+ }
+});
+
+// node_modules/ws/lib/validation.js
+var require_validation = __commonJS({
+ "node_modules/ws/lib/validation.js"(exports2, module2) {
+ "use strict";
+ var { isUtf8 } = require("buffer");
+ var { hasBlob } = require_constants();
+ var tokenChars = [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ // 0 - 15
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ // 16 - 31
+ 0,
+ 1,
+ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ 1,
+ 1,
+ 0,
+ 1,
+ 1,
+ 0,
+ // 32 - 47
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ // 48 - 63
+ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ // 64 - 79
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ 0,
+ 1,
+ 1,
+ // 80 - 95
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ // 96 - 111
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 1,
+ 0,
+ 1,
+ 0
+ // 112 - 127
+ ];
+ function isValidStatusCode(code) {
+ return code >= 1e3 && code <= 1014 && code !== 1004 && code !== 1005 && code !== 1006 || code >= 3e3 && code <= 4999;
+ }
+ function _isValidUTF8(buf) {
+ const len = buf.length;
+ let i3 = 0;
+ while (i3 < len) {
+ if ((buf[i3] & 128) === 0) {
+ i3++;
+ } else if ((buf[i3] & 224) === 192) {
+ if (i3 + 1 === len || (buf[i3 + 1] & 192) !== 128 || (buf[i3] & 254) === 192) {
+ return false;
+ }
+ i3 += 2;
+ } else if ((buf[i3] & 240) === 224) {
+ if (i3 + 2 >= len || (buf[i3 + 1] & 192) !== 128 || (buf[i3 + 2] & 192) !== 128 || buf[i3] === 224 && (buf[i3 + 1] & 224) === 128 || // Overlong
+ buf[i3] === 237 && (buf[i3 + 1] & 224) === 160) {
+ return false;
+ }
+ i3 += 3;
+ } else if ((buf[i3] & 248) === 240) {
+ if (i3 + 3 >= len || (buf[i3 + 1] & 192) !== 128 || (buf[i3 + 2] & 192) !== 128 || (buf[i3 + 3] & 192) !== 128 || buf[i3] === 240 && (buf[i3 + 1] & 240) === 128 || // Overlong
+ buf[i3] === 244 && buf[i3 + 1] > 143 || buf[i3] > 244) {
+ return false;
+ }
+ i3 += 4;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+ function isBlob(value) {
+ return hasBlob && typeof value === "object" && typeof value.arrayBuffer === "function" && typeof value.type === "string" && typeof value.stream === "function" && (value[Symbol.toStringTag] === "Blob" || value[Symbol.toStringTag] === "File");
+ }
+ module2.exports = {
+ isBlob,
+ isValidStatusCode,
+ isValidUTF8: _isValidUTF8,
+ tokenChars
+ };
+ if (isUtf8) {
+ module2.exports.isValidUTF8 = function(buf) {
+ return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);
+ };
+ } else if (!process.env.WS_NO_UTF_8_VALIDATE) {
+ try {
+ const isValidUTF8 = require("utf-8-validate");
+ module2.exports.isValidUTF8 = function(buf) {
+ return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
+ };
+ } catch (e) {
+ }
+ }
+ }
+});
+
+// node_modules/ws/lib/receiver.js
+var require_receiver = __commonJS({
+ "node_modules/ws/lib/receiver.js"(exports2, module2) {
+ "use strict";
+ var { Writable } = require("stream");
+ var PerMessageDeflate = require_permessage_deflate();
+ var {
+ BINARY_TYPES,
+ EMPTY_BUFFER: EMPTY_BUFFER2,
+ kStatusCode,
+ kWebSocket
+ } = require_constants();
+ var { concat, toArrayBuffer, unmask } = require_buffer_util();
+ var { isValidStatusCode, isValidUTF8 } = require_validation();
+ var FastBuffer = Buffer[Symbol.species];
+ var GET_INFO = 0;
+ var GET_PAYLOAD_LENGTH_16 = 1;
+ var GET_PAYLOAD_LENGTH_64 = 2;
+ var GET_MASK = 3;
+ var GET_DATA = 4;
+ var INFLATING = 5;
+ var DEFER_EVENT = 6;
+ var Receiver2 = class extends Writable {
+ /**
+ * Creates a Receiver instance.
+ *
+ * @param {Object} [options] Options object
+ * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
+ * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
+ * multiple times in the same tick
+ * @param {String} [options.binaryType=nodebuffer] The type for binary data
+ * @param {Object} [options.extensions] An object containing the negotiated
+ * extensions
+ * @param {Boolean} [options.isServer=false] Specifies whether to operate in
+ * client or server mode
+ * @param {Number} [options.maxPayload=0] The maximum allowed message length
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
+ * not to skip UTF-8 validation for text and close messages
+ */
+ constructor(options = {}) {
+ super();
+ this._allowSynchronousEvents = options.allowSynchronousEvents !== void 0 ? options.allowSynchronousEvents : true;
+ this._binaryType = options.binaryType || BINARY_TYPES[0];
+ this._extensions = options.extensions || {};
+ this._isServer = !!options.isServer;
+ this._maxPayload = options.maxPayload | 0;
+ this._skipUTF8Validation = !!options.skipUTF8Validation;
+ this[kWebSocket] = void 0;
+ this._bufferedBytes = 0;
+ this._buffers = [];
+ this._compressed = false;
+ this._payloadLength = 0;
+ this._mask = void 0;
+ this._fragmented = 0;
+ this._masked = false;
+ this._fin = false;
+ this._opcode = 0;
+ this._totalPayloadLength = 0;
+ this._messageLength = 0;
+ this._fragments = [];
+ this._errored = false;
+ this._loop = false;
+ this._state = GET_INFO;
+ }
+ /**
+ * Implements `Writable.prototype._write()`.
+ *
+ * @param {Buffer} chunk The chunk of data to write
+ * @param {String} encoding The character encoding of `chunk`
+ * @param {Function} cb Callback
+ * @private
+ */
+ _write(chunk, encoding, cb) {
+ if (this._opcode === 8 && this._state == GET_INFO) return cb();
+ this._bufferedBytes += chunk.length;
+ this._buffers.push(chunk);
+ this.startLoop(cb);
+ }
+ /**
+ * Consumes `n` bytes from the buffered data.
+ *
+ * @param {Number} n The number of bytes to consume
+ * @return {Buffer} The consumed bytes
+ * @private
+ */
+ consume(n) {
+ this._bufferedBytes -= n;
+ if (n === this._buffers[0].length) return this._buffers.shift();
+ if (n < this._buffers[0].length) {
+ const buf = this._buffers[0];
+ this._buffers[0] = new FastBuffer(
+ buf.buffer,
+ buf.byteOffset + n,
+ buf.length - n
+ );
+ return new FastBuffer(buf.buffer, buf.byteOffset, n);
+ }
+ const dst = Buffer.allocUnsafe(n);
+ do {
+ const buf = this._buffers[0];
+ const offset = dst.length - n;
+ if (n >= buf.length) {
+ dst.set(this._buffers.shift(), offset);
+ } else {
+ dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);
+ this._buffers[0] = new FastBuffer(
+ buf.buffer,
+ buf.byteOffset + n,
+ buf.length - n
+ );
+ }
+ n -= buf.length;
+ } while (n > 0);
+ return dst;
+ }
+ /**
+ * Starts the parsing loop.
+ *
+ * @param {Function} cb Callback
+ * @private
+ */
+ startLoop(cb) {
+ this._loop = true;
+ do {
+ switch (this._state) {
+ case GET_INFO:
+ this.getInfo(cb);
+ break;
+ case GET_PAYLOAD_LENGTH_16:
+ this.getPayloadLength16(cb);
+ break;
+ case GET_PAYLOAD_LENGTH_64:
+ this.getPayloadLength64(cb);
+ break;
+ case GET_MASK:
+ this.getMask();
+ break;
+ case GET_DATA:
+ this.getData(cb);
+ break;
+ case INFLATING:
+ case DEFER_EVENT:
+ this._loop = false;
+ return;
+ }
+ } while (this._loop);
+ if (!this._errored) cb();
+ }
+ /**
+ * Reads the first two bytes of a frame.
+ *
+ * @param {Function} cb Callback
+ * @private
+ */
+ getInfo(cb) {
+ if (this._bufferedBytes < 2) {
+ this._loop = false;
+ return;
+ }
+ const buf = this.consume(2);
+ if ((buf[0] & 48) !== 0) {
+ const error = this.createError(
+ RangeError,
+ "RSV2 and RSV3 must be clear",
+ true,
+ 1002,
+ "WS_ERR_UNEXPECTED_RSV_2_3"
+ );
+ cb(error);
+ return;
+ }
+ const compressed = (buf[0] & 64) === 64;
+ if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {
+ const error = this.createError(
+ RangeError,
+ "RSV1 must be clear",
+ true,
+ 1002,
+ "WS_ERR_UNEXPECTED_RSV_1"
+ );
+ cb(error);
+ return;
+ }
+ this._fin = (buf[0] & 128) === 128;
+ this._opcode = buf[0] & 15;
+ this._payloadLength = buf[1] & 127;
+ if (this._opcode === 0) {
+ if (compressed) {
+ const error = this.createError(
+ RangeError,
+ "RSV1 must be clear",
+ true,
+ 1002,
+ "WS_ERR_UNEXPECTED_RSV_1"
+ );
+ cb(error);
+ return;
+ }
+ if (!this._fragmented) {
+ const error = this.createError(
+ RangeError,
+ "invalid opcode 0",
+ true,
+ 1002,
+ "WS_ERR_INVALID_OPCODE"
+ );
+ cb(error);
+ return;
+ }
+ this._opcode = this._fragmented;
+ } else if (this._opcode === 1 || this._opcode === 2) {
+ if (this._fragmented) {
+ const error = this.createError(
+ RangeError,
+ `invalid opcode ${this._opcode}`,
+ true,
+ 1002,
+ "WS_ERR_INVALID_OPCODE"
+ );
+ cb(error);
+ return;
+ }
+ this._compressed = compressed;
+ } else if (this._opcode > 7 && this._opcode < 11) {
+ if (!this._fin) {
+ const error = this.createError(
+ RangeError,
+ "FIN must be set",
+ true,
+ 1002,
+ "WS_ERR_EXPECTED_FIN"
+ );
+ cb(error);
+ return;
+ }
+ if (compressed) {
+ const error = this.createError(
+ RangeError,
+ "RSV1 must be clear",
+ true,
+ 1002,
+ "WS_ERR_UNEXPECTED_RSV_1"
+ );
+ cb(error);
+ return;
+ }
+ if (this._payloadLength > 125 || this._opcode === 8 && this._payloadLength === 1) {
+ const error = this.createError(
+ RangeError,
+ `invalid payload length ${this._payloadLength}`,
+ true,
+ 1002,
+ "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH"
+ );
+ cb(error);
+ return;
+ }
+ } else {
+ const error = this.createError(
+ RangeError,
+ `invalid opcode ${this._opcode}`,
+ true,
+ 1002,
+ "WS_ERR_INVALID_OPCODE"
+ );
+ cb(error);
+ return;
+ }
+ if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
+ this._masked = (buf[1] & 128) === 128;
+ if (this._isServer) {
+ if (!this._masked) {
+ const error = this.createError(
+ RangeError,
+ "MASK must be set",
+ true,
+ 1002,
+ "WS_ERR_EXPECTED_MASK"
+ );
+ cb(error);
+ return;
+ }
+ } else if (this._masked) {
+ const error = this.createError(
+ RangeError,
+ "MASK must be clear",
+ true,
+ 1002,
+ "WS_ERR_UNEXPECTED_MASK"
+ );
+ cb(error);
+ return;
+ }
+ if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
+ else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
+ else this.haveLength(cb);
+ }
+ /**
+ * Gets extended payload length (7+16).
+ *
+ * @param {Function} cb Callback
+ * @private
+ */
+ getPayloadLength16(cb) {
+ if (this._bufferedBytes < 2) {
+ this._loop = false;
+ return;
+ }
+ this._payloadLength = this.consume(2).readUInt16BE(0);
+ this.haveLength(cb);
+ }
+ /**
+ * Gets extended payload length (7+64).
+ *
+ * @param {Function} cb Callback
+ * @private
+ */
+ getPayloadLength64(cb) {
+ if (this._bufferedBytes < 8) {
+ this._loop = false;
+ return;
+ }
+ const buf = this.consume(8);
+ const num = buf.readUInt32BE(0);
+ if (num > Math.pow(2, 53 - 32) - 1) {
+ const error = this.createError(
+ RangeError,
+ "Unsupported WebSocket frame: payload length > 2^53 - 1",
+ false,
+ 1009,
+ "WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH"
+ );
+ cb(error);
+ return;
+ }
+ this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
+ this.haveLength(cb);
+ }
+ /**
+ * Payload length has been read.
+ *
+ * @param {Function} cb Callback
+ * @private
+ */
+ haveLength(cb) {
+ if (this._payloadLength && this._opcode < 8) {
+ this._totalPayloadLength += this._payloadLength;
+ if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
+ const error = this.createError(
+ RangeError,
+ "Max payload size exceeded",
+ false,
+ 1009,
+ "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"
+ );
+ cb(error);
+ return;
+ }
+ }
+ if (this._masked) this._state = GET_MASK;
+ else this._state = GET_DATA;
+ }
+ /**
+ * Reads mask bytes.
+ *
+ * @private
+ */
+ getMask() {
+ if (this._bufferedBytes < 4) {
+ this._loop = false;
+ return;
+ }
+ this._mask = this.consume(4);
+ this._state = GET_DATA;
+ }
+ /**
+ * Reads data bytes.
+ *
+ * @param {Function} cb Callback
+ * @private
+ */
+ getData(cb) {
+ let data = EMPTY_BUFFER2;
+ if (this._payloadLength) {
+ if (this._bufferedBytes < this._payloadLength) {
+ this._loop = false;
+ return;
+ }
+ data = this.consume(this._payloadLength);
+ if (this._masked && (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0) {
+ unmask(data, this._mask);
+ }
+ }
+ if (this._opcode > 7) {
+ this.controlMessage(data, cb);
+ return;
+ }
+ if (this._compressed) {
+ this._state = INFLATING;
+ this.decompress(data, cb);
+ return;
+ }
+ if (data.length) {
+ this._messageLength = this._totalPayloadLength;
+ this._fragments.push(data);
+ }
+ this.dataMessage(cb);
+ }
+ /**
+ * Decompresses data.
+ *
+ * @param {Buffer} data Compressed data
+ * @param {Function} cb Callback
+ * @private
+ */
+ decompress(data, cb) {
+ const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
+ perMessageDeflate.decompress(data, this._fin, (err, buf) => {
+ if (err) return cb(err);
+ if (buf.length) {
+ this._messageLength += buf.length;
+ if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
+ const error = this.createError(
+ RangeError,
+ "Max payload size exceeded",
+ false,
+ 1009,
+ "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"
+ );
+ cb(error);
+ return;
+ }
+ this._fragments.push(buf);
+ }
+ this.dataMessage(cb);
+ if (this._state === GET_INFO) this.startLoop(cb);
+ });
+ }
+ /**
+ * Handles a data message.
+ *
+ * @param {Function} cb Callback
+ * @private
+ */
+ dataMessage(cb) {
+ if (!this._fin) {
+ this._state = GET_INFO;
+ return;
+ }
+ const messageLength = this._messageLength;
+ const fragments = this._fragments;
+ this._totalPayloadLength = 0;
+ this._messageLength = 0;
+ this._fragmented = 0;
+ this._fragments = [];
+ if (this._opcode === 2) {
+ let data;
+ if (this._binaryType === "nodebuffer") {
+ data = concat(fragments, messageLength);
+ } else if (this._binaryType === "arraybuffer") {
+ data = toArrayBuffer(concat(fragments, messageLength));
+ } else if (this._binaryType === "blob") {
+ data = new Blob(fragments);
+ } else {
+ data = fragments;
+ }
+ if (this._allowSynchronousEvents) {
+ this.emit("message", data, true);
+ this._state = GET_INFO;
+ } else {
+ this._state = DEFER_EVENT;
+ setImmediate(() => {
+ this.emit("message", data, true);
+ this._state = GET_INFO;
+ this.startLoop(cb);
+ });
+ }
+ } else {
+ const buf = concat(fragments, messageLength);
+ if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
+ const error = this.createError(
+ Error,
+ "invalid UTF-8 sequence",
+ true,
+ 1007,
+ "WS_ERR_INVALID_UTF8"
+ );
+ cb(error);
+ return;
+ }
+ if (this._state === INFLATING || this._allowSynchronousEvents) {
+ this.emit("message", buf, false);
+ this._state = GET_INFO;
+ } else {
+ this._state = DEFER_EVENT;
+ setImmediate(() => {
+ this.emit("message", buf, false);
+ this._state = GET_INFO;
+ this.startLoop(cb);
+ });
+ }
+ }
+ }
+ /**
+ * Handles a control message.
+ *
+ * @param {Buffer} data Data to handle
+ * @return {(Error|RangeError|undefined)} A possible error
+ * @private
+ */
+ controlMessage(data, cb) {
+ if (this._opcode === 8) {
+ if (data.length === 0) {
+ this._loop = false;
+ this.emit("conclude", 1005, EMPTY_BUFFER2);
+ this.end();
+ } else {
+ const code = data.readUInt16BE(0);
+ if (!isValidStatusCode(code)) {
+ const error = this.createError(
+ RangeError,
+ `invalid status code ${code}`,
+ true,
+ 1002,
+ "WS_ERR_INVALID_CLOSE_CODE"
+ );
+ cb(error);
+ return;
+ }
+ const buf = new FastBuffer(
+ data.buffer,
+ data.byteOffset + 2,
+ data.length - 2
+ );
+ if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
+ const error = this.createError(
+ Error,
+ "invalid UTF-8 sequence",
+ true,
+ 1007,
+ "WS_ERR_INVALID_UTF8"
+ );
+ cb(error);
+ return;
+ }
+ this._loop = false;
+ this.emit("conclude", code, buf);
+ this.end();
+ }
+ this._state = GET_INFO;
+ return;
+ }
+ if (this._allowSynchronousEvents) {
+ this.emit(this._opcode === 9 ? "ping" : "pong", data);
+ this._state = GET_INFO;
+ } else {
+ this._state = DEFER_EVENT;
+ setImmediate(() => {
+ this.emit(this._opcode === 9 ? "ping" : "pong", data);
+ this._state = GET_INFO;
+ this.startLoop(cb);
+ });
+ }
+ }
+ /**
+ * Builds an error object.
+ *
+ * @param {function(new:Error|RangeError)} ErrorCtor The error constructor
+ * @param {String} message The error message
+ * @param {Boolean} prefix Specifies whether or not to add a default prefix to
+ * `message`
+ * @param {Number} statusCode The status code
+ * @param {String} errorCode The exposed error code
+ * @return {(Error|RangeError)} The error
+ * @private
+ */
+ createError(ErrorCtor, message, prefix, statusCode, errorCode) {
+ this._loop = false;
+ this._errored = true;
+ const err = new ErrorCtor(
+ prefix ? `Invalid WebSocket frame: ${message}` : message
+ );
+ Error.captureStackTrace(err, this.createError);
+ err.code = errorCode;
+ err[kStatusCode] = statusCode;
+ return err;
+ }
+ };
+ module2.exports = Receiver2;
+ }
+});
+
+// node_modules/ws/lib/sender.js
+var require_sender = __commonJS({
+ "node_modules/ws/lib/sender.js"(exports2, module2) {
+ "use strict";
+ var { Duplex } = require("stream");
+ var { randomFillSync } = require("crypto");
+ var PerMessageDeflate = require_permessage_deflate();
+ var { EMPTY_BUFFER: EMPTY_BUFFER2, kWebSocket, NOOP } = require_constants();
+ var { isBlob, isValidStatusCode } = require_validation();
+ var { mask: applyMask, toBuffer } = require_buffer_util();
+ var kByteLength = Symbol("kByteLength");
+ var maskBuffer = Buffer.alloc(4);
+ var RANDOM_POOL_SIZE = 8 * 1024;
+ var randomPool;
+ var randomPoolPointer = RANDOM_POOL_SIZE;
+ var DEFAULT = 0;
+ var DEFLATING = 1;
+ var GET_BLOB_DATA = 2;
+ var Sender2 = class _Sender {
+ /**
+ * Creates a Sender instance.
+ *
+ * @param {Duplex} socket The connection socket
+ * @param {Object} [extensions] An object containing the negotiated extensions
+ * @param {Function} [generateMask] The function used to generate the masking
+ * key
+ */
+ constructor(socket, extensions, generateMask) {
+ this._extensions = extensions || {};
+ if (generateMask) {
+ this._generateMask = generateMask;
+ this._maskBuffer = Buffer.alloc(4);
+ }
+ this._socket = socket;
+ this._firstFragment = true;
+ this._compress = false;
+ this._bufferedBytes = 0;
+ this._queue = [];
+ this._state = DEFAULT;
+ this.onerror = NOOP;
+ this[kWebSocket] = void 0;
+ }
+ /**
+ * Frames a piece of data according to the HyBi WebSocket protocol.
+ *
+ * @param {(Buffer|String)} data The data to frame
+ * @param {Object} options Options object
+ * @param {Boolean} [options.fin=false] Specifies whether or not to set the
+ * FIN bit
+ * @param {Function} [options.generateMask] The function used to generate the
+ * masking key
+ * @param {Boolean} [options.mask=false] Specifies whether or not to mask
+ * `data`
+ * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
+ * key
+ * @param {Number} options.opcode The opcode
+ * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
+ * modified
+ * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
+ * RSV1 bit
+ * @return {(Buffer|String)[]} The framed data
+ * @public
+ */
+ static frame(data, options) {
+ let mask;
+ let merge = false;
+ let offset = 2;
+ let skipMasking = false;
+ if (options.mask) {
+ mask = options.maskBuffer || maskBuffer;
+ if (options.generateMask) {
+ options.generateMask(mask);
+ } else {
+ if (randomPoolPointer === RANDOM_POOL_SIZE) {
+ if (randomPool === void 0) {
+ randomPool = Buffer.alloc(RANDOM_POOL_SIZE);
+ }
+ randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);
+ randomPoolPointer = 0;
+ }
+ mask[0] = randomPool[randomPoolPointer++];
+ mask[1] = randomPool[randomPoolPointer++];
+ mask[2] = randomPool[randomPoolPointer++];
+ mask[3] = randomPool[randomPoolPointer++];
+ }
+ skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;
+ offset = 6;
+ }
+ let dataLength;
+ if (typeof data === "string") {
+ if ((!options.mask || skipMasking) && options[kByteLength] !== void 0) {
+ dataLength = options[kByteLength];
+ } else {
+ data = Buffer.from(data);
+ dataLength = data.length;
+ }
+ } else {
+ dataLength = data.length;
+ merge = options.mask && options.readOnly && !skipMasking;
+ }
+ let payloadLength = dataLength;
+ if (dataLength >= 65536) {
+ offset += 8;
+ payloadLength = 127;
+ } else if (dataLength > 125) {
+ offset += 2;
+ payloadLength = 126;
+ }
+ const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);
+ target[0] = options.fin ? options.opcode | 128 : options.opcode;
+ if (options.rsv1) target[0] |= 64;
+ target[1] = payloadLength;
+ if (payloadLength === 126) {
+ target.writeUInt16BE(dataLength, 2);
+ } else if (payloadLength === 127) {
+ target[2] = target[3] = 0;
+ target.writeUIntBE(dataLength, 4, 6);
+ }
+ if (!options.mask) return [target, data];
+ target[1] |= 128;
+ target[offset - 4] = mask[0];
+ target[offset - 3] = mask[1];
+ target[offset - 2] = mask[2];
+ target[offset - 1] = mask[3];
+ if (skipMasking) return [target, data];
+ if (merge) {
+ applyMask(data, mask, target, offset, dataLength);
+ return [target];
+ }
+ applyMask(data, mask, data, 0, dataLength);
+ return [target, data];
+ }
+ /**
+ * Sends a close message to the other peer.
+ *
+ * @param {Number} [code] The status code component of the body
+ * @param {(String|Buffer)} [data] The message component of the body
+ * @param {Boolean} [mask=false] Specifies whether or not to mask the message
+ * @param {Function} [cb] Callback
+ * @public
+ */
+ close(code, data, mask, cb) {
+ let buf;
+ if (code === void 0) {
+ buf = EMPTY_BUFFER2;
+ } else if (typeof code !== "number" || !isValidStatusCode(code)) {
+ throw new TypeError("First argument must be a valid error code number");
+ } else if (data === void 0 || !data.length) {
+ buf = Buffer.allocUnsafe(2);
+ buf.writeUInt16BE(code, 0);
+ } else {
+ const length = Buffer.byteLength(data);
+ if (length > 123) {
+ throw new RangeError("The message must not be greater than 123 bytes");
+ }
+ buf = Buffer.allocUnsafe(2 + length);
+ buf.writeUInt16BE(code, 0);
+ if (typeof data === "string") {
+ buf.write(data, 2);
+ } else {
+ buf.set(data, 2);
+ }
+ }
+ const options = {
+ [kByteLength]: buf.length,
+ fin: true,
+ generateMask: this._generateMask,
+ mask,
+ maskBuffer: this._maskBuffer,
+ opcode: 8,
+ readOnly: false,
+ rsv1: false
+ };
+ if (this._state !== DEFAULT) {
+ this.enqueue([this.dispatch, buf, false, options, cb]);
+ } else {
+ this.sendFrame(_Sender.frame(buf, options), cb);
+ }
+ }
+ /**
+ * Sends a ping message to the other peer.
+ *
+ * @param {*} data The message to send
+ * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
+ * @param {Function} [cb] Callback
+ * @public
+ */
+ ping(data, mask, cb) {
+ let byteLength;
+ let readOnly;
+ if (typeof data === "string") {
+ byteLength = Buffer.byteLength(data);
+ readOnly = false;
+ } else if (isBlob(data)) {
+ byteLength = data.size;
+ readOnly = false;
+ } else {
+ data = toBuffer(data);
+ byteLength = data.length;
+ readOnly = toBuffer.readOnly;
+ }
+ if (byteLength > 125) {
+ throw new RangeError("The data size must not be greater than 125 bytes");
+ }
+ const options = {
+ [kByteLength]: byteLength,
+ fin: true,
+ generateMask: this._generateMask,
+ mask,
+ maskBuffer: this._maskBuffer,
+ opcode: 9,
+ readOnly,
+ rsv1: false
+ };
+ if (isBlob(data)) {
+ if (this._state !== DEFAULT) {
+ this.enqueue([this.getBlobData, data, false, options, cb]);
+ } else {
+ this.getBlobData(data, false, options, cb);
+ }
+ } else if (this._state !== DEFAULT) {
+ this.enqueue([this.dispatch, data, false, options, cb]);
+ } else {
+ this.sendFrame(_Sender.frame(data, options), cb);
+ }
+ }
+ /**
+ * Sends a pong message to the other peer.
+ *
+ * @param {*} data The message to send
+ * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
+ * @param {Function} [cb] Callback
+ * @public
+ */
+ pong(data, mask, cb) {
+ let byteLength;
+ let readOnly;
+ if (typeof data === "string") {
+ byteLength = Buffer.byteLength(data);
+ readOnly = false;
+ } else if (isBlob(data)) {
+ byteLength = data.size;
+ readOnly = false;
+ } else {
+ data = toBuffer(data);
+ byteLength = data.length;
+ readOnly = toBuffer.readOnly;
+ }
+ if (byteLength > 125) {
+ throw new RangeError("The data size must not be greater than 125 bytes");
+ }
+ const options = {
+ [kByteLength]: byteLength,
+ fin: true,
+ generateMask: this._generateMask,
+ mask,
+ maskBuffer: this._maskBuffer,
+ opcode: 10,
+ readOnly,
+ rsv1: false
+ };
+ if (isBlob(data)) {
+ if (this._state !== DEFAULT) {
+ this.enqueue([this.getBlobData, data, false, options, cb]);
+ } else {
+ this.getBlobData(data, false, options, cb);
+ }
+ } else if (this._state !== DEFAULT) {
+ this.enqueue([this.dispatch, data, false, options, cb]);
+ } else {
+ this.sendFrame(_Sender.frame(data, options), cb);
+ }
+ }
+ /**
+ * Sends a data message to the other peer.
+ *
+ * @param {*} data The message to send
+ * @param {Object} options Options object
+ * @param {Boolean} [options.binary=false] Specifies whether `data` is binary
+ * or text
+ * @param {Boolean} [options.compress=false] Specifies whether or not to
+ * compress `data`
+ * @param {Boolean} [options.fin=false] Specifies whether the fragment is the
+ * last one
+ * @param {Boolean} [options.mask=false] Specifies whether or not to mask
+ * `data`
+ * @param {Function} [cb] Callback
+ * @public
+ */
+ send(data, options, cb) {
+ const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
+ let opcode = options.binary ? 2 : 1;
+ let rsv1 = options.compress;
+ let byteLength;
+ let readOnly;
+ if (typeof data === "string") {
+ byteLength = Buffer.byteLength(data);
+ readOnly = false;
+ } else if (isBlob(data)) {
+ byteLength = data.size;
+ readOnly = false;
+ } else {
+ data = toBuffer(data);
+ byteLength = data.length;
+ readOnly = toBuffer.readOnly;
+ }
+ if (this._firstFragment) {
+ this._firstFragment = false;
+ if (rsv1 && perMessageDeflate && perMessageDeflate.params[perMessageDeflate._isServer ? "server_no_context_takeover" : "client_no_context_takeover"]) {
+ rsv1 = byteLength >= perMessageDeflate._threshold;
+ }
+ this._compress = rsv1;
+ } else {
+ rsv1 = false;
+ opcode = 0;
+ }
+ if (options.fin) this._firstFragment = true;
+ const opts = {
+ [kByteLength]: byteLength,
+ fin: options.fin,
+ generateMask: this._generateMask,
+ mask: options.mask,
+ maskBuffer: this._maskBuffer,
+ opcode,
+ readOnly,
+ rsv1
+ };
+ if (isBlob(data)) {
+ if (this._state !== DEFAULT) {
+ this.enqueue([this.getBlobData, data, this._compress, opts, cb]);
+ } else {
+ this.getBlobData(data, this._compress, opts, cb);
+ }
+ } else if (this._state !== DEFAULT) {
+ this.enqueue([this.dispatch, data, this._compress, opts, cb]);
+ } else {
+ this.dispatch(data, this._compress, opts, cb);
+ }
+ }
+ /**
+ * Gets the contents of a blob as binary data.
+ *
+ * @param {Blob} blob The blob
+ * @param {Boolean} [compress=false] Specifies whether or not to compress
+ * the data
+ * @param {Object} options Options object
+ * @param {Boolean} [options.fin=false] Specifies whether or not to set the
+ * FIN bit
+ * @param {Function} [options.generateMask] The function used to generate the
+ * masking key
+ * @param {Boolean} [options.mask=false] Specifies whether or not to mask
+ * `data`
+ * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
+ * key
+ * @param {Number} options.opcode The opcode
+ * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
+ * modified
+ * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
+ * RSV1 bit
+ * @param {Function} [cb] Callback
+ * @private
+ */
+ getBlobData(blob, compress, options, cb) {
+ this._bufferedBytes += options[kByteLength];
+ this._state = GET_BLOB_DATA;
+ blob.arrayBuffer().then((arrayBuffer) => {
+ if (this._socket.destroyed) {
+ const err = new Error(
+ "The socket was closed while the blob was being read"
+ );
+ process.nextTick(callCallbacks, this, err, cb);
+ return;
+ }
+ this._bufferedBytes -= options[kByteLength];
+ const data = toBuffer(arrayBuffer);
+ if (!compress) {
+ this._state = DEFAULT;
+ this.sendFrame(_Sender.frame(data, options), cb);
+ this.dequeue();
+ } else {
+ this.dispatch(data, compress, options, cb);
+ }
+ }).catch((err) => {
+ process.nextTick(onError, this, err, cb);
+ });
+ }
+ /**
+ * Dispatches a message.
+ *
+ * @param {(Buffer|String)} data The message to send
+ * @param {Boolean} [compress=false] Specifies whether or not to compress
+ * `data`
+ * @param {Object} options Options object
+ * @param {Boolean} [options.fin=false] Specifies whether or not to set the
+ * FIN bit
+ * @param {Function} [options.generateMask] The function used to generate the
+ * masking key
+ * @param {Boolean} [options.mask=false] Specifies whether or not to mask
+ * `data`
+ * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
+ * key
+ * @param {Number} options.opcode The opcode
+ * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
+ * modified
+ * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
+ * RSV1 bit
+ * @param {Function} [cb] Callback
+ * @private
+ */
+ dispatch(data, compress, options, cb) {
+ if (!compress) {
+ this.sendFrame(_Sender.frame(data, options), cb);
+ return;
+ }
+ const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
+ this._bufferedBytes += options[kByteLength];
+ this._state = DEFLATING;
+ perMessageDeflate.compress(data, options.fin, (_, buf) => {
+ if (this._socket.destroyed) {
+ const err = new Error(
+ "The socket was closed while data was being compressed"
+ );
+ callCallbacks(this, err, cb);
+ return;
+ }
+ this._bufferedBytes -= options[kByteLength];
+ this._state = DEFAULT;
+ options.readOnly = false;
+ this.sendFrame(_Sender.frame(buf, options), cb);
+ this.dequeue();
+ });
+ }
+ /**
+ * Executes queued send operations.
+ *
+ * @private
+ */
+ dequeue() {
+ while (this._state === DEFAULT && this._queue.length) {
+ const params = this._queue.shift();
+ this._bufferedBytes -= params[3][kByteLength];
+ Reflect.apply(params[0], this, params.slice(1));
+ }
+ }
+ /**
+ * Enqueues a send operation.
+ *
+ * @param {Array} params Send operation parameters.
+ * @private
+ */
+ enqueue(params) {
+ this._bufferedBytes += params[3][kByteLength];
+ this._queue.push(params);
+ }
+ /**
+ * Sends a frame.
+ *
+ * @param {(Buffer | String)[]} list The frame to send
+ * @param {Function} [cb] Callback
+ * @private
+ */
+ sendFrame(list, cb) {
+ if (list.length === 2) {
+ this._socket.cork();
+ this._socket.write(list[0]);
+ this._socket.write(list[1], cb);
+ this._socket.uncork();
+ } else {
+ this._socket.write(list[0], cb);
+ }
+ }
+ };
+ module2.exports = Sender2;
+ function callCallbacks(sender, err, cb) {
+ if (typeof cb === "function") cb(err);
+ for (let i3 = 0; i3 < sender._queue.length; i3++) {
+ const params = sender._queue[i3];
+ const callback = params[params.length - 1];
+ if (typeof callback === "function") callback(err);
+ }
+ }
+ function onError(sender, err, cb) {
+ callCallbacks(sender, err, cb);
+ sender.onerror(err);
+ }
+ }
+});
+
+// node_modules/ws/lib/event-target.js
+var require_event_target = __commonJS({
+ "node_modules/ws/lib/event-target.js"(exports2, module2) {
+ "use strict";
+ var { kForOnEventAttribute, kListener } = require_constants();
+ var kCode = Symbol("kCode");
+ var kData = Symbol("kData");
+ var kError = Symbol("kError");
+ var kMessage = Symbol("kMessage");
+ var kReason = Symbol("kReason");
+ var kTarget = Symbol("kTarget");
+ var kType = Symbol("kType");
+ var kWasClean = Symbol("kWasClean");
+ var Event = class {
+ /**
+ * Create a new `Event`.
+ *
+ * @param {String} type The name of the event
+ * @throws {TypeError} If the `type` argument is not specified
+ */
+ constructor(type) {
+ this[kTarget] = null;
+ this[kType] = type;
+ }
+ /**
+ * @type {*}
+ */
+ get target() {
+ return this[kTarget];
+ }
+ /**
+ * @type {String}
+ */
+ get type() {
+ return this[kType];
+ }
+ };
+ Object.defineProperty(Event.prototype, "target", { enumerable: true });
+ Object.defineProperty(Event.prototype, "type", { enumerable: true });
+ var CloseEvent = class extends Event {
+ /**
+ * Create a new `CloseEvent`.
+ *
+ * @param {String} type The name of the event
+ * @param {Object} [options] A dictionary object that allows for setting
+ * attributes via object members of the same name
+ * @param {Number} [options.code=0] The status code explaining why the
+ * connection was closed
+ * @param {String} [options.reason=''] A human-readable string explaining why
+ * the connection was closed
+ * @param {Boolean} [options.wasClean=false] Indicates whether or not the
+ * connection was cleanly closed
+ */
+ constructor(type, options = {}) {
+ super(type);
+ this[kCode] = options.code === void 0 ? 0 : options.code;
+ this[kReason] = options.reason === void 0 ? "" : options.reason;
+ this[kWasClean] = options.wasClean === void 0 ? false : options.wasClean;
+ }
+ /**
+ * @type {Number}
+ */
+ get code() {
+ return this[kCode];
+ }
+ /**
+ * @type {String}
+ */
+ get reason() {
+ return this[kReason];
+ }
+ /**
+ * @type {Boolean}
+ */
+ get wasClean() {
+ return this[kWasClean];
+ }
+ };
+ Object.defineProperty(CloseEvent.prototype, "code", { enumerable: true });
+ Object.defineProperty(CloseEvent.prototype, "reason", { enumerable: true });
+ Object.defineProperty(CloseEvent.prototype, "wasClean", { enumerable: true });
+ var ErrorEvent = class extends Event {
+ /**
+ * Create a new `ErrorEvent`.
+ *
+ * @param {String} type The name of the event
+ * @param {Object} [options] A dictionary object that allows for setting
+ * attributes via object members of the same name
+ * @param {*} [options.error=null] The error that generated this event
+ * @param {String} [options.message=''] The error message
+ */
+ constructor(type, options = {}) {
+ super(type);
+ this[kError] = options.error === void 0 ? null : options.error;
+ this[kMessage] = options.message === void 0 ? "" : options.message;
+ }
+ /**
+ * @type {*}
+ */
+ get error() {
+ return this[kError];
+ }
+ /**
+ * @type {String}
+ */
+ get message() {
+ return this[kMessage];
+ }
+ };
+ Object.defineProperty(ErrorEvent.prototype, "error", { enumerable: true });
+ Object.defineProperty(ErrorEvent.prototype, "message", { enumerable: true });
+ var MessageEvent = class extends Event {
+ /**
+ * Create a new `MessageEvent`.
+ *
+ * @param {String} type The name of the event
+ * @param {Object} [options] A dictionary object that allows for setting
+ * attributes via object members of the same name
+ * @param {*} [options.data=null] The message content
+ */
+ constructor(type, options = {}) {
+ super(type);
+ this[kData] = options.data === void 0 ? null : options.data;
+ }
+ /**
+ * @type {*}
+ */
+ get data() {
+ return this[kData];
+ }
+ };
+ Object.defineProperty(MessageEvent.prototype, "data", { enumerable: true });
+ var EventTarget = {
+ /**
+ * Register an event listener.
+ *
+ * @param {String} type A string representing the event type to listen for
+ * @param {(Function|Object)} handler The listener to add
+ * @param {Object} [options] An options object specifies characteristics about
+ * the event listener
+ * @param {Boolean} [options.once=false] A `Boolean` indicating that the
+ * listener should be invoked at most once after being added. If `true`,
+ * the listener would be automatically removed when invoked.
+ * @public
+ */
+ addEventListener(type, handler, options = {}) {
+ for (const listener of this.listeners(type)) {
+ if (!options[kForOnEventAttribute] && listener[kListener] === handler && !listener[kForOnEventAttribute]) {
+ return;
+ }
+ }
+ let wrapper;
+ if (type === "message") {
+ wrapper = function onMessage(data, isBinary) {
+ const event = new MessageEvent("message", {
+ data: isBinary ? data : data.toString()
+ });
+ event[kTarget] = this;
+ callListener(handler, this, event);
+ };
+ } else if (type === "close") {
+ wrapper = function onClose(code, message) {
+ const event = new CloseEvent("close", {
+ code,
+ reason: message.toString(),
+ wasClean: this._closeFrameReceived && this._closeFrameSent
+ });
+ event[kTarget] = this;
+ callListener(handler, this, event);
+ };
+ } else if (type === "error") {
+ wrapper = function onError(error) {
+ const event = new ErrorEvent("error", {
+ error,
+ message: error.message
+ });
+ event[kTarget] = this;
+ callListener(handler, this, event);
+ };
+ } else if (type === "open") {
+ wrapper = function onOpen() {
+ const event = new Event("open");
+ event[kTarget] = this;
+ callListener(handler, this, event);
+ };
+ } else {
+ return;
+ }
+ wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];
+ wrapper[kListener] = handler;
+ if (options.once) {
+ this.once(type, wrapper);
+ } else {
+ this.on(type, wrapper);
+ }
+ },
+ /**
+ * Remove an event listener.
+ *
+ * @param {String} type A string representing the event type to remove
+ * @param {(Function|Object)} handler The listener to remove
+ * @public
+ */
+ removeEventListener(type, handler) {
+ for (const listener of this.listeners(type)) {
+ if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {
+ this.removeListener(type, listener);
+ break;
+ }
+ }
+ }
+ };
+ module2.exports = {
+ CloseEvent,
+ ErrorEvent,
+ Event,
+ EventTarget,
+ MessageEvent
+ };
+ function callListener(listener, thisArg, event) {
+ if (typeof listener === "object" && listener.handleEvent) {
+ listener.handleEvent.call(listener, event);
+ } else {
+ listener.call(thisArg, event);
+ }
+ }
+ }
+});
+
+// node_modules/ws/lib/extension.js
+var require_extension = __commonJS({
+ "node_modules/ws/lib/extension.js"(exports2, module2) {
+ "use strict";
+ var { tokenChars } = require_validation();
+ function push(dest, name, elem) {
+ if (dest[name] === void 0) dest[name] = [elem];
+ else dest[name].push(elem);
+ }
+ function parse4(header) {
+ const offers = /* @__PURE__ */ Object.create(null);
+ let params = /* @__PURE__ */ Object.create(null);
+ let mustUnescape = false;
+ let isEscaping = false;
+ let inQuotes = false;
+ let extensionName;
+ let paramName;
+ let start = -1;
+ let code = -1;
+ let end = -1;
+ let i3 = 0;
+ for (; i3 < header.length; i3++) {
+ code = header.charCodeAt(i3);
+ if (extensionName === void 0) {
+ if (end === -1 && tokenChars[code] === 1) {
+ if (start === -1) start = i3;
+ } else if (i3 !== 0 && (code === 32 || code === 9)) {
+ if (end === -1 && start !== -1) end = i3;
+ } else if (code === 59 || code === 44) {
+ if (start === -1) {
+ throw new SyntaxError(`Unexpected character at index ${i3}`);
+ }
+ if (end === -1) end = i3;
+ const name = header.slice(start, end);
+ if (code === 44) {
+ push(offers, name, params);
+ params = /* @__PURE__ */ Object.create(null);
+ } else {
+ extensionName = name;
+ }
+ start = end = -1;
+ } else {
+ throw new SyntaxError(`Unexpected character at index ${i3}`);
+ }
+ } else if (paramName === void 0) {
+ if (end === -1 && tokenChars[code] === 1) {
+ if (start === -1) start = i3;
+ } else if (code === 32 || code === 9) {
+ if (end === -1 && start !== -1) end = i3;
+ } else if (code === 59 || code === 44) {
+ if (start === -1) {
+ throw new SyntaxError(`Unexpected character at index ${i3}`);
+ }
+ if (end === -1) end = i3;
+ push(params, header.slice(start, end), true);
+ if (code === 44) {
+ push(offers, extensionName, params);
+ params = /* @__PURE__ */ Object.create(null);
+ extensionName = void 0;
+ }
+ start = end = -1;
+ } else if (code === 61 && start !== -1 && end === -1) {
+ paramName = header.slice(start, i3);
+ start = end = -1;
+ } else {
+ throw new SyntaxError(`Unexpected character at index ${i3}`);
+ }
+ } else {
+ if (isEscaping) {
+ if (tokenChars[code] !== 1) {
+ throw new SyntaxError(`Unexpected character at index ${i3}`);
+ }
+ if (start === -1) start = i3;
+ else if (!mustUnescape) mustUnescape = true;
+ isEscaping = false;
+ } else if (inQuotes) {
+ if (tokenChars[code] === 1) {
+ if (start === -1) start = i3;
+ } else if (code === 34 && start !== -1) {
+ inQuotes = false;
+ end = i3;
+ } else if (code === 92) {
+ isEscaping = true;
+ } else {
+ throw new SyntaxError(`Unexpected character at index ${i3}`);
+ }
+ } else if (code === 34 && header.charCodeAt(i3 - 1) === 61) {
+ inQuotes = true;
+ } else if (end === -1 && tokenChars[code] === 1) {
+ if (start === -1) start = i3;
+ } else if (start !== -1 && (code === 32 || code === 9)) {
+ if (end === -1) end = i3;
+ } else if (code === 59 || code === 44) {
+ if (start === -1) {
+ throw new SyntaxError(`Unexpected character at index ${i3}`);
+ }
+ if (end === -1) end = i3;
+ let value = header.slice(start, end);
+ if (mustUnescape) {
+ value = value.replace(/\\/g, "");
+ mustUnescape = false;
+ }
+ push(params, paramName, value);
+ if (code === 44) {
+ push(offers, extensionName, params);
+ params = /* @__PURE__ */ Object.create(null);
+ extensionName = void 0;
+ }
+ paramName = void 0;
+ start = end = -1;
+ } else {
+ throw new SyntaxError(`Unexpected character at index ${i3}`);
+ }
+ }
+ }
+ if (start === -1 || inQuotes || code === 32 || code === 9) {
+ throw new SyntaxError("Unexpected end of input");
+ }
+ if (end === -1) end = i3;
+ const token = header.slice(start, end);
+ if (extensionName === void 0) {
+ push(offers, token, params);
+ } else {
+ if (paramName === void 0) {
+ push(params, token, true);
+ } else if (mustUnescape) {
+ push(params, paramName, token.replace(/\\/g, ""));
+ } else {
+ push(params, paramName, token);
+ }
+ push(offers, extensionName, params);
+ }
+ return offers;
+ }
+ function format(extensions) {
+ return Object.keys(extensions).map((extension) => {
+ let configurations = extensions[extension];
+ if (!Array.isArray(configurations)) configurations = [configurations];
+ return configurations.map((params) => {
+ return [extension].concat(
+ Object.keys(params).map((k) => {
+ let values = params[k];
+ if (!Array.isArray(values)) values = [values];
+ return values.map((v) => v === true ? k : `${k}=${v}`).join("; ");
+ })
+ ).join("; ");
+ }).join(", ");
+ }).join(", ");
+ }
+ module2.exports = { format, parse: parse4 };
+ }
+});
+
+// node_modules/ws/lib/websocket.js
+var require_websocket = __commonJS({
+ "node_modules/ws/lib/websocket.js"(exports2, module2) {
+ "use strict";
+ var EventEmitter = require("events");
+ var https = require("https");
+ var http = require("http");
+ var net = require("net");
+ var tls = require("tls");
+ var { randomBytes: randomBytes3, createHash } = require("crypto");
+ var { Duplex, Readable } = require("stream");
+ var { URL: URL2 } = require("url");
+ var PerMessageDeflate = require_permessage_deflate();
+ var Receiver2 = require_receiver();
+ var Sender2 = require_sender();
+ var { isBlob } = require_validation();
+ var {
+ BINARY_TYPES,
+ EMPTY_BUFFER: EMPTY_BUFFER2,
+ GUID,
+ kForOnEventAttribute,
+ kListener,
+ kStatusCode,
+ kWebSocket,
+ NOOP
+ } = require_constants();
+ var {
+ EventTarget: { addEventListener, removeEventListener }
+ } = require_event_target();
+ var { format, parse: parse4 } = require_extension();
+ var { toBuffer } = require_buffer_util();
+ var closeTimeout = 30 * 1e3;
+ var kAborted = Symbol("kAborted");
+ var protocolVersions = [8, 13];
+ var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
+ var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
+ var WebSocket3 = class _WebSocket4 extends EventEmitter {
+ /**
+ * Create a new `WebSocket`.
+ *
+ * @param {(String|URL)} address The URL to which to connect
+ * @param {(String|String[])} [protocols] The subprotocols
+ * @param {Object} [options] Connection options
+ */
+ constructor(address, protocols, options) {
+ super();
+ this._binaryType = BINARY_TYPES[0];
+ this._closeCode = 1006;
+ this._closeFrameReceived = false;
+ this._closeFrameSent = false;
+ this._closeMessage = EMPTY_BUFFER2;
+ this._closeTimer = null;
+ this._errorEmitted = false;
+ this._extensions = {};
+ this._paused = false;
+ this._protocol = "";
+ this._readyState = _WebSocket4.CONNECTING;
+ this._receiver = null;
+ this._sender = null;
+ this._socket = null;
+ if (address !== null) {
+ this._bufferedAmount = 0;
+ this._isServer = false;
+ this._redirects = 0;
+ if (protocols === void 0) {
+ protocols = [];
+ } else if (!Array.isArray(protocols)) {
+ if (typeof protocols === "object" && protocols !== null) {
+ options = protocols;
+ protocols = [];
+ } else {
+ protocols = [protocols];
+ }
+ }
+ initAsClient(this, address, protocols, options);
+ } else {
+ this._autoPong = options.autoPong;
+ this._isServer = true;
+ }
+ }
+ /**
+ * For historical reasons, the custom "nodebuffer" type is used by the default
+ * instead of "blob".
+ *
+ * @type {String}
+ */
+ get binaryType() {
+ return this._binaryType;
+ }
+ set binaryType(type) {
+ if (!BINARY_TYPES.includes(type)) return;
+ this._binaryType = type;
+ if (this._receiver) this._receiver._binaryType = type;
+ }
+ /**
+ * @type {Number}
+ */
+ get bufferedAmount() {
+ if (!this._socket) return this._bufferedAmount;
+ return this._socket._writableState.length + this._sender._bufferedBytes;
+ }
+ /**
+ * @type {String}
+ */
+ get extensions() {
+ return Object.keys(this._extensions).join();
+ }
+ /**
+ * @type {Boolean}
+ */
+ get isPaused() {
+ return this._paused;
+ }
+ /**
+ * @type {Function}
+ */
+ /* istanbul ignore next */
+ get onclose() {
+ return null;
+ }
+ /**
+ * @type {Function}
+ */
+ /* istanbul ignore next */
+ get onerror() {
+ return null;
+ }
+ /**
+ * @type {Function}
+ */
+ /* istanbul ignore next */
+ get onopen() {
+ return null;
+ }
+ /**
+ * @type {Function}
+ */
+ /* istanbul ignore next */
+ get onmessage() {
+ return null;
+ }
+ /**
+ * @type {String}
+ */
+ get protocol() {
+ return this._protocol;
+ }
+ /**
+ * @type {Number}
+ */
+ get readyState() {
+ return this._readyState;
+ }
+ /**
+ * @type {String}
+ */
+ get url() {
+ return this._url;
+ }
+ /**
+ * Set up the socket and the internal resources.
+ *
+ * @param {Duplex} socket The network socket between the server and client
+ * @param {Buffer} head The first packet of the upgraded stream
+ * @param {Object} options Options object
+ * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether
+ * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
+ * multiple times in the same tick
+ * @param {Function} [options.generateMask] The function used to generate the
+ * masking key
+ * @param {Number} [options.maxPayload=0] The maximum allowed message size
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
+ * not to skip UTF-8 validation for text and close messages
+ * @private
+ */
+ setSocket(socket, head, options) {
+ const receiver = new Receiver2({
+ allowSynchronousEvents: options.allowSynchronousEvents,
+ binaryType: this.binaryType,
+ extensions: this._extensions,
+ isServer: this._isServer,
+ maxPayload: options.maxPayload,
+ skipUTF8Validation: options.skipUTF8Validation
+ });
+ const sender = new Sender2(socket, this._extensions, options.generateMask);
+ this._receiver = receiver;
+ this._sender = sender;
+ this._socket = socket;
+ receiver[kWebSocket] = this;
+ sender[kWebSocket] = this;
+ socket[kWebSocket] = this;
+ receiver.on("conclude", receiverOnConclude);
+ receiver.on("drain", receiverOnDrain);
+ receiver.on("error", receiverOnError);
+ receiver.on("message", receiverOnMessage);
+ receiver.on("ping", receiverOnPing);
+ receiver.on("pong", receiverOnPong);
+ sender.onerror = senderOnError;
+ if (socket.setTimeout) socket.setTimeout(0);
+ if (socket.setNoDelay) socket.setNoDelay();
+ if (head.length > 0) socket.unshift(head);
+ socket.on("close", socketOnClose);
+ socket.on("data", socketOnData);
+ socket.on("end", socketOnEnd);
+ socket.on("error", socketOnError);
+ this._readyState = _WebSocket4.OPEN;
+ this.emit("open");
+ }
+ /**
+ * Emit the `'close'` event.
+ *
+ * @private
+ */
+ emitClose() {
+ if (!this._socket) {
+ this._readyState = _WebSocket4.CLOSED;
+ this.emit("close", this._closeCode, this._closeMessage);
+ return;
+ }
+ if (this._extensions[PerMessageDeflate.extensionName]) {
+ this._extensions[PerMessageDeflate.extensionName].cleanup();
+ }
+ this._receiver.removeAllListeners();
+ this._readyState = _WebSocket4.CLOSED;
+ this.emit("close", this._closeCode, this._closeMessage);
+ }
+ /**
+ * Start a closing handshake.
+ *
+ * +----------+ +-----------+ +----------+
+ * - - -|ws.close()|-->|close frame|-->|ws.close()|- - -
+ * | +----------+ +-----------+ +----------+ |
+ * +----------+ +-----------+ |
+ * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING
+ * +----------+ +-----------+ |
+ * | | | +---+ |
+ * +------------------------+-->|fin| - - - -
+ * | +---+ | +---+
+ * - - - - -|fin|<---------------------+
+ * +---+
+ *
+ * @param {Number} [code] Status code explaining why the connection is closing
+ * @param {(String|Buffer)} [data] The reason why the connection is
+ * closing
+ * @public
+ */
+ close(code, data) {
+ if (this.readyState === _WebSocket4.CLOSED) return;
+ if (this.readyState === _WebSocket4.CONNECTING) {
+ const msg = "WebSocket was closed before the connection was established";
+ abortHandshake(this, this._req, msg);
+ return;
+ }
+ if (this.readyState === _WebSocket4.CLOSING) {
+ if (this._closeFrameSent && (this._closeFrameReceived || this._receiver._writableState.errorEmitted)) {
+ this._socket.end();
+ }
+ return;
+ }
+ this._readyState = _WebSocket4.CLOSING;
+ this._sender.close(code, data, !this._isServer, (err) => {
+ if (err) return;
+ this._closeFrameSent = true;
+ if (this._closeFrameReceived || this._receiver._writableState.errorEmitted) {
+ this._socket.end();
+ }
+ });
+ setCloseTimer(this);
+ }
+ /**
+ * Pause the socket.
+ *
+ * @public
+ */
+ pause() {
+ if (this.readyState === _WebSocket4.CONNECTING || this.readyState === _WebSocket4.CLOSED) {
+ return;
+ }
+ this._paused = true;
+ this._socket.pause();
+ }
+ /**
+ * Send a ping.
+ *
+ * @param {*} [data] The data to send
+ * @param {Boolean} [mask] Indicates whether or not to mask `data`
+ * @param {Function} [cb] Callback which is executed when the ping is sent
+ * @public
+ */
+ ping(data, mask, cb) {
+ if (this.readyState === _WebSocket4.CONNECTING) {
+ throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
+ }
+ if (typeof data === "function") {
+ cb = data;
+ data = mask = void 0;
+ } else if (typeof mask === "function") {
+ cb = mask;
+ mask = void 0;
+ }
+ if (typeof data === "number") data = data.toString();
+ if (this.readyState !== _WebSocket4.OPEN) {
+ sendAfterClose(this, data, cb);
+ return;
+ }
+ if (mask === void 0) mask = !this._isServer;
+ this._sender.ping(data || EMPTY_BUFFER2, mask, cb);
+ }
+ /**
+ * Send a pong.
+ *
+ * @param {*} [data] The data to send
+ * @param {Boolean} [mask] Indicates whether or not to mask `data`
+ * @param {Function} [cb] Callback which is executed when the pong is sent
+ * @public
+ */
+ pong(data, mask, cb) {
+ if (this.readyState === _WebSocket4.CONNECTING) {
+ throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
+ }
+ if (typeof data === "function") {
+ cb = data;
+ data = mask = void 0;
+ } else if (typeof mask === "function") {
+ cb = mask;
+ mask = void 0;
+ }
+ if (typeof data === "number") data = data.toString();
+ if (this.readyState !== _WebSocket4.OPEN) {
+ sendAfterClose(this, data, cb);
+ return;
+ }
+ if (mask === void 0) mask = !this._isServer;
+ this._sender.pong(data || EMPTY_BUFFER2, mask, cb);
+ }
+ /**
+ * Resume the socket.
+ *
+ * @public
+ */
+ resume() {
+ if (this.readyState === _WebSocket4.CONNECTING || this.readyState === _WebSocket4.CLOSED) {
+ return;
+ }
+ this._paused = false;
+ if (!this._receiver._writableState.needDrain) this._socket.resume();
+ }
+ /**
+ * Send a data message.
+ *
+ * @param {*} data The message to send
+ * @param {Object} [options] Options object
+ * @param {Boolean} [options.binary] Specifies whether `data` is binary or
+ * text
+ * @param {Boolean} [options.compress] Specifies whether or not to compress
+ * `data`
+ * @param {Boolean} [options.fin=true] Specifies whether the fragment is the
+ * last one
+ * @param {Boolean} [options.mask] Specifies whether or not to mask `data`
+ * @param {Function} [cb] Callback which is executed when data is written out
+ * @public
+ */
+ send(data, options, cb) {
+ if (this.readyState === _WebSocket4.CONNECTING) {
+ throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
+ }
+ if (typeof options === "function") {
+ cb = options;
+ options = {};
+ }
+ if (typeof data === "number") data = data.toString();
+ if (this.readyState !== _WebSocket4.OPEN) {
+ sendAfterClose(this, data, cb);
+ return;
+ }
+ const opts = {
+ binary: typeof data !== "string",
+ mask: !this._isServer,
+ compress: true,
+ fin: true,
+ ...options
+ };
+ if (!this._extensions[PerMessageDeflate.extensionName]) {
+ opts.compress = false;
+ }
+ this._sender.send(data || EMPTY_BUFFER2, opts, cb);
+ }
+ /**
+ * Forcibly close the connection.
+ *
+ * @public
+ */
+ terminate() {
+ if (this.readyState === _WebSocket4.CLOSED) return;
+ if (this.readyState === _WebSocket4.CONNECTING) {
+ const msg = "WebSocket was closed before the connection was established";
+ abortHandshake(this, this._req, msg);
+ return;
+ }
+ if (this._socket) {
+ this._readyState = _WebSocket4.CLOSING;
+ this._socket.destroy();
+ }
+ }
+ };
+ Object.defineProperty(WebSocket3, "CONNECTING", {
+ enumerable: true,
+ value: readyStates.indexOf("CONNECTING")
+ });
+ Object.defineProperty(WebSocket3.prototype, "CONNECTING", {
+ enumerable: true,
+ value: readyStates.indexOf("CONNECTING")
+ });
+ Object.defineProperty(WebSocket3, "OPEN", {
+ enumerable: true,
+ value: readyStates.indexOf("OPEN")
+ });
+ Object.defineProperty(WebSocket3.prototype, "OPEN", {
+ enumerable: true,
+ value: readyStates.indexOf("OPEN")
+ });
+ Object.defineProperty(WebSocket3, "CLOSING", {
+ enumerable: true,
+ value: readyStates.indexOf("CLOSING")
+ });
+ Object.defineProperty(WebSocket3.prototype, "CLOSING", {
+ enumerable: true,
+ value: readyStates.indexOf("CLOSING")
+ });
+ Object.defineProperty(WebSocket3, "CLOSED", {
+ enumerable: true,
+ value: readyStates.indexOf("CLOSED")
+ });
+ Object.defineProperty(WebSocket3.prototype, "CLOSED", {
+ enumerable: true,
+ value: readyStates.indexOf("CLOSED")
+ });
+ [
+ "binaryType",
+ "bufferedAmount",
+ "extensions",
+ "isPaused",
+ "protocol",
+ "readyState",
+ "url"
+ ].forEach((property) => {
+ Object.defineProperty(WebSocket3.prototype, property, { enumerable: true });
+ });
+ ["open", "error", "close", "message"].forEach((method) => {
+ Object.defineProperty(WebSocket3.prototype, `on${method}`, {
+ enumerable: true,
+ get() {
+ for (const listener of this.listeners(method)) {
+ if (listener[kForOnEventAttribute]) return listener[kListener];
+ }
+ return null;
+ },
+ set(handler) {
+ for (const listener of this.listeners(method)) {
+ if (listener[kForOnEventAttribute]) {
+ this.removeListener(method, listener);
+ break;
+ }
+ }
+ if (typeof handler !== "function") return;
+ this.addEventListener(method, handler, {
+ [kForOnEventAttribute]: true
+ });
+ }
+ });
+ });
+ WebSocket3.prototype.addEventListener = addEventListener;
+ WebSocket3.prototype.removeEventListener = removeEventListener;
+ module2.exports = WebSocket3;
+ function initAsClient(websocket, address, protocols, options) {
+ const opts = {
+ allowSynchronousEvents: true,
+ autoPong: true,
+ protocolVersion: protocolVersions[1],
+ maxPayload: 100 * 1024 * 1024,
+ skipUTF8Validation: false,
+ perMessageDeflate: true,
+ followRedirects: false,
+ maxRedirects: 10,
+ ...options,
+ socketPath: void 0,
+ hostname: void 0,
+ protocol: void 0,
+ timeout: void 0,
+ method: "GET",
+ host: void 0,
+ path: void 0,
+ port: void 0
+ };
+ websocket._autoPong = opts.autoPong;
+ if (!protocolVersions.includes(opts.protocolVersion)) {
+ throw new RangeError(
+ `Unsupported protocol version: ${opts.protocolVersion} (supported versions: ${protocolVersions.join(", ")})`
+ );
+ }
+ let parsedUrl;
+ if (address instanceof URL2) {
+ parsedUrl = address;
+ } else {
+ try {
+ parsedUrl = new URL2(address);
+ } catch (e) {
+ throw new SyntaxError(`Invalid URL: ${address}`);
+ }
+ }
+ if (parsedUrl.protocol === "http:") {
+ parsedUrl.protocol = "ws:";
+ } else if (parsedUrl.protocol === "https:") {
+ parsedUrl.protocol = "wss:";
+ }
+ websocket._url = parsedUrl.href;
+ const isSecure = parsedUrl.protocol === "wss:";
+ const isIpcUrl = parsedUrl.protocol === "ws+unix:";
+ let invalidUrlMessage;
+ if (parsedUrl.protocol !== "ws:" && !isSecure && !isIpcUrl) {
+ invalidUrlMessage = `The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`;
+ } else if (isIpcUrl && !parsedUrl.pathname) {
+ invalidUrlMessage = "The URL's pathname is empty";
+ } else if (parsedUrl.hash) {
+ invalidUrlMessage = "The URL contains a fragment identifier";
+ }
+ if (invalidUrlMessage) {
+ const err = new SyntaxError(invalidUrlMessage);
+ if (websocket._redirects === 0) {
+ throw err;
+ } else {
+ emitErrorAndClose(websocket, err);
+ return;
+ }
+ }
+ const defaultPort = isSecure ? 443 : 80;
+ const key = randomBytes3(16).toString("base64");
+ const request = isSecure ? https.request : http.request;
+ const protocolSet = /* @__PURE__ */ new Set();
+ let perMessageDeflate;
+ opts.createConnection = opts.createConnection || (isSecure ? tlsConnect : netConnect);
+ opts.defaultPort = opts.defaultPort || defaultPort;
+ opts.port = parsedUrl.port || defaultPort;
+ opts.host = parsedUrl.hostname.startsWith("[") ? parsedUrl.hostname.slice(1, -1) : parsedUrl.hostname;
+ opts.headers = {
+ ...opts.headers,
+ "Sec-WebSocket-Version": opts.protocolVersion,
+ "Sec-WebSocket-Key": key,
+ Connection: "Upgrade",
+ Upgrade: "websocket"
+ };
+ opts.path = parsedUrl.pathname + parsedUrl.search;
+ opts.timeout = opts.handshakeTimeout;
+ if (opts.perMessageDeflate) {
+ perMessageDeflate = new PerMessageDeflate(
+ opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},
+ false,
+ opts.maxPayload
+ );
+ opts.headers["Sec-WebSocket-Extensions"] = format({
+ [PerMessageDeflate.extensionName]: perMessageDeflate.offer()
+ });
+ }
+ if (protocols.length) {
+ for (const protocol of protocols) {
+ if (typeof protocol !== "string" || !subprotocolRegex.test(protocol) || protocolSet.has(protocol)) {
+ throw new SyntaxError(
+ "An invalid or duplicated subprotocol was specified"
+ );
+ }
+ protocolSet.add(protocol);
+ }
+ opts.headers["Sec-WebSocket-Protocol"] = protocols.join(",");
+ }
+ if (opts.origin) {
+ if (opts.protocolVersion < 13) {
+ opts.headers["Sec-WebSocket-Origin"] = opts.origin;
+ } else {
+ opts.headers.Origin = opts.origin;
+ }
+ }
+ if (parsedUrl.username || parsedUrl.password) {
+ opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
+ }
+ if (isIpcUrl) {
+ const parts = opts.path.split(":");
+ opts.socketPath = parts[0];
+ opts.path = parts[1];
+ }
+ let req;
+ if (opts.followRedirects) {
+ if (websocket._redirects === 0) {
+ websocket._originalIpc = isIpcUrl;
+ websocket._originalSecure = isSecure;
+ websocket._originalHostOrSocketPath = isIpcUrl ? opts.socketPath : parsedUrl.host;
+ const headers = options && options.headers;
+ options = { ...options, headers: {} };
+ if (headers) {
+ for (const [key2, value] of Object.entries(headers)) {
+ options.headers[key2.toLowerCase()] = value;
+ }
+ }
+ } else if (websocket.listenerCount("redirect") === 0) {
+ const isSameHost = isIpcUrl ? websocket._originalIpc ? opts.socketPath === websocket._originalHostOrSocketPath : false : websocket._originalIpc ? false : parsedUrl.host === websocket._originalHostOrSocketPath;
+ if (!isSameHost || websocket._originalSecure && !isSecure) {
+ delete opts.headers.authorization;
+ delete opts.headers.cookie;
+ if (!isSameHost) delete opts.headers.host;
+ opts.auth = void 0;
+ }
+ }
+ if (opts.auth && !options.headers.authorization) {
+ options.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64");
+ }
+ req = websocket._req = request(opts);
+ if (websocket._redirects) {
+ websocket.emit("redirect", websocket.url, req);
+ }
+ } else {
+ req = websocket._req = request(opts);
+ }
+ if (opts.timeout) {
+ req.on("timeout", () => {
+ abortHandshake(websocket, req, "Opening handshake has timed out");
+ });
+ }
+ req.on("error", (err) => {
+ if (req === null || req[kAborted]) return;
+ req = websocket._req = null;
+ emitErrorAndClose(websocket, err);
+ });
+ req.on("response", (res) => {
+ const location = res.headers.location;
+ const statusCode = res.statusCode;
+ if (location && opts.followRedirects && statusCode >= 300 && statusCode < 400) {
+ if (++websocket._redirects > opts.maxRedirects) {
+ abortHandshake(websocket, req, "Maximum redirects exceeded");
+ return;
+ }
+ req.abort();
+ let addr;
+ try {
+ addr = new URL2(location, address);
+ } catch (e) {
+ const err = new SyntaxError(`Invalid URL: ${location}`);
+ emitErrorAndClose(websocket, err);
+ return;
+ }
+ initAsClient(websocket, addr, protocols, options);
+ } else if (!websocket.emit("unexpected-response", req, res)) {
+ abortHandshake(
+ websocket,
+ req,
+ `Unexpected server response: ${res.statusCode}`
+ );
+ }
+ });
+ req.on("upgrade", (res, socket, head) => {
+ websocket.emit("upgrade", res);
+ if (websocket.readyState !== WebSocket3.CONNECTING) return;
+ req = websocket._req = null;
+ const upgrade = res.headers.upgrade;
+ if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
+ abortHandshake(websocket, socket, "Invalid Upgrade header");
+ return;
+ }
+ const digest = createHash("sha1").update(key + GUID).digest("base64");
+ if (res.headers["sec-websocket-accept"] !== digest) {
+ abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
+ return;
+ }
+ const serverProt = res.headers["sec-websocket-protocol"];
+ let protError;
+ if (serverProt !== void 0) {
+ if (!protocolSet.size) {
+ protError = "Server sent a subprotocol but none was requested";
+ } else if (!protocolSet.has(serverProt)) {
+ protError = "Server sent an invalid subprotocol";
+ }
+ } else if (protocolSet.size) {
+ protError = "Server sent no subprotocol";
+ }
+ if (protError) {
+ abortHandshake(websocket, socket, protError);
+ return;
+ }
+ if (serverProt) websocket._protocol = serverProt;
+ const secWebSocketExtensions = res.headers["sec-websocket-extensions"];
+ if (secWebSocketExtensions !== void 0) {
+ if (!perMessageDeflate) {
+ const message = "Server sent a Sec-WebSocket-Extensions header but no extension was requested";
+ abortHandshake(websocket, socket, message);
+ return;
+ }
+ let extensions;
+ try {
+ extensions = parse4(secWebSocketExtensions);
+ } catch (err) {
+ const message = "Invalid Sec-WebSocket-Extensions header";
+ abortHandshake(websocket, socket, message);
+ return;
+ }
+ const extensionNames = Object.keys(extensions);
+ if (extensionNames.length !== 1 || extensionNames[0] !== PerMessageDeflate.extensionName) {
+ const message = "Server indicated an extension that was not requested";
+ abortHandshake(websocket, socket, message);
+ return;
+ }
+ try {
+ perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
+ } catch (err) {
+ const message = "Invalid Sec-WebSocket-Extensions header";
+ abortHandshake(websocket, socket, message);
+ return;
+ }
+ websocket._extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
+ }
+ websocket.setSocket(socket, head, {
+ allowSynchronousEvents: opts.allowSynchronousEvents,
+ generateMask: opts.generateMask,
+ maxPayload: opts.maxPayload,
+ skipUTF8Validation: opts.skipUTF8Validation
+ });
+ });
+ if (opts.finishRequest) {
+ opts.finishRequest(req, websocket);
+ } else {
+ req.end();
+ }
+ }
+ function emitErrorAndClose(websocket, err) {
+ websocket._readyState = WebSocket3.CLOSING;
+ websocket._errorEmitted = true;
+ websocket.emit("error", err);
+ websocket.emitClose();
+ }
+ function netConnect(options) {
+ options.path = options.socketPath;
+ return net.connect(options);
+ }
+ function tlsConnect(options) {
+ options.path = void 0;
+ if (!options.servername && options.servername !== "") {
+ options.servername = net.isIP(options.host) ? "" : options.host;
+ }
+ return tls.connect(options);
+ }
+ function abortHandshake(websocket, stream, message) {
+ websocket._readyState = WebSocket3.CLOSING;
+ const err = new Error(message);
+ Error.captureStackTrace(err, abortHandshake);
+ if (stream.setHeader) {
+ stream[kAborted] = true;
+ stream.abort();
+ if (stream.socket && !stream.socket.destroyed) {
+ stream.socket.destroy();
+ }
+ process.nextTick(emitErrorAndClose, websocket, err);
+ } else {
+ stream.destroy(err);
+ stream.once("error", websocket.emit.bind(websocket, "error"));
+ stream.once("close", websocket.emitClose.bind(websocket));
+ }
+ }
+ function sendAfterClose(websocket, data, cb) {
+ if (data) {
+ const length = isBlob(data) ? data.size : toBuffer(data).length;
+ if (websocket._socket) websocket._sender._bufferedBytes += length;
+ else websocket._bufferedAmount += length;
+ }
+ if (cb) {
+ const err = new Error(
+ `WebSocket is not open: readyState ${websocket.readyState} (${readyStates[websocket.readyState]})`
+ );
+ process.nextTick(cb, err);
+ }
+ }
+ function receiverOnConclude(code, reason) {
+ const websocket = this[kWebSocket];
+ websocket._closeFrameReceived = true;
+ websocket._closeMessage = reason;
+ websocket._closeCode = code;
+ if (websocket._socket[kWebSocket] === void 0) return;
+ websocket._socket.removeListener("data", socketOnData);
+ process.nextTick(resume, websocket._socket);
+ if (code === 1005) websocket.close();
+ else websocket.close(code, reason);
+ }
+ function receiverOnDrain() {
+ const websocket = this[kWebSocket];
+ if (!websocket.isPaused) websocket._socket.resume();
+ }
+ function receiverOnError(err) {
+ const websocket = this[kWebSocket];
+ if (websocket._socket[kWebSocket] !== void 0) {
+ websocket._socket.removeListener("data", socketOnData);
+ process.nextTick(resume, websocket._socket);
+ websocket.close(err[kStatusCode]);
+ }
+ if (!websocket._errorEmitted) {
+ websocket._errorEmitted = true;
+ websocket.emit("error", err);
+ }
+ }
+ function receiverOnFinish() {
+ this[kWebSocket].emitClose();
+ }
+ function receiverOnMessage(data, isBinary) {
+ this[kWebSocket].emit("message", data, isBinary);
+ }
+ function receiverOnPing(data) {
+ const websocket = this[kWebSocket];
+ if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);
+ websocket.emit("ping", data);
+ }
+ function receiverOnPong(data) {
+ this[kWebSocket].emit("pong", data);
+ }
+ function resume(stream) {
+ stream.resume();
+ }
+ function senderOnError(err) {
+ const websocket = this[kWebSocket];
+ if (websocket.readyState === WebSocket3.CLOSED) return;
+ if (websocket.readyState === WebSocket3.OPEN) {
+ websocket._readyState = WebSocket3.CLOSING;
+ setCloseTimer(websocket);
+ }
+ this._socket.end();
+ if (!websocket._errorEmitted) {
+ websocket._errorEmitted = true;
+ websocket.emit("error", err);
+ }
+ }
+ function setCloseTimer(websocket) {
+ websocket._closeTimer = setTimeout(
+ websocket._socket.destroy.bind(websocket._socket),
+ closeTimeout
+ );
+ }
+ function socketOnClose() {
+ const websocket = this[kWebSocket];
+ this.removeListener("close", socketOnClose);
+ this.removeListener("data", socketOnData);
+ this.removeListener("end", socketOnEnd);
+ websocket._readyState = WebSocket3.CLOSING;
+ let chunk;
+ if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && (chunk = websocket._socket.read()) !== null) {
+ websocket._receiver.write(chunk);
+ }
+ websocket._receiver.end();
+ this[kWebSocket] = void 0;
+ clearTimeout(websocket._closeTimer);
+ if (websocket._receiver._writableState.finished || websocket._receiver._writableState.errorEmitted) {
+ websocket.emitClose();
+ } else {
+ websocket._receiver.on("error", receiverOnFinish);
+ websocket._receiver.on("finish", receiverOnFinish);
+ }
+ }
+ function socketOnData(chunk) {
+ if (!this[kWebSocket]._receiver.write(chunk)) {
+ this.pause();
+ }
+ }
+ function socketOnEnd() {
+ const websocket = this[kWebSocket];
+ websocket._readyState = WebSocket3.CLOSING;
+ websocket._receiver.end();
+ this.end();
+ }
+ function socketOnError() {
+ const websocket = this[kWebSocket];
+ this.removeListener("error", socketOnError);
+ this.on("error", NOOP);
+ if (websocket) {
+ websocket._readyState = WebSocket3.CLOSING;
+ this.destroy();
+ }
+ }
+ }
+});
+
+// node_modules/ws/lib/stream.js
+var require_stream = __commonJS({
+ "node_modules/ws/lib/stream.js"(exports2, module2) {
+ "use strict";
+ var WebSocket3 = require_websocket();
+ var { Duplex } = require("stream");
+ function emitClose(stream) {
+ stream.emit("close");
+ }
+ function duplexOnEnd() {
+ if (!this.destroyed && this._writableState.finished) {
+ this.destroy();
+ }
+ }
+ function duplexOnError(err) {
+ this.removeListener("error", duplexOnError);
+ this.destroy();
+ if (this.listenerCount("error") === 0) {
+ this.emit("error", err);
+ }
+ }
+ function createWebSocketStream2(ws, options) {
+ let terminateOnDestroy = true;
+ const duplex = new Duplex({
+ ...options,
+ autoDestroy: false,
+ emitClose: false,
+ objectMode: false,
+ writableObjectMode: false
+ });
+ ws.on("message", function message(msg, isBinary) {
+ const data = !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;
+ if (!duplex.push(data)) ws.pause();
+ });
+ ws.once("error", function error(err) {
+ if (duplex.destroyed) return;
+ terminateOnDestroy = false;
+ duplex.destroy(err);
+ });
+ ws.once("close", function close() {
+ if (duplex.destroyed) return;
+ duplex.push(null);
+ });
+ duplex._destroy = function(err, callback) {
+ if (ws.readyState === ws.CLOSED) {
+ callback(err);
+ process.nextTick(emitClose, duplex);
+ return;
+ }
+ let called = false;
+ ws.once("error", function error(err2) {
+ called = true;
+ callback(err2);
+ });
+ ws.once("close", function close() {
+ if (!called) callback(err);
+ process.nextTick(emitClose, duplex);
+ });
+ if (terminateOnDestroy) ws.terminate();
+ };
+ duplex._final = function(callback) {
+ if (ws.readyState === ws.CONNECTING) {
+ ws.once("open", function open() {
+ duplex._final(callback);
+ });
+ return;
+ }
+ if (ws._socket === null) return;
+ if (ws._socket._writableState.finished) {
+ callback();
+ if (duplex._readableState.endEmitted) duplex.destroy();
+ } else {
+ ws._socket.once("finish", function finish() {
+ callback();
+ });
+ ws.close();
+ }
+ };
+ duplex._read = function() {
+ if (ws.isPaused) ws.resume();
+ };
+ duplex._write = function(chunk, encoding, callback) {
+ if (ws.readyState === ws.CONNECTING) {
+ ws.once("open", function open() {
+ duplex._write(chunk, encoding, callback);
+ });
+ return;
+ }
+ ws.send(chunk, callback);
+ };
+ duplex.on("end", duplexOnEnd);
+ duplex.on("error", duplexOnError);
+ return duplex;
+ }
+ module2.exports = createWebSocketStream2;
+ }
+});
+
+// node_modules/ws/lib/subprotocol.js
+var require_subprotocol = __commonJS({
+ "node_modules/ws/lib/subprotocol.js"(exports2, module2) {
+ "use strict";
+ var { tokenChars } = require_validation();
+ function parse4(header) {
+ const protocols = /* @__PURE__ */ new Set();
+ let start = -1;
+ let end = -1;
+ let i3 = 0;
+ for (i3; i3 < header.length; i3++) {
+ const code = header.charCodeAt(i3);
+ if (end === -1 && tokenChars[code] === 1) {
+ if (start === -1) start = i3;
+ } else if (i3 !== 0 && (code === 32 || code === 9)) {
+ if (end === -1 && start !== -1) end = i3;
+ } else if (code === 44) {
+ if (start === -1) {
+ throw new SyntaxError(`Unexpected character at index ${i3}`);
+ }
+ if (end === -1) end = i3;
+ const protocol2 = header.slice(start, end);
+ if (protocols.has(protocol2)) {
+ throw new SyntaxError(`The "${protocol2}" subprotocol is duplicated`);
+ }
+ protocols.add(protocol2);
+ start = end = -1;
+ } else {
+ throw new SyntaxError(`Unexpected character at index ${i3}`);
+ }
+ }
+ if (start === -1 || end !== -1) {
+ throw new SyntaxError("Unexpected end of input");
+ }
+ const protocol = header.slice(start, i3);
+ if (protocols.has(protocol)) {
+ throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
+ }
+ protocols.add(protocol);
+ return protocols;
+ }
+ module2.exports = { parse: parse4 };
+ }
+});
+
+// node_modules/ws/lib/websocket-server.js
+var require_websocket_server = __commonJS({
+ "node_modules/ws/lib/websocket-server.js"(exports2, module2) {
+ "use strict";
+ var EventEmitter = require("events");
+ var http = require("http");
+ var { Duplex } = require("stream");
+ var { createHash } = require("crypto");
+ var extension = require_extension();
+ var PerMessageDeflate = require_permessage_deflate();
+ var subprotocol = require_subprotocol();
+ var WebSocket3 = require_websocket();
+ var { GUID, kWebSocket } = require_constants();
+ var keyRegex = /^[+/0-9A-Za-z]{22}==$/;
+ var RUNNING = 0;
+ var CLOSING = 1;
+ var CLOSED = 2;
+ var WebSocketServer2 = class extends EventEmitter {
+ /**
+ * Create a `WebSocketServer` instance.
+ *
+ * @param {Object} options Configuration options
+ * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
+ * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
+ * multiple times in the same tick
+ * @param {Boolean} [options.autoPong=true] Specifies whether or not to
+ * automatically send a pong in response to a ping
+ * @param {Number} [options.backlog=511] The maximum length of the queue of
+ * pending connections
+ * @param {Boolean} [options.clientTracking=true] Specifies whether or not to
+ * track clients
+ * @param {Function} [options.handleProtocols] A hook to handle protocols
+ * @param {String} [options.host] The hostname where to bind the server
+ * @param {Number} [options.maxPayload=104857600] The maximum allowed message
+ * size
+ * @param {Boolean} [options.noServer=false] Enable no server mode
+ * @param {String} [options.path] Accept only connections matching this path
+ * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable
+ * permessage-deflate
+ * @param {Number} [options.port] The port where to bind the server
+ * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
+ * server to use
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
+ * not to skip UTF-8 validation for text and close messages
+ * @param {Function} [options.verifyClient] A hook to reject connections
+ * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`
+ * class to use. It must be the `WebSocket` class or class that extends it
+ * @param {Function} [callback] A listener for the `listening` event
+ */
+ constructor(options, callback) {
+ super();
+ options = {
+ allowSynchronousEvents: true,
+ autoPong: true,
+ maxPayload: 100 * 1024 * 1024,
+ skipUTF8Validation: false,
+ perMessageDeflate: false,
+ handleProtocols: null,
+ clientTracking: true,
+ verifyClient: null,
+ noServer: false,
+ backlog: null,
+ // use default (511 as implemented in net.js)
+ server: null,
+ host: null,
+ path: null,
+ port: null,
+ WebSocket: WebSocket3,
+ ...options
+ };
+ if (options.port == null && !options.server && !options.noServer || options.port != null && (options.server || options.noServer) || options.server && options.noServer) {
+ throw new TypeError(
+ 'One and only one of the "port", "server", or "noServer" options must be specified'
+ );
+ }
+ if (options.port != null) {
+ this._server = http.createServer((req, res) => {
+ const body = http.STATUS_CODES[426];
+ res.writeHead(426, {
+ "Content-Length": body.length,
+ "Content-Type": "text/plain"
+ });
+ res.end(body);
+ });
+ this._server.listen(
+ options.port,
+ options.host,
+ options.backlog,
+ callback
+ );
+ } else if (options.server) {
+ this._server = options.server;
+ }
+ if (this._server) {
+ const emitConnection = this.emit.bind(this, "connection");
+ this._removeListeners = addListeners(this._server, {
+ listening: this.emit.bind(this, "listening"),
+ error: this.emit.bind(this, "error"),
+ upgrade: (req, socket, head) => {
+ this.handleUpgrade(req, socket, head, emitConnection);
+ }
+ });
+ }
+ if (options.perMessageDeflate === true) options.perMessageDeflate = {};
+ if (options.clientTracking) {
+ this.clients = /* @__PURE__ */ new Set();
+ this._shouldEmitClose = false;
+ }
+ this.options = options;
+ this._state = RUNNING;
+ }
+ /**
+ * Returns the bound address, the address family name, and port of the server
+ * as reported by the operating system if listening on an IP socket.
+ * If the server is listening on a pipe or UNIX domain socket, the name is
+ * returned as a string.
+ *
+ * @return {(Object|String|null)} The address of the server
+ * @public
+ */
+ address() {
+ if (this.options.noServer) {
+ throw new Error('The server is operating in "noServer" mode');
+ }
+ if (!this._server) return null;
+ return this._server.address();
+ }
+ /**
+ * Stop the server from accepting new connections and emit the `'close'` event
+ * when all existing connections are closed.
+ *
+ * @param {Function} [cb] A one-time listener for the `'close'` event
+ * @public
+ */
+ close(cb) {
+ if (this._state === CLOSED) {
+ if (cb) {
+ this.once("close", () => {
+ cb(new Error("The server is not running"));
+ });
+ }
+ process.nextTick(emitClose, this);
+ return;
+ }
+ if (cb) this.once("close", cb);
+ if (this._state === CLOSING) return;
+ this._state = CLOSING;
+ if (this.options.noServer || this.options.server) {
+ if (this._server) {
+ this._removeListeners();
+ this._removeListeners = this._server = null;
+ }
+ if (this.clients) {
+ if (!this.clients.size) {
+ process.nextTick(emitClose, this);
+ } else {
+ this._shouldEmitClose = true;
+ }
+ } else {
+ process.nextTick(emitClose, this);
+ }
+ } else {
+ const server = this._server;
+ this._removeListeners();
+ this._removeListeners = this._server = null;
+ server.close(() => {
+ emitClose(this);
+ });
+ }
+ }
+ /**
+ * See if a given request should be handled by this server instance.
+ *
+ * @param {http.IncomingMessage} req Request object to inspect
+ * @return {Boolean} `true` if the request is valid, else `false`
+ * @public
+ */
+ shouldHandle(req) {
+ if (this.options.path) {
+ const index = req.url.indexOf("?");
+ const pathname = index !== -1 ? req.url.slice(0, index) : req.url;
+ if (pathname !== this.options.path) return false;
+ }
+ return true;
+ }
+ /**
+ * Handle a HTTP Upgrade request.
+ *
+ * @param {http.IncomingMessage} req The request object
+ * @param {Duplex} socket The network socket between the server and client
+ * @param {Buffer} head The first packet of the upgraded stream
+ * @param {Function} cb Callback
+ * @public
+ */
+ handleUpgrade(req, socket, head, cb) {
+ socket.on("error", socketOnError);
+ const key = req.headers["sec-websocket-key"];
+ const upgrade = req.headers.upgrade;
+ const version = +req.headers["sec-websocket-version"];
+ if (req.method !== "GET") {
+ const message = "Invalid HTTP method";
+ abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);
+ return;
+ }
+ if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
+ const message = "Invalid Upgrade header";
+ abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
+ return;
+ }
+ if (key === void 0 || !keyRegex.test(key)) {
+ const message = "Missing or invalid Sec-WebSocket-Key header";
+ abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
+ return;
+ }
+ if (version !== 13 && version !== 8) {
+ const message = "Missing or invalid Sec-WebSocket-Version header";
+ abortHandshakeOrEmitwsClientError(this, req, socket, 400, message, {
+ "Sec-WebSocket-Version": "13, 8"
+ });
+ return;
+ }
+ if (!this.shouldHandle(req)) {
+ abortHandshake(socket, 400);
+ return;
+ }
+ const secWebSocketProtocol = req.headers["sec-websocket-protocol"];
+ let protocols = /* @__PURE__ */ new Set();
+ if (secWebSocketProtocol !== void 0) {
+ try {
+ protocols = subprotocol.parse(secWebSocketProtocol);
+ } catch (err) {
+ const message = "Invalid Sec-WebSocket-Protocol header";
+ abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
+ return;
+ }
+ }
+ const secWebSocketExtensions = req.headers["sec-websocket-extensions"];
+ const extensions = {};
+ if (this.options.perMessageDeflate && secWebSocketExtensions !== void 0) {
+ const perMessageDeflate = new PerMessageDeflate(
+ this.options.perMessageDeflate,
+ true,
+ this.options.maxPayload
+ );
+ try {
+ const offers = extension.parse(secWebSocketExtensions);
+ if (offers[PerMessageDeflate.extensionName]) {
+ perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
+ extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
+ }
+ } catch (err) {
+ const message = "Invalid or unacceptable Sec-WebSocket-Extensions header";
+ abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
+ return;
+ }
+ }
+ if (this.options.verifyClient) {
+ const info = {
+ origin: req.headers[`${version === 8 ? "sec-websocket-origin" : "origin"}`],
+ secure: !!(req.socket.authorized || req.socket.encrypted),
+ req
+ };
+ if (this.options.verifyClient.length === 2) {
+ this.options.verifyClient(info, (verified, code, message, headers) => {
+ if (!verified) {
+ return abortHandshake(socket, code || 401, message, headers);
+ }
+ this.completeUpgrade(
+ extensions,
+ key,
+ protocols,
+ req,
+ socket,
+ head,
+ cb
+ );
+ });
+ return;
+ }
+ if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
+ }
+ this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
+ }
+ /**
+ * Upgrade the connection to WebSocket.
+ *
+ * @param {Object} extensions The accepted extensions
+ * @param {String} key The value of the `Sec-WebSocket-Key` header
+ * @param {Set} protocols The subprotocols
+ * @param {http.IncomingMessage} req The request object
+ * @param {Duplex} socket The network socket between the server and client
+ * @param {Buffer} head The first packet of the upgraded stream
+ * @param {Function} cb Callback
+ * @throws {Error} If called more than once with the same socket
+ * @private
+ */
+ completeUpgrade(extensions, key, protocols, req, socket, head, cb) {
+ if (!socket.readable || !socket.writable) return socket.destroy();
+ if (socket[kWebSocket]) {
+ throw new Error(
+ "server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration"
+ );
+ }
+ if (this._state > RUNNING) return abortHandshake(socket, 503);
+ const digest = createHash("sha1").update(key + GUID).digest("base64");
+ const headers = [
+ "HTTP/1.1 101 Switching Protocols",
+ "Upgrade: websocket",
+ "Connection: Upgrade",
+ `Sec-WebSocket-Accept: ${digest}`
+ ];
+ const ws = new this.options.WebSocket(null, void 0, this.options);
+ if (protocols.size) {
+ const protocol = this.options.handleProtocols ? this.options.handleProtocols(protocols, req) : protocols.values().next().value;
+ if (protocol) {
+ headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
+ ws._protocol = protocol;
+ }
+ }
+ if (extensions[PerMessageDeflate.extensionName]) {
+ const params = extensions[PerMessageDeflate.extensionName].params;
+ const value = extension.format({
+ [PerMessageDeflate.extensionName]: [params]
+ });
+ headers.push(`Sec-WebSocket-Extensions: ${value}`);
+ ws._extensions = extensions;
+ }
+ this.emit("headers", headers, req);
+ socket.write(headers.concat("\r\n").join("\r\n"));
+ socket.removeListener("error", socketOnError);
+ ws.setSocket(socket, head, {
+ allowSynchronousEvents: this.options.allowSynchronousEvents,
+ maxPayload: this.options.maxPayload,
+ skipUTF8Validation: this.options.skipUTF8Validation
+ });
+ if (this.clients) {
+ this.clients.add(ws);
+ ws.on("close", () => {
+ this.clients.delete(ws);
+ if (this._shouldEmitClose && !this.clients.size) {
+ process.nextTick(emitClose, this);
+ }
+ });
+ }
+ cb(ws, req);
+ }
+ };
+ module2.exports = WebSocketServer2;
+ function addListeners(server, map) {
+ for (const event of Object.keys(map)) server.on(event, map[event]);
+ return function removeListeners() {
+ for (const event of Object.keys(map)) {
+ server.removeListener(event, map[event]);
+ }
+ };
+ }
+ function emitClose(server) {
+ server._state = CLOSED;
+ server.emit("close");
+ }
+ function socketOnError() {
+ this.destroy();
+ }
+ function abortHandshake(socket, code, message, headers) {
+ message = message || http.STATUS_CODES[code];
+ headers = {
+ Connection: "close",
+ "Content-Type": "text/html",
+ "Content-Length": Buffer.byteLength(message),
+ ...headers
+ };
+ socket.once("finish", socket.destroy);
+ socket.end(
+ `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r
+` + Object.keys(headers).map((h) => `${h}: ${headers[h]}`).join("\r\n") + "\r\n\r\n" + message
+ );
+ }
+ function abortHandshakeOrEmitwsClientError(server, req, socket, code, message, headers) {
+ if (server.listenerCount("wsClientError")) {
+ const err = new Error(message);
+ Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);
+ server.emit("wsClientError", err, socket, req);
+ } else {
+ abortHandshake(socket, code, message, headers);
+ }
+ }
+ }
+});
+
+// node_modules/qrcode/lib/can-promise.js
+var require_can_promise = __commonJS({
+ "node_modules/qrcode/lib/can-promise.js"(exports2, module2) {
+ module2.exports = function() {
+ return typeof Promise === "function" && Promise.prototype && Promise.prototype.then;
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/utils.js
+var require_utils = __commonJS({
+ "node_modules/qrcode/lib/core/utils.js"(exports2) {
+ var toSJISFunction;
+ var CODEWORDS_COUNT = [
+ 0,
+ // Not used
+ 26,
+ 44,
+ 70,
+ 100,
+ 134,
+ 172,
+ 196,
+ 242,
+ 292,
+ 346,
+ 404,
+ 466,
+ 532,
+ 581,
+ 655,
+ 733,
+ 815,
+ 901,
+ 991,
+ 1085,
+ 1156,
+ 1258,
+ 1364,
+ 1474,
+ 1588,
+ 1706,
+ 1828,
+ 1921,
+ 2051,
+ 2185,
+ 2323,
+ 2465,
+ 2611,
+ 2761,
+ 2876,
+ 3034,
+ 3196,
+ 3362,
+ 3532,
+ 3706
+ ];
+ exports2.getSymbolSize = function getSymbolSize(version) {
+ if (!version) throw new Error('"version" cannot be null or undefined');
+ if (version < 1 || version > 40) throw new Error('"version" should be in range from 1 to 40');
+ return version * 4 + 17;
+ };
+ exports2.getSymbolTotalCodewords = function getSymbolTotalCodewords(version) {
+ return CODEWORDS_COUNT[version];
+ };
+ exports2.getBCHDigit = function(data) {
+ let digit = 0;
+ while (data !== 0) {
+ digit++;
+ data >>>= 1;
+ }
+ return digit;
+ };
+ exports2.setToSJISFunction = function setToSJISFunction(f) {
+ if (typeof f !== "function") {
+ throw new Error('"toSJISFunc" is not a valid function.');
+ }
+ toSJISFunction = f;
+ };
+ exports2.isKanjiModeEnabled = function() {
+ return typeof toSJISFunction !== "undefined";
+ };
+ exports2.toSJIS = function toSJIS(kanji) {
+ return toSJISFunction(kanji);
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/error-correction-level.js
+var require_error_correction_level = __commonJS({
+ "node_modules/qrcode/lib/core/error-correction-level.js"(exports2) {
+ exports2.L = { bit: 1 };
+ exports2.M = { bit: 0 };
+ exports2.Q = { bit: 3 };
+ exports2.H = { bit: 2 };
+ function fromString(string) {
+ if (typeof string !== "string") {
+ throw new Error("Param is not a string");
+ }
+ const lcStr = string.toLowerCase();
+ switch (lcStr) {
+ case "l":
+ case "low":
+ return exports2.L;
+ case "m":
+ case "medium":
+ return exports2.M;
+ case "q":
+ case "quartile":
+ return exports2.Q;
+ case "h":
+ case "high":
+ return exports2.H;
+ default:
+ throw new Error("Unknown EC Level: " + string);
+ }
+ }
+ exports2.isValid = function isValid2(level) {
+ return level && typeof level.bit !== "undefined" && level.bit >= 0 && level.bit < 4;
+ };
+ exports2.from = function from(value, defaultValue) {
+ if (exports2.isValid(value)) {
+ return value;
+ }
+ try {
+ return fromString(value);
+ } catch (e) {
+ return defaultValue;
+ }
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/bit-buffer.js
+var require_bit_buffer = __commonJS({
+ "node_modules/qrcode/lib/core/bit-buffer.js"(exports2, module2) {
+ function BitBuffer() {
+ this.buffer = [];
+ this.length = 0;
+ }
+ BitBuffer.prototype = {
+ get: function(index) {
+ const bufIndex = Math.floor(index / 8);
+ return (this.buffer[bufIndex] >>> 7 - index % 8 & 1) === 1;
+ },
+ put: function(num, length) {
+ for (let i3 = 0; i3 < length; i3++) {
+ this.putBit((num >>> length - i3 - 1 & 1) === 1);
+ }
+ },
+ getLengthInBits: function() {
+ return this.length;
+ },
+ putBit: function(bit) {
+ const bufIndex = Math.floor(this.length / 8);
+ if (this.buffer.length <= bufIndex) {
+ this.buffer.push(0);
+ }
+ if (bit) {
+ this.buffer[bufIndex] |= 128 >>> this.length % 8;
+ }
+ this.length++;
+ }
+ };
+ module2.exports = BitBuffer;
+ }
+});
+
+// node_modules/qrcode/lib/core/bit-matrix.js
+var require_bit_matrix = __commonJS({
+ "node_modules/qrcode/lib/core/bit-matrix.js"(exports2, module2) {
+ function BitMatrix(size) {
+ if (!size || size < 1) {
+ throw new Error("BitMatrix size must be defined and greater than 0");
+ }
+ this.size = size;
+ this.data = new Uint8Array(size * size);
+ this.reservedBit = new Uint8Array(size * size);
+ }
+ BitMatrix.prototype.set = function(row, col, value, reserved) {
+ const index = row * this.size + col;
+ this.data[index] = value;
+ if (reserved) this.reservedBit[index] = true;
+ };
+ BitMatrix.prototype.get = function(row, col) {
+ return this.data[row * this.size + col];
+ };
+ BitMatrix.prototype.xor = function(row, col, value) {
+ this.data[row * this.size + col] ^= value;
+ };
+ BitMatrix.prototype.isReserved = function(row, col) {
+ return this.reservedBit[row * this.size + col];
+ };
+ module2.exports = BitMatrix;
+ }
+});
+
+// node_modules/qrcode/lib/core/alignment-pattern.js
+var require_alignment_pattern = __commonJS({
+ "node_modules/qrcode/lib/core/alignment-pattern.js"(exports2) {
+ var getSymbolSize = require_utils().getSymbolSize;
+ exports2.getRowColCoords = function getRowColCoords(version) {
+ if (version === 1) return [];
+ const posCount = Math.floor(version / 7) + 2;
+ const size = getSymbolSize(version);
+ const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2;
+ const positions = [size - 7];
+ for (let i3 = 1; i3 < posCount - 1; i3++) {
+ positions[i3] = positions[i3 - 1] - intervals;
+ }
+ positions.push(6);
+ return positions.reverse();
+ };
+ exports2.getPositions = function getPositions(version) {
+ const coords = [];
+ const pos = exports2.getRowColCoords(version);
+ const posLength = pos.length;
+ for (let i3 = 0; i3 < posLength; i3++) {
+ for (let j = 0; j < posLength; j++) {
+ if (i3 === 0 && j === 0 || // top-left
+ i3 === 0 && j === posLength - 1 || // bottom-left
+ i3 === posLength - 1 && j === 0) {
+ continue;
+ }
+ coords.push([pos[i3], pos[j]]);
+ }
+ }
+ return coords;
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/finder-pattern.js
+var require_finder_pattern = __commonJS({
+ "node_modules/qrcode/lib/core/finder-pattern.js"(exports2) {
+ var getSymbolSize = require_utils().getSymbolSize;
+ var FINDER_PATTERN_SIZE = 7;
+ exports2.getPositions = function getPositions(version) {
+ const size = getSymbolSize(version);
+ return [
+ // top-left
+ [0, 0],
+ // top-right
+ [size - FINDER_PATTERN_SIZE, 0],
+ // bottom-left
+ [0, size - FINDER_PATTERN_SIZE]
+ ];
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/mask-pattern.js
+var require_mask_pattern = __commonJS({
+ "node_modules/qrcode/lib/core/mask-pattern.js"(exports2) {
+ exports2.Patterns = {
+ PATTERN000: 0,
+ PATTERN001: 1,
+ PATTERN010: 2,
+ PATTERN011: 3,
+ PATTERN100: 4,
+ PATTERN101: 5,
+ PATTERN110: 6,
+ PATTERN111: 7
+ };
+ var PenaltyScores = {
+ N1: 3,
+ N2: 3,
+ N3: 40,
+ N4: 10
+ };
+ exports2.isValid = function isValid2(mask) {
+ return mask != null && mask !== "" && !isNaN(mask) && mask >= 0 && mask <= 7;
+ };
+ exports2.from = function from(value) {
+ return exports2.isValid(value) ? parseInt(value, 10) : void 0;
+ };
+ exports2.getPenaltyN1 = function getPenaltyN1(data) {
+ const size = data.size;
+ let points = 0;
+ let sameCountCol = 0;
+ let sameCountRow = 0;
+ let lastCol = null;
+ let lastRow = null;
+ for (let row = 0; row < size; row++) {
+ sameCountCol = sameCountRow = 0;
+ lastCol = lastRow = null;
+ for (let col = 0; col < size; col++) {
+ let module3 = data.get(row, col);
+ if (module3 === lastCol) {
+ sameCountCol++;
+ } else {
+ if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);
+ lastCol = module3;
+ sameCountCol = 1;
+ }
+ module3 = data.get(col, row);
+ if (module3 === lastRow) {
+ sameCountRow++;
+ } else {
+ if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);
+ lastRow = module3;
+ sameCountRow = 1;
+ }
+ }
+ if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);
+ if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);
+ }
+ return points;
+ };
+ exports2.getPenaltyN2 = function getPenaltyN2(data) {
+ const size = data.size;
+ let points = 0;
+ for (let row = 0; row < size - 1; row++) {
+ for (let col = 0; col < size - 1; col++) {
+ const last = data.get(row, col) + data.get(row, col + 1) + data.get(row + 1, col) + data.get(row + 1, col + 1);
+ if (last === 4 || last === 0) points++;
+ }
+ }
+ return points * PenaltyScores.N2;
+ };
+ exports2.getPenaltyN3 = function getPenaltyN3(data) {
+ const size = data.size;
+ let points = 0;
+ let bitsCol = 0;
+ let bitsRow = 0;
+ for (let row = 0; row < size; row++) {
+ bitsCol = bitsRow = 0;
+ for (let col = 0; col < size; col++) {
+ bitsCol = bitsCol << 1 & 2047 | data.get(row, col);
+ if (col >= 10 && (bitsCol === 1488 || bitsCol === 93)) points++;
+ bitsRow = bitsRow << 1 & 2047 | data.get(col, row);
+ if (col >= 10 && (bitsRow === 1488 || bitsRow === 93)) points++;
+ }
+ }
+ return points * PenaltyScores.N3;
+ };
+ exports2.getPenaltyN4 = function getPenaltyN4(data) {
+ let darkCount = 0;
+ const modulesCount = data.data.length;
+ for (let i3 = 0; i3 < modulesCount; i3++) darkCount += data.data[i3];
+ const k = Math.abs(Math.ceil(darkCount * 100 / modulesCount / 5) - 10);
+ return k * PenaltyScores.N4;
+ };
+ function getMaskAt(maskPattern, i3, j) {
+ switch (maskPattern) {
+ case exports2.Patterns.PATTERN000:
+ return (i3 + j) % 2 === 0;
+ case exports2.Patterns.PATTERN001:
+ return i3 % 2 === 0;
+ case exports2.Patterns.PATTERN010:
+ return j % 3 === 0;
+ case exports2.Patterns.PATTERN011:
+ return (i3 + j) % 3 === 0;
+ case exports2.Patterns.PATTERN100:
+ return (Math.floor(i3 / 2) + Math.floor(j / 3)) % 2 === 0;
+ case exports2.Patterns.PATTERN101:
+ return i3 * j % 2 + i3 * j % 3 === 0;
+ case exports2.Patterns.PATTERN110:
+ return (i3 * j % 2 + i3 * j % 3) % 2 === 0;
+ case exports2.Patterns.PATTERN111:
+ return (i3 * j % 3 + (i3 + j) % 2) % 2 === 0;
+ default:
+ throw new Error("bad maskPattern:" + maskPattern);
+ }
+ }
+ exports2.applyMask = function applyMask(pattern, data) {
+ const size = data.size;
+ for (let col = 0; col < size; col++) {
+ for (let row = 0; row < size; row++) {
+ if (data.isReserved(row, col)) continue;
+ data.xor(row, col, getMaskAt(pattern, row, col));
+ }
+ }
+ };
+ exports2.getBestMask = function getBestMask(data, setupFormatFunc) {
+ const numPatterns = Object.keys(exports2.Patterns).length;
+ let bestPattern = 0;
+ let lowerPenalty = Infinity;
+ for (let p = 0; p < numPatterns; p++) {
+ setupFormatFunc(p);
+ exports2.applyMask(p, data);
+ const penalty = exports2.getPenaltyN1(data) + exports2.getPenaltyN2(data) + exports2.getPenaltyN3(data) + exports2.getPenaltyN4(data);
+ exports2.applyMask(p, data);
+ if (penalty < lowerPenalty) {
+ lowerPenalty = penalty;
+ bestPattern = p;
+ }
+ }
+ return bestPattern;
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/error-correction-code.js
+var require_error_correction_code = __commonJS({
+ "node_modules/qrcode/lib/core/error-correction-code.js"(exports2) {
+ var ECLevel = require_error_correction_level();
+ var EC_BLOCKS_TABLE = [
+ // L M Q H
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 2,
+ 2,
+ 1,
+ 2,
+ 2,
+ 4,
+ 1,
+ 2,
+ 4,
+ 4,
+ 2,
+ 4,
+ 4,
+ 4,
+ 2,
+ 4,
+ 6,
+ 5,
+ 2,
+ 4,
+ 6,
+ 6,
+ 2,
+ 5,
+ 8,
+ 8,
+ 4,
+ 5,
+ 8,
+ 8,
+ 4,
+ 5,
+ 8,
+ 11,
+ 4,
+ 8,
+ 10,
+ 11,
+ 4,
+ 9,
+ 12,
+ 16,
+ 4,
+ 9,
+ 16,
+ 16,
+ 6,
+ 10,
+ 12,
+ 18,
+ 6,
+ 10,
+ 17,
+ 16,
+ 6,
+ 11,
+ 16,
+ 19,
+ 6,
+ 13,
+ 18,
+ 21,
+ 7,
+ 14,
+ 21,
+ 25,
+ 8,
+ 16,
+ 20,
+ 25,
+ 8,
+ 17,
+ 23,
+ 25,
+ 9,
+ 17,
+ 23,
+ 34,
+ 9,
+ 18,
+ 25,
+ 30,
+ 10,
+ 20,
+ 27,
+ 32,
+ 12,
+ 21,
+ 29,
+ 35,
+ 12,
+ 23,
+ 34,
+ 37,
+ 12,
+ 25,
+ 34,
+ 40,
+ 13,
+ 26,
+ 35,
+ 42,
+ 14,
+ 28,
+ 38,
+ 45,
+ 15,
+ 29,
+ 40,
+ 48,
+ 16,
+ 31,
+ 43,
+ 51,
+ 17,
+ 33,
+ 45,
+ 54,
+ 18,
+ 35,
+ 48,
+ 57,
+ 19,
+ 37,
+ 51,
+ 60,
+ 19,
+ 38,
+ 53,
+ 63,
+ 20,
+ 40,
+ 56,
+ 66,
+ 21,
+ 43,
+ 59,
+ 70,
+ 22,
+ 45,
+ 62,
+ 74,
+ 24,
+ 47,
+ 65,
+ 77,
+ 25,
+ 49,
+ 68,
+ 81
+ ];
+ var EC_CODEWORDS_TABLE = [
+ // L M Q H
+ 7,
+ 10,
+ 13,
+ 17,
+ 10,
+ 16,
+ 22,
+ 28,
+ 15,
+ 26,
+ 36,
+ 44,
+ 20,
+ 36,
+ 52,
+ 64,
+ 26,
+ 48,
+ 72,
+ 88,
+ 36,
+ 64,
+ 96,
+ 112,
+ 40,
+ 72,
+ 108,
+ 130,
+ 48,
+ 88,
+ 132,
+ 156,
+ 60,
+ 110,
+ 160,
+ 192,
+ 72,
+ 130,
+ 192,
+ 224,
+ 80,
+ 150,
+ 224,
+ 264,
+ 96,
+ 176,
+ 260,
+ 308,
+ 104,
+ 198,
+ 288,
+ 352,
+ 120,
+ 216,
+ 320,
+ 384,
+ 132,
+ 240,
+ 360,
+ 432,
+ 144,
+ 280,
+ 408,
+ 480,
+ 168,
+ 308,
+ 448,
+ 532,
+ 180,
+ 338,
+ 504,
+ 588,
+ 196,
+ 364,
+ 546,
+ 650,
+ 224,
+ 416,
+ 600,
+ 700,
+ 224,
+ 442,
+ 644,
+ 750,
+ 252,
+ 476,
+ 690,
+ 816,
+ 270,
+ 504,
+ 750,
+ 900,
+ 300,
+ 560,
+ 810,
+ 960,
+ 312,
+ 588,
+ 870,
+ 1050,
+ 336,
+ 644,
+ 952,
+ 1110,
+ 360,
+ 700,
+ 1020,
+ 1200,
+ 390,
+ 728,
+ 1050,
+ 1260,
+ 420,
+ 784,
+ 1140,
+ 1350,
+ 450,
+ 812,
+ 1200,
+ 1440,
+ 480,
+ 868,
+ 1290,
+ 1530,
+ 510,
+ 924,
+ 1350,
+ 1620,
+ 540,
+ 980,
+ 1440,
+ 1710,
+ 570,
+ 1036,
+ 1530,
+ 1800,
+ 570,
+ 1064,
+ 1590,
+ 1890,
+ 600,
+ 1120,
+ 1680,
+ 1980,
+ 630,
+ 1204,
+ 1770,
+ 2100,
+ 660,
+ 1260,
+ 1860,
+ 2220,
+ 720,
+ 1316,
+ 1950,
+ 2310,
+ 750,
+ 1372,
+ 2040,
+ 2430
+ ];
+ exports2.getBlocksCount = function getBlocksCount(version, errorCorrectionLevel) {
+ switch (errorCorrectionLevel) {
+ case ECLevel.L:
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 0];
+ case ECLevel.M:
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 1];
+ case ECLevel.Q:
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 2];
+ case ECLevel.H:
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 3];
+ default:
+ return void 0;
+ }
+ };
+ exports2.getTotalCodewordsCount = function getTotalCodewordsCount(version, errorCorrectionLevel) {
+ switch (errorCorrectionLevel) {
+ case ECLevel.L:
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0];
+ case ECLevel.M:
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1];
+ case ECLevel.Q:
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2];
+ case ECLevel.H:
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3];
+ default:
+ return void 0;
+ }
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/galois-field.js
+var require_galois_field = __commonJS({
+ "node_modules/qrcode/lib/core/galois-field.js"(exports2) {
+ var EXP_TABLE = new Uint8Array(512);
+ var LOG_TABLE = new Uint8Array(256);
+ (function initTables() {
+ let x = 1;
+ for (let i3 = 0; i3 < 255; i3++) {
+ EXP_TABLE[i3] = x;
+ LOG_TABLE[x] = i3;
+ x <<= 1;
+ if (x & 256) {
+ x ^= 285;
+ }
+ }
+ for (let i3 = 255; i3 < 512; i3++) {
+ EXP_TABLE[i3] = EXP_TABLE[i3 - 255];
+ }
+ })();
+ exports2.log = function log(n) {
+ if (n < 1) throw new Error("log(" + n + ")");
+ return LOG_TABLE[n];
+ };
+ exports2.exp = function exp(n) {
+ return EXP_TABLE[n];
+ };
+ exports2.mul = function mul3(x, y) {
+ if (x === 0 || y === 0) return 0;
+ return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]];
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/polynomial.js
+var require_polynomial = __commonJS({
+ "node_modules/qrcode/lib/core/polynomial.js"(exports2) {
+ var GF = require_galois_field();
+ exports2.mul = function mul3(p1, p2) {
+ const coeff = new Uint8Array(p1.length + p2.length - 1);
+ for (let i3 = 0; i3 < p1.length; i3++) {
+ for (let j = 0; j < p2.length; j++) {
+ coeff[i3 + j] ^= GF.mul(p1[i3], p2[j]);
+ }
+ }
+ return coeff;
+ };
+ exports2.mod = function mod2(divident, divisor) {
+ let result = new Uint8Array(divident);
+ while (result.length - divisor.length >= 0) {
+ const coeff = result[0];
+ for (let i3 = 0; i3 < divisor.length; i3++) {
+ result[i3] ^= GF.mul(divisor[i3], coeff);
+ }
+ let offset = 0;
+ while (offset < result.length && result[offset] === 0) offset++;
+ result = result.slice(offset);
+ }
+ return result;
+ };
+ exports2.generateECPolynomial = function generateECPolynomial(degree) {
+ let poly = new Uint8Array([1]);
+ for (let i3 = 0; i3 < degree; i3++) {
+ poly = exports2.mul(poly, new Uint8Array([1, GF.exp(i3)]));
+ }
+ return poly;
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/reed-solomon-encoder.js
+var require_reed_solomon_encoder = __commonJS({
+ "node_modules/qrcode/lib/core/reed-solomon-encoder.js"(exports2, module2) {
+ var Polynomial = require_polynomial();
+ function ReedSolomonEncoder(degree) {
+ this.genPoly = void 0;
+ this.degree = degree;
+ if (this.degree) this.initialize(this.degree);
+ }
+ ReedSolomonEncoder.prototype.initialize = function initialize(degree) {
+ this.degree = degree;
+ this.genPoly = Polynomial.generateECPolynomial(this.degree);
+ };
+ ReedSolomonEncoder.prototype.encode = function encode(data) {
+ if (!this.genPoly) {
+ throw new Error("Encoder not initialized");
+ }
+ const paddedData = new Uint8Array(data.length + this.degree);
+ paddedData.set(data);
+ const remainder = Polynomial.mod(paddedData, this.genPoly);
+ const start = this.degree - remainder.length;
+ if (start > 0) {
+ const buff = new Uint8Array(this.degree);
+ buff.set(remainder, start);
+ return buff;
+ }
+ return remainder;
+ };
+ module2.exports = ReedSolomonEncoder;
+ }
+});
+
+// node_modules/qrcode/lib/core/version-check.js
+var require_version_check = __commonJS({
+ "node_modules/qrcode/lib/core/version-check.js"(exports2) {
+ exports2.isValid = function isValid2(version) {
+ return !isNaN(version) && version >= 1 && version <= 40;
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/regex.js
+var require_regex = __commonJS({
+ "node_modules/qrcode/lib/core/regex.js"(exports2) {
+ var numeric = "[0-9]+";
+ var alphanumeric = "[A-Z $%*+\\-./:]+";
+ var kanji = "(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";
+ kanji = kanji.replace(/u/g, "\\u");
+ var byte = "(?:(?![A-Z0-9 $%*+\\-./:]|" + kanji + ")(?:.|[\r\n]))+";
+ exports2.KANJI = new RegExp(kanji, "g");
+ exports2.BYTE_KANJI = new RegExp("[^A-Z0-9 $%*+\\-./:]+", "g");
+ exports2.BYTE = new RegExp(byte, "g");
+ exports2.NUMERIC = new RegExp(numeric, "g");
+ exports2.ALPHANUMERIC = new RegExp(alphanumeric, "g");
+ var TEST_KANJI = new RegExp("^" + kanji + "$");
+ var TEST_NUMERIC = new RegExp("^" + numeric + "$");
+ var TEST_ALPHANUMERIC = new RegExp("^[A-Z0-9 $%*+\\-./:]+$");
+ exports2.testKanji = function testKanji(str) {
+ return TEST_KANJI.test(str);
+ };
+ exports2.testNumeric = function testNumeric(str) {
+ return TEST_NUMERIC.test(str);
+ };
+ exports2.testAlphanumeric = function testAlphanumeric(str) {
+ return TEST_ALPHANUMERIC.test(str);
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/mode.js
+var require_mode = __commonJS({
+ "node_modules/qrcode/lib/core/mode.js"(exports2) {
+ var VersionCheck = require_version_check();
+ var Regex = require_regex();
+ exports2.NUMERIC = {
+ id: "Numeric",
+ bit: 1 << 0,
+ ccBits: [10, 12, 14]
+ };
+ exports2.ALPHANUMERIC = {
+ id: "Alphanumeric",
+ bit: 1 << 1,
+ ccBits: [9, 11, 13]
+ };
+ exports2.BYTE = {
+ id: "Byte",
+ bit: 1 << 2,
+ ccBits: [8, 16, 16]
+ };
+ exports2.KANJI = {
+ id: "Kanji",
+ bit: 1 << 3,
+ ccBits: [8, 10, 12]
+ };
+ exports2.MIXED = {
+ bit: -1
+ };
+ exports2.getCharCountIndicator = function getCharCountIndicator(mode, version) {
+ if (!mode.ccBits) throw new Error("Invalid mode: " + mode);
+ if (!VersionCheck.isValid(version)) {
+ throw new Error("Invalid version: " + version);
+ }
+ if (version >= 1 && version < 10) return mode.ccBits[0];
+ else if (version < 27) return mode.ccBits[1];
+ return mode.ccBits[2];
+ };
+ exports2.getBestModeForData = function getBestModeForData(dataStr) {
+ if (Regex.testNumeric(dataStr)) return exports2.NUMERIC;
+ else if (Regex.testAlphanumeric(dataStr)) return exports2.ALPHANUMERIC;
+ else if (Regex.testKanji(dataStr)) return exports2.KANJI;
+ else return exports2.BYTE;
+ };
+ exports2.toString = function toString(mode) {
+ if (mode && mode.id) return mode.id;
+ throw new Error("Invalid mode");
+ };
+ exports2.isValid = function isValid2(mode) {
+ return mode && mode.bit && mode.ccBits;
+ };
+ function fromString(string) {
+ if (typeof string !== "string") {
+ throw new Error("Param is not a string");
+ }
+ const lcStr = string.toLowerCase();
+ switch (lcStr) {
+ case "numeric":
+ return exports2.NUMERIC;
+ case "alphanumeric":
+ return exports2.ALPHANUMERIC;
+ case "kanji":
+ return exports2.KANJI;
+ case "byte":
+ return exports2.BYTE;
+ default:
+ throw new Error("Unknown mode: " + string);
+ }
+ }
+ exports2.from = function from(value, defaultValue) {
+ if (exports2.isValid(value)) {
+ return value;
+ }
+ try {
+ return fromString(value);
+ } catch (e) {
+ return defaultValue;
+ }
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/version.js
+var require_version = __commonJS({
+ "node_modules/qrcode/lib/core/version.js"(exports2) {
+ var Utils = require_utils();
+ var ECCode = require_error_correction_code();
+ var ECLevel = require_error_correction_level();
+ var Mode = require_mode();
+ var VersionCheck = require_version_check();
+ var G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0;
+ var G18_BCH = Utils.getBCHDigit(G18);
+ function getBestVersionForDataLength(mode, length, errorCorrectionLevel) {
+ for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {
+ if (length <= exports2.getCapacity(currentVersion, errorCorrectionLevel, mode)) {
+ return currentVersion;
+ }
+ }
+ return void 0;
+ }
+ function getReservedBitsCount(mode, version) {
+ return Mode.getCharCountIndicator(mode, version) + 4;
+ }
+ function getTotalBitsFromDataArray(segments, version) {
+ let totalBits = 0;
+ segments.forEach(function(data) {
+ const reservedBits = getReservedBitsCount(data.mode, version);
+ totalBits += reservedBits + data.getBitsLength();
+ });
+ return totalBits;
+ }
+ function getBestVersionForMixedData(segments, errorCorrectionLevel) {
+ for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {
+ const length = getTotalBitsFromDataArray(segments, currentVersion);
+ if (length <= exports2.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) {
+ return currentVersion;
+ }
+ }
+ return void 0;
+ }
+ exports2.from = function from(value, defaultValue) {
+ if (VersionCheck.isValid(value)) {
+ return parseInt(value, 10);
+ }
+ return defaultValue;
+ };
+ exports2.getCapacity = function getCapacity(version, errorCorrectionLevel, mode) {
+ if (!VersionCheck.isValid(version)) {
+ throw new Error("Invalid QR Code version");
+ }
+ if (typeof mode === "undefined") mode = Mode.BYTE;
+ const totalCodewords = Utils.getSymbolTotalCodewords(version);
+ const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);
+ const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;
+ if (mode === Mode.MIXED) return dataTotalCodewordsBits;
+ const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version);
+ switch (mode) {
+ case Mode.NUMERIC:
+ return Math.floor(usableBits / 10 * 3);
+ case Mode.ALPHANUMERIC:
+ return Math.floor(usableBits / 11 * 2);
+ case Mode.KANJI:
+ return Math.floor(usableBits / 13);
+ case Mode.BYTE:
+ default:
+ return Math.floor(usableBits / 8);
+ }
+ };
+ exports2.getBestVersionForData = function getBestVersionForData(data, errorCorrectionLevel) {
+ let seg;
+ const ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M);
+ if (Array.isArray(data)) {
+ if (data.length > 1) {
+ return getBestVersionForMixedData(data, ecl);
+ }
+ if (data.length === 0) {
+ return 1;
+ }
+ seg = data[0];
+ } else {
+ seg = data;
+ }
+ return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl);
+ };
+ exports2.getEncodedBits = function getEncodedBits(version) {
+ if (!VersionCheck.isValid(version) || version < 7) {
+ throw new Error("Invalid QR Code version");
+ }
+ let d = version << 12;
+ while (Utils.getBCHDigit(d) - G18_BCH >= 0) {
+ d ^= G18 << Utils.getBCHDigit(d) - G18_BCH;
+ }
+ return version << 12 | d;
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/format-info.js
+var require_format_info = __commonJS({
+ "node_modules/qrcode/lib/core/format-info.js"(exports2) {
+ var Utils = require_utils();
+ var G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0;
+ var G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1;
+ var G15_BCH = Utils.getBCHDigit(G15);
+ exports2.getEncodedBits = function getEncodedBits(errorCorrectionLevel, mask) {
+ const data = errorCorrectionLevel.bit << 3 | mask;
+ let d = data << 10;
+ while (Utils.getBCHDigit(d) - G15_BCH >= 0) {
+ d ^= G15 << Utils.getBCHDigit(d) - G15_BCH;
+ }
+ return (data << 10 | d) ^ G15_MASK;
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/numeric-data.js
+var require_numeric_data = __commonJS({
+ "node_modules/qrcode/lib/core/numeric-data.js"(exports2, module2) {
+ var Mode = require_mode();
+ function NumericData(data) {
+ this.mode = Mode.NUMERIC;
+ this.data = data.toString();
+ }
+ NumericData.getBitsLength = function getBitsLength(length) {
+ return 10 * Math.floor(length / 3) + (length % 3 ? length % 3 * 3 + 1 : 0);
+ };
+ NumericData.prototype.getLength = function getLength() {
+ return this.data.length;
+ };
+ NumericData.prototype.getBitsLength = function getBitsLength() {
+ return NumericData.getBitsLength(this.data.length);
+ };
+ NumericData.prototype.write = function write(bitBuffer) {
+ let i3, group, value;
+ for (i3 = 0; i3 + 3 <= this.data.length; i3 += 3) {
+ group = this.data.substr(i3, 3);
+ value = parseInt(group, 10);
+ bitBuffer.put(value, 10);
+ }
+ const remainingNum = this.data.length - i3;
+ if (remainingNum > 0) {
+ group = this.data.substr(i3);
+ value = parseInt(group, 10);
+ bitBuffer.put(value, remainingNum * 3 + 1);
+ }
+ };
+ module2.exports = NumericData;
+ }
+});
+
+// node_modules/qrcode/lib/core/alphanumeric-data.js
+var require_alphanumeric_data = __commonJS({
+ "node_modules/qrcode/lib/core/alphanumeric-data.js"(exports2, module2) {
+ var Mode = require_mode();
+ var ALPHA_NUM_CHARS = [
+ "0",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ " ",
+ "$",
+ "%",
+ "*",
+ "+",
+ "-",
+ ".",
+ "/",
+ ":"
+ ];
+ function AlphanumericData(data) {
+ this.mode = Mode.ALPHANUMERIC;
+ this.data = data;
+ }
+ AlphanumericData.getBitsLength = function getBitsLength(length) {
+ return 11 * Math.floor(length / 2) + 6 * (length % 2);
+ };
+ AlphanumericData.prototype.getLength = function getLength() {
+ return this.data.length;
+ };
+ AlphanumericData.prototype.getBitsLength = function getBitsLength() {
+ return AlphanumericData.getBitsLength(this.data.length);
+ };
+ AlphanumericData.prototype.write = function write(bitBuffer) {
+ let i3;
+ for (i3 = 0; i3 + 2 <= this.data.length; i3 += 2) {
+ let value = ALPHA_NUM_CHARS.indexOf(this.data[i3]) * 45;
+ value += ALPHA_NUM_CHARS.indexOf(this.data[i3 + 1]);
+ bitBuffer.put(value, 11);
+ }
+ if (this.data.length % 2) {
+ bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i3]), 6);
+ }
+ };
+ module2.exports = AlphanumericData;
+ }
+});
+
+// node_modules/qrcode/lib/core/byte-data.js
+var require_byte_data = __commonJS({
+ "node_modules/qrcode/lib/core/byte-data.js"(exports2, module2) {
+ var Mode = require_mode();
+ function ByteData(data) {
+ this.mode = Mode.BYTE;
+ if (typeof data === "string") {
+ this.data = new TextEncoder().encode(data);
+ } else {
+ this.data = new Uint8Array(data);
+ }
+ }
+ ByteData.getBitsLength = function getBitsLength(length) {
+ return length * 8;
+ };
+ ByteData.prototype.getLength = function getLength() {
+ return this.data.length;
+ };
+ ByteData.prototype.getBitsLength = function getBitsLength() {
+ return ByteData.getBitsLength(this.data.length);
+ };
+ ByteData.prototype.write = function(bitBuffer) {
+ for (let i3 = 0, l = this.data.length; i3 < l; i3++) {
+ bitBuffer.put(this.data[i3], 8);
+ }
+ };
+ module2.exports = ByteData;
+ }
+});
+
+// node_modules/qrcode/lib/core/kanji-data.js
+var require_kanji_data = __commonJS({
+ "node_modules/qrcode/lib/core/kanji-data.js"(exports2, module2) {
+ var Mode = require_mode();
+ var Utils = require_utils();
+ function KanjiData(data) {
+ this.mode = Mode.KANJI;
+ this.data = data;
+ }
+ KanjiData.getBitsLength = function getBitsLength(length) {
+ return length * 13;
+ };
+ KanjiData.prototype.getLength = function getLength() {
+ return this.data.length;
+ };
+ KanjiData.prototype.getBitsLength = function getBitsLength() {
+ return KanjiData.getBitsLength(this.data.length);
+ };
+ KanjiData.prototype.write = function(bitBuffer) {
+ let i3;
+ for (i3 = 0; i3 < this.data.length; i3++) {
+ let value = Utils.toSJIS(this.data[i3]);
+ if (value >= 33088 && value <= 40956) {
+ value -= 33088;
+ } else if (value >= 57408 && value <= 60351) {
+ value -= 49472;
+ } else {
+ throw new Error(
+ "Invalid SJIS character: " + this.data[i3] + "\nMake sure your charset is UTF-8"
+ );
+ }
+ value = (value >>> 8 & 255) * 192 + (value & 255);
+ bitBuffer.put(value, 13);
+ }
+ };
+ module2.exports = KanjiData;
+ }
+});
+
+// node_modules/dijkstrajs/dijkstra.js
+var require_dijkstra = __commonJS({
+ "node_modules/dijkstrajs/dijkstra.js"(exports2, module2) {
+ "use strict";
+ var dijkstra = {
+ single_source_shortest_paths: function(graph, s, d) {
+ var predecessors = {};
+ var costs = {};
+ costs[s] = 0;
+ var open = dijkstra.PriorityQueue.make();
+ open.push(s, 0);
+ var closest, u, v, cost_of_s_to_u, adjacent_nodes, cost_of_e, cost_of_s_to_u_plus_cost_of_e, cost_of_s_to_v, first_visit;
+ while (!open.empty()) {
+ closest = open.pop();
+ u = closest.value;
+ cost_of_s_to_u = closest.cost;
+ adjacent_nodes = graph[u] || {};
+ for (v in adjacent_nodes) {
+ if (adjacent_nodes.hasOwnProperty(v)) {
+ cost_of_e = adjacent_nodes[v];
+ cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;
+ cost_of_s_to_v = costs[v];
+ first_visit = typeof costs[v] === "undefined";
+ if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {
+ costs[v] = cost_of_s_to_u_plus_cost_of_e;
+ open.push(v, cost_of_s_to_u_plus_cost_of_e);
+ predecessors[v] = u;
+ }
+ }
+ }
+ }
+ if (typeof d !== "undefined" && typeof costs[d] === "undefined") {
+ var msg = ["Could not find a path from ", s, " to ", d, "."].join("");
+ throw new Error(msg);
+ }
+ return predecessors;
+ },
+ extract_shortest_path_from_predecessor_list: function(predecessors, d) {
+ var nodes = [];
+ var u = d;
+ var predecessor;
+ while (u) {
+ nodes.push(u);
+ predecessor = predecessors[u];
+ u = predecessors[u];
+ }
+ nodes.reverse();
+ return nodes;
+ },
+ find_path: function(graph, s, d) {
+ var predecessors = dijkstra.single_source_shortest_paths(graph, s, d);
+ return dijkstra.extract_shortest_path_from_predecessor_list(
+ predecessors,
+ d
+ );
+ },
+ /**
+ * A very naive priority queue implementation.
+ */
+ PriorityQueue: {
+ make: function(opts) {
+ var T = dijkstra.PriorityQueue, t = {}, key;
+ opts = opts || {};
+ for (key in T) {
+ if (T.hasOwnProperty(key)) {
+ t[key] = T[key];
+ }
+ }
+ t.queue = [];
+ t.sorter = opts.sorter || T.default_sorter;
+ return t;
+ },
+ default_sorter: function(a, b) {
+ return a.cost - b.cost;
+ },
+ /**
+ * Add a new item to the queue and ensure the highest priority element
+ * is at the front of the queue.
+ */
+ push: function(value, cost) {
+ var item = { value, cost };
+ this.queue.push(item);
+ this.queue.sort(this.sorter);
+ },
+ /**
+ * Return the highest priority element in the queue.
+ */
+ pop: function() {
+ return this.queue.shift();
+ },
+ empty: function() {
+ return this.queue.length === 0;
+ }
+ }
+ };
+ if (typeof module2 !== "undefined") {
+ module2.exports = dijkstra;
+ }
+ }
+});
+
+// node_modules/qrcode/lib/core/segments.js
+var require_segments = __commonJS({
+ "node_modules/qrcode/lib/core/segments.js"(exports2) {
+ var Mode = require_mode();
+ var NumericData = require_numeric_data();
+ var AlphanumericData = require_alphanumeric_data();
+ var ByteData = require_byte_data();
+ var KanjiData = require_kanji_data();
+ var Regex = require_regex();
+ var Utils = require_utils();
+ var dijkstra = require_dijkstra();
+ function getStringByteLength(str) {
+ return unescape(encodeURIComponent(str)).length;
+ }
+ function getSegments(regex2, mode, str) {
+ const segments = [];
+ let result;
+ while ((result = regex2.exec(str)) !== null) {
+ segments.push({
+ data: result[0],
+ index: result.index,
+ mode,
+ length: result[0].length
+ });
+ }
+ return segments;
+ }
+ function getSegmentsFromString(dataStr) {
+ const numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr);
+ const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr);
+ let byteSegs;
+ let kanjiSegs;
+ if (Utils.isKanjiModeEnabled()) {
+ byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr);
+ kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr);
+ } else {
+ byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr);
+ kanjiSegs = [];
+ }
+ const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs);
+ return segs.sort(function(s1, s2) {
+ return s1.index - s2.index;
+ }).map(function(obj) {
+ return {
+ data: obj.data,
+ mode: obj.mode,
+ length: obj.length
+ };
+ });
+ }
+ function getSegmentBitsLength(length, mode) {
+ switch (mode) {
+ case Mode.NUMERIC:
+ return NumericData.getBitsLength(length);
+ case Mode.ALPHANUMERIC:
+ return AlphanumericData.getBitsLength(length);
+ case Mode.KANJI:
+ return KanjiData.getBitsLength(length);
+ case Mode.BYTE:
+ return ByteData.getBitsLength(length);
+ }
+ }
+ function mergeSegments(segs) {
+ return segs.reduce(function(acc, curr) {
+ const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null;
+ if (prevSeg && prevSeg.mode === curr.mode) {
+ acc[acc.length - 1].data += curr.data;
+ return acc;
+ }
+ acc.push(curr);
+ return acc;
+ }, []);
+ }
+ function buildNodes(segs) {
+ const nodes = [];
+ for (let i3 = 0; i3 < segs.length; i3++) {
+ const seg = segs[i3];
+ switch (seg.mode) {
+ case Mode.NUMERIC:
+ nodes.push([
+ seg,
+ { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length },
+ { data: seg.data, mode: Mode.BYTE, length: seg.length }
+ ]);
+ break;
+ case Mode.ALPHANUMERIC:
+ nodes.push([
+ seg,
+ { data: seg.data, mode: Mode.BYTE, length: seg.length }
+ ]);
+ break;
+ case Mode.KANJI:
+ nodes.push([
+ seg,
+ { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }
+ ]);
+ break;
+ case Mode.BYTE:
+ nodes.push([
+ { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }
+ ]);
+ }
+ }
+ return nodes;
+ }
+ function buildGraph(nodes, version) {
+ const table = {};
+ const graph = { start: {} };
+ let prevNodeIds = ["start"];
+ for (let i3 = 0; i3 < nodes.length; i3++) {
+ const nodeGroup = nodes[i3];
+ const currentNodeIds = [];
+ for (let j = 0; j < nodeGroup.length; j++) {
+ const node = nodeGroup[j];
+ const key = "" + i3 + j;
+ currentNodeIds.push(key);
+ table[key] = { node, lastCount: 0 };
+ graph[key] = {};
+ for (let n = 0; n < prevNodeIds.length; n++) {
+ const prevNodeId = prevNodeIds[n];
+ if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) {
+ graph[prevNodeId][key] = getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) - getSegmentBitsLength(table[prevNodeId].lastCount, node.mode);
+ table[prevNodeId].lastCount += node.length;
+ } else {
+ if (table[prevNodeId]) table[prevNodeId].lastCount = node.length;
+ graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) + 4 + Mode.getCharCountIndicator(node.mode, version);
+ }
+ }
+ }
+ prevNodeIds = currentNodeIds;
+ }
+ for (let n = 0; n < prevNodeIds.length; n++) {
+ graph[prevNodeIds[n]].end = 0;
+ }
+ return { map: graph, table };
+ }
+ function buildSingleSegment(data, modesHint) {
+ let mode;
+ const bestMode = Mode.getBestModeForData(data);
+ mode = Mode.from(modesHint, bestMode);
+ if (mode !== Mode.BYTE && mode.bit < bestMode.bit) {
+ throw new Error('"' + data + '" cannot be encoded with mode ' + Mode.toString(mode) + ".\n Suggested mode is: " + Mode.toString(bestMode));
+ }
+ if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) {
+ mode = Mode.BYTE;
+ }
+ switch (mode) {
+ case Mode.NUMERIC:
+ return new NumericData(data);
+ case Mode.ALPHANUMERIC:
+ return new AlphanumericData(data);
+ case Mode.KANJI:
+ return new KanjiData(data);
+ case Mode.BYTE:
+ return new ByteData(data);
+ }
+ }
+ exports2.fromArray = function fromArray(array) {
+ return array.reduce(function(acc, seg) {
+ if (typeof seg === "string") {
+ acc.push(buildSingleSegment(seg, null));
+ } else if (seg.data) {
+ acc.push(buildSingleSegment(seg.data, seg.mode));
+ }
+ return acc;
+ }, []);
+ };
+ exports2.fromString = function fromString(data, version) {
+ const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled());
+ const nodes = buildNodes(segs);
+ const graph = buildGraph(nodes, version);
+ const path = dijkstra.find_path(graph.map, "start", "end");
+ const optimizedSegs = [];
+ for (let i3 = 1; i3 < path.length - 1; i3++) {
+ optimizedSegs.push(graph.table[path[i3]].node);
+ }
+ return exports2.fromArray(mergeSegments(optimizedSegs));
+ };
+ exports2.rawSplit = function rawSplit(data) {
+ return exports2.fromArray(
+ getSegmentsFromString(data, Utils.isKanjiModeEnabled())
+ );
+ };
+ }
+});
+
+// node_modules/qrcode/lib/core/qrcode.js
+var require_qrcode = __commonJS({
+ "node_modules/qrcode/lib/core/qrcode.js"(exports2) {
+ var Utils = require_utils();
+ var ECLevel = require_error_correction_level();
+ var BitBuffer = require_bit_buffer();
+ var BitMatrix = require_bit_matrix();
+ var AlignmentPattern = require_alignment_pattern();
+ var FinderPattern = require_finder_pattern();
+ var MaskPattern = require_mask_pattern();
+ var ECCode = require_error_correction_code();
+ var ReedSolomonEncoder = require_reed_solomon_encoder();
+ var Version = require_version();
+ var FormatInfo = require_format_info();
+ var Mode = require_mode();
+ var Segments = require_segments();
+ function setupFinderPattern(matrix, version) {
+ const size = matrix.size;
+ const pos = FinderPattern.getPositions(version);
+ for (let i3 = 0; i3 < pos.length; i3++) {
+ const row = pos[i3][0];
+ const col = pos[i3][1];
+ for (let r = -1; r <= 7; r++) {
+ if (row + r <= -1 || size <= row + r) continue;
+ for (let c = -1; c <= 7; c++) {
+ if (col + c <= -1 || size <= col + c) continue;
+ if (r >= 0 && r <= 6 && (c === 0 || c === 6) || c >= 0 && c <= 6 && (r === 0 || r === 6) || r >= 2 && r <= 4 && c >= 2 && c <= 4) {
+ matrix.set(row + r, col + c, true, true);
+ } else {
+ matrix.set(row + r, col + c, false, true);
+ }
+ }
+ }
+ }
+ }
+ function setupTimingPattern(matrix) {
+ const size = matrix.size;
+ for (let r = 8; r < size - 8; r++) {
+ const value = r % 2 === 0;
+ matrix.set(r, 6, value, true);
+ matrix.set(6, r, value, true);
+ }
+ }
+ function setupAlignmentPattern(matrix, version) {
+ const pos = AlignmentPattern.getPositions(version);
+ for (let i3 = 0; i3 < pos.length; i3++) {
+ const row = pos[i3][0];
+ const col = pos[i3][1];
+ for (let r = -2; r <= 2; r++) {
+ for (let c = -2; c <= 2; c++) {
+ if (r === -2 || r === 2 || c === -2 || c === 2 || r === 0 && c === 0) {
+ matrix.set(row + r, col + c, true, true);
+ } else {
+ matrix.set(row + r, col + c, false, true);
+ }
+ }
+ }
+ }
+ }
+ function setupVersionInfo(matrix, version) {
+ const size = matrix.size;
+ const bits = Version.getEncodedBits(version);
+ let row, col, mod2;
+ for (let i3 = 0; i3 < 18; i3++) {
+ row = Math.floor(i3 / 3);
+ col = i3 % 3 + size - 8 - 3;
+ mod2 = (bits >> i3 & 1) === 1;
+ matrix.set(row, col, mod2, true);
+ matrix.set(col, row, mod2, true);
+ }
+ }
+ function setupFormatInfo(matrix, errorCorrectionLevel, maskPattern) {
+ const size = matrix.size;
+ const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern);
+ let i3, mod2;
+ for (i3 = 0; i3 < 15; i3++) {
+ mod2 = (bits >> i3 & 1) === 1;
+ if (i3 < 6) {
+ matrix.set(i3, 8, mod2, true);
+ } else if (i3 < 8) {
+ matrix.set(i3 + 1, 8, mod2, true);
+ } else {
+ matrix.set(size - 15 + i3, 8, mod2, true);
+ }
+ if (i3 < 8) {
+ matrix.set(8, size - i3 - 1, mod2, true);
+ } else if (i3 < 9) {
+ matrix.set(8, 15 - i3 - 1 + 1, mod2, true);
+ } else {
+ matrix.set(8, 15 - i3 - 1, mod2, true);
+ }
+ }
+ matrix.set(size - 8, 8, 1, true);
+ }
+ function setupData(matrix, data) {
+ const size = matrix.size;
+ let inc = -1;
+ let row = size - 1;
+ let bitIndex = 7;
+ let byteIndex = 0;
+ for (let col = size - 1; col > 0; col -= 2) {
+ if (col === 6) col--;
+ while (true) {
+ for (let c = 0; c < 2; c++) {
+ if (!matrix.isReserved(row, col - c)) {
+ let dark = false;
+ if (byteIndex < data.length) {
+ dark = (data[byteIndex] >>> bitIndex & 1) === 1;
+ }
+ matrix.set(row, col - c, dark);
+ bitIndex--;
+ if (bitIndex === -1) {
+ byteIndex++;
+ bitIndex = 7;
+ }
+ }
+ }
+ row += inc;
+ if (row < 0 || size <= row) {
+ row -= inc;
+ inc = -inc;
+ break;
+ }
+ }
+ }
+ }
+ function createData(version, errorCorrectionLevel, segments) {
+ const buffer = new BitBuffer();
+ segments.forEach(function(data) {
+ buffer.put(data.mode.bit, 4);
+ buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version));
+ data.write(buffer);
+ });
+ const totalCodewords = Utils.getSymbolTotalCodewords(version);
+ const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);
+ const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;
+ if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) {
+ buffer.put(0, 4);
+ }
+ while (buffer.getLengthInBits() % 8 !== 0) {
+ buffer.putBit(0);
+ }
+ const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8;
+ for (let i3 = 0; i3 < remainingByte; i3++) {
+ buffer.put(i3 % 2 ? 17 : 236, 8);
+ }
+ return createCodewords(buffer, version, errorCorrectionLevel);
+ }
+ function createCodewords(bitBuffer, version, errorCorrectionLevel) {
+ const totalCodewords = Utils.getSymbolTotalCodewords(version);
+ const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);
+ const dataTotalCodewords = totalCodewords - ecTotalCodewords;
+ const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel);
+ const blocksInGroup2 = totalCodewords % ecTotalBlocks;
+ const blocksInGroup1 = ecTotalBlocks - blocksInGroup2;
+ const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks);
+ const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks);
+ const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1;
+ const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1;
+ const rs = new ReedSolomonEncoder(ecCount);
+ let offset = 0;
+ const dcData = new Array(ecTotalBlocks);
+ const ecData = new Array(ecTotalBlocks);
+ let maxDataSize = 0;
+ const buffer = new Uint8Array(bitBuffer.buffer);
+ for (let b = 0; b < ecTotalBlocks; b++) {
+ const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2;
+ dcData[b] = buffer.slice(offset, offset + dataSize);
+ ecData[b] = rs.encode(dcData[b]);
+ offset += dataSize;
+ maxDataSize = Math.max(maxDataSize, dataSize);
+ }
+ const data = new Uint8Array(totalCodewords);
+ let index = 0;
+ let i3, r;
+ for (i3 = 0; i3 < maxDataSize; i3++) {
+ for (r = 0; r < ecTotalBlocks; r++) {
+ if (i3 < dcData[r].length) {
+ data[index++] = dcData[r][i3];
+ }
+ }
+ }
+ for (i3 = 0; i3 < ecCount; i3++) {
+ for (r = 0; r < ecTotalBlocks; r++) {
+ data[index++] = ecData[r][i3];
+ }
+ }
+ return data;
+ }
+ function createSymbol(data, version, errorCorrectionLevel, maskPattern) {
+ let segments;
+ if (Array.isArray(data)) {
+ segments = Segments.fromArray(data);
+ } else if (typeof data === "string") {
+ let estimatedVersion = version;
+ if (!estimatedVersion) {
+ const rawSegments = Segments.rawSplit(data);
+ estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel);
+ }
+ segments = Segments.fromString(data, estimatedVersion || 40);
+ } else {
+ throw new Error("Invalid data");
+ }
+ const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel);
+ if (!bestVersion) {
+ throw new Error("The amount of data is too big to be stored in a QR Code");
+ }
+ if (!version) {
+ version = bestVersion;
+ } else if (version < bestVersion) {
+ throw new Error(
+ "\nThe chosen QR Code version cannot contain this amount of data.\nMinimum version required to store current data is: " + bestVersion + ".\n"
+ );
+ }
+ const dataBits = createData(version, errorCorrectionLevel, segments);
+ const moduleCount = Utils.getSymbolSize(version);
+ const modules = new BitMatrix(moduleCount);
+ setupFinderPattern(modules, version);
+ setupTimingPattern(modules);
+ setupAlignmentPattern(modules, version);
+ setupFormatInfo(modules, errorCorrectionLevel, 0);
+ if (version >= 7) {
+ setupVersionInfo(modules, version);
+ }
+ setupData(modules, dataBits);
+ if (isNaN(maskPattern)) {
+ maskPattern = MaskPattern.getBestMask(
+ modules,
+ setupFormatInfo.bind(null, modules, errorCorrectionLevel)
+ );
+ }
+ MaskPattern.applyMask(maskPattern, modules);
+ setupFormatInfo(modules, errorCorrectionLevel, maskPattern);
+ return {
+ modules,
+ version,
+ errorCorrectionLevel,
+ maskPattern,
+ segments
+ };
+ }
+ exports2.create = function create(data, options) {
+ if (typeof data === "undefined" || data === "") {
+ throw new Error("No input text");
+ }
+ let errorCorrectionLevel = ECLevel.M;
+ let version;
+ let mask;
+ if (typeof options !== "undefined") {
+ errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M);
+ version = Version.from(options.version);
+ mask = MaskPattern.from(options.maskPattern);
+ if (options.toSJISFunc) {
+ Utils.setToSJISFunction(options.toSJISFunc);
+ }
+ }
+ return createSymbol(data, version, errorCorrectionLevel, mask);
+ };
+ }
+});
+
+// node_modules/pngjs/lib/chunkstream.js
+var require_chunkstream = __commonJS({
+ "node_modules/pngjs/lib/chunkstream.js"(exports2, module2) {
+ "use strict";
+ var util = require("util");
+ var Stream = require("stream");
+ var ChunkStream = module2.exports = function() {
+ Stream.call(this);
+ this._buffers = [];
+ this._buffered = 0;
+ this._reads = [];
+ this._paused = false;
+ this._encoding = "utf8";
+ this.writable = true;
+ };
+ util.inherits(ChunkStream, Stream);
+ ChunkStream.prototype.read = function(length, callback) {
+ this._reads.push({
+ length: Math.abs(length),
+ // if length < 0 then at most this length
+ allowLess: length < 0,
+ func: callback
+ });
+ process.nextTick(
+ function() {
+ this._process();
+ if (this._paused && this._reads && this._reads.length > 0) {
+ this._paused = false;
+ this.emit("drain");
+ }
+ }.bind(this)
+ );
+ };
+ ChunkStream.prototype.write = function(data, encoding) {
+ if (!this.writable) {
+ this.emit("error", new Error("Stream not writable"));
+ return false;
+ }
+ let dataBuffer;
+ if (Buffer.isBuffer(data)) {
+ dataBuffer = data;
+ } else {
+ dataBuffer = Buffer.from(data, encoding || this._encoding);
+ }
+ this._buffers.push(dataBuffer);
+ this._buffered += dataBuffer.length;
+ this._process();
+ if (this._reads && this._reads.length === 0) {
+ this._paused = true;
+ }
+ return this.writable && !this._paused;
+ };
+ ChunkStream.prototype.end = function(data, encoding) {
+ if (data) {
+ this.write(data, encoding);
+ }
+ this.writable = false;
+ if (!this._buffers) {
+ return;
+ }
+ if (this._buffers.length === 0) {
+ this._end();
+ } else {
+ this._buffers.push(null);
+ this._process();
+ }
+ };
+ ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
+ ChunkStream.prototype._end = function() {
+ if (this._reads.length > 0) {
+ this.emit("error", new Error("Unexpected end of input"));
+ }
+ this.destroy();
+ };
+ ChunkStream.prototype.destroy = function() {
+ if (!this._buffers) {
+ return;
+ }
+ this.writable = false;
+ this._reads = null;
+ this._buffers = null;
+ this.emit("close");
+ };
+ ChunkStream.prototype._processReadAllowingLess = function(read) {
+ this._reads.shift();
+ let smallerBuf = this._buffers[0];
+ if (smallerBuf.length > read.length) {
+ this._buffered -= read.length;
+ this._buffers[0] = smallerBuf.slice(read.length);
+ read.func.call(this, smallerBuf.slice(0, read.length));
+ } else {
+ this._buffered -= smallerBuf.length;
+ this._buffers.shift();
+ read.func.call(this, smallerBuf);
+ }
+ };
+ ChunkStream.prototype._processRead = function(read) {
+ this._reads.shift();
+ let pos = 0;
+ let count = 0;
+ let data = Buffer.alloc(read.length);
+ while (pos < read.length) {
+ let buf = this._buffers[count++];
+ let len = Math.min(buf.length, read.length - pos);
+ buf.copy(data, pos, 0, len);
+ pos += len;
+ if (len !== buf.length) {
+ this._buffers[--count] = buf.slice(len);
+ }
+ }
+ if (count > 0) {
+ this._buffers.splice(0, count);
+ }
+ this._buffered -= read.length;
+ read.func.call(this, data);
+ };
+ ChunkStream.prototype._process = function() {
+ try {
+ while (this._buffered > 0 && this._reads && this._reads.length > 0) {
+ let read = this._reads[0];
+ if (read.allowLess) {
+ this._processReadAllowingLess(read);
+ } else if (this._buffered >= read.length) {
+ this._processRead(read);
+ } else {
+ break;
+ }
+ }
+ if (this._buffers && !this.writable) {
+ this._end();
+ }
+ } catch (ex) {
+ this.emit("error", ex);
+ }
+ };
+ }
+});
+
+// node_modules/pngjs/lib/interlace.js
+var require_interlace = __commonJS({
+ "node_modules/pngjs/lib/interlace.js"(exports2) {
+ "use strict";
+ var imagePasses = [
+ {
+ // pass 1 - 1px
+ x: [0],
+ y: [0]
+ },
+ {
+ // pass 2 - 1px
+ x: [4],
+ y: [0]
+ },
+ {
+ // pass 3 - 2px
+ x: [0, 4],
+ y: [4]
+ },
+ {
+ // pass 4 - 4px
+ x: [2, 6],
+ y: [0, 4]
+ },
+ {
+ // pass 5 - 8px
+ x: [0, 2, 4, 6],
+ y: [2, 6]
+ },
+ {
+ // pass 6 - 16px
+ x: [1, 3, 5, 7],
+ y: [0, 2, 4, 6]
+ },
+ {
+ // pass 7 - 32px
+ x: [0, 1, 2, 3, 4, 5, 6, 7],
+ y: [1, 3, 5, 7]
+ }
+ ];
+ exports2.getImagePasses = function(width, height) {
+ let images = [];
+ let xLeftOver = width % 8;
+ let yLeftOver = height % 8;
+ let xRepeats = (width - xLeftOver) / 8;
+ let yRepeats = (height - yLeftOver) / 8;
+ for (let i3 = 0; i3 < imagePasses.length; i3++) {
+ let pass = imagePasses[i3];
+ let passWidth = xRepeats * pass.x.length;
+ let passHeight = yRepeats * pass.y.length;
+ for (let j = 0; j < pass.x.length; j++) {
+ if (pass.x[j] < xLeftOver) {
+ passWidth++;
+ } else {
+ break;
+ }
+ }
+ for (let j = 0; j < pass.y.length; j++) {
+ if (pass.y[j] < yLeftOver) {
+ passHeight++;
+ } else {
+ break;
+ }
+ }
+ if (passWidth > 0 && passHeight > 0) {
+ images.push({ width: passWidth, height: passHeight, index: i3 });
+ }
+ }
+ return images;
+ };
+ exports2.getInterlaceIterator = function(width) {
+ return function(x, y, pass) {
+ let outerXLeftOver = x % imagePasses[pass].x.length;
+ let outerX = (x - outerXLeftOver) / imagePasses[pass].x.length * 8 + imagePasses[pass].x[outerXLeftOver];
+ let outerYLeftOver = y % imagePasses[pass].y.length;
+ let outerY = (y - outerYLeftOver) / imagePasses[pass].y.length * 8 + imagePasses[pass].y[outerYLeftOver];
+ return outerX * 4 + outerY * width * 4;
+ };
+ };
+ }
+});
+
+// node_modules/pngjs/lib/paeth-predictor.js
+var require_paeth_predictor = __commonJS({
+ "node_modules/pngjs/lib/paeth-predictor.js"(exports2, module2) {
+ "use strict";
+ module2.exports = function paethPredictor(left, above, upLeft) {
+ let paeth = left + above - upLeft;
+ let pLeft = Math.abs(paeth - left);
+ let pAbove = Math.abs(paeth - above);
+ let pUpLeft = Math.abs(paeth - upLeft);
+ if (pLeft <= pAbove && pLeft <= pUpLeft) {
+ return left;
+ }
+ if (pAbove <= pUpLeft) {
+ return above;
+ }
+ return upLeft;
+ };
+ }
+});
+
+// node_modules/pngjs/lib/filter-parse.js
+var require_filter_parse = __commonJS({
+ "node_modules/pngjs/lib/filter-parse.js"(exports2, module2) {
+ "use strict";
+ var interlaceUtils = require_interlace();
+ var paethPredictor = require_paeth_predictor();
+ function getByteWidth(width, bpp, depth) {
+ let byteWidth = width * bpp;
+ if (depth !== 8) {
+ byteWidth = Math.ceil(byteWidth / (8 / depth));
+ }
+ return byteWidth;
+ }
+ var Filter = module2.exports = function(bitmapInfo, dependencies) {
+ let width = bitmapInfo.width;
+ let height = bitmapInfo.height;
+ let interlace = bitmapInfo.interlace;
+ let bpp = bitmapInfo.bpp;
+ let depth = bitmapInfo.depth;
+ this.read = dependencies.read;
+ this.write = dependencies.write;
+ this.complete = dependencies.complete;
+ this._imageIndex = 0;
+ this._images = [];
+ if (interlace) {
+ let passes = interlaceUtils.getImagePasses(width, height);
+ for (let i3 = 0; i3 < passes.length; i3++) {
+ this._images.push({
+ byteWidth: getByteWidth(passes[i3].width, bpp, depth),
+ height: passes[i3].height,
+ lineIndex: 0
+ });
+ }
+ } else {
+ this._images.push({
+ byteWidth: getByteWidth(width, bpp, depth),
+ height,
+ lineIndex: 0
+ });
+ }
+ if (depth === 8) {
+ this._xComparison = bpp;
+ } else if (depth === 16) {
+ this._xComparison = bpp * 2;
+ } else {
+ this._xComparison = 1;
+ }
+ };
+ Filter.prototype.start = function() {
+ this.read(
+ this._images[this._imageIndex].byteWidth + 1,
+ this._reverseFilterLine.bind(this)
+ );
+ };
+ Filter.prototype._unFilterType1 = function(rawData, unfilteredLine, byteWidth) {
+ let xComparison = this._xComparison;
+ let xBiggerThan = xComparison - 1;
+ for (let x = 0; x < byteWidth; x++) {
+ let rawByte = rawData[1 + x];
+ let f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
+ unfilteredLine[x] = rawByte + f1Left;
+ }
+ };
+ Filter.prototype._unFilterType2 = function(rawData, unfilteredLine, byteWidth) {
+ let lastLine = this._lastLine;
+ for (let x = 0; x < byteWidth; x++) {
+ let rawByte = rawData[1 + x];
+ let f2Up = lastLine ? lastLine[x] : 0;
+ unfilteredLine[x] = rawByte + f2Up;
+ }
+ };
+ Filter.prototype._unFilterType3 = function(rawData, unfilteredLine, byteWidth) {
+ let xComparison = this._xComparison;
+ let xBiggerThan = xComparison - 1;
+ let lastLine = this._lastLine;
+ for (let x = 0; x < byteWidth; x++) {
+ let rawByte = rawData[1 + x];
+ let f3Up = lastLine ? lastLine[x] : 0;
+ let f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
+ let f3Add = Math.floor((f3Left + f3Up) / 2);
+ unfilteredLine[x] = rawByte + f3Add;
+ }
+ };
+ Filter.prototype._unFilterType4 = function(rawData, unfilteredLine, byteWidth) {
+ let xComparison = this._xComparison;
+ let xBiggerThan = xComparison - 1;
+ let lastLine = this._lastLine;
+ for (let x = 0; x < byteWidth; x++) {
+ let rawByte = rawData[1 + x];
+ let f4Up = lastLine ? lastLine[x] : 0;
+ let f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
+ let f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0;
+ let f4Add = paethPredictor(f4Left, f4Up, f4UpLeft);
+ unfilteredLine[x] = rawByte + f4Add;
+ }
+ };
+ Filter.prototype._reverseFilterLine = function(rawData) {
+ let filter = rawData[0];
+ let unfilteredLine;
+ let currentImage = this._images[this._imageIndex];
+ let byteWidth = currentImage.byteWidth;
+ if (filter === 0) {
+ unfilteredLine = rawData.slice(1, byteWidth + 1);
+ } else {
+ unfilteredLine = Buffer.alloc(byteWidth);
+ switch (filter) {
+ case 1:
+ this._unFilterType1(rawData, unfilteredLine, byteWidth);
+ break;
+ case 2:
+ this._unFilterType2(rawData, unfilteredLine, byteWidth);
+ break;
+ case 3:
+ this._unFilterType3(rawData, unfilteredLine, byteWidth);
+ break;
+ case 4:
+ this._unFilterType4(rawData, unfilteredLine, byteWidth);
+ break;
+ default:
+ throw new Error("Unrecognised filter type - " + filter);
+ }
+ }
+ this.write(unfilteredLine);
+ currentImage.lineIndex++;
+ if (currentImage.lineIndex >= currentImage.height) {
+ this._lastLine = null;
+ this._imageIndex++;
+ currentImage = this._images[this._imageIndex];
+ } else {
+ this._lastLine = unfilteredLine;
+ }
+ if (currentImage) {
+ this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this));
+ } else {
+ this._lastLine = null;
+ this.complete();
+ }
+ };
+ }
+});
+
+// node_modules/pngjs/lib/filter-parse-async.js
+var require_filter_parse_async = __commonJS({
+ "node_modules/pngjs/lib/filter-parse-async.js"(exports2, module2) {
+ "use strict";
+ var util = require("util");
+ var ChunkStream = require_chunkstream();
+ var Filter = require_filter_parse();
+ var FilterAsync = module2.exports = function(bitmapInfo) {
+ ChunkStream.call(this);
+ let buffers = [];
+ let that = this;
+ this._filter = new Filter(bitmapInfo, {
+ read: this.read.bind(this),
+ write: function(buffer) {
+ buffers.push(buffer);
+ },
+ complete: function() {
+ that.emit("complete", Buffer.concat(buffers));
+ }
+ });
+ this._filter.start();
+ };
+ util.inherits(FilterAsync, ChunkStream);
+ }
+});
+
+// node_modules/pngjs/lib/constants.js
+var require_constants2 = __commonJS({
+ "node_modules/pngjs/lib/constants.js"(exports2, module2) {
+ "use strict";
+ module2.exports = {
+ PNG_SIGNATURE: [137, 80, 78, 71, 13, 10, 26, 10],
+ TYPE_IHDR: 1229472850,
+ TYPE_IEND: 1229278788,
+ TYPE_IDAT: 1229209940,
+ TYPE_PLTE: 1347179589,
+ TYPE_tRNS: 1951551059,
+ // eslint-disable-line camelcase
+ TYPE_gAMA: 1732332865,
+ // eslint-disable-line camelcase
+ // color-type bits
+ COLORTYPE_GRAYSCALE: 0,
+ COLORTYPE_PALETTE: 1,
+ COLORTYPE_COLOR: 2,
+ COLORTYPE_ALPHA: 4,
+ // e.g. grayscale and alpha
+ // color-type combinations
+ COLORTYPE_PALETTE_COLOR: 3,
+ COLORTYPE_COLOR_ALPHA: 6,
+ COLORTYPE_TO_BPP_MAP: {
+ 0: 1,
+ 2: 3,
+ 3: 1,
+ 4: 2,
+ 6: 4
+ },
+ GAMMA_DIVISION: 1e5
+ };
+ }
+});
+
+// node_modules/pngjs/lib/crc.js
+var require_crc = __commonJS({
+ "node_modules/pngjs/lib/crc.js"(exports2, module2) {
+ "use strict";
+ var crcTable = [];
+ (function() {
+ for (let i3 = 0; i3 < 256; i3++) {
+ let currentCrc = i3;
+ for (let j = 0; j < 8; j++) {
+ if (currentCrc & 1) {
+ currentCrc = 3988292384 ^ currentCrc >>> 1;
+ } else {
+ currentCrc = currentCrc >>> 1;
+ }
+ }
+ crcTable[i3] = currentCrc;
+ }
+ })();
+ var CrcCalculator = module2.exports = function() {
+ this._crc = -1;
+ };
+ CrcCalculator.prototype.write = function(data) {
+ for (let i3 = 0; i3 < data.length; i3++) {
+ this._crc = crcTable[(this._crc ^ data[i3]) & 255] ^ this._crc >>> 8;
+ }
+ return true;
+ };
+ CrcCalculator.prototype.crc32 = function() {
+ return this._crc ^ -1;
+ };
+ CrcCalculator.crc32 = function(buf) {
+ let crc = -1;
+ for (let i3 = 0; i3 < buf.length; i3++) {
+ crc = crcTable[(crc ^ buf[i3]) & 255] ^ crc >>> 8;
+ }
+ return crc ^ -1;
+ };
+ }
+});
+
+// node_modules/pngjs/lib/parser.js
+var require_parser = __commonJS({
+ "node_modules/pngjs/lib/parser.js"(exports2, module2) {
+ "use strict";
+ var constants = require_constants2();
+ var CrcCalculator = require_crc();
+ var Parser = module2.exports = function(options, dependencies) {
+ this._options = options;
+ options.checkCRC = options.checkCRC !== false;
+ this._hasIHDR = false;
+ this._hasIEND = false;
+ this._emittedHeadersFinished = false;
+ this._palette = [];
+ this._colorType = 0;
+ this._chunks = {};
+ this._chunks[constants.TYPE_IHDR] = this._handleIHDR.bind(this);
+ this._chunks[constants.TYPE_IEND] = this._handleIEND.bind(this);
+ this._chunks[constants.TYPE_IDAT] = this._handleIDAT.bind(this);
+ this._chunks[constants.TYPE_PLTE] = this._handlePLTE.bind(this);
+ this._chunks[constants.TYPE_tRNS] = this._handleTRNS.bind(this);
+ this._chunks[constants.TYPE_gAMA] = this._handleGAMA.bind(this);
+ this.read = dependencies.read;
+ this.error = dependencies.error;
+ this.metadata = dependencies.metadata;
+ this.gamma = dependencies.gamma;
+ this.transColor = dependencies.transColor;
+ this.palette = dependencies.palette;
+ this.parsed = dependencies.parsed;
+ this.inflateData = dependencies.inflateData;
+ this.finished = dependencies.finished;
+ this.simpleTransparency = dependencies.simpleTransparency;
+ this.headersFinished = dependencies.headersFinished || function() {
+ };
+ };
+ Parser.prototype.start = function() {
+ this.read(constants.PNG_SIGNATURE.length, this._parseSignature.bind(this));
+ };
+ Parser.prototype._parseSignature = function(data) {
+ let signature = constants.PNG_SIGNATURE;
+ for (let i3 = 0; i3 < signature.length; i3++) {
+ if (data[i3] !== signature[i3]) {
+ this.error(new Error("Invalid file signature"));
+ return;
+ }
+ }
+ this.read(8, this._parseChunkBegin.bind(this));
+ };
+ Parser.prototype._parseChunkBegin = function(data) {
+ let length = data.readUInt32BE(0);
+ let type = data.readUInt32BE(4);
+ let name = "";
+ for (let i3 = 4; i3 < 8; i3++) {
+ name += String.fromCharCode(data[i3]);
+ }
+ let ancillary = Boolean(data[4] & 32);
+ if (!this._hasIHDR && type !== constants.TYPE_IHDR) {
+ this.error(new Error("Expected IHDR on beggining"));
+ return;
+ }
+ this._crc = new CrcCalculator();
+ this._crc.write(Buffer.from(name));
+ if (this._chunks[type]) {
+ return this._chunks[type](length);
+ }
+ if (!ancillary) {
+ this.error(new Error("Unsupported critical chunk type " + name));
+ return;
+ }
+ this.read(length + 4, this._skipChunk.bind(this));
+ };
+ Parser.prototype._skipChunk = function() {
+ this.read(8, this._parseChunkBegin.bind(this));
+ };
+ Parser.prototype._handleChunkEnd = function() {
+ this.read(4, this._parseChunkEnd.bind(this));
+ };
+ Parser.prototype._parseChunkEnd = function(data) {
+ let fileCrc = data.readInt32BE(0);
+ let calcCrc = this._crc.crc32();
+ if (this._options.checkCRC && calcCrc !== fileCrc) {
+ this.error(new Error("Crc error - " + fileCrc + " - " + calcCrc));
+ return;
+ }
+ if (!this._hasIEND) {
+ this.read(8, this._parseChunkBegin.bind(this));
+ }
+ };
+ Parser.prototype._handleIHDR = function(length) {
+ this.read(length, this._parseIHDR.bind(this));
+ };
+ Parser.prototype._parseIHDR = function(data) {
+ this._crc.write(data);
+ let width = data.readUInt32BE(0);
+ let height = data.readUInt32BE(4);
+ let depth = data[8];
+ let colorType = data[9];
+ let compr = data[10];
+ let filter = data[11];
+ let interlace = data[12];
+ if (depth !== 8 && depth !== 4 && depth !== 2 && depth !== 1 && depth !== 16) {
+ this.error(new Error("Unsupported bit depth " + depth));
+ return;
+ }
+ if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) {
+ this.error(new Error("Unsupported color type"));
+ return;
+ }
+ if (compr !== 0) {
+ this.error(new Error("Unsupported compression method"));
+ return;
+ }
+ if (filter !== 0) {
+ this.error(new Error("Unsupported filter method"));
+ return;
+ }
+ if (interlace !== 0 && interlace !== 1) {
+ this.error(new Error("Unsupported interlace method"));
+ return;
+ }
+ this._colorType = colorType;
+ let bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType];
+ this._hasIHDR = true;
+ this.metadata({
+ width,
+ height,
+ depth,
+ interlace: Boolean(interlace),
+ palette: Boolean(colorType & constants.COLORTYPE_PALETTE),
+ color: Boolean(colorType & constants.COLORTYPE_COLOR),
+ alpha: Boolean(colorType & constants.COLORTYPE_ALPHA),
+ bpp,
+ colorType
+ });
+ this._handleChunkEnd();
+ };
+ Parser.prototype._handlePLTE = function(length) {
+ this.read(length, this._parsePLTE.bind(this));
+ };
+ Parser.prototype._parsePLTE = function(data) {
+ this._crc.write(data);
+ let entries = Math.floor(data.length / 3);
+ for (let i3 = 0; i3 < entries; i3++) {
+ this._palette.push([data[i3 * 3], data[i3 * 3 + 1], data[i3 * 3 + 2], 255]);
+ }
+ this.palette(this._palette);
+ this._handleChunkEnd();
+ };
+ Parser.prototype._handleTRNS = function(length) {
+ this.simpleTransparency();
+ this.read(length, this._parseTRNS.bind(this));
+ };
+ Parser.prototype._parseTRNS = function(data) {
+ this._crc.write(data);
+ if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) {
+ if (this._palette.length === 0) {
+ this.error(new Error("Transparency chunk must be after palette"));
+ return;
+ }
+ if (data.length > this._palette.length) {
+ this.error(new Error("More transparent colors than palette size"));
+ return;
+ }
+ for (let i3 = 0; i3 < data.length; i3++) {
+ this._palette[i3][3] = data[i3];
+ }
+ this.palette(this._palette);
+ }
+ if (this._colorType === constants.COLORTYPE_GRAYSCALE) {
+ this.transColor([data.readUInt16BE(0)]);
+ }
+ if (this._colorType === constants.COLORTYPE_COLOR) {
+ this.transColor([
+ data.readUInt16BE(0),
+ data.readUInt16BE(2),
+ data.readUInt16BE(4)
+ ]);
+ }
+ this._handleChunkEnd();
+ };
+ Parser.prototype._handleGAMA = function(length) {
+ this.read(length, this._parseGAMA.bind(this));
+ };
+ Parser.prototype._parseGAMA = function(data) {
+ this._crc.write(data);
+ this.gamma(data.readUInt32BE(0) / constants.GAMMA_DIVISION);
+ this._handleChunkEnd();
+ };
+ Parser.prototype._handleIDAT = function(length) {
+ if (!this._emittedHeadersFinished) {
+ this._emittedHeadersFinished = true;
+ this.headersFinished();
+ }
+ this.read(-length, this._parseIDAT.bind(this, length));
+ };
+ Parser.prototype._parseIDAT = function(length, data) {
+ this._crc.write(data);
+ if (this._colorType === constants.COLORTYPE_PALETTE_COLOR && this._palette.length === 0) {
+ throw new Error("Expected palette not found");
+ }
+ this.inflateData(data);
+ let leftOverLength = length - data.length;
+ if (leftOverLength > 0) {
+ this._handleIDAT(leftOverLength);
+ } else {
+ this._handleChunkEnd();
+ }
+ };
+ Parser.prototype._handleIEND = function(length) {
+ this.read(length, this._parseIEND.bind(this));
+ };
+ Parser.prototype._parseIEND = function(data) {
+ this._crc.write(data);
+ this._hasIEND = true;
+ this._handleChunkEnd();
+ if (this.finished) {
+ this.finished();
+ }
+ };
+ }
+});
+
+// node_modules/pngjs/lib/bitmapper.js
+var require_bitmapper = __commonJS({
+ "node_modules/pngjs/lib/bitmapper.js"(exports2) {
+ "use strict";
+ var interlaceUtils = require_interlace();
+ var pixelBppMapper = [
+ // 0 - dummy entry
+ function() {
+ },
+ // 1 - L
+ // 0: 0, 1: 0, 2: 0, 3: 0xff
+ function(pxData, data, pxPos, rawPos) {
+ if (rawPos === data.length) {
+ throw new Error("Ran out of data");
+ }
+ let pixel = data[rawPos];
+ pxData[pxPos] = pixel;
+ pxData[pxPos + 1] = pixel;
+ pxData[pxPos + 2] = pixel;
+ pxData[pxPos + 3] = 255;
+ },
+ // 2 - LA
+ // 0: 0, 1: 0, 2: 0, 3: 1
+ function(pxData, data, pxPos, rawPos) {
+ if (rawPos + 1 >= data.length) {
+ throw new Error("Ran out of data");
+ }
+ let pixel = data[rawPos];
+ pxData[pxPos] = pixel;
+ pxData[pxPos + 1] = pixel;
+ pxData[pxPos + 2] = pixel;
+ pxData[pxPos + 3] = data[rawPos + 1];
+ },
+ // 3 - RGB
+ // 0: 0, 1: 1, 2: 2, 3: 0xff
+ function(pxData, data, pxPos, rawPos) {
+ if (rawPos + 2 >= data.length) {
+ throw new Error("Ran out of data");
+ }
+ pxData[pxPos] = data[rawPos];
+ pxData[pxPos + 1] = data[rawPos + 1];
+ pxData[pxPos + 2] = data[rawPos + 2];
+ pxData[pxPos + 3] = 255;
+ },
+ // 4 - RGBA
+ // 0: 0, 1: 1, 2: 2, 3: 3
+ function(pxData, data, pxPos, rawPos) {
+ if (rawPos + 3 >= data.length) {
+ throw new Error("Ran out of data");
+ }
+ pxData[pxPos] = data[rawPos];
+ pxData[pxPos + 1] = data[rawPos + 1];
+ pxData[pxPos + 2] = data[rawPos + 2];
+ pxData[pxPos + 3] = data[rawPos + 3];
+ }
+ ];
+ var pixelBppCustomMapper = [
+ // 0 - dummy entry
+ function() {
+ },
+ // 1 - L
+ // 0: 0, 1: 0, 2: 0, 3: 0xff
+ function(pxData, pixelData, pxPos, maxBit) {
+ let pixel = pixelData[0];
+ pxData[pxPos] = pixel;
+ pxData[pxPos + 1] = pixel;
+ pxData[pxPos + 2] = pixel;
+ pxData[pxPos + 3] = maxBit;
+ },
+ // 2 - LA
+ // 0: 0, 1: 0, 2: 0, 3: 1
+ function(pxData, pixelData, pxPos) {
+ let pixel = pixelData[0];
+ pxData[pxPos] = pixel;
+ pxData[pxPos + 1] = pixel;
+ pxData[pxPos + 2] = pixel;
+ pxData[pxPos + 3] = pixelData[1];
+ },
+ // 3 - RGB
+ // 0: 0, 1: 1, 2: 2, 3: 0xff
+ function(pxData, pixelData, pxPos, maxBit) {
+ pxData[pxPos] = pixelData[0];
+ pxData[pxPos + 1] = pixelData[1];
+ pxData[pxPos + 2] = pixelData[2];
+ pxData[pxPos + 3] = maxBit;
+ },
+ // 4 - RGBA
+ // 0: 0, 1: 1, 2: 2, 3: 3
+ function(pxData, pixelData, pxPos) {
+ pxData[pxPos] = pixelData[0];
+ pxData[pxPos + 1] = pixelData[1];
+ pxData[pxPos + 2] = pixelData[2];
+ pxData[pxPos + 3] = pixelData[3];
+ }
+ ];
+ function bitRetriever(data, depth) {
+ let leftOver = [];
+ let i3 = 0;
+ function split() {
+ if (i3 === data.length) {
+ throw new Error("Ran out of data");
+ }
+ let byte = data[i3];
+ i3++;
+ let byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
+ switch (depth) {
+ default:
+ throw new Error("unrecognised depth");
+ case 16:
+ byte2 = data[i3];
+ i3++;
+ leftOver.push((byte << 8) + byte2);
+ break;
+ case 4:
+ byte2 = byte & 15;
+ byte1 = byte >> 4;
+ leftOver.push(byte1, byte2);
+ break;
+ case 2:
+ byte4 = byte & 3;
+ byte3 = byte >> 2 & 3;
+ byte2 = byte >> 4 & 3;
+ byte1 = byte >> 6 & 3;
+ leftOver.push(byte1, byte2, byte3, byte4);
+ break;
+ case 1:
+ byte8 = byte & 1;
+ byte7 = byte >> 1 & 1;
+ byte6 = byte >> 2 & 1;
+ byte5 = byte >> 3 & 1;
+ byte4 = byte >> 4 & 1;
+ byte3 = byte >> 5 & 1;
+ byte2 = byte >> 6 & 1;
+ byte1 = byte >> 7 & 1;
+ leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8);
+ break;
+ }
+ }
+ return {
+ get: function(count) {
+ while (leftOver.length < count) {
+ split();
+ }
+ let returner = leftOver.slice(0, count);
+ leftOver = leftOver.slice(count);
+ return returner;
+ },
+ resetAfterLine: function() {
+ leftOver.length = 0;
+ },
+ end: function() {
+ if (i3 !== data.length) {
+ throw new Error("extra data found");
+ }
+ }
+ };
+ }
+ function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) {
+ let imageWidth = image.width;
+ let imageHeight = image.height;
+ let imagePass = image.index;
+ for (let y = 0; y < imageHeight; y++) {
+ for (let x = 0; x < imageWidth; x++) {
+ let pxPos = getPxPos(x, y, imagePass);
+ pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
+ rawPos += bpp;
+ }
+ }
+ return rawPos;
+ }
+ function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) {
+ let imageWidth = image.width;
+ let imageHeight = image.height;
+ let imagePass = image.index;
+ for (let y = 0; y < imageHeight; y++) {
+ for (let x = 0; x < imageWidth; x++) {
+ let pixelData = bits.get(bpp);
+ let pxPos = getPxPos(x, y, imagePass);
+ pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
+ }
+ bits.resetAfterLine();
+ }
+ }
+ exports2.dataToBitMap = function(data, bitmapInfo) {
+ let width = bitmapInfo.width;
+ let height = bitmapInfo.height;
+ let depth = bitmapInfo.depth;
+ let bpp = bitmapInfo.bpp;
+ let interlace = bitmapInfo.interlace;
+ let bits;
+ if (depth !== 8) {
+ bits = bitRetriever(data, depth);
+ }
+ let pxData;
+ if (depth <= 8) {
+ pxData = Buffer.alloc(width * height * 4);
+ } else {
+ pxData = new Uint16Array(width * height * 4);
+ }
+ let maxBit = Math.pow(2, depth) - 1;
+ let rawPos = 0;
+ let images;
+ let getPxPos;
+ if (interlace) {
+ images = interlaceUtils.getImagePasses(width, height);
+ getPxPos = interlaceUtils.getInterlaceIterator(width, height);
+ } else {
+ let nonInterlacedPxPos = 0;
+ getPxPos = function() {
+ let returner = nonInterlacedPxPos;
+ nonInterlacedPxPos += 4;
+ return returner;
+ };
+ images = [{ width, height }];
+ }
+ for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
+ if (depth === 8) {
+ rawPos = mapImage8Bit(
+ images[imageIndex],
+ pxData,
+ getPxPos,
+ bpp,
+ data,
+ rawPos
+ );
+ } else {
+ mapImageCustomBit(
+ images[imageIndex],
+ pxData,
+ getPxPos,
+ bpp,
+ bits,
+ maxBit
+ );
+ }
+ }
+ if (depth === 8) {
+ if (rawPos !== data.length) {
+ throw new Error("extra data found");
+ }
+ } else {
+ bits.end();
+ }
+ return pxData;
+ };
+ }
+});
+
+// node_modules/pngjs/lib/format-normaliser.js
+var require_format_normaliser = __commonJS({
+ "node_modules/pngjs/lib/format-normaliser.js"(exports2, module2) {
+ "use strict";
+ function dePalette(indata, outdata, width, height, palette) {
+ let pxPos = 0;
+ for (let y = 0; y < height; y++) {
+ for (let x = 0; x < width; x++) {
+ let color = palette[indata[pxPos]];
+ if (!color) {
+ throw new Error("index " + indata[pxPos] + " not in palette");
+ }
+ for (let i3 = 0; i3 < 4; i3++) {
+ outdata[pxPos + i3] = color[i3];
+ }
+ pxPos += 4;
+ }
+ }
+ }
+ function replaceTransparentColor(indata, outdata, width, height, transColor) {
+ let pxPos = 0;
+ for (let y = 0; y < height; y++) {
+ for (let x = 0; x < width; x++) {
+ let makeTrans = false;
+ if (transColor.length === 1) {
+ if (transColor[0] === indata[pxPos]) {
+ makeTrans = true;
+ }
+ } else if (transColor[0] === indata[pxPos] && transColor[1] === indata[pxPos + 1] && transColor[2] === indata[pxPos + 2]) {
+ makeTrans = true;
+ }
+ if (makeTrans) {
+ for (let i3 = 0; i3 < 4; i3++) {
+ outdata[pxPos + i3] = 0;
+ }
+ }
+ pxPos += 4;
+ }
+ }
+ }
+ function scaleDepth(indata, outdata, width, height, depth) {
+ let maxOutSample = 255;
+ let maxInSample = Math.pow(2, depth) - 1;
+ let pxPos = 0;
+ for (let y = 0; y < height; y++) {
+ for (let x = 0; x < width; x++) {
+ for (let i3 = 0; i3 < 4; i3++) {
+ outdata[pxPos + i3] = Math.floor(
+ indata[pxPos + i3] * maxOutSample / maxInSample + 0.5
+ );
+ }
+ pxPos += 4;
+ }
+ }
+ }
+ module2.exports = function(indata, imageData) {
+ let depth = imageData.depth;
+ let width = imageData.width;
+ let height = imageData.height;
+ let colorType = imageData.colorType;
+ let transColor = imageData.transColor;
+ let palette = imageData.palette;
+ let outdata = indata;
+ if (colorType === 3) {
+ dePalette(indata, outdata, width, height, palette);
+ } else {
+ if (transColor) {
+ replaceTransparentColor(indata, outdata, width, height, transColor);
+ }
+ if (depth !== 8) {
+ if (depth === 16) {
+ outdata = Buffer.alloc(width * height * 4);
+ }
+ scaleDepth(indata, outdata, width, height, depth);
+ }
+ }
+ return outdata;
+ };
+ }
+});
+
+// node_modules/pngjs/lib/parser-async.js
+var require_parser_async = __commonJS({
+ "node_modules/pngjs/lib/parser-async.js"(exports2, module2) {
+ "use strict";
+ var util = require("util");
+ var zlib = require("zlib");
+ var ChunkStream = require_chunkstream();
+ var FilterAsync = require_filter_parse_async();
+ var Parser = require_parser();
+ var bitmapper = require_bitmapper();
+ var formatNormaliser = require_format_normaliser();
+ var ParserAsync = module2.exports = function(options) {
+ ChunkStream.call(this);
+ this._parser = new Parser(options, {
+ read: this.read.bind(this),
+ error: this._handleError.bind(this),
+ metadata: this._handleMetaData.bind(this),
+ gamma: this.emit.bind(this, "gamma"),
+ palette: this._handlePalette.bind(this),
+ transColor: this._handleTransColor.bind(this),
+ finished: this._finished.bind(this),
+ inflateData: this._inflateData.bind(this),
+ simpleTransparency: this._simpleTransparency.bind(this),
+ headersFinished: this._headersFinished.bind(this)
+ });
+ this._options = options;
+ this.writable = true;
+ this._parser.start();
+ };
+ util.inherits(ParserAsync, ChunkStream);
+ ParserAsync.prototype._handleError = function(err) {
+ this.emit("error", err);
+ this.writable = false;
+ this.destroy();
+ if (this._inflate && this._inflate.destroy) {
+ this._inflate.destroy();
+ }
+ if (this._filter) {
+ this._filter.destroy();
+ this._filter.on("error", function() {
+ });
+ }
+ this.errord = true;
+ };
+ ParserAsync.prototype._inflateData = function(data) {
+ if (!this._inflate) {
+ if (this._bitmapInfo.interlace) {
+ this._inflate = zlib.createInflate();
+ this._inflate.on("error", this.emit.bind(this, "error"));
+ this._filter.on("complete", this._complete.bind(this));
+ this._inflate.pipe(this._filter);
+ } else {
+ let rowSize = (this._bitmapInfo.width * this._bitmapInfo.bpp * this._bitmapInfo.depth + 7 >> 3) + 1;
+ let imageSize = rowSize * this._bitmapInfo.height;
+ let chunkSize = Math.max(imageSize, zlib.Z_MIN_CHUNK);
+ this._inflate = zlib.createInflate({ chunkSize });
+ let leftToInflate = imageSize;
+ let emitError = this.emit.bind(this, "error");
+ this._inflate.on("error", function(err) {
+ if (!leftToInflate) {
+ return;
+ }
+ emitError(err);
+ });
+ this._filter.on("complete", this._complete.bind(this));
+ let filterWrite = this._filter.write.bind(this._filter);
+ this._inflate.on("data", function(chunk) {
+ if (!leftToInflate) {
+ return;
+ }
+ if (chunk.length > leftToInflate) {
+ chunk = chunk.slice(0, leftToInflate);
+ }
+ leftToInflate -= chunk.length;
+ filterWrite(chunk);
+ });
+ this._inflate.on("end", this._filter.end.bind(this._filter));
+ }
+ }
+ this._inflate.write(data);
+ };
+ ParserAsync.prototype._handleMetaData = function(metaData) {
+ this._metaData = metaData;
+ this._bitmapInfo = Object.create(metaData);
+ this._filter = new FilterAsync(this._bitmapInfo);
+ };
+ ParserAsync.prototype._handleTransColor = function(transColor) {
+ this._bitmapInfo.transColor = transColor;
+ };
+ ParserAsync.prototype._handlePalette = function(palette) {
+ this._bitmapInfo.palette = palette;
+ };
+ ParserAsync.prototype._simpleTransparency = function() {
+ this._metaData.alpha = true;
+ };
+ ParserAsync.prototype._headersFinished = function() {
+ this.emit("metadata", this._metaData);
+ };
+ ParserAsync.prototype._finished = function() {
+ if (this.errord) {
+ return;
+ }
+ if (!this._inflate) {
+ this.emit("error", "No Inflate block");
+ } else {
+ this._inflate.end();
+ }
+ };
+ ParserAsync.prototype._complete = function(filteredData) {
+ if (this.errord) {
+ return;
+ }
+ let normalisedBitmapData;
+ try {
+ let bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo);
+ normalisedBitmapData = formatNormaliser(bitmapData, this._bitmapInfo);
+ bitmapData = null;
+ } catch (ex) {
+ this._handleError(ex);
+ return;
+ }
+ this.emit("parsed", normalisedBitmapData);
+ };
+ }
+});
+
+// node_modules/pngjs/lib/bitpacker.js
+var require_bitpacker = __commonJS({
+ "node_modules/pngjs/lib/bitpacker.js"(exports2, module2) {
+ "use strict";
+ var constants = require_constants2();
+ module2.exports = function(dataIn, width, height, options) {
+ let outHasAlpha = [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(
+ options.colorType
+ ) !== -1;
+ if (options.colorType === options.inputColorType) {
+ let bigEndian = (function() {
+ let buffer = new ArrayBuffer(2);
+ new DataView(buffer).setInt16(
+ 0,
+ 256,
+ true
+ /* littleEndian */
+ );
+ return new Int16Array(buffer)[0] !== 256;
+ })();
+ if (options.bitDepth === 8 || options.bitDepth === 16 && bigEndian) {
+ return dataIn;
+ }
+ }
+ let data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
+ let maxValue = 255;
+ let inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
+ if (inBpp === 4 && !options.inputHasAlpha) {
+ inBpp = 3;
+ }
+ let outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
+ if (options.bitDepth === 16) {
+ maxValue = 65535;
+ outBpp *= 2;
+ }
+ let outData = Buffer.alloc(width * height * outBpp);
+ let inIndex = 0;
+ let outIndex = 0;
+ let bgColor = options.bgColor || {};
+ if (bgColor.red === void 0) {
+ bgColor.red = maxValue;
+ }
+ if (bgColor.green === void 0) {
+ bgColor.green = maxValue;
+ }
+ if (bgColor.blue === void 0) {
+ bgColor.blue = maxValue;
+ }
+ function getRGBA() {
+ let red;
+ let green;
+ let blue;
+ let alpha = maxValue;
+ switch (options.inputColorType) {
+ case constants.COLORTYPE_COLOR_ALPHA:
+ alpha = data[inIndex + 3];
+ red = data[inIndex];
+ green = data[inIndex + 1];
+ blue = data[inIndex + 2];
+ break;
+ case constants.COLORTYPE_COLOR:
+ red = data[inIndex];
+ green = data[inIndex + 1];
+ blue = data[inIndex + 2];
+ break;
+ case constants.COLORTYPE_ALPHA:
+ alpha = data[inIndex + 1];
+ red = data[inIndex];
+ green = red;
+ blue = red;
+ break;
+ case constants.COLORTYPE_GRAYSCALE:
+ red = data[inIndex];
+ green = red;
+ blue = red;
+ break;
+ default:
+ throw new Error(
+ "input color type:" + options.inputColorType + " is not supported at present"
+ );
+ }
+ if (options.inputHasAlpha) {
+ if (!outHasAlpha) {
+ alpha /= maxValue;
+ red = Math.min(
+ Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0),
+ maxValue
+ );
+ green = Math.min(
+ Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0),
+ maxValue
+ );
+ blue = Math.min(
+ Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0),
+ maxValue
+ );
+ }
+ }
+ return { red, green, blue, alpha };
+ }
+ for (let y = 0; y < height; y++) {
+ for (let x = 0; x < width; x++) {
+ let rgba = getRGBA(data, inIndex);
+ switch (options.colorType) {
+ case constants.COLORTYPE_COLOR_ALPHA:
+ case constants.COLORTYPE_COLOR:
+ if (options.bitDepth === 8) {
+ outData[outIndex] = rgba.red;
+ outData[outIndex + 1] = rgba.green;
+ outData[outIndex + 2] = rgba.blue;
+ if (outHasAlpha) {
+ outData[outIndex + 3] = rgba.alpha;
+ }
+ } else {
+ outData.writeUInt16BE(rgba.red, outIndex);
+ outData.writeUInt16BE(rgba.green, outIndex + 2);
+ outData.writeUInt16BE(rgba.blue, outIndex + 4);
+ if (outHasAlpha) {
+ outData.writeUInt16BE(rgba.alpha, outIndex + 6);
+ }
+ }
+ break;
+ case constants.COLORTYPE_ALPHA:
+ case constants.COLORTYPE_GRAYSCALE: {
+ let grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
+ if (options.bitDepth === 8) {
+ outData[outIndex] = grayscale;
+ if (outHasAlpha) {
+ outData[outIndex + 1] = rgba.alpha;
+ }
+ } else {
+ outData.writeUInt16BE(grayscale, outIndex);
+ if (outHasAlpha) {
+ outData.writeUInt16BE(rgba.alpha, outIndex + 2);
+ }
+ }
+ break;
+ }
+ default:
+ throw new Error("unrecognised color Type " + options.colorType);
+ }
+ inIndex += inBpp;
+ outIndex += outBpp;
+ }
+ }
+ return outData;
+ };
+ }
+});
+
+// node_modules/pngjs/lib/filter-pack.js
+var require_filter_pack = __commonJS({
+ "node_modules/pngjs/lib/filter-pack.js"(exports2, module2) {
+ "use strict";
+ var paethPredictor = require_paeth_predictor();
+ function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) {
+ for (let x = 0; x < byteWidth; x++) {
+ rawData[rawPos + x] = pxData[pxPos + x];
+ }
+ }
+ function filterSumNone(pxData, pxPos, byteWidth) {
+ let sum = 0;
+ let length = pxPos + byteWidth;
+ for (let i3 = pxPos; i3 < length; i3++) {
+ sum += Math.abs(pxData[i3]);
+ }
+ return sum;
+ }
+ function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
+ for (let x = 0; x < byteWidth; x++) {
+ let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+ let val = pxData[pxPos + x] - left;
+ rawData[rawPos + x] = val;
+ }
+ }
+ function filterSumSub(pxData, pxPos, byteWidth, bpp) {
+ let sum = 0;
+ for (let x = 0; x < byteWidth; x++) {
+ let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+ let val = pxData[pxPos + x] - left;
+ sum += Math.abs(val);
+ }
+ return sum;
+ }
+ function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) {
+ for (let x = 0; x < byteWidth; x++) {
+ let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+ let val = pxData[pxPos + x] - up;
+ rawData[rawPos + x] = val;
+ }
+ }
+ function filterSumUp(pxData, pxPos, byteWidth) {
+ let sum = 0;
+ let length = pxPos + byteWidth;
+ for (let x = pxPos; x < length; x++) {
+ let up = pxPos > 0 ? pxData[x - byteWidth] : 0;
+ let val = pxData[x] - up;
+ sum += Math.abs(val);
+ }
+ return sum;
+ }
+ function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
+ for (let x = 0; x < byteWidth; x++) {
+ let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+ let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+ let val = pxData[pxPos + x] - (left + up >> 1);
+ rawData[rawPos + x] = val;
+ }
+ }
+ function filterSumAvg(pxData, pxPos, byteWidth, bpp) {
+ let sum = 0;
+ for (let x = 0; x < byteWidth; x++) {
+ let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+ let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+ let val = pxData[pxPos + x] - (left + up >> 1);
+ sum += Math.abs(val);
+ }
+ return sum;
+ }
+ function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
+ for (let x = 0; x < byteWidth; x++) {
+ let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+ let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+ let upleft = pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
+ let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
+ rawData[rawPos + x] = val;
+ }
+ }
+ function filterSumPaeth(pxData, pxPos, byteWidth, bpp) {
+ let sum = 0;
+ for (let x = 0; x < byteWidth; x++) {
+ let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+ let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+ let upleft = pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
+ let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
+ sum += Math.abs(val);
+ }
+ return sum;
+ }
+ var filters = {
+ 0: filterNone,
+ 1: filterSub,
+ 2: filterUp,
+ 3: filterAvg,
+ 4: filterPaeth
+ };
+ var filterSums = {
+ 0: filterSumNone,
+ 1: filterSumSub,
+ 2: filterSumUp,
+ 3: filterSumAvg,
+ 4: filterSumPaeth
+ };
+ module2.exports = function(pxData, width, height, options, bpp) {
+ let filterTypes;
+ if (!("filterType" in options) || options.filterType === -1) {
+ filterTypes = [0, 1, 2, 3, 4];
+ } else if (typeof options.filterType === "number") {
+ filterTypes = [options.filterType];
+ } else {
+ throw new Error("unrecognised filter types");
+ }
+ if (options.bitDepth === 16) {
+ bpp *= 2;
+ }
+ let byteWidth = width * bpp;
+ let rawPos = 0;
+ let pxPos = 0;
+ let rawData = Buffer.alloc((byteWidth + 1) * height);
+ let sel = filterTypes[0];
+ for (let y = 0; y < height; y++) {
+ if (filterTypes.length > 1) {
+ let min = Infinity;
+ for (let i3 = 0; i3 < filterTypes.length; i3++) {
+ let sum = filterSums[filterTypes[i3]](pxData, pxPos, byteWidth, bpp);
+ if (sum < min) {
+ sel = filterTypes[i3];
+ min = sum;
+ }
+ }
+ }
+ rawData[rawPos] = sel;
+ rawPos++;
+ filters[sel](pxData, pxPos, byteWidth, rawData, rawPos, bpp);
+ rawPos += byteWidth;
+ pxPos += byteWidth;
+ }
+ return rawData;
+ };
+ }
+});
+
+// node_modules/pngjs/lib/packer.js
+var require_packer = __commonJS({
+ "node_modules/pngjs/lib/packer.js"(exports2, module2) {
+ "use strict";
+ var constants = require_constants2();
+ var CrcStream = require_crc();
+ var bitPacker = require_bitpacker();
+ var filter = require_filter_pack();
+ var zlib = require("zlib");
+ var Packer = module2.exports = function(options) {
+ this._options = options;
+ options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
+ options.deflateLevel = options.deflateLevel != null ? options.deflateLevel : 9;
+ options.deflateStrategy = options.deflateStrategy != null ? options.deflateStrategy : 3;
+ options.inputHasAlpha = options.inputHasAlpha != null ? options.inputHasAlpha : true;
+ options.deflateFactory = options.deflateFactory || zlib.createDeflate;
+ options.bitDepth = options.bitDepth || 8;
+ options.colorType = typeof options.colorType === "number" ? options.colorType : constants.COLORTYPE_COLOR_ALPHA;
+ options.inputColorType = typeof options.inputColorType === "number" ? options.inputColorType : constants.COLORTYPE_COLOR_ALPHA;
+ if ([
+ constants.COLORTYPE_GRAYSCALE,
+ constants.COLORTYPE_COLOR,
+ constants.COLORTYPE_COLOR_ALPHA,
+ constants.COLORTYPE_ALPHA
+ ].indexOf(options.colorType) === -1) {
+ throw new Error(
+ "option color type:" + options.colorType + " is not supported at present"
+ );
+ }
+ if ([
+ constants.COLORTYPE_GRAYSCALE,
+ constants.COLORTYPE_COLOR,
+ constants.COLORTYPE_COLOR_ALPHA,
+ constants.COLORTYPE_ALPHA
+ ].indexOf(options.inputColorType) === -1) {
+ throw new Error(
+ "option input color type:" + options.inputColorType + " is not supported at present"
+ );
+ }
+ if (options.bitDepth !== 8 && options.bitDepth !== 16) {
+ throw new Error(
+ "option bit depth:" + options.bitDepth + " is not supported at present"
+ );
+ }
+ };
+ Packer.prototype.getDeflateOptions = function() {
+ return {
+ chunkSize: this._options.deflateChunkSize,
+ level: this._options.deflateLevel,
+ strategy: this._options.deflateStrategy
+ };
+ };
+ Packer.prototype.createDeflate = function() {
+ return this._options.deflateFactory(this.getDeflateOptions());
+ };
+ Packer.prototype.filterData = function(data, width, height) {
+ let packedData = bitPacker(data, width, height, this._options);
+ let bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType];
+ let filteredData = filter(packedData, width, height, this._options, bpp);
+ return filteredData;
+ };
+ Packer.prototype._packChunk = function(type, data) {
+ let len = data ? data.length : 0;
+ let buf = Buffer.alloc(len + 12);
+ buf.writeUInt32BE(len, 0);
+ buf.writeUInt32BE(type, 4);
+ if (data) {
+ data.copy(buf, 8);
+ }
+ buf.writeInt32BE(
+ CrcStream.crc32(buf.slice(4, buf.length - 4)),
+ buf.length - 4
+ );
+ return buf;
+ };
+ Packer.prototype.packGAMA = function(gamma) {
+ let buf = Buffer.alloc(4);
+ buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0);
+ return this._packChunk(constants.TYPE_gAMA, buf);
+ };
+ Packer.prototype.packIHDR = function(width, height) {
+ let buf = Buffer.alloc(13);
+ buf.writeUInt32BE(width, 0);
+ buf.writeUInt32BE(height, 4);
+ buf[8] = this._options.bitDepth;
+ buf[9] = this._options.colorType;
+ buf[10] = 0;
+ buf[11] = 0;
+ buf[12] = 0;
+ return this._packChunk(constants.TYPE_IHDR, buf);
+ };
+ Packer.prototype.packIDAT = function(data) {
+ return this._packChunk(constants.TYPE_IDAT, data);
+ };
+ Packer.prototype.packIEND = function() {
+ return this._packChunk(constants.TYPE_IEND, null);
+ };
+ }
+});
+
+// node_modules/pngjs/lib/packer-async.js
+var require_packer_async = __commonJS({
+ "node_modules/pngjs/lib/packer-async.js"(exports2, module2) {
+ "use strict";
+ var util = require("util");
+ var Stream = require("stream");
+ var constants = require_constants2();
+ var Packer = require_packer();
+ var PackerAsync = module2.exports = function(opt) {
+ Stream.call(this);
+ let options = opt || {};
+ this._packer = new Packer(options);
+ this._deflate = this._packer.createDeflate();
+ this.readable = true;
+ };
+ util.inherits(PackerAsync, Stream);
+ PackerAsync.prototype.pack = function(data, width, height, gamma) {
+ this.emit("data", Buffer.from(constants.PNG_SIGNATURE));
+ this.emit("data", this._packer.packIHDR(width, height));
+ if (gamma) {
+ this.emit("data", this._packer.packGAMA(gamma));
+ }
+ let filteredData = this._packer.filterData(data, width, height);
+ this._deflate.on("error", this.emit.bind(this, "error"));
+ this._deflate.on(
+ "data",
+ function(compressedData) {
+ this.emit("data", this._packer.packIDAT(compressedData));
+ }.bind(this)
+ );
+ this._deflate.on(
+ "end",
+ function() {
+ this.emit("data", this._packer.packIEND());
+ this.emit("end");
+ }.bind(this)
+ );
+ this._deflate.end(filteredData);
+ };
+ }
+});
+
+// node_modules/pngjs/lib/sync-inflate.js
+var require_sync_inflate = __commonJS({
+ "node_modules/pngjs/lib/sync-inflate.js"(exports2, module2) {
+ "use strict";
+ var assert2 = require("assert").ok;
+ var zlib = require("zlib");
+ var util = require("util");
+ var kMaxLength = require("buffer").kMaxLength;
+ function Inflate(opts) {
+ if (!(this instanceof Inflate)) {
+ return new Inflate(opts);
+ }
+ if (opts && opts.chunkSize < zlib.Z_MIN_CHUNK) {
+ opts.chunkSize = zlib.Z_MIN_CHUNK;
+ }
+ zlib.Inflate.call(this, opts);
+ this._offset = this._offset === void 0 ? this._outOffset : this._offset;
+ this._buffer = this._buffer || this._outBuffer;
+ if (opts && opts.maxLength != null) {
+ this._maxLength = opts.maxLength;
+ }
+ }
+ function createInflate(opts) {
+ return new Inflate(opts);
+ }
+ function _close(engine, callback) {
+ if (callback) {
+ process.nextTick(callback);
+ }
+ if (!engine._handle) {
+ return;
+ }
+ engine._handle.close();
+ engine._handle = null;
+ }
+ Inflate.prototype._processChunk = function(chunk, flushFlag, asyncCb) {
+ if (typeof asyncCb === "function") {
+ return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb);
+ }
+ let self = this;
+ let availInBefore = chunk && chunk.length;
+ let availOutBefore = this._chunkSize - this._offset;
+ let leftToInflate = this._maxLength;
+ let inOff = 0;
+ let buffers = [];
+ let nread = 0;
+ let error;
+ this.on("error", function(err) {
+ error = err;
+ });
+ function handleChunk(availInAfter, availOutAfter) {
+ if (self._hadError) {
+ return;
+ }
+ let have = availOutBefore - availOutAfter;
+ assert2(have >= 0, "have should not go down");
+ if (have > 0) {
+ let out = self._buffer.slice(self._offset, self._offset + have);
+ self._offset += have;
+ if (out.length > leftToInflate) {
+ out = out.slice(0, leftToInflate);
+ }
+ buffers.push(out);
+ nread += out.length;
+ leftToInflate -= out.length;
+ if (leftToInflate === 0) {
+ return false;
+ }
+ }
+ if (availOutAfter === 0 || self._offset >= self._chunkSize) {
+ availOutBefore = self._chunkSize;
+ self._offset = 0;
+ self._buffer = Buffer.allocUnsafe(self._chunkSize);
+ }
+ if (availOutAfter === 0) {
+ inOff += availInBefore - availInAfter;
+ availInBefore = availInAfter;
+ return true;
+ }
+ return false;
+ }
+ assert2(this._handle, "zlib binding closed");
+ let res;
+ do {
+ res = this._handle.writeSync(
+ flushFlag,
+ chunk,
+ // in
+ inOff,
+ // in_off
+ availInBefore,
+ // in_len
+ this._buffer,
+ // out
+ this._offset,
+ //out_off
+ availOutBefore
+ );
+ res = res || this._writeState;
+ } while (!this._hadError && handleChunk(res[0], res[1]));
+ if (this._hadError) {
+ throw error;
+ }
+ if (nread >= kMaxLength) {
+ _close(this);
+ throw new RangeError(
+ "Cannot create final Buffer. It would be larger than 0x" + kMaxLength.toString(16) + " bytes"
+ );
+ }
+ let buf = Buffer.concat(buffers, nread);
+ _close(this);
+ return buf;
+ };
+ util.inherits(Inflate, zlib.Inflate);
+ function zlibBufferSync(engine, buffer) {
+ if (typeof buffer === "string") {
+ buffer = Buffer.from(buffer);
+ }
+ if (!(buffer instanceof Buffer)) {
+ throw new TypeError("Not a string or buffer");
+ }
+ let flushFlag = engine._finishFlushFlag;
+ if (flushFlag == null) {
+ flushFlag = zlib.Z_FINISH;
+ }
+ return engine._processChunk(buffer, flushFlag);
+ }
+ function inflateSync(buffer, opts) {
+ return zlibBufferSync(new Inflate(opts), buffer);
+ }
+ module2.exports = exports2 = inflateSync;
+ exports2.Inflate = Inflate;
+ exports2.createInflate = createInflate;
+ exports2.inflateSync = inflateSync;
+ }
+});
+
+// node_modules/pngjs/lib/sync-reader.js
+var require_sync_reader = __commonJS({
+ "node_modules/pngjs/lib/sync-reader.js"(exports2, module2) {
+ "use strict";
+ var SyncReader = module2.exports = function(buffer) {
+ this._buffer = buffer;
+ this._reads = [];
+ };
+ SyncReader.prototype.read = function(length, callback) {
+ this._reads.push({
+ length: Math.abs(length),
+ // if length < 0 then at most this length
+ allowLess: length < 0,
+ func: callback
+ });
+ };
+ SyncReader.prototype.process = function() {
+ while (this._reads.length > 0 && this._buffer.length) {
+ let read = this._reads[0];
+ if (this._buffer.length && (this._buffer.length >= read.length || read.allowLess)) {
+ this._reads.shift();
+ let buf = this._buffer;
+ this._buffer = buf.slice(read.length);
+ read.func.call(this, buf.slice(0, read.length));
+ } else {
+ break;
+ }
+ }
+ if (this._reads.length > 0) {
+ return new Error("There are some read requests waitng on finished stream");
+ }
+ if (this._buffer.length > 0) {
+ return new Error("unrecognised content at end of stream");
+ }
+ };
+ }
+});
+
+// node_modules/pngjs/lib/filter-parse-sync.js
+var require_filter_parse_sync = __commonJS({
+ "node_modules/pngjs/lib/filter-parse-sync.js"(exports2) {
+ "use strict";
+ var SyncReader = require_sync_reader();
+ var Filter = require_filter_parse();
+ exports2.process = function(inBuffer, bitmapInfo) {
+ let outBuffers = [];
+ let reader = new SyncReader(inBuffer);
+ let filter = new Filter(bitmapInfo, {
+ read: reader.read.bind(reader),
+ write: function(bufferPart) {
+ outBuffers.push(bufferPart);
+ },
+ complete: function() {
+ }
+ });
+ filter.start();
+ reader.process();
+ return Buffer.concat(outBuffers);
+ };
+ }
+});
+
+// node_modules/pngjs/lib/parser-sync.js
+var require_parser_sync = __commonJS({
+ "node_modules/pngjs/lib/parser-sync.js"(exports2, module2) {
+ "use strict";
+ var hasSyncZlib = true;
+ var zlib = require("zlib");
+ var inflateSync = require_sync_inflate();
+ if (!zlib.deflateSync) {
+ hasSyncZlib = false;
+ }
+ var SyncReader = require_sync_reader();
+ var FilterSync = require_filter_parse_sync();
+ var Parser = require_parser();
+ var bitmapper = require_bitmapper();
+ var formatNormaliser = require_format_normaliser();
+ module2.exports = function(buffer, options) {
+ if (!hasSyncZlib) {
+ throw new Error(
+ "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
+ );
+ }
+ let err;
+ function handleError(_err_) {
+ err = _err_;
+ }
+ let metaData;
+ function handleMetaData(_metaData_) {
+ metaData = _metaData_;
+ }
+ function handleTransColor(transColor) {
+ metaData.transColor = transColor;
+ }
+ function handlePalette(palette) {
+ metaData.palette = palette;
+ }
+ function handleSimpleTransparency() {
+ metaData.alpha = true;
+ }
+ let gamma;
+ function handleGamma(_gamma_) {
+ gamma = _gamma_;
+ }
+ let inflateDataList = [];
+ function handleInflateData(inflatedData2) {
+ inflateDataList.push(inflatedData2);
+ }
+ let reader = new SyncReader(buffer);
+ let parser = new Parser(options, {
+ read: reader.read.bind(reader),
+ error: handleError,
+ metadata: handleMetaData,
+ gamma: handleGamma,
+ palette: handlePalette,
+ transColor: handleTransColor,
+ inflateData: handleInflateData,
+ simpleTransparency: handleSimpleTransparency
+ });
+ parser.start();
+ reader.process();
+ if (err) {
+ throw err;
+ }
+ let inflateData = Buffer.concat(inflateDataList);
+ inflateDataList.length = 0;
+ let inflatedData;
+ if (metaData.interlace) {
+ inflatedData = zlib.inflateSync(inflateData);
+ } else {
+ let rowSize = (metaData.width * metaData.bpp * metaData.depth + 7 >> 3) + 1;
+ let imageSize = rowSize * metaData.height;
+ inflatedData = inflateSync(inflateData, {
+ chunkSize: imageSize,
+ maxLength: imageSize
+ });
+ }
+ inflateData = null;
+ if (!inflatedData || !inflatedData.length) {
+ throw new Error("bad png - invalid inflate data response");
+ }
+ let unfilteredData = FilterSync.process(inflatedData, metaData);
+ inflateData = null;
+ let bitmapData = bitmapper.dataToBitMap(unfilteredData, metaData);
+ unfilteredData = null;
+ let normalisedBitmapData = formatNormaliser(bitmapData, metaData);
+ metaData.data = normalisedBitmapData;
+ metaData.gamma = gamma || 0;
+ return metaData;
+ };
+ }
+});
+
+// node_modules/pngjs/lib/packer-sync.js
+var require_packer_sync = __commonJS({
+ "node_modules/pngjs/lib/packer-sync.js"(exports2, module2) {
+ "use strict";
+ var hasSyncZlib = true;
+ var zlib = require("zlib");
+ if (!zlib.deflateSync) {
+ hasSyncZlib = false;
+ }
+ var constants = require_constants2();
+ var Packer = require_packer();
+ module2.exports = function(metaData, opt) {
+ if (!hasSyncZlib) {
+ throw new Error(
+ "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
+ );
+ }
+ let options = opt || {};
+ let packer = new Packer(options);
+ let chunks = [];
+ chunks.push(Buffer.from(constants.PNG_SIGNATURE));
+ chunks.push(packer.packIHDR(metaData.width, metaData.height));
+ if (metaData.gamma) {
+ chunks.push(packer.packGAMA(metaData.gamma));
+ }
+ let filteredData = packer.filterData(
+ metaData.data,
+ metaData.width,
+ metaData.height
+ );
+ let compressedData = zlib.deflateSync(
+ filteredData,
+ packer.getDeflateOptions()
+ );
+ filteredData = null;
+ if (!compressedData || !compressedData.length) {
+ throw new Error("bad png - invalid compressed data response");
+ }
+ chunks.push(packer.packIDAT(compressedData));
+ chunks.push(packer.packIEND());
+ return Buffer.concat(chunks);
+ };
+ }
+});
+
+// node_modules/pngjs/lib/png-sync.js
+var require_png_sync = __commonJS({
+ "node_modules/pngjs/lib/png-sync.js"(exports2) {
+ "use strict";
+ var parse4 = require_parser_sync();
+ var pack = require_packer_sync();
+ exports2.read = function(buffer, options) {
+ return parse4(buffer, options || {});
+ };
+ exports2.write = function(png, options) {
+ return pack(png, options);
+ };
+ }
+});
+
+// node_modules/pngjs/lib/png.js
+var require_png = __commonJS({
+ "node_modules/pngjs/lib/png.js"(exports2) {
+ "use strict";
+ var util = require("util");
+ var Stream = require("stream");
+ var Parser = require_parser_async();
+ var Packer = require_packer_async();
+ var PNGSync = require_png_sync();
+ var PNG = exports2.PNG = function(options) {
+ Stream.call(this);
+ options = options || {};
+ this.width = options.width | 0;
+ this.height = options.height | 0;
+ this.data = this.width > 0 && this.height > 0 ? Buffer.alloc(4 * this.width * this.height) : null;
+ if (options.fill && this.data) {
+ this.data.fill(0);
+ }
+ this.gamma = 0;
+ this.readable = this.writable = true;
+ this._parser = new Parser(options);
+ this._parser.on("error", this.emit.bind(this, "error"));
+ this._parser.on("close", this._handleClose.bind(this));
+ this._parser.on("metadata", this._metadata.bind(this));
+ this._parser.on("gamma", this._gamma.bind(this));
+ this._parser.on(
+ "parsed",
+ function(data) {
+ this.data = data;
+ this.emit("parsed", data);
+ }.bind(this)
+ );
+ this._packer = new Packer(options);
+ this._packer.on("data", this.emit.bind(this, "data"));
+ this._packer.on("end", this.emit.bind(this, "end"));
+ this._parser.on("close", this._handleClose.bind(this));
+ this._packer.on("error", this.emit.bind(this, "error"));
+ };
+ util.inherits(PNG, Stream);
+ PNG.sync = PNGSync;
+ PNG.prototype.pack = function() {
+ if (!this.data || !this.data.length) {
+ this.emit("error", "No data provided");
+ return this;
+ }
+ process.nextTick(
+ function() {
+ this._packer.pack(this.data, this.width, this.height, this.gamma);
+ }.bind(this)
+ );
+ return this;
+ };
+ PNG.prototype.parse = function(data, callback) {
+ if (callback) {
+ let onParsed, onError;
+ onParsed = function(parsedData) {
+ this.removeListener("error", onError);
+ this.data = parsedData;
+ callback(null, this);
+ }.bind(this);
+ onError = function(err) {
+ this.removeListener("parsed", onParsed);
+ callback(err, null);
+ }.bind(this);
+ this.once("parsed", onParsed);
+ this.once("error", onError);
+ }
+ this.end(data);
+ return this;
+ };
+ PNG.prototype.write = function(data) {
+ this._parser.write(data);
+ return true;
+ };
+ PNG.prototype.end = function(data) {
+ this._parser.end(data);
+ };
+ PNG.prototype._metadata = function(metadata) {
+ this.width = metadata.width;
+ this.height = metadata.height;
+ this.emit("metadata", metadata);
+ };
+ PNG.prototype._gamma = function(gamma) {
+ this.gamma = gamma;
+ };
+ PNG.prototype._handleClose = function() {
+ if (!this._parser.writable && !this._packer.readable) {
+ this.emit("close");
+ }
+ };
+ PNG.bitblt = function(src, dst, srcX, srcY, width, height, deltaX, deltaY) {
+ srcX |= 0;
+ srcY |= 0;
+ width |= 0;
+ height |= 0;
+ deltaX |= 0;
+ deltaY |= 0;
+ if (srcX > src.width || srcY > src.height || srcX + width > src.width || srcY + height > src.height) {
+ throw new Error("bitblt reading outside image");
+ }
+ if (deltaX > dst.width || deltaY > dst.height || deltaX + width > dst.width || deltaY + height > dst.height) {
+ throw new Error("bitblt writing outside image");
+ }
+ for (let y = 0; y < height; y++) {
+ src.data.copy(
+ dst.data,
+ (deltaY + y) * dst.width + deltaX << 2,
+ (srcY + y) * src.width + srcX << 2,
+ (srcY + y) * src.width + srcX + width << 2
+ );
+ }
+ };
+ PNG.prototype.bitblt = function(dst, srcX, srcY, width, height, deltaX, deltaY) {
+ PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY);
+ return this;
+ };
+ PNG.adjustGamma = function(src) {
+ if (src.gamma) {
+ for (let y = 0; y < src.height; y++) {
+ for (let x = 0; x < src.width; x++) {
+ let idx = src.width * y + x << 2;
+ for (let i3 = 0; i3 < 3; i3++) {
+ let sample = src.data[idx + i3] / 255;
+ sample = Math.pow(sample, 1 / 2.2 / src.gamma);
+ src.data[idx + i3] = Math.round(sample * 255);
+ }
+ }
+ }
+ src.gamma = 0;
+ }
+ };
+ PNG.prototype.adjustGamma = function() {
+ PNG.adjustGamma(this);
+ };
+ }
+});
+
+// node_modules/qrcode/lib/renderer/utils.js
+var require_utils2 = __commonJS({
+ "node_modules/qrcode/lib/renderer/utils.js"(exports2) {
+ function hex2rgba(hex2) {
+ if (typeof hex2 === "number") {
+ hex2 = hex2.toString();
+ }
+ if (typeof hex2 !== "string") {
+ throw new Error("Color should be defined as hex string");
+ }
+ let hexCode = hex2.slice().replace("#", "").split("");
+ if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) {
+ throw new Error("Invalid hex color: " + hex2);
+ }
+ if (hexCode.length === 3 || hexCode.length === 4) {
+ hexCode = Array.prototype.concat.apply([], hexCode.map(function(c) {
+ return [c, c];
+ }));
+ }
+ if (hexCode.length === 6) hexCode.push("F", "F");
+ const hexValue = parseInt(hexCode.join(""), 16);
+ return {
+ r: hexValue >> 24 & 255,
+ g: hexValue >> 16 & 255,
+ b: hexValue >> 8 & 255,
+ a: hexValue & 255,
+ hex: "#" + hexCode.slice(0, 6).join("")
+ };
+ }
+ exports2.getOptions = function getOptions(options) {
+ if (!options) options = {};
+ if (!options.color) options.color = {};
+ const margin = typeof options.margin === "undefined" || options.margin === null || options.margin < 0 ? 4 : options.margin;
+ const width = options.width && options.width >= 21 ? options.width : void 0;
+ const scale = options.scale || 4;
+ return {
+ width,
+ scale: width ? 4 : scale,
+ margin,
+ color: {
+ dark: hex2rgba(options.color.dark || "#000000ff"),
+ light: hex2rgba(options.color.light || "#ffffffff")
+ },
+ type: options.type,
+ rendererOpts: options.rendererOpts || {}
+ };
+ };
+ exports2.getScale = function getScale(qrSize, opts) {
+ return opts.width && opts.width >= qrSize + opts.margin * 2 ? opts.width / (qrSize + opts.margin * 2) : opts.scale;
+ };
+ exports2.getImageWidth = function getImageWidth(qrSize, opts) {
+ const scale = exports2.getScale(qrSize, opts);
+ return Math.floor((qrSize + opts.margin * 2) * scale);
+ };
+ exports2.qrToImageData = function qrToImageData(imgData, qr, opts) {
+ const size = qr.modules.size;
+ const data = qr.modules.data;
+ const scale = exports2.getScale(size, opts);
+ const symbolSize = Math.floor((size + opts.margin * 2) * scale);
+ const scaledMargin = opts.margin * scale;
+ const palette = [opts.color.light, opts.color.dark];
+ for (let i3 = 0; i3 < symbolSize; i3++) {
+ for (let j = 0; j < symbolSize; j++) {
+ let posDst = (i3 * symbolSize + j) * 4;
+ let pxColor = opts.color.light;
+ if (i3 >= scaledMargin && j >= scaledMargin && i3 < symbolSize - scaledMargin && j < symbolSize - scaledMargin) {
+ const iSrc = Math.floor((i3 - scaledMargin) / scale);
+ const jSrc = Math.floor((j - scaledMargin) / scale);
+ pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0];
+ }
+ imgData[posDst++] = pxColor.r;
+ imgData[posDst++] = pxColor.g;
+ imgData[posDst++] = pxColor.b;
+ imgData[posDst] = pxColor.a;
+ }
+ }
+ };
+ }
+});
+
+// node_modules/qrcode/lib/renderer/png.js
+var require_png2 = __commonJS({
+ "node_modules/qrcode/lib/renderer/png.js"(exports2) {
+ var fs = require("fs");
+ var PNG = require_png().PNG;
+ var Utils = require_utils2();
+ exports2.render = function render(qrData, options) {
+ const opts = Utils.getOptions(options);
+ const pngOpts = opts.rendererOpts;
+ const size = Utils.getImageWidth(qrData.modules.size, opts);
+ pngOpts.width = size;
+ pngOpts.height = size;
+ const pngImage = new PNG(pngOpts);
+ Utils.qrToImageData(pngImage.data, qrData, opts);
+ return pngImage;
+ };
+ exports2.renderToDataURL = function renderToDataURL(qrData, options, cb) {
+ if (typeof cb === "undefined") {
+ cb = options;
+ options = void 0;
+ }
+ exports2.renderToBuffer(qrData, options, function(err, output4) {
+ if (err) cb(err);
+ let url = "data:image/png;base64,";
+ url += output4.toString("base64");
+ cb(null, url);
+ });
+ };
+ exports2.renderToBuffer = function renderToBuffer(qrData, options, cb) {
+ if (typeof cb === "undefined") {
+ cb = options;
+ options = void 0;
+ }
+ const png = exports2.render(qrData, options);
+ const buffer = [];
+ png.on("error", cb);
+ png.on("data", function(data) {
+ buffer.push(data);
+ });
+ png.on("end", function() {
+ cb(null, Buffer.concat(buffer));
+ });
+ png.pack();
+ };
+ exports2.renderToFile = function renderToFile(path, qrData, options, cb) {
+ if (typeof cb === "undefined") {
+ cb = options;
+ options = void 0;
+ }
+ let called = false;
+ const done = (...args) => {
+ if (called) return;
+ called = true;
+ cb.apply(null, args);
+ };
+ const stream = fs.createWriteStream(path);
+ stream.on("error", done);
+ stream.on("close", done);
+ exports2.renderToFileStream(stream, qrData, options);
+ };
+ exports2.renderToFileStream = function renderToFileStream(stream, qrData, options) {
+ const png = exports2.render(qrData, options);
+ png.pack().pipe(stream);
+ };
+ }
+});
+
+// node_modules/qrcode/lib/renderer/utf8.js
+var require_utf8 = __commonJS({
+ "node_modules/qrcode/lib/renderer/utf8.js"(exports2) {
+ var Utils = require_utils2();
+ var BLOCK_CHAR = {
+ WW: " ",
+ WB: "\u2584",
+ BB: "\u2588",
+ BW: "\u2580"
+ };
+ var INVERTED_BLOCK_CHAR = {
+ BB: " ",
+ BW: "\u2584",
+ WW: "\u2588",
+ WB: "\u2580"
+ };
+ function getBlockChar(top, bottom, blocks) {
+ if (top && bottom) return blocks.BB;
+ if (top && !bottom) return blocks.BW;
+ if (!top && bottom) return blocks.WB;
+ return blocks.WW;
+ }
+ exports2.render = function(qrData, options, cb) {
+ const opts = Utils.getOptions(options);
+ let blocks = BLOCK_CHAR;
+ if (opts.color.dark.hex === "#ffffff" || opts.color.light.hex === "#000000") {
+ blocks = INVERTED_BLOCK_CHAR;
+ }
+ const size = qrData.modules.size;
+ const data = qrData.modules.data;
+ let output4 = "";
+ let hMargin = Array(size + opts.margin * 2 + 1).join(blocks.WW);
+ hMargin = Array(opts.margin / 2 + 1).join(hMargin + "\n");
+ const vMargin = Array(opts.margin + 1).join(blocks.WW);
+ output4 += hMargin;
+ for (let i3 = 0; i3 < size; i3 += 2) {
+ output4 += vMargin;
+ for (let j = 0; j < size; j++) {
+ const topModule = data[i3 * size + j];
+ const bottomModule = data[(i3 + 1) * size + j];
+ output4 += getBlockChar(topModule, bottomModule, blocks);
+ }
+ output4 += vMargin + "\n";
+ }
+ output4 += hMargin.slice(0, -1);
+ if (typeof cb === "function") {
+ cb(null, output4);
+ }
+ return output4;
+ };
+ exports2.renderToFile = function renderToFile(path, qrData, options, cb) {
+ if (typeof cb === "undefined") {
+ cb = options;
+ options = void 0;
+ }
+ const fs = require("fs");
+ const utf82 = exports2.render(qrData, options);
+ fs.writeFile(path, utf82, cb);
+ };
+ }
+});
+
+// node_modules/qrcode/lib/renderer/terminal/terminal.js
+var require_terminal = __commonJS({
+ "node_modules/qrcode/lib/renderer/terminal/terminal.js"(exports2) {
+ exports2.render = function(qrData, options, cb) {
+ const size = qrData.modules.size;
+ const data = qrData.modules.data;
+ const black = "\x1B[40m \x1B[0m";
+ const white = "\x1B[47m \x1B[0m";
+ let output4 = "";
+ const hMargin = Array(size + 3).join(white);
+ const vMargin = Array(2).join(white);
+ output4 += hMargin + "\n";
+ for (let i3 = 0; i3 < size; ++i3) {
+ output4 += white;
+ for (let j = 0; j < size; j++) {
+ output4 += data[i3 * size + j] ? black : white;
+ }
+ output4 += vMargin + "\n";
+ }
+ output4 += hMargin + "\n";
+ if (typeof cb === "function") {
+ cb(null, output4);
+ }
+ return output4;
+ };
+ }
+});
+
+// node_modules/qrcode/lib/renderer/terminal/terminal-small.js
+var require_terminal_small = __commonJS({
+ "node_modules/qrcode/lib/renderer/terminal/terminal-small.js"(exports2) {
+ var backgroundWhite = "\x1B[47m";
+ var backgroundBlack = "\x1B[40m";
+ var foregroundWhite = "\x1B[37m";
+ var foregroundBlack = "\x1B[30m";
+ var reset = "\x1B[0m";
+ var lineSetupNormal = backgroundWhite + foregroundBlack;
+ var lineSetupInverse = backgroundBlack + foregroundWhite;
+ var createPalette = function(lineSetup, foregroundWhite2, foregroundBlack2) {
+ return {
+ // 1 ... white, 2 ... black, 0 ... transparent (default)
+ "00": reset + " " + lineSetup,
+ "01": reset + foregroundWhite2 + "\u2584" + lineSetup,
+ "02": reset + foregroundBlack2 + "\u2584" + lineSetup,
+ 10: reset + foregroundWhite2 + "\u2580" + lineSetup,
+ 11: " ",
+ 12: "\u2584",
+ 20: reset + foregroundBlack2 + "\u2580" + lineSetup,
+ 21: "\u2580",
+ 22: "\u2588"
+ };
+ };
+ var mkCodePixel = function(modules, size, x, y) {
+ const sizePlus = size + 1;
+ if (x >= sizePlus || y >= sizePlus || y < -1 || x < -1) return "0";
+ if (x >= size || y >= size || y < 0 || x < 0) return "1";
+ const idx = y * size + x;
+ return modules[idx] ? "2" : "1";
+ };
+ var mkCode = function(modules, size, x, y) {
+ return mkCodePixel(modules, size, x, y) + mkCodePixel(modules, size, x, y + 1);
+ };
+ exports2.render = function(qrData, options, cb) {
+ const size = qrData.modules.size;
+ const data = qrData.modules.data;
+ const inverse = !!(options && options.inverse);
+ const lineSetup = options && options.inverse ? lineSetupInverse : lineSetupNormal;
+ const white = inverse ? foregroundBlack : foregroundWhite;
+ const black = inverse ? foregroundWhite : foregroundBlack;
+ const palette = createPalette(lineSetup, white, black);
+ const newLine = reset + "\n" + lineSetup;
+ let output4 = lineSetup;
+ for (let y = -1; y < size + 1; y += 2) {
+ for (let x = -1; x < size; x++) {
+ output4 += palette[mkCode(data, size, x, y)];
+ }
+ output4 += palette[mkCode(data, size, size, y)] + newLine;
+ }
+ output4 += reset;
+ if (typeof cb === "function") {
+ cb(null, output4);
+ }
+ return output4;
+ };
+ }
+});
+
+// node_modules/qrcode/lib/renderer/terminal.js
+var require_terminal2 = __commonJS({
+ "node_modules/qrcode/lib/renderer/terminal.js"(exports2) {
+ var big = require_terminal();
+ var small = require_terminal_small();
+ exports2.render = function(qrData, options, cb) {
+ if (options && options.small) {
+ return small.render(qrData, options, cb);
+ }
+ return big.render(qrData, options, cb);
+ };
+ }
+});
+
+// node_modules/qrcode/lib/renderer/svg-tag.js
+var require_svg_tag = __commonJS({
+ "node_modules/qrcode/lib/renderer/svg-tag.js"(exports2) {
+ var Utils = require_utils2();
+ function getColorAttrib(color, attrib) {
+ const alpha = color.a / 255;
+ const str = attrib + '="' + color.hex + '"';
+ return alpha < 1 ? str + " " + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' : str;
+ }
+ function svgCmd(cmd, x, y) {
+ let str = cmd + x;
+ if (typeof y !== "undefined") str += " " + y;
+ return str;
+ }
+ function qrToPath(data, size, margin) {
+ let path = "";
+ let moveBy = 0;
+ let newRow = false;
+ let lineLength = 0;
+ for (let i3 = 0; i3 < data.length; i3++) {
+ const col = Math.floor(i3 % size);
+ const row = Math.floor(i3 / size);
+ if (!col && !newRow) newRow = true;
+ if (data[i3]) {
+ lineLength++;
+ if (!(i3 > 0 && col > 0 && data[i3 - 1])) {
+ path += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
+ moveBy = 0;
+ newRow = false;
+ }
+ if (!(col + 1 < size && data[i3 + 1])) {
+ path += svgCmd("h", lineLength);
+ lineLength = 0;
+ }
+ } else {
+ moveBy++;
+ }
+ }
+ return path;
+ }
+ exports2.render = function render(qrData, options, cb) {
+ const opts = Utils.getOptions(options);
+ const size = qrData.modules.size;
+ const data = qrData.modules.data;
+ const qrcodesize = size + opts.margin * 2;
+ const bg = !opts.color.light.a ? "" : "';
+ const path = "';
+ const viewBox = 'viewBox="0 0 ' + qrcodesize + " " + qrcodesize + '"';
+ const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" ';
+ const svgTag = '\n";
+ if (typeof cb === "function") {
+ cb(null, svgTag);
+ }
+ return svgTag;
+ };
+ }
+});
+
+// node_modules/qrcode/lib/renderer/svg.js
+var require_svg = __commonJS({
+ "node_modules/qrcode/lib/renderer/svg.js"(exports2) {
+ var svgTagRenderer = require_svg_tag();
+ exports2.render = svgTagRenderer.render;
+ exports2.renderToFile = function renderToFile(path, qrData, options, cb) {
+ if (typeof cb === "undefined") {
+ cb = options;
+ options = void 0;
+ }
+ const fs = require("fs");
+ const svgTag = exports2.render(qrData, options);
+ const xmlStr = '' + svgTag;
+ fs.writeFile(path, xmlStr, cb);
+ };
+ }
+});
+
+// node_modules/qrcode/lib/renderer/canvas.js
+var require_canvas = __commonJS({
+ "node_modules/qrcode/lib/renderer/canvas.js"(exports2) {
+ var Utils = require_utils2();
+ function clearCanvas(ctx, canvas, size) {
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ if (!canvas.style) canvas.style = {};
+ canvas.height = size;
+ canvas.width = size;
+ canvas.style.height = size + "px";
+ canvas.style.width = size + "px";
+ }
+ function getCanvasElement() {
+ try {
+ return document.createElement("canvas");
+ } catch (e) {
+ throw new Error("You need to specify a canvas element");
+ }
+ }
+ exports2.render = function render(qrData, canvas, options) {
+ let opts = options;
+ let canvasEl = canvas;
+ if (typeof opts === "undefined" && (!canvas || !canvas.getContext)) {
+ opts = canvas;
+ canvas = void 0;
+ }
+ if (!canvas) {
+ canvasEl = getCanvasElement();
+ }
+ opts = Utils.getOptions(opts);
+ const size = Utils.getImageWidth(qrData.modules.size, opts);
+ const ctx = canvasEl.getContext("2d");
+ const image = ctx.createImageData(size, size);
+ Utils.qrToImageData(image.data, qrData, opts);
+ clearCanvas(ctx, canvasEl, size);
+ ctx.putImageData(image, 0, 0);
+ return canvasEl;
+ };
+ exports2.renderToDataURL = function renderToDataURL(qrData, canvas, options) {
+ let opts = options;
+ if (typeof opts === "undefined" && (!canvas || !canvas.getContext)) {
+ opts = canvas;
+ canvas = void 0;
+ }
+ if (!opts) opts = {};
+ const canvasEl = exports2.render(qrData, canvas, opts);
+ const type = opts.type || "image/png";
+ const rendererOpts = opts.rendererOpts || {};
+ return canvasEl.toDataURL(type, rendererOpts.quality);
+ };
+ }
+});
+
+// node_modules/qrcode/lib/browser.js
+var require_browser = __commonJS({
+ "node_modules/qrcode/lib/browser.js"(exports2) {
+ var canPromise = require_can_promise();
+ var QRCode2 = require_qrcode();
+ var CanvasRenderer = require_canvas();
+ var SvgRenderer = require_svg_tag();
+ function renderCanvas(renderFunc, canvas, text, opts, cb) {
+ const args = [].slice.call(arguments, 1);
+ const argsNum = args.length;
+ const isLastArgCb = typeof args[argsNum - 1] === "function";
+ if (!isLastArgCb && !canPromise()) {
+ throw new Error("Callback required as last argument");
+ }
+ if (isLastArgCb) {
+ if (argsNum < 2) {
+ throw new Error("Too few arguments provided");
+ }
+ if (argsNum === 2) {
+ cb = text;
+ text = canvas;
+ canvas = opts = void 0;
+ } else if (argsNum === 3) {
+ if (canvas.getContext && typeof cb === "undefined") {
+ cb = opts;
+ opts = void 0;
+ } else {
+ cb = opts;
+ opts = text;
+ text = canvas;
+ canvas = void 0;
+ }
+ }
+ } else {
+ if (argsNum < 1) {
+ throw new Error("Too few arguments provided");
+ }
+ if (argsNum === 1) {
+ text = canvas;
+ canvas = opts = void 0;
+ } else if (argsNum === 2 && !canvas.getContext) {
+ opts = text;
+ text = canvas;
+ canvas = void 0;
+ }
+ return new Promise(function(resolve, reject) {
+ try {
+ const data = QRCode2.create(text, opts);
+ resolve(renderFunc(data, canvas, opts));
+ } catch (e) {
+ reject(e);
+ }
+ });
+ }
+ try {
+ const data = QRCode2.create(text, opts);
+ cb(null, renderFunc(data, canvas, opts));
+ } catch (e) {
+ cb(e);
+ }
+ }
+ exports2.create = QRCode2.create;
+ exports2.toCanvas = renderCanvas.bind(null, CanvasRenderer.render);
+ exports2.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL);
+ exports2.toString = renderCanvas.bind(null, function(data, _, opts) {
+ return SvgRenderer.render(data, opts);
+ });
+ }
+});
+
+// node_modules/qrcode/lib/server.js
+var require_server = __commonJS({
+ "node_modules/qrcode/lib/server.js"(exports2) {
+ var canPromise = require_can_promise();
+ var QRCode2 = require_qrcode();
+ var PngRenderer = require_png2();
+ var Utf8Renderer = require_utf8();
+ var TerminalRenderer = require_terminal2();
+ var SvgRenderer = require_svg();
+ function checkParams(text, opts, cb) {
+ if (typeof text === "undefined") {
+ throw new Error("String required as first argument");
+ }
+ if (typeof cb === "undefined") {
+ cb = opts;
+ opts = {};
+ }
+ if (typeof cb !== "function") {
+ if (!canPromise()) {
+ throw new Error("Callback required as last argument");
+ } else {
+ opts = cb || {};
+ cb = null;
+ }
+ }
+ return {
+ opts,
+ cb
+ };
+ }
+ function getTypeFromFilename(path) {
+ return path.slice((path.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
+ }
+ function getRendererFromType(type) {
+ switch (type) {
+ case "svg":
+ return SvgRenderer;
+ case "txt":
+ case "utf8":
+ return Utf8Renderer;
+ case "png":
+ case "image/png":
+ default:
+ return PngRenderer;
+ }
+ }
+ function getStringRendererFromType(type) {
+ switch (type) {
+ case "svg":
+ return SvgRenderer;
+ case "terminal":
+ return TerminalRenderer;
+ case "utf8":
+ default:
+ return Utf8Renderer;
+ }
+ }
+ function render(renderFunc, text, params) {
+ if (!params.cb) {
+ return new Promise(function(resolve, reject) {
+ try {
+ const data = QRCode2.create(text, params.opts);
+ return renderFunc(data, params.opts, function(err, data2) {
+ return err ? reject(err) : resolve(data2);
+ });
+ } catch (e) {
+ reject(e);
+ }
+ });
+ }
+ try {
+ const data = QRCode2.create(text, params.opts);
+ return renderFunc(data, params.opts, params.cb);
+ } catch (e) {
+ params.cb(e);
+ }
+ }
+ exports2.create = QRCode2.create;
+ exports2.toCanvas = require_browser().toCanvas;
+ exports2.toString = function toString(text, opts, cb) {
+ const params = checkParams(text, opts, cb);
+ const type = params.opts ? params.opts.type : void 0;
+ const renderer = getStringRendererFromType(type);
+ return render(renderer.render, text, params);
+ };
+ exports2.toDataURL = function toDataURL(text, opts, cb) {
+ const params = checkParams(text, opts, cb);
+ const renderer = getRendererFromType(params.opts.type);
+ return render(renderer.renderToDataURL, text, params);
+ };
+ exports2.toBuffer = function toBuffer(text, opts, cb) {
+ const params = checkParams(text, opts, cb);
+ const renderer = getRendererFromType(params.opts.type);
+ return render(renderer.renderToBuffer, text, params);
+ };
+ exports2.toFile = function toFile(path, text, opts, cb) {
+ if (typeof path !== "string" || !(typeof text === "string" || typeof text === "object")) {
+ throw new Error("Invalid argument");
+ }
+ if (arguments.length < 3 && !canPromise()) {
+ throw new Error("Too few arguments provided");
+ }
+ const params = checkParams(text, opts, cb);
+ const type = params.opts.type || getTypeFromFilename(path);
+ const renderer = getRendererFromType(type);
+ const renderToFile = renderer.renderToFile.bind(null, path);
+ return render(renderToFile, text, params);
+ };
+ exports2.toFileStream = function toFileStream(stream, text, opts) {
+ if (arguments.length < 2) {
+ throw new Error("Too few arguments provided");
+ }
+ const params = checkParams(text, opts, stream.emit.bind(stream, "error"));
+ const renderer = getRendererFromType("png");
+ const renderToFileStream = renderer.renderToFileStream.bind(null, stream);
+ render(renderToFileStream, text, params);
+ };
+ }
+});
+
+// node_modules/qrcode/lib/index.js
+var require_lib = __commonJS({
+ "node_modules/qrcode/lib/index.js"(exports2, module2) {
+ module2.exports = require_server();
+ }
+});
+
+// tools/payment-helper.mjs
+var import_bech32 = __toESM(require_dist(), 1);
+
+// node_modules/@noble/curves/node_modules/@noble/hashes/esm/_assert.js
+function number(n) {
+ if (!Number.isSafeInteger(n) || n < 0)
+ throw new Error(`Wrong positive integer: ${n}`);
+}
+function bytes(b, ...lengths) {
+ if (!(b instanceof Uint8Array))
+ throw new Error("Expected Uint8Array");
+ if (lengths.length > 0 && !lengths.includes(b.length))
+ throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
+}
+function hash(hash3) {
+ if (typeof hash3 !== "function" || typeof hash3.create !== "function")
+ throw new Error("Hash should be wrapped by utils.wrapConstructor");
+ number(hash3.outputLen);
+ number(hash3.blockLen);
+}
+function exists(instance, checkFinished = true) {
+ if (instance.destroyed)
+ throw new Error("Hash instance has been destroyed");
+ if (checkFinished && instance.finished)
+ throw new Error("Hash#digest() has already been called");
+}
+function output(out, instance) {
+ bytes(out);
+ const min = instance.outputLen;
+ if (out.length < min) {
+ throw new Error(`digestInto() expects output buffer of length at least ${min}`);
+ }
+}
+
+// node_modules/@noble/curves/node_modules/@noble/hashes/esm/cryptoNode.js
+var nc = __toESM(require("node:crypto"), 1);
+var crypto = nc && typeof nc === "object" && "webcrypto" in nc ? nc.webcrypto : void 0;
+
+// node_modules/@noble/curves/node_modules/@noble/hashes/esm/utils.js
+var u8a = (a) => a instanceof Uint8Array;
+var createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
+var rotr = (word, shift) => word << 32 - shift | word >>> shift;
+var isLE = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
+if (!isLE)
+ throw new Error("Non little-endian hardware is not supported");
+function utf8ToBytes(str) {
+ if (typeof str !== "string")
+ throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
+ return new Uint8Array(new TextEncoder().encode(str));
+}
+function toBytes(data) {
+ if (typeof data === "string")
+ data = utf8ToBytes(data);
+ if (!u8a(data))
+ throw new Error(`expected Uint8Array, got ${typeof data}`);
+ return data;
+}
+function concatBytes(...arrays) {
+ const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
+ let pad2 = 0;
+ arrays.forEach((a) => {
+ if (!u8a(a))
+ throw new Error("Uint8Array expected");
+ r.set(a, pad2);
+ pad2 += a.length;
+ });
+ return r;
+}
+var Hash = class {
+ // Safe version that clones internal state
+ clone() {
+ return this._cloneInto();
+ }
+};
+var toStr = {}.toString;
+function wrapConstructor(hashCons) {
+ const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
+ const tmp = hashCons();
+ hashC.outputLen = tmp.outputLen;
+ hashC.blockLen = tmp.blockLen;
+ hashC.create = () => hashCons();
+ return hashC;
+}
+function randomBytes(bytesLength = 32) {
+ if (crypto && typeof crypto.getRandomValues === "function") {
+ return crypto.getRandomValues(new Uint8Array(bytesLength));
+ }
+ throw new Error("crypto.getRandomValues must be defined");
+}
+
+// node_modules/@noble/curves/node_modules/@noble/hashes/esm/_sha2.js
+function setBigUint64(view, byteOffset, value, isLE4) {
+ if (typeof view.setBigUint64 === "function")
+ return view.setBigUint64(byteOffset, value, isLE4);
+ const _32n = BigInt(32);
+ const _u32_max = BigInt(4294967295);
+ const wh = Number(value >> _32n & _u32_max);
+ const wl = Number(value & _u32_max);
+ const h = isLE4 ? 4 : 0;
+ const l = isLE4 ? 0 : 4;
+ view.setUint32(byteOffset + h, wh, isLE4);
+ view.setUint32(byteOffset + l, wl, isLE4);
+}
+var SHA2 = class extends Hash {
+ constructor(blockLen, outputLen, padOffset, isLE4) {
+ super();
+ this.blockLen = blockLen;
+ this.outputLen = outputLen;
+ this.padOffset = padOffset;
+ this.isLE = isLE4;
+ this.finished = false;
+ this.length = 0;
+ this.pos = 0;
+ this.destroyed = false;
+ this.buffer = new Uint8Array(blockLen);
+ this.view = createView(this.buffer);
+ }
+ update(data) {
+ exists(this);
+ const { view, buffer, blockLen } = this;
+ data = toBytes(data);
+ const len = data.length;
+ for (let pos = 0; pos < len; ) {
+ const take = Math.min(blockLen - this.pos, len - pos);
+ if (take === blockLen) {
+ const dataView = createView(data);
+ for (; blockLen <= len - pos; pos += blockLen)
+ this.process(dataView, pos);
+ continue;
+ }
+ buffer.set(data.subarray(pos, pos + take), this.pos);
+ this.pos += take;
+ pos += take;
+ if (this.pos === blockLen) {
+ this.process(view, 0);
+ this.pos = 0;
+ }
+ }
+ this.length += data.length;
+ this.roundClean();
+ return this;
+ }
+ digestInto(out) {
+ exists(this);
+ output(out, this);
+ this.finished = true;
+ const { buffer, view, blockLen, isLE: isLE4 } = this;
+ let { pos } = this;
+ buffer[pos++] = 128;
+ this.buffer.subarray(pos).fill(0);
+ if (this.padOffset > blockLen - pos) {
+ this.process(view, 0);
+ pos = 0;
+ }
+ for (let i3 = pos; i3 < blockLen; i3++)
+ buffer[i3] = 0;
+ setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE4);
+ this.process(view, 0);
+ const oview = createView(out);
+ const len = this.outputLen;
+ if (len % 4)
+ throw new Error("_sha2: outputLen should be aligned to 32bit");
+ const outLen = len / 4;
+ const state = this.get();
+ if (outLen > state.length)
+ throw new Error("_sha2: outputLen bigger than state");
+ for (let i3 = 0; i3 < outLen; i3++)
+ oview.setUint32(4 * i3, state[i3], isLE4);
+ }
+ digest() {
+ const { buffer, outputLen } = this;
+ this.digestInto(buffer);
+ const res = buffer.slice(0, outputLen);
+ this.destroy();
+ return res;
+ }
+ _cloneInto(to) {
+ to || (to = new this.constructor());
+ to.set(...this.get());
+ const { blockLen, buffer, length, finished, destroyed, pos } = this;
+ to.length = length;
+ to.pos = pos;
+ to.finished = finished;
+ to.destroyed = destroyed;
+ if (length % blockLen)
+ to.buffer.set(buffer);
+ return to;
+ }
+};
+
+// node_modules/@noble/curves/node_modules/@noble/hashes/esm/sha256.js
+var Chi = (a, b, c) => a & b ^ ~a & c;
+var Maj = (a, b, c) => a & b ^ a & c ^ b & c;
+var SHA256_K = /* @__PURE__ */ new Uint32Array([
+ 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
+]);
+var IV = /* @__PURE__ */ new Uint32Array([
+ 1779033703,
+ 3144134277,
+ 1013904242,
+ 2773480762,
+ 1359893119,
+ 2600822924,
+ 528734635,
+ 1541459225
+]);
+var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
+var SHA256 = class extends SHA2 {
+ constructor() {
+ super(64, 32, 8, false);
+ this.A = IV[0] | 0;
+ this.B = IV[1] | 0;
+ this.C = IV[2] | 0;
+ this.D = IV[3] | 0;
+ this.E = IV[4] | 0;
+ this.F = IV[5] | 0;
+ this.G = IV[6] | 0;
+ this.H = IV[7] | 0;
+ }
+ get() {
+ const { A, B, C, D, E, F, G, H } = this;
+ return [A, B, C, D, E, F, G, H];
+ }
+ // prettier-ignore
+ set(A, B, C, D, E, F, G, H) {
+ this.A = A | 0;
+ this.B = B | 0;
+ this.C = C | 0;
+ this.D = D | 0;
+ this.E = E | 0;
+ this.F = F | 0;
+ this.G = G | 0;
+ this.H = H | 0;
+ }
+ process(view, offset) {
+ for (let i3 = 0; i3 < 16; i3++, offset += 4)
+ SHA256_W[i3] = view.getUint32(offset, false);
+ for (let i3 = 16; i3 < 64; i3++) {
+ const W15 = SHA256_W[i3 - 15];
+ const W2 = SHA256_W[i3 - 2];
+ const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
+ const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
+ SHA256_W[i3] = s1 + SHA256_W[i3 - 7] + s0 + SHA256_W[i3 - 16] | 0;
+ }
+ let { A, B, C, D, E, F, G, H } = this;
+ for (let i3 = 0; i3 < 64; i3++) {
+ const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
+ const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i3] + SHA256_W[i3] | 0;
+ const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
+ const T2 = sigma0 + Maj(A, B, C) | 0;
+ H = G;
+ G = F;
+ F = E;
+ E = D + T1 | 0;
+ D = C;
+ C = B;
+ B = A;
+ A = T1 + T2 | 0;
+ }
+ A = A + this.A | 0;
+ B = B + this.B | 0;
+ C = C + this.C | 0;
+ D = D + this.D | 0;
+ E = E + this.E | 0;
+ F = F + this.F | 0;
+ G = G + this.G | 0;
+ H = H + this.H | 0;
+ this.set(A, B, C, D, E, F, G, H);
+ }
+ roundClean() {
+ SHA256_W.fill(0);
+ }
+ destroy() {
+ this.set(0, 0, 0, 0, 0, 0, 0, 0);
+ this.buffer.fill(0);
+ }
+};
+var sha256 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
+
+// node_modules/@noble/curves/esm/abstract/utils.js
+var utils_exports = {};
+__export(utils_exports, {
+ bitGet: () => bitGet,
+ bitLen: () => bitLen,
+ bitMask: () => bitMask,
+ bitSet: () => bitSet,
+ bytesToHex: () => bytesToHex,
+ bytesToNumberBE: () => bytesToNumberBE,
+ bytesToNumberLE: () => bytesToNumberLE,
+ concatBytes: () => concatBytes2,
+ createHmacDrbg: () => createHmacDrbg,
+ ensureBytes: () => ensureBytes,
+ equalBytes: () => equalBytes,
+ hexToBytes: () => hexToBytes,
+ hexToNumber: () => hexToNumber,
+ numberToBytesBE: () => numberToBytesBE,
+ numberToBytesLE: () => numberToBytesLE,
+ numberToHexUnpadded: () => numberToHexUnpadded,
+ numberToVarBytesBE: () => numberToVarBytesBE,
+ utf8ToBytes: () => utf8ToBytes2,
+ validateObject: () => validateObject
+});
+var _0n = BigInt(0);
+var _1n = BigInt(1);
+var _2n = BigInt(2);
+var u8a2 = (a) => a instanceof Uint8Array;
+var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i3) => i3.toString(16).padStart(2, "0"));
+function bytesToHex(bytes4) {
+ if (!u8a2(bytes4))
+ throw new Error("Uint8Array expected");
+ let hex2 = "";
+ for (let i3 = 0; i3 < bytes4.length; i3++) {
+ hex2 += hexes[bytes4[i3]];
+ }
+ return hex2;
+}
+function numberToHexUnpadded(num) {
+ const hex2 = num.toString(16);
+ return hex2.length & 1 ? `0${hex2}` : hex2;
+}
+function hexToNumber(hex2) {
+ if (typeof hex2 !== "string")
+ throw new Error("hex string expected, got " + typeof hex2);
+ return BigInt(hex2 === "" ? "0" : `0x${hex2}`);
+}
+function hexToBytes(hex2) {
+ if (typeof hex2 !== "string")
+ throw new Error("hex string expected, got " + typeof hex2);
+ const len = hex2.length;
+ if (len % 2)
+ throw new Error("padded hex string expected, got unpadded hex of length " + len);
+ const array = new Uint8Array(len / 2);
+ for (let i3 = 0; i3 < array.length; i3++) {
+ const j = i3 * 2;
+ const hexByte = hex2.slice(j, j + 2);
+ const byte = Number.parseInt(hexByte, 16);
+ if (Number.isNaN(byte) || byte < 0)
+ throw new Error("Invalid byte sequence");
+ array[i3] = byte;
+ }
+ return array;
+}
+function bytesToNumberBE(bytes4) {
+ return hexToNumber(bytesToHex(bytes4));
+}
+function bytesToNumberLE(bytes4) {
+ if (!u8a2(bytes4))
+ throw new Error("Uint8Array expected");
+ return hexToNumber(bytesToHex(Uint8Array.from(bytes4).reverse()));
+}
+function numberToBytesBE(n, len) {
+ return hexToBytes(n.toString(16).padStart(len * 2, "0"));
+}
+function numberToBytesLE(n, len) {
+ return numberToBytesBE(n, len).reverse();
+}
+function numberToVarBytesBE(n) {
+ return hexToBytes(numberToHexUnpadded(n));
+}
+function ensureBytes(title, hex2, expectedLength) {
+ let res;
+ if (typeof hex2 === "string") {
+ try {
+ res = hexToBytes(hex2);
+ } catch (e) {
+ throw new Error(`${title} must be valid hex string, got "${hex2}". Cause: ${e}`);
+ }
+ } else if (u8a2(hex2)) {
+ res = Uint8Array.from(hex2);
+ } else {
+ throw new Error(`${title} must be hex string or Uint8Array`);
+ }
+ const len = res.length;
+ if (typeof expectedLength === "number" && len !== expectedLength)
+ throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);
+ return res;
+}
+function concatBytes2(...arrays) {
+ const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
+ let pad2 = 0;
+ arrays.forEach((a) => {
+ if (!u8a2(a))
+ throw new Error("Uint8Array expected");
+ r.set(a, pad2);
+ pad2 += a.length;
+ });
+ return r;
+}
+function equalBytes(b1, b2) {
+ if (b1.length !== b2.length)
+ return false;
+ for (let i3 = 0; i3 < b1.length; i3++)
+ if (b1[i3] !== b2[i3])
+ return false;
+ return true;
+}
+function utf8ToBytes2(str) {
+ if (typeof str !== "string")
+ throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
+ return new Uint8Array(new TextEncoder().encode(str));
+}
+function bitLen(n) {
+ let len;
+ for (len = 0; n > _0n; n >>= _1n, len += 1)
+ ;
+ return len;
+}
+function bitGet(n, pos) {
+ return n >> BigInt(pos) & _1n;
+}
+var bitSet = (n, pos, value) => {
+ return n | (value ? _1n : _0n) << BigInt(pos);
+};
+var bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;
+var u8n = (data) => new Uint8Array(data);
+var u8fr = (arr) => Uint8Array.from(arr);
+function createHmacDrbg(hashLen, qByteLen, hmacFn) {
+ if (typeof hashLen !== "number" || hashLen < 2)
+ throw new Error("hashLen must be a number");
+ if (typeof qByteLen !== "number" || qByteLen < 2)
+ throw new Error("qByteLen must be a number");
+ if (typeof hmacFn !== "function")
+ throw new Error("hmacFn must be a function");
+ let v = u8n(hashLen);
+ let k = u8n(hashLen);
+ let i3 = 0;
+ const reset = () => {
+ v.fill(1);
+ k.fill(0);
+ i3 = 0;
+ };
+ const h = (...b) => hmacFn(k, v, ...b);
+ const reseed = (seed = u8n()) => {
+ k = h(u8fr([0]), seed);
+ v = h();
+ if (seed.length === 0)
+ return;
+ k = h(u8fr([1]), seed);
+ v = h();
+ };
+ const gen = () => {
+ if (i3++ >= 1e3)
+ throw new Error("drbg: tried 1000 values");
+ let len = 0;
+ const out = [];
+ while (len < qByteLen) {
+ v = h();
+ const sl = v.slice();
+ out.push(sl);
+ len += v.length;
+ }
+ return concatBytes2(...out);
+ };
+ const genUntil = (seed, pred) => {
+ reset();
+ reseed(seed);
+ let res = void 0;
+ while (!(res = pred(gen())))
+ reseed();
+ reset();
+ return res;
+ };
+ return genUntil;
+}
+var validatorFns = {
+ bigint: (val) => typeof val === "bigint",
+ function: (val) => typeof val === "function",
+ boolean: (val) => typeof val === "boolean",
+ string: (val) => typeof val === "string",
+ stringOrUint8Array: (val) => typeof val === "string" || val instanceof Uint8Array,
+ isSafeInteger: (val) => Number.isSafeInteger(val),
+ array: (val) => Array.isArray(val),
+ field: (val, object) => object.Fp.isValid(val),
+ hash: (val) => typeof val === "function" && Number.isSafeInteger(val.outputLen)
+};
+function validateObject(object, validators, optValidators = {}) {
+ const checkField = (fieldName, type, isOptional) => {
+ const checkVal = validatorFns[type];
+ if (typeof checkVal !== "function")
+ throw new Error(`Invalid validator "${type}", expected function`);
+ const val = object[fieldName];
+ if (isOptional && val === void 0)
+ return;
+ if (!checkVal(val, object)) {
+ throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);
+ }
+ };
+ for (const [fieldName, type] of Object.entries(validators))
+ checkField(fieldName, type, false);
+ for (const [fieldName, type] of Object.entries(optValidators))
+ checkField(fieldName, type, true);
+ return object;
+}
+
+// node_modules/@noble/curves/esm/abstract/modular.js
+var _0n2 = BigInt(0);
+var _1n2 = BigInt(1);
+var _2n2 = BigInt(2);
+var _3n = BigInt(3);
+var _4n = BigInt(4);
+var _5n = BigInt(5);
+var _8n = BigInt(8);
+var _9n = BigInt(9);
+var _16n = BigInt(16);
+function mod(a, b) {
+ const result = a % b;
+ return result >= _0n2 ? result : b + result;
+}
+function pow(num, power, modulo) {
+ if (modulo <= _0n2 || power < _0n2)
+ throw new Error("Expected power/modulo > 0");
+ if (modulo === _1n2)
+ return _0n2;
+ let res = _1n2;
+ while (power > _0n2) {
+ if (power & _1n2)
+ res = res * num % modulo;
+ num = num * num % modulo;
+ power >>= _1n2;
+ }
+ return res;
+}
+function pow2(x, power, modulo) {
+ let res = x;
+ while (power-- > _0n2) {
+ res *= res;
+ res %= modulo;
+ }
+ return res;
+}
+function invert(number4, modulo) {
+ if (number4 === _0n2 || modulo <= _0n2) {
+ throw new Error(`invert: expected positive integers, got n=${number4} mod=${modulo}`);
+ }
+ let a = mod(number4, modulo);
+ let b = modulo;
+ let x = _0n2, y = _1n2, u = _1n2, v = _0n2;
+ while (a !== _0n2) {
+ const q = b / a;
+ const r = b % a;
+ const m = x - u * q;
+ const n = y - v * q;
+ b = a, a = r, x = u, y = v, u = m, v = n;
+ }
+ const gcd2 = b;
+ if (gcd2 !== _1n2)
+ throw new Error("invert: does not exist");
+ return mod(x, modulo);
+}
+function tonelliShanks(P) {
+ const legendreC = (P - _1n2) / _2n2;
+ let Q, S, Z;
+ for (Q = P - _1n2, S = 0; Q % _2n2 === _0n2; Q /= _2n2, S++)
+ ;
+ for (Z = _2n2; Z < P && pow(Z, legendreC, P) !== P - _1n2; Z++)
+ ;
+ if (S === 1) {
+ const p1div4 = (P + _1n2) / _4n;
+ return function tonelliFast(Fp2, n) {
+ const root = Fp2.pow(n, p1div4);
+ if (!Fp2.eql(Fp2.sqr(root), n))
+ throw new Error("Cannot find square root");
+ return root;
+ };
+ }
+ const Q1div2 = (Q + _1n2) / _2n2;
+ return function tonelliSlow(Fp2, n) {
+ if (Fp2.pow(n, legendreC) === Fp2.neg(Fp2.ONE))
+ throw new Error("Cannot find square root");
+ let r = S;
+ let g = Fp2.pow(Fp2.mul(Fp2.ONE, Z), Q);
+ let x = Fp2.pow(n, Q1div2);
+ let b = Fp2.pow(n, Q);
+ while (!Fp2.eql(b, Fp2.ONE)) {
+ if (Fp2.eql(b, Fp2.ZERO))
+ return Fp2.ZERO;
+ let m = 1;
+ for (let t2 = Fp2.sqr(b); m < r; m++) {
+ if (Fp2.eql(t2, Fp2.ONE))
+ break;
+ t2 = Fp2.sqr(t2);
+ }
+ const ge2 = Fp2.pow(g, _1n2 << BigInt(r - m - 1));
+ g = Fp2.sqr(ge2);
+ x = Fp2.mul(x, ge2);
+ b = Fp2.mul(b, g);
+ r = m;
+ }
+ return x;
+ };
+}
+function FpSqrt(P) {
+ if (P % _4n === _3n) {
+ const p1div4 = (P + _1n2) / _4n;
+ return function sqrt3mod4(Fp2, n) {
+ const root = Fp2.pow(n, p1div4);
+ if (!Fp2.eql(Fp2.sqr(root), n))
+ throw new Error("Cannot find square root");
+ return root;
+ };
+ }
+ if (P % _8n === _5n) {
+ const c1 = (P - _5n) / _8n;
+ return function sqrt5mod8(Fp2, n) {
+ const n2 = Fp2.mul(n, _2n2);
+ const v = Fp2.pow(n2, c1);
+ const nv = Fp2.mul(n, v);
+ const i3 = Fp2.mul(Fp2.mul(nv, _2n2), v);
+ const root = Fp2.mul(nv, Fp2.sub(i3, Fp2.ONE));
+ if (!Fp2.eql(Fp2.sqr(root), n))
+ throw new Error("Cannot find square root");
+ return root;
+ };
+ }
+ if (P % _16n === _9n) {
+ }
+ return tonelliShanks(P);
+}
+var FIELD_FIELDS = [
+ "create",
+ "isValid",
+ "is0",
+ "neg",
+ "inv",
+ "sqrt",
+ "sqr",
+ "eql",
+ "add",
+ "sub",
+ "mul",
+ "pow",
+ "div",
+ "addN",
+ "subN",
+ "mulN",
+ "sqrN"
+];
+function validateField(field) {
+ const initial = {
+ ORDER: "bigint",
+ MASK: "bigint",
+ BYTES: "isSafeInteger",
+ BITS: "isSafeInteger"
+ };
+ const opts = FIELD_FIELDS.reduce((map, val) => {
+ map[val] = "function";
+ return map;
+ }, initial);
+ return validateObject(field, opts);
+}
+function FpPow(f, num, power) {
+ if (power < _0n2)
+ throw new Error("Expected power > 0");
+ if (power === _0n2)
+ return f.ONE;
+ if (power === _1n2)
+ return num;
+ let p = f.ONE;
+ let d = num;
+ while (power > _0n2) {
+ if (power & _1n2)
+ p = f.mul(p, d);
+ d = f.sqr(d);
+ power >>= _1n2;
+ }
+ return p;
+}
+function FpInvertBatch(f, nums) {
+ const tmp = new Array(nums.length);
+ const lastMultiplied = nums.reduce((acc, num, i3) => {
+ if (f.is0(num))
+ return acc;
+ tmp[i3] = acc;
+ return f.mul(acc, num);
+ }, f.ONE);
+ const inverted = f.inv(lastMultiplied);
+ nums.reduceRight((acc, num, i3) => {
+ if (f.is0(num))
+ return acc;
+ tmp[i3] = f.mul(acc, tmp[i3]);
+ return f.mul(acc, num);
+ }, inverted);
+ return tmp;
+}
+function nLength(n, nBitLength) {
+ const _nBitLength = nBitLength !== void 0 ? nBitLength : n.toString(2).length;
+ const nByteLength = Math.ceil(_nBitLength / 8);
+ return { nBitLength: _nBitLength, nByteLength };
+}
+function Field(ORDER, bitLen2, isLE4 = false, redef = {}) {
+ if (ORDER <= _0n2)
+ throw new Error(`Expected Field ORDER > 0, got ${ORDER}`);
+ const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen2);
+ if (BYTES > 2048)
+ throw new Error("Field lengths over 2048 bytes are not supported");
+ const sqrtP = FpSqrt(ORDER);
+ const f = Object.freeze({
+ ORDER,
+ BITS,
+ BYTES,
+ MASK: bitMask(BITS),
+ ZERO: _0n2,
+ ONE: _1n2,
+ create: (num) => mod(num, ORDER),
+ isValid: (num) => {
+ if (typeof num !== "bigint")
+ throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);
+ return _0n2 <= num && num < ORDER;
+ },
+ is0: (num) => num === _0n2,
+ isOdd: (num) => (num & _1n2) === _1n2,
+ neg: (num) => mod(-num, ORDER),
+ eql: (lhs, rhs) => lhs === rhs,
+ sqr: (num) => mod(num * num, ORDER),
+ add: (lhs, rhs) => mod(lhs + rhs, ORDER),
+ sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
+ mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
+ pow: (num, power) => FpPow(f, num, power),
+ div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
+ // Same as above, but doesn't normalize
+ sqrN: (num) => num * num,
+ addN: (lhs, rhs) => lhs + rhs,
+ subN: (lhs, rhs) => lhs - rhs,
+ mulN: (lhs, rhs) => lhs * rhs,
+ inv: (num) => invert(num, ORDER),
+ sqrt: redef.sqrt || ((n) => sqrtP(f, n)),
+ invertBatch: (lst) => FpInvertBatch(f, lst),
+ // TODO: do we really need constant cmov?
+ // We don't have const-time bigints anyway, so probably will be not very useful
+ cmov: (a, b, c) => c ? b : a,
+ toBytes: (num) => isLE4 ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES),
+ fromBytes: (bytes4) => {
+ if (bytes4.length !== BYTES)
+ throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes4.length}`);
+ return isLE4 ? bytesToNumberLE(bytes4) : bytesToNumberBE(bytes4);
+ }
+ });
+ return Object.freeze(f);
+}
+function getFieldBytesLength(fieldOrder) {
+ if (typeof fieldOrder !== "bigint")
+ throw new Error("field order must be bigint");
+ const bitLength = fieldOrder.toString(2).length;
+ return Math.ceil(bitLength / 8);
+}
+function getMinHashLength(fieldOrder) {
+ const length = getFieldBytesLength(fieldOrder);
+ return length + Math.ceil(length / 2);
+}
+function mapHashToField(key, fieldOrder, isLE4 = false) {
+ const len = key.length;
+ const fieldLen = getFieldBytesLength(fieldOrder);
+ const minLen = getMinHashLength(fieldOrder);
+ if (len < 16 || len < minLen || len > 1024)
+ throw new Error(`expected ${minLen}-1024 bytes of input, got ${len}`);
+ const num = isLE4 ? bytesToNumberBE(key) : bytesToNumberLE(key);
+ const reduced = mod(num, fieldOrder - _1n2) + _1n2;
+ return isLE4 ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
+}
+
+// node_modules/@noble/curves/esm/abstract/curve.js
+var _0n3 = BigInt(0);
+var _1n3 = BigInt(1);
+function wNAF(c, bits) {
+ const constTimeNegate = (condition, item) => {
+ const neg = item.negate();
+ return condition ? neg : item;
+ };
+ const opts = (W) => {
+ const windows = Math.ceil(bits / W) + 1;
+ const windowSize = 2 ** (W - 1);
+ return { windows, windowSize };
+ };
+ return {
+ constTimeNegate,
+ // non-const time multiplication ladder
+ unsafeLadder(elm, n) {
+ let p = c.ZERO;
+ let d = elm;
+ while (n > _0n3) {
+ if (n & _1n3)
+ p = p.add(d);
+ d = d.double();
+ n >>= _1n3;
+ }
+ return p;
+ },
+ /**
+ * Creates a wNAF precomputation window. Used for caching.
+ * Default window size is set by `utils.precompute()` and is equal to 8.
+ * Number of precomputed points depends on the curve size:
+ * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
+ * - 𝑊 is the window size
+ * - 𝑛 is the bitlength of the curve order.
+ * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
+ * @returns precomputed point tables flattened to a single array
+ */
+ precomputeWindow(elm, W) {
+ const { windows, windowSize } = opts(W);
+ const points = [];
+ let p = elm;
+ let base = p;
+ for (let window = 0; window < windows; window++) {
+ base = p;
+ points.push(base);
+ for (let i3 = 1; i3 < windowSize; i3++) {
+ base = base.add(p);
+ points.push(base);
+ }
+ p = base.double();
+ }
+ return points;
+ },
+ /**
+ * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
+ * @param W window size
+ * @param precomputes precomputed tables
+ * @param n scalar (we don't check here, but should be less than curve order)
+ * @returns real and fake (for const-time) points
+ */
+ wNAF(W, precomputes, n) {
+ const { windows, windowSize } = opts(W);
+ let p = c.ZERO;
+ let f = c.BASE;
+ const mask = BigInt(2 ** W - 1);
+ const maxNumber = 2 ** W;
+ const shiftBy = BigInt(W);
+ for (let window = 0; window < windows; window++) {
+ const offset = window * windowSize;
+ let wbits = Number(n & mask);
+ n >>= shiftBy;
+ if (wbits > windowSize) {
+ wbits -= maxNumber;
+ n += _1n3;
+ }
+ const offset1 = offset;
+ const offset2 = offset + Math.abs(wbits) - 1;
+ const cond1 = window % 2 !== 0;
+ const cond2 = wbits < 0;
+ if (wbits === 0) {
+ f = f.add(constTimeNegate(cond1, precomputes[offset1]));
+ } else {
+ p = p.add(constTimeNegate(cond2, precomputes[offset2]));
+ }
+ }
+ return { p, f };
+ },
+ wNAFCached(P, precomputesMap, n, transform) {
+ const W = P._WINDOW_SIZE || 1;
+ let comp = precomputesMap.get(P);
+ if (!comp) {
+ comp = this.precomputeWindow(P, W);
+ if (W !== 1) {
+ precomputesMap.set(P, transform(comp));
+ }
+ }
+ return this.wNAF(W, comp, n);
+ }
+ };
+}
+function validateBasic(curve) {
+ validateField(curve.Fp);
+ validateObject(curve, {
+ n: "bigint",
+ h: "bigint",
+ Gx: "field",
+ Gy: "field"
+ }, {
+ nBitLength: "isSafeInteger",
+ nByteLength: "isSafeInteger"
+ });
+ return Object.freeze({
+ ...nLength(curve.n, curve.nBitLength),
+ ...curve,
+ ...{ p: curve.Fp.ORDER }
+ });
+}
+
+// node_modules/@noble/curves/esm/abstract/weierstrass.js
+function validatePointOpts(curve) {
+ const opts = validateBasic(curve);
+ validateObject(opts, {
+ a: "field",
+ b: "field"
+ }, {
+ allowedPrivateKeyLengths: "array",
+ wrapPrivateKey: "boolean",
+ isTorsionFree: "function",
+ clearCofactor: "function",
+ allowInfinityPoint: "boolean",
+ fromBytes: "function",
+ toBytes: "function"
+ });
+ const { endo, Fp: Fp2, a } = opts;
+ if (endo) {
+ if (!Fp2.eql(a, Fp2.ZERO)) {
+ throw new Error("Endomorphism can only be defined for Koblitz curves that have a=0");
+ }
+ if (typeof endo !== "object" || typeof endo.beta !== "bigint" || typeof endo.splitScalar !== "function") {
+ throw new Error("Expected endomorphism with beta: bigint and splitScalar: function");
+ }
+ }
+ return Object.freeze({ ...opts });
+}
+var { bytesToNumberBE: b2n, hexToBytes: h2b } = utils_exports;
+var DER = {
+ // asn.1 DER encoding utils
+ Err: class DERErr extends Error {
+ constructor(m = "") {
+ super(m);
+ }
+ },
+ _parseInt(data) {
+ const { Err: E } = DER;
+ if (data.length < 2 || data[0] !== 2)
+ throw new E("Invalid signature integer tag");
+ const len = data[1];
+ const res = data.subarray(2, len + 2);
+ if (!len || res.length !== len)
+ throw new E("Invalid signature integer: wrong length");
+ if (res[0] & 128)
+ throw new E("Invalid signature integer: negative");
+ if (res[0] === 0 && !(res[1] & 128))
+ throw new E("Invalid signature integer: unnecessary leading zero");
+ return { d: b2n(res), l: data.subarray(len + 2) };
+ },
+ toSig(hex2) {
+ const { Err: E } = DER;
+ const data = typeof hex2 === "string" ? h2b(hex2) : hex2;
+ if (!(data instanceof Uint8Array))
+ throw new Error("ui8a expected");
+ let l = data.length;
+ if (l < 2 || data[0] != 48)
+ throw new E("Invalid signature tag");
+ if (data[1] !== l - 2)
+ throw new E("Invalid signature: incorrect length");
+ const { d: r, l: sBytes } = DER._parseInt(data.subarray(2));
+ const { d: s, l: rBytesLeft } = DER._parseInt(sBytes);
+ if (rBytesLeft.length)
+ throw new E("Invalid signature: left bytes after parsing");
+ return { r, s };
+ },
+ hexFromSig(sig) {
+ const slice = (s2) => Number.parseInt(s2[0], 16) & 8 ? "00" + s2 : s2;
+ const h = (num) => {
+ const hex2 = num.toString(16);
+ return hex2.length & 1 ? `0${hex2}` : hex2;
+ };
+ const s = slice(h(sig.s));
+ const r = slice(h(sig.r));
+ const shl = s.length / 2;
+ const rhl = r.length / 2;
+ const sl = h(shl);
+ const rl = h(rhl);
+ return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`;
+ }
+};
+var _0n4 = BigInt(0);
+var _1n4 = BigInt(1);
+var _2n3 = BigInt(2);
+var _3n2 = BigInt(3);
+var _4n2 = BigInt(4);
+function weierstrassPoints(opts) {
+ const CURVE = validatePointOpts(opts);
+ const { Fp: Fp2 } = CURVE;
+ const toBytes4 = CURVE.toBytes || ((_c, point, _isCompressed) => {
+ const a = point.toAffine();
+ return concatBytes2(Uint8Array.from([4]), Fp2.toBytes(a.x), Fp2.toBytes(a.y));
+ });
+ const fromBytes = CURVE.fromBytes || ((bytes4) => {
+ const tail = bytes4.subarray(1);
+ const x = Fp2.fromBytes(tail.subarray(0, Fp2.BYTES));
+ const y = Fp2.fromBytes(tail.subarray(Fp2.BYTES, 2 * Fp2.BYTES));
+ return { x, y };
+ });
+ function weierstrassEquation(x) {
+ const { a, b } = CURVE;
+ const x2 = Fp2.sqr(x);
+ const x3 = Fp2.mul(x2, x);
+ return Fp2.add(Fp2.add(x3, Fp2.mul(x, a)), b);
+ }
+ if (!Fp2.eql(Fp2.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
+ throw new Error("bad generator point: equation left != right");
+ function isWithinCurveOrder(num) {
+ return typeof num === "bigint" && _0n4 < num && num < CURVE.n;
+ }
+ function assertGE(num) {
+ if (!isWithinCurveOrder(num))
+ throw new Error("Expected valid bigint: 0 < bigint < curve.n");
+ }
+ function normPrivateKeyToScalar(key) {
+ const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
+ if (lengths && typeof key !== "bigint") {
+ if (key instanceof Uint8Array)
+ key = bytesToHex(key);
+ if (typeof key !== "string" || !lengths.includes(key.length))
+ throw new Error("Invalid key");
+ key = key.padStart(nByteLength * 2, "0");
+ }
+ let num;
+ try {
+ num = typeof key === "bigint" ? key : bytesToNumberBE(ensureBytes("private key", key, nByteLength));
+ } catch (error) {
+ throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
+ }
+ if (wrapPrivateKey)
+ num = mod(num, n);
+ assertGE(num);
+ return num;
+ }
+ const pointPrecomputes = /* @__PURE__ */ new Map();
+ function assertPrjPoint(other) {
+ if (!(other instanceof Point2))
+ throw new Error("ProjectivePoint expected");
+ }
+ class Point2 {
+ constructor(px, py, pz) {
+ this.px = px;
+ this.py = py;
+ this.pz = pz;
+ if (px == null || !Fp2.isValid(px))
+ throw new Error("x required");
+ if (py == null || !Fp2.isValid(py))
+ throw new Error("y required");
+ if (pz == null || !Fp2.isValid(pz))
+ throw new Error("z required");
+ }
+ // Does not validate if the point is on-curve.
+ // Use fromHex instead, or call assertValidity() later.
+ static fromAffine(p) {
+ const { x, y } = p || {};
+ if (!p || !Fp2.isValid(x) || !Fp2.isValid(y))
+ throw new Error("invalid affine point");
+ if (p instanceof Point2)
+ throw new Error("projective point not allowed");
+ const is0 = (i3) => Fp2.eql(i3, Fp2.ZERO);
+ if (is0(x) && is0(y))
+ return Point2.ZERO;
+ return new Point2(x, y, Fp2.ONE);
+ }
+ get x() {
+ return this.toAffine().x;
+ }
+ get y() {
+ return this.toAffine().y;
+ }
+ /**
+ * Takes a bunch of Projective Points but executes only one
+ * inversion on all of them. Inversion is very slow operation,
+ * so this improves performance massively.
+ * Optimization: converts a list of projective points to a list of identical points with Z=1.
+ */
+ static normalizeZ(points) {
+ const toInv = Fp2.invertBatch(points.map((p) => p.pz));
+ return points.map((p, i3) => p.toAffine(toInv[i3])).map(Point2.fromAffine);
+ }
+ /**
+ * Converts hash string or Uint8Array to Point.
+ * @param hex short/long ECDSA hex
+ */
+ static fromHex(hex2) {
+ const P = Point2.fromAffine(fromBytes(ensureBytes("pointHex", hex2)));
+ P.assertValidity();
+ return P;
+ }
+ // Multiplies generator point by privateKey.
+ static fromPrivateKey(privateKey) {
+ return Point2.BASE.multiply(normPrivateKeyToScalar(privateKey));
+ }
+ // "Private method", don't use it directly
+ _setWindowSize(windowSize) {
+ this._WINDOW_SIZE = windowSize;
+ pointPrecomputes.delete(this);
+ }
+ // A point on curve is valid if it conforms to equation.
+ assertValidity() {
+ if (this.is0()) {
+ if (CURVE.allowInfinityPoint && !Fp2.is0(this.py))
+ return;
+ throw new Error("bad point: ZERO");
+ }
+ const { x, y } = this.toAffine();
+ if (!Fp2.isValid(x) || !Fp2.isValid(y))
+ throw new Error("bad point: x or y not FE");
+ const left = Fp2.sqr(y);
+ const right = weierstrassEquation(x);
+ if (!Fp2.eql(left, right))
+ throw new Error("bad point: equation left != right");
+ if (!this.isTorsionFree())
+ throw new Error("bad point: not in prime-order subgroup");
+ }
+ hasEvenY() {
+ const { y } = this.toAffine();
+ if (Fp2.isOdd)
+ return !Fp2.isOdd(y);
+ throw new Error("Field doesn't support isOdd");
+ }
+ /**
+ * Compare one point to another.
+ */
+ equals(other) {
+ assertPrjPoint(other);
+ const { px: X1, py: Y1, pz: Z1 } = this;
+ const { px: X2, py: Y2, pz: Z2 } = other;
+ const U1 = Fp2.eql(Fp2.mul(X1, Z2), Fp2.mul(X2, Z1));
+ const U2 = Fp2.eql(Fp2.mul(Y1, Z2), Fp2.mul(Y2, Z1));
+ return U1 && U2;
+ }
+ /**
+ * Flips point to one corresponding to (x, -y) in Affine coordinates.
+ */
+ negate() {
+ return new Point2(this.px, Fp2.neg(this.py), this.pz);
+ }
+ // Renes-Costello-Batina exception-free doubling formula.
+ // There is 30% faster Jacobian formula, but it is not complete.
+ // https://eprint.iacr.org/2015/1060, algorithm 3
+ // Cost: 8M + 3S + 3*a + 2*b3 + 15add.
+ double() {
+ const { a, b } = CURVE;
+ const b3 = Fp2.mul(b, _3n2);
+ const { px: X1, py: Y1, pz: Z1 } = this;
+ let X3 = Fp2.ZERO, Y3 = Fp2.ZERO, Z3 = Fp2.ZERO;
+ let t0 = Fp2.mul(X1, X1);
+ let t1 = Fp2.mul(Y1, Y1);
+ let t2 = Fp2.mul(Z1, Z1);
+ let t3 = Fp2.mul(X1, Y1);
+ t3 = Fp2.add(t3, t3);
+ Z3 = Fp2.mul(X1, Z1);
+ Z3 = Fp2.add(Z3, Z3);
+ X3 = Fp2.mul(a, Z3);
+ Y3 = Fp2.mul(b3, t2);
+ Y3 = Fp2.add(X3, Y3);
+ X3 = Fp2.sub(t1, Y3);
+ Y3 = Fp2.add(t1, Y3);
+ Y3 = Fp2.mul(X3, Y3);
+ X3 = Fp2.mul(t3, X3);
+ Z3 = Fp2.mul(b3, Z3);
+ t2 = Fp2.mul(a, t2);
+ t3 = Fp2.sub(t0, t2);
+ t3 = Fp2.mul(a, t3);
+ t3 = Fp2.add(t3, Z3);
+ Z3 = Fp2.add(t0, t0);
+ t0 = Fp2.add(Z3, t0);
+ t0 = Fp2.add(t0, t2);
+ t0 = Fp2.mul(t0, t3);
+ Y3 = Fp2.add(Y3, t0);
+ t2 = Fp2.mul(Y1, Z1);
+ t2 = Fp2.add(t2, t2);
+ t0 = Fp2.mul(t2, t3);
+ X3 = Fp2.sub(X3, t0);
+ Z3 = Fp2.mul(t2, t1);
+ Z3 = Fp2.add(Z3, Z3);
+ Z3 = Fp2.add(Z3, Z3);
+ return new Point2(X3, Y3, Z3);
+ }
+ // Renes-Costello-Batina exception-free addition formula.
+ // There is 30% faster Jacobian formula, but it is not complete.
+ // https://eprint.iacr.org/2015/1060, algorithm 1
+ // Cost: 12M + 0S + 3*a + 3*b3 + 23add.
+ add(other) {
+ assertPrjPoint(other);
+ const { px: X1, py: Y1, pz: Z1 } = this;
+ const { px: X2, py: Y2, pz: Z2 } = other;
+ let X3 = Fp2.ZERO, Y3 = Fp2.ZERO, Z3 = Fp2.ZERO;
+ const a = CURVE.a;
+ const b3 = Fp2.mul(CURVE.b, _3n2);
+ let t0 = Fp2.mul(X1, X2);
+ let t1 = Fp2.mul(Y1, Y2);
+ let t2 = Fp2.mul(Z1, Z2);
+ let t3 = Fp2.add(X1, Y1);
+ let t4 = Fp2.add(X2, Y2);
+ t3 = Fp2.mul(t3, t4);
+ t4 = Fp2.add(t0, t1);
+ t3 = Fp2.sub(t3, t4);
+ t4 = Fp2.add(X1, Z1);
+ let t5 = Fp2.add(X2, Z2);
+ t4 = Fp2.mul(t4, t5);
+ t5 = Fp2.add(t0, t2);
+ t4 = Fp2.sub(t4, t5);
+ t5 = Fp2.add(Y1, Z1);
+ X3 = Fp2.add(Y2, Z2);
+ t5 = Fp2.mul(t5, X3);
+ X3 = Fp2.add(t1, t2);
+ t5 = Fp2.sub(t5, X3);
+ Z3 = Fp2.mul(a, t4);
+ X3 = Fp2.mul(b3, t2);
+ Z3 = Fp2.add(X3, Z3);
+ X3 = Fp2.sub(t1, Z3);
+ Z3 = Fp2.add(t1, Z3);
+ Y3 = Fp2.mul(X3, Z3);
+ t1 = Fp2.add(t0, t0);
+ t1 = Fp2.add(t1, t0);
+ t2 = Fp2.mul(a, t2);
+ t4 = Fp2.mul(b3, t4);
+ t1 = Fp2.add(t1, t2);
+ t2 = Fp2.sub(t0, t2);
+ t2 = Fp2.mul(a, t2);
+ t4 = Fp2.add(t4, t2);
+ t0 = Fp2.mul(t1, t4);
+ Y3 = Fp2.add(Y3, t0);
+ t0 = Fp2.mul(t5, t4);
+ X3 = Fp2.mul(t3, X3);
+ X3 = Fp2.sub(X3, t0);
+ t0 = Fp2.mul(t3, t1);
+ Z3 = Fp2.mul(t5, Z3);
+ Z3 = Fp2.add(Z3, t0);
+ return new Point2(X3, Y3, Z3);
+ }
+ subtract(other) {
+ return this.add(other.negate());
+ }
+ is0() {
+ return this.equals(Point2.ZERO);
+ }
+ wNAF(n) {
+ return wnaf.wNAFCached(this, pointPrecomputes, n, (comp) => {
+ const toInv = Fp2.invertBatch(comp.map((p) => p.pz));
+ return comp.map((p, i3) => p.toAffine(toInv[i3])).map(Point2.fromAffine);
+ });
+ }
+ /**
+ * Non-constant-time multiplication. Uses double-and-add algorithm.
+ * It's faster, but should only be used when you don't care about
+ * an exposed private key e.g. sig verification, which works over *public* keys.
+ */
+ multiplyUnsafe(n) {
+ const I = Point2.ZERO;
+ if (n === _0n4)
+ return I;
+ assertGE(n);
+ if (n === _1n4)
+ return this;
+ const { endo } = CURVE;
+ if (!endo)
+ return wnaf.unsafeLadder(this, n);
+ let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
+ let k1p = I;
+ let k2p = I;
+ let d = this;
+ while (k1 > _0n4 || k2 > _0n4) {
+ if (k1 & _1n4)
+ k1p = k1p.add(d);
+ if (k2 & _1n4)
+ k2p = k2p.add(d);
+ d = d.double();
+ k1 >>= _1n4;
+ k2 >>= _1n4;
+ }
+ if (k1neg)
+ k1p = k1p.negate();
+ if (k2neg)
+ k2p = k2p.negate();
+ k2p = new Point2(Fp2.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
+ return k1p.add(k2p);
+ }
+ /**
+ * Constant time multiplication.
+ * Uses wNAF method. Windowed method may be 10% faster,
+ * but takes 2x longer to generate and consumes 2x memory.
+ * Uses precomputes when available.
+ * Uses endomorphism for Koblitz curves.
+ * @param scalar by which the point would be multiplied
+ * @returns New point
+ */
+ multiply(scalar) {
+ assertGE(scalar);
+ let n = scalar;
+ let point, fake;
+ const { endo } = CURVE;
+ if (endo) {
+ const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
+ let { p: k1p, f: f1p } = this.wNAF(k1);
+ let { p: k2p, f: f2p } = this.wNAF(k2);
+ k1p = wnaf.constTimeNegate(k1neg, k1p);
+ k2p = wnaf.constTimeNegate(k2neg, k2p);
+ k2p = new Point2(Fp2.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
+ point = k1p.add(k2p);
+ fake = f1p.add(f2p);
+ } else {
+ const { p, f } = this.wNAF(n);
+ point = p;
+ fake = f;
+ }
+ return Point2.normalizeZ([point, fake])[0];
+ }
+ /**
+ * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.
+ * Not using Strauss-Shamir trick: precomputation tables are faster.
+ * The trick could be useful if both P and Q are not G (not in our case).
+ * @returns non-zero affine point
+ */
+ multiplyAndAddUnsafe(Q, a, b) {
+ const G = Point2.BASE;
+ const mul3 = (P, a2) => a2 === _0n4 || a2 === _1n4 || !P.equals(G) ? P.multiplyUnsafe(a2) : P.multiply(a2);
+ const sum = mul3(this, a).add(mul3(Q, b));
+ return sum.is0() ? void 0 : sum;
+ }
+ // Converts Projective point to affine (x, y) coordinates.
+ // Can accept precomputed Z^-1 - for example, from invertBatch.
+ // (x, y, z) ∋ (x=x/z, y=y/z)
+ toAffine(iz) {
+ const { px: x, py: y, pz: z } = this;
+ const is0 = this.is0();
+ if (iz == null)
+ iz = is0 ? Fp2.ONE : Fp2.inv(z);
+ const ax = Fp2.mul(x, iz);
+ const ay = Fp2.mul(y, iz);
+ const zz = Fp2.mul(z, iz);
+ if (is0)
+ return { x: Fp2.ZERO, y: Fp2.ZERO };
+ if (!Fp2.eql(zz, Fp2.ONE))
+ throw new Error("invZ was invalid");
+ return { x: ax, y: ay };
+ }
+ isTorsionFree() {
+ const { h: cofactor, isTorsionFree } = CURVE;
+ if (cofactor === _1n4)
+ return true;
+ if (isTorsionFree)
+ return isTorsionFree(Point2, this);
+ throw new Error("isTorsionFree() has not been declared for the elliptic curve");
+ }
+ clearCofactor() {
+ const { h: cofactor, clearCofactor } = CURVE;
+ if (cofactor === _1n4)
+ return this;
+ if (clearCofactor)
+ return clearCofactor(Point2, this);
+ return this.multiplyUnsafe(CURVE.h);
+ }
+ toRawBytes(isCompressed = true) {
+ this.assertValidity();
+ return toBytes4(Point2, this, isCompressed);
+ }
+ toHex(isCompressed = true) {
+ return bytesToHex(this.toRawBytes(isCompressed));
+ }
+ }
+ Point2.BASE = new Point2(CURVE.Gx, CURVE.Gy, Fp2.ONE);
+ Point2.ZERO = new Point2(Fp2.ZERO, Fp2.ONE, Fp2.ZERO);
+ const _bits = CURVE.nBitLength;
+ const wnaf = wNAF(Point2, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
+ return {
+ CURVE,
+ ProjectivePoint: Point2,
+ normPrivateKeyToScalar,
+ weierstrassEquation,
+ isWithinCurveOrder
+ };
+}
+function validateOpts(curve) {
+ const opts = validateBasic(curve);
+ validateObject(opts, {
+ hash: "hash",
+ hmac: "function",
+ randomBytes: "function"
+ }, {
+ bits2int: "function",
+ bits2int_modN: "function",
+ lowS: "boolean"
+ });
+ return Object.freeze({ lowS: true, ...opts });
+}
+function weierstrass(curveDef) {
+ const CURVE = validateOpts(curveDef);
+ const { Fp: Fp2, n: CURVE_ORDER } = CURVE;
+ const compressedLen = Fp2.BYTES + 1;
+ const uncompressedLen = 2 * Fp2.BYTES + 1;
+ function isValidFieldElement(num) {
+ return _0n4 < num && num < Fp2.ORDER;
+ }
+ function modN2(a) {
+ return mod(a, CURVE_ORDER);
+ }
+ function invN(a) {
+ return invert(a, CURVE_ORDER);
+ }
+ const { ProjectivePoint: Point2, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder } = weierstrassPoints({
+ ...CURVE,
+ toBytes(_c, point, isCompressed) {
+ const a = point.toAffine();
+ const x = Fp2.toBytes(a.x);
+ const cat = concatBytes2;
+ if (isCompressed) {
+ return cat(Uint8Array.from([point.hasEvenY() ? 2 : 3]), x);
+ } else {
+ return cat(Uint8Array.from([4]), x, Fp2.toBytes(a.y));
+ }
+ },
+ fromBytes(bytes4) {
+ const len = bytes4.length;
+ const head = bytes4[0];
+ const tail = bytes4.subarray(1);
+ if (len === compressedLen && (head === 2 || head === 3)) {
+ const x = bytesToNumberBE(tail);
+ if (!isValidFieldElement(x))
+ throw new Error("Point is not on curve");
+ const y2 = weierstrassEquation(x);
+ let y = Fp2.sqrt(y2);
+ const isYOdd = (y & _1n4) === _1n4;
+ const isHeadOdd = (head & 1) === 1;
+ if (isHeadOdd !== isYOdd)
+ y = Fp2.neg(y);
+ return { x, y };
+ } else if (len === uncompressedLen && head === 4) {
+ const x = Fp2.fromBytes(tail.subarray(0, Fp2.BYTES));
+ const y = Fp2.fromBytes(tail.subarray(Fp2.BYTES, 2 * Fp2.BYTES));
+ return { x, y };
+ } else {
+ throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
+ }
+ }
+ });
+ const numToNByteStr = (num) => bytesToHex(numberToBytesBE(num, CURVE.nByteLength));
+ function isBiggerThanHalfOrder(number4) {
+ const HALF = CURVE_ORDER >> _1n4;
+ return number4 > HALF;
+ }
+ function normalizeS(s) {
+ return isBiggerThanHalfOrder(s) ? modN2(-s) : s;
+ }
+ const slcNum = (b, from, to) => bytesToNumberBE(b.slice(from, to));
+ class Signature {
+ constructor(r, s, recovery) {
+ this.r = r;
+ this.s = s;
+ this.recovery = recovery;
+ this.assertValidity();
+ }
+ // pair (bytes of r, bytes of s)
+ static fromCompact(hex2) {
+ const l = CURVE.nByteLength;
+ hex2 = ensureBytes("compactSignature", hex2, l * 2);
+ return new Signature(slcNum(hex2, 0, l), slcNum(hex2, l, 2 * l));
+ }
+ // DER encoded ECDSA signature
+ // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
+ static fromDER(hex2) {
+ const { r, s } = DER.toSig(ensureBytes("DER", hex2));
+ return new Signature(r, s);
+ }
+ assertValidity() {
+ if (!isWithinCurveOrder(this.r))
+ throw new Error("r must be 0 < r < CURVE.n");
+ if (!isWithinCurveOrder(this.s))
+ throw new Error("s must be 0 < s < CURVE.n");
+ }
+ addRecoveryBit(recovery) {
+ return new Signature(this.r, this.s, recovery);
+ }
+ recoverPublicKey(msgHash) {
+ const { r, s, recovery: rec } = this;
+ const h = bits2int_modN(ensureBytes("msgHash", msgHash));
+ if (rec == null || ![0, 1, 2, 3].includes(rec))
+ throw new Error("recovery id invalid");
+ const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
+ if (radj >= Fp2.ORDER)
+ throw new Error("recovery id 2 or 3 invalid");
+ const prefix = (rec & 1) === 0 ? "02" : "03";
+ const R = Point2.fromHex(prefix + numToNByteStr(radj));
+ const ir = invN(radj);
+ const u1 = modN2(-h * ir);
+ const u2 = modN2(s * ir);
+ const Q = Point2.BASE.multiplyAndAddUnsafe(R, u1, u2);
+ if (!Q)
+ throw new Error("point at infinify");
+ Q.assertValidity();
+ return Q;
+ }
+ // Signatures should be low-s, to prevent malleability.
+ hasHighS() {
+ return isBiggerThanHalfOrder(this.s);
+ }
+ normalizeS() {
+ return this.hasHighS() ? new Signature(this.r, modN2(-this.s), this.recovery) : this;
+ }
+ // DER-encoded
+ toDERRawBytes() {
+ return hexToBytes(this.toDERHex());
+ }
+ toDERHex() {
+ return DER.hexFromSig({ r: this.r, s: this.s });
+ }
+ // padded bytes of r, then padded bytes of s
+ toCompactRawBytes() {
+ return hexToBytes(this.toCompactHex());
+ }
+ toCompactHex() {
+ return numToNByteStr(this.r) + numToNByteStr(this.s);
+ }
+ }
+ const utils = {
+ isValidPrivateKey(privateKey) {
+ try {
+ normPrivateKeyToScalar(privateKey);
+ return true;
+ } catch (error) {
+ return false;
+ }
+ },
+ normPrivateKeyToScalar,
+ /**
+ * Produces cryptographically secure private key from random of size
+ * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
+ */
+ randomPrivateKey: () => {
+ const length = getMinHashLength(CURVE.n);
+ return mapHashToField(CURVE.randomBytes(length), CURVE.n);
+ },
+ /**
+ * Creates precompute table for an arbitrary EC point. Makes point "cached".
+ * Allows to massively speed-up `point.multiply(scalar)`.
+ * @returns cached point
+ * @example
+ * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));
+ * fast.multiply(privKey); // much faster ECDH now
+ */
+ precompute(windowSize = 8, point = Point2.BASE) {
+ point._setWindowSize(windowSize);
+ point.multiply(BigInt(3));
+ return point;
+ }
+ };
+ function getPublicKey3(privateKey, isCompressed = true) {
+ return Point2.fromPrivateKey(privateKey).toRawBytes(isCompressed);
+ }
+ function isProbPub(item) {
+ const arr = item instanceof Uint8Array;
+ const str = typeof item === "string";
+ const len = (arr || str) && item.length;
+ if (arr)
+ return len === compressedLen || len === uncompressedLen;
+ if (str)
+ return len === 2 * compressedLen || len === 2 * uncompressedLen;
+ if (item instanceof Point2)
+ return true;
+ return false;
+ }
+ function getSharedSecret(privateA, publicB, isCompressed = true) {
+ if (isProbPub(privateA))
+ throw new Error("first arg must be private key");
+ if (!isProbPub(publicB))
+ throw new Error("second arg must be public key");
+ const b = Point2.fromHex(publicB);
+ return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
+ }
+ const bits2int = CURVE.bits2int || function(bytes4) {
+ const num = bytesToNumberBE(bytes4);
+ const delta = bytes4.length * 8 - CURVE.nBitLength;
+ return delta > 0 ? num >> BigInt(delta) : num;
+ };
+ const bits2int_modN = CURVE.bits2int_modN || function(bytes4) {
+ return modN2(bits2int(bytes4));
+ };
+ const ORDER_MASK = bitMask(CURVE.nBitLength);
+ function int2octets(num) {
+ if (typeof num !== "bigint")
+ throw new Error("bigint expected");
+ if (!(_0n4 <= num && num < ORDER_MASK))
+ throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
+ return numberToBytesBE(num, CURVE.nByteLength);
+ }
+ function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
+ if (["recovered", "canonical"].some((k) => k in opts))
+ throw new Error("sign() legacy options not supported");
+ const { hash: hash3, randomBytes: randomBytes3 } = CURVE;
+ let { lowS, prehash, extraEntropy: ent } = opts;
+ if (lowS == null)
+ lowS = true;
+ msgHash = ensureBytes("msgHash", msgHash);
+ if (prehash)
+ msgHash = ensureBytes("prehashed msgHash", hash3(msgHash));
+ const h1int = bits2int_modN(msgHash);
+ const d = normPrivateKeyToScalar(privateKey);
+ const seedArgs = [int2octets(d), int2octets(h1int)];
+ if (ent != null) {
+ const e = ent === true ? randomBytes3(Fp2.BYTES) : ent;
+ seedArgs.push(ensureBytes("extraEntropy", e));
+ }
+ const seed = concatBytes2(...seedArgs);
+ const m = h1int;
+ function k2sig(kBytes) {
+ const k = bits2int(kBytes);
+ if (!isWithinCurveOrder(k))
+ return;
+ const ik = invN(k);
+ const q = Point2.BASE.multiply(k).toAffine();
+ const r = modN2(q.x);
+ if (r === _0n4)
+ return;
+ const s = modN2(ik * modN2(m + r * d));
+ if (s === _0n4)
+ return;
+ let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n4);
+ let normS = s;
+ if (lowS && isBiggerThanHalfOrder(s)) {
+ normS = normalizeS(s);
+ recovery ^= 1;
+ }
+ return new Signature(r, normS, recovery);
+ }
+ return { seed, k2sig };
+ }
+ const defaultSigOpts = { lowS: CURVE.lowS, prehash: false };
+ const defaultVerOpts = { lowS: CURVE.lowS, prehash: false };
+ function sign(msgHash, privKey, opts = defaultSigOpts) {
+ const { seed, k2sig } = prepSig(msgHash, privKey, opts);
+ const C = CURVE;
+ const drbg = createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac);
+ return drbg(seed, k2sig);
+ }
+ Point2.BASE._setWindowSize(8);
+ function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {
+ const sg = signature;
+ msgHash = ensureBytes("msgHash", msgHash);
+ publicKey = ensureBytes("publicKey", publicKey);
+ if ("strict" in opts)
+ throw new Error("options.strict was renamed to lowS");
+ const { lowS, prehash } = opts;
+ let _sig = void 0;
+ let P;
+ try {
+ if (typeof sg === "string" || sg instanceof Uint8Array) {
+ try {
+ _sig = Signature.fromDER(sg);
+ } catch (derError) {
+ if (!(derError instanceof DER.Err))
+ throw derError;
+ _sig = Signature.fromCompact(sg);
+ }
+ } else if (typeof sg === "object" && typeof sg.r === "bigint" && typeof sg.s === "bigint") {
+ const { r: r2, s: s2 } = sg;
+ _sig = new Signature(r2, s2);
+ } else {
+ throw new Error("PARSE");
+ }
+ P = Point2.fromHex(publicKey);
+ } catch (error) {
+ if (error.message === "PARSE")
+ throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
+ return false;
+ }
+ if (lowS && _sig.hasHighS())
+ return false;
+ if (prehash)
+ msgHash = CURVE.hash(msgHash);
+ const { r, s } = _sig;
+ const h = bits2int_modN(msgHash);
+ const is = invN(s);
+ const u1 = modN2(h * is);
+ const u2 = modN2(r * is);
+ const R = Point2.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine();
+ if (!R)
+ return false;
+ const v = modN2(R.x);
+ return v === r;
+ }
+ return {
+ CURVE,
+ getPublicKey: getPublicKey3,
+ getSharedSecret,
+ sign,
+ verify,
+ ProjectivePoint: Point2,
+ Signature,
+ utils
+ };
+}
+
+// node_modules/@noble/curves/node_modules/@noble/hashes/esm/hmac.js
+var HMAC = class extends Hash {
+ constructor(hash3, _key) {
+ super();
+ this.finished = false;
+ this.destroyed = false;
+ hash(hash3);
+ const key = toBytes(_key);
+ this.iHash = hash3.create();
+ if (typeof this.iHash.update !== "function")
+ throw new Error("Expected instance of class which extends utils.Hash");
+ this.blockLen = this.iHash.blockLen;
+ this.outputLen = this.iHash.outputLen;
+ const blockLen = this.blockLen;
+ const pad2 = new Uint8Array(blockLen);
+ pad2.set(key.length > blockLen ? hash3.create().update(key).digest() : key);
+ for (let i3 = 0; i3 < pad2.length; i3++)
+ pad2[i3] ^= 54;
+ this.iHash.update(pad2);
+ this.oHash = hash3.create();
+ for (let i3 = 0; i3 < pad2.length; i3++)
+ pad2[i3] ^= 54 ^ 92;
+ this.oHash.update(pad2);
+ pad2.fill(0);
+ }
+ update(buf) {
+ exists(this);
+ this.iHash.update(buf);
+ return this;
+ }
+ digestInto(out) {
+ exists(this);
+ bytes(out, this.outputLen);
+ this.finished = true;
+ this.iHash.digestInto(out);
+ this.oHash.update(out);
+ this.oHash.digestInto(out);
+ this.destroy();
+ }
+ digest() {
+ const out = new Uint8Array(this.oHash.outputLen);
+ this.digestInto(out);
+ return out;
+ }
+ _cloneInto(to) {
+ to || (to = Object.create(Object.getPrototypeOf(this), {}));
+ const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
+ to = to;
+ to.finished = finished;
+ to.destroyed = destroyed;
+ to.blockLen = blockLen;
+ to.outputLen = outputLen;
+ to.oHash = oHash._cloneInto(to.oHash);
+ to.iHash = iHash._cloneInto(to.iHash);
+ return to;
+ }
+ destroy() {
+ this.destroyed = true;
+ this.oHash.destroy();
+ this.iHash.destroy();
+ }
+};
+var hmac = (hash3, key, message) => new HMAC(hash3, key).update(message).digest();
+hmac.create = (hash3, key) => new HMAC(hash3, key);
+
+// node_modules/@noble/curves/esm/_shortw_utils.js
+function getHash(hash3) {
+ return {
+ hash: hash3,
+ hmac: (key, ...msgs) => hmac(hash3, key, concatBytes(...msgs)),
+ randomBytes
+ };
+}
+function createCurve(curveDef, defHash) {
+ const create = (hash3) => weierstrass({ ...curveDef, ...getHash(hash3) });
+ return Object.freeze({ ...create(defHash), create });
+}
+
+// node_modules/@noble/curves/esm/secp256k1.js
+var secp256k1P = BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f");
+var secp256k1N = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
+var _1n5 = BigInt(1);
+var _2n4 = BigInt(2);
+var divNearest = (a, b) => (a + b / _2n4) / b;
+function sqrtMod(y) {
+ const P = secp256k1P;
+ const _3n3 = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);
+ const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88);
+ const b2 = y * y * y % P;
+ const b3 = b2 * b2 * y % P;
+ const b6 = pow2(b3, _3n3, P) * b3 % P;
+ const b9 = pow2(b6, _3n3, P) * b3 % P;
+ const b11 = pow2(b9, _2n4, P) * b2 % P;
+ const b22 = pow2(b11, _11n, P) * b11 % P;
+ const b44 = pow2(b22, _22n, P) * b22 % P;
+ const b88 = pow2(b44, _44n, P) * b44 % P;
+ const b176 = pow2(b88, _88n, P) * b88 % P;
+ const b220 = pow2(b176, _44n, P) * b44 % P;
+ const b223 = pow2(b220, _3n3, P) * b3 % P;
+ const t1 = pow2(b223, _23n, P) * b22 % P;
+ const t2 = pow2(t1, _6n, P) * b2 % P;
+ const root = pow2(t2, _2n4, P);
+ if (!Fp.eql(Fp.sqr(root), y))
+ throw new Error("Cannot find square root");
+ return root;
+}
+var Fp = Field(secp256k1P, void 0, void 0, { sqrt: sqrtMod });
+var secp256k1 = createCurve({
+ a: BigInt(0),
+ b: BigInt(7),
+ Fp,
+ n: secp256k1N,
+ // Base point (x, y) aka generator point
+ Gx: BigInt("55066263022277343669578718895168534326250603453777594175500187360389116729240"),
+ Gy: BigInt("32670510020758816978083085130507043184471273380659243275938904335757337482424"),
+ h: BigInt(1),
+ lowS: true,
+ /**
+ * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.
+ * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
+ * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.
+ * Explanation: https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
+ */
+ endo: {
+ beta: BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"),
+ splitScalar: (k) => {
+ const n = secp256k1N;
+ const a1 = BigInt("0x3086d221a7d46bcde86c90e49284eb15");
+ const b1 = -_1n5 * BigInt("0xe4437ed6010e88286f547fa90abfe4c3");
+ const a2 = BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8");
+ const b2 = a1;
+ const POW_2_128 = BigInt("0x100000000000000000000000000000000");
+ const c1 = divNearest(b2 * k, n);
+ const c2 = divNearest(-b1 * k, n);
+ let k1 = mod(k - c1 * a1 - c2 * a2, n);
+ let k2 = mod(-c1 * b1 - c2 * b2, n);
+ const k1neg = k1 > POW_2_128;
+ const k2neg = k2 > POW_2_128;
+ if (k1neg)
+ k1 = n - k1;
+ if (k2neg)
+ k2 = n - k2;
+ if (k1 > POW_2_128 || k2 > POW_2_128) {
+ throw new Error("splitScalar: Endomorphism failed, k=" + k);
+ }
+ return { k1neg, k1, k2neg, k2 };
+ }
+ }
+}, sha256);
+var _0n5 = BigInt(0);
+var fe = (x) => typeof x === "bigint" && _0n5 < x && x < secp256k1P;
+var ge = (x) => typeof x === "bigint" && _0n5 < x && x < secp256k1N;
+var TAGGED_HASH_PREFIXES = {};
+function taggedHash(tag, ...messages) {
+ let tagP = TAGGED_HASH_PREFIXES[tag];
+ if (tagP === void 0) {
+ const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0)));
+ tagP = concatBytes2(tagH, tagH);
+ TAGGED_HASH_PREFIXES[tag] = tagP;
+ }
+ return sha256(concatBytes2(tagP, ...messages));
+}
+var pointToBytes = (point) => point.toRawBytes(true).slice(1);
+var numTo32b = (n) => numberToBytesBE(n, 32);
+var modP = (x) => mod(x, secp256k1P);
+var modN = (x) => mod(x, secp256k1N);
+var Point = secp256k1.ProjectivePoint;
+var GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b);
+function schnorrGetExtPubKey(priv) {
+ let d_ = secp256k1.utils.normPrivateKeyToScalar(priv);
+ let p = Point.fromPrivateKey(d_);
+ const scalar = p.hasEvenY() ? d_ : modN(-d_);
+ return { scalar, bytes: pointToBytes(p) };
+}
+function lift_x(x) {
+ if (!fe(x))
+ throw new Error("bad x: need 0 < x < p");
+ const xx = modP(x * x);
+ const c = modP(xx * x + BigInt(7));
+ let y = sqrtMod(c);
+ if (y % _2n4 !== _0n5)
+ y = modP(-y);
+ const p = new Point(x, y, _1n5);
+ p.assertValidity();
+ return p;
+}
+function challenge(...args) {
+ return modN(bytesToNumberBE(taggedHash("BIP0340/challenge", ...args)));
+}
+function schnorrGetPublicKey(privateKey) {
+ return schnorrGetExtPubKey(privateKey).bytes;
+}
+function schnorrSign(message, privateKey, auxRand = randomBytes(32)) {
+ const m = ensureBytes("message", message);
+ const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey);
+ const a = ensureBytes("auxRand", auxRand, 32);
+ const t = numTo32b(d ^ bytesToNumberBE(taggedHash("BIP0340/aux", a)));
+ const rand = taggedHash("BIP0340/nonce", t, px, m);
+ const k_ = modN(bytesToNumberBE(rand));
+ if (k_ === _0n5)
+ throw new Error("sign failed: k is zero");
+ const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_);
+ const e = challenge(rx, px, m);
+ const sig = new Uint8Array(64);
+ sig.set(rx, 0);
+ sig.set(numTo32b(modN(k + e * d)), 32);
+ if (!schnorrVerify(sig, m, px))
+ throw new Error("sign: Invalid signature produced");
+ return sig;
+}
+function schnorrVerify(signature, message, publicKey) {
+ const sig = ensureBytes("signature", signature, 64);
+ const m = ensureBytes("message", message);
+ const pub = ensureBytes("publicKey", publicKey, 32);
+ try {
+ const P = lift_x(bytesToNumberBE(pub));
+ const r = bytesToNumberBE(sig.subarray(0, 32));
+ if (!fe(r))
+ return false;
+ const s = bytesToNumberBE(sig.subarray(32, 64));
+ if (!ge(s))
+ return false;
+ const e = challenge(numTo32b(r), pointToBytes(P), m);
+ const R = GmulAdd(P, s, modN(-e));
+ if (!R || !R.hasEvenY() || R.toAffine().x !== r)
+ return false;
+ return true;
+ } catch (error) {
+ return false;
+ }
+}
+var schnorr = /* @__PURE__ */ (() => ({
+ getPublicKey: schnorrGetPublicKey,
+ sign: schnorrSign,
+ verify: schnorrVerify,
+ utils: {
+ randomPrivateKey: secp256k1.utils.randomPrivateKey,
+ lift_x,
+ pointToBytes,
+ numberToBytesBE,
+ bytesToNumberBE,
+ taggedHash,
+ mod
+ }
+}))();
+
+// node_modules/@noble/hashes/esm/cryptoNode.js
+var nc2 = __toESM(require("node:crypto"), 1);
+var crypto2 = nc2 && typeof nc2 === "object" && "webcrypto" in nc2 ? nc2.webcrypto : void 0;
+
+// node_modules/@noble/hashes/esm/utils.js
+var u8a3 = (a) => a instanceof Uint8Array;
+var createView2 = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
+var rotr2 = (word, shift) => word << 32 - shift | word >>> shift;
+var isLE2 = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
+if (!isLE2)
+ throw new Error("Non little-endian hardware is not supported");
+var hexes2 = Array.from({ length: 256 }, (v, i3) => i3.toString(16).padStart(2, "0"));
+function bytesToHex2(bytes4) {
+ if (!u8a3(bytes4))
+ throw new Error("Uint8Array expected");
+ let hex2 = "";
+ for (let i3 = 0; i3 < bytes4.length; i3++) {
+ hex2 += hexes2[bytes4[i3]];
+ }
+ return hex2;
+}
+function hexToBytes2(hex2) {
+ if (typeof hex2 !== "string")
+ throw new Error("hex string expected, got " + typeof hex2);
+ const len = hex2.length;
+ if (len % 2)
+ throw new Error("padded hex string expected, got unpadded hex of length " + len);
+ const array = new Uint8Array(len / 2);
+ for (let i3 = 0; i3 < array.length; i3++) {
+ const j = i3 * 2;
+ const hexByte = hex2.slice(j, j + 2);
+ const byte = Number.parseInt(hexByte, 16);
+ if (Number.isNaN(byte) || byte < 0)
+ throw new Error("Invalid byte sequence");
+ array[i3] = byte;
+ }
+ return array;
+}
+function utf8ToBytes3(str) {
+ if (typeof str !== "string")
+ throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
+ return new Uint8Array(new TextEncoder().encode(str));
+}
+function toBytes2(data) {
+ if (typeof data === "string")
+ data = utf8ToBytes3(data);
+ if (!u8a3(data))
+ throw new Error(`expected Uint8Array, got ${typeof data}`);
+ return data;
+}
+function concatBytes3(...arrays) {
+ const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
+ let pad2 = 0;
+ arrays.forEach((a) => {
+ if (!u8a3(a))
+ throw new Error("Uint8Array expected");
+ r.set(a, pad2);
+ pad2 += a.length;
+ });
+ return r;
+}
+var Hash2 = class {
+ // Safe version that clones internal state
+ clone() {
+ return this._cloneInto();
+ }
+};
+function wrapConstructor2(hashCons) {
+ const hashC = (msg) => hashCons().update(toBytes2(msg)).digest();
+ const tmp = hashCons();
+ hashC.outputLen = tmp.outputLen;
+ hashC.blockLen = tmp.blockLen;
+ hashC.create = () => hashCons();
+ return hashC;
+}
+function randomBytes2(bytesLength = 32) {
+ if (crypto2 && typeof crypto2.getRandomValues === "function") {
+ return crypto2.getRandomValues(new Uint8Array(bytesLength));
+ }
+ throw new Error("crypto.getRandomValues must be defined");
+}
+
+// node_modules/@noble/hashes/esm/_assert.js
+function number2(n) {
+ if (!Number.isSafeInteger(n) || n < 0)
+ throw new Error(`Wrong positive integer: ${n}`);
+}
+function bool(b) {
+ if (typeof b !== "boolean")
+ throw new Error(`Expected boolean, not ${b}`);
+}
+function bytes2(b, ...lengths) {
+ if (!(b instanceof Uint8Array))
+ throw new Error("Expected Uint8Array");
+ if (lengths.length > 0 && !lengths.includes(b.length))
+ throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
+}
+function hash2(hash3) {
+ if (typeof hash3 !== "function" || typeof hash3.create !== "function")
+ throw new Error("Hash should be wrapped by utils.wrapConstructor");
+ number2(hash3.outputLen);
+ number2(hash3.blockLen);
+}
+function exists2(instance, checkFinished = true) {
+ if (instance.destroyed)
+ throw new Error("Hash instance has been destroyed");
+ if (checkFinished && instance.finished)
+ throw new Error("Hash#digest() has already been called");
+}
+function output2(out, instance) {
+ bytes2(out);
+ const min = instance.outputLen;
+ if (out.length < min) {
+ throw new Error(`digestInto() expects output buffer of length at least ${min}`);
+ }
+}
+var assert = {
+ number: number2,
+ bool,
+ bytes: bytes2,
+ hash: hash2,
+ exists: exists2,
+ output: output2
+};
+var assert_default = assert;
+
+// node_modules/@noble/hashes/esm/_sha2.js
+function setBigUint642(view, byteOffset, value, isLE4) {
+ if (typeof view.setBigUint64 === "function")
+ return view.setBigUint64(byteOffset, value, isLE4);
+ const _32n = BigInt(32);
+ const _u32_max = BigInt(4294967295);
+ const wh = Number(value >> _32n & _u32_max);
+ const wl = Number(value & _u32_max);
+ const h = isLE4 ? 4 : 0;
+ const l = isLE4 ? 0 : 4;
+ view.setUint32(byteOffset + h, wh, isLE4);
+ view.setUint32(byteOffset + l, wl, isLE4);
+}
+var SHA22 = class extends Hash2 {
+ constructor(blockLen, outputLen, padOffset, isLE4) {
+ super();
+ this.blockLen = blockLen;
+ this.outputLen = outputLen;
+ this.padOffset = padOffset;
+ this.isLE = isLE4;
+ this.finished = false;
+ this.length = 0;
+ this.pos = 0;
+ this.destroyed = false;
+ this.buffer = new Uint8Array(blockLen);
+ this.view = createView2(this.buffer);
+ }
+ update(data) {
+ assert_default.exists(this);
+ const { view, buffer, blockLen } = this;
+ data = toBytes2(data);
+ const len = data.length;
+ for (let pos = 0; pos < len; ) {
+ const take = Math.min(blockLen - this.pos, len - pos);
+ if (take === blockLen) {
+ const dataView = createView2(data);
+ for (; blockLen <= len - pos; pos += blockLen)
+ this.process(dataView, pos);
+ continue;
+ }
+ buffer.set(data.subarray(pos, pos + take), this.pos);
+ this.pos += take;
+ pos += take;
+ if (this.pos === blockLen) {
+ this.process(view, 0);
+ this.pos = 0;
+ }
+ }
+ this.length += data.length;
+ this.roundClean();
+ return this;
+ }
+ digestInto(out) {
+ assert_default.exists(this);
+ assert_default.output(out, this);
+ this.finished = true;
+ const { buffer, view, blockLen, isLE: isLE4 } = this;
+ let { pos } = this;
+ buffer[pos++] = 128;
+ this.buffer.subarray(pos).fill(0);
+ if (this.padOffset > blockLen - pos) {
+ this.process(view, 0);
+ pos = 0;
+ }
+ for (let i3 = pos; i3 < blockLen; i3++)
+ buffer[i3] = 0;
+ setBigUint642(view, blockLen - 8, BigInt(this.length * 8), isLE4);
+ this.process(view, 0);
+ const oview = createView2(out);
+ const len = this.outputLen;
+ if (len % 4)
+ throw new Error("_sha2: outputLen should be aligned to 32bit");
+ const outLen = len / 4;
+ const state = this.get();
+ if (outLen > state.length)
+ throw new Error("_sha2: outputLen bigger than state");
+ for (let i3 = 0; i3 < outLen; i3++)
+ oview.setUint32(4 * i3, state[i3], isLE4);
+ }
+ digest() {
+ const { buffer, outputLen } = this;
+ this.digestInto(buffer);
+ const res = buffer.slice(0, outputLen);
+ this.destroy();
+ return res;
+ }
+ _cloneInto(to) {
+ to || (to = new this.constructor());
+ to.set(...this.get());
+ const { blockLen, buffer, length, finished, destroyed, pos } = this;
+ to.length = length;
+ to.pos = pos;
+ to.finished = finished;
+ to.destroyed = destroyed;
+ if (length % blockLen)
+ to.buffer.set(buffer);
+ return to;
+ }
+};
+
+// node_modules/@noble/hashes/esm/sha256.js
+var Chi2 = (a, b, c) => a & b ^ ~a & c;
+var Maj2 = (a, b, c) => a & b ^ a & c ^ b & c;
+var SHA256_K2 = new Uint32Array([
+ 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
+]);
+var IV2 = new Uint32Array([
+ 1779033703,
+ 3144134277,
+ 1013904242,
+ 2773480762,
+ 1359893119,
+ 2600822924,
+ 528734635,
+ 1541459225
+]);
+var SHA256_W2 = new Uint32Array(64);
+var SHA2562 = class extends SHA22 {
+ constructor() {
+ super(64, 32, 8, false);
+ this.A = IV2[0] | 0;
+ this.B = IV2[1] | 0;
+ this.C = IV2[2] | 0;
+ this.D = IV2[3] | 0;
+ this.E = IV2[4] | 0;
+ this.F = IV2[5] | 0;
+ this.G = IV2[6] | 0;
+ this.H = IV2[7] | 0;
+ }
+ get() {
+ const { A, B, C, D, E, F, G, H } = this;
+ return [A, B, C, D, E, F, G, H];
+ }
+ // prettier-ignore
+ set(A, B, C, D, E, F, G, H) {
+ this.A = A | 0;
+ this.B = B | 0;
+ this.C = C | 0;
+ this.D = D | 0;
+ this.E = E | 0;
+ this.F = F | 0;
+ this.G = G | 0;
+ this.H = H | 0;
+ }
+ process(view, offset) {
+ for (let i3 = 0; i3 < 16; i3++, offset += 4)
+ SHA256_W2[i3] = view.getUint32(offset, false);
+ for (let i3 = 16; i3 < 64; i3++) {
+ const W15 = SHA256_W2[i3 - 15];
+ const W2 = SHA256_W2[i3 - 2];
+ const s0 = rotr2(W15, 7) ^ rotr2(W15, 18) ^ W15 >>> 3;
+ const s1 = rotr2(W2, 17) ^ rotr2(W2, 19) ^ W2 >>> 10;
+ SHA256_W2[i3] = s1 + SHA256_W2[i3 - 7] + s0 + SHA256_W2[i3 - 16] | 0;
+ }
+ let { A, B, C, D, E, F, G, H } = this;
+ for (let i3 = 0; i3 < 64; i3++) {
+ const sigma1 = rotr2(E, 6) ^ rotr2(E, 11) ^ rotr2(E, 25);
+ const T1 = H + sigma1 + Chi2(E, F, G) + SHA256_K2[i3] + SHA256_W2[i3] | 0;
+ const sigma0 = rotr2(A, 2) ^ rotr2(A, 13) ^ rotr2(A, 22);
+ const T2 = sigma0 + Maj2(A, B, C) | 0;
+ H = G;
+ G = F;
+ F = E;
+ E = D + T1 | 0;
+ D = C;
+ C = B;
+ B = A;
+ A = T1 + T2 | 0;
+ }
+ A = A + this.A | 0;
+ B = B + this.B | 0;
+ C = C + this.C | 0;
+ D = D + this.D | 0;
+ E = E + this.E | 0;
+ F = F + this.F | 0;
+ G = G + this.G | 0;
+ H = H + this.H | 0;
+ this.set(A, B, C, D, E, F, G, H);
+ }
+ roundClean() {
+ SHA256_W2.fill(0);
+ }
+ destroy() {
+ this.set(0, 0, 0, 0, 0, 0, 0, 0);
+ this.buffer.fill(0);
+ }
+};
+var SHA224 = class extends SHA2562 {
+ constructor() {
+ super();
+ this.A = 3238371032 | 0;
+ this.B = 914150663 | 0;
+ this.C = 812702999 | 0;
+ this.D = 4144912697 | 0;
+ this.E = 4290775857 | 0;
+ this.F = 1750603025 | 0;
+ this.G = 1694076839 | 0;
+ this.H = 3204075428 | 0;
+ this.outputLen = 28;
+ }
+};
+var sha2562 = wrapConstructor2(() => new SHA2562());
+var sha224 = wrapConstructor2(() => new SHA224());
+
+// node_modules/@scure/base/lib/esm/index.js
+function assertNumber(n) {
+ if (!Number.isSafeInteger(n))
+ throw new Error(`Wrong integer: ${n}`);
+}
+function chain(...args) {
+ const wrap = (a, b) => (c) => a(b(c));
+ const encode = Array.from(args).reverse().reduce((acc, i3) => acc ? wrap(acc, i3.encode) : i3.encode, void 0);
+ const decode2 = args.reduce((acc, i3) => acc ? wrap(acc, i3.decode) : i3.decode, void 0);
+ return { encode, decode: decode2 };
+}
+function alphabet(alphabet2) {
+ return {
+ encode: (digits) => {
+ if (!Array.isArray(digits) || digits.length && typeof digits[0] !== "number")
+ throw new Error("alphabet.encode input should be an array of numbers");
+ return digits.map((i3) => {
+ assertNumber(i3);
+ if (i3 < 0 || i3 >= alphabet2.length)
+ throw new Error(`Digit index outside alphabet: ${i3} (alphabet: ${alphabet2.length})`);
+ return alphabet2[i3];
+ });
+ },
+ decode: (input) => {
+ if (!Array.isArray(input) || input.length && typeof input[0] !== "string")
+ throw new Error("alphabet.decode input should be array of strings");
+ return input.map((letter) => {
+ if (typeof letter !== "string")
+ throw new Error(`alphabet.decode: not string element=${letter}`);
+ const index = alphabet2.indexOf(letter);
+ if (index === -1)
+ throw new Error(`Unknown letter: "${letter}". Allowed: ${alphabet2}`);
+ return index;
+ });
+ }
+ };
+}
+function join(separator = "") {
+ if (typeof separator !== "string")
+ throw new Error("join separator should be string");
+ return {
+ encode: (from) => {
+ if (!Array.isArray(from) || from.length && typeof from[0] !== "string")
+ throw new Error("join.encode input should be array of strings");
+ for (let i3 of from)
+ if (typeof i3 !== "string")
+ throw new Error(`join.encode: non-string input=${i3}`);
+ return from.join(separator);
+ },
+ decode: (to) => {
+ if (typeof to !== "string")
+ throw new Error("join.decode input should be string");
+ return to.split(separator);
+ }
+ };
+}
+function padding(bits, chr = "=") {
+ assertNumber(bits);
+ if (typeof chr !== "string")
+ throw new Error("padding chr should be string");
+ return {
+ encode(data) {
+ if (!Array.isArray(data) || data.length && typeof data[0] !== "string")
+ throw new Error("padding.encode input should be array of strings");
+ for (let i3 of data)
+ if (typeof i3 !== "string")
+ throw new Error(`padding.encode: non-string input=${i3}`);
+ while (data.length * bits % 8)
+ data.push(chr);
+ return data;
+ },
+ decode(input) {
+ if (!Array.isArray(input) || input.length && typeof input[0] !== "string")
+ throw new Error("padding.encode input should be array of strings");
+ for (let i3 of input)
+ if (typeof i3 !== "string")
+ throw new Error(`padding.decode: non-string input=${i3}`);
+ let end = input.length;
+ if (end * bits % 8)
+ throw new Error("Invalid padding: string should have whole number of bytes");
+ for (; end > 0 && input[end - 1] === chr; end--) {
+ if (!((end - 1) * bits % 8))
+ throw new Error("Invalid padding: string has too much padding");
+ }
+ return input.slice(0, end);
+ }
+ };
+}
+function normalize(fn) {
+ if (typeof fn !== "function")
+ throw new Error("normalize fn should be function");
+ return { encode: (from) => from, decode: (to) => fn(to) };
+}
+function convertRadix(data, from, to) {
+ if (from < 2)
+ throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);
+ if (to < 2)
+ throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);
+ if (!Array.isArray(data))
+ throw new Error("convertRadix: data should be array");
+ if (!data.length)
+ return [];
+ let pos = 0;
+ const res = [];
+ const digits = Array.from(data);
+ digits.forEach((d) => {
+ assertNumber(d);
+ if (d < 0 || d >= from)
+ throw new Error(`Wrong integer: ${d}`);
+ });
+ while (true) {
+ let carry = 0;
+ let done = true;
+ for (let i3 = pos; i3 < digits.length; i3++) {
+ const digit = digits[i3];
+ const digitBase = from * carry + digit;
+ if (!Number.isSafeInteger(digitBase) || from * carry / from !== carry || digitBase - digit !== from * carry) {
+ throw new Error("convertRadix: carry overflow");
+ }
+ carry = digitBase % to;
+ digits[i3] = Math.floor(digitBase / to);
+ if (!Number.isSafeInteger(digits[i3]) || digits[i3] * to + carry !== digitBase)
+ throw new Error("convertRadix: carry overflow");
+ if (!done)
+ continue;
+ else if (!digits[i3])
+ pos = i3;
+ else
+ done = false;
+ }
+ res.push(carry);
+ if (done)
+ break;
+ }
+ for (let i3 = 0; i3 < data.length - 1 && data[i3] === 0; i3++)
+ res.push(0);
+ return res.reverse();
+}
+var gcd = (a, b) => !b ? a : gcd(b, a % b);
+var radix2carry = (from, to) => from + (to - gcd(from, to));
+function convertRadix2(data, from, to, padding2) {
+ if (!Array.isArray(data))
+ throw new Error("convertRadix2: data should be array");
+ if (from <= 0 || from > 32)
+ throw new Error(`convertRadix2: wrong from=${from}`);
+ if (to <= 0 || to > 32)
+ throw new Error(`convertRadix2: wrong to=${to}`);
+ if (radix2carry(from, to) > 32) {
+ throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);
+ }
+ let carry = 0;
+ let pos = 0;
+ const mask = 2 ** to - 1;
+ const res = [];
+ for (const n of data) {
+ assertNumber(n);
+ if (n >= 2 ** from)
+ throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
+ carry = carry << from | n;
+ if (pos + from > 32)
+ throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
+ pos += from;
+ for (; pos >= to; pos -= to)
+ res.push((carry >> pos - to & mask) >>> 0);
+ carry &= 2 ** pos - 1;
+ }
+ carry = carry << to - pos & mask;
+ if (!padding2 && pos >= from)
+ throw new Error("Excess padding");
+ if (!padding2 && carry)
+ throw new Error(`Non-zero padding: ${carry}`);
+ if (padding2 && pos > 0)
+ res.push(carry >>> 0);
+ return res;
+}
+function radix(num) {
+ assertNumber(num);
+ return {
+ encode: (bytes4) => {
+ if (!(bytes4 instanceof Uint8Array))
+ throw new Error("radix.encode input should be Uint8Array");
+ return convertRadix(Array.from(bytes4), 2 ** 8, num);
+ },
+ decode: (digits) => {
+ if (!Array.isArray(digits) || digits.length && typeof digits[0] !== "number")
+ throw new Error("radix.decode input should be array of strings");
+ return Uint8Array.from(convertRadix(digits, num, 2 ** 8));
+ }
+ };
+}
+function radix2(bits, revPadding = false) {
+ assertNumber(bits);
+ if (bits <= 0 || bits > 32)
+ throw new Error("radix2: bits should be in (0..32]");
+ if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)
+ throw new Error("radix2: carry overflow");
+ return {
+ encode: (bytes4) => {
+ if (!(bytes4 instanceof Uint8Array))
+ throw new Error("radix2.encode input should be Uint8Array");
+ return convertRadix2(Array.from(bytes4), 8, bits, !revPadding);
+ },
+ decode: (digits) => {
+ if (!Array.isArray(digits) || digits.length && typeof digits[0] !== "number")
+ throw new Error("radix2.decode input should be array of strings");
+ return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
+ }
+ };
+}
+function unsafeWrapper(fn) {
+ if (typeof fn !== "function")
+ throw new Error("unsafeWrapper fn should be function");
+ return function(...args) {
+ try {
+ return fn.apply(null, args);
+ } catch (e) {
+ }
+ };
+}
+var base16 = chain(radix2(4), alphabet("0123456789ABCDEF"), join(""));
+var base32 = chain(radix2(5), alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"), padding(5), join(""));
+var base32hex = chain(radix2(5), alphabet("0123456789ABCDEFGHIJKLMNOPQRSTUV"), padding(5), join(""));
+var base32crockford = chain(radix2(5), alphabet("0123456789ABCDEFGHJKMNPQRSTVWXYZ"), join(""), normalize((s) => s.toUpperCase().replace(/O/g, "0").replace(/[IL]/g, "1")));
+var base64 = chain(radix2(6), alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), padding(6), join(""));
+var base64url = chain(radix2(6), alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"), padding(6), join(""));
+var genBase58 = (abc) => chain(radix(58), alphabet(abc), join(""));
+var base58 = genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
+var base58flickr = genBase58("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ");
+var base58xrp = genBase58("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz");
+var XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];
+var base58xmr = {
+ encode(data) {
+ let res = "";
+ for (let i3 = 0; i3 < data.length; i3 += 8) {
+ const block = data.subarray(i3, i3 + 8);
+ res += base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], "1");
+ }
+ return res;
+ },
+ decode(str) {
+ let res = [];
+ for (let i3 = 0; i3 < str.length; i3 += 11) {
+ const slice = str.slice(i3, i3 + 11);
+ const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);
+ const block = base58.decode(slice);
+ for (let j = 0; j < block.length - blockLen; j++) {
+ if (block[j] !== 0)
+ throw new Error("base58xmr: wrong padding");
+ }
+ res = res.concat(Array.from(block.slice(block.length - blockLen)));
+ }
+ return Uint8Array.from(res);
+ }
+};
+var BECH_ALPHABET = chain(alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), join(""));
+var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
+function bech32Polymod(pre) {
+ const b = pre >> 25;
+ let chk = (pre & 33554431) << 5;
+ for (let i3 = 0; i3 < POLYMOD_GENERATORS.length; i3++) {
+ if ((b >> i3 & 1) === 1)
+ chk ^= POLYMOD_GENERATORS[i3];
+ }
+ return chk;
+}
+function bechChecksum(prefix, words, encodingConst = 1) {
+ const len = prefix.length;
+ let chk = 1;
+ for (let i3 = 0; i3 < len; i3++) {
+ const c = prefix.charCodeAt(i3);
+ if (c < 33 || c > 126)
+ throw new Error(`Invalid prefix (${prefix})`);
+ chk = bech32Polymod(chk) ^ c >> 5;
+ }
+ chk = bech32Polymod(chk);
+ for (let i3 = 0; i3 < len; i3++)
+ chk = bech32Polymod(chk) ^ prefix.charCodeAt(i3) & 31;
+ for (let v of words)
+ chk = bech32Polymod(chk) ^ v;
+ for (let i3 = 0; i3 < 6; i3++)
+ chk = bech32Polymod(chk);
+ chk ^= encodingConst;
+ return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));
+}
+function genBech32(encoding) {
+ const ENCODING_CONST = encoding === "bech32" ? 1 : 734539939;
+ const _words = radix2(5);
+ const fromWords = _words.decode;
+ const toWords = _words.encode;
+ const fromWordsUnsafe = unsafeWrapper(fromWords);
+ function encode(prefix, words, limit2 = 90) {
+ if (typeof prefix !== "string")
+ throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);
+ if (!Array.isArray(words) || words.length && typeof words[0] !== "number")
+ throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);
+ const actualLength = prefix.length + 7 + words.length;
+ if (limit2 !== false && actualLength > limit2)
+ throw new TypeError(`Length ${actualLength} exceeds limit ${limit2}`);
+ prefix = prefix.toLowerCase();
+ return `${prefix}1${BECH_ALPHABET.encode(words)}${bechChecksum(prefix, words, ENCODING_CONST)}`;
+ }
+ function decode2(str, limit2 = 90) {
+ if (typeof str !== "string")
+ throw new Error(`bech32.decode input should be string, not ${typeof str}`);
+ if (str.length < 8 || limit2 !== false && str.length > limit2)
+ throw new TypeError(`Wrong string length: ${str.length} (${str}). Expected (8..${limit2})`);
+ const lowered = str.toLowerCase();
+ if (str !== lowered && str !== str.toUpperCase())
+ throw new Error(`String must be lowercase or uppercase`);
+ str = lowered;
+ const sepIndex = str.lastIndexOf("1");
+ if (sepIndex === 0 || sepIndex === -1)
+ throw new Error(`Letter "1" must be present between prefix and data only`);
+ const prefix = str.slice(0, sepIndex);
+ const _words2 = str.slice(sepIndex + 1);
+ if (_words2.length < 6)
+ throw new Error("Data must be at least 6 characters long");
+ const words = BECH_ALPHABET.decode(_words2).slice(0, -6);
+ const sum = bechChecksum(prefix, words, ENCODING_CONST);
+ if (!_words2.endsWith(sum))
+ throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
+ return { prefix, words };
+ }
+ const decodeUnsafe = unsafeWrapper(decode2);
+ function decodeToBytes(str) {
+ const { prefix, words } = decode2(str, false);
+ return { prefix, words, bytes: fromWords(words) };
+ }
+ return { encode, decode: decode2, decodeToBytes, decodeUnsafe, fromWords, fromWordsUnsafe, toWords };
+}
+var bech32 = genBech32("bech32");
+var bech32m = genBech32("bech32m");
+var utf8 = {
+ encode: (data) => new TextDecoder().decode(data),
+ decode: (str) => new TextEncoder().encode(str)
+};
+var hex = chain(radix2(4), alphabet("0123456789abcdef"), join(""), normalize((s) => {
+ if (typeof s !== "string" || s.length % 2)
+ throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);
+ return s.toLowerCase();
+}));
+var CODERS = {
+ utf8,
+ hex,
+ base16,
+ base32,
+ base64,
+ base64url,
+ base58,
+ base58xmr
+};
+var coderTypeError = `Invalid encoding type. Available types: ${Object.keys(CODERS).join(", ")}`;
+
+// node_modules/@noble/ciphers/esm/_assert.js
+function number3(n) {
+ if (!Number.isSafeInteger(n) || n < 0)
+ throw new Error(`positive integer expected, not ${n}`);
+}
+function bool2(b) {
+ if (typeof b !== "boolean")
+ throw new Error(`boolean expected, not ${b}`);
+}
+function isBytes(a) {
+ return a instanceof Uint8Array || a != null && typeof a === "object" && a.constructor.name === "Uint8Array";
+}
+function bytes3(b, ...lengths) {
+ if (!isBytes(b))
+ throw new Error("Uint8Array expected");
+ if (lengths.length > 0 && !lengths.includes(b.length))
+ throw new Error(`Uint8Array expected of length ${lengths}, not of length=${b.length}`);
+}
+function exists3(instance, checkFinished = true) {
+ if (instance.destroyed)
+ throw new Error("Hash instance has been destroyed");
+ if (checkFinished && instance.finished)
+ throw new Error("Hash#digest() has already been called");
+}
+function output3(out, instance) {
+ bytes3(out);
+ const min = instance.outputLen;
+ if (out.length < min) {
+ throw new Error(`digestInto() expects output buffer of length at least ${min}`);
+ }
+}
+
+// node_modules/@noble/ciphers/esm/utils.js
+var u8 = (arr) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
+var u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
+var createView3 = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
+var isLE3 = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
+if (!isLE3)
+ throw new Error("Non little-endian hardware is not supported");
+function utf8ToBytes4(str) {
+ if (typeof str !== "string")
+ throw new Error(`string expected, got ${typeof str}`);
+ return new Uint8Array(new TextEncoder().encode(str));
+}
+function toBytes3(data) {
+ if (typeof data === "string")
+ data = utf8ToBytes4(data);
+ else if (isBytes(data))
+ data = data.slice();
+ else
+ throw new Error(`Uint8Array expected, got ${typeof data}`);
+ return data;
+}
+function checkOpts(defaults, opts) {
+ if (opts == null || typeof opts !== "object")
+ throw new Error("options must be defined");
+ const merged = Object.assign(defaults, opts);
+ return merged;
+}
+function equalBytes2(a, b) {
+ if (a.length !== b.length)
+ return false;
+ let diff = 0;
+ for (let i3 = 0; i3 < a.length; i3++)
+ diff |= a[i3] ^ b[i3];
+ return diff === 0;
+}
+var wrapCipher = /* @__NO_SIDE_EFFECTS__ */ (params, c) => {
+ Object.assign(c, params);
+ return c;
+};
+function setBigUint643(view, byteOffset, value, isLE4) {
+ if (typeof view.setBigUint64 === "function")
+ return view.setBigUint64(byteOffset, value, isLE4);
+ const _32n = BigInt(32);
+ const _u32_max = BigInt(4294967295);
+ const wh = Number(value >> _32n & _u32_max);
+ const wl = Number(value & _u32_max);
+ const h = isLE4 ? 4 : 0;
+ const l = isLE4 ? 0 : 4;
+ view.setUint32(byteOffset + h, wh, isLE4);
+ view.setUint32(byteOffset + l, wl, isLE4);
+}
+
+// node_modules/@noble/ciphers/esm/_polyval.js
+var BLOCK_SIZE = 16;
+var ZEROS16 = /* @__PURE__ */ new Uint8Array(16);
+var ZEROS32 = u32(ZEROS16);
+var POLY = 225;
+var mul2 = (s0, s1, s2, s3) => {
+ const hiBit = s3 & 1;
+ return {
+ s3: s2 << 31 | s3 >>> 1,
+ s2: s1 << 31 | s2 >>> 1,
+ s1: s0 << 31 | s1 >>> 1,
+ s0: s0 >>> 1 ^ POLY << 24 & -(hiBit & 1)
+ // reduce % poly
+ };
+};
+var swapLE = (n) => (n >>> 0 & 255) << 24 | (n >>> 8 & 255) << 16 | (n >>> 16 & 255) << 8 | n >>> 24 & 255 | 0;
+function _toGHASHKey(k) {
+ k.reverse();
+ const hiBit = k[15] & 1;
+ let carry = 0;
+ for (let i3 = 0; i3 < k.length; i3++) {
+ const t = k[i3];
+ k[i3] = t >>> 1 | carry;
+ carry = (t & 1) << 7;
+ }
+ k[0] ^= -hiBit & 225;
+ return k;
+}
+var estimateWindow = (bytes4) => {
+ if (bytes4 > 64 * 1024)
+ return 8;
+ if (bytes4 > 1024)
+ return 4;
+ return 2;
+};
+var GHASH = class {
+ // We select bits per window adaptively based on expectedLength
+ constructor(key, expectedLength) {
+ this.blockLen = BLOCK_SIZE;
+ this.outputLen = BLOCK_SIZE;
+ this.s0 = 0;
+ this.s1 = 0;
+ this.s2 = 0;
+ this.s3 = 0;
+ this.finished = false;
+ key = toBytes3(key);
+ bytes3(key, 16);
+ const kView = createView3(key);
+ let k0 = kView.getUint32(0, false);
+ let k1 = kView.getUint32(4, false);
+ let k2 = kView.getUint32(8, false);
+ let k3 = kView.getUint32(12, false);
+ const doubles = [];
+ for (let i3 = 0; i3 < 128; i3++) {
+ doubles.push({ s0: swapLE(k0), s1: swapLE(k1), s2: swapLE(k2), s3: swapLE(k3) });
+ ({ s0: k0, s1: k1, s2: k2, s3: k3 } = mul2(k0, k1, k2, k3));
+ }
+ const W = estimateWindow(expectedLength || 1024);
+ if (![1, 2, 4, 8].includes(W))
+ throw new Error(`ghash: wrong window size=${W}, should be 2, 4 or 8`);
+ this.W = W;
+ const bits = 128;
+ const windows = bits / W;
+ const windowSize = this.windowSize = 2 ** W;
+ const items = [];
+ for (let w = 0; w < windows; w++) {
+ for (let byte = 0; byte < windowSize; byte++) {
+ let s0 = 0, s1 = 0, s2 = 0, s3 = 0;
+ for (let j = 0; j < W; j++) {
+ const bit = byte >>> W - j - 1 & 1;
+ if (!bit)
+ continue;
+ const { s0: d0, s1: d1, s2: d2, s3: d3 } = doubles[W * w + j];
+ s0 ^= d0, s1 ^= d1, s2 ^= d2, s3 ^= d3;
+ }
+ items.push({ s0, s1, s2, s3 });
+ }
+ }
+ this.t = items;
+ }
+ _updateBlock(s0, s1, s2, s3) {
+ s0 ^= this.s0, s1 ^= this.s1, s2 ^= this.s2, s3 ^= this.s3;
+ const { W, t, windowSize } = this;
+ let o0 = 0, o1 = 0, o2 = 0, o3 = 0;
+ const mask = (1 << W) - 1;
+ let w = 0;
+ for (const num of [s0, s1, s2, s3]) {
+ for (let bytePos = 0; bytePos < 4; bytePos++) {
+ const byte = num >>> 8 * bytePos & 255;
+ for (let bitPos = 8 / W - 1; bitPos >= 0; bitPos--) {
+ const bit = byte >>> W * bitPos & mask;
+ const { s0: e0, s1: e1, s2: e2, s3: e3 } = t[w * windowSize + bit];
+ o0 ^= e0, o1 ^= e1, o2 ^= e2, o3 ^= e3;
+ w += 1;
+ }
+ }
+ }
+ this.s0 = o0;
+ this.s1 = o1;
+ this.s2 = o2;
+ this.s3 = o3;
+ }
+ update(data) {
+ data = toBytes3(data);
+ exists3(this);
+ const b32 = u32(data);
+ const blocks = Math.floor(data.length / BLOCK_SIZE);
+ const left = data.length % BLOCK_SIZE;
+ for (let i3 = 0; i3 < blocks; i3++) {
+ this._updateBlock(b32[i3 * 4 + 0], b32[i3 * 4 + 1], b32[i3 * 4 + 2], b32[i3 * 4 + 3]);
+ }
+ if (left) {
+ ZEROS16.set(data.subarray(blocks * BLOCK_SIZE));
+ this._updateBlock(ZEROS32[0], ZEROS32[1], ZEROS32[2], ZEROS32[3]);
+ ZEROS32.fill(0);
+ }
+ return this;
+ }
+ destroy() {
+ const { t } = this;
+ for (const elm of t) {
+ elm.s0 = 0, elm.s1 = 0, elm.s2 = 0, elm.s3 = 0;
+ }
+ }
+ digestInto(out) {
+ exists3(this);
+ output3(out, this);
+ this.finished = true;
+ const { s0, s1, s2, s3 } = this;
+ const o32 = u32(out);
+ o32[0] = s0;
+ o32[1] = s1;
+ o32[2] = s2;
+ o32[3] = s3;
+ return out;
+ }
+ digest() {
+ const res = new Uint8Array(BLOCK_SIZE);
+ this.digestInto(res);
+ this.destroy();
+ return res;
+ }
+};
+var Polyval = class extends GHASH {
+ constructor(key, expectedLength) {
+ key = toBytes3(key);
+ const ghKey = _toGHASHKey(key.slice());
+ super(ghKey, expectedLength);
+ ghKey.fill(0);
+ }
+ update(data) {
+ data = toBytes3(data);
+ exists3(this);
+ const b32 = u32(data);
+ const left = data.length % BLOCK_SIZE;
+ const blocks = Math.floor(data.length / BLOCK_SIZE);
+ for (let i3 = 0; i3 < blocks; i3++) {
+ this._updateBlock(swapLE(b32[i3 * 4 + 3]), swapLE(b32[i3 * 4 + 2]), swapLE(b32[i3 * 4 + 1]), swapLE(b32[i3 * 4 + 0]));
+ }
+ if (left) {
+ ZEROS16.set(data.subarray(blocks * BLOCK_SIZE));
+ this._updateBlock(swapLE(ZEROS32[3]), swapLE(ZEROS32[2]), swapLE(ZEROS32[1]), swapLE(ZEROS32[0]));
+ ZEROS32.fill(0);
+ }
+ return this;
+ }
+ digestInto(out) {
+ exists3(this);
+ output3(out, this);
+ this.finished = true;
+ const { s0, s1, s2, s3 } = this;
+ const o32 = u32(out);
+ o32[0] = s0;
+ o32[1] = s1;
+ o32[2] = s2;
+ o32[3] = s3;
+ return out.reverse();
+ }
+};
+function wrapConstructorWithKey(hashCons) {
+ const hashC = (msg, key) => hashCons(key, msg.length).update(toBytes3(msg)).digest();
+ const tmp = hashCons(new Uint8Array(16), 0);
+ hashC.outputLen = tmp.outputLen;
+ hashC.blockLen = tmp.blockLen;
+ hashC.create = (key, expectedLength) => hashCons(key, expectedLength);
+ return hashC;
+}
+var ghash = wrapConstructorWithKey((key, expectedLength) => new GHASH(key, expectedLength));
+var polyval = wrapConstructorWithKey((key, expectedLength) => new Polyval(key, expectedLength));
+
+// node_modules/@noble/ciphers/esm/aes.js
+var BLOCK_SIZE2 = 16;
+var BLOCK_SIZE32 = 4;
+var EMPTY_BLOCK = new Uint8Array(BLOCK_SIZE2);
+var POLY2 = 283;
+function mul22(n) {
+ return n << 1 ^ POLY2 & -(n >> 7);
+}
+function mul(a, b) {
+ let res = 0;
+ for (; b > 0; b >>= 1) {
+ res ^= a & -(b & 1);
+ a = mul22(a);
+ }
+ return res;
+}
+var sbox = /* @__PURE__ */ (() => {
+ let t = new Uint8Array(256);
+ for (let i3 = 0, x = 1; i3 < 256; i3++, x ^= mul22(x))
+ t[i3] = x;
+ const box = new Uint8Array(256);
+ box[0] = 99;
+ for (let i3 = 0; i3 < 255; i3++) {
+ let x = t[255 - i3];
+ x |= x << 8;
+ box[t[i3]] = (x ^ x >> 4 ^ x >> 5 ^ x >> 6 ^ x >> 7 ^ 99) & 255;
+ }
+ return box;
+})();
+var invSbox = /* @__PURE__ */ sbox.map((_, j) => sbox.indexOf(j));
+var rotr32_8 = (n) => n << 24 | n >>> 8;
+var rotl32_8 = (n) => n << 8 | n >>> 24;
+function genTtable(sbox2, fn) {
+ if (sbox2.length !== 256)
+ throw new Error("Wrong sbox length");
+ const T0 = new Uint32Array(256).map((_, j) => fn(sbox2[j]));
+ const T1 = T0.map(rotl32_8);
+ const T2 = T1.map(rotl32_8);
+ const T3 = T2.map(rotl32_8);
+ const T01 = new Uint32Array(256 * 256);
+ const T23 = new Uint32Array(256 * 256);
+ const sbox22 = new Uint16Array(256 * 256);
+ for (let i3 = 0; i3 < 256; i3++) {
+ for (let j = 0; j < 256; j++) {
+ const idx = i3 * 256 + j;
+ T01[idx] = T0[i3] ^ T1[j];
+ T23[idx] = T2[i3] ^ T3[j];
+ sbox22[idx] = sbox2[i3] << 8 | sbox2[j];
+ }
+ }
+ return { sbox: sbox2, sbox2: sbox22, T0, T1, T2, T3, T01, T23 };
+}
+var tableEncoding = /* @__PURE__ */ genTtable(sbox, (s) => mul(s, 3) << 24 | s << 16 | s << 8 | mul(s, 2));
+var tableDecoding = /* @__PURE__ */ genTtable(invSbox, (s) => mul(s, 11) << 24 | mul(s, 13) << 16 | mul(s, 9) << 8 | mul(s, 14));
+var xPowers = /* @__PURE__ */ (() => {
+ const p = new Uint8Array(16);
+ for (let i3 = 0, x = 1; i3 < 16; i3++, x = mul22(x))
+ p[i3] = x;
+ return p;
+})();
+function expandKeyLE(key) {
+ bytes3(key);
+ const len = key.length;
+ if (![16, 24, 32].includes(len))
+ throw new Error(`aes: wrong key size: should be 16, 24 or 32, got: ${len}`);
+ const { sbox2 } = tableEncoding;
+ const k32 = u32(key);
+ const Nk = k32.length;
+ const subByte = (n) => applySbox(sbox2, n, n, n, n);
+ const xk = new Uint32Array(len + 28);
+ xk.set(k32);
+ for (let i3 = Nk; i3 < xk.length; i3++) {
+ let t = xk[i3 - 1];
+ if (i3 % Nk === 0)
+ t = subByte(rotr32_8(t)) ^ xPowers[i3 / Nk - 1];
+ else if (Nk > 6 && i3 % Nk === 4)
+ t = subByte(t);
+ xk[i3] = xk[i3 - Nk] ^ t;
+ }
+ return xk;
+}
+function expandKeyDecLE(key) {
+ const encKey = expandKeyLE(key);
+ const xk = encKey.slice();
+ const Nk = encKey.length;
+ const { sbox2 } = tableEncoding;
+ const { T0, T1, T2, T3 } = tableDecoding;
+ for (let i3 = 0; i3 < Nk; i3 += 4) {
+ for (let j = 0; j < 4; j++)
+ xk[i3 + j] = encKey[Nk - i3 - 4 + j];
+ }
+ encKey.fill(0);
+ for (let i3 = 4; i3 < Nk - 4; i3++) {
+ const x = xk[i3];
+ const w = applySbox(sbox2, x, x, x, x);
+ xk[i3] = T0[w & 255] ^ T1[w >>> 8 & 255] ^ T2[w >>> 16 & 255] ^ T3[w >>> 24];
+ }
+ return xk;
+}
+function apply0123(T01, T23, s0, s1, s2, s3) {
+ return T01[s0 << 8 & 65280 | s1 >>> 8 & 255] ^ T23[s2 >>> 8 & 65280 | s3 >>> 24 & 255];
+}
+function applySbox(sbox2, s0, s1, s2, s3) {
+ return sbox2[s0 & 255 | s1 & 65280] | sbox2[s2 >>> 16 & 255 | s3 >>> 16 & 65280] << 16;
+}
+function encrypt(xk, s0, s1, s2, s3) {
+ const { sbox2, T01, T23 } = tableEncoding;
+ let k = 0;
+ s0 ^= xk[k++], s1 ^= xk[k++], s2 ^= xk[k++], s3 ^= xk[k++];
+ const rounds = xk.length / 4 - 2;
+ for (let i3 = 0; i3 < rounds; i3++) {
+ const t02 = xk[k++] ^ apply0123(T01, T23, s0, s1, s2, s3);
+ const t12 = xk[k++] ^ apply0123(T01, T23, s1, s2, s3, s0);
+ const t22 = xk[k++] ^ apply0123(T01, T23, s2, s3, s0, s1);
+ const t32 = xk[k++] ^ apply0123(T01, T23, s3, s0, s1, s2);
+ s0 = t02, s1 = t12, s2 = t22, s3 = t32;
+ }
+ const t0 = xk[k++] ^ applySbox(sbox2, s0, s1, s2, s3);
+ const t1 = xk[k++] ^ applySbox(sbox2, s1, s2, s3, s0);
+ const t2 = xk[k++] ^ applySbox(sbox2, s2, s3, s0, s1);
+ const t3 = xk[k++] ^ applySbox(sbox2, s3, s0, s1, s2);
+ return { s0: t0, s1: t1, s2: t2, s3: t3 };
+}
+function decrypt(xk, s0, s1, s2, s3) {
+ const { sbox2, T01, T23 } = tableDecoding;
+ let k = 0;
+ s0 ^= xk[k++], s1 ^= xk[k++], s2 ^= xk[k++], s3 ^= xk[k++];
+ const rounds = xk.length / 4 - 2;
+ for (let i3 = 0; i3 < rounds; i3++) {
+ const t02 = xk[k++] ^ apply0123(T01, T23, s0, s3, s2, s1);
+ const t12 = xk[k++] ^ apply0123(T01, T23, s1, s0, s3, s2);
+ const t22 = xk[k++] ^ apply0123(T01, T23, s2, s1, s0, s3);
+ const t32 = xk[k++] ^ apply0123(T01, T23, s3, s2, s1, s0);
+ s0 = t02, s1 = t12, s2 = t22, s3 = t32;
+ }
+ const t0 = xk[k++] ^ applySbox(sbox2, s0, s3, s2, s1);
+ const t1 = xk[k++] ^ applySbox(sbox2, s1, s0, s3, s2);
+ const t2 = xk[k++] ^ applySbox(sbox2, s2, s1, s0, s3);
+ const t3 = xk[k++] ^ applySbox(sbox2, s3, s2, s1, s0);
+ return { s0: t0, s1: t1, s2: t2, s3: t3 };
+}
+function getDst(len, dst) {
+ if (!dst)
+ return new Uint8Array(len);
+ bytes3(dst);
+ if (dst.length < len)
+ throw new Error(`aes: wrong destination length, expected at least ${len}, got: ${dst.length}`);
+ return dst;
+}
+function ctrCounter(xk, nonce, src, dst) {
+ bytes3(nonce, BLOCK_SIZE2);
+ bytes3(src);
+ const srcLen = src.length;
+ dst = getDst(srcLen, dst);
+ const ctr3 = nonce;
+ const c32 = u32(ctr3);
+ let { s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]);
+ const src32 = u32(src);
+ const dst32 = u32(dst);
+ for (let i3 = 0; i3 + 4 <= src32.length; i3 += 4) {
+ dst32[i3 + 0] = src32[i3 + 0] ^ s0;
+ dst32[i3 + 1] = src32[i3 + 1] ^ s1;
+ dst32[i3 + 2] = src32[i3 + 2] ^ s2;
+ dst32[i3 + 3] = src32[i3 + 3] ^ s3;
+ let carry = 1;
+ for (let i4 = ctr3.length - 1; i4 >= 0; i4--) {
+ carry = carry + (ctr3[i4] & 255) | 0;
+ ctr3[i4] = carry & 255;
+ carry >>>= 8;
+ }
+ ({ s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]));
+ }
+ const start = BLOCK_SIZE2 * Math.floor(src32.length / BLOCK_SIZE32);
+ if (start < srcLen) {
+ const b32 = new Uint32Array([s0, s1, s2, s3]);
+ const buf = u8(b32);
+ for (let i3 = start, pos = 0; i3 < srcLen; i3++, pos++)
+ dst[i3] = src[i3] ^ buf[pos];
+ }
+ return dst;
+}
+function ctr32(xk, isLE4, nonce, src, dst) {
+ bytes3(nonce, BLOCK_SIZE2);
+ bytes3(src);
+ dst = getDst(src.length, dst);
+ const ctr3 = nonce;
+ const c32 = u32(ctr3);
+ const view = createView3(ctr3);
+ const src32 = u32(src);
+ const dst32 = u32(dst);
+ const ctrPos = isLE4 ? 0 : 12;
+ const srcLen = src.length;
+ let ctrNum = view.getUint32(ctrPos, isLE4);
+ let { s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]);
+ for (let i3 = 0; i3 + 4 <= src32.length; i3 += 4) {
+ dst32[i3 + 0] = src32[i3 + 0] ^ s0;
+ dst32[i3 + 1] = src32[i3 + 1] ^ s1;
+ dst32[i3 + 2] = src32[i3 + 2] ^ s2;
+ dst32[i3 + 3] = src32[i3 + 3] ^ s3;
+ ctrNum = ctrNum + 1 >>> 0;
+ view.setUint32(ctrPos, ctrNum, isLE4);
+ ({ s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]));
+ }
+ const start = BLOCK_SIZE2 * Math.floor(src32.length / BLOCK_SIZE32);
+ if (start < srcLen) {
+ const b32 = new Uint32Array([s0, s1, s2, s3]);
+ const buf = u8(b32);
+ for (let i3 = start, pos = 0; i3 < srcLen; i3++, pos++)
+ dst[i3] = src[i3] ^ buf[pos];
+ }
+ return dst;
+}
+var ctr = wrapCipher({ blockSize: 16, nonceLength: 16 }, function ctr2(key, nonce) {
+ bytes3(key);
+ bytes3(nonce, BLOCK_SIZE2);
+ function processCtr(buf, dst) {
+ const xk = expandKeyLE(key);
+ const n = nonce.slice();
+ const out = ctrCounter(xk, n, buf, dst);
+ xk.fill(0);
+ n.fill(0);
+ return out;
+ }
+ return {
+ encrypt: (plaintext, dst) => processCtr(plaintext, dst),
+ decrypt: (ciphertext, dst) => processCtr(ciphertext, dst)
+ };
+});
+function validateBlockDecrypt(data) {
+ bytes3(data);
+ if (data.length % BLOCK_SIZE2 !== 0) {
+ throw new Error(`aes/(cbc-ecb).decrypt ciphertext should consist of blocks with size ${BLOCK_SIZE2}`);
+ }
+}
+function validateBlockEncrypt(plaintext, pcks5, dst) {
+ let outLen = plaintext.length;
+ const remaining = outLen % BLOCK_SIZE2;
+ if (!pcks5 && remaining !== 0)
+ throw new Error("aec/(cbc-ecb): unpadded plaintext with disabled padding");
+ const b = u32(plaintext);
+ if (pcks5) {
+ let left = BLOCK_SIZE2 - remaining;
+ if (!left)
+ left = BLOCK_SIZE2;
+ outLen = outLen + left;
+ }
+ const out = getDst(outLen, dst);
+ const o = u32(out);
+ return { b, o, out };
+}
+function validatePCKS(data, pcks5) {
+ if (!pcks5)
+ return data;
+ const len = data.length;
+ if (!len)
+ throw new Error(`aes/pcks5: empty ciphertext not allowed`);
+ const lastByte = data[len - 1];
+ if (lastByte <= 0 || lastByte > 16)
+ throw new Error(`aes/pcks5: wrong padding byte: ${lastByte}`);
+ const out = data.subarray(0, -lastByte);
+ for (let i3 = 0; i3 < lastByte; i3++)
+ if (data[len - i3 - 1] !== lastByte)
+ throw new Error(`aes/pcks5: wrong padding`);
+ return out;
+}
+function padPCKS(left) {
+ const tmp = new Uint8Array(16);
+ const tmp32 = u32(tmp);
+ tmp.set(left);
+ const paddingByte = BLOCK_SIZE2 - left.length;
+ for (let i3 = BLOCK_SIZE2 - paddingByte; i3 < BLOCK_SIZE2; i3++)
+ tmp[i3] = paddingByte;
+ return tmp32;
+}
+var ecb = wrapCipher({ blockSize: 16 }, function ecb2(key, opts = {}) {
+ bytes3(key);
+ const pcks5 = !opts.disablePadding;
+ return {
+ encrypt: (plaintext, dst) => {
+ bytes3(plaintext);
+ const { b, o, out: _out } = validateBlockEncrypt(plaintext, pcks5, dst);
+ const xk = expandKeyLE(key);
+ let i3 = 0;
+ for (; i3 + 4 <= b.length; ) {
+ const { s0, s1, s2, s3 } = encrypt(xk, b[i3 + 0], b[i3 + 1], b[i3 + 2], b[i3 + 3]);
+ o[i3++] = s0, o[i3++] = s1, o[i3++] = s2, o[i3++] = s3;
+ }
+ if (pcks5) {
+ const tmp32 = padPCKS(plaintext.subarray(i3 * 4));
+ const { s0, s1, s2, s3 } = encrypt(xk, tmp32[0], tmp32[1], tmp32[2], tmp32[3]);
+ o[i3++] = s0, o[i3++] = s1, o[i3++] = s2, o[i3++] = s3;
+ }
+ xk.fill(0);
+ return _out;
+ },
+ decrypt: (ciphertext, dst) => {
+ validateBlockDecrypt(ciphertext);
+ const xk = expandKeyDecLE(key);
+ const out = getDst(ciphertext.length, dst);
+ const b = u32(ciphertext);
+ const o = u32(out);
+ for (let i3 = 0; i3 + 4 <= b.length; ) {
+ const { s0, s1, s2, s3 } = decrypt(xk, b[i3 + 0], b[i3 + 1], b[i3 + 2], b[i3 + 3]);
+ o[i3++] = s0, o[i3++] = s1, o[i3++] = s2, o[i3++] = s3;
+ }
+ xk.fill(0);
+ return validatePCKS(out, pcks5);
+ }
+ };
+});
+var cbc = wrapCipher({ blockSize: 16, nonceLength: 16 }, function cbc2(key, iv, opts = {}) {
+ bytes3(key);
+ bytes3(iv, 16);
+ const pcks5 = !opts.disablePadding;
+ return {
+ encrypt: (plaintext, dst) => {
+ const xk = expandKeyLE(key);
+ const { b, o, out: _out } = validateBlockEncrypt(plaintext, pcks5, dst);
+ const n32 = u32(iv);
+ let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
+ let i3 = 0;
+ for (; i3 + 4 <= b.length; ) {
+ s0 ^= b[i3 + 0], s1 ^= b[i3 + 1], s2 ^= b[i3 + 2], s3 ^= b[i3 + 3];
+ ({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
+ o[i3++] = s0, o[i3++] = s1, o[i3++] = s2, o[i3++] = s3;
+ }
+ if (pcks5) {
+ const tmp32 = padPCKS(plaintext.subarray(i3 * 4));
+ s0 ^= tmp32[0], s1 ^= tmp32[1], s2 ^= tmp32[2], s3 ^= tmp32[3];
+ ({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
+ o[i3++] = s0, o[i3++] = s1, o[i3++] = s2, o[i3++] = s3;
+ }
+ xk.fill(0);
+ return _out;
+ },
+ decrypt: (ciphertext, dst) => {
+ validateBlockDecrypt(ciphertext);
+ const xk = expandKeyDecLE(key);
+ const n32 = u32(iv);
+ const out = getDst(ciphertext.length, dst);
+ const b = u32(ciphertext);
+ const o = u32(out);
+ let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
+ for (let i3 = 0; i3 + 4 <= b.length; ) {
+ const ps0 = s0, ps1 = s1, ps2 = s2, ps3 = s3;
+ s0 = b[i3 + 0], s1 = b[i3 + 1], s2 = b[i3 + 2], s3 = b[i3 + 3];
+ const { s0: o0, s1: o1, s2: o2, s3: o3 } = decrypt(xk, s0, s1, s2, s3);
+ o[i3++] = o0 ^ ps0, o[i3++] = o1 ^ ps1, o[i3++] = o2 ^ ps2, o[i3++] = o3 ^ ps3;
+ }
+ xk.fill(0);
+ return validatePCKS(out, pcks5);
+ }
+ };
+});
+var cfb = wrapCipher({ blockSize: 16, nonceLength: 16 }, function cfb2(key, iv) {
+ bytes3(key);
+ bytes3(iv, 16);
+ function processCfb(src, isEncrypt, dst) {
+ const xk = expandKeyLE(key);
+ const srcLen = src.length;
+ dst = getDst(srcLen, dst);
+ const src32 = u32(src);
+ const dst32 = u32(dst);
+ const next32 = isEncrypt ? dst32 : src32;
+ const n32 = u32(iv);
+ let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
+ for (let i3 = 0; i3 + 4 <= src32.length; ) {
+ const { s0: e0, s1: e1, s2: e2, s3: e3 } = encrypt(xk, s0, s1, s2, s3);
+ dst32[i3 + 0] = src32[i3 + 0] ^ e0;
+ dst32[i3 + 1] = src32[i3 + 1] ^ e1;
+ dst32[i3 + 2] = src32[i3 + 2] ^ e2;
+ dst32[i3 + 3] = src32[i3 + 3] ^ e3;
+ s0 = next32[i3++], s1 = next32[i3++], s2 = next32[i3++], s3 = next32[i3++];
+ }
+ const start = BLOCK_SIZE2 * Math.floor(src32.length / BLOCK_SIZE32);
+ if (start < srcLen) {
+ ({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
+ const buf = u8(new Uint32Array([s0, s1, s2, s3]));
+ for (let i3 = start, pos = 0; i3 < srcLen; i3++, pos++)
+ dst[i3] = src[i3] ^ buf[pos];
+ buf.fill(0);
+ }
+ xk.fill(0);
+ return dst;
+ }
+ return {
+ encrypt: (plaintext, dst) => processCfb(plaintext, true, dst),
+ decrypt: (ciphertext, dst) => processCfb(ciphertext, false, dst)
+ };
+});
+function computeTag(fn, isLE4, key, data, AAD) {
+ const h = fn.create(key, data.length + (AAD?.length || 0));
+ if (AAD)
+ h.update(AAD);
+ h.update(data);
+ const num = new Uint8Array(16);
+ const view = createView3(num);
+ if (AAD)
+ setBigUint643(view, 0, BigInt(AAD.length * 8), isLE4);
+ setBigUint643(view, 8, BigInt(data.length * 8), isLE4);
+ h.update(num);
+ return h.digest();
+}
+var gcm = wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16 }, function gcm2(key, nonce, AAD) {
+ bytes3(nonce);
+ if (nonce.length === 0)
+ throw new Error("aes/gcm: empty nonce");
+ const tagLength = 16;
+ function _computeTag(authKey, tagMask, data) {
+ const tag = computeTag(ghash, false, authKey, data, AAD);
+ for (let i3 = 0; i3 < tagMask.length; i3++)
+ tag[i3] ^= tagMask[i3];
+ return tag;
+ }
+ function deriveKeys() {
+ const xk = expandKeyLE(key);
+ const authKey = EMPTY_BLOCK.slice();
+ const counter = EMPTY_BLOCK.slice();
+ ctr32(xk, false, counter, counter, authKey);
+ if (nonce.length === 12) {
+ counter.set(nonce);
+ } else {
+ const nonceLen = EMPTY_BLOCK.slice();
+ const view = createView3(nonceLen);
+ setBigUint643(view, 8, BigInt(nonce.length * 8), false);
+ ghash.create(authKey).update(nonce).update(nonceLen).digestInto(counter);
+ }
+ const tagMask = ctr32(xk, false, counter, EMPTY_BLOCK);
+ return { xk, authKey, counter, tagMask };
+ }
+ return {
+ encrypt: (plaintext) => {
+ bytes3(plaintext);
+ const { xk, authKey, counter, tagMask } = deriveKeys();
+ const out = new Uint8Array(plaintext.length + tagLength);
+ ctr32(xk, false, counter, plaintext, out);
+ const tag = _computeTag(authKey, tagMask, out.subarray(0, out.length - tagLength));
+ out.set(tag, plaintext.length);
+ xk.fill(0);
+ return out;
+ },
+ decrypt: (ciphertext) => {
+ bytes3(ciphertext);
+ if (ciphertext.length < tagLength)
+ throw new Error(`aes/gcm: ciphertext less than tagLen (${tagLength})`);
+ const { xk, authKey, counter, tagMask } = deriveKeys();
+ const data = ciphertext.subarray(0, -tagLength);
+ const passedTag = ciphertext.subarray(-tagLength);
+ const tag = _computeTag(authKey, tagMask, data);
+ if (!equalBytes2(tag, passedTag))
+ throw new Error("aes/gcm: invalid ghash tag");
+ const out = ctr32(xk, false, counter, data);
+ authKey.fill(0);
+ tagMask.fill(0);
+ xk.fill(0);
+ return out;
+ }
+ };
+});
+var limit = (name, min, max) => (value) => {
+ if (!Number.isSafeInteger(value) || min > value || value > max)
+ throw new Error(`${name}: invalid value=${value}, must be [${min}..${max}]`);
+};
+var siv = wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16 }, function siv2(key, nonce, AAD) {
+ const tagLength = 16;
+ const AAD_LIMIT = limit("AAD", 0, 2 ** 36);
+ const PLAIN_LIMIT = limit("plaintext", 0, 2 ** 36);
+ const NONCE_LIMIT = limit("nonce", 12, 12);
+ const CIPHER_LIMIT = limit("ciphertext", 16, 2 ** 36 + 16);
+ bytes3(nonce);
+ NONCE_LIMIT(nonce.length);
+ if (AAD) {
+ bytes3(AAD);
+ AAD_LIMIT(AAD.length);
+ }
+ function deriveKeys() {
+ const len = key.length;
+ if (len !== 16 && len !== 24 && len !== 32)
+ throw new Error(`key length must be 16, 24 or 32 bytes, got: ${len} bytes`);
+ const xk = expandKeyLE(key);
+ const encKey = new Uint8Array(len);
+ const authKey = new Uint8Array(16);
+ const n32 = u32(nonce);
+ let s0 = 0, s1 = n32[0], s2 = n32[1], s3 = n32[2];
+ let counter = 0;
+ for (const derivedKey of [authKey, encKey].map(u32)) {
+ const d32 = u32(derivedKey);
+ for (let i3 = 0; i3 < d32.length; i3 += 2) {
+ const { s0: o0, s1: o1 } = encrypt(xk, s0, s1, s2, s3);
+ d32[i3 + 0] = o0;
+ d32[i3 + 1] = o1;
+ s0 = ++counter;
+ }
+ }
+ xk.fill(0);
+ return { authKey, encKey: expandKeyLE(encKey) };
+ }
+ function _computeTag(encKey, authKey, data) {
+ const tag = computeTag(polyval, true, authKey, data, AAD);
+ for (let i3 = 0; i3 < 12; i3++)
+ tag[i3] ^= nonce[i3];
+ tag[15] &= 127;
+ const t32 = u32(tag);
+ let s0 = t32[0], s1 = t32[1], s2 = t32[2], s3 = t32[3];
+ ({ s0, s1, s2, s3 } = encrypt(encKey, s0, s1, s2, s3));
+ t32[0] = s0, t32[1] = s1, t32[2] = s2, t32[3] = s3;
+ return tag;
+ }
+ function processSiv(encKey, tag, input) {
+ let block = tag.slice();
+ block[15] |= 128;
+ return ctr32(encKey, true, block, input);
+ }
+ return {
+ encrypt: (plaintext) => {
+ bytes3(plaintext);
+ PLAIN_LIMIT(plaintext.length);
+ const { encKey, authKey } = deriveKeys();
+ const tag = _computeTag(encKey, authKey, plaintext);
+ const out = new Uint8Array(plaintext.length + tagLength);
+ out.set(tag, plaintext.length);
+ out.set(processSiv(encKey, tag, plaintext));
+ encKey.fill(0);
+ authKey.fill(0);
+ return out;
+ },
+ decrypt: (ciphertext) => {
+ bytes3(ciphertext);
+ CIPHER_LIMIT(ciphertext.length);
+ const tag = ciphertext.subarray(-tagLength);
+ const { encKey, authKey } = deriveKeys();
+ const plaintext = processSiv(encKey, tag, ciphertext.subarray(0, -tagLength));
+ const expectedTag = _computeTag(encKey, authKey, plaintext);
+ encKey.fill(0);
+ authKey.fill(0);
+ if (!equalBytes2(tag, expectedTag))
+ throw new Error("invalid polyval tag");
+ return plaintext;
+ }
+ };
+});
+
+// node_modules/@noble/ciphers/esm/_poly1305.js
+var u8to16 = (a, i3) => a[i3++] & 255 | (a[i3++] & 255) << 8;
+var Poly1305 = class {
+ constructor(key) {
+ this.blockLen = 16;
+ this.outputLen = 16;
+ this.buffer = new Uint8Array(16);
+ this.r = new Uint16Array(10);
+ this.h = new Uint16Array(10);
+ this.pad = new Uint16Array(8);
+ this.pos = 0;
+ this.finished = false;
+ key = toBytes3(key);
+ bytes3(key, 32);
+ const t0 = u8to16(key, 0);
+ const t1 = u8to16(key, 2);
+ const t2 = u8to16(key, 4);
+ const t3 = u8to16(key, 6);
+ const t4 = u8to16(key, 8);
+ const t5 = u8to16(key, 10);
+ const t6 = u8to16(key, 12);
+ const t7 = u8to16(key, 14);
+ this.r[0] = t0 & 8191;
+ this.r[1] = (t0 >>> 13 | t1 << 3) & 8191;
+ this.r[2] = (t1 >>> 10 | t2 << 6) & 7939;
+ this.r[3] = (t2 >>> 7 | t3 << 9) & 8191;
+ this.r[4] = (t3 >>> 4 | t4 << 12) & 255;
+ this.r[5] = t4 >>> 1 & 8190;
+ this.r[6] = (t4 >>> 14 | t5 << 2) & 8191;
+ this.r[7] = (t5 >>> 11 | t6 << 5) & 8065;
+ this.r[8] = (t6 >>> 8 | t7 << 8) & 8191;
+ this.r[9] = t7 >>> 5 & 127;
+ for (let i3 = 0; i3 < 8; i3++)
+ this.pad[i3] = u8to16(key, 16 + 2 * i3);
+ }
+ process(data, offset, isLast = false) {
+ const hibit = isLast ? 0 : 1 << 11;
+ const { h, r } = this;
+ const r0 = r[0];
+ const r1 = r[1];
+ const r2 = r[2];
+ const r3 = r[3];
+ const r4 = r[4];
+ const r5 = r[5];
+ const r6 = r[6];
+ const r7 = r[7];
+ const r8 = r[8];
+ const r9 = r[9];
+ const t0 = u8to16(data, offset + 0);
+ const t1 = u8to16(data, offset + 2);
+ const t2 = u8to16(data, offset + 4);
+ const t3 = u8to16(data, offset + 6);
+ const t4 = u8to16(data, offset + 8);
+ const t5 = u8to16(data, offset + 10);
+ const t6 = u8to16(data, offset + 12);
+ const t7 = u8to16(data, offset + 14);
+ let h0 = h[0] + (t0 & 8191);
+ let h1 = h[1] + ((t0 >>> 13 | t1 << 3) & 8191);
+ let h2 = h[2] + ((t1 >>> 10 | t2 << 6) & 8191);
+ let h3 = h[3] + ((t2 >>> 7 | t3 << 9) & 8191);
+ let h4 = h[4] + ((t3 >>> 4 | t4 << 12) & 8191);
+ let h5 = h[5] + (t4 >>> 1 & 8191);
+ let h6 = h[6] + ((t4 >>> 14 | t5 << 2) & 8191);
+ let h7 = h[7] + ((t5 >>> 11 | t6 << 5) & 8191);
+ let h8 = h[8] + ((t6 >>> 8 | t7 << 8) & 8191);
+ let h9 = h[9] + (t7 >>> 5 | hibit);
+ let c = 0;
+ let d0 = c + h0 * r0 + h1 * (5 * r9) + h2 * (5 * r8) + h3 * (5 * r7) + h4 * (5 * r6);
+ c = d0 >>> 13;
+ d0 &= 8191;
+ d0 += h5 * (5 * r5) + h6 * (5 * r4) + h7 * (5 * r3) + h8 * (5 * r2) + h9 * (5 * r1);
+ c += d0 >>> 13;
+ d0 &= 8191;
+ let d1 = c + h0 * r1 + h1 * r0 + h2 * (5 * r9) + h3 * (5 * r8) + h4 * (5 * r7);
+ c = d1 >>> 13;
+ d1 &= 8191;
+ d1 += h5 * (5 * r6) + h6 * (5 * r5) + h7 * (5 * r4) + h8 * (5 * r3) + h9 * (5 * r2);
+ c += d1 >>> 13;
+ d1 &= 8191;
+ let d2 = c + h0 * r2 + h1 * r1 + h2 * r0 + h3 * (5 * r9) + h4 * (5 * r8);
+ c = d2 >>> 13;
+ d2 &= 8191;
+ d2 += h5 * (5 * r7) + h6 * (5 * r6) + h7 * (5 * r5) + h8 * (5 * r4) + h9 * (5 * r3);
+ c += d2 >>> 13;
+ d2 &= 8191;
+ let d3 = c + h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * (5 * r9);
+ c = d3 >>> 13;
+ d3 &= 8191;
+ d3 += h5 * (5 * r8) + h6 * (5 * r7) + h7 * (5 * r6) + h8 * (5 * r5) + h9 * (5 * r4);
+ c += d3 >>> 13;
+ d3 &= 8191;
+ let d4 = c + h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0;
+ c = d4 >>> 13;
+ d4 &= 8191;
+ d4 += h5 * (5 * r9) + h6 * (5 * r8) + h7 * (5 * r7) + h8 * (5 * r6) + h9 * (5 * r5);
+ c += d4 >>> 13;
+ d4 &= 8191;
+ let d5 = c + h0 * r5 + h1 * r4 + h2 * r3 + h3 * r2 + h4 * r1;
+ c = d5 >>> 13;
+ d5 &= 8191;
+ d5 += h5 * r0 + h6 * (5 * r9) + h7 * (5 * r8) + h8 * (5 * r7) + h9 * (5 * r6);
+ c += d5 >>> 13;
+ d5 &= 8191;
+ let d6 = c + h0 * r6 + h1 * r5 + h2 * r4 + h3 * r3 + h4 * r2;
+ c = d6 >>> 13;
+ d6 &= 8191;
+ d6 += h5 * r1 + h6 * r0 + h7 * (5 * r9) + h8 * (5 * r8) + h9 * (5 * r7);
+ c += d6 >>> 13;
+ d6 &= 8191;
+ let d7 = c + h0 * r7 + h1 * r6 + h2 * r5 + h3 * r4 + h4 * r3;
+ c = d7 >>> 13;
+ d7 &= 8191;
+ d7 += h5 * r2 + h6 * r1 + h7 * r0 + h8 * (5 * r9) + h9 * (5 * r8);
+ c += d7 >>> 13;
+ d7 &= 8191;
+ let d8 = c + h0 * r8 + h1 * r7 + h2 * r6 + h3 * r5 + h4 * r4;
+ c = d8 >>> 13;
+ d8 &= 8191;
+ d8 += h5 * r3 + h6 * r2 + h7 * r1 + h8 * r0 + h9 * (5 * r9);
+ c += d8 >>> 13;
+ d8 &= 8191;
+ let d9 = c + h0 * r9 + h1 * r8 + h2 * r7 + h3 * r6 + h4 * r5;
+ c = d9 >>> 13;
+ d9 &= 8191;
+ d9 += h5 * r4 + h6 * r3 + h7 * r2 + h8 * r1 + h9 * r0;
+ c += d9 >>> 13;
+ d9 &= 8191;
+ c = (c << 2) + c | 0;
+ c = c + d0 | 0;
+ d0 = c & 8191;
+ c = c >>> 13;
+ d1 += c;
+ h[0] = d0;
+ h[1] = d1;
+ h[2] = d2;
+ h[3] = d3;
+ h[4] = d4;
+ h[5] = d5;
+ h[6] = d6;
+ h[7] = d7;
+ h[8] = d8;
+ h[9] = d9;
+ }
+ finalize() {
+ const { h, pad: pad2 } = this;
+ const g = new Uint16Array(10);
+ let c = h[1] >>> 13;
+ h[1] &= 8191;
+ for (let i3 = 2; i3 < 10; i3++) {
+ h[i3] += c;
+ c = h[i3] >>> 13;
+ h[i3] &= 8191;
+ }
+ h[0] += c * 5;
+ c = h[0] >>> 13;
+ h[0] &= 8191;
+ h[1] += c;
+ c = h[1] >>> 13;
+ h[1] &= 8191;
+ h[2] += c;
+ g[0] = h[0] + 5;
+ c = g[0] >>> 13;
+ g[0] &= 8191;
+ for (let i3 = 1; i3 < 10; i3++) {
+ g[i3] = h[i3] + c;
+ c = g[i3] >>> 13;
+ g[i3] &= 8191;
+ }
+ g[9] -= 1 << 13;
+ let mask = (c ^ 1) - 1;
+ for (let i3 = 0; i3 < 10; i3++)
+ g[i3] &= mask;
+ mask = ~mask;
+ for (let i3 = 0; i3 < 10; i3++)
+ h[i3] = h[i3] & mask | g[i3];
+ h[0] = (h[0] | h[1] << 13) & 65535;
+ h[1] = (h[1] >>> 3 | h[2] << 10) & 65535;
+ h[2] = (h[2] >>> 6 | h[3] << 7) & 65535;
+ h[3] = (h[3] >>> 9 | h[4] << 4) & 65535;
+ h[4] = (h[4] >>> 12 | h[5] << 1 | h[6] << 14) & 65535;
+ h[5] = (h[6] >>> 2 | h[7] << 11) & 65535;
+ h[6] = (h[7] >>> 5 | h[8] << 8) & 65535;
+ h[7] = (h[8] >>> 8 | h[9] << 5) & 65535;
+ let f = h[0] + pad2[0];
+ h[0] = f & 65535;
+ for (let i3 = 1; i3 < 8; i3++) {
+ f = (h[i3] + pad2[i3] | 0) + (f >>> 16) | 0;
+ h[i3] = f & 65535;
+ }
+ }
+ update(data) {
+ exists3(this);
+ const { buffer, blockLen } = this;
+ data = toBytes3(data);
+ const len = data.length;
+ for (let pos = 0; pos < len; ) {
+ const take = Math.min(blockLen - this.pos, len - pos);
+ if (take === blockLen) {
+ for (; blockLen <= len - pos; pos += blockLen)
+ this.process(data, pos);
+ continue;
+ }
+ buffer.set(data.subarray(pos, pos + take), this.pos);
+ this.pos += take;
+ pos += take;
+ if (this.pos === blockLen) {
+ this.process(buffer, 0, false);
+ this.pos = 0;
+ }
+ }
+ return this;
+ }
+ destroy() {
+ this.h.fill(0);
+ this.r.fill(0);
+ this.buffer.fill(0);
+ this.pad.fill(0);
+ }
+ digestInto(out) {
+ exists3(this);
+ output3(out, this);
+ this.finished = true;
+ const { buffer, h } = this;
+ let { pos } = this;
+ if (pos) {
+ buffer[pos++] = 1;
+ for (; pos < 16; pos++)
+ buffer[pos] = 0;
+ this.process(buffer, 0, true);
+ }
+ this.finalize();
+ let opos = 0;
+ for (let i3 = 0; i3 < 8; i3++) {
+ out[opos++] = h[i3] >>> 0;
+ out[opos++] = h[i3] >>> 8;
+ }
+ return out;
+ }
+ digest() {
+ const { buffer, outputLen } = this;
+ this.digestInto(buffer);
+ const res = buffer.slice(0, outputLen);
+ this.destroy();
+ return res;
+ }
+};
+function wrapConstructorWithKey2(hashCons) {
+ const hashC = (msg, key) => hashCons(key).update(toBytes3(msg)).digest();
+ const tmp = hashCons(new Uint8Array(32));
+ hashC.outputLen = tmp.outputLen;
+ hashC.blockLen = tmp.blockLen;
+ hashC.create = (key) => hashCons(key);
+ return hashC;
+}
+var poly1305 = wrapConstructorWithKey2((key) => new Poly1305(key));
+
+// node_modules/@noble/ciphers/esm/_arx.js
+var _utf8ToBytes = (str) => Uint8Array.from(str.split("").map((c) => c.charCodeAt(0)));
+var sigma16 = _utf8ToBytes("expand 16-byte k");
+var sigma32 = _utf8ToBytes("expand 32-byte k");
+var sigma16_32 = u32(sigma16);
+var sigma32_32 = u32(sigma32);
+var sigma = sigma32_32.slice();
+function rotl(a, b) {
+ return a << b | a >>> 32 - b;
+}
+function isAligned32(b) {
+ return b.byteOffset % 4 === 0;
+}
+var BLOCK_LEN = 64;
+var BLOCK_LEN32 = 16;
+var MAX_COUNTER = 2 ** 32 - 1;
+var U32_EMPTY = new Uint32Array();
+function runCipher(core, sigma2, key, nonce, data, output4, counter, rounds) {
+ const len = data.length;
+ const block = new Uint8Array(BLOCK_LEN);
+ const b32 = u32(block);
+ const isAligned = isAligned32(data) && isAligned32(output4);
+ const d32 = isAligned ? u32(data) : U32_EMPTY;
+ const o32 = isAligned ? u32(output4) : U32_EMPTY;
+ for (let pos = 0; pos < len; counter++) {
+ core(sigma2, key, nonce, b32, counter, rounds);
+ if (counter >= MAX_COUNTER)
+ throw new Error("arx: counter overflow");
+ const take = Math.min(BLOCK_LEN, len - pos);
+ if (isAligned && take === BLOCK_LEN) {
+ const pos32 = pos / 4;
+ if (pos % 4 !== 0)
+ throw new Error("arx: invalid block position");
+ for (let j = 0, posj; j < BLOCK_LEN32; j++) {
+ posj = pos32 + j;
+ o32[posj] = d32[posj] ^ b32[j];
+ }
+ pos += BLOCK_LEN;
+ continue;
+ }
+ for (let j = 0, posj; j < take; j++) {
+ posj = pos + j;
+ output4[posj] = data[posj] ^ block[j];
+ }
+ pos += take;
+ }
+}
+function createCipher(core, opts) {
+ const { allowShortKeys, extendNonceFn, counterLength, counterRight, rounds } = checkOpts({ allowShortKeys: false, counterLength: 8, counterRight: false, rounds: 20 }, opts);
+ if (typeof core !== "function")
+ throw new Error("core must be a function");
+ number3(counterLength);
+ number3(rounds);
+ bool2(counterRight);
+ bool2(allowShortKeys);
+ return (key, nonce, data, output4, counter = 0) => {
+ bytes3(key);
+ bytes3(nonce);
+ bytes3(data);
+ const len = data.length;
+ if (!output4)
+ output4 = new Uint8Array(len);
+ bytes3(output4);
+ number3(counter);
+ if (counter < 0 || counter >= MAX_COUNTER)
+ throw new Error("arx: counter overflow");
+ if (output4.length < len)
+ throw new Error(`arx: output (${output4.length}) is shorter than data (${len})`);
+ const toClean = [];
+ let l = key.length, k, sigma2;
+ if (l === 32) {
+ k = key.slice();
+ toClean.push(k);
+ sigma2 = sigma32_32;
+ } else if (l === 16 && allowShortKeys) {
+ k = new Uint8Array(32);
+ k.set(key);
+ k.set(key, 16);
+ sigma2 = sigma16_32;
+ toClean.push(k);
+ } else {
+ throw new Error(`arx: invalid 32-byte key, got length=${l}`);
+ }
+ if (!isAligned32(nonce)) {
+ nonce = nonce.slice();
+ toClean.push(nonce);
+ }
+ const k32 = u32(k);
+ if (extendNonceFn) {
+ if (nonce.length !== 24)
+ throw new Error(`arx: extended nonce must be 24 bytes`);
+ extendNonceFn(sigma2, k32, u32(nonce.subarray(0, 16)), k32);
+ nonce = nonce.subarray(16);
+ }
+ const nonceNcLen = 16 - counterLength;
+ if (nonceNcLen !== nonce.length)
+ throw new Error(`arx: nonce must be ${nonceNcLen} or 16 bytes`);
+ if (nonceNcLen !== 12) {
+ const nc3 = new Uint8Array(12);
+ nc3.set(nonce, counterRight ? 0 : 12 - nonce.length);
+ nonce = nc3;
+ toClean.push(nonce);
+ }
+ const n32 = u32(nonce);
+ runCipher(core, sigma2, k32, n32, data, output4, counter, rounds);
+ while (toClean.length > 0)
+ toClean.pop().fill(0);
+ return output4;
+ };
+}
+
+// node_modules/@noble/ciphers/esm/chacha.js
+function chachaCore(s, k, n, out, cnt, rounds = 20) {
+ let y00 = s[0], y01 = s[1], y02 = s[2], y03 = s[3], y04 = k[0], y05 = k[1], y06 = k[2], y07 = k[3], y08 = k[4], y09 = k[5], y10 = k[6], y11 = k[7], y12 = cnt, y13 = n[0], y14 = n[1], y15 = n[2];
+ let x00 = y00, x01 = y01, x02 = y02, x03 = y03, x04 = y04, x05 = y05, x06 = y06, x07 = y07, x08 = y08, x09 = y09, x10 = y10, x11 = y11, x12 = y12, x13 = y13, x14 = y14, x15 = y15;
+ for (let r = 0; r < rounds; r += 2) {
+ x00 = x00 + x04 | 0;
+ x12 = rotl(x12 ^ x00, 16);
+ x08 = x08 + x12 | 0;
+ x04 = rotl(x04 ^ x08, 12);
+ x00 = x00 + x04 | 0;
+ x12 = rotl(x12 ^ x00, 8);
+ x08 = x08 + x12 | 0;
+ x04 = rotl(x04 ^ x08, 7);
+ x01 = x01 + x05 | 0;
+ x13 = rotl(x13 ^ x01, 16);
+ x09 = x09 + x13 | 0;
+ x05 = rotl(x05 ^ x09, 12);
+ x01 = x01 + x05 | 0;
+ x13 = rotl(x13 ^ x01, 8);
+ x09 = x09 + x13 | 0;
+ x05 = rotl(x05 ^ x09, 7);
+ x02 = x02 + x06 | 0;
+ x14 = rotl(x14 ^ x02, 16);
+ x10 = x10 + x14 | 0;
+ x06 = rotl(x06 ^ x10, 12);
+ x02 = x02 + x06 | 0;
+ x14 = rotl(x14 ^ x02, 8);
+ x10 = x10 + x14 | 0;
+ x06 = rotl(x06 ^ x10, 7);
+ x03 = x03 + x07 | 0;
+ x15 = rotl(x15 ^ x03, 16);
+ x11 = x11 + x15 | 0;
+ x07 = rotl(x07 ^ x11, 12);
+ x03 = x03 + x07 | 0;
+ x15 = rotl(x15 ^ x03, 8);
+ x11 = x11 + x15 | 0;
+ x07 = rotl(x07 ^ x11, 7);
+ x00 = x00 + x05 | 0;
+ x15 = rotl(x15 ^ x00, 16);
+ x10 = x10 + x15 | 0;
+ x05 = rotl(x05 ^ x10, 12);
+ x00 = x00 + x05 | 0;
+ x15 = rotl(x15 ^ x00, 8);
+ x10 = x10 + x15 | 0;
+ x05 = rotl(x05 ^ x10, 7);
+ x01 = x01 + x06 | 0;
+ x12 = rotl(x12 ^ x01, 16);
+ x11 = x11 + x12 | 0;
+ x06 = rotl(x06 ^ x11, 12);
+ x01 = x01 + x06 | 0;
+ x12 = rotl(x12 ^ x01, 8);
+ x11 = x11 + x12 | 0;
+ x06 = rotl(x06 ^ x11, 7);
+ x02 = x02 + x07 | 0;
+ x13 = rotl(x13 ^ x02, 16);
+ x08 = x08 + x13 | 0;
+ x07 = rotl(x07 ^ x08, 12);
+ x02 = x02 + x07 | 0;
+ x13 = rotl(x13 ^ x02, 8);
+ x08 = x08 + x13 | 0;
+ x07 = rotl(x07 ^ x08, 7);
+ x03 = x03 + x04 | 0;
+ x14 = rotl(x14 ^ x03, 16);
+ x09 = x09 + x14 | 0;
+ x04 = rotl(x04 ^ x09, 12);
+ x03 = x03 + x04 | 0;
+ x14 = rotl(x14 ^ x03, 8);
+ x09 = x09 + x14 | 0;
+ x04 = rotl(x04 ^ x09, 7);
+ }
+ let oi = 0;
+ out[oi++] = y00 + x00 | 0;
+ out[oi++] = y01 + x01 | 0;
+ out[oi++] = y02 + x02 | 0;
+ out[oi++] = y03 + x03 | 0;
+ out[oi++] = y04 + x04 | 0;
+ out[oi++] = y05 + x05 | 0;
+ out[oi++] = y06 + x06 | 0;
+ out[oi++] = y07 + x07 | 0;
+ out[oi++] = y08 + x08 | 0;
+ out[oi++] = y09 + x09 | 0;
+ out[oi++] = y10 + x10 | 0;
+ out[oi++] = y11 + x11 | 0;
+ out[oi++] = y12 + x12 | 0;
+ out[oi++] = y13 + x13 | 0;
+ out[oi++] = y14 + x14 | 0;
+ out[oi++] = y15 + x15 | 0;
+}
+function hchacha(s, k, i3, o32) {
+ let x00 = s[0], x01 = s[1], x02 = s[2], x03 = s[3], x04 = k[0], x05 = k[1], x06 = k[2], x07 = k[3], x08 = k[4], x09 = k[5], x10 = k[6], x11 = k[7], x12 = i3[0], x13 = i3[1], x14 = i3[2], x15 = i3[3];
+ for (let r = 0; r < 20; r += 2) {
+ x00 = x00 + x04 | 0;
+ x12 = rotl(x12 ^ x00, 16);
+ x08 = x08 + x12 | 0;
+ x04 = rotl(x04 ^ x08, 12);
+ x00 = x00 + x04 | 0;
+ x12 = rotl(x12 ^ x00, 8);
+ x08 = x08 + x12 | 0;
+ x04 = rotl(x04 ^ x08, 7);
+ x01 = x01 + x05 | 0;
+ x13 = rotl(x13 ^ x01, 16);
+ x09 = x09 + x13 | 0;
+ x05 = rotl(x05 ^ x09, 12);
+ x01 = x01 + x05 | 0;
+ x13 = rotl(x13 ^ x01, 8);
+ x09 = x09 + x13 | 0;
+ x05 = rotl(x05 ^ x09, 7);
+ x02 = x02 + x06 | 0;
+ x14 = rotl(x14 ^ x02, 16);
+ x10 = x10 + x14 | 0;
+ x06 = rotl(x06 ^ x10, 12);
+ x02 = x02 + x06 | 0;
+ x14 = rotl(x14 ^ x02, 8);
+ x10 = x10 + x14 | 0;
+ x06 = rotl(x06 ^ x10, 7);
+ x03 = x03 + x07 | 0;
+ x15 = rotl(x15 ^ x03, 16);
+ x11 = x11 + x15 | 0;
+ x07 = rotl(x07 ^ x11, 12);
+ x03 = x03 + x07 | 0;
+ x15 = rotl(x15 ^ x03, 8);
+ x11 = x11 + x15 | 0;
+ x07 = rotl(x07 ^ x11, 7);
+ x00 = x00 + x05 | 0;
+ x15 = rotl(x15 ^ x00, 16);
+ x10 = x10 + x15 | 0;
+ x05 = rotl(x05 ^ x10, 12);
+ x00 = x00 + x05 | 0;
+ x15 = rotl(x15 ^ x00, 8);
+ x10 = x10 + x15 | 0;
+ x05 = rotl(x05 ^ x10, 7);
+ x01 = x01 + x06 | 0;
+ x12 = rotl(x12 ^ x01, 16);
+ x11 = x11 + x12 | 0;
+ x06 = rotl(x06 ^ x11, 12);
+ x01 = x01 + x06 | 0;
+ x12 = rotl(x12 ^ x01, 8);
+ x11 = x11 + x12 | 0;
+ x06 = rotl(x06 ^ x11, 7);
+ x02 = x02 + x07 | 0;
+ x13 = rotl(x13 ^ x02, 16);
+ x08 = x08 + x13 | 0;
+ x07 = rotl(x07 ^ x08, 12);
+ x02 = x02 + x07 | 0;
+ x13 = rotl(x13 ^ x02, 8);
+ x08 = x08 + x13 | 0;
+ x07 = rotl(x07 ^ x08, 7);
+ x03 = x03 + x04 | 0;
+ x14 = rotl(x14 ^ x03, 16);
+ x09 = x09 + x14 | 0;
+ x04 = rotl(x04 ^ x09, 12);
+ x03 = x03 + x04 | 0;
+ x14 = rotl(x14 ^ x03, 8);
+ x09 = x09 + x14 | 0;
+ x04 = rotl(x04 ^ x09, 7);
+ }
+ let oi = 0;
+ o32[oi++] = x00;
+ o32[oi++] = x01;
+ o32[oi++] = x02;
+ o32[oi++] = x03;
+ o32[oi++] = x12;
+ o32[oi++] = x13;
+ o32[oi++] = x14;
+ o32[oi++] = x15;
+}
+var chacha20 = /* @__PURE__ */ createCipher(chachaCore, {
+ counterRight: false,
+ counterLength: 4,
+ allowShortKeys: false
+});
+var xchacha20 = /* @__PURE__ */ createCipher(chachaCore, {
+ counterRight: false,
+ counterLength: 8,
+ extendNonceFn: hchacha,
+ allowShortKeys: false
+});
+var ZEROS162 = /* @__PURE__ */ new Uint8Array(16);
+var updatePadded = (h, msg) => {
+ h.update(msg);
+ const left = msg.length % 16;
+ if (left)
+ h.update(ZEROS162.subarray(left));
+};
+var ZEROS322 = /* @__PURE__ */ new Uint8Array(32);
+function computeTag2(fn, key, nonce, data, AAD) {
+ const authKey = fn(key, nonce, ZEROS322);
+ const h = poly1305.create(authKey);
+ if (AAD)
+ updatePadded(h, AAD);
+ updatePadded(h, data);
+ const num = new Uint8Array(16);
+ const view = createView3(num);
+ setBigUint643(view, 0, BigInt(AAD ? AAD.length : 0), true);
+ setBigUint643(view, 8, BigInt(data.length), true);
+ h.update(num);
+ const res = h.digest();
+ authKey.fill(0);
+ return res;
+}
+var _poly1305_aead = (xorStream) => (key, nonce, AAD) => {
+ const tagLength = 16;
+ bytes3(key, 32);
+ bytes3(nonce);
+ return {
+ encrypt: (plaintext, output4) => {
+ const plength = plaintext.length;
+ const clength = plength + tagLength;
+ if (output4) {
+ bytes3(output4, clength);
+ } else {
+ output4 = new Uint8Array(clength);
+ }
+ xorStream(key, nonce, plaintext, output4, 1);
+ const tag = computeTag2(xorStream, key, nonce, output4.subarray(0, -tagLength), AAD);
+ output4.set(tag, plength);
+ return output4;
+ },
+ decrypt: (ciphertext, output4) => {
+ const clength = ciphertext.length;
+ const plength = clength - tagLength;
+ if (clength < tagLength)
+ throw new Error(`encrypted data must be at least ${tagLength} bytes`);
+ if (output4) {
+ bytes3(output4, plength);
+ } else {
+ output4 = new Uint8Array(plength);
+ }
+ const data = ciphertext.subarray(0, -tagLength);
+ const passedTag = ciphertext.subarray(-tagLength);
+ const tag = computeTag2(xorStream, key, nonce, data, AAD);
+ if (!equalBytes2(passedTag, tag))
+ throw new Error("invalid tag");
+ xorStream(key, nonce, data, output4, 1);
+ return output4;
+ }
+ };
+};
+var chacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 12, tagLength: 16 }, _poly1305_aead(chacha20));
+var xchacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 24, tagLength: 16 }, _poly1305_aead(xchacha20));
+
+// node_modules/@noble/hashes/esm/hmac.js
+var HMAC2 = class extends Hash2 {
+ constructor(hash3, _key) {
+ super();
+ this.finished = false;
+ this.destroyed = false;
+ assert_default.hash(hash3);
+ const key = toBytes2(_key);
+ this.iHash = hash3.create();
+ if (typeof this.iHash.update !== "function")
+ throw new Error("Expected instance of class which extends utils.Hash");
+ this.blockLen = this.iHash.blockLen;
+ this.outputLen = this.iHash.outputLen;
+ const blockLen = this.blockLen;
+ const pad2 = new Uint8Array(blockLen);
+ pad2.set(key.length > blockLen ? hash3.create().update(key).digest() : key);
+ for (let i3 = 0; i3 < pad2.length; i3++)
+ pad2[i3] ^= 54;
+ this.iHash.update(pad2);
+ this.oHash = hash3.create();
+ for (let i3 = 0; i3 < pad2.length; i3++)
+ pad2[i3] ^= 54 ^ 92;
+ this.oHash.update(pad2);
+ pad2.fill(0);
+ }
+ update(buf) {
+ assert_default.exists(this);
+ this.iHash.update(buf);
+ return this;
+ }
+ digestInto(out) {
+ assert_default.exists(this);
+ assert_default.bytes(out, this.outputLen);
+ this.finished = true;
+ this.iHash.digestInto(out);
+ this.oHash.update(out);
+ this.oHash.digestInto(out);
+ this.destroy();
+ }
+ digest() {
+ const out = new Uint8Array(this.oHash.outputLen);
+ this.digestInto(out);
+ return out;
+ }
+ _cloneInto(to) {
+ to || (to = Object.create(Object.getPrototypeOf(this), {}));
+ const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
+ to = to;
+ to.finished = finished;
+ to.destroyed = destroyed;
+ to.blockLen = blockLen;
+ to.outputLen = outputLen;
+ to.oHash = oHash._cloneInto(to.oHash);
+ to.iHash = iHash._cloneInto(to.iHash);
+ return to;
+ }
+ destroy() {
+ this.destroyed = true;
+ this.oHash.destroy();
+ this.iHash.destroy();
+ }
+};
+var hmac2 = (hash3, key, message) => new HMAC2(hash3, key).update(message).digest();
+hmac2.create = (hash3, key) => new HMAC2(hash3, key);
+
+// node_modules/@noble/hashes/esm/hkdf.js
+function extract(hash3, ikm, salt) {
+ assert_default.hash(hash3);
+ if (salt === void 0)
+ salt = new Uint8Array(hash3.outputLen);
+ return hmac2(hash3, toBytes2(salt), toBytes2(ikm));
+}
+var HKDF_COUNTER = new Uint8Array([0]);
+var EMPTY_BUFFER = new Uint8Array();
+function expand(hash3, prk, info, length = 32) {
+ assert_default.hash(hash3);
+ assert_default.number(length);
+ if (length > 255 * hash3.outputLen)
+ throw new Error("Length should be <= 255*HashLen");
+ const blocks = Math.ceil(length / hash3.outputLen);
+ if (info === void 0)
+ info = EMPTY_BUFFER;
+ const okm = new Uint8Array(blocks * hash3.outputLen);
+ const HMAC3 = hmac2.create(hash3, prk);
+ const HMACTmp = HMAC3._cloneInto();
+ const T = new Uint8Array(HMAC3.outputLen);
+ for (let counter = 0; counter < blocks; counter++) {
+ HKDF_COUNTER[0] = counter + 1;
+ HMACTmp.update(counter === 0 ? EMPTY_BUFFER : T).update(info).update(HKDF_COUNTER).digestInto(T);
+ okm.set(T, hash3.outputLen * counter);
+ HMAC3._cloneInto(HMACTmp);
+ }
+ HMAC3.destroy();
+ HMACTmp.destroy();
+ T.fill(0);
+ HKDF_COUNTER.fill(0);
+ return okm.slice(0, length);
+}
+
+// node_modules/nostr-tools/lib/esm/index.js
+var __defProp2 = Object.defineProperty;
+var __export2 = (target, all) => {
+ for (var name in all)
+ __defProp2(target, name, { get: all[name], enumerable: true });
+};
+var verifiedSymbol = Symbol("verified");
+var isRecord = (obj) => obj instanceof Object;
+function validateEvent(event) {
+ if (!isRecord(event))
+ return false;
+ if (typeof event.kind !== "number")
+ return false;
+ if (typeof event.content !== "string")
+ return false;
+ if (typeof event.created_at !== "number")
+ return false;
+ if (typeof event.pubkey !== "string")
+ return false;
+ if (!event.pubkey.match(/^[a-f0-9]{64}$/))
+ return false;
+ if (!Array.isArray(event.tags))
+ return false;
+ for (let i22 = 0; i22 < event.tags.length; i22++) {
+ let tag = event.tags[i22];
+ if (!Array.isArray(tag))
+ return false;
+ for (let j = 0; j < tag.length; j++) {
+ if (typeof tag[j] !== "string")
+ return false;
+ }
+ }
+ return true;
+}
+var utils_exports2 = {};
+__export2(utils_exports2, {
+ Queue: () => Queue,
+ QueueNode: () => QueueNode,
+ binarySearch: () => binarySearch,
+ insertEventIntoAscendingList: () => insertEventIntoAscendingList,
+ insertEventIntoDescendingList: () => insertEventIntoDescendingList,
+ normalizeURL: () => normalizeURL,
+ utf8Decoder: () => utf8Decoder,
+ utf8Encoder: () => utf8Encoder
+});
+var utf8Decoder = new TextDecoder("utf-8");
+var utf8Encoder = new TextEncoder();
+function normalizeURL(url) {
+ try {
+ if (url.indexOf("://") === -1)
+ url = "wss://" + url;
+ let p = new URL(url);
+ p.pathname = p.pathname.replace(/\/+/g, "/");
+ if (p.pathname.endsWith("/"))
+ p.pathname = p.pathname.slice(0, -1);
+ if (p.port === "80" && p.protocol === "ws:" || p.port === "443" && p.protocol === "wss:")
+ p.port = "";
+ p.searchParams.sort();
+ p.hash = "";
+ return p.toString();
+ } catch (e) {
+ throw new Error(`Invalid URL: ${url}`);
+ }
+}
+function insertEventIntoDescendingList(sortedArray, event) {
+ const [idx, found] = binarySearch(sortedArray, (b) => {
+ if (event.id === b.id)
+ return 0;
+ if (event.created_at === b.created_at)
+ return -1;
+ return b.created_at - event.created_at;
+ });
+ if (!found) {
+ sortedArray.splice(idx, 0, event);
+ }
+ return sortedArray;
+}
+function insertEventIntoAscendingList(sortedArray, event) {
+ const [idx, found] = binarySearch(sortedArray, (b) => {
+ if (event.id === b.id)
+ return 0;
+ if (event.created_at === b.created_at)
+ return -1;
+ return event.created_at - b.created_at;
+ });
+ if (!found) {
+ sortedArray.splice(idx, 0, event);
+ }
+ return sortedArray;
+}
+function binarySearch(arr, compare) {
+ let start = 0;
+ let end = arr.length - 1;
+ while (start <= end) {
+ const mid = Math.floor((start + end) / 2);
+ const cmp = compare(arr[mid]);
+ if (cmp === 0) {
+ return [mid, true];
+ }
+ if (cmp < 0) {
+ end = mid - 1;
+ } else {
+ start = mid + 1;
+ }
+ }
+ return [start, false];
+}
+var QueueNode = class {
+ value;
+ next = null;
+ prev = null;
+ constructor(message) {
+ this.value = message;
+ }
+};
+var Queue = class {
+ first;
+ last;
+ constructor() {
+ this.first = null;
+ this.last = null;
+ }
+ enqueue(value) {
+ const newNode = new QueueNode(value);
+ if (!this.last) {
+ this.first = newNode;
+ this.last = newNode;
+ } else if (this.last === this.first) {
+ this.last = newNode;
+ this.last.prev = this.first;
+ this.first.next = newNode;
+ } else {
+ newNode.prev = this.last;
+ this.last.next = newNode;
+ this.last = newNode;
+ }
+ return true;
+ }
+ dequeue() {
+ if (!this.first)
+ return null;
+ if (this.first === this.last) {
+ const target2 = this.first;
+ this.first = null;
+ this.last = null;
+ return target2.value;
+ }
+ const target = this.first;
+ this.first = target.next;
+ if (this.first) {
+ this.first.prev = null;
+ }
+ return target.value;
+ }
+};
+var JS = class {
+ generateSecretKey() {
+ return schnorr.utils.randomPrivateKey();
+ }
+ getPublicKey(secretKey) {
+ return bytesToHex2(schnorr.getPublicKey(secretKey));
+ }
+ finalizeEvent(t, secretKey) {
+ const event = t;
+ event.pubkey = bytesToHex2(schnorr.getPublicKey(secretKey));
+ event.id = getEventHash(event);
+ event.sig = bytesToHex2(schnorr.sign(getEventHash(event), secretKey));
+ event[verifiedSymbol] = true;
+ return event;
+ }
+ verifyEvent(event) {
+ if (typeof event[verifiedSymbol] === "boolean")
+ return event[verifiedSymbol];
+ const hash3 = getEventHash(event);
+ if (hash3 !== event.id) {
+ event[verifiedSymbol] = false;
+ return false;
+ }
+ try {
+ const valid = schnorr.verify(event.sig, hash3, event.pubkey);
+ event[verifiedSymbol] = valid;
+ return valid;
+ } catch (err) {
+ event[verifiedSymbol] = false;
+ return false;
+ }
+ }
+};
+function serializeEvent(evt) {
+ if (!validateEvent(evt))
+ throw new Error("can't serialize event with wrong or missing properties");
+ return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);
+}
+function getEventHash(event) {
+ let eventHash = sha2562(utf8Encoder.encode(serializeEvent(event)));
+ return bytesToHex2(eventHash);
+}
+var i = new JS();
+var generateSecretKey = i.generateSecretKey;
+var getPublicKey = i.getPublicKey;
+var finalizeEvent = i.finalizeEvent;
+var verifyEvent = i.verifyEvent;
+var kinds_exports = {};
+__export2(kinds_exports, {
+ Application: () => Application,
+ BadgeAward: () => BadgeAward,
+ BadgeDefinition: () => BadgeDefinition,
+ BlockedRelaysList: () => BlockedRelaysList,
+ BookmarkList: () => BookmarkList,
+ Bookmarksets: () => Bookmarksets,
+ Calendar: () => Calendar,
+ CalendarEventRSVP: () => CalendarEventRSVP,
+ ChannelCreation: () => ChannelCreation,
+ ChannelHideMessage: () => ChannelHideMessage,
+ ChannelMessage: () => ChannelMessage,
+ ChannelMetadata: () => ChannelMetadata,
+ ChannelMuteUser: () => ChannelMuteUser,
+ ClassifiedListing: () => ClassifiedListing,
+ ClientAuth: () => ClientAuth,
+ CommunitiesList: () => CommunitiesList,
+ CommunityDefinition: () => CommunityDefinition,
+ CommunityPostApproval: () => CommunityPostApproval,
+ Contacts: () => Contacts,
+ CreateOrUpdateProduct: () => CreateOrUpdateProduct,
+ CreateOrUpdateStall: () => CreateOrUpdateStall,
+ Curationsets: () => Curationsets,
+ Date: () => Date2,
+ DirectMessageRelaysList: () => DirectMessageRelaysList,
+ DraftClassifiedListing: () => DraftClassifiedListing,
+ DraftLong: () => DraftLong,
+ Emojisets: () => Emojisets,
+ EncryptedDirectMessage: () => EncryptedDirectMessage,
+ EventDeletion: () => EventDeletion,
+ FileMetadata: () => FileMetadata,
+ FileServerPreference: () => FileServerPreference,
+ Followsets: () => Followsets,
+ GenericRepost: () => GenericRepost,
+ Genericlists: () => Genericlists,
+ GiftWrap: () => GiftWrap,
+ HTTPAuth: () => HTTPAuth,
+ Handlerinformation: () => Handlerinformation,
+ Handlerrecommendation: () => Handlerrecommendation,
+ Highlights: () => Highlights,
+ InterestsList: () => InterestsList,
+ Interestsets: () => Interestsets,
+ JobFeedback: () => JobFeedback,
+ JobRequest: () => JobRequest,
+ JobResult: () => JobResult,
+ Label: () => Label,
+ LightningPubRPC: () => LightningPubRPC,
+ LiveChatMessage: () => LiveChatMessage,
+ LiveEvent: () => LiveEvent,
+ LongFormArticle: () => LongFormArticle,
+ Metadata: () => Metadata,
+ Mutelist: () => Mutelist,
+ NWCWalletInfo: () => NWCWalletInfo,
+ NWCWalletRequest: () => NWCWalletRequest,
+ NWCWalletResponse: () => NWCWalletResponse,
+ NostrConnect: () => NostrConnect,
+ OpenTimestamps: () => OpenTimestamps,
+ Pinlist: () => Pinlist,
+ PrivateDirectMessage: () => PrivateDirectMessage,
+ ProblemTracker: () => ProblemTracker,
+ ProfileBadges: () => ProfileBadges,
+ PublicChatsList: () => PublicChatsList,
+ Reaction: () => Reaction,
+ RecommendRelay: () => RecommendRelay,
+ RelayList: () => RelayList,
+ Relaysets: () => Relaysets,
+ Report: () => Report,
+ Reporting: () => Reporting,
+ Repost: () => Repost,
+ Seal: () => Seal,
+ SearchRelaysList: () => SearchRelaysList,
+ ShortTextNote: () => ShortTextNote,
+ Time: () => Time,
+ UserEmojiList: () => UserEmojiList,
+ UserStatuses: () => UserStatuses,
+ Zap: () => Zap,
+ ZapGoal: () => ZapGoal,
+ ZapRequest: () => ZapRequest,
+ classifyKind: () => classifyKind,
+ isAddressableKind: () => isAddressableKind,
+ isEphemeralKind: () => isEphemeralKind,
+ isKind: () => isKind,
+ isParameterizedReplaceableKind: () => isParameterizedReplaceableKind,
+ isRegularKind: () => isRegularKind,
+ isReplaceableKind: () => isReplaceableKind
+});
+function isRegularKind(kind) {
+ return 1e3 <= kind && kind < 1e4 || [1, 2, 4, 5, 6, 7, 8, 16, 40, 41, 42, 43, 44].includes(kind);
+}
+function isReplaceableKind(kind) {
+ return [0, 3].includes(kind) || 1e4 <= kind && kind < 2e4;
+}
+function isEphemeralKind(kind) {
+ return 2e4 <= kind && kind < 3e4;
+}
+function isAddressableKind(kind) {
+ return 3e4 <= kind && kind < 4e4;
+}
+var isParameterizedReplaceableKind = isAddressableKind;
+function classifyKind(kind) {
+ if (isRegularKind(kind))
+ return "regular";
+ if (isReplaceableKind(kind))
+ return "replaceable";
+ if (isEphemeralKind(kind))
+ return "ephemeral";
+ if (isAddressableKind(kind))
+ return "parameterized";
+ return "unknown";
+}
+function isKind(event, kind) {
+ const kindAsArray = kind instanceof Array ? kind : [kind];
+ return validateEvent(event) && kindAsArray.includes(event.kind) || false;
+}
+var Metadata = 0;
+var ShortTextNote = 1;
+var RecommendRelay = 2;
+var Contacts = 3;
+var EncryptedDirectMessage = 4;
+var EventDeletion = 5;
+var Repost = 6;
+var Reaction = 7;
+var BadgeAward = 8;
+var Seal = 13;
+var PrivateDirectMessage = 14;
+var GenericRepost = 16;
+var ChannelCreation = 40;
+var ChannelMetadata = 41;
+var ChannelMessage = 42;
+var ChannelHideMessage = 43;
+var ChannelMuteUser = 44;
+var OpenTimestamps = 1040;
+var GiftWrap = 1059;
+var FileMetadata = 1063;
+var LiveChatMessage = 1311;
+var ProblemTracker = 1971;
+var Report = 1984;
+var Reporting = 1984;
+var Label = 1985;
+var CommunityPostApproval = 4550;
+var JobRequest = 5999;
+var JobResult = 6999;
+var JobFeedback = 7e3;
+var ZapGoal = 9041;
+var ZapRequest = 9734;
+var Zap = 9735;
+var Highlights = 9802;
+var Mutelist = 1e4;
+var Pinlist = 10001;
+var RelayList = 10002;
+var BookmarkList = 10003;
+var CommunitiesList = 10004;
+var PublicChatsList = 10005;
+var BlockedRelaysList = 10006;
+var SearchRelaysList = 10007;
+var InterestsList = 10015;
+var UserEmojiList = 10030;
+var DirectMessageRelaysList = 10050;
+var FileServerPreference = 10096;
+var NWCWalletInfo = 13194;
+var LightningPubRPC = 21e3;
+var ClientAuth = 22242;
+var NWCWalletRequest = 23194;
+var NWCWalletResponse = 23195;
+var NostrConnect = 24133;
+var HTTPAuth = 27235;
+var Followsets = 3e4;
+var Genericlists = 30001;
+var Relaysets = 30002;
+var Bookmarksets = 30003;
+var Curationsets = 30004;
+var ProfileBadges = 30008;
+var BadgeDefinition = 30009;
+var Interestsets = 30015;
+var CreateOrUpdateStall = 30017;
+var CreateOrUpdateProduct = 30018;
+var LongFormArticle = 30023;
+var DraftLong = 30024;
+var Emojisets = 30030;
+var Application = 30078;
+var LiveEvent = 30311;
+var UserStatuses = 30315;
+var ClassifiedListing = 30402;
+var DraftClassifiedListing = 30403;
+var Date2 = 31922;
+var Time = 31923;
+var Calendar = 31924;
+var CalendarEventRSVP = 31925;
+var Handlerrecommendation = 31989;
+var Handlerinformation = 31990;
+var CommunityDefinition = 34550;
+var fakejson_exports = {};
+__export2(fakejson_exports, {
+ getHex64: () => getHex64,
+ getInt: () => getInt,
+ getSubscriptionId: () => getSubscriptionId,
+ matchEventId: () => matchEventId,
+ matchEventKind: () => matchEventKind,
+ matchEventPubkey: () => matchEventPubkey
+});
+function getHex64(json, field) {
+ let len = field.length + 3;
+ let idx = json.indexOf(`"${field}":`) + len;
+ let s = json.slice(idx).indexOf(`"`) + idx + 1;
+ return json.slice(s, s + 64);
+}
+function getInt(json, field) {
+ let len = field.length;
+ let idx = json.indexOf(`"${field}":`) + len + 3;
+ let sliced = json.slice(idx);
+ let end = Math.min(sliced.indexOf(","), sliced.indexOf("}"));
+ return parseInt(sliced.slice(0, end), 10);
+}
+function getSubscriptionId(json) {
+ let idx = json.slice(0, 22).indexOf(`"EVENT"`);
+ if (idx === -1)
+ return null;
+ let pstart = json.slice(idx + 7 + 1).indexOf(`"`);
+ if (pstart === -1)
+ return null;
+ let start = idx + 7 + 1 + pstart;
+ let pend = json.slice(start + 1, 80).indexOf(`"`);
+ if (pend === -1)
+ return null;
+ let end = start + 1 + pend;
+ return json.slice(start + 1, end);
+}
+function matchEventId(json, id) {
+ return id === getHex64(json, "id");
+}
+function matchEventPubkey(json, pubkey) {
+ return pubkey === getHex64(json, "pubkey");
+}
+function matchEventKind(json, kind) {
+ return kind === getInt(json, "kind");
+}
+var nip42_exports = {};
+__export2(nip42_exports, {
+ makeAuthEvent: () => makeAuthEvent
+});
+function makeAuthEvent(relayURL, challenge2) {
+ return {
+ kind: ClientAuth,
+ created_at: Math.floor(Date.now() / 1e3),
+ tags: [
+ ["relay", relayURL],
+ ["challenge", challenge2]
+ ],
+ content: ""
+ };
+}
+var _WebSocket;
+try {
+ _WebSocket = WebSocket;
+} catch {
+}
+var _WebSocket2;
+try {
+ _WebSocket2 = WebSocket;
+} catch {
+}
+var nip19_exports = {};
+__export2(nip19_exports, {
+ BECH32_REGEX: () => BECH32_REGEX,
+ Bech32MaxSize: () => Bech32MaxSize,
+ NostrTypeGuard: () => NostrTypeGuard,
+ decode: () => decode,
+ decodeNostrURI: () => decodeNostrURI,
+ encodeBytes: () => encodeBytes,
+ naddrEncode: () => naddrEncode,
+ neventEncode: () => neventEncode,
+ noteEncode: () => noteEncode,
+ nprofileEncode: () => nprofileEncode,
+ npubEncode: () => npubEncode,
+ nsecEncode: () => nsecEncode
+});
+var NostrTypeGuard = {
+ isNProfile: (value) => /^nprofile1[a-z\d]+$/.test(value || ""),
+ isNEvent: (value) => /^nevent1[a-z\d]+$/.test(value || ""),
+ isNAddr: (value) => /^naddr1[a-z\d]+$/.test(value || ""),
+ isNSec: (value) => /^nsec1[a-z\d]{58}$/.test(value || ""),
+ isNPub: (value) => /^npub1[a-z\d]{58}$/.test(value || ""),
+ isNote: (value) => /^note1[a-z\d]+$/.test(value || ""),
+ isNcryptsec: (value) => /^ncryptsec1[a-z\d]+$/.test(value || "")
+};
+var Bech32MaxSize = 5e3;
+var BECH32_REGEX = /[\x21-\x7E]{1,83}1[023456789acdefghjklmnpqrstuvwxyz]{6,}/;
+function integerToUint8Array(number4) {
+ const uint8Array = new Uint8Array(4);
+ uint8Array[0] = number4 >> 24 & 255;
+ uint8Array[1] = number4 >> 16 & 255;
+ uint8Array[2] = number4 >> 8 & 255;
+ uint8Array[3] = number4 & 255;
+ return uint8Array;
+}
+function decodeNostrURI(nip19code) {
+ try {
+ if (nip19code.startsWith("nostr:"))
+ nip19code = nip19code.substring(6);
+ return decode(nip19code);
+ } catch (_err) {
+ return { type: "invalid", data: null };
+ }
+}
+function decode(code) {
+ let { prefix, words } = bech32.decode(code, Bech32MaxSize);
+ let data = new Uint8Array(bech32.fromWords(words));
+ switch (prefix) {
+ case "nprofile": {
+ let tlv = parseTLV(data);
+ if (!tlv[0]?.[0])
+ throw new Error("missing TLV 0 for nprofile");
+ if (tlv[0][0].length !== 32)
+ throw new Error("TLV 0 should be 32 bytes");
+ return {
+ type: "nprofile",
+ data: {
+ pubkey: bytesToHex2(tlv[0][0]),
+ relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
+ }
+ };
+ }
+ case "nevent": {
+ let tlv = parseTLV(data);
+ if (!tlv[0]?.[0])
+ throw new Error("missing TLV 0 for nevent");
+ if (tlv[0][0].length !== 32)
+ throw new Error("TLV 0 should be 32 bytes");
+ if (tlv[2] && tlv[2][0].length !== 32)
+ throw new Error("TLV 2 should be 32 bytes");
+ if (tlv[3] && tlv[3][0].length !== 4)
+ throw new Error("TLV 3 should be 4 bytes");
+ return {
+ type: "nevent",
+ data: {
+ id: bytesToHex2(tlv[0][0]),
+ relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : [],
+ author: tlv[2]?.[0] ? bytesToHex2(tlv[2][0]) : void 0,
+ kind: tlv[3]?.[0] ? parseInt(bytesToHex2(tlv[3][0]), 16) : void 0
+ }
+ };
+ }
+ case "naddr": {
+ let tlv = parseTLV(data);
+ if (!tlv[0]?.[0])
+ throw new Error("missing TLV 0 for naddr");
+ if (!tlv[2]?.[0])
+ throw new Error("missing TLV 2 for naddr");
+ if (tlv[2][0].length !== 32)
+ throw new Error("TLV 2 should be 32 bytes");
+ if (!tlv[3]?.[0])
+ throw new Error("missing TLV 3 for naddr");
+ if (tlv[3][0].length !== 4)
+ throw new Error("TLV 3 should be 4 bytes");
+ return {
+ type: "naddr",
+ data: {
+ identifier: utf8Decoder.decode(tlv[0][0]),
+ pubkey: bytesToHex2(tlv[2][0]),
+ kind: parseInt(bytesToHex2(tlv[3][0]), 16),
+ relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
+ }
+ };
+ }
+ case "nsec":
+ return { type: prefix, data };
+ case "npub":
+ case "note":
+ return { type: prefix, data: bytesToHex2(data) };
+ default:
+ throw new Error(`unknown prefix ${prefix}`);
+ }
+}
+function parseTLV(data) {
+ let result = {};
+ let rest = data;
+ while (rest.length > 0) {
+ let t = rest[0];
+ let l = rest[1];
+ let v = rest.slice(2, 2 + l);
+ rest = rest.slice(2 + l);
+ if (v.length < l)
+ throw new Error(`not enough data to read on TLV ${t}`);
+ result[t] = result[t] || [];
+ result[t].push(v);
+ }
+ return result;
+}
+function nsecEncode(key) {
+ return encodeBytes("nsec", key);
+}
+function npubEncode(hex2) {
+ return encodeBytes("npub", hexToBytes2(hex2));
+}
+function noteEncode(hex2) {
+ return encodeBytes("note", hexToBytes2(hex2));
+}
+function encodeBech32(prefix, data) {
+ let words = bech32.toWords(data);
+ return bech32.encode(prefix, words, Bech32MaxSize);
+}
+function encodeBytes(prefix, bytes4) {
+ return encodeBech32(prefix, bytes4);
+}
+function nprofileEncode(profile) {
+ let data = encodeTLV({
+ 0: [hexToBytes2(profile.pubkey)],
+ 1: (profile.relays || []).map((url) => utf8Encoder.encode(url))
+ });
+ return encodeBech32("nprofile", data);
+}
+function neventEncode(event) {
+ let kindArray;
+ if (event.kind !== void 0) {
+ kindArray = integerToUint8Array(event.kind);
+ }
+ let data = encodeTLV({
+ 0: [hexToBytes2(event.id)],
+ 1: (event.relays || []).map((url) => utf8Encoder.encode(url)),
+ 2: event.author ? [hexToBytes2(event.author)] : [],
+ 3: kindArray ? [new Uint8Array(kindArray)] : []
+ });
+ return encodeBech32("nevent", data);
+}
+function naddrEncode(addr) {
+ let kind = new ArrayBuffer(4);
+ new DataView(kind).setUint32(0, addr.kind, false);
+ let data = encodeTLV({
+ 0: [utf8Encoder.encode(addr.identifier)],
+ 1: (addr.relays || []).map((url) => utf8Encoder.encode(url)),
+ 2: [hexToBytes2(addr.pubkey)],
+ 3: [new Uint8Array(kind)]
+ });
+ return encodeBech32("naddr", data);
+}
+function encodeTLV(tlv) {
+ let entries = [];
+ Object.entries(tlv).reverse().forEach(([t, vs]) => {
+ vs.forEach((v) => {
+ let entry = new Uint8Array(v.length + 2);
+ entry.set([parseInt(t)], 0);
+ entry.set([v.length], 1);
+ entry.set(v, 2);
+ entries.push(entry);
+ });
+ });
+ return concatBytes3(...entries);
+}
+var nip04_exports = {};
+__export2(nip04_exports, {
+ decrypt: () => decrypt2,
+ encrypt: () => encrypt2
+});
+function encrypt2(secretKey, pubkey, text) {
+ const privkey = secretKey instanceof Uint8Array ? bytesToHex2(secretKey) : secretKey;
+ const key = secp256k1.getSharedSecret(privkey, "02" + pubkey);
+ const normalizedKey = getNormalizedX(key);
+ let iv = Uint8Array.from(randomBytes2(16));
+ let plaintext = utf8Encoder.encode(text);
+ let ciphertext = cbc(normalizedKey, iv).encrypt(plaintext);
+ let ctb64 = base64.encode(new Uint8Array(ciphertext));
+ let ivb64 = base64.encode(new Uint8Array(iv.buffer));
+ return `${ctb64}?iv=${ivb64}`;
+}
+function decrypt2(secretKey, pubkey, data) {
+ const privkey = secretKey instanceof Uint8Array ? bytesToHex2(secretKey) : secretKey;
+ let [ctb64, ivb64] = data.split("?iv=");
+ let key = secp256k1.getSharedSecret(privkey, "02" + pubkey);
+ let normalizedKey = getNormalizedX(key);
+ let iv = base64.decode(ivb64);
+ let ciphertext = base64.decode(ctb64);
+ let plaintext = cbc(normalizedKey, iv).decrypt(ciphertext);
+ return utf8Decoder.decode(plaintext);
+}
+function getNormalizedX(key) {
+ return key.slice(1, 33);
+}
+var nip05_exports = {};
+__export2(nip05_exports, {
+ NIP05_REGEX: () => NIP05_REGEX,
+ isNip05: () => isNip05,
+ isValid: () => isValid,
+ queryProfile: () => queryProfile,
+ searchDomain: () => searchDomain,
+ useFetchImplementation: () => useFetchImplementation
+});
+var NIP05_REGEX = /^(?:([\w.+-]+)@)?([\w_-]+(\.[\w_-]+)+)$/;
+var isNip05 = (value) => NIP05_REGEX.test(value || "");
+var _fetch;
+try {
+ _fetch = fetch;
+} catch (_) {
+ null;
+}
+function useFetchImplementation(fetchImplementation) {
+ _fetch = fetchImplementation;
+}
+async function searchDomain(domain, query = "") {
+ try {
+ const url = `https://${domain}/.well-known/nostr.json?name=${query}`;
+ const res = await _fetch(url, { redirect: "manual" });
+ if (res.status !== 200) {
+ throw Error("Wrong response code");
+ }
+ const json = await res.json();
+ return json.names;
+ } catch (_) {
+ return {};
+ }
+}
+async function queryProfile(fullname) {
+ const match = fullname.match(NIP05_REGEX);
+ if (!match)
+ return null;
+ const [, name = "_", domain] = match;
+ try {
+ const url = `https://${domain}/.well-known/nostr.json?name=${name}`;
+ const res = await _fetch(url, { redirect: "manual" });
+ if (res.status !== 200) {
+ throw Error("Wrong response code");
+ }
+ const json = await res.json();
+ const pubkey = json.names[name];
+ return pubkey ? { pubkey, relays: json.relays?.[pubkey] } : null;
+ } catch (_e) {
+ return null;
+ }
+}
+async function isValid(pubkey, nip05) {
+ const res = await queryProfile(nip05);
+ return res ? res.pubkey === pubkey : false;
+}
+var nip10_exports = {};
+__export2(nip10_exports, {
+ parse: () => parse
+});
+function parse(event) {
+ const result = {
+ reply: void 0,
+ root: void 0,
+ mentions: [],
+ profiles: [],
+ quotes: []
+ };
+ let maybeParent;
+ let maybeRoot;
+ for (let i22 = event.tags.length - 1; i22 >= 0; i22--) {
+ const tag = event.tags[i22];
+ if (tag[0] === "e" && tag[1]) {
+ const [_, eTagEventId, eTagRelayUrl, eTagMarker, eTagAuthor] = tag;
+ const eventPointer = {
+ id: eTagEventId,
+ relays: eTagRelayUrl ? [eTagRelayUrl] : [],
+ author: eTagAuthor
+ };
+ if (eTagMarker === "root") {
+ result.root = eventPointer;
+ continue;
+ }
+ if (eTagMarker === "reply") {
+ result.reply = eventPointer;
+ continue;
+ }
+ if (eTagMarker === "mention") {
+ result.mentions.push(eventPointer);
+ continue;
+ }
+ if (!maybeParent) {
+ maybeParent = eventPointer;
+ } else {
+ maybeRoot = eventPointer;
+ }
+ result.mentions.push(eventPointer);
+ continue;
+ }
+ if (tag[0] === "q" && tag[1]) {
+ const [_, eTagEventId, eTagRelayUrl] = tag;
+ result.quotes.push({
+ id: eTagEventId,
+ relays: eTagRelayUrl ? [eTagRelayUrl] : []
+ });
+ }
+ if (tag[0] === "p" && tag[1]) {
+ result.profiles.push({
+ pubkey: tag[1],
+ relays: tag[2] ? [tag[2]] : []
+ });
+ continue;
+ }
+ }
+ if (!result.root) {
+ result.root = maybeRoot || maybeParent || result.reply;
+ }
+ if (!result.reply) {
+ result.reply = maybeParent || result.root;
+ }
+ ;
+ [result.reply, result.root].forEach((ref) => {
+ if (!ref)
+ return;
+ let idx = result.mentions.indexOf(ref);
+ if (idx !== -1) {
+ result.mentions.splice(idx, 1);
+ }
+ if (ref.author) {
+ let author = result.profiles.find((p) => p.pubkey === ref.author);
+ if (author && author.relays) {
+ if (!ref.relays) {
+ ref.relays = [];
+ }
+ author.relays.forEach((url) => {
+ if (ref.relays?.indexOf(url) === -1)
+ ref.relays.push(url);
+ });
+ author.relays = ref.relays;
+ }
+ }
+ });
+ result.mentions.forEach((ref) => {
+ if (ref.author) {
+ let author = result.profiles.find((p) => p.pubkey === ref.author);
+ if (author && author.relays) {
+ if (!ref.relays) {
+ ref.relays = [];
+ }
+ author.relays.forEach((url) => {
+ if (ref.relays.indexOf(url) === -1)
+ ref.relays.push(url);
+ });
+ author.relays = ref.relays;
+ }
+ }
+ });
+ return result;
+}
+var nip11_exports = {};
+__export2(nip11_exports, {
+ fetchRelayInformation: () => fetchRelayInformation,
+ useFetchImplementation: () => useFetchImplementation2
+});
+var _fetch2;
+try {
+ _fetch2 = fetch;
+} catch {
+}
+function useFetchImplementation2(fetchImplementation) {
+ _fetch2 = fetchImplementation;
+}
+async function fetchRelayInformation(url) {
+ return await (await fetch(url.replace("ws://", "http://").replace("wss://", "https://"), {
+ headers: { Accept: "application/nostr+json" }
+ })).json();
+}
+var nip13_exports = {};
+__export2(nip13_exports, {
+ fastEventHash: () => fastEventHash,
+ getPow: () => getPow,
+ minePow: () => minePow
+});
+function getPow(hex2) {
+ let count = 0;
+ for (let i22 = 0; i22 < 64; i22 += 8) {
+ const nibble = parseInt(hex2.substring(i22, i22 + 8), 16);
+ if (nibble === 0) {
+ count += 32;
+ } else {
+ count += Math.clz32(nibble);
+ break;
+ }
+ }
+ return count;
+}
+function minePow(unsigned, difficulty) {
+ let count = 0;
+ const event = unsigned;
+ const tag = ["nonce", count.toString(), difficulty.toString()];
+ event.tags.push(tag);
+ while (true) {
+ const now2 = Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3);
+ if (now2 !== event.created_at) {
+ count = 0;
+ event.created_at = now2;
+ }
+ tag[1] = (++count).toString();
+ event.id = fastEventHash(event);
+ if (getPow(event.id) >= difficulty) {
+ break;
+ }
+ }
+ return event;
+}
+function fastEventHash(evt) {
+ return bytesToHex2(
+ sha2562(utf8Encoder.encode(JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content])))
+ );
+}
+var nip17_exports = {};
+__export2(nip17_exports, {
+ unwrapEvent: () => unwrapEvent2,
+ unwrapManyEvents: () => unwrapManyEvents2,
+ wrapEvent: () => wrapEvent2,
+ wrapManyEvents: () => wrapManyEvents2
+});
+var nip59_exports = {};
+__export2(nip59_exports, {
+ createRumor: () => createRumor,
+ createSeal: () => createSeal,
+ createWrap: () => createWrap,
+ unwrapEvent: () => unwrapEvent,
+ unwrapManyEvents: () => unwrapManyEvents,
+ wrapEvent: () => wrapEvent,
+ wrapManyEvents: () => wrapManyEvents
+});
+var nip44_exports = {};
+__export2(nip44_exports, {
+ decrypt: () => decrypt22,
+ encrypt: () => encrypt22,
+ getConversationKey: () => getConversationKey,
+ v2: () => v2
+});
+var minPlaintextSize = 1;
+var maxPlaintextSize = 65535;
+function getConversationKey(privkeyA, pubkeyB) {
+ const sharedX = secp256k1.getSharedSecret(privkeyA, "02" + pubkeyB).subarray(1, 33);
+ return extract(sha2562, sharedX, "nip44-v2");
+}
+function getMessageKeys(conversationKey, nonce) {
+ const keys = expand(sha2562, conversationKey, nonce, 76);
+ return {
+ chacha_key: keys.subarray(0, 32),
+ chacha_nonce: keys.subarray(32, 44),
+ hmac_key: keys.subarray(44, 76)
+ };
+}
+function calcPaddedLen(len) {
+ if (!Number.isSafeInteger(len) || len < 1)
+ throw new Error("expected positive integer");
+ if (len <= 32)
+ return 32;
+ const nextPower = 1 << Math.floor(Math.log2(len - 1)) + 1;
+ const chunk = nextPower <= 256 ? 32 : nextPower / 8;
+ return chunk * (Math.floor((len - 1) / chunk) + 1);
+}
+function writeU16BE(num) {
+ if (!Number.isSafeInteger(num) || num < minPlaintextSize || num > maxPlaintextSize)
+ throw new Error("invalid plaintext size: must be between 1 and 65535 bytes");
+ const arr = new Uint8Array(2);
+ new DataView(arr.buffer).setUint16(0, num, false);
+ return arr;
+}
+function pad(plaintext) {
+ const unpadded = utf8Encoder.encode(plaintext);
+ const unpaddedLen = unpadded.length;
+ const prefix = writeU16BE(unpaddedLen);
+ const suffix = new Uint8Array(calcPaddedLen(unpaddedLen) - unpaddedLen);
+ return concatBytes3(prefix, unpadded, suffix);
+}
+function unpad(padded) {
+ const unpaddedLen = new DataView(padded.buffer).getUint16(0);
+ const unpadded = padded.subarray(2, 2 + unpaddedLen);
+ if (unpaddedLen < minPlaintextSize || unpaddedLen > maxPlaintextSize || unpadded.length !== unpaddedLen || padded.length !== 2 + calcPaddedLen(unpaddedLen))
+ throw new Error("invalid padding");
+ return utf8Decoder.decode(unpadded);
+}
+function hmacAad(key, message, aad) {
+ if (aad.length !== 32)
+ throw new Error("AAD associated data must be 32 bytes");
+ const combined = concatBytes3(aad, message);
+ return hmac2(sha2562, key, combined);
+}
+function decodePayload(payload) {
+ if (typeof payload !== "string")
+ throw new Error("payload must be a valid string");
+ const plen = payload.length;
+ if (plen < 132 || plen > 87472)
+ throw new Error("invalid payload length: " + plen);
+ if (payload[0] === "#")
+ throw new Error("unknown encryption version");
+ let data;
+ try {
+ data = base64.decode(payload);
+ } catch (error) {
+ throw new Error("invalid base64: " + error.message);
+ }
+ const dlen = data.length;
+ if (dlen < 99 || dlen > 65603)
+ throw new Error("invalid data length: " + dlen);
+ const vers = data[0];
+ if (vers !== 2)
+ throw new Error("unknown encryption version " + vers);
+ return {
+ nonce: data.subarray(1, 33),
+ ciphertext: data.subarray(33, -32),
+ mac: data.subarray(-32)
+ };
+}
+function encrypt22(plaintext, conversationKey, nonce = randomBytes2(32)) {
+ const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce);
+ const padded = pad(plaintext);
+ const ciphertext = chacha20(chacha_key, chacha_nonce, padded);
+ const mac = hmacAad(hmac_key, ciphertext, nonce);
+ return base64.encode(concatBytes3(new Uint8Array([2]), nonce, ciphertext, mac));
+}
+function decrypt22(payload, conversationKey) {
+ const { nonce, ciphertext, mac } = decodePayload(payload);
+ const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce);
+ const calculatedMac = hmacAad(hmac_key, ciphertext, nonce);
+ if (!equalBytes2(calculatedMac, mac))
+ throw new Error("invalid MAC");
+ const padded = chacha20(chacha_key, chacha_nonce, ciphertext);
+ return unpad(padded);
+}
+var v2 = {
+ utils: {
+ getConversationKey,
+ calcPaddedLen
+ },
+ encrypt: encrypt22,
+ decrypt: decrypt22
+};
+var TWO_DAYS = 2 * 24 * 60 * 60;
+var now = () => Math.round(Date.now() / 1e3);
+var randomNow = () => Math.round(now() - Math.random() * TWO_DAYS);
+var nip44ConversationKey = (privateKey, publicKey) => getConversationKey(privateKey, publicKey);
+var nip44Encrypt = (data, privateKey, publicKey) => encrypt22(JSON.stringify(data), nip44ConversationKey(privateKey, publicKey));
+var nip44Decrypt = (data, privateKey) => JSON.parse(decrypt22(data.content, nip44ConversationKey(privateKey, data.pubkey)));
+function createRumor(event, privateKey) {
+ const rumor = {
+ created_at: now(),
+ content: "",
+ tags: [],
+ ...event,
+ pubkey: getPublicKey(privateKey)
+ };
+ rumor.id = getEventHash(rumor);
+ return rumor;
+}
+function createSeal(rumor, privateKey, recipientPublicKey) {
+ return finalizeEvent(
+ {
+ kind: Seal,
+ content: nip44Encrypt(rumor, privateKey, recipientPublicKey),
+ created_at: randomNow(),
+ tags: []
+ },
+ privateKey
+ );
+}
+function createWrap(seal, recipientPublicKey) {
+ const randomKey = generateSecretKey();
+ return finalizeEvent(
+ {
+ kind: GiftWrap,
+ content: nip44Encrypt(seal, randomKey, recipientPublicKey),
+ created_at: randomNow(),
+ tags: [["p", recipientPublicKey]]
+ },
+ randomKey
+ );
+}
+function wrapEvent(event, senderPrivateKey, recipientPublicKey) {
+ const rumor = createRumor(event, senderPrivateKey);
+ const seal = createSeal(rumor, senderPrivateKey, recipientPublicKey);
+ return createWrap(seal, recipientPublicKey);
+}
+function wrapManyEvents(event, senderPrivateKey, recipientsPublicKeys) {
+ if (!recipientsPublicKeys || recipientsPublicKeys.length === 0) {
+ throw new Error("At least one recipient is required.");
+ }
+ const senderPublicKey = getPublicKey(senderPrivateKey);
+ const wrappeds = [wrapEvent(event, senderPrivateKey, senderPublicKey)];
+ recipientsPublicKeys.forEach((recipientPublicKey) => {
+ wrappeds.push(wrapEvent(event, senderPrivateKey, recipientPublicKey));
+ });
+ return wrappeds;
+}
+function unwrapEvent(wrap, recipientPrivateKey) {
+ const unwrappedSeal = nip44Decrypt(wrap, recipientPrivateKey);
+ return nip44Decrypt(unwrappedSeal, recipientPrivateKey);
+}
+function unwrapManyEvents(wrappedEvents, recipientPrivateKey) {
+ let unwrappedEvents = [];
+ wrappedEvents.forEach((e) => {
+ unwrappedEvents.push(unwrapEvent(e, recipientPrivateKey));
+ });
+ unwrappedEvents.sort((a, b) => a.created_at - b.created_at);
+ return unwrappedEvents;
+}
+function createEvent(recipients, message, conversationTitle, replyTo) {
+ const baseEvent = {
+ created_at: Math.ceil(Date.now() / 1e3),
+ kind: PrivateDirectMessage,
+ tags: [],
+ content: message
+ };
+ const recipientsArray = Array.isArray(recipients) ? recipients : [recipients];
+ recipientsArray.forEach(({ publicKey, relayUrl }) => {
+ baseEvent.tags.push(relayUrl ? ["p", publicKey, relayUrl] : ["p", publicKey]);
+ });
+ if (replyTo) {
+ baseEvent.tags.push(["e", replyTo.eventId, replyTo.relayUrl || "", "reply"]);
+ }
+ if (conversationTitle) {
+ baseEvent.tags.push(["subject", conversationTitle]);
+ }
+ return baseEvent;
+}
+function wrapEvent2(senderPrivateKey, recipient, message, conversationTitle, replyTo) {
+ const event = createEvent(recipient, message, conversationTitle, replyTo);
+ return wrapEvent(event, senderPrivateKey, recipient.publicKey);
+}
+function wrapManyEvents2(senderPrivateKey, recipients, message, conversationTitle, replyTo) {
+ if (!recipients || recipients.length === 0) {
+ throw new Error("At least one recipient is required.");
+ }
+ const senderPublicKey = getPublicKey(senderPrivateKey);
+ return [{ publicKey: senderPublicKey }, ...recipients].map(
+ (recipient) => wrapEvent2(senderPrivateKey, recipient, message, conversationTitle, replyTo)
+ );
+}
+var unwrapEvent2 = unwrapEvent;
+var unwrapManyEvents2 = unwrapManyEvents;
+var nip18_exports = {};
+__export2(nip18_exports, {
+ finishRepostEvent: () => finishRepostEvent,
+ getRepostedEvent: () => getRepostedEvent,
+ getRepostedEventPointer: () => getRepostedEventPointer
+});
+function finishRepostEvent(t, reposted, relayUrl, privateKey) {
+ let kind;
+ const tags = [...t.tags ?? [], ["e", reposted.id, relayUrl], ["p", reposted.pubkey]];
+ if (reposted.kind === ShortTextNote) {
+ kind = Repost;
+ } else {
+ kind = GenericRepost;
+ tags.push(["k", String(reposted.kind)]);
+ }
+ return finalizeEvent(
+ {
+ kind,
+ tags,
+ content: t.content === "" || reposted.tags?.find((tag) => tag[0] === "-") ? "" : JSON.stringify(reposted),
+ created_at: t.created_at
+ },
+ privateKey
+ );
+}
+function getRepostedEventPointer(event) {
+ if (![Repost, GenericRepost].includes(event.kind)) {
+ return void 0;
+ }
+ let lastETag;
+ let lastPTag;
+ for (let i22 = event.tags.length - 1; i22 >= 0 && (lastETag === void 0 || lastPTag === void 0); i22--) {
+ const tag = event.tags[i22];
+ if (tag.length >= 2) {
+ if (tag[0] === "e" && lastETag === void 0) {
+ lastETag = tag;
+ } else if (tag[0] === "p" && lastPTag === void 0) {
+ lastPTag = tag;
+ }
+ }
+ }
+ if (lastETag === void 0) {
+ return void 0;
+ }
+ return {
+ id: lastETag[1],
+ relays: [lastETag[2], lastPTag?.[2]].filter((x) => typeof x === "string"),
+ author: lastPTag?.[1]
+ };
+}
+function getRepostedEvent(event, { skipVerification } = {}) {
+ const pointer = getRepostedEventPointer(event);
+ if (pointer === void 0 || event.content === "") {
+ return void 0;
+ }
+ let repostedEvent;
+ try {
+ repostedEvent = JSON.parse(event.content);
+ } catch (error) {
+ return void 0;
+ }
+ if (repostedEvent.id !== pointer.id) {
+ return void 0;
+ }
+ if (!skipVerification && !verifyEvent(repostedEvent)) {
+ return void 0;
+ }
+ return repostedEvent;
+}
+var nip21_exports = {};
+__export2(nip21_exports, {
+ NOSTR_URI_REGEX: () => NOSTR_URI_REGEX,
+ parse: () => parse2,
+ test: () => test
+});
+var NOSTR_URI_REGEX = new RegExp(`nostr:(${BECH32_REGEX.source})`);
+function test(value) {
+ return typeof value === "string" && new RegExp(`^${NOSTR_URI_REGEX.source}$`).test(value);
+}
+function parse2(uri) {
+ const match = uri.match(new RegExp(`^${NOSTR_URI_REGEX.source}$`));
+ if (!match)
+ throw new Error(`Invalid Nostr URI: ${uri}`);
+ return {
+ uri: match[0],
+ value: match[1],
+ decoded: decode(match[1])
+ };
+}
+var nip25_exports = {};
+__export2(nip25_exports, {
+ finishReactionEvent: () => finishReactionEvent,
+ getReactedEventPointer: () => getReactedEventPointer
+});
+function finishReactionEvent(t, reacted, privateKey) {
+ const inheritedTags = reacted.tags.filter((tag) => tag.length >= 2 && (tag[0] === "e" || tag[0] === "p"));
+ return finalizeEvent(
+ {
+ ...t,
+ kind: Reaction,
+ tags: [...t.tags ?? [], ...inheritedTags, ["e", reacted.id], ["p", reacted.pubkey]],
+ content: t.content ?? "+"
+ },
+ privateKey
+ );
+}
+function getReactedEventPointer(event) {
+ if (event.kind !== Reaction) {
+ return void 0;
+ }
+ let lastETag;
+ let lastPTag;
+ for (let i22 = event.tags.length - 1; i22 >= 0 && (lastETag === void 0 || lastPTag === void 0); i22--) {
+ const tag = event.tags[i22];
+ if (tag.length >= 2) {
+ if (tag[0] === "e" && lastETag === void 0) {
+ lastETag = tag;
+ } else if (tag[0] === "p" && lastPTag === void 0) {
+ lastPTag = tag;
+ }
+ }
+ }
+ if (lastETag === void 0 || lastPTag === void 0) {
+ return void 0;
+ }
+ return {
+ id: lastETag[1],
+ relays: [lastETag[2], lastPTag[2]].filter((x) => x !== void 0),
+ author: lastPTag[1]
+ };
+}
+var nip27_exports = {};
+__export2(nip27_exports, {
+ parse: () => parse3
+});
+var noCharacter = /\W/m;
+var noURLCharacter = /\W |\W$|$|,| /m;
+function* parse3(content) {
+ const max = content.length;
+ let prevIndex = 0;
+ let index = 0;
+ while (index < max) {
+ let u = content.indexOf(":", index);
+ if (u === -1) {
+ break;
+ }
+ if (content.substring(u - 5, u) === "nostr") {
+ const m = content.substring(u + 60).match(noCharacter);
+ const end = m ? u + 60 + m.index : max;
+ try {
+ let pointer;
+ let { data, type } = decode(content.substring(u + 1, end));
+ switch (type) {
+ case "npub":
+ pointer = { pubkey: data };
+ break;
+ case "nsec":
+ case "note":
+ index = end + 1;
+ continue;
+ default:
+ pointer = data;
+ }
+ if (prevIndex !== u - 5) {
+ yield { type: "text", text: content.substring(prevIndex, u - 5) };
+ }
+ yield { type: "reference", pointer };
+ index = end;
+ prevIndex = index;
+ continue;
+ } catch (_err) {
+ index = u + 1;
+ continue;
+ }
+ } else if (content.substring(u - 5, u) === "https" || content.substring(u - 4, u) === "http") {
+ const m = content.substring(u + 4).match(noURLCharacter);
+ const end = m ? u + 4 + m.index : max;
+ const prefixLen = content[u - 1] === "s" ? 5 : 4;
+ try {
+ let url = new URL(content.substring(u - prefixLen, end));
+ if (url.hostname.indexOf(".") === -1) {
+ throw new Error("invalid url");
+ }
+ if (prevIndex !== u - prefixLen) {
+ yield { type: "text", text: content.substring(prevIndex, u - prefixLen) };
+ }
+ if (url.pathname.endsWith(".png") || url.pathname.endsWith(".jpg") || url.pathname.endsWith(".jpeg") || url.pathname.endsWith(".gif") || url.pathname.endsWith(".webp")) {
+ yield { type: "image", url: url.toString() };
+ index = end;
+ prevIndex = index;
+ continue;
+ }
+ if (url.pathname.endsWith(".mp4") || url.pathname.endsWith(".avi") || url.pathname.endsWith(".webm") || url.pathname.endsWith(".mkv")) {
+ yield { type: "video", url: url.toString() };
+ index = end;
+ prevIndex = index;
+ continue;
+ }
+ if (url.pathname.endsWith(".mp3") || url.pathname.endsWith(".aac") || url.pathname.endsWith(".ogg") || url.pathname.endsWith(".opus")) {
+ yield { type: "audio", url: url.toString() };
+ index = end;
+ prevIndex = index;
+ continue;
+ }
+ yield { type: "url", url: url.toString() };
+ index = end;
+ prevIndex = index;
+ continue;
+ } catch (_err) {
+ index = end + 1;
+ continue;
+ }
+ } else if (content.substring(u - 3, u) === "wss" || content.substring(u - 2, u) === "ws") {
+ const m = content.substring(u + 4).match(noURLCharacter);
+ const end = m ? u + 4 + m.index : max;
+ const prefixLen = content[u - 1] === "s" ? 3 : 2;
+ try {
+ let url = new URL(content.substring(u - prefixLen, end));
+ if (url.hostname.indexOf(".") === -1) {
+ throw new Error("invalid ws url");
+ }
+ if (prevIndex !== u - prefixLen) {
+ yield { type: "text", text: content.substring(prevIndex, u - prefixLen) };
+ }
+ yield { type: "relay", url: url.toString() };
+ index = end;
+ prevIndex = index;
+ continue;
+ } catch (_err) {
+ index = end + 1;
+ continue;
+ }
+ } else {
+ index = u + 1;
+ continue;
+ }
+ }
+ if (prevIndex !== max) {
+ yield { type: "text", text: content.substring(prevIndex) };
+ }
+}
+var nip28_exports = {};
+__export2(nip28_exports, {
+ channelCreateEvent: () => channelCreateEvent,
+ channelHideMessageEvent: () => channelHideMessageEvent,
+ channelMessageEvent: () => channelMessageEvent,
+ channelMetadataEvent: () => channelMetadataEvent,
+ channelMuteUserEvent: () => channelMuteUserEvent
+});
+var channelCreateEvent = (t, privateKey) => {
+ let content;
+ if (typeof t.content === "object") {
+ content = JSON.stringify(t.content);
+ } else if (typeof t.content === "string") {
+ content = t.content;
+ } else {
+ return void 0;
+ }
+ return finalizeEvent(
+ {
+ kind: ChannelCreation,
+ tags: [...t.tags ?? []],
+ content,
+ created_at: t.created_at
+ },
+ privateKey
+ );
+};
+var channelMetadataEvent = (t, privateKey) => {
+ let content;
+ if (typeof t.content === "object") {
+ content = JSON.stringify(t.content);
+ } else if (typeof t.content === "string") {
+ content = t.content;
+ } else {
+ return void 0;
+ }
+ return finalizeEvent(
+ {
+ kind: ChannelMetadata,
+ tags: [["e", t.channel_create_event_id], ...t.tags ?? []],
+ content,
+ created_at: t.created_at
+ },
+ privateKey
+ );
+};
+var channelMessageEvent = (t, privateKey) => {
+ const tags = [["e", t.channel_create_event_id, t.relay_url, "root"]];
+ if (t.reply_to_channel_message_event_id) {
+ tags.push(["e", t.reply_to_channel_message_event_id, t.relay_url, "reply"]);
+ }
+ return finalizeEvent(
+ {
+ kind: ChannelMessage,
+ tags: [...tags, ...t.tags ?? []],
+ content: t.content,
+ created_at: t.created_at
+ },
+ privateKey
+ );
+};
+var channelHideMessageEvent = (t, privateKey) => {
+ let content;
+ if (typeof t.content === "object") {
+ content = JSON.stringify(t.content);
+ } else if (typeof t.content === "string") {
+ content = t.content;
+ } else {
+ return void 0;
+ }
+ return finalizeEvent(
+ {
+ kind: ChannelHideMessage,
+ tags: [["e", t.channel_message_event_id], ...t.tags ?? []],
+ content,
+ created_at: t.created_at
+ },
+ privateKey
+ );
+};
+var channelMuteUserEvent = (t, privateKey) => {
+ let content;
+ if (typeof t.content === "object") {
+ content = JSON.stringify(t.content);
+ } else if (typeof t.content === "string") {
+ content = t.content;
+ } else {
+ return void 0;
+ }
+ return finalizeEvent(
+ {
+ kind: ChannelMuteUser,
+ tags: [["p", t.pubkey_to_mute], ...t.tags ?? []],
+ content,
+ created_at: t.created_at
+ },
+ privateKey
+ );
+};
+var nip30_exports = {};
+__export2(nip30_exports, {
+ EMOJI_SHORTCODE_REGEX: () => EMOJI_SHORTCODE_REGEX,
+ matchAll: () => matchAll,
+ regex: () => regex,
+ replaceAll: () => replaceAll
+});
+var EMOJI_SHORTCODE_REGEX = /:(\w+):/;
+var regex = () => new RegExp(`\\B${EMOJI_SHORTCODE_REGEX.source}\\B`, "g");
+function* matchAll(content) {
+ const matches = content.matchAll(regex());
+ for (const match of matches) {
+ try {
+ const [shortcode, name] = match;
+ yield {
+ shortcode,
+ name,
+ start: match.index,
+ end: match.index + shortcode.length
+ };
+ } catch (_e) {
+ }
+ }
+}
+function replaceAll(content, replacer) {
+ return content.replaceAll(regex(), (shortcode, name) => {
+ return replacer({
+ shortcode,
+ name
+ });
+ });
+}
+var nip39_exports = {};
+__export2(nip39_exports, {
+ useFetchImplementation: () => useFetchImplementation3,
+ validateGithub: () => validateGithub
+});
+var _fetch3;
+try {
+ _fetch3 = fetch;
+} catch {
+}
+function useFetchImplementation3(fetchImplementation) {
+ _fetch3 = fetchImplementation;
+}
+async function validateGithub(pubkey, username, proof) {
+ try {
+ let res = await (await _fetch3(`https://gist.github.com/${username}/${proof}/raw`)).text();
+ return res === `Verifying that I control the following Nostr public key: ${pubkey}`;
+ } catch (_) {
+ return false;
+ }
+}
+var nip47_exports = {};
+__export2(nip47_exports, {
+ makeNwcRequestEvent: () => makeNwcRequestEvent,
+ parseConnectionString: () => parseConnectionString
+});
+function parseConnectionString(connectionString) {
+ const { pathname, searchParams } = new URL(connectionString);
+ const pubkey = pathname;
+ const relay = searchParams.get("relay");
+ const secret = searchParams.get("secret");
+ if (!pubkey || !relay || !secret) {
+ throw new Error("invalid connection string");
+ }
+ return { pubkey, relay, secret };
+}
+async function makeNwcRequestEvent(pubkey, secretKey, invoice) {
+ const content = {
+ method: "pay_invoice",
+ params: {
+ invoice
+ }
+ };
+ const encryptedContent = await encrypt2(secretKey, pubkey, JSON.stringify(content));
+ const eventTemplate = {
+ kind: NWCWalletRequest,
+ created_at: Math.round(Date.now() / 1e3),
+ content: encryptedContent,
+ tags: [["p", pubkey]]
+ };
+ return finalizeEvent(eventTemplate, secretKey);
+}
+var nip54_exports = {};
+__export2(nip54_exports, {
+ normalizeIdentifier: () => normalizeIdentifier
+});
+function normalizeIdentifier(name) {
+ name = name.trim().toLowerCase();
+ name = name.normalize("NFKC");
+ return Array.from(name).map((char) => {
+ if (new RegExp("\\p{Letter}", "u").test(char) || new RegExp("\\p{Number}", "u").test(char)) {
+ return char;
+ }
+ return "-";
+ }).join("");
+}
+var nip57_exports = {};
+__export2(nip57_exports, {
+ getZapEndpoint: () => getZapEndpoint,
+ makeZapReceipt: () => makeZapReceipt,
+ makeZapRequest: () => makeZapRequest,
+ useFetchImplementation: () => useFetchImplementation4,
+ validateZapRequest: () => validateZapRequest
+});
+var _fetch4;
+try {
+ _fetch4 = fetch;
+} catch {
+}
+function useFetchImplementation4(fetchImplementation) {
+ _fetch4 = fetchImplementation;
+}
+async function getZapEndpoint(metadata) {
+ try {
+ let lnurl = "";
+ let { lud06, lud16 } = JSON.parse(metadata.content);
+ if (lud06) {
+ let { words } = bech32.decode(lud06, 1e3);
+ let data = bech32.fromWords(words);
+ lnurl = utf8Decoder.decode(data);
+ } else if (lud16) {
+ let [name, domain] = lud16.split("@");
+ lnurl = new URL(`/.well-known/lnurlp/${name}`, `https://${domain}`).toString();
+ } else {
+ return null;
+ }
+ let res = await _fetch4(lnurl);
+ let body = await res.json();
+ if (body.allowsNostr && body.nostrPubkey) {
+ return body.callback;
+ }
+ } catch (err) {
+ }
+ return null;
+}
+function makeZapRequest({
+ profile,
+ event,
+ amount,
+ relays,
+ comment = ""
+}) {
+ if (!amount)
+ throw new Error("amount not given");
+ if (!profile)
+ throw new Error("profile not given");
+ let zr = {
+ kind: 9734,
+ created_at: Math.round(Date.now() / 1e3),
+ content: comment,
+ tags: [
+ ["p", profile],
+ ["amount", amount.toString()],
+ ["relays", ...relays]
+ ]
+ };
+ if (event && typeof event === "string") {
+ zr.tags.push(["e", event]);
+ }
+ if (event && typeof event === "object") {
+ if (isReplaceableKind(event.kind)) {
+ const a = ["a", `${event.kind}:${event.pubkey}:`];
+ zr.tags.push(a);
+ } else if (isAddressableKind(event.kind)) {
+ let d = event.tags.find(([t, v]) => t === "d" && v);
+ if (!d)
+ throw new Error("d tag not found or is empty");
+ const a = ["a", `${event.kind}:${event.pubkey}:${d[1]}`];
+ zr.tags.push(a);
+ }
+ }
+ return zr;
+}
+function validateZapRequest(zapRequestString) {
+ let zapRequest;
+ try {
+ zapRequest = JSON.parse(zapRequestString);
+ } catch (err) {
+ return "Invalid zap request JSON.";
+ }
+ if (!validateEvent(zapRequest))
+ return "Zap request is not a valid Nostr event.";
+ if (!verifyEvent(zapRequest))
+ return "Invalid signature on zap request.";
+ let p = zapRequest.tags.find(([t, v]) => t === "p" && v);
+ if (!p)
+ return "Zap request doesn't have a 'p' tag.";
+ if (!p[1].match(/^[a-f0-9]{64}$/))
+ return "Zap request 'p' tag is not valid hex.";
+ let e = zapRequest.tags.find(([t, v]) => t === "e" && v);
+ if (e && !e[1].match(/^[a-f0-9]{64}$/))
+ return "Zap request 'e' tag is not valid hex.";
+ let relays = zapRequest.tags.find(([t, v]) => t === "relays" && v);
+ if (!relays)
+ return "Zap request doesn't have a 'relays' tag.";
+ return null;
+}
+function makeZapReceipt({
+ zapRequest,
+ preimage,
+ bolt11,
+ paidAt
+}) {
+ let zr = JSON.parse(zapRequest);
+ let tagsFromZapRequest = zr.tags.filter(([t]) => t === "e" || t === "p" || t === "a");
+ let zap = {
+ kind: 9735,
+ created_at: Math.round(paidAt.getTime() / 1e3),
+ content: "",
+ tags: [...tagsFromZapRequest, ["P", zr.pubkey], ["bolt11", bolt11], ["description", zapRequest]]
+ };
+ if (preimage) {
+ zap.tags.push(["preimage", preimage]);
+ }
+ return zap;
+}
+var nip98_exports = {};
+__export2(nip98_exports, {
+ getToken: () => getToken,
+ hashPayload: () => hashPayload,
+ unpackEventFromToken: () => unpackEventFromToken,
+ validateEvent: () => validateEvent2,
+ validateEventKind: () => validateEventKind,
+ validateEventMethodTag: () => validateEventMethodTag,
+ validateEventPayloadTag: () => validateEventPayloadTag,
+ validateEventTimestamp: () => validateEventTimestamp,
+ validateEventUrlTag: () => validateEventUrlTag,
+ validateToken: () => validateToken
+});
+var _authorizationScheme = "Nostr ";
+async function getToken(loginUrl, httpMethod, sign, includeAuthorizationScheme = false, payload) {
+ const event = {
+ kind: HTTPAuth,
+ tags: [
+ ["u", loginUrl],
+ ["method", httpMethod]
+ ],
+ created_at: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
+ content: ""
+ };
+ if (payload) {
+ event.tags.push(["payload", hashPayload(payload)]);
+ }
+ const signedEvent = await sign(event);
+ const authorizationScheme = includeAuthorizationScheme ? _authorizationScheme : "";
+ return authorizationScheme + base64.encode(utf8Encoder.encode(JSON.stringify(signedEvent)));
+}
+async function validateToken(token, url, method) {
+ const event = await unpackEventFromToken(token).catch((error) => {
+ throw error;
+ });
+ const valid = await validateEvent2(event, url, method).catch((error) => {
+ throw error;
+ });
+ return valid;
+}
+async function unpackEventFromToken(token) {
+ if (!token) {
+ throw new Error("Missing token");
+ }
+ token = token.replace(_authorizationScheme, "");
+ const eventB64 = utf8Decoder.decode(base64.decode(token));
+ if (!eventB64 || eventB64.length === 0 || !eventB64.startsWith("{")) {
+ throw new Error("Invalid token");
+ }
+ const event = JSON.parse(eventB64);
+ return event;
+}
+function validateEventTimestamp(event) {
+ if (!event.created_at) {
+ return false;
+ }
+ return Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3) - event.created_at < 60;
+}
+function validateEventKind(event) {
+ return event.kind === HTTPAuth;
+}
+function validateEventUrlTag(event, url) {
+ const urlTag = event.tags.find((t) => t[0] === "u");
+ if (!urlTag) {
+ return false;
+ }
+ return urlTag.length > 0 && urlTag[1] === url;
+}
+function validateEventMethodTag(event, method) {
+ const methodTag = event.tags.find((t) => t[0] === "method");
+ if (!methodTag) {
+ return false;
+ }
+ return methodTag.length > 0 && methodTag[1].toLowerCase() === method.toLowerCase();
+}
+function hashPayload(payload) {
+ const hash3 = sha2562(utf8Encoder.encode(JSON.stringify(payload)));
+ return bytesToHex2(hash3);
+}
+function validateEventPayloadTag(event, payload) {
+ const payloadTag = event.tags.find((t) => t[0] === "payload");
+ if (!payloadTag) {
+ return false;
+ }
+ const payloadHash = hashPayload(payload);
+ return payloadTag.length > 0 && payloadTag[1] === payloadHash;
+}
+async function validateEvent2(event, url, method, body) {
+ if (!verifyEvent(event)) {
+ throw new Error("Invalid nostr event, signature invalid");
+ }
+ if (!validateEventKind(event)) {
+ throw new Error("Invalid nostr event, kind invalid");
+ }
+ if (!validateEventTimestamp(event)) {
+ throw new Error("Invalid nostr event, created_at timestamp invalid");
+ }
+ if (!validateEventUrlTag(event, url)) {
+ throw new Error("Invalid nostr event, url tag invalid");
+ }
+ if (!validateEventMethodTag(event, method)) {
+ throw new Error("Invalid nostr event, method tag invalid");
+ }
+ if (Boolean(body) && typeof body === "object" && Object.keys(body).length > 0) {
+ if (!validateEventPayloadTag(event, body)) {
+ throw new Error("Invalid nostr event, payload tag does not match request body hash");
+ }
+ }
+ return true;
+}
+
+// node_modules/nostr-tools/lib/esm/pool.js
+var verifiedSymbol2 = Symbol("verified");
+var isRecord2 = (obj) => obj instanceof Object;
+function validateEvent3(event) {
+ if (!isRecord2(event))
+ return false;
+ if (typeof event.kind !== "number")
+ return false;
+ if (typeof event.content !== "string")
+ return false;
+ if (typeof event.created_at !== "number")
+ return false;
+ if (typeof event.pubkey !== "string")
+ return false;
+ if (!event.pubkey.match(/^[a-f0-9]{64}$/))
+ return false;
+ if (!Array.isArray(event.tags))
+ return false;
+ for (let i22 = 0; i22 < event.tags.length; i22++) {
+ let tag = event.tags[i22];
+ if (!Array.isArray(tag))
+ return false;
+ for (let j = 0; j < tag.length; j++) {
+ if (typeof tag[j] !== "string")
+ return false;
+ }
+ }
+ return true;
+}
+var utf8Decoder2 = new TextDecoder("utf-8");
+var utf8Encoder2 = new TextEncoder();
+function normalizeURL2(url) {
+ try {
+ if (url.indexOf("://") === -1)
+ url = "wss://" + url;
+ let p = new URL(url);
+ p.pathname = p.pathname.replace(/\/+/g, "/");
+ if (p.pathname.endsWith("/"))
+ p.pathname = p.pathname.slice(0, -1);
+ if (p.port === "80" && p.protocol === "ws:" || p.port === "443" && p.protocol === "wss:")
+ p.port = "";
+ p.searchParams.sort();
+ p.hash = "";
+ return p.toString();
+ } catch (e) {
+ throw new Error(`Invalid URL: ${url}`);
+ }
+}
+var QueueNode2 = class {
+ value;
+ next = null;
+ prev = null;
+ constructor(message) {
+ this.value = message;
+ }
+};
+var Queue2 = class {
+ first;
+ last;
+ constructor() {
+ this.first = null;
+ this.last = null;
+ }
+ enqueue(value) {
+ const newNode = new QueueNode2(value);
+ if (!this.last) {
+ this.first = newNode;
+ this.last = newNode;
+ } else if (this.last === this.first) {
+ this.last = newNode;
+ this.last.prev = this.first;
+ this.first.next = newNode;
+ } else {
+ newNode.prev = this.last;
+ this.last.next = newNode;
+ this.last = newNode;
+ }
+ return true;
+ }
+ dequeue() {
+ if (!this.first)
+ return null;
+ if (this.first === this.last) {
+ const target2 = this.first;
+ this.first = null;
+ this.last = null;
+ return target2.value;
+ }
+ const target = this.first;
+ this.first = target.next;
+ if (this.first) {
+ this.first.prev = null;
+ }
+ return target.value;
+ }
+};
+var JS2 = class {
+ generateSecretKey() {
+ return schnorr.utils.randomPrivateKey();
+ }
+ getPublicKey(secretKey) {
+ return bytesToHex2(schnorr.getPublicKey(secretKey));
+ }
+ finalizeEvent(t, secretKey) {
+ const event = t;
+ event.pubkey = bytesToHex2(schnorr.getPublicKey(secretKey));
+ event.id = getEventHash2(event);
+ event.sig = bytesToHex2(schnorr.sign(getEventHash2(event), secretKey));
+ event[verifiedSymbol2] = true;
+ return event;
+ }
+ verifyEvent(event) {
+ if (typeof event[verifiedSymbol2] === "boolean")
+ return event[verifiedSymbol2];
+ const hash3 = getEventHash2(event);
+ if (hash3 !== event.id) {
+ event[verifiedSymbol2] = false;
+ return false;
+ }
+ try {
+ const valid = schnorr.verify(event.sig, hash3, event.pubkey);
+ event[verifiedSymbol2] = valid;
+ return valid;
+ } catch (err) {
+ event[verifiedSymbol2] = false;
+ return false;
+ }
+ }
+};
+function serializeEvent2(evt) {
+ if (!validateEvent3(evt))
+ throw new Error("can't serialize event with wrong or missing properties");
+ return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);
+}
+function getEventHash2(event) {
+ let eventHash = sha2562(utf8Encoder2.encode(serializeEvent2(event)));
+ return bytesToHex2(eventHash);
+}
+var i2 = new JS2();
+var generateSecretKey2 = i2.generateSecretKey;
+var getPublicKey2 = i2.getPublicKey;
+var finalizeEvent2 = i2.finalizeEvent;
+var verifyEvent2 = i2.verifyEvent;
+var ClientAuth2 = 22242;
+function matchFilter(filter, event) {
+ if (filter.ids && filter.ids.indexOf(event.id) === -1) {
+ return false;
+ }
+ if (filter.kinds && filter.kinds.indexOf(event.kind) === -1) {
+ return false;
+ }
+ if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {
+ return false;
+ }
+ for (let f in filter) {
+ if (f[0] === "#") {
+ let tagName = f.slice(1);
+ let values = filter[`#${tagName}`];
+ if (values && !event.tags.find(([t, v]) => t === f.slice(1) && values.indexOf(v) !== -1))
+ return false;
+ }
+ }
+ if (filter.since && event.created_at < filter.since)
+ return false;
+ if (filter.until && event.created_at > filter.until)
+ return false;
+ return true;
+}
+function matchFilters(filters, event) {
+ for (let i22 = 0; i22 < filters.length; i22++) {
+ if (matchFilter(filters[i22], event)) {
+ return true;
+ }
+ }
+ return false;
+}
+function getHex642(json, field) {
+ let len = field.length + 3;
+ let idx = json.indexOf(`"${field}":`) + len;
+ let s = json.slice(idx).indexOf(`"`) + idx + 1;
+ return json.slice(s, s + 64);
+}
+function getSubscriptionId2(json) {
+ let idx = json.slice(0, 22).indexOf(`"EVENT"`);
+ if (idx === -1)
+ return null;
+ let pstart = json.slice(idx + 7 + 1).indexOf(`"`);
+ if (pstart === -1)
+ return null;
+ let start = idx + 7 + 1 + pstart;
+ let pend = json.slice(start + 1, 80).indexOf(`"`);
+ if (pend === -1)
+ return null;
+ let end = start + 1 + pend;
+ return json.slice(start + 1, end);
+}
+function makeAuthEvent2(relayURL, challenge2) {
+ return {
+ kind: ClientAuth2,
+ created_at: Math.floor(Date.now() / 1e3),
+ tags: [
+ ["relay", relayURL],
+ ["challenge", challenge2]
+ ],
+ content: ""
+ };
+}
+async function yieldThread() {
+ return new Promise((resolve) => {
+ const ch = new MessageChannel();
+ const handler = () => {
+ ch.port1.removeEventListener("message", handler);
+ resolve();
+ };
+ ch.port1.addEventListener("message", handler);
+ ch.port2.postMessage(0);
+ ch.port1.start();
+ });
+}
+var alwaysTrue = (t) => {
+ t[verifiedSymbol2] = true;
+ return true;
+};
+var AbstractRelay = class {
+ url;
+ _connected = false;
+ onclose = null;
+ onnotice = (msg) => console.debug(`NOTICE from ${this.url}: ${msg}`);
+ _onauth = null;
+ baseEoseTimeout = 4400;
+ connectionTimeout = 4400;
+ publishTimeout = 4400;
+ openSubs = /* @__PURE__ */ new Map();
+ connectionTimeoutHandle;
+ connectionPromise;
+ openCountRequests = /* @__PURE__ */ new Map();
+ openEventPublishes = /* @__PURE__ */ new Map();
+ ws;
+ incomingMessageQueue = new Queue2();
+ queueRunning = false;
+ challenge;
+ authPromise;
+ serial = 0;
+ verifyEvent;
+ _WebSocket;
+ constructor(url, opts) {
+ this.url = normalizeURL2(url);
+ this.verifyEvent = opts.verifyEvent;
+ this._WebSocket = opts.websocketImplementation || WebSocket;
+ }
+ static async connect(url, opts) {
+ const relay = new AbstractRelay(url, opts);
+ await relay.connect();
+ return relay;
+ }
+ closeAllSubscriptions(reason) {
+ for (let [_, sub] of this.openSubs) {
+ sub.close(reason);
+ }
+ this.openSubs.clear();
+ for (let [_, ep] of this.openEventPublishes) {
+ ep.reject(new Error(reason));
+ }
+ this.openEventPublishes.clear();
+ for (let [_, cr] of this.openCountRequests) {
+ cr.reject(new Error(reason));
+ }
+ this.openCountRequests.clear();
+ }
+ get connected() {
+ return this._connected;
+ }
+ async connect() {
+ if (this.connectionPromise)
+ return this.connectionPromise;
+ this.challenge = void 0;
+ this.authPromise = void 0;
+ this.connectionPromise = new Promise((resolve, reject) => {
+ this.connectionTimeoutHandle = setTimeout(() => {
+ reject("connection timed out");
+ this.connectionPromise = void 0;
+ this.onclose?.();
+ this.closeAllSubscriptions("relay connection timed out");
+ }, this.connectionTimeout);
+ try {
+ this.ws = new this._WebSocket(this.url);
+ } catch (err) {
+ clearTimeout(this.connectionTimeoutHandle);
+ reject(err);
+ return;
+ }
+ this.ws.onopen = () => {
+ clearTimeout(this.connectionTimeoutHandle);
+ this._connected = true;
+ resolve();
+ };
+ this.ws.onerror = (ev) => {
+ clearTimeout(this.connectionTimeoutHandle);
+ reject(ev.message || "websocket error");
+ if (this._connected) {
+ this._connected = false;
+ this.connectionPromise = void 0;
+ this.onclose?.();
+ this.closeAllSubscriptions("relay connection errored");
+ }
+ };
+ this.ws.onclose = async () => {
+ if (this._connected) {
+ this._connected = false;
+ this.connectionPromise = void 0;
+ this.onclose?.();
+ this.closeAllSubscriptions("relay connection closed");
+ }
+ };
+ this.ws.onmessage = this._onmessage.bind(this);
+ });
+ return this.connectionPromise;
+ }
+ async runQueue() {
+ this.queueRunning = true;
+ while (true) {
+ if (false === this.handleNext()) {
+ break;
+ }
+ await yieldThread();
+ }
+ this.queueRunning = false;
+ }
+ handleNext() {
+ const json = this.incomingMessageQueue.dequeue();
+ if (!json) {
+ return false;
+ }
+ const subid = getSubscriptionId2(json);
+ if (subid) {
+ const so = this.openSubs.get(subid);
+ if (!so) {
+ return;
+ }
+ const id = getHex642(json, "id");
+ const alreadyHave = so.alreadyHaveEvent?.(id);
+ so.receivedEvent?.(this, id);
+ if (alreadyHave) {
+ return;
+ }
+ }
+ try {
+ let data = JSON.parse(json);
+ switch (data[0]) {
+ case "EVENT": {
+ const so = this.openSubs.get(data[1]);
+ const event = data[2];
+ if (this.verifyEvent(event) && matchFilters(so.filters, event)) {
+ so.onevent(event);
+ }
+ return;
+ }
+ case "COUNT": {
+ const id = data[1];
+ const payload = data[2];
+ const cr = this.openCountRequests.get(id);
+ if (cr) {
+ cr.resolve(payload.count);
+ this.openCountRequests.delete(id);
+ }
+ return;
+ }
+ case "EOSE": {
+ const so = this.openSubs.get(data[1]);
+ if (!so)
+ return;
+ so.receivedEose();
+ return;
+ }
+ case "OK": {
+ const id = data[1];
+ const ok = data[2];
+ const reason = data[3];
+ const ep = this.openEventPublishes.get(id);
+ if (ep) {
+ clearTimeout(ep.timeout);
+ if (ok)
+ ep.resolve(reason);
+ else
+ ep.reject(new Error(reason));
+ this.openEventPublishes.delete(id);
+ }
+ return;
+ }
+ case "CLOSED": {
+ const id = data[1];
+ const so = this.openSubs.get(id);
+ if (!so)
+ return;
+ so.closed = true;
+ so.close(data[2]);
+ return;
+ }
+ case "NOTICE":
+ this.onnotice(data[1]);
+ return;
+ case "AUTH": {
+ this.challenge = data[1];
+ this._onauth?.(data[1]);
+ return;
+ }
+ }
+ } catch (err) {
+ return;
+ }
+ }
+ async send(message) {
+ if (!this.connectionPromise)
+ throw new Error("sending on closed connection");
+ this.connectionPromise.then(() => {
+ this.ws?.send(message);
+ });
+ }
+ async auth(signAuthEvent) {
+ const challenge2 = this.challenge;
+ if (!challenge2)
+ throw new Error("can't perform auth, no challenge was received");
+ if (this.authPromise)
+ return this.authPromise;
+ this.authPromise = new Promise(async (resolve, reject) => {
+ const evt = await signAuthEvent(makeAuthEvent2(this.url, challenge2));
+ const timeout = setTimeout(() => {
+ const ep = this.openEventPublishes.get(evt.id);
+ if (ep) {
+ ep.reject(new Error("auth timed out"));
+ this.openEventPublishes.delete(evt.id);
+ }
+ }, this.publishTimeout);
+ this.openEventPublishes.set(evt.id, { resolve, reject, timeout });
+ this.send('["AUTH",' + JSON.stringify(evt) + "]");
+ });
+ return this.authPromise;
+ }
+ async publish(event) {
+ const ret = new Promise((resolve, reject) => {
+ const timeout = setTimeout(() => {
+ const ep = this.openEventPublishes.get(event.id);
+ if (ep) {
+ ep.reject(new Error("publish timed out"));
+ this.openEventPublishes.delete(event.id);
+ }
+ }, this.publishTimeout);
+ this.openEventPublishes.set(event.id, { resolve, reject, timeout });
+ });
+ this.send('["EVENT",' + JSON.stringify(event) + "]");
+ return ret;
+ }
+ async count(filters, params) {
+ this.serial++;
+ const id = params?.id || "count:" + this.serial;
+ const ret = new Promise((resolve, reject) => {
+ this.openCountRequests.set(id, { resolve, reject });
+ });
+ this.send('["COUNT","' + id + '",' + JSON.stringify(filters).substring(1));
+ return ret;
+ }
+ subscribe(filters, params) {
+ const subscription = this.prepareSubscription(filters, params);
+ subscription.fire();
+ return subscription;
+ }
+ prepareSubscription(filters, params) {
+ this.serial++;
+ const id = params.id || (params.label ? params.label + ":" : "sub:") + this.serial;
+ const subscription = new Subscription(this, id, filters, params);
+ this.openSubs.set(id, subscription);
+ return subscription;
+ }
+ close() {
+ this.closeAllSubscriptions("relay connection closed by us");
+ this._connected = false;
+ this.ws?.close();
+ }
+ _onmessage(ev) {
+ this.incomingMessageQueue.enqueue(ev.data);
+ if (!this.queueRunning) {
+ this.runQueue();
+ }
+ }
+};
+var Subscription = class {
+ relay;
+ id;
+ closed = false;
+ eosed = false;
+ filters;
+ alreadyHaveEvent;
+ receivedEvent;
+ onevent;
+ oneose;
+ onclose;
+ eoseTimeout;
+ eoseTimeoutHandle;
+ constructor(relay, id, filters, params) {
+ this.relay = relay;
+ this.filters = filters;
+ this.id = id;
+ this.alreadyHaveEvent = params.alreadyHaveEvent;
+ this.receivedEvent = params.receivedEvent;
+ this.eoseTimeout = params.eoseTimeout || relay.baseEoseTimeout;
+ this.oneose = params.oneose;
+ this.onclose = params.onclose;
+ this.onevent = params.onevent || ((event) => {
+ console.warn(
+ `onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`,
+ event
+ );
+ });
+ }
+ fire() {
+ this.relay.send('["REQ","' + this.id + '",' + JSON.stringify(this.filters).substring(1));
+ this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout);
+ }
+ receivedEose() {
+ if (this.eosed)
+ return;
+ clearTimeout(this.eoseTimeoutHandle);
+ this.eosed = true;
+ this.oneose?.();
+ }
+ close(reason = "closed by caller") {
+ if (!this.closed && this.relay.connected) {
+ this.relay.send('["CLOSE",' + JSON.stringify(this.id) + "]");
+ this.closed = true;
+ }
+ this.relay.openSubs.delete(this.id);
+ this.onclose?.(reason);
+ }
+};
+var AbstractSimplePool = class {
+ relays = /* @__PURE__ */ new Map();
+ seenOn = /* @__PURE__ */ new Map();
+ trackRelays = false;
+ verifyEvent;
+ trustedRelayURLs = /* @__PURE__ */ new Set();
+ _WebSocket;
+ constructor(opts) {
+ this.verifyEvent = opts.verifyEvent;
+ this._WebSocket = opts.websocketImplementation;
+ }
+ async ensureRelay(url, params) {
+ url = normalizeURL2(url);
+ let relay = this.relays.get(url);
+ if (!relay) {
+ relay = new AbstractRelay(url, {
+ verifyEvent: this.trustedRelayURLs.has(url) ? alwaysTrue : this.verifyEvent,
+ websocketImplementation: this._WebSocket
+ });
+ if (params?.connectionTimeout)
+ relay.connectionTimeout = params.connectionTimeout;
+ this.relays.set(url, relay);
+ }
+ await relay.connect();
+ return relay;
+ }
+ close(relays) {
+ relays.map(normalizeURL2).forEach((url) => {
+ this.relays.get(url)?.close();
+ });
+ }
+ subscribe(relays, filter, params) {
+ return this.subscribeMap(
+ relays.map((url) => ({ url, filter })),
+ params
+ );
+ }
+ subscribeMany(relays, filters, params) {
+ return this.subscribeMap(
+ relays.flatMap((url) => filters.map((filter) => ({ url, filter }))),
+ params
+ );
+ }
+ subscribeMap(requests, params) {
+ if (this.trackRelays) {
+ params.receivedEvent = (relay, id) => {
+ let set = this.seenOn.get(id);
+ if (!set) {
+ set = /* @__PURE__ */ new Set();
+ this.seenOn.set(id, set);
+ }
+ set.add(relay);
+ };
+ }
+ const _knownIds = /* @__PURE__ */ new Set();
+ const subs = [];
+ const eosesReceived = [];
+ let handleEose = (i22) => {
+ if (eosesReceived[i22])
+ return;
+ eosesReceived[i22] = true;
+ if (eosesReceived.filter((a) => a).length === requests.length) {
+ params.oneose?.();
+ handleEose = () => {
+ };
+ }
+ };
+ const closesReceived = [];
+ let handleClose = (i22, reason) => {
+ if (closesReceived[i22])
+ return;
+ handleEose(i22);
+ closesReceived[i22] = reason;
+ if (closesReceived.filter((a) => a).length === requests.length) {
+ params.onclose?.(closesReceived);
+ handleClose = () => {
+ };
+ }
+ };
+ const localAlreadyHaveEventHandler = (id) => {
+ if (params.alreadyHaveEvent?.(id)) {
+ return true;
+ }
+ const have = _knownIds.has(id);
+ _knownIds.add(id);
+ return have;
+ };
+ const allOpened = Promise.all(
+ requests.map(async ({ url, filter }, i22) => {
+ url = normalizeURL2(url);
+ let relay;
+ try {
+ relay = await this.ensureRelay(url, {
+ connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : void 0
+ });
+ } catch (err) {
+ handleClose(i22, err?.message || String(err));
+ return;
+ }
+ let subscription = relay.subscribe([filter], {
+ ...params,
+ oneose: () => handleEose(i22),
+ onclose: (reason) => {
+ if (reason.startsWith("auth-required:") && params.doauth) {
+ relay.auth(params.doauth).then(() => {
+ relay.subscribe([filter], {
+ ...params,
+ oneose: () => handleEose(i22),
+ onclose: (reason2) => {
+ handleClose(i22, reason2);
+ },
+ alreadyHaveEvent: localAlreadyHaveEventHandler,
+ eoseTimeout: params.maxWait
+ });
+ }).catch((err) => {
+ handleClose(i22, `auth was required and attempted, but failed with: ${err}`);
+ });
+ } else {
+ handleClose(i22, reason);
+ }
+ },
+ alreadyHaveEvent: localAlreadyHaveEventHandler,
+ eoseTimeout: params.maxWait
+ });
+ subs.push(subscription);
+ })
+ );
+ return {
+ async close() {
+ await allOpened;
+ subs.forEach((sub) => {
+ sub.close();
+ });
+ }
+ };
+ }
+ subscribeManyMap(requests, params) {
+ if (this.trackRelays) {
+ params.receivedEvent = (relay, id) => {
+ let set = this.seenOn.get(id);
+ if (!set) {
+ set = /* @__PURE__ */ new Set();
+ this.seenOn.set(id, set);
+ }
+ set.add(relay);
+ };
+ }
+ const _knownIds = /* @__PURE__ */ new Set();
+ const subs = [];
+ const relaysLength = Object.keys(requests).length;
+ const eosesReceived = [];
+ let handleEose = (i22) => {
+ if (eosesReceived[i22])
+ return;
+ eosesReceived[i22] = true;
+ if (eosesReceived.filter((a) => a).length === relaysLength) {
+ params.oneose?.();
+ handleEose = () => {
+ };
+ }
+ };
+ const closesReceived = [];
+ let handleClose = (i22, reason) => {
+ if (closesReceived[i22])
+ return;
+ handleEose(i22);
+ closesReceived[i22] = reason;
+ if (closesReceived.filter((a) => a).length === relaysLength) {
+ params.onclose?.(closesReceived);
+ handleClose = () => {
+ };
+ }
+ };
+ const localAlreadyHaveEventHandler = (id) => {
+ if (params.alreadyHaveEvent?.(id)) {
+ return true;
+ }
+ const have = _knownIds.has(id);
+ _knownIds.add(id);
+ return have;
+ };
+ const allOpened = Promise.all(
+ Object.entries(requests).map(async (req, i22, arr) => {
+ if (arr.indexOf(req) !== i22) {
+ handleClose(i22, "duplicate url");
+ return;
+ }
+ let [url, filters] = req;
+ url = normalizeURL2(url);
+ let relay;
+ try {
+ relay = await this.ensureRelay(url, {
+ connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : void 0
+ });
+ } catch (err) {
+ handleClose(i22, err?.message || String(err));
+ return;
+ }
+ let subscription = relay.subscribe(filters, {
+ ...params,
+ oneose: () => handleEose(i22),
+ onclose: (reason) => {
+ if (reason.startsWith("auth-required:") && params.doauth) {
+ relay.auth(params.doauth).then(() => {
+ relay.subscribe(filters, {
+ ...params,
+ oneose: () => handleEose(i22),
+ onclose: (reason2) => {
+ handleClose(i22, reason2);
+ },
+ alreadyHaveEvent: localAlreadyHaveEventHandler,
+ eoseTimeout: params.maxWait
+ });
+ }).catch((err) => {
+ handleClose(i22, `auth was required and attempted, but failed with: ${err}`);
+ });
+ } else {
+ handleClose(i22, reason);
+ }
+ },
+ alreadyHaveEvent: localAlreadyHaveEventHandler,
+ eoseTimeout: params.maxWait
+ });
+ subs.push(subscription);
+ })
+ );
+ return {
+ async close() {
+ await allOpened;
+ subs.forEach((sub) => {
+ sub.close();
+ });
+ }
+ };
+ }
+ subscribeEose(relays, filter, params) {
+ const subcloser = this.subscribe(relays, filter, {
+ ...params,
+ oneose() {
+ subcloser.close();
+ }
+ });
+ return subcloser;
+ }
+ subscribeManyEose(relays, filters, params) {
+ const subcloser = this.subscribeMany(relays, filters, {
+ ...params,
+ oneose() {
+ subcloser.close();
+ }
+ });
+ return subcloser;
+ }
+ async querySync(relays, filter, params) {
+ return new Promise(async (resolve) => {
+ const events = [];
+ this.subscribeEose(relays, filter, {
+ ...params,
+ onevent(event) {
+ events.push(event);
+ },
+ onclose(_) {
+ resolve(events);
+ }
+ });
+ });
+ }
+ async get(relays, filter, params) {
+ filter.limit = 1;
+ const events = await this.querySync(relays, filter, params);
+ events.sort((a, b) => b.created_at - a.created_at);
+ return events[0] || null;
+ }
+ publish(relays, event) {
+ return relays.map(normalizeURL2).map(async (url, i22, arr) => {
+ if (arr.indexOf(url) !== i22) {
+ return Promise.reject("duplicate url");
+ }
+ let r = await this.ensureRelay(url);
+ return r.publish(event).then((reason) => {
+ if (this.trackRelays) {
+ let set = this.seenOn.get(event.id);
+ if (!set) {
+ set = /* @__PURE__ */ new Set();
+ this.seenOn.set(event.id, set);
+ }
+ set.add(r);
+ }
+ return reason;
+ });
+ });
+ }
+ listConnectionStatus() {
+ const map = /* @__PURE__ */ new Map();
+ this.relays.forEach((relay, url) => map.set(url, relay.connected));
+ return map;
+ }
+ destroy() {
+ this.relays.forEach((conn) => conn.close());
+ this.relays = /* @__PURE__ */ new Map();
+ }
+};
+var _WebSocket3;
+try {
+ _WebSocket3 = WebSocket;
+} catch {
+}
+function useWebSocketImplementation(websocketImplementation) {
+ _WebSocket3 = websocketImplementation;
+}
+var SimplePool = class extends AbstractSimplePool {
+ constructor() {
+ super({ verifyEvent: verifyEvent2, websocketImplementation: _WebSocket3 });
+ }
+};
+
+// node_modules/ws/wrapper.mjs
+var import_stream = __toESM(require_stream(), 1);
+var import_receiver = __toESM(require_receiver(), 1);
+var import_sender = __toESM(require_sender(), 1);
+var import_websocket = __toESM(require_websocket(), 1);
+var import_websocket_server = __toESM(require_websocket_server(), 1);
+var wrapper_default = import_websocket.default;
+
+// tools/payment-helper.mjs
+var import_qrcode = __toESM(require_lib(), 1);
+
+// tools/screen-tips.mjs
+function recentScreenTips(events, recipient, provider, now2) {
+ const seen = /* @__PURE__ */ new Set();
+ const tips = [];
+ for (const event of events.slice(0, 100)) {
+ try {
+ if (event.kind !== 9735 || event.pubkey !== provider || !validateEvent(event) || !verifyEvent(event) || !Number.isSafeInteger(event.created_at) || event.created_at <= now2 - 120 || event.created_at > now2 || !event.tags.some((t) => t[0] === "p" && t[1] === recipient)) continue;
+ const description = event.tags.find((t) => t[0] === "description")?.[1];
+ if (!description || description.length > 16e3) continue;
+ const request = JSON.parse(description);
+ if (request.kind !== 9734 || !validateEvent(request) || !verifyEvent(request) || !request.tags.some((t) => t[0] === "p" && t[1] === recipient) || request.tags.some((t) => t[0] === "e")) continue;
+ const msats = Number(request.tags.find((t) => t[0] === "amount")?.[1]);
+ if (!Number.isSafeInteger(msats) || msats < 1e3 || seen.has(request.id)) continue;
+ seen.add(request.id);
+ tips.push({ sats: Math.floor(msats / 1e3), occurred_at: new Date(event.created_at * 1e3).toISOString() });
+ } catch {
+ }
+ }
+ return tips.sort((a, b) => b.occurred_at.localeCompare(a.occurred_at)).slice(0, 30);
+}
+
+// tools/payment-helper.mjs
+useWebSocketImplementation(wrapper_default);
+async function main() {
+ const input = JSON.parse(await new Promise((resolve) => {
+ let value = "";
+ process.stdin.setEncoding("utf8");
+ process.stdin.on("data", (chunk) => value += chunk);
+ process.stdin.on("end", () => resolve(value));
+ }));
+ if (input.action === "create") {
+ const secret = generateSecretKey();
+ const lnurl = import_bech32.bech32.encode("lnurl", import_bech32.bech32.toWords(Buffer.from(input.lnurlUrl, "utf8")), 2e3);
+ const event = finalizeEvent({
+ kind: 9734,
+ created_at: Math.floor(Date.now() / 1e3),
+ content: input.content || `Just Works \xB7 Table ${input.table}`,
+ tags: [["relays", ...input.relays], ["amount", String(input.amountMsat)], ["lnurl", lnurl], ["p", input.recipient]]
+ }, secret);
+ process.stdout.write(JSON.stringify({ event, pubkey: getPublicKey(secret), lnurl }));
+ } else if (input.action === "check") {
+ const pool = new SimplePool();
+ try {
+ const events = await pool.querySync(input.relays, { kinds: [9735], "#p": [input.recipient], since: input.since - 5, limit: 100 }, { maxWait: 1800 });
+ const receipt = events.find((event) => {
+ if (event.pubkey !== input.recipient) return false;
+ const description = event.tags.find((tag) => tag[0] === "description")?.[1];
+ if (!description) return false;
+ try {
+ return JSON.parse(description).pubkey === input.pubkey;
+ } catch {
+ return false;
+ }
+ });
+ process.stdout.write(JSON.stringify({ paid: Boolean(receipt), receipt: receipt?.id || null }));
+ } finally {
+ pool.close(input.relays);
+ }
+ } else if (input.action === "screen-tips") {
+ const decoded = nip19_exports.decode(input.npub);
+ if (decoded.type !== "npub" || !/^[a-f0-9]{64}$/.test(input.provider)) throw new Error("invalid merchant/provider");
+ const now2 = Math.floor(Date.now() / 1e3);
+ const pool = new SimplePool();
+ try {
+ const events = await pool.querySync(input.relays, { kinds: [9735], authors: [input.provider], "#p": [decoded.data], since: now2 - 120, limit: 100 }, { maxWait: 1800 });
+ process.stdout.write(JSON.stringify({ tips: recentScreenTips(events, decoded.data, input.provider, now2) }));
+ } finally {
+ pool.close(input.relays);
+ }
+ } else if (input.action === "latest") {
+ const decoded = nip19_exports.decode(input.npub);
+ if (decoded.type !== "npub") throw new Error("invalid npub");
+ const pool = new SimplePool();
+ try {
+ const events = await pool.querySync(input.relays, { kinds: [1, 30023], authors: [decoded.data], limit: 20 }, { maxWait: 4500 });
+ const event = events.filter((item) => item.content?.trim()).sort((a, b) => b.created_at - a.created_at)[0];
+ process.stdout.write(JSON.stringify({ event: event ? { id: event.id, kind: event.kind, content: event.content, created_at: event.created_at, pubkey: event.pubkey } : null }));
+ } finally {
+ pool.close(input.relays);
+ }
+ } else if (input.action === "qr") {
+ const svg = await import_qrcode.default.toString(input.text, { type: "svg", margin: 1, width: 320, color: { dark: "#0a0a0a", light: "#ffffff" }, errorCorrectionLevel: "M" });
+ process.stdout.write(JSON.stringify({ svg }));
+ } else {
+ throw new Error("unknown action");
+ }
+}
+main().catch((error) => {
+ console.error(error);
+ process.exitCode = 1;
+});
+/*! Bundled license information:
+
+@noble/hashes/esm/utils.js:
+@noble/hashes/esm/utils.js:
+ (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
+
+@noble/curves/esm/abstract/utils.js:
+@noble/curves/esm/abstract/modular.js:
+@noble/curves/esm/abstract/curve.js:
+@noble/curves/esm/abstract/weierstrass.js:
+@noble/curves/esm/_shortw_utils.js:
+@noble/curves/esm/secp256k1.js:
+ (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
+
+@scure/base/lib/esm/index.js:
+ (*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
+
+@noble/ciphers/esm/utils.js:
+ (*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) *)
+*/
diff --git a/docker/justworks/business/public/assets/app-mode.css b/docker/justworks/business/public/assets/app-mode.css
new file mode 100644
index 00000000..7806c119
--- /dev/null
+++ b/docker/justworks/business/public/assets/app-mode.css
@@ -0,0 +1,19 @@
+.app-mode{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap;color:#f7f7f4;font:500 12px/1.4 var(--jw-font-sans,system-ui,sans-serif)}
+.app-mode>button,.app-help-close{appearance:none;border:1px solid #ffffff45;border-radius:999px;background:#101613d9;color:#f7f7f4;min-height:40px;padding:8px 14px;font:inherit;cursor:pointer;white-space:nowrap}
+.app-mode button:hover{border-color:#ff996f;background:#242c27}.app-mode button:focus-visible{outline:3px solid #ff996f;outline-offset:3px}.app-mode button[hidden]{display:none}.app-mode button:disabled{opacity:.6;cursor:wait}
+.app-mode-status:empty{display:none}.app-mode-status{max-width:28em;color:#ffce96;flex-basis:100%;text-align:right}
+.app-install-help{position:fixed;inset:0;margin:auto;width:min(440px,calc(100vw - 32px));max-height:calc(100dvh - 32px);overflow:auto;padding:28px;border:1px solid #ffffff40;border-radius:24px;background:#111914;color:#f7f7f4;font:400 16px/1.6 var(--jw-font-sans,system-ui,sans-serif);text-align:left;box-shadow:0 24px 100px #0009}
+.app-install-help::backdrop{background:#000b;backdrop-filter:blur(6px)}.app-install-help h2{font-size:25px;line-height:1.2;letter-spacing:-.03em;margin:0 0 20px}.app-install-help p{color:#d5dfd8}.app-help-close{font-size:15px;min-width:100px}
+body[data-pwa-app=pos]>.app-mode{display:none}
+.pos-app-controls{position:sticky;top:calc(76px + env(safe-area-inset-top));z-index:10;padding:8px max(24px,env(safe-area-inset-right)) 8px max(24px,env(safe-area-inset-left));background:#080909}
+body[data-pwa-app=pos] .tabs{top:calc(76px + var(--app-toolbar-height,56px) + env(safe-area-inset-top))}
+body[data-pwa-app=pos]{padding-top:calc(76px + env(safe-area-inset-top));padding-bottom:env(safe-area-inset-bottom)}
+body[data-pwa-app=pos] .topbar[data-topbar]{top:env(safe-area-inset-top)!important}
+body[data-pwa-app=pos] .topbar{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto auto;gap:16px}
+body[data-pwa-app=pos] .topbar .jw-login-open{margin:0;justify-self:end}
+.screen-utilities{justify-self:end;display:flex;flex-direction:column;align-items:flex-end;gap:8px;min-width:0}.screen-utilities .app-mode{font-size:12px}.screen-utilities .app-mode>button{min-height:36px;padding:6px 11px}
+.screen-utilities time{white-space:nowrap;flex-shrink:0}
+body[data-pwa-app=screen] .stage{padding-top:max(3vh,env(safe-area-inset-top));padding-right:max(4vw,env(safe-area-inset-right));padding-bottom:max(2vh,env(safe-area-inset-bottom));padding-left:max(4vw,env(safe-area-inset-left))}
+@media(max-width:700px){body[data-pwa-app=pos]{padding-top:calc(64px + env(safe-area-inset-top))}.pos-app-controls{top:calc(64px + env(safe-area-inset-top));padding:8px 12px}body[data-pwa-app=pos] .tabs{top:calc(64px + var(--app-toolbar-height,60px) + env(safe-area-inset-top))}.app-mode>button{min-height:44px}.screen-utilities{align-items:flex-start;justify-self:start;grid-column:1/-1;flex-direction:row;justify-content:space-between;width:100%}.screen-utilities .app-mode{justify-content:flex-end}.screen-utilities .app-mode>button{min-height:40px}.app-mode-status{font-size:11px}.app-install-help{padding:24px}}
+@media print{.app-mode{display:none!important}}
+@media(max-width:700px){body[data-pwa-app=pos] .topbar{grid-template-columns:minmax(0,1fr) auto auto;gap:10px;padding-inline:12px}body[data-pwa-app=pos] .topbar .merchant{display:none}body[data-pwa-app=pos] .brand small{display:none}body[data-pwa-app=pos] .topbar .jw-login-open{min-height:40px}}
diff --git a/docker/justworks/business/public/assets/app-mode.js b/docker/justworks/business/public/assets/app-mode.js
new file mode 100644
index 00000000..051e4ee5
--- /dev/null
+++ b/docker/justworks/business/public/assets/app-mode.js
@@ -0,0 +1,93 @@
+// Shared display controls; credentials, live records and writes never enter storage.
+const app = document.body.dataset.pwaApp;
+const standalone = matchMedia('(display-mode: standalone)');
+const fullscreen = matchMedia('(display-mode: fullscreen)');
+let installed = standalone.matches || fullscreen.matches || navigator.standalone === true;
+let installPrompt;
+const controls = document.createElement('div');
+controls.className = 'app-mode';
+controls.setAttribute('aria-label', `${app === 'pos' ? 'POS' : 'Screen'} app controls`);
+controls.innerHTML = ``;
+const install = controls.querySelector('.app-install');
+const full = controls.querySelector('.app-fullscreen');
+const status = controls.querySelector('.app-mode-status');
+const help = controls.querySelector('dialog');
+const manifest = document.querySelector('link[rel="manifest"]');
+const npub = new URLSearchParams(location.search).get('npub');
+// Manifest endpoint validates checksum. Never carry login tokens or fragments.
+if (npub && /^npub1[023456789acdefghjklmnpqrstuvwxyz]{58}$/.test(npub)) {
+ manifest.href = `/${app}.webmanifest?npub=${encodeURIComponent(npub)}`;
+}
+function syncInstall() {
+ install.hidden = installed;
+ install.textContent = installPrompt ? 'Install app' : 'Install guide';
+}
+function syncFullscreen() {
+ const active = Boolean(document.fullscreenElement || document.webkitFullscreenElement);
+ full.textContent = active ? 'Exit fullscreen' : 'Fullscreen';
+ full.setAttribute('aria-pressed', String(active));
+ full.title = active ? 'Exit fullscreen (Esc)' : 'Enter fullscreen';
+}
+function syncConnection() {
+ status.textContent = navigator.onLine ? '' : 'Offline · live updates unavailable';
+ controls.classList.toggle('is-offline', !navigator.onLine);
+}
+window.addEventListener('beforeinstallprompt', event => {
+ event.preventDefault();
+ installPrompt = event;
+ syncInstall();
+});
+window.addEventListener('appinstalled', () => {
+ installed = true;
+ installPrompt = undefined;
+ syncInstall();
+ status.textContent = 'App installed';
+});
+standalone.addEventListener('change', () => {installed = standalone.matches || navigator.standalone === true; syncInstall();});
+install.addEventListener('click', async () => {
+ if (installPrompt) {
+ const prompt = installPrompt;
+ installPrompt = undefined;
+ install.disabled = true;
+ try {
+ await prompt.prompt();
+ const choice = await prompt.userChoice;
+ if (choice.outcome === 'accepted') status.textContent = 'Installation requested';
+ } catch {status.textContent = 'Use your browser menu to install this app.';}
+ finally {install.disabled = false; syncInstall();}
+ return;
+ }
+ const ios = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
+ help.querySelector('.app-install-instructions').textContent = ios
+ ? 'In Safari, tap Share → Add to Home Screen, then enable Open as Web App if shown.'
+ : 'Open your browser menu and choose Install app or Add to Home Screen. If it is not offered, use a browser that supports web app installation.';
+ help.showModal();
+});
+help.querySelector('.app-help-close').addEventListener('click', () => help.close());
+help.addEventListener('click', event => {if (event.target === help) {const r = help.getBoundingClientRect(); if (event.clientX < r.left || event.clientX > r.right || event.clientY < r.top || event.clientY > r.bottom) help.close();}});
+full.addEventListener('click', async () => {
+ const active = document.fullscreenElement || document.webkitFullscreenElement;
+ const action = active ? (document.exitFullscreen || document.webkitExitFullscreen) : (document.documentElement.requestFullscreen || document.documentElement.webkitRequestFullscreen);
+ if (!action) {status.textContent = 'Fullscreen is unavailable in this browser. Install the app for a standalone view.'; return;}
+ try {await action.call(active ? document : document.documentElement); syncFullscreen(); status.textContent = '';}
+ catch {status.textContent = 'Fullscreen could not open. Try again or use your browser fullscreen command.';}
+});
+document.addEventListener('fullscreenchange', syncFullscreen);
+document.addEventListener('webkitfullscreenchange', syncFullscreen);
+document.addEventListener('fullscreenerror', () => {status.textContent = 'Fullscreen is unavailable right now.'; syncFullscreen();});
+window.addEventListener('online', syncConnection);
+window.addEventListener('offline', syncConnection);
+syncInstall(); syncFullscreen(); syncConnection();
+
+// Dedicated production origins only: a localhost multi-surface server must not
+// install competing root-scope workers. Tests use separate secure origins.
+if (location.hostname === `${app}.justworks.cash` && 'serviceWorker' in navigator) {
+ navigator.serviceWorker.register(`/${app}-sw.js`, {scope: '/', updateViaCache: 'none'})
+ .catch(() => {install.title = 'Installation may be unavailable; the live website still works.';});
+}
+export function mountAppControls(host) {
+ host.append(controls);
+ if (app === 'pos' && 'ResizeObserver' in window) {
+ new ResizeObserver(() => document.body.style.setProperty('--app-toolbar-height', `${host.getBoundingClientRect().height}px`)).observe(host);
+ }
+}
diff --git a/docker/justworks/business/public/assets/app.css b/docker/justworks/business/public/assets/app.css
new file mode 100644
index 00000000..a9933478
--- /dev/null
+++ b/docker/justworks/business/public/assets/app.css
@@ -0,0 +1 @@
+:root{color-scheme:light;--bg:var(--jw-bg,#fafafa);--panel:var(--jw-surface,#fafafa);--soft:var(--jw-surface-sunken,#f2f4f3);--line:var(--jw-line,rgba(10,10,10,.1));--line-strong:var(--jw-line-strong,rgba(10,10,10,.2));--text:var(--jw-text-primary,#0a0a0a);--body:var(--jw-text-body,#454545);--muted:var(--jw-text-muted,#737373);--accent:var(--jw-accent,#f4511e);--green:var(--jw-success,#08806b);--gold:var(--jw-highlight,#ffcc4d);font-family:var(--jw-font-sans,"Geist Variable",Inter,system-ui,sans-serif)}*{box-sizing:border-box}html{min-height:100%;background:var(--bg)}body{min-height:100vh;margin:0;background:var(--jw-bg-gradient,linear-gradient(180deg,#fafafa,#e9ebea));color:var(--text)}button,input,textarea{font:inherit}.shell{width:min(1240px,calc(100% - 40px));margin:auto;padding:24px 0 70px}.top{min-height:72px;display:flex;justify-content:space-between;gap:20px;align-items:center;margin-bottom:clamp(36px,7vw,80px)}.brand{display:flex;align-items:center;gap:12px;font-weight:900;font-size:17px;letter-spacing:-.02em}.brand small{display:block;color:var(--muted);font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase}.hero-copy{margin-bottom:34px}.eyebrow{margin:0;color:var(--accent);text-transform:uppercase;letter-spacing:.16em;font-size:11px;font-weight:900}.muted{color:var(--muted)}h1,h2{font-family:var(--jw-font-display,"Syne Variable",system-ui,sans-serif);font-synthesis:none}h1{max-width:850px;font-size:clamp(44px,7vw,88px);line-height:.92;letter-spacing:-.055em;margin:12px 0 18px;font-weight:650}.hero-copy>p:last-child{max-width:650px;color:var(--body);font-size:18px;line-height:1.55}.grid{display:grid;grid-template-columns:minmax(0,.9fr) minmax(360px,1.35fr);gap:16px}.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--jw-radius-lg,24px);padding:clamp(20px,3vw,30px);box-shadow:var(--jw-shadow-sm,0 8px 22px rgba(0,0,0,.045))}.card h2{margin:7px 0 4px;font-size:clamp(25px,3vw,36px);letter-spacing:-.04em}.switchrow,.row,.orderhead{display:flex;justify-content:space-between;align-items:center;gap:14px}.switch{position:relative;width:54px;height:30px;margin:0;flex:none}.switch input{opacity:0}.switch span{position:absolute;inset:0;background:#c9cecb;border-radius:99px;cursor:pointer;box-shadow:inset 0 0 0 1px var(--line-strong)}.switch span:after{content:"";position:absolute;width:22px;height:22px;left:4px;top:4px;border-radius:50%;background:#fafafa;transition:.2s;box-shadow:0 2px 5px rgba(0,0,0,.18)}.switch input:checked+span{background:var(--green)}.switch input:checked+span:after{transform:translateX(24px)}label{display:block;color:var(--muted);font-size:12px;font-weight:800;margin:20px 0 7px;text-transform:uppercase;letter-spacing:.06em}input,textarea{width:100%;background:var(--soft);border:1px solid var(--line);border-radius:12px;padding:12px 13px;color:var(--text);outline:none}input:focus,textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--jw-accent-ring,rgba(244,81,30,.18))}.products{display:grid;gap:8px}.productedit{display:grid;grid-template-columns:1fr 100px;gap:8px}.button{border:1px solid var(--text);border-radius:999px;padding:11px 18px;font-weight:850;cursor:pointer;background:var(--text);color:var(--bg);transition:transform .15s ease}.button:hover{transform:translateY(-1px)}.button.secondary{background:transparent;color:var(--text);border-color:var(--line-strong)}.button.small{padding:7px 11px;font-size:12px}.orders{display:grid;gap:10px;margin-top:18px}.order{border:1px solid var(--line);border-radius:15px;padding:16px;background:var(--soft)}.order[data-status=closed]{opacity:.55}.badge{display:inline-flex;align-items:center;border:1px solid transparent;border-radius:99px;padding:6px 10px;font-size:10px;font-weight:850;text-transform:uppercase;letter-spacing:.05em;background:color-mix(in srgb, var(--gold) 20%, var(--panel));color:color-mix(in srgb, var(--gold) 65%, var(--text))}.order[data-status=accepted] .badge{background:color-mix(in srgb, var(--jw-info,#2764ff) 18%, var(--panel));color:var(--jw-info,#2764ff)}.order[data-status=delivered] .badge{background:color-mix(in srgb, var(--green) 20%, var(--panel));color:var(--green)}.order[data-status=closed] .badge{background:var(--soft);color:var(--muted)}.items{font-size:18px;font-weight:850;margin:12px 0}.actions{display:flex;gap:7px;flex-wrap:wrap}.empty{padding:60px 24px;text-align:center;border:1px dashed var(--line-strong);border-radius:15px;color:var(--muted)}.demo-links{display:flex;gap:8px;flex-wrap:wrap}.demo-links a{color:var(--text);border:1px solid var(--line-strong);padding:9px 14px;border-radius:99px;text-decoration:none;font-size:13px;font-weight:750;background:var(--panel)}.table-destination{margin-top:24px;padding-top:20px;border-top:1px solid var(--line)}#tableUrl{word-break:break-all;margin-top:8px;font-size:12px;color:var(--body)}.toast{position:fixed;right:20px;bottom:20px;background:var(--green);color:#fff;padding:12px 18px;border-radius:12px;font-weight:800;opacity:0;transform:translateY(10px);transition:.2s}.toast.show{opacity:1;transform:none}@media(prefers-color-scheme:dark){:root{color-scheme:dark}}@media(max-width:800px){.shell{width:min(100% - 28px,1240px)}.grid{grid-template-columns:1fr}.top{align-items:flex-start;flex-direction:column;margin-bottom:40px}.hero-copy>p:last-child{font-size:16px}.demo-links{width:100%}.demo-links a{flex:1;text-align:center}}
diff --git a/docker/justworks/business/public/assets/archipelago-paths.js b/docker/justworks/business/public/assets/archipelago-paths.js
new file mode 100644
index 00000000..58f44409
--- /dev/null
+++ b/docker/justworks/business/public/assets/archipelago-paths.js
@@ -0,0 +1,10 @@
+// Keep the unchanged Business UI's API requests in its isolated app namespace.
+const businessFetch = window.fetch.bind(window);
+window.fetch = (input, init) => {
+ const url = new URL(input instanceof Request ? input.url : input, location.href);
+ if (url.origin === location.origin && url.pathname.startsWith('/api/')) {
+ url.pathname = '/business-demo' + url.pathname;
+ input = input instanceof Request ? new Request(url, input) : url;
+ }
+ return businessFetch(input, init);
+};
diff --git a/docker/justworks/business/public/assets/book.css b/docker/justworks/business/public/assets/book.css
new file mode 100644
index 00000000..9200ece5
--- /dev/null
+++ b/docker/justworks/business/public/assets/book.css
@@ -0,0 +1,3 @@
+:root{--orange:#ff4f1f;--black:#080808;--ink:#0d0d0d;--muted:#747873;--line:#d3d6d2;--soft:#eff1ee;font-family:var(--jw-font-sans,"Geist Variable",Inter,system-ui,sans-serif)}*{box-sizing:border-box}html,body{min-height:100%;margin:0;background:var(--black)}button,input{font:inherit}.visual{position:relative;min-height:160px;padding:18px 20px 24px;display:flex;flex-direction:column;color:#fff;background:#111 var(--hero,linear-gradient(135deg,#252525,#090909)) center/cover}.wash{position:absolute;inset:0;background:linear-gradient(0deg,rgba(0,0,0,.88),rgba(0,0,0,.2)),linear-gradient(90deg,rgba(0,0,0,.75),transparent)}nav,.identity{position:relative;z-index:1}nav{display:flex;justify-content:space-between;align-items:center}nav a{color:#fff;text-decoration:none;font-size:14px;font-weight:900}nav small{font-size:8px;font-weight:900;letter-spacing:.15em;text-transform:uppercase}.identity{margin-top:auto}.identity p,.eyebrow{margin:0;color:var(--orange);font-size:10px;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.identity h1{margin:15px 0 0;font-family:var(--jw-font-display,"Syne Variable");font-size:clamp(34px,11vw,48px);line-height:.85;letter-spacing:-.06em}.identity>span{display:none}.booking{min-height:calc(100dvh - 160px);padding:26px 20px max(24px,env(safe-area-inset-bottom));background:#fff}form{max-width:560px;margin:auto}h2{max-width:500px;margin:9px 0 25px;font-family:var(--jw-font-display,"Syne Variable");font-size:clamp(38px,11vw,54px);font-weight:620;line-height:.92;letter-spacing:-.055em}.mode{display:grid;grid-template-columns:1fr 1fr;margin-bottom:18px;padding:4px;border-radius:12px;background:var(--soft)}.mode button,.soon button{min-height:47px;border:0;border-radius:9px;background:transparent;color:var(--muted);font-weight:850}.mode button.active,.soon button.active{background:var(--black);color:#fff}.booking label,#when>label{display:block;margin:17px 0 7px;color:var(--muted);font-size:10px;font-weight:900;letter-spacing:.1em;text-transform:uppercase}.booking label small{font-weight:600}.booking input{width:100%;min-height:51px;padding:14px;border:1px solid var(--line);border-radius:11px;background:var(--soft);color:var(--ink);outline:none}.booking input:focus{border-color:var(--orange);box-shadow:0 0 0 3px rgba(255,79,31,.14)}.soon{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}.soon button{border:1px solid var(--line);font-size:13px}.guests{display:grid;grid-template-columns:55px 1fr 55px;align-items:center;min-height:57px;border:1px solid var(--line);border-radius:11px;background:var(--soft)}.guests button{height:100%;border:0;background:transparent;font-size:24px}.guests strong{text-align:center;font-size:22px}#submit{width:100%;min-height:58px;display:flex;justify-content:space-between;align-items:center;margin-top:23px;padding:0 18px;border:0;border-radius:11px;background:var(--orange);color:#fff;font-weight:900}.privacy{text-align:center;color:var(--muted);font-size:9px}.loading,.failure,.confirmed{min-height:100vh;display:grid;place-content:center;text-align:center;padding:28px;background:var(--black);color:#fff}.loading>span,.failure>span,.confirmed>span{font-size:70px}.failure h1,.confirmed h1{max-width:800px;margin:18px auto;font-family:var(--jw-font-display,"Syne Variable");font-size:clamp(45px,8vw,90px);line-height:.9}.failure small,.confirmed>small{color:#888}.confirmed>span{width:90px;height:90px;display:grid;place-items:center;margin:0 auto 24px;border-radius:50%;background:#16806a;font-size:44px}.confirmed>p:not(.eyebrow){max-width:620px;color:#bbb;font-size:17px;line-height:1.6}
+@media(min-width:760px){body{padding:24px}.visual,.booking{min-height:min(780px,calc(100dvh - 48px))}#app:has(.visual){display:grid;grid-template-columns:minmax(330px,44%) minmax(430px,56%);width:min(1180px,100%);margin:auto}.visual{padding:28px 34px 40px;border-radius:28px 0 0 28px}.identity p{font-size:11px}.identity h1{font-size:clamp(58px,6vw,88px)}.identity>span{display:block;max-width:330px;margin-top:20px;color:#ccc}.booking{display:grid;align-items:center;padding:44px clamp(40px,5vw,72px);border-radius:0 28px 28px 0}h2{font-size:clamp(48px,4.6vw,66px)}}
+@media(max-width:410px){.visual{min-height:145px}.booking{min-height:calc(100dvh - 145px);padding-top:22px}h2{font-size:37px}.soon button{font-size:12px}}
diff --git a/docker/justworks/business/public/assets/book.js b/docker/justworks/business/public/assets/book.js
new file mode 100644
index 00000000..f9743c06
--- /dev/null
+++ b/docker/justworks/business/public/assets/book.js
@@ -0,0 +1,13 @@
+import {frame} from './ds/frame.js';
+import {npubFrom} from './ds/env.js';
+const app=document.querySelector('#app'),npub=npubFrom();let merchant,mode='now',delay=0,guests=2,busy=false;
+const esc=value=>String(value??'').replace(/[&<>"']/g,char=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[char]));
+function timeValue(offsetMinutes){const date=new Date(Date.now()+offsetMinutes*60000);date.setMinutes(Math.ceil(date.getMinutes()/30)*30,0,0);return `${date.getFullYear()}-${String(date.getMonth()+1).padStart(2,'0')}-${String(date.getDate()).padStart(2,'0')}T${String(date.getHours()).padStart(2,'0')}:${String(date.getMinutes()).padStart(2,'0')}`}
+function error(message){app.innerHTML=`⌁
Table booking
${esc(message)}
Use book.justworks.cash/?npub=npub1…`}
+function render(data){merchant=data.merchant;document.title=`Book ${merchant.name} · Just Works`;frame(app,{label:'Bookings',surface:'book',html:`
Reserve a table
When should we expect you?
Your table at ${esc(merchant.name)}, without the phone call.
`});document.querySelectorAll('[data-mode]').forEach(button=>button.onclick=()=>setMode(button.dataset.mode));document.querySelector('#less').onclick=()=>setGuests(guests-1);document.querySelector('#more').onclick=()=>setGuests(guests+1);document.querySelector('#form').onsubmit=submit;renderWhen()}
+function setMode(next){mode=next;document.querySelectorAll('[data-mode]').forEach(button=>button.classList.toggle('active',button.dataset.mode===mode));renderWhen()}
+function setGuests(next){guests=Math.max(1,Math.min(20,next));document.querySelector('#guestCount').textContent=guests}
+function renderWhen(){const host=document.querySelector('#when');if(mode==='now'){host.innerHTML=``;host.querySelectorAll('[data-delay]').forEach(button=>button.onclick=()=>{delay=Number(button.dataset.delay);renderWhen()})}else host.innerHTML=``}
+async function submit(event){event.preventDefault();if(busy)return;busy=true;const button=document.querySelector('#submit');button.disabled=true;button.firstChild.textContent='Sending… ';try{const scheduled=mode==='now'?new Date(Date.now()+delay*60000):new Date(document.querySelector('#date').value);const response=await fetch('/api/bookings',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({npub,name:document.querySelector('#name').value,notes:document.querySelector('#notes').value,guests,mode,scheduled_at:scheduled.toISOString()})});const result=await response.json();if(!response.ok)throw new Error(result.error||'Could not book');confirm(result)}catch(error){button.disabled=false;button.firstChild.textContent='Try again ';alert(error.message)}finally{busy=false}}
+function confirm(result){const date=new Date(result.scheduled_at);frame(app,{label:'Bookings',surface:'book',html:`✓
Request sent
Table for ${result.guests} requested.
${esc(merchant.name)} received your booking for ${date.toLocaleDateString([],{weekday:'long',day:'numeric',month:'long'})} at ${date.toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'})}.
The merchant still needs to confirm it. Keep this screen open for your reference.`})}
+if(!npub)error('Add the merchant npub to book.');else fetch(`/api/order-merchant?npub=${encodeURIComponent(npub)}`,{cache:'no-store'}).then(async response=>{const data=await response.json();if(!response.ok)throw new Error(data.error);render(data)}).catch(reason=>error(reason.message||'Merchant unavailable'));
diff --git a/docker/justworks/business/public/assets/business-deps.css b/docker/justworks/business/public/assets/business-deps.css
new file mode 100644
index 00000000..25f8542e
--- /dev/null
+++ b/docker/justworks/business/public/assets/business-deps.css
@@ -0,0 +1,4 @@
+.module.needs-setup{border-color:#d4d4cf;background:#e8e8e4;color:#696965}
+.module.needs-setup .module-icon{background:#aaa}
+.module.needs-setup .module-actions>a{max-width:76%;color:#111;pointer-events:auto}
+.setup-lock{color:#999;font-size:9px;font-weight:850;letter-spacing:.1em;text-transform:uppercase}
diff --git a/docker/justworks/business/public/assets/business-destinations.js b/docker/justworks/business/public/assets/business-destinations.js
new file mode 100644
index 00000000..cdb15d75
--- /dev/null
+++ b/docker/justworks/business/public/assets/business-destinations.js
@@ -0,0 +1,72 @@
+import { link, base } from './ds/frame.js';
+import { prod } from './ds/env.js';
+import { moduleQrUrl } from './module-qr.js?v=2';
+
+// The dashboard and the printable master use one destination catalog.
+export const freeDefinitions = [
+ ['justworks', 'Just Works page', 'Your public merchant page', 'JW'],
+ ['tip', 'Tip', 'Bitcoin tips and community wall', '⚡'],
+ ['nsite', 'nsite', 'Your site on Nostr', 'NS'],
+ ['nostr', 'Nostr profile', 'Your signed identity', 'NP'],
+ ['maps', 'Maps', 'Find your place on the map', '⌖'],
+ ['gallery', 'Gallery', 'Photos and discovery', '□'],
+];
+export const businessDefinitions = [
+ ['pos', 'POS', 'Run orders and payments', 'Counter view', '↗', false],
+ ['order', 'Order', 'Order to table', 'Customer', '+', true],
+ ['pay', 'Pay Bill', 'Settle an open order', 'Customer', '€', true],
+ ['payandgo', 'Just Pay', 'Pay a paper receipt', 'Customer', '₿', true],
+ ['booking', 'Bookings', 'Tables now or later', 'Customer', '⌁', true, 'book'],
+ ['screen', 'Screen', 'Merchant media display', '4K display', '▣', true],
+ ['stats', 'Stats', 'Audience, actions and revenue', 'Merchant view', '↗', true, 'business'],
+ ['events', 'Events', 'Merchant Nostr events', 'Coming soon', '◌', true],
+];
+
+export function businessUrl(npub, sheet = false) {
+ const path = sheet ? '/qr-sheet' : prod ? '/' : '/dashboard';
+ return `${prod ? 'https://business.justworks.cash' : location.origin + base}${path}?npub=${encodeURIComponent(npub)}`;
+}
+
+export function moduleDestination(definition, data, npub) {
+ const [id, , , , , configurable, target = id] = definition;
+ const state = data.modules?.[id] || {};
+ const paymentSetup = ['pay', 'payandgo'].includes(id) && !data.payment_ready;
+ const disabled = id === 'events' || state.status === 'coming-soon' || paymentSetup;
+ const url = paymentSetup
+ ? `${base}/profile?npub=${encodeURIComponent(npub)}#lightning`
+ : id === 'stats'
+ ? `${prod ? 'https://business.justworks.cash' : base}/stats?npub=${encodeURIComponent(npub)}`
+ : prod ? `https://${target}.justworks.cash/?npub=${encodeURIComponent(npub)}` : link(target);
+ return {state, paymentSetup, disabled, url,
+ qrUrl: disabled ? '' : moduleQrUrl(url, npub),
+ available: !disabled && (!configurable || !!state.enabled)};
+}
+
+export function sheetDestinations(data, npub) {
+ return [
+ {id: 'business', title: 'Business dashboard', url: businessUrl(npub)},
+ ...freeDefinitions.filter(([id]) => data.links?.[id] && data.links[id] !== '#')
+ .map(([id, title]) => ({id, title, url: data.links[id]})),
+ ...businessDefinitions.flatMap(definition => {
+ const destination = moduleDestination(definition, data, npub);
+ return destination.available ? [{id: definition[0], title: definition[1], url: destination.qrUrl}] : [];
+ }),
+ ];
+}
+
+// Verify the Bech32 checksum and the 32-byte public-key payload, without a CDN.
+export function validNpub(value) {
+ if (!/^npub1[023456789acdefghjklmnpqrstuvwxyz]{58}$/.test(value || '')) return false;
+ const alphabet = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
+ const words = [...value.slice(5)].map(char => alphabet.indexOf(char));
+ let checksum = 1;
+ const expanded = [...'npub'].map(char => char.charCodeAt(0) >> 5)
+ .concat(0, [...'npub'].map(char => char.charCodeAt(0) & 31), words);
+ const generators = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
+ for (const word of expanded) {
+ const top = checksum >>> 25;
+ checksum = ((checksum & 0x1ffffff) << 5) ^ word;
+ for (let bit = 0; bit < 5; bit++) if ((top >>> bit) & 1) checksum ^= generators[bit];
+ }
+ return checksum === 1 && (words[51] & 15) === 0;
+}
diff --git a/docker/justworks/business/public/assets/business-sso.css b/docker/justworks/business/public/assets/business-sso.css
new file mode 100644
index 00000000..38bbde73
--- /dev/null
+++ b/docker/justworks/business/public/assets/business-sso.css
@@ -0,0 +1,2 @@
+.exchange {max-width:36rem; margin:2rem auto; padding:1.5rem; font:1rem/1.5 system-ui,sans-serif; overflow-wrap:anywhere}
+.exchange h1 {font-size:1.6rem}.exchange button {padding:.8rem 1rem; margin:.3rem; min-height:44px; cursor:pointer}.exchange button:disabled {cursor:default; opacity:.6}.exchange :focus-visible {outline:3px solid #e99a30; outline-offset:3px}.jw-session-transfer {padding:.75rem; margin-bottom:1rem; width:100%; cursor:pointer}
diff --git a/docker/justworks/business/public/assets/business-sso.js b/docker/justworks/business/public/assets/business-sso.js
new file mode 100644
index 00000000..0fec0999
--- /dev/null
+++ b/docker/justworks/business/public/assets/business-sso.js
@@ -0,0 +1,64 @@
+// Business-only session transfer. Identity verification remains with Core/Keys/Login.
+export async function post(path, body) {
+ const response = await fetch(path, {method:'POST', credentials:'same-origin', cache:'no-store', headers:{'Content-Type':'application/json'}, body:JSON.stringify(body)});
+ const result = await response.json();
+ if (!response.ok) throw new Error(result.error || 'Please log in and try again.');
+ return result;
+}
+
+export async function transferSession(npub, status) {
+ const popup = window.open('about:blank', 'justworks-session', 'popup,width=560,height=680');
+ if (!popup) throw new Error('Allow the login window, or use the login form below.');
+ let remove = () => {};
+ try {
+ status.textContent = 'Confirm access in the Business login window…';
+ const pending = await post('/api/business-sso/start', {npub, return_path:location.pathname + location.search});
+ await new Promise((resolve, reject) => {
+ let busy = false;
+ const timeout = setTimeout(() => { remove(); reject(new Error('Login window expired. Please try again.')); }, 180000);
+ const onMessage = async event => {
+ if (busy || event.origin !== pending.source_origin || event.source !== popup || event.data?.type !== 'justworks-session' || event.data.request_id !== pending.request_id) return;
+ busy = true;
+ try {
+ await post('/api/business-sso/complete', {request_id:pending.request_id, code:event.data.code});
+ remove(); resolve();
+ } catch (error) { remove(); reject(error); }
+ };
+ remove = () => { clearTimeout(timeout); window.removeEventListener('message', onMessage); };
+ window.addEventListener('message', onMessage);
+ popup.location = pending.authorize_url;
+ });
+ status.textContent = 'Business session connected.';
+ // Keep the existing URL and fragment; no server-provided redirect is followed.
+ location.reload();
+ } finally { remove(); if (!popup.closed) popup.close(); }
+}
+
+if (location.pathname.endsWith('/business-sso')) {
+ const requestId = location.hash.slice(1);
+ history.replaceState(null, '', location.pathname + location.search);
+ const status = document.querySelector('#exchange-status');
+ const destination = document.querySelector('#exchange-destination');
+ const approve = document.querySelector('#exchange-approve');
+ async function details() {
+ approve.disabled = true;
+ try {
+ const result = await post('/api/business-sso/details', {request_id:requestId});
+ destination.textContent = new URL(result.audience).hostname;
+ status.textContent = 'Your verified Business login will be used for this site only.';
+ approve.disabled = !window.opener;
+ if (!window.opener) status.textContent = 'Start session transfer from the site you want to open.';
+ } catch (error) { status.textContent = 'Use Login above, then confirm access. ' + error.message; }
+ }
+ approve.addEventListener('click', async () => {
+ approve.disabled = true;
+ try {
+ const result = await post('/api/business-sso/approve', {request_id:requestId});
+ window.opener.postMessage({type:'justworks-session', request_id:requestId, code:result.code}, result.audience);
+ status.textContent = 'Access confirmed. Return to your original window.';
+ } catch (error) { status.textContent = error.message; }
+ });
+ document.querySelector('#exchange-cancel').onclick = () => window.close();
+ window.addEventListener('jw-session-changed', details);
+ details();
+}
diff --git a/docker/justworks/business/public/assets/business.css b/docker/justworks/business/public/assets/business.css
new file mode 100644
index 00000000..b2e1f588
--- /dev/null
+++ b/docker/justworks/business/public/assets/business.css
@@ -0,0 +1,7 @@
+:root{--orange:#ff4f1f;--black:#080808;--ink:#101010;--muted:#777;--line:#deded9;font-family:var(--jw-font-sans,"Geist Variable",Inter,system-ui,sans-serif)}*{box-sizing:border-box}html{background:var(--black)}body{min-height:100vh;margin:0;background:#f5f5f1;color:var(--ink)}a{color:inherit}.top{position:fixed;top:0;left:0;right:0;z-index:40;height:76px;display:flex;align-items:center;justify-content:space-between;padding:0 clamp(18px,4vw,56px);background:transparent;border-bottom:1px solid transparent;color:#fff;transition:background .3s ease,border-color .3s ease}.top.is-scrolled{border-bottom-color:rgba(255,255,255,.09);background:linear-gradient(180deg,rgba(8,8,8,.72),rgba(8,8,8,.45));backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.brand{display:flex;align-items:center;gap:11px;text-decoration:none;font-size:16px;font-weight:900}.brand [data-logo]{width:26px;display:block}.brand i{width:25px;height:25px;display:grid;place-items:center;border:1px solid #fff;font-style:normal}.brand b{font-size:16px;font-weight:900}.brand small{display:inline;font-size:16px;font-weight:900;color:inherit;letter-spacing:0;text-transform:none}.brand small:before{content:"·";color:#90908d;margin:0 9px}.profile{margin-left:auto;padding:9px 13px;border:1px solid #393939;border-radius:99px;text-decoration:none;font-size:11px;font-weight:800}.merchant{position:relative;min-height:clamp(330px,48vw,610px);display:flex;align-items:flex-end;padding:clamp(24px,5vw,68px);overflow:hidden;color:#fff;background:#111 var(--hero,linear-gradient(135deg,#252525,#090909)) center/cover}.merchant-wash{position:absolute;inset:0;background:linear-gradient(0deg,rgba(0,0,0,.93),rgba(0,0,0,.12) 75%),linear-gradient(90deg,rgba(0,0,0,.5),transparent)}.merchant-copy,.merchant-stats{position:relative;z-index:1}.merchant-copy{max-width:850px}.merchant-copy p,.eyebrow{margin:0;color:var(--orange);font-size:10px;font-weight:900;letter-spacing:.17em;text-transform:uppercase}.merchant-copy h1{max-width:900px;margin:14px 0 20px;font-family:var(--jw-font-display,"Syne Variable",system-ui);font-size:clamp(54px,10vw,140px);font-weight:620;line-height:.78;letter-spacing:-.065em}.merchant-copy>span{color:#d1d1ce;font-size:clamp(14px,2vw,18px)}.merchant-stats{display:flex;align-items:stretch;gap:8px;margin-left:auto}.merchant-stats>div,.merchant-stats>a{min-width:120px;display:flex;flex-direction:column;justify-content:flex-end;padding:16px;border:1px solid rgba(255,255,255,.22);background:rgba(0,0,0,.45);backdrop-filter:blur(12px);text-decoration:none}.merchant-stats strong{font-size:28px}.merchant-stats span{color:#aeadab;font-size:10px;text-transform:uppercase}.merchant-stats>a{justify-content:space-between;background:var(--orange);border-color:var(--orange);font-size:13px;font-weight:900}.merchant-stats b{text-align:right;font-size:20px}.modules-head{display:flex;justify-content:space-between;gap:40px;align-items:end;padding:clamp(46px,7vw,92px) clamp(18px,4vw,56px) 30px}.modules-head h2{max-width:760px;margin:10px 0 0;font-family:var(--jw-font-display,"Syne Variable");font-size:clamp(38px,6vw,78px);font-weight:620;line-height:.9;letter-spacing:-.055em}.modules-head>p{max-width:390px;margin:0;color:#686864;line-height:1.55}.modules{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;padding:0 clamp(18px,4vw,56px) clamp(60px,8vw,110px)}.module{min-height:290px;display:flex;flex-direction:column;justify-content:space-between;padding:22px;border:1px solid var(--line);background:#fff;transition:transform .18s,border-color .18s}.module:hover{transform:translateY(-3px);border-color:#aaa}.module-top,.module-actions{display:flex;justify-content:space-between;align-items:center;gap:12px}.module-icon{width:45px;height:45px;display:grid;place-items:center;background:var(--black);color:#fff;font-size:19px;font-weight:900}.module-audience,.always{color:#858580;font-size:9px;font-weight:850;letter-spacing:.1em;text-transform:uppercase}.module h2{margin:0 0 9px;font-family:var(--jw-font-display,"Syne Variable");font-size:36px;letter-spacing:-.05em}.module p{margin:0;color:#72726e;font-size:14px}.module-actions{padding-top:19px;border-top:1px solid var(--line)}.module-actions>a{font-size:13px;font-weight:900;text-decoration:none}.module-actions>a span{color:var(--orange);margin-left:5px}.switch{position:relative;width:48px;height:28px}.switch input{position:absolute;opacity:0}.switch>span{position:absolute;inset:0;border-radius:99px;background:#d5d5d0;cursor:pointer}.switch>span:after{content:"";position:absolute;left:4px;top:4px;width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:0 2px 5px rgba(0,0,0,.2);transition:.2s}.switch input:checked+span{background:var(--orange)}.switch input:checked+span:after{transform:translateX(20px)}.switch input:disabled+span{cursor:not-allowed;opacity:.5}.module.soon{background:#ededE9}.module.soon .module-icon{background:#aaa}.module.soon .module-actions>a{pointer-events:none;color:#999}footer{display:flex;gap:14px;align-items:center;padding:22px clamp(18px,4vw,56px);background:var(--black);color:#8d8d89;font-size:10px}footer span{text-transform:uppercase;letter-spacing:.12em}footer code{overflow:hidden;text-overflow:ellipsis}.loading,.failure{min-height:100vh;display:grid;place-content:center;text-align:center;padding:25px;background:var(--black);color:#fff}.loading>span,.failure>span{font-size:70px}.failure h1{max-width:760px;margin:16px auto;font-family:var(--jw-font-display,"Syne Variable");font-size:clamp(44px,8vw,90px);line-height:.9}.failure>p:not(.eyebrow){color:#999}.failure form{width:min(520px,90vw);display:flex;margin:28px auto 0}.failure input{min-width:0;flex:1;padding:16px;border:1px solid #333;background:#111;color:#fff}.failure button{border:0;padding:0 18px;background:var(--orange);color:#fff;font-weight:900}.toast{position:fixed;z-index:10;right:18px;bottom:18px;padding:13px 17px;background:#167a62;color:#fff;font-size:12px;font-weight:850;opacity:0;transform:translateY(12px);transition:.2s}.toast.show{opacity:1;transform:none}.toast.error{background:#b22}
+.free-head{background:var(--black);color:#fff}.free-head>p{color:#aaa}.free-links{display:grid;grid-template-columns:repeat(6,1fr);gap:1px;padding:0 clamp(18px,4vw,56px) clamp(62px,7vw,90px);background:var(--black)}.free-link{min-height:180px;display:flex;flex-direction:column;justify-content:space-between;gap:20px;padding:22px;background:#151515;color:#fff;text-decoration:none;transition:background .18s,transform .18s}.free-link:hover{z-index:1;background:#202020;transform:translateY(-3px)}.free-icon{width:42px;height:42px;display:grid;place-items:center;border:1px solid #414141;color:var(--orange);font-size:14px;font-weight:900}.free-link h2{margin:0 0 7px;font-family:var(--jw-font-display,"Syne Variable");font-size:25px;letter-spacing:-.04em}.free-link p{margin:0;color:#8d8d89;font-size:12px}.free-link>b{align-self:flex-end;color:var(--orange);font-size:20px}.business-head{padding-top:clamp(62px,8vw,110px)}
+@media(max-width:1050px){.free-links{grid-template-columns:repeat(3,1fr)}.modules{grid-template-columns:repeat(2,1fr)}.merchant{align-items:flex-end}.merchant-stats{position:absolute;right:24px;top:24px}.merchant-stats>div{display:none}}
+@media(max-width:680px){.top{height:66px}.profile{font-size:10px}.merchant{min-height:380px;padding:24px 18px}.merchant-copy h1{font-size:17vw}.merchant-copy>span{display:block;max-width:280px}.merchant-stats{right:18px;top:18px}.merchant-stats>a{min-width:105px;height:80px;padding:12px}.modules-head{display:block;padding-top:48px}.modules-head>p{margin-top:20px}.free-links{grid-template-columns:1fr 1fr}.free-link{min-height:160px;padding:18px}.free-link:first-child{grid-column:1/-1}.modules{grid-template-columns:1fr}.module{min-height:230px}.failure form{display:grid}.failure button{min-height:52px}}
+@media(max-width:680px){.merchant{min-height:560px;display:flex;flex-direction:column;align-items:stretch;justify-content:flex-end;padding:100px 18px 24px}.merchant-copy{width:100%}.merchant-copy h1{font-size:17vw}.merchant-copy>span{max-width:100%}.merchant-stats{position:relative;inset:auto;width:100%;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px;margin:22px 0 0}.merchant-stats>div{display:flex;min-width:0;min-height:76px;padding:12px}.merchant-stats>a{min-width:0;height:auto;min-height:76px;padding:12px}.merchant-stats strong{font-size:22px}.merchant-stats span{font-size:8px}.merchant-stats>a{font-size:11px}}
+.brand [data-logo]{width:var(--jw-app-icon-size)!important;height:var(--jw-app-icon-size)!important}
+.stats-shortcut{width:38px;height:38px;display:grid;place-items:center;flex:0 0 auto;margin-left:auto;border:1px solid #393939;border-radius:50%;color:#fff;text-decoration:none;transition:background .18s,border-color .18s,transform .18s}.stats-shortcut+.profile{margin-left:0}.stats-shortcut svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round}.stats-shortcut:hover{border-color:var(--orange);background:var(--orange);transform:translateY(-1px)}@media(max-width:680px){.stats-shortcut{width:36px;height:36px}.profile{display:none}}
diff --git a/docker/justworks/business/public/assets/business.js b/docker/justworks/business/public/assets/business.js
new file mode 100644
index 00000000..64826f29
--- /dev/null
+++ b/docker/justworks/business/public/assets/business.js
@@ -0,0 +1,89 @@
+import { mountLogo } from "./ds/logo.js";
+import { startNavScroll } from "./ds/header.js";
+import { mountMobileChrome, base } from "./ds/frame.js";
+import { npubFrom, prod } from "./ds/env.js";
+import { qrButton, mountModuleQrs } from "./module-qr.js?v=3";
+import { freeDefinitions, businessDefinitions, moduleDestination, businessUrl } from './business-destinations.js?v=1';
+const app = document.querySelector("#app"),
+ toast = document.querySelector("#toast");
+const npub = npubFrom();
+const esc = (value) =>
+ String(value ?? "").replace(
+ /[&<>"']/g,
+ (char) =>
+ ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[
+ char
+ ],
+ );
+function freeCard([id, name, copy, icon], data) {
+ const url = data.links?.[id] || "#";
+ const qr = url === '#' ? '' : qrButton(id, name, url, {free: true});
+ return `