diff --git a/Dockerfile b/Dockerfile
index 63e832d..9cf40ab 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -5,20 +5,22 @@
FROM golang:1.25-bookworm AS builder
# Install build dependencies
-RUN apt-get update && apt-get install -y --no-install-recommends git make && rm -rf /var/lib/apt/lists/*
+RUN apt-get update && apt-get install -y --no-install-recommends git make ca-certificates && rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /build
-# Copy go mod files
+# Copy go mod files, vendored dependencies, and local nostr clone
COPY go.mod go.sum ./
-RUN go mod download
+COPY vendor/ ./vendor/
+COPY .docker-build-context/ ./docker-build-context/
# Copy source code
COPY . .
-# Build the binary with CGO disabled
-RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o orly -ldflags="-w -s" .
+# Build from vendored code only - completely offline, no network access, no external addresses
+RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
+ go build -mod=vendor -o orly -ldflags="-w -s" .
# Stage 2: Runtime stage
# Use Debian slim instead of Alpine because Debian's libsecp256k1 includes
diff --git a/Dockerfile.with-web b/Dockerfile.with-web
new file mode 100644
index 0000000..1022176
--- /dev/null
+++ b/Dockerfile.with-web
@@ -0,0 +1,74 @@
+# Multi-stage Dockerfile for ORLY relay with embedded web UI
+
+# Stage 1: Web UI build
+FROM node:20-bookworm AS web-builder
+
+WORKDIR /web
+
+# Copy web UI files
+COPY app/web/package.json app/web/package-lock.json* app/web/ ./
+
+# Install dependencies and build
+RUN npm ci && npm run build
+
+# Stage 2: Go build stage
+FROM golang:1.25-bookworm AS builder
+
+# Install build dependencies
+RUN apt-get update && apt-get install -y --no-install-recommends git make && rm -rf /var/lib/apt/lists/*
+
+# Set working directory
+WORKDIR /build
+
+# Copy go mod files
+COPY go.mod go.sum ./
+RUN go mod download
+
+# Copy source code
+COPY . .
+
+# Copy built web UI from web-builder stage
+COPY --from=web-builder /web/dist ./app/web/dist
+
+# Build the binary with CGO disabled
+RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o orly -ldflags="-w -s" .
+
+# Stage 3: Runtime stage
+FROM debian:bookworm-slim
+
+# Install runtime dependencies
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends ca-certificates curl libsecp256k1-1 && \
+ rm -rf /var/lib/apt/lists/*
+
+# Create app user
+RUN groupadd -g 1000 orly && \
+ useradd -m -u 1000 -g orly orly
+
+# Set working directory
+WORKDIR /app
+
+# Copy binary (libsecp256k1.so.1 is already installed via apt)
+COPY --from=builder /build/orly /app/orly
+
+# Create data directory
+RUN mkdir -p /data && chown -R orly:orly /data /app
+
+# Switch to app user
+USER orly
+
+# Expose ports
+EXPOSE 3334
+
+# Health check
+HEALTHCHECK --interval=10s --timeout=5s --start-period=20s --retries=3 \
+ CMD curl -f http://localhost:3334/ || exit 1
+
+# Set default environment variables
+ENV ORLY_LISTEN=0.0.0.0 \
+ ORLY_PORT=3334 \
+ ORLY_DATA_DIR=/data \
+ ORLY_LOG_LEVEL=info
+
+# Run the binary
+ENTRYPOINT ["/app/orly"]
diff --git a/RUN_REMOTE.md b/RUN_REMOTE.md
new file mode 100644
index 0000000..648e222
--- /dev/null
+++ b/RUN_REMOTE.md
@@ -0,0 +1,129 @@
+# Running ORLY Relay Remotely
+
+## Quick Start
+
+### 1. Pull the Image
+```bash
+docker pull silberengel/next-orly:v0.58.5
+```
+
+### 2. Run with Docker Run
+```bash
+docker run -d \
+ --name orly-relay \
+ --restart always \
+ -p 3334:3334 \
+ -v /var/lib/orly:/data \
+ -e ORLY_DATA_DIR=/data \
+ -e ORLY_LISTEN=0.0.0.0 \
+ -e ORLY_PORT=3334 \
+ -e ORLY_LOG_LEVEL=info \
+ silberengel/next-orly:v0.58.5
+```
+
+### 3. Or Use Docker Compose
+
+Create a `docker-compose.yml`:
+```yaml
+version: '3.8'
+
+services:
+ orly-relay:
+ image: silberengel/next-orly:v0.58.5
+ container_name: orly-relay
+ restart: always
+ ports:
+ - "3334:3334"
+ volumes:
+ - /var/lib/orly:/data
+ environment:
+ - ORLY_DATA_DIR=/data
+ - ORLY_LISTEN=0.0.0.0
+ - ORLY_PORT=3334
+ - ORLY_LOG_LEVEL=info
+```
+
+Then run:
+```bash
+docker-compose up -d
+```
+
+## Configuration Options
+
+### Basic Configuration
+- `ORLY_DATA_DIR` - Data directory (default: `/data`)
+- `ORLY_LISTEN` - Listen address (default: `0.0.0.0`)
+- `ORLY_PORT` - Port number (default: `3334`)
+- `ORLY_LOG_LEVEL` - Log level: `debug`, `info`, `warn`, `error`
+
+### Advanced Configuration
+- `ORLY_ADMINS` - Comma-separated list of admin npub keys
+- `ORLY_OWNERS` - Comma-separated list of owner npub keys
+- `ORLY_ACL_MODE` - ACL mode: `open`, `follows`, `managed`
+- `ORLY_SPIDER_MODE` - Spider mode: `off`, `follows`, `all`
+- `ORLY_RELAY_URL` - Public relay URL (for metadata)
+- `ORLY_MAX_CONNECTIONS` - Max concurrent connections (default: 1000)
+- `ORLY_MAX_EVENT_SIZE` - Max event size in bytes (default: 65536)
+
+## Useful Commands
+
+### View Logs
+```bash
+docker logs -f orly-relay
+```
+
+### Stop Container
+```bash
+docker stop orly-relay
+```
+
+### Start Container
+```bash
+docker start orly-relay
+```
+
+### Restart Container
+```bash
+docker restart orly-relay
+```
+
+### Remove Container
+```bash
+docker rm -f orly-relay
+```
+
+### Update to Latest Version
+```bash
+docker pull silberengel/next-orly:v0.58.5
+docker stop orly-relay
+docker rm orly-relay
+# Then run your docker run or docker-compose command again
+```
+
+## Behind a Reverse Proxy
+
+If running behind nginx/Caddy/etc, bind to localhost only:
+```bash
+docker run -d \
+ --name orly-relay \
+ --restart always \
+ -p 127.0.0.1:3334:3334 \
+ -v /var/lib/orly:/data \
+ -e ORLY_DATA_DIR=/data \
+ -e ORLY_LISTEN=0.0.0.0 \
+ -e ORLY_PORT=3334 \
+ silberengel/next-orly:v0.58.5
+```
+
+## Data Persistence
+
+Data is stored in `/var/lib/orly` on the host (or whatever path you mount).
+To backup:
+```bash
+tar -czf orly-backup-$(date +%Y%m%d).tar.gz /var/lib/orly
+```
+
+To restore:
+```bash
+tar -xzf orly-backup-YYYYMMDD.tar.gz -C /
+```
diff --git a/app/web/dist/bundle.js.map b/app/web/dist/bundle.js.map
index d2b8e86..29ce713 100644
--- a/app/web/dist/bundle.js.map
+++ b/app/web/dist/bundle.js.map
@@ -1 +1 @@
-{"version":3,"file":"bundle.js","sources":["../node_modules/svelte/internal/index.mjs","../node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes/esm/_assert.js","../node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes/esm/crypto.js","../node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes/esm/utils.js","../node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes/esm/_sha2.js","../node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes/esm/sha256.js","../node_modules/nostr-tools/node_modules/@noble/curves/esm/abstract/utils.js","../node_modules/nostr-tools/node_modules/@noble/curves/esm/abstract/modular.js","../node_modules/nostr-tools/node_modules/@noble/curves/esm/abstract/curve.js","../node_modules/nostr-tools/node_modules/@noble/curves/esm/abstract/weierstrass.js","../node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes/esm/hmac.js","../node_modules/nostr-tools/node_modules/@noble/curves/esm/_shortw_utils.js","../node_modules/nostr-tools/node_modules/@noble/curves/esm/secp256k1.js","../node_modules/nostr-tools/node_modules/@noble/hashes/esm/crypto.js","../node_modules/nostr-tools/node_modules/@noble/hashes/esm/utils.js","../node_modules/nostr-tools/node_modules/@noble/hashes/esm/_assert.js","../node_modules/nostr-tools/node_modules/@noble/hashes/esm/_sha2.js","../node_modules/nostr-tools/node_modules/@noble/hashes/esm/sha256.js","../node_modules/nostr-tools/lib/esm/pool.js","../node_modules/nostr-tools/node_modules/@scure/base/lib/esm/index.js","../node_modules/@noble/ciphers/esm/_assert.js","../node_modules/@noble/ciphers/esm/utils.js","../node_modules/@noble/ciphers/esm/aes.js","../node_modules/@noble/ciphers/esm/_arx.js","../node_modules/@noble/ciphers/esm/chacha.js","../node_modules/nostr-tools/node_modules/@noble/hashes/esm/hmac.js","../node_modules/nostr-tools/node_modules/@noble/hashes/esm/hkdf.js","../node_modules/nostr-tools/lib/esm/index.js","../node_modules/nostr-tools/lib/esm/kinds.js","../node_modules/tslib/tslib.es6.mjs","../node_modules/rxjs/dist/esm5/internal/util/isFunction.js","../node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js","../node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js","../node_modules/rxjs/dist/esm5/internal/util/arrRemove.js","../node_modules/rxjs/dist/esm5/internal/Subscription.js","../node_modules/rxjs/dist/esm5/internal/config.js","../node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js","../node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js","../node_modules/rxjs/dist/esm5/internal/util/noop.js","../node_modules/rxjs/dist/esm5/internal/util/errorContext.js","../node_modules/rxjs/dist/esm5/internal/Subscriber.js","../node_modules/rxjs/dist/esm5/internal/symbol/observable.js","../node_modules/rxjs/dist/esm5/internal/util/identity.js","../node_modules/rxjs/dist/esm5/internal/Observable.js","../node_modules/rxjs/dist/esm5/internal/util/pipe.js","../node_modules/rxjs/dist/esm5/internal/util/lift.js","../node_modules/rxjs/dist/esm5/internal/operators/OperatorSubscriber.js","../node_modules/rxjs/dist/esm5/internal/util/ObjectUnsubscribedError.js","../node_modules/rxjs/dist/esm5/internal/Subject.js","../node_modules/rxjs/dist/esm5/internal/scheduler/dateTimestampProvider.js","../node_modules/rxjs/dist/esm5/internal/ReplaySubject.js","../node_modules/rxjs/dist/esm5/internal/scheduler/Action.js","../node_modules/rxjs/dist/esm5/internal/scheduler/intervalProvider.js","../node_modules/rxjs/dist/esm5/internal/scheduler/AsyncAction.js","../node_modules/rxjs/dist/esm5/internal/Scheduler.js","../node_modules/rxjs/dist/esm5/internal/scheduler/AsyncScheduler.js","../node_modules/rxjs/dist/esm5/internal/scheduler/async.js","../node_modules/rxjs/dist/esm5/internal/observable/empty.js","../node_modules/rxjs/dist/esm5/internal/util/isScheduler.js","../node_modules/rxjs/dist/esm5/internal/util/args.js","../node_modules/rxjs/dist/esm5/internal/util/isArrayLike.js","../node_modules/rxjs/dist/esm5/internal/util/isPromise.js","../node_modules/rxjs/dist/esm5/internal/util/isInteropObservable.js","../node_modules/rxjs/dist/esm5/internal/util/isAsyncIterable.js","../node_modules/rxjs/dist/esm5/internal/util/throwUnobservableError.js","../node_modules/rxjs/dist/esm5/internal/symbol/iterator.js","../node_modules/rxjs/dist/esm5/internal/util/isIterable.js","../node_modules/rxjs/dist/esm5/internal/util/isReadableStreamLike.js","../node_modules/rxjs/dist/esm5/internal/observable/innerFrom.js","../node_modules/rxjs/dist/esm5/internal/util/executeSchedule.js","../node_modules/rxjs/dist/esm5/internal/operators/observeOn.js","../node_modules/rxjs/dist/esm5/internal/operators/subscribeOn.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleAsyncIterable.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduled.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleObservable.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleArray.js","../node_modules/rxjs/dist/esm5/internal/scheduled/schedulePromise.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleIterable.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleReadableStreamLike.js","../node_modules/rxjs/dist/esm5/internal/observable/from.js","../node_modules/rxjs/dist/esm5/internal/observable/of.js","../node_modules/rxjs/dist/esm5/internal/operators/map.js","../node_modules/rxjs/dist/esm5/internal/util/mapOneOrManyArgs.js","../node_modules/rxjs/dist/esm5/internal/util/argsArgArrayOrObject.js","../node_modules/rxjs/dist/esm5/internal/observable/combineLatest.js","../node_modules/rxjs/dist/esm5/internal/util/createObject.js","../node_modules/rxjs/dist/esm5/internal/operators/mergeMap.js","../node_modules/rxjs/dist/esm5/internal/operators/mergeInternals.js","../node_modules/rxjs/dist/esm5/internal/operators/mergeAll.js","../node_modules/rxjs/dist/esm5/internal/observable/concat.js","../node_modules/rxjs/dist/esm5/internal/operators/concatAll.js","../node_modules/rxjs/dist/esm5/internal/observable/defer.js","../node_modules/rxjs/dist/esm5/internal/observable/timer.js","../node_modules/rxjs/dist/esm5/internal/util/isDate.js","../node_modules/rxjs/dist/esm5/internal/observable/merge.js","../node_modules/rxjs/dist/esm5/internal/operators/filter.js","../node_modules/rxjs/dist/esm5/internal/operators/take.js","../node_modules/rxjs/dist/esm5/internal/operators/distinctUntilChanged.js","../node_modules/rxjs/dist/esm5/internal/operators/endWith.js","../node_modules/rxjs/dist/esm5/internal/operators/finalize.js","../node_modules/rxjs/dist/esm5/internal/operators/merge.js","../node_modules/rxjs/dist/esm5/internal/operators/mergeWith.js","../node_modules/rxjs/dist/esm5/internal/operators/scan.js","../node_modules/rxjs/dist/esm5/internal/operators/scanInternals.js","../node_modules/rxjs/dist/esm5/internal/operators/share.js","../node_modules/rxjs/dist/esm5/internal/operators/switchMap.js","../node_modules/rxjs/dist/esm5/internal/operators/tap.js","../node_modules/applesauce-core/dist/helpers/tags.js","../node_modules/nostr-tools/lib/esm/pure.js","../node_modules/applesauce-core/dist/helpers/cache.js","../node_modules/nostr-tools/lib/esm/utils.js","../node_modules/applesauce-core/dist/helpers/event.js","../node_modules/applesauce-core/dist/helpers/time.js","../node_modules/applesauce-core/dist/helpers/expiration.js","../node_modules/nostr-tools/lib/esm/nip19.js","../node_modules/applesauce-core/dist/helpers/url.js","../node_modules/applesauce-core/dist/helpers/relays.js","../node_modules/applesauce-core/dist/helpers/string.js","../node_modules/@noble/hashes/esm/crypto.js","../node_modules/@noble/hashes/esm/utils.js","../node_modules/applesauce-core/dist/helpers/pointers.js","../node_modules/applesauce-core/dist/helpers/groups.js","../node_modules/applesauce-core/dist/helpers/encrypted-content.js","../node_modules/applesauce-core/dist/helpers/hidden-content.js","../node_modules/applesauce-core/dist/helpers/hidden-tags.js","../node_modules/applesauce-core/dist/helpers/event-tags.js","../node_modules/applesauce-core/dist/helpers/lru.js","../node_modules/ms/index.js","../node_modules/debug/src/common.js","../node_modules/debug/src/browser.js","../node_modules/applesauce-core/dist/logger.js","../node_modules/applesauce-core/dist/event-store/event-memory.js","../node_modules/hash-sum/hash-sum.js","../node_modules/applesauce-core/dist/helpers/filter.js","../node_modules/applesauce-core/dist/models/blossom.js","../node_modules/applesauce-core/dist/helpers/blossom.js","../node_modules/applesauce-core/dist/helpers/profile.js","../node_modules/applesauce-core/dist/helpers/json.js","../node_modules/light-bolt11-decoder/node_modules/@scure/base/lib/index.js","../node_modules/light-bolt11-decoder/bolt11.js","../node_modules/applesauce-core/dist/helpers/comment.js","../node_modules/applesauce-core/dist/helpers/contacts.js","../node_modules/applesauce-core/dist/helpers/encrypted-content-cache.js","../node_modules/applesauce-core/dist/helpers/event-cache.js","../node_modules/applesauce-core/dist/helpers/lnurl.js","../node_modules/applesauce-core/dist/helpers/mailboxes.js","../node_modules/applesauce-core/dist/helpers/mutes.js","../node_modules/applesauce-core/dist/helpers/reports.js","../node_modules/applesauce-core/dist/helpers/threading.js","../node_modules/applesauce-core/dist/observable/claim-events.js","../node_modules/applesauce-core/dist/observable/claim-latest.js","../node_modules/applesauce-core/dist/observable/defined.js","../node_modules/applesauce-core/dist/observable/with-immediate-value.js","../node_modules/applesauce-core/dist/models/common.js","../node_modules/rxjs/dist/esm5/internal/operators/ignoreElements.js","../node_modules/rxjs/dist/esm5/internal/operators/takeUntil.js","../node_modules/rxjs/dist/esm5/internal/operators/repeat.js","../node_modules/applesauce-core/dist/observable/watch-event-updates.js","../node_modules/applesauce-core/dist/models/contacts.js","../node_modules/applesauce-core/dist/models/comments.js","../node_modules/applesauce-core/dist/models/mailboxes.js","../node_modules/applesauce-core/dist/models/mutes.js","../node_modules/applesauce-core/dist/models/profile.js","../node_modules/applesauce-core/dist/models/reactions.js","../node_modules/applesauce-core/dist/models/thread.js","../node_modules/applesauce-core/dist/event-store/model-mixin.js","../node_modules/applesauce-core/dist/event-store/event-store.js","../node_modules/applesauce-core/dist/helpers/delete.js","../node_modules/applesauce-core/dist/promise/deferred.js","../node_modules/applesauce-signers/dist/signers/amber-clipboard-signer.js","../node_modules/applesauce-signers/dist/helpers/nostr-connect.js","../node_modules/applesauce-signers/dist/signers/private-key-signer.js","../node_modules/applesauce-signers/node_modules/@noble/secp256k1/lib/esm/index.js","../node_modules/applesauce-signers/node_modules/@scure/base/lib/esm/index.js","../node_modules/applesauce-signers/dist/signers/serial-port-signer.js","../node_modules/svelte/store/index.mjs","../src/stores.js","../src/config.js","../src/constants.js","../src/nostr.js","../node_modules/hash-wasm/dist/index.esm.js","../src/nsec-crypto.js","../src/LoginModal.svelte","../src/ManagedACL.svelte","../src/Header.svelte","../src/Sidebar.svelte","../src/ExportView.svelte","../src/ImportView.svelte","../src/helpers.tsx","../src/FilterBuilder.svelte","../src/EventsView.svelte","../src/eventKinds.js","../src/EventTemplateSelector.svelte","../src/ComposeView.svelte","../src/SprocketView.svelte","../src/PolicyView.svelte","../src/kindCategories.js","../src/CurationView.svelte","../src/BlossomView.svelte","../src/LogView.svelte","../src/api.js","../src/utils.js","../src/RelayConnectView.svelte","../src/FilterDisplay.svelte","../src/RelayConnectModal.svelte","../src/websocket-auth.js","../src/App.svelte","../src/main.js"],"sourcesContent":["function noop() { }\nconst identity = x => x;\nfunction assign(tar, src) {\n // @ts-ignore\n for (const k in src)\n tar[k] = src[k];\n return tar;\n}\n// Adapted from https://github.com/then/is-promise/blob/master/index.js\n// Distributed under MIT License https://github.com/then/is-promise/blob/master/LICENSE\nfunction is_promise(value) {\n return !!value && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function';\n}\nfunction add_location(element, file, line, column, char) {\n element.__svelte_meta = {\n loc: { file, line, column, char }\n };\n}\nfunction run(fn) {\n return fn();\n}\nfunction blank_object() {\n return Object.create(null);\n}\nfunction run_all(fns) {\n fns.forEach(run);\n}\nfunction is_function(thing) {\n return typeof thing === 'function';\n}\nfunction safe_not_equal(a, b) {\n return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');\n}\nlet src_url_equal_anchor;\nfunction src_url_equal(element_src, url) {\n if (!src_url_equal_anchor) {\n src_url_equal_anchor = document.createElement('a');\n }\n src_url_equal_anchor.href = url;\n return element_src === src_url_equal_anchor.href;\n}\nfunction not_equal(a, b) {\n return a != a ? b == b : a !== b;\n}\nfunction is_empty(obj) {\n return Object.keys(obj).length === 0;\n}\nfunction validate_store(store, name) {\n if (store != null && typeof store.subscribe !== 'function') {\n throw new Error(`'${name}' is not a store with a 'subscribe' method`);\n }\n}\nfunction subscribe(store, ...callbacks) {\n if (store == null) {\n return noop;\n }\n const unsub = store.subscribe(...callbacks);\n return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;\n}\nfunction get_store_value(store) {\n let value;\n subscribe(store, _ => value = _)();\n return value;\n}\nfunction component_subscribe(component, store, callback) {\n component.$$.on_destroy.push(subscribe(store, callback));\n}\nfunction create_slot(definition, ctx, $$scope, fn) {\n if (definition) {\n const slot_ctx = get_slot_context(definition, ctx, $$scope, fn);\n return definition[0](slot_ctx);\n }\n}\nfunction get_slot_context(definition, ctx, $$scope, fn) {\n return definition[1] && fn\n ? assign($$scope.ctx.slice(), definition[1](fn(ctx)))\n : $$scope.ctx;\n}\nfunction get_slot_changes(definition, $$scope, dirty, fn) {\n if (definition[2] && fn) {\n const lets = definition[2](fn(dirty));\n if ($$scope.dirty === undefined) {\n return lets;\n }\n if (typeof lets === 'object') {\n const merged = [];\n const len = Math.max($$scope.dirty.length, lets.length);\n for (let i = 0; i < len; i += 1) {\n merged[i] = $$scope.dirty[i] | lets[i];\n }\n return merged;\n }\n return $$scope.dirty | lets;\n }\n return $$scope.dirty;\n}\nfunction update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn) {\n if (slot_changes) {\n const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);\n slot.p(slot_context, slot_changes);\n }\n}\nfunction update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {\n const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);\n update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn);\n}\nfunction get_all_dirty_from_scope($$scope) {\n if ($$scope.ctx.length > 32) {\n const dirty = [];\n const length = $$scope.ctx.length / 32;\n for (let i = 0; i < length; i++) {\n dirty[i] = -1;\n }\n return dirty;\n }\n return -1;\n}\nfunction exclude_internal_props(props) {\n const result = {};\n for (const k in props)\n if (k[0] !== '$')\n result[k] = props[k];\n return result;\n}\nfunction compute_rest_props(props, keys) {\n const rest = {};\n keys = new Set(keys);\n for (const k in props)\n if (!keys.has(k) && k[0] !== '$')\n rest[k] = props[k];\n return rest;\n}\nfunction compute_slots(slots) {\n const result = {};\n for (const key in slots) {\n result[key] = true;\n }\n return result;\n}\nfunction once(fn) {\n let ran = false;\n return function (...args) {\n if (ran)\n return;\n ran = true;\n fn.call(this, ...args);\n };\n}\nfunction null_to_empty(value) {\n return value == null ? '' : value;\n}\nfunction set_store_value(store, ret, value) {\n store.set(value);\n return ret;\n}\nconst has_prop = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);\nfunction action_destroyer(action_result) {\n return action_result && is_function(action_result.destroy) ? action_result.destroy : noop;\n}\nfunction split_css_unit(value) {\n const split = typeof value === 'string' && value.match(/^\\s*(-?[\\d.]+)([^\\s]*)\\s*$/);\n return split ? [parseFloat(split[1]), split[2] || 'px'] : [value, 'px'];\n}\nconst contenteditable_truthy_values = ['', true, 1, 'true', 'contenteditable'];\n\nconst is_client = typeof window !== 'undefined';\nlet now = is_client\n ? () => window.performance.now()\n : () => Date.now();\nlet raf = is_client ? cb => requestAnimationFrame(cb) : noop;\n// used internally for testing\nfunction set_now(fn) {\n now = fn;\n}\nfunction set_raf(fn) {\n raf = fn;\n}\n\nconst tasks = new Set();\nfunction run_tasks(now) {\n tasks.forEach(task => {\n if (!task.c(now)) {\n tasks.delete(task);\n task.f();\n }\n });\n if (tasks.size !== 0)\n raf(run_tasks);\n}\n/**\n * For testing purposes only!\n */\nfunction clear_loops() {\n tasks.clear();\n}\n/**\n * Creates a new task that runs on each raf frame\n * until it returns a falsy value or is aborted\n */\nfunction loop(callback) {\n let task;\n if (tasks.size === 0)\n raf(run_tasks);\n return {\n promise: new Promise(fulfill => {\n tasks.add(task = { c: callback, f: fulfill });\n }),\n abort() {\n tasks.delete(task);\n }\n };\n}\n\nconst globals = (typeof window !== 'undefined'\n ? window\n : typeof globalThis !== 'undefined'\n ? globalThis\n : global);\n\n/**\n * Resize observer singleton.\n * One listener per element only!\n * https://groups.google.com/a/chromium.org/g/blink-dev/c/z6ienONUb5A/m/F5-VcUZtBAAJ\n */\nclass ResizeObserverSingleton {\n constructor(options) {\n this.options = options;\n this._listeners = 'WeakMap' in globals ? new WeakMap() : undefined;\n }\n observe(element, listener) {\n this._listeners.set(element, listener);\n this._getObserver().observe(element, this.options);\n return () => {\n this._listeners.delete(element);\n this._observer.unobserve(element); // this line can probably be removed\n };\n }\n _getObserver() {\n var _a;\n return (_a = this._observer) !== null && _a !== void 0 ? _a : (this._observer = new ResizeObserver((entries) => {\n var _a;\n for (const entry of entries) {\n ResizeObserverSingleton.entries.set(entry.target, entry);\n (_a = this._listeners.get(entry.target)) === null || _a === void 0 ? void 0 : _a(entry);\n }\n }));\n }\n}\n// Needs to be written like this to pass the tree-shake-test\nResizeObserverSingleton.entries = 'WeakMap' in globals ? new WeakMap() : undefined;\n\n// Track which nodes are claimed during hydration. Unclaimed nodes can then be removed from the DOM\n// at the end of hydration without touching the remaining nodes.\nlet is_hydrating = false;\nfunction start_hydrating() {\n is_hydrating = true;\n}\nfunction end_hydrating() {\n is_hydrating = false;\n}\nfunction upper_bound(low, high, key, value) {\n // Return first index of value larger than input value in the range [low, high)\n while (low < high) {\n const mid = low + ((high - low) >> 1);\n if (key(mid) <= value) {\n low = mid + 1;\n }\n else {\n high = mid;\n }\n }\n return low;\n}\nfunction init_hydrate(target) {\n if (target.hydrate_init)\n return;\n target.hydrate_init = true;\n // We know that all children have claim_order values since the unclaimed have been detached if target is not
\n let children = target.childNodes;\n // If target is , there may be children without claim_order\n if (target.nodeName === 'HEAD') {\n const myChildren = [];\n for (let i = 0; i < children.length; i++) {\n const node = children[i];\n if (node.claim_order !== undefined) {\n myChildren.push(node);\n }\n }\n children = myChildren;\n }\n /*\n * Reorder claimed children optimally.\n * We can reorder claimed children optimally by finding the longest subsequence of\n * nodes that are already claimed in order and only moving the rest. The longest\n * subsequence of nodes that are claimed in order can be found by\n * computing the longest increasing subsequence of .claim_order values.\n *\n * This algorithm is optimal in generating the least amount of reorder operations\n * possible.\n *\n * Proof:\n * We know that, given a set of reordering operations, the nodes that do not move\n * always form an increasing subsequence, since they do not move among each other\n * meaning that they must be already ordered among each other. Thus, the maximal\n * set of nodes that do not move form a longest increasing subsequence.\n */\n // Compute longest increasing subsequence\n // m: subsequence length j => index k of smallest value that ends an increasing subsequence of length j\n const m = new Int32Array(children.length + 1);\n // Predecessor indices + 1\n const p = new Int32Array(children.length);\n m[0] = -1;\n let longest = 0;\n for (let i = 0; i < children.length; i++) {\n const current = children[i].claim_order;\n // Find the largest subsequence length such that it ends in a value less than our current value\n // upper_bound returns first greater value, so we subtract one\n // with fast path for when we are on the current longest subsequence\n const seqLen = ((longest > 0 && children[m[longest]].claim_order <= current) ? longest + 1 : upper_bound(1, longest, idx => children[m[idx]].claim_order, current)) - 1;\n p[i] = m[seqLen] + 1;\n const newLen = seqLen + 1;\n // We can guarantee that current is the smallest value. Otherwise, we would have generated a longer sequence.\n m[newLen] = i;\n longest = Math.max(newLen, longest);\n }\n // The longest increasing subsequence of nodes (initially reversed)\n const lis = [];\n // The rest of the nodes, nodes that will be moved\n const toMove = [];\n let last = children.length - 1;\n for (let cur = m[longest] + 1; cur != 0; cur = p[cur - 1]) {\n lis.push(children[cur - 1]);\n for (; last >= cur; last--) {\n toMove.push(children[last]);\n }\n last--;\n }\n for (; last >= 0; last--) {\n toMove.push(children[last]);\n }\n lis.reverse();\n // We sort the nodes being moved to guarantee that their insertion order matches the claim order\n toMove.sort((a, b) => a.claim_order - b.claim_order);\n // Finally, we move the nodes\n for (let i = 0, j = 0; i < toMove.length; i++) {\n while (j < lis.length && toMove[i].claim_order >= lis[j].claim_order) {\n j++;\n }\n const anchor = j < lis.length ? lis[j] : null;\n target.insertBefore(toMove[i], anchor);\n }\n}\nfunction append(target, node) {\n target.appendChild(node);\n}\nfunction append_styles(target, style_sheet_id, styles) {\n const append_styles_to = get_root_for_style(target);\n if (!append_styles_to.getElementById(style_sheet_id)) {\n const style = element('style');\n style.id = style_sheet_id;\n style.textContent = styles;\n append_stylesheet(append_styles_to, style);\n }\n}\nfunction get_root_for_style(node) {\n if (!node)\n return document;\n const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;\n if (root && root.host) {\n return root;\n }\n return node.ownerDocument;\n}\nfunction append_empty_stylesheet(node) {\n const style_element = element('style');\n append_stylesheet(get_root_for_style(node), style_element);\n return style_element.sheet;\n}\nfunction append_stylesheet(node, style) {\n append(node.head || node, style);\n return style.sheet;\n}\nfunction append_hydration(target, node) {\n if (is_hydrating) {\n init_hydrate(target);\n if ((target.actual_end_child === undefined) || ((target.actual_end_child !== null) && (target.actual_end_child.parentNode !== target))) {\n target.actual_end_child = target.firstChild;\n }\n // Skip nodes of undefined ordering\n while ((target.actual_end_child !== null) && (target.actual_end_child.claim_order === undefined)) {\n target.actual_end_child = target.actual_end_child.nextSibling;\n }\n if (node !== target.actual_end_child) {\n // We only insert if the ordering of this node should be modified or the parent node is not target\n if (node.claim_order !== undefined || node.parentNode !== target) {\n target.insertBefore(node, target.actual_end_child);\n }\n }\n else {\n target.actual_end_child = node.nextSibling;\n }\n }\n else if (node.parentNode !== target || node.nextSibling !== null) {\n target.appendChild(node);\n }\n}\nfunction insert(target, node, anchor) {\n target.insertBefore(node, anchor || null);\n}\nfunction insert_hydration(target, node, anchor) {\n if (is_hydrating && !anchor) {\n append_hydration(target, node);\n }\n else if (node.parentNode !== target || node.nextSibling != anchor) {\n target.insertBefore(node, anchor || null);\n }\n}\nfunction detach(node) {\n if (node.parentNode) {\n node.parentNode.removeChild(node);\n }\n}\nfunction destroy_each(iterations, detaching) {\n for (let i = 0; i < iterations.length; i += 1) {\n if (iterations[i])\n iterations[i].d(detaching);\n }\n}\nfunction element(name) {\n return document.createElement(name);\n}\nfunction element_is(name, is) {\n return document.createElement(name, { is });\n}\nfunction object_without_properties(obj, exclude) {\n const target = {};\n for (const k in obj) {\n if (has_prop(obj, k)\n // @ts-ignore\n && exclude.indexOf(k) === -1) {\n // @ts-ignore\n target[k] = obj[k];\n }\n }\n return target;\n}\nfunction svg_element(name) {\n return document.createElementNS('http://www.w3.org/2000/svg', name);\n}\nfunction text(data) {\n return document.createTextNode(data);\n}\nfunction space() {\n return text(' ');\n}\nfunction empty() {\n return text('');\n}\nfunction comment(content) {\n return document.createComment(content);\n}\nfunction listen(node, event, handler, options) {\n node.addEventListener(event, handler, options);\n return () => node.removeEventListener(event, handler, options);\n}\nfunction prevent_default(fn) {\n return function (event) {\n event.preventDefault();\n // @ts-ignore\n return fn.call(this, event);\n };\n}\nfunction stop_propagation(fn) {\n return function (event) {\n event.stopPropagation();\n // @ts-ignore\n return fn.call(this, event);\n };\n}\nfunction stop_immediate_propagation(fn) {\n return function (event) {\n event.stopImmediatePropagation();\n // @ts-ignore\n return fn.call(this, event);\n };\n}\nfunction self(fn) {\n return function (event) {\n // @ts-ignore\n if (event.target === this)\n fn.call(this, event);\n };\n}\nfunction trusted(fn) {\n return function (event) {\n // @ts-ignore\n if (event.isTrusted)\n fn.call(this, event);\n };\n}\nfunction attr(node, attribute, value) {\n if (value == null)\n node.removeAttribute(attribute);\n else if (node.getAttribute(attribute) !== value)\n node.setAttribute(attribute, value);\n}\n/**\n * List of attributes that should always be set through the attr method,\n * because updating them through the property setter doesn't work reliably.\n * In the example of `width`/`height`, the problem is that the setter only\n * accepts numeric values, but the attribute can also be set to a string like `50%`.\n * If this list becomes too big, rethink this approach.\n */\nconst always_set_through_set_attribute = ['width', 'height'];\nfunction set_attributes(node, attributes) {\n // @ts-ignore\n const descriptors = Object.getOwnPropertyDescriptors(node.__proto__);\n for (const key in attributes) {\n if (attributes[key] == null) {\n node.removeAttribute(key);\n }\n else if (key === 'style') {\n node.style.cssText = attributes[key];\n }\n else if (key === '__value') {\n node.value = node[key] = attributes[key];\n }\n else if (descriptors[key] && descriptors[key].set && always_set_through_set_attribute.indexOf(key) === -1) {\n node[key] = attributes[key];\n }\n else {\n attr(node, key, attributes[key]);\n }\n }\n}\nfunction set_svg_attributes(node, attributes) {\n for (const key in attributes) {\n attr(node, key, attributes[key]);\n }\n}\nfunction set_custom_element_data_map(node, data_map) {\n Object.keys(data_map).forEach((key) => {\n set_custom_element_data(node, key, data_map[key]);\n });\n}\nfunction set_custom_element_data(node, prop, value) {\n if (prop in node) {\n node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;\n }\n else {\n attr(node, prop, value);\n }\n}\nfunction set_dynamic_element_data(tag) {\n return (/-/.test(tag)) ? set_custom_element_data_map : set_attributes;\n}\nfunction xlink_attr(node, attribute, value) {\n node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);\n}\nfunction get_binding_group_value(group, __value, checked) {\n const value = new Set();\n for (let i = 0; i < group.length; i += 1) {\n if (group[i].checked)\n value.add(group[i].__value);\n }\n if (!checked) {\n value.delete(__value);\n }\n return Array.from(value);\n}\nfunction init_binding_group(group) {\n let _inputs;\n return {\n /* push */ p(...inputs) {\n _inputs = inputs;\n _inputs.forEach(input => group.push(input));\n },\n /* remove */ r() {\n _inputs.forEach(input => group.splice(group.indexOf(input), 1));\n }\n };\n}\nfunction init_binding_group_dynamic(group, indexes) {\n let _group = get_binding_group(group);\n let _inputs;\n function get_binding_group(group) {\n for (let i = 0; i < indexes.length; i++) {\n group = group[indexes[i]] = group[indexes[i]] || [];\n }\n return group;\n }\n function push() {\n _inputs.forEach(input => _group.push(input));\n }\n function remove() {\n _inputs.forEach(input => _group.splice(_group.indexOf(input), 1));\n }\n return {\n /* update */ u(new_indexes) {\n indexes = new_indexes;\n const new_group = get_binding_group(group);\n if (new_group !== _group) {\n remove();\n _group = new_group;\n push();\n }\n },\n /* push */ p(...inputs) {\n _inputs = inputs;\n push();\n },\n /* remove */ r: remove\n };\n}\nfunction to_number(value) {\n return value === '' ? null : +value;\n}\nfunction time_ranges_to_array(ranges) {\n const array = [];\n for (let i = 0; i < ranges.length; i += 1) {\n array.push({ start: ranges.start(i), end: ranges.end(i) });\n }\n return array;\n}\nfunction children(element) {\n return Array.from(element.childNodes);\n}\nfunction init_claim_info(nodes) {\n if (nodes.claim_info === undefined) {\n nodes.claim_info = { last_index: 0, total_claimed: 0 };\n }\n}\nfunction claim_node(nodes, predicate, processNode, createNode, dontUpdateLastIndex = false) {\n // Try to find nodes in an order such that we lengthen the longest increasing subsequence\n init_claim_info(nodes);\n const resultNode = (() => {\n // We first try to find an element after the previous one\n for (let i = nodes.claim_info.last_index; i < nodes.length; i++) {\n const node = nodes[i];\n if (predicate(node)) {\n const replacement = processNode(node);\n if (replacement === undefined) {\n nodes.splice(i, 1);\n }\n else {\n nodes[i] = replacement;\n }\n if (!dontUpdateLastIndex) {\n nodes.claim_info.last_index = i;\n }\n return node;\n }\n }\n // Otherwise, we try to find one before\n // We iterate in reverse so that we don't go too far back\n for (let i = nodes.claim_info.last_index - 1; i >= 0; i--) {\n const node = nodes[i];\n if (predicate(node)) {\n const replacement = processNode(node);\n if (replacement === undefined) {\n nodes.splice(i, 1);\n }\n else {\n nodes[i] = replacement;\n }\n if (!dontUpdateLastIndex) {\n nodes.claim_info.last_index = i;\n }\n else if (replacement === undefined) {\n // Since we spliced before the last_index, we decrease it\n nodes.claim_info.last_index--;\n }\n return node;\n }\n }\n // If we can't find any matching node, we create a new one\n return createNode();\n })();\n resultNode.claim_order = nodes.claim_info.total_claimed;\n nodes.claim_info.total_claimed += 1;\n return resultNode;\n}\nfunction claim_element_base(nodes, name, attributes, create_element) {\n return claim_node(nodes, (node) => node.nodeName === name, (node) => {\n const remove = [];\n for (let j = 0; j < node.attributes.length; j++) {\n const attribute = node.attributes[j];\n if (!attributes[attribute.name]) {\n remove.push(attribute.name);\n }\n }\n remove.forEach(v => node.removeAttribute(v));\n return undefined;\n }, () => create_element(name));\n}\nfunction claim_element(nodes, name, attributes) {\n return claim_element_base(nodes, name, attributes, element);\n}\nfunction claim_svg_element(nodes, name, attributes) {\n return claim_element_base(nodes, name, attributes, svg_element);\n}\nfunction claim_text(nodes, data) {\n return claim_node(nodes, (node) => node.nodeType === 3, (node) => {\n const dataStr = '' + data;\n if (node.data.startsWith(dataStr)) {\n if (node.data.length !== dataStr.length) {\n return node.splitText(dataStr.length);\n }\n }\n else {\n node.data = dataStr;\n }\n }, () => text(data), true // Text nodes should not update last index since it is likely not worth it to eliminate an increasing subsequence of actual elements\n );\n}\nfunction claim_space(nodes) {\n return claim_text(nodes, ' ');\n}\nfunction claim_comment(nodes, data) {\n return claim_node(nodes, (node) => node.nodeType === 8, (node) => {\n node.data = '' + data;\n return undefined;\n }, () => comment(data), true);\n}\nfunction find_comment(nodes, text, start) {\n for (let i = start; i < nodes.length; i += 1) {\n const node = nodes[i];\n if (node.nodeType === 8 /* comment node */ && node.textContent.trim() === text) {\n return i;\n }\n }\n return nodes.length;\n}\nfunction claim_html_tag(nodes, is_svg) {\n // find html opening tag\n const start_index = find_comment(nodes, 'HTML_TAG_START', 0);\n const end_index = find_comment(nodes, 'HTML_TAG_END', start_index);\n if (start_index === end_index) {\n return new HtmlTagHydration(undefined, is_svg);\n }\n init_claim_info(nodes);\n const html_tag_nodes = nodes.splice(start_index, end_index - start_index + 1);\n detach(html_tag_nodes[0]);\n detach(html_tag_nodes[html_tag_nodes.length - 1]);\n const claimed_nodes = html_tag_nodes.slice(1, html_tag_nodes.length - 1);\n for (const n of claimed_nodes) {\n n.claim_order = nodes.claim_info.total_claimed;\n nodes.claim_info.total_claimed += 1;\n }\n return new HtmlTagHydration(claimed_nodes, is_svg);\n}\nfunction set_data(text, data) {\n data = '' + data;\n if (text.data === data)\n return;\n text.data = data;\n}\nfunction set_data_contenteditable(text, data) {\n data = '' + data;\n if (text.wholeText === data)\n return;\n text.data = data;\n}\nfunction set_data_maybe_contenteditable(text, data, attr_value) {\n if (~contenteditable_truthy_values.indexOf(attr_value)) {\n set_data_contenteditable(text, data);\n }\n else {\n set_data(text, data);\n }\n}\nfunction set_input_value(input, value) {\n input.value = value == null ? '' : value;\n}\nfunction set_input_type(input, type) {\n try {\n input.type = type;\n }\n catch (e) {\n // do nothing\n }\n}\nfunction set_style(node, key, value, important) {\n if (value == null) {\n node.style.removeProperty(key);\n }\n else {\n node.style.setProperty(key, value, important ? 'important' : '');\n }\n}\nfunction select_option(select, value, mounting) {\n for (let i = 0; i < select.options.length; i += 1) {\n const option = select.options[i];\n if (option.__value === value) {\n option.selected = true;\n return;\n }\n }\n if (!mounting || value !== undefined) {\n select.selectedIndex = -1; // no option should be selected\n }\n}\nfunction select_options(select, value) {\n for (let i = 0; i < select.options.length; i += 1) {\n const option = select.options[i];\n option.selected = ~value.indexOf(option.__value);\n }\n}\nfunction select_value(select) {\n const selected_option = select.querySelector(':checked');\n return selected_option && selected_option.__value;\n}\nfunction select_multiple_value(select) {\n return [].map.call(select.querySelectorAll(':checked'), option => option.__value);\n}\n// unfortunately this can't be a constant as that wouldn't be tree-shakeable\n// so we cache the result instead\nlet crossorigin;\nfunction is_crossorigin() {\n if (crossorigin === undefined) {\n crossorigin = false;\n try {\n if (typeof window !== 'undefined' && window.parent) {\n void window.parent.document;\n }\n }\n catch (error) {\n crossorigin = true;\n }\n }\n return crossorigin;\n}\nfunction add_iframe_resize_listener(node, fn) {\n const computed_style = getComputedStyle(node);\n if (computed_style.position === 'static') {\n node.style.position = 'relative';\n }\n const iframe = element('iframe');\n iframe.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; ' +\n 'overflow: hidden; border: 0; opacity: 0; pointer-events: none; z-index: -1;');\n iframe.setAttribute('aria-hidden', 'true');\n iframe.tabIndex = -1;\n const crossorigin = is_crossorigin();\n let unsubscribe;\n if (crossorigin) {\n iframe.src = \"data:text/html,\";\n unsubscribe = listen(window, 'message', (event) => {\n if (event.source === iframe.contentWindow)\n fn();\n });\n }\n else {\n iframe.src = 'about:blank';\n iframe.onload = () => {\n unsubscribe = listen(iframe.contentWindow, 'resize', fn);\n // make sure an initial resize event is fired _after_ the iframe is loaded (which is asynchronous)\n // see https://github.com/sveltejs/svelte/issues/4233\n fn();\n };\n }\n append(node, iframe);\n return () => {\n if (crossorigin) {\n unsubscribe();\n }\n else if (unsubscribe && iframe.contentWindow) {\n unsubscribe();\n }\n detach(iframe);\n };\n}\nconst resize_observer_content_box = /* @__PURE__ */ new ResizeObserverSingleton({ box: 'content-box' });\nconst resize_observer_border_box = /* @__PURE__ */ new ResizeObserverSingleton({ box: 'border-box' });\nconst resize_observer_device_pixel_content_box = /* @__PURE__ */ new ResizeObserverSingleton({ box: 'device-pixel-content-box' });\nfunction toggle_class(element, name, toggle) {\n element.classList[toggle ? 'add' : 'remove'](name);\n}\nfunction custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {\n const e = document.createEvent('CustomEvent');\n e.initCustomEvent(type, bubbles, cancelable, detail);\n return e;\n}\nfunction query_selector_all(selector, parent = document.body) {\n return Array.from(parent.querySelectorAll(selector));\n}\nfunction head_selector(nodeId, head) {\n const result = [];\n let started = 0;\n for (const node of head.childNodes) {\n if (node.nodeType === 8 /* comment node */) {\n const comment = node.textContent.trim();\n if (comment === `HEAD_${nodeId}_END`) {\n started -= 1;\n result.push(node);\n }\n else if (comment === `HEAD_${nodeId}_START`) {\n started += 1;\n result.push(node);\n }\n }\n else if (started > 0) {\n result.push(node);\n }\n }\n return result;\n}\nclass HtmlTag {\n constructor(is_svg = false) {\n this.is_svg = false;\n this.is_svg = is_svg;\n this.e = this.n = null;\n }\n c(html) {\n this.h(html);\n }\n m(html, target, anchor = null) {\n if (!this.e) {\n if (this.is_svg)\n this.e = svg_element(target.nodeName);\n /** #7364 target for may be provided as #document-fragment(11) */\n else\n this.e = element((target.nodeType === 11 ? 'TEMPLATE' : target.nodeName));\n this.t = target.tagName !== 'TEMPLATE' ? target : target.content;\n this.c(html);\n }\n this.i(anchor);\n }\n h(html) {\n this.e.innerHTML = html;\n this.n = Array.from(this.e.nodeName === 'TEMPLATE' ? this.e.content.childNodes : this.e.childNodes);\n }\n i(anchor) {\n for (let i = 0; i < this.n.length; i += 1) {\n insert(this.t, this.n[i], anchor);\n }\n }\n p(html) {\n this.d();\n this.h(html);\n this.i(this.a);\n }\n d() {\n this.n.forEach(detach);\n }\n}\nclass HtmlTagHydration extends HtmlTag {\n constructor(claimed_nodes, is_svg = false) {\n super(is_svg);\n this.e = this.n = null;\n this.l = claimed_nodes;\n }\n c(html) {\n if (this.l) {\n this.n = this.l;\n }\n else {\n super.c(html);\n }\n }\n i(anchor) {\n for (let i = 0; i < this.n.length; i += 1) {\n insert_hydration(this.t, this.n[i], anchor);\n }\n }\n}\nfunction attribute_to_object(attributes) {\n const result = {};\n for (const attribute of attributes) {\n result[attribute.name] = attribute.value;\n }\n return result;\n}\nfunction get_custom_elements_slots(element) {\n const result = {};\n element.childNodes.forEach((node) => {\n result[node.slot || 'default'] = true;\n });\n return result;\n}\nfunction construct_svelte_component(component, props) {\n return new component(props);\n}\n\n// we need to store the information for multiple documents because a Svelte application could also contain iframes\n// https://github.com/sveltejs/svelte/issues/3624\nconst managed_styles = new Map();\nlet active = 0;\n// https://github.com/darkskyapp/string-hash/blob/master/index.js\nfunction hash(str) {\n let hash = 5381;\n let i = str.length;\n while (i--)\n hash = ((hash << 5) - hash) ^ str.charCodeAt(i);\n return hash >>> 0;\n}\nfunction create_style_information(doc, node) {\n const info = { stylesheet: append_empty_stylesheet(node), rules: {} };\n managed_styles.set(doc, info);\n return info;\n}\nfunction create_rule(node, a, b, duration, delay, ease, fn, uid = 0) {\n const step = 16.666 / duration;\n let keyframes = '{\\n';\n for (let p = 0; p <= 1; p += step) {\n const t = a + (b - a) * ease(p);\n keyframes += p * 100 + `%{${fn(t, 1 - t)}}\\n`;\n }\n const rule = keyframes + `100% {${fn(b, 1 - b)}}\\n}`;\n const name = `__svelte_${hash(rule)}_${uid}`;\n const doc = get_root_for_style(node);\n const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node);\n if (!rules[name]) {\n rules[name] = true;\n stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);\n }\n const animation = node.style.animation || '';\n node.style.animation = `${animation ? `${animation}, ` : ''}${name} ${duration}ms linear ${delay}ms 1 both`;\n active += 1;\n return name;\n}\nfunction delete_rule(node, name) {\n const previous = (node.style.animation || '').split(', ');\n const next = previous.filter(name\n ? anim => anim.indexOf(name) < 0 // remove specific animation\n : anim => anim.indexOf('__svelte') === -1 // remove all Svelte animations\n );\n const deleted = previous.length - next.length;\n if (deleted) {\n node.style.animation = next.join(', ');\n active -= deleted;\n if (!active)\n clear_rules();\n }\n}\nfunction clear_rules() {\n raf(() => {\n if (active)\n return;\n managed_styles.forEach(info => {\n const { ownerNode } = info.stylesheet;\n // there is no ownerNode if it runs on jsdom.\n if (ownerNode)\n detach(ownerNode);\n });\n managed_styles.clear();\n });\n}\n\nfunction create_animation(node, from, fn, params) {\n if (!from)\n return noop;\n const to = node.getBoundingClientRect();\n if (from.left === to.left && from.right === to.right && from.top === to.top && from.bottom === to.bottom)\n return noop;\n const { delay = 0, duration = 300, easing = identity, \n // @ts-ignore todo: should this be separated from destructuring? Or start/end added to public api and documentation?\n start: start_time = now() + delay, \n // @ts-ignore todo:\n end = start_time + duration, tick = noop, css } = fn(node, { from, to }, params);\n let running = true;\n let started = false;\n let name;\n function start() {\n if (css) {\n name = create_rule(node, 0, 1, duration, delay, easing, css);\n }\n if (!delay) {\n started = true;\n }\n }\n function stop() {\n if (css)\n delete_rule(node, name);\n running = false;\n }\n loop(now => {\n if (!started && now >= start_time) {\n started = true;\n }\n if (started && now >= end) {\n tick(1, 0);\n stop();\n }\n if (!running) {\n return false;\n }\n if (started) {\n const p = now - start_time;\n const t = 0 + 1 * easing(p / duration);\n tick(t, 1 - t);\n }\n return true;\n });\n start();\n tick(0, 1);\n return stop;\n}\nfunction fix_position(node) {\n const style = getComputedStyle(node);\n if (style.position !== 'absolute' && style.position !== 'fixed') {\n const { width, height } = style;\n const a = node.getBoundingClientRect();\n node.style.position = 'absolute';\n node.style.width = width;\n node.style.height = height;\n add_transform(node, a);\n }\n}\nfunction add_transform(node, a) {\n const b = node.getBoundingClientRect();\n if (a.left !== b.left || a.top !== b.top) {\n const style = getComputedStyle(node);\n const transform = style.transform === 'none' ? '' : style.transform;\n node.style.transform = `${transform} translate(${a.left - b.left}px, ${a.top - b.top}px)`;\n }\n}\n\nlet current_component;\nfunction set_current_component(component) {\n current_component = component;\n}\nfunction get_current_component() {\n if (!current_component)\n throw new Error('Function called outside component initialization');\n return current_component;\n}\n/**\n * Schedules a callback to run immediately before the component is updated after any state change.\n *\n * The first time the callback runs will be before the initial `onMount`\n *\n * https://svelte.dev/docs#run-time-svelte-beforeupdate\n */\nfunction beforeUpdate(fn) {\n get_current_component().$$.before_update.push(fn);\n}\n/**\n * The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.\n * It must be called during the component's initialisation (but doesn't need to live *inside* the component;\n * it can be called from an external module).\n *\n * `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api).\n *\n * https://svelte.dev/docs#run-time-svelte-onmount\n */\nfunction onMount(fn) {\n get_current_component().$$.on_mount.push(fn);\n}\n/**\n * Schedules a callback to run immediately after the component has been updated.\n *\n * The first time the callback runs will be after the initial `onMount`\n */\nfunction afterUpdate(fn) {\n get_current_component().$$.after_update.push(fn);\n}\n/**\n * Schedules a callback to run immediately before the component is unmounted.\n *\n * Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the\n * only one that runs inside a server-side component.\n *\n * https://svelte.dev/docs#run-time-svelte-ondestroy\n */\nfunction onDestroy(fn) {\n get_current_component().$$.on_destroy.push(fn);\n}\n/**\n * Creates an event dispatcher that can be used to dispatch [component events](/docs#template-syntax-component-directives-on-eventname).\n * Event dispatchers are functions that can take two arguments: `name` and `detail`.\n *\n * Component events created with `createEventDispatcher` create a\n * [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent).\n * These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture).\n * The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail)\n * property and can contain any type of data.\n *\n * https://svelte.dev/docs#run-time-svelte-createeventdispatcher\n */\nfunction createEventDispatcher() {\n const component = get_current_component();\n return (type, detail, { cancelable = false } = {}) => {\n const callbacks = component.$$.callbacks[type];\n if (callbacks) {\n // TODO are there situations where events could be dispatched\n // in a server (non-DOM) environment?\n const event = custom_event(type, detail, { cancelable });\n callbacks.slice().forEach(fn => {\n fn.call(component, event);\n });\n return !event.defaultPrevented;\n }\n return true;\n };\n}\n/**\n * Associates an arbitrary `context` object with the current component and the specified `key`\n * and returns that object. The context is then available to children of the component\n * (including slotted content) with `getContext`.\n *\n * Like lifecycle functions, this must be called during component initialisation.\n *\n * https://svelte.dev/docs#run-time-svelte-setcontext\n */\nfunction setContext(key, context) {\n get_current_component().$$.context.set(key, context);\n return context;\n}\n/**\n * Retrieves the context that belongs to the closest parent component with the specified `key`.\n * Must be called during component initialisation.\n *\n * https://svelte.dev/docs#run-time-svelte-getcontext\n */\nfunction getContext(key) {\n return get_current_component().$$.context.get(key);\n}\n/**\n * Retrieves the whole context map that belongs to the closest parent component.\n * Must be called during component initialisation. Useful, for example, if you\n * programmatically create a component and want to pass the existing context to it.\n *\n * https://svelte.dev/docs#run-time-svelte-getallcontexts\n */\nfunction getAllContexts() {\n return get_current_component().$$.context;\n}\n/**\n * Checks whether a given `key` has been set in the context of a parent component.\n * Must be called during component initialisation.\n *\n * https://svelte.dev/docs#run-time-svelte-hascontext\n */\nfunction hasContext(key) {\n return get_current_component().$$.context.has(key);\n}\n// TODO figure out if we still want to support\n// shorthand events, or if we want to implement\n// a real bubbling mechanism\nfunction bubble(component, event) {\n const callbacks = component.$$.callbacks[event.type];\n if (callbacks) {\n // @ts-ignore\n callbacks.slice().forEach(fn => fn.call(this, event));\n }\n}\n\nconst dirty_components = [];\nconst intros = { enabled: false };\nconst binding_callbacks = [];\nlet render_callbacks = [];\nconst flush_callbacks = [];\nconst resolved_promise = /* @__PURE__ */ Promise.resolve();\nlet update_scheduled = false;\nfunction schedule_update() {\n if (!update_scheduled) {\n update_scheduled = true;\n resolved_promise.then(flush);\n }\n}\nfunction tick() {\n schedule_update();\n return resolved_promise;\n}\nfunction add_render_callback(fn) {\n render_callbacks.push(fn);\n}\nfunction add_flush_callback(fn) {\n flush_callbacks.push(fn);\n}\n// flush() calls callbacks in this order:\n// 1. All beforeUpdate callbacks, in order: parents before children\n// 2. All bind:this callbacks, in reverse order: children before parents.\n// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT\n// for afterUpdates called during the initial onMount, which are called in\n// reverse order: children before parents.\n// Since callbacks might update component values, which could trigger another\n// call to flush(), the following steps guard against this:\n// 1. During beforeUpdate, any updated components will be added to the\n// dirty_components array and will cause a reentrant call to flush(). Because\n// the flush index is kept outside the function, the reentrant call will pick\n// up where the earlier call left off and go through all dirty components. The\n// current_component value is saved and restored so that the reentrant call will\n// not interfere with the \"parent\" flush() call.\n// 2. bind:this callbacks cannot trigger new flush() calls.\n// 3. During afterUpdate, any updated components will NOT have their afterUpdate\n// callback called a second time; the seen_callbacks set, outside the flush()\n// function, guarantees this behavior.\nconst seen_callbacks = new Set();\nlet flushidx = 0; // Do *not* move this inside the flush() function\nfunction flush() {\n // Do not reenter flush while dirty components are updated, as this can\n // result in an infinite loop. Instead, let the inner flush handle it.\n // Reentrancy is ok afterwards for bindings etc.\n if (flushidx !== 0) {\n return;\n }\n const saved_component = current_component;\n do {\n // first, call beforeUpdate functions\n // and update components\n try {\n while (flushidx < dirty_components.length) {\n const component = dirty_components[flushidx];\n flushidx++;\n set_current_component(component);\n update(component.$$);\n }\n }\n catch (e) {\n // reset dirty state to not end up in a deadlocked state and then rethrow\n dirty_components.length = 0;\n flushidx = 0;\n throw e;\n }\n set_current_component(null);\n dirty_components.length = 0;\n flushidx = 0;\n while (binding_callbacks.length)\n binding_callbacks.pop()();\n // then, once components are updated, call\n // afterUpdate functions. This may cause\n // subsequent updates...\n for (let i = 0; i < render_callbacks.length; i += 1) {\n const callback = render_callbacks[i];\n if (!seen_callbacks.has(callback)) {\n // ...so guard against infinite loops\n seen_callbacks.add(callback);\n callback();\n }\n }\n render_callbacks.length = 0;\n } while (dirty_components.length);\n while (flush_callbacks.length) {\n flush_callbacks.pop()();\n }\n update_scheduled = false;\n seen_callbacks.clear();\n set_current_component(saved_component);\n}\nfunction update($$) {\n if ($$.fragment !== null) {\n $$.update();\n run_all($$.before_update);\n const dirty = $$.dirty;\n $$.dirty = [-1];\n $$.fragment && $$.fragment.p($$.ctx, dirty);\n $$.after_update.forEach(add_render_callback);\n }\n}\n/**\n * Useful for example to execute remaining `afterUpdate` callbacks before executing `destroy`.\n */\nfunction flush_render_callbacks(fns) {\n const filtered = [];\n const targets = [];\n render_callbacks.forEach((c) => fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c));\n targets.forEach((c) => c());\n render_callbacks = filtered;\n}\n\nlet promise;\nfunction wait() {\n if (!promise) {\n promise = Promise.resolve();\n promise.then(() => {\n promise = null;\n });\n }\n return promise;\n}\nfunction dispatch(node, direction, kind) {\n node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`));\n}\nconst outroing = new Set();\nlet outros;\nfunction group_outros() {\n outros = {\n r: 0,\n c: [],\n p: outros // parent group\n };\n}\nfunction check_outros() {\n if (!outros.r) {\n run_all(outros.c);\n }\n outros = outros.p;\n}\nfunction transition_in(block, local) {\n if (block && block.i) {\n outroing.delete(block);\n block.i(local);\n }\n}\nfunction transition_out(block, local, detach, callback) {\n if (block && block.o) {\n if (outroing.has(block))\n return;\n outroing.add(block);\n outros.c.push(() => {\n outroing.delete(block);\n if (callback) {\n if (detach)\n block.d(1);\n callback();\n }\n });\n block.o(local);\n }\n else if (callback) {\n callback();\n }\n}\nconst null_transition = { duration: 0 };\nfunction create_in_transition(node, fn, params) {\n const options = { direction: 'in' };\n let config = fn(node, params, options);\n let running = false;\n let animation_name;\n let task;\n let uid = 0;\n function cleanup() {\n if (animation_name)\n delete_rule(node, animation_name);\n }\n function go() {\n const { delay = 0, duration = 300, easing = identity, tick = noop, css } = config || null_transition;\n if (css)\n animation_name = create_rule(node, 0, 1, duration, delay, easing, css, uid++);\n tick(0, 1);\n const start_time = now() + delay;\n const end_time = start_time + duration;\n if (task)\n task.abort();\n running = true;\n add_render_callback(() => dispatch(node, true, 'start'));\n task = loop(now => {\n if (running) {\n if (now >= end_time) {\n tick(1, 0);\n dispatch(node, true, 'end');\n cleanup();\n return running = false;\n }\n if (now >= start_time) {\n const t = easing((now - start_time) / duration);\n tick(t, 1 - t);\n }\n }\n return running;\n });\n }\n let started = false;\n return {\n start() {\n if (started)\n return;\n started = true;\n delete_rule(node);\n if (is_function(config)) {\n config = config(options);\n wait().then(go);\n }\n else {\n go();\n }\n },\n invalidate() {\n started = false;\n },\n end() {\n if (running) {\n cleanup();\n running = false;\n }\n }\n };\n}\nfunction create_out_transition(node, fn, params) {\n const options = { direction: 'out' };\n let config = fn(node, params, options);\n let running = true;\n let animation_name;\n const group = outros;\n group.r += 1;\n function go() {\n const { delay = 0, duration = 300, easing = identity, tick = noop, css } = config || null_transition;\n if (css)\n animation_name = create_rule(node, 1, 0, duration, delay, easing, css);\n const start_time = now() + delay;\n const end_time = start_time + duration;\n add_render_callback(() => dispatch(node, false, 'start'));\n loop(now => {\n if (running) {\n if (now >= end_time) {\n tick(0, 1);\n dispatch(node, false, 'end');\n if (!--group.r) {\n // this will result in `end()` being called,\n // so we don't need to clean up here\n run_all(group.c);\n }\n return false;\n }\n if (now >= start_time) {\n const t = easing((now - start_time) / duration);\n tick(1 - t, t);\n }\n }\n return running;\n });\n }\n if (is_function(config)) {\n wait().then(() => {\n // @ts-ignore\n config = config(options);\n go();\n });\n }\n else {\n go();\n }\n return {\n end(reset) {\n if (reset && config.tick) {\n config.tick(1, 0);\n }\n if (running) {\n if (animation_name)\n delete_rule(node, animation_name);\n running = false;\n }\n }\n };\n}\nfunction create_bidirectional_transition(node, fn, params, intro) {\n const options = { direction: 'both' };\n let config = fn(node, params, options);\n let t = intro ? 0 : 1;\n let running_program = null;\n let pending_program = null;\n let animation_name = null;\n function clear_animation() {\n if (animation_name)\n delete_rule(node, animation_name);\n }\n function init(program, duration) {\n const d = (program.b - t);\n duration *= Math.abs(d);\n return {\n a: t,\n b: program.b,\n d,\n duration,\n start: program.start,\n end: program.start + duration,\n group: program.group\n };\n }\n function go(b) {\n const { delay = 0, duration = 300, easing = identity, tick = noop, css } = config || null_transition;\n const program = {\n start: now() + delay,\n b\n };\n if (!b) {\n // @ts-ignore todo: improve typings\n program.group = outros;\n outros.r += 1;\n }\n if (running_program || pending_program) {\n pending_program = program;\n }\n else {\n // if this is an intro, and there's a delay, we need to do\n // an initial tick and/or apply CSS animation immediately\n if (css) {\n clear_animation();\n animation_name = create_rule(node, t, b, duration, delay, easing, css);\n }\n if (b)\n tick(0, 1);\n running_program = init(program, duration);\n add_render_callback(() => dispatch(node, b, 'start'));\n loop(now => {\n if (pending_program && now > pending_program.start) {\n running_program = init(pending_program, duration);\n pending_program = null;\n dispatch(node, running_program.b, 'start');\n if (css) {\n clear_animation();\n animation_name = create_rule(node, t, running_program.b, running_program.duration, 0, easing, config.css);\n }\n }\n if (running_program) {\n if (now >= running_program.end) {\n tick(t = running_program.b, 1 - t);\n dispatch(node, running_program.b, 'end');\n if (!pending_program) {\n // we're done\n if (running_program.b) {\n // intro — we can tidy up immediately\n clear_animation();\n }\n else {\n // outro — needs to be coordinated\n if (!--running_program.group.r)\n run_all(running_program.group.c);\n }\n }\n running_program = null;\n }\n else if (now >= running_program.start) {\n const p = now - running_program.start;\n t = running_program.a + running_program.d * easing(p / running_program.duration);\n tick(t, 1 - t);\n }\n }\n return !!(running_program || pending_program);\n });\n }\n }\n return {\n run(b) {\n if (is_function(config)) {\n wait().then(() => {\n // @ts-ignore\n config = config(options);\n go(b);\n });\n }\n else {\n go(b);\n }\n },\n end() {\n clear_animation();\n running_program = pending_program = null;\n }\n };\n}\n\nfunction handle_promise(promise, info) {\n const token = info.token = {};\n function update(type, index, key, value) {\n if (info.token !== token)\n return;\n info.resolved = value;\n let child_ctx = info.ctx;\n if (key !== undefined) {\n child_ctx = child_ctx.slice();\n child_ctx[key] = value;\n }\n const block = type && (info.current = type)(child_ctx);\n let needs_flush = false;\n if (info.block) {\n if (info.blocks) {\n info.blocks.forEach((block, i) => {\n if (i !== index && block) {\n group_outros();\n transition_out(block, 1, 1, () => {\n if (info.blocks[i] === block) {\n info.blocks[i] = null;\n }\n });\n check_outros();\n }\n });\n }\n else {\n info.block.d(1);\n }\n block.c();\n transition_in(block, 1);\n block.m(info.mount(), info.anchor);\n needs_flush = true;\n }\n info.block = block;\n if (info.blocks)\n info.blocks[index] = block;\n if (needs_flush) {\n flush();\n }\n }\n if (is_promise(promise)) {\n const current_component = get_current_component();\n promise.then(value => {\n set_current_component(current_component);\n update(info.then, 1, info.value, value);\n set_current_component(null);\n }, error => {\n set_current_component(current_component);\n update(info.catch, 2, info.error, error);\n set_current_component(null);\n if (!info.hasCatch) {\n throw error;\n }\n });\n // if we previously had a then/catch block, destroy it\n if (info.current !== info.pending) {\n update(info.pending, 0);\n return true;\n }\n }\n else {\n if (info.current !== info.then) {\n update(info.then, 1, info.value, promise);\n return true;\n }\n info.resolved = promise;\n }\n}\nfunction update_await_block_branch(info, ctx, dirty) {\n const child_ctx = ctx.slice();\n const { resolved } = info;\n if (info.current === info.then) {\n child_ctx[info.value] = resolved;\n }\n if (info.current === info.catch) {\n child_ctx[info.error] = resolved;\n }\n info.block.p(child_ctx, dirty);\n}\n\nfunction destroy_block(block, lookup) {\n block.d(1);\n lookup.delete(block.key);\n}\nfunction outro_and_destroy_block(block, lookup) {\n transition_out(block, 1, 1, () => {\n lookup.delete(block.key);\n });\n}\nfunction fix_and_destroy_block(block, lookup) {\n block.f();\n destroy_block(block, lookup);\n}\nfunction fix_and_outro_and_destroy_block(block, lookup) {\n block.f();\n outro_and_destroy_block(block, lookup);\n}\nfunction update_keyed_each(old_blocks, dirty, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, next, get_context) {\n let o = old_blocks.length;\n let n = list.length;\n let i = o;\n const old_indexes = {};\n while (i--)\n old_indexes[old_blocks[i].key] = i;\n const new_blocks = [];\n const new_lookup = new Map();\n const deltas = new Map();\n const updates = [];\n i = n;\n while (i--) {\n const child_ctx = get_context(ctx, list, i);\n const key = get_key(child_ctx);\n let block = lookup.get(key);\n if (!block) {\n block = create_each_block(key, child_ctx);\n block.c();\n }\n else if (dynamic) {\n // defer updates until all the DOM shuffling is done\n updates.push(() => block.p(child_ctx, dirty));\n }\n new_lookup.set(key, new_blocks[i] = block);\n if (key in old_indexes)\n deltas.set(key, Math.abs(i - old_indexes[key]));\n }\n const will_move = new Set();\n const did_move = new Set();\n function insert(block) {\n transition_in(block, 1);\n block.m(node, next);\n lookup.set(block.key, block);\n next = block.first;\n n--;\n }\n while (o && n) {\n const new_block = new_blocks[n - 1];\n const old_block = old_blocks[o - 1];\n const new_key = new_block.key;\n const old_key = old_block.key;\n if (new_block === old_block) {\n // do nothing\n next = new_block.first;\n o--;\n n--;\n }\n else if (!new_lookup.has(old_key)) {\n // remove old block\n destroy(old_block, lookup);\n o--;\n }\n else if (!lookup.has(new_key) || will_move.has(new_key)) {\n insert(new_block);\n }\n else if (did_move.has(old_key)) {\n o--;\n }\n else if (deltas.get(new_key) > deltas.get(old_key)) {\n did_move.add(new_key);\n insert(new_block);\n }\n else {\n will_move.add(old_key);\n o--;\n }\n }\n while (o--) {\n const old_block = old_blocks[o];\n if (!new_lookup.has(old_block.key))\n destroy(old_block, lookup);\n }\n while (n)\n insert(new_blocks[n - 1]);\n run_all(updates);\n return new_blocks;\n}\nfunction validate_each_keys(ctx, list, get_context, get_key) {\n const keys = new Set();\n for (let i = 0; i < list.length; i++) {\n const key = get_key(get_context(ctx, list, i));\n if (keys.has(key)) {\n throw new Error('Cannot have duplicate keys in a keyed each');\n }\n keys.add(key);\n }\n}\n\nfunction get_spread_update(levels, updates) {\n const update = {};\n const to_null_out = {};\n const accounted_for = { $$scope: 1 };\n let i = levels.length;\n while (i--) {\n const o = levels[i];\n const n = updates[i];\n if (n) {\n for (const key in o) {\n if (!(key in n))\n to_null_out[key] = 1;\n }\n for (const key in n) {\n if (!accounted_for[key]) {\n update[key] = n[key];\n accounted_for[key] = 1;\n }\n }\n levels[i] = n;\n }\n else {\n for (const key in o) {\n accounted_for[key] = 1;\n }\n }\n }\n for (const key in to_null_out) {\n if (!(key in update))\n update[key] = undefined;\n }\n return update;\n}\nfunction get_spread_object(spread_props) {\n return typeof spread_props === 'object' && spread_props !== null ? spread_props : {};\n}\n\nconst _boolean_attributes = [\n 'allowfullscreen',\n 'allowpaymentrequest',\n 'async',\n 'autofocus',\n 'autoplay',\n 'checked',\n 'controls',\n 'default',\n 'defer',\n 'disabled',\n 'formnovalidate',\n 'hidden',\n 'inert',\n 'ismap',\n 'loop',\n 'multiple',\n 'muted',\n 'nomodule',\n 'novalidate',\n 'open',\n 'playsinline',\n 'readonly',\n 'required',\n 'reversed',\n 'selected'\n];\n/**\n * List of HTML boolean attributes (e.g. ``).\n * Source: https://html.spec.whatwg.org/multipage/indices.html\n */\nconst boolean_attributes = new Set([..._boolean_attributes]);\n\n/** regex of all html void element names */\nconst void_element_names = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;\nfunction is_void(name) {\n return void_element_names.test(name) || name.toLowerCase() === '!doctype';\n}\n\nconst invalid_attribute_name_character = /[\\s'\">/=\\u{FDD0}-\\u{FDEF}\\u{FFFE}\\u{FFFF}\\u{1FFFE}\\u{1FFFF}\\u{2FFFE}\\u{2FFFF}\\u{3FFFE}\\u{3FFFF}\\u{4FFFE}\\u{4FFFF}\\u{5FFFE}\\u{5FFFF}\\u{6FFFE}\\u{6FFFF}\\u{7FFFE}\\u{7FFFF}\\u{8FFFE}\\u{8FFFF}\\u{9FFFE}\\u{9FFFF}\\u{AFFFE}\\u{AFFFF}\\u{BFFFE}\\u{BFFFF}\\u{CFFFE}\\u{CFFFF}\\u{DFFFE}\\u{DFFFF}\\u{EFFFE}\\u{EFFFF}\\u{FFFFE}\\u{FFFFF}\\u{10FFFE}\\u{10FFFF}]/u;\n// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n// https://infra.spec.whatwg.org/#noncharacter\nfunction spread(args, attrs_to_add) {\n const attributes = Object.assign({}, ...args);\n if (attrs_to_add) {\n const classes_to_add = attrs_to_add.classes;\n const styles_to_add = attrs_to_add.styles;\n if (classes_to_add) {\n if (attributes.class == null) {\n attributes.class = classes_to_add;\n }\n else {\n attributes.class += ' ' + classes_to_add;\n }\n }\n if (styles_to_add) {\n if (attributes.style == null) {\n attributes.style = style_object_to_string(styles_to_add);\n }\n else {\n attributes.style = style_object_to_string(merge_ssr_styles(attributes.style, styles_to_add));\n }\n }\n }\n let str = '';\n Object.keys(attributes).forEach(name => {\n if (invalid_attribute_name_character.test(name))\n return;\n const value = attributes[name];\n if (value === true)\n str += ' ' + name;\n else if (boolean_attributes.has(name.toLowerCase())) {\n if (value)\n str += ' ' + name;\n }\n else if (value != null) {\n str += ` ${name}=\"${value}\"`;\n }\n });\n return str;\n}\nfunction merge_ssr_styles(style_attribute, style_directive) {\n const style_object = {};\n for (const individual_style of style_attribute.split(';')) {\n const colon_index = individual_style.indexOf(':');\n const name = individual_style.slice(0, colon_index).trim();\n const value = individual_style.slice(colon_index + 1).trim();\n if (!name)\n continue;\n style_object[name] = value;\n }\n for (const name in style_directive) {\n const value = style_directive[name];\n if (value) {\n style_object[name] = value;\n }\n else {\n delete style_object[name];\n }\n }\n return style_object;\n}\nconst ATTR_REGEX = /[&\"]/g;\nconst CONTENT_REGEX = /[&<]/g;\n/**\n * Note: this method is performance sensitive and has been optimized\n * https://github.com/sveltejs/svelte/pull/5701\n */\nfunction escape(value, is_attr = false) {\n const str = String(value);\n const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX;\n pattern.lastIndex = 0;\n let escaped = '';\n let last = 0;\n while (pattern.test(str)) {\n const i = pattern.lastIndex - 1;\n const ch = str[i];\n escaped += str.substring(last, i) + (ch === '&' ? '&' : (ch === '\"' ? '"' : '<'));\n last = i + 1;\n }\n return escaped + str.substring(last);\n}\nfunction escape_attribute_value(value) {\n // keep booleans, null, and undefined for the sake of `spread`\n const should_escape = typeof value === 'string' || (value && typeof value === 'object');\n return should_escape ? escape(value, true) : value;\n}\nfunction escape_object(obj) {\n const result = {};\n for (const key in obj) {\n result[key] = escape_attribute_value(obj[key]);\n }\n return result;\n}\nfunction each(items, fn) {\n let str = '';\n for (let i = 0; i < items.length; i += 1) {\n str += fn(items[i], i);\n }\n return str;\n}\nconst missing_component = {\n $$render: () => ''\n};\nfunction validate_component(component, name) {\n if (!component || !component.$$render) {\n if (name === 'svelte:component')\n name += ' this={...}';\n throw new Error(`<${name}> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules. Otherwise you may need to fix a <${name}>.`);\n }\n return component;\n}\nfunction debug(file, line, column, values) {\n console.log(`{@debug} ${file ? file + ' ' : ''}(${line}:${column})`); // eslint-disable-line no-console\n console.log(values); // eslint-disable-line no-console\n return '';\n}\nlet on_destroy;\nfunction create_ssr_component(fn) {\n function $$render(result, props, bindings, slots, context) {\n const parent_component = current_component;\n const $$ = {\n on_destroy,\n context: new Map(context || (parent_component ? parent_component.$$.context : [])),\n // these will be immediately discarded\n on_mount: [],\n before_update: [],\n after_update: [],\n callbacks: blank_object()\n };\n set_current_component({ $$ });\n const html = fn(result, props, bindings, slots);\n set_current_component(parent_component);\n return html;\n }\n return {\n render: (props = {}, { $$slots = {}, context = new Map() } = {}) => {\n on_destroy = [];\n const result = { title: '', head: '', css: new Set() };\n const html = $$render(result, props, {}, $$slots, context);\n run_all(on_destroy);\n return {\n html,\n css: {\n code: Array.from(result.css).map(css => css.code).join('\\n'),\n map: null // TODO\n },\n head: result.title + result.head\n };\n },\n $$render\n };\n}\nfunction add_attribute(name, value, boolean) {\n if (value == null || (boolean && !value))\n return '';\n const assignment = (boolean && value === true) ? '' : `=\"${escape(value, true)}\"`;\n return ` ${name}${assignment}`;\n}\nfunction add_classes(classes) {\n return classes ? ` class=\"${classes}\"` : '';\n}\nfunction style_object_to_string(style_object) {\n return Object.keys(style_object)\n .filter(key => style_object[key])\n .map(key => `${key}: ${escape_attribute_value(style_object[key])};`)\n .join(' ');\n}\nfunction add_styles(style_object) {\n const styles = style_object_to_string(style_object);\n return styles ? ` style=\"${styles}\"` : '';\n}\n\nfunction bind(component, name, callback) {\n const index = component.$$.props[name];\n if (index !== undefined) {\n component.$$.bound[index] = callback;\n callback(component.$$.ctx[index]);\n }\n}\nfunction create_component(block) {\n block && block.c();\n}\nfunction claim_component(block, parent_nodes) {\n block && block.l(parent_nodes);\n}\nfunction mount_component(component, target, anchor, customElement) {\n const { fragment, after_update } = component.$$;\n fragment && fragment.m(target, anchor);\n if (!customElement) {\n // onMount happens before the initial afterUpdate\n add_render_callback(() => {\n const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);\n // if the component was destroyed immediately\n // it will update the `$$.on_destroy` reference to `null`.\n // the destructured on_destroy may still reference to the old array\n if (component.$$.on_destroy) {\n component.$$.on_destroy.push(...new_on_destroy);\n }\n else {\n // Edge case - component was destroyed immediately,\n // most likely as a result of a binding initialising\n run_all(new_on_destroy);\n }\n component.$$.on_mount = [];\n });\n }\n after_update.forEach(add_render_callback);\n}\nfunction destroy_component(component, detaching) {\n const $$ = component.$$;\n if ($$.fragment !== null) {\n flush_render_callbacks($$.after_update);\n run_all($$.on_destroy);\n $$.fragment && $$.fragment.d(detaching);\n // TODO null out other refs, including component.$$ (but need to\n // preserve final state?)\n $$.on_destroy = $$.fragment = null;\n $$.ctx = [];\n }\n}\nfunction make_dirty(component, i) {\n if (component.$$.dirty[0] === -1) {\n dirty_components.push(component);\n schedule_update();\n component.$$.dirty.fill(0);\n }\n component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));\n}\nfunction init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {\n const parent_component = current_component;\n set_current_component(component);\n const $$ = component.$$ = {\n fragment: null,\n ctx: [],\n // state\n props,\n update: noop,\n not_equal,\n bound: blank_object(),\n // lifecycle\n on_mount: [],\n on_destroy: [],\n on_disconnect: [],\n before_update: [],\n after_update: [],\n context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),\n // everything else\n callbacks: blank_object(),\n dirty,\n skip_bound: false,\n root: options.target || parent_component.$$.root\n };\n append_styles && append_styles($$.root);\n let ready = false;\n $$.ctx = instance\n ? instance(component, options.props || {}, (i, ret, ...rest) => {\n const value = rest.length ? rest[0] : ret;\n if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {\n if (!$$.skip_bound && $$.bound[i])\n $$.bound[i](value);\n if (ready)\n make_dirty(component, i);\n }\n return ret;\n })\n : [];\n $$.update();\n ready = true;\n run_all($$.before_update);\n // `false` as a special case of no DOM component\n $$.fragment = create_fragment ? create_fragment($$.ctx) : false;\n if (options.target) {\n if (options.hydrate) {\n start_hydrating();\n const nodes = children(options.target);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n $$.fragment && $$.fragment.l(nodes);\n nodes.forEach(detach);\n }\n else {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n $$.fragment && $$.fragment.c();\n }\n if (options.intro)\n transition_in(component.$$.fragment);\n mount_component(component, options.target, options.anchor, options.customElement);\n end_hydrating();\n flush();\n }\n set_current_component(parent_component);\n}\nlet SvelteElement;\nif (typeof HTMLElement === 'function') {\n SvelteElement = class extends HTMLElement {\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n }\n connectedCallback() {\n const { on_mount } = this.$$;\n this.$$.on_disconnect = on_mount.map(run).filter(is_function);\n // @ts-ignore todo: improve typings\n for (const key in this.$$.slotted) {\n // @ts-ignore todo: improve typings\n this.appendChild(this.$$.slotted[key]);\n }\n }\n attributeChangedCallback(attr, _oldValue, newValue) {\n this[attr] = newValue;\n }\n disconnectedCallback() {\n run_all(this.$$.on_disconnect);\n }\n $destroy() {\n destroy_component(this, 1);\n this.$destroy = noop;\n }\n $on(type, callback) {\n // TODO should this delegate to addEventListener?\n if (!is_function(callback)) {\n return noop;\n }\n const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));\n callbacks.push(callback);\n return () => {\n const index = callbacks.indexOf(callback);\n if (index !== -1)\n callbacks.splice(index, 1);\n };\n }\n $set($$props) {\n if (this.$$set && !is_empty($$props)) {\n this.$$.skip_bound = true;\n this.$$set($$props);\n this.$$.skip_bound = false;\n }\n }\n };\n}\n/**\n * Base class for Svelte components. Used when dev=false.\n */\nclass SvelteComponent {\n $destroy() {\n destroy_component(this, 1);\n this.$destroy = noop;\n }\n $on(type, callback) {\n if (!is_function(callback)) {\n return noop;\n }\n const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));\n callbacks.push(callback);\n return () => {\n const index = callbacks.indexOf(callback);\n if (index !== -1)\n callbacks.splice(index, 1);\n };\n }\n $set($$props) {\n if (this.$$set && !is_empty($$props)) {\n this.$$.skip_bound = true;\n this.$$set($$props);\n this.$$.skip_bound = false;\n }\n }\n}\n\nfunction dispatch_dev(type, detail) {\n document.dispatchEvent(custom_event(type, Object.assign({ version: '3.59.2' }, detail), { bubbles: true }));\n}\nfunction append_dev(target, node) {\n dispatch_dev('SvelteDOMInsert', { target, node });\n append(target, node);\n}\nfunction append_hydration_dev(target, node) {\n dispatch_dev('SvelteDOMInsert', { target, node });\n append_hydration(target, node);\n}\nfunction insert_dev(target, node, anchor) {\n dispatch_dev('SvelteDOMInsert', { target, node, anchor });\n insert(target, node, anchor);\n}\nfunction insert_hydration_dev(target, node, anchor) {\n dispatch_dev('SvelteDOMInsert', { target, node, anchor });\n insert_hydration(target, node, anchor);\n}\nfunction detach_dev(node) {\n dispatch_dev('SvelteDOMRemove', { node });\n detach(node);\n}\nfunction detach_between_dev(before, after) {\n while (before.nextSibling && before.nextSibling !== after) {\n detach_dev(before.nextSibling);\n }\n}\nfunction detach_before_dev(after) {\n while (after.previousSibling) {\n detach_dev(after.previousSibling);\n }\n}\nfunction detach_after_dev(before) {\n while (before.nextSibling) {\n detach_dev(before.nextSibling);\n }\n}\nfunction listen_dev(node, event, handler, options, has_prevent_default, has_stop_propagation, has_stop_immediate_propagation) {\n const modifiers = options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : [];\n if (has_prevent_default)\n modifiers.push('preventDefault');\n if (has_stop_propagation)\n modifiers.push('stopPropagation');\n if (has_stop_immediate_propagation)\n modifiers.push('stopImmediatePropagation');\n dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers });\n const dispose = listen(node, event, handler, options);\n return () => {\n dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers });\n dispose();\n };\n}\nfunction attr_dev(node, attribute, value) {\n attr(node, attribute, value);\n if (value == null)\n dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute });\n else\n dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value });\n}\nfunction prop_dev(node, property, value) {\n node[property] = value;\n dispatch_dev('SvelteDOMSetProperty', { node, property, value });\n}\nfunction dataset_dev(node, property, value) {\n node.dataset[property] = value;\n dispatch_dev('SvelteDOMSetDataset', { node, property, value });\n}\nfunction set_data_dev(text, data) {\n data = '' + data;\n if (text.data === data)\n return;\n dispatch_dev('SvelteDOMSetData', { node: text, data });\n text.data = data;\n}\nfunction set_data_contenteditable_dev(text, data) {\n data = '' + data;\n if (text.wholeText === data)\n return;\n dispatch_dev('SvelteDOMSetData', { node: text, data });\n text.data = data;\n}\nfunction set_data_maybe_contenteditable_dev(text, data, attr_value) {\n if (~contenteditable_truthy_values.indexOf(attr_value)) {\n set_data_contenteditable_dev(text, data);\n }\n else {\n set_data_dev(text, data);\n }\n}\nfunction validate_each_argument(arg) {\n if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) {\n let msg = '{#each} only iterates over array-like objects.';\n if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) {\n msg += ' You can use a spread to convert this iterable into an array.';\n }\n throw new Error(msg);\n }\n}\nfunction validate_slots(name, slot, keys) {\n for (const slot_key of Object.keys(slot)) {\n if (!~keys.indexOf(slot_key)) {\n console.warn(`<${name}> received an unexpected slot \"${slot_key}\".`);\n }\n }\n}\nfunction validate_dynamic_element(tag) {\n const is_string = typeof tag === 'string';\n if (tag && !is_string) {\n throw new Error(' expects \"this\" attribute to be a string.');\n }\n}\nfunction validate_void_dynamic_element(tag) {\n if (tag && is_void(tag)) {\n console.warn(` is self-closing and cannot have content.`);\n }\n}\nfunction construct_svelte_component_dev(component, props) {\n const error_message = 'this={...} of should specify a Svelte component.';\n try {\n const instance = new component(props);\n if (!instance.$$ || !instance.$set || !instance.$on || !instance.$destroy) {\n throw new Error(error_message);\n }\n return instance;\n }\n catch (err) {\n const { message } = err;\n if (typeof message === 'string' && message.indexOf('is not a constructor') !== -1) {\n throw new Error(error_message);\n }\n else {\n throw err;\n }\n }\n}\n/**\n * Base class for Svelte components with some minor dev-enhancements. Used when dev=true.\n */\nclass SvelteComponentDev extends SvelteComponent {\n constructor(options) {\n if (!options || (!options.target && !options.$$inline)) {\n throw new Error(\"'target' is a required option\");\n }\n super();\n }\n $destroy() {\n super.$destroy();\n this.$destroy = () => {\n console.warn('Component was already destroyed'); // eslint-disable-line no-console\n };\n }\n $capture_state() { }\n $inject_state() { }\n}\n/**\n * Base class to create strongly typed Svelte components.\n * This only exists for typing purposes and should be used in `.d.ts` files.\n *\n * ### Example:\n *\n * You have component library on npm called `component-library`, from which\n * you export a component called `MyComponent`. For Svelte+TypeScript users,\n * you want to provide typings. Therefore you create a `index.d.ts`:\n * ```ts\n * import { SvelteComponentTyped } from \"svelte\";\n * export class MyComponent extends SvelteComponentTyped<{foo: string}> {}\n * ```\n * Typing this makes it possible for IDEs like VS Code with the Svelte extension\n * to provide intellisense and to use the component like this in a Svelte file\n * with TypeScript:\n * ```svelte\n * \n * \n * ```\n *\n * #### Why not make this part of `SvelteComponent(Dev)`?\n * Because\n * ```ts\n * class ASubclassOfSvelteComponent extends SvelteComponent<{foo: string}> {}\n * const component: typeof SvelteComponent = ASubclassOfSvelteComponent;\n * ```\n * will throw a type error, so we need to separate the more strictly typed class.\n */\nclass SvelteComponentTyped extends SvelteComponentDev {\n constructor(options) {\n super(options);\n }\n}\nfunction loop_guard(timeout) {\n const start = Date.now();\n return () => {\n if (Date.now() - start > timeout) {\n throw new Error('Infinite loop detected');\n }\n };\n}\n\nexport { HtmlTag, HtmlTagHydration, ResizeObserverSingleton, SvelteComponent, SvelteComponentDev, SvelteComponentTyped, SvelteElement, action_destroyer, add_attribute, add_classes, add_flush_callback, add_iframe_resize_listener, add_location, add_render_callback, add_styles, add_transform, afterUpdate, append, append_dev, append_empty_stylesheet, append_hydration, append_hydration_dev, append_styles, assign, attr, attr_dev, attribute_to_object, beforeUpdate, bind, binding_callbacks, blank_object, bubble, check_outros, children, claim_comment, claim_component, claim_element, claim_html_tag, claim_space, claim_svg_element, claim_text, clear_loops, comment, component_subscribe, compute_rest_props, compute_slots, construct_svelte_component, construct_svelte_component_dev, contenteditable_truthy_values, createEventDispatcher, create_animation, create_bidirectional_transition, create_component, create_in_transition, create_out_transition, create_slot, create_ssr_component, current_component, custom_event, dataset_dev, debug, destroy_block, destroy_component, destroy_each, detach, detach_after_dev, detach_before_dev, detach_between_dev, detach_dev, dirty_components, dispatch_dev, each, element, element_is, empty, end_hydrating, escape, escape_attribute_value, escape_object, exclude_internal_props, fix_and_destroy_block, fix_and_outro_and_destroy_block, fix_position, flush, flush_render_callbacks, getAllContexts, getContext, get_all_dirty_from_scope, get_binding_group_value, get_current_component, get_custom_elements_slots, get_root_for_style, get_slot_changes, get_spread_object, get_spread_update, get_store_value, globals, group_outros, handle_promise, hasContext, has_prop, head_selector, identity, init, init_binding_group, init_binding_group_dynamic, insert, insert_dev, insert_hydration, insert_hydration_dev, intros, invalid_attribute_name_character, is_client, is_crossorigin, is_empty, is_function, is_promise, is_void, listen, listen_dev, loop, loop_guard, merge_ssr_styles, missing_component, mount_component, noop, not_equal, now, null_to_empty, object_without_properties, onDestroy, onMount, once, outro_and_destroy_block, prevent_default, prop_dev, query_selector_all, raf, resize_observer_border_box, resize_observer_content_box, resize_observer_device_pixel_content_box, run, run_all, safe_not_equal, schedule_update, select_multiple_value, select_option, select_options, select_value, self, setContext, set_attributes, set_current_component, set_custom_element_data, set_custom_element_data_map, set_data, set_data_contenteditable, set_data_contenteditable_dev, set_data_dev, set_data_maybe_contenteditable, set_data_maybe_contenteditable_dev, set_dynamic_element_data, set_input_type, set_input_value, set_now, set_raf, set_store_value, set_style, set_svg_attributes, space, split_css_unit, spread, src_url_equal, start_hydrating, stop_immediate_propagation, stop_propagation, subscribe, svg_element, text, tick, time_ranges_to_array, to_number, toggle_class, transition_in, transition_out, trusted, update_await_block_branch, update_keyed_each, update_slot, update_slot_base, validate_component, validate_dynamic_element, validate_each_argument, validate_each_keys, validate_slots, validate_store, validate_void_dynamic_element, xlink_attr };\n","function number(n) {\n if (!Number.isSafeInteger(n) || n < 0)\n throw new Error(`Wrong positive integer: ${n}`);\n}\nfunction bool(b) {\n if (typeof b !== 'boolean')\n throw new Error(`Expected boolean, not ${b}`);\n}\nfunction bytes(b, ...lengths) {\n if (!(b instanceof Uint8Array))\n throw new Error('Expected Uint8Array');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);\n}\nfunction hash(hash) {\n if (typeof hash !== 'function' || typeof hash.create !== 'function')\n throw new Error('Hash should be wrapped by utils.wrapConstructor');\n number(hash.outputLen);\n number(hash.blockLen);\n}\nfunction exists(instance, checkFinished = true) {\n if (instance.destroyed)\n throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished)\n throw new Error('Hash#digest() has already been called');\n}\nfunction output(out, instance) {\n bytes(out);\n const min = instance.outputLen;\n if (out.length < min) {\n throw new Error(`digestInto() expects output buffer of length at least ${min}`);\n }\n}\nexport { number, bool, bytes, hash, exists, output };\nconst assert = { number, bool, bytes, hash, exists, output };\nexport default assert;\n//# sourceMappingURL=_assert.js.map","export const crypto = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;\n//# sourceMappingURL=crypto.js.map","/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// node.js versions earlier than v19 don't declare it in global scope.\n// For node.js, package.json#exports field mapping rewrites import\n// from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated, we can just drop the import.\nimport { crypto } from '@noble/hashes/crypto';\nconst u8a = (a) => a instanceof Uint8Array;\n// Cast array to different type\nexport const u8 = (arr) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\nexport const u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n// Cast array to view\nexport const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n// The rotate right (circular right shift) operation for uint32\nexport const rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);\n// big-endian hardware is rare. Just in case someone still decides to run hashes:\n// early-throw an error because we don't support BE yet.\nexport const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;\nif (!isLE)\n throw new Error('Non little-endian hardware is not supported');\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));\n/**\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes) {\n if (!u8a(bytes))\n throw new Error('Uint8Array expected');\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n/**\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n const len = hex.length;\n if (len % 2)\n throw new Error('padded hex string expected, got unpadded hex of length ' + len);\n const array = new Uint8Array(len / 2);\n for (let i = 0; i < array.length; i++) {\n const j = i * 2;\n const hexByte = hex.slice(j, j + 2);\n const byte = Number.parseInt(hexByte, 16);\n if (Number.isNaN(byte) || byte < 0)\n throw new Error('Invalid byte sequence');\n array[i] = byte;\n }\n return array;\n}\n// There is no setImmediate in browser and setTimeout is slow.\n// call of async fn will return Promise, which will be fullfiled only on\n// next scheduler queue processing step and this is exactly what we need.\nexport const nextTick = async () => { };\n// Returns control to thread each 'tick' ms to avoid blocking\nexport async function asyncLoop(iters, tick, cb) {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick)\n continue;\n await nextTick();\n ts += diff;\n }\n}\n/**\n * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])\n */\nexport function utf8ToBytes(str) {\n if (typeof str !== 'string')\n throw new Error(`utf8ToBytes expected string, got ${typeof str}`);\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data) {\n if (typeof data === 'string')\n data = utf8ToBytes(data);\n if (!u8a(data))\n throw new Error(`expected Uint8Array, got ${typeof data}`);\n return data;\n}\n/**\n * Copies several Uint8Arrays into one.\n */\nexport function concatBytes(...arrays) {\n const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));\n let pad = 0; // walk through each item, ensure they have proper type\n arrays.forEach((a) => {\n if (!u8a(a))\n throw new Error('Uint8Array expected');\n r.set(a, pad);\n pad += a.length;\n });\n return r;\n}\n// For runtime check if class implements interface\nexport class Hash {\n // Safe version that clones internal state\n clone() {\n return this._cloneInto();\n }\n}\nconst toStr = {}.toString;\nexport function checkOpts(defaults, opts) {\n if (opts !== undefined && toStr.call(opts) !== '[object Object]')\n throw new Error('Options should be object or undefined');\n const merged = Object.assign(defaults, opts);\n return merged;\n}\nexport function wrapConstructor(hashCons) {\n const hashC = (msg) => hashCons().update(toBytes(msg)).digest();\n const tmp = hashCons();\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = () => hashCons();\n return hashC;\n}\nexport function wrapConstructorWithOpts(hashCons) {\n const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({});\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts) => hashCons(opts);\n return hashC;\n}\nexport function wrapXOFConstructorWithOpts(hashCons) {\n const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({});\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts) => hashCons(opts);\n return hashC;\n}\n/**\n * Secure PRNG. Uses `crypto.getRandomValues`, which defers to OS.\n */\nexport function randomBytes(bytesLength = 32) {\n if (crypto && typeof crypto.getRandomValues === 'function') {\n return crypto.getRandomValues(new Uint8Array(bytesLength));\n }\n throw new Error('crypto.getRandomValues must be defined');\n}\n//# sourceMappingURL=utils.js.map","import { exists, output } from './_assert.js';\nimport { Hash, createView, toBytes } from './utils.js';\n// Polyfill for Safari 14\nfunction setBigUint64(view, byteOffset, value, isLE) {\n if (typeof view.setBigUint64 === 'function')\n return view.setBigUint64(byteOffset, value, isLE);\n const _32n = BigInt(32);\n const _u32_max = BigInt(0xffffffff);\n const wh = Number((value >> _32n) & _u32_max);\n const wl = Number(value & _u32_max);\n const h = isLE ? 4 : 0;\n const l = isLE ? 0 : 4;\n view.setUint32(byteOffset + h, wh, isLE);\n view.setUint32(byteOffset + l, wl, isLE);\n}\n// Base SHA2 class (RFC 6234)\nexport class SHA2 extends Hash {\n constructor(blockLen, outputLen, padOffset, isLE) {\n super();\n this.blockLen = blockLen;\n this.outputLen = outputLen;\n this.padOffset = padOffset;\n this.isLE = isLE;\n this.finished = false;\n this.length = 0;\n this.pos = 0;\n this.destroyed = false;\n this.buffer = new Uint8Array(blockLen);\n this.view = createView(this.buffer);\n }\n update(data) {\n exists(this);\n const { view, buffer, blockLen } = this;\n data = toBytes(data);\n const len = data.length;\n for (let pos = 0; pos < len;) {\n const take = Math.min(blockLen - this.pos, len - pos);\n // Fast path: we have at least one block in input, cast it to view and process\n if (take === blockLen) {\n const dataView = createView(data);\n for (; blockLen <= len - pos; pos += blockLen)\n this.process(dataView, pos);\n continue;\n }\n buffer.set(data.subarray(pos, pos + take), this.pos);\n this.pos += take;\n pos += take;\n if (this.pos === blockLen) {\n this.process(view, 0);\n this.pos = 0;\n }\n }\n this.length += data.length;\n this.roundClean();\n return this;\n }\n digestInto(out) {\n exists(this);\n output(out, this);\n this.finished = true;\n // Padding\n // We can avoid allocation of buffer for padding completely if it\n // was previously not allocated here. But it won't change performance.\n const { buffer, view, blockLen, isLE } = this;\n let { pos } = this;\n // append the bit '1' to the message\n buffer[pos++] = 0b10000000;\n this.buffer.subarray(pos).fill(0);\n // we have less than padOffset left in buffer, so we cannot put length in current block, need process it and pad again\n if (this.padOffset > blockLen - pos) {\n this.process(view, 0);\n pos = 0;\n }\n // Pad until full block byte with zeros\n for (let i = pos; i < blockLen; i++)\n buffer[i] = 0;\n // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that\n // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.\n // So we just write lowest 64 bits of that value.\n setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);\n this.process(view, 0);\n const oview = createView(out);\n const len = this.outputLen;\n // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT\n if (len % 4)\n throw new Error('_sha2: outputLen should be aligned to 32bit');\n const outLen = len / 4;\n const state = this.get();\n if (outLen > state.length)\n throw new Error('_sha2: outputLen bigger than state');\n for (let i = 0; i < outLen; i++)\n oview.setUint32(4 * i, state[i], isLE);\n }\n digest() {\n const { buffer, outputLen } = this;\n this.digestInto(buffer);\n const res = buffer.slice(0, outputLen);\n this.destroy();\n return res;\n }\n _cloneInto(to) {\n to || (to = new this.constructor());\n to.set(...this.get());\n const { blockLen, buffer, length, finished, destroyed, pos } = this;\n to.length = length;\n to.pos = pos;\n to.finished = finished;\n to.destroyed = destroyed;\n if (length % blockLen)\n to.buffer.set(buffer);\n return to;\n }\n}\n//# sourceMappingURL=_sha2.js.map","import { SHA2 } from './_sha2.js';\nimport { rotr, wrapConstructor } from './utils.js';\n// SHA2-256 need to try 2^128 hashes to execute birthday attack.\n// BTC network is doing 2^67 hashes/sec as per early 2023.\n// Choice: a ? b : c\nconst Chi = (a, b, c) => (a & b) ^ (~a & c);\n// Majority function, true if any two inpust is true\nconst Maj = (a, b, c) => (a & b) ^ (a & c) ^ (b & c);\n// Round constants:\n// first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)\n// prettier-ignore\nconst SHA256_K = /* @__PURE__ */ new Uint32Array([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n]);\n// Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):\n// prettier-ignore\nconst IV = /* @__PURE__ */ new Uint32Array([\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19\n]);\n// Temporary buffer, not used to store anything between runs\n// Named this way because it matches specification.\nconst SHA256_W = /* @__PURE__ */ new Uint32Array(64);\nclass SHA256 extends SHA2 {\n constructor() {\n super(64, 32, 8, false);\n // We cannot use array here since array allows indexing by variable\n // which means optimizer/compiler cannot use registers.\n this.A = IV[0] | 0;\n this.B = IV[1] | 0;\n this.C = IV[2] | 0;\n this.D = IV[3] | 0;\n this.E = IV[4] | 0;\n this.F = IV[5] | 0;\n this.G = IV[6] | 0;\n this.H = IV[7] | 0;\n }\n get() {\n const { A, B, C, D, E, F, G, H } = this;\n return [A, B, C, D, E, F, G, H];\n }\n // prettier-ignore\n set(A, B, C, D, E, F, G, H) {\n this.A = A | 0;\n this.B = B | 0;\n this.C = C | 0;\n this.D = D | 0;\n this.E = E | 0;\n this.F = F | 0;\n this.G = G | 0;\n this.H = H | 0;\n }\n process(view, offset) {\n // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4)\n SHA256_W[i] = view.getUint32(offset, false);\n for (let i = 16; i < 64; i++) {\n const W15 = SHA256_W[i - 15];\n const W2 = SHA256_W[i - 2];\n const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);\n const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);\n SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;\n }\n // Compression function main loop, 64 rounds\n let { A, B, C, D, E, F, G, H } = this;\n for (let i = 0; i < 64; i++) {\n const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);\n const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);\n const T2 = (sigma0 + Maj(A, B, C)) | 0;\n H = G;\n G = F;\n F = E;\n E = (D + T1) | 0;\n D = C;\n C = B;\n B = A;\n A = (T1 + T2) | 0;\n }\n // Add the compressed chunk to the current hash value\n A = (A + this.A) | 0;\n B = (B + this.B) | 0;\n C = (C + this.C) | 0;\n D = (D + this.D) | 0;\n E = (E + this.E) | 0;\n F = (F + this.F) | 0;\n G = (G + this.G) | 0;\n H = (H + this.H) | 0;\n this.set(A, B, C, D, E, F, G, H);\n }\n roundClean() {\n SHA256_W.fill(0);\n }\n destroy() {\n this.set(0, 0, 0, 0, 0, 0, 0, 0);\n this.buffer.fill(0);\n }\n}\n// Constants from https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf\nclass SHA224 extends SHA256 {\n constructor() {\n super();\n this.A = 0xc1059ed8 | 0;\n this.B = 0x367cd507 | 0;\n this.C = 0x3070dd17 | 0;\n this.D = 0xf70e5939 | 0;\n this.E = 0xffc00b31 | 0;\n this.F = 0x68581511 | 0;\n this.G = 0x64f98fa7 | 0;\n this.H = 0xbefa4fa4 | 0;\n this.outputLen = 28;\n }\n}\n/**\n * SHA2-256 hash function\n * @param message - data that would be hashed\n */\nexport const sha256 = /* @__PURE__ */ wrapConstructor(() => new SHA256());\nexport const sha224 = /* @__PURE__ */ wrapConstructor(() => new SHA224());\n//# sourceMappingURL=sha256.js.map","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// 100 lines of code in the file are duplicated from noble-hashes (utils).\n// This is OK: `abstract` directory does not use noble-hashes.\n// User may opt-in into using different hashing library. This way, noble-hashes\n// won't be included into their bundle.\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nconst u8a = (a) => a instanceof Uint8Array;\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));\n/**\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes) {\n if (!u8a(bytes))\n throw new Error('Uint8Array expected');\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\nexport function numberToHexUnpadded(num) {\n const hex = num.toString(16);\n return hex.length & 1 ? `0${hex}` : hex;\n}\nexport function hexToNumber(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n // Big Endian\n return BigInt(hex === '' ? '0' : `0x${hex}`);\n}\n/**\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n const len = hex.length;\n if (len % 2)\n throw new Error('padded hex string expected, got unpadded hex of length ' + len);\n const array = new Uint8Array(len / 2);\n for (let i = 0; i < array.length; i++) {\n const j = i * 2;\n const hexByte = hex.slice(j, j + 2);\n const byte = Number.parseInt(hexByte, 16);\n if (Number.isNaN(byte) || byte < 0)\n throw new Error('Invalid byte sequence');\n array[i] = byte;\n }\n return array;\n}\n// BE: Big Endian, LE: Little Endian\nexport function bytesToNumberBE(bytes) {\n return hexToNumber(bytesToHex(bytes));\n}\nexport function bytesToNumberLE(bytes) {\n if (!u8a(bytes))\n throw new Error('Uint8Array expected');\n return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));\n}\nexport function numberToBytesBE(n, len) {\n return hexToBytes(n.toString(16).padStart(len * 2, '0'));\n}\nexport function numberToBytesLE(n, len) {\n return numberToBytesBE(n, len).reverse();\n}\n// Unpadded, rarely used\nexport function numberToVarBytesBE(n) {\n return hexToBytes(numberToHexUnpadded(n));\n}\n/**\n * Takes hex string or Uint8Array, converts to Uint8Array.\n * Validates output length.\n * Will throw error for other types.\n * @param title descriptive title for an error e.g. 'private key'\n * @param hex hex string or Uint8Array\n * @param expectedLength optional, will compare to result array's length\n * @returns\n */\nexport function ensureBytes(title, hex, expectedLength) {\n let res;\n if (typeof hex === 'string') {\n try {\n res = hexToBytes(hex);\n }\n catch (e) {\n throw new Error(`${title} must be valid hex string, got \"${hex}\". Cause: ${e}`);\n }\n }\n else if (u8a(hex)) {\n // Uint8Array.from() instead of hash.slice() because node.js Buffer\n // is instance of Uint8Array, and its slice() creates **mutable** copy\n res = Uint8Array.from(hex);\n }\n else {\n throw new Error(`${title} must be hex string or Uint8Array`);\n }\n const len = res.length;\n if (typeof expectedLength === 'number' && len !== expectedLength)\n throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);\n return res;\n}\n/**\n * Copies several Uint8Arrays into one.\n */\nexport function concatBytes(...arrays) {\n const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));\n let pad = 0; // walk through each item, ensure they have proper type\n arrays.forEach((a) => {\n if (!u8a(a))\n throw new Error('Uint8Array expected');\n r.set(a, pad);\n pad += a.length;\n });\n return r;\n}\nexport function equalBytes(b1, b2) {\n // We don't care about timing attacks here\n if (b1.length !== b2.length)\n return false;\n for (let i = 0; i < b1.length; i++)\n if (b1[i] !== b2[i])\n return false;\n return true;\n}\n/**\n * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])\n */\nexport function utf8ToBytes(str) {\n if (typeof str !== 'string')\n throw new Error(`utf8ToBytes expected string, got ${typeof str}`);\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n// Bit operations\n/**\n * Calculates amount of bits in a bigint.\n * Same as `n.toString(2).length`\n */\nexport function bitLen(n) {\n let len;\n for (len = 0; n > _0n; n >>= _1n, len += 1)\n ;\n return len;\n}\n/**\n * Gets single bit at position.\n * NOTE: first bit position is 0 (same as arrays)\n * Same as `!!+Array.from(n.toString(2)).reverse()[pos]`\n */\nexport function bitGet(n, pos) {\n return (n >> BigInt(pos)) & _1n;\n}\n/**\n * Sets single bit at position.\n */\nexport const bitSet = (n, pos, value) => {\n return n | ((value ? _1n : _0n) << BigInt(pos));\n};\n/**\n * Calculate mask for N bits. Not using ** operator with bigints because of old engines.\n * Same as BigInt(`0b${Array(i).fill('1').join('')}`)\n */\nexport const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;\n// DRBG\nconst u8n = (data) => new Uint8Array(data); // creates Uint8Array\nconst u8fr = (arr) => Uint8Array.from(arr); // another shortcut\n/**\n * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.\n * @returns function that will call DRBG until 2nd arg returns something meaningful\n * @example\n * const drbg = createHmacDRBG(32, 32, hmac);\n * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined\n */\nexport function createHmacDrbg(hashLen, qByteLen, hmacFn) {\n if (typeof hashLen !== 'number' || hashLen < 2)\n throw new Error('hashLen must be a number');\n if (typeof qByteLen !== 'number' || qByteLen < 2)\n throw new Error('qByteLen must be a number');\n if (typeof hmacFn !== 'function')\n throw new Error('hmacFn must be a function');\n // Step B, Step C: set hashLen to 8*ceil(hlen/8)\n let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.\n let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same\n let i = 0; // Iterations counter, will throw when over 1000\n const reset = () => {\n v.fill(1);\n k.fill(0);\n i = 0;\n };\n const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)\n const reseed = (seed = u8n()) => {\n // HMAC-DRBG reseed() function. Steps D-G\n k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)\n v = h(); // v = hmac(k || v)\n if (seed.length === 0)\n return;\n k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)\n v = h(); // v = hmac(k || v)\n };\n const gen = () => {\n // HMAC-DRBG generate() function\n if (i++ >= 1000)\n throw new Error('drbg: tried 1000 values');\n let len = 0;\n const out = [];\n while (len < qByteLen) {\n v = h();\n const sl = v.slice();\n out.push(sl);\n len += v.length;\n }\n return concatBytes(...out);\n };\n const genUntil = (seed, pred) => {\n reset();\n reseed(seed); // Steps D-G\n let res = undefined; // Step H: grind until k is in [1..n-1]\n while (!(res = pred(gen())))\n reseed();\n reset();\n return res;\n };\n return genUntil;\n}\n// Validating curves and fields\nconst validatorFns = {\n bigint: (val) => typeof val === 'bigint',\n function: (val) => typeof val === 'function',\n boolean: (val) => typeof val === 'boolean',\n string: (val) => typeof val === 'string',\n stringOrUint8Array: (val) => typeof val === 'string' || val instanceof Uint8Array,\n isSafeInteger: (val) => Number.isSafeInteger(val),\n array: (val) => Array.isArray(val),\n field: (val, object) => object.Fp.isValid(val),\n hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),\n};\n// type Record = { [P in K]: T; }\nexport function validateObject(object, validators, optValidators = {}) {\n const checkField = (fieldName, type, isOptional) => {\n const checkVal = validatorFns[type];\n if (typeof checkVal !== 'function')\n throw new Error(`Invalid validator \"${type}\", expected function`);\n const val = object[fieldName];\n if (isOptional && val === undefined)\n return;\n if (!checkVal(val, object)) {\n throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);\n }\n };\n for (const [fieldName, type] of Object.entries(validators))\n checkField(fieldName, type, false);\n for (const [fieldName, type] of Object.entries(optValidators))\n checkField(fieldName, type, true);\n return object;\n}\n// validate type tests\n// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };\n// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!\n// // Should fail type-check\n// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });\n// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });\n// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });\n// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });\n//# sourceMappingURL=utils.js.map","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Utilities for modular arithmetics and finite fields\nimport { bitMask, numberToBytesBE, numberToBytesLE, bytesToNumberBE, bytesToNumberLE, ensureBytes, validateObject, } from './utils.js';\n// prettier-ignore\nconst _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);\n// prettier-ignore\nconst _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);\n// prettier-ignore\nconst _9n = BigInt(9), _16n = BigInt(16);\n// Calculates a modulo b\nexport function mod(a, b) {\n const result = a % b;\n return result >= _0n ? result : b + result;\n}\n/**\n * Efficiently raise num to power and do modular division.\n * Unsafe in some contexts: uses ladder, so can expose bigint bits.\n * @example\n * pow(2n, 6n, 11n) // 64n % 11n == 9n\n */\n// TODO: use field version && remove\nexport function pow(num, power, modulo) {\n if (modulo <= _0n || power < _0n)\n throw new Error('Expected power/modulo > 0');\n if (modulo === _1n)\n return _0n;\n let res = _1n;\n while (power > _0n) {\n if (power & _1n)\n res = (res * num) % modulo;\n num = (num * num) % modulo;\n power >>= _1n;\n }\n return res;\n}\n// Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)\nexport function pow2(x, power, modulo) {\n let res = x;\n while (power-- > _0n) {\n res *= res;\n res %= modulo;\n }\n return res;\n}\n// Inverses number over modulo\nexport function invert(number, modulo) {\n if (number === _0n || modulo <= _0n) {\n throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);\n }\n // Euclidean GCD https://brilliant.org/wiki/extended-euclidean-algorithm/\n // Fermat's little theorem \"CT-like\" version inv(n) = n^(m-2) mod m is 30x slower.\n let a = mod(number, modulo);\n let b = modulo;\n // prettier-ignore\n let x = _0n, y = _1n, u = _1n, v = _0n;\n while (a !== _0n) {\n // JIT applies optimization if those two lines follow each other\n const q = b / a;\n const r = b % a;\n const m = x - u * q;\n const n = y - v * q;\n // prettier-ignore\n b = a, a = r, x = u, y = v, u = m, v = n;\n }\n const gcd = b;\n if (gcd !== _1n)\n throw new Error('invert: does not exist');\n return mod(x, modulo);\n}\n/**\n * Tonelli-Shanks square root search algorithm.\n * 1. https://eprint.iacr.org/2012/685.pdf (page 12)\n * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks\n * Will start an infinite loop if field order P is not prime.\n * @param P field order\n * @returns function that takes field Fp (created from P) and number n\n */\nexport function tonelliShanks(P) {\n // Legendre constant: used to calculate Legendre symbol (a | p),\n // which denotes the value of a^((p-1)/2) (mod p).\n // (a | p) ≡ 1 if a is a square (mod p)\n // (a | p) ≡ -1 if a is not a square (mod p)\n // (a | p) ≡ 0 if a ≡ 0 (mod p)\n const legendreC = (P - _1n) / _2n;\n let Q, S, Z;\n // Step 1: By factoring out powers of 2 from p - 1,\n // find q and s such that p - 1 = q*(2^s) with q odd\n for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++)\n ;\n // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq\n for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++)\n ;\n // Fast-path\n if (S === 1) {\n const p1div4 = (P + _1n) / _4n;\n return function tonelliFast(Fp, n) {\n const root = Fp.pow(n, p1div4);\n if (!Fp.eql(Fp.sqr(root), n))\n throw new Error('Cannot find square root');\n return root;\n };\n }\n // Slow-path\n const Q1div2 = (Q + _1n) / _2n;\n return function tonelliSlow(Fp, n) {\n // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1\n if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE))\n throw new Error('Cannot find square root');\n let r = S;\n // TODO: will fail at Fp2/etc\n let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q); // will update both x and b\n let x = Fp.pow(n, Q1div2); // first guess at the square root\n let b = Fp.pow(n, Q); // first guess at the fudge factor\n while (!Fp.eql(b, Fp.ONE)) {\n if (Fp.eql(b, Fp.ZERO))\n return Fp.ZERO; // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0)\n // Find m such b^(2^m)==1\n let m = 1;\n for (let t2 = Fp.sqr(b); m < r; m++) {\n if (Fp.eql(t2, Fp.ONE))\n break;\n t2 = Fp.sqr(t2); // t2 *= t2\n }\n // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow\n const ge = Fp.pow(g, _1n << BigInt(r - m - 1)); // ge = 2^(r-m-1)\n g = Fp.sqr(ge); // g = ge * ge\n x = Fp.mul(x, ge); // x *= ge\n b = Fp.mul(b, g); // b *= g\n r = m;\n }\n return x;\n };\n}\nexport function FpSqrt(P) {\n // NOTE: different algorithms can give different roots, it is up to user to decide which one they want.\n // For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).\n // P ≡ 3 (mod 4)\n // √n = n^((P+1)/4)\n if (P % _4n === _3n) {\n // Not all roots possible!\n // const ORDER =\n // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;\n // const NUM = 72057594037927816n;\n const p1div4 = (P + _1n) / _4n;\n return function sqrt3mod4(Fp, n) {\n const root = Fp.pow(n, p1div4);\n // Throw if root**2 != n\n if (!Fp.eql(Fp.sqr(root), n))\n throw new Error('Cannot find square root');\n return root;\n };\n }\n // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10)\n if (P % _8n === _5n) {\n const c1 = (P - _5n) / _8n;\n return function sqrt5mod8(Fp, n) {\n const n2 = Fp.mul(n, _2n);\n const v = Fp.pow(n2, c1);\n const nv = Fp.mul(n, v);\n const i = Fp.mul(Fp.mul(nv, _2n), v);\n const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));\n if (!Fp.eql(Fp.sqr(root), n))\n throw new Error('Cannot find square root');\n return root;\n };\n }\n // P ≡ 9 (mod 16)\n if (P % _16n === _9n) {\n // NOTE: tonelli is too slow for bls-Fp2 calculations even on start\n // Means we cannot use sqrt for constants at all!\n //\n // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F\n // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F\n // const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F\n // const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic\n // sqrt = (x) => {\n // let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4\n // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1\n // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1\n // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1\n // const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x\n // const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x\n // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x\n // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x\n // const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x\n // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2\n // }\n }\n // Other cases: Tonelli-Shanks algorithm\n return tonelliShanks(P);\n}\n// Little-endian check for first LE bit (last BE bit);\nexport const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n;\n// prettier-ignore\nconst FIELD_FIELDS = [\n 'create', 'isValid', 'is0', 'neg', 'inv', 'sqrt', 'sqr',\n 'eql', 'add', 'sub', 'mul', 'pow', 'div',\n 'addN', 'subN', 'mulN', 'sqrN'\n];\nexport function validateField(field) {\n const initial = {\n ORDER: 'bigint',\n MASK: 'bigint',\n BYTES: 'isSafeInteger',\n BITS: 'isSafeInteger',\n };\n const opts = FIELD_FIELDS.reduce((map, val) => {\n map[val] = 'function';\n return map;\n }, initial);\n return validateObject(field, opts);\n}\n// Generic field functions\n/**\n * Same as `pow` but for Fp: non-constant-time.\n * Unsafe in some contexts: uses ladder, so can expose bigint bits.\n */\nexport function FpPow(f, num, power) {\n // Should have same speed as pow for bigints\n // TODO: benchmark!\n if (power < _0n)\n throw new Error('Expected power > 0');\n if (power === _0n)\n return f.ONE;\n if (power === _1n)\n return num;\n let p = f.ONE;\n let d = num;\n while (power > _0n) {\n if (power & _1n)\n p = f.mul(p, d);\n d = f.sqr(d);\n power >>= _1n;\n }\n return p;\n}\n/**\n * Efficiently invert an array of Field elements.\n * `inv(0)` will return `undefined` here: make sure to throw an error.\n */\nexport function FpInvertBatch(f, nums) {\n const tmp = new Array(nums.length);\n // Walk from first to last, multiply them by each other MOD p\n const lastMultiplied = nums.reduce((acc, num, i) => {\n if (f.is0(num))\n return acc;\n tmp[i] = acc;\n return f.mul(acc, num);\n }, f.ONE);\n // Invert last element\n const inverted = f.inv(lastMultiplied);\n // Walk from last to first, multiply them by inverted each other MOD p\n nums.reduceRight((acc, num, i) => {\n if (f.is0(num))\n return acc;\n tmp[i] = f.mul(acc, tmp[i]);\n return f.mul(acc, num);\n }, inverted);\n return tmp;\n}\nexport function FpDiv(f, lhs, rhs) {\n return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs));\n}\n// This function returns True whenever the value x is a square in the field F.\nexport function FpIsSquare(f) {\n const legendreConst = (f.ORDER - _1n) / _2n; // Integer arithmetic\n return (x) => {\n const p = f.pow(x, legendreConst);\n return f.eql(p, f.ZERO) || f.eql(p, f.ONE);\n };\n}\n// CURVE.n lengths\nexport function nLength(n, nBitLength) {\n // Bit size, byte size of CURVE.n\n const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;\n const nByteLength = Math.ceil(_nBitLength / 8);\n return { nBitLength: _nBitLength, nByteLength };\n}\n/**\n * Initializes a finite field over prime. **Non-primes are not supported.**\n * Do not init in loop: slow. Very fragile: always run a benchmark on a change.\n * Major performance optimizations:\n * * a) denormalized operations like mulN instead of mul\n * * b) same object shape: never add or remove keys\n * * c) Object.freeze\n * @param ORDER prime positive bigint\n * @param bitLen how many bits the field consumes\n * @param isLE (def: false) if encoding / decoding should be in little-endian\n * @param redef optional faster redefinitions of sqrt and other methods\n */\nexport function Field(ORDER, bitLen, isLE = false, redef = {}) {\n if (ORDER <= _0n)\n throw new Error(`Expected Field ORDER > 0, got ${ORDER}`);\n const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen);\n if (BYTES > 2048)\n throw new Error('Field lengths over 2048 bytes are not supported');\n const sqrtP = FpSqrt(ORDER);\n const f = Object.freeze({\n ORDER,\n BITS,\n BYTES,\n MASK: bitMask(BITS),\n ZERO: _0n,\n ONE: _1n,\n create: (num) => mod(num, ORDER),\n isValid: (num) => {\n if (typeof num !== 'bigint')\n throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);\n return _0n <= num && num < ORDER; // 0 is valid element, but it's not invertible\n },\n is0: (num) => num === _0n,\n isOdd: (num) => (num & _1n) === _1n,\n neg: (num) => mod(-num, ORDER),\n eql: (lhs, rhs) => lhs === rhs,\n sqr: (num) => mod(num * num, ORDER),\n add: (lhs, rhs) => mod(lhs + rhs, ORDER),\n sub: (lhs, rhs) => mod(lhs - rhs, ORDER),\n mul: (lhs, rhs) => mod(lhs * rhs, ORDER),\n pow: (num, power) => FpPow(f, num, power),\n div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),\n // Same as above, but doesn't normalize\n sqrN: (num) => num * num,\n addN: (lhs, rhs) => lhs + rhs,\n subN: (lhs, rhs) => lhs - rhs,\n mulN: (lhs, rhs) => lhs * rhs,\n inv: (num) => invert(num, ORDER),\n sqrt: redef.sqrt || ((n) => sqrtP(f, n)),\n invertBatch: (lst) => FpInvertBatch(f, lst),\n // TODO: do we really need constant cmov?\n // We don't have const-time bigints anyway, so probably will be not very useful\n cmov: (a, b, c) => (c ? b : a),\n toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),\n fromBytes: (bytes) => {\n if (bytes.length !== BYTES)\n throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`);\n return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);\n },\n });\n return Object.freeze(f);\n}\nexport function FpSqrtOdd(Fp, elm) {\n if (!Fp.isOdd)\n throw new Error(`Field doesn't have isOdd`);\n const root = Fp.sqrt(elm);\n return Fp.isOdd(root) ? root : Fp.neg(root);\n}\nexport function FpSqrtEven(Fp, elm) {\n if (!Fp.isOdd)\n throw new Error(`Field doesn't have isOdd`);\n const root = Fp.sqrt(elm);\n return Fp.isOdd(root) ? Fp.neg(root) : root;\n}\n/**\n * \"Constant-time\" private key generation utility.\n * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field).\n * Which makes it slightly more biased, less secure.\n * @deprecated use mapKeyToField instead\n */\nexport function hashToPrivateScalar(hash, groupOrder, isLE = false) {\n hash = ensureBytes('privateHash', hash);\n const hashLen = hash.length;\n const minLen = nLength(groupOrder).nByteLength + 8;\n if (minLen < 24 || hashLen < minLen || hashLen > 1024)\n throw new Error(`hashToPrivateScalar: expected ${minLen}-1024 bytes of input, got ${hashLen}`);\n const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);\n return mod(num, groupOrder - _1n) + _1n;\n}\n/**\n * Returns total number of bytes consumed by the field element.\n * For example, 32 bytes for usual 256-bit weierstrass curve.\n * @param fieldOrder number of field elements, usually CURVE.n\n * @returns byte length of field\n */\nexport function getFieldBytesLength(fieldOrder) {\n if (typeof fieldOrder !== 'bigint')\n throw new Error('field order must be bigint');\n const bitLength = fieldOrder.toString(2).length;\n return Math.ceil(bitLength / 8);\n}\n/**\n * Returns minimal amount of bytes that can be safely reduced\n * by field order.\n * Should be 2^-128 for 128-bit curve such as P256.\n * @param fieldOrder number of field elements, usually CURVE.n\n * @returns byte length of target hash\n */\nexport function getMinHashLength(fieldOrder) {\n const length = getFieldBytesLength(fieldOrder);\n return length + Math.ceil(length / 2);\n}\n/**\n * \"Constant-time\" private key generation utility.\n * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF\n * and convert them into private scalar, with the modulo bias being negligible.\n * Needs at least 48 bytes of input for 32-byte private key.\n * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/\n * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final\n * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5\n * @param hash hash output from SHA3 or a similar function\n * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n)\n * @param isLE interpret hash bytes as LE num\n * @returns valid private scalar\n */\nexport function mapHashToField(key, fieldOrder, isLE = false) {\n const len = key.length;\n const fieldLen = getFieldBytesLength(fieldOrder);\n const minLen = getMinHashLength(fieldOrder);\n // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.\n if (len < 16 || len < minLen || len > 1024)\n throw new Error(`expected ${minLen}-1024 bytes of input, got ${len}`);\n const num = isLE ? bytesToNumberBE(key) : bytesToNumberLE(key);\n // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0\n const reduced = mod(num, fieldOrder - _1n) + _1n;\n return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);\n}\n//# sourceMappingURL=modular.js.map","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Abelian group utilities\nimport { validateField, nLength } from './modular.js';\nimport { validateObject } from './utils.js';\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\n// Elliptic curve multiplication of Point by scalar. Fragile.\n// Scalars should always be less than curve order: this should be checked inside of a curve itself.\n// Creates precomputation tables for fast multiplication:\n// - private scalar is split by fixed size windows of W bits\n// - every window point is collected from window's table & added to accumulator\n// - since windows are different, same point inside tables won't be accessed more than once per calc\n// - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)\n// - +1 window is neccessary for wNAF\n// - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication\n// TODO: Research returning 2d JS array of windows, instead of a single window. This would allow\n// windows to be in different memory locations\nexport function wNAF(c, bits) {\n const constTimeNegate = (condition, item) => {\n const neg = item.negate();\n return condition ? neg : item;\n };\n const opts = (W) => {\n const windows = Math.ceil(bits / W) + 1; // +1, because\n const windowSize = 2 ** (W - 1); // -1 because we skip zero\n return { windows, windowSize };\n };\n return {\n constTimeNegate,\n // non-const time multiplication ladder\n unsafeLadder(elm, n) {\n let p = c.ZERO;\n let d = elm;\n while (n > _0n) {\n if (n & _1n)\n p = p.add(d);\n d = d.double();\n n >>= _1n;\n }\n return p;\n },\n /**\n * Creates a wNAF precomputation window. Used for caching.\n * Default window size is set by `utils.precompute()` and is equal to 8.\n * Number of precomputed points depends on the curve size:\n * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:\n * - 𝑊 is the window size\n * - 𝑛 is the bitlength of the curve order.\n * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.\n * @returns precomputed point tables flattened to a single array\n */\n precomputeWindow(elm, W) {\n const { windows, windowSize } = opts(W);\n const points = [];\n let p = elm;\n let base = p;\n for (let window = 0; window < windows; window++) {\n base = p;\n points.push(base);\n // =1, because we skip zero\n for (let i = 1; i < windowSize; i++) {\n base = base.add(p);\n points.push(base);\n }\n p = base.double();\n }\n return points;\n },\n /**\n * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.\n * @param W window size\n * @param precomputes precomputed tables\n * @param n scalar (we don't check here, but should be less than curve order)\n * @returns real and fake (for const-time) points\n */\n wNAF(W, precomputes, n) {\n // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise\n // But need to carefully remove other checks before wNAF. ORDER == bits here\n const { windows, windowSize } = opts(W);\n let p = c.ZERO;\n let f = c.BASE;\n const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc.\n const maxNumber = 2 ** W;\n const shiftBy = BigInt(W);\n for (let window = 0; window < windows; window++) {\n const offset = window * windowSize;\n // Extract W bits.\n let wbits = Number(n & mask);\n // Shift number by W bits.\n n >>= shiftBy;\n // If the bits are bigger than max size, we'll split those.\n // +224 => 256 - 32\n if (wbits > windowSize) {\n wbits -= maxNumber;\n n += _1n;\n }\n // This code was first written with assumption that 'f' and 'p' will never be infinity point:\n // since each addition is multiplied by 2 ** W, it cannot cancel each other. However,\n // there is negate now: it is possible that negated element from low value\n // would be the same as high element, which will create carry into next window.\n // It's not obvious how this can fail, but still worth investigating later.\n // Check if we're onto Zero point.\n // Add random point inside current window to f.\n const offset1 = offset;\n const offset2 = offset + Math.abs(wbits) - 1; // -1 because we skip zero\n const cond1 = window % 2 !== 0;\n const cond2 = wbits < 0;\n if (wbits === 0) {\n // The most important part for const-time getPublicKey\n f = f.add(constTimeNegate(cond1, precomputes[offset1]));\n }\n else {\n p = p.add(constTimeNegate(cond2, precomputes[offset2]));\n }\n }\n // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ()\n // Even if the variable is still unused, there are some checks which will\n // throw an exception, so compiler needs to prove they won't happen, which is hard.\n // At this point there is a way to F be infinity-point even if p is not,\n // which makes it less const-time: around 1 bigint multiply.\n return { p, f };\n },\n wNAFCached(P, precomputesMap, n, transform) {\n // @ts-ignore\n const W = P._WINDOW_SIZE || 1;\n // Calculate precomputes on a first run, reuse them after\n let comp = precomputesMap.get(P);\n if (!comp) {\n comp = this.precomputeWindow(P, W);\n if (W !== 1) {\n precomputesMap.set(P, transform(comp));\n }\n }\n return this.wNAF(W, comp, n);\n },\n };\n}\nexport function validateBasic(curve) {\n validateField(curve.Fp);\n validateObject(curve, {\n n: 'bigint',\n h: 'bigint',\n Gx: 'field',\n Gy: 'field',\n }, {\n nBitLength: 'isSafeInteger',\n nByteLength: 'isSafeInteger',\n });\n // Set defaults\n return Object.freeze({\n ...nLength(curve.n, curve.nBitLength),\n ...curve,\n ...{ p: curve.Fp.ORDER },\n });\n}\n//# sourceMappingURL=curve.js.map","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Short Weierstrass curve. The formula is: y² = x³ + ax + b\nimport * as mod from './modular.js';\nimport * as ut from './utils.js';\nimport { ensureBytes } from './utils.js';\nimport { wNAF, validateBasic } from './curve.js';\nfunction validatePointOpts(curve) {\n const opts = validateBasic(curve);\n ut.validateObject(opts, {\n a: 'field',\n b: 'field',\n }, {\n allowedPrivateKeyLengths: 'array',\n wrapPrivateKey: 'boolean',\n isTorsionFree: 'function',\n clearCofactor: 'function',\n allowInfinityPoint: 'boolean',\n fromBytes: 'function',\n toBytes: 'function',\n });\n const { endo, Fp, a } = opts;\n if (endo) {\n if (!Fp.eql(a, Fp.ZERO)) {\n throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0');\n }\n if (typeof endo !== 'object' ||\n typeof endo.beta !== 'bigint' ||\n typeof endo.splitScalar !== 'function') {\n throw new Error('Expected endomorphism with beta: bigint and splitScalar: function');\n }\n }\n return Object.freeze({ ...opts });\n}\n// ASN.1 DER encoding utilities\nconst { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;\nexport const DER = {\n // asn.1 DER encoding utils\n Err: class DERErr extends Error {\n constructor(m = '') {\n super(m);\n }\n },\n _parseInt(data) {\n const { Err: E } = DER;\n if (data.length < 2 || data[0] !== 0x02)\n throw new E('Invalid signature integer tag');\n const len = data[1];\n const res = data.subarray(2, len + 2);\n if (!len || res.length !== len)\n throw new E('Invalid signature integer: wrong length');\n // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,\n // since we always use positive integers here. It must always be empty:\n // - add zero byte if exists\n // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)\n if (res[0] & 0b10000000)\n throw new E('Invalid signature integer: negative');\n if (res[0] === 0x00 && !(res[1] & 0b10000000))\n throw new E('Invalid signature integer: unnecessary leading zero');\n return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left\n },\n toSig(hex) {\n // parse DER signature\n const { Err: E } = DER;\n const data = typeof hex === 'string' ? h2b(hex) : hex;\n if (!(data instanceof Uint8Array))\n throw new Error('ui8a expected');\n let l = data.length;\n if (l < 2 || data[0] != 0x30)\n throw new E('Invalid signature tag');\n if (data[1] !== l - 2)\n throw new E('Invalid signature: incorrect length');\n const { d: r, l: sBytes } = DER._parseInt(data.subarray(2));\n const { d: s, l: rBytesLeft } = DER._parseInt(sBytes);\n if (rBytesLeft.length)\n throw new E('Invalid signature: left bytes after parsing');\n return { r, s };\n },\n hexFromSig(sig) {\n // Add leading zero if first byte has negative bit enabled. More details in '_parseInt'\n const slice = (s) => (Number.parseInt(s[0], 16) & 0b1000 ? '00' + s : s);\n const h = (num) => {\n const hex = num.toString(16);\n return hex.length & 1 ? `0${hex}` : hex;\n };\n const s = slice(h(sig.s));\n const r = slice(h(sig.r));\n const shl = s.length / 2;\n const rhl = r.length / 2;\n const sl = h(shl);\n const rl = h(rhl);\n return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`;\n },\n};\n// Be friendly to bad ECMAScript parsers by not using bigint literals\n// prettier-ignore\nconst _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);\nexport function weierstrassPoints(opts) {\n const CURVE = validatePointOpts(opts);\n const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ\n const toBytes = CURVE.toBytes ||\n ((_c, point, _isCompressed) => {\n const a = point.toAffine();\n return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y));\n });\n const fromBytes = CURVE.fromBytes ||\n ((bytes) => {\n // const head = bytes[0];\n const tail = bytes.subarray(1);\n // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported');\n const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));\n const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));\n return { x, y };\n });\n /**\n * y² = x³ + ax + b: Short weierstrass curve formula\n * @returns y²\n */\n function weierstrassEquation(x) {\n const { a, b } = CURVE;\n const x2 = Fp.sqr(x); // x * x\n const x3 = Fp.mul(x2, x); // x2 * x\n return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x3 + a * x + b\n }\n // Validate whether the passed curve params are valid.\n // We check if curve equation works for generator point.\n // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381.\n // ProjectivePoint class has not been initialized yet.\n if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))\n throw new Error('bad generator point: equation left != right');\n // Valid group elements reside in range 1..n-1\n function isWithinCurveOrder(num) {\n return typeof num === 'bigint' && _0n < num && num < CURVE.n;\n }\n function assertGE(num) {\n if (!isWithinCurveOrder(num))\n throw new Error('Expected valid bigint: 0 < bigint < curve.n');\n }\n // Validates if priv key is valid and converts it to bigint.\n // Supports options allowedPrivateKeyLengths and wrapPrivateKey.\n function normPrivateKeyToScalar(key) {\n const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;\n if (lengths && typeof key !== 'bigint') {\n if (key instanceof Uint8Array)\n key = ut.bytesToHex(key);\n // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes\n if (typeof key !== 'string' || !lengths.includes(key.length))\n throw new Error('Invalid key');\n key = key.padStart(nByteLength * 2, '0');\n }\n let num;\n try {\n num =\n typeof key === 'bigint'\n ? key\n : ut.bytesToNumberBE(ensureBytes('private key', key, nByteLength));\n }\n catch (error) {\n throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);\n }\n if (wrapPrivateKey)\n num = mod.mod(num, n); // disabled by default, enabled for BLS\n assertGE(num); // num in range [1..N-1]\n return num;\n }\n const pointPrecomputes = new Map();\n function assertPrjPoint(other) {\n if (!(other instanceof Point))\n throw new Error('ProjectivePoint expected');\n }\n /**\n * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)\n * Default Point works in 2d / affine coordinates: (x, y)\n * We're doing calculations in projective, because its operations don't require costly inversion.\n */\n class Point {\n constructor(px, py, pz) {\n this.px = px;\n this.py = py;\n this.pz = pz;\n if (px == null || !Fp.isValid(px))\n throw new Error('x required');\n if (py == null || !Fp.isValid(py))\n throw new Error('y required');\n if (pz == null || !Fp.isValid(pz))\n throw new Error('z required');\n }\n // Does not validate if the point is on-curve.\n // Use fromHex instead, or call assertValidity() later.\n static fromAffine(p) {\n const { x, y } = p || {};\n if (!p || !Fp.isValid(x) || !Fp.isValid(y))\n throw new Error('invalid affine point');\n if (p instanceof Point)\n throw new Error('projective point not allowed');\n const is0 = (i) => Fp.eql(i, Fp.ZERO);\n // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0)\n if (is0(x) && is0(y))\n return Point.ZERO;\n return new Point(x, y, Fp.ONE);\n }\n get x() {\n return this.toAffine().x;\n }\n get y() {\n return this.toAffine().y;\n }\n /**\n * Takes a bunch of Projective Points but executes only one\n * inversion on all of them. Inversion is very slow operation,\n * so this improves performance massively.\n * Optimization: converts a list of projective points to a list of identical points with Z=1.\n */\n static normalizeZ(points) {\n const toInv = Fp.invertBatch(points.map((p) => p.pz));\n return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);\n }\n /**\n * Converts hash string or Uint8Array to Point.\n * @param hex short/long ECDSA hex\n */\n static fromHex(hex) {\n const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex)));\n P.assertValidity();\n return P;\n }\n // Multiplies generator point by privateKey.\n static fromPrivateKey(privateKey) {\n return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));\n }\n // \"Private method\", don't use it directly\n _setWindowSize(windowSize) {\n this._WINDOW_SIZE = windowSize;\n pointPrecomputes.delete(this);\n }\n // A point on curve is valid if it conforms to equation.\n assertValidity() {\n if (this.is0()) {\n // (0, 1, 0) aka ZERO is invalid in most contexts.\n // In BLS, ZERO can be serialized, so we allow it.\n // (0, 0, 0) is wrong representation of ZERO and is always invalid.\n if (CURVE.allowInfinityPoint && !Fp.is0(this.py))\n return;\n throw new Error('bad point: ZERO');\n }\n // Some 3rd-party test vectors require different wording between here & `fromCompressedHex`\n const { x, y } = this.toAffine();\n // Check if x, y are valid field elements\n if (!Fp.isValid(x) || !Fp.isValid(y))\n throw new Error('bad point: x or y not FE');\n const left = Fp.sqr(y); // y²\n const right = weierstrassEquation(x); // x³ + ax + b\n if (!Fp.eql(left, right))\n throw new Error('bad point: equation left != right');\n if (!this.isTorsionFree())\n throw new Error('bad point: not in prime-order subgroup');\n }\n hasEvenY() {\n const { y } = this.toAffine();\n if (Fp.isOdd)\n return !Fp.isOdd(y);\n throw new Error(\"Field doesn't support isOdd\");\n }\n /**\n * Compare one point to another.\n */\n equals(other) {\n assertPrjPoint(other);\n const { px: X1, py: Y1, pz: Z1 } = this;\n const { px: X2, py: Y2, pz: Z2 } = other;\n const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));\n const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));\n return U1 && U2;\n }\n /**\n * Flips point to one corresponding to (x, -y) in Affine coordinates.\n */\n negate() {\n return new Point(this.px, Fp.neg(this.py), this.pz);\n }\n // Renes-Costello-Batina exception-free doubling formula.\n // There is 30% faster Jacobian formula, but it is not complete.\n // https://eprint.iacr.org/2015/1060, algorithm 3\n // Cost: 8M + 3S + 3*a + 2*b3 + 15add.\n double() {\n const { a, b } = CURVE;\n const b3 = Fp.mul(b, _3n);\n const { px: X1, py: Y1, pz: Z1 } = this;\n let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore\n let t0 = Fp.mul(X1, X1); // step 1\n let t1 = Fp.mul(Y1, Y1);\n let t2 = Fp.mul(Z1, Z1);\n let t3 = Fp.mul(X1, Y1);\n t3 = Fp.add(t3, t3); // step 5\n Z3 = Fp.mul(X1, Z1);\n Z3 = Fp.add(Z3, Z3);\n X3 = Fp.mul(a, Z3);\n Y3 = Fp.mul(b3, t2);\n Y3 = Fp.add(X3, Y3); // step 10\n X3 = Fp.sub(t1, Y3);\n Y3 = Fp.add(t1, Y3);\n Y3 = Fp.mul(X3, Y3);\n X3 = Fp.mul(t3, X3);\n Z3 = Fp.mul(b3, Z3); // step 15\n t2 = Fp.mul(a, t2);\n t3 = Fp.sub(t0, t2);\n t3 = Fp.mul(a, t3);\n t3 = Fp.add(t3, Z3);\n Z3 = Fp.add(t0, t0); // step 20\n t0 = Fp.add(Z3, t0);\n t0 = Fp.add(t0, t2);\n t0 = Fp.mul(t0, t3);\n Y3 = Fp.add(Y3, t0);\n t2 = Fp.mul(Y1, Z1); // step 25\n t2 = Fp.add(t2, t2);\n t0 = Fp.mul(t2, t3);\n X3 = Fp.sub(X3, t0);\n Z3 = Fp.mul(t2, t1);\n Z3 = Fp.add(Z3, Z3); // step 30\n Z3 = Fp.add(Z3, Z3);\n return new Point(X3, Y3, Z3);\n }\n // Renes-Costello-Batina exception-free addition formula.\n // There is 30% faster Jacobian formula, but it is not complete.\n // https://eprint.iacr.org/2015/1060, algorithm 1\n // Cost: 12M + 0S + 3*a + 3*b3 + 23add.\n add(other) {\n assertPrjPoint(other);\n const { px: X1, py: Y1, pz: Z1 } = this;\n const { px: X2, py: Y2, pz: Z2 } = other;\n let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore\n const a = CURVE.a;\n const b3 = Fp.mul(CURVE.b, _3n);\n let t0 = Fp.mul(X1, X2); // step 1\n let t1 = Fp.mul(Y1, Y2);\n let t2 = Fp.mul(Z1, Z2);\n let t3 = Fp.add(X1, Y1);\n let t4 = Fp.add(X2, Y2); // step 5\n t3 = Fp.mul(t3, t4);\n t4 = Fp.add(t0, t1);\n t3 = Fp.sub(t3, t4);\n t4 = Fp.add(X1, Z1);\n let t5 = Fp.add(X2, Z2); // step 10\n t4 = Fp.mul(t4, t5);\n t5 = Fp.add(t0, t2);\n t4 = Fp.sub(t4, t5);\n t5 = Fp.add(Y1, Z1);\n X3 = Fp.add(Y2, Z2); // step 15\n t5 = Fp.mul(t5, X3);\n X3 = Fp.add(t1, t2);\n t5 = Fp.sub(t5, X3);\n Z3 = Fp.mul(a, t4);\n X3 = Fp.mul(b3, t2); // step 20\n Z3 = Fp.add(X3, Z3);\n X3 = Fp.sub(t1, Z3);\n Z3 = Fp.add(t1, Z3);\n Y3 = Fp.mul(X3, Z3);\n t1 = Fp.add(t0, t0); // step 25\n t1 = Fp.add(t1, t0);\n t2 = Fp.mul(a, t2);\n t4 = Fp.mul(b3, t4);\n t1 = Fp.add(t1, t2);\n t2 = Fp.sub(t0, t2); // step 30\n t2 = Fp.mul(a, t2);\n t4 = Fp.add(t4, t2);\n t0 = Fp.mul(t1, t4);\n Y3 = Fp.add(Y3, t0);\n t0 = Fp.mul(t5, t4); // step 35\n X3 = Fp.mul(t3, X3);\n X3 = Fp.sub(X3, t0);\n t0 = Fp.mul(t3, t1);\n Z3 = Fp.mul(t5, Z3);\n Z3 = Fp.add(Z3, t0); // step 40\n return new Point(X3, Y3, Z3);\n }\n subtract(other) {\n return this.add(other.negate());\n }\n is0() {\n return this.equals(Point.ZERO);\n }\n wNAF(n) {\n return wnaf.wNAFCached(this, pointPrecomputes, n, (comp) => {\n const toInv = Fp.invertBatch(comp.map((p) => p.pz));\n return comp.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);\n });\n }\n /**\n * Non-constant-time multiplication. Uses double-and-add algorithm.\n * It's faster, but should only be used when you don't care about\n * an exposed private key e.g. sig verification, which works over *public* keys.\n */\n multiplyUnsafe(n) {\n const I = Point.ZERO;\n if (n === _0n)\n return I;\n assertGE(n); // Will throw on 0\n if (n === _1n)\n return this;\n const { endo } = CURVE;\n if (!endo)\n return wnaf.unsafeLadder(this, n);\n // Apply endomorphism\n let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);\n let k1p = I;\n let k2p = I;\n let d = this;\n while (k1 > _0n || k2 > _0n) {\n if (k1 & _1n)\n k1p = k1p.add(d);\n if (k2 & _1n)\n k2p = k2p.add(d);\n d = d.double();\n k1 >>= _1n;\n k2 >>= _1n;\n }\n if (k1neg)\n k1p = k1p.negate();\n if (k2neg)\n k2p = k2p.negate();\n k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);\n return k1p.add(k2p);\n }\n /**\n * Constant time multiplication.\n * Uses wNAF method. Windowed method may be 10% faster,\n * but takes 2x longer to generate and consumes 2x memory.\n * Uses precomputes when available.\n * Uses endomorphism for Koblitz curves.\n * @param scalar by which the point would be multiplied\n * @returns New point\n */\n multiply(scalar) {\n assertGE(scalar);\n let n = scalar;\n let point, fake; // Fake point is used to const-time mult\n const { endo } = CURVE;\n if (endo) {\n const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);\n let { p: k1p, f: f1p } = this.wNAF(k1);\n let { p: k2p, f: f2p } = this.wNAF(k2);\n k1p = wnaf.constTimeNegate(k1neg, k1p);\n k2p = wnaf.constTimeNegate(k2neg, k2p);\n k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);\n point = k1p.add(k2p);\n fake = f1p.add(f2p);\n }\n else {\n const { p, f } = this.wNAF(n);\n point = p;\n fake = f;\n }\n // Normalize `z` for both points, but return only real one\n return Point.normalizeZ([point, fake])[0];\n }\n /**\n * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.\n * Not using Strauss-Shamir trick: precomputation tables are faster.\n * The trick could be useful if both P and Q are not G (not in our case).\n * @returns non-zero affine point\n */\n multiplyAndAddUnsafe(Q, a, b) {\n const G = Point.BASE; // No Strauss-Shamir trick: we have 10% faster G precomputes\n const mul = (P, a // Select faster multiply() method\n ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a));\n const sum = mul(this, a).add(mul(Q, b));\n return sum.is0() ? undefined : sum;\n }\n // Converts Projective point to affine (x, y) coordinates.\n // Can accept precomputed Z^-1 - for example, from invertBatch.\n // (x, y, z) ∋ (x=x/z, y=y/z)\n toAffine(iz) {\n const { px: x, py: y, pz: z } = this;\n const is0 = this.is0();\n // If invZ was 0, we return zero point. However we still want to execute\n // all operations, so we replace invZ with a random number, 1.\n if (iz == null)\n iz = is0 ? Fp.ONE : Fp.inv(z);\n const ax = Fp.mul(x, iz);\n const ay = Fp.mul(y, iz);\n const zz = Fp.mul(z, iz);\n if (is0)\n return { x: Fp.ZERO, y: Fp.ZERO };\n if (!Fp.eql(zz, Fp.ONE))\n throw new Error('invZ was invalid');\n return { x: ax, y: ay };\n }\n isTorsionFree() {\n const { h: cofactor, isTorsionFree } = CURVE;\n if (cofactor === _1n)\n return true; // No subgroups, always torsion-free\n if (isTorsionFree)\n return isTorsionFree(Point, this);\n throw new Error('isTorsionFree() has not been declared for the elliptic curve');\n }\n clearCofactor() {\n const { h: cofactor, clearCofactor } = CURVE;\n if (cofactor === _1n)\n return this; // Fast-path\n if (clearCofactor)\n return clearCofactor(Point, this);\n return this.multiplyUnsafe(CURVE.h);\n }\n toRawBytes(isCompressed = true) {\n this.assertValidity();\n return toBytes(Point, this, isCompressed);\n }\n toHex(isCompressed = true) {\n return ut.bytesToHex(this.toRawBytes(isCompressed));\n }\n }\n Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);\n Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO);\n const _bits = CURVE.nBitLength;\n const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);\n // Validate if generator point is on curve\n return {\n CURVE,\n ProjectivePoint: Point,\n normPrivateKeyToScalar,\n weierstrassEquation,\n isWithinCurveOrder,\n };\n}\nfunction validateOpts(curve) {\n const opts = validateBasic(curve);\n ut.validateObject(opts, {\n hash: 'hash',\n hmac: 'function',\n randomBytes: 'function',\n }, {\n bits2int: 'function',\n bits2int_modN: 'function',\n lowS: 'boolean',\n });\n return Object.freeze({ lowS: true, ...opts });\n}\nexport function weierstrass(curveDef) {\n const CURVE = validateOpts(curveDef);\n const { Fp, n: CURVE_ORDER } = CURVE;\n const compressedLen = Fp.BYTES + 1; // e.g. 33 for 32\n const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32\n function isValidFieldElement(num) {\n return _0n < num && num < Fp.ORDER; // 0 is banned since it's not invertible FE\n }\n function modN(a) {\n return mod.mod(a, CURVE_ORDER);\n }\n function invN(a) {\n return mod.invert(a, CURVE_ORDER);\n }\n const { ProjectivePoint: Point, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder, } = weierstrassPoints({\n ...CURVE,\n toBytes(_c, point, isCompressed) {\n const a = point.toAffine();\n const x = Fp.toBytes(a.x);\n const cat = ut.concatBytes;\n if (isCompressed) {\n return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);\n }\n else {\n return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));\n }\n },\n fromBytes(bytes) {\n const len = bytes.length;\n const head = bytes[0];\n const tail = bytes.subarray(1);\n // this.assertValidity() is done inside of fromHex\n if (len === compressedLen && (head === 0x02 || head === 0x03)) {\n const x = ut.bytesToNumberBE(tail);\n if (!isValidFieldElement(x))\n throw new Error('Point is not on curve');\n const y2 = weierstrassEquation(x); // y² = x³ + ax + b\n let y = Fp.sqrt(y2); // y = y² ^ (p+1)/4\n const isYOdd = (y & _1n) === _1n;\n // ECDSA\n const isHeadOdd = (head & 1) === 1;\n if (isHeadOdd !== isYOdd)\n y = Fp.neg(y);\n return { x, y };\n }\n else if (len === uncompressedLen && head === 0x04) {\n const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));\n const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));\n return { x, y };\n }\n else {\n throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);\n }\n },\n });\n const numToNByteStr = (num) => ut.bytesToHex(ut.numberToBytesBE(num, CURVE.nByteLength));\n function isBiggerThanHalfOrder(number) {\n const HALF = CURVE_ORDER >> _1n;\n return number > HALF;\n }\n function normalizeS(s) {\n return isBiggerThanHalfOrder(s) ? modN(-s) : s;\n }\n // slice bytes num\n const slcNum = (b, from, to) => ut.bytesToNumberBE(b.slice(from, to));\n /**\n * ECDSA signature with its (r, s) properties. Supports DER & compact representations.\n */\n class Signature {\n constructor(r, s, recovery) {\n this.r = r;\n this.s = s;\n this.recovery = recovery;\n this.assertValidity();\n }\n // pair (bytes of r, bytes of s)\n static fromCompact(hex) {\n const l = CURVE.nByteLength;\n hex = ensureBytes('compactSignature', hex, l * 2);\n return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l));\n }\n // DER encoded ECDSA signature\n // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script\n static fromDER(hex) {\n const { r, s } = DER.toSig(ensureBytes('DER', hex));\n return new Signature(r, s);\n }\n assertValidity() {\n // can use assertGE here\n if (!isWithinCurveOrder(this.r))\n throw new Error('r must be 0 < r < CURVE.n');\n if (!isWithinCurveOrder(this.s))\n throw new Error('s must be 0 < s < CURVE.n');\n }\n addRecoveryBit(recovery) {\n return new Signature(this.r, this.s, recovery);\n }\n recoverPublicKey(msgHash) {\n const { r, s, recovery: rec } = this;\n const h = bits2int_modN(ensureBytes('msgHash', msgHash)); // Truncate hash\n if (rec == null || ![0, 1, 2, 3].includes(rec))\n throw new Error('recovery id invalid');\n const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;\n if (radj >= Fp.ORDER)\n throw new Error('recovery id 2 or 3 invalid');\n const prefix = (rec & 1) === 0 ? '02' : '03';\n const R = Point.fromHex(prefix + numToNByteStr(radj));\n const ir = invN(radj); // r^-1\n const u1 = modN(-h * ir); // -hr^-1\n const u2 = modN(s * ir); // sr^-1\n const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)\n if (!Q)\n throw new Error('point at infinify'); // unsafe is fine: no priv data leaked\n Q.assertValidity();\n return Q;\n }\n // Signatures should be low-s, to prevent malleability.\n hasHighS() {\n return isBiggerThanHalfOrder(this.s);\n }\n normalizeS() {\n return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this;\n }\n // DER-encoded\n toDERRawBytes() {\n return ut.hexToBytes(this.toDERHex());\n }\n toDERHex() {\n return DER.hexFromSig({ r: this.r, s: this.s });\n }\n // padded bytes of r, then padded bytes of s\n toCompactRawBytes() {\n return ut.hexToBytes(this.toCompactHex());\n }\n toCompactHex() {\n return numToNByteStr(this.r) + numToNByteStr(this.s);\n }\n }\n const utils = {\n isValidPrivateKey(privateKey) {\n try {\n normPrivateKeyToScalar(privateKey);\n return true;\n }\n catch (error) {\n return false;\n }\n },\n normPrivateKeyToScalar: normPrivateKeyToScalar,\n /**\n * Produces cryptographically secure private key from random of size\n * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.\n */\n randomPrivateKey: () => {\n const length = mod.getMinHashLength(CURVE.n);\n return mod.mapHashToField(CURVE.randomBytes(length), CURVE.n);\n },\n /**\n * Creates precompute table for an arbitrary EC point. Makes point \"cached\".\n * Allows to massively speed-up `point.multiply(scalar)`.\n * @returns cached point\n * @example\n * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));\n * fast.multiply(privKey); // much faster ECDH now\n */\n precompute(windowSize = 8, point = Point.BASE) {\n point._setWindowSize(windowSize);\n point.multiply(BigInt(3)); // 3 is arbitrary, just need any number here\n return point;\n },\n };\n /**\n * Computes public key for a private key. Checks for validity of the private key.\n * @param privateKey private key\n * @param isCompressed whether to return compact (default), or full key\n * @returns Public key, full when isCompressed=false; short when isCompressed=true\n */\n function getPublicKey(privateKey, isCompressed = true) {\n return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed);\n }\n /**\n * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.\n */\n function isProbPub(item) {\n const arr = item instanceof Uint8Array;\n const str = typeof item === 'string';\n const len = (arr || str) && item.length;\n if (arr)\n return len === compressedLen || len === uncompressedLen;\n if (str)\n return len === 2 * compressedLen || len === 2 * uncompressedLen;\n if (item instanceof Point)\n return true;\n return false;\n }\n /**\n * ECDH (Elliptic Curve Diffie Hellman).\n * Computes shared public key from private key and public key.\n * Checks: 1) private key validity 2) shared key is on-curve.\n * Does NOT hash the result.\n * @param privateA private key\n * @param publicB different public key\n * @param isCompressed whether to return compact (default), or full key\n * @returns shared public key\n */\n function getSharedSecret(privateA, publicB, isCompressed = true) {\n if (isProbPub(privateA))\n throw new Error('first arg must be private key');\n if (!isProbPub(publicB))\n throw new Error('second arg must be public key');\n const b = Point.fromHex(publicB); // check for being on-curve\n return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);\n }\n // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.\n // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.\n // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same.\n // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors\n const bits2int = CURVE.bits2int ||\n function (bytes) {\n // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)\n // for some cases, since bytes.length * 8 is not actual bitLength.\n const num = ut.bytesToNumberBE(bytes); // check for == u8 done here\n const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits\n return delta > 0 ? num >> BigInt(delta) : num;\n };\n const bits2int_modN = CURVE.bits2int_modN ||\n function (bytes) {\n return modN(bits2int(bytes)); // can't use bytesToNumberBE here\n };\n // NOTE: pads output with zero as per spec\n const ORDER_MASK = ut.bitMask(CURVE.nBitLength);\n /**\n * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.\n */\n function int2octets(num) {\n if (typeof num !== 'bigint')\n throw new Error('bigint expected');\n if (!(_0n <= num && num < ORDER_MASK))\n throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);\n // works with order, can have different size than numToField!\n return ut.numberToBytesBE(num, CURVE.nByteLength);\n }\n // Steps A, D of RFC6979 3.2\n // Creates RFC6979 seed; converts msg/privKey to numbers.\n // Used only in sign, not in verify.\n // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, this will be wrong at least for P521.\n // Also it can be bigger for P224 + SHA256\n function prepSig(msgHash, privateKey, opts = defaultSigOpts) {\n if (['recovered', 'canonical'].some((k) => k in opts))\n throw new Error('sign() legacy options not supported');\n const { hash, randomBytes } = CURVE;\n let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default\n if (lowS == null)\n lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash\n msgHash = ensureBytes('msgHash', msgHash);\n if (prehash)\n msgHash = ensureBytes('prehashed msgHash', hash(msgHash));\n // We can't later call bits2octets, since nested bits2int is broken for curves\n // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.\n // const bits2octets = (bits) => int2octets(bits2int_modN(bits))\n const h1int = bits2int_modN(msgHash);\n const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint\n const seedArgs = [int2octets(d), int2octets(h1int)];\n // extraEntropy. RFC6979 3.6: additional k' (optional).\n if (ent != null) {\n // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')\n const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is\n seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes\n }\n const seed = ut.concatBytes(...seedArgs); // Step D of RFC6979 3.2\n const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!\n // Converts signature params into point w r/s, checks result for validity.\n function k2sig(kBytes) {\n // RFC 6979 Section 3.2, step 3: k = bits2int(T)\n const k = bits2int(kBytes); // Cannot use fields methods, since it is group element\n if (!isWithinCurveOrder(k))\n return; // Important: all mod() calls here must be done over N\n const ik = invN(k); // k^-1 mod n\n const q = Point.BASE.multiply(k).toAffine(); // q = Gk\n const r = modN(q.x); // r = q.x mod n\n if (r === _0n)\n return;\n // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to\n // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:\n // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT\n const s = modN(ik * modN(m + r * d)); // Not using blinding here\n if (s === _0n)\n return;\n let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)\n let normS = s;\n if (lowS && isBiggerThanHalfOrder(s)) {\n normS = normalizeS(s); // if lowS was passed, ensure s is always\n recovery ^= 1; // // in the bottom half of N\n }\n return new Signature(r, normS, recovery); // use normS, not s\n }\n return { seed, k2sig };\n }\n const defaultSigOpts = { lowS: CURVE.lowS, prehash: false };\n const defaultVerOpts = { lowS: CURVE.lowS, prehash: false };\n /**\n * Signs message hash with a private key.\n * ```\n * sign(m, d, k) where\n * (x, y) = G × k\n * r = x mod n\n * s = (m + dr)/k mod n\n * ```\n * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`.\n * @param privKey private key\n * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg.\n * @returns signature with recovery param\n */\n function sign(msgHash, privKey, opts = defaultSigOpts) {\n const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.\n const C = CURVE;\n const drbg = ut.createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac);\n return drbg(seed, k2sig); // Steps B, C, D, E, F, G\n }\n // Enable precomputes. Slows down first publicKey computation by 20ms.\n Point.BASE._setWindowSize(8);\n // utils.precompute(8, ProjectivePoint.BASE)\n /**\n * Verifies a signature against message hash and public key.\n * Rejects lowS signatures by default: to override,\n * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf:\n *\n * ```\n * verify(r, s, h, P) where\n * U1 = hs^-1 mod n\n * U2 = rs^-1 mod n\n * R = U1⋅G - U2⋅P\n * mod(R.x, n) == r\n * ```\n */\n function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {\n const sg = signature;\n msgHash = ensureBytes('msgHash', msgHash);\n publicKey = ensureBytes('publicKey', publicKey);\n if ('strict' in opts)\n throw new Error('options.strict was renamed to lowS');\n const { lowS, prehash } = opts;\n let _sig = undefined;\n let P;\n try {\n if (typeof sg === 'string' || sg instanceof Uint8Array) {\n // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).\n // Since DER can also be 2*nByteLength bytes, we check for it first.\n try {\n _sig = Signature.fromDER(sg);\n }\n catch (derError) {\n if (!(derError instanceof DER.Err))\n throw derError;\n _sig = Signature.fromCompact(sg);\n }\n }\n else if (typeof sg === 'object' && typeof sg.r === 'bigint' && typeof sg.s === 'bigint') {\n const { r, s } = sg;\n _sig = new Signature(r, s);\n }\n else {\n throw new Error('PARSE');\n }\n P = Point.fromHex(publicKey);\n }\n catch (error) {\n if (error.message === 'PARSE')\n throw new Error(`signature must be Signature instance, Uint8Array or hex string`);\n return false;\n }\n if (lowS && _sig.hasHighS())\n return false;\n if (prehash)\n msgHash = CURVE.hash(msgHash);\n const { r, s } = _sig;\n const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element\n const is = invN(s); // s^-1\n const u1 = modN(h * is); // u1 = hs^-1 mod n\n const u2 = modN(r * is); // u2 = rs^-1 mod n\n const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine(); // R = u1⋅G + u2⋅P\n if (!R)\n return false;\n const v = modN(R.x);\n return v === r;\n }\n return {\n CURVE,\n getPublicKey,\n getSharedSecret,\n sign,\n verify,\n ProjectivePoint: Point,\n Signature,\n utils,\n };\n}\n/**\n * Implementation of the Shallue and van de Woestijne method for any weierstrass curve.\n * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular.\n * b = True and y = sqrt(u / v) if (u / v) is square in F, and\n * b = False and y = sqrt(Z * (u / v)) otherwise.\n * @param Fp\n * @param Z\n * @returns\n */\nexport function SWUFpSqrtRatio(Fp, Z) {\n // Generic implementation\n const q = Fp.ORDER;\n let l = _0n;\n for (let o = q - _1n; o % _2n === _0n; o /= _2n)\n l += _1n;\n const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.\n // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<.\n // 2n ** c1 == 2n << (c1-1)\n const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n);\n const _2n_pow_c1 = _2n_pow_c1_1 * _2n;\n const c2 = (q - _1n) / _2n_pow_c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic\n const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic\n const c4 = _2n_pow_c1 - _1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic\n const c5 = _2n_pow_c1_1; // 5. c5 = 2^(c1 - 1) # Integer arithmetic\n const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2\n const c7 = Fp.pow(Z, (c2 + _1n) / _2n); // 7. c7 = Z^((c2 + 1) / 2)\n let sqrtRatio = (u, v) => {\n let tv1 = c6; // 1. tv1 = c6\n let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4\n let tv3 = Fp.sqr(tv2); // 3. tv3 = tv2^2\n tv3 = Fp.mul(tv3, v); // 4. tv3 = tv3 * v\n let tv5 = Fp.mul(u, tv3); // 5. tv5 = u * tv3\n tv5 = Fp.pow(tv5, c3); // 6. tv5 = tv5^c3\n tv5 = Fp.mul(tv5, tv2); // 7. tv5 = tv5 * tv2\n tv2 = Fp.mul(tv5, v); // 8. tv2 = tv5 * v\n tv3 = Fp.mul(tv5, u); // 9. tv3 = tv5 * u\n let tv4 = Fp.mul(tv3, tv2); // 10. tv4 = tv3 * tv2\n tv5 = Fp.pow(tv4, c5); // 11. tv5 = tv4^c5\n let isQR = Fp.eql(tv5, Fp.ONE); // 12. isQR = tv5 == 1\n tv2 = Fp.mul(tv3, c7); // 13. tv2 = tv3 * c7\n tv5 = Fp.mul(tv4, tv1); // 14. tv5 = tv4 * tv1\n tv3 = Fp.cmov(tv2, tv3, isQR); // 15. tv3 = CMOV(tv2, tv3, isQR)\n tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)\n // 17. for i in (c1, c1 - 1, ..., 2):\n for (let i = c1; i > _1n; i--) {\n let tv5 = i - _2n; // 18. tv5 = i - 2\n tv5 = _2n << (tv5 - _1n); // 19. tv5 = 2^tv5\n let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5\n const e1 = Fp.eql(tvv5, Fp.ONE); // 21. e1 = tv5 == 1\n tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1\n tv1 = Fp.mul(tv1, tv1); // 23. tv1 = tv1 * tv1\n tvv5 = Fp.mul(tv4, tv1); // 24. tv5 = tv4 * tv1\n tv3 = Fp.cmov(tv2, tv3, e1); // 25. tv3 = CMOV(tv2, tv3, e1)\n tv4 = Fp.cmov(tvv5, tv4, e1); // 26. tv4 = CMOV(tv5, tv4, e1)\n }\n return { isValid: isQR, value: tv3 };\n };\n if (Fp.ORDER % _4n === _3n) {\n // sqrt_ratio_3mod4(u, v)\n const c1 = (Fp.ORDER - _3n) / _4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic\n const c2 = Fp.sqrt(Fp.neg(Z)); // 2. c2 = sqrt(-Z)\n sqrtRatio = (u, v) => {\n let tv1 = Fp.sqr(v); // 1. tv1 = v^2\n const tv2 = Fp.mul(u, v); // 2. tv2 = u * v\n tv1 = Fp.mul(tv1, tv2); // 3. tv1 = tv1 * tv2\n let y1 = Fp.pow(tv1, c1); // 4. y1 = tv1^c1\n y1 = Fp.mul(y1, tv2); // 5. y1 = y1 * tv2\n const y2 = Fp.mul(y1, c2); // 6. y2 = y1 * c2\n const tv3 = Fp.mul(Fp.sqr(y1), v); // 7. tv3 = y1^2; 8. tv3 = tv3 * v\n const isQR = Fp.eql(tv3, u); // 9. isQR = tv3 == u\n let y = Fp.cmov(y2, y1, isQR); // 10. y = CMOV(y2, y1, isQR)\n return { isValid: isQR, value: y }; // 11. return (isQR, y) isQR ? y : y*c2\n };\n }\n // No curves uses that\n // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8\n return sqrtRatio;\n}\n/**\n * Simplified Shallue-van de Woestijne-Ulas Method\n * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2\n */\nexport function mapToCurveSimpleSWU(Fp, opts) {\n mod.validateField(Fp);\n if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z))\n throw new Error('mapToCurveSimpleSWU: invalid opts');\n const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z);\n if (!Fp.isOdd)\n throw new Error('Fp.isOdd is not implemented!');\n // Input: u, an element of F.\n // Output: (x, y), a point on E.\n return (u) => {\n // prettier-ignore\n let tv1, tv2, tv3, tv4, tv5, tv6, x, y;\n tv1 = Fp.sqr(u); // 1. tv1 = u^2\n tv1 = Fp.mul(tv1, opts.Z); // 2. tv1 = Z * tv1\n tv2 = Fp.sqr(tv1); // 3. tv2 = tv1^2\n tv2 = Fp.add(tv2, tv1); // 4. tv2 = tv2 + tv1\n tv3 = Fp.add(tv2, Fp.ONE); // 5. tv3 = tv2 + 1\n tv3 = Fp.mul(tv3, opts.B); // 6. tv3 = B * tv3\n tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)); // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)\n tv4 = Fp.mul(tv4, opts.A); // 8. tv4 = A * tv4\n tv2 = Fp.sqr(tv3); // 9. tv2 = tv3^2\n tv6 = Fp.sqr(tv4); // 10. tv6 = tv4^2\n tv5 = Fp.mul(tv6, opts.A); // 11. tv5 = A * tv6\n tv2 = Fp.add(tv2, tv5); // 12. tv2 = tv2 + tv5\n tv2 = Fp.mul(tv2, tv3); // 13. tv2 = tv2 * tv3\n tv6 = Fp.mul(tv6, tv4); // 14. tv6 = tv6 * tv4\n tv5 = Fp.mul(tv6, opts.B); // 15. tv5 = B * tv6\n tv2 = Fp.add(tv2, tv5); // 16. tv2 = tv2 + tv5\n x = Fp.mul(tv1, tv3); // 17. x = tv1 * tv3\n const { isValid, value } = sqrtRatio(tv2, tv6); // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)\n y = Fp.mul(tv1, u); // 19. y = tv1 * u -> Z * u^3 * y1\n y = Fp.mul(y, value); // 20. y = y * y1\n x = Fp.cmov(x, tv3, isValid); // 21. x = CMOV(x, tv3, is_gx1_square)\n y = Fp.cmov(y, value, isValid); // 22. y = CMOV(y, y1, is_gx1_square)\n const e1 = Fp.isOdd(u) === Fp.isOdd(y); // 23. e1 = sgn0(u) == sgn0(y)\n y = Fp.cmov(Fp.neg(y), y, e1); // 24. y = CMOV(-y, y, e1)\n x = Fp.div(x, tv4); // 25. x = x / tv4\n return { x, y };\n };\n}\n//# sourceMappingURL=weierstrass.js.map","import { hash as assertHash, bytes as assertBytes, exists as assertExists } from './_assert.js';\nimport { Hash, toBytes } from './utils.js';\n// HMAC (RFC 2104)\nexport class HMAC extends Hash {\n constructor(hash, _key) {\n super();\n this.finished = false;\n this.destroyed = false;\n assertHash(hash);\n const key = toBytes(_key);\n this.iHash = hash.create();\n if (typeof this.iHash.update !== 'function')\n throw new Error('Expected instance of class which extends utils.Hash');\n this.blockLen = this.iHash.blockLen;\n this.outputLen = this.iHash.outputLen;\n const blockLen = this.blockLen;\n const pad = new Uint8Array(blockLen);\n // blockLen can be bigger than outputLen\n pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);\n for (let i = 0; i < pad.length; i++)\n pad[i] ^= 0x36;\n this.iHash.update(pad);\n // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone\n this.oHash = hash.create();\n // Undo internal XOR && apply outer XOR\n for (let i = 0; i < pad.length; i++)\n pad[i] ^= 0x36 ^ 0x5c;\n this.oHash.update(pad);\n pad.fill(0);\n }\n update(buf) {\n assertExists(this);\n this.iHash.update(buf);\n return this;\n }\n digestInto(out) {\n assertExists(this);\n assertBytes(out, this.outputLen);\n this.finished = true;\n this.iHash.digestInto(out);\n this.oHash.update(out);\n this.oHash.digestInto(out);\n this.destroy();\n }\n digest() {\n const out = new Uint8Array(this.oHash.outputLen);\n this.digestInto(out);\n return out;\n }\n _cloneInto(to) {\n // Create new instance without calling constructor since key already in state and we don't know it.\n to || (to = Object.create(Object.getPrototypeOf(this), {}));\n const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;\n to = to;\n to.finished = finished;\n to.destroyed = destroyed;\n to.blockLen = blockLen;\n to.outputLen = outputLen;\n to.oHash = oHash._cloneInto(to.oHash);\n to.iHash = iHash._cloneInto(to.iHash);\n return to;\n }\n destroy() {\n this.destroyed = true;\n this.oHash.destroy();\n this.iHash.destroy();\n }\n}\n/**\n * HMAC: RFC2104 message authentication code.\n * @param hash - function that would be used e.g. sha256\n * @param key - message key\n * @param message - message data\n */\nexport const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();\nhmac.create = (hash, key) => new HMAC(hash, key);\n//# sourceMappingURL=hmac.js.map","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nimport { hmac } from '@noble/hashes/hmac';\nimport { concatBytes, randomBytes } from '@noble/hashes/utils';\nimport { weierstrass } from './abstract/weierstrass.js';\n// connects noble-curves to noble-hashes\nexport function getHash(hash) {\n return {\n hash,\n hmac: (key, ...msgs) => hmac(hash, key, concatBytes(...msgs)),\n randomBytes,\n };\n}\nexport function createCurve(curveDef, defHash) {\n const create = (hash) => weierstrass({ ...curveDef, ...getHash(hash) });\n return Object.freeze({ ...create(defHash), create });\n}\n//# sourceMappingURL=_shortw_utils.js.map","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nimport { sha256 } from '@noble/hashes/sha256';\nimport { randomBytes } from '@noble/hashes/utils';\nimport { Field, mod, pow2 } from './abstract/modular.js';\nimport { mapToCurveSimpleSWU } from './abstract/weierstrass.js';\nimport { bytesToNumberBE, concatBytes, ensureBytes, numberToBytesBE } from './abstract/utils.js';\nimport { createHasher, isogenyMap } from './abstract/hash-to-curve.js';\nimport { createCurve } from './_shortw_utils.js';\nconst secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');\nconst secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nconst divNearest = (a, b) => (a + b / _2n) / b;\n/**\n * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit.\n * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]\n */\nfunction sqrtMod(y) {\n const P = secp256k1P;\n // prettier-ignore\n const _3n = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);\n // prettier-ignore\n const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88);\n const b2 = (y * y * y) % P; // x^3, 11\n const b3 = (b2 * b2 * y) % P; // x^7\n const b6 = (pow2(b3, _3n, P) * b3) % P;\n const b9 = (pow2(b6, _3n, P) * b3) % P;\n const b11 = (pow2(b9, _2n, P) * b2) % P;\n const b22 = (pow2(b11, _11n, P) * b11) % P;\n const b44 = (pow2(b22, _22n, P) * b22) % P;\n const b88 = (pow2(b44, _44n, P) * b44) % P;\n const b176 = (pow2(b88, _88n, P) * b88) % P;\n const b220 = (pow2(b176, _44n, P) * b44) % P;\n const b223 = (pow2(b220, _3n, P) * b3) % P;\n const t1 = (pow2(b223, _23n, P) * b22) % P;\n const t2 = (pow2(t1, _6n, P) * b2) % P;\n const root = pow2(t2, _2n, P);\n if (!Fp.eql(Fp.sqr(root), y))\n throw new Error('Cannot find square root');\n return root;\n}\nconst Fp = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod });\nexport const secp256k1 = createCurve({\n a: BigInt(0),\n b: BigInt(7),\n Fp,\n n: secp256k1N,\n // Base point (x, y) aka generator point\n Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),\n Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),\n h: BigInt(1),\n lowS: true,\n /**\n * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.\n * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.\n * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.\n * Explanation: https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066\n */\n endo: {\n beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),\n splitScalar: (k) => {\n const n = secp256k1N;\n const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');\n const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');\n const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');\n const b2 = a1;\n const POW_2_128 = BigInt('0x100000000000000000000000000000000'); // (2n**128n).toString(16)\n const c1 = divNearest(b2 * k, n);\n const c2 = divNearest(-b1 * k, n);\n let k1 = mod(k - c1 * a1 - c2 * a2, n);\n let k2 = mod(-c1 * b1 - c2 * b2, n);\n const k1neg = k1 > POW_2_128;\n const k2neg = k2 > POW_2_128;\n if (k1neg)\n k1 = n - k1;\n if (k2neg)\n k2 = n - k2;\n if (k1 > POW_2_128 || k2 > POW_2_128) {\n throw new Error('splitScalar: Endomorphism failed, k=' + k);\n }\n return { k1neg, k1, k2neg, k2 };\n },\n },\n}, sha256);\n// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.\n// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki\nconst _0n = BigInt(0);\nconst fe = (x) => typeof x === 'bigint' && _0n < x && x < secp256k1P;\nconst ge = (x) => typeof x === 'bigint' && _0n < x && x < secp256k1N;\n/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */\nconst TAGGED_HASH_PREFIXES = {};\nfunction taggedHash(tag, ...messages) {\n let tagP = TAGGED_HASH_PREFIXES[tag];\n if (tagP === undefined) {\n const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0)));\n tagP = concatBytes(tagH, tagH);\n TAGGED_HASH_PREFIXES[tag] = tagP;\n }\n return sha256(concatBytes(tagP, ...messages));\n}\n// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03\nconst pointToBytes = (point) => point.toRawBytes(true).slice(1);\nconst numTo32b = (n) => numberToBytesBE(n, 32);\nconst modP = (x) => mod(x, secp256k1P);\nconst modN = (x) => mod(x, secp256k1N);\nconst Point = secp256k1.ProjectivePoint;\nconst GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b);\n// Calculate point, scalar and bytes\nfunction schnorrGetExtPubKey(priv) {\n let d_ = secp256k1.utils.normPrivateKeyToScalar(priv); // same method executed in fromPrivateKey\n let p = Point.fromPrivateKey(d_); // P = d'⋅G; 0 < d' < n check is done inside\n const scalar = p.hasEvenY() ? d_ : modN(-d_);\n return { scalar: scalar, bytes: pointToBytes(p) };\n}\n/**\n * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point.\n * @returns valid point checked for being on-curve\n */\nfunction lift_x(x) {\n if (!fe(x))\n throw new Error('bad x: need 0 < x < p'); // Fail if x ≥ p.\n const xx = modP(x * x);\n const c = modP(xx * x + BigInt(7)); // Let c = x³ + 7 mod p.\n let y = sqrtMod(c); // Let y = c^(p+1)/4 mod p.\n if (y % _2n !== _0n)\n y = modP(-y); // Return the unique point P such that x(P) = x and\n const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.\n p.assertValidity();\n return p;\n}\n/**\n * Create tagged hash, convert it to bigint, reduce modulo-n.\n */\nfunction challenge(...args) {\n return modN(bytesToNumberBE(taggedHash('BIP0340/challenge', ...args)));\n}\n/**\n * Schnorr public key is just `x` coordinate of Point as per BIP340.\n */\nfunction schnorrGetPublicKey(privateKey) {\n return schnorrGetExtPubKey(privateKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)\n}\n/**\n * Creates Schnorr signature as per BIP340. Verifies itself before returning anything.\n * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous.\n */\nfunction schnorrSign(message, privateKey, auxRand = randomBytes(32)) {\n const m = ensureBytes('message', message);\n const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey); // checks for isWithinCurveOrder\n const a = ensureBytes('auxRand', auxRand, 32); // Auxiliary random data a: a 32-byte array\n const t = numTo32b(d ^ bytesToNumberBE(taggedHash('BIP0340/aux', a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)\n const rand = taggedHash('BIP0340/nonce', t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)\n const k_ = modN(bytesToNumberBE(rand)); // Let k' = int(rand) mod n\n if (k_ === _0n)\n throw new Error('sign failed: k is zero'); // Fail if k' = 0.\n const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.\n const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.\n const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).\n sig.set(rx, 0);\n sig.set(numTo32b(modN(k + e * d)), 32);\n // If Verify(bytes(P), m, sig) (see below) returns failure, abort\n if (!schnorrVerify(sig, m, px))\n throw new Error('sign: Invalid signature produced');\n return sig;\n}\n/**\n * Verifies Schnorr signature.\n * Will swallow errors & return false except for initial type validation of arguments.\n */\nfunction schnorrVerify(signature, message, publicKey) {\n const sig = ensureBytes('signature', signature, 64);\n const m = ensureBytes('message', message);\n const pub = ensureBytes('publicKey', publicKey, 32);\n try {\n const P = lift_x(bytesToNumberBE(pub)); // P = lift_x(int(pk)); fail if that fails\n const r = bytesToNumberBE(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.\n if (!fe(r))\n return false;\n const s = bytesToNumberBE(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.\n if (!ge(s))\n return false;\n const e = challenge(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m))%n\n const R = GmulAdd(P, s, modN(-e)); // R = s⋅G - e⋅P\n if (!R || !R.hasEvenY() || R.toAffine().x !== r)\n return false; // -eP == (n-e)P\n return true; // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r.\n }\n catch (error) {\n return false;\n }\n}\nexport const schnorr = /* @__PURE__ */ (() => ({\n getPublicKey: schnorrGetPublicKey,\n sign: schnorrSign,\n verify: schnorrVerify,\n utils: {\n randomPrivateKey: secp256k1.utils.randomPrivateKey,\n lift_x,\n pointToBytes,\n numberToBytesBE,\n bytesToNumberBE,\n taggedHash,\n mod,\n },\n}))();\nconst isoMap = /* @__PURE__ */ (() => isogenyMap(Fp, [\n // xNum\n [\n '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7',\n '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581',\n '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262',\n '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c',\n ],\n // xDen\n [\n '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b',\n '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14',\n '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1\n ],\n // yNum\n [\n '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c',\n '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3',\n '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931',\n '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84',\n ],\n // yDen\n [\n '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b',\n '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573',\n '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f',\n '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1\n ],\n].map((i) => i.map((j) => BigInt(j)))))();\nconst mapSWU = /* @__PURE__ */ (() => mapToCurveSimpleSWU(Fp, {\n A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'),\n B: BigInt('1771'),\n Z: Fp.create(BigInt('-11')),\n}))();\nconst htf = /* @__PURE__ */ (() => createHasher(secp256k1.ProjectivePoint, (scalars) => {\n const { x, y } = mapSWU(Fp.create(scalars[0]));\n return isoMap(x, y);\n}, {\n DST: 'secp256k1_XMD:SHA-256_SSWU_RO_',\n encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_',\n p: Fp.ORDER,\n m: 1,\n k: 128,\n expand: 'xmd',\n hash: sha256,\n}))();\nexport const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)();\nexport const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)();\n//# sourceMappingURL=secp256k1.js.map","export const crypto = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;\n//# sourceMappingURL=crypto.js.map","/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// node.js versions earlier than v19 don't declare it in global scope.\n// For node.js, package.json#exports field mapping rewrites import\n// from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated, we can just drop the import.\nimport { crypto } from '@noble/hashes/crypto';\nconst u8a = (a) => a instanceof Uint8Array;\n// Cast array to different type\nexport const u8 = (arr) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\nexport const u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n// Cast array to view\nexport const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n// The rotate right (circular right shift) operation for uint32\nexport const rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);\n// big-endian hardware is rare. Just in case someone still decides to run hashes:\n// early-throw an error because we don't support BE yet.\nexport const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;\nif (!isLE)\n throw new Error('Non little-endian hardware is not supported');\nconst hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));\n/**\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes) {\n if (!u8a(bytes))\n throw new Error('Uint8Array expected');\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n/**\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n const len = hex.length;\n if (len % 2)\n throw new Error('padded hex string expected, got unpadded hex of length ' + len);\n const array = new Uint8Array(len / 2);\n for (let i = 0; i < array.length; i++) {\n const j = i * 2;\n const hexByte = hex.slice(j, j + 2);\n const byte = Number.parseInt(hexByte, 16);\n if (Number.isNaN(byte) || byte < 0)\n throw new Error('Invalid byte sequence');\n array[i] = byte;\n }\n return array;\n}\n// There is no setImmediate in browser and setTimeout is slow.\n// call of async fn will return Promise, which will be fullfiled only on\n// next scheduler queue processing step and this is exactly what we need.\nexport const nextTick = async () => { };\n// Returns control to thread each 'tick' ms to avoid blocking\nexport async function asyncLoop(iters, tick, cb) {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick)\n continue;\n await nextTick();\n ts += diff;\n }\n}\n/**\n * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])\n */\nexport function utf8ToBytes(str) {\n if (typeof str !== 'string')\n throw new Error(`utf8ToBytes expected string, got ${typeof str}`);\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data) {\n if (typeof data === 'string')\n data = utf8ToBytes(data);\n if (!u8a(data))\n throw new Error(`expected Uint8Array, got ${typeof data}`);\n return data;\n}\n/**\n * Copies several Uint8Arrays into one.\n */\nexport function concatBytes(...arrays) {\n const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));\n let pad = 0; // walk through each item, ensure they have proper type\n arrays.forEach((a) => {\n if (!u8a(a))\n throw new Error('Uint8Array expected');\n r.set(a, pad);\n pad += a.length;\n });\n return r;\n}\n// For runtime check if class implements interface\nexport class Hash {\n // Safe version that clones internal state\n clone() {\n return this._cloneInto();\n }\n}\n// Check if object doens't have custom constructor (like Uint8Array/Array)\nconst isPlainObject = (obj) => Object.prototype.toString.call(obj) === '[object Object]' && obj.constructor === Object;\nexport function checkOpts(defaults, opts) {\n if (opts !== undefined && (typeof opts !== 'object' || !isPlainObject(opts)))\n throw new Error('Options should be object or undefined');\n const merged = Object.assign(defaults, opts);\n return merged;\n}\nexport function wrapConstructor(hashCons) {\n const hashC = (msg) => hashCons().update(toBytes(msg)).digest();\n const tmp = hashCons();\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = () => hashCons();\n return hashC;\n}\nexport function wrapConstructorWithOpts(hashCons) {\n const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({});\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts) => hashCons(opts);\n return hashC;\n}\nexport function wrapXOFConstructorWithOpts(hashCons) {\n const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({});\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts) => hashCons(opts);\n return hashC;\n}\n/**\n * Secure PRNG. Uses `crypto.getRandomValues`, which defers to OS.\n */\nexport function randomBytes(bytesLength = 32) {\n if (crypto && typeof crypto.getRandomValues === 'function') {\n return crypto.getRandomValues(new Uint8Array(bytesLength));\n }\n throw new Error('crypto.getRandomValues must be defined');\n}\n//# sourceMappingURL=utils.js.map","export function number(n) {\n if (!Number.isSafeInteger(n) || n < 0)\n throw new Error(`Wrong positive integer: ${n}`);\n}\nexport function bool(b) {\n if (typeof b !== 'boolean')\n throw new Error(`Expected boolean, not ${b}`);\n}\nexport function bytes(b, ...lengths) {\n if (!(b instanceof Uint8Array))\n throw new Error('Expected Uint8Array');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);\n}\nexport function hash(hash) {\n if (typeof hash !== 'function' || typeof hash.create !== 'function')\n throw new Error('Hash should be wrapped by utils.wrapConstructor');\n number(hash.outputLen);\n number(hash.blockLen);\n}\nexport function exists(instance, checkFinished = true) {\n if (instance.destroyed)\n throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished)\n throw new Error('Hash#digest() has already been called');\n}\nexport function output(out, instance) {\n bytes(out);\n const min = instance.outputLen;\n if (out.length < min) {\n throw new Error(`digestInto() expects output buffer of length at least ${min}`);\n }\n}\nconst assert = {\n number,\n bool,\n bytes,\n hash,\n exists,\n output,\n};\nexport default assert;\n//# sourceMappingURL=_assert.js.map","import assert from './_assert.js';\nimport { Hash, createView, toBytes } from './utils.js';\n// Polyfill for Safari 14\nfunction setBigUint64(view, byteOffset, value, isLE) {\n if (typeof view.setBigUint64 === 'function')\n return view.setBigUint64(byteOffset, value, isLE);\n const _32n = BigInt(32);\n const _u32_max = BigInt(0xffffffff);\n const wh = Number((value >> _32n) & _u32_max);\n const wl = Number(value & _u32_max);\n const h = isLE ? 4 : 0;\n const l = isLE ? 0 : 4;\n view.setUint32(byteOffset + h, wh, isLE);\n view.setUint32(byteOffset + l, wl, isLE);\n}\n// Base SHA2 class (RFC 6234)\nexport class SHA2 extends Hash {\n constructor(blockLen, outputLen, padOffset, isLE) {\n super();\n this.blockLen = blockLen;\n this.outputLen = outputLen;\n this.padOffset = padOffset;\n this.isLE = isLE;\n this.finished = false;\n this.length = 0;\n this.pos = 0;\n this.destroyed = false;\n this.buffer = new Uint8Array(blockLen);\n this.view = createView(this.buffer);\n }\n update(data) {\n assert.exists(this);\n const { view, buffer, blockLen } = this;\n data = toBytes(data);\n const len = data.length;\n for (let pos = 0; pos < len;) {\n const take = Math.min(blockLen - this.pos, len - pos);\n // Fast path: we have at least one block in input, cast it to view and process\n if (take === blockLen) {\n const dataView = createView(data);\n for (; blockLen <= len - pos; pos += blockLen)\n this.process(dataView, pos);\n continue;\n }\n buffer.set(data.subarray(pos, pos + take), this.pos);\n this.pos += take;\n pos += take;\n if (this.pos === blockLen) {\n this.process(view, 0);\n this.pos = 0;\n }\n }\n this.length += data.length;\n this.roundClean();\n return this;\n }\n digestInto(out) {\n assert.exists(this);\n assert.output(out, this);\n this.finished = true;\n // Padding\n // We can avoid allocation of buffer for padding completely if it\n // was previously not allocated here. But it won't change performance.\n const { buffer, view, blockLen, isLE } = this;\n let { pos } = this;\n // append the bit '1' to the message\n buffer[pos++] = 0b10000000;\n this.buffer.subarray(pos).fill(0);\n // we have less than padOffset left in buffer, so we cannot put length in current block, need process it and pad again\n if (this.padOffset > blockLen - pos) {\n this.process(view, 0);\n pos = 0;\n }\n // Pad until full block byte with zeros\n for (let i = pos; i < blockLen; i++)\n buffer[i] = 0;\n // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that\n // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.\n // So we just write lowest 64 bits of that value.\n setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);\n this.process(view, 0);\n const oview = createView(out);\n const len = this.outputLen;\n // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT\n if (len % 4)\n throw new Error('_sha2: outputLen should be aligned to 32bit');\n const outLen = len / 4;\n const state = this.get();\n if (outLen > state.length)\n throw new Error('_sha2: outputLen bigger than state');\n for (let i = 0; i < outLen; i++)\n oview.setUint32(4 * i, state[i], isLE);\n }\n digest() {\n const { buffer, outputLen } = this;\n this.digestInto(buffer);\n const res = buffer.slice(0, outputLen);\n this.destroy();\n return res;\n }\n _cloneInto(to) {\n to || (to = new this.constructor());\n to.set(...this.get());\n const { blockLen, buffer, length, finished, destroyed, pos } = this;\n to.length = length;\n to.pos = pos;\n to.finished = finished;\n to.destroyed = destroyed;\n if (length % blockLen)\n to.buffer.set(buffer);\n return to;\n }\n}\n//# sourceMappingURL=_sha2.js.map","import { SHA2 } from './_sha2.js';\nimport { rotr, wrapConstructor } from './utils.js';\n// Choice: a ? b : c\nconst Chi = (a, b, c) => (a & b) ^ (~a & c);\n// Majority function, true if any two inpust is true\nconst Maj = (a, b, c) => (a & b) ^ (a & c) ^ (b & c);\n// Round constants:\n// first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)\n// prettier-ignore\nconst SHA256_K = new Uint32Array([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n]);\n// Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):\n// prettier-ignore\nconst IV = new Uint32Array([\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19\n]);\n// Temporary buffer, not used to store anything between runs\n// Named this way because it matches specification.\nconst SHA256_W = new Uint32Array(64);\nclass SHA256 extends SHA2 {\n constructor() {\n super(64, 32, 8, false);\n // We cannot use array here since array allows indexing by variable\n // which means optimizer/compiler cannot use registers.\n this.A = IV[0] | 0;\n this.B = IV[1] | 0;\n this.C = IV[2] | 0;\n this.D = IV[3] | 0;\n this.E = IV[4] | 0;\n this.F = IV[5] | 0;\n this.G = IV[6] | 0;\n this.H = IV[7] | 0;\n }\n get() {\n const { A, B, C, D, E, F, G, H } = this;\n return [A, B, C, D, E, F, G, H];\n }\n // prettier-ignore\n set(A, B, C, D, E, F, G, H) {\n this.A = A | 0;\n this.B = B | 0;\n this.C = C | 0;\n this.D = D | 0;\n this.E = E | 0;\n this.F = F | 0;\n this.G = G | 0;\n this.H = H | 0;\n }\n process(view, offset) {\n // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4)\n SHA256_W[i] = view.getUint32(offset, false);\n for (let i = 16; i < 64; i++) {\n const W15 = SHA256_W[i - 15];\n const W2 = SHA256_W[i - 2];\n const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);\n const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);\n SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;\n }\n // Compression function main loop, 64 rounds\n let { A, B, C, D, E, F, G, H } = this;\n for (let i = 0; i < 64; i++) {\n const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);\n const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);\n const T2 = (sigma0 + Maj(A, B, C)) | 0;\n H = G;\n G = F;\n F = E;\n E = (D + T1) | 0;\n D = C;\n C = B;\n B = A;\n A = (T1 + T2) | 0;\n }\n // Add the compressed chunk to the current hash value\n A = (A + this.A) | 0;\n B = (B + this.B) | 0;\n C = (C + this.C) | 0;\n D = (D + this.D) | 0;\n E = (E + this.E) | 0;\n F = (F + this.F) | 0;\n G = (G + this.G) | 0;\n H = (H + this.H) | 0;\n this.set(A, B, C, D, E, F, G, H);\n }\n roundClean() {\n SHA256_W.fill(0);\n }\n destroy() {\n this.set(0, 0, 0, 0, 0, 0, 0, 0);\n this.buffer.fill(0);\n }\n}\n// Constants from https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf\nclass SHA224 extends SHA256 {\n constructor() {\n super();\n this.A = 0xc1059ed8 | 0;\n this.B = 0x367cd507 | 0;\n this.C = 0x3070dd17 | 0;\n this.D = 0xf70e5939 | 0;\n this.E = 0xffc00b31 | 0;\n this.F = 0x68581511 | 0;\n this.G = 0x64f98fa7 | 0;\n this.H = 0xbefa4fa4 | 0;\n this.outputLen = 28;\n }\n}\n/**\n * SHA2-256 hash function\n * @param message - data that would be hashed\n */\nexport const sha256 = wrapConstructor(() => new SHA256());\nexport const sha224 = wrapConstructor(() => new SHA224());\n//# sourceMappingURL=sha256.js.map","// pure.ts\nimport { schnorr } from \"@noble/curves/secp256k1\";\nimport { bytesToHex as bytesToHex2 } from \"@noble/hashes/utils\";\n\n// core.ts\nvar verifiedSymbol = Symbol(\"verified\");\nvar isRecord = (obj) => obj instanceof Object;\nfunction validateEvent(event) {\n if (!isRecord(event))\n return false;\n if (typeof event.kind !== \"number\")\n return false;\n if (typeof event.content !== \"string\")\n return false;\n if (typeof event.created_at !== \"number\")\n return false;\n if (typeof event.pubkey !== \"string\")\n return false;\n if (!event.pubkey.match(/^[a-f0-9]{64}$/))\n return false;\n if (!Array.isArray(event.tags))\n return false;\n for (let i2 = 0; i2 < event.tags.length; i2++) {\n let tag = event.tags[i2];\n if (!Array.isArray(tag))\n return false;\n for (let j = 0; j < tag.length; j++) {\n if (typeof tag[j] !== \"string\")\n return false;\n }\n }\n return true;\n}\n\n// pure.ts\nimport { sha256 } from \"@noble/hashes/sha256\";\n\n// utils.ts\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils\";\nvar utf8Decoder = new TextDecoder(\"utf-8\");\nvar utf8Encoder = new TextEncoder();\nfunction normalizeURL(url) {\n try {\n if (url.indexOf(\"://\") === -1)\n url = \"wss://\" + url;\n let p = new URL(url);\n p.pathname = p.pathname.replace(/\\/+/g, \"/\");\n if (p.pathname.endsWith(\"/\"))\n p.pathname = p.pathname.slice(0, -1);\n if (p.port === \"80\" && p.protocol === \"ws:\" || p.port === \"443\" && p.protocol === \"wss:\")\n p.port = \"\";\n p.searchParams.sort();\n p.hash = \"\";\n return p.toString();\n } catch (e) {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\nvar QueueNode = class {\n value;\n next = null;\n prev = null;\n constructor(message) {\n this.value = message;\n }\n};\nvar Queue = class {\n first;\n last;\n constructor() {\n this.first = null;\n this.last = null;\n }\n enqueue(value) {\n const newNode = new QueueNode(value);\n if (!this.last) {\n this.first = newNode;\n this.last = newNode;\n } else if (this.last === this.first) {\n this.last = newNode;\n this.last.prev = this.first;\n this.first.next = newNode;\n } else {\n newNode.prev = this.last;\n this.last.next = newNode;\n this.last = newNode;\n }\n return true;\n }\n dequeue() {\n if (!this.first)\n return null;\n if (this.first === this.last) {\n const target2 = this.first;\n this.first = null;\n this.last = null;\n return target2.value;\n }\n const target = this.first;\n this.first = target.next;\n if (this.first) {\n this.first.prev = null;\n }\n return target.value;\n }\n};\n\n// pure.ts\nvar JS = class {\n generateSecretKey() {\n return schnorr.utils.randomPrivateKey();\n }\n getPublicKey(secretKey) {\n return bytesToHex2(schnorr.getPublicKey(secretKey));\n }\n finalizeEvent(t, secretKey) {\n const event = t;\n event.pubkey = bytesToHex2(schnorr.getPublicKey(secretKey));\n event.id = getEventHash(event);\n event.sig = bytesToHex2(schnorr.sign(getEventHash(event), secretKey));\n event[verifiedSymbol] = true;\n return event;\n }\n verifyEvent(event) {\n if (typeof event[verifiedSymbol] === \"boolean\")\n return event[verifiedSymbol];\n const hash = getEventHash(event);\n if (hash !== event.id) {\n event[verifiedSymbol] = false;\n return false;\n }\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey);\n event[verifiedSymbol] = valid;\n return valid;\n } catch (err) {\n event[verifiedSymbol] = false;\n return false;\n }\n }\n};\nfunction serializeEvent(evt) {\n if (!validateEvent(evt))\n throw new Error(\"can't serialize event with wrong or missing properties\");\n return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);\n}\nfunction getEventHash(event) {\n let eventHash = sha256(utf8Encoder.encode(serializeEvent(event)));\n return bytesToHex2(eventHash);\n}\nvar i = new JS();\nvar generateSecretKey = i.generateSecretKey;\nvar getPublicKey = i.getPublicKey;\nvar finalizeEvent = i.finalizeEvent;\nvar verifyEvent = i.verifyEvent;\n\n// kinds.ts\nvar ClientAuth = 22242;\n\n// filter.ts\nfunction matchFilter(filter, event) {\n if (filter.ids && filter.ids.indexOf(event.id) === -1) {\n return false;\n }\n if (filter.kinds && filter.kinds.indexOf(event.kind) === -1) {\n return false;\n }\n if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {\n return false;\n }\n for (let f in filter) {\n if (f[0] === \"#\") {\n let tagName = f.slice(1);\n let values = filter[`#${tagName}`];\n if (values && !event.tags.find(([t, v]) => t === f.slice(1) && values.indexOf(v) !== -1))\n return false;\n }\n }\n if (filter.since && event.created_at < filter.since)\n return false;\n if (filter.until && event.created_at > filter.until)\n return false;\n return true;\n}\nfunction matchFilters(filters, event) {\n for (let i2 = 0; i2 < filters.length; i2++) {\n if (matchFilter(filters[i2], event)) {\n return true;\n }\n }\n return false;\n}\n\n// fakejson.ts\nfunction getHex64(json, field) {\n let len = field.length + 3;\n let idx = json.indexOf(`\"${field}\":`) + len;\n let s = json.slice(idx).indexOf(`\"`) + idx + 1;\n return json.slice(s, s + 64);\n}\nfunction getSubscriptionId(json) {\n let idx = json.slice(0, 22).indexOf(`\"EVENT\"`);\n if (idx === -1)\n return null;\n let pstart = json.slice(idx + 7 + 1).indexOf(`\"`);\n if (pstart === -1)\n return null;\n let start = idx + 7 + 1 + pstart;\n let pend = json.slice(start + 1, 80).indexOf(`\"`);\n if (pend === -1)\n return null;\n let end = start + 1 + pend;\n return json.slice(start + 1, end);\n}\n\n// nip42.ts\nfunction makeAuthEvent(relayURL, challenge) {\n return {\n kind: ClientAuth,\n created_at: Math.floor(Date.now() / 1e3),\n tags: [\n [\"relay\", relayURL],\n [\"challenge\", challenge]\n ],\n content: \"\"\n };\n}\n\n// helpers.ts\nasync function yieldThread() {\n return new Promise((resolve) => {\n const ch = new MessageChannel();\n const handler = () => {\n ch.port1.removeEventListener(\"message\", handler);\n resolve();\n };\n ch.port1.addEventListener(\"message\", handler);\n ch.port2.postMessage(0);\n ch.port1.start();\n });\n}\nvar alwaysTrue = (t) => {\n t[verifiedSymbol] = true;\n return true;\n};\n\n// abstract-relay.ts\nvar SendingOnClosedConnection = class extends Error {\n constructor(message, relay) {\n super(`Tried to send message '${message} on a closed connection to ${relay}.`);\n this.name = \"SendingOnClosedConnection\";\n }\n};\nvar AbstractRelay = class {\n url;\n _connected = false;\n onclose = null;\n onnotice = (msg) => console.debug(`NOTICE from ${this.url}: ${msg}`);\n baseEoseTimeout = 4400;\n connectionTimeout = 4400;\n publishTimeout = 4400;\n pingFrequency = 2e4;\n pingTimeout = 2e4;\n openSubs = /* @__PURE__ */ new Map();\n enablePing;\n connectionTimeoutHandle;\n connectionPromise;\n openCountRequests = /* @__PURE__ */ new Map();\n openEventPublishes = /* @__PURE__ */ new Map();\n ws;\n incomingMessageQueue = new Queue();\n queueRunning = false;\n challenge;\n authPromise;\n serial = 0;\n verifyEvent;\n _WebSocket;\n constructor(url, opts) {\n this.url = normalizeURL(url);\n this.verifyEvent = opts.verifyEvent;\n this._WebSocket = opts.websocketImplementation || WebSocket;\n this.enablePing = opts.enablePing;\n }\n static async connect(url, opts) {\n const relay = new AbstractRelay(url, opts);\n await relay.connect();\n return relay;\n }\n closeAllSubscriptions(reason) {\n for (let [_, sub] of this.openSubs) {\n sub.close(reason);\n }\n this.openSubs.clear();\n for (let [_, ep] of this.openEventPublishes) {\n ep.reject(new Error(reason));\n }\n this.openEventPublishes.clear();\n for (let [_, cr] of this.openCountRequests) {\n cr.reject(new Error(reason));\n }\n this.openCountRequests.clear();\n }\n get connected() {\n return this._connected;\n }\n async connect() {\n if (this.connectionPromise)\n return this.connectionPromise;\n this.challenge = void 0;\n this.authPromise = void 0;\n this.connectionPromise = new Promise((resolve, reject) => {\n this.connectionTimeoutHandle = setTimeout(() => {\n reject(\"connection timed out\");\n this.connectionPromise = void 0;\n this.onclose?.();\n this.closeAllSubscriptions(\"relay connection timed out\");\n }, this.connectionTimeout);\n try {\n this.ws = new this._WebSocket(this.url);\n } catch (err) {\n clearTimeout(this.connectionTimeoutHandle);\n reject(err);\n return;\n }\n this.ws.onopen = () => {\n clearTimeout(this.connectionTimeoutHandle);\n this._connected = true;\n if (this.enablePing) {\n this.pingpong();\n }\n resolve();\n };\n this.ws.onerror = (ev) => {\n clearTimeout(this.connectionTimeoutHandle);\n reject(ev.message || \"websocket error\");\n this._connected = false;\n this.connectionPromise = void 0;\n this.onclose?.();\n this.closeAllSubscriptions(\"relay connection errored\");\n };\n this.ws.onclose = (ev) => {\n clearTimeout(this.connectionTimeoutHandle);\n reject(ev.message || \"websocket closed\");\n this._connected = false;\n this.connectionPromise = void 0;\n this.onclose?.();\n this.closeAllSubscriptions(\"relay connection closed\");\n };\n this.ws.onmessage = this._onmessage.bind(this);\n });\n return this.connectionPromise;\n }\n async waitForPingPong() {\n return new Promise((res, err) => {\n ;\n this.ws && this.ws.on && this.ws.on(\"pong\", () => res(true)) || err(\"ws can't listen for pong\");\n this.ws && this.ws.ping && this.ws.ping();\n });\n }\n async waitForDummyReq() {\n return new Promise((resolve, _) => {\n const sub = this.subscribe([{ ids: [\"a\".repeat(64)] }], {\n oneose: () => {\n sub.close();\n resolve(true);\n },\n eoseTimeout: this.pingTimeout + 1e3\n });\n });\n }\n async pingpong() {\n if (this.ws?.readyState === 1) {\n const result = await Promise.any([\n this.ws && this.ws.ping && this.ws.on ? this.waitForPingPong() : this.waitForDummyReq(),\n new Promise((res) => setTimeout(() => res(false), this.pingTimeout))\n ]);\n if (result) {\n setTimeout(() => this.pingpong(), this.pingFrequency);\n } else {\n this.closeAllSubscriptions(\"pingpong timed out\");\n this._connected = false;\n this.onclose?.();\n this.ws?.close();\n }\n }\n }\n async runQueue() {\n this.queueRunning = true;\n while (true) {\n if (false === this.handleNext()) {\n break;\n }\n await yieldThread();\n }\n this.queueRunning = false;\n }\n handleNext() {\n const json = this.incomingMessageQueue.dequeue();\n if (!json) {\n return false;\n }\n const subid = getSubscriptionId(json);\n if (subid) {\n const so = this.openSubs.get(subid);\n if (!so) {\n return;\n }\n const id = getHex64(json, \"id\");\n const alreadyHave = so.alreadyHaveEvent?.(id);\n so.receivedEvent?.(this, id);\n if (alreadyHave) {\n return;\n }\n }\n try {\n let data = JSON.parse(json);\n switch (data[0]) {\n case \"EVENT\": {\n const so = this.openSubs.get(data[1]);\n const event = data[2];\n if (this.verifyEvent(event) && matchFilters(so.filters, event)) {\n so.onevent(event);\n }\n return;\n }\n case \"COUNT\": {\n const id = data[1];\n const payload = data[2];\n const cr = this.openCountRequests.get(id);\n if (cr) {\n cr.resolve(payload.count);\n this.openCountRequests.delete(id);\n }\n return;\n }\n case \"EOSE\": {\n const so = this.openSubs.get(data[1]);\n if (!so)\n return;\n so.receivedEose();\n return;\n }\n case \"OK\": {\n const id = data[1];\n const ok = data[2];\n const reason = data[3];\n const ep = this.openEventPublishes.get(id);\n if (ep) {\n clearTimeout(ep.timeout);\n if (ok)\n ep.resolve(reason);\n else\n ep.reject(new Error(reason));\n this.openEventPublishes.delete(id);\n }\n return;\n }\n case \"CLOSED\": {\n const id = data[1];\n const so = this.openSubs.get(id);\n if (!so)\n return;\n so.closed = true;\n so.close(data[2]);\n return;\n }\n case \"NOTICE\":\n this.onnotice(data[1]);\n return;\n case \"AUTH\": {\n this.challenge = data[1];\n return;\n }\n }\n } catch (err) {\n return;\n }\n }\n async send(message) {\n if (!this.connectionPromise)\n throw new SendingOnClosedConnection(message, this.url);\n this.connectionPromise.then(() => {\n this.ws?.send(message);\n });\n }\n async auth(signAuthEvent) {\n const challenge = this.challenge;\n if (!challenge)\n throw new Error(\"can't perform auth, no challenge was received\");\n if (this.authPromise)\n return this.authPromise;\n this.authPromise = new Promise(async (resolve, reject) => {\n try {\n let evt = await signAuthEvent(makeAuthEvent(this.url, challenge));\n let timeout = setTimeout(() => {\n let ep = this.openEventPublishes.get(evt.id);\n if (ep) {\n ep.reject(new Error(\"auth timed out\"));\n this.openEventPublishes.delete(evt.id);\n }\n }, this.publishTimeout);\n this.openEventPublishes.set(evt.id, { resolve, reject, timeout });\n this.send('[\"AUTH\",' + JSON.stringify(evt) + \"]\");\n } catch (err) {\n console.warn(\"subscribe auth function failed:\", err);\n }\n });\n return this.authPromise;\n }\n async publish(event) {\n const ret = new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n const ep = this.openEventPublishes.get(event.id);\n if (ep) {\n ep.reject(new Error(\"publish timed out\"));\n this.openEventPublishes.delete(event.id);\n }\n }, this.publishTimeout);\n this.openEventPublishes.set(event.id, { resolve, reject, timeout });\n });\n this.send('[\"EVENT\",' + JSON.stringify(event) + \"]\");\n return ret;\n }\n async count(filters, params) {\n this.serial++;\n const id = params?.id || \"count:\" + this.serial;\n const ret = new Promise((resolve, reject) => {\n this.openCountRequests.set(id, { resolve, reject });\n });\n this.send('[\"COUNT\",\"' + id + '\",' + JSON.stringify(filters).substring(1));\n return ret;\n }\n subscribe(filters, params) {\n const subscription = this.prepareSubscription(filters, params);\n subscription.fire();\n return subscription;\n }\n prepareSubscription(filters, params) {\n this.serial++;\n const id = params.id || (params.label ? params.label + \":\" : \"sub:\") + this.serial;\n const subscription = new Subscription(this, id, filters, params);\n this.openSubs.set(id, subscription);\n return subscription;\n }\n close() {\n this.closeAllSubscriptions(\"relay connection closed by us\");\n this._connected = false;\n this.onclose?.();\n this.ws?.close();\n }\n _onmessage(ev) {\n this.incomingMessageQueue.enqueue(ev.data);\n if (!this.queueRunning) {\n this.runQueue();\n }\n }\n};\nvar Subscription = class {\n relay;\n id;\n closed = false;\n eosed = false;\n filters;\n alreadyHaveEvent;\n receivedEvent;\n onevent;\n oneose;\n onclose;\n eoseTimeout;\n eoseTimeoutHandle;\n constructor(relay, id, filters, params) {\n this.relay = relay;\n this.filters = filters;\n this.id = id;\n this.alreadyHaveEvent = params.alreadyHaveEvent;\n this.receivedEvent = params.receivedEvent;\n this.eoseTimeout = params.eoseTimeout || relay.baseEoseTimeout;\n this.oneose = params.oneose;\n this.onclose = params.onclose;\n this.onevent = params.onevent || ((event) => {\n console.warn(\n `onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`,\n event\n );\n });\n }\n fire() {\n this.relay.send('[\"REQ\",\"' + this.id + '\",' + JSON.stringify(this.filters).substring(1));\n this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout);\n }\n receivedEose() {\n if (this.eosed)\n return;\n clearTimeout(this.eoseTimeoutHandle);\n this.eosed = true;\n this.oneose?.();\n }\n close(reason = \"closed by caller\") {\n if (!this.closed && this.relay.connected) {\n try {\n this.relay.send('[\"CLOSE\",' + JSON.stringify(this.id) + \"]\");\n } catch (err) {\n if (err instanceof SendingOnClosedConnection) {\n } else {\n throw err;\n }\n }\n this.closed = true;\n }\n this.relay.openSubs.delete(this.id);\n this.onclose?.(reason);\n }\n};\n\n// abstract-pool.ts\nvar AbstractSimplePool = class {\n relays = /* @__PURE__ */ new Map();\n seenOn = /* @__PURE__ */ new Map();\n trackRelays = false;\n verifyEvent;\n enablePing;\n trustedRelayURLs = /* @__PURE__ */ new Set();\n _WebSocket;\n constructor(opts) {\n this.verifyEvent = opts.verifyEvent;\n this._WebSocket = opts.websocketImplementation;\n this.enablePing = opts.enablePing;\n }\n async ensureRelay(url, params) {\n url = normalizeURL(url);\n let relay = this.relays.get(url);\n if (!relay) {\n relay = new AbstractRelay(url, {\n verifyEvent: this.trustedRelayURLs.has(url) ? alwaysTrue : this.verifyEvent,\n websocketImplementation: this._WebSocket,\n enablePing: this.enablePing\n });\n relay.onclose = () => {\n this.relays.delete(url);\n };\n if (params?.connectionTimeout)\n relay.connectionTimeout = params.connectionTimeout;\n this.relays.set(url, relay);\n }\n await relay.connect();\n return relay;\n }\n close(relays) {\n relays.map(normalizeURL).forEach((url) => {\n this.relays.get(url)?.close();\n this.relays.delete(url);\n });\n }\n subscribe(relays, filter, params) {\n params.onauth = params.onauth || params.doauth;\n const request = [];\n for (let i2 = 0; i2 < relays.length; i2++) {\n const url = normalizeURL(relays[i2]);\n if (!request.find((r) => r.url === url)) {\n request.push({ url, filter });\n }\n }\n return this.subscribeMap(request, params);\n }\n subscribeMany(relays, filter, params) {\n params.onauth = params.onauth || params.doauth;\n const request = [];\n const uniqUrls = [];\n for (let i2 = 0; i2 < relays.length; i2++) {\n const url = normalizeURL(relays[i2]);\n if (uniqUrls.indexOf(url) === -1) {\n uniqUrls.push(url);\n request.push({ url, filter });\n }\n }\n return this.subscribeMap(request, params);\n }\n subscribeMap(requests, params) {\n params.onauth = params.onauth || params.doauth;\n const grouped = /* @__PURE__ */ new Map();\n for (const req of requests) {\n const { url, filter } = req;\n if (!grouped.has(url))\n grouped.set(url, []);\n grouped.get(url).push(filter);\n }\n const groupedRequests = Array.from(grouped.entries()).map(([url, filters]) => ({ url, filters }));\n if (this.trackRelays) {\n params.receivedEvent = (relay, id) => {\n let set = this.seenOn.get(id);\n if (!set) {\n set = /* @__PURE__ */ new Set();\n this.seenOn.set(id, set);\n }\n set.add(relay);\n };\n }\n const _knownIds = /* @__PURE__ */ new Set();\n const subs = [];\n const eosesReceived = [];\n let handleEose = (i2) => {\n if (eosesReceived[i2])\n return;\n eosesReceived[i2] = true;\n if (eosesReceived.filter((a) => a).length === requests.length) {\n params.oneose?.();\n handleEose = () => {\n };\n }\n };\n const closesReceived = [];\n let handleClose = (i2, reason) => {\n if (closesReceived[i2])\n return;\n handleEose(i2);\n closesReceived[i2] = reason;\n if (closesReceived.filter((a) => a).length === requests.length) {\n params.onclose?.(closesReceived);\n handleClose = () => {\n };\n }\n };\n const localAlreadyHaveEventHandler = (id) => {\n if (params.alreadyHaveEvent?.(id)) {\n return true;\n }\n const have = _knownIds.has(id);\n _knownIds.add(id);\n return have;\n };\n const allOpened = Promise.all(\n groupedRequests.map(async ({ url, filters }, i2) => {\n let relay;\n try {\n relay = await this.ensureRelay(url, {\n connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : void 0\n });\n } catch (err) {\n handleClose(i2, err?.message || String(err));\n return;\n }\n let subscription = relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i2),\n onclose: (reason) => {\n if (reason.startsWith(\"auth-required: \") && params.onauth) {\n relay.auth(params.onauth).then(() => {\n relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i2),\n onclose: (reason2) => {\n handleClose(i2, reason2);\n },\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait\n });\n }).catch((err) => {\n handleClose(i2, `auth was required and attempted, but failed with: ${err}`);\n });\n } else {\n handleClose(i2, reason);\n }\n },\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait\n });\n subs.push(subscription);\n })\n );\n return {\n async close(reason) {\n await allOpened;\n subs.forEach((sub) => {\n sub.close(reason);\n });\n }\n };\n }\n subscribeEose(relays, filter, params) {\n params.onauth = params.onauth || params.doauth;\n const subcloser = this.subscribe(relays, filter, {\n ...params,\n oneose() {\n subcloser.close(\"closed automatically on eose\");\n }\n });\n return subcloser;\n }\n subscribeManyEose(relays, filter, params) {\n params.onauth = params.onauth || params.doauth;\n const subcloser = this.subscribeMany(relays, filter, {\n ...params,\n oneose() {\n subcloser.close(\"closed automatically on eose\");\n }\n });\n return subcloser;\n }\n async querySync(relays, filter, params) {\n return new Promise(async (resolve) => {\n const events = [];\n this.subscribeEose(relays, filter, {\n ...params,\n onevent(event) {\n events.push(event);\n },\n onclose(_) {\n resolve(events);\n }\n });\n });\n }\n async get(relays, filter, params) {\n filter.limit = 1;\n const events = await this.querySync(relays, filter, params);\n events.sort((a, b) => b.created_at - a.created_at);\n return events[0] || null;\n }\n publish(relays, event, options) {\n return relays.map(normalizeURL).map(async (url, i2, arr) => {\n if (arr.indexOf(url) !== i2) {\n return Promise.reject(\"duplicate url\");\n }\n let r = await this.ensureRelay(url);\n return r.publish(event).catch(async (err) => {\n if (err instanceof Error && err.message.startsWith(\"auth-required: \") && options?.onauth) {\n await r.auth(options.onauth);\n return r.publish(event);\n }\n throw err;\n }).then((reason) => {\n if (this.trackRelays) {\n let set = this.seenOn.get(event.id);\n if (!set) {\n set = /* @__PURE__ */ new Set();\n this.seenOn.set(event.id, set);\n }\n set.add(r);\n }\n return reason;\n });\n });\n }\n listConnectionStatus() {\n const map = /* @__PURE__ */ new Map();\n this.relays.forEach((relay, url) => map.set(url, relay.connected));\n return map;\n }\n destroy() {\n this.relays.forEach((conn) => conn.close());\n this.relays = /* @__PURE__ */ new Map();\n }\n};\n\n// pool.ts\nvar _WebSocket;\ntry {\n _WebSocket = WebSocket;\n} catch {\n}\nfunction useWebSocketImplementation(websocketImplementation) {\n _WebSocket = websocketImplementation;\n}\nvar SimplePool = class extends AbstractSimplePool {\n constructor(options) {\n super({ verifyEvent, websocketImplementation: _WebSocket, ...options });\n }\n};\nexport {\n AbstractSimplePool,\n SimplePool,\n useWebSocketImplementation\n};\n","/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nexport function assertNumber(n) {\n if (!Number.isSafeInteger(n))\n throw new Error(`Wrong integer: ${n}`);\n}\nfunction chain(...args) {\n const wrap = (a, b) => (c) => a(b(c));\n const encode = Array.from(args)\n .reverse()\n .reduce((acc, i) => (acc ? wrap(acc, i.encode) : i.encode), undefined);\n const decode = args.reduce((acc, i) => (acc ? wrap(acc, i.decode) : i.decode), undefined);\n return { encode, decode };\n}\nfunction alphabet(alphabet) {\n return {\n encode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('alphabet.encode input should be an array of numbers');\n return digits.map((i) => {\n assertNumber(i);\n if (i < 0 || i >= alphabet.length)\n throw new Error(`Digit index outside alphabet: ${i} (alphabet: ${alphabet.length})`);\n return alphabet[i];\n });\n },\n decode: (input) => {\n if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))\n throw new Error('alphabet.decode input should be array of strings');\n return input.map((letter) => {\n if (typeof letter !== 'string')\n throw new Error(`alphabet.decode: not string element=${letter}`);\n const index = alphabet.indexOf(letter);\n if (index === -1)\n throw new Error(`Unknown letter: \"${letter}\". Allowed: ${alphabet}`);\n return index;\n });\n },\n };\n}\nfunction join(separator = '') {\n if (typeof separator !== 'string')\n throw new Error('join separator should be string');\n return {\n encode: (from) => {\n if (!Array.isArray(from) || (from.length && typeof from[0] !== 'string'))\n throw new Error('join.encode input should be array of strings');\n for (let i of from)\n if (typeof i !== 'string')\n throw new Error(`join.encode: non-string input=${i}`);\n return from.join(separator);\n },\n decode: (to) => {\n if (typeof to !== 'string')\n throw new Error('join.decode input should be string');\n return to.split(separator);\n },\n };\n}\nfunction padding(bits, chr = '=') {\n assertNumber(bits);\n if (typeof chr !== 'string')\n throw new Error('padding chr should be string');\n return {\n encode(data) {\n if (!Array.isArray(data) || (data.length && typeof data[0] !== 'string'))\n throw new Error('padding.encode input should be array of strings');\n for (let i of data)\n if (typeof i !== 'string')\n throw new Error(`padding.encode: non-string input=${i}`);\n while ((data.length * bits) % 8)\n data.push(chr);\n return data;\n },\n decode(input) {\n if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))\n throw new Error('padding.encode input should be array of strings');\n for (let i of input)\n if (typeof i !== 'string')\n throw new Error(`padding.decode: non-string input=${i}`);\n let end = input.length;\n if ((end * bits) % 8)\n throw new Error('Invalid padding: string should have whole number of bytes');\n for (; end > 0 && input[end - 1] === chr; end--) {\n if (!(((end - 1) * bits) % 8))\n throw new Error('Invalid padding: string has too much padding');\n }\n return input.slice(0, end);\n },\n };\n}\nfunction normalize(fn) {\n if (typeof fn !== 'function')\n throw new Error('normalize fn should be function');\n return { encode: (from) => from, decode: (to) => fn(to) };\n}\nfunction convertRadix(data, from, to) {\n if (from < 2)\n throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);\n if (to < 2)\n throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);\n if (!Array.isArray(data))\n throw new Error('convertRadix: data should be array');\n if (!data.length)\n return [];\n let pos = 0;\n const res = [];\n const digits = Array.from(data);\n digits.forEach((d) => {\n assertNumber(d);\n if (d < 0 || d >= from)\n throw new Error(`Wrong integer: ${d}`);\n });\n while (true) {\n let carry = 0;\n let done = true;\n for (let i = pos; i < digits.length; i++) {\n const digit = digits[i];\n const digitBase = from * carry + digit;\n if (!Number.isSafeInteger(digitBase) ||\n (from * carry) / from !== carry ||\n digitBase - digit !== from * carry) {\n throw new Error('convertRadix: carry overflow');\n }\n carry = digitBase % to;\n digits[i] = Math.floor(digitBase / to);\n if (!Number.isSafeInteger(digits[i]) || digits[i] * to + carry !== digitBase)\n throw new Error('convertRadix: carry overflow');\n if (!done)\n continue;\n else if (!digits[i])\n pos = i;\n else\n done = false;\n }\n res.push(carry);\n if (done)\n break;\n }\n for (let i = 0; i < data.length - 1 && data[i] === 0; i++)\n res.push(0);\n return res.reverse();\n}\nconst gcd = (a, b) => (!b ? a : gcd(b, a % b));\nconst radix2carry = (from, to) => from + (to - gcd(from, to));\nfunction convertRadix2(data, from, to, padding) {\n if (!Array.isArray(data))\n throw new Error('convertRadix2: data should be array');\n if (from <= 0 || from > 32)\n throw new Error(`convertRadix2: wrong from=${from}`);\n if (to <= 0 || to > 32)\n throw new Error(`convertRadix2: wrong to=${to}`);\n if (radix2carry(from, to) > 32) {\n throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);\n }\n let carry = 0;\n let pos = 0;\n const mask = 2 ** to - 1;\n const res = [];\n for (const n of data) {\n assertNumber(n);\n if (n >= 2 ** from)\n throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);\n carry = (carry << from) | n;\n if (pos + from > 32)\n throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);\n pos += from;\n for (; pos >= to; pos -= to)\n res.push(((carry >> (pos - to)) & mask) >>> 0);\n carry &= 2 ** pos - 1;\n }\n carry = (carry << (to - pos)) & mask;\n if (!padding && pos >= from)\n throw new Error('Excess padding');\n if (!padding && carry)\n throw new Error(`Non-zero padding: ${carry}`);\n if (padding && pos > 0)\n res.push(carry >>> 0);\n return res;\n}\nfunction radix(num) {\n assertNumber(num);\n return {\n encode: (bytes) => {\n if (!(bytes instanceof Uint8Array))\n throw new Error('radix.encode input should be Uint8Array');\n return convertRadix(Array.from(bytes), 2 ** 8, num);\n },\n decode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('radix.decode input should be array of strings');\n return Uint8Array.from(convertRadix(digits, num, 2 ** 8));\n },\n };\n}\nfunction radix2(bits, revPadding = false) {\n assertNumber(bits);\n if (bits <= 0 || bits > 32)\n throw new Error('radix2: bits should be in (0..32]');\n if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)\n throw new Error('radix2: carry overflow');\n return {\n encode: (bytes) => {\n if (!(bytes instanceof Uint8Array))\n throw new Error('radix2.encode input should be Uint8Array');\n return convertRadix2(Array.from(bytes), 8, bits, !revPadding);\n },\n decode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('radix2.decode input should be array of strings');\n return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));\n },\n };\n}\nfunction unsafeWrapper(fn) {\n if (typeof fn !== 'function')\n throw new Error('unsafeWrapper fn should be function');\n return function (...args) {\n try {\n return fn.apply(null, args);\n }\n catch (e) { }\n };\n}\nfunction checksum(len, fn) {\n assertNumber(len);\n if (typeof fn !== 'function')\n throw new Error('checksum fn should be function');\n return {\n encode(data) {\n if (!(data instanceof Uint8Array))\n throw new Error('checksum.encode: input should be Uint8Array');\n const checksum = fn(data).slice(0, len);\n const res = new Uint8Array(data.length + len);\n res.set(data);\n res.set(checksum, data.length);\n return res;\n },\n decode(data) {\n if (!(data instanceof Uint8Array))\n throw new Error('checksum.decode: input should be Uint8Array');\n const payload = data.slice(0, -len);\n const newChecksum = fn(payload).slice(0, len);\n const oldChecksum = data.slice(-len);\n for (let i = 0; i < len; i++)\n if (newChecksum[i] !== oldChecksum[i])\n throw new Error('Invalid checksum');\n return payload;\n },\n };\n}\nexport const utils = { alphabet, chain, checksum, radix, radix2, join, padding };\nexport const base16 = chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));\nexport const base32 = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));\nexport const base32hex = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));\nexport const base32crockford = chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));\nexport const base64 = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));\nexport const base64url = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));\nconst genBase58 = (abc) => chain(radix(58), alphabet(abc), join(''));\nexport const base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');\nexport const base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');\nexport const base58xrp = genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');\nconst XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];\nexport const base58xmr = {\n encode(data) {\n let res = '';\n for (let i = 0; i < data.length; i += 8) {\n const block = data.subarray(i, i + 8);\n res += base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');\n }\n return res;\n },\n decode(str) {\n let res = [];\n for (let i = 0; i < str.length; i += 11) {\n const slice = str.slice(i, i + 11);\n const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);\n const block = base58.decode(slice);\n for (let j = 0; j < block.length - blockLen; j++) {\n if (block[j] !== 0)\n throw new Error('base58xmr: wrong padding');\n }\n res = res.concat(Array.from(block.slice(block.length - blockLen)));\n }\n return Uint8Array.from(res);\n },\n};\nexport const base58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), base58);\nconst BECH_ALPHABET = chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));\nconst POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\nfunction bech32Polymod(pre) {\n const b = pre >> 25;\n let chk = (pre & 0x1ffffff) << 5;\n for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {\n if (((b >> i) & 1) === 1)\n chk ^= POLYMOD_GENERATORS[i];\n }\n return chk;\n}\nfunction bechChecksum(prefix, words, encodingConst = 1) {\n const len = prefix.length;\n let chk = 1;\n for (let i = 0; i < len; i++) {\n const c = prefix.charCodeAt(i);\n if (c < 33 || c > 126)\n throw new Error(`Invalid prefix (${prefix})`);\n chk = bech32Polymod(chk) ^ (c >> 5);\n }\n chk = bech32Polymod(chk);\n for (let i = 0; i < len; i++)\n chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (let v of words)\n chk = bech32Polymod(chk) ^ v;\n for (let i = 0; i < 6; i++)\n chk = bech32Polymod(chk);\n chk ^= encodingConst;\n return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));\n}\nfunction genBech32(encoding) {\n const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;\n const _words = radix2(5);\n const fromWords = _words.decode;\n const toWords = _words.encode;\n const fromWordsUnsafe = unsafeWrapper(fromWords);\n function encode(prefix, words, limit = 90) {\n if (typeof prefix !== 'string')\n throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);\n if (!Array.isArray(words) || (words.length && typeof words[0] !== 'number'))\n throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);\n const actualLength = prefix.length + 7 + words.length;\n if (limit !== false && actualLength > limit)\n throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);\n prefix = prefix.toLowerCase();\n return `${prefix}1${BECH_ALPHABET.encode(words)}${bechChecksum(prefix, words, ENCODING_CONST)}`;\n }\n function decode(str, limit = 90) {\n if (typeof str !== 'string')\n throw new Error(`bech32.decode input should be string, not ${typeof str}`);\n if (str.length < 8 || (limit !== false && str.length > limit))\n throw new TypeError(`Wrong string length: ${str.length} (${str}). Expected (8..${limit})`);\n const lowered = str.toLowerCase();\n if (str !== lowered && str !== str.toUpperCase())\n throw new Error(`String must be lowercase or uppercase`);\n str = lowered;\n const sepIndex = str.lastIndexOf('1');\n if (sepIndex === 0 || sepIndex === -1)\n throw new Error(`Letter \"1\" must be present between prefix and data only`);\n const prefix = str.slice(0, sepIndex);\n const _words = str.slice(sepIndex + 1);\n if (_words.length < 6)\n throw new Error('Data must be at least 6 characters long');\n const words = BECH_ALPHABET.decode(_words).slice(0, -6);\n const sum = bechChecksum(prefix, words, ENCODING_CONST);\n if (!_words.endsWith(sum))\n throw new Error(`Invalid checksum in ${str}: expected \"${sum}\"`);\n return { prefix, words };\n }\n const decodeUnsafe = unsafeWrapper(decode);\n function decodeToBytes(str) {\n const { prefix, words } = decode(str, false);\n return { prefix, words, bytes: fromWords(words) };\n }\n return { encode, decode, decodeToBytes, decodeUnsafe, fromWords, fromWordsUnsafe, toWords };\n}\nexport const bech32 = genBech32('bech32');\nexport const bech32m = genBech32('bech32m');\nexport const utf8 = {\n encode: (data) => new TextDecoder().decode(data),\n decode: (str) => new TextEncoder().encode(str),\n};\nexport const hex = chain(radix2(4), alphabet('0123456789abcdef'), join(''), normalize((s) => {\n if (typeof s !== 'string' || s.length % 2)\n throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);\n return s.toLowerCase();\n}));\nconst CODERS = {\n utf8, hex, base16, base32, base64, base64url, base58, base58xmr\n};\nconst coderTypeError = `Invalid encoding type. Available types: ${Object.keys(CODERS).join(', ')}`;\nexport const bytesToString = (type, bytes) => {\n if (typeof type !== 'string' || !CODERS.hasOwnProperty(type))\n throw new TypeError(coderTypeError);\n if (!(bytes instanceof Uint8Array))\n throw new TypeError('bytesToString() expects Uint8Array');\n return CODERS[type].encode(bytes);\n};\nexport const str = bytesToString;\nexport const stringToBytes = (type, str) => {\n if (!CODERS.hasOwnProperty(type))\n throw new TypeError(coderTypeError);\n if (typeof str !== 'string')\n throw new TypeError('stringToBytes() expects string');\n return CODERS[type].decode(str);\n};\nexport const bytes = stringToBytes;\n","function number(n) {\n if (!Number.isSafeInteger(n) || n < 0)\n throw new Error(`positive integer expected, not ${n}`);\n}\nfunction bool(b) {\n if (typeof b !== 'boolean')\n throw new Error(`boolean expected, not ${b}`);\n}\nexport function isBytes(a) {\n return (a instanceof Uint8Array ||\n (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));\n}\nfunction bytes(b, ...lengths) {\n if (!isBytes(b))\n throw new Error('Uint8Array expected');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error(`Uint8Array expected of length ${lengths}, not of length=${b.length}`);\n}\nfunction hash(hash) {\n if (typeof hash !== 'function' || typeof hash.create !== 'function')\n throw new Error('hash must be wrapped by utils.wrapConstructor');\n number(hash.outputLen);\n number(hash.blockLen);\n}\nfunction exists(instance, checkFinished = true) {\n if (instance.destroyed)\n throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished)\n throw new Error('Hash#digest() has already been called');\n}\nfunction output(out, instance) {\n bytes(out);\n const min = instance.outputLen;\n if (out.length < min) {\n throw new Error(`digestInto() expects output buffer of length at least ${min}`);\n }\n}\nexport { number, bool, bytes, hash, exists, output };\nconst assert = { number, bool, bytes, hash, exists, output };\nexport default assert;\n//# sourceMappingURL=_assert.js.map","/*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */\nimport { bytes as abytes, isBytes } from './_assert.js';\n// Cast array to different type\nexport const u8 = (arr) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\nexport const u16 = (arr) => new Uint16Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 2));\nexport const u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n// Cast array to view\nexport const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n// big-endian hardware is rare. Just in case someone still decides to run ciphers:\n// early-throw an error because we don't support BE yet.\nexport const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;\nif (!isLE)\n throw new Error('Non little-endian hardware is not supported');\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));\n/**\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes) {\n abytes(bytes);\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 };\nfunction asciiToBase16(char) {\n if (char >= asciis._0 && char <= asciis._9)\n return char - asciis._0;\n if (char >= asciis._A && char <= asciis._F)\n return char - (asciis._A - 10);\n if (char >= asciis._a && char <= asciis._f)\n return char - (asciis._a - 10);\n return;\n}\n/**\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2)\n throw new Error('padded hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2;\n }\n return array;\n}\nexport function hexToNumber(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n // Big Endian\n return BigInt(hex === '' ? '0' : `0x${hex}`);\n}\n// BE: Big Endian, LE: Little Endian\nexport function bytesToNumberBE(bytes) {\n return hexToNumber(bytesToHex(bytes));\n}\nexport function numberToBytesBE(n, len) {\n return hexToBytes(n.toString(16).padStart(len * 2, '0'));\n}\n// There is no setImmediate in browser and setTimeout is slow.\n// call of async fn will return Promise, which will be fullfiled only on\n// next scheduler queue processing step and this is exactly what we need.\nexport const nextTick = async () => { };\n// Returns control to thread each 'tick' ms to avoid blocking\nexport async function asyncLoop(iters, tick, cb) {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick)\n continue;\n await nextTick();\n ts += diff;\n }\n}\n/**\n * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])\n */\nexport function utf8ToBytes(str) {\n if (typeof str !== 'string')\n throw new Error(`string expected, got ${typeof str}`);\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n/**\n * @example bytesToUtf8(new Uint8Array([97, 98, 99])) // 'abc'\n */\nexport function bytesToUtf8(bytes) {\n return new TextDecoder().decode(bytes);\n}\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data) {\n if (typeof data === 'string')\n data = utf8ToBytes(data);\n else if (isBytes(data))\n data = data.slice();\n else\n throw new Error(`Uint8Array expected, got ${typeof data}`);\n return data;\n}\n/**\n * Copies several Uint8Arrays into one.\n */\nexport function concatBytes(...arrays) {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\nexport function checkOpts(defaults, opts) {\n if (opts == null || typeof opts !== 'object')\n throw new Error('options must be defined');\n const merged = Object.assign(defaults, opts);\n return merged;\n}\n// Compares 2 u8a-s in kinda constant time\nexport function equalBytes(a, b) {\n if (a.length !== b.length)\n return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++)\n diff |= a[i] ^ b[i];\n return diff === 0;\n}\n// For runtime check if class implements interface\nexport class Hash {\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nexport const wrapCipher = (params, c) => {\n Object.assign(c, params);\n return c;\n};\n// Polyfill for Safari 14\nexport function setBigUint64(view, byteOffset, value, isLE) {\n if (typeof view.setBigUint64 === 'function')\n return view.setBigUint64(byteOffset, value, isLE);\n const _32n = BigInt(32);\n const _u32_max = BigInt(0xffffffff);\n const wh = Number((value >> _32n) & _u32_max);\n const wl = Number(value & _u32_max);\n const h = isLE ? 4 : 0;\n const l = isLE ? 0 : 4;\n view.setUint32(byteOffset + h, wh, isLE);\n view.setUint32(byteOffset + l, wl, isLE);\n}\nexport function u64Lengths(ciphertext, AAD) {\n const num = new Uint8Array(16);\n const view = createView(num);\n setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true);\n setBigUint64(view, 8, BigInt(ciphertext.length), true);\n return num;\n}\n//# sourceMappingURL=utils.js.map","// prettier-ignore\nimport { wrapCipher, createView, setBigUint64, equalBytes, u32, u8, } from './utils.js';\nimport { ghash, polyval } from './_polyval.js';\nimport { bytes as abytes } from './_assert.js';\n/*\nAES (Advanced Encryption Standard) aka Rijndael block cipher.\n\nData is split into 128-bit blocks. Encrypted in 10/12/14 rounds (128/192/256 bits). In every round:\n1. **S-box**, table substitution\n2. **Shift rows**, cyclic shift left of all rows of data array\n3. **Mix columns**, multiplying every column by fixed polynomial\n4. **Add round key**, round_key xor i-th column of array\n\nResources:\n- FIPS-197 https://csrc.nist.gov/files/pubs/fips/197/final/docs/fips-197.pdf\n- Original proposal: https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf\n*/\nconst BLOCK_SIZE = 16;\nconst BLOCK_SIZE32 = 4;\nconst EMPTY_BLOCK = new Uint8Array(BLOCK_SIZE);\nconst POLY = 0x11b; // 1 + x + x**3 + x**4 + x**8\n// TODO: remove multiplication, binary ops only\nfunction mul2(n) {\n return (n << 1) ^ (POLY & -(n >> 7));\n}\nfunction mul(a, b) {\n let res = 0;\n for (; b > 0; b >>= 1) {\n // Montgomery ladder\n res ^= a & -(b & 1); // if (b&1) res ^=a (but const-time).\n a = mul2(a); // a = 2*a\n }\n return res;\n}\n// AES S-box is generated using finite field inversion,\n// an affine transform, and xor of a constant 0x63.\nconst sbox = /* @__PURE__ */ (() => {\n let t = new Uint8Array(256);\n for (let i = 0, x = 1; i < 256; i++, x ^= mul2(x))\n t[i] = x;\n const box = new Uint8Array(256);\n box[0] = 0x63; // first elm\n for (let i = 0; i < 255; i++) {\n let x = t[255 - i];\n x |= x << 8;\n box[t[i]] = (x ^ (x >> 4) ^ (x >> 5) ^ (x >> 6) ^ (x >> 7) ^ 0x63) & 0xff;\n }\n return box;\n})();\n// Inverted S-box\nconst invSbox = /* @__PURE__ */ sbox.map((_, j) => sbox.indexOf(j));\n// Rotate u32 by 8\nconst rotr32_8 = (n) => (n << 24) | (n >>> 8);\nconst rotl32_8 = (n) => (n << 8) | (n >>> 24);\n// T-table is optimization suggested in 5.2 of original proposal (missed from FIPS-197). Changes:\n// - LE instead of BE\n// - bigger tables: T0 and T1 are merged into T01 table and T2 & T3 into T23;\n// so index is u16, instead of u8. This speeds up things, unexpectedly\nfunction genTtable(sbox, fn) {\n if (sbox.length !== 256)\n throw new Error('Wrong sbox length');\n const T0 = new Uint32Array(256).map((_, j) => fn(sbox[j]));\n const T1 = T0.map(rotl32_8);\n const T2 = T1.map(rotl32_8);\n const T3 = T2.map(rotl32_8);\n const T01 = new Uint32Array(256 * 256);\n const T23 = new Uint32Array(256 * 256);\n const sbox2 = new Uint16Array(256 * 256);\n for (let i = 0; i < 256; i++) {\n for (let j = 0; j < 256; j++) {\n const idx = i * 256 + j;\n T01[idx] = T0[i] ^ T1[j];\n T23[idx] = T2[i] ^ T3[j];\n sbox2[idx] = (sbox[i] << 8) | sbox[j];\n }\n }\n return { sbox, sbox2, T0, T1, T2, T3, T01, T23 };\n}\nconst tableEncoding = /* @__PURE__ */ genTtable(sbox, (s) => (mul(s, 3) << 24) | (s << 16) | (s << 8) | mul(s, 2));\nconst tableDecoding = /* @__PURE__ */ genTtable(invSbox, (s) => (mul(s, 11) << 24) | (mul(s, 13) << 16) | (mul(s, 9) << 8) | mul(s, 14));\nconst xPowers = /* @__PURE__ */ (() => {\n const p = new Uint8Array(16);\n for (let i = 0, x = 1; i < 16; i++, x = mul2(x))\n p[i] = x;\n return p;\n})();\nexport function expandKeyLE(key) {\n abytes(key);\n const len = key.length;\n if (![16, 24, 32].includes(len))\n throw new Error(`aes: wrong key size: should be 16, 24 or 32, got: ${len}`);\n const { sbox2 } = tableEncoding;\n const k32 = u32(key);\n const Nk = k32.length;\n const subByte = (n) => applySbox(sbox2, n, n, n, n);\n const xk = new Uint32Array(len + 28); // expanded key\n xk.set(k32);\n // 4.3.1 Key expansion\n for (let i = Nk; i < xk.length; i++) {\n let t = xk[i - 1];\n if (i % Nk === 0)\n t = subByte(rotr32_8(t)) ^ xPowers[i / Nk - 1];\n else if (Nk > 6 && i % Nk === 4)\n t = subByte(t);\n xk[i] = xk[i - Nk] ^ t;\n }\n return xk;\n}\nexport function expandKeyDecLE(key) {\n const encKey = expandKeyLE(key);\n const xk = encKey.slice();\n const Nk = encKey.length;\n const { sbox2 } = tableEncoding;\n const { T0, T1, T2, T3 } = tableDecoding;\n // Inverse key by chunks of 4 (rounds)\n for (let i = 0; i < Nk; i += 4) {\n for (let j = 0; j < 4; j++)\n xk[i + j] = encKey[Nk - i - 4 + j];\n }\n encKey.fill(0);\n // apply InvMixColumn except first & last round\n for (let i = 4; i < Nk - 4; i++) {\n const x = xk[i];\n const w = applySbox(sbox2, x, x, x, x);\n xk[i] = T0[w & 0xff] ^ T1[(w >>> 8) & 0xff] ^ T2[(w >>> 16) & 0xff] ^ T3[w >>> 24];\n }\n return xk;\n}\n// Apply tables\nfunction apply0123(T01, T23, s0, s1, s2, s3) {\n return (T01[((s0 << 8) & 0xff00) | ((s1 >>> 8) & 0xff)] ^\n T23[((s2 >>> 8) & 0xff00) | ((s3 >>> 24) & 0xff)]);\n}\nfunction applySbox(sbox2, s0, s1, s2, s3) {\n return (sbox2[(s0 & 0xff) | (s1 & 0xff00)] |\n (sbox2[((s2 >>> 16) & 0xff) | ((s3 >>> 16) & 0xff00)] << 16));\n}\nfunction encrypt(xk, s0, s1, s2, s3) {\n const { sbox2, T01, T23 } = tableEncoding;\n let k = 0;\n (s0 ^= xk[k++]), (s1 ^= xk[k++]), (s2 ^= xk[k++]), (s3 ^= xk[k++]);\n const rounds = xk.length / 4 - 2;\n for (let i = 0; i < rounds; i++) {\n const t0 = xk[k++] ^ apply0123(T01, T23, s0, s1, s2, s3);\n const t1 = xk[k++] ^ apply0123(T01, T23, s1, s2, s3, s0);\n const t2 = xk[k++] ^ apply0123(T01, T23, s2, s3, s0, s1);\n const t3 = xk[k++] ^ apply0123(T01, T23, s3, s0, s1, s2);\n (s0 = t0), (s1 = t1), (s2 = t2), (s3 = t3);\n }\n // last round (without mixcolumns, so using SBOX2 table)\n const t0 = xk[k++] ^ applySbox(sbox2, s0, s1, s2, s3);\n const t1 = xk[k++] ^ applySbox(sbox2, s1, s2, s3, s0);\n const t2 = xk[k++] ^ applySbox(sbox2, s2, s3, s0, s1);\n const t3 = xk[k++] ^ applySbox(sbox2, s3, s0, s1, s2);\n return { s0: t0, s1: t1, s2: t2, s3: t3 };\n}\nfunction decrypt(xk, s0, s1, s2, s3) {\n const { sbox2, T01, T23 } = tableDecoding;\n let k = 0;\n (s0 ^= xk[k++]), (s1 ^= xk[k++]), (s2 ^= xk[k++]), (s3 ^= xk[k++]);\n const rounds = xk.length / 4 - 2;\n for (let i = 0; i < rounds; i++) {\n const t0 = xk[k++] ^ apply0123(T01, T23, s0, s3, s2, s1);\n const t1 = xk[k++] ^ apply0123(T01, T23, s1, s0, s3, s2);\n const t2 = xk[k++] ^ apply0123(T01, T23, s2, s1, s0, s3);\n const t3 = xk[k++] ^ apply0123(T01, T23, s3, s2, s1, s0);\n (s0 = t0), (s1 = t1), (s2 = t2), (s3 = t3);\n }\n // Last round\n const t0 = xk[k++] ^ applySbox(sbox2, s0, s3, s2, s1);\n const t1 = xk[k++] ^ applySbox(sbox2, s1, s0, s3, s2);\n const t2 = xk[k++] ^ applySbox(sbox2, s2, s1, s0, s3);\n const t3 = xk[k++] ^ applySbox(sbox2, s3, s2, s1, s0);\n return { s0: t0, s1: t1, s2: t2, s3: t3 };\n}\nfunction getDst(len, dst) {\n if (!dst)\n return new Uint8Array(len);\n abytes(dst);\n if (dst.length < len)\n throw new Error(`aes: wrong destination length, expected at least ${len}, got: ${dst.length}`);\n return dst;\n}\n// TODO: investigate merging with ctr32\nfunction ctrCounter(xk, nonce, src, dst) {\n abytes(nonce, BLOCK_SIZE);\n abytes(src);\n const srcLen = src.length;\n dst = getDst(srcLen, dst);\n const ctr = nonce;\n const c32 = u32(ctr);\n // Fill block (empty, ctr=0)\n let { s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]);\n const src32 = u32(src);\n const dst32 = u32(dst);\n // process blocks\n for (let i = 0; i + 4 <= src32.length; i += 4) {\n dst32[i + 0] = src32[i + 0] ^ s0;\n dst32[i + 1] = src32[i + 1] ^ s1;\n dst32[i + 2] = src32[i + 2] ^ s2;\n dst32[i + 3] = src32[i + 3] ^ s3;\n // Full 128 bit counter with wrap around\n let carry = 1;\n for (let i = ctr.length - 1; i >= 0; i--) {\n carry = (carry + (ctr[i] & 0xff)) | 0;\n ctr[i] = carry & 0xff;\n carry >>>= 8;\n }\n ({ s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]));\n }\n // leftovers (less than block)\n // It's possible to handle > u32 fast, but is it worth it?\n const start = BLOCK_SIZE * Math.floor(src32.length / BLOCK_SIZE32);\n if (start < srcLen) {\n const b32 = new Uint32Array([s0, s1, s2, s3]);\n const buf = u8(b32);\n for (let i = start, pos = 0; i < srcLen; i++, pos++)\n dst[i] = src[i] ^ buf[pos];\n }\n return dst;\n}\n// AES CTR with overflowing 32 bit counter\n// It's possible to do 32le significantly simpler (and probably faster) by using u32.\n// But, we need both, and perf bottleneck is in ghash anyway.\nfunction ctr32(xk, isLE, nonce, src, dst) {\n abytes(nonce, BLOCK_SIZE);\n abytes(src);\n dst = getDst(src.length, dst);\n const ctr = nonce; // write new value to nonce, so it can be re-used\n const c32 = u32(ctr);\n const view = createView(ctr);\n const src32 = u32(src);\n const dst32 = u32(dst);\n const ctrPos = isLE ? 0 : 12;\n const srcLen = src.length;\n // Fill block (empty, ctr=0)\n let ctrNum = view.getUint32(ctrPos, isLE); // read current counter value\n let { s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]);\n // process blocks\n for (let i = 0; i + 4 <= src32.length; i += 4) {\n dst32[i + 0] = src32[i + 0] ^ s0;\n dst32[i + 1] = src32[i + 1] ^ s1;\n dst32[i + 2] = src32[i + 2] ^ s2;\n dst32[i + 3] = src32[i + 3] ^ s3;\n ctrNum = (ctrNum + 1) >>> 0; // u32 wrap\n view.setUint32(ctrPos, ctrNum, isLE);\n ({ s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]));\n }\n // leftovers (less than a block)\n const start = BLOCK_SIZE * Math.floor(src32.length / BLOCK_SIZE32);\n if (start < srcLen) {\n const b32 = new Uint32Array([s0, s1, s2, s3]);\n const buf = u8(b32);\n for (let i = start, pos = 0; i < srcLen; i++, pos++)\n dst[i] = src[i] ^ buf[pos];\n }\n return dst;\n}\n/**\n * CTR: counter mode. Creates stream cipher.\n * Requires good IV. Parallelizable. OK, but no MAC.\n */\nexport const ctr = wrapCipher({ blockSize: 16, nonceLength: 16 }, function ctr(key, nonce) {\n abytes(key);\n abytes(nonce, BLOCK_SIZE);\n function processCtr(buf, dst) {\n const xk = expandKeyLE(key);\n const n = nonce.slice();\n const out = ctrCounter(xk, n, buf, dst);\n xk.fill(0);\n n.fill(0);\n return out;\n }\n return {\n encrypt: (plaintext, dst) => processCtr(plaintext, dst),\n decrypt: (ciphertext, dst) => processCtr(ciphertext, dst),\n };\n});\nfunction validateBlockDecrypt(data) {\n abytes(data);\n if (data.length % BLOCK_SIZE !== 0) {\n throw new Error(`aes/(cbc-ecb).decrypt ciphertext should consist of blocks with size ${BLOCK_SIZE}`);\n }\n}\nfunction validateBlockEncrypt(plaintext, pcks5, dst) {\n let outLen = plaintext.length;\n const remaining = outLen % BLOCK_SIZE;\n if (!pcks5 && remaining !== 0)\n throw new Error('aec/(cbc-ecb): unpadded plaintext with disabled padding');\n const b = u32(plaintext);\n if (pcks5) {\n let left = BLOCK_SIZE - remaining;\n if (!left)\n left = BLOCK_SIZE; // if no bytes left, create empty padding block\n outLen = outLen + left;\n }\n const out = getDst(outLen, dst);\n const o = u32(out);\n return { b, o, out };\n}\nfunction validatePCKS(data, pcks5) {\n if (!pcks5)\n return data;\n const len = data.length;\n if (!len)\n throw new Error(`aes/pcks5: empty ciphertext not allowed`);\n const lastByte = data[len - 1];\n if (lastByte <= 0 || lastByte > 16)\n throw new Error(`aes/pcks5: wrong padding byte: ${lastByte}`);\n const out = data.subarray(0, -lastByte);\n for (let i = 0; i < lastByte; i++)\n if (data[len - i - 1] !== lastByte)\n throw new Error(`aes/pcks5: wrong padding`);\n return out;\n}\nfunction padPCKS(left) {\n const tmp = new Uint8Array(16);\n const tmp32 = u32(tmp);\n tmp.set(left);\n const paddingByte = BLOCK_SIZE - left.length;\n for (let i = BLOCK_SIZE - paddingByte; i < BLOCK_SIZE; i++)\n tmp[i] = paddingByte;\n return tmp32;\n}\n/**\n * ECB: Electronic CodeBook. Simple deterministic replacement.\n * Dangerous: always map x to y. See [AES Penguin](https://words.filippo.io/the-ecb-penguin/).\n */\nexport const ecb = wrapCipher({ blockSize: 16 }, function ecb(key, opts = {}) {\n abytes(key);\n const pcks5 = !opts.disablePadding;\n return {\n encrypt: (plaintext, dst) => {\n abytes(plaintext);\n const { b, o, out: _out } = validateBlockEncrypt(plaintext, pcks5, dst);\n const xk = expandKeyLE(key);\n let i = 0;\n for (; i + 4 <= b.length;) {\n const { s0, s1, s2, s3 } = encrypt(xk, b[i + 0], b[i + 1], b[i + 2], b[i + 3]);\n (o[i++] = s0), (o[i++] = s1), (o[i++] = s2), (o[i++] = s3);\n }\n if (pcks5) {\n const tmp32 = padPCKS(plaintext.subarray(i * 4));\n const { s0, s1, s2, s3 } = encrypt(xk, tmp32[0], tmp32[1], tmp32[2], tmp32[3]);\n (o[i++] = s0), (o[i++] = s1), (o[i++] = s2), (o[i++] = s3);\n }\n xk.fill(0);\n return _out;\n },\n decrypt: (ciphertext, dst) => {\n validateBlockDecrypt(ciphertext);\n const xk = expandKeyDecLE(key);\n const out = getDst(ciphertext.length, dst);\n const b = u32(ciphertext);\n const o = u32(out);\n for (let i = 0; i + 4 <= b.length;) {\n const { s0, s1, s2, s3 } = decrypt(xk, b[i + 0], b[i + 1], b[i + 2], b[i + 3]);\n (o[i++] = s0), (o[i++] = s1), (o[i++] = s2), (o[i++] = s3);\n }\n xk.fill(0);\n return validatePCKS(out, pcks5);\n },\n };\n});\n/**\n * CBC: Cipher-Block-Chaining. Key is previous round’s block.\n * Fragile: needs proper padding. Unauthenticated: needs MAC.\n */\nexport const cbc = wrapCipher({ blockSize: 16, nonceLength: 16 }, function cbc(key, iv, opts = {}) {\n abytes(key);\n abytes(iv, 16);\n const pcks5 = !opts.disablePadding;\n return {\n encrypt: (plaintext, dst) => {\n const xk = expandKeyLE(key);\n const { b, o, out: _out } = validateBlockEncrypt(plaintext, pcks5, dst);\n const n32 = u32(iv);\n // prettier-ignore\n let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];\n let i = 0;\n for (; i + 4 <= b.length;) {\n (s0 ^= b[i + 0]), (s1 ^= b[i + 1]), (s2 ^= b[i + 2]), (s3 ^= b[i + 3]);\n ({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));\n (o[i++] = s0), (o[i++] = s1), (o[i++] = s2), (o[i++] = s3);\n }\n if (pcks5) {\n const tmp32 = padPCKS(plaintext.subarray(i * 4));\n (s0 ^= tmp32[0]), (s1 ^= tmp32[1]), (s2 ^= tmp32[2]), (s3 ^= tmp32[3]);\n ({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));\n (o[i++] = s0), (o[i++] = s1), (o[i++] = s2), (o[i++] = s3);\n }\n xk.fill(0);\n return _out;\n },\n decrypt: (ciphertext, dst) => {\n validateBlockDecrypt(ciphertext);\n const xk = expandKeyDecLE(key);\n const n32 = u32(iv);\n const out = getDst(ciphertext.length, dst);\n const b = u32(ciphertext);\n const o = u32(out);\n // prettier-ignore\n let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];\n for (let i = 0; i + 4 <= b.length;) {\n // prettier-ignore\n const ps0 = s0, ps1 = s1, ps2 = s2, ps3 = s3;\n (s0 = b[i + 0]), (s1 = b[i + 1]), (s2 = b[i + 2]), (s3 = b[i + 3]);\n const { s0: o0, s1: o1, s2: o2, s3: o3 } = decrypt(xk, s0, s1, s2, s3);\n (o[i++] = o0 ^ ps0), (o[i++] = o1 ^ ps1), (o[i++] = o2 ^ ps2), (o[i++] = o3 ^ ps3);\n }\n xk.fill(0);\n return validatePCKS(out, pcks5);\n },\n };\n});\n/**\n * CFB: Cipher Feedback Mode. The input for the block cipher is the previous cipher output.\n * Unauthenticated: needs MAC.\n */\nexport const cfb = wrapCipher({ blockSize: 16, nonceLength: 16 }, function cfb(key, iv) {\n abytes(key);\n abytes(iv, 16);\n function processCfb(src, isEncrypt, dst) {\n const xk = expandKeyLE(key);\n const srcLen = src.length;\n dst = getDst(srcLen, dst);\n const src32 = u32(src);\n const dst32 = u32(dst);\n const next32 = isEncrypt ? dst32 : src32;\n const n32 = u32(iv);\n // prettier-ignore\n let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];\n for (let i = 0; i + 4 <= src32.length;) {\n const { s0: e0, s1: e1, s2: e2, s3: e3 } = encrypt(xk, s0, s1, s2, s3);\n dst32[i + 0] = src32[i + 0] ^ e0;\n dst32[i + 1] = src32[i + 1] ^ e1;\n dst32[i + 2] = src32[i + 2] ^ e2;\n dst32[i + 3] = src32[i + 3] ^ e3;\n (s0 = next32[i++]), (s1 = next32[i++]), (s2 = next32[i++]), (s3 = next32[i++]);\n }\n // leftovers (less than block)\n const start = BLOCK_SIZE * Math.floor(src32.length / BLOCK_SIZE32);\n if (start < srcLen) {\n ({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));\n const buf = u8(new Uint32Array([s0, s1, s2, s3]));\n for (let i = start, pos = 0; i < srcLen; i++, pos++)\n dst[i] = src[i] ^ buf[pos];\n buf.fill(0);\n }\n xk.fill(0);\n return dst;\n }\n return {\n encrypt: (plaintext, dst) => processCfb(plaintext, true, dst),\n decrypt: (ciphertext, dst) => processCfb(ciphertext, false, dst),\n };\n});\n// TODO: merge with chacha, however gcm has bitLen while chacha has byteLen\nfunction computeTag(fn, isLE, key, data, AAD) {\n const h = fn.create(key, data.length + (AAD?.length || 0));\n if (AAD)\n h.update(AAD);\n h.update(data);\n const num = new Uint8Array(16);\n const view = createView(num);\n if (AAD)\n setBigUint64(view, 0, BigInt(AAD.length * 8), isLE);\n setBigUint64(view, 8, BigInt(data.length * 8), isLE);\n h.update(num);\n return h.digest();\n}\n/**\n * GCM: Galois/Counter Mode.\n * Good, modern version of CTR, parallel, with MAC.\n * Be careful: MACs can be forged.\n */\nexport const gcm = wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16 }, function gcm(key, nonce, AAD) {\n abytes(nonce);\n // Nonce can be pretty much anything (even 1 byte). But smaller nonces less secure.\n if (nonce.length === 0)\n throw new Error('aes/gcm: empty nonce');\n const tagLength = 16;\n function _computeTag(authKey, tagMask, data) {\n const tag = computeTag(ghash, false, authKey, data, AAD);\n for (let i = 0; i < tagMask.length; i++)\n tag[i] ^= tagMask[i];\n return tag;\n }\n function deriveKeys() {\n const xk = expandKeyLE(key);\n const authKey = EMPTY_BLOCK.slice();\n const counter = EMPTY_BLOCK.slice();\n ctr32(xk, false, counter, counter, authKey);\n if (nonce.length === 12) {\n counter.set(nonce);\n }\n else {\n // Spec (NIST 800-38d) supports variable size nonce.\n // Not supported for now, but can be useful.\n const nonceLen = EMPTY_BLOCK.slice();\n const view = createView(nonceLen);\n setBigUint64(view, 8, BigInt(nonce.length * 8), false);\n // ghash(nonce || u64be(0) || u64be(nonceLen*8))\n ghash.create(authKey).update(nonce).update(nonceLen).digestInto(counter);\n }\n const tagMask = ctr32(xk, false, counter, EMPTY_BLOCK);\n return { xk, authKey, counter, tagMask };\n }\n return {\n encrypt: (plaintext) => {\n abytes(plaintext);\n const { xk, authKey, counter, tagMask } = deriveKeys();\n const out = new Uint8Array(plaintext.length + tagLength);\n ctr32(xk, false, counter, plaintext, out);\n const tag = _computeTag(authKey, tagMask, out.subarray(0, out.length - tagLength));\n out.set(tag, plaintext.length);\n xk.fill(0);\n return out;\n },\n decrypt: (ciphertext) => {\n abytes(ciphertext);\n if (ciphertext.length < tagLength)\n throw new Error(`aes/gcm: ciphertext less than tagLen (${tagLength})`);\n const { xk, authKey, counter, tagMask } = deriveKeys();\n const data = ciphertext.subarray(0, -tagLength);\n const passedTag = ciphertext.subarray(-tagLength);\n const tag = _computeTag(authKey, tagMask, data);\n if (!equalBytes(tag, passedTag))\n throw new Error('aes/gcm: invalid ghash tag');\n const out = ctr32(xk, false, counter, data);\n authKey.fill(0);\n tagMask.fill(0);\n xk.fill(0);\n return out;\n },\n };\n});\nconst limit = (name, min, max) => (value) => {\n if (!Number.isSafeInteger(value) || min > value || value > max)\n throw new Error(`${name}: invalid value=${value}, must be [${min}..${max}]`);\n};\n/**\n * AES-GCM-SIV: classic AES-GCM with nonce-misuse resistance.\n * Guarantees that, when a nonce is repeated, the only security loss is that identical\n * plaintexts will produce identical ciphertexts.\n * RFC 8452, https://datatracker.ietf.org/doc/html/rfc8452\n */\nexport const siv = wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16 }, function siv(key, nonce, AAD) {\n const tagLength = 16;\n // From RFC 8452: Section 6\n const AAD_LIMIT = limit('AAD', 0, 2 ** 36);\n const PLAIN_LIMIT = limit('plaintext', 0, 2 ** 36);\n const NONCE_LIMIT = limit('nonce', 12, 12);\n const CIPHER_LIMIT = limit('ciphertext', 16, 2 ** 36 + 16);\n abytes(nonce);\n NONCE_LIMIT(nonce.length);\n if (AAD) {\n abytes(AAD);\n AAD_LIMIT(AAD.length);\n }\n function deriveKeys() {\n const len = key.length;\n if (len !== 16 && len !== 24 && len !== 32)\n throw new Error(`key length must be 16, 24 or 32 bytes, got: ${len} bytes`);\n const xk = expandKeyLE(key);\n const encKey = new Uint8Array(len);\n const authKey = new Uint8Array(16);\n const n32 = u32(nonce);\n // prettier-ignore\n let s0 = 0, s1 = n32[0], s2 = n32[1], s3 = n32[2];\n let counter = 0;\n for (const derivedKey of [authKey, encKey].map(u32)) {\n const d32 = u32(derivedKey);\n for (let i = 0; i < d32.length; i += 2) {\n // aes(u32le(0) || nonce)[:8] || aes(u32le(1) || nonce)[:8] ...\n const { s0: o0, s1: o1 } = encrypt(xk, s0, s1, s2, s3);\n d32[i + 0] = o0;\n d32[i + 1] = o1;\n s0 = ++counter; // increment counter inside state\n }\n }\n xk.fill(0);\n return { authKey, encKey: expandKeyLE(encKey) };\n }\n function _computeTag(encKey, authKey, data) {\n const tag = computeTag(polyval, true, authKey, data, AAD);\n // Compute the expected tag by XORing S_s and the nonce, clearing the\n // most significant bit of the last byte and encrypting with the\n // message-encryption key.\n for (let i = 0; i < 12; i++)\n tag[i] ^= nonce[i];\n tag[15] &= 0x7f; // Clear the highest bit\n // encrypt tag as block\n const t32 = u32(tag);\n // prettier-ignore\n let s0 = t32[0], s1 = t32[1], s2 = t32[2], s3 = t32[3];\n ({ s0, s1, s2, s3 } = encrypt(encKey, s0, s1, s2, s3));\n (t32[0] = s0), (t32[1] = s1), (t32[2] = s2), (t32[3] = s3);\n return tag;\n }\n // actual decrypt/encrypt of message.\n function processSiv(encKey, tag, input) {\n let block = tag.slice();\n block[15] |= 0x80; // Force highest bit\n return ctr32(encKey, true, block, input);\n }\n return {\n encrypt: (plaintext) => {\n abytes(plaintext);\n PLAIN_LIMIT(plaintext.length);\n const { encKey, authKey } = deriveKeys();\n const tag = _computeTag(encKey, authKey, plaintext);\n const out = new Uint8Array(plaintext.length + tagLength);\n out.set(tag, plaintext.length);\n out.set(processSiv(encKey, tag, plaintext));\n encKey.fill(0);\n authKey.fill(0);\n return out;\n },\n decrypt: (ciphertext) => {\n abytes(ciphertext);\n CIPHER_LIMIT(ciphertext.length);\n const tag = ciphertext.subarray(-tagLength);\n const { encKey, authKey } = deriveKeys();\n const plaintext = processSiv(encKey, tag, ciphertext.subarray(0, -tagLength));\n const expectedTag = _computeTag(encKey, authKey, plaintext);\n encKey.fill(0);\n authKey.fill(0);\n if (!equalBytes(tag, expectedTag))\n throw new Error('invalid polyval tag');\n return plaintext;\n },\n };\n});\nfunction isBytes32(a) {\n return (a != null &&\n typeof a === 'object' &&\n (a instanceof Uint32Array || a.constructor.name === 'Uint32Array'));\n}\nfunction encryptBlock(xk, block) {\n abytes(block, 16);\n if (!isBytes32(xk))\n throw new Error('_encryptBlock accepts result of expandKeyLE');\n const b32 = u32(block);\n let { s0, s1, s2, s3 } = encrypt(xk, b32[0], b32[1], b32[2], b32[3]);\n (b32[0] = s0), (b32[1] = s1), (b32[2] = s2), (b32[3] = s3);\n return block;\n}\nfunction decryptBlock(xk, block) {\n abytes(block, 16);\n if (!isBytes32(xk))\n throw new Error('_decryptBlock accepts result of expandKeyLE');\n const b32 = u32(block);\n let { s0, s1, s2, s3 } = decrypt(xk, b32[0], b32[1], b32[2], b32[3]);\n (b32[0] = s0), (b32[1] = s1), (b32[2] = s2), (b32[3] = s3);\n return block;\n}\n// Highly unsafe private functions for implementing new modes or ciphers based on AES\n// Can change at any time, no API guarantees\nexport const unsafe = {\n expandKeyLE,\n expandKeyDecLE,\n encrypt,\n decrypt,\n encryptBlock,\n decryptBlock,\n ctrCounter,\n ctr32,\n};\n//# sourceMappingURL=aes.js.map","// Basic utils for ARX (add-rotate-xor) salsa and chacha ciphers.\nimport { number as anumber, bytes as abytes, bool as abool } from './_assert.js';\nimport { checkOpts, u32 } from './utils.js';\n/*\nRFC8439 requires multi-step cipher stream, where\nauthKey starts with counter: 0, actual msg with counter: 1.\n\nFor this, we need a way to re-use nonce / counter:\n\n const counter = new Uint8Array(4);\n chacha(..., counter, ...); // counter is now 1\n chacha(..., counter, ...); // counter is now 2\n\nThis is complicated:\n\n- 32-bit counters are enough, no need for 64-bit: max ArrayBuffer size in JS is 4GB\n- Original papers don't allow mutating counters\n- Counter overflow is undefined [^1]\n- Idea A: allow providing (nonce | counter) instead of just nonce, re-use it\n- Caveat: Cannot be re-used through all cases:\n- * chacha has (counter | nonce)\n- * xchacha has (nonce16 | counter | nonce16)\n- Idea B: separate nonce / counter and provide separate API for counter re-use\n- Caveat: there are different counter sizes depending on an algorithm.\n- salsa & chacha also differ in structures of key & sigma:\n salsa20: s[0] | k(4) | s[1] | nonce(2) | ctr(2) | s[2] | k(4) | s[3]\n chacha: s(4) | k(8) | ctr(1) | nonce(3)\n chacha20orig: s(4) | k(8) | ctr(2) | nonce(2)\n- Idea C: helper method such as `setSalsaState(key, nonce, sigma, data)`\n- Caveat: we can't re-use counter array\n\nxchacha [^2] uses the subkey and remaining 8 byte nonce with ChaCha20 as normal\n(prefixed by 4 NUL bytes, since [RFC8439] specifies a 12-byte nonce).\n\n[^1]: https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU/\n[^2]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#appendix-A.2\n*/\n// We can't make top-level var depend on utils.utf8ToBytes\n// because it's not present in all envs. Creating a similar fn here\nconst _utf8ToBytes = (str) => Uint8Array.from(str.split('').map((c) => c.charCodeAt(0)));\nconst sigma16 = _utf8ToBytes('expand 16-byte k');\nconst sigma32 = _utf8ToBytes('expand 32-byte k');\nconst sigma16_32 = u32(sigma16);\nconst sigma32_32 = u32(sigma32);\nexport const sigma = sigma32_32.slice();\nexport function rotl(a, b) {\n return (a << b) | (a >>> (32 - b));\n}\n// Is byte array aligned to 4 byte offset (u32)?\nfunction isAligned32(b) {\n return b.byteOffset % 4 === 0;\n}\n// Salsa and Chacha block length is always 512-bit\nconst BLOCK_LEN = 64;\nconst BLOCK_LEN32 = 16;\n// new Uint32Array([2**32]) // => Uint32Array(1) [ 0 ]\n// new Uint32Array([2**32-1]) // => Uint32Array(1) [ 4294967295 ]\nconst MAX_COUNTER = 2 ** 32 - 1;\nconst U32_EMPTY = new Uint32Array();\nfunction runCipher(core, sigma, key, nonce, data, output, counter, rounds) {\n const len = data.length;\n const block = new Uint8Array(BLOCK_LEN);\n const b32 = u32(block);\n // Make sure that buffers aligned to 4 bytes\n const isAligned = isAligned32(data) && isAligned32(output);\n const d32 = isAligned ? u32(data) : U32_EMPTY;\n const o32 = isAligned ? u32(output) : U32_EMPTY;\n for (let pos = 0; pos < len; counter++) {\n core(sigma, key, nonce, b32, counter, rounds);\n if (counter >= MAX_COUNTER)\n throw new Error('arx: counter overflow');\n const take = Math.min(BLOCK_LEN, len - pos);\n // aligned to 4 bytes\n if (isAligned && take === BLOCK_LEN) {\n const pos32 = pos / 4;\n if (pos % 4 !== 0)\n throw new Error('arx: invalid block position');\n for (let j = 0, posj; j < BLOCK_LEN32; j++) {\n posj = pos32 + j;\n o32[posj] = d32[posj] ^ b32[j];\n }\n pos += BLOCK_LEN;\n continue;\n }\n for (let j = 0, posj; j < take; j++) {\n posj = pos + j;\n output[posj] = data[posj] ^ block[j];\n }\n pos += take;\n }\n}\nexport function createCipher(core, opts) {\n const { allowShortKeys, extendNonceFn, counterLength, counterRight, rounds } = checkOpts({ allowShortKeys: false, counterLength: 8, counterRight: false, rounds: 20 }, opts);\n if (typeof core !== 'function')\n throw new Error('core must be a function');\n anumber(counterLength);\n anumber(rounds);\n abool(counterRight);\n abool(allowShortKeys);\n return (key, nonce, data, output, counter = 0) => {\n abytes(key);\n abytes(nonce);\n abytes(data);\n const len = data.length;\n if (!output)\n output = new Uint8Array(len);\n abytes(output);\n anumber(counter);\n if (counter < 0 || counter >= MAX_COUNTER)\n throw new Error('arx: counter overflow');\n if (output.length < len)\n throw new Error(`arx: output (${output.length}) is shorter than data (${len})`);\n const toClean = [];\n // Key & sigma\n // key=16 -> sigma16, k=key|key\n // key=32 -> sigma32, k=key\n let l = key.length, k, sigma;\n if (l === 32) {\n k = key.slice();\n toClean.push(k);\n sigma = sigma32_32;\n }\n else if (l === 16 && allowShortKeys) {\n k = new Uint8Array(32);\n k.set(key);\n k.set(key, 16);\n sigma = sigma16_32;\n toClean.push(k);\n }\n else {\n throw new Error(`arx: invalid 32-byte key, got length=${l}`);\n }\n // Nonce\n // salsa20: 8 (8-byte counter)\n // chacha20orig: 8 (8-byte counter)\n // chacha20: 12 (4-byte counter)\n // xsalsa20: 24 (16 -> hsalsa, 8 -> old nonce)\n // xchacha20: 24 (16 -> hchacha, 8 -> old nonce)\n // Align nonce to 4 bytes\n if (!isAligned32(nonce)) {\n nonce = nonce.slice();\n toClean.push(nonce);\n }\n const k32 = u32(k);\n // hsalsa & hchacha: handle extended nonce\n if (extendNonceFn) {\n if (nonce.length !== 24)\n throw new Error(`arx: extended nonce must be 24 bytes`);\n extendNonceFn(sigma, k32, u32(nonce.subarray(0, 16)), k32);\n nonce = nonce.subarray(16);\n }\n // Handle nonce counter\n const nonceNcLen = 16 - counterLength;\n if (nonceNcLen !== nonce.length)\n throw new Error(`arx: nonce must be ${nonceNcLen} or 16 bytes`);\n // Pad counter when nonce is 64 bit\n if (nonceNcLen !== 12) {\n const nc = new Uint8Array(12);\n nc.set(nonce, counterRight ? 0 : 12 - nonce.length);\n nonce = nc;\n toClean.push(nonce);\n }\n const n32 = u32(nonce);\n runCipher(core, sigma, k32, n32, data, output, counter, rounds);\n while (toClean.length > 0)\n toClean.pop().fill(0);\n return output;\n };\n}\n//# sourceMappingURL=_arx.js.map","// prettier-ignore\nimport { wrapCipher, createView, equalBytes, setBigUint64, } from './utils.js';\nimport { poly1305 } from './_poly1305.js';\nimport { createCipher, rotl } from './_arx.js';\nimport { bytes as abytes } from './_assert.js';\n// ChaCha20 stream cipher was released in 2008. ChaCha aims to increase\n// the diffusion per round, but had slightly less cryptanalysis.\n// https://cr.yp.to/chacha.html, http://cr.yp.to/chacha/chacha-20080128.pdf\n/**\n * ChaCha core function.\n */\n// prettier-ignore\nfunction chachaCore(s, k, n, out, cnt, rounds = 20) {\n let y00 = s[0], y01 = s[1], y02 = s[2], y03 = s[3], // \"expa\" \"nd 3\" \"2-by\" \"te k\"\n y04 = k[0], y05 = k[1], y06 = k[2], y07 = k[3], // Key Key Key Key\n y08 = k[4], y09 = k[5], y10 = k[6], y11 = k[7], // Key Key Key Key\n y12 = cnt, y13 = n[0], y14 = n[1], y15 = n[2]; // Counter Counter\tNonce Nonce\n // Save state to temporary variables\n 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;\n for (let r = 0; r < rounds; r += 2) {\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 16);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 12);\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 8);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 7);\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 16);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 12);\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 8);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 7);\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 16);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 12);\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 8);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 7);\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 16);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 12);\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 8);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 7);\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 16);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 12);\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 8);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 7);\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 16);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 12);\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 8);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 7);\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 16);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 12);\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 8);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 7);\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 16);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 12);\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 8);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 7);\n }\n // Write output\n let oi = 0;\n out[oi++] = (y00 + x00) | 0;\n out[oi++] = (y01 + x01) | 0;\n out[oi++] = (y02 + x02) | 0;\n out[oi++] = (y03 + x03) | 0;\n out[oi++] = (y04 + x04) | 0;\n out[oi++] = (y05 + x05) | 0;\n out[oi++] = (y06 + x06) | 0;\n out[oi++] = (y07 + x07) | 0;\n out[oi++] = (y08 + x08) | 0;\n out[oi++] = (y09 + x09) | 0;\n out[oi++] = (y10 + x10) | 0;\n out[oi++] = (y11 + x11) | 0;\n out[oi++] = (y12 + x12) | 0;\n out[oi++] = (y13 + x13) | 0;\n out[oi++] = (y14 + x14) | 0;\n out[oi++] = (y15 + x15) | 0;\n}\n/**\n * hchacha helper method, used primarily in xchacha, to hash\n * key and nonce into key' and nonce'.\n * Same as chachaCore, but there doesn't seem to be a way to move the block\n * out without 25% performance hit.\n */\n// prettier-ignore\nexport function hchacha(s, k, i, o32) {\n 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 = i[0], x13 = i[1], x14 = i[2], x15 = i[3];\n for (let r = 0; r < 20; r += 2) {\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 16);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 12);\n x00 = (x00 + x04) | 0;\n x12 = rotl(x12 ^ x00, 8);\n x08 = (x08 + x12) | 0;\n x04 = rotl(x04 ^ x08, 7);\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 16);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 12);\n x01 = (x01 + x05) | 0;\n x13 = rotl(x13 ^ x01, 8);\n x09 = (x09 + x13) | 0;\n x05 = rotl(x05 ^ x09, 7);\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 16);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 12);\n x02 = (x02 + x06) | 0;\n x14 = rotl(x14 ^ x02, 8);\n x10 = (x10 + x14) | 0;\n x06 = rotl(x06 ^ x10, 7);\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 16);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 12);\n x03 = (x03 + x07) | 0;\n x15 = rotl(x15 ^ x03, 8);\n x11 = (x11 + x15) | 0;\n x07 = rotl(x07 ^ x11, 7);\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 16);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 12);\n x00 = (x00 + x05) | 0;\n x15 = rotl(x15 ^ x00, 8);\n x10 = (x10 + x15) | 0;\n x05 = rotl(x05 ^ x10, 7);\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 16);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 12);\n x01 = (x01 + x06) | 0;\n x12 = rotl(x12 ^ x01, 8);\n x11 = (x11 + x12) | 0;\n x06 = rotl(x06 ^ x11, 7);\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 16);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 12);\n x02 = (x02 + x07) | 0;\n x13 = rotl(x13 ^ x02, 8);\n x08 = (x08 + x13) | 0;\n x07 = rotl(x07 ^ x08, 7);\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 16);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 12);\n x03 = (x03 + x04) | 0;\n x14 = rotl(x14 ^ x03, 8);\n x09 = (x09 + x14) | 0;\n x04 = rotl(x04 ^ x09, 7);\n }\n let oi = 0;\n o32[oi++] = x00;\n o32[oi++] = x01;\n o32[oi++] = x02;\n o32[oi++] = x03;\n o32[oi++] = x12;\n o32[oi++] = x13;\n o32[oi++] = x14;\n o32[oi++] = x15;\n}\n/**\n * Original, non-RFC chacha20 from DJB. 8-byte nonce, 8-byte counter.\n */\nexport const chacha20orig = /* @__PURE__ */ createCipher(chachaCore, {\n counterRight: false,\n counterLength: 8,\n allowShortKeys: true,\n});\n/**\n * ChaCha stream cipher. Conforms to RFC 8439 (IETF, TLS). 12-byte nonce, 4-byte counter.\n * With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance.\n */\nexport const chacha20 = /* @__PURE__ */ createCipher(chachaCore, {\n counterRight: false,\n counterLength: 4,\n allowShortKeys: false,\n});\n/**\n * XChaCha eXtended-nonce ChaCha. 24-byte nonce.\n * With 24-byte nonce, it's safe to use fill it with random (CSPRNG).\n * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha\n */\nexport const xchacha20 = /* @__PURE__ */ createCipher(chachaCore, {\n counterRight: false,\n counterLength: 8,\n extendNonceFn: hchacha,\n allowShortKeys: false,\n});\n/**\n * Reduced 8-round chacha, described in original paper.\n */\nexport const chacha8 = /* @__PURE__ */ createCipher(chachaCore, {\n counterRight: false,\n counterLength: 4,\n rounds: 8,\n});\n/**\n * Reduced 12-round chacha, described in original paper.\n */\nexport const chacha12 = /* @__PURE__ */ createCipher(chachaCore, {\n counterRight: false,\n counterLength: 4,\n rounds: 12,\n});\nconst ZEROS16 = /* @__PURE__ */ new Uint8Array(16);\n// Pad to digest size with zeros\nconst updatePadded = (h, msg) => {\n h.update(msg);\n const left = msg.length % 16;\n if (left)\n h.update(ZEROS16.subarray(left));\n};\nconst ZEROS32 = /* @__PURE__ */ new Uint8Array(32);\nfunction computeTag(fn, key, nonce, data, AAD) {\n const authKey = fn(key, nonce, ZEROS32);\n const h = poly1305.create(authKey);\n if (AAD)\n updatePadded(h, AAD);\n updatePadded(h, data);\n const num = new Uint8Array(16);\n const view = createView(num);\n setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true);\n setBigUint64(view, 8, BigInt(data.length), true);\n h.update(num);\n const res = h.digest();\n authKey.fill(0);\n return res;\n}\n/**\n * AEAD algorithm from RFC 8439.\n * Salsa20 and chacha (RFC 8439) use poly1305 differently.\n * We could have composed them similar to:\n * https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250\n * But it's hard because of authKey:\n * In salsa20, authKey changes position in salsa stream.\n * In chacha, authKey can't be computed inside computeTag, it modifies the counter.\n */\nexport const _poly1305_aead = (xorStream) => (key, nonce, AAD) => {\n const tagLength = 16;\n abytes(key, 32);\n abytes(nonce);\n return {\n encrypt: (plaintext, output) => {\n const plength = plaintext.length;\n const clength = plength + tagLength;\n if (output) {\n abytes(output, clength);\n }\n else {\n output = new Uint8Array(clength);\n }\n xorStream(key, nonce, plaintext, output, 1);\n const tag = computeTag(xorStream, key, nonce, output.subarray(0, -tagLength), AAD);\n output.set(tag, plength); // append tag\n return output;\n },\n decrypt: (ciphertext, output) => {\n const clength = ciphertext.length;\n const plength = clength - tagLength;\n if (clength < tagLength)\n throw new Error(`encrypted data must be at least ${tagLength} bytes`);\n if (output) {\n abytes(output, plength);\n }\n else {\n output = new Uint8Array(plength);\n }\n const data = ciphertext.subarray(0, -tagLength);\n const passedTag = ciphertext.subarray(-tagLength);\n const tag = computeTag(xorStream, key, nonce, data, AAD);\n if (!equalBytes(passedTag, tag))\n throw new Error('invalid tag');\n xorStream(key, nonce, data, output, 1);\n return output;\n },\n };\n};\n/**\n * ChaCha20-Poly1305 from RFC 8439.\n * With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance.\n */\nexport const chacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 12, tagLength: 16 }, _poly1305_aead(chacha20));\n/**\n * XChaCha20-Poly1305 extended-nonce chacha.\n * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha\n * With 24-byte nonce, it's safe to use fill it with random (CSPRNG).\n */\nexport const xchacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 24, tagLength: 16 }, _poly1305_aead(xchacha20));\n//# sourceMappingURL=chacha.js.map","import assert from './_assert.js';\nimport { Hash, toBytes } from './utils.js';\n// HMAC (RFC 2104)\nexport class HMAC extends Hash {\n constructor(hash, _key) {\n super();\n this.finished = false;\n this.destroyed = false;\n assert.hash(hash);\n const key = toBytes(_key);\n this.iHash = hash.create();\n if (typeof this.iHash.update !== 'function')\n throw new Error('Expected instance of class which extends utils.Hash');\n this.blockLen = this.iHash.blockLen;\n this.outputLen = this.iHash.outputLen;\n const blockLen = this.blockLen;\n const pad = new Uint8Array(blockLen);\n // blockLen can be bigger than outputLen\n pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);\n for (let i = 0; i < pad.length; i++)\n pad[i] ^= 0x36;\n this.iHash.update(pad);\n // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone\n this.oHash = hash.create();\n // Undo internal XOR && apply outer XOR\n for (let i = 0; i < pad.length; i++)\n pad[i] ^= 0x36 ^ 0x5c;\n this.oHash.update(pad);\n pad.fill(0);\n }\n update(buf) {\n assert.exists(this);\n this.iHash.update(buf);\n return this;\n }\n digestInto(out) {\n assert.exists(this);\n assert.bytes(out, this.outputLen);\n this.finished = true;\n this.iHash.digestInto(out);\n this.oHash.update(out);\n this.oHash.digestInto(out);\n this.destroy();\n }\n digest() {\n const out = new Uint8Array(this.oHash.outputLen);\n this.digestInto(out);\n return out;\n }\n _cloneInto(to) {\n // Create new instance without calling constructor since key already in state and we don't know it.\n to || (to = Object.create(Object.getPrototypeOf(this), {}));\n const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;\n to = to;\n to.finished = finished;\n to.destroyed = destroyed;\n to.blockLen = blockLen;\n to.outputLen = outputLen;\n to.oHash = oHash._cloneInto(to.oHash);\n to.iHash = iHash._cloneInto(to.iHash);\n return to;\n }\n destroy() {\n this.destroyed = true;\n this.oHash.destroy();\n this.iHash.destroy();\n }\n}\n/**\n * HMAC: RFC2104 message authentication code.\n * @param hash - function that would be used e.g. sha256\n * @param key - message key\n * @param message - message data\n */\nexport const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();\nhmac.create = (hash, key) => new HMAC(hash, key);\n//# sourceMappingURL=hmac.js.map","import assert from './_assert.js';\nimport { toBytes } from './utils.js';\nimport { hmac } from './hmac.js';\n// HKDF (RFC 5869)\n// https://soatok.blog/2021/11/17/understanding-hkdf/\n/**\n * HKDF-Extract(IKM, salt) -> PRK\n * Arguments position differs from spec (IKM is first one, since it is not optional)\n * @param hash\n * @param ikm\n * @param salt\n * @returns\n */\nexport function extract(hash, ikm, salt) {\n assert.hash(hash);\n // NOTE: some libraries treat zero-length array as 'not provided';\n // we don't, since we have undefined as 'not provided'\n // https://github.com/RustCrypto/KDFs/issues/15\n if (salt === undefined)\n salt = new Uint8Array(hash.outputLen); // if not provided, it is set to a string of HashLen zeros\n return hmac(hash, toBytes(salt), toBytes(ikm));\n}\n// HKDF-Expand(PRK, info, L) -> OKM\nconst HKDF_COUNTER = new Uint8Array([0]);\nconst EMPTY_BUFFER = new Uint8Array();\n/**\n * HKDF-expand from the spec.\n * @param prk - a pseudorandom key of at least HashLen octets (usually, the output from the extract step)\n * @param info - optional context and application specific information (can be a zero-length string)\n * @param length - length of output keying material in octets\n */\nexport function expand(hash, prk, info, length = 32) {\n assert.hash(hash);\n assert.number(length);\n if (length > 255 * hash.outputLen)\n throw new Error('Length should be <= 255*HashLen');\n const blocks = Math.ceil(length / hash.outputLen);\n if (info === undefined)\n info = EMPTY_BUFFER;\n // first L(ength) octets of T\n const okm = new Uint8Array(blocks * hash.outputLen);\n // Re-use HMAC instance between blocks\n const HMAC = hmac.create(hash, prk);\n const HMACTmp = HMAC._cloneInto();\n const T = new Uint8Array(HMAC.outputLen);\n for (let counter = 0; counter < blocks; counter++) {\n HKDF_COUNTER[0] = counter + 1;\n // T(0) = empty string (zero length)\n // T(N) = HMAC-Hash(PRK, T(N-1) | info | N)\n HMACTmp.update(counter === 0 ? EMPTY_BUFFER : T)\n .update(info)\n .update(HKDF_COUNTER)\n .digestInto(T);\n okm.set(T, hash.outputLen * counter);\n HMAC._cloneInto(HMACTmp);\n }\n HMAC.destroy();\n HMACTmp.destroy();\n T.fill(0);\n HKDF_COUNTER.fill(0);\n return okm.slice(0, length);\n}\n/**\n * HKDF (RFC 5869): extract + expand in one step.\n * @param hash - hash function that would be used (e.g. sha256)\n * @param ikm - input keying material, the initial key\n * @param salt - optional salt value (a non-secret random value)\n * @param info - optional context and application specific information\n * @param length - length of output keying material in octets\n */\nexport const hkdf = (hash, ikm, salt, info, length) => expand(hash, extract(hash, ikm, salt), info, length);\n//# sourceMappingURL=hkdf.js.map","var __defProp = Object.defineProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\n\n// pure.ts\nimport { schnorr } from \"@noble/curves/secp256k1\";\nimport { bytesToHex as bytesToHex2 } from \"@noble/hashes/utils\";\n\n// core.ts\nvar verifiedSymbol = Symbol(\"verified\");\nvar isRecord = (obj) => obj instanceof Object;\nfunction validateEvent(event) {\n if (!isRecord(event))\n return false;\n if (typeof event.kind !== \"number\")\n return false;\n if (typeof event.content !== \"string\")\n return false;\n if (typeof event.created_at !== \"number\")\n return false;\n if (typeof event.pubkey !== \"string\")\n return false;\n if (!event.pubkey.match(/^[a-f0-9]{64}$/))\n return false;\n if (!Array.isArray(event.tags))\n return false;\n for (let i2 = 0; i2 < event.tags.length; i2++) {\n let tag = event.tags[i2];\n if (!Array.isArray(tag))\n return false;\n for (let j = 0; j < tag.length; j++) {\n if (typeof tag[j] !== \"string\")\n return false;\n }\n }\n return true;\n}\nfunction sortEvents(events) {\n return events.sort((a, b) => {\n if (a.created_at !== b.created_at) {\n return b.created_at - a.created_at;\n }\n return a.id.localeCompare(b.id);\n });\n}\n\n// pure.ts\nimport { sha256 } from \"@noble/hashes/sha256\";\n\n// utils.ts\nvar utils_exports = {};\n__export(utils_exports, {\n Queue: () => Queue,\n QueueNode: () => QueueNode,\n binarySearch: () => binarySearch,\n bytesToHex: () => bytesToHex,\n hexToBytes: () => hexToBytes,\n insertEventIntoAscendingList: () => insertEventIntoAscendingList,\n insertEventIntoDescendingList: () => insertEventIntoDescendingList,\n normalizeURL: () => normalizeURL,\n utf8Decoder: () => utf8Decoder,\n utf8Encoder: () => utf8Encoder\n});\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils\";\nvar utf8Decoder = new TextDecoder(\"utf-8\");\nvar utf8Encoder = new TextEncoder();\nfunction normalizeURL(url) {\n try {\n if (url.indexOf(\"://\") === -1)\n url = \"wss://\" + url;\n let p = new URL(url);\n p.pathname = p.pathname.replace(/\\/+/g, \"/\");\n if (p.pathname.endsWith(\"/\"))\n p.pathname = p.pathname.slice(0, -1);\n if (p.port === \"80\" && p.protocol === \"ws:\" || p.port === \"443\" && p.protocol === \"wss:\")\n p.port = \"\";\n p.searchParams.sort();\n p.hash = \"\";\n return p.toString();\n } catch (e) {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\nfunction insertEventIntoDescendingList(sortedArray, event) {\n const [idx, found] = binarySearch(sortedArray, (b) => {\n if (event.id === b.id)\n return 0;\n if (event.created_at === b.created_at)\n return -1;\n return b.created_at - event.created_at;\n });\n if (!found) {\n sortedArray.splice(idx, 0, event);\n }\n return sortedArray;\n}\nfunction insertEventIntoAscendingList(sortedArray, event) {\n const [idx, found] = binarySearch(sortedArray, (b) => {\n if (event.id === b.id)\n return 0;\n if (event.created_at === b.created_at)\n return -1;\n return event.created_at - b.created_at;\n });\n if (!found) {\n sortedArray.splice(idx, 0, event);\n }\n return sortedArray;\n}\nfunction binarySearch(arr, compare) {\n let start = 0;\n let end = arr.length - 1;\n while (start <= end) {\n const mid = Math.floor((start + end) / 2);\n const cmp = compare(arr[mid]);\n if (cmp === 0) {\n return [mid, true];\n }\n if (cmp < 0) {\n end = mid - 1;\n } else {\n start = mid + 1;\n }\n }\n return [start, false];\n}\nvar QueueNode = class {\n value;\n next = null;\n prev = null;\n constructor(message) {\n this.value = message;\n }\n};\nvar Queue = class {\n first;\n last;\n constructor() {\n this.first = null;\n this.last = null;\n }\n enqueue(value) {\n const newNode = new QueueNode(value);\n if (!this.last) {\n this.first = newNode;\n this.last = newNode;\n } else if (this.last === this.first) {\n this.last = newNode;\n this.last.prev = this.first;\n this.first.next = newNode;\n } else {\n newNode.prev = this.last;\n this.last.next = newNode;\n this.last = newNode;\n }\n return true;\n }\n dequeue() {\n if (!this.first)\n return null;\n if (this.first === this.last) {\n const target2 = this.first;\n this.first = null;\n this.last = null;\n return target2.value;\n }\n const target = this.first;\n this.first = target.next;\n if (this.first) {\n this.first.prev = null;\n }\n return target.value;\n }\n};\n\n// pure.ts\nvar JS = class {\n generateSecretKey() {\n return schnorr.utils.randomPrivateKey();\n }\n getPublicKey(secretKey) {\n return bytesToHex2(schnorr.getPublicKey(secretKey));\n }\n finalizeEvent(t, secretKey) {\n const event = t;\n event.pubkey = bytesToHex2(schnorr.getPublicKey(secretKey));\n event.id = getEventHash(event);\n event.sig = bytesToHex2(schnorr.sign(getEventHash(event), secretKey));\n event[verifiedSymbol] = true;\n return event;\n }\n verifyEvent(event) {\n if (typeof event[verifiedSymbol] === \"boolean\")\n return event[verifiedSymbol];\n const hash = getEventHash(event);\n if (hash !== event.id) {\n event[verifiedSymbol] = false;\n return false;\n }\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey);\n event[verifiedSymbol] = valid;\n return valid;\n } catch (err) {\n event[verifiedSymbol] = false;\n return false;\n }\n }\n};\nfunction serializeEvent(evt) {\n if (!validateEvent(evt))\n throw new Error(\"can't serialize event with wrong or missing properties\");\n return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);\n}\nfunction getEventHash(event) {\n let eventHash = sha256(utf8Encoder.encode(serializeEvent(event)));\n return bytesToHex2(eventHash);\n}\nvar i = new JS();\nvar generateSecretKey = i.generateSecretKey;\nvar getPublicKey = i.getPublicKey;\nvar finalizeEvent = i.finalizeEvent;\nvar verifyEvent = i.verifyEvent;\n\n// kinds.ts\nvar kinds_exports = {};\n__export(kinds_exports, {\n Application: () => Application,\n BadgeAward: () => BadgeAward,\n BadgeDefinition: () => BadgeDefinition,\n BlockedRelaysList: () => BlockedRelaysList,\n BookmarkList: () => BookmarkList,\n Bookmarksets: () => Bookmarksets,\n Calendar: () => Calendar,\n CalendarEventRSVP: () => CalendarEventRSVP,\n ChannelCreation: () => ChannelCreation,\n ChannelHideMessage: () => ChannelHideMessage,\n ChannelMessage: () => ChannelMessage,\n ChannelMetadata: () => ChannelMetadata,\n ChannelMuteUser: () => ChannelMuteUser,\n ClassifiedListing: () => ClassifiedListing,\n ClientAuth: () => ClientAuth,\n CommunitiesList: () => CommunitiesList,\n CommunityDefinition: () => CommunityDefinition,\n CommunityPostApproval: () => CommunityPostApproval,\n Contacts: () => Contacts,\n CreateOrUpdateProduct: () => CreateOrUpdateProduct,\n CreateOrUpdateStall: () => CreateOrUpdateStall,\n Curationsets: () => Curationsets,\n Date: () => Date2,\n DirectMessageRelaysList: () => DirectMessageRelaysList,\n DraftClassifiedListing: () => DraftClassifiedListing,\n DraftLong: () => DraftLong,\n Emojisets: () => Emojisets,\n EncryptedDirectMessage: () => EncryptedDirectMessage,\n EventDeletion: () => EventDeletion,\n FileMetadata: () => FileMetadata,\n FileServerPreference: () => FileServerPreference,\n Followsets: () => Followsets,\n GenericRepost: () => GenericRepost,\n Genericlists: () => Genericlists,\n GiftWrap: () => GiftWrap,\n HTTPAuth: () => HTTPAuth,\n Handlerinformation: () => Handlerinformation,\n Handlerrecommendation: () => Handlerrecommendation,\n Highlights: () => Highlights,\n InterestsList: () => InterestsList,\n Interestsets: () => Interestsets,\n JobFeedback: () => JobFeedback,\n JobRequest: () => JobRequest,\n JobResult: () => JobResult,\n Label: () => Label,\n LightningPubRPC: () => LightningPubRPC,\n LiveChatMessage: () => LiveChatMessage,\n LiveEvent: () => LiveEvent,\n LongFormArticle: () => LongFormArticle,\n Metadata: () => Metadata,\n Mutelist: () => Mutelist,\n NWCWalletInfo: () => NWCWalletInfo,\n NWCWalletRequest: () => NWCWalletRequest,\n NWCWalletResponse: () => NWCWalletResponse,\n NostrConnect: () => NostrConnect,\n OpenTimestamps: () => OpenTimestamps,\n Pinlist: () => Pinlist,\n PrivateDirectMessage: () => PrivateDirectMessage,\n ProblemTracker: () => ProblemTracker,\n ProfileBadges: () => ProfileBadges,\n PublicChatsList: () => PublicChatsList,\n Reaction: () => Reaction,\n RecommendRelay: () => RecommendRelay,\n RelayList: () => RelayList,\n Relaysets: () => Relaysets,\n Report: () => Report,\n Reporting: () => Reporting,\n Repost: () => Repost,\n Seal: () => Seal,\n SearchRelaysList: () => SearchRelaysList,\n ShortTextNote: () => ShortTextNote,\n Time: () => Time,\n UserEmojiList: () => UserEmojiList,\n UserStatuses: () => UserStatuses,\n Zap: () => Zap,\n ZapGoal: () => ZapGoal,\n ZapRequest: () => ZapRequest,\n classifyKind: () => classifyKind,\n isAddressableKind: () => isAddressableKind,\n isEphemeralKind: () => isEphemeralKind,\n isKind: () => isKind,\n isRegularKind: () => isRegularKind,\n isReplaceableKind: () => isReplaceableKind\n});\nfunction isRegularKind(kind) {\n return 1e3 <= kind && kind < 1e4 || [1, 2, 4, 5, 6, 7, 8, 16, 40, 41, 42, 43, 44].includes(kind);\n}\nfunction isReplaceableKind(kind) {\n return [0, 3].includes(kind) || 1e4 <= kind && kind < 2e4;\n}\nfunction isEphemeralKind(kind) {\n return 2e4 <= kind && kind < 3e4;\n}\nfunction isAddressableKind(kind) {\n return 3e4 <= kind && kind < 4e4;\n}\nfunction classifyKind(kind) {\n if (isRegularKind(kind))\n return \"regular\";\n if (isReplaceableKind(kind))\n return \"replaceable\";\n if (isEphemeralKind(kind))\n return \"ephemeral\";\n if (isAddressableKind(kind))\n return \"parameterized\";\n return \"unknown\";\n}\nfunction isKind(event, kind) {\n const kindAsArray = kind instanceof Array ? kind : [kind];\n return validateEvent(event) && kindAsArray.includes(event.kind) || false;\n}\nvar Metadata = 0;\nvar ShortTextNote = 1;\nvar RecommendRelay = 2;\nvar Contacts = 3;\nvar EncryptedDirectMessage = 4;\nvar EventDeletion = 5;\nvar Repost = 6;\nvar Reaction = 7;\nvar BadgeAward = 8;\nvar Seal = 13;\nvar PrivateDirectMessage = 14;\nvar GenericRepost = 16;\nvar ChannelCreation = 40;\nvar ChannelMetadata = 41;\nvar ChannelMessage = 42;\nvar ChannelHideMessage = 43;\nvar ChannelMuteUser = 44;\nvar OpenTimestamps = 1040;\nvar GiftWrap = 1059;\nvar FileMetadata = 1063;\nvar LiveChatMessage = 1311;\nvar ProblemTracker = 1971;\nvar Report = 1984;\nvar Reporting = 1984;\nvar Label = 1985;\nvar CommunityPostApproval = 4550;\nvar JobRequest = 5999;\nvar JobResult = 6999;\nvar JobFeedback = 7e3;\nvar ZapGoal = 9041;\nvar ZapRequest = 9734;\nvar Zap = 9735;\nvar Highlights = 9802;\nvar Mutelist = 1e4;\nvar Pinlist = 10001;\nvar RelayList = 10002;\nvar BookmarkList = 10003;\nvar CommunitiesList = 10004;\nvar PublicChatsList = 10005;\nvar BlockedRelaysList = 10006;\nvar SearchRelaysList = 10007;\nvar InterestsList = 10015;\nvar UserEmojiList = 10030;\nvar DirectMessageRelaysList = 10050;\nvar FileServerPreference = 10096;\nvar NWCWalletInfo = 13194;\nvar LightningPubRPC = 21e3;\nvar ClientAuth = 22242;\nvar NWCWalletRequest = 23194;\nvar NWCWalletResponse = 23195;\nvar NostrConnect = 24133;\nvar HTTPAuth = 27235;\nvar Followsets = 3e4;\nvar Genericlists = 30001;\nvar Relaysets = 30002;\nvar Bookmarksets = 30003;\nvar Curationsets = 30004;\nvar ProfileBadges = 30008;\nvar BadgeDefinition = 30009;\nvar Interestsets = 30015;\nvar CreateOrUpdateStall = 30017;\nvar CreateOrUpdateProduct = 30018;\nvar LongFormArticle = 30023;\nvar DraftLong = 30024;\nvar Emojisets = 30030;\nvar Application = 30078;\nvar LiveEvent = 30311;\nvar UserStatuses = 30315;\nvar ClassifiedListing = 30402;\nvar DraftClassifiedListing = 30403;\nvar Date2 = 31922;\nvar Time = 31923;\nvar Calendar = 31924;\nvar CalendarEventRSVP = 31925;\nvar Handlerrecommendation = 31989;\nvar Handlerinformation = 31990;\nvar CommunityDefinition = 34550;\n\n// filter.ts\nfunction matchFilter(filter, event) {\n if (filter.ids && filter.ids.indexOf(event.id) === -1) {\n return false;\n }\n if (filter.kinds && filter.kinds.indexOf(event.kind) === -1) {\n return false;\n }\n if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {\n return false;\n }\n for (let f in filter) {\n if (f[0] === \"#\") {\n let tagName = f.slice(1);\n let values = filter[`#${tagName}`];\n if (values && !event.tags.find(([t, v]) => t === f.slice(1) && values.indexOf(v) !== -1))\n return false;\n }\n }\n if (filter.since && event.created_at < filter.since)\n return false;\n if (filter.until && event.created_at > filter.until)\n return false;\n return true;\n}\nfunction matchFilters(filters, event) {\n for (let i2 = 0; i2 < filters.length; i2++) {\n if (matchFilter(filters[i2], event)) {\n return true;\n }\n }\n return false;\n}\nfunction mergeFilters(...filters) {\n let result = {};\n for (let i2 = 0; i2 < filters.length; i2++) {\n let filter = filters[i2];\n Object.entries(filter).forEach(([property, values]) => {\n if (property === \"kinds\" || property === \"ids\" || property === \"authors\" || property[0] === \"#\") {\n result[property] = result[property] || [];\n for (let v = 0; v < values.length; v++) {\n let value = values[v];\n if (!result[property].includes(value))\n result[property].push(value);\n }\n }\n });\n if (filter.limit && (!result.limit || filter.limit > result.limit))\n result.limit = filter.limit;\n if (filter.until && (!result.until || filter.until > result.until))\n result.until = filter.until;\n if (filter.since && (!result.since || filter.since < result.since))\n result.since = filter.since;\n }\n return result;\n}\nfunction getFilterLimit(filter) {\n if (filter.ids && !filter.ids.length)\n return 0;\n if (filter.kinds && !filter.kinds.length)\n return 0;\n if (filter.authors && !filter.authors.length)\n return 0;\n for (const [key, value] of Object.entries(filter)) {\n if (key[0] === \"#\" && Array.isArray(value) && !value.length)\n return 0;\n }\n return Math.min(\n Math.max(0, filter.limit ?? Infinity),\n filter.ids?.length ?? Infinity,\n filter.authors?.length && filter.kinds?.every((kind) => isReplaceableKind(kind)) ? filter.authors.length * filter.kinds.length : Infinity,\n filter.authors?.length && filter.kinds?.every((kind) => isAddressableKind(kind)) && filter[\"#d\"]?.length ? filter.authors.length * filter.kinds.length * filter[\"#d\"].length : Infinity\n );\n}\n\n// fakejson.ts\nvar fakejson_exports = {};\n__export(fakejson_exports, {\n getHex64: () => getHex64,\n getInt: () => getInt,\n getSubscriptionId: () => getSubscriptionId,\n matchEventId: () => matchEventId,\n matchEventKind: () => matchEventKind,\n matchEventPubkey: () => matchEventPubkey\n});\nfunction getHex64(json, field) {\n let len = field.length + 3;\n let idx = json.indexOf(`\"${field}\":`) + len;\n let s = json.slice(idx).indexOf(`\"`) + idx + 1;\n return json.slice(s, s + 64);\n}\nfunction getInt(json, field) {\n let len = field.length;\n let idx = json.indexOf(`\"${field}\":`) + len + 3;\n let sliced = json.slice(idx);\n let end = Math.min(sliced.indexOf(\",\"), sliced.indexOf(\"}\"));\n return parseInt(sliced.slice(0, end), 10);\n}\nfunction getSubscriptionId(json) {\n let idx = json.slice(0, 22).indexOf(`\"EVENT\"`);\n if (idx === -1)\n return null;\n let pstart = json.slice(idx + 7 + 1).indexOf(`\"`);\n if (pstart === -1)\n return null;\n let start = idx + 7 + 1 + pstart;\n let pend = json.slice(start + 1, 80).indexOf(`\"`);\n if (pend === -1)\n return null;\n let end = start + 1 + pend;\n return json.slice(start + 1, end);\n}\nfunction matchEventId(json, id) {\n return id === getHex64(json, \"id\");\n}\nfunction matchEventPubkey(json, pubkey) {\n return pubkey === getHex64(json, \"pubkey\");\n}\nfunction matchEventKind(json, kind) {\n return kind === getInt(json, \"kind\");\n}\n\n// nip42.ts\nvar nip42_exports = {};\n__export(nip42_exports, {\n makeAuthEvent: () => makeAuthEvent\n});\nfunction makeAuthEvent(relayURL, challenge) {\n return {\n kind: ClientAuth,\n created_at: Math.floor(Date.now() / 1e3),\n tags: [\n [\"relay\", relayURL],\n [\"challenge\", challenge]\n ],\n content: \"\"\n };\n}\n\n// helpers.ts\nasync function yieldThread() {\n return new Promise((resolve) => {\n const ch = new MessageChannel();\n const handler = () => {\n ch.port1.removeEventListener(\"message\", handler);\n resolve();\n };\n ch.port1.addEventListener(\"message\", handler);\n ch.port2.postMessage(0);\n ch.port1.start();\n });\n}\nvar alwaysTrue = (t) => {\n t[verifiedSymbol] = true;\n return true;\n};\n\n// abstract-relay.ts\nvar SendingOnClosedConnection = class extends Error {\n constructor(message, relay) {\n super(`Tried to send message '${message} on a closed connection to ${relay}.`);\n this.name = \"SendingOnClosedConnection\";\n }\n};\nvar AbstractRelay = class {\n url;\n _connected = false;\n onclose = null;\n onnotice = (msg) => console.debug(`NOTICE from ${this.url}: ${msg}`);\n baseEoseTimeout = 4400;\n connectionTimeout = 4400;\n publishTimeout = 4400;\n pingFrequency = 2e4;\n pingTimeout = 2e4;\n openSubs = /* @__PURE__ */ new Map();\n enablePing;\n connectionTimeoutHandle;\n connectionPromise;\n openCountRequests = /* @__PURE__ */ new Map();\n openEventPublishes = /* @__PURE__ */ new Map();\n ws;\n incomingMessageQueue = new Queue();\n queueRunning = false;\n challenge;\n authPromise;\n serial = 0;\n verifyEvent;\n _WebSocket;\n constructor(url, opts) {\n this.url = normalizeURL(url);\n this.verifyEvent = opts.verifyEvent;\n this._WebSocket = opts.websocketImplementation || WebSocket;\n this.enablePing = opts.enablePing;\n }\n static async connect(url, opts) {\n const relay = new AbstractRelay(url, opts);\n await relay.connect();\n return relay;\n }\n closeAllSubscriptions(reason) {\n for (let [_, sub] of this.openSubs) {\n sub.close(reason);\n }\n this.openSubs.clear();\n for (let [_, ep] of this.openEventPublishes) {\n ep.reject(new Error(reason));\n }\n this.openEventPublishes.clear();\n for (let [_, cr] of this.openCountRequests) {\n cr.reject(new Error(reason));\n }\n this.openCountRequests.clear();\n }\n get connected() {\n return this._connected;\n }\n async connect() {\n if (this.connectionPromise)\n return this.connectionPromise;\n this.challenge = void 0;\n this.authPromise = void 0;\n this.connectionPromise = new Promise((resolve, reject) => {\n this.connectionTimeoutHandle = setTimeout(() => {\n reject(\"connection timed out\");\n this.connectionPromise = void 0;\n this.onclose?.();\n this.closeAllSubscriptions(\"relay connection timed out\");\n }, this.connectionTimeout);\n try {\n this.ws = new this._WebSocket(this.url);\n } catch (err) {\n clearTimeout(this.connectionTimeoutHandle);\n reject(err);\n return;\n }\n this.ws.onopen = () => {\n clearTimeout(this.connectionTimeoutHandle);\n this._connected = true;\n if (this.enablePing) {\n this.pingpong();\n }\n resolve();\n };\n this.ws.onerror = (ev) => {\n clearTimeout(this.connectionTimeoutHandle);\n reject(ev.message || \"websocket error\");\n this._connected = false;\n this.connectionPromise = void 0;\n this.onclose?.();\n this.closeAllSubscriptions(\"relay connection errored\");\n };\n this.ws.onclose = (ev) => {\n clearTimeout(this.connectionTimeoutHandle);\n reject(ev.message || \"websocket closed\");\n this._connected = false;\n this.connectionPromise = void 0;\n this.onclose?.();\n this.closeAllSubscriptions(\"relay connection closed\");\n };\n this.ws.onmessage = this._onmessage.bind(this);\n });\n return this.connectionPromise;\n }\n async waitForPingPong() {\n return new Promise((res, err) => {\n ;\n this.ws && this.ws.on && this.ws.on(\"pong\", () => res(true)) || err(\"ws can't listen for pong\");\n this.ws && this.ws.ping && this.ws.ping();\n });\n }\n async waitForDummyReq() {\n return new Promise((resolve, _) => {\n const sub = this.subscribe([{ ids: [\"a\".repeat(64)] }], {\n oneose: () => {\n sub.close();\n resolve(true);\n },\n eoseTimeout: this.pingTimeout + 1e3\n });\n });\n }\n async pingpong() {\n if (this.ws?.readyState === 1) {\n const result = await Promise.any([\n this.ws && this.ws.ping && this.ws.on ? this.waitForPingPong() : this.waitForDummyReq(),\n new Promise((res) => setTimeout(() => res(false), this.pingTimeout))\n ]);\n if (result) {\n setTimeout(() => this.pingpong(), this.pingFrequency);\n } else {\n this.closeAllSubscriptions(\"pingpong timed out\");\n this._connected = false;\n this.onclose?.();\n this.ws?.close();\n }\n }\n }\n async runQueue() {\n this.queueRunning = true;\n while (true) {\n if (false === this.handleNext()) {\n break;\n }\n await yieldThread();\n }\n this.queueRunning = false;\n }\n handleNext() {\n const json = this.incomingMessageQueue.dequeue();\n if (!json) {\n return false;\n }\n const subid = getSubscriptionId(json);\n if (subid) {\n const so = this.openSubs.get(subid);\n if (!so) {\n return;\n }\n const id = getHex64(json, \"id\");\n const alreadyHave = so.alreadyHaveEvent?.(id);\n so.receivedEvent?.(this, id);\n if (alreadyHave) {\n return;\n }\n }\n try {\n let data = JSON.parse(json);\n switch (data[0]) {\n case \"EVENT\": {\n const so = this.openSubs.get(data[1]);\n const event = data[2];\n if (this.verifyEvent(event) && matchFilters(so.filters, event)) {\n so.onevent(event);\n }\n return;\n }\n case \"COUNT\": {\n const id = data[1];\n const payload = data[2];\n const cr = this.openCountRequests.get(id);\n if (cr) {\n cr.resolve(payload.count);\n this.openCountRequests.delete(id);\n }\n return;\n }\n case \"EOSE\": {\n const so = this.openSubs.get(data[1]);\n if (!so)\n return;\n so.receivedEose();\n return;\n }\n case \"OK\": {\n const id = data[1];\n const ok = data[2];\n const reason = data[3];\n const ep = this.openEventPublishes.get(id);\n if (ep) {\n clearTimeout(ep.timeout);\n if (ok)\n ep.resolve(reason);\n else\n ep.reject(new Error(reason));\n this.openEventPublishes.delete(id);\n }\n return;\n }\n case \"CLOSED\": {\n const id = data[1];\n const so = this.openSubs.get(id);\n if (!so)\n return;\n so.closed = true;\n so.close(data[2]);\n return;\n }\n case \"NOTICE\":\n this.onnotice(data[1]);\n return;\n case \"AUTH\": {\n this.challenge = data[1];\n return;\n }\n }\n } catch (err) {\n return;\n }\n }\n async send(message) {\n if (!this.connectionPromise)\n throw new SendingOnClosedConnection(message, this.url);\n this.connectionPromise.then(() => {\n this.ws?.send(message);\n });\n }\n async auth(signAuthEvent) {\n const challenge = this.challenge;\n if (!challenge)\n throw new Error(\"can't perform auth, no challenge was received\");\n if (this.authPromise)\n return this.authPromise;\n this.authPromise = new Promise(async (resolve, reject) => {\n try {\n let evt = await signAuthEvent(makeAuthEvent(this.url, challenge));\n let timeout = setTimeout(() => {\n let ep = this.openEventPublishes.get(evt.id);\n if (ep) {\n ep.reject(new Error(\"auth timed out\"));\n this.openEventPublishes.delete(evt.id);\n }\n }, this.publishTimeout);\n this.openEventPublishes.set(evt.id, { resolve, reject, timeout });\n this.send('[\"AUTH\",' + JSON.stringify(evt) + \"]\");\n } catch (err) {\n console.warn(\"subscribe auth function failed:\", err);\n }\n });\n return this.authPromise;\n }\n async publish(event) {\n const ret = new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n const ep = this.openEventPublishes.get(event.id);\n if (ep) {\n ep.reject(new Error(\"publish timed out\"));\n this.openEventPublishes.delete(event.id);\n }\n }, this.publishTimeout);\n this.openEventPublishes.set(event.id, { resolve, reject, timeout });\n });\n this.send('[\"EVENT\",' + JSON.stringify(event) + \"]\");\n return ret;\n }\n async count(filters, params) {\n this.serial++;\n const id = params?.id || \"count:\" + this.serial;\n const ret = new Promise((resolve, reject) => {\n this.openCountRequests.set(id, { resolve, reject });\n });\n this.send('[\"COUNT\",\"' + id + '\",' + JSON.stringify(filters).substring(1));\n return ret;\n }\n subscribe(filters, params) {\n const subscription = this.prepareSubscription(filters, params);\n subscription.fire();\n return subscription;\n }\n prepareSubscription(filters, params) {\n this.serial++;\n const id = params.id || (params.label ? params.label + \":\" : \"sub:\") + this.serial;\n const subscription = new Subscription(this, id, filters, params);\n this.openSubs.set(id, subscription);\n return subscription;\n }\n close() {\n this.closeAllSubscriptions(\"relay connection closed by us\");\n this._connected = false;\n this.onclose?.();\n this.ws?.close();\n }\n _onmessage(ev) {\n this.incomingMessageQueue.enqueue(ev.data);\n if (!this.queueRunning) {\n this.runQueue();\n }\n }\n};\nvar Subscription = class {\n relay;\n id;\n closed = false;\n eosed = false;\n filters;\n alreadyHaveEvent;\n receivedEvent;\n onevent;\n oneose;\n onclose;\n eoseTimeout;\n eoseTimeoutHandle;\n constructor(relay, id, filters, params) {\n this.relay = relay;\n this.filters = filters;\n this.id = id;\n this.alreadyHaveEvent = params.alreadyHaveEvent;\n this.receivedEvent = params.receivedEvent;\n this.eoseTimeout = params.eoseTimeout || relay.baseEoseTimeout;\n this.oneose = params.oneose;\n this.onclose = params.onclose;\n this.onevent = params.onevent || ((event) => {\n console.warn(\n `onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`,\n event\n );\n });\n }\n fire() {\n this.relay.send('[\"REQ\",\"' + this.id + '\",' + JSON.stringify(this.filters).substring(1));\n this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout);\n }\n receivedEose() {\n if (this.eosed)\n return;\n clearTimeout(this.eoseTimeoutHandle);\n this.eosed = true;\n this.oneose?.();\n }\n close(reason = \"closed by caller\") {\n if (!this.closed && this.relay.connected) {\n try {\n this.relay.send('[\"CLOSE\",' + JSON.stringify(this.id) + \"]\");\n } catch (err) {\n if (err instanceof SendingOnClosedConnection) {\n } else {\n throw err;\n }\n }\n this.closed = true;\n }\n this.relay.openSubs.delete(this.id);\n this.onclose?.(reason);\n }\n};\n\n// relay.ts\nvar _WebSocket;\ntry {\n _WebSocket = WebSocket;\n} catch {\n}\nvar Relay = class extends AbstractRelay {\n constructor(url) {\n super(url, { verifyEvent, websocketImplementation: _WebSocket });\n }\n static async connect(url) {\n const relay = new Relay(url);\n await relay.connect();\n return relay;\n }\n};\n\n// abstract-pool.ts\nvar AbstractSimplePool = class {\n relays = /* @__PURE__ */ new Map();\n seenOn = /* @__PURE__ */ new Map();\n trackRelays = false;\n verifyEvent;\n enablePing;\n trustedRelayURLs = /* @__PURE__ */ new Set();\n _WebSocket;\n constructor(opts) {\n this.verifyEvent = opts.verifyEvent;\n this._WebSocket = opts.websocketImplementation;\n this.enablePing = opts.enablePing;\n }\n async ensureRelay(url, params) {\n url = normalizeURL(url);\n let relay = this.relays.get(url);\n if (!relay) {\n relay = new AbstractRelay(url, {\n verifyEvent: this.trustedRelayURLs.has(url) ? alwaysTrue : this.verifyEvent,\n websocketImplementation: this._WebSocket,\n enablePing: this.enablePing\n });\n relay.onclose = () => {\n this.relays.delete(url);\n };\n if (params?.connectionTimeout)\n relay.connectionTimeout = params.connectionTimeout;\n this.relays.set(url, relay);\n }\n await relay.connect();\n return relay;\n }\n close(relays) {\n relays.map(normalizeURL).forEach((url) => {\n this.relays.get(url)?.close();\n this.relays.delete(url);\n });\n }\n subscribe(relays, filter, params) {\n params.onauth = params.onauth || params.doauth;\n const request = [];\n for (let i2 = 0; i2 < relays.length; i2++) {\n const url = normalizeURL(relays[i2]);\n if (!request.find((r) => r.url === url)) {\n request.push({ url, filter });\n }\n }\n return this.subscribeMap(request, params);\n }\n subscribeMany(relays, filter, params) {\n params.onauth = params.onauth || params.doauth;\n const request = [];\n const uniqUrls = [];\n for (let i2 = 0; i2 < relays.length; i2++) {\n const url = normalizeURL(relays[i2]);\n if (uniqUrls.indexOf(url) === -1) {\n uniqUrls.push(url);\n request.push({ url, filter });\n }\n }\n return this.subscribeMap(request, params);\n }\n subscribeMap(requests, params) {\n params.onauth = params.onauth || params.doauth;\n const grouped = /* @__PURE__ */ new Map();\n for (const req of requests) {\n const { url, filter } = req;\n if (!grouped.has(url))\n grouped.set(url, []);\n grouped.get(url).push(filter);\n }\n const groupedRequests = Array.from(grouped.entries()).map(([url, filters]) => ({ url, filters }));\n if (this.trackRelays) {\n params.receivedEvent = (relay, id) => {\n let set = this.seenOn.get(id);\n if (!set) {\n set = /* @__PURE__ */ new Set();\n this.seenOn.set(id, set);\n }\n set.add(relay);\n };\n }\n const _knownIds = /* @__PURE__ */ new Set();\n const subs = [];\n const eosesReceived = [];\n let handleEose = (i2) => {\n if (eosesReceived[i2])\n return;\n eosesReceived[i2] = true;\n if (eosesReceived.filter((a) => a).length === requests.length) {\n params.oneose?.();\n handleEose = () => {\n };\n }\n };\n const closesReceived = [];\n let handleClose = (i2, reason) => {\n if (closesReceived[i2])\n return;\n handleEose(i2);\n closesReceived[i2] = reason;\n if (closesReceived.filter((a) => a).length === requests.length) {\n params.onclose?.(closesReceived);\n handleClose = () => {\n };\n }\n };\n const localAlreadyHaveEventHandler = (id) => {\n if (params.alreadyHaveEvent?.(id)) {\n return true;\n }\n const have = _knownIds.has(id);\n _knownIds.add(id);\n return have;\n };\n const allOpened = Promise.all(\n groupedRequests.map(async ({ url, filters }, i2) => {\n let relay;\n try {\n relay = await this.ensureRelay(url, {\n connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : void 0\n });\n } catch (err) {\n handleClose(i2, err?.message || String(err));\n return;\n }\n let subscription = relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i2),\n onclose: (reason) => {\n if (reason.startsWith(\"auth-required: \") && params.onauth) {\n relay.auth(params.onauth).then(() => {\n relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i2),\n onclose: (reason2) => {\n handleClose(i2, reason2);\n },\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait\n });\n }).catch((err) => {\n handleClose(i2, `auth was required and attempted, but failed with: ${err}`);\n });\n } else {\n handleClose(i2, reason);\n }\n },\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait\n });\n subs.push(subscription);\n })\n );\n return {\n async close(reason) {\n await allOpened;\n subs.forEach((sub) => {\n sub.close(reason);\n });\n }\n };\n }\n subscribeEose(relays, filter, params) {\n params.onauth = params.onauth || params.doauth;\n const subcloser = this.subscribe(relays, filter, {\n ...params,\n oneose() {\n subcloser.close(\"closed automatically on eose\");\n }\n });\n return subcloser;\n }\n subscribeManyEose(relays, filter, params) {\n params.onauth = params.onauth || params.doauth;\n const subcloser = this.subscribeMany(relays, filter, {\n ...params,\n oneose() {\n subcloser.close(\"closed automatically on eose\");\n }\n });\n return subcloser;\n }\n async querySync(relays, filter, params) {\n return new Promise(async (resolve) => {\n const events = [];\n this.subscribeEose(relays, filter, {\n ...params,\n onevent(event) {\n events.push(event);\n },\n onclose(_) {\n resolve(events);\n }\n });\n });\n }\n async get(relays, filter, params) {\n filter.limit = 1;\n const events = await this.querySync(relays, filter, params);\n events.sort((a, b) => b.created_at - a.created_at);\n return events[0] || null;\n }\n publish(relays, event, options) {\n return relays.map(normalizeURL).map(async (url, i2, arr) => {\n if (arr.indexOf(url) !== i2) {\n return Promise.reject(\"duplicate url\");\n }\n let r = await this.ensureRelay(url);\n return r.publish(event).catch(async (err) => {\n if (err instanceof Error && err.message.startsWith(\"auth-required: \") && options?.onauth) {\n await r.auth(options.onauth);\n return r.publish(event);\n }\n throw err;\n }).then((reason) => {\n if (this.trackRelays) {\n let set = this.seenOn.get(event.id);\n if (!set) {\n set = /* @__PURE__ */ new Set();\n this.seenOn.set(event.id, set);\n }\n set.add(r);\n }\n return reason;\n });\n });\n }\n listConnectionStatus() {\n const map = /* @__PURE__ */ new Map();\n this.relays.forEach((relay, url) => map.set(url, relay.connected));\n return map;\n }\n destroy() {\n this.relays.forEach((conn) => conn.close());\n this.relays = /* @__PURE__ */ new Map();\n }\n};\n\n// pool.ts\nvar _WebSocket2;\ntry {\n _WebSocket2 = WebSocket;\n} catch {\n}\nvar SimplePool = class extends AbstractSimplePool {\n constructor(options) {\n super({ verifyEvent, websocketImplementation: _WebSocket2, ...options });\n }\n};\n\n// nip19.ts\nvar nip19_exports = {};\n__export(nip19_exports, {\n BECH32_REGEX: () => BECH32_REGEX,\n Bech32MaxSize: () => Bech32MaxSize,\n NostrTypeGuard: () => NostrTypeGuard,\n decode: () => decode,\n decodeNostrURI: () => decodeNostrURI,\n encodeBytes: () => encodeBytes,\n naddrEncode: () => naddrEncode,\n neventEncode: () => neventEncode,\n noteEncode: () => noteEncode,\n nprofileEncode: () => nprofileEncode,\n npubEncode: () => npubEncode,\n nsecEncode: () => nsecEncode\n});\nimport { bytesToHex as bytesToHex3, concatBytes, hexToBytes as hexToBytes2 } from \"@noble/hashes/utils\";\nimport { bech32 } from \"@scure/base\";\nvar NostrTypeGuard = {\n isNProfile: (value) => /^nprofile1[a-z\\d]+$/.test(value || \"\"),\n isNEvent: (value) => /^nevent1[a-z\\d]+$/.test(value || \"\"),\n isNAddr: (value) => /^naddr1[a-z\\d]+$/.test(value || \"\"),\n isNSec: (value) => /^nsec1[a-z\\d]{58}$/.test(value || \"\"),\n isNPub: (value) => /^npub1[a-z\\d]{58}$/.test(value || \"\"),\n isNote: (value) => /^note1[a-z\\d]+$/.test(value || \"\"),\n isNcryptsec: (value) => /^ncryptsec1[a-z\\d]+$/.test(value || \"\")\n};\nvar Bech32MaxSize = 5e3;\nvar BECH32_REGEX = /[\\x21-\\x7E]{1,83}1[023456789acdefghjklmnpqrstuvwxyz]{6,}/;\nfunction integerToUint8Array(number) {\n const uint8Array = new Uint8Array(4);\n uint8Array[0] = number >> 24 & 255;\n uint8Array[1] = number >> 16 & 255;\n uint8Array[2] = number >> 8 & 255;\n uint8Array[3] = number & 255;\n return uint8Array;\n}\nfunction decodeNostrURI(nip19code) {\n try {\n if (nip19code.startsWith(\"nostr:\"))\n nip19code = nip19code.substring(6);\n return decode(nip19code);\n } catch (_err) {\n return { type: \"invalid\", data: null };\n }\n}\nfunction decode(code) {\n let { prefix, words } = bech32.decode(code, Bech32MaxSize);\n let data = new Uint8Array(bech32.fromWords(words));\n switch (prefix) {\n case \"nprofile\": {\n let tlv = parseTLV(data);\n if (!tlv[0]?.[0])\n throw new Error(\"missing TLV 0 for nprofile\");\n if (tlv[0][0].length !== 32)\n throw new Error(\"TLV 0 should be 32 bytes\");\n return {\n type: \"nprofile\",\n data: {\n pubkey: bytesToHex3(tlv[0][0]),\n relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []\n }\n };\n }\n case \"nevent\": {\n let tlv = parseTLV(data);\n if (!tlv[0]?.[0])\n throw new Error(\"missing TLV 0 for nevent\");\n if (tlv[0][0].length !== 32)\n throw new Error(\"TLV 0 should be 32 bytes\");\n if (tlv[2] && tlv[2][0].length !== 32)\n throw new Error(\"TLV 2 should be 32 bytes\");\n if (tlv[3] && tlv[3][0].length !== 4)\n throw new Error(\"TLV 3 should be 4 bytes\");\n return {\n type: \"nevent\",\n data: {\n id: bytesToHex3(tlv[0][0]),\n relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : [],\n author: tlv[2]?.[0] ? bytesToHex3(tlv[2][0]) : void 0,\n kind: tlv[3]?.[0] ? parseInt(bytesToHex3(tlv[3][0]), 16) : void 0\n }\n };\n }\n case \"naddr\": {\n let tlv = parseTLV(data);\n if (!tlv[0]?.[0])\n throw new Error(\"missing TLV 0 for naddr\");\n if (!tlv[2]?.[0])\n throw new Error(\"missing TLV 2 for naddr\");\n if (tlv[2][0].length !== 32)\n throw new Error(\"TLV 2 should be 32 bytes\");\n if (!tlv[3]?.[0])\n throw new Error(\"missing TLV 3 for naddr\");\n if (tlv[3][0].length !== 4)\n throw new Error(\"TLV 3 should be 4 bytes\");\n return {\n type: \"naddr\",\n data: {\n identifier: utf8Decoder.decode(tlv[0][0]),\n pubkey: bytesToHex3(tlv[2][0]),\n kind: parseInt(bytesToHex3(tlv[3][0]), 16),\n relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []\n }\n };\n }\n case \"nsec\":\n return { type: prefix, data };\n case \"npub\":\n case \"note\":\n return { type: prefix, data: bytesToHex3(data) };\n default:\n throw new Error(`unknown prefix ${prefix}`);\n }\n}\nfunction parseTLV(data) {\n let result = {};\n let rest = data;\n while (rest.length > 0) {\n let t = rest[0];\n let l = rest[1];\n let v = rest.slice(2, 2 + l);\n rest = rest.slice(2 + l);\n if (v.length < l)\n throw new Error(`not enough data to read on TLV ${t}`);\n result[t] = result[t] || [];\n result[t].push(v);\n }\n return result;\n}\nfunction nsecEncode(key) {\n return encodeBytes(\"nsec\", key);\n}\nfunction npubEncode(hex) {\n return encodeBytes(\"npub\", hexToBytes2(hex));\n}\nfunction noteEncode(hex) {\n return encodeBytes(\"note\", hexToBytes2(hex));\n}\nfunction encodeBech32(prefix, data) {\n let words = bech32.toWords(data);\n return bech32.encode(prefix, words, Bech32MaxSize);\n}\nfunction encodeBytes(prefix, bytes) {\n return encodeBech32(prefix, bytes);\n}\nfunction nprofileEncode(profile) {\n let data = encodeTLV({\n 0: [hexToBytes2(profile.pubkey)],\n 1: (profile.relays || []).map((url) => utf8Encoder.encode(url))\n });\n return encodeBech32(\"nprofile\", data);\n}\nfunction neventEncode(event) {\n let kindArray;\n if (event.kind !== void 0) {\n kindArray = integerToUint8Array(event.kind);\n }\n let data = encodeTLV({\n 0: [hexToBytes2(event.id)],\n 1: (event.relays || []).map((url) => utf8Encoder.encode(url)),\n 2: event.author ? [hexToBytes2(event.author)] : [],\n 3: kindArray ? [new Uint8Array(kindArray)] : []\n });\n return encodeBech32(\"nevent\", data);\n}\nfunction naddrEncode(addr) {\n let kind = new ArrayBuffer(4);\n new DataView(kind).setUint32(0, addr.kind, false);\n let data = encodeTLV({\n 0: [utf8Encoder.encode(addr.identifier)],\n 1: (addr.relays || []).map((url) => utf8Encoder.encode(url)),\n 2: [hexToBytes2(addr.pubkey)],\n 3: [new Uint8Array(kind)]\n });\n return encodeBech32(\"naddr\", data);\n}\nfunction encodeTLV(tlv) {\n let entries = [];\n Object.entries(tlv).reverse().forEach(([t, vs]) => {\n vs.forEach((v) => {\n let entry = new Uint8Array(v.length + 2);\n entry.set([parseInt(t)], 0);\n entry.set([v.length], 1);\n entry.set(v, 2);\n entries.push(entry);\n });\n });\n return concatBytes(...entries);\n}\n\n// references.ts\nvar mentionRegex = /\\bnostr:((note|npub|naddr|nevent|nprofile)1\\w+)\\b|#\\[(\\d+)\\]/g;\nfunction parseReferences(evt) {\n let references = [];\n for (let ref of evt.content.matchAll(mentionRegex)) {\n if (ref[2]) {\n try {\n let { type, data } = decode(ref[1]);\n switch (type) {\n case \"npub\": {\n references.push({\n text: ref[0],\n profile: { pubkey: data, relays: [] }\n });\n break;\n }\n case \"nprofile\": {\n references.push({\n text: ref[0],\n profile: data\n });\n break;\n }\n case \"note\": {\n references.push({\n text: ref[0],\n event: { id: data, relays: [] }\n });\n break;\n }\n case \"nevent\": {\n references.push({\n text: ref[0],\n event: data\n });\n break;\n }\n case \"naddr\": {\n references.push({\n text: ref[0],\n address: data\n });\n break;\n }\n }\n } catch (err) {\n }\n } else if (ref[3]) {\n let idx = parseInt(ref[3], 10);\n let tag = evt.tags[idx];\n if (!tag)\n continue;\n switch (tag[0]) {\n case \"p\": {\n references.push({\n text: ref[0],\n profile: { pubkey: tag[1], relays: tag[2] ? [tag[2]] : [] }\n });\n break;\n }\n case \"e\": {\n references.push({\n text: ref[0],\n event: { id: tag[1], relays: tag[2] ? [tag[2]] : [] }\n });\n break;\n }\n case \"a\": {\n try {\n let [kind, pubkey, identifier] = tag[1].split(\":\");\n references.push({\n text: ref[0],\n address: {\n identifier,\n pubkey,\n kind: parseInt(kind, 10),\n relays: tag[2] ? [tag[2]] : []\n }\n });\n } catch (err) {\n }\n break;\n }\n }\n }\n }\n return references;\n}\n\n// nip04.ts\nvar nip04_exports = {};\n__export(nip04_exports, {\n decrypt: () => decrypt,\n encrypt: () => encrypt\n});\nimport { bytesToHex as bytesToHex4, randomBytes } from \"@noble/hashes/utils\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { cbc } from \"@noble/ciphers/aes\";\nimport { base64 } from \"@scure/base\";\nfunction encrypt(secretKey, pubkey, text) {\n const privkey = secretKey instanceof Uint8Array ? bytesToHex4(secretKey) : secretKey;\n const key = secp256k1.getSharedSecret(privkey, \"02\" + pubkey);\n const normalizedKey = getNormalizedX(key);\n let iv = Uint8Array.from(randomBytes(16));\n let plaintext = utf8Encoder.encode(text);\n let ciphertext = cbc(normalizedKey, iv).encrypt(plaintext);\n let ctb64 = base64.encode(new Uint8Array(ciphertext));\n let ivb64 = base64.encode(new Uint8Array(iv.buffer));\n return `${ctb64}?iv=${ivb64}`;\n}\nfunction decrypt(secretKey, pubkey, data) {\n const privkey = secretKey instanceof Uint8Array ? bytesToHex4(secretKey) : secretKey;\n let [ctb64, ivb64] = data.split(\"?iv=\");\n let key = secp256k1.getSharedSecret(privkey, \"02\" + pubkey);\n let normalizedKey = getNormalizedX(key);\n let iv = base64.decode(ivb64);\n let ciphertext = base64.decode(ctb64);\n let plaintext = cbc(normalizedKey, iv).decrypt(ciphertext);\n return utf8Decoder.decode(plaintext);\n}\nfunction getNormalizedX(key) {\n return key.slice(1, 33);\n}\n\n// nip05.ts\nvar nip05_exports = {};\n__export(nip05_exports, {\n NIP05_REGEX: () => NIP05_REGEX,\n isNip05: () => isNip05,\n isValid: () => isValid,\n queryProfile: () => queryProfile,\n searchDomain: () => searchDomain,\n useFetchImplementation: () => useFetchImplementation\n});\nvar NIP05_REGEX = /^(?:([\\w.+-]+)@)?([\\w_-]+(\\.[\\w_-]+)+)$/;\nvar isNip05 = (value) => NIP05_REGEX.test(value || \"\");\nvar _fetch;\ntry {\n _fetch = fetch;\n} catch (_) {\n null;\n}\nfunction useFetchImplementation(fetchImplementation) {\n _fetch = fetchImplementation;\n}\nasync function searchDomain(domain, query = \"\") {\n try {\n const url = `https://${domain}/.well-known/nostr.json?name=${query}`;\n const res = await _fetch(url, { redirect: \"manual\" });\n if (res.status !== 200) {\n throw Error(\"Wrong response code\");\n }\n const json = await res.json();\n return json.names;\n } catch (_) {\n return {};\n }\n}\nasync function queryProfile(fullname) {\n const match = fullname.match(NIP05_REGEX);\n if (!match)\n return null;\n const [, name = \"_\", domain] = match;\n try {\n const url = `https://${domain}/.well-known/nostr.json?name=${name}`;\n const res = await _fetch(url, { redirect: \"manual\" });\n if (res.status !== 200) {\n throw Error(\"Wrong response code\");\n }\n const json = await res.json();\n const pubkey = json.names[name];\n return pubkey ? { pubkey, relays: json.relays?.[pubkey] } : null;\n } catch (_e) {\n return null;\n }\n}\nasync function isValid(pubkey, nip05) {\n const res = await queryProfile(nip05);\n return res ? res.pubkey === pubkey : false;\n}\n\n// nip10.ts\nvar nip10_exports = {};\n__export(nip10_exports, {\n parse: () => parse\n});\nfunction parse(event) {\n const result = {\n reply: void 0,\n root: void 0,\n mentions: [],\n profiles: [],\n quotes: []\n };\n let maybeParent;\n let maybeRoot;\n for (let i2 = event.tags.length - 1; i2 >= 0; i2--) {\n const tag = event.tags[i2];\n if (tag[0] === \"e\" && tag[1]) {\n const [_, eTagEventId, eTagRelayUrl, eTagMarker, eTagAuthor] = tag;\n const eventPointer = {\n id: eTagEventId,\n relays: eTagRelayUrl ? [eTagRelayUrl] : [],\n author: eTagAuthor\n };\n if (eTagMarker === \"root\") {\n result.root = eventPointer;\n continue;\n }\n if (eTagMarker === \"reply\") {\n result.reply = eventPointer;\n continue;\n }\n if (eTagMarker === \"mention\") {\n result.mentions.push(eventPointer);\n continue;\n }\n if (!maybeParent) {\n maybeParent = eventPointer;\n } else {\n maybeRoot = eventPointer;\n }\n result.mentions.push(eventPointer);\n continue;\n }\n if (tag[0] === \"q\" && tag[1]) {\n const [_, eTagEventId, eTagRelayUrl] = tag;\n result.quotes.push({\n id: eTagEventId,\n relays: eTagRelayUrl ? [eTagRelayUrl] : []\n });\n }\n if (tag[0] === \"p\" && tag[1]) {\n result.profiles.push({\n pubkey: tag[1],\n relays: tag[2] ? [tag[2]] : []\n });\n continue;\n }\n }\n if (!result.root) {\n result.root = maybeRoot || maybeParent || result.reply;\n }\n if (!result.reply) {\n result.reply = maybeParent || result.root;\n }\n ;\n [result.reply, result.root].forEach((ref) => {\n if (!ref)\n return;\n let idx = result.mentions.indexOf(ref);\n if (idx !== -1) {\n result.mentions.splice(idx, 1);\n }\n if (ref.author) {\n let author = result.profiles.find((p) => p.pubkey === ref.author);\n if (author && author.relays) {\n if (!ref.relays) {\n ref.relays = [];\n }\n author.relays.forEach((url) => {\n if (ref.relays?.indexOf(url) === -1)\n ref.relays.push(url);\n });\n author.relays = ref.relays;\n }\n }\n });\n result.mentions.forEach((ref) => {\n if (ref.author) {\n let author = result.profiles.find((p) => p.pubkey === ref.author);\n if (author && author.relays) {\n if (!ref.relays) {\n ref.relays = [];\n }\n author.relays.forEach((url) => {\n if (ref.relays.indexOf(url) === -1)\n ref.relays.push(url);\n });\n author.relays = ref.relays;\n }\n }\n });\n return result;\n}\n\n// nip11.ts\nvar nip11_exports = {};\n__export(nip11_exports, {\n fetchRelayInformation: () => fetchRelayInformation,\n useFetchImplementation: () => useFetchImplementation2\n});\nvar _fetch2;\ntry {\n _fetch2 = fetch;\n} catch {\n}\nfunction useFetchImplementation2(fetchImplementation) {\n _fetch2 = fetchImplementation;\n}\nasync function fetchRelayInformation(url) {\n return await (await fetch(url.replace(\"ws://\", \"http://\").replace(\"wss://\", \"https://\"), {\n headers: { Accept: \"application/nostr+json\" }\n })).json();\n}\n\n// nip13.ts\nvar nip13_exports = {};\n__export(nip13_exports, {\n fastEventHash: () => fastEventHash,\n getPow: () => getPow,\n minePow: () => minePow\n});\nimport { bytesToHex as bytesToHex5 } from \"@noble/hashes/utils\";\nimport { sha256 as sha2562 } from \"@noble/hashes/sha256\";\nfunction getPow(hex) {\n let count = 0;\n for (let i2 = 0; i2 < 64; i2 += 8) {\n const nibble = parseInt(hex.substring(i2, i2 + 8), 16);\n if (nibble === 0) {\n count += 32;\n } else {\n count += Math.clz32(nibble);\n break;\n }\n }\n return count;\n}\nfunction minePow(unsigned, difficulty) {\n let count = 0;\n const event = unsigned;\n const tag = [\"nonce\", count.toString(), difficulty.toString()];\n event.tags.push(tag);\n while (true) {\n const now2 = Math.floor(new Date().getTime() / 1e3);\n if (now2 !== event.created_at) {\n count = 0;\n event.created_at = now2;\n }\n tag[1] = (++count).toString();\n event.id = fastEventHash(event);\n if (getPow(event.id) >= difficulty) {\n break;\n }\n }\n return event;\n}\nfunction fastEventHash(evt) {\n return bytesToHex5(\n sha2562(utf8Encoder.encode(JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content])))\n );\n}\n\n// nip17.ts\nvar nip17_exports = {};\n__export(nip17_exports, {\n unwrapEvent: () => unwrapEvent2,\n unwrapManyEvents: () => unwrapManyEvents2,\n wrapEvent: () => wrapEvent2,\n wrapManyEvents: () => wrapManyEvents2\n});\n\n// nip59.ts\nvar nip59_exports = {};\n__export(nip59_exports, {\n createRumor: () => createRumor,\n createSeal: () => createSeal,\n createWrap: () => createWrap,\n unwrapEvent: () => unwrapEvent,\n unwrapManyEvents: () => unwrapManyEvents,\n wrapEvent: () => wrapEvent,\n wrapManyEvents: () => wrapManyEvents\n});\n\n// nip44.ts\nvar nip44_exports = {};\n__export(nip44_exports, {\n decrypt: () => decrypt2,\n encrypt: () => encrypt2,\n getConversationKey: () => getConversationKey,\n v2: () => v2\n});\nimport { chacha20 } from \"@noble/ciphers/chacha\";\nimport { equalBytes } from \"@noble/ciphers/utils\";\nimport { secp256k1 as secp256k12 } from \"@noble/curves/secp256k1\";\nimport { extract as hkdf_extract, expand as hkdf_expand } from \"@noble/hashes/hkdf\";\nimport { hmac } from \"@noble/hashes/hmac\";\nimport { sha256 as sha2563 } from \"@noble/hashes/sha256\";\nimport { concatBytes as concatBytes2, randomBytes as randomBytes2 } from \"@noble/hashes/utils\";\nimport { base64 as base642 } from \"@scure/base\";\nvar minPlaintextSize = 1;\nvar maxPlaintextSize = 65535;\nfunction getConversationKey(privkeyA, pubkeyB) {\n const sharedX = secp256k12.getSharedSecret(privkeyA, \"02\" + pubkeyB).subarray(1, 33);\n return hkdf_extract(sha2563, sharedX, \"nip44-v2\");\n}\nfunction getMessageKeys(conversationKey, nonce) {\n const keys = hkdf_expand(sha2563, conversationKey, nonce, 76);\n return {\n chacha_key: keys.subarray(0, 32),\n chacha_nonce: keys.subarray(32, 44),\n hmac_key: keys.subarray(44, 76)\n };\n}\nfunction calcPaddedLen(len) {\n if (!Number.isSafeInteger(len) || len < 1)\n throw new Error(\"expected positive integer\");\n if (len <= 32)\n return 32;\n const nextPower = 1 << Math.floor(Math.log2(len - 1)) + 1;\n const chunk = nextPower <= 256 ? 32 : nextPower / 8;\n return chunk * (Math.floor((len - 1) / chunk) + 1);\n}\nfunction writeU16BE(num) {\n if (!Number.isSafeInteger(num) || num < minPlaintextSize || num > maxPlaintextSize)\n throw new Error(\"invalid plaintext size: must be between 1 and 65535 bytes\");\n const arr = new Uint8Array(2);\n new DataView(arr.buffer).setUint16(0, num, false);\n return arr;\n}\nfunction pad(plaintext) {\n const unpadded = utf8Encoder.encode(plaintext);\n const unpaddedLen = unpadded.length;\n const prefix = writeU16BE(unpaddedLen);\n const suffix = new Uint8Array(calcPaddedLen(unpaddedLen) - unpaddedLen);\n return concatBytes2(prefix, unpadded, suffix);\n}\nfunction unpad(padded) {\n const unpaddedLen = new DataView(padded.buffer).getUint16(0);\n const unpadded = padded.subarray(2, 2 + unpaddedLen);\n if (unpaddedLen < minPlaintextSize || unpaddedLen > maxPlaintextSize || unpadded.length !== unpaddedLen || padded.length !== 2 + calcPaddedLen(unpaddedLen))\n throw new Error(\"invalid padding\");\n return utf8Decoder.decode(unpadded);\n}\nfunction hmacAad(key, message, aad) {\n if (aad.length !== 32)\n throw new Error(\"AAD associated data must be 32 bytes\");\n const combined = concatBytes2(aad, message);\n return hmac(sha2563, key, combined);\n}\nfunction decodePayload(payload) {\n if (typeof payload !== \"string\")\n throw new Error(\"payload must be a valid string\");\n const plen = payload.length;\n if (plen < 132 || plen > 87472)\n throw new Error(\"invalid payload length: \" + plen);\n if (payload[0] === \"#\")\n throw new Error(\"unknown encryption version\");\n let data;\n try {\n data = base642.decode(payload);\n } catch (error) {\n throw new Error(\"invalid base64: \" + error.message);\n }\n const dlen = data.length;\n if (dlen < 99 || dlen > 65603)\n throw new Error(\"invalid data length: \" + dlen);\n const vers = data[0];\n if (vers !== 2)\n throw new Error(\"unknown encryption version \" + vers);\n return {\n nonce: data.subarray(1, 33),\n ciphertext: data.subarray(33, -32),\n mac: data.subarray(-32)\n };\n}\nfunction encrypt2(plaintext, conversationKey, nonce = randomBytes2(32)) {\n const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce);\n const padded = pad(plaintext);\n const ciphertext = chacha20(chacha_key, chacha_nonce, padded);\n const mac = hmacAad(hmac_key, ciphertext, nonce);\n return base642.encode(concatBytes2(new Uint8Array([2]), nonce, ciphertext, mac));\n}\nfunction decrypt2(payload, conversationKey) {\n const { nonce, ciphertext, mac } = decodePayload(payload);\n const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce);\n const calculatedMac = hmacAad(hmac_key, ciphertext, nonce);\n if (!equalBytes(calculatedMac, mac))\n throw new Error(\"invalid MAC\");\n const padded = chacha20(chacha_key, chacha_nonce, ciphertext);\n return unpad(padded);\n}\nvar v2 = {\n utils: {\n getConversationKey,\n calcPaddedLen\n },\n encrypt: encrypt2,\n decrypt: decrypt2\n};\n\n// nip59.ts\nvar TWO_DAYS = 2 * 24 * 60 * 60;\nvar now = () => Math.round(Date.now() / 1e3);\nvar randomNow = () => Math.round(now() - Math.random() * TWO_DAYS);\nvar nip44ConversationKey = (privateKey, publicKey) => getConversationKey(privateKey, publicKey);\nvar nip44Encrypt = (data, privateKey, publicKey) => encrypt2(JSON.stringify(data), nip44ConversationKey(privateKey, publicKey));\nvar nip44Decrypt = (data, privateKey) => JSON.parse(decrypt2(data.content, nip44ConversationKey(privateKey, data.pubkey)));\nfunction createRumor(event, privateKey) {\n const rumor = {\n created_at: now(),\n content: \"\",\n tags: [],\n ...event,\n pubkey: getPublicKey(privateKey)\n };\n rumor.id = getEventHash(rumor);\n return rumor;\n}\nfunction createSeal(rumor, privateKey, recipientPublicKey) {\n return finalizeEvent(\n {\n kind: Seal,\n content: nip44Encrypt(rumor, privateKey, recipientPublicKey),\n created_at: randomNow(),\n tags: []\n },\n privateKey\n );\n}\nfunction createWrap(seal, recipientPublicKey) {\n const randomKey = generateSecretKey();\n return finalizeEvent(\n {\n kind: GiftWrap,\n content: nip44Encrypt(seal, randomKey, recipientPublicKey),\n created_at: randomNow(),\n tags: [[\"p\", recipientPublicKey]]\n },\n randomKey\n );\n}\nfunction wrapEvent(event, senderPrivateKey, recipientPublicKey) {\n const rumor = createRumor(event, senderPrivateKey);\n const seal = createSeal(rumor, senderPrivateKey, recipientPublicKey);\n return createWrap(seal, recipientPublicKey);\n}\nfunction wrapManyEvents(event, senderPrivateKey, recipientsPublicKeys) {\n if (!recipientsPublicKeys || recipientsPublicKeys.length === 0) {\n throw new Error(\"At least one recipient is required.\");\n }\n const senderPublicKey = getPublicKey(senderPrivateKey);\n const wrappeds = [wrapEvent(event, senderPrivateKey, senderPublicKey)];\n recipientsPublicKeys.forEach((recipientPublicKey) => {\n wrappeds.push(wrapEvent(event, senderPrivateKey, recipientPublicKey));\n });\n return wrappeds;\n}\nfunction unwrapEvent(wrap, recipientPrivateKey) {\n const unwrappedSeal = nip44Decrypt(wrap, recipientPrivateKey);\n return nip44Decrypt(unwrappedSeal, recipientPrivateKey);\n}\nfunction unwrapManyEvents(wrappedEvents, recipientPrivateKey) {\n let unwrappedEvents = [];\n wrappedEvents.forEach((e) => {\n unwrappedEvents.push(unwrapEvent(e, recipientPrivateKey));\n });\n unwrappedEvents.sort((a, b) => a.created_at - b.created_at);\n return unwrappedEvents;\n}\n\n// nip17.ts\nfunction createEvent(recipients, message, conversationTitle, replyTo) {\n const baseEvent = {\n created_at: Math.ceil(Date.now() / 1e3),\n kind: PrivateDirectMessage,\n tags: [],\n content: message\n };\n const recipientsArray = Array.isArray(recipients) ? recipients : [recipients];\n recipientsArray.forEach(({ publicKey, relayUrl }) => {\n baseEvent.tags.push(relayUrl ? [\"p\", publicKey, relayUrl] : [\"p\", publicKey]);\n });\n if (replyTo) {\n baseEvent.tags.push([\"e\", replyTo.eventId, replyTo.relayUrl || \"\", \"reply\"]);\n }\n if (conversationTitle) {\n baseEvent.tags.push([\"subject\", conversationTitle]);\n }\n return baseEvent;\n}\nfunction wrapEvent2(senderPrivateKey, recipient, message, conversationTitle, replyTo) {\n const event = createEvent(recipient, message, conversationTitle, replyTo);\n return wrapEvent(event, senderPrivateKey, recipient.publicKey);\n}\nfunction wrapManyEvents2(senderPrivateKey, recipients, message, conversationTitle, replyTo) {\n if (!recipients || recipients.length === 0) {\n throw new Error(\"At least one recipient is required.\");\n }\n const senderPublicKey = getPublicKey(senderPrivateKey);\n return [{ publicKey: senderPublicKey }, ...recipients].map(\n (recipient) => wrapEvent2(senderPrivateKey, recipient, message, conversationTitle, replyTo)\n );\n}\nvar unwrapEvent2 = unwrapEvent;\nvar unwrapManyEvents2 = unwrapManyEvents;\n\n// nip18.ts\nvar nip18_exports = {};\n__export(nip18_exports, {\n finishRepostEvent: () => finishRepostEvent,\n getRepostedEvent: () => getRepostedEvent,\n getRepostedEventPointer: () => getRepostedEventPointer\n});\nfunction finishRepostEvent(t, reposted, relayUrl, privateKey) {\n let kind;\n const tags = [...t.tags ?? [], [\"e\", reposted.id, relayUrl], [\"p\", reposted.pubkey]];\n if (reposted.kind === ShortTextNote) {\n kind = Repost;\n } else {\n kind = GenericRepost;\n tags.push([\"k\", String(reposted.kind)]);\n }\n return finalizeEvent(\n {\n kind,\n tags,\n content: t.content === \"\" || reposted.tags?.find((tag) => tag[0] === \"-\") ? \"\" : JSON.stringify(reposted),\n created_at: t.created_at\n },\n privateKey\n );\n}\nfunction getRepostedEventPointer(event) {\n if (![Repost, GenericRepost].includes(event.kind)) {\n return void 0;\n }\n let lastETag;\n let lastPTag;\n for (let i2 = event.tags.length - 1; i2 >= 0 && (lastETag === void 0 || lastPTag === void 0); i2--) {\n const tag = event.tags[i2];\n if (tag.length >= 2) {\n if (tag[0] === \"e\" && lastETag === void 0) {\n lastETag = tag;\n } else if (tag[0] === \"p\" && lastPTag === void 0) {\n lastPTag = tag;\n }\n }\n }\n if (lastETag === void 0) {\n return void 0;\n }\n return {\n id: lastETag[1],\n relays: [lastETag[2], lastPTag?.[2]].filter((x) => typeof x === \"string\"),\n author: lastPTag?.[1]\n };\n}\nfunction getRepostedEvent(event, { skipVerification } = {}) {\n const pointer = getRepostedEventPointer(event);\n if (pointer === void 0 || event.content === \"\") {\n return void 0;\n }\n let repostedEvent;\n try {\n repostedEvent = JSON.parse(event.content);\n } catch (error) {\n return void 0;\n }\n if (repostedEvent.id !== pointer.id) {\n return void 0;\n }\n if (!skipVerification && !verifyEvent(repostedEvent)) {\n return void 0;\n }\n return repostedEvent;\n}\n\n// nip21.ts\nvar nip21_exports = {};\n__export(nip21_exports, {\n NOSTR_URI_REGEX: () => NOSTR_URI_REGEX,\n parse: () => parse2,\n test: () => test\n});\nvar NOSTR_URI_REGEX = new RegExp(`nostr:(${BECH32_REGEX.source})`);\nfunction test(value) {\n return typeof value === \"string\" && new RegExp(`^${NOSTR_URI_REGEX.source}$`).test(value);\n}\nfunction parse2(uri) {\n const match = uri.match(new RegExp(`^${NOSTR_URI_REGEX.source}$`));\n if (!match)\n throw new Error(`Invalid Nostr URI: ${uri}`);\n return {\n uri: match[0],\n value: match[1],\n decoded: decode(match[1])\n };\n}\n\n// nip25.ts\nvar nip25_exports = {};\n__export(nip25_exports, {\n finishReactionEvent: () => finishReactionEvent,\n getReactedEventPointer: () => getReactedEventPointer\n});\nfunction finishReactionEvent(t, reacted, privateKey) {\n const inheritedTags = reacted.tags.filter((tag) => tag.length >= 2 && (tag[0] === \"e\" || tag[0] === \"p\"));\n return finalizeEvent(\n {\n ...t,\n kind: Reaction,\n tags: [...t.tags ?? [], ...inheritedTags, [\"e\", reacted.id], [\"p\", reacted.pubkey]],\n content: t.content ?? \"+\"\n },\n privateKey\n );\n}\nfunction getReactedEventPointer(event) {\n if (event.kind !== Reaction) {\n return void 0;\n }\n let lastETag;\n let lastPTag;\n for (let i2 = event.tags.length - 1; i2 >= 0 && (lastETag === void 0 || lastPTag === void 0); i2--) {\n const tag = event.tags[i2];\n if (tag.length >= 2) {\n if (tag[0] === \"e\" && lastETag === void 0) {\n lastETag = tag;\n } else if (tag[0] === \"p\" && lastPTag === void 0) {\n lastPTag = tag;\n }\n }\n }\n if (lastETag === void 0 || lastPTag === void 0) {\n return void 0;\n }\n return {\n id: lastETag[1],\n relays: [lastETag[2], lastPTag[2]].filter((x) => x !== void 0),\n author: lastPTag[1]\n };\n}\n\n// nip27.ts\nvar nip27_exports = {};\n__export(nip27_exports, {\n parse: () => parse3\n});\nvar noCharacter = /\\W/m;\nvar noURLCharacter = /\\W |\\W$|$|,| /m;\nfunction* parse3(content) {\n const max = content.length;\n let prevIndex = 0;\n let index = 0;\n while (index < max) {\n let u = content.indexOf(\":\", index);\n if (u === -1) {\n break;\n }\n if (content.substring(u - 5, u) === \"nostr\") {\n const m = content.substring(u + 60).match(noCharacter);\n const end = m ? u + 60 + m.index : max;\n try {\n let pointer;\n let { data, type } = decode(content.substring(u + 1, end));\n switch (type) {\n case \"npub\":\n pointer = { pubkey: data };\n break;\n case \"nsec\":\n case \"note\":\n index = end + 1;\n continue;\n default:\n pointer = data;\n }\n if (prevIndex !== u - 5) {\n yield { type: \"text\", text: content.substring(prevIndex, u - 5) };\n }\n yield { type: \"reference\", pointer };\n index = end;\n prevIndex = index;\n continue;\n } catch (_err) {\n index = u + 1;\n continue;\n }\n } else if (content.substring(u - 5, u) === \"https\" || content.substring(u - 4, u) === \"http\") {\n const m = content.substring(u + 4).match(noURLCharacter);\n const end = m ? u + 4 + m.index : max;\n const prefixLen = content[u - 1] === \"s\" ? 5 : 4;\n try {\n let url = new URL(content.substring(u - prefixLen, end));\n if (url.hostname.indexOf(\".\") === -1) {\n throw new Error(\"invalid url\");\n }\n if (prevIndex !== u - prefixLen) {\n yield { type: \"text\", text: content.substring(prevIndex, u - prefixLen) };\n }\n if (/\\.(png|jpe?g|gif|webp)$/i.test(url.pathname)) {\n yield { type: \"image\", url: url.toString() };\n index = end;\n prevIndex = index;\n continue;\n }\n if (/\\.(mp4|avi|webm|mkv)$/i.test(url.pathname)) {\n yield { type: \"video\", url: url.toString() };\n index = end;\n prevIndex = index;\n continue;\n }\n if (/\\.(mp3|aac|ogg|opus)$/i.test(url.pathname)) {\n yield { type: \"audio\", url: url.toString() };\n index = end;\n prevIndex = index;\n continue;\n }\n yield { type: \"url\", url: url.toString() };\n index = end;\n prevIndex = index;\n continue;\n } catch (_err) {\n index = end + 1;\n continue;\n }\n } else if (content.substring(u - 3, u) === \"wss\" || content.substring(u - 2, u) === \"ws\") {\n const m = content.substring(u + 4).match(noURLCharacter);\n const end = m ? u + 4 + m.index : max;\n const prefixLen = content[u - 1] === \"s\" ? 3 : 2;\n try {\n let url = new URL(content.substring(u - prefixLen, end));\n if (url.hostname.indexOf(\".\") === -1) {\n throw new Error(\"invalid ws url\");\n }\n if (prevIndex !== u - prefixLen) {\n yield { type: \"text\", text: content.substring(prevIndex, u - prefixLen) };\n }\n yield { type: \"relay\", url: url.toString() };\n index = end;\n prevIndex = index;\n continue;\n } catch (_err) {\n index = end + 1;\n continue;\n }\n } else {\n index = u + 1;\n continue;\n }\n }\n if (prevIndex !== max) {\n yield { type: \"text\", text: content.substring(prevIndex) };\n }\n}\n\n// nip28.ts\nvar nip28_exports = {};\n__export(nip28_exports, {\n channelCreateEvent: () => channelCreateEvent,\n channelHideMessageEvent: () => channelHideMessageEvent,\n channelMessageEvent: () => channelMessageEvent,\n channelMetadataEvent: () => channelMetadataEvent,\n channelMuteUserEvent: () => channelMuteUserEvent\n});\nvar channelCreateEvent = (t, privateKey) => {\n let content;\n if (typeof t.content === \"object\") {\n content = JSON.stringify(t.content);\n } else if (typeof t.content === \"string\") {\n content = t.content;\n } else {\n return void 0;\n }\n return finalizeEvent(\n {\n kind: ChannelCreation,\n tags: [...t.tags ?? []],\n content,\n created_at: t.created_at\n },\n privateKey\n );\n};\nvar channelMetadataEvent = (t, privateKey) => {\n let content;\n if (typeof t.content === \"object\") {\n content = JSON.stringify(t.content);\n } else if (typeof t.content === \"string\") {\n content = t.content;\n } else {\n return void 0;\n }\n return finalizeEvent(\n {\n kind: ChannelMetadata,\n tags: [[\"e\", t.channel_create_event_id], ...t.tags ?? []],\n content,\n created_at: t.created_at\n },\n privateKey\n );\n};\nvar channelMessageEvent = (t, privateKey) => {\n const tags = [[\"e\", t.channel_create_event_id, t.relay_url, \"root\"]];\n if (t.reply_to_channel_message_event_id) {\n tags.push([\"e\", t.reply_to_channel_message_event_id, t.relay_url, \"reply\"]);\n }\n return finalizeEvent(\n {\n kind: ChannelMessage,\n tags: [...tags, ...t.tags ?? []],\n content: t.content,\n created_at: t.created_at\n },\n privateKey\n );\n};\nvar channelHideMessageEvent = (t, privateKey) => {\n let content;\n if (typeof t.content === \"object\") {\n content = JSON.stringify(t.content);\n } else if (typeof t.content === \"string\") {\n content = t.content;\n } else {\n return void 0;\n }\n return finalizeEvent(\n {\n kind: ChannelHideMessage,\n tags: [[\"e\", t.channel_message_event_id], ...t.tags ?? []],\n content,\n created_at: t.created_at\n },\n privateKey\n );\n};\nvar channelMuteUserEvent = (t, privateKey) => {\n let content;\n if (typeof t.content === \"object\") {\n content = JSON.stringify(t.content);\n } else if (typeof t.content === \"string\") {\n content = t.content;\n } else {\n return void 0;\n }\n return finalizeEvent(\n {\n kind: ChannelMuteUser,\n tags: [[\"p\", t.pubkey_to_mute], ...t.tags ?? []],\n content,\n created_at: t.created_at\n },\n privateKey\n );\n};\n\n// nip30.ts\nvar nip30_exports = {};\n__export(nip30_exports, {\n EMOJI_SHORTCODE_REGEX: () => EMOJI_SHORTCODE_REGEX,\n matchAll: () => matchAll,\n regex: () => regex,\n replaceAll: () => replaceAll\n});\nvar EMOJI_SHORTCODE_REGEX = /:(\\w+):/;\nvar regex = () => new RegExp(`\\\\B${EMOJI_SHORTCODE_REGEX.source}\\\\B`, \"g\");\nfunction* matchAll(content) {\n const matches = content.matchAll(regex());\n for (const match of matches) {\n try {\n const [shortcode, name] = match;\n yield {\n shortcode,\n name,\n start: match.index,\n end: match.index + shortcode.length\n };\n } catch (_e) {\n }\n }\n}\nfunction replaceAll(content, replacer) {\n return content.replaceAll(regex(), (shortcode, name) => {\n return replacer({\n shortcode,\n name\n });\n });\n}\n\n// nip39.ts\nvar nip39_exports = {};\n__export(nip39_exports, {\n useFetchImplementation: () => useFetchImplementation3,\n validateGithub: () => validateGithub\n});\nvar _fetch3;\ntry {\n _fetch3 = fetch;\n} catch {\n}\nfunction useFetchImplementation3(fetchImplementation) {\n _fetch3 = fetchImplementation;\n}\nasync function validateGithub(pubkey, username, proof) {\n try {\n let res = await (await _fetch3(`https://gist.github.com/${username}/${proof}/raw`)).text();\n return res === `Verifying that I control the following Nostr public key: ${pubkey}`;\n } catch (_) {\n return false;\n }\n}\n\n// nip47.ts\nvar nip47_exports = {};\n__export(nip47_exports, {\n makeNwcRequestEvent: () => makeNwcRequestEvent,\n parseConnectionString: () => parseConnectionString\n});\nfunction parseConnectionString(connectionString) {\n const { host, pathname, searchParams } = new URL(connectionString);\n const pubkey = pathname || host;\n const relay = searchParams.get(\"relay\");\n const secret = searchParams.get(\"secret\");\n if (!pubkey || !relay || !secret) {\n throw new Error(\"invalid connection string\");\n }\n return { pubkey, relay, secret };\n}\nasync function makeNwcRequestEvent(pubkey, secretKey, invoice) {\n const content = {\n method: \"pay_invoice\",\n params: {\n invoice\n }\n };\n const encryptedContent = encrypt(secretKey, pubkey, JSON.stringify(content));\n const eventTemplate = {\n kind: NWCWalletRequest,\n created_at: Math.round(Date.now() / 1e3),\n content: encryptedContent,\n tags: [[\"p\", pubkey]]\n };\n return finalizeEvent(eventTemplate, secretKey);\n}\n\n// nip54.ts\nvar nip54_exports = {};\n__export(nip54_exports, {\n normalizeIdentifier: () => normalizeIdentifier\n});\nfunction normalizeIdentifier(name) {\n name = name.trim().toLowerCase();\n name = name.normalize(\"NFKC\");\n return Array.from(name).map((char) => {\n if (/\\p{Letter}/u.test(char) || /\\p{Number}/u.test(char)) {\n return char;\n }\n return \"-\";\n }).join(\"\");\n}\n\n// nip57.ts\nvar nip57_exports = {};\n__export(nip57_exports, {\n getSatoshisAmountFromBolt11: () => getSatoshisAmountFromBolt11,\n getZapEndpoint: () => getZapEndpoint,\n makeZapReceipt: () => makeZapReceipt,\n makeZapRequest: () => makeZapRequest,\n useFetchImplementation: () => useFetchImplementation4,\n validateZapRequest: () => validateZapRequest\n});\nimport { bech32 as bech322 } from \"@scure/base\";\nvar _fetch4;\ntry {\n _fetch4 = fetch;\n} catch {\n}\nfunction useFetchImplementation4(fetchImplementation) {\n _fetch4 = fetchImplementation;\n}\nasync function getZapEndpoint(metadata) {\n try {\n let lnurl = \"\";\n let { lud06, lud16 } = JSON.parse(metadata.content);\n if (lud06) {\n let { words } = bech322.decode(lud06, 1e3);\n let data = bech322.fromWords(words);\n lnurl = utf8Decoder.decode(data);\n } else if (lud16) {\n let [name, domain] = lud16.split(\"@\");\n lnurl = new URL(`/.well-known/lnurlp/${name}`, `https://${domain}`).toString();\n } else {\n return null;\n }\n let res = await _fetch4(lnurl);\n let body = await res.json();\n if (body.allowsNostr && body.nostrPubkey) {\n return body.callback;\n }\n } catch (err) {\n }\n return null;\n}\nfunction makeZapRequest(params) {\n let zr = {\n kind: 9734,\n created_at: Math.round(Date.now() / 1e3),\n content: params.comment || \"\",\n tags: [\n [\"p\", \"pubkey\" in params ? params.pubkey : params.event.pubkey],\n [\"amount\", params.amount.toString()],\n [\"relays\", ...params.relays]\n ]\n };\n if (\"event\" in params) {\n zr.tags.push([\"e\", params.event.id]);\n if (isReplaceableKind(params.event.kind)) {\n const a = [\"a\", `${params.event.kind}:${params.event.pubkey}:`];\n zr.tags.push(a);\n } else if (isAddressableKind(params.event.kind)) {\n let d = params.event.tags.find(([t, v]) => t === \"d\" && v);\n if (!d)\n throw new Error(\"d tag not found or is empty\");\n const a = [\"a\", `${params.event.kind}:${params.event.pubkey}:${d[1]}`];\n zr.tags.push(a);\n }\n zr.tags.push([\"k\", params.event.kind.toString()]);\n }\n return zr;\n}\nfunction validateZapRequest(zapRequestString) {\n let zapRequest;\n try {\n zapRequest = JSON.parse(zapRequestString);\n } catch (err) {\n return \"Invalid zap request JSON.\";\n }\n if (!validateEvent(zapRequest))\n return \"Zap request is not a valid Nostr event.\";\n if (!verifyEvent(zapRequest))\n return \"Invalid signature on zap request.\";\n let p = zapRequest.tags.find(([t, v]) => t === \"p\" && v);\n if (!p)\n return \"Zap request doesn't have a 'p' tag.\";\n if (!p[1].match(/^[a-f0-9]{64}$/))\n return \"Zap request 'p' tag is not valid hex.\";\n let e = zapRequest.tags.find(([t, v]) => t === \"e\" && v);\n if (e && !e[1].match(/^[a-f0-9]{64}$/))\n return \"Zap request 'e' tag is not valid hex.\";\n let relays = zapRequest.tags.find(([t, v]) => t === \"relays\" && v);\n if (!relays)\n return \"Zap request doesn't have a 'relays' tag.\";\n return null;\n}\nfunction makeZapReceipt({\n zapRequest,\n preimage,\n bolt11,\n paidAt\n}) {\n let zr = JSON.parse(zapRequest);\n let tagsFromZapRequest = zr.tags.filter(([t]) => t === \"e\" || t === \"p\" || t === \"a\");\n let zap = {\n kind: 9735,\n created_at: Math.round(paidAt.getTime() / 1e3),\n content: \"\",\n tags: [...tagsFromZapRequest, [\"P\", zr.pubkey], [\"bolt11\", bolt11], [\"description\", zapRequest]]\n };\n if (preimage) {\n zap.tags.push([\"preimage\", preimage]);\n }\n return zap;\n}\nfunction getSatoshisAmountFromBolt11(bolt11) {\n if (bolt11.length < 50) {\n return 0;\n }\n bolt11 = bolt11.substring(0, 50);\n const idx = bolt11.lastIndexOf(\"1\");\n if (idx === -1) {\n return 0;\n }\n const hrp = bolt11.substring(0, idx);\n if (!hrp.startsWith(\"lnbc\")) {\n return 0;\n }\n const amount = hrp.substring(4);\n if (amount.length < 1) {\n return 0;\n }\n const char = amount[amount.length - 1];\n const digit = char.charCodeAt(0) - \"0\".charCodeAt(0);\n const isDigit = digit >= 0 && digit <= 9;\n let cutPoint = amount.length - 1;\n if (isDigit) {\n cutPoint++;\n }\n if (cutPoint < 1) {\n return 0;\n }\n const num = parseInt(amount.substring(0, cutPoint));\n switch (char) {\n case \"m\":\n return num * 1e5;\n case \"u\":\n return num * 100;\n case \"n\":\n return num / 10;\n case \"p\":\n return num / 1e4;\n default:\n return num * 1e8;\n }\n}\n\n// nip98.ts\nvar nip98_exports = {};\n__export(nip98_exports, {\n getToken: () => getToken,\n hashPayload: () => hashPayload,\n unpackEventFromToken: () => unpackEventFromToken,\n validateEvent: () => validateEvent2,\n validateEventKind: () => validateEventKind,\n validateEventMethodTag: () => validateEventMethodTag,\n validateEventPayloadTag: () => validateEventPayloadTag,\n validateEventTimestamp: () => validateEventTimestamp,\n validateEventUrlTag: () => validateEventUrlTag,\n validateToken: () => validateToken\n});\nimport { sha256 as sha2564 } from \"@noble/hashes/sha256\";\nimport { bytesToHex as bytesToHex6 } from \"@noble/hashes/utils\";\nimport { base64 as base643 } from \"@scure/base\";\nvar _authorizationScheme = \"Nostr \";\nasync function getToken(loginUrl, httpMethod, sign, includeAuthorizationScheme = false, payload) {\n const event = {\n kind: HTTPAuth,\n tags: [\n [\"u\", loginUrl],\n [\"method\", httpMethod]\n ],\n created_at: Math.round(new Date().getTime() / 1e3),\n content: \"\"\n };\n if (payload) {\n event.tags.push([\"payload\", hashPayload(payload)]);\n }\n const signedEvent = await sign(event);\n const authorizationScheme = includeAuthorizationScheme ? _authorizationScheme : \"\";\n return authorizationScheme + base643.encode(utf8Encoder.encode(JSON.stringify(signedEvent)));\n}\nasync function validateToken(token, url, method) {\n const event = await unpackEventFromToken(token).catch((error) => {\n throw error;\n });\n const valid = await validateEvent2(event, url, method).catch((error) => {\n throw error;\n });\n return valid;\n}\nasync function unpackEventFromToken(token) {\n if (!token) {\n throw new Error(\"Missing token\");\n }\n token = token.replace(_authorizationScheme, \"\");\n const eventB64 = utf8Decoder.decode(base643.decode(token));\n if (!eventB64 || eventB64.length === 0 || !eventB64.startsWith(\"{\")) {\n throw new Error(\"Invalid token\");\n }\n const event = JSON.parse(eventB64);\n return event;\n}\nfunction validateEventTimestamp(event) {\n if (!event.created_at) {\n return false;\n }\n return Math.round(new Date().getTime() / 1e3) - event.created_at < 60;\n}\nfunction validateEventKind(event) {\n return event.kind === HTTPAuth;\n}\nfunction validateEventUrlTag(event, url) {\n const urlTag = event.tags.find((t) => t[0] === \"u\");\n if (!urlTag) {\n return false;\n }\n return urlTag.length > 0 && urlTag[1] === url;\n}\nfunction validateEventMethodTag(event, method) {\n const methodTag = event.tags.find((t) => t[0] === \"method\");\n if (!methodTag) {\n return false;\n }\n return methodTag.length > 0 && methodTag[1].toLowerCase() === method.toLowerCase();\n}\nfunction hashPayload(payload) {\n const hash = sha2564(utf8Encoder.encode(JSON.stringify(payload)));\n return bytesToHex6(hash);\n}\nfunction validateEventPayloadTag(event, payload) {\n const payloadTag = event.tags.find((t) => t[0] === \"payload\");\n if (!payloadTag) {\n return false;\n }\n const payloadHash = hashPayload(payload);\n return payloadTag.length > 0 && payloadTag[1] === payloadHash;\n}\nasync function validateEvent2(event, url, method, body) {\n if (!verifyEvent(event)) {\n throw new Error(\"Invalid nostr event, signature invalid\");\n }\n if (!validateEventKind(event)) {\n throw new Error(\"Invalid nostr event, kind invalid\");\n }\n if (!validateEventTimestamp(event)) {\n throw new Error(\"Invalid nostr event, created_at timestamp invalid\");\n }\n if (!validateEventUrlTag(event, url)) {\n throw new Error(\"Invalid nostr event, url tag invalid\");\n }\n if (!validateEventMethodTag(event, method)) {\n throw new Error(\"Invalid nostr event, method tag invalid\");\n }\n if (Boolean(body) && typeof body === \"object\" && Object.keys(body).length > 0) {\n if (!validateEventPayloadTag(event, body)) {\n throw new Error(\"Invalid nostr event, payload tag does not match request body hash\");\n }\n }\n return true;\n}\nexport {\n Relay,\n SimplePool,\n finalizeEvent,\n fakejson_exports as fj,\n generateSecretKey,\n getEventHash,\n getFilterLimit,\n getPublicKey,\n kinds_exports as kinds,\n matchFilter,\n matchFilters,\n mergeFilters,\n nip04_exports as nip04,\n nip05_exports as nip05,\n nip10_exports as nip10,\n nip11_exports as nip11,\n nip13_exports as nip13,\n nip17_exports as nip17,\n nip18_exports as nip18,\n nip19_exports as nip19,\n nip21_exports as nip21,\n nip25_exports as nip25,\n nip27_exports as nip27,\n nip28_exports as nip28,\n nip30_exports as nip30,\n nip39_exports as nip39,\n nip42_exports as nip42,\n nip44_exports as nip44,\n nip47_exports as nip47,\n nip54_exports as nip54,\n nip57_exports as nip57,\n nip59_exports as nip59,\n nip98_exports as nip98,\n parseReferences,\n serializeEvent,\n sortEvents,\n utils_exports as utils,\n validateEvent,\n verifiedSymbol,\n verifyEvent\n};\n","// core.ts\nvar verifiedSymbol = Symbol(\"verified\");\nvar isRecord = (obj) => obj instanceof Object;\nfunction validateEvent(event) {\n if (!isRecord(event))\n return false;\n if (typeof event.kind !== \"number\")\n return false;\n if (typeof event.content !== \"string\")\n return false;\n if (typeof event.created_at !== \"number\")\n return false;\n if (typeof event.pubkey !== \"string\")\n return false;\n if (!event.pubkey.match(/^[a-f0-9]{64}$/))\n return false;\n if (!Array.isArray(event.tags))\n return false;\n for (let i = 0; i < event.tags.length; i++) {\n let tag = event.tags[i];\n if (!Array.isArray(tag))\n return false;\n for (let j = 0; j < tag.length; j++) {\n if (typeof tag[j] !== \"string\")\n return false;\n }\n }\n return true;\n}\n\n// kinds.ts\nfunction isRegularKind(kind) {\n return 1e3 <= kind && kind < 1e4 || [1, 2, 4, 5, 6, 7, 8, 16, 40, 41, 42, 43, 44].includes(kind);\n}\nfunction isReplaceableKind(kind) {\n return [0, 3].includes(kind) || 1e4 <= kind && kind < 2e4;\n}\nfunction isEphemeralKind(kind) {\n return 2e4 <= kind && kind < 3e4;\n}\nfunction isAddressableKind(kind) {\n return 3e4 <= kind && kind < 4e4;\n}\nfunction classifyKind(kind) {\n if (isRegularKind(kind))\n return \"regular\";\n if (isReplaceableKind(kind))\n return \"replaceable\";\n if (isEphemeralKind(kind))\n return \"ephemeral\";\n if (isAddressableKind(kind))\n return \"parameterized\";\n return \"unknown\";\n}\nfunction isKind(event, kind) {\n const kindAsArray = kind instanceof Array ? kind : [kind];\n return validateEvent(event) && kindAsArray.includes(event.kind) || false;\n}\nvar Metadata = 0;\nvar ShortTextNote = 1;\nvar RecommendRelay = 2;\nvar Contacts = 3;\nvar EncryptedDirectMessage = 4;\nvar EventDeletion = 5;\nvar Repost = 6;\nvar Reaction = 7;\nvar BadgeAward = 8;\nvar Seal = 13;\nvar PrivateDirectMessage = 14;\nvar GenericRepost = 16;\nvar ChannelCreation = 40;\nvar ChannelMetadata = 41;\nvar ChannelMessage = 42;\nvar ChannelHideMessage = 43;\nvar ChannelMuteUser = 44;\nvar OpenTimestamps = 1040;\nvar GiftWrap = 1059;\nvar FileMetadata = 1063;\nvar LiveChatMessage = 1311;\nvar ProblemTracker = 1971;\nvar Report = 1984;\nvar Reporting = 1984;\nvar Label = 1985;\nvar CommunityPostApproval = 4550;\nvar JobRequest = 5999;\nvar JobResult = 6999;\nvar JobFeedback = 7e3;\nvar ZapGoal = 9041;\nvar ZapRequest = 9734;\nvar Zap = 9735;\nvar Highlights = 9802;\nvar Mutelist = 1e4;\nvar Pinlist = 10001;\nvar RelayList = 10002;\nvar BookmarkList = 10003;\nvar CommunitiesList = 10004;\nvar PublicChatsList = 10005;\nvar BlockedRelaysList = 10006;\nvar SearchRelaysList = 10007;\nvar InterestsList = 10015;\nvar UserEmojiList = 10030;\nvar DirectMessageRelaysList = 10050;\nvar FileServerPreference = 10096;\nvar NWCWalletInfo = 13194;\nvar LightningPubRPC = 21e3;\nvar ClientAuth = 22242;\nvar NWCWalletRequest = 23194;\nvar NWCWalletResponse = 23195;\nvar NostrConnect = 24133;\nvar HTTPAuth = 27235;\nvar Followsets = 3e4;\nvar Genericlists = 30001;\nvar Relaysets = 30002;\nvar Bookmarksets = 30003;\nvar Curationsets = 30004;\nvar ProfileBadges = 30008;\nvar BadgeDefinition = 30009;\nvar Interestsets = 30015;\nvar CreateOrUpdateStall = 30017;\nvar CreateOrUpdateProduct = 30018;\nvar LongFormArticle = 30023;\nvar DraftLong = 30024;\nvar Emojisets = 30030;\nvar Application = 30078;\nvar LiveEvent = 30311;\nvar UserStatuses = 30315;\nvar ClassifiedListing = 30402;\nvar DraftClassifiedListing = 30403;\nvar Date = 31922;\nvar Time = 31923;\nvar Calendar = 31924;\nvar CalendarEventRSVP = 31925;\nvar Handlerrecommendation = 31989;\nvar Handlerinformation = 31990;\nvar CommunityDefinition = 34550;\nexport {\n Application,\n BadgeAward,\n BadgeDefinition,\n BlockedRelaysList,\n BookmarkList,\n Bookmarksets,\n Calendar,\n CalendarEventRSVP,\n ChannelCreation,\n ChannelHideMessage,\n ChannelMessage,\n ChannelMetadata,\n ChannelMuteUser,\n ClassifiedListing,\n ClientAuth,\n CommunitiesList,\n CommunityDefinition,\n CommunityPostApproval,\n Contacts,\n CreateOrUpdateProduct,\n CreateOrUpdateStall,\n Curationsets,\n Date,\n DirectMessageRelaysList,\n DraftClassifiedListing,\n DraftLong,\n Emojisets,\n EncryptedDirectMessage,\n EventDeletion,\n FileMetadata,\n FileServerPreference,\n Followsets,\n GenericRepost,\n Genericlists,\n GiftWrap,\n HTTPAuth,\n Handlerinformation,\n Handlerrecommendation,\n Highlights,\n InterestsList,\n Interestsets,\n JobFeedback,\n JobRequest,\n JobResult,\n Label,\n LightningPubRPC,\n LiveChatMessage,\n LiveEvent,\n LongFormArticle,\n Metadata,\n Mutelist,\n NWCWalletInfo,\n NWCWalletRequest,\n NWCWalletResponse,\n NostrConnect,\n OpenTimestamps,\n Pinlist,\n PrivateDirectMessage,\n ProblemTracker,\n ProfileBadges,\n PublicChatsList,\n Reaction,\n RecommendRelay,\n RelayList,\n Relaysets,\n Report,\n Reporting,\n Repost,\n Seal,\n SearchRelaysList,\n ShortTextNote,\n Time,\n UserEmojiList,\n UserStatuses,\n Zap,\n ZapGoal,\n ZapRequest,\n classifyKind,\n isAddressableKind,\n isEphemeralKind,\n isKind,\n isRegularKind,\n isReplaceableKind\n};\n","/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\n\nvar extendStatics = function(d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n }\n return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n var _, done = false;\n for (var i = decorators.length - 1; i >= 0; i--) {\n var context = {};\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n if (kind === \"accessor\") {\n if (result === void 0) continue;\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n if (_ = accept(result.get)) descriptor.get = _;\n if (_ = accept(result.set)) descriptor.set = _;\n if (_ = accept(result.init)) initializers.unshift(_);\n }\n else if (_ = accept(result)) {\n if (kind === \"field\") initializers.unshift(_);\n else descriptor[key] = _;\n }\n }\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\n done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n var useValue = arguments.length > 2;\n for (var i = 0; i < initializers.length; i++) {\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n }\n return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n}\n\nexport function __generator(thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n for (var ar = [], i = 0; i < arguments.length; i++)\n ar = ar.concat(__read(arguments[i]));\n return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n var i, p;\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n};\n\nvar ownKeys = function(o) {\n ownKeys = Object.getOwnPropertyNames || function (o) {\n var ar = [];\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\n return ar;\n };\n return ownKeys(o);\n};\n\nexport function __importStar(mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\n __setModuleDefault(result, mod);\n return result;\n}\n\nexport function __importDefault(mod) {\n return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n if (value !== null && value !== void 0) {\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n var dispose, inner;\n if (async) {\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n dispose = value[Symbol.asyncDispose];\n }\n if (dispose === void 0) {\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n dispose = value[Symbol.dispose];\n if (async) inner = dispose;\n }\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\n env.stack.push({ value: value, dispose: dispose, async: async });\n }\n else if (async) {\n env.stack.push({ async: true });\n }\n return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n function fail(e) {\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n env.hasError = true;\n }\n var r, s = 0;\n function next() {\n while (r = env.stack.pop()) {\n try {\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\n if (r.dispose) {\n var result = r.dispose.call(r.value);\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n }\n else s |= 1;\n }\n catch (e) {\n fail(e);\n }\n }\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\n if (env.hasError) throw env.error;\n }\n return next();\n}\n\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\n });\n }\n return path;\n}\n\nexport default {\n __extends,\n __assign,\n __rest,\n __decorate,\n __param,\n __esDecorate,\n __runInitializers,\n __propKey,\n __setFunctionName,\n __metadata,\n __awaiter,\n __generator,\n __createBinding,\n __exportStar,\n __values,\n __read,\n __spread,\n __spreadArrays,\n __spreadArray,\n __await,\n __asyncGenerator,\n __asyncDelegator,\n __asyncValues,\n __makeTemplateObject,\n __importStar,\n __importDefault,\n __classPrivateFieldGet,\n __classPrivateFieldSet,\n __classPrivateFieldIn,\n __addDisposableResource,\n __disposeResources,\n __rewriteRelativeImportExtension,\n};\n","export function isFunction(value) {\n return typeof value === 'function';\n}\n//# sourceMappingURL=isFunction.js.map","export function createErrorClass(createImpl) {\n var _super = function (instance) {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n var ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n//# sourceMappingURL=createErrorClass.js.map","import { createErrorClass } from './createErrorClass';\nexport var UnsubscriptionError = createErrorClass(function (_super) {\n return function UnsubscriptionErrorImpl(errors) {\n _super(this);\n this.message = errors\n ? errors.length + \" errors occurred during unsubscription:\\n\" + errors.map(function (err, i) { return i + 1 + \") \" + err.toString(); }).join('\\n ')\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n };\n});\n//# sourceMappingURL=UnsubscriptionError.js.map","export function arrRemove(arr, item) {\n if (arr) {\n var index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n//# sourceMappingURL=arrRemove.js.map","import { __read, __spreadArray, __values } from \"tslib\";\nimport { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { arrRemove } from './util/arrRemove';\nvar Subscription = (function () {\n function Subscription(initialTeardown) {\n this.initialTeardown = initialTeardown;\n this.closed = false;\n this._parentage = null;\n this._finalizers = null;\n }\n Subscription.prototype.unsubscribe = function () {\n var e_1, _a, e_2, _b;\n var errors;\n if (!this.closed) {\n this.closed = true;\n var _parentage = this._parentage;\n if (_parentage) {\n this._parentage = null;\n if (Array.isArray(_parentage)) {\n try {\n for (var _parentage_1 = __values(_parentage), _parentage_1_1 = _parentage_1.next(); !_parentage_1_1.done; _parentage_1_1 = _parentage_1.next()) {\n var parent_1 = _parentage_1_1.value;\n parent_1.remove(this);\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (_parentage_1_1 && !_parentage_1_1.done && (_a = _parentage_1.return)) _a.call(_parentage_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n }\n else {\n _parentage.remove(this);\n }\n }\n var initialFinalizer = this.initialTeardown;\n if (isFunction(initialFinalizer)) {\n try {\n initialFinalizer();\n }\n catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n var _finalizers = this._finalizers;\n if (_finalizers) {\n this._finalizers = null;\n try {\n for (var _finalizers_1 = __values(_finalizers), _finalizers_1_1 = _finalizers_1.next(); !_finalizers_1_1.done; _finalizers_1_1 = _finalizers_1.next()) {\n var finalizer = _finalizers_1_1.value;\n try {\n execFinalizer(finalizer);\n }\n catch (err) {\n errors = errors !== null && errors !== void 0 ? errors : [];\n if (err instanceof UnsubscriptionError) {\n errors = __spreadArray(__spreadArray([], __read(errors)), __read(err.errors));\n }\n else {\n errors.push(err);\n }\n }\n }\n }\n catch (e_2_1) { e_2 = { error: e_2_1 }; }\n finally {\n try {\n if (_finalizers_1_1 && !_finalizers_1_1.done && (_b = _finalizers_1.return)) _b.call(_finalizers_1);\n }\n finally { if (e_2) throw e_2.error; }\n }\n }\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n };\n Subscription.prototype.add = function (teardown) {\n var _a;\n if (teardown && teardown !== this) {\n if (this.closed) {\n execFinalizer(teardown);\n }\n else {\n if (teardown instanceof Subscription) {\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._finalizers = (_a = this._finalizers) !== null && _a !== void 0 ? _a : []).push(teardown);\n }\n }\n };\n Subscription.prototype._hasParent = function (parent) {\n var _parentage = this._parentage;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n };\n Subscription.prototype._addParent = function (parent) {\n var _parentage = this._parentage;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n };\n Subscription.prototype._removeParent = function (parent) {\n var _parentage = this._parentage;\n if (_parentage === parent) {\n this._parentage = null;\n }\n else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n };\n Subscription.prototype.remove = function (teardown) {\n var _finalizers = this._finalizers;\n _finalizers && arrRemove(_finalizers, teardown);\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n };\n Subscription.EMPTY = (function () {\n var empty = new Subscription();\n empty.closed = true;\n return empty;\n })();\n return Subscription;\n}());\nexport { Subscription };\nexport var EMPTY_SUBSCRIPTION = Subscription.EMPTY;\nexport function isSubscription(value) {\n return (value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe)));\n}\nfunction execFinalizer(finalizer) {\n if (isFunction(finalizer)) {\n finalizer();\n }\n else {\n finalizer.unsubscribe();\n }\n}\n//# sourceMappingURL=Subscription.js.map","export var config = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n//# sourceMappingURL=config.js.map","import { __read, __spreadArray } from \"tslib\";\nexport var timeoutProvider = {\n setTimeout: function (handler, timeout) {\n var args = [];\n for (var _i = 2; _i < arguments.length; _i++) {\n args[_i - 2] = arguments[_i];\n }\n var delegate = timeoutProvider.delegate;\n if (delegate === null || delegate === void 0 ? void 0 : delegate.setTimeout) {\n return delegate.setTimeout.apply(delegate, __spreadArray([handler, timeout], __read(args)));\n }\n return setTimeout.apply(void 0, __spreadArray([handler, timeout], __read(args)));\n },\n clearTimeout: function (handle) {\n var delegate = timeoutProvider.delegate;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearTimeout) || clearTimeout)(handle);\n },\n delegate: undefined,\n};\n//# sourceMappingURL=timeoutProvider.js.map","import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\nexport function reportUnhandledError(err) {\n timeoutProvider.setTimeout(function () {\n var onUnhandledError = config.onUnhandledError;\n if (onUnhandledError) {\n onUnhandledError(err);\n }\n else {\n throw err;\n }\n });\n}\n//# sourceMappingURL=reportUnhandledError.js.map","export function noop() { }\n//# sourceMappingURL=noop.js.map","import { config } from '../config';\nvar context = null;\nexport function errorContext(cb) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n var isRoot = !context;\n if (isRoot) {\n context = { errorThrown: false, error: null };\n }\n cb();\n if (isRoot) {\n var _a = context, errorThrown = _a.errorThrown, error = _a.error;\n context = null;\n if (errorThrown) {\n throw error;\n }\n }\n }\n else {\n cb();\n }\n}\nexport function captureError(err) {\n if (config.useDeprecatedSynchronousErrorHandling && context) {\n context.errorThrown = true;\n context.error = err;\n }\n}\n//# sourceMappingURL=errorContext.js.map","import { __extends } from \"tslib\";\nimport { isFunction } from './util/isFunction';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nimport { captureError } from './util/errorContext';\nvar Subscriber = (function (_super) {\n __extends(Subscriber, _super);\n function Subscriber(destination) {\n var _this = _super.call(this) || this;\n _this.isStopped = false;\n if (destination) {\n _this.destination = destination;\n if (isSubscription(destination)) {\n destination.add(_this);\n }\n }\n else {\n _this.destination = EMPTY_OBSERVER;\n }\n return _this;\n }\n Subscriber.create = function (next, error, complete) {\n return new SafeSubscriber(next, error, complete);\n };\n Subscriber.prototype.next = function (value) {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n }\n else {\n this._next(value);\n }\n };\n Subscriber.prototype.error = function (err) {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n }\n else {\n this.isStopped = true;\n this._error(err);\n }\n };\n Subscriber.prototype.complete = function () {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n }\n else {\n this.isStopped = true;\n this._complete();\n }\n };\n Subscriber.prototype.unsubscribe = function () {\n if (!this.closed) {\n this.isStopped = true;\n _super.prototype.unsubscribe.call(this);\n this.destination = null;\n }\n };\n Subscriber.prototype._next = function (value) {\n this.destination.next(value);\n };\n Subscriber.prototype._error = function (err) {\n try {\n this.destination.error(err);\n }\n finally {\n this.unsubscribe();\n }\n };\n Subscriber.prototype._complete = function () {\n try {\n this.destination.complete();\n }\n finally {\n this.unsubscribe();\n }\n };\n return Subscriber;\n}(Subscription));\nexport { Subscriber };\nvar _bind = Function.prototype.bind;\nfunction bind(fn, thisArg) {\n return _bind.call(fn, thisArg);\n}\nvar ConsumerObserver = (function () {\n function ConsumerObserver(partialObserver) {\n this.partialObserver = partialObserver;\n }\n ConsumerObserver.prototype.next = function (value) {\n var partialObserver = this.partialObserver;\n if (partialObserver.next) {\n try {\n partialObserver.next(value);\n }\n catch (error) {\n handleUnhandledError(error);\n }\n }\n };\n ConsumerObserver.prototype.error = function (err) {\n var partialObserver = this.partialObserver;\n if (partialObserver.error) {\n try {\n partialObserver.error(err);\n }\n catch (error) {\n handleUnhandledError(error);\n }\n }\n else {\n handleUnhandledError(err);\n }\n };\n ConsumerObserver.prototype.complete = function () {\n var partialObserver = this.partialObserver;\n if (partialObserver.complete) {\n try {\n partialObserver.complete();\n }\n catch (error) {\n handleUnhandledError(error);\n }\n }\n };\n return ConsumerObserver;\n}());\nvar SafeSubscriber = (function (_super) {\n __extends(SafeSubscriber, _super);\n function SafeSubscriber(observerOrNext, error, complete) {\n var _this = _super.call(this) || this;\n var partialObserver;\n if (isFunction(observerOrNext) || !observerOrNext) {\n partialObserver = {\n next: (observerOrNext !== null && observerOrNext !== void 0 ? observerOrNext : undefined),\n error: error !== null && error !== void 0 ? error : undefined,\n complete: complete !== null && complete !== void 0 ? complete : undefined,\n };\n }\n else {\n var context_1;\n if (_this && config.useDeprecatedNextContext) {\n context_1 = Object.create(observerOrNext);\n context_1.unsubscribe = function () { return _this.unsubscribe(); };\n partialObserver = {\n next: observerOrNext.next && bind(observerOrNext.next, context_1),\n error: observerOrNext.error && bind(observerOrNext.error, context_1),\n complete: observerOrNext.complete && bind(observerOrNext.complete, context_1),\n };\n }\n else {\n partialObserver = observerOrNext;\n }\n }\n _this.destination = new ConsumerObserver(partialObserver);\n return _this;\n }\n return SafeSubscriber;\n}(Subscriber));\nexport { SafeSubscriber };\nfunction handleUnhandledError(error) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n captureError(error);\n }\n else {\n reportUnhandledError(error);\n }\n}\nfunction defaultErrorHandler(err) {\n throw err;\n}\nfunction handleStoppedNotification(notification, subscriber) {\n var onStoppedNotification = config.onStoppedNotification;\n onStoppedNotification && timeoutProvider.setTimeout(function () { return onStoppedNotification(notification, subscriber); });\n}\nexport var EMPTY_OBSERVER = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n//# sourceMappingURL=Subscriber.js.map","export var observable = (function () { return (typeof Symbol === 'function' && Symbol.observable) || '@@observable'; })();\n//# sourceMappingURL=observable.js.map","export function identity(x) {\n return x;\n}\n//# sourceMappingURL=identity.js.map","import { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription } from './Subscription';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nimport { errorContext } from './util/errorContext';\nvar Observable = (function () {\n function Observable(subscribe) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n Observable.prototype.lift = function (operator) {\n var observable = new Observable();\n observable.source = this;\n observable.operator = operator;\n return observable;\n };\n Observable.prototype.subscribe = function (observerOrNext, error, complete) {\n var _this = this;\n var subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n errorContext(function () {\n var _a = _this, operator = _a.operator, source = _a.source;\n subscriber.add(operator\n ?\n operator.call(subscriber, source)\n : source\n ?\n _this._subscribe(subscriber)\n :\n _this._trySubscribe(subscriber));\n });\n return subscriber;\n };\n Observable.prototype._trySubscribe = function (sink) {\n try {\n return this._subscribe(sink);\n }\n catch (err) {\n sink.error(err);\n }\n };\n Observable.prototype.forEach = function (next, promiseCtor) {\n var _this = this;\n promiseCtor = getPromiseCtor(promiseCtor);\n return new promiseCtor(function (resolve, reject) {\n var subscriber = new SafeSubscriber({\n next: function (value) {\n try {\n next(value);\n }\n catch (err) {\n reject(err);\n subscriber.unsubscribe();\n }\n },\n error: reject,\n complete: resolve,\n });\n _this.subscribe(subscriber);\n });\n };\n Observable.prototype._subscribe = function (subscriber) {\n var _a;\n return (_a = this.source) === null || _a === void 0 ? void 0 : _a.subscribe(subscriber);\n };\n Observable.prototype[Symbol_observable] = function () {\n return this;\n };\n Observable.prototype.pipe = function () {\n var operations = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n operations[_i] = arguments[_i];\n }\n return pipeFromArray(operations)(this);\n };\n Observable.prototype.toPromise = function (promiseCtor) {\n var _this = this;\n promiseCtor = getPromiseCtor(promiseCtor);\n return new promiseCtor(function (resolve, reject) {\n var value;\n _this.subscribe(function (x) { return (value = x); }, function (err) { return reject(err); }, function () { return resolve(value); });\n });\n };\n Observable.create = function (subscribe) {\n return new Observable(subscribe);\n };\n return Observable;\n}());\nexport { Observable };\nfunction getPromiseCtor(promiseCtor) {\n var _a;\n return (_a = promiseCtor !== null && promiseCtor !== void 0 ? promiseCtor : config.Promise) !== null && _a !== void 0 ? _a : Promise;\n}\nfunction isObserver(value) {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\nfunction isSubscriber(value) {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n//# sourceMappingURL=Observable.js.map","import { identity } from './identity';\nexport function pipe() {\n var fns = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n fns[_i] = arguments[_i];\n }\n return pipeFromArray(fns);\n}\nexport function pipeFromArray(fns) {\n if (fns.length === 0) {\n return identity;\n }\n if (fns.length === 1) {\n return fns[0];\n }\n return function piped(input) {\n return fns.reduce(function (prev, fn) { return fn(prev); }, input);\n };\n}\n//# sourceMappingURL=pipe.js.map","import { isFunction } from './isFunction';\nexport function hasLift(source) {\n return isFunction(source === null || source === void 0 ? void 0 : source.lift);\n}\nexport function operate(init) {\n return function (source) {\n if (hasLift(source)) {\n return source.lift(function (liftedSource) {\n try {\n return init(liftedSource, this);\n }\n catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n//# sourceMappingURL=lift.js.map","import { __extends } from \"tslib\";\nimport { Subscriber } from '../Subscriber';\nexport function createOperatorSubscriber(destination, onNext, onComplete, onError, onFinalize) {\n return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);\n}\nvar OperatorSubscriber = (function (_super) {\n __extends(OperatorSubscriber, _super);\n function OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize, shouldUnsubscribe) {\n var _this = _super.call(this, destination) || this;\n _this.onFinalize = onFinalize;\n _this.shouldUnsubscribe = shouldUnsubscribe;\n _this._next = onNext\n ? function (value) {\n try {\n onNext(value);\n }\n catch (err) {\n destination.error(err);\n }\n }\n : _super.prototype._next;\n _this._error = onError\n ? function (err) {\n try {\n onError(err);\n }\n catch (err) {\n destination.error(err);\n }\n finally {\n this.unsubscribe();\n }\n }\n : _super.prototype._error;\n _this._complete = onComplete\n ? function () {\n try {\n onComplete();\n }\n catch (err) {\n destination.error(err);\n }\n finally {\n this.unsubscribe();\n }\n }\n : _super.prototype._complete;\n return _this;\n }\n OperatorSubscriber.prototype.unsubscribe = function () {\n var _a;\n if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {\n var closed_1 = this.closed;\n _super.prototype.unsubscribe.call(this);\n !closed_1 && ((_a = this.onFinalize) === null || _a === void 0 ? void 0 : _a.call(this));\n }\n };\n return OperatorSubscriber;\n}(Subscriber));\nexport { OperatorSubscriber };\n//# sourceMappingURL=OperatorSubscriber.js.map","import { createErrorClass } from './createErrorClass';\nexport var ObjectUnsubscribedError = createErrorClass(function (_super) {\n return function ObjectUnsubscribedErrorImpl() {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n };\n});\n//# sourceMappingURL=ObjectUnsubscribedError.js.map","import { __extends, __values } from \"tslib\";\nimport { Observable } from './Observable';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nimport { errorContext } from './util/errorContext';\nvar Subject = (function (_super) {\n __extends(Subject, _super);\n function Subject() {\n var _this = _super.call(this) || this;\n _this.closed = false;\n _this.currentObservers = null;\n _this.observers = [];\n _this.isStopped = false;\n _this.hasError = false;\n _this.thrownError = null;\n return _this;\n }\n Subject.prototype.lift = function (operator) {\n var subject = new AnonymousSubject(this, this);\n subject.operator = operator;\n return subject;\n };\n Subject.prototype._throwIfClosed = function () {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n };\n Subject.prototype.next = function (value) {\n var _this = this;\n errorContext(function () {\n var e_1, _a;\n _this._throwIfClosed();\n if (!_this.isStopped) {\n if (!_this.currentObservers) {\n _this.currentObservers = Array.from(_this.observers);\n }\n try {\n for (var _b = __values(_this.currentObservers), _c = _b.next(); !_c.done; _c = _b.next()) {\n var observer = _c.value;\n observer.next(value);\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (_c && !_c.done && (_a = _b.return)) _a.call(_b);\n }\n finally { if (e_1) throw e_1.error; }\n }\n }\n });\n };\n Subject.prototype.error = function (err) {\n var _this = this;\n errorContext(function () {\n _this._throwIfClosed();\n if (!_this.isStopped) {\n _this.hasError = _this.isStopped = true;\n _this.thrownError = err;\n var observers = _this.observers;\n while (observers.length) {\n observers.shift().error(err);\n }\n }\n });\n };\n Subject.prototype.complete = function () {\n var _this = this;\n errorContext(function () {\n _this._throwIfClosed();\n if (!_this.isStopped) {\n _this.isStopped = true;\n var observers = _this.observers;\n while (observers.length) {\n observers.shift().complete();\n }\n }\n });\n };\n Subject.prototype.unsubscribe = function () {\n this.isStopped = this.closed = true;\n this.observers = this.currentObservers = null;\n };\n Object.defineProperty(Subject.prototype, \"observed\", {\n get: function () {\n var _a;\n return ((_a = this.observers) === null || _a === void 0 ? void 0 : _a.length) > 0;\n },\n enumerable: false,\n configurable: true\n });\n Subject.prototype._trySubscribe = function (subscriber) {\n this._throwIfClosed();\n return _super.prototype._trySubscribe.call(this, subscriber);\n };\n Subject.prototype._subscribe = function (subscriber) {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n };\n Subject.prototype._innerSubscribe = function (subscriber) {\n var _this = this;\n var _a = this, hasError = _a.hasError, isStopped = _a.isStopped, observers = _a.observers;\n if (hasError || isStopped) {\n return EMPTY_SUBSCRIPTION;\n }\n this.currentObservers = null;\n observers.push(subscriber);\n return new Subscription(function () {\n _this.currentObservers = null;\n arrRemove(observers, subscriber);\n });\n };\n Subject.prototype._checkFinalizedStatuses = function (subscriber) {\n var _a = this, hasError = _a.hasError, thrownError = _a.thrownError, isStopped = _a.isStopped;\n if (hasError) {\n subscriber.error(thrownError);\n }\n else if (isStopped) {\n subscriber.complete();\n }\n };\n Subject.prototype.asObservable = function () {\n var observable = new Observable();\n observable.source = this;\n return observable;\n };\n Subject.create = function (destination, source) {\n return new AnonymousSubject(destination, source);\n };\n return Subject;\n}(Observable));\nexport { Subject };\nvar AnonymousSubject = (function (_super) {\n __extends(AnonymousSubject, _super);\n function AnonymousSubject(destination, source) {\n var _this = _super.call(this) || this;\n _this.destination = destination;\n _this.source = source;\n return _this;\n }\n AnonymousSubject.prototype.next = function (value) {\n var _a, _b;\n (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.next) === null || _b === void 0 ? void 0 : _b.call(_a, value);\n };\n AnonymousSubject.prototype.error = function (err) {\n var _a, _b;\n (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.call(_a, err);\n };\n AnonymousSubject.prototype.complete = function () {\n var _a, _b;\n (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.complete) === null || _b === void 0 ? void 0 : _b.call(_a);\n };\n AnonymousSubject.prototype._subscribe = function (subscriber) {\n var _a, _b;\n return (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.subscribe(subscriber)) !== null && _b !== void 0 ? _b : EMPTY_SUBSCRIPTION;\n };\n return AnonymousSubject;\n}(Subject));\nexport { AnonymousSubject };\n//# sourceMappingURL=Subject.js.map","export var dateTimestampProvider = {\n now: function () {\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n//# sourceMappingURL=dateTimestampProvider.js.map","import { __extends } from \"tslib\";\nimport { Subject } from './Subject';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\nvar ReplaySubject = (function (_super) {\n __extends(ReplaySubject, _super);\n function ReplaySubject(_bufferSize, _windowTime, _timestampProvider) {\n if (_bufferSize === void 0) { _bufferSize = Infinity; }\n if (_windowTime === void 0) { _windowTime = Infinity; }\n if (_timestampProvider === void 0) { _timestampProvider = dateTimestampProvider; }\n var _this = _super.call(this) || this;\n _this._bufferSize = _bufferSize;\n _this._windowTime = _windowTime;\n _this._timestampProvider = _timestampProvider;\n _this._buffer = [];\n _this._infiniteTimeWindow = true;\n _this._infiniteTimeWindow = _windowTime === Infinity;\n _this._bufferSize = Math.max(1, _bufferSize);\n _this._windowTime = Math.max(1, _windowTime);\n return _this;\n }\n ReplaySubject.prototype.next = function (value) {\n var _a = this, isStopped = _a.isStopped, _buffer = _a._buffer, _infiniteTimeWindow = _a._infiniteTimeWindow, _timestampProvider = _a._timestampProvider, _windowTime = _a._windowTime;\n if (!isStopped) {\n _buffer.push(value);\n !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);\n }\n this._trimBuffer();\n _super.prototype.next.call(this, value);\n };\n ReplaySubject.prototype._subscribe = function (subscriber) {\n this._throwIfClosed();\n this._trimBuffer();\n var subscription = this._innerSubscribe(subscriber);\n var _a = this, _infiniteTimeWindow = _a._infiniteTimeWindow, _buffer = _a._buffer;\n var copy = _buffer.slice();\n for (var i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i]);\n }\n this._checkFinalizedStatuses(subscriber);\n return subscription;\n };\n ReplaySubject.prototype._trimBuffer = function () {\n var _a = this, _bufferSize = _a._bufferSize, _timestampProvider = _a._timestampProvider, _buffer = _a._buffer, _infiniteTimeWindow = _a._infiniteTimeWindow;\n var adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;\n _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);\n if (!_infiniteTimeWindow) {\n var now = _timestampProvider.now();\n var last = 0;\n for (var i = 1; i < _buffer.length && _buffer[i] <= now; i += 2) {\n last = i;\n }\n last && _buffer.splice(0, last + 1);\n }\n };\n return ReplaySubject;\n}(Subject));\nexport { ReplaySubject };\n//# sourceMappingURL=ReplaySubject.js.map","import { __extends } from \"tslib\";\nimport { Subscription } from '../Subscription';\nvar Action = (function (_super) {\n __extends(Action, _super);\n function Action(scheduler, work) {\n return _super.call(this) || this;\n }\n Action.prototype.schedule = function (state, delay) {\n if (delay === void 0) { delay = 0; }\n return this;\n };\n return Action;\n}(Subscription));\nexport { Action };\n//# sourceMappingURL=Action.js.map","import { __read, __spreadArray } from \"tslib\";\nexport var intervalProvider = {\n setInterval: function (handler, timeout) {\n var args = [];\n for (var _i = 2; _i < arguments.length; _i++) {\n args[_i - 2] = arguments[_i];\n }\n var delegate = intervalProvider.delegate;\n if (delegate === null || delegate === void 0 ? void 0 : delegate.setInterval) {\n return delegate.setInterval.apply(delegate, __spreadArray([handler, timeout], __read(args)));\n }\n return setInterval.apply(void 0, __spreadArray([handler, timeout], __read(args)));\n },\n clearInterval: function (handle) {\n var delegate = intervalProvider.delegate;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearInterval) || clearInterval)(handle);\n },\n delegate: undefined,\n};\n//# sourceMappingURL=intervalProvider.js.map","import { __extends } from \"tslib\";\nimport { Action } from './Action';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nvar AsyncAction = (function (_super) {\n __extends(AsyncAction, _super);\n function AsyncAction(scheduler, work) {\n var _this = _super.call(this, scheduler, work) || this;\n _this.scheduler = scheduler;\n _this.work = work;\n _this.pending = false;\n return _this;\n }\n AsyncAction.prototype.schedule = function (state, delay) {\n var _a;\n if (delay === void 0) { delay = 0; }\n if (this.closed) {\n return this;\n }\n this.state = state;\n var id = this.id;\n var scheduler = this.scheduler;\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n this.pending = true;\n this.delay = delay;\n this.id = (_a = this.id) !== null && _a !== void 0 ? _a : this.requestAsyncId(scheduler, this.id, delay);\n return this;\n };\n AsyncAction.prototype.requestAsyncId = function (scheduler, _id, delay) {\n if (delay === void 0) { delay = 0; }\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n };\n AsyncAction.prototype.recycleAsyncId = function (_scheduler, id, delay) {\n if (delay === void 0) { delay = 0; }\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n if (id != null) {\n intervalProvider.clearInterval(id);\n }\n return undefined;\n };\n AsyncAction.prototype.execute = function (state, delay) {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n this.pending = false;\n var error = this._execute(state, delay);\n if (error) {\n return error;\n }\n else if (this.pending === false && this.id != null) {\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n };\n AsyncAction.prototype._execute = function (state, _delay) {\n var errored = false;\n var errorValue;\n try {\n this.work(state);\n }\n catch (e) {\n errored = true;\n errorValue = e ? e : new Error('Scheduled action threw falsy error');\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n };\n AsyncAction.prototype.unsubscribe = function () {\n if (!this.closed) {\n var _a = this, id = _a.id, scheduler = _a.scheduler;\n var actions = scheduler.actions;\n this.work = this.state = this.scheduler = null;\n this.pending = false;\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n this.delay = null;\n _super.prototype.unsubscribe.call(this);\n }\n };\n return AsyncAction;\n}(Action));\nexport { AsyncAction };\n//# sourceMappingURL=AsyncAction.js.map","import { dateTimestampProvider } from './scheduler/dateTimestampProvider';\nvar Scheduler = (function () {\n function Scheduler(schedulerActionCtor, now) {\n if (now === void 0) { now = Scheduler.now; }\n this.schedulerActionCtor = schedulerActionCtor;\n this.now = now;\n }\n Scheduler.prototype.schedule = function (work, delay, state) {\n if (delay === void 0) { delay = 0; }\n return new this.schedulerActionCtor(this, work).schedule(state, delay);\n };\n Scheduler.now = dateTimestampProvider.now;\n return Scheduler;\n}());\nexport { Scheduler };\n//# sourceMappingURL=Scheduler.js.map","import { __extends } from \"tslib\";\nimport { Scheduler } from '../Scheduler';\nvar AsyncScheduler = (function (_super) {\n __extends(AsyncScheduler, _super);\n function AsyncScheduler(SchedulerAction, now) {\n if (now === void 0) { now = Scheduler.now; }\n var _this = _super.call(this, SchedulerAction, now) || this;\n _this.actions = [];\n _this._active = false;\n return _this;\n }\n AsyncScheduler.prototype.flush = function (action) {\n var actions = this.actions;\n if (this._active) {\n actions.push(action);\n return;\n }\n var error;\n this._active = true;\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions.shift()));\n this._active = false;\n if (error) {\n while ((action = actions.shift())) {\n action.unsubscribe();\n }\n throw error;\n }\n };\n return AsyncScheduler;\n}(Scheduler));\nexport { AsyncScheduler };\n//# sourceMappingURL=AsyncScheduler.js.map","import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\nexport var asyncScheduler = new AsyncScheduler(AsyncAction);\nexport var async = asyncScheduler;\n//# sourceMappingURL=async.js.map","import { Observable } from '../Observable';\nexport var EMPTY = new Observable(function (subscriber) { return subscriber.complete(); });\nexport function empty(scheduler) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\nfunction emptyScheduled(scheduler) {\n return new Observable(function (subscriber) { return scheduler.schedule(function () { return subscriber.complete(); }); });\n}\n//# sourceMappingURL=empty.js.map","import { isFunction } from './isFunction';\nexport function isScheduler(value) {\n return value && isFunction(value.schedule);\n}\n//# sourceMappingURL=isScheduler.js.map","import { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\nfunction last(arr) {\n return arr[arr.length - 1];\n}\nexport function popResultSelector(args) {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\nexport function popScheduler(args) {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\nexport function popNumber(args, defaultValue) {\n return typeof last(args) === 'number' ? args.pop() : defaultValue;\n}\n//# sourceMappingURL=args.js.map","export var isArrayLike = (function (x) { return x && typeof x.length === 'number' && typeof x !== 'function'; });\n//# sourceMappingURL=isArrayLike.js.map","import { isFunction } from \"./isFunction\";\nexport function isPromise(value) {\n return isFunction(value === null || value === void 0 ? void 0 : value.then);\n}\n//# sourceMappingURL=isPromise.js.map","import { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\nexport function isInteropObservable(input) {\n return isFunction(input[Symbol_observable]);\n}\n//# sourceMappingURL=isInteropObservable.js.map","import { isFunction } from './isFunction';\nexport function isAsyncIterable(obj) {\n return Symbol.asyncIterator && isFunction(obj === null || obj === void 0 ? void 0 : obj[Symbol.asyncIterator]);\n}\n//# sourceMappingURL=isAsyncIterable.js.map","export function createInvalidObservableTypeError(input) {\n return new TypeError(\"You provided \" + (input !== null && typeof input === 'object' ? 'an invalid object' : \"'\" + input + \"'\") + \" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.\");\n}\n//# sourceMappingURL=throwUnobservableError.js.map","export function getSymbolIterator() {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator';\n }\n return Symbol.iterator;\n}\nexport var iterator = getSymbolIterator();\n//# sourceMappingURL=iterator.js.map","import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\nexport function isIterable(input) {\n return isFunction(input === null || input === void 0 ? void 0 : input[Symbol_iterator]);\n}\n//# sourceMappingURL=isIterable.js.map","import { __asyncGenerator, __await, __generator } from \"tslib\";\nimport { isFunction } from './isFunction';\nexport function readableStreamLikeToAsyncGenerator(readableStream) {\n return __asyncGenerator(this, arguments, function readableStreamLikeToAsyncGenerator_1() {\n var reader, _a, value, done;\n return __generator(this, function (_b) {\n switch (_b.label) {\n case 0:\n reader = readableStream.getReader();\n _b.label = 1;\n case 1:\n _b.trys.push([1, , 9, 10]);\n _b.label = 2;\n case 2:\n if (!true) return [3, 8];\n return [4, __await(reader.read())];\n case 3:\n _a = _b.sent(), value = _a.value, done = _a.done;\n if (!done) return [3, 5];\n return [4, __await(void 0)];\n case 4: return [2, _b.sent()];\n case 5: return [4, __await(value)];\n case 6: return [4, _b.sent()];\n case 7:\n _b.sent();\n return [3, 2];\n case 8: return [3, 10];\n case 9:\n reader.releaseLock();\n return [7];\n case 10: return [2];\n }\n });\n });\n}\nexport function isReadableStreamLike(obj) {\n return isFunction(obj === null || obj === void 0 ? void 0 : obj.getReader);\n}\n//# sourceMappingURL=isReadableStreamLike.js.map","import { __asyncValues, __awaiter, __generator, __values } from \"tslib\";\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isPromise } from '../util/isPromise';\nimport { Observable } from '../Observable';\nimport { isInteropObservable } from '../util/isInteropObservable';\nimport { isAsyncIterable } from '../util/isAsyncIterable';\nimport { createInvalidObservableTypeError } from '../util/throwUnobservableError';\nimport { isIterable } from '../util/isIterable';\nimport { isReadableStreamLike, readableStreamLikeToAsyncGenerator } from '../util/isReadableStreamLike';\nimport { isFunction } from '../util/isFunction';\nimport { reportUnhandledError } from '../util/reportUnhandledError';\nimport { observable as Symbol_observable } from '../symbol/observable';\nexport function innerFrom(input) {\n if (input instanceof Observable) {\n return input;\n }\n if (input != null) {\n if (isInteropObservable(input)) {\n return fromInteropObservable(input);\n }\n if (isArrayLike(input)) {\n return fromArrayLike(input);\n }\n if (isPromise(input)) {\n return fromPromise(input);\n }\n if (isAsyncIterable(input)) {\n return fromAsyncIterable(input);\n }\n if (isIterable(input)) {\n return fromIterable(input);\n }\n if (isReadableStreamLike(input)) {\n return fromReadableStreamLike(input);\n }\n }\n throw createInvalidObservableTypeError(input);\n}\nexport function fromInteropObservable(obj) {\n return new Observable(function (subscriber) {\n var obs = obj[Symbol_observable]();\n if (isFunction(obs.subscribe)) {\n return obs.subscribe(subscriber);\n }\n throw new TypeError('Provided object does not correctly implement Symbol.observable');\n });\n}\nexport function fromArrayLike(array) {\n return new Observable(function (subscriber) {\n for (var i = 0; i < array.length && !subscriber.closed; i++) {\n subscriber.next(array[i]);\n }\n subscriber.complete();\n });\n}\nexport function fromPromise(promise) {\n return new Observable(function (subscriber) {\n promise\n .then(function (value) {\n if (!subscriber.closed) {\n subscriber.next(value);\n subscriber.complete();\n }\n }, function (err) { return subscriber.error(err); })\n .then(null, reportUnhandledError);\n });\n}\nexport function fromIterable(iterable) {\n return new Observable(function (subscriber) {\n var e_1, _a;\n try {\n for (var iterable_1 = __values(iterable), iterable_1_1 = iterable_1.next(); !iterable_1_1.done; iterable_1_1 = iterable_1.next()) {\n var value = iterable_1_1.value;\n subscriber.next(value);\n if (subscriber.closed) {\n return;\n }\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (iterable_1_1 && !iterable_1_1.done && (_a = iterable_1.return)) _a.call(iterable_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n subscriber.complete();\n });\n}\nexport function fromAsyncIterable(asyncIterable) {\n return new Observable(function (subscriber) {\n process(asyncIterable, subscriber).catch(function (err) { return subscriber.error(err); });\n });\n}\nexport function fromReadableStreamLike(readableStream) {\n return fromAsyncIterable(readableStreamLikeToAsyncGenerator(readableStream));\n}\nfunction process(asyncIterable, subscriber) {\n var asyncIterable_1, asyncIterable_1_1;\n var e_2, _a;\n return __awaiter(this, void 0, void 0, function () {\n var value, e_2_1;\n return __generator(this, function (_b) {\n switch (_b.label) {\n case 0:\n _b.trys.push([0, 5, 6, 11]);\n asyncIterable_1 = __asyncValues(asyncIterable);\n _b.label = 1;\n case 1: return [4, asyncIterable_1.next()];\n case 2:\n if (!(asyncIterable_1_1 = _b.sent(), !asyncIterable_1_1.done)) return [3, 4];\n value = asyncIterable_1_1.value;\n subscriber.next(value);\n if (subscriber.closed) {\n return [2];\n }\n _b.label = 3;\n case 3: return [3, 1];\n case 4: return [3, 11];\n case 5:\n e_2_1 = _b.sent();\n e_2 = { error: e_2_1 };\n return [3, 11];\n case 6:\n _b.trys.push([6, , 9, 10]);\n if (!(asyncIterable_1_1 && !asyncIterable_1_1.done && (_a = asyncIterable_1.return))) return [3, 8];\n return [4, _a.call(asyncIterable_1)];\n case 7:\n _b.sent();\n _b.label = 8;\n case 8: return [3, 10];\n case 9:\n if (e_2) throw e_2.error;\n return [7];\n case 10: return [7];\n case 11:\n subscriber.complete();\n return [2];\n }\n });\n });\n}\n//# sourceMappingURL=innerFrom.js.map","export function executeSchedule(parentSubscription, scheduler, work, delay, repeat) {\n if (delay === void 0) { delay = 0; }\n if (repeat === void 0) { repeat = false; }\n var scheduleSubscription = scheduler.schedule(function () {\n work();\n if (repeat) {\n parentSubscription.add(this.schedule(null, delay));\n }\n else {\n this.unsubscribe();\n }\n }, delay);\n parentSubscription.add(scheduleSubscription);\n if (!repeat) {\n return scheduleSubscription;\n }\n}\n//# sourceMappingURL=executeSchedule.js.map","import { executeSchedule } from '../util/executeSchedule';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nexport function observeOn(scheduler, delay) {\n if (delay === void 0) { delay = 0; }\n return operate(function (source, subscriber) {\n source.subscribe(createOperatorSubscriber(subscriber, function (value) { return executeSchedule(subscriber, scheduler, function () { return subscriber.next(value); }, delay); }, function () { return executeSchedule(subscriber, scheduler, function () { return subscriber.complete(); }, delay); }, function (err) { return executeSchedule(subscriber, scheduler, function () { return subscriber.error(err); }, delay); }));\n });\n}\n//# sourceMappingURL=observeOn.js.map","import { operate } from '../util/lift';\nexport function subscribeOn(scheduler, delay) {\n if (delay === void 0) { delay = 0; }\n return operate(function (source, subscriber) {\n subscriber.add(scheduler.schedule(function () { return source.subscribe(subscriber); }, delay));\n });\n}\n//# sourceMappingURL=subscribeOn.js.map","import { Observable } from '../Observable';\nimport { executeSchedule } from '../util/executeSchedule';\nexport function scheduleAsyncIterable(input, scheduler) {\n if (!input) {\n throw new Error('Iterable cannot be null');\n }\n return new Observable(function (subscriber) {\n executeSchedule(subscriber, scheduler, function () {\n var iterator = input[Symbol.asyncIterator]();\n executeSchedule(subscriber, scheduler, function () {\n iterator.next().then(function (result) {\n if (result.done) {\n subscriber.complete();\n }\n else {\n subscriber.next(result.value);\n }\n });\n }, 0, true);\n });\n });\n}\n//# sourceMappingURL=scheduleAsyncIterable.js.map","import { scheduleObservable } from './scheduleObservable';\nimport { schedulePromise } from './schedulePromise';\nimport { scheduleArray } from './scheduleArray';\nimport { scheduleIterable } from './scheduleIterable';\nimport { scheduleAsyncIterable } from './scheduleAsyncIterable';\nimport { isInteropObservable } from '../util/isInteropObservable';\nimport { isPromise } from '../util/isPromise';\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isIterable } from '../util/isIterable';\nimport { isAsyncIterable } from '../util/isAsyncIterable';\nimport { createInvalidObservableTypeError } from '../util/throwUnobservableError';\nimport { isReadableStreamLike } from '../util/isReadableStreamLike';\nimport { scheduleReadableStreamLike } from './scheduleReadableStreamLike';\nexport function scheduled(input, scheduler) {\n if (input != null) {\n if (isInteropObservable(input)) {\n return scheduleObservable(input, scheduler);\n }\n if (isArrayLike(input)) {\n return scheduleArray(input, scheduler);\n }\n if (isPromise(input)) {\n return schedulePromise(input, scheduler);\n }\n if (isAsyncIterable(input)) {\n return scheduleAsyncIterable(input, scheduler);\n }\n if (isIterable(input)) {\n return scheduleIterable(input, scheduler);\n }\n if (isReadableStreamLike(input)) {\n return scheduleReadableStreamLike(input, scheduler);\n }\n }\n throw createInvalidObservableTypeError(input);\n}\n//# sourceMappingURL=scheduled.js.map","import { innerFrom } from '../observable/innerFrom';\nimport { observeOn } from '../operators/observeOn';\nimport { subscribeOn } from '../operators/subscribeOn';\nexport function scheduleObservable(input, scheduler) {\n return innerFrom(input).pipe(subscribeOn(scheduler), observeOn(scheduler));\n}\n//# sourceMappingURL=scheduleObservable.js.map","import { Observable } from '../Observable';\nexport function scheduleArray(input, scheduler) {\n return new Observable(function (subscriber) {\n var i = 0;\n return scheduler.schedule(function () {\n if (i === input.length) {\n subscriber.complete();\n }\n else {\n subscriber.next(input[i++]);\n if (!subscriber.closed) {\n this.schedule();\n }\n }\n });\n });\n}\n//# sourceMappingURL=scheduleArray.js.map","import { innerFrom } from '../observable/innerFrom';\nimport { observeOn } from '../operators/observeOn';\nimport { subscribeOn } from '../operators/subscribeOn';\nexport function schedulePromise(input, scheduler) {\n return innerFrom(input).pipe(subscribeOn(scheduler), observeOn(scheduler));\n}\n//# sourceMappingURL=schedulePromise.js.map","import { Observable } from '../Observable';\nimport { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from '../util/isFunction';\nimport { executeSchedule } from '../util/executeSchedule';\nexport function scheduleIterable(input, scheduler) {\n return new Observable(function (subscriber) {\n var iterator;\n executeSchedule(subscriber, scheduler, function () {\n iterator = input[Symbol_iterator]();\n executeSchedule(subscriber, scheduler, function () {\n var _a;\n var value;\n var done;\n try {\n (_a = iterator.next(), value = _a.value, done = _a.done);\n }\n catch (err) {\n subscriber.error(err);\n return;\n }\n if (done) {\n subscriber.complete();\n }\n else {\n subscriber.next(value);\n }\n }, 0, true);\n });\n return function () { return isFunction(iterator === null || iterator === void 0 ? void 0 : iterator.return) && iterator.return(); };\n });\n}\n//# sourceMappingURL=scheduleIterable.js.map","import { scheduleAsyncIterable } from './scheduleAsyncIterable';\nimport { readableStreamLikeToAsyncGenerator } from '../util/isReadableStreamLike';\nexport function scheduleReadableStreamLike(input, scheduler) {\n return scheduleAsyncIterable(readableStreamLikeToAsyncGenerator(input), scheduler);\n}\n//# sourceMappingURL=scheduleReadableStreamLike.js.map","import { scheduled } from '../scheduled/scheduled';\nimport { innerFrom } from './innerFrom';\nexport function from(input, scheduler) {\n return scheduler ? scheduled(input, scheduler) : innerFrom(input);\n}\n//# sourceMappingURL=from.js.map","import { popScheduler } from '../util/args';\nimport { from } from './from';\nexport function of() {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n var scheduler = popScheduler(args);\n return from(args, scheduler);\n}\n//# sourceMappingURL=of.js.map","import { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nexport function map(project, thisArg) {\n return operate(function (source, subscriber) {\n var index = 0;\n source.subscribe(createOperatorSubscriber(subscriber, function (value) {\n subscriber.next(project.call(thisArg, value, index++));\n }));\n });\n}\n//# sourceMappingURL=map.js.map","import { __read, __spreadArray } from \"tslib\";\nimport { map } from \"../operators/map\";\nvar isArray = Array.isArray;\nfunction callOrApply(fn, args) {\n return isArray(args) ? fn.apply(void 0, __spreadArray([], __read(args))) : fn(args);\n}\nexport function mapOneOrManyArgs(fn) {\n return map(function (args) { return callOrApply(fn, args); });\n}\n//# sourceMappingURL=mapOneOrManyArgs.js.map","var isArray = Array.isArray;\nvar getPrototypeOf = Object.getPrototypeOf, objectProto = Object.prototype, getKeys = Object.keys;\nexport function argsArgArrayOrObject(args) {\n if (args.length === 1) {\n var first_1 = args[0];\n if (isArray(first_1)) {\n return { args: first_1, keys: null };\n }\n if (isPOJO(first_1)) {\n var keys = getKeys(first_1);\n return {\n args: keys.map(function (key) { return first_1[key]; }),\n keys: keys,\n };\n }\n }\n return { args: args, keys: null };\n}\nfunction isPOJO(obj) {\n return obj && typeof obj === 'object' && getPrototypeOf(obj) === objectProto;\n}\n//# sourceMappingURL=argsArgArrayOrObject.js.map","import { Observable } from '../Observable';\nimport { argsArgArrayOrObject } from '../util/argsArgArrayOrObject';\nimport { from } from './from';\nimport { identity } from '../util/identity';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs';\nimport { popResultSelector, popScheduler } from '../util/args';\nimport { createObject } from '../util/createObject';\nimport { createOperatorSubscriber } from '../operators/OperatorSubscriber';\nimport { executeSchedule } from '../util/executeSchedule';\nexport function combineLatest() {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n var scheduler = popScheduler(args);\n var resultSelector = popResultSelector(args);\n var _a = argsArgArrayOrObject(args), observables = _a.args, keys = _a.keys;\n if (observables.length === 0) {\n return from([], scheduler);\n }\n var result = new Observable(combineLatestInit(observables, scheduler, keys\n ?\n function (values) { return createObject(keys, values); }\n :\n identity));\n return resultSelector ? result.pipe(mapOneOrManyArgs(resultSelector)) : result;\n}\nexport function combineLatestInit(observables, scheduler, valueTransform) {\n if (valueTransform === void 0) { valueTransform = identity; }\n return function (subscriber) {\n maybeSchedule(scheduler, function () {\n var length = observables.length;\n var values = new Array(length);\n var active = length;\n var remainingFirstValues = length;\n var _loop_1 = function (i) {\n maybeSchedule(scheduler, function () {\n var source = from(observables[i], scheduler);\n var hasFirstValue = false;\n source.subscribe(createOperatorSubscriber(subscriber, function (value) {\n values[i] = value;\n if (!hasFirstValue) {\n hasFirstValue = true;\n remainingFirstValues--;\n }\n if (!remainingFirstValues) {\n subscriber.next(valueTransform(values.slice()));\n }\n }, function () {\n if (!--active) {\n subscriber.complete();\n }\n }));\n }, subscriber);\n };\n for (var i = 0; i < length; i++) {\n _loop_1(i);\n }\n }, subscriber);\n };\n}\nfunction maybeSchedule(scheduler, execute, subscription) {\n if (scheduler) {\n executeSchedule(subscription, scheduler, execute);\n }\n else {\n execute();\n }\n}\n//# sourceMappingURL=combineLatest.js.map","export function createObject(keys, values) {\n return keys.reduce(function (result, key, i) { return ((result[key] = values[i]), result); }, {});\n}\n//# sourceMappingURL=createObject.js.map","import { map } from './map';\nimport { innerFrom } from '../observable/innerFrom';\nimport { operate } from '../util/lift';\nimport { mergeInternals } from './mergeInternals';\nimport { isFunction } from '../util/isFunction';\nexport function mergeMap(project, resultSelector, concurrent) {\n if (concurrent === void 0) { concurrent = Infinity; }\n if (isFunction(resultSelector)) {\n return mergeMap(function (a, i) { return map(function (b, ii) { return resultSelector(a, b, i, ii); })(innerFrom(project(a, i))); }, concurrent);\n }\n else if (typeof resultSelector === 'number') {\n concurrent = resultSelector;\n }\n return operate(function (source, subscriber) { return mergeInternals(source, subscriber, project, concurrent); });\n}\n//# sourceMappingURL=mergeMap.js.map","import { innerFrom } from '../observable/innerFrom';\nimport { executeSchedule } from '../util/executeSchedule';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nexport function mergeInternals(source, subscriber, project, concurrent, onBeforeNext, expand, innerSubScheduler, additionalFinalizer) {\n var buffer = [];\n var active = 0;\n var index = 0;\n var isComplete = false;\n var checkComplete = function () {\n if (isComplete && !buffer.length && !active) {\n subscriber.complete();\n }\n };\n var outerNext = function (value) { return (active < concurrent ? doInnerSub(value) : buffer.push(value)); };\n var doInnerSub = function (value) {\n expand && subscriber.next(value);\n active++;\n var innerComplete = false;\n innerFrom(project(value, index++)).subscribe(createOperatorSubscriber(subscriber, function (innerValue) {\n onBeforeNext === null || onBeforeNext === void 0 ? void 0 : onBeforeNext(innerValue);\n if (expand) {\n outerNext(innerValue);\n }\n else {\n subscriber.next(innerValue);\n }\n }, function () {\n innerComplete = true;\n }, undefined, function () {\n if (innerComplete) {\n try {\n active--;\n var _loop_1 = function () {\n var bufferedValue = buffer.shift();\n if (innerSubScheduler) {\n executeSchedule(subscriber, innerSubScheduler, function () { return doInnerSub(bufferedValue); });\n }\n else {\n doInnerSub(bufferedValue);\n }\n };\n while (buffer.length && active < concurrent) {\n _loop_1();\n }\n checkComplete();\n }\n catch (err) {\n subscriber.error(err);\n }\n }\n }));\n };\n source.subscribe(createOperatorSubscriber(subscriber, outerNext, function () {\n isComplete = true;\n checkComplete();\n }));\n return function () {\n additionalFinalizer === null || additionalFinalizer === void 0 ? void 0 : additionalFinalizer();\n };\n}\n//# sourceMappingURL=mergeInternals.js.map","import { mergeMap } from './mergeMap';\nimport { identity } from '../util/identity';\nexport function mergeAll(concurrent) {\n if (concurrent === void 0) { concurrent = Infinity; }\n return mergeMap(identity, concurrent);\n}\n//# sourceMappingURL=mergeAll.js.map","import { concatAll } from '../operators/concatAll';\nimport { popScheduler } from '../util/args';\nimport { from } from './from';\nexport function concat() {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n return concatAll()(from(args, popScheduler(args)));\n}\n//# sourceMappingURL=concat.js.map","import { mergeAll } from './mergeAll';\nexport function concatAll() {\n return mergeAll(1);\n}\n//# sourceMappingURL=concatAll.js.map","import { Observable } from '../Observable';\nimport { innerFrom } from './innerFrom';\nexport function defer(observableFactory) {\n return new Observable(function (subscriber) {\n innerFrom(observableFactory()).subscribe(subscriber);\n });\n}\n//# sourceMappingURL=defer.js.map","import { Observable } from '../Observable';\nimport { async as asyncScheduler } from '../scheduler/async';\nimport { isScheduler } from '../util/isScheduler';\nimport { isValidDate } from '../util/isDate';\nexport function timer(dueTime, intervalOrScheduler, scheduler) {\n if (dueTime === void 0) { dueTime = 0; }\n if (scheduler === void 0) { scheduler = asyncScheduler; }\n var intervalDuration = -1;\n if (intervalOrScheduler != null) {\n if (isScheduler(intervalOrScheduler)) {\n scheduler = intervalOrScheduler;\n }\n else {\n intervalDuration = intervalOrScheduler;\n }\n }\n return new Observable(function (subscriber) {\n var due = isValidDate(dueTime) ? +dueTime - scheduler.now() : dueTime;\n if (due < 0) {\n due = 0;\n }\n var n = 0;\n return scheduler.schedule(function () {\n if (!subscriber.closed) {\n subscriber.next(n++);\n if (0 <= intervalDuration) {\n this.schedule(undefined, intervalDuration);\n }\n else {\n subscriber.complete();\n }\n }\n }, due);\n });\n}\n//# sourceMappingURL=timer.js.map","export function isValidDate(value) {\n return value instanceof Date && !isNaN(value);\n}\n//# sourceMappingURL=isDate.js.map","import { mergeAll } from '../operators/mergeAll';\nimport { innerFrom } from './innerFrom';\nimport { EMPTY } from './empty';\nimport { popNumber, popScheduler } from '../util/args';\nimport { from } from './from';\nexport function merge() {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n var scheduler = popScheduler(args);\n var concurrent = popNumber(args, Infinity);\n var sources = args;\n return !sources.length\n ?\n EMPTY\n : sources.length === 1\n ?\n innerFrom(sources[0])\n :\n mergeAll(concurrent)(from(sources, scheduler));\n}\n//# sourceMappingURL=merge.js.map","import { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nexport function filter(predicate, thisArg) {\n return operate(function (source, subscriber) {\n var index = 0;\n source.subscribe(createOperatorSubscriber(subscriber, function (value) { return predicate.call(thisArg, value, index++) && subscriber.next(value); }));\n });\n}\n//# sourceMappingURL=filter.js.map","import { EMPTY } from '../observable/empty';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nexport function take(count) {\n return count <= 0\n ?\n function () { return EMPTY; }\n : operate(function (source, subscriber) {\n var seen = 0;\n source.subscribe(createOperatorSubscriber(subscriber, function (value) {\n if (++seen <= count) {\n subscriber.next(value);\n if (count <= seen) {\n subscriber.complete();\n }\n }\n }));\n });\n}\n//# sourceMappingURL=take.js.map","import { identity } from '../util/identity';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nexport function distinctUntilChanged(comparator, keySelector) {\n if (keySelector === void 0) { keySelector = identity; }\n comparator = comparator !== null && comparator !== void 0 ? comparator : defaultCompare;\n return operate(function (source, subscriber) {\n var previousKey;\n var first = true;\n source.subscribe(createOperatorSubscriber(subscriber, function (value) {\n var currentKey = keySelector(value);\n if (first || !comparator(previousKey, currentKey)) {\n first = false;\n previousKey = currentKey;\n subscriber.next(value);\n }\n }));\n });\n}\nfunction defaultCompare(a, b) {\n return a === b;\n}\n//# sourceMappingURL=distinctUntilChanged.js.map","import { __read, __spreadArray } from \"tslib\";\nimport { concat } from '../observable/concat';\nimport { of } from '../observable/of';\nexport function endWith() {\n var values = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n values[_i] = arguments[_i];\n }\n return function (source) { return concat(source, of.apply(void 0, __spreadArray([], __read(values)))); };\n}\n//# sourceMappingURL=endWith.js.map","import { operate } from '../util/lift';\nexport function finalize(callback) {\n return operate(function (source, subscriber) {\n try {\n source.subscribe(subscriber);\n }\n finally {\n subscriber.add(callback);\n }\n });\n}\n//# sourceMappingURL=finalize.js.map","import { __read, __spreadArray } from \"tslib\";\nimport { operate } from '../util/lift';\nimport { mergeAll } from './mergeAll';\nimport { popNumber, popScheduler } from '../util/args';\nimport { from } from '../observable/from';\nexport function merge() {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n var scheduler = popScheduler(args);\n var concurrent = popNumber(args, Infinity);\n return operate(function (source, subscriber) {\n mergeAll(concurrent)(from(__spreadArray([source], __read(args)), scheduler)).subscribe(subscriber);\n });\n}\n//# sourceMappingURL=merge.js.map","import { __read, __spreadArray } from \"tslib\";\nimport { merge } from './merge';\nexport function mergeWith() {\n var otherSources = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n otherSources[_i] = arguments[_i];\n }\n return merge.apply(void 0, __spreadArray([], __read(otherSources)));\n}\n//# sourceMappingURL=mergeWith.js.map","import { operate } from '../util/lift';\nimport { scanInternals } from './scanInternals';\nexport function scan(accumulator, seed) {\n return operate(scanInternals(accumulator, seed, arguments.length >= 2, true));\n}\n//# sourceMappingURL=scan.js.map","import { createOperatorSubscriber } from './OperatorSubscriber';\nexport function scanInternals(accumulator, seed, hasSeed, emitOnNext, emitBeforeComplete) {\n return function (source, subscriber) {\n var hasState = hasSeed;\n var state = seed;\n var index = 0;\n source.subscribe(createOperatorSubscriber(subscriber, function (value) {\n var i = index++;\n state = hasState\n ?\n accumulator(state, value, i)\n :\n ((hasState = true), value);\n emitOnNext && subscriber.next(state);\n }, emitBeforeComplete &&\n (function () {\n hasState && subscriber.next(state);\n subscriber.complete();\n })));\n };\n}\n//# sourceMappingURL=scanInternals.js.map","import { __read, __spreadArray } from \"tslib\";\nimport { innerFrom } from '../observable/innerFrom';\nimport { Subject } from '../Subject';\nimport { SafeSubscriber } from '../Subscriber';\nimport { operate } from '../util/lift';\nexport function share(options) {\n if (options === void 0) { options = {}; }\n var _a = options.connector, connector = _a === void 0 ? function () { return new Subject(); } : _a, _b = options.resetOnError, resetOnError = _b === void 0 ? true : _b, _c = options.resetOnComplete, resetOnComplete = _c === void 0 ? true : _c, _d = options.resetOnRefCountZero, resetOnRefCountZero = _d === void 0 ? true : _d;\n return function (wrapperSource) {\n var connection;\n var resetConnection;\n var subject;\n var refCount = 0;\n var hasCompleted = false;\n var hasErrored = false;\n var cancelReset = function () {\n resetConnection === null || resetConnection === void 0 ? void 0 : resetConnection.unsubscribe();\n resetConnection = undefined;\n };\n var reset = function () {\n cancelReset();\n connection = subject = undefined;\n hasCompleted = hasErrored = false;\n };\n var resetAndUnsubscribe = function () {\n var conn = connection;\n reset();\n conn === null || conn === void 0 ? void 0 : conn.unsubscribe();\n };\n return operate(function (source, subscriber) {\n refCount++;\n if (!hasErrored && !hasCompleted) {\n cancelReset();\n }\n var dest = (subject = subject !== null && subject !== void 0 ? subject : connector());\n subscriber.add(function () {\n refCount--;\n if (refCount === 0 && !hasErrored && !hasCompleted) {\n resetConnection = handleReset(resetAndUnsubscribe, resetOnRefCountZero);\n }\n });\n dest.subscribe(subscriber);\n if (!connection &&\n refCount > 0) {\n connection = new SafeSubscriber({\n next: function (value) { return dest.next(value); },\n error: function (err) {\n hasErrored = true;\n cancelReset();\n resetConnection = handleReset(reset, resetOnError, err);\n dest.error(err);\n },\n complete: function () {\n hasCompleted = true;\n cancelReset();\n resetConnection = handleReset(reset, resetOnComplete);\n dest.complete();\n },\n });\n innerFrom(source).subscribe(connection);\n }\n })(wrapperSource);\n };\n}\nfunction handleReset(reset, on) {\n var args = [];\n for (var _i = 2; _i < arguments.length; _i++) {\n args[_i - 2] = arguments[_i];\n }\n if (on === true) {\n reset();\n return;\n }\n if (on === false) {\n return;\n }\n var onSubscriber = new SafeSubscriber({\n next: function () {\n onSubscriber.unsubscribe();\n reset();\n },\n });\n return innerFrom(on.apply(void 0, __spreadArray([], __read(args)))).subscribe(onSubscriber);\n}\n//# sourceMappingURL=share.js.map","import { innerFrom } from '../observable/innerFrom';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nexport function switchMap(project, resultSelector) {\n return operate(function (source, subscriber) {\n var innerSubscriber = null;\n var index = 0;\n var isComplete = false;\n var checkComplete = function () { return isComplete && !innerSubscriber && subscriber.complete(); };\n source.subscribe(createOperatorSubscriber(subscriber, function (value) {\n innerSubscriber === null || innerSubscriber === void 0 ? void 0 : innerSubscriber.unsubscribe();\n var innerIndex = 0;\n var outerIndex = index++;\n innerFrom(project(value, outerIndex)).subscribe((innerSubscriber = createOperatorSubscriber(subscriber, function (innerValue) { return subscriber.next(resultSelector ? resultSelector(value, innerValue, outerIndex, innerIndex++) : innerValue); }, function () {\n innerSubscriber = null;\n checkComplete();\n })));\n }, function () {\n isComplete = true;\n checkComplete();\n }));\n });\n}\n//# sourceMappingURL=switchMap.js.map","import { isFunction } from '../util/isFunction';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { identity } from '../util/identity';\nexport function tap(observerOrNext, error, complete) {\n var tapObserver = isFunction(observerOrNext) || error || complete\n ?\n { next: observerOrNext, error: error, complete: complete }\n : observerOrNext;\n return tapObserver\n ? operate(function (source, subscriber) {\n var _a;\n (_a = tapObserver.subscribe) === null || _a === void 0 ? void 0 : _a.call(tapObserver);\n var isUnsub = true;\n source.subscribe(createOperatorSubscriber(subscriber, function (value) {\n var _a;\n (_a = tapObserver.next) === null || _a === void 0 ? void 0 : _a.call(tapObserver, value);\n subscriber.next(value);\n }, function () {\n var _a;\n isUnsub = false;\n (_a = tapObserver.complete) === null || _a === void 0 ? void 0 : _a.call(tapObserver);\n subscriber.complete();\n }, function (err) {\n var _a;\n isUnsub = false;\n (_a = tapObserver.error) === null || _a === void 0 ? void 0 : _a.call(tapObserver, err);\n subscriber.error(err);\n }, function () {\n var _a, _b;\n if (isUnsub) {\n (_a = tapObserver.unsubscribe) === null || _a === void 0 ? void 0 : _a.call(tapObserver);\n }\n (_b = tapObserver.finalize) === null || _b === void 0 ? void 0 : _b.call(tapObserver);\n }));\n })\n :\n identity;\n}\n//# sourceMappingURL=tap.js.map","/** Tests if a tag has at least two indexes, and optionally the value of the first */\nexport function isNameValueTag(tag, name) {\n return tag[0] !== undefined && tag[1] !== undefined && (name ? tag[0] === name : true);\n}\n/** Checks if tag is an \"e\" tag and has at least one value */\nexport function isETag(tag) {\n return isNameValueTag(tag, \"e\");\n}\n/** Checks if tag is an \"p\" tag and has at least one value */\nexport function isPTag(tag) {\n return isNameValueTag(tag, \"p\");\n}\n/** Checks if tag is an \"r\" tag and has at least one value */\nexport function isRTag(tag) {\n return isNameValueTag(tag, \"r\");\n}\n/** Checks if tag is an \"d\" tag and has at least one value */\nexport function isDTag(tag) {\n return isNameValueTag(tag, \"d\");\n}\n/** Checks if tag is an \"a\" tag and has at least one value */\nexport function isATag(tag) {\n return isNameValueTag(tag, \"a\");\n}\n/** Checks if tag is an \"a\" tag and has at least one value */\nexport function isTTag(tag) {\n return isNameValueTag(tag, \"t\");\n}\n/** Filter and transform tags */\nexport const processTags = (tags, ...fns) => {\n return fns.reduce((step, fn) => {\n const next = [];\n for (const value of step) {\n try {\n const result = fn(value);\n if (result === undefined)\n continue; // value is undefined, ignore\n next.push(result);\n }\n catch (error) {\n // failed to process value, ignore\n }\n }\n return next;\n }, tags);\n};\n","// pure.ts\nimport { schnorr } from \"@noble/curves/secp256k1\";\nimport { bytesToHex as bytesToHex2 } from \"@noble/hashes/utils\";\n\n// core.ts\nvar verifiedSymbol = Symbol(\"verified\");\nvar isRecord = (obj) => obj instanceof Object;\nfunction validateEvent(event) {\n if (!isRecord(event))\n return false;\n if (typeof event.kind !== \"number\")\n return false;\n if (typeof event.content !== \"string\")\n return false;\n if (typeof event.created_at !== \"number\")\n return false;\n if (typeof event.pubkey !== \"string\")\n return false;\n if (!event.pubkey.match(/^[a-f0-9]{64}$/))\n return false;\n if (!Array.isArray(event.tags))\n return false;\n for (let i2 = 0; i2 < event.tags.length; i2++) {\n let tag = event.tags[i2];\n if (!Array.isArray(tag))\n return false;\n for (let j = 0; j < tag.length; j++) {\n if (typeof tag[j] !== \"string\")\n return false;\n }\n }\n return true;\n}\nfunction sortEvents(events) {\n return events.sort((a, b) => {\n if (a.created_at !== b.created_at) {\n return b.created_at - a.created_at;\n }\n return a.id.localeCompare(b.id);\n });\n}\n\n// pure.ts\nimport { sha256 } from \"@noble/hashes/sha256\";\n\n// utils.ts\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils\";\nvar utf8Decoder = new TextDecoder(\"utf-8\");\nvar utf8Encoder = new TextEncoder();\n\n// pure.ts\nvar JS = class {\n generateSecretKey() {\n return schnorr.utils.randomPrivateKey();\n }\n getPublicKey(secretKey) {\n return bytesToHex2(schnorr.getPublicKey(secretKey));\n }\n finalizeEvent(t, secretKey) {\n const event = t;\n event.pubkey = bytesToHex2(schnorr.getPublicKey(secretKey));\n event.id = getEventHash(event);\n event.sig = bytesToHex2(schnorr.sign(getEventHash(event), secretKey));\n event[verifiedSymbol] = true;\n return event;\n }\n verifyEvent(event) {\n if (typeof event[verifiedSymbol] === \"boolean\")\n return event[verifiedSymbol];\n const hash = getEventHash(event);\n if (hash !== event.id) {\n event[verifiedSymbol] = false;\n return false;\n }\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey);\n event[verifiedSymbol] = valid;\n return valid;\n } catch (err) {\n event[verifiedSymbol] = false;\n return false;\n }\n }\n};\nfunction serializeEvent(evt) {\n if (!validateEvent(evt))\n throw new Error(\"can't serialize event with wrong or missing properties\");\n return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);\n}\nfunction getEventHash(event) {\n let eventHash = sha256(utf8Encoder.encode(serializeEvent(event)));\n return bytesToHex2(eventHash);\n}\nvar i = new JS();\nvar generateSecretKey = i.generateSecretKey;\nvar getPublicKey = i.getPublicKey;\nvar finalizeEvent = i.finalizeEvent;\nvar verifyEvent = i.verifyEvent;\nexport {\n finalizeEvent,\n generateSecretKey,\n getEventHash,\n getPublicKey,\n serializeEvent,\n sortEvents,\n validateEvent,\n verifiedSymbol,\n verifyEvent\n};\n","export function getCachedValue(event, symbol) {\n return Reflect.get(event, symbol);\n}\nexport function setCachedValue(event, symbol, value) {\n Reflect.set(event, symbol, value);\n}\n/** Internal method used to cache computed values on events */\nexport function getOrComputeCachedValue(event, symbol, compute) {\n if (Reflect.has(event, symbol)) {\n return Reflect.get(event, symbol);\n }\n else {\n const value = compute();\n Reflect.set(event, symbol, value);\n return value;\n }\n}\n","// utils.ts\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils\";\nvar utf8Decoder = new TextDecoder(\"utf-8\");\nvar utf8Encoder = new TextEncoder();\nfunction normalizeURL(url) {\n try {\n if (url.indexOf(\"://\") === -1)\n url = \"wss://\" + url;\n let p = new URL(url);\n p.pathname = p.pathname.replace(/\\/+/g, \"/\");\n if (p.pathname.endsWith(\"/\"))\n p.pathname = p.pathname.slice(0, -1);\n if (p.port === \"80\" && p.protocol === \"ws:\" || p.port === \"443\" && p.protocol === \"wss:\")\n p.port = \"\";\n p.searchParams.sort();\n p.hash = \"\";\n return p.toString();\n } catch (e) {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\nfunction insertEventIntoDescendingList(sortedArray, event) {\n const [idx, found] = binarySearch(sortedArray, (b) => {\n if (event.id === b.id)\n return 0;\n if (event.created_at === b.created_at)\n return -1;\n return b.created_at - event.created_at;\n });\n if (!found) {\n sortedArray.splice(idx, 0, event);\n }\n return sortedArray;\n}\nfunction insertEventIntoAscendingList(sortedArray, event) {\n const [idx, found] = binarySearch(sortedArray, (b) => {\n if (event.id === b.id)\n return 0;\n if (event.created_at === b.created_at)\n return -1;\n return event.created_at - b.created_at;\n });\n if (!found) {\n sortedArray.splice(idx, 0, event);\n }\n return sortedArray;\n}\nfunction binarySearch(arr, compare) {\n let start = 0;\n let end = arr.length - 1;\n while (start <= end) {\n const mid = Math.floor((start + end) / 2);\n const cmp = compare(arr[mid]);\n if (cmp === 0) {\n return [mid, true];\n }\n if (cmp < 0) {\n end = mid - 1;\n } else {\n start = mid + 1;\n }\n }\n return [start, false];\n}\nvar QueueNode = class {\n value;\n next = null;\n prev = null;\n constructor(message) {\n this.value = message;\n }\n};\nvar Queue = class {\n first;\n last;\n constructor() {\n this.first = null;\n this.last = null;\n }\n enqueue(value) {\n const newNode = new QueueNode(value);\n if (!this.last) {\n this.first = newNode;\n this.last = newNode;\n } else if (this.last === this.first) {\n this.last = newNode;\n this.last.prev = this.first;\n this.first.next = newNode;\n } else {\n newNode.prev = this.last;\n this.last.next = newNode;\n this.last = newNode;\n }\n return true;\n }\n dequeue() {\n if (!this.first)\n return null;\n if (this.first === this.last) {\n const target2 = this.first;\n this.first = null;\n this.last = null;\n return target2.value;\n }\n const target = this.first;\n this.first = target.next;\n if (this.first) {\n this.first.prev = null;\n }\n return target.value;\n }\n};\nexport {\n Queue,\n QueueNode,\n binarySearch,\n bytesToHex,\n hexToBytes,\n insertEventIntoAscendingList,\n insertEventIntoDescendingList,\n normalizeURL,\n utf8Decoder,\n utf8Encoder\n};\n","import { verifiedSymbol, verifyEvent } from \"nostr-tools/pure\";\nimport { isAddressableKind, isReplaceableKind } from \"nostr-tools/kinds\";\nimport { getOrComputeCachedValue } from \"./cache.js\";\n// Re-export types from nostr-tools\nexport { verifiedSymbol, verifyEvent } from \"nostr-tools/pure\";\nexport { bytesToHex, hexToBytes, insertEventIntoAscendingList, insertEventIntoDescendingList, binarySearch, } from \"nostr-tools/utils\";\nexport * as kinds from \"nostr-tools/kinds\";\n/** A symbol on an event that marks which event store its part of */\nexport const EventStoreSymbol = Symbol.for(\"event-store\");\nexport const EventUIDSymbol = Symbol.for(\"event-uid\");\nexport const ReplaceableAddressSymbol = Symbol.for(\"replaceable-address\");\nexport const FromCacheSymbol = Symbol.for(\"from-cache\");\nexport const ReplaceableIdentifierSymbol = Symbol.for(\"replaceable-identifier\");\n/**\n * Checks if an object is a nostr event\n * NOTE: does not validate the signature on the event\n */\nexport function isEvent(event) {\n if (event === undefined || event === null)\n return false;\n return (event.id?.length === 64 &&\n typeof event.sig === \"string\" &&\n typeof event.pubkey === \"string\" &&\n event.pubkey.length === 64 &&\n typeof event.content === \"string\" &&\n Array.isArray(event.tags) &&\n typeof event.created_at === \"number\" &&\n event.created_at > 0);\n}\n/**\n * Returns if a kind is replaceable ( 10000 <= n < 20000 || n == 0 || n == 3 )\n * or parameterized replaceable ( 30000 <= n < 40000 )\n */\nexport function isReplaceable(kind) {\n return isReplaceableKind(kind) || isAddressableKind(kind);\n}\n/**\n * Returns the events Unique ID\n * For normal or ephemeral events this is ( event.id )\n * For replaceable events this is ( event.kind + \":\" + event.pubkey + \":\" )\n * For parametrized replaceable events this is ( event.kind + \":\" + event.pubkey + \":\" + event.tags.d )\n */\nexport function getEventUID(event) {\n let uid = Reflect.get(event, EventUIDSymbol);\n if (!uid) {\n if (isAddressableKind(event.kind) || isReplaceableKind(event.kind))\n uid = getReplaceableAddress(event);\n else\n uid = event.id;\n Reflect.set(event, EventUIDSymbol, uid);\n }\n return uid;\n}\n/** Returns the replaceable event address for an addressable event */\nexport function getReplaceableAddress(event) {\n if (!isAddressableKind(event.kind) && !isReplaceableKind(event.kind))\n throw new Error(\"Event is not replaceable or addressable\");\n return getOrComputeCachedValue(event, ReplaceableAddressSymbol, () => {\n return createReplaceableAddress(event.kind, event.pubkey, getReplaceableIdentifier(event));\n });\n}\n/** Creates a replaceable event address from a kind, pubkey, and identifier */\nexport function createReplaceableAddress(kind, pubkey, identifier) {\n return kind + \":\" + pubkey + \":\" + (identifier ?? \"\");\n}\n/** @deprecated use createReplaceableAddress instead */\nexport const getReplaceableUID = createReplaceableAddress;\n// Internal method for verifying events (used by zaps, gift-wraps, etc)\nlet verifyWrappedEventMethod = verifyEvent;\n/** Sets the internal method used to verify events in helpers (zaps, gift-wraps, etc) */\nexport function setVerifyWrappedEventMethod(method) {\n verifyWrappedEventMethod = method;\n}\n/** Verifies an internal (wrapped) event using the set internal verification method */\nexport function verifyWrappedEvent(event) {\n return verifyWrappedEventMethod(event);\n}\n/** Sets events verified flag without checking anything */\nexport function fakeVerifyEvent(event) {\n event[verifiedSymbol] = true;\n return true;\n}\n/** Marks an event as being from a cache */\nexport function markFromCache(event) {\n Reflect.set(event, FromCacheSymbol, true);\n}\n/** Returns if an event was from a cache */\nexport function isFromCache(event) {\n return Reflect.get(event, FromCacheSymbol) === true;\n}\n/** Returns the EventStore of an event if its been added to one */\nexport function getParentEventStore(event) {\n return Reflect.get(event, EventStoreSymbol);\n}\n/** Notifies the events parent store that an event has been updated */\nexport function notifyEventUpdate(event) {\n if (!isEvent(event))\n return;\n const eventStore = getParentEventStore(event);\n if (eventStore)\n eventStore.update(event);\n}\n/** Returns the replaceable identifier for a replaceable event */\nexport function getReplaceableIdentifier(event) {\n return getOrComputeCachedValue(event, ReplaceableIdentifierSymbol, () => {\n return event.tags.find((t) => t[0] === \"d\")?.[1] ?? \"\";\n });\n}\n/** Checks if an event is a NIP-70 protected event */\nexport function isProtectedEvent(event) {\n return event.tags.some((t) => t[0] === \"-\");\n}\n","/** Returns the current unix timestamp */\nexport function unixNow() {\n return Math.round(Date.now() / 1000);\n}\n","import { getOrComputeCachedValue } from \"./cache.js\";\nimport { unixNow } from \"./time.js\";\nexport const ExpirationTimestampSymbol = Symbol(\"expiration-timestamp\");\n/** Returns the NIP-40 expiration timestamp for an event */\nexport function getExpirationTimestamp(event) {\n return getOrComputeCachedValue(event, ExpirationTimestampSymbol, () => {\n const expiration = event.tags.find((t) => t[0] === \"expiration\")?.[1];\n return expiration ? parseInt(expiration) : undefined;\n });\n}\n/** Checks if an event has expired based on the NIP-40 expiration timestamp */\nexport function isExpired(event) {\n const expiration = getExpirationTimestamp(event);\n return expiration ? unixNow() > expiration : false;\n}\n","// nip19.ts\nimport { bytesToHex as bytesToHex2, concatBytes, hexToBytes as hexToBytes2 } from \"@noble/hashes/utils\";\nimport { bech32 } from \"@scure/base\";\n\n// utils.ts\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils\";\nvar utf8Decoder = new TextDecoder(\"utf-8\");\nvar utf8Encoder = new TextEncoder();\n\n// nip19.ts\nvar NostrTypeGuard = {\n isNProfile: (value) => /^nprofile1[a-z\\d]+$/.test(value || \"\"),\n isNEvent: (value) => /^nevent1[a-z\\d]+$/.test(value || \"\"),\n isNAddr: (value) => /^naddr1[a-z\\d]+$/.test(value || \"\"),\n isNSec: (value) => /^nsec1[a-z\\d]{58}$/.test(value || \"\"),\n isNPub: (value) => /^npub1[a-z\\d]{58}$/.test(value || \"\"),\n isNote: (value) => /^note1[a-z\\d]+$/.test(value || \"\"),\n isNcryptsec: (value) => /^ncryptsec1[a-z\\d]+$/.test(value || \"\")\n};\nvar Bech32MaxSize = 5e3;\nvar BECH32_REGEX = /[\\x21-\\x7E]{1,83}1[023456789acdefghjklmnpqrstuvwxyz]{6,}/;\nfunction integerToUint8Array(number) {\n const uint8Array = new Uint8Array(4);\n uint8Array[0] = number >> 24 & 255;\n uint8Array[1] = number >> 16 & 255;\n uint8Array[2] = number >> 8 & 255;\n uint8Array[3] = number & 255;\n return uint8Array;\n}\nfunction decodeNostrURI(nip19code) {\n try {\n if (nip19code.startsWith(\"nostr:\"))\n nip19code = nip19code.substring(6);\n return decode(nip19code);\n } catch (_err) {\n return { type: \"invalid\", data: null };\n }\n}\nfunction decode(code) {\n let { prefix, words } = bech32.decode(code, Bech32MaxSize);\n let data = new Uint8Array(bech32.fromWords(words));\n switch (prefix) {\n case \"nprofile\": {\n let tlv = parseTLV(data);\n if (!tlv[0]?.[0])\n throw new Error(\"missing TLV 0 for nprofile\");\n if (tlv[0][0].length !== 32)\n throw new Error(\"TLV 0 should be 32 bytes\");\n return {\n type: \"nprofile\",\n data: {\n pubkey: bytesToHex2(tlv[0][0]),\n relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []\n }\n };\n }\n case \"nevent\": {\n let tlv = parseTLV(data);\n if (!tlv[0]?.[0])\n throw new Error(\"missing TLV 0 for nevent\");\n if (tlv[0][0].length !== 32)\n throw new Error(\"TLV 0 should be 32 bytes\");\n if (tlv[2] && tlv[2][0].length !== 32)\n throw new Error(\"TLV 2 should be 32 bytes\");\n if (tlv[3] && tlv[3][0].length !== 4)\n throw new Error(\"TLV 3 should be 4 bytes\");\n return {\n type: \"nevent\",\n data: {\n id: bytesToHex2(tlv[0][0]),\n relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : [],\n author: tlv[2]?.[0] ? bytesToHex2(tlv[2][0]) : void 0,\n kind: tlv[3]?.[0] ? parseInt(bytesToHex2(tlv[3][0]), 16) : void 0\n }\n };\n }\n case \"naddr\": {\n let tlv = parseTLV(data);\n if (!tlv[0]?.[0])\n throw new Error(\"missing TLV 0 for naddr\");\n if (!tlv[2]?.[0])\n throw new Error(\"missing TLV 2 for naddr\");\n if (tlv[2][0].length !== 32)\n throw new Error(\"TLV 2 should be 32 bytes\");\n if (!tlv[3]?.[0])\n throw new Error(\"missing TLV 3 for naddr\");\n if (tlv[3][0].length !== 4)\n throw new Error(\"TLV 3 should be 4 bytes\");\n return {\n type: \"naddr\",\n data: {\n identifier: utf8Decoder.decode(tlv[0][0]),\n pubkey: bytesToHex2(tlv[2][0]),\n kind: parseInt(bytesToHex2(tlv[3][0]), 16),\n relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []\n }\n };\n }\n case \"nsec\":\n return { type: prefix, data };\n case \"npub\":\n case \"note\":\n return { type: prefix, data: bytesToHex2(data) };\n default:\n throw new Error(`unknown prefix ${prefix}`);\n }\n}\nfunction parseTLV(data) {\n let result = {};\n let rest = data;\n while (rest.length > 0) {\n let t = rest[0];\n let l = rest[1];\n let v = rest.slice(2, 2 + l);\n rest = rest.slice(2 + l);\n if (v.length < l)\n throw new Error(`not enough data to read on TLV ${t}`);\n result[t] = result[t] || [];\n result[t].push(v);\n }\n return result;\n}\nfunction nsecEncode(key) {\n return encodeBytes(\"nsec\", key);\n}\nfunction npubEncode(hex) {\n return encodeBytes(\"npub\", hexToBytes2(hex));\n}\nfunction noteEncode(hex) {\n return encodeBytes(\"note\", hexToBytes2(hex));\n}\nfunction encodeBech32(prefix, data) {\n let words = bech32.toWords(data);\n return bech32.encode(prefix, words, Bech32MaxSize);\n}\nfunction encodeBytes(prefix, bytes) {\n return encodeBech32(prefix, bytes);\n}\nfunction nprofileEncode(profile) {\n let data = encodeTLV({\n 0: [hexToBytes2(profile.pubkey)],\n 1: (profile.relays || []).map((url) => utf8Encoder.encode(url))\n });\n return encodeBech32(\"nprofile\", data);\n}\nfunction neventEncode(event) {\n let kindArray;\n if (event.kind !== void 0) {\n kindArray = integerToUint8Array(event.kind);\n }\n let data = encodeTLV({\n 0: [hexToBytes2(event.id)],\n 1: (event.relays || []).map((url) => utf8Encoder.encode(url)),\n 2: event.author ? [hexToBytes2(event.author)] : [],\n 3: kindArray ? [new Uint8Array(kindArray)] : []\n });\n return encodeBech32(\"nevent\", data);\n}\nfunction naddrEncode(addr) {\n let kind = new ArrayBuffer(4);\n new DataView(kind).setUint32(0, addr.kind, false);\n let data = encodeTLV({\n 0: [utf8Encoder.encode(addr.identifier)],\n 1: (addr.relays || []).map((url) => utf8Encoder.encode(url)),\n 2: [hexToBytes2(addr.pubkey)],\n 3: [new Uint8Array(kind)]\n });\n return encodeBech32(\"naddr\", data);\n}\nfunction encodeTLV(tlv) {\n let entries = [];\n Object.entries(tlv).reverse().forEach(([t, vs]) => {\n vs.forEach((v) => {\n let entry = new Uint8Array(v.length + 2);\n entry.set([parseInt(t)], 0);\n entry.set([v.length], 1);\n entry.set(v, 2);\n entries.push(entry);\n });\n });\n return concatBytes(...entries);\n}\nexport {\n BECH32_REGEX,\n Bech32MaxSize,\n NostrTypeGuard,\n decode,\n decodeNostrURI,\n encodeBytes,\n naddrEncode,\n neventEncode,\n noteEncode,\n nprofileEncode,\n npubEncode,\n nsecEncode\n};\n","export const convertToUrl = (url) => (url instanceof URL ? url : new URL(url));\nexport const getURLFilename = (url) => url.pathname.split(\"/\").pop()?.toLocaleLowerCase() || url.searchParams.get(\"filename\")?.toLocaleLowerCase();\nexport const IMAGE_EXT = [\".svg\", \".gif\", \".png\", \".jpg\", \".jpeg\", \".webp\", \".avif\"];\nexport const VIDEO_EXT = [\".mp4\", \".mkv\", \".webm\", \".mov\"];\nexport const STREAM_EXT = [\".m3u8\"];\nexport const AUDIO_EXT = [\".mp3\", \".wav\", \".ogg\", \".aac\", \".m4a\"];\n/** Checks if a url is a image URL */\nexport function isImageURL(url) {\n url = convertToUrl(url);\n const filename = getURLFilename(url);\n return !!filename && IMAGE_EXT.some((ext) => filename.endsWith(ext));\n}\n/** Checks if a url is a video URL */\nexport function isVideoURL(url) {\n url = convertToUrl(url);\n const filename = getURLFilename(url);\n return !!filename && VIDEO_EXT.some((ext) => filename.endsWith(ext));\n}\n/** Checks if a url is a stream URL */\nexport function isStreamURL(url) {\n url = convertToUrl(url);\n const filename = getURLFilename(url);\n return !!filename && STREAM_EXT.some((ext) => filename.endsWith(ext));\n}\n/** Checks if a url is a audio URL */\nexport function isAudioURL(url) {\n url = convertToUrl(url);\n const filename = getURLFilename(url);\n return !!filename && AUDIO_EXT.some((ext) => filename.endsWith(ext));\n}\n/** Tests if two URLs are the same */\nexport function isSameURL(a, b) {\n try {\n a = normalizeURL(a);\n b = normalizeURL(b);\n return a === b;\n }\n catch (error) {\n return false;\n }\n}\n/** Adds a protocol to a URL string if its missing one */\nexport function ensureProtocol(url, protocol = \"https:\") {\n // Check if the URL already has a protocol\n if (/^[a-zA-Z][a-zA-Z0-9+.-]+:/.test(url))\n return url;\n return protocol + \"//\" + url;\n}\n/** Converts a domain or HTTP URL to a WebSocket URL */\nexport function ensureWebSocketURL(url) {\n const p = typeof url === \"string\" ? new URL(ensureProtocol(url, \"wss:\")) : new URL(url);\n if (p.protocol === \"http:\")\n p.protocol = \"ws:\";\n else if (p.protocol === \"https:\")\n p.protocol = \"wss:\";\n else\n p.protocol = \"wss:\";\n // return a string if a string was passed in\n // @ts-expect-error\n return typeof url === \"string\" ? p.toString() : p;\n}\n/** Converts a domain or WS URL to a HTTP URL */\nexport function ensureHttpURL(url) {\n const p = typeof url === \"string\" ? new URL(ensureProtocol(url, \"http:\")) : new URL(url);\n if (p.protocol === \"ws:\")\n p.protocol = \"http:\";\n else if (p.protocol === \"wss:\")\n p.protocol = \"https:\";\n else\n p.protocol = \"https:\";\n // return a string if a string was passed in\n // @ts-expect-error\n return typeof url === \"string\" ? p.toString() : p;\n}\n/**\n * Normalizes a string into a relay URL\n * Does not remove the trailing slash\n */\nexport function normalizeURL(url) {\n let p = new URL(url);\n // Remove any double slashes\n p.pathname = p.pathname.replace(/\\/+/g, \"/\");\n // Remove the port if its not needed\n if ((p.port === \"80\" && (p.protocol === \"ws:\" || p.protocol === \"http:\")) ||\n (p.port === \"443\" && (p.protocol === \"wss:\" || p.protocol === \"https:\")))\n p.port = \"\";\n // Return a string if a string was passed in\n // @ts-expect-error\n return typeof url === \"string\" ? p.toString() : p;\n}\n","import { normalizeURL } from \"./url.js\";\nexport const SeenRelaysSymbol = Symbol.for(\"seen-relays\");\n/** Marks an event as being seen on a relay */\nexport function addSeenRelay(event, relay) {\n if (!event[SeenRelaysSymbol])\n event[SeenRelaysSymbol] = new Set();\n event[SeenRelaysSymbol].add(relay);\n return event[SeenRelaysSymbol];\n}\n/** Returns the set of relays this event was seen on */\nexport function getSeenRelays(event) {\n return event[SeenRelaysSymbol];\n}\nconst WEBSOCKET_URL_CHECK = /^wss?:\\/\\/([-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}|localhost)\\b([-a-zA-Z0-9()@:%_\\+.~#?&\\/\\/=]*)$/;\n/** A fast check to make sure relay hints are safe to connect to */\nexport function isSafeRelayURL(relay) {\n // anything smaller than 8 is not a URL\n return relay.length >= 8 && WEBSOCKET_URL_CHECK.test(relay);\n}\n/** Merge multiple sets of relays and remove duplicates (ignores invalid URLs) */\nexport function mergeRelaySets(...sources) {\n const set = new Set();\n for (const src of sources) {\n if (!src)\n continue;\n if (typeof src === \"string\") {\n // Source is a string\n try {\n const safe = normalizeURL(src).toString();\n if (safe)\n set.add(safe);\n }\n catch (error) {\n // failed to parse URL, ignore\n }\n }\n else {\n // Source is iterable\n for (const url of src) {\n try {\n const safe = normalizeURL(url).toString();\n if (safe)\n set.add(safe);\n }\n catch (error) {\n // failed to parse URL, ignore\n }\n }\n }\n }\n return Array.from(set);\n}\n/** Alias for {@link mergeRelaySets} */\nexport const relaySet = mergeRelaySets;\n","/** Tests if a string is hex */\nexport function isHex(str) {\n if (str?.match(/^[0-9a-f]+$/i))\n return true;\n return false;\n}\n/** Tests if a string is a 64 length hex string */\nexport function isHexKey(key) {\n if (key?.toLowerCase()?.match(/^[0-9a-f]{64}$/))\n return true;\n return false;\n}\nexport function stripInvisibleChar(str) {\n return str && str.replaceAll(/[\\p{Cf}\\p{Zs}]/gu, \"\");\n}\n","export const crypto = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;\n//# sourceMappingURL=crypto.js.map","/**\n * Utilities for hex, bytes, CSPRNG.\n * @module\n */\n/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// node.js versions earlier than v19 don't declare it in global scope.\n// For node.js, package.json#exports field mapping rewrites import\n// from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated (2025-04-30), we can just drop the import.\nimport { crypto } from '@noble/hashes/crypto';\n/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */\nexport function isBytes(a) {\n return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');\n}\n/** Asserts something is positive integer. */\nexport function anumber(n) {\n if (!Number.isSafeInteger(n) || n < 0)\n throw new Error('positive integer expected, got ' + n);\n}\n/** Asserts something is Uint8Array. */\nexport function abytes(b, ...lengths) {\n if (!isBytes(b))\n throw new Error('Uint8Array expected');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);\n}\n/** Asserts something is hash */\nexport function ahash(h) {\n if (typeof h !== 'function' || typeof h.create !== 'function')\n throw new Error('Hash should be wrapped by utils.createHasher');\n anumber(h.outputLen);\n anumber(h.blockLen);\n}\n/** Asserts a hash instance has not been destroyed / finished */\nexport function aexists(instance, checkFinished = true) {\n if (instance.destroyed)\n throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished)\n throw new Error('Hash#digest() has already been called');\n}\n/** Asserts output is properly-sized byte array */\nexport function aoutput(out, instance) {\n abytes(out);\n const min = instance.outputLen;\n if (out.length < min) {\n throw new Error('digestInto() expects output buffer of length at least ' + min);\n }\n}\n/** Cast u8 / u16 / u32 to u8. */\nexport function u8(arr) {\n return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n/** Cast u8 / u16 / u32 to u32. */\nexport function u32(arr) {\n return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n}\n/** Zeroize a byte array. Warning: JS provides no guarantees. */\nexport function clean(...arrays) {\n for (let i = 0; i < arrays.length; i++) {\n arrays[i].fill(0);\n }\n}\n/** Create DataView of an array for easy byte-level manipulation. */\nexport function createView(arr) {\n return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n/** The rotate right (circular right shift) operation for uint32 */\nexport function rotr(word, shift) {\n return (word << (32 - shift)) | (word >>> shift);\n}\n/** The rotate left (circular left shift) operation for uint32 */\nexport function rotl(word, shift) {\n return (word << shift) | ((word >>> (32 - shift)) >>> 0);\n}\n/** Is current platform little-endian? Most are. Big-Endian platform: IBM */\nexport const isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();\n/** The byte swap operation for uint32 */\nexport function byteSwap(word) {\n return (((word << 24) & 0xff000000) |\n ((word << 8) & 0xff0000) |\n ((word >>> 8) & 0xff00) |\n ((word >>> 24) & 0xff));\n}\n/** Conditionally byte swap if on a big-endian platform */\nexport const swap8IfBE = isLE\n ? (n) => n\n : (n) => byteSwap(n);\n/** @deprecated */\nexport const byteSwapIfBE = swap8IfBE;\n/** In place byte swap for Uint32Array */\nexport function byteSwap32(arr) {\n for (let i = 0; i < arr.length; i++) {\n arr[i] = byteSwap(arr[i]);\n }\n return arr;\n}\nexport const swap32IfBE = isLE\n ? (u) => u\n : byteSwap32;\n// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex\nconst hasHexBuiltin = /* @__PURE__ */ (() => \n// @ts-ignore\ntypeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));\n/**\n * Convert byte array to hex string. Uses built-in function, when available.\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes) {\n abytes(bytes);\n // @ts-ignore\n if (hasHexBuiltin)\n return bytes.toHex();\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };\nfunction asciiToBase16(ch) {\n if (ch >= asciis._0 && ch <= asciis._9)\n return ch - asciis._0; // '2' => 50-48\n if (ch >= asciis.A && ch <= asciis.F)\n return ch - (asciis.A - 10); // 'B' => 66-(65-10)\n if (ch >= asciis.a && ch <= asciis.f)\n return ch - (asciis.a - 10); // 'b' => 98-(97-10)\n return;\n}\n/**\n * Convert hex string to byte array. Uses built-in function, when available.\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n // @ts-ignore\n if (hasHexBuiltin)\n return Uint8Array.fromHex(hex);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2)\n throw new Error('hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163\n }\n return array;\n}\n/**\n * There is no setImmediate in browser and setTimeout is slow.\n * Call of async fn will return Promise, which will be fullfiled only on\n * next scheduler queue processing step and this is exactly what we need.\n */\nexport const nextTick = async () => { };\n/** Returns control to thread each 'tick' ms to avoid blocking. */\nexport async function asyncLoop(iters, tick, cb) {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick)\n continue;\n await nextTick();\n ts += diff;\n }\n}\n/**\n * Converts string to bytes using UTF8 encoding.\n * @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])\n */\nexport function utf8ToBytes(str) {\n if (typeof str !== 'string')\n throw new Error('string expected');\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n/**\n * Converts bytes to string using UTF8 encoding.\n * @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'\n */\nexport function bytesToUtf8(bytes) {\n return new TextDecoder().decode(bytes);\n}\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data) {\n if (typeof data === 'string')\n data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n/**\n * Helper for KDFs: consumes uint8array or string.\n * When string is passed, does utf8 decoding, using TextDecoder.\n */\nexport function kdfInputToBytes(data) {\n if (typeof data === 'string')\n data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n/** Copies several Uint8Arrays into one. */\nexport function concatBytes(...arrays) {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\nexport function checkOpts(defaults, opts) {\n if (opts !== undefined && {}.toString.call(opts) !== '[object Object]')\n throw new Error('options should be object or undefined');\n const merged = Object.assign(defaults, opts);\n return merged;\n}\n/** For runtime check if class implements interface */\nexport class Hash {\n}\n/** Wraps hash function, creating an interface on top of it */\nexport function createHasher(hashCons) {\n const hashC = (msg) => hashCons().update(toBytes(msg)).digest();\n const tmp = hashCons();\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = () => hashCons();\n return hashC;\n}\nexport function createOptHasher(hashCons) {\n const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({});\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts) => hashCons(opts);\n return hashC;\n}\nexport function createXOFer(hashCons) {\n const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({});\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts) => hashCons(opts);\n return hashC;\n}\nexport const wrapConstructor = createHasher;\nexport const wrapConstructorWithOpts = createOptHasher;\nexport const wrapXOFConstructorWithOpts = createXOFer;\n/** Cryptographically secure PRNG. Uses internal OS-level `crypto.getRandomValues`. */\nexport function randomBytes(bytesLength = 32) {\n if (crypto && typeof crypto.getRandomValues === 'function') {\n return crypto.getRandomValues(new Uint8Array(bytesLength));\n }\n // Legacy Node.js compatibility\n if (crypto && typeof crypto.randomBytes === 'function') {\n return Uint8Array.from(crypto.randomBytes(bytesLength));\n }\n throw new Error('crypto.getRandomValues must be defined');\n}\n//# sourceMappingURL=utils.js.map","import { naddrEncode, neventEncode, noteEncode, nprofileEncode, npubEncode, nsecEncode, } from \"nostr-tools/nip19\";\nimport { getPublicKey, kinds, nip19 } from \"nostr-tools\";\n// export nip-19 helpers\nexport { naddrEncode, neventEncode, noteEncode, nprofileEncode, npubEncode, nsecEncode, decode as decodePointer, } from \"nostr-tools/nip19\";\nimport { getReplaceableIdentifier } from \"./event.js\";\nimport { isAddressableKind, isReplaceableKind } from \"nostr-tools/kinds\";\nimport { isSafeRelayURL, relaySet } from \"./relays.js\";\nimport { isHexKey } from \"./string.js\";\nimport { hexToBytes } from \"@noble/hashes/utils\";\nimport { normalizeURL } from \"./url.js\";\nexport function parseCoordinate(a, requireD = false, silent = true) {\n const parts = a.split(\":\");\n const kind = parts[0] ? parseInt(parts[0]) : undefined;\n const pubkey = parts[1];\n const d = parts[2];\n if (kind === undefined) {\n if (silent)\n return null;\n else\n throw new Error(\"Missing kind\");\n }\n if (pubkey === undefined || pubkey === \"\") {\n if (silent)\n return null;\n else\n throw new Error(\"Missing pubkey\");\n }\n if (requireD && d === undefined) {\n if (silent)\n return null;\n else\n throw new Error(\"Missing identifier\");\n }\n return {\n kind,\n pubkey,\n identifier: d,\n };\n}\n/** Extra a pubkey from the result of nip19.decode */\nexport function getPubkeyFromDecodeResult(result) {\n if (!result)\n return;\n switch (result.type) {\n case \"naddr\":\n case \"nprofile\":\n return result.data.pubkey;\n case \"npub\":\n return result.data;\n case \"nsec\":\n return getPublicKey(result.data);\n default:\n return undefined;\n }\n}\n/** Gets the relays from a decode result */\nexport function getRelaysFromDecodeResult(result) {\n if (!result)\n return;\n switch (result.type) {\n case \"naddr\":\n return result.data.relays;\n case \"nprofile\":\n return result.data.relays;\n case \"nevent\":\n return result.data.relays;\n }\n return undefined;\n}\n/** Encodes the result of nip19.decode */\nexport function encodeDecodeResult(result) {\n switch (result.type) {\n case \"naddr\":\n return naddrEncode(result.data);\n case \"nprofile\":\n return nprofileEncode(result.data);\n case \"nevent\":\n return neventEncode(result.data);\n case \"nsec\":\n return nsecEncode(result.data);\n case \"npub\":\n return npubEncode(result.data);\n case \"note\":\n return noteEncode(result.data);\n }\n return \"\";\n}\n/**\n * Gets an EventPointer form a common \"e\" tag\n * @throws\n */\nexport function getEventPointerFromETag(tag) {\n if (!tag[1])\n throw new Error(\"Missing event id in tag\");\n let pointer = { id: tag[1] };\n if (tag[2] && isSafeRelayURL(tag[2]))\n pointer.relays = [tag[2]];\n return pointer;\n}\n/**\n * Gets an EventPointer form a common \"q\" tag\n * @throws if the tag is invalid\n */\nexport function getEventPointerFromQTag(tag) {\n if (!tag[1])\n throw new Error(\"Missing event id in tag\");\n let pointer = { id: tag[1] };\n if (tag[2] && isSafeRelayURL(tag[2]))\n pointer.relays = [tag[2]];\n if (tag[3] && tag[3].length === 64)\n pointer.author = tag[3];\n return pointer;\n}\n/**\n * Get an AddressPointer from a common \"a\" tag\n * @throws if the tag is invalid\n */\nexport function getAddressPointerFromATag(tag) {\n if (!tag[1])\n throw new Error(\"Missing coordinate in tag\");\n const pointer = parseCoordinate(tag[1], true, false);\n if (tag[2] && isSafeRelayURL(tag[2]))\n pointer.relays = [tag[2]];\n return pointer;\n}\n/**\n * Gets a ProfilePointer from a common \"p\" tag\n * @throws if the tag is invalid\n */\nexport function getProfilePointerFromPTag(tag) {\n if (!tag[1])\n throw new Error(\"Missing pubkey in tag\");\n if (!isHexKey(tag[1]))\n throw new Error(\"Invalid pubkey\");\n const pointer = { pubkey: tag[1] };\n if (tag[2] && isSafeRelayURL(tag[2]))\n pointer.relays = [normalizeURL(tag[2])];\n return pointer;\n}\n/** Checks if a pointer is an AddressPointer */\nexport function isAddressPointer(pointer) {\n return (typeof pointer !== \"string\" &&\n Reflect.has(pointer, \"identifier\") &&\n Reflect.has(pointer, \"pubkey\") &&\n Reflect.has(pointer, \"kind\"));\n}\n/** Checks if a pointer is an EventPointer */\nexport function isEventPointer(pointer) {\n return typeof pointer !== \"string\" && Reflect.has(pointer, \"id\");\n}\n/** Returns the coordinate string for an AddressPointer */\nexport function getCoordinateFromAddressPointer(pointer) {\n return pointer.kind + \":\" + pointer.pubkey + \":\" + pointer.identifier;\n}\n/**\n * Returns an AddressPointer for a replaceable event\n * @throws if the event is not replaceable or addressable\n */\nexport function getAddressPointerForEvent(event, relays) {\n if (!isAddressableKind(event.kind) && !isReplaceableKind(event.kind))\n throw new Error(\"Cant get AddressPointer for non-replaceable event\");\n const d = getReplaceableIdentifier(event);\n return {\n identifier: d,\n kind: event.kind,\n pubkey: event.pubkey,\n relays,\n };\n}\n/** Returns an EventPointer for an event */\nexport function getEventPointerForEvent(event, relays) {\n return {\n id: event.id,\n kind: event.kind,\n author: event.pubkey,\n relays,\n };\n}\n/** Returns a pointer for a given event */\nexport function getPointerForEvent(event, relays) {\n if (kinds.isAddressableKind(event.kind) || kinds.isReplaceableKind(event.kind)) {\n return {\n type: \"naddr\",\n data: getAddressPointerForEvent(event, relays),\n };\n }\n else {\n return {\n type: \"nevent\",\n data: getEventPointerForEvent(event, relays),\n };\n }\n}\n/** Adds relay hints to a pointer object that has a relays array */\nexport function addRelayHintsToPointer(pointer, relays) {\n if (!relays)\n return pointer;\n else\n return { ...pointer, relays: relaySet(relays, pointer.relays) };\n}\n/** Gets the hex pubkey from any nip-19 encoded string */\nexport function normalizeToPubkey(str) {\n if (isHexKey(str))\n return str.toLowerCase();\n else {\n const decode = nip19.decode(str);\n const pubkey = getPubkeyFromDecodeResult(decode);\n if (!pubkey)\n throw new Error(`Cant find pubkey in ${decode.type}`);\n return pubkey;\n }\n}\n/** Gets a ProfilePointer from any nip-19 encoded string */\nexport function normalizeToProfilePointer(str) {\n if (isHexKey(str))\n return { pubkey: str.toLowerCase() };\n else {\n const decode = nip19.decode(str);\n // Return it if it's a profile pointer\n if (decode.type === \"nprofile\")\n return decode.data;\n // fallback to just getting the pubkey\n const pubkey = getPubkeyFromDecodeResult(decode);\n if (!pubkey)\n throw new Error(`Cant find pubkey in ${decode.type}`);\n const relays = getRelaysFromDecodeResult(decode);\n return { pubkey, relays };\n }\n}\n/** Converts hex to nsec strings into Uint8 secret keys */\nexport function normalizeToSecretKey(str) {\n if (str instanceof Uint8Array)\n return str;\n else if (isHexKey(str))\n return hexToBytes(str);\n else {\n const decode = nip19.decode(str);\n if (decode.type !== \"nsec\")\n throw new Error(`Cant get secret key from ${decode.type}`);\n return decode.data;\n }\n}\n/**\n * Merges two event points and keeps all relays\n * @throws if the ids are different\n */\nexport function mergeEventPointers(a, b) {\n if (a.id !== b.id)\n throw new Error(\"Cant merge event pointers with different ids\");\n const relays = relaySet(a.relays, b.relays);\n return { id: a.id, kind: a.kind ?? b.kind, author: a.author ?? b.author, relays };\n}\n/**\n * Merges two address pointers and keeps all relays\n * @throws if the kinds, pubkeys, or identifiers are different\n */\nexport function mergeAddressPointers(a, b) {\n if (a.kind !== b.kind || a.pubkey !== b.pubkey || a.identifier !== b.identifier)\n throw new Error(\"Cant merge address pointers with different kinds, pubkeys, or identifiers\");\n const relays = relaySet(a.relays, b.relays);\n return { ...a, relays };\n}\n/**\n * Merges two profile pointers and keeps all relays\n * @throws if the pubkeys are different\n */\nexport function mergeProfilePointers(a, b) {\n if (a.pubkey !== b.pubkey)\n throw new Error(\"Cant merge profile pointers with different pubkeys\");\n const relays = relaySet(a.relays, b.relays);\n return { ...a, relays };\n}\n","import { getOrComputeCachedValue } from \"./cache.js\";\nimport { getHiddenTags } from \"./hidden-tags.js\";\nimport { processTags } from \"./tags.js\";\nimport { normalizeURL } from \"./url.js\";\nexport const GROUPS_LIST_KIND = 10009;\nexport const GROUP_MESSAGE_KIND = 9;\n/** decodes a group identifier into a group pointer object */\nexport function decodeGroupPointer(str) {\n let [relay, id] = str.split(\"'\");\n if (!relay)\n return null;\n // Prepend wss:// if missing\n if (!relay.match(/^wss?:/))\n relay = `wss://${relay}`;\n // Normalize the relay url\n relay = normalizeURL(relay);\n return { relay, id: id || \"_\" };\n}\n/** Converts a group pointer into a group identifier */\nexport function encodeGroupPointer(pointer) {\n const hostname = URL.canParse(pointer.relay) ? new URL(pointer.relay).hostname : pointer.relay;\n return `${hostname}'${pointer.id}`;\n}\nexport const GroupsPublicSymbol = Symbol.for(\"groups-public\");\nexport const GroupsHiddenSymbol = Symbol.for(\"groups-hidden\");\n/** gets a {@link GroupPointer} from a \"h\" tag if it has a relay hint */\nexport function getGroupPointerFromHTag(tag) {\n const [_, id, relay] = tag;\n if (!id || !relay)\n return undefined;\n return { id, relay };\n}\n/** gets a {@link GroupPointer} from a \"group\" tag */\nexport function getGroupPointerFromGroupTag(tag) {\n const [_, id, relay, name] = tag;\n return { id, relay, name };\n}\n/** Returns all the public groups from a k:10009 list */\nexport function getPublicGroups(bookmark) {\n return getOrComputeCachedValue(bookmark, GroupsPublicSymbol, () => processTags(bookmark.tags.filter((t) => t[0] === \"group\"), getGroupPointerFromGroupTag));\n}\n/** Returns all the hidden groups from a k:10009 list */\nexport function getHiddenGroups(bookmark) {\n return getOrComputeCachedValue(bookmark, GroupsHiddenSymbol, () => {\n const tags = getHiddenTags(bookmark);\n return (tags &&\n processTags(bookmark.tags.filter((t) => t[0] === \"group\"), getGroupPointerFromGroupTag));\n });\n}\n","import { kinds } from \"nostr-tools\";\nimport { notifyEventUpdate } from \"./event.js\";\n/** A symbol use to store the encrypted content of an event in memory */\nexport const EncryptedContentSymbol = Symbol.for(\"encrypted-content\");\n/** Various event kinds that can have encrypted content and which encryption method they use */\nexport const EventContentEncryptionMethod = {\n [kinds.EncryptedDirectMessage]: \"nip04\",\n [kinds.Seal]: \"nip44\",\n [kinds.GiftWrap]: \"nip44\",\n};\n/** Sets the encryption method that is used for the contents of a specific event kind */\nexport function setEncryptedContentEncryptionMethod(kind, method) {\n EventContentEncryptionMethod[kind] = method;\n return kind;\n}\n/**\n * Returns either nip04 or nip44 encryption methods depending on event kind\n * @param kind The event kind to get the encryption method for\n * @param signer The signer to use to get the encryption methods\n * @param override The encryption method to use instead of the default\n * @throws If the event kind does not support encrypted content\n * @throws If the signer does not support the encryption method\n * @returns The encryption methods for the event kind\n */\nexport function getEncryptedContentEncryptionMethods(kind, signer, override) {\n const method = override ?? EventContentEncryptionMethod[kind];\n if (!method)\n throw new Error(`Event kind ${kind} does not support encrypted content`);\n const encryption = signer[method];\n if (!encryption)\n throw new Error(`Signer does not support ${method} encryption`);\n return encryption;\n}\n/** Checks if an event can have encrypted content */\nexport function canHaveEncryptedContent(kind) {\n return EventContentEncryptionMethod[kind] !== undefined;\n}\n/** Checks if an event has encrypted content */\nexport function hasEncryptedContent(event) {\n return event.content.length > 0;\n}\nexport function getEncryptedContent(event) {\n return Reflect.get(event, EncryptedContentSymbol);\n}\n/** Checks if the encrypted content is unlocked and casts it to the {@link UnlockedEncryptedContent} type */\nexport function isEncryptedContentUnlocked(event) {\n return Reflect.has(event, EncryptedContentSymbol) === true;\n}\n/**\n * Unlocks the encrypted content in an event and caches it\n * @param event The event with content to decrypt\n * @param pubkey The other pubkey that encrypted the content\n * @param signer A signer to use to decrypt the content\n * @throws If the event kind does not support encrypted content\n */\nexport async function unlockEncryptedContent(event, pubkey, signer) {\n if (!canHaveEncryptedContent(event.kind))\n throw new Error(\"Event kind does not support encrypted content\");\n // Get the encryption methods from the signer\n const encryption = getEncryptedContentEncryptionMethods(event.kind, signer);\n const plaintext = await encryption.decrypt(pubkey, event.content);\n // Set the cached value and trigger update\n setEncryptedContentCache(event, plaintext);\n // Return the decrypted content\n return plaintext;\n}\n/** Sets the encrypted content on an event and updates it if its part of an event store */\nexport function setEncryptedContentCache(event, plaintext) {\n Reflect.set(event, EncryptedContentSymbol, plaintext);\n // if the event has been added to an event store, notify it\n notifyEventUpdate(event);\n}\n/** Removes the encrypted content cache on an event */\nexport function lockEncryptedContent(event) {\n Reflect.deleteProperty(event, EncryptedContentSymbol);\n // if the event has been added to an event store, notify it\n notifyEventUpdate(event);\n}\n","import { kinds } from \"nostr-tools\";\nimport { canHaveEncryptedContent, EncryptedContentSymbol, getEncryptedContent, getEncryptedContentEncryptionMethods, hasEncryptedContent, isEncryptedContentUnlocked, lockEncryptedContent, setEncryptedContentCache, setEncryptedContentEncryptionMethod, } from \"./encrypted-content.js\";\n/** Symbol for caching hidden content. Alias for {@link EncryptedContentSymbol} */\nexport const HiddenContentSymbol = EncryptedContentSymbol;\n/** Alias for {@link getEncryptedContentEncryptionMethods} */\nexport const getHiddenContentEncryptionMethods = getEncryptedContentEncryptionMethods;\n/** Various event kinds that can have hidden content */\nexport const HiddenContentKinds = new Set([setEncryptedContentEncryptionMethod(kinds.DraftLong, \"nip04\")]);\n/** Sets the encryption method for hidden content on a kind */\nexport function setHiddenContentEncryptionMethod(kind, method) {\n HiddenContentKinds.add(setEncryptedContentEncryptionMethod(kind, method));\n return kind;\n}\n/** Checks if an event can have hidden content */\nexport function canHaveHiddenContent(kind) {\n return canHaveEncryptedContent(kind) && HiddenContentKinds.has(kind);\n}\n/** Checks if an event has hidden content */\nexport function hasHiddenContent(event) {\n return canHaveHiddenContent(event.kind) && hasEncryptedContent(event);\n}\n/** Checks if the hidden content is unlocked and casts it to the {@link UnlockedEncryptedContent} type */\nexport function isHiddenContentUnlocked(event) {\n if (!canHaveHiddenContent(event.kind))\n return false;\n return isEncryptedContentUnlocked(event) && Reflect.has(event, HiddenContentSymbol) === true;\n}\nexport function getHiddenContent(event) {\n if (!canHaveHiddenContent(event.kind))\n return undefined;\n if (isHiddenContentUnlocked(event))\n return event[EncryptedContentSymbol];\n return getEncryptedContent(event);\n}\n/**\n * Unlocks the hidden content in the event\n * @param event The event with content to decrypt\n * @param signer A signer to use to decrypt the content\n * @throws\n */\nexport async function unlockHiddenContent(event, signer, override) {\n if (!canHaveHiddenContent(event.kind))\n throw new Error(\"Event kind does not support hidden content\");\n // If the encrypted content is already unlocked, return the cached value\n if (isEncryptedContentUnlocked(event))\n return event[EncryptedContentSymbol];\n // Get the encryption method from the signer\n const encryption = getEncryptedContentEncryptionMethods(event.kind, signer, override);\n // Decrypt the content using the events pubkey\n const plaintext = await encryption.decrypt(event.pubkey, event.content);\n // Set the cached value\n setHiddenContentCache(event, plaintext);\n // Return the decrypted content\n return plaintext;\n}\n/**\n * Sets the hidden content on an event and updates it if its part of an event store\n * @throws If the event kind does not support hidden content\n */\nexport function setHiddenContentCache(event, plaintext) {\n if (!canHaveHiddenContent(event.kind))\n throw new Error(\"Event kind does not support hidden content\");\n // Set the encrypted content\n setEncryptedContentCache(event, plaintext);\n}\n/** Removes the unencrypted hidden content on an event */\nexport function lockHiddenContent(event) {\n lockEncryptedContent(event);\n}\n","import { kinds } from \"nostr-tools\";\nimport { GROUPS_LIST_KIND } from \"./groups.js\";\nimport { canHaveHiddenContent, getHiddenContent, getHiddenContentEncryptionMethods, hasHiddenContent, isHiddenContentUnlocked, lockHiddenContent, setHiddenContentCache, setHiddenContentEncryptionMethod, unlockHiddenContent, } from \"./hidden-content.js\";\n/** Symbol for caching hidden tags. */\nexport const HiddenTagsSymbol = Symbol.for(\"hidden-tags\");\n/** Various event kinds that can have hidden tags */\nexport const HiddenTagsKinds = new Set([\n // NIP-51 lists\n setHiddenContentEncryptionMethod(kinds.BookmarkList, \"nip04\"),\n setHiddenContentEncryptionMethod(kinds.InterestsList, \"nip04\"),\n setHiddenContentEncryptionMethod(kinds.Mutelist, \"nip04\"),\n setHiddenContentEncryptionMethod(kinds.CommunitiesList, \"nip04\"),\n setHiddenContentEncryptionMethod(kinds.PublicChatsList, \"nip04\"),\n setHiddenContentEncryptionMethod(kinds.SearchRelaysList, \"nip04\"),\n setHiddenContentEncryptionMethod(GROUPS_LIST_KIND, \"nip04\"),\n // NIP-51 sets\n setHiddenContentEncryptionMethod(kinds.Bookmarksets, \"nip04\"),\n setHiddenContentEncryptionMethod(kinds.Relaysets, \"nip04\"),\n setHiddenContentEncryptionMethod(kinds.Followsets, \"nip04\"),\n setHiddenContentEncryptionMethod(kinds.Curationsets, \"nip04\"),\n setHiddenContentEncryptionMethod(kinds.Interestsets, \"nip04\"),\n]);\n/** Checks if an event can have hidden tags */\nexport function canHaveHiddenTags(kind) {\n return canHaveHiddenContent(kind) && HiddenTagsKinds.has(kind);\n}\n/** Sets the type of encryption to use for hidden tags on a kind */\nexport function setHiddenTagsEncryptionMethod(kind, method) {\n HiddenTagsKinds.add(setHiddenContentEncryptionMethod(kind, method));\n return kind;\n}\n/** Checks if an event has hidden tags */\nexport function hasHiddenTags(event) {\n return canHaveHiddenTags(event.kind) && hasHiddenContent(event);\n}\n/** Returns either nip04 or nip44 encryption method depending on list kind */\nexport function getHiddenTagsEncryptionMethods(kind, signer) {\n return getHiddenContentEncryptionMethods(kind, signer);\n}\n/** Checks if the hidden tags are locked and casts it to the {@link UnlockedHiddenTags} type */\nexport function isHiddenTagsUnlocked(event) {\n if (!canHaveHiddenTags(event.kind))\n return false;\n return isHiddenContentUnlocked(event) && Reflect.has(event, `HiddenTagsSymbol`);\n}\nexport function getHiddenTags(event) {\n if (!canHaveHiddenTags(event.kind))\n return undefined;\n // If the hidden tags are already unlocked, return the cached value\n if (isHiddenTagsUnlocked(event))\n return event[HiddenTagsSymbol];\n // unlock hidden content is needed\n const content = getHiddenContent(event);\n // Return undefined if the hidden content is not unlocked\n if (content === undefined)\n return undefined;\n // Parse the hidden content as an array of tags\n const parsed = JSON.parse(content);\n // Throw error if content is not an array of tags\n if (!Array.isArray(parsed))\n throw new Error(\"Content is not an array of tags\");\n // Convert array to tags array string[][]\n const tags = parsed.filter((t) => Array.isArray(t)).map((t) => t.map((v) => String(v)));\n // Set the cached value\n Reflect.set(event, HiddenTagsSymbol, tags);\n return tags;\n}\n/**\n * Decrypts the private list\n * @param event The list event to decrypt\n * @param signer A signer to use to decrypt the tags\n * @param override The encryption method to use instead of the default\n * @throws\n */\nexport async function unlockHiddenTags(event, signer, override) {\n if (!canHaveHiddenTags(event.kind))\n throw new Error(\"Event kind does not support hidden tags\");\n // Return the cached value if the hidden tags are already unlocked\n if (isHiddenTagsUnlocked(event))\n return event[HiddenTagsSymbol];\n // Unlock hidden content\n await unlockHiddenContent(event, signer, override);\n // Parse the hidden tags\n const tags = getHiddenTags(event);\n if (tags === undefined)\n throw new Error(\"Failed to unlock hidden tags\");\n // Set cache an notify event store\n setHiddenTagsCache(event, tags);\n return tags;\n}\n/**\n * Sets the hidden tags on an event and updates it if its part of an event store\n * @throws If the event kind does not support hidden tags\n */\nexport function setHiddenTagsCache(event, tags) {\n if (!canHaveHiddenTags(event.kind))\n throw new Error(\"Event kind does not support hidden tags\");\n // Set the cached value\n Reflect.set(event, HiddenTagsSymbol, tags);\n // Set the cached content\n setHiddenContentCache(event, JSON.stringify(tags));\n}\n/** Clears the cached hidden tags on an event */\nexport function lockHiddenTags(event) {\n Reflect.deleteProperty(event, HiddenTagsSymbol);\n lockHiddenContent(event);\n}\n","import { getHiddenTags } from \"./hidden-tags.js\";\nconst LETTERS = \"abcdefghijklmnopqrstuvwxyz\";\nexport const INDEXABLE_TAGS = new Set((LETTERS + LETTERS.toUpperCase()).split(\"\"));\nexport const EventIndexableTagsSymbol = Symbol.for(\"indexable-tags\");\n/**\n * Returns the second index ( tag[1] ) of the first tag that matches the name\n * If the event has any hidden tags they will be searched first\n */\nexport function getTagValue(event, name) {\n const hidden = getHiddenTags(event);\n const hiddenValue = hidden?.find((t) => t[0] === name)?.[1];\n if (hiddenValue)\n return hiddenValue;\n return event.tags.find((t) => t[0] === name)?.[1];\n}\n/** Checks if an event has a public name / value tag*/\nexport function hasNameValueTag(event, name, value) {\n return event.tags.some((t) => t[0] === name && t[1] === value);\n}\n/** Returns a Set of tag names and values that are indexable */\nexport function getIndexableTags(event) {\n let indexable = Reflect.get(event, EventIndexableTagsSymbol);\n if (!indexable) {\n const tags = new Set();\n for (const tag of event.tags) {\n if (tag.length >= 2 && tag[0].length === 1 && INDEXABLE_TAGS.has(tag[0])) {\n tags.add(tag[0] + \":\" + tag[1]);\n }\n }\n indexable = tags;\n Reflect.set(event, EventIndexableTagsSymbol, tags);\n }\n return indexable;\n}\n","/**\n * Copied from tiny-lru and modified to support typescript\n * @see https://github.com/avoidwork/tiny-lru/blob/master/src/lru.js\n */\nexport class LRU {\n first = null;\n items = Object.create(null);\n last = null;\n max;\n resetTtl;\n size;\n ttl;\n constructor(max = 0, ttl = 0, resetTtl = false) {\n this.first = null;\n this.items = Object.create(null);\n this.last = null;\n this.max = max;\n this.resetTtl = resetTtl;\n this.size = 0;\n this.ttl = ttl;\n }\n clear() {\n this.first = null;\n this.items = Object.create(null);\n this.last = null;\n this.size = 0;\n return this;\n }\n delete(key) {\n if (this.has(key)) {\n const item = this.items[key];\n delete this.items[key];\n this.size--;\n if (item.prev !== null) {\n item.prev.next = item.next;\n }\n if (item.next !== null) {\n item.next.prev = item.prev;\n }\n if (this.first === item) {\n this.first = item.next;\n }\n if (this.last === item) {\n this.last = item.prev;\n }\n }\n return this;\n }\n entries(keys = this.keys()) {\n return keys.map((key) => [key, this.get(key)]);\n }\n evict(bypass = false) {\n if (bypass || this.size > 0) {\n const item = this.first;\n delete this.items[item.key];\n if (--this.size === 0) {\n this.first = null;\n this.last = null;\n }\n else {\n this.first = item.next;\n this.first.prev = null;\n }\n }\n return this;\n }\n expiresAt(key) {\n let result;\n if (this.has(key)) {\n result = this.items[key].expiry;\n }\n return result;\n }\n get(key) {\n let result;\n if (this.has(key)) {\n const item = this.items[key];\n if (this.ttl > 0 && item.expiry <= Date.now()) {\n this.delete(key);\n }\n else {\n result = item.value;\n this.set(key, result, true);\n }\n }\n return result;\n }\n has(key) {\n return key in this.items;\n }\n keys() {\n const result = [];\n let x = this.first;\n while (x !== null) {\n result.push(x.key);\n x = x.next;\n }\n return result;\n }\n set(key, value, bypass = false, resetTtl = this.resetTtl) {\n let item;\n if (bypass || this.has(key)) {\n item = this.items[key];\n item.value = value;\n if (bypass === false && resetTtl) {\n item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\n }\n if (this.last !== item) {\n const last = this.last, next = item.next, prev = item.prev;\n if (this.first === item) {\n this.first = item.next;\n }\n item.next = null;\n item.prev = this.last;\n last.next = item;\n if (prev !== null) {\n prev.next = next;\n }\n if (next !== null) {\n next.prev = prev;\n }\n }\n }\n else {\n if (this.max > 0 && this.size === this.max) {\n this.evict(true);\n }\n item = this.items[key] = {\n expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\n key: key,\n prev: this.last,\n next: null,\n value,\n };\n if (++this.size === 1) {\n this.first = item;\n }\n else {\n this.last.next = item;\n }\n }\n this.last = item;\n return this;\n }\n values(keys = this.keys()) {\n return keys.map((key) => this.get(key));\n }\n}\n","/**\n * Helpers.\n */\n\nvar s = 1000;\nvar m = s * 60;\nvar h = m * 60;\nvar d = h * 24;\nvar w = d * 7;\nvar y = d * 365.25;\n\n/**\n * Parse or format the given `val`.\n *\n * Options:\n *\n * - `long` verbose formatting [false]\n *\n * @param {String|Number} val\n * @param {Object} [options]\n * @throws {Error} throw an error if val is not a non-empty string or a number\n * @return {String|Number}\n * @api public\n */\n\nmodule.exports = function (val, options) {\n options = options || {};\n var type = typeof val;\n if (type === 'string' && val.length > 0) {\n return parse(val);\n } else if (type === 'number' && isFinite(val)) {\n return options.long ? fmtLong(val) : fmtShort(val);\n }\n throw new Error(\n 'val is not a non-empty string or a valid number. val=' +\n JSON.stringify(val)\n );\n};\n\n/**\n * Parse the given `str` and return milliseconds.\n *\n * @param {String} str\n * @return {Number}\n * @api private\n */\n\nfunction parse(str) {\n str = String(str);\n if (str.length > 100) {\n return;\n }\n var match = /^(-?(?:\\d+)?\\.?\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(\n str\n );\n if (!match) {\n return;\n }\n var n = parseFloat(match[1]);\n var type = (match[2] || 'ms').toLowerCase();\n switch (type) {\n case 'years':\n case 'year':\n case 'yrs':\n case 'yr':\n case 'y':\n return n * y;\n case 'weeks':\n case 'week':\n case 'w':\n return n * w;\n case 'days':\n case 'day':\n case 'd':\n return n * d;\n case 'hours':\n case 'hour':\n case 'hrs':\n case 'hr':\n case 'h':\n return n * h;\n case 'minutes':\n case 'minute':\n case 'mins':\n case 'min':\n case 'm':\n return n * m;\n case 'seconds':\n case 'second':\n case 'secs':\n case 'sec':\n case 's':\n return n * s;\n case 'milliseconds':\n case 'millisecond':\n case 'msecs':\n case 'msec':\n case 'ms':\n return n;\n default:\n return undefined;\n }\n}\n\n/**\n * Short format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtShort(ms) {\n var msAbs = Math.abs(ms);\n if (msAbs >= d) {\n return Math.round(ms / d) + 'd';\n }\n if (msAbs >= h) {\n return Math.round(ms / h) + 'h';\n }\n if (msAbs >= m) {\n return Math.round(ms / m) + 'm';\n }\n if (msAbs >= s) {\n return Math.round(ms / s) + 's';\n }\n return ms + 'ms';\n}\n\n/**\n * Long format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtLong(ms) {\n var msAbs = Math.abs(ms);\n if (msAbs >= d) {\n return plural(ms, msAbs, d, 'day');\n }\n if (msAbs >= h) {\n return plural(ms, msAbs, h, 'hour');\n }\n if (msAbs >= m) {\n return plural(ms, msAbs, m, 'minute');\n }\n if (msAbs >= s) {\n return plural(ms, msAbs, s, 'second');\n }\n return ms + ' ms';\n}\n\n/**\n * Pluralization helper.\n */\n\nfunction plural(ms, msAbs, n, name) {\n var isPlural = msAbs >= n * 1.5;\n return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');\n}\n","\n/**\n * This is the common logic for both the Node.js and web browser\n * implementations of `debug()`.\n */\n\nfunction setup(env) {\n\tcreateDebug.debug = createDebug;\n\tcreateDebug.default = createDebug;\n\tcreateDebug.coerce = coerce;\n\tcreateDebug.disable = disable;\n\tcreateDebug.enable = enable;\n\tcreateDebug.enabled = enabled;\n\tcreateDebug.humanize = require('ms');\n\tcreateDebug.destroy = destroy;\n\n\tObject.keys(env).forEach(key => {\n\t\tcreateDebug[key] = env[key];\n\t});\n\n\t/**\n\t* The currently active debug mode names, and names to skip.\n\t*/\n\n\tcreateDebug.names = [];\n\tcreateDebug.skips = [];\n\n\t/**\n\t* Map of special \"%n\" handling functions, for the debug \"format\" argument.\n\t*\n\t* Valid key names are a single, lower or upper-case letter, i.e. \"n\" and \"N\".\n\t*/\n\tcreateDebug.formatters = {};\n\n\t/**\n\t* Selects a color for a debug namespace\n\t* @param {String} namespace The namespace string for the debug instance to be colored\n\t* @return {Number|String} An ANSI color code for the given namespace\n\t* @api private\n\t*/\n\tfunction selectColor(namespace) {\n\t\tlet hash = 0;\n\n\t\tfor (let i = 0; i < namespace.length; i++) {\n\t\t\thash = ((hash << 5) - hash) + namespace.charCodeAt(i);\n\t\t\thash |= 0; // Convert to 32bit integer\n\t\t}\n\n\t\treturn createDebug.colors[Math.abs(hash) % createDebug.colors.length];\n\t}\n\tcreateDebug.selectColor = selectColor;\n\n\t/**\n\t* Create a debugger with the given `namespace`.\n\t*\n\t* @param {String} namespace\n\t* @return {Function}\n\t* @api public\n\t*/\n\tfunction createDebug(namespace) {\n\t\tlet prevTime;\n\t\tlet enableOverride = null;\n\t\tlet namespacesCache;\n\t\tlet enabledCache;\n\n\t\tfunction debug(...args) {\n\t\t\t// Disabled?\n\t\t\tif (!debug.enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst self = debug;\n\n\t\t\t// Set `diff` timestamp\n\t\t\tconst curr = Number(new Date());\n\t\t\tconst ms = curr - (prevTime || curr);\n\t\t\tself.diff = ms;\n\t\t\tself.prev = prevTime;\n\t\t\tself.curr = curr;\n\t\t\tprevTime = curr;\n\n\t\t\targs[0] = createDebug.coerce(args[0]);\n\n\t\t\tif (typeof args[0] !== 'string') {\n\t\t\t\t// Anything else let's inspect with %O\n\t\t\t\targs.unshift('%O');\n\t\t\t}\n\n\t\t\t// Apply any `formatters` transformations\n\t\t\tlet index = 0;\n\t\t\targs[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {\n\t\t\t\t// If we encounter an escaped % then don't increase the array index\n\t\t\t\tif (match === '%%') {\n\t\t\t\t\treturn '%';\n\t\t\t\t}\n\t\t\t\tindex++;\n\t\t\t\tconst formatter = createDebug.formatters[format];\n\t\t\t\tif (typeof formatter === 'function') {\n\t\t\t\t\tconst val = args[index];\n\t\t\t\t\tmatch = formatter.call(self, val);\n\n\t\t\t\t\t// Now we need to remove `args[index]` since it's inlined in the `format`\n\t\t\t\t\targs.splice(index, 1);\n\t\t\t\t\tindex--;\n\t\t\t\t}\n\t\t\t\treturn match;\n\t\t\t});\n\n\t\t\t// Apply env-specific formatting (colors, etc.)\n\t\t\tcreateDebug.formatArgs.call(self, args);\n\n\t\t\tconst logFn = self.log || createDebug.log;\n\t\t\tlogFn.apply(self, args);\n\t\t}\n\n\t\tdebug.namespace = namespace;\n\t\tdebug.useColors = createDebug.useColors();\n\t\tdebug.color = createDebug.selectColor(namespace);\n\t\tdebug.extend = extend;\n\t\tdebug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.\n\n\t\tObject.defineProperty(debug, 'enabled', {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: false,\n\t\t\tget: () => {\n\t\t\t\tif (enableOverride !== null) {\n\t\t\t\t\treturn enableOverride;\n\t\t\t\t}\n\t\t\t\tif (namespacesCache !== createDebug.namespaces) {\n\t\t\t\t\tnamespacesCache = createDebug.namespaces;\n\t\t\t\t\tenabledCache = createDebug.enabled(namespace);\n\t\t\t\t}\n\n\t\t\t\treturn enabledCache;\n\t\t\t},\n\t\t\tset: v => {\n\t\t\t\tenableOverride = v;\n\t\t\t}\n\t\t});\n\n\t\t// Env-specific initialization logic for debug instances\n\t\tif (typeof createDebug.init === 'function') {\n\t\t\tcreateDebug.init(debug);\n\t\t}\n\n\t\treturn debug;\n\t}\n\n\tfunction extend(namespace, delimiter) {\n\t\tconst newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);\n\t\tnewDebug.log = this.log;\n\t\treturn newDebug;\n\t}\n\n\t/**\n\t* Enables a debug mode by namespaces. This can include modes\n\t* separated by a colon and wildcards.\n\t*\n\t* @param {String} namespaces\n\t* @api public\n\t*/\n\tfunction enable(namespaces) {\n\t\tcreateDebug.save(namespaces);\n\t\tcreateDebug.namespaces = namespaces;\n\n\t\tcreateDebug.names = [];\n\t\tcreateDebug.skips = [];\n\n\t\tconst split = (typeof namespaces === 'string' ? namespaces : '')\n\t\t\t.trim()\n\t\t\t.replace(/\\s+/g, ',')\n\t\t\t.split(',')\n\t\t\t.filter(Boolean);\n\n\t\tfor (const ns of split) {\n\t\t\tif (ns[0] === '-') {\n\t\t\t\tcreateDebug.skips.push(ns.slice(1));\n\t\t\t} else {\n\t\t\t\tcreateDebug.names.push(ns);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the given string matches a namespace template, honoring\n\t * asterisks as wildcards.\n\t *\n\t * @param {String} search\n\t * @param {String} template\n\t * @return {Boolean}\n\t */\n\tfunction matchesTemplate(search, template) {\n\t\tlet searchIndex = 0;\n\t\tlet templateIndex = 0;\n\t\tlet starIndex = -1;\n\t\tlet matchIndex = 0;\n\n\t\twhile (searchIndex < search.length) {\n\t\t\tif (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {\n\t\t\t\t// Match character or proceed with wildcard\n\t\t\t\tif (template[templateIndex] === '*') {\n\t\t\t\t\tstarIndex = templateIndex;\n\t\t\t\t\tmatchIndex = searchIndex;\n\t\t\t\t\ttemplateIndex++; // Skip the '*'\n\t\t\t\t} else {\n\t\t\t\t\tsearchIndex++;\n\t\t\t\t\ttemplateIndex++;\n\t\t\t\t}\n\t\t\t} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition\n\t\t\t\t// Backtrack to the last '*' and try to match more characters\n\t\t\t\ttemplateIndex = starIndex + 1;\n\t\t\t\tmatchIndex++;\n\t\t\t\tsearchIndex = matchIndex;\n\t\t\t} else {\n\t\t\t\treturn false; // No match\n\t\t\t}\n\t\t}\n\n\t\t// Handle trailing '*' in template\n\t\twhile (templateIndex < template.length && template[templateIndex] === '*') {\n\t\t\ttemplateIndex++;\n\t\t}\n\n\t\treturn templateIndex === template.length;\n\t}\n\n\t/**\n\t* Disable debug output.\n\t*\n\t* @return {String} namespaces\n\t* @api public\n\t*/\n\tfunction disable() {\n\t\tconst namespaces = [\n\t\t\t...createDebug.names,\n\t\t\t...createDebug.skips.map(namespace => '-' + namespace)\n\t\t].join(',');\n\t\tcreateDebug.enable('');\n\t\treturn namespaces;\n\t}\n\n\t/**\n\t* Returns true if the given mode name is enabled, false otherwise.\n\t*\n\t* @param {String} name\n\t* @return {Boolean}\n\t* @api public\n\t*/\n\tfunction enabled(name) {\n\t\tfor (const skip of createDebug.skips) {\n\t\t\tif (matchesTemplate(name, skip)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tfor (const ns of createDebug.names) {\n\t\t\tif (matchesTemplate(name, ns)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t* Coerce `val`.\n\t*\n\t* @param {Mixed} val\n\t* @return {Mixed}\n\t* @api private\n\t*/\n\tfunction coerce(val) {\n\t\tif (val instanceof Error) {\n\t\t\treturn val.stack || val.message;\n\t\t}\n\t\treturn val;\n\t}\n\n\t/**\n\t* XXX DO NOT USE. This is a temporary stub function.\n\t* XXX It WILL be removed in the next major release.\n\t*/\n\tfunction destroy() {\n\t\tconsole.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');\n\t}\n\n\tcreateDebug.enable(createDebug.load());\n\n\treturn createDebug;\n}\n\nmodule.exports = setup;\n","/* eslint-env browser */\n\n/**\n * This is the web browser implementation of `debug()`.\n */\n\nexports.formatArgs = formatArgs;\nexports.save = save;\nexports.load = load;\nexports.useColors = useColors;\nexports.storage = localstorage();\nexports.destroy = (() => {\n\tlet warned = false;\n\n\treturn () => {\n\t\tif (!warned) {\n\t\t\twarned = true;\n\t\t\tconsole.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');\n\t\t}\n\t};\n})();\n\n/**\n * Colors.\n */\n\nexports.colors = [\n\t'#0000CC',\n\t'#0000FF',\n\t'#0033CC',\n\t'#0033FF',\n\t'#0066CC',\n\t'#0066FF',\n\t'#0099CC',\n\t'#0099FF',\n\t'#00CC00',\n\t'#00CC33',\n\t'#00CC66',\n\t'#00CC99',\n\t'#00CCCC',\n\t'#00CCFF',\n\t'#3300CC',\n\t'#3300FF',\n\t'#3333CC',\n\t'#3333FF',\n\t'#3366CC',\n\t'#3366FF',\n\t'#3399CC',\n\t'#3399FF',\n\t'#33CC00',\n\t'#33CC33',\n\t'#33CC66',\n\t'#33CC99',\n\t'#33CCCC',\n\t'#33CCFF',\n\t'#6600CC',\n\t'#6600FF',\n\t'#6633CC',\n\t'#6633FF',\n\t'#66CC00',\n\t'#66CC33',\n\t'#9900CC',\n\t'#9900FF',\n\t'#9933CC',\n\t'#9933FF',\n\t'#99CC00',\n\t'#99CC33',\n\t'#CC0000',\n\t'#CC0033',\n\t'#CC0066',\n\t'#CC0099',\n\t'#CC00CC',\n\t'#CC00FF',\n\t'#CC3300',\n\t'#CC3333',\n\t'#CC3366',\n\t'#CC3399',\n\t'#CC33CC',\n\t'#CC33FF',\n\t'#CC6600',\n\t'#CC6633',\n\t'#CC9900',\n\t'#CC9933',\n\t'#CCCC00',\n\t'#CCCC33',\n\t'#FF0000',\n\t'#FF0033',\n\t'#FF0066',\n\t'#FF0099',\n\t'#FF00CC',\n\t'#FF00FF',\n\t'#FF3300',\n\t'#FF3333',\n\t'#FF3366',\n\t'#FF3399',\n\t'#FF33CC',\n\t'#FF33FF',\n\t'#FF6600',\n\t'#FF6633',\n\t'#FF9900',\n\t'#FF9933',\n\t'#FFCC00',\n\t'#FFCC33'\n];\n\n/**\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\n * and the Firebug extension (any Firefox version) are known\n * to support \"%c\" CSS customizations.\n *\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\n */\n\n// eslint-disable-next-line complexity\nfunction useColors() {\n\t// NB: In an Electron preload script, document will be defined but not fully\n\t// initialized. Since we know we're in Chrome, we'll just detect this case\n\t// explicitly\n\tif (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {\n\t\treturn true;\n\t}\n\n\t// Internet Explorer and Edge do not support colors.\n\tif (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\\/(\\d+)/)) {\n\t\treturn false;\n\t}\n\n\tlet m;\n\n\t// Is webkit? http://stackoverflow.com/a/16459606/376773\n\t// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\n\t// eslint-disable-next-line no-return-assign\n\treturn (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||\n\t\t// Is firebug? http://stackoverflow.com/a/398120/376773\n\t\t(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||\n\t\t// Is firefox >= v31?\n\t\t// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\n\t\t(typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\\/(\\d+)/)) && parseInt(m[1], 10) >= 31) ||\n\t\t// Double check webkit in userAgent just in case we are in a worker\n\t\t(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\\/(\\d+)/));\n}\n\n/**\n * Colorize log arguments if enabled.\n *\n * @api public\n */\n\nfunction formatArgs(args) {\n\targs[0] = (this.useColors ? '%c' : '') +\n\t\tthis.namespace +\n\t\t(this.useColors ? ' %c' : ' ') +\n\t\targs[0] +\n\t\t(this.useColors ? '%c ' : ' ') +\n\t\t'+' + module.exports.humanize(this.diff);\n\n\tif (!this.useColors) {\n\t\treturn;\n\t}\n\n\tconst c = 'color: ' + this.color;\n\targs.splice(1, 0, c, 'color: inherit');\n\n\t// The final \"%c\" is somewhat tricky, because there could be other\n\t// arguments passed either before or after the %c, so we need to\n\t// figure out the correct index to insert the CSS into\n\tlet index = 0;\n\tlet lastC = 0;\n\targs[0].replace(/%[a-zA-Z%]/g, match => {\n\t\tif (match === '%%') {\n\t\t\treturn;\n\t\t}\n\t\tindex++;\n\t\tif (match === '%c') {\n\t\t\t// We only are interested in the *last* %c\n\t\t\t// (the user may have provided their own)\n\t\t\tlastC = index;\n\t\t}\n\t});\n\n\targs.splice(lastC, 0, c);\n}\n\n/**\n * Invokes `console.debug()` when available.\n * No-op when `console.debug` is not a \"function\".\n * If `console.debug` is not available, falls back\n * to `console.log`.\n *\n * @api public\n */\nexports.log = console.debug || console.log || (() => {});\n\n/**\n * Save `namespaces`.\n *\n * @param {String} namespaces\n * @api private\n */\nfunction save(namespaces) {\n\ttry {\n\t\tif (namespaces) {\n\t\t\texports.storage.setItem('debug', namespaces);\n\t\t} else {\n\t\t\texports.storage.removeItem('debug');\n\t\t}\n\t} catch (error) {\n\t\t// Swallow\n\t\t// XXX (@Qix-) should we be logging these?\n\t}\n}\n\n/**\n * Load `namespaces`.\n *\n * @return {String} returns the previously persisted debug modes\n * @api private\n */\nfunction load() {\n\tlet r;\n\ttry {\n\t\tr = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ;\n\t} catch (error) {\n\t\t// Swallow\n\t\t// XXX (@Qix-) should we be logging these?\n\t}\n\n\t// If debug isn't set in LS, and we're in Electron, try to load $DEBUG\n\tif (!r && typeof process !== 'undefined' && 'env' in process) {\n\t\tr = process.env.DEBUG;\n\t}\n\n\treturn r;\n}\n\n/**\n * Localstorage attempts to return the localstorage.\n *\n * This is necessary because safari throws\n * when a user disables cookies/localstorage\n * and you attempt to access it.\n *\n * @return {LocalStorage}\n * @api private\n */\n\nfunction localstorage() {\n\ttry {\n\t\t// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context\n\t\t// The Browser also has localStorage in the global context.\n\t\treturn localStorage;\n\t} catch (error) {\n\t\t// Swallow\n\t\t// XXX (@Qix-) should we be logging these?\n\t}\n}\n\nmodule.exports = require('./common')(exports);\n\nconst {formatters} = module.exports;\n\n/**\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\n */\n\nformatters.j = function (v) {\n\ttry {\n\t\treturn JSON.stringify(v);\n\t} catch (error) {\n\t\treturn '[UnexpectedJSONParseError]: ' + error.message;\n\t}\n};\n","import debug from \"debug\";\n/** @hidden */\nexport const logger = debug(\"applesauce\");\n","import { binarySearch, insertEventIntoDescendingList } from \"nostr-tools/utils\";\nimport { getIndexableTags, INDEXABLE_TAGS } from \"../helpers/event-tags.js\";\nimport { createReplaceableAddress, isReplaceable } from \"../helpers/event.js\";\nimport { LRU } from \"../helpers/lru.js\";\nimport { logger } from \"../logger.js\";\n/** An in-memory database of events */\nexport class EventMemory {\n log = logger.extend(\"EventMemory\");\n /** Indexes */\n kinds = new Map();\n authors = new Map();\n tags = new LRU();\n created_at = [];\n /** Composite index for kind+author queries (common pattern) */\n kindAuthor = new Map();\n /** LRU cache of last events touched */\n events = new LRU();\n /** A sorted array of replaceable events by address */\n replaceable = new Map();\n /** The number of events in the database */\n get size() {\n return this.events.size;\n }\n /** Checks if the database contains an event without touching it */\n hasEvent(id) {\n return this.events.has(id);\n }\n /** Gets a single event based on id */\n getEvent(id) {\n return this.events.get(id);\n }\n /** Checks if the event set has a replaceable event */\n hasReplaceable(kind, pubkey, identifier) {\n const events = this.replaceable.get(createReplaceableAddress(kind, pubkey, identifier));\n return !!events && events.length > 0;\n }\n /** Gets the latest replaceable event */\n getReplaceable(kind, pubkey, identifier) {\n const address = createReplaceableAddress(kind, pubkey, identifier);\n const events = this.replaceable.get(address);\n return events?.[0];\n }\n /** Gets the history of a replaceable event */\n getReplaceableHistory(kind, pubkey, identifier) {\n const address = createReplaceableAddress(kind, pubkey, identifier);\n return this.replaceable.get(address);\n }\n /** Gets all events that match the filters */\n getByFilters(filters) {\n return Array.from(this.getEventsForFilters(Array.isArray(filters) ? filters : [filters]));\n }\n /** Gets a timeline of events that match the filters */\n getTimeline(filters) {\n const timeline = [];\n const events = this.getByFilters(filters);\n for (const event of events)\n insertEventIntoDescendingList(timeline, event);\n return timeline;\n }\n /** Inserts an event into the database and notifies all subscriptions */\n add(event) {\n const id = event.id;\n const current = this.events.get(id);\n if (current)\n return current;\n this.events.set(id, event);\n this.getKindIndex(event.kind).add(event);\n this.getAuthorsIndex(event.pubkey).add(event);\n this.getKindAuthorIndex(event.kind, event.pubkey).add(event);\n // Add the event to the tag indexes if they exist\n for (const tag of getIndexableTags(event)) {\n if (this.tags.has(tag))\n this.getTagIndex(tag).add(event);\n }\n // Insert into time index\n insertEventIntoDescendingList(this.created_at, event);\n // Insert into replaceable index\n if (isReplaceable(event.kind)) {\n const identifier = event.tags.find((t) => t[0] === \"d\")?.[1];\n const address = createReplaceableAddress(event.kind, event.pubkey, identifier);\n let array = this.replaceable.get(address);\n if (!this.replaceable.has(address)) {\n // add an empty array if there is no array\n array = [];\n this.replaceable.set(address, array);\n }\n // insert the event into the sorted array\n insertEventIntoDescendingList(array, event);\n }\n return event;\n }\n /** Removes an event from the database and notifies all subscriptions */\n remove(eventOrId) {\n let event = typeof eventOrId === \"string\" ? this.events.get(eventOrId) : eventOrId;\n if (!event)\n return false;\n const id = event.id;\n // only remove events that are known\n if (!this.events.has(id))\n return false;\n this.getAuthorsIndex(event.pubkey).delete(event);\n this.getKindIndex(event.kind).delete(event);\n // Remove from composite kind+author index\n const kindAuthorKey = `${event.kind}:${event.pubkey}`;\n if (this.kindAuthor.has(kindAuthorKey)) {\n this.kindAuthor.get(kindAuthorKey).delete(event);\n }\n for (const tag of getIndexableTags(event)) {\n if (this.tags.has(tag)) {\n this.getTagIndex(tag).delete(event);\n }\n }\n // remove from created_at index using binary search\n this.removeFromSortedArray(this.created_at, event);\n this.events.delete(id);\n // remove from replaceable index using binary search\n if (isReplaceable(event.kind)) {\n const identifier = event.tags.find((t) => t[0] === \"d\")?.[1];\n const address = createReplaceableAddress(event.kind, event.pubkey, identifier);\n const array = this.replaceable.get(address);\n if (array)\n this.removeFromSortedArray(array, event);\n }\n // remove any claims this event has\n this.claims.delete(event);\n return true;\n }\n /** Remove multiple events that match the given filters */\n removeByFilters(filters) {\n const eventsToRemove = this.getByFilters(filters);\n let removedCount = 0;\n for (const event of eventsToRemove) {\n if (this.remove(event)) {\n removedCount++;\n }\n }\n return removedCount;\n }\n /** Notify the database that an event has updated */\n update(_event) {\n // Do nothing\n }\n /** A weak map of events to claim reference counts */\n claims = new WeakMap();\n /** Moves an event to the top of the LRU cache */\n touch(event) {\n // Make sure the event is in the database before adding it to the LRU\n if (!this.events.has(event.id))\n return;\n // Move to the top of the LRU\n this.events.set(event.id, event);\n }\n /** Increments the claim count on the event and touches it */\n claim(event) {\n const currentCount = this.claims.get(event) || 0;\n this.claims.set(event, currentCount + 1);\n // always touch event\n this.touch(event);\n }\n /** Checks if an event is claimed by anything */\n isClaimed(event) {\n const count = this.claims.get(event);\n return count !== undefined && count > 0;\n }\n /** Decrements the claim count on an event */\n removeClaim(event) {\n const currentCount = this.claims.get(event);\n if (currentCount !== undefined && currentCount > 0) {\n const newCount = currentCount - 1;\n if (newCount === 0) {\n this.claims.delete(event);\n }\n else {\n this.claims.set(event, newCount);\n }\n }\n }\n /** Removes all claims on an event */\n clearClaim(event) {\n this.claims.delete(event);\n }\n /** Returns a generator of unclaimed events in order of least used */\n *unclaimed() {\n let removed = 0;\n let cursor = this.events.first;\n while (cursor) {\n const event = cursor.value;\n if (!this.isClaimed(event))\n yield event;\n cursor = cursor.next;\n }\n return removed;\n }\n /** Removes events that are not claimed (free up memory) */\n prune(limit) {\n let removed = 0;\n const unclaimed = this.unclaimed();\n for (const event of unclaimed) {\n this.remove(event);\n removed++;\n if (limit && removed >= limit)\n break;\n }\n return removed;\n }\n /** Index helper methods */\n getKindIndex(kind) {\n if (!this.kinds.has(kind))\n this.kinds.set(kind, new Set());\n return this.kinds.get(kind);\n }\n getAuthorsIndex(author) {\n if (!this.authors.has(author))\n this.authors.set(author, new Set());\n return this.authors.get(author);\n }\n getKindAuthorIndex(kind, pubkey) {\n const key = `${kind}:${pubkey}`;\n if (!this.kindAuthor.has(key))\n this.kindAuthor.set(key, new Set());\n return this.kindAuthor.get(key);\n }\n getTagIndex(tagAndValue) {\n if (!this.tags.has(tagAndValue)) {\n // build new tag index from existing events\n const events = new Set();\n const ts = Date.now();\n for (const event of this.events.values()) {\n if (getIndexableTags(event).has(tagAndValue)) {\n events.add(event);\n }\n }\n const took = Date.now() - ts;\n if (took > 100)\n this.log(`Built index ${tagAndValue} took ${took}ms`);\n this.tags.set(tagAndValue, events);\n }\n return this.tags.get(tagAndValue);\n }\n /**\n * Helper method to remove an event from a sorted array using binary search.\n * Falls back to indexOf if binary search doesn't find exact match.\n */\n removeFromSortedArray(array, event) {\n if (array.length === 0)\n return;\n // Use binary search to find the approximate position\n const result = binarySearch(array, (mid) => mid.created_at - event.created_at);\n if (result) {\n let index = result[0];\n // Binary search finds the position, but we need to find the exact event\n // since multiple events can have the same created_at timestamp.\n // Search backwards and forwards from the found position\n let found = false;\n // Check the found position first\n if (array[index] === event) {\n array.splice(index, 1);\n return;\n }\n // Search backwards\n for (let i = index - 1; i >= 0 && array[i].created_at === event.created_at; i--) {\n if (array[i] === event) {\n array.splice(i, 1);\n found = true;\n break;\n }\n }\n if (found)\n return;\n // Search forwards\n for (let i = index + 1; i < array.length && array[i].created_at === event.created_at; i++) {\n if (array[i] === event) {\n array.splice(i, 1);\n return;\n }\n }\n }\n // Fallback to indexOf if binary search doesn't find the event\n // This should rarely happen, but ensures correctness\n const idx = array.indexOf(event);\n if (idx !== -1)\n array.splice(idx, 1);\n }\n /** Iterates over all events by author */\n *iterateAuthors(authors) {\n for (const author of authors) {\n const events = this.authors.get(author);\n if (events) {\n for (const event of events)\n yield event;\n }\n }\n }\n /** Iterates over all events by indexable tag and value */\n *iterateTag(tag, values) {\n for (const value of values) {\n const events = this.getTagIndex(tag + \":\" + value);\n if (events) {\n for (const event of events)\n yield event;\n }\n }\n }\n /** Iterates over all events by kind */\n *iterateKinds(kinds) {\n for (const kind of kinds) {\n const events = this.kinds.get(kind);\n if (events) {\n for (const event of events)\n yield event;\n }\n }\n }\n /** Iterates over all events by time */\n *iterateTime(since, until) {\n let startIndex = 0;\n let endIndex = this.created_at.length - 1;\n // If until is set, use binary search to find better start index\n let start = until\n ? binarySearch(this.created_at, (mid) => {\n return mid.created_at - until;\n })\n : undefined;\n if (start)\n startIndex = start[0];\n // If since is set, use binary search to find better end index\n const end = since\n ? binarySearch(this.created_at, (mid) => {\n return mid.created_at - since;\n })\n : undefined;\n if (end)\n endIndex = end[0];\n // Yield events in the range, filtering by exact bounds\n for (let i = startIndex; i <= endIndex; i++) {\n const event = this.created_at[i];\n if (until !== undefined && event.created_at > until)\n continue;\n if (since !== undefined && event.created_at < since)\n break;\n yield event;\n }\n }\n /** Iterates over all events by id */\n *iterateIds(ids) {\n for (const id of ids) {\n if (this.events.has(id))\n yield this.events.get(id);\n }\n }\n /** Returns all events that match the filter */\n getEventsForFilter(filter) {\n // search is not supported, return an empty set\n if (filter.search)\n return new Set();\n let first = true;\n let events = new Set();\n const and = (iterable) => {\n const set = iterable instanceof Set ? iterable : new Set(iterable);\n if (first) {\n events = set;\n first = false;\n }\n else {\n for (const event of events) {\n if (!set.has(event))\n events.delete(event);\n }\n }\n return events;\n };\n if (filter.ids)\n and(this.iterateIds(filter.ids));\n let time = null;\n // query for time first if since is set\n if (filter.since !== undefined) {\n time = Array.from(this.iterateTime(filter.since, filter.until));\n and(time);\n }\n // Process AND tag filters (& prefix) first - NIP-ND\n // AND takes precedence and requires ALL values to be present\n for (const t of INDEXABLE_TAGS) {\n const key = `&${t}`;\n const values = filter[key];\n if (values?.length) {\n // For AND logic, we need to intersect events that have ALL the specified tag values\n // We do this by iterating through each value and intersecting the results\n for (const value of values) {\n and(this.iterateTag(t, [value]));\n }\n }\n }\n // Process OR tag filters (# prefix)\n // Skip values that are in AND tags (NIP-ND rule)\n for (const t of INDEXABLE_TAGS) {\n const key = `#${t}`;\n const values = filter[key];\n if (values?.length) {\n // Check if there's a corresponding AND filter for this tag\n const andKey = `&${t}`;\n const andValues = filter[andKey];\n // Filter out values that are in AND tags (NIP-ND rule)\n const filteredValues = andValues ? values.filter((v) => !andValues.includes(v)) : values;\n // Only apply OR filter if there are values left after filtering\n if (filteredValues.length > 0)\n and(this.iterateTag(t, filteredValues));\n }\n }\n // Optimize: Use composite kind+author index when both are present and the cross-product is small\n if (filter.authors && filter.kinds && filter.authors.length * filter.kinds.length <= 20) {\n const combined = new Set();\n for (const kind of filter.kinds) {\n for (const author of filter.authors) {\n const key = `${kind}:${author}`;\n const kindAuthorEvents = this.kindAuthor.get(key);\n if (kindAuthorEvents) {\n for (const event of kindAuthorEvents)\n combined.add(event);\n }\n }\n }\n and(combined);\n }\n else {\n // Use separate indexes\n if (filter.authors)\n and(this.iterateAuthors(filter.authors));\n if (filter.kinds)\n and(this.iterateKinds(filter.kinds));\n }\n // query for time last if only until is set\n if (filter.since === undefined && filter.until !== undefined) {\n time = Array.from(this.iterateTime(filter.since, filter.until));\n and(time);\n }\n // If no filters were applied (empty filter), return all events\n if (first) {\n return new Set(this.events.values());\n }\n // if the filter queried on time and has a limit. truncate the events now\n if (filter.limit && time) {\n const limited = new Set();\n for (const event of time) {\n if (limited.size >= filter.limit)\n break;\n if (events.has(event))\n limited.add(event);\n }\n return limited;\n }\n return events;\n }\n /** Returns all events that match the filters */\n getEventsForFilters(filters) {\n if (filters.length === 0)\n return new Set();\n let events = new Set();\n for (const filter of filters) {\n const filtered = this.getEventsForFilter(filter);\n for (const event of filtered)\n events.add(event);\n }\n return events;\n }\n /** Resets the event set */\n reset() {\n this.events.clear();\n this.kinds.clear();\n this.authors.clear();\n this.kindAuthor.clear();\n this.tags.clear();\n this.created_at = [];\n this.replaceable.clear();\n this.claims = new WeakMap();\n }\n}\n","'use strict';\n\nfunction pad (hash, len) {\n while (hash.length < len) {\n hash = '0' + hash;\n }\n return hash;\n}\n\nfunction fold (hash, text) {\n var i;\n var chr;\n var len;\n if (text.length === 0) {\n return hash;\n }\n for (i = 0, len = text.length; i < len; i++) {\n chr = text.charCodeAt(i);\n hash = ((hash << 5) - hash) + chr;\n hash |= 0;\n }\n return hash < 0 ? hash * -2 : hash;\n}\n\nfunction foldObject (hash, o, seen) {\n return Object.keys(o).sort().reduce(foldKey, hash);\n function foldKey (hash, key) {\n return foldValue(hash, o[key], key, seen);\n }\n}\n\nfunction foldValue (input, value, key, seen) {\n var hash = fold(fold(fold(input, key), toString(value)), typeof value);\n if (value === null) {\n return fold(hash, 'null');\n }\n if (value === undefined) {\n return fold(hash, 'undefined');\n }\n if (typeof value === 'object' || typeof value === 'function') {\n if (seen.indexOf(value) !== -1) {\n return fold(hash, '[Circular]' + key);\n }\n seen.push(value);\n\n var objHash = foldObject(hash, value, seen)\n\n if (!('valueOf' in value) || typeof value.valueOf !== 'function') {\n return objHash;\n }\n\n try {\n return fold(objHash, String(value.valueOf()))\n } catch (err) {\n return fold(objHash, '[valueOf exception]' + (err.stack || err.message))\n }\n }\n return fold(hash, value.toString());\n}\n\nfunction toString (o) {\n return Object.prototype.toString.call(o);\n}\n\nfunction sum (o) {\n return pad(foldValue(0, o, '', []).toString(16), 8);\n}\n\nmodule.exports = sum;\n","import equal from \"fast-deep-equal\";\nimport { getIndexableTags } from \"./event-tags.js\";\n/**\n * Copied from nostr-tools and modified to use {@link getIndexableTags}\n * Extended to support NIP-ND AND operator with `&` prefix\n * @see https://github.com/nbd-wtf/nostr-tools/blob/a61cde77eacc9518001f11d7f67f1a50ae05fd80/filter.ts\n */\nexport function matchFilter(filter, event) {\n if (filter.ids && filter.ids.indexOf(event.id) === -1)\n return false;\n if (filter.kinds && filter.kinds.indexOf(event.kind) === -1)\n return false;\n if (filter.authors && filter.authors.indexOf(event.pubkey) === -1)\n return false;\n if (filter.since && event.created_at < filter.since)\n return false;\n if (filter.until && event.created_at > filter.until)\n return false;\n // Process AND tag filters (& prefix) first - NIP-ND\n // AND takes precedence and requires ALL values to be present\n for (let f in filter) {\n if (f[0] === \"&\") {\n let tagName = f.slice(1);\n let values = filter[f];\n if (values && values.length > 0) {\n const tags = getIndexableTags(event);\n // ALL values must be present (AND logic)\n for (const value of values) {\n if (!tags.has(tagName + \":\" + value)) {\n return false;\n }\n }\n }\n }\n }\n // Process OR tag filters (# prefix)\n // Skip values that are in AND tags (NIP-ND rule)\n for (let f in filter) {\n if (f[0] === \"#\") {\n let tagName = f.slice(1);\n let values = filter[f];\n if (values) {\n // Check if there's a corresponding AND filter for this tag\n const andKey = `&${tagName}`;\n const andValues = filter[andKey];\n // Filter out values that are in AND tags (NIP-ND rule)\n const filteredValues = andValues ? values.filter((v) => !andValues.includes(v)) : values;\n // If there are no values left after filtering, skip this check\n if (filteredValues.length === 0)\n continue;\n const tags = getIndexableTags(event);\n if (filteredValues.some((v) => tags.has(tagName + \":\" + v)) === false)\n return false;\n }\n }\n }\n return true;\n}\n/** Copied from nostr-tools and modified to use {@link matchFilter} */\nexport function matchFilters(filters, event) {\n for (let i = 0; i < filters.length; i++) {\n if (matchFilter(filters[i], event))\n return true;\n }\n return false;\n}\n/** Copied from nostr-tools and modified to support undefined values and NIP-ND AND operator */\nexport function mergeFilters(...filters) {\n let result = {};\n for (let i = 0; i < filters.length; i++) {\n let filter = filters[i];\n Object.entries(filter).forEach(([property, values]) => {\n // skip undefined\n if (values === undefined)\n return;\n if (property === \"kinds\" ||\n property === \"ids\" ||\n property === \"authors\" ||\n property[0] === \"#\" ||\n property[0] === \"&\") {\n // @ts-ignore\n result[property] = result[property] || [];\n // @ts-ignore\n for (let v = 0; v < values.length; v++) {\n // @ts-ignore\n let value = values[v];\n // @ts-ignore\n if (!result[property].includes(value))\n result[property].push(value);\n }\n }\n });\n if (filter.limit && (!result.limit || filter.limit > result.limit))\n result.limit = filter.limit;\n if (filter.until && (!result.until || filter.until > result.until))\n result.until = filter.until;\n if (filter.since && (!result.since || filter.since < result.since))\n result.since = filter.since;\n }\n return result;\n}\n/** Check if two filters are equal */\nexport function isFilterEqual(a, b) {\n return equal(a, b);\n}\n","import { map } from \"rxjs/operators\";\nimport { BLOSSOM_SERVER_LIST_KIND, getBlossomServersFromList } from \"../helpers/blossom.js\";\n/** A model that returns a users blossom servers */\nexport function UserBlossomServersModel(user) {\n if (typeof user === \"string\")\n user = { pubkey: user };\n return (store) => store\n .replaceable({ kind: BLOSSOM_SERVER_LIST_KIND, pubkey: user.pubkey, relays: user.relays })\n .pipe(map((event) => (event ? getBlossomServersFromList(event) : [])));\n}\n","import { isNameValueTag, processTags } from \"./tags.js\";\nexport const BLOSSOM_SERVER_LIST_KIND = 10063;\n/** Check if two servers are the same */\nexport function areBlossomServersEqual(a, b) {\n const hostnameA = new URL(\"/\", a).toString();\n const hostnameB = new URL(\"/\", b).toString();\n return hostnameA === hostnameB;\n}\n/** Checks if a string is a sha256 hash */\nexport function isSha256(str) {\n return !!str.match(/^[0-9a-f]{64}$/);\n}\n/** Returns an ordered array of servers found in a server list event (10063) */\nexport function getBlossomServersFromList(event) {\n const tags = Array.isArray(event) ? event : event.tags;\n return processTags(tags, (tag) => {\n if (isNameValueTag(tag, \"server\") && URL.canParse(tag[1]))\n return new URL(\"/\", tag[1]);\n else\n return undefined;\n });\n}\n/** A method that merges multiple arrays of blossom servers into a single array of unique servers */\nexport function mergeBlossomServers(...servers) {\n let merged = [];\n const seen = new Set();\n for (const arg of servers) {\n let arr = Array.isArray(arg) ? arg : [arg];\n for (const s of arr) {\n if (s === null || s === undefined)\n continue;\n const key = new URL(\"/\", s).toString();\n if (seen.has(key))\n continue;\n seen.add(key);\n merged.push(s);\n }\n }\n return merged;\n}\n","import { kinds } from \"nostr-tools\";\nimport { npubEncode } from \"nostr-tools/nip19\";\nimport { getOrComputeCachedValue } from \"./cache.js\";\nimport { safeParse } from \"./index.js\";\nexport const ProfileContentSymbol = Symbol.for(\"profile-content\");\nexport function getProfileContent(event) {\n return getOrComputeCachedValue(event, ProfileContentSymbol, () => {\n const profile = safeParse(event.content);\n if (!profile)\n return undefined;\n // ensure nip05 is a string\n if (profile.nip05 && typeof profile.nip05 !== \"string\")\n profile.nip05 = String(profile.nip05);\n // add missing protocol to website\n if (profile.website && profile.website?.length > 0 && profile.website?.startsWith(\"http\") === false) {\n profile.website = \"https://\" + profile.website;\n }\n return profile;\n });\n}\n/** Checks if the content of the kind 0 event is valid JSON */\nexport function isValidProfile(profile) {\n if (!profile)\n return false;\n if (profile.kind !== kinds.Metadata && profile.kind !== kinds.Handlerinformation)\n return false;\n // Check if the profile content is valid\n if (!getProfileContent(profile))\n return false;\n return true;\n}\nexport function getProfilePicture(metadata, fallback) {\n if (!metadata)\n return fallback;\n // Get the metadata from the nostr event\n if (\"pubkey\" in metadata && \"id\" in metadata && \"sig\" in metadata) {\n if (isValidProfile(metadata))\n metadata = getProfileContent(metadata);\n else\n metadata = undefined;\n }\n // Return the display name or fallback\n return (metadata?.picture || metadata?.image || fallback)?.trim();\n}\nexport function getDisplayName(metadata, fallback) {\n if (!metadata)\n return fallback;\n // Get the metadata from the nostr event\n if (\"pubkey\" in metadata && \"id\" in metadata && \"sig\" in metadata) {\n // Set the fallback to the npub if not set\n if (!fallback) {\n const npub = npubEncode(metadata.pubkey);\n fallback = npub.slice(0, 5 + 4) + \"…\" + npub.slice(-4);\n }\n // Get the profile content\n if (isValidProfile(metadata))\n metadata = getProfileContent(metadata);\n else\n metadata = undefined;\n }\n // Return the display name or fallback\n return (metadata?.display_name || metadata?.displayName || metadata?.name || fallback)?.trim();\n}\n","/** Returns the parsed JSON or undefined if invalid */\nexport function safeParse(str) {\n try {\n return JSON.parse(str);\n }\n catch (error) {\n return undefined;\n }\n}\n","\"use strict\";\n/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.bytes = exports.stringToBytes = exports.str = exports.bytesToString = exports.hex = exports.utf8 = exports.bech32m = exports.bech32 = exports.base58check = exports.base58xmr = exports.base58xrp = exports.base58flickr = exports.base58 = exports.base64url = exports.base64 = exports.base32crockford = exports.base32hex = exports.base32 = exports.base16 = exports.utils = exports.assertNumber = void 0;\nfunction assertNumber(n) {\n if (!Number.isSafeInteger(n))\n throw new Error(`Wrong integer: ${n}`);\n}\nexports.assertNumber = assertNumber;\nfunction chain(...args) {\n const wrap = (a, b) => (c) => a(b(c));\n const encode = Array.from(args)\n .reverse()\n .reduce((acc, i) => (acc ? wrap(acc, i.encode) : i.encode), undefined);\n const decode = args.reduce((acc, i) => (acc ? wrap(acc, i.decode) : i.decode), undefined);\n return { encode, decode };\n}\nfunction alphabet(alphabet) {\n return {\n encode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('alphabet.encode input should be an array of numbers');\n return digits.map((i) => {\n assertNumber(i);\n if (i < 0 || i >= alphabet.length)\n throw new Error(`Digit index outside alphabet: ${i} (alphabet: ${alphabet.length})`);\n return alphabet[i];\n });\n },\n decode: (input) => {\n if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))\n throw new Error('alphabet.decode input should be array of strings');\n return input.map((letter) => {\n if (typeof letter !== 'string')\n throw new Error(`alphabet.decode: not string element=${letter}`);\n const index = alphabet.indexOf(letter);\n if (index === -1)\n throw new Error(`Unknown letter: \"${letter}\". Allowed: ${alphabet}`);\n return index;\n });\n },\n };\n}\nfunction join(separator = '') {\n if (typeof separator !== 'string')\n throw new Error('join separator should be string');\n return {\n encode: (from) => {\n if (!Array.isArray(from) || (from.length && typeof from[0] !== 'string'))\n throw new Error('join.encode input should be array of strings');\n for (let i of from)\n if (typeof i !== 'string')\n throw new Error(`join.encode: non-string input=${i}`);\n return from.join(separator);\n },\n decode: (to) => {\n if (typeof to !== 'string')\n throw new Error('join.decode input should be string');\n return to.split(separator);\n },\n };\n}\nfunction padding(bits, chr = '=') {\n assertNumber(bits);\n if (typeof chr !== 'string')\n throw new Error('padding chr should be string');\n return {\n encode(data) {\n if (!Array.isArray(data) || (data.length && typeof data[0] !== 'string'))\n throw new Error('padding.encode input should be array of strings');\n for (let i of data)\n if (typeof i !== 'string')\n throw new Error(`padding.encode: non-string input=${i}`);\n while ((data.length * bits) % 8)\n data.push(chr);\n return data;\n },\n decode(input) {\n if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))\n throw new Error('padding.encode input should be array of strings');\n for (let i of input)\n if (typeof i !== 'string')\n throw new Error(`padding.decode: non-string input=${i}`);\n let end = input.length;\n if ((end * bits) % 8)\n throw new Error('Invalid padding: string should have whole number of bytes');\n for (; end > 0 && input[end - 1] === chr; end--) {\n if (!(((end - 1) * bits) % 8))\n throw new Error('Invalid padding: string has too much padding');\n }\n return input.slice(0, end);\n },\n };\n}\nfunction normalize(fn) {\n if (typeof fn !== 'function')\n throw new Error('normalize fn should be function');\n return { encode: (from) => from, decode: (to) => fn(to) };\n}\nfunction convertRadix(data, from, to) {\n if (from < 2)\n throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);\n if (to < 2)\n throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);\n if (!Array.isArray(data))\n throw new Error('convertRadix: data should be array');\n if (!data.length)\n return [];\n let pos = 0;\n const res = [];\n const digits = Array.from(data);\n digits.forEach((d) => {\n assertNumber(d);\n if (d < 0 || d >= from)\n throw new Error(`Wrong integer: ${d}`);\n });\n while (true) {\n let carry = 0;\n let done = true;\n for (let i = pos; i < digits.length; i++) {\n const digit = digits[i];\n const digitBase = from * carry + digit;\n if (!Number.isSafeInteger(digitBase) ||\n (from * carry) / from !== carry ||\n digitBase - digit !== from * carry) {\n throw new Error('convertRadix: carry overflow');\n }\n carry = digitBase % to;\n digits[i] = Math.floor(digitBase / to);\n if (!Number.isSafeInteger(digits[i]) || digits[i] * to + carry !== digitBase)\n throw new Error('convertRadix: carry overflow');\n if (!done)\n continue;\n else if (!digits[i])\n pos = i;\n else\n done = false;\n }\n res.push(carry);\n if (done)\n break;\n }\n for (let i = 0; i < data.length - 1 && data[i] === 0; i++)\n res.push(0);\n return res.reverse();\n}\nconst gcd = (a, b) => (!b ? a : gcd(b, a % b));\nconst radix2carry = (from, to) => from + (to - gcd(from, to));\nfunction convertRadix2(data, from, to, padding) {\n if (!Array.isArray(data))\n throw new Error('convertRadix2: data should be array');\n if (from <= 0 || from > 32)\n throw new Error(`convertRadix2: wrong from=${from}`);\n if (to <= 0 || to > 32)\n throw new Error(`convertRadix2: wrong to=${to}`);\n if (radix2carry(from, to) > 32) {\n throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);\n }\n let carry = 0;\n let pos = 0;\n const mask = 2 ** to - 1;\n const res = [];\n for (const n of data) {\n assertNumber(n);\n if (n >= 2 ** from)\n throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);\n carry = (carry << from) | n;\n if (pos + from > 32)\n throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);\n pos += from;\n for (; pos >= to; pos -= to)\n res.push(((carry >> (pos - to)) & mask) >>> 0);\n carry &= 2 ** pos - 1;\n }\n carry = (carry << (to - pos)) & mask;\n if (!padding && pos >= from)\n throw new Error('Excess padding');\n if (!padding && carry)\n throw new Error(`Non-zero padding: ${carry}`);\n if (padding && pos > 0)\n res.push(carry >>> 0);\n return res;\n}\nfunction radix(num) {\n assertNumber(num);\n return {\n encode: (bytes) => {\n if (!(bytes instanceof Uint8Array))\n throw new Error('radix.encode input should be Uint8Array');\n return convertRadix(Array.from(bytes), 2 ** 8, num);\n },\n decode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('radix.decode input should be array of strings');\n return Uint8Array.from(convertRadix(digits, num, 2 ** 8));\n },\n };\n}\nfunction radix2(bits, revPadding = false) {\n assertNumber(bits);\n if (bits <= 0 || bits > 32)\n throw new Error('radix2: bits should be in (0..32]');\n if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)\n throw new Error('radix2: carry overflow');\n return {\n encode: (bytes) => {\n if (!(bytes instanceof Uint8Array))\n throw new Error('radix2.encode input should be Uint8Array');\n return convertRadix2(Array.from(bytes), 8, bits, !revPadding);\n },\n decode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('radix2.decode input should be array of strings');\n return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));\n },\n };\n}\nfunction unsafeWrapper(fn) {\n if (typeof fn !== 'function')\n throw new Error('unsafeWrapper fn should be function');\n return function (...args) {\n try {\n return fn.apply(null, args);\n }\n catch (e) { }\n };\n}\nfunction checksum(len, fn) {\n assertNumber(len);\n if (typeof fn !== 'function')\n throw new Error('checksum fn should be function');\n return {\n encode(data) {\n if (!(data instanceof Uint8Array))\n throw new Error('checksum.encode: input should be Uint8Array');\n const checksum = fn(data).slice(0, len);\n const res = new Uint8Array(data.length + len);\n res.set(data);\n res.set(checksum, data.length);\n return res;\n },\n decode(data) {\n if (!(data instanceof Uint8Array))\n throw new Error('checksum.decode: input should be Uint8Array');\n const payload = data.slice(0, -len);\n const newChecksum = fn(payload).slice(0, len);\n const oldChecksum = data.slice(-len);\n for (let i = 0; i < len; i++)\n if (newChecksum[i] !== oldChecksum[i])\n throw new Error('Invalid checksum');\n return payload;\n },\n };\n}\nexports.utils = { alphabet, chain, checksum, radix, radix2, join, padding };\nexports.base16 = chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));\nexports.base32 = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));\nexports.base32hex = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));\nexports.base32crockford = chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));\nexports.base64 = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));\nexports.base64url = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));\nconst genBase58 = (abc) => chain(radix(58), alphabet(abc), join(''));\nexports.base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');\nexports.base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');\nexports.base58xrp = genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');\nconst XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];\nexports.base58xmr = {\n encode(data) {\n let res = '';\n for (let i = 0; i < data.length; i += 8) {\n const block = data.subarray(i, i + 8);\n res += exports.base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');\n }\n return res;\n },\n decode(str) {\n let res = [];\n for (let i = 0; i < str.length; i += 11) {\n const slice = str.slice(i, i + 11);\n const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);\n const block = exports.base58.decode(slice);\n for (let j = 0; j < block.length - blockLen; j++) {\n if (block[j] !== 0)\n throw new Error('base58xmr: wrong padding');\n }\n res = res.concat(Array.from(block.slice(block.length - blockLen)));\n }\n return Uint8Array.from(res);\n },\n};\nconst base58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), exports.base58);\nexports.base58check = base58check;\nconst BECH_ALPHABET = chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));\nconst POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\nfunction bech32Polymod(pre) {\n const b = pre >> 25;\n let chk = (pre & 0x1ffffff) << 5;\n for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {\n if (((b >> i) & 1) === 1)\n chk ^= POLYMOD_GENERATORS[i];\n }\n return chk;\n}\nfunction bechChecksum(prefix, words, encodingConst = 1) {\n const len = prefix.length;\n let chk = 1;\n for (let i = 0; i < len; i++) {\n const c = prefix.charCodeAt(i);\n if (c < 33 || c > 126)\n throw new Error(`Invalid prefix (${prefix})`);\n chk = bech32Polymod(chk) ^ (c >> 5);\n }\n chk = bech32Polymod(chk);\n for (let i = 0; i < len; i++)\n chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (let v of words)\n chk = bech32Polymod(chk) ^ v;\n for (let i = 0; i < 6; i++)\n chk = bech32Polymod(chk);\n chk ^= encodingConst;\n return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));\n}\nfunction genBech32(encoding) {\n const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;\n const _words = radix2(5);\n const fromWords = _words.decode;\n const toWords = _words.encode;\n const fromWordsUnsafe = unsafeWrapper(fromWords);\n function encode(prefix, words, limit = 90) {\n if (typeof prefix !== 'string')\n throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);\n if (!Array.isArray(words) || (words.length && typeof words[0] !== 'number'))\n throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);\n const actualLength = prefix.length + 7 + words.length;\n if (limit !== false && actualLength > limit)\n throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);\n prefix = prefix.toLowerCase();\n return `${prefix}1${BECH_ALPHABET.encode(words)}${bechChecksum(prefix, words, ENCODING_CONST)}`;\n }\n function decode(str, limit = 90) {\n if (typeof str !== 'string')\n throw new Error(`bech32.decode input should be string, not ${typeof str}`);\n if (str.length < 8 || (limit !== false && str.length > limit))\n throw new TypeError(`Wrong string length: ${str.length} (${str}). Expected (8..${limit})`);\n const lowered = str.toLowerCase();\n if (str !== lowered && str !== str.toUpperCase())\n throw new Error(`String must be lowercase or uppercase`);\n str = lowered;\n const sepIndex = str.lastIndexOf('1');\n if (sepIndex === 0 || sepIndex === -1)\n throw new Error(`Letter \"1\" must be present between prefix and data only`);\n const prefix = str.slice(0, sepIndex);\n const _words = str.slice(sepIndex + 1);\n if (_words.length < 6)\n throw new Error('Data must be at least 6 characters long');\n const words = BECH_ALPHABET.decode(_words).slice(0, -6);\n const sum = bechChecksum(prefix, words, ENCODING_CONST);\n if (!_words.endsWith(sum))\n throw new Error(`Invalid checksum in ${str}: expected \"${sum}\"`);\n return { prefix, words };\n }\n const decodeUnsafe = unsafeWrapper(decode);\n function decodeToBytes(str) {\n const { prefix, words } = decode(str, false);\n return { prefix, words, bytes: fromWords(words) };\n }\n return { encode, decode, decodeToBytes, decodeUnsafe, fromWords, fromWordsUnsafe, toWords };\n}\nexports.bech32 = genBech32('bech32');\nexports.bech32m = genBech32('bech32m');\nexports.utf8 = {\n encode: (data) => new TextDecoder().decode(data),\n decode: (str) => new TextEncoder().encode(str),\n};\nexports.hex = chain(radix2(4), alphabet('0123456789abcdef'), join(''), normalize((s) => {\n if (typeof s !== 'string' || s.length % 2)\n throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);\n return s.toLowerCase();\n}));\nconst CODERS = {\n utf8: exports.utf8, hex: exports.hex, base16: exports.base16, base32: exports.base32, base64: exports.base64, base64url: exports.base64url, base58: exports.base58, base58xmr: exports.base58xmr\n};\nconst coderTypeError = `Invalid encoding type. Available types: ${Object.keys(CODERS).join(', ')}`;\nconst bytesToString = (type, bytes) => {\n if (typeof type !== 'string' || !CODERS.hasOwnProperty(type))\n throw new TypeError(coderTypeError);\n if (!(bytes instanceof Uint8Array))\n throw new TypeError('bytesToString() expects Uint8Array');\n return CODERS[type].encode(bytes);\n};\nexports.bytesToString = bytesToString;\nexports.str = exports.bytesToString;\nconst stringToBytes = (type, str) => {\n if (!CODERS.hasOwnProperty(type))\n throw new TypeError(coderTypeError);\n if (typeof str !== 'string')\n throw new TypeError('stringToBytes() expects string');\n return CODERS[type].decode(str);\n};\nexports.stringToBytes = stringToBytes;\nexports.bytes = exports.stringToBytes;\n","const {bech32, hex, utf8} = require('@scure/base')\n\n// defaults for encode; default timestamp is current time at call\nconst DEFAULTNETWORK = {\n // default network is bitcoin\n bech32: 'bc',\n pubKeyHash: 0x00,\n scriptHash: 0x05,\n validWitnessVersions: [0]\n}\nconst TESTNETWORK = {\n bech32: 'tb',\n pubKeyHash: 0x6f,\n scriptHash: 0xc4,\n validWitnessVersions: [0]\n}\nconst SIGNETNETWORK = {\n bech32: 'tbs',\n pubKeyHash: 0x6f,\n scriptHash: 0xc4,\n validWitnessVersions: [0]\n}\nconst REGTESTNETWORK = {\n bech32: 'bcrt',\n pubKeyHash: 0x6f,\n scriptHash: 0xc4,\n validWitnessVersions: [0]\n}\nconst SIMNETWORK = {\n bech32: 'sb',\n pubKeyHash: 0x3f,\n scriptHash: 0x7b,\n validWitnessVersions: [0]\n}\n\nconst FEATUREBIT_ORDER = [\n 'option_data_loss_protect',\n 'initial_routing_sync',\n 'option_upfront_shutdown_script',\n 'gossip_queries',\n 'var_onion_optin',\n 'gossip_queries_ex',\n 'option_static_remotekey',\n 'payment_secret',\n 'basic_mpp',\n 'option_support_large_channel'\n]\n\nconst DIVISORS = {\n m: BigInt(1e3),\n u: BigInt(1e6),\n n: BigInt(1e9),\n p: BigInt(1e12)\n}\n\nconst MAX_MILLISATS = BigInt('2100000000000000000')\n\nconst MILLISATS_PER_BTC = BigInt(1e11)\n\nconst TAGCODES = {\n payment_hash: 1,\n payment_secret: 16,\n description: 13,\n payee: 19,\n description_hash: 23, // commit to longer descriptions (used by lnurl-pay)\n expiry: 6, // default: 3600 (1 hour)\n min_final_cltv_expiry: 24, // default: 9\n fallback_address: 9,\n route_hint: 3, // for extra routing info (private etc.)\n feature_bits: 5,\n metadata: 27\n}\n\n// reverse the keys and values of TAGCODES and insert into TAGNAMES\nconst TAGNAMES = {}\nfor (let i = 0, keys = Object.keys(TAGCODES); i < keys.length; i++) {\n const currentName = keys[i]\n const currentCode = TAGCODES[keys[i]].toString()\n TAGNAMES[currentCode] = currentName\n}\n\nconst TAGPARSERS = {\n 1: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits\n 16: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits\n 13: words => utf8.encode(bech32.fromWordsUnsafe(words)), // string variable length\n 19: words => hex.encode(bech32.fromWordsUnsafe(words)), // 264 bits\n 23: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits\n 27: words => hex.encode(bech32.fromWordsUnsafe(words)), // variable\n 6: wordsToIntBE, // default: 3600 (1 hour)\n 24: wordsToIntBE, // default: 9\n 3: routingInfoParser, // for extra routing info (private etc.)\n 5: featureBitsParser // keep feature bits as array of 5 bit words\n}\n\nfunction getUnknownParser(tagCode) {\n return words => ({\n tagCode: parseInt(tagCode),\n words: bech32.encode('unknown', words, Number.MAX_SAFE_INTEGER)\n })\n}\n\nfunction wordsToIntBE(words) {\n return words.reverse().reduce((total, item, index) => {\n return total + item * Math.pow(32, index)\n }, 0)\n}\n\n// first convert from words to buffer, trimming padding where necessary\n// parse in 51 byte chunks. See encoder for details.\nfunction routingInfoParser(words) {\n const routes = []\n let pubkey,\n shortChannelId,\n feeBaseMSats,\n feeProportionalMillionths,\n cltvExpiryDelta\n let routesBuffer = bech32.fromWordsUnsafe(words)\n while (routesBuffer.length > 0) {\n pubkey = hex.encode(routesBuffer.slice(0, 33)) // 33 bytes\n shortChannelId = hex.encode(routesBuffer.slice(33, 41)) // 8 bytes\n feeBaseMSats = parseInt(hex.encode(routesBuffer.slice(41, 45)), 16) // 4 bytes\n feeProportionalMillionths = parseInt(\n hex.encode(routesBuffer.slice(45, 49)),\n 16\n ) // 4 bytes\n cltvExpiryDelta = parseInt(hex.encode(routesBuffer.slice(49, 51)), 16) // 2 bytes\n\n routesBuffer = routesBuffer.slice(51)\n\n routes.push({\n pubkey,\n short_channel_id: shortChannelId,\n fee_base_msat: feeBaseMSats,\n fee_proportional_millionths: feeProportionalMillionths,\n cltv_expiry_delta: cltvExpiryDelta\n })\n }\n return routes\n}\n\nfunction featureBitsParser(words) {\n const bools = words\n .slice()\n .reverse()\n .map(word => [\n !!(word & 0b1),\n !!(word & 0b10),\n !!(word & 0b100),\n !!(word & 0b1000),\n !!(word & 0b10000)\n ])\n .reduce((finalArr, itemArr) => finalArr.concat(itemArr), [])\n while (bools.length < FEATUREBIT_ORDER.length * 2) {\n bools.push(false)\n }\n\n const featureBits = {}\n\n FEATUREBIT_ORDER.forEach((featureName, index) => {\n let status\n if (bools[index * 2]) {\n status = 'required'\n } else if (bools[index * 2 + 1]) {\n status = 'supported'\n } else {\n status = 'unsupported'\n }\n featureBits[featureName] = status\n })\n\n const extraBits = bools.slice(FEATUREBIT_ORDER.length * 2)\n featureBits.extra_bits = {\n start_bit: FEATUREBIT_ORDER.length * 2,\n bits: extraBits,\n has_required: extraBits.reduce(\n (result, bit, index) =>\n index % 2 !== 0 ? result || false : result || bit,\n false\n )\n }\n\n return featureBits\n}\n\nfunction hrpToMillisat(hrpString, outputString) {\n let divisor, value\n if (hrpString.slice(-1).match(/^[munp]$/)) {\n divisor = hrpString.slice(-1)\n value = hrpString.slice(0, -1)\n } else if (hrpString.slice(-1).match(/^[^munp0-9]$/)) {\n throw new Error('Not a valid multiplier for the amount')\n } else {\n value = hrpString\n }\n\n if (!value.match(/^\\d+$/))\n throw new Error('Not a valid human readable amount')\n\n const valueBN = BigInt(value)\n\n const millisatoshisBN = divisor\n ? (valueBN * MILLISATS_PER_BTC) / DIVISORS[divisor]\n : valueBN * MILLISATS_PER_BTC\n\n if (\n (divisor === 'p' && !(valueBN % BigInt(10) === BigInt(0))) ||\n millisatoshisBN > MAX_MILLISATS\n ) {\n throw new Error('Amount is outside of valid range')\n }\n\n return outputString ? millisatoshisBN.toString() : millisatoshisBN\n}\n\n// decode will only have extra comments that aren't covered in encode comments.\n// also if anything is hard to read I'll comment.\nfunction decode(paymentRequest, network) {\n if (typeof paymentRequest !== 'string')\n throw new Error('Lightning Payment Request must be string')\n if (paymentRequest.slice(0, 2).toLowerCase() !== 'ln')\n throw new Error('Not a proper lightning payment request')\n\n const sections = []\n const decoded = bech32.decode(paymentRequest, Number.MAX_SAFE_INTEGER)\n paymentRequest = paymentRequest.toLowerCase()\n const prefix = decoded.prefix\n let words = decoded.words\n let letters = paymentRequest.slice(prefix.length + 1)\n let sigWords = words.slice(-104)\n words = words.slice(0, -104)\n\n // Without reverse lookups, can't say that the multipier at the end must\n // have a number before it, so instead we parse, and if the second group\n // doesn't have anything, there's a good chance the last letter of the\n // coin type got captured by the third group, so just re-regex without\n // the number.\n let prefixMatches = prefix.match(/^ln(\\S+?)(\\d*)([a-zA-Z]?)$/)\n if (prefixMatches && !prefixMatches[2])\n prefixMatches = prefix.match(/^ln(\\S+)$/)\n if (!prefixMatches) {\n throw new Error('Not a proper lightning payment request')\n }\n\n // \"ln\" section\n sections.push({\n name: 'lightning_network',\n letters: 'ln'\n })\n\n // \"bc\" section\n const bech32Prefix = prefixMatches[1]\n let coinNetwork\n if (!network) {\n switch (bech32Prefix) {\n case DEFAULTNETWORK.bech32:\n coinNetwork = DEFAULTNETWORK\n break\n case TESTNETWORK.bech32:\n coinNetwork = TESTNETWORK\n break\n case SIGNETNETWORK.bech32:\n coinNetwork = SIGNETNETWORK\n break\n case REGTESTNETWORK.bech32:\n coinNetwork = REGTESTNETWORK\n break\n case SIMNETWORK.bech32:\n coinNetwork = SIMNETWORK\n break\n }\n } else {\n if (\n network.bech32 === undefined ||\n network.pubKeyHash === undefined ||\n network.scriptHash === undefined ||\n !Array.isArray(network.validWitnessVersions)\n )\n throw new Error('Invalid network')\n coinNetwork = network\n }\n if (!coinNetwork || coinNetwork.bech32 !== bech32Prefix) {\n throw new Error('Unknown coin bech32 prefix')\n }\n sections.push({\n name: 'coin_network',\n letters: bech32Prefix,\n value: coinNetwork\n })\n\n // amount section\n const value = prefixMatches[2]\n let millisatoshis\n if (value) {\n const divisor = prefixMatches[3]\n millisatoshis = hrpToMillisat(value + divisor, true)\n sections.push({\n name: 'amount',\n letters: prefixMatches[2] + prefixMatches[3],\n value: millisatoshis\n })\n } else {\n millisatoshis = null\n }\n\n // \"1\" separator\n sections.push({\n name: 'separator',\n letters: '1'\n })\n\n // timestamp\n const timestamp = wordsToIntBE(words.slice(0, 7))\n words = words.slice(7) // trim off the left 7 words\n sections.push({\n name: 'timestamp',\n letters: letters.slice(0, 7),\n value: timestamp\n })\n letters = letters.slice(7)\n\n let tagName, parser, tagLength, tagWords\n // we have no tag count to go on, so just keep hacking off words\n // until we have none.\n while (words.length > 0) {\n const tagCode = words[0].toString()\n tagName = TAGNAMES[tagCode] || 'unknown_tag'\n parser = TAGPARSERS[tagCode] || getUnknownParser(tagCode)\n words = words.slice(1)\n\n tagLength = wordsToIntBE(words.slice(0, 2))\n words = words.slice(2)\n\n tagWords = words.slice(0, tagLength)\n words = words.slice(tagLength)\n\n sections.push({\n name: tagName,\n tag: letters[0],\n letters: letters.slice(0, 1 + 2 + tagLength),\n value: parser(tagWords) // see: parsers for more comments\n })\n letters = letters.slice(1 + 2 + tagLength)\n }\n\n // signature\n sections.push({\n name: 'signature',\n letters: letters.slice(0, 104),\n value: hex.encode(bech32.fromWordsUnsafe(sigWords))\n })\n letters = letters.slice(104)\n\n // checksum\n sections.push({\n name: 'checksum',\n letters: letters\n })\n\n let result = {\n paymentRequest,\n sections,\n\n get expiry() {\n let exp = sections.find(s => s.name === 'expiry')\n if (exp) return getValue('timestamp') + exp.value\n },\n\n get route_hints() {\n return sections.filter(s => s.name === 'route_hint').map(s => s.value)\n }\n }\n\n for (let name in TAGCODES) {\n if (name === 'route_hint') {\n // route hints can be multiple, so this won't work for them\n continue\n }\n\n Object.defineProperty(result, name, {\n get() {\n return getValue(name)\n }\n })\n }\n\n return result\n\n function getValue(name) {\n let section = sections.find(s => s.name === name)\n return section ? section.value : undefined\n }\n}\n\nmodule.exports = {\n decode,\n hrpToMillisat\n}\n","import { getExternalPointerFromTag } from \"./external-id.js\";\nimport { getOrComputeCachedValue } from \"./cache.js\";\nimport { getAddressPointerFromATag } from \"./pointers.js\";\nimport { isSafeRelayURL } from \"./relays.js\";\nexport const COMMENT_KIND = 1111;\nexport const CommentRootPointerSymbol = Symbol.for(\"comment-root-pointer\");\nexport const CommentReplyPointerSymbol = Symbol.for(\"comment-reply-pointer\");\n/** Gets the EventPointer from an array of tags */\nexport function getCommentEventPointer(tags, root = false) {\n const eTag = tags.find((t) => t[0] === (root ? \"E\" : \"e\"));\n const kind = tags.find((t) => t[0] === (root ? \"K\" : \"k\"))?.[1];\n if (eTag) {\n // Missing kind tag, return null\n if (!kind)\n return null;\n // only the root pubkey can be gotten from the tags, since due to quotes and mentions there will be many \"p\" tags for replies\n const rootPubkey = root ? tags.find((t) => t[0] === \"P\")?.[1] : undefined;\n const pointer = {\n type: \"event\",\n id: eTag[1],\n kind: parseInt(kind),\n pubkey: eTag[3] || rootPubkey || undefined,\n relay: eTag[2] && isSafeRelayURL(eTag[2]) ? eTag[2] : undefined,\n };\n return pointer;\n }\n return null;\n}\n/** Gets the AddressPointer from an array of tags */\nexport function getCommentAddressPointer(tags, root = false) {\n const aTag = tags.find((t) => t[0] === (root ? \"A\" : \"a\"));\n const eTag = tags.find((t) => t[0] === (root ? \"E\" : \"e\"));\n const kind = tags.find((t) => t[0] === (root ? \"K\" : \"k\"))?.[1];\n if (aTag) {\n // Missing kind tag, return null\n if (!kind)\n return null;\n const addressPointer = getAddressPointerFromATag(aTag);\n const pointer = {\n type: \"address\",\n id: eTag?.[1],\n pubkey: addressPointer.pubkey,\n identifier: addressPointer.identifier,\n kind: addressPointer.kind || parseInt(kind),\n relay: addressPointer.relays?.[0] || eTag?.[2],\n };\n return pointer;\n }\n return null;\n}\n/** Gets the ExternalPointer from an array of tags */\nexport function getCommentExternalPointer(tags, root = false) {\n const iTag = tags.find((t) => t[0] === (root ? \"I\" : \"i\"));\n if (iTag) {\n return {\n type: \"external\",\n ...getExternalPointerFromTag(iTag),\n };\n }\n return null;\n}\nexport function getCommentRootPointer(comment) {\n if (comment.kind !== COMMENT_KIND)\n return null;\n return getOrComputeCachedValue(comment, CommentRootPointerSymbol, () => {\n // check for address pointer first since it can also have E tags\n const A = getCommentAddressPointer(comment.tags, true);\n if (A)\n return A;\n const E = getCommentEventPointer(comment.tags, true);\n if (E)\n return E;\n const I = getCommentExternalPointer(comment.tags, true);\n if (I)\n return I;\n return null;\n });\n}\n/** Returns the reply pointer for a comment */\nexport function getCommentReplyPointer(comment) {\n if (comment.kind !== COMMENT_KIND)\n return null;\n return getOrComputeCachedValue(comment, CommentReplyPointerSymbol, () => {\n // check for address pointer first since it can also have E tags\n const A = getCommentAddressPointer(comment.tags, false);\n if (A)\n return A;\n const E = getCommentEventPointer(comment.tags, false);\n if (E)\n return E;\n const I = getCommentExternalPointer(comment.tags, false);\n if (I)\n return I;\n return null;\n });\n}\n/** Checks if a pointer is a {@link CommentEventPointer} */\nexport function isCommentEventPointer(pointer) {\n return (Reflect.has(pointer, \"id\") &&\n Reflect.has(pointer, \"kind\") &&\n !Reflect.has(pointer, \"identifier\") &&\n typeof pointer.kind === \"number\");\n}\n/** Checks if a pointer is a {@link CommentAddressPointer} */\nexport function isCommentAddressPointer(pointer) {\n return (Reflect.has(pointer, \"identifier\") &&\n Reflect.has(pointer, \"pubkey\") &&\n Reflect.has(pointer, \"kind\") &&\n typeof pointer.kind === \"number\");\n}\n/** Checks if a comment event is valid */\nexport function isValidComment(comment) {\n return (comment.kind === COMMENT_KIND && getCommentRootPointer(comment) !== null && getCommentReplyPointer(comment) !== null);\n}\n","import { getOrComputeCachedValue } from \"./cache.js\";\nimport { isSafeRelayURL } from \"./relays.js\";\nimport { isPTag, processTags } from \"./tags.js\";\nimport { getProfilePointerFromPTag } from \"./pointers.js\";\nimport { getHiddenTags, isHiddenTagsUnlocked, unlockHiddenTags } from \"./hidden-tags.js\";\nimport { notifyEventUpdate } from \"./index.js\";\nexport const ContactsRelaysSymbol = Symbol.for(\"contacts-relays\");\nexport const PublicContactsSymbol = Symbol.for(\"public-contacts\");\nexport const HiddenContactsSymbol = Symbol.for(\"hidden-contacts\");\nexport function getRelaysFromContactsEvent(event) {\n return getOrComputeCachedValue(event, ContactsRelaysSymbol, () => {\n try {\n const relayJson = JSON.parse(event.content);\n const relays = new Map();\n for (const [url, opts] of Object.entries(relayJson)) {\n if (!isSafeRelayURL(url))\n continue;\n if (opts.write && opts.read)\n relays.set(url, \"all\");\n else if (opts.read)\n relays.set(url, \"inbox\");\n else if (opts.write)\n relays.set(url, \"outbox\");\n }\n return relays;\n }\n catch (error) {\n return null;\n }\n });\n}\n/** Merges any number of contact lists into a single list */\nexport function mergeContacts(...pointers) {\n const merged = new Map();\n for (const arr of pointers) {\n if (Array.isArray(arr)) {\n for (const pointer of arr)\n if (pointer)\n merged.set(pointer.pubkey, pointer);\n }\n else if (arr) {\n merged.set(arr.pubkey, arr);\n }\n }\n return Array.from(merged.values());\n}\n/** Returns all public and hidden contacts from a contacts list event */\nexport function getContacts(event) {\n return mergeContacts(getPublicContacts(event), getHiddenContacts(event));\n}\n/** Returns only the public contacts from a contacts list event */\nexport function getPublicContacts(event) {\n return getOrComputeCachedValue(event, PublicContactsSymbol, () => processTags(event.tags, (t) => (isPTag(t) ? t : undefined), getProfilePointerFromPTag));\n}\n/** Checks if the hidden contacts are unlocked */\nexport function isHiddenContactsUnlocked(event) {\n return isHiddenTagsUnlocked(event) && Reflect.has(event, HiddenContactsSymbol);\n}\n/** Returns only the hidden contacts from a contacts list event */\nexport function getHiddenContacts(event) {\n if (isHiddenContactsUnlocked(event))\n return event[HiddenContactsSymbol];\n // Get hidden tags\n const tags = getHiddenTags(event);\n if (!tags)\n return undefined;\n // Parse tags\n const contacts = processTags(tags, (t) => (isPTag(t) ? t : undefined), getProfilePointerFromPTag);\n // Set cache and notify event store\n Reflect.set(event, HiddenContactsSymbol, contacts);\n return contacts;\n}\n/** Unlocks the hidden contacts */\nexport async function unlockHiddenContacts(event, signer) {\n if (isHiddenContactsUnlocked(event))\n return event[HiddenContactsSymbol];\n // Unlock hidden tags\n await unlockHiddenTags(event, signer);\n // Get hidden contacts\n const contacts = getHiddenContacts(event);\n if (!contacts)\n throw new Error(\"Failed to unlock hidden contacts\");\n // Set cache and notify event store\n notifyEventUpdate(event);\n return contacts;\n}\n","import { kinds } from \"nostr-tools\";\nimport { catchError, combineLatest, distinct, EMPTY, filter, isObservable, map, merge, mergeMap, of, switchMap, } from \"rxjs\";\nimport { logger } from \"../logger.js\";\nimport { canHaveEncryptedContent, getEncryptedContent, isEncryptedContentUnlocked, setEncryptedContentCache, } from \"./encrypted-content.js\";\nimport { notifyEventUpdate } from \"./event.js\";\nimport { getGiftWrapSeal, getSealGiftWrap, getSealRumor } from \"./gift-wraps.js\";\n/** A symbol that is used to mark encrypted content as being from a cache */\nexport const EncryptedContentFromCacheSymbol = Symbol.for(\"encrypted-content-from-cache\");\n/** Marks the encrypted content as being from a cache */\nexport function markEncryptedContentFromCache(event) {\n Reflect.set(event, EncryptedContentFromCacheSymbol, true);\n}\n/** Checks if the encrypted content is from a cache */\nexport function isEncryptedContentFromCache(event) {\n return Reflect.has(event, EncryptedContentFromCacheSymbol);\n}\nconst log = logger.extend(\"EncryptedContentCache\");\n/**\n * Starts a process that persists and restores all encrypted content\n * @param eventStore - The event store to listen to\n * @param storage - The storage to use\n * @param fallback - A function that will be called when the encrypted content is not found in storage\n * @returns A function that can be used to stop the process\n */\nexport function persistEncryptedContent(eventStore, storage, fallback) {\n const storage$ = isObservable(storage) ? storage : of(storage);\n // Get the encrypted content from storage or call the fallback\n const getItem = async (storage, event) => {\n return (await storage.getItem(event.id)) || (fallback ? await fallback(event) : null);\n };\n // Restore encrypted content when it is inserted\n const restore = eventStore.insert$\n .pipe(\n // Look for events that support encrypted content and are locked\n filter((e) => canHaveEncryptedContent(e.kind) && isEncryptedContentUnlocked(e) === false), \n // Get the encrypted content from storage\n mergeMap((event) => \n // Wait for storage to be available\n storage$.pipe(switchMap((storage) => combineLatest([of(event), getItem(storage, event)])), catchError((error) => {\n log(`Failed to restore encrypted content for ${event.id}`, error);\n return EMPTY;\n }))))\n .subscribe(async ([event, content]) => {\n if (!content)\n return;\n // Restore the encrypted content and set it as from a cache\n markEncryptedContentFromCache(event);\n setEncryptedContentCache(event, content);\n log(`Restored encrypted content for ${event.id}`);\n });\n // Restore seals when they are unlocked\n const restoreSeals = eventStore.update$\n .pipe(\n // Look for gift wraps that are unlocked\n filter((e) => e.kind === kinds.GiftWrap && isEncryptedContentUnlocked(e)), \n // Get the seal event\n map((gift) => getGiftWrapSeal(gift)), \n // Look for gift wraps with locked seals\n filter((seal) => seal !== undefined && isEncryptedContentUnlocked(seal) === false), \n // Only attempt to unlock seals once\n distinct((seal) => seal.id), \n // Get encrypted content from storage\n mergeMap((seal) => \n // Wait for storage to be available\n storage$.pipe(switchMap((storage) => combineLatest([of(seal), getItem(storage, seal)])), catchError((error) => {\n log(`Failed to restore encrypted content for ${seal.id}`, error);\n return EMPTY;\n }))))\n .subscribe(async ([seal, content]) => {\n if (!seal || !content)\n return;\n markEncryptedContentFromCache(seal);\n setEncryptedContentCache(seal, content);\n // Parse the rumor event\n getSealRumor(seal);\n // Trigger an update to the gift wrap event\n const gift = getSealGiftWrap(seal);\n if (gift)\n notifyEventUpdate(gift);\n log(`Restored encrypted content for ${seal.id}`);\n });\n // Persist encrypted content when it is updated or inserted\n const persist = combineLatest([merge(eventStore.update$, eventStore.insert$), storage$])\n .pipe(\n // Look for events that support encrypted content and are unlocked and not from the cache\n filter(([event]) => canHaveEncryptedContent(event.kind) &&\n isEncryptedContentUnlocked(event) &&\n !isEncryptedContentFromCache(event)), \n // Only persist the encrypted content once\n distinct(([event]) => event.id))\n .subscribe(async ([event, storage]) => {\n try {\n const content = getEncryptedContent(event);\n if (content) {\n await storage.setItem(event.id, content);\n log(`Persisted encrypted content for ${event.id}`);\n }\n }\n catch (error) {\n // Ignore errors when saving encrypted content\n log(`Failed to persist encrypted content for ${event.id}`, error);\n }\n });\n // Persist seals when the gift warp is unlocked or inserted unlocked\n // This relies on the gift wrap event being updated when a seal is unlocked\n const persistSeals = combineLatest([merge(eventStore.update$, eventStore.insert$), storage$])\n .pipe(\n // Look for gift wraps that are unlocked\n filter(([event]) => event.kind === kinds.GiftWrap && isEncryptedContentUnlocked(event)), \n // Get the seal event\n map(([gift, storage]) => [getGiftWrapSeal(gift), storage]), \n // Make sure the seal is defined\n filter(([seal]) => seal !== undefined), \n // Make sure seal is unlocked and not from cache\n filter(([seal]) => isEncryptedContentUnlocked(seal) && !isEncryptedContentFromCache(seal)), \n // Only persist the seal once\n distinct(([seal]) => seal.id))\n .subscribe(async ([seal, storage]) => {\n if (!seal)\n return;\n try {\n const content = getEncryptedContent(seal);\n if (content) {\n await storage.setItem(seal.id, content);\n log(`Persisted encrypted content for ${seal.id}`);\n }\n }\n catch (error) {\n // Ignore errors when saving encrypted content\n log(`Failed to persist encrypted content for ${seal.id}`, error);\n }\n });\n return () => {\n restore.unsubscribe();\n persist.unsubscribe();\n restoreSeals.unsubscribe();\n persistSeals.unsubscribe();\n };\n}\n","import { bufferTime, filter } from \"rxjs\";\nimport { logger } from \"../logger.js\";\nimport { isFromCache } from \"./index.js\";\nconst log = logger.extend(\"event-cache\");\n/**\n * Setups a process to write batches of new events from an event store to a cache\n * @param eventStore - The event store to read from\n * @param write - The function to write the events to the cache\n * @param opts - The options for the process\n * @param opts.batchTime - The time to wait before writing a batch (default: 5 seconds)\n * @param opts.maxBatchSize - The maximum number of events to write in a batch\n * @returns A function to stop the process\n */\nexport function persistEventsToCache(eventStore, write, opts) {\n const time = opts?.batchTime ?? 5_000;\n // Save all new events to the cache\n const sub = eventStore.insert$\n .pipe(\n // Only select events that are not from the cache\n filter((e) => !isFromCache(e)), \n // Buffer events for 5 seconds\n opts?.maxBatchSize ? bufferTime(time, undefined, opts?.maxBatchSize ?? 100) : bufferTime(time), \n // Only select buffers with events\n filter((b) => b.length > 0))\n .subscribe((events) => {\n // Save all new events to the cache\n write(events)\n .then(() => log(`Saved ${events.length} events to cache`))\n .catch((e) => log(`Failed to save ${events.length} events to cache`, e));\n });\n return () => sub.unsubscribe();\n}\n/** @deprecated Use persistEventsToCache instead */\nexport const presistEventsToCache = persistEventsToCache;\n","import { bech32 } from \"@scure/base\";\nimport { parseBolt11 } from \"./bolt11.js\";\nconst decoder = new TextDecoder();\n/** Parses a lightning address (lud16) into a LNURLp */\nexport function parseLightningAddress(address) {\n let [name, domain] = address.split(\"@\");\n if (!name || !domain)\n return;\n return new URL(`https://${domain}/.well-known/lnurlp/${name}`);\n}\n/** Parses a LNURLp into a URL */\nexport function decodeLNURL(lnurl) {\n try {\n const { words, prefix } = bech32.decode(lnurl);\n if (prefix !== \"lnurl\")\n return;\n const str = decoder.decode(bech32.fromWords(words));\n return new URL(str);\n }\n catch (error) { }\n return undefined;\n}\n/** Parses a lightning address or LNURLp into a URL */\nexport function parseLNURLOrAddress(addressOrLNURL) {\n if (addressOrLNURL.includes(\"@\"))\n return parseLightningAddress(addressOrLNURL);\n else\n return decodeLNURL(addressOrLNURL);\n}\n/** Requests a bolt11 invoice from a LNURLp callback URL */\nexport async function getInvoice(callback) {\n const { pr: payRequest } = await fetch(callback).then((res) => res.json());\n const amount = callback.searchParams.get(\"amount\");\n if (!amount)\n throw new Error(\"Missing amount\");\n if (payRequest) {\n const parsed = parseBolt11(payRequest);\n if (parsed.amount !== parseInt(amount))\n throw new Error(\"Incorrect amount\");\n return payRequest;\n }\n else\n throw new Error(\"Failed to get invoice\");\n}\n","import { getOrComputeCachedValue } from \"./cache.js\";\nimport { isSafeRelayURL } from \"./relays.js\";\nimport { isRTag } from \"./tags.js\";\nimport { normalizeURL } from \"./url.js\";\nexport const MailboxesInboxesSymbol = Symbol.for(\"mailboxes-inboxes\");\nexport const MailboxesOutboxesSymbol = Symbol.for(\"mailboxes-outboxes\");\n/** Parses a 10002 event and stores the inboxes in the event using the {@link MailboxesInboxesSymbol} symbol */\nexport function getInboxes(event) {\n return getOrComputeCachedValue(event, MailboxesInboxesSymbol, () => {\n const inboxes = [];\n for (const tag of event.tags) {\n if (!isRTag(tag))\n continue;\n try {\n const [, url, mode] = tag;\n if (url && isSafeRelayURL(url) && !inboxes.includes(url) && (mode === \"read\" || mode === undefined)) {\n inboxes.push(normalizeURL(url));\n }\n }\n catch {\n // Ignore invalid url tags\n }\n }\n return inboxes;\n });\n}\n/** Parses a 10002 event and stores the outboxes in the event using the {@link MailboxesOutboxesSymbol} symbol */\nexport function getOutboxes(event) {\n return getOrComputeCachedValue(event, MailboxesOutboxesSymbol, () => {\n const outboxes = [];\n for (const tag of event.tags) {\n if (!isRTag(tag))\n continue;\n try {\n const [name, url, mode] = tag;\n if (name === \"r\" &&\n isSafeRelayURL(url) &&\n !outboxes.includes(url) &&\n (mode === \"write\" || mode === undefined)) {\n outboxes.push(normalizeURL(url));\n }\n }\n catch {\n // Ignore invalid url tags\n }\n }\n return outboxes;\n });\n}\n","import { kinds } from \"nostr-tools\";\nimport { getOrComputeCachedValue } from \"./cache.js\";\nimport { getHiddenTags, isHiddenTagsUnlocked, unlockHiddenTags } from \"./hidden-tags.js\";\nimport { getIndexableTags, getNip10References, notifyEventUpdate } from \"./index.js\";\nimport { isETag, isPTag, isTTag } from \"./tags.js\";\nexport const MutePublicSymbol = Symbol.for(\"mute-public\");\nexport const MuteHiddenSymbol = Symbol.for(\"mute-hidden\");\n/** Merges any number of mute sets */\nexport function mergeMutes(...mutes) {\n const mute = { pubkeys: new Set(), threads: new Set(), hashtags: new Set(), words: new Set() };\n for (const m of mutes) {\n for (const pubkey of m.pubkeys)\n mute.pubkeys.add(pubkey);\n for (const thread of m.threads)\n mute.threads.add(thread);\n for (const hashtag of m.hashtags)\n mute.hashtags.add(hashtag);\n for (const word of m.words)\n mute.words.add(word);\n }\n return mute;\n}\n/** Parses mute tags */\nexport function parseMutedTags(tags) {\n const pubkeys = new Set(tags.filter(isPTag).map((t) => t[1]));\n const threads = new Set(tags.filter(isETag).map((t) => t[1]));\n const hashtags = new Set(tags.filter(isTTag).map((t) => t[1].toLocaleLowerCase()));\n const words = new Set(tags.filter((t) => t[0] === \"word\" && t[1]).map((t) => t[1].toLocaleLowerCase()));\n return { pubkeys, threads, hashtags, words };\n}\n/** Returns muted things */\nexport function getMutedThings(mute) {\n const hidden = getHiddenMutedThings(mute);\n const mutes = getPublicMutedThings(mute);\n if (hidden)\n return mergeMutes(hidden, mutes);\n return mutes;\n}\n/** Returns only the public muted things from a mute event */\nexport function getPublicMutedThings(mute) {\n return getOrComputeCachedValue(mute, MutePublicSymbol, () => parseMutedTags(mute.tags));\n}\n/** Checks if the hidden mutes are unlocked */\nexport function isHiddenMutesUnlocked(mute) {\n return isHiddenTagsUnlocked(mute) && Reflect.has(mute, MuteHiddenSymbol);\n}\nexport function getHiddenMutedThings(mute) {\n if (isHiddenMutesUnlocked(mute))\n return mute[MuteHiddenSymbol];\n // get hidden tags\n const tags = getHiddenTags(mute);\n if (!tags)\n return undefined;\n // parse muted tags\n const mutes = parseMutedTags(tags);\n // set cached value\n Reflect.set(mute, MuteHiddenSymbol, mutes);\n return mutes;\n}\n/** Unlocks the hidden mutes */\nexport async function unlockHiddenMutes(mute, signer) {\n if (isHiddenMutesUnlocked(mute))\n return mute[MuteHiddenSymbol];\n // Unlock hidden tags\n await unlockHiddenTags(mute, signer);\n // get hidden mutes\n const mutes = getHiddenMutedThings(mute);\n if (!mutes)\n throw new Error(\"Failed to unlock hidden mutes\");\n // Notify event store\n notifyEventUpdate(mute);\n return mutes;\n}\n/** Creates a RegExp for matching muted words */\nexport function createMutedWordsRegExp(mutedWords) {\n // Escape special characters and join with |\n const escapedWords = mutedWords.map((word) => word.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n // Create the RegExp with word boundaries and case insensitive flag\n return new RegExp(`\\\\b(${escapedWords.join(\"|\")})\\\\b`, \"gi\");\n}\n/** Returns true if the event matches the mutes */\nexport function matchMutes(mutes, event) {\n // Filter on muted pubkeys\n if (mutes.pubkeys.size > 0) {\n if (mutes.pubkeys.has(event.pubkey))\n return true;\n }\n // Filter on muted hashtags`\n if (mutes.hashtags.size > 0) {\n const tags = getIndexableTags(event);\n for (let tag of mutes.hashtags) {\n if (tags.has(\"t:\" + tag))\n return true;\n }\n }\n // Filter on muted threads\n if (mutes.threads.size > 0 && event.kind === kinds.ShortTextNote) {\n const refs = getNip10References(event);\n if (refs.root?.e && mutes.threads.has(refs.root.e.id))\n return true;\n }\n // Filter on muted words\n if (mutes.words.size > 0) {\n const regExp = createMutedWordsRegExp(Array.from(mutes.words));\n if (regExp.test(event.content))\n return true;\n }\n // Event does not match any mutes\n return false;\n}\n","import { isETag, isPTag } from \"./tags.js\";\nimport { getOrComputeCachedValue } from \"./cache.js\";\nexport const ParsedReportSymbol = Symbol(\"parsed-report\");\nexport var ReportReason;\n(function (ReportReason) {\n ReportReason[\"nudity\"] = \"nudity\";\n ReportReason[\"malware\"] = \"malware\";\n ReportReason[\"profanity\"] = \"profanity\";\n ReportReason[\"illegal\"] = \"illegal\";\n ReportReason[\"spam\"] = \"spam\";\n ReportReason[\"impersonation\"] = \"impersonation\";\n ReportReason[\"other\"] = \"other\";\n})(ReportReason || (ReportReason = {}));\n/** Reads a report event as either a user or event report */\nexport function getReported(report) {\n return getOrComputeCachedValue(report, ParsedReportSymbol, () => {\n const p = report.tags.find(isPTag);\n if (!p)\n throw new Error(\"Report missing p tag\");\n const comment = report.content ? report.content.trim() : undefined;\n const e = report.tags.find(isETag);\n // Event report\n if (e) {\n const blobs = report.tags.filter((t) => t[0] === \"x\" && t[1]).map((t) => t[1]);\n return {\n type: \"event\",\n event: report,\n comment,\n id: e[1],\n pubkey: p[1],\n reason: e[2],\n blobs,\n };\n }\n // User report\n return { type: \"user\", event: report, comment, pubkey: p[1], reason: p[2] };\n });\n}\n","import { getAddressPointerFromATag } from \"./pointers.js\";\nimport { getOrComputeCachedValue } from \"./cache.js\";\nimport { isSafeRelayURL } from \"./relays.js\";\nexport const Nip10ThreadRefsSymbol = Symbol.for(\"nip10-thread-refs\");\n/**\n * Gets an EventPointer form a NIP-10 threading \"e\" tag\n * @throws\n */\nexport function getEventPointerFromThreadTag(tag) {\n if (!tag[1])\n throw new Error(\"Missing event id in tag\");\n let pointer = { id: tag[1] };\n if (tag[2] && isSafeRelayURL(tag[2]))\n pointer.relays = [tag[2]];\n // get author from NIP-18 quote tags, nip-22 comments tags, or nip-10 thread tags\n if (tag[0] === \"e\" &&\n (tag[3] === \"root\" || tag[3] === \"reply\" || tag[3] === \"mention\") &&\n tag[4] &&\n tag[4].length === 64) {\n // NIP-10 \"e\" tag\n pointer.author = tag[4];\n }\n return pointer;\n}\n/** Parses NIP-10 tags and handles legacy behavior */\nexport function interpretThreadTags(tags) {\n const eTags = tags.filter((t) => t[0] === \"e\" && t[1]);\n const aTags = tags.filter((t) => t[0] === \"a\" && t[1]);\n // find the root and reply tags.\n let rootETag = eTags.find((t) => t[3] === \"root\");\n let replyETag = eTags.find((t) => t[3] === \"reply\");\n let rootATag = aTags.find((t) => t[3] === \"root\");\n let replyATag = aTags.find((t) => t[3] === \"reply\");\n if (!rootETag || !replyETag) {\n // a direct reply does not need a \"reply\" reference\n // https://github.com/nostr-protocol/nips/blob/master/10.md\n // this is not necessarily to spec. but if there is only one id (root or reply) then assign it to both\n // this handles the cases where a client only set a \"reply\" tag and no root\n rootETag = replyETag = rootETag || replyETag;\n }\n if (!rootATag || !replyATag) {\n rootATag = replyATag = rootATag || replyATag;\n }\n if (!rootETag && !replyETag) {\n // legacy behavior\n // https://github.com/nostr-protocol/nips/blob/master/10.md#positional-e-tags-deprecated\n const legacyETags = eTags.filter((t) => {\n // ignore it if there is a marker\n if (t[3])\n return false;\n return true;\n });\n if (legacyETags.length >= 1) {\n // first tag is the root\n rootETag = legacyETags[0];\n // last tag is reply\n replyETag = legacyETags[legacyETags.length - 1] ?? rootETag;\n }\n }\n return {\n root: rootETag || rootATag ? { e: rootETag, a: rootATag } : undefined,\n reply: replyETag || replyATag ? { e: replyETag, a: replyATag } : undefined,\n };\n}\n/** Returns the parsed NIP-10 tags for an event */\nexport function getNip10References(event) {\n return getOrComputeCachedValue(event, Nip10ThreadRefsSymbol, () => {\n const tags = interpretThreadTags(event.tags);\n let root;\n if (tags.root) {\n try {\n root = {\n e: tags.root.e && getEventPointerFromThreadTag(tags.root.e),\n a: tags.root.a && getAddressPointerFromATag(tags.root.a),\n };\n }\n catch (error) { }\n }\n let reply;\n if (tags.reply) {\n try {\n reply = {\n e: tags.reply.e && getEventPointerFromThreadTag(tags.reply.e),\n a: tags.reply.a && getAddressPointerFromATag(tags.reply.a),\n };\n }\n catch (error) { }\n }\n return {\n root,\n reply,\n };\n });\n}\n","import { finalize, tap } from \"rxjs\";\n/** keep a claim on any event that goes through this observable, claims are removed when the observable is unsubscribed or completes */\nexport function claimEvents(claims) {\n return (source) => {\n const seen = new Set();\n return source.pipe(\n // claim all events\n tap((message) => {\n if (message === undefined)\n return;\n if (Array.isArray(message)) {\n for (const event of message) {\n if (seen.has(event))\n continue;\n seen.add(event);\n claims.claim(event);\n }\n }\n else if (!seen.has(message)) {\n seen.add(message);\n claims.claim(message);\n }\n }), \n // remove claims on cleanup\n finalize(() => {\n for (const e of seen)\n claims.removeClaim(e);\n }));\n };\n}\n","import { finalize, tap } from \"rxjs\";\n/** An operator that claims the latest event with the database */\nexport function claimLatest(claims) {\n return (source) => {\n let latest = undefined;\n return source.pipe(tap((event) => {\n // only update if the event changed\n if (latest !== event) {\n // remove old claim\n if (latest)\n claims.removeClaim(latest);\n // claim new event\n if (event)\n claims.claim(event);\n // update state\n latest = event;\n }\n }), finalize(() => {\n // remove latest claim\n if (latest)\n claims.removeClaim(latest);\n }));\n };\n}\n","import { filter } from \"rxjs\";\n/** Filters out undefined and null values */\nexport function defined() {\n return (source) => source.pipe(filter((v) => v !== undefined && v !== null));\n}\n","import { Observable } from \"rxjs\";\n/** if a synchronous value is not emitted, default is emitted */\nexport function withImmediateValueOrDefault(defaultValue) {\n return (source) => new Observable((observer) => {\n let seen = false;\n const sub = source.subscribe({\n next: (v) => {\n seen = true;\n observer.next(v);\n },\n error: (err) => observer.error(err),\n complete: () => observer.complete(),\n });\n // if a value is not emitted sync, emit default\n if (!seen)\n observer.next(defaultValue);\n return sub;\n });\n}\n","import { combineLatest, defer, distinctUntilChanged, EMPTY, endWith, filter, finalize, from, ignoreElements, map, merge, mergeWith, of, repeat, scan, switchMap, take, takeUntil, tap, } from \"rxjs\";\nimport { insertEventIntoDescendingList } from \"nostr-tools/utils\";\nimport { createReplaceableAddress, getEventUID, getReplaceableIdentifier, isReplaceable, matchFilters, } from \"../helpers/index.js\";\nimport { claimEvents } from \"../observable/claim-events.js\";\nimport { claimLatest } from \"../observable/claim-latest.js\";\nimport { defined } from \"../observable/defined.js\";\nimport { withImmediateValueOrDefault } from \"../observable/with-immediate-value.js\";\n/** Gets a single event from both types of event stores and returns an observable that completes */\nfunction getEventFromStores(store, pointer) {\n const r = store.getEvent(pointer.id);\n if (r instanceof Promise)\n return from(r);\n else\n return of(r);\n}\n/** Gets a single replaceable event from both types of event stores and returns an observable that completes */\nfunction getReplaceableFromStores(store, pointer) {\n const r = store.getReplaceable(pointer.kind, pointer.pubkey, pointer.identifier);\n if (r instanceof Promise)\n return from(r);\n else\n return of(r);\n}\n/** If event is undefined, attempt to load using the fallback loader */\nfunction loadEventUsingFallback(store, pointer) {\n return switchMap((event) => {\n if (event)\n return of(event);\n // If event was not found, attempt to load\n if (!store.eventLoader)\n return EMPTY;\n return from(store.eventLoader(pointer));\n });\n}\n/** If replaceable event is undefined, attempt to load using the fallback loader */\nfunction loadReplaceableUsingFallback(store, pointer) {\n return switchMap((event) => {\n if (event)\n return of(event);\n else if (pointer.identifier !== undefined) {\n if (!store.addressableLoader)\n return EMPTY;\n return from(store.addressableLoader(pointer)).pipe(filter((e) => !!e));\n }\n else {\n if (!store.replaceableLoader)\n return EMPTY;\n return from(store.replaceableLoader(pointer)).pipe(filter((e) => !!e));\n }\n });\n}\n/** A model that returns a single event or undefined when its removed */\nexport function EventModel(pointer) {\n if (typeof pointer === \"string\")\n pointer = { id: pointer };\n return (store) => merge(\n // get current event and ignore if there is none\n defer(() => getEventFromStores(store, pointer)).pipe(\n // If the event isn't found, attempt to load using the fallback loader\n loadEventUsingFallback(store, pointer), \n // Only emit found events\n defined()), \n // Listen for new events\n store.insert$.pipe(filter((e) => e.id === pointer.id)), \n // emit undefined when deleted\n store.remove$.pipe(filter((e) => e.id === pointer.id), take(1), ignoreElements(), \n // Emit undefined when deleted\n endWith(undefined))).pipe(\n // claim all events\n claimLatest(store), \n // ignore duplicate events\n distinctUntilChanged((a, b) => a?.id === b?.id), \n // always emit undefined so the observable is synchronous\n withImmediateValueOrDefault(undefined));\n}\n/** A model that returns the latest version of a replaceable event or undefined if its removed */\nexport function ReplaceableModel(pointer) {\n return (store) => {\n let current = undefined;\n return merge(\n // lazily get current event\n defer(() => getReplaceableFromStores(store, pointer)).pipe(\n // If the event isn't found, attempt to load using the fallback loader\n loadReplaceableUsingFallback(store, pointer), \n // Only emit found events\n defined()), \n // Subscribe to new events that match the pointer\n store.insert$.pipe(filter((e) => e.pubkey == pointer.pubkey &&\n e.kind === pointer.kind &&\n (pointer.identifier !== undefined ? getReplaceableIdentifier(e) === pointer.identifier : true)))).pipe(\n // only update if event is newer\n distinctUntilChanged((prev, event) => {\n // are the events the same? i.e. is the prev event older\n return prev.created_at >= event.created_at;\n }), \n // Hacky way to extract the current event so takeUntil can access it\n tap((event) => (current = event)), \n // complete when event is removed\n takeUntil(store.remove$.pipe(filter((e) => e.id === current?.id))), \n // emit undefined when removed\n endWith(undefined), \n // keep the observable hot\n repeat(), \n // claim latest event\n claimLatest(store), \n // always emit undefined so the observable is synchronous\n withImmediateValueOrDefault(undefined));\n };\n}\n/** A model that returns an array of sorted events matching the filters */\nexport function TimelineModel(filters, includeOldVersion) {\n filters = Array.isArray(filters) ? filters : [filters];\n return (store) => {\n const seen = new Map();\n // get current events\n return defer(() => {\n const r = store.getTimeline(filters);\n if (r instanceof Promise)\n return from(r);\n else\n return of(r);\n }).pipe(\n // claim existing events\n claimEvents(store), \n // subscribe to newer events\n mergeWith(store.insert$.pipe(filter((e) => matchFilters(filters, e)), \n // claim all new events\n claimEvents(store))), \n // subscribe to delete events\n mergeWith(store.remove$.pipe(filter((e) => matchFilters(filters, e)), map((e) => e.id))), \n // build a timeline\n scan((timeline, event) => {\n // filter out removed events from timeline\n if (typeof event === \"string\")\n return timeline.filter((e) => e.id !== event);\n // initial timeline array\n if (Array.isArray(event)) {\n if (!includeOldVersion) {\n for (const e of event)\n if (isReplaceable(e.kind))\n seen.set(getEventUID(e), e);\n }\n return event;\n }\n // create a new timeline and insert the event into it\n let newTimeline = [...timeline];\n // remove old replaceable events if enabled\n if (!includeOldVersion && isReplaceable(event.kind)) {\n const uid = getEventUID(event);\n const existing = seen.get(uid);\n // if this is an older replaceable event, exit\n if (existing && event.created_at < existing.created_at)\n return timeline;\n // update latest version\n seen.set(uid, event);\n // remove old event from timeline\n if (existing)\n newTimeline.slice(newTimeline.indexOf(existing), 1);\n }\n // add event into timeline\n insertEventIntoDescendingList(newTimeline, event);\n return newTimeline;\n }, []), \n // ignore changes that do not modify the timeline instance\n distinctUntilChanged(), \n // hacky hack to clear seen on unsubscribe\n finalize(() => seen.clear()));\n };\n}\n/**\n * A model that returns a multiple events in a map\n * @deprecated use multiple {@link EventModel} instead\n */\nexport function EventsModel(ids) {\n return (events) => combineLatest(Object.fromEntries(ids.map((id) => [id, events.model(EventModel, { id })])));\n}\n/**\n * A model that returns a directory of events by their UID\n * @deprecated use multiple {@link ReplaceableModel} instead\n */\nexport function ReplaceableSetModel(pointers) {\n return (events) => combineLatest(Object.fromEntries(pointers.map((pointer) => [\n createReplaceableAddress(pointer.kind, pointer.pubkey, pointer.identifier),\n events.model(ReplaceableModel, pointer),\n ])));\n}\n","import { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { noop } from '../util/noop';\nexport function ignoreElements() {\n return operate(function (source, subscriber) {\n source.subscribe(createOperatorSubscriber(subscriber, noop));\n });\n}\n//# sourceMappingURL=ignoreElements.js.map","import { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { innerFrom } from '../observable/innerFrom';\nimport { noop } from '../util/noop';\nexport function takeUntil(notifier) {\n return operate(function (source, subscriber) {\n innerFrom(notifier).subscribe(createOperatorSubscriber(subscriber, function () { return subscriber.complete(); }, noop));\n !subscriber.closed && source.subscribe(subscriber);\n });\n}\n//# sourceMappingURL=takeUntil.js.map","import { EMPTY } from '../observable/empty';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { innerFrom } from '../observable/innerFrom';\nimport { timer } from '../observable/timer';\nexport function repeat(countOrConfig) {\n var _a;\n var count = Infinity;\n var delay;\n if (countOrConfig != null) {\n if (typeof countOrConfig === 'object') {\n (_a = countOrConfig.count, count = _a === void 0 ? Infinity : _a, delay = countOrConfig.delay);\n }\n else {\n count = countOrConfig;\n }\n }\n return count <= 0\n ? function () { return EMPTY; }\n : operate(function (source, subscriber) {\n var soFar = 0;\n var sourceSub;\n var resubscribe = function () {\n sourceSub === null || sourceSub === void 0 ? void 0 : sourceSub.unsubscribe();\n sourceSub = null;\n if (delay != null) {\n var notifier = typeof delay === 'number' ? timer(delay) : innerFrom(delay(soFar));\n var notifierSubscriber_1 = createOperatorSubscriber(subscriber, function () {\n notifierSubscriber_1.unsubscribe();\n subscribeToSource();\n });\n notifier.subscribe(notifierSubscriber_1);\n }\n else {\n subscribeToSource();\n }\n };\n var subscribeToSource = function () {\n var syncUnsub = false;\n sourceSub = source.subscribe(createOperatorSubscriber(subscriber, undefined, function () {\n if (++soFar < count) {\n if (sourceSub) {\n resubscribe();\n }\n else {\n syncUnsub = true;\n }\n }\n else {\n subscriber.complete();\n }\n }));\n if (syncUnsub) {\n resubscribe();\n }\n };\n subscribeToSource();\n });\n}\n//# sourceMappingURL=repeat.js.map","import { filter, map, merge, tap } from \"rxjs\";\n/** Watches for any updates to the latest event and remits the event when updated */\nexport function watchEventUpdates(eventStore) {\n return (source) => {\n let latest;\n return merge(\n // Get the latest event\n source.pipe(tap((value) => (latest = value))), \n // listen for updates\n eventStore.update$.pipe(filter((e) => e.id === latest?.id)));\n };\n}\n/** Watches for any updates to the latest array of events and remits the array of events when updated */\nexport function watchEventsUpdates(eventStore) {\n return (source) => {\n let latest = [];\n return merge(\n // Get the latest event\n source.pipe(tap((value) => (latest = value))), \n // listen for updates\n eventStore.update$.pipe(filter((e) => latest.includes(e)), \n // re-emit the array of events\n map(() => latest)));\n };\n}\n","import { kinds } from \"nostr-tools\";\nimport { map } from \"rxjs/operators\";\nimport { getContacts, getHiddenContacts, getPublicContacts } from \"../helpers/contacts.js\";\nimport { watchEventUpdates } from \"../observable/index.js\";\n/** A model that returns all contacts for a user */\nexport function ContactsModel(user) {\n if (typeof user === \"string\")\n user = { pubkey: user };\n return (events) => events.replaceable({ kind: kinds.Contacts, pubkey: user.pubkey, relays: user.relays }).pipe(\n // listen for event updates (hidden tags unlocked)\n watchEventUpdates(events), \n // Get all contacts\n map((e) => (e ? getContacts(e) : [])));\n}\n/** A model that returns all public contacts for a user */\nexport function PublicContactsModel(pubkey) {\n return (events) => events.replaceable(kinds.Contacts, pubkey).pipe(map((e) => e && getPublicContacts(e)));\n}\n/** A model that returns all hidden contacts for a user */\nexport function HiddenContactsModel(pubkey) {\n return (events) => events.replaceable(kinds.Contacts, pubkey).pipe(\n // listen for event updates (hidden tags unlocked)\n watchEventUpdates(events), \n // Get hidden contacts\n map((e) => e && (getHiddenContacts(e) ?? null)));\n}\n","import { isAddressableKind } from \"nostr-tools/kinds\";\nimport { COMMENT_KIND, getReplaceableAddress } from \"../helpers/index.js\";\n/** A model that returns all NIP-22 comment replies for the event */\nexport function CommentsModel(parent) {\n return (events) => {\n const filters = [{ kinds: [COMMENT_KIND], \"#e\": [parent.id] }];\n if (isAddressableKind(parent.kind))\n filters.push({ kinds: [COMMENT_KIND], \"#a\": [getReplaceableAddress(parent)] });\n return events.timeline(filters);\n };\n}\n","import { kinds } from \"nostr-tools\";\nimport { map } from \"rxjs/operators\";\nimport { getInboxes, getOutboxes } from \"../helpers/mailboxes.js\";\n/** A model that gets and parses the inbox and outbox relays for a pubkey */\nexport function MailboxesModel(user) {\n if (typeof user === \"string\")\n user = { pubkey: user };\n return (events) => events.replaceable({ kind: kinds.RelayList, pubkey: user.pubkey, relays: user.relays }).pipe(map((event) => event && {\n inboxes: getInboxes(event),\n outboxes: getOutboxes(event),\n }));\n}\n","import { kinds } from \"nostr-tools\";\nimport { map } from \"rxjs/operators\";\nimport { getHiddenMutedThings, getMutedThings, getPublicMutedThings } from \"../helpers/mutes.js\";\nimport { watchEventUpdates } from \"../observable/watch-event-updates.js\";\n/** A model that returns all a users muted things */\nexport function MuteModel(user) {\n if (typeof user === \"string\")\n user = { pubkey: user };\n return (events) => events.replaceable({ kind: kinds.Mutelist, pubkey: user.pubkey, relays: user.relays }).pipe(\n // listen for event updates (hidden tags unlocked)\n watchEventUpdates(events), \n // Get all muted things\n map((event) => event && getMutedThings(event)));\n}\n/** A model that returns all a users public muted things */\nexport function PublicMuteModel(pubkey) {\n return (events) => events.replaceable(kinds.Mutelist, pubkey).pipe(map((event) => event && getPublicMutedThings(event)));\n}\n/** A model that returns all a users hidden muted things */\nexport function HiddenMuteModel(pubkey) {\n return (events) => events.replaceable(kinds.Mutelist, pubkey).pipe(\n // listen for event updates (hidden tags unlocked)\n watchEventUpdates(events), \n // Get hidden muted things\n map((event) => event && getHiddenMutedThings(event)));\n}\n","import { kinds } from \"nostr-tools\";\nimport { filter, map } from \"rxjs/operators\";\nimport { getProfileContent, isValidProfile } from \"../helpers/profile.js\";\nimport { withImmediateValueOrDefault } from \"../observable/with-immediate-value.js\";\n/** A model that gets and parses the kind 0 metadata for a pubkey */\nexport function ProfileModel(user) {\n if (typeof user === \"string\")\n user = { pubkey: user };\n return (events) => events.replaceable({ kind: kinds.Metadata, pubkey: user.pubkey, relays: user.relays }).pipe(\n // Filter out invalid profile events\n filter(isValidProfile), \n // Parse the profile event into a ProfileContent\n map((event) => event && getProfileContent(event)), \n // Ensure the model is synchronous\n withImmediateValueOrDefault(undefined));\n}\n","import { kinds } from \"nostr-tools\";\nimport { getEventUID, isReplaceable } from \"../helpers/event.js\";\n/** A model that returns all reactions to an event (supports replaceable events) */\nexport function ReactionsModel(event) {\n return (events) => events.timeline(isReplaceable(event.kind)\n ? [\n { kinds: [kinds.Reaction], \"#e\": [event.id] },\n { kinds: [kinds.Reaction], \"#a\": [getEventUID(event)] },\n ]\n : [\n {\n kinds: [kinds.Reaction],\n \"#e\": [event.id],\n },\n ]);\n}\n","import { kinds } from \"nostr-tools\";\nimport { isAddressableKind } from \"nostr-tools/kinds\";\nimport { map } from \"rxjs/operators\";\nimport { COMMENT_KIND } from \"../helpers/comment.js\";\nimport { getTagValue } from \"../helpers/event-tags.js\";\nimport { createReplaceableAddress, getEventUID, isEvent } from \"../helpers/event.js\";\nimport { getCoordinateFromAddressPointer, isAddressPointer, isEventPointer } from \"../helpers/pointers.js\";\nimport { getNip10References, interpretThreadTags } from \"../helpers/threading.js\";\nconst defaultOptions = {\n kinds: [kinds.ShortTextNote],\n};\n/** A model that returns a NIP-10 thread of events */\nexport function ThreadModel(root, opts) {\n const parentReferences = new Map();\n const items = new Map();\n const { kinds } = { ...defaultOptions, ...opts };\n let rootUID = \"\";\n const rootFilter = {};\n const replyFilter = { kinds };\n if (isAddressPointer(root)) {\n rootUID = getCoordinateFromAddressPointer(root);\n rootFilter.kinds = [root.kind];\n rootFilter.authors = [root.pubkey];\n rootFilter[\"#d\"] = [root.identifier];\n replyFilter[\"#a\"] = [rootUID];\n }\n else if (typeof root === \"string\") {\n rootUID = root;\n rootFilter.ids = [root];\n replyFilter[\"#e\"] = [root];\n }\n else {\n rootUID = root.id;\n rootFilter.ids = [root.id];\n replyFilter[\"#e\"] = [root.id];\n }\n return (events) => events.filters([rootFilter, replyFilter]).pipe(map((event) => {\n if (!items.has(getEventUID(event))) {\n const refs = getNip10References(event);\n const replies = parentReferences.get(getEventUID(event)) || new Set();\n const item = { event, refs, replies };\n for (const child of replies) {\n child.parent = item;\n }\n // add item to parent\n if (refs.reply?.e || refs.reply?.a) {\n let uid = refs.reply.e ? refs.reply.e.id : getCoordinateFromAddressPointer(refs.reply.a);\n item.parent = items.get(uid);\n if (item.parent) {\n item.parent.replies.add(item);\n }\n else {\n // parent isn't created yet, store ref for later\n let set = parentReferences.get(uid);\n if (!set) {\n set = new Set();\n parentReferences.set(uid, set);\n }\n set.add(item);\n }\n }\n // add item to map\n items.set(getEventUID(event), item);\n }\n return { root: items.get(rootUID), all: items };\n }));\n}\n/** A model that gets all legacy and NIP-10, and NIP-22 replies for an event */\nexport function RepliesModel(event, overrideKinds) {\n return (events) => {\n const kinds = overrideKinds || event.kind === 1 ? [1, COMMENT_KIND] : [COMMENT_KIND];\n const filter = { kinds };\n if (isEvent(parent) || isEventPointer(event))\n filter[\"#e\"] = [event.id];\n const address = isAddressableKind(event.kind)\n ? createReplaceableAddress(event.kind, event.pubkey, getTagValue(event, \"d\"))\n : undefined;\n if (address) {\n filter[\"#a\"] = [address];\n }\n return events.timeline(filter).pipe(map((events) => {\n return events.filter((e) => {\n const refs = interpretThreadTags(e.tags);\n return refs.reply?.e?.[1] === event.id || refs.reply?.a?.[1] === address;\n });\n }));\n };\n}\n","import hash_sum from \"hash-sum\";\nimport { EMPTY, ReplaySubject, filter, finalize, from, merge, mergeMap, share, timer } from \"rxjs\";\nimport { matchFilters } from \"../helpers/filter.js\";\n// Model imports\nimport { UserBlossomServersModel } from \"../models/blossom.js\";\nimport { EventModel, EventsModel, ReplaceableModel, ReplaceableSetModel, TimelineModel } from \"../models/common.js\";\nimport { ContactsModel } from \"../models/contacts.js\";\nimport { CommentsModel, ThreadModel } from \"../models/index.js\";\nimport { MailboxesModel } from \"../models/mailboxes.js\";\nimport { MuteModel } from \"../models/mutes.js\";\nimport { ProfileModel } from \"../models/profile.js\";\nimport { ReactionsModel } from \"../models/reactions.js\";\n/** A mixin that provides model functionality for both sync and async event stores */\nexport function EventStoreModelMixin(Base) {\n return class extends Base {\n /** A directory of all active models */\n models = new Map();\n /** How long a model should be kept \"warm\" while nothing is subscribed to it */\n modelKeepWarm = 60_000;\n /** Get or create a model on the event store */\n model(constructor, ...args) {\n let models = this.models.get(constructor);\n if (!models) {\n models = new Map();\n this.models.set(constructor, models);\n }\n const key = constructor.getKey ? constructor.getKey(...args) : hash_sum(args);\n let model = models.get(key);\n // Create the model if it does not exist\n if (!model) {\n const cleanup = () => {\n // Remove the model from the cache if its the same one\n if (models.get(key) === model)\n models.delete(key);\n };\n model = constructor(...args)(this).pipe(\n // remove the model when its unsubscribed\n finalize(cleanup), \n // only subscribe to models once for all subscriptions\n share({\n connector: () => new ReplaySubject(1),\n resetOnComplete: () => timer(this.modelKeepWarm),\n resetOnRefCountZero: () => timer(this.modelKeepWarm),\n }));\n // Add the model to the cache\n models.set(key, model);\n }\n return model;\n }\n /**\n * Creates an observable that streams all events that match the filter\n * @param filters\n * @param [onlyNew=false] Only subscribe to new events\n */\n filters(filters, onlyNew = false) {\n filters = Array.isArray(filters) ? filters : [filters];\n const getByFiltersResult = this.getByFilters(filters);\n // Create the existing events observable\n const existingEvents$ = onlyNew\n ? EMPTY\n : // Check if result is a Promise (async) or direct Set (sync)\n getByFiltersResult && typeof getByFiltersResult.then === \"function\"\n ? from(getByFiltersResult).pipe(mergeMap((events) => from(Array.from(events))))\n : from(Array.from(getByFiltersResult));\n // Create the new events observable\n const newEvents$ = this.insert$.pipe(filter((e) => matchFilters(filters, e)));\n return merge(existingEvents$, newEvents$);\n }\n // Helper methods for creating models\n /** Creates a {@link EventModel} */\n event(pointer) {\n if (typeof pointer === \"string\")\n pointer = { id: pointer };\n return this.model(EventModel, pointer);\n }\n replaceable(...args) {\n let pointer;\n // Parse arguments\n if (args.length === 1) {\n pointer = args[0];\n }\n else if (args.length === 3 || args.length === 2) {\n let [kind, pubkey, identifier] = args;\n pointer = { kind, pubkey, identifier };\n }\n if (!pointer)\n throw new Error(\"Invalid arguments, expected address pointer or kind, pubkey, identifier\");\n return this.model(ReplaceableModel, pointer);\n }\n /** Subscribe to an addressable event by pointer */\n addressable(pointer) {\n return this.model(ReplaceableModel, pointer);\n }\n /** Creates a {@link TimelineModel} */\n timeline(filters, includeOldVersion = false) {\n return this.model(TimelineModel, filters, includeOldVersion);\n }\n /** Subscribe to a users profile */\n profile(user) {\n return this.model(ProfileModel, user);\n }\n /** Subscribe to a users contacts */\n contacts(user) {\n if (typeof user === \"string\")\n user = { pubkey: user };\n return this.model(ContactsModel, user);\n }\n /** Subscribe to a users mutes */\n mutes(user) {\n if (typeof user === \"string\")\n user = { pubkey: user };\n return this.model(MuteModel, user);\n }\n /** Subscribe to a users NIP-65 mailboxes */\n mailboxes(user) {\n if (typeof user === \"string\")\n user = { pubkey: user };\n return this.model(MailboxesModel, user);\n }\n /** Subscribe to a users blossom servers */\n blossomServers(user) {\n if (typeof user === \"string\")\n user = { pubkey: user };\n return this.model(UserBlossomServersModel, user);\n }\n /** Subscribe to an event's reactions */\n reactions(event) {\n return this.model(ReactionsModel, event);\n }\n /** Subscribe to a thread */\n thread(root) {\n return this.model(ThreadModel, root);\n }\n /** Subscribe to a event's comments */\n comments(event) {\n return this.model(CommentsModel, event);\n }\n /** @deprecated use multiple {@link EventModel} instead */\n events(ids) {\n return this.model(EventsModel, ids);\n }\n /** @deprecated use multiple {@link ReplaceableModel} instead */\n replaceableSet(pointers) {\n return this.model(ReplaceableSetModel, pointers);\n }\n };\n}\n","import { kinds } from \"nostr-tools\";\nimport { isAddressableKind } from \"nostr-tools/kinds\";\nimport { EMPTY, filter, mergeMap, Subject, take } from \"rxjs\";\nimport { getDeleteCoordinates, getDeleteIds } from \"../helpers/delete.js\";\nimport { createReplaceableAddress, EventStoreSymbol, FromCacheSymbol, isReplaceable } from \"../helpers/event.js\";\nimport { getExpirationTimestamp } from \"../helpers/expiration.js\";\nimport { parseCoordinate } from \"../helpers/pointers.js\";\nimport { addSeenRelay, getSeenRelays } from \"../helpers/relays.js\";\nimport { unixNow } from \"../helpers/time.js\";\nimport { EventMemory } from \"./event-memory.js\";\nimport { EventStoreModelMixin } from \"./model-mixin.js\";\n/** A wrapper around an event database that handles replaceable events, deletes, and models */\nexport class EventStore extends EventStoreModelMixin(class {\n}) {\n database;\n /** Optional memory database for ensuring single event instances */\n memory;\n /** Enable this to keep old versions of replaceable events */\n keepOldVersions = false;\n /** Enable this to keep expired events */\n keepExpired = false;\n /**\n * A method used to verify new events before added them\n * @returns true if the event is valid, false if it should be ignored\n */\n verifyEvent;\n /** A stream of new events added to the store */\n insert$ = new Subject();\n /** A stream of events that have been updated */\n update$ = new Subject();\n /** A stream of events that have been removed */\n remove$ = new Subject();\n /**\n * A method that will be called when an event isn't found in the store\n * @experimental\n */\n eventLoader;\n /**\n * A method that will be called when a replaceable event isn't found in the store\n * @experimental\n */\n replaceableLoader;\n /**\n * A method that will be called when an addressable event isn't found in the store\n * @experimental\n */\n addressableLoader;\n constructor(database = new EventMemory()) {\n super();\n if (database) {\n this.database = database;\n this.memory = new EventMemory();\n }\n else {\n // If no database is provided, its the same as having a memory database\n this.database = this.memory = new EventMemory();\n }\n // when events are added to the database, add the symbol\n this.insert$.subscribe((event) => {\n Reflect.set(event, EventStoreSymbol, this);\n });\n // when events are removed from the database, remove the symbol\n this.remove$.subscribe((event) => {\n Reflect.deleteProperty(event, EventStoreSymbol);\n });\n }\n mapToMemory(event) {\n if (event === undefined)\n return undefined;\n if (!this.memory)\n return event;\n return this.memory.add(event);\n }\n // delete state\n deletedIds = new Set();\n deletedCoords = new Map();\n checkDeleted(event) {\n if (typeof event === \"string\")\n return this.deletedIds.has(event);\n else {\n if (this.deletedIds.has(event.id))\n return true;\n if (isAddressableKind(event.kind)) {\n const identifier = event.tags.find((t) => t[0] === \"d\")?.[1];\n const deleted = this.deletedCoords.get(createReplaceableAddress(event.kind, event.pubkey, identifier));\n if (deleted)\n return deleted > event.created_at;\n }\n }\n return false;\n }\n expirations = new Map();\n /** Adds an event to the expiration map */\n addExpiration(event) {\n const expiration = getExpirationTimestamp(event);\n if (expiration && Number.isFinite(expiration))\n this.expirations.set(event.id, expiration);\n }\n expirationTimeout = null;\n nextExpirationCheck = null;\n handleExpiringEvent(event) {\n const expiration = getExpirationTimestamp(event);\n if (!expiration)\n return;\n // Add event to expiration map\n this.expirations.set(event.id, expiration);\n // Exit if the next check is already less than the next expiration\n if (this.expirationTimeout && this.nextExpirationCheck && this.nextExpirationCheck < expiration)\n return;\n // Set timeout to prune expired events\n if (this.expirationTimeout)\n clearTimeout(this.expirationTimeout);\n const timeout = expiration - unixNow();\n this.expirationTimeout = setTimeout(this.pruneExpired.bind(this), timeout * 1000 + 10);\n this.nextExpirationCheck = expiration;\n }\n /** Remove expired events from the store */\n pruneExpired() {\n const now = unixNow();\n for (const [id, expiration] of this.expirations) {\n if (expiration <= now) {\n this.expirations.delete(id);\n this.remove(id);\n }\n }\n // Cleanup timers\n if (this.expirationTimeout)\n clearTimeout(this.expirationTimeout);\n this.nextExpirationCheck = null;\n this.expirationTimeout = null;\n }\n // handling delete events\n handleDeleteEvent(deleteEvent) {\n const ids = getDeleteIds(deleteEvent);\n for (const id of ids) {\n this.deletedIds.add(id);\n // remove deleted events in the database\n this.remove(id);\n }\n const coords = getDeleteCoordinates(deleteEvent);\n for (const coord of coords) {\n this.deletedCoords.set(coord, Math.max(this.deletedCoords.get(coord) ?? 0, deleteEvent.created_at));\n // Parse the nostr address coordinate\n const parsed = parseCoordinate(coord);\n if (!parsed)\n continue;\n // Remove older versions of replaceable events\n const events = this.database.getReplaceableHistory(parsed.kind, parsed.pubkey, parsed.identifier) ?? [];\n for (const event of events) {\n if (event.created_at < deleteEvent.created_at)\n this.remove(event);\n }\n }\n }\n /** Copies important metadata from and identical event to another */\n static mergeDuplicateEvent(source, dest) {\n const relays = getSeenRelays(source);\n if (relays) {\n for (const relay of relays)\n addSeenRelay(dest, relay);\n }\n // copy the from cache symbol only if its true\n const fromCache = Reflect.get(source, FromCacheSymbol);\n if (fromCache && !Reflect.get(dest, FromCacheSymbol))\n Reflect.set(dest, FromCacheSymbol, fromCache);\n }\n /**\n * Adds an event to the store and update subscriptions\n * @returns The existing event or the event that was added, if it was ignored returns null\n */\n add(event, fromRelay) {\n // Handle delete events differently\n if (event.kind === kinds.EventDeletion)\n this.handleDeleteEvent(event);\n // Ignore if the event was deleted\n if (this.checkDeleted(event))\n return event;\n // Reject expired events if keepExpired is false\n const expiration = getExpirationTimestamp(event);\n if (this.keepExpired === false && expiration && expiration <= unixNow())\n return null;\n // Get the replaceable identifier\n const identifier = isReplaceable(event.kind) ? event.tags.find((t) => t[0] === \"d\")?.[1] : undefined;\n // Don't insert the event if there is already a newer version\n if (!this.keepOldVersions && isReplaceable(event.kind)) {\n const existing = this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);\n // If there is already a newer version, copy cached symbols and return existing event\n if (existing && existing.length > 0 && existing[0].created_at >= event.created_at) {\n EventStore.mergeDuplicateEvent(event, existing[0]);\n return existing[0];\n }\n }\n // Verify event before inserting into the database\n if (this.verifyEvent && this.verifyEvent(event) === false)\n return null;\n // Always add event to memory\n const existing = this.memory?.add(event);\n // If the memory returned a different instance, this is a duplicate event\n if (existing && existing !== event) {\n // Copy cached symbols and return existing event\n EventStore.mergeDuplicateEvent(event, existing);\n // attach relay this event was from\n if (fromRelay)\n addSeenRelay(existing, fromRelay);\n return existing;\n }\n // Insert event into database\n const inserted = this.mapToMemory(this.database.add(event));\n // Copy cached data if its a duplicate event\n if (event !== inserted)\n EventStore.mergeDuplicateEvent(event, inserted);\n // attach relay this event was from\n if (fromRelay)\n addSeenRelay(inserted, fromRelay);\n // Emit insert$ signal\n if (inserted === event)\n this.insert$.next(inserted);\n // remove all old version of the replaceable event\n if (!this.keepOldVersions && isReplaceable(event.kind)) {\n const existing = this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);\n if (existing && existing.length > 0) {\n const older = Array.from(existing).filter((e) => e.created_at < event.created_at);\n for (const old of older)\n this.remove(old);\n // return the newest version of the replaceable event\n // most of the time this will be === event, but not always\n if (existing.length !== older.length)\n return existing[0];\n }\n }\n // Add event to expiration map\n if (this.keepExpired === false && expiration)\n this.handleExpiringEvent(inserted);\n return inserted;\n }\n /** Removes an event from the store and updates subscriptions */\n remove(event) {\n let instance = this.memory?.getEvent(typeof event === \"string\" ? event : event.id);\n // Remove from memory if available\n if (this.memory)\n this.memory.remove(event);\n // Remove the event from the database\n const removed = this.database.remove(event);\n // If the event was removed, notify the subscriptions\n if (removed && instance) {\n this.remove$.next(instance);\n }\n return removed;\n }\n /** Remove multiple events that match the given filters */\n removeByFilters(filters) {\n // Get events that will be removed for notification\n const eventsToRemove = this.getByFilters(filters);\n // Remove from memory if available\n if (this.memory)\n this.memory.removeByFilters(filters);\n // Remove from database\n const removedCount = this.database.removeByFilters(filters);\n // Notify subscriptions for each removed event\n for (const event of eventsToRemove) {\n this.remove$.next(event);\n }\n return removedCount;\n }\n /** Add an event to the store and notifies all subscribes it has updated */\n update(event) {\n // Map the event to the current instance in the database\n const e = this.database.add(event);\n if (!e)\n return false;\n // Notify the database that the event has updated\n this.database.update?.(event);\n this.update$.next(event);\n return true;\n }\n /** Check if the store has an event by id */\n hasEvent(id) {\n // Check if the event exists in memory first, then in the database\n return this.memory?.hasEvent(id) || this.database.hasEvent(id);\n }\n /** Get an event by id from the store */\n getEvent(id) {\n // Get the event from memory first, then from the database\n return this.memory?.getEvent(id) ?? this.mapToMemory(this.database.getEvent(id));\n }\n /** Check if the store has a replaceable event */\n hasReplaceable(kind, pubkey, d) {\n // Check if the event exists in memory first, then in the database\n return this.memory?.hasReplaceable(kind, pubkey, d) || this.database.hasReplaceable(kind, pubkey, d);\n }\n /** Gets the latest version of a replaceable event */\n getReplaceable(kind, pubkey, identifier) {\n // Get the event from memory first, then from the database\n return (this.memory?.getReplaceable(kind, pubkey, identifier) ??\n this.mapToMemory(this.database.getReplaceable(kind, pubkey, identifier)));\n }\n /** Returns all versions of a replaceable event */\n getReplaceableHistory(kind, pubkey, identifier) {\n // Get the events from memory first, then from the database\n return (this.memory?.getReplaceableHistory(kind, pubkey, identifier) ??\n this.database.getReplaceableHistory(kind, pubkey, identifier)?.map((e) => this.mapToMemory(e) ?? e));\n }\n /** Get all events matching a filter */\n getByFilters(filters) {\n // NOTE: no way to read from memory since memory won't have the full set of events\n const events = this.database.getByFilters(filters);\n // Map events to memory if available for better performance\n if (this.memory)\n return events.map((e) => this.mapToMemory(e));\n else\n return events;\n }\n /** Returns a timeline of events that match filters */\n getTimeline(filters) {\n const events = this.database.getTimeline(filters);\n if (this.memory)\n return events.map((e) => this.mapToMemory(e));\n else\n return events;\n }\n /** Passthrough method for the database.touch */\n touch(event) {\n return this.memory?.touch(event);\n }\n /** Increments the claim count on the event and touches it */\n claim(event) {\n return this.memory?.claim(event);\n }\n /** Checks if an event is claimed by anything */\n isClaimed(event) {\n return this.memory?.isClaimed(event) ?? false;\n }\n /** Decrements the claim count on an event */\n removeClaim(event) {\n return this.memory?.removeClaim(event);\n }\n /** Removes all claims on an event */\n clearClaim(event) {\n return this.memory?.clearClaim(event);\n }\n /** Pass through method for the database.unclaimed */\n unclaimed() {\n return this.memory?.unclaimed() || (function* () { })();\n }\n /** Removes any event that is not being used by a subscription */\n prune(limit) {\n return this.memory?.prune(limit) ?? 0;\n }\n /** Returns an observable that completes when an event is removed */\n removed(id) {\n const deleted = this.checkDeleted(id);\n if (deleted)\n return EMPTY;\n return this.remove$.pipe(\n // listen for removed events\n filter((e) => e.id === id), \n // complete as soon as we find a matching removed event\n take(1), \n // switch to empty\n mergeMap(() => EMPTY));\n }\n /** Creates an observable that emits when event is updated */\n updated(event) {\n return this.update$.pipe(filter((e) => e.id === event || e === event));\n }\n}\n","import { isATag, isETag } from \"./tags.js\";\nexport function getDeleteIds(deleteEvent) {\n return deleteEvent.tags.filter(isETag).map((t) => t[1]);\n}\nexport function getDeleteCoordinates(deleteEvent) {\n return deleteEvent.tags.filter(isATag).map((t) => t[1]);\n}\n","/** Creates a controlled promise */\nexport function createDefer() {\n let _resolve;\n let _reject;\n const promise = new Promise((resolve, reject) => {\n // @ts-ignore\n _resolve = resolve;\n _reject = reject;\n });\n // @ts-ignore\n promise.resolve = _resolve;\n // @ts-ignore\n promise.reject = _reject;\n return promise;\n}\n","import { getEventHash, nip19, verifyEvent } from \"nostr-tools\";\nimport { getPubkeyFromDecodeResult, isHexKey, isHex } from \"applesauce-core/helpers\";\nimport { createDefer } from \"applesauce-core/promise\";\n/**\n * A Signer for [amber](https://github.com/greenart7c3/Amber) clipboard API\n * @see https://github.com/greenart7c3/Amber/blob/master/docs/web-apps.md\n */\nexport class AmberClipboardSigner {\n /** If the signer is supported on this platform */\n static SUPPORTED = `navigator` in globalThis &&\n navigator.userAgent.includes(\"Android\") &&\n navigator.clipboard &&\n navigator.clipboard.readText;\n pendingRequest = null;\n pubkey;\n verifyEvent = verifyEvent;\n nip04;\n nip44;\n constructor() {\n document.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n this.nip04 = {\n encrypt: this.nip04Encrypt.bind(this),\n decrypt: this.nip04Decrypt.bind(this),\n };\n this.nip44 = {\n encrypt: this.nip44Encrypt.bind(this),\n decrypt: this.nip44Decrypt.bind(this),\n };\n }\n onVisibilityChange = () => {\n if (document.visibilityState === \"visible\") {\n if (!this.pendingRequest || !navigator.clipboard)\n return;\n // read the result from the clipboard\n setTimeout(() => {\n navigator.clipboard\n .readText()\n .then((result) => this.pendingRequest?.resolve(result))\n .catch((e) => this.pendingRequest?.reject(e));\n }, 200);\n }\n };\n async intentRequest(intent) {\n this.rejectPending();\n const request = createDefer();\n window.open(intent, \"_blank\");\n // NOTE: wait 500ms before setting the pending request since the visibilitychange event fires as soon as window.open is called\n setTimeout(() => {\n this.pendingRequest = request;\n }, 500);\n const result = await request;\n if (result.length === 0)\n throw new Error(\"Empty clipboard\");\n return result;\n }\n /** Reject the currently pending request */\n rejectPending() {\n if (this.pendingRequest) {\n this.pendingRequest.reject(\"Canceled\");\n this.pendingRequest = null;\n }\n }\n /** Removes any event listeners created */\n destroy() {\n document.removeEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n checkSupport() {\n if (!AmberClipboardSigner.SUPPORTED)\n throw new Error(\"Cant use Amber on non-Android device\");\n }\n async getPublicKey() {\n this.checkSupport();\n if (this.pubkey)\n return this.pubkey;\n const result = await this.intentRequest(AmberClipboardSigner.createGetPublicKeyIntent());\n if (isHexKey(result)) {\n this.pubkey = result;\n return result;\n }\n else if (result.startsWith(\"npub\") || result.startsWith(\"nprofile\")) {\n const decode = nip19.decode(result);\n const pubkey = getPubkeyFromDecodeResult(decode);\n if (!pubkey)\n throw new Error(\"Expected npub from clipboard\");\n this.pubkey = pubkey;\n return pubkey;\n }\n throw new Error(\"Expected clipboard to have pubkey\");\n }\n async signEvent(draft) {\n this.checkSupport();\n const pubkey = draft.pubkey || this.pubkey;\n if (!pubkey)\n throw new Error(\"Unknown signer pubkey\");\n const draftWithId = { ...draft, id: getEventHash({ ...draft, pubkey }) };\n const sig = await this.intentRequest(AmberClipboardSigner.createSignEventIntent(draftWithId));\n if (!isHex(sig))\n throw new Error(\"Expected hex signature\");\n const event = { ...draftWithId, sig, pubkey };\n if (!this.verifyEvent(event))\n throw new Error(\"Invalid signature\");\n return event;\n }\n // NIP-04\n async nip04Encrypt(pubkey, plaintext) {\n this.checkSupport();\n const data = await this.intentRequest(AmberClipboardSigner.createNip04EncryptIntent(pubkey, plaintext));\n return data;\n }\n async nip04Decrypt(pubkey, data) {\n this.checkSupport();\n const plaintext = await this.intentRequest(AmberClipboardSigner.createNip04DecryptIntent(pubkey, data));\n return plaintext;\n }\n // NIP-44\n async nip44Encrypt(pubkey, plaintext) {\n this.checkSupport();\n const data = await this.intentRequest(AmberClipboardSigner.createNip44EncryptIntent(pubkey, plaintext));\n return data;\n }\n async nip44Decrypt(pubkey, data) {\n this.checkSupport();\n const plaintext = await this.intentRequest(AmberClipboardSigner.createNip44DecryptIntent(pubkey, data));\n return plaintext;\n }\n // static methods\n static createGetPublicKeyIntent() {\n return `intent:#Intent;scheme=nostrsigner;S.compressionType=none;S.returnType=signature;S.type=get_public_key;end`;\n }\n static createSignEventIntent(draft) {\n return `intent:${encodeURIComponent(JSON.stringify(draft))}#Intent;scheme=nostrsigner;S.compressionType=none;S.returnType=signature;S.type=sign_event;end`;\n }\n static createNip04EncryptIntent(pubkey, plainText) {\n return `intent:${encodeURIComponent(plainText)}#Intent;scheme=nostrsigner;S.pubKey=${pubkey};S.compressionType=none;S.returnType=signature;S.type=nip04_encrypt;end`;\n }\n static createNip04DecryptIntent(pubkey, ciphertext) {\n return `intent:${encodeURIComponent(ciphertext)}#Intent;scheme=nostrsigner;S.pubKey=${pubkey};S.compressionType=none;S.returnType=signature;S.type=nip04_decrypt;end`;\n }\n static createNip44EncryptIntent(pubkey, plainText) {\n return `intent:${encodeURIComponent(plainText)}#Intent;scheme=nostrsigner;S.pubKey=${pubkey};S.compressionType=none;S.returnType=signature;S.type=nip44_encrypt;end`;\n }\n static createNip44DecryptIntent(pubkey, ciphertext) {\n return `intent:${encodeURIComponent(ciphertext)}#Intent;scheme=nostrsigner;S.pubKey=${pubkey};S.compressionType=none;S.returnType=signature;S.type=nip44_decrypt;end`;\n }\n}\n","import { setHiddenContentEncryptionMethod } from \"applesauce-core/helpers\";\nimport { isHexKey } from \"applesauce-core/helpers/string\";\nimport { kinds } from \"nostr-tools\";\n// Set encryption types for nostr connect events\nsetHiddenContentEncryptionMethod(kinds.NostrConnect, \"nip44\");\nexport function isErrorResponse(response) {\n return !!response.error;\n}\nexport var Permission;\n(function (Permission) {\n Permission[\"GetPublicKey\"] = \"get_pubic_key\";\n Permission[\"SignEvent\"] = \"sign_event\";\n Permission[\"Nip04Encrypt\"] = \"nip04_encrypt\";\n Permission[\"Nip04Decrypt\"] = \"nip04_decrypt\";\n Permission[\"Nip44Encrypt\"] = \"nip44_encrypt\";\n Permission[\"Nip44Decrypt\"] = \"nip44_decrypt\";\n})(Permission || (Permission = {}));\nexport var NostrConnectMethod;\n(function (NostrConnectMethod) {\n NostrConnectMethod[\"Connect\"] = \"connect\";\n NostrConnectMethod[\"CreateAccount\"] = \"create_account\";\n NostrConnectMethod[\"GetPublicKey\"] = \"get_public_key\";\n NostrConnectMethod[\"SignEvent\"] = \"sign_event\";\n NostrConnectMethod[\"Nip04Encrypt\"] = \"nip04_encrypt\";\n NostrConnectMethod[\"Nip04Decrypt\"] = \"nip04_decrypt\";\n NostrConnectMethod[\"Nip44Encrypt\"] = \"nip44_encrypt\";\n NostrConnectMethod[\"Nip44Decrypt\"] = \"nip44_decrypt\";\n})(NostrConnectMethod || (NostrConnectMethod = {}));\n/** Parse a bunker:// URI */\nexport function parseBunkerURI(uri) {\n const url = new URL(uri);\n // firefox puts pubkey part in host, chrome puts pubkey in pathname\n const remote = url.host || url.pathname.replace(\"//\", \"\");\n if (!isHexKey(remote))\n throw new Error(\"Invalid bunker URI: remote is not a valid hex key\");\n const relays = url.searchParams.getAll(\"relay\");\n if (relays.length === 0)\n throw new Error(\"Invalid bunker URI: missing relays\");\n const secret = url.searchParams.get(\"secret\") ?? undefined;\n return { remote, relays, secret };\n}\n/** Creates a bunker:// URI from a {@link BunkerURI} object */\nexport function createBunkerURI(data) {\n const url = new URL(`bunker://${data.remote}`);\n data.relays.forEach((relay) => url.searchParams.append(\"relay\", relay));\n if (data.secret)\n url.searchParams.set(\"secret\", data.secret);\n return url.toString();\n}\n/** Parse a nostrconnect:// URI */\nexport function parseNostrConnectURI(uri) {\n const url = new URL(uri);\n const client = url.host || url.pathname.replace(\"//\", \"\");\n if (!isHexKey(client))\n throw new Error(\"Invalid nostrconnect URI: client is not a valid hex key\");\n const secret = url.searchParams.get(\"secret\");\n const relays = url.searchParams.getAll(\"relay\");\n if (!secret)\n throw new Error(\"Invalid nostrconnect URI: missing secret\");\n if (relays.length === 0)\n throw new Error(\"Invalid nostrconnect URI: missing relays\");\n const metadata = {\n name: url.searchParams.get(\"name\") ?? undefined,\n image: url.searchParams.get(\"image\") ?? undefined,\n url: url.searchParams.get(\"url\") ?? undefined,\n permissions: url.searchParams.get(\"perms\")?.split(\",\") ?? undefined,\n };\n /** Omit metadata if all values are undefined */\n if (Object.values(metadata).every((v) => v === undefined))\n return { client, secret, relays };\n else\n return { client, secret, relays, metadata };\n}\n/** Create a nostrconnect:// URI from a {@link NostrConnectURI} object */\nexport function createNostrConnectURI(data) {\n const params = new URLSearchParams();\n params.set(\"secret\", data.secret);\n if (data.metadata?.name)\n params.set(\"name\", data.metadata.name);\n if (data.metadata?.url)\n params.set(\"url\", String(data.metadata.url));\n if (data.metadata?.image)\n params.set(\"image\", data.metadata.image);\n if (data.metadata?.permissions)\n params.set(\"perms\", data.metadata.permissions.join(\",\"));\n for (const relay of data.relays)\n params.append(\"relay\", relay);\n return `nostrconnect://${data.client}?` + params.toString();\n}\n/** Build an array of signing permissions for event kinds */\nexport function buildSigningPermissions(kinds) {\n return [Permission.GetPublicKey, ...kinds.map((k) => `${Permission.SignEvent}:${k}`)];\n}\n","import { normalizeToSecretKey } from \"applesauce-core/helpers\";\nimport { finalizeEvent, generateSecretKey, getPublicKey, nip04, nip44 } from \"nostr-tools\";\n/** A Simple signer that holds the private key in memory */\nexport class PrivateKeySigner {\n key;\n constructor(key) {\n this.key = key || generateSecretKey();\n }\n async getPublicKey() {\n return getPublicKey(this.key);\n }\n async signEvent(event) {\n return finalizeEvent(event, this.key);\n }\n nip04 = {\n encrypt: async (pubkey, plaintext) => nip04.encrypt(this.key, pubkey, plaintext),\n decrypt: async (pubkey, ciphertext) => nip04.decrypt(this.key, pubkey, ciphertext),\n };\n nip44 = {\n encrypt: async (pubkey, plaintext) => nip44.v2.encrypt(plaintext, nip44.v2.utils.getConversationKey(this.key, pubkey)),\n decrypt: async (pubkey, ciphertext) => nip44.v2.decrypt(ciphertext, nip44.v2.utils.getConversationKey(this.key, pubkey)),\n };\n /** Creates a PrivateKeySigner from a hex private key or NIP-19 nsec */\n static fromKey(privateKey) {\n return new PrivateKeySigner(normalizeToSecretKey(privateKey));\n }\n}\n","/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */\nimport * as nodeCrypto from 'crypto';\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nconst _3n = BigInt(3);\nconst _8n = BigInt(8);\nconst CURVE = Object.freeze({\n a: _0n,\n b: BigInt(7),\n P: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),\n n: BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'),\n h: _1n,\n Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),\n Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),\n beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),\n});\nconst divNearest = (a, b) => (a + b / _2n) / b;\nconst endo = {\n beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),\n splitScalar(k) {\n const { n } = CURVE;\n const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');\n const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');\n const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');\n const b2 = a1;\n const POW_2_128 = BigInt('0x100000000000000000000000000000000');\n const c1 = divNearest(b2 * k, n);\n const c2 = divNearest(-b1 * k, n);\n let k1 = mod(k - c1 * a1 - c2 * a2, n);\n let k2 = mod(-c1 * b1 - c2 * b2, n);\n const k1neg = k1 > POW_2_128;\n const k2neg = k2 > POW_2_128;\n if (k1neg)\n k1 = n - k1;\n if (k2neg)\n k2 = n - k2;\n if (k1 > POW_2_128 || k2 > POW_2_128) {\n throw new Error('splitScalarEndo: Endomorphism failed, k=' + k);\n }\n return { k1neg, k1, k2neg, k2 };\n },\n};\nconst fieldLen = 32;\nconst groupLen = 32;\nconst hashLen = 32;\nconst compressedLen = fieldLen + 1;\nconst uncompressedLen = 2 * fieldLen + 1;\nexport { CURVE };\nfunction weierstrass(x) {\n const { a, b } = CURVE;\n const x2 = mod(x * x);\n const x3 = mod(x2 * x);\n return mod(x3 + a * x + b);\n}\nconst USE_ENDOMORPHISM = CURVE.a === _0n;\nclass ShaError extends Error {\n constructor(message) {\n super(message);\n }\n}\nfunction assertJacPoint(other) {\n if (!(other instanceof JacobianPoint))\n throw new TypeError('JacobianPoint expected');\n}\nclass JacobianPoint {\n constructor(x, y, z) {\n this.x = x;\n this.y = y;\n this.z = z;\n }\n static fromAffine(p) {\n if (!(p instanceof Point)) {\n throw new TypeError('JacobianPoint#fromAffine: expected Point');\n }\n if (p.equals(Point.ZERO))\n return JacobianPoint.ZERO;\n return new JacobianPoint(p.x, p.y, _1n);\n }\n static toAffineBatch(points) {\n const toInv = invertBatch(points.map((p) => p.z));\n return points.map((p, i) => p.toAffine(toInv[i]));\n }\n static normalizeZ(points) {\n return JacobianPoint.toAffineBatch(points).map(JacobianPoint.fromAffine);\n }\n equals(other) {\n assertJacPoint(other);\n const { x: X1, y: Y1, z: Z1 } = this;\n const { x: X2, y: Y2, z: Z2 } = other;\n const Z1Z1 = mod(Z1 * Z1);\n const Z2Z2 = mod(Z2 * Z2);\n const U1 = mod(X1 * Z2Z2);\n const U2 = mod(X2 * Z1Z1);\n const S1 = mod(mod(Y1 * Z2) * Z2Z2);\n const S2 = mod(mod(Y2 * Z1) * Z1Z1);\n return U1 === U2 && S1 === S2;\n }\n negate() {\n return new JacobianPoint(this.x, mod(-this.y), this.z);\n }\n double() {\n const { x: X1, y: Y1, z: Z1 } = this;\n const A = mod(X1 * X1);\n const B = mod(Y1 * Y1);\n const C = mod(B * B);\n const x1b = X1 + B;\n const D = mod(_2n * (mod(x1b * x1b) - A - C));\n const E = mod(_3n * A);\n const F = mod(E * E);\n const X3 = mod(F - _2n * D);\n const Y3 = mod(E * (D - X3) - _8n * C);\n const Z3 = mod(_2n * Y1 * Z1);\n return new JacobianPoint(X3, Y3, Z3);\n }\n add(other) {\n assertJacPoint(other);\n const { x: X1, y: Y1, z: Z1 } = this;\n const { x: X2, y: Y2, z: Z2 } = other;\n if (X2 === _0n || Y2 === _0n)\n return this;\n if (X1 === _0n || Y1 === _0n)\n return other;\n const Z1Z1 = mod(Z1 * Z1);\n const Z2Z2 = mod(Z2 * Z2);\n const U1 = mod(X1 * Z2Z2);\n const U2 = mod(X2 * Z1Z1);\n const S1 = mod(mod(Y1 * Z2) * Z2Z2);\n const S2 = mod(mod(Y2 * Z1) * Z1Z1);\n const H = mod(U2 - U1);\n const r = mod(S2 - S1);\n if (H === _0n) {\n if (r === _0n) {\n return this.double();\n }\n else {\n return JacobianPoint.ZERO;\n }\n }\n const HH = mod(H * H);\n const HHH = mod(H * HH);\n const V = mod(U1 * HH);\n const X3 = mod(r * r - HHH - _2n * V);\n const Y3 = mod(r * (V - X3) - S1 * HHH);\n const Z3 = mod(Z1 * Z2 * H);\n return new JacobianPoint(X3, Y3, Z3);\n }\n subtract(other) {\n return this.add(other.negate());\n }\n multiplyUnsafe(scalar) {\n const P0 = JacobianPoint.ZERO;\n if (typeof scalar === 'bigint' && scalar === _0n)\n return P0;\n let n = normalizeScalar(scalar);\n if (n === _1n)\n return this;\n if (!USE_ENDOMORPHISM) {\n let p = P0;\n let d = this;\n while (n > _0n) {\n if (n & _1n)\n p = p.add(d);\n d = d.double();\n n >>= _1n;\n }\n return p;\n }\n let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);\n let k1p = P0;\n let k2p = P0;\n let d = this;\n while (k1 > _0n || k2 > _0n) {\n if (k1 & _1n)\n k1p = k1p.add(d);\n if (k2 & _1n)\n k2p = k2p.add(d);\n d = d.double();\n k1 >>= _1n;\n k2 >>= _1n;\n }\n if (k1neg)\n k1p = k1p.negate();\n if (k2neg)\n k2p = k2p.negate();\n k2p = new JacobianPoint(mod(k2p.x * endo.beta), k2p.y, k2p.z);\n return k1p.add(k2p);\n }\n precomputeWindow(W) {\n const windows = USE_ENDOMORPHISM ? 128 / W + 1 : 256 / W + 1;\n const points = [];\n let p = this;\n let base = p;\n for (let window = 0; window < windows; window++) {\n base = p;\n points.push(base);\n for (let i = 1; i < 2 ** (W - 1); i++) {\n base = base.add(p);\n points.push(base);\n }\n p = base.double();\n }\n return points;\n }\n wNAF(n, affinePoint) {\n if (!affinePoint && this.equals(JacobianPoint.BASE))\n affinePoint = Point.BASE;\n const W = (affinePoint && affinePoint._WINDOW_SIZE) || 1;\n if (256 % W) {\n throw new Error('Point#wNAF: Invalid precomputation window, must be power of 2');\n }\n let precomputes = affinePoint && pointPrecomputes.get(affinePoint);\n if (!precomputes) {\n precomputes = this.precomputeWindow(W);\n if (affinePoint && W !== 1) {\n precomputes = JacobianPoint.normalizeZ(precomputes);\n pointPrecomputes.set(affinePoint, precomputes);\n }\n }\n let p = JacobianPoint.ZERO;\n let f = JacobianPoint.BASE;\n const windows = 1 + (USE_ENDOMORPHISM ? 128 / W : 256 / W);\n const windowSize = 2 ** (W - 1);\n const mask = BigInt(2 ** W - 1);\n const maxNumber = 2 ** W;\n const shiftBy = BigInt(W);\n for (let window = 0; window < windows; window++) {\n const offset = window * windowSize;\n let wbits = Number(n & mask);\n n >>= shiftBy;\n if (wbits > windowSize) {\n wbits -= maxNumber;\n n += _1n;\n }\n const offset1 = offset;\n const offset2 = offset + Math.abs(wbits) - 1;\n const cond1 = window % 2 !== 0;\n const cond2 = wbits < 0;\n if (wbits === 0) {\n f = f.add(constTimeNegate(cond1, precomputes[offset1]));\n }\n else {\n p = p.add(constTimeNegate(cond2, precomputes[offset2]));\n }\n }\n return { p, f };\n }\n multiply(scalar, affinePoint) {\n let n = normalizeScalar(scalar);\n let point;\n let fake;\n if (USE_ENDOMORPHISM) {\n const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);\n let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint);\n let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint);\n k1p = constTimeNegate(k1neg, k1p);\n k2p = constTimeNegate(k2neg, k2p);\n k2p = new JacobianPoint(mod(k2p.x * endo.beta), k2p.y, k2p.z);\n point = k1p.add(k2p);\n fake = f1p.add(f2p);\n }\n else {\n const { p, f } = this.wNAF(n, affinePoint);\n point = p;\n fake = f;\n }\n return JacobianPoint.normalizeZ([point, fake])[0];\n }\n toAffine(invZ) {\n const { x, y, z } = this;\n const is0 = this.equals(JacobianPoint.ZERO);\n if (invZ == null)\n invZ = is0 ? _8n : invert(z);\n const iz1 = invZ;\n const iz2 = mod(iz1 * iz1);\n const iz3 = mod(iz2 * iz1);\n const ax = mod(x * iz2);\n const ay = mod(y * iz3);\n const zz = mod(z * iz1);\n if (is0)\n return Point.ZERO;\n if (zz !== _1n)\n throw new Error('invZ was invalid');\n return new Point(ax, ay);\n }\n}\nJacobianPoint.BASE = new JacobianPoint(CURVE.Gx, CURVE.Gy, _1n);\nJacobianPoint.ZERO = new JacobianPoint(_0n, _1n, _0n);\nfunction constTimeNegate(condition, item) {\n const neg = item.negate();\n return condition ? neg : item;\n}\nconst pointPrecomputes = new WeakMap();\nexport class Point {\n constructor(x, y) {\n this.x = x;\n this.y = y;\n }\n _setWindowSize(windowSize) {\n this._WINDOW_SIZE = windowSize;\n pointPrecomputes.delete(this);\n }\n hasEvenY() {\n return this.y % _2n === _0n;\n }\n static fromCompressedHex(bytes) {\n const isShort = bytes.length === 32;\n const x = bytesToNumber(isShort ? bytes : bytes.subarray(1));\n if (!isValidFieldElement(x))\n throw new Error('Point is not on curve');\n const y2 = weierstrass(x);\n let y = sqrtMod(y2);\n const isYOdd = (y & _1n) === _1n;\n if (isShort) {\n if (isYOdd)\n y = mod(-y);\n }\n else {\n const isFirstByteOdd = (bytes[0] & 1) === 1;\n if (isFirstByteOdd !== isYOdd)\n y = mod(-y);\n }\n const point = new Point(x, y);\n point.assertValidity();\n return point;\n }\n static fromUncompressedHex(bytes) {\n const x = bytesToNumber(bytes.subarray(1, fieldLen + 1));\n const y = bytesToNumber(bytes.subarray(fieldLen + 1, fieldLen * 2 + 1));\n const point = new Point(x, y);\n point.assertValidity();\n return point;\n }\n static fromHex(hex) {\n const bytes = ensureBytes(hex);\n const len = bytes.length;\n const header = bytes[0];\n if (len === fieldLen)\n return this.fromCompressedHex(bytes);\n if (len === compressedLen && (header === 0x02 || header === 0x03)) {\n return this.fromCompressedHex(bytes);\n }\n if (len === uncompressedLen && header === 0x04)\n return this.fromUncompressedHex(bytes);\n throw new Error(`Point.fromHex: received invalid point. Expected 32-${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes, not ${len}`);\n }\n static fromPrivateKey(privateKey) {\n return Point.BASE.multiply(normalizePrivateKey(privateKey));\n }\n static fromSignature(msgHash, signature, recovery) {\n const { r, s } = normalizeSignature(signature);\n if (![0, 1, 2, 3].includes(recovery))\n throw new Error('Cannot recover: invalid recovery bit');\n const h = truncateHash(ensureBytes(msgHash));\n const { n } = CURVE;\n const radj = recovery === 2 || recovery === 3 ? r + n : r;\n const rinv = invert(radj, n);\n const u1 = mod(-h * rinv, n);\n const u2 = mod(s * rinv, n);\n const prefix = recovery & 1 ? '03' : '02';\n const R = Point.fromHex(prefix + numTo32bStr(radj));\n const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2);\n if (!Q)\n throw new Error('Cannot recover signature: point at infinify');\n Q.assertValidity();\n return Q;\n }\n toRawBytes(isCompressed = false) {\n return hexToBytes(this.toHex(isCompressed));\n }\n toHex(isCompressed = false) {\n const x = numTo32bStr(this.x);\n if (isCompressed) {\n const prefix = this.hasEvenY() ? '02' : '03';\n return `${prefix}${x}`;\n }\n else {\n return `04${x}${numTo32bStr(this.y)}`;\n }\n }\n toHexX() {\n return this.toHex(true).slice(2);\n }\n toRawX() {\n return this.toRawBytes(true).slice(1);\n }\n assertValidity() {\n const msg = 'Point is not on elliptic curve';\n const { x, y } = this;\n if (!isValidFieldElement(x) || !isValidFieldElement(y))\n throw new Error(msg);\n const left = mod(y * y);\n const right = weierstrass(x);\n if (mod(left - right) !== _0n)\n throw new Error(msg);\n }\n equals(other) {\n return this.x === other.x && this.y === other.y;\n }\n negate() {\n return new Point(this.x, mod(-this.y));\n }\n double() {\n return JacobianPoint.fromAffine(this).double().toAffine();\n }\n add(other) {\n return JacobianPoint.fromAffine(this).add(JacobianPoint.fromAffine(other)).toAffine();\n }\n subtract(other) {\n return this.add(other.negate());\n }\n multiply(scalar) {\n return JacobianPoint.fromAffine(this).multiply(scalar, this).toAffine();\n }\n multiplyAndAddUnsafe(Q, a, b) {\n const P = JacobianPoint.fromAffine(this);\n const aP = a === _0n || a === _1n || this !== Point.BASE ? P.multiplyUnsafe(a) : P.multiply(a);\n const bQ = JacobianPoint.fromAffine(Q).multiplyUnsafe(b);\n const sum = aP.add(bQ);\n return sum.equals(JacobianPoint.ZERO) ? undefined : sum.toAffine();\n }\n}\nPoint.BASE = new Point(CURVE.Gx, CURVE.Gy);\nPoint.ZERO = new Point(_0n, _0n);\nfunction sliceDER(s) {\n return Number.parseInt(s[0], 16) >= 8 ? '00' + s : s;\n}\nfunction parseDERInt(data) {\n if (data.length < 2 || data[0] !== 0x02) {\n throw new Error(`Invalid signature integer tag: ${bytesToHex(data)}`);\n }\n const len = data[1];\n const res = data.subarray(2, len + 2);\n if (!len || res.length !== len) {\n throw new Error(`Invalid signature integer: wrong length`);\n }\n if (res[0] === 0x00 && res[1] <= 0x7f) {\n throw new Error('Invalid signature integer: trailing length');\n }\n return { data: bytesToNumber(res), left: data.subarray(len + 2) };\n}\nfunction parseDERSignature(data) {\n if (data.length < 2 || data[0] != 0x30) {\n throw new Error(`Invalid signature tag: ${bytesToHex(data)}`);\n }\n if (data[1] !== data.length - 2) {\n throw new Error('Invalid signature: incorrect length');\n }\n const { data: r, left: sBytes } = parseDERInt(data.subarray(2));\n const { data: s, left: rBytesLeft } = parseDERInt(sBytes);\n if (rBytesLeft.length) {\n throw new Error(`Invalid signature: left bytes after parsing: ${bytesToHex(rBytesLeft)}`);\n }\n return { r, s };\n}\nexport class Signature {\n constructor(r, s) {\n this.r = r;\n this.s = s;\n this.assertValidity();\n }\n static fromCompact(hex) {\n const arr = isBytes(hex);\n const name = 'Signature.fromCompact';\n if (typeof hex !== 'string' && !arr)\n throw new TypeError(`${name}: Expected string or Uint8Array`);\n const str = arr ? bytesToHex(hex) : hex;\n if (str.length !== 128)\n throw new Error(`${name}: Expected 64-byte hex`);\n return new Signature(hexToNumber(str.slice(0, 64)), hexToNumber(str.slice(64, 128)));\n }\n static fromDER(hex) {\n const arr = isBytes(hex);\n if (typeof hex !== 'string' && !arr)\n throw new TypeError(`Signature.fromDER: Expected string or Uint8Array`);\n const { r, s } = parseDERSignature(arr ? hex : hexToBytes(hex));\n return new Signature(r, s);\n }\n static fromHex(hex) {\n return this.fromDER(hex);\n }\n assertValidity() {\n const { r, s } = this;\n if (!isWithinCurveOrder(r))\n throw new Error('Invalid Signature: r must be 0 < r < n');\n if (!isWithinCurveOrder(s))\n throw new Error('Invalid Signature: s must be 0 < s < n');\n }\n hasHighS() {\n const HALF = CURVE.n >> _1n;\n return this.s > HALF;\n }\n normalizeS() {\n return this.hasHighS() ? new Signature(this.r, mod(-this.s, CURVE.n)) : this;\n }\n toDERRawBytes() {\n return hexToBytes(this.toDERHex());\n }\n toDERHex() {\n const sHex = sliceDER(numberToHexUnpadded(this.s));\n const rHex = sliceDER(numberToHexUnpadded(this.r));\n const sHexL = sHex.length / 2;\n const rHexL = rHex.length / 2;\n const sLen = numberToHexUnpadded(sHexL);\n const rLen = numberToHexUnpadded(rHexL);\n const length = numberToHexUnpadded(rHexL + sHexL + 4);\n return `30${length}02${rLen}${rHex}02${sLen}${sHex}`;\n }\n toRawBytes() {\n return this.toDERRawBytes();\n }\n toHex() {\n return this.toDERHex();\n }\n toCompactRawBytes() {\n return hexToBytes(this.toCompactHex());\n }\n toCompactHex() {\n return numTo32bStr(this.r) + numTo32bStr(this.s);\n }\n}\nfunction isBytes(a) {\n return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');\n}\nfunction abytes(item) {\n if (!isBytes(item))\n throw new Error('Uint8Array expected');\n}\nfunction concatBytes(...arrays) {\n arrays.every(abytes);\n if (arrays.length === 1)\n return arrays[0];\n const length = arrays.reduce((a, arr) => a + arr.length, 0);\n const result = new Uint8Array(length);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const arr = arrays[i];\n result.set(arr, pad);\n pad += arr.length;\n }\n return result;\n}\nconst hexes = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));\nexport function bytesToHex(bytes) {\n abytes(bytes);\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\nconst asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };\nfunction asciiToBase16(ch) {\n if (ch >= asciis._0 && ch <= asciis._9)\n return ch - asciis._0;\n if (ch >= asciis.A && ch <= asciis.F)\n return ch - (asciis.A - 10);\n if (ch >= asciis.a && ch <= asciis.f)\n return ch - (asciis.a - 10);\n return;\n}\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2)\n throw new Error('hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2;\n }\n return array;\n}\nconst POW_2_256 = BigInt('0x10000000000000000000000000000000000000000000000000000000000000000');\nfunction numTo32bStr(num) {\n if (typeof num !== 'bigint')\n throw new Error('Expected bigint');\n if (!(_0n <= num && num < POW_2_256))\n throw new Error('Expected number 0 <= n < 2^256');\n return num.toString(16).padStart(64, '0');\n}\nfunction numTo32b(num) {\n const b = hexToBytes(numTo32bStr(num));\n if (b.length !== 32)\n throw new Error('Error: expected 32 bytes');\n return b;\n}\nfunction numberToHexUnpadded(num) {\n const hex = num.toString(16);\n return hex.length & 1 ? `0${hex}` : hex;\n}\nfunction hexToNumber(hex) {\n if (typeof hex !== 'string') {\n throw new TypeError('hexToNumber: expected string, got ' + typeof hex);\n }\n return BigInt(`0x${hex}`);\n}\nfunction bytesToNumber(bytes) {\n return hexToNumber(bytesToHex(bytes));\n}\nfunction ensureBytes(hex) {\n return isBytes(hex) ? Uint8Array.from(hex) : hexToBytes(hex);\n}\nfunction normalizeScalar(num) {\n if (typeof num === 'number' && Number.isSafeInteger(num) && num > 0)\n return BigInt(num);\n if (typeof num === 'bigint' && isWithinCurveOrder(num))\n return num;\n throw new TypeError('Expected valid private scalar: 0 < scalar < curve.n');\n}\nfunction mod(a, b = CURVE.P) {\n const result = a % b;\n return result >= _0n ? result : b + result;\n}\nfunction pow2(x, power) {\n const { P } = CURVE;\n let res = x;\n while (power-- > _0n) {\n res *= res;\n res %= P;\n }\n return res;\n}\nfunction sqrtMod(x) {\n const { P } = CURVE;\n const _6n = BigInt(6);\n const _11n = BigInt(11);\n const _22n = BigInt(22);\n const _23n = BigInt(23);\n const _44n = BigInt(44);\n const _88n = BigInt(88);\n const b2 = (x * x * x) % P;\n const b3 = (b2 * b2 * x) % P;\n const b6 = (pow2(b3, _3n) * b3) % P;\n const b9 = (pow2(b6, _3n) * b3) % P;\n const b11 = (pow2(b9, _2n) * b2) % P;\n const b22 = (pow2(b11, _11n) * b11) % P;\n const b44 = (pow2(b22, _22n) * b22) % P;\n const b88 = (pow2(b44, _44n) * b44) % P;\n const b176 = (pow2(b88, _88n) * b88) % P;\n const b220 = (pow2(b176, _44n) * b44) % P;\n const b223 = (pow2(b220, _3n) * b3) % P;\n const t1 = (pow2(b223, _23n) * b22) % P;\n const t2 = (pow2(t1, _6n) * b2) % P;\n const rt = pow2(t2, _2n);\n const xc = (rt * rt) % P;\n if (xc !== x)\n throw new Error('Cannot find square root');\n return rt;\n}\nfunction invert(number, modulo = CURVE.P) {\n if (number === _0n || modulo <= _0n) {\n throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);\n }\n let a = mod(number, modulo);\n let b = modulo;\n let x = _0n, y = _1n, u = _1n, v = _0n;\n while (a !== _0n) {\n const q = b / a;\n const r = b % a;\n const m = x - u * q;\n const n = y - v * q;\n b = a, a = r, x = u, y = v, u = m, v = n;\n }\n const gcd = b;\n if (gcd !== _1n)\n throw new Error('invert: does not exist');\n return mod(x, modulo);\n}\nfunction invertBatch(nums, p = CURVE.P) {\n const scratch = new Array(nums.length);\n const lastMultiplied = nums.reduce((acc, num, i) => {\n if (num === _0n)\n return acc;\n scratch[i] = acc;\n return mod(acc * num, p);\n }, _1n);\n const inverted = invert(lastMultiplied, p);\n nums.reduceRight((acc, num, i) => {\n if (num === _0n)\n return acc;\n scratch[i] = mod(acc * scratch[i], p);\n return mod(acc * num, p);\n }, inverted);\n return scratch;\n}\nfunction bits2int_2(bytes) {\n const delta = bytes.length * 8 - groupLen * 8;\n const num = bytesToNumber(bytes);\n return delta > 0 ? num >> BigInt(delta) : num;\n}\nfunction truncateHash(hash, truncateOnly = false) {\n const h = bits2int_2(hash);\n if (truncateOnly)\n return h;\n const { n } = CURVE;\n return h >= n ? h - n : h;\n}\nlet _sha256Sync;\nlet _hmacSha256Sync;\nclass HmacDrbg {\n constructor(hashLen, qByteLen) {\n this.hashLen = hashLen;\n this.qByteLen = qByteLen;\n if (typeof hashLen !== 'number' || hashLen < 2)\n throw new Error('hashLen must be a number');\n if (typeof qByteLen !== 'number' || qByteLen < 2)\n throw new Error('qByteLen must be a number');\n this.v = new Uint8Array(hashLen).fill(1);\n this.k = new Uint8Array(hashLen).fill(0);\n this.counter = 0;\n }\n hmac(...values) {\n return utils.hmacSha256(this.k, ...values);\n }\n hmacSync(...values) {\n return _hmacSha256Sync(this.k, ...values);\n }\n checkSync() {\n if (typeof _hmacSha256Sync !== 'function')\n throw new ShaError('hmacSha256Sync needs to be set');\n }\n incr() {\n if (this.counter >= 1000)\n throw new Error('Tried 1,000 k values for sign(), all were invalid');\n this.counter += 1;\n }\n async reseed(seed = new Uint8Array()) {\n this.k = await this.hmac(this.v, Uint8Array.from([0x00]), seed);\n this.v = await this.hmac(this.v);\n if (seed.length === 0)\n return;\n this.k = await this.hmac(this.v, Uint8Array.from([0x01]), seed);\n this.v = await this.hmac(this.v);\n }\n reseedSync(seed = new Uint8Array()) {\n this.checkSync();\n this.k = this.hmacSync(this.v, Uint8Array.from([0x00]), seed);\n this.v = this.hmacSync(this.v);\n if (seed.length === 0)\n return;\n this.k = this.hmacSync(this.v, Uint8Array.from([0x01]), seed);\n this.v = this.hmacSync(this.v);\n }\n async generate() {\n this.incr();\n let len = 0;\n const out = [];\n while (len < this.qByteLen) {\n this.v = await this.hmac(this.v);\n const sl = this.v.slice();\n out.push(sl);\n len += this.v.length;\n }\n return concatBytes(...out);\n }\n generateSync() {\n this.checkSync();\n this.incr();\n let len = 0;\n const out = [];\n while (len < this.qByteLen) {\n this.v = this.hmacSync(this.v);\n const sl = this.v.slice();\n out.push(sl);\n len += this.v.length;\n }\n return concatBytes(...out);\n }\n}\nfunction isWithinCurveOrder(num) {\n return _0n < num && num < CURVE.n;\n}\nfunction isValidFieldElement(num) {\n return _0n < num && num < CURVE.P;\n}\nfunction kmdToSig(kBytes, m, d, lowS = true) {\n const { n } = CURVE;\n const k = truncateHash(kBytes, true);\n if (!isWithinCurveOrder(k))\n return;\n const kinv = invert(k, n);\n const q = Point.BASE.multiply(k);\n const r = mod(q.x, n);\n if (r === _0n)\n return;\n const s = mod(kinv * mod(m + d * r, n), n);\n if (s === _0n)\n return;\n let sig = new Signature(r, s);\n let recovery = (q.x === sig.r ? 0 : 2) | Number(q.y & _1n);\n if (lowS && sig.hasHighS()) {\n sig = sig.normalizeS();\n recovery ^= 1;\n }\n return { sig, recovery };\n}\nfunction normalizePrivateKey(key) {\n let num;\n if (typeof key === 'bigint') {\n num = key;\n }\n else if (typeof key === 'number' && Number.isSafeInteger(key) && key > 0) {\n num = BigInt(key);\n }\n else if (typeof key === 'string') {\n if (key.length !== 2 * groupLen)\n throw new Error('Expected 32 bytes of private key');\n num = hexToNumber(key);\n }\n else if (isBytes(key)) {\n if (key.length !== groupLen)\n throw new Error('Expected 32 bytes of private key');\n num = bytesToNumber(key);\n }\n else {\n throw new TypeError('Expected valid private key');\n }\n if (!isWithinCurveOrder(num))\n throw new Error('Expected private key: 0 < key < n');\n return num;\n}\nfunction normalizePublicKey(publicKey) {\n if (publicKey instanceof Point) {\n publicKey.assertValidity();\n return publicKey;\n }\n else {\n return Point.fromHex(publicKey);\n }\n}\nfunction normalizeSignature(signature) {\n if (signature instanceof Signature) {\n signature.assertValidity();\n return signature;\n }\n try {\n return Signature.fromDER(signature);\n }\n catch (error) {\n return Signature.fromCompact(signature);\n }\n}\nexport function getPublicKey(privateKey, isCompressed = false) {\n return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed);\n}\nexport function recoverPublicKey(msgHash, signature, recovery, isCompressed = false) {\n return Point.fromSignature(msgHash, signature, recovery).toRawBytes(isCompressed);\n}\nfunction isProbPub(item) {\n const arr = isBytes(item);\n const str = typeof item === 'string';\n const len = (arr || str) && item.length;\n if (arr)\n return len === compressedLen || len === uncompressedLen;\n if (str)\n return len === compressedLen * 2 || len === uncompressedLen * 2;\n if (item instanceof Point)\n return true;\n return false;\n}\nexport function getSharedSecret(privateA, publicB, isCompressed = false) {\n if (isProbPub(privateA))\n throw new TypeError('getSharedSecret: first arg must be private key');\n if (!isProbPub(publicB))\n throw new TypeError('getSharedSecret: second arg must be public key');\n const b = normalizePublicKey(publicB);\n b.assertValidity();\n return b.multiply(normalizePrivateKey(privateA)).toRawBytes(isCompressed);\n}\nfunction bits2int(bytes) {\n const slice = bytes.length > fieldLen ? bytes.slice(0, fieldLen) : bytes;\n return bytesToNumber(slice);\n}\nfunction bits2octets(bytes) {\n const z1 = bits2int(bytes);\n const z2 = mod(z1, CURVE.n);\n return int2octets(z2 < _0n ? z1 : z2);\n}\nfunction int2octets(num) {\n return numTo32b(num);\n}\nfunction initSigArgs(msgHash, privateKey, extraEntropy) {\n if (msgHash == null)\n throw new Error(`sign: expected valid message hash, not \"${msgHash}\"`);\n const h1 = ensureBytes(msgHash);\n const d = normalizePrivateKey(privateKey);\n const seedArgs = [int2octets(d), bits2octets(h1)];\n if (extraEntropy != null) {\n if (extraEntropy === true)\n extraEntropy = utils.randomBytes(fieldLen);\n const e = ensureBytes(extraEntropy);\n if (e.length !== fieldLen)\n throw new Error(`sign: Expected ${fieldLen} bytes of extra data`);\n seedArgs.push(e);\n }\n const seed = concatBytes(...seedArgs);\n const m = bits2int(h1);\n return { seed, m, d };\n}\nfunction finalizeSig(recSig, opts) {\n const { sig, recovery } = recSig;\n const { der, recovered } = Object.assign({ canonical: true, der: true }, opts);\n const hashed = der ? sig.toDERRawBytes() : sig.toCompactRawBytes();\n return recovered ? [hashed, recovery] : hashed;\n}\nasync function sign(msgHash, privKey, opts = {}) {\n const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy);\n const drbg = new HmacDrbg(hashLen, groupLen);\n await drbg.reseed(seed);\n let sig;\n while (!(sig = kmdToSig(await drbg.generate(), m, d, opts.canonical)))\n await drbg.reseed();\n return finalizeSig(sig, opts);\n}\nfunction signSync(msgHash, privKey, opts = {}) {\n const { seed, m, d } = initSigArgs(msgHash, privKey, opts.extraEntropy);\n const drbg = new HmacDrbg(hashLen, groupLen);\n drbg.reseedSync(seed);\n let sig;\n while (!(sig = kmdToSig(drbg.generateSync(), m, d, opts.canonical)))\n drbg.reseedSync();\n return finalizeSig(sig, opts);\n}\nexport { sign, signSync };\nconst vopts = { strict: true };\nexport function verify(signature, msgHash, publicKey, opts = vopts) {\n let sig;\n try {\n sig = normalizeSignature(signature);\n msgHash = ensureBytes(msgHash);\n }\n catch (error) {\n return false;\n }\n const { r, s } = sig;\n if (opts.strict && sig.hasHighS())\n return false;\n const h = truncateHash(msgHash);\n let P;\n try {\n P = normalizePublicKey(publicKey);\n }\n catch (error) {\n return false;\n }\n const { n } = CURVE;\n const sinv = invert(s, n);\n const u1 = mod(h * sinv, n);\n const u2 = mod(r * sinv, n);\n const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2);\n if (!R)\n return false;\n const v = mod(R.x, n);\n return v === r;\n}\nfunction schnorrChallengeFinalize(ch) {\n return mod(bytesToNumber(ch), CURVE.n);\n}\nclass SchnorrSignature {\n constructor(r, s) {\n this.r = r;\n this.s = s;\n this.assertValidity();\n }\n static fromHex(hex) {\n const bytes = ensureBytes(hex);\n if (bytes.length !== 64)\n throw new TypeError(`SchnorrSignature.fromHex: expected 64 bytes, not ${bytes.length}`);\n const r = bytesToNumber(bytes.subarray(0, 32));\n const s = bytesToNumber(bytes.subarray(32, 64));\n return new SchnorrSignature(r, s);\n }\n assertValidity() {\n const { r, s } = this;\n if (!isValidFieldElement(r) || !isWithinCurveOrder(s))\n throw new Error('Invalid signature');\n }\n toHex() {\n return numTo32bStr(this.r) + numTo32bStr(this.s);\n }\n toRawBytes() {\n return hexToBytes(this.toHex());\n }\n}\nfunction schnorrGetPublicKey(privateKey) {\n return Point.fromPrivateKey(privateKey).toRawX();\n}\nclass InternalSchnorrSignature {\n constructor(message, privateKey, auxRand = utils.randomBytes()) {\n if (message == null)\n throw new TypeError(`sign: Expected valid message, not \"${message}\"`);\n this.m = ensureBytes(message);\n const { x, scalar } = this.getScalar(normalizePrivateKey(privateKey));\n this.px = x;\n this.d = scalar;\n this.rand = ensureBytes(auxRand);\n if (this.rand.length !== 32)\n throw new TypeError('sign: Expected 32 bytes of aux randomness');\n }\n getScalar(priv) {\n const point = Point.fromPrivateKey(priv);\n const scalar = point.hasEvenY() ? priv : CURVE.n - priv;\n return { point, scalar, x: point.toRawX() };\n }\n initNonce(d, t0h) {\n return numTo32b(d ^ bytesToNumber(t0h));\n }\n finalizeNonce(k0h) {\n const k0 = mod(bytesToNumber(k0h), CURVE.n);\n if (k0 === _0n)\n throw new Error('sign: Creation of signature failed. k is zero');\n const { point: R, x: rx, scalar: k } = this.getScalar(k0);\n return { R, rx, k };\n }\n finalizeSig(R, k, e, d) {\n return new SchnorrSignature(R.x, mod(k + e * d, CURVE.n)).toRawBytes();\n }\n error() {\n throw new Error('sign: Invalid signature produced');\n }\n async calc() {\n const { m, d, px, rand } = this;\n const tag = utils.taggedHash;\n const t = this.initNonce(d, await tag(TAGS.aux, rand));\n const { R, rx, k } = this.finalizeNonce(await tag(TAGS.nonce, t, px, m));\n const e = schnorrChallengeFinalize(await tag(TAGS.challenge, rx, px, m));\n const sig = this.finalizeSig(R, k, e, d);\n if (!(await schnorrVerify(sig, m, px)))\n this.error();\n return sig;\n }\n calcSync() {\n const { m, d, px, rand } = this;\n const tag = utils.taggedHashSync;\n const t = this.initNonce(d, tag(TAGS.aux, rand));\n const { R, rx, k } = this.finalizeNonce(tag(TAGS.nonce, t, px, m));\n const e = schnorrChallengeFinalize(tag(TAGS.challenge, rx, px, m));\n const sig = this.finalizeSig(R, k, e, d);\n if (!schnorrVerifySync(sig, m, px))\n this.error();\n return sig;\n }\n}\nasync function schnorrSign(msg, privKey, auxRand) {\n return new InternalSchnorrSignature(msg, privKey, auxRand).calc();\n}\nfunction schnorrSignSync(msg, privKey, auxRand) {\n return new InternalSchnorrSignature(msg, privKey, auxRand).calcSync();\n}\nfunction initSchnorrVerify(signature, message, publicKey) {\n const raw = signature instanceof SchnorrSignature;\n const sig = raw ? signature : SchnorrSignature.fromHex(signature);\n if (raw)\n sig.assertValidity();\n return {\n ...sig,\n m: ensureBytes(message),\n P: normalizePublicKey(publicKey),\n };\n}\nfunction finalizeSchnorrVerify(r, P, s, e) {\n const R = Point.BASE.multiplyAndAddUnsafe(P, normalizePrivateKey(s), mod(-e, CURVE.n));\n if (!R || !R.hasEvenY() || R.x !== r)\n return false;\n return true;\n}\nasync function schnorrVerify(signature, message, publicKey) {\n try {\n const { r, s, m, P } = initSchnorrVerify(signature, message, publicKey);\n const e = schnorrChallengeFinalize(await utils.taggedHash(TAGS.challenge, numTo32b(r), P.toRawX(), m));\n return finalizeSchnorrVerify(r, P, s, e);\n }\n catch (error) {\n return false;\n }\n}\nfunction schnorrVerifySync(signature, message, publicKey) {\n try {\n const { r, s, m, P } = initSchnorrVerify(signature, message, publicKey);\n const e = schnorrChallengeFinalize(utils.taggedHashSync(TAGS.challenge, numTo32b(r), P.toRawX(), m));\n return finalizeSchnorrVerify(r, P, s, e);\n }\n catch (error) {\n if (error instanceof ShaError)\n throw error;\n return false;\n }\n}\nexport const schnorr = {\n Signature: SchnorrSignature,\n getPublicKey: schnorrGetPublicKey,\n sign: schnorrSign,\n verify: schnorrVerify,\n signSync: schnorrSignSync,\n verifySync: schnorrVerifySync,\n};\nPoint.BASE._setWindowSize(8);\nconst crypto = {\n node: nodeCrypto,\n web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined,\n};\nconst TAGS = {\n challenge: 'BIP0340/challenge',\n aux: 'BIP0340/aux',\n nonce: 'BIP0340/nonce',\n};\nconst TAGGED_HASH_PREFIXES = {};\nexport const utils = {\n bytesToHex,\n hexToBytes,\n concatBytes,\n mod,\n invert,\n isValidPrivateKey(privateKey) {\n try {\n normalizePrivateKey(privateKey);\n return true;\n }\n catch (error) {\n return false;\n }\n },\n _bigintTo32Bytes: numTo32b,\n _normalizePrivateKey: normalizePrivateKey,\n hashToPrivateKey: (hash) => {\n hash = ensureBytes(hash);\n const minLen = groupLen + 8;\n if (hash.length < minLen || hash.length > 1024) {\n throw new Error(`Expected valid bytes of private key as per FIPS 186`);\n }\n const num = mod(bytesToNumber(hash), CURVE.n - _1n) + _1n;\n return numTo32b(num);\n },\n randomBytes: (bytesLength = 32) => {\n if (crypto.web) {\n return crypto.web.getRandomValues(new Uint8Array(bytesLength));\n }\n else if (crypto.node) {\n const { randomBytes } = crypto.node;\n return Uint8Array.from(randomBytes(bytesLength));\n }\n else {\n throw new Error(\"The environment doesn't have randomBytes function\");\n }\n },\n randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)),\n precompute(windowSize = 8, point = Point.BASE) {\n const cached = point === Point.BASE ? point : new Point(point.x, point.y);\n cached._setWindowSize(windowSize);\n cached.multiply(_3n);\n return cached;\n },\n sha256: async (...messages) => {\n if (crypto.web) {\n const buffer = await crypto.web.subtle.digest('SHA-256', concatBytes(...messages));\n return new Uint8Array(buffer);\n }\n else if (crypto.node) {\n const { createHash } = crypto.node;\n const hash = createHash('sha256');\n messages.forEach((m) => hash.update(m));\n return Uint8Array.from(hash.digest());\n }\n else {\n throw new Error(\"The environment doesn't have sha256 function\");\n }\n },\n hmacSha256: async (key, ...messages) => {\n if (crypto.web) {\n const ckey = await crypto.web.subtle.importKey('raw', key, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']);\n const message = concatBytes(...messages);\n const buffer = await crypto.web.subtle.sign('HMAC', ckey, message);\n return new Uint8Array(buffer);\n }\n else if (crypto.node) {\n const { createHmac } = crypto.node;\n const hash = createHmac('sha256', key);\n messages.forEach((m) => hash.update(m));\n return Uint8Array.from(hash.digest());\n }\n else {\n throw new Error(\"The environment doesn't have hmac-sha256 function\");\n }\n },\n sha256Sync: undefined,\n hmacSha256Sync: undefined,\n taggedHash: async (tag, ...messages) => {\n let tagP = TAGGED_HASH_PREFIXES[tag];\n if (tagP === undefined) {\n const tagH = await utils.sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0)));\n tagP = concatBytes(tagH, tagH);\n TAGGED_HASH_PREFIXES[tag] = tagP;\n }\n return utils.sha256(tagP, ...messages);\n },\n taggedHashSync: (tag, ...messages) => {\n if (typeof _sha256Sync !== 'function')\n throw new ShaError('sha256Sync is undefined, you need to set it');\n let tagP = TAGGED_HASH_PREFIXES[tag];\n if (tagP === undefined) {\n const tagH = _sha256Sync(Uint8Array.from(tag, (c) => c.charCodeAt(0)));\n tagP = concatBytes(tagH, tagH);\n TAGGED_HASH_PREFIXES[tag] = tagP;\n }\n return _sha256Sync(tagP, ...messages);\n },\n _JacobianPoint: JacobianPoint,\n};\nObject.defineProperties(utils, {\n sha256Sync: {\n configurable: false,\n get() {\n return _sha256Sync;\n },\n set(val) {\n if (!_sha256Sync)\n _sha256Sync = val;\n },\n },\n hmacSha256Sync: {\n configurable: false,\n get() {\n return _hmacSha256Sync;\n },\n set(val) {\n if (!_hmacSha256Sync)\n _hmacSha256Sync = val;\n },\n },\n});\n","/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nfunction isBytes(a) {\n return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');\n}\n/** Asserts something is Uint8Array. */\nfunction abytes(b, ...lengths) {\n if (!isBytes(b))\n throw new Error('Uint8Array expected');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);\n}\nfunction isArrayOf(isString, arr) {\n if (!Array.isArray(arr))\n return false;\n if (arr.length === 0)\n return true;\n if (isString) {\n return arr.every((item) => typeof item === 'string');\n }\n else {\n return arr.every((item) => Number.isSafeInteger(item));\n }\n}\n// no abytes: seems to have 10% slowdown. Why?!\nfunction afn(input) {\n if (typeof input !== 'function')\n throw new Error('function expected');\n return true;\n}\nfunction astr(label, input) {\n if (typeof input !== 'string')\n throw new Error(`${label}: string expected`);\n return true;\n}\nfunction anumber(n) {\n if (!Number.isSafeInteger(n))\n throw new Error(`invalid integer: ${n}`);\n}\nfunction aArr(input) {\n if (!Array.isArray(input))\n throw new Error('array expected');\n}\nfunction astrArr(label, input) {\n if (!isArrayOf(true, input))\n throw new Error(`${label}: array of strings expected`);\n}\nfunction anumArr(label, input) {\n if (!isArrayOf(false, input))\n throw new Error(`${label}: array of numbers expected`);\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction chain(...args) {\n const id = (a) => a;\n // Wrap call in closure so JIT can inline calls\n const wrap = (a, b) => (c) => a(b(c));\n // Construct chain of args[-1].encode(args[-2].encode([...]))\n const encode = args.map((x) => x.encode).reduceRight(wrap, id);\n // Construct chain of args[0].decode(args[1].decode(...))\n const decode = args.map((x) => x.decode).reduce(wrap, id);\n return { encode, decode };\n}\n/**\n * Encodes integer radix representation to array of strings using alphabet and back.\n * Could also be array of strings.\n * @__NO_SIDE_EFFECTS__\n */\nfunction alphabet(letters) {\n // mapping 1 to \"b\"\n const lettersA = typeof letters === 'string' ? letters.split('') : letters;\n const len = lettersA.length;\n astrArr('alphabet', lettersA);\n // mapping \"b\" to 1\n const indexes = new Map(lettersA.map((l, i) => [l, i]));\n return {\n encode: (digits) => {\n aArr(digits);\n return digits.map((i) => {\n if (!Number.isSafeInteger(i) || i < 0 || i >= len)\n throw new Error(`alphabet.encode: digit index outside alphabet \"${i}\". Allowed: ${letters}`);\n return lettersA[i];\n });\n },\n decode: (input) => {\n aArr(input);\n return input.map((letter) => {\n astr('alphabet.decode', letter);\n const i = indexes.get(letter);\n if (i === undefined)\n throw new Error(`Unknown letter: \"${letter}\". Allowed: ${letters}`);\n return i;\n });\n },\n };\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction join(separator = '') {\n astr('join', separator);\n return {\n encode: (from) => {\n astrArr('join.decode', from);\n return from.join(separator);\n },\n decode: (to) => {\n astr('join.decode', to);\n return to.split(separator);\n },\n };\n}\n/**\n * Pad strings array so it has integer number of bits\n * @__NO_SIDE_EFFECTS__\n */\nfunction padding(bits, chr = '=') {\n anumber(bits);\n astr('padding', chr);\n return {\n encode(data) {\n astrArr('padding.encode', data);\n while ((data.length * bits) % 8)\n data.push(chr);\n return data;\n },\n decode(input) {\n astrArr('padding.decode', input);\n let end = input.length;\n if ((end * bits) % 8)\n throw new Error('padding: invalid, string should have whole number of bytes');\n for (; end > 0 && input[end - 1] === chr; end--) {\n const last = end - 1;\n const byte = last * bits;\n if (byte % 8 === 0)\n throw new Error('padding: invalid, string has too much padding');\n }\n return input.slice(0, end);\n },\n };\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction normalize(fn) {\n afn(fn);\n return { encode: (from) => from, decode: (to) => fn(to) };\n}\n/**\n * Slow: O(n^2) time complexity\n */\nfunction convertRadix(data, from, to) {\n // base 1 is impossible\n if (from < 2)\n throw new Error(`convertRadix: invalid from=${from}, base cannot be less than 2`);\n if (to < 2)\n throw new Error(`convertRadix: invalid to=${to}, base cannot be less than 2`);\n aArr(data);\n if (!data.length)\n return [];\n let pos = 0;\n const res = [];\n const digits = Array.from(data, (d) => {\n anumber(d);\n if (d < 0 || d >= from)\n throw new Error(`invalid integer: ${d}`);\n return d;\n });\n const dlen = digits.length;\n while (true) {\n let carry = 0;\n let done = true;\n for (let i = pos; i < dlen; i++) {\n const digit = digits[i];\n const fromCarry = from * carry;\n const digitBase = fromCarry + digit;\n if (!Number.isSafeInteger(digitBase) ||\n fromCarry / from !== carry ||\n digitBase - digit !== fromCarry) {\n throw new Error('convertRadix: carry overflow');\n }\n const div = digitBase / to;\n carry = digitBase % to;\n const rounded = Math.floor(div);\n digits[i] = rounded;\n if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)\n throw new Error('convertRadix: carry overflow');\n if (!done)\n continue;\n else if (!rounded)\n pos = i;\n else\n done = false;\n }\n res.push(carry);\n if (done)\n break;\n }\n for (let i = 0; i < data.length - 1 && data[i] === 0; i++)\n res.push(0);\n return res.reverse();\n}\nconst gcd = (a, b) => (b === 0 ? a : gcd(b, a % b));\nconst radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));\nconst powers = /* @__PURE__ */ (() => {\n let res = [];\n for (let i = 0; i < 40; i++)\n res.push(2 ** i);\n return res;\n})();\n/**\n * Implemented with numbers, because BigInt is 5x slower\n */\nfunction convertRadix2(data, from, to, padding) {\n aArr(data);\n if (from <= 0 || from > 32)\n throw new Error(`convertRadix2: wrong from=${from}`);\n if (to <= 0 || to > 32)\n throw new Error(`convertRadix2: wrong to=${to}`);\n if (radix2carry(from, to) > 32) {\n throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);\n }\n let carry = 0;\n let pos = 0; // bitwise position in current element\n const max = powers[from];\n const mask = powers[to] - 1;\n const res = [];\n for (const n of data) {\n anumber(n);\n if (n >= max)\n throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);\n carry = (carry << from) | n;\n if (pos + from > 32)\n throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);\n pos += from;\n for (; pos >= to; pos -= to)\n res.push(((carry >> (pos - to)) & mask) >>> 0);\n const pow = powers[pos];\n if (pow === undefined)\n throw new Error('invalid carry');\n carry &= pow - 1; // clean carry, otherwise it will cause overflow\n }\n carry = (carry << (to - pos)) & mask;\n if (!padding && pos >= from)\n throw new Error('Excess padding');\n if (!padding && carry > 0)\n throw new Error(`Non-zero padding: ${carry}`);\n if (padding && pos > 0)\n res.push(carry >>> 0);\n return res;\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction radix(num) {\n anumber(num);\n const _256 = 2 ** 8;\n return {\n encode: (bytes) => {\n if (!isBytes(bytes))\n throw new Error('radix.encode input should be Uint8Array');\n return convertRadix(Array.from(bytes), _256, num);\n },\n decode: (digits) => {\n anumArr('radix.decode', digits);\n return Uint8Array.from(convertRadix(digits, num, _256));\n },\n };\n}\n/**\n * If both bases are power of same number (like `2**8 <-> 2**64`),\n * there is a linear algorithm. For now we have implementation for power-of-two bases only.\n * @__NO_SIDE_EFFECTS__\n */\nfunction radix2(bits, revPadding = false) {\n anumber(bits);\n if (bits <= 0 || bits > 32)\n throw new Error('radix2: bits should be in (0..32]');\n if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)\n throw new Error('radix2: carry overflow');\n return {\n encode: (bytes) => {\n if (!isBytes(bytes))\n throw new Error('radix2.encode input should be Uint8Array');\n return convertRadix2(Array.from(bytes), 8, bits, !revPadding);\n },\n decode: (digits) => {\n anumArr('radix2.decode', digits);\n return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));\n },\n };\n}\nfunction unsafeWrapper(fn) {\n afn(fn);\n return function (...args) {\n try {\n return fn.apply(null, args);\n }\n catch (e) { }\n };\n}\nfunction checksum(len, fn) {\n anumber(len);\n afn(fn);\n return {\n encode(data) {\n if (!isBytes(data))\n throw new Error('checksum.encode: input should be Uint8Array');\n const sum = fn(data).slice(0, len);\n const res = new Uint8Array(data.length + len);\n res.set(data);\n res.set(sum, data.length);\n return res;\n },\n decode(data) {\n if (!isBytes(data))\n throw new Error('checksum.decode: input should be Uint8Array');\n const payload = data.slice(0, -len);\n const oldChecksum = data.slice(-len);\n const newChecksum = fn(payload).slice(0, len);\n for (let i = 0; i < len; i++)\n if (newChecksum[i] !== oldChecksum[i])\n throw new Error('Invalid checksum');\n return payload;\n },\n };\n}\n// prettier-ignore\nexport const utils = {\n alphabet, chain, checksum, convertRadix, convertRadix2, radix, radix2, join, padding,\n};\n// RFC 4648 aka RFC 3548\n// ---------------------\n/**\n * base16 encoding from RFC 4648.\n * @example\n * ```js\n * base16.encode(Uint8Array.from([0x12, 0xab]));\n * // => '12AB'\n * ```\n */\nexport const base16 = chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));\n/**\n * base32 encoding from RFC 4648. Has padding.\n * Use `base32nopad` for unpadded version.\n * Also check out `base32hex`, `base32hexnopad`, `base32crockford`.\n * @example\n * ```js\n * base32.encode(Uint8Array.from([0x12, 0xab]));\n * // => 'CKVQ===='\n * base32.decode('CKVQ====');\n * // => Uint8Array.from([0x12, 0xab])\n * ```\n */\nexport const base32 = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));\n/**\n * base32 encoding from RFC 4648. No padding.\n * Use `base32` for padded version.\n * Also check out `base32hex`, `base32hexnopad`, `base32crockford`.\n * @example\n * ```js\n * base32nopad.encode(Uint8Array.from([0x12, 0xab]));\n * // => 'CKVQ'\n * base32nopad.decode('CKVQ');\n * // => Uint8Array.from([0x12, 0xab])\n * ```\n */\nexport const base32nopad = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), join(''));\n/**\n * base32 encoding from RFC 4648. Padded. Compared to ordinary `base32`, slightly different alphabet.\n * Use `base32hexnopad` for unpadded version.\n * @example\n * ```js\n * base32hex.encode(Uint8Array.from([0x12, 0xab]));\n * // => '2ALG===='\n * base32hex.decode('2ALG====');\n * // => Uint8Array.from([0x12, 0xab])\n * ```\n */\nexport const base32hex = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));\n/**\n * base32 encoding from RFC 4648. No padding. Compared to ordinary `base32`, slightly different alphabet.\n * Use `base32hex` for padded version.\n * @example\n * ```js\n * base32hexnopad.encode(Uint8Array.from([0x12, 0xab]));\n * // => '2ALG'\n * base32hexnopad.decode('2ALG');\n * // => Uint8Array.from([0x12, 0xab])\n * ```\n */\nexport const base32hexnopad = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), join(''));\n/**\n * base32 encoding from RFC 4648. Doug Crockford's version.\n * https://www.crockford.com/base32.html\n * @example\n * ```js\n * base32crockford.encode(Uint8Array.from([0x12, 0xab]));\n * // => '2ANG'\n * base32crockford.decode('2ANG');\n * // => Uint8Array.from([0x12, 0xab])\n * ```\n */\nexport const base32crockford = chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));\n// Built-in base64 conversion https://caniuse.com/mdn-javascript_builtins_uint8array_frombase64\n// prettier-ignore\nconst hasBase64Builtin = /* @__PURE__ */ (() => typeof Uint8Array.from([]).toBase64 === 'function' &&\n typeof Uint8Array.fromBase64 === 'function')();\nconst decodeBase64Builtin = (s, isUrl) => {\n astr('base64', s);\n const re = isUrl ? /^[A-Za-z0-9=_-]+$/ : /^[A-Za-z0-9=+/]+$/;\n const alphabet = isUrl ? 'base64url' : 'base64';\n if (s.length > 0 && !re.test(s))\n throw new Error('invalid base64');\n return Uint8Array.fromBase64(s, { alphabet, lastChunkHandling: 'strict' });\n};\n/**\n * base64 from RFC 4648. Padded.\n * Use `base64nopad` for unpadded version.\n * Also check out `base64url`, `base64urlnopad`.\n * Falls back to built-in function, when available.\n * @example\n * ```js\n * base64.encode(Uint8Array.from([0x12, 0xab]));\n * // => 'Eqs='\n * base64.decode('Eqs=');\n * // => Uint8Array.from([0x12, 0xab])\n * ```\n */\n// prettier-ignore\nexport const base64 = hasBase64Builtin ? {\n encode(b) { abytes(b); return b.toBase64(); },\n decode(s) { return decodeBase64Builtin(s, false); },\n} : chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));\n/**\n * base64 from RFC 4648. No padding.\n * Use `base64` for padded version.\n * @example\n * ```js\n * base64nopad.encode(Uint8Array.from([0x12, 0xab]));\n * // => 'Eqs'\n * base64nopad.decode('Eqs');\n * // => Uint8Array.from([0x12, 0xab])\n * ```\n */\nexport const base64nopad = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), join(''));\n/**\n * base64 from RFC 4648, using URL-safe alphabet. Padded.\n * Use `base64urlnopad` for unpadded version.\n * Falls back to built-in function, when available.\n * @example\n * ```js\n * base64url.encode(Uint8Array.from([0x12, 0xab]));\n * // => 'Eqs='\n * base64url.decode('Eqs=');\n * // => Uint8Array.from([0x12, 0xab])\n * ```\n */\n// prettier-ignore\nexport const base64url = hasBase64Builtin ? {\n encode(b) { abytes(b); return b.toBase64({ alphabet: 'base64url' }); },\n decode(s) { return decodeBase64Builtin(s, true); },\n} : chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));\n/**\n * base64 from RFC 4648, using URL-safe alphabet. No padding.\n * Use `base64url` for padded version.\n * @example\n * ```js\n * base64urlnopad.encode(Uint8Array.from([0x12, 0xab]));\n * // => 'Eqs'\n * base64urlnopad.decode('Eqs');\n * // => Uint8Array.from([0x12, 0xab])\n * ```\n */\nexport const base64urlnopad = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), join(''));\n// base58 code\n// -----------\nconst genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => chain(radix(58), alphabet(abc), join(''));\n/**\n * base58: base64 without ambigous characters +, /, 0, O, I, l.\n * Quadratic (O(n^2)) - so, can't be used on large inputs.\n * @example\n * ```js\n * base58.decode('01abcdef');\n * // => '3UhJW'\n * ```\n */\nexport const base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');\n/**\n * base58: flickr version. Check out `base58`.\n */\nexport const base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');\n/**\n * base58: XRP version. Check out `base58`.\n */\nexport const base58xrp = genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');\n// Data len (index) -> encoded block len\nconst XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];\n/**\n * base58: XMR version. Check out `base58`.\n * Done in 8-byte blocks (which equals 11 chars in decoding). Last (non-full) block padded with '1' to size in XMR_BLOCK_LEN.\n * Block encoding significantly reduces quadratic complexity of base58.\n */\nexport const base58xmr = {\n encode(data) {\n let res = '';\n for (let i = 0; i < data.length; i += 8) {\n const block = data.subarray(i, i + 8);\n res += base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');\n }\n return res;\n },\n decode(str) {\n let res = [];\n for (let i = 0; i < str.length; i += 11) {\n const slice = str.slice(i, i + 11);\n const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);\n const block = base58.decode(slice);\n for (let j = 0; j < block.length - blockLen; j++) {\n if (block[j] !== 0)\n throw new Error('base58xmr: wrong padding');\n }\n res = res.concat(Array.from(block.slice(block.length - blockLen)));\n }\n return Uint8Array.from(res);\n },\n};\n/**\n * Method, which creates base58check encoder.\n * Requires function, calculating sha256.\n */\nexport const createBase58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), base58);\n/**\n * Use `createBase58check` instead.\n * @deprecated\n */\nexport const base58check = createBase58check;\nconst BECH_ALPHABET = chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));\nconst POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\nfunction bech32Polymod(pre) {\n const b = pre >> 25;\n let chk = (pre & 0x1ffffff) << 5;\n for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {\n if (((b >> i) & 1) === 1)\n chk ^= POLYMOD_GENERATORS[i];\n }\n return chk;\n}\nfunction bechChecksum(prefix, words, encodingConst = 1) {\n const len = prefix.length;\n let chk = 1;\n for (let i = 0; i < len; i++) {\n const c = prefix.charCodeAt(i);\n if (c < 33 || c > 126)\n throw new Error(`Invalid prefix (${prefix})`);\n chk = bech32Polymod(chk) ^ (c >> 5);\n }\n chk = bech32Polymod(chk);\n for (let i = 0; i < len; i++)\n chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (let v of words)\n chk = bech32Polymod(chk) ^ v;\n for (let i = 0; i < 6; i++)\n chk = bech32Polymod(chk);\n chk ^= encodingConst;\n return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction genBech32(encoding) {\n const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;\n const _words = radix2(5);\n const fromWords = _words.decode;\n const toWords = _words.encode;\n const fromWordsUnsafe = unsafeWrapper(fromWords);\n function encode(prefix, words, limit = 90) {\n astr('bech32.encode prefix', prefix);\n if (isBytes(words))\n words = Array.from(words);\n anumArr('bech32.encode', words);\n const plen = prefix.length;\n if (plen === 0)\n throw new TypeError(`Invalid prefix length ${plen}`);\n const actualLength = plen + 7 + words.length;\n if (limit !== false && actualLength > limit)\n throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);\n const lowered = prefix.toLowerCase();\n const sum = bechChecksum(lowered, words, ENCODING_CONST);\n return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;\n }\n function decode(str, limit = 90) {\n astr('bech32.decode input', str);\n const slen = str.length;\n if (slen < 8 || (limit !== false && slen > limit))\n throw new TypeError(`invalid string length: ${slen} (${str}). Expected (8..${limit})`);\n // don't allow mixed case\n const lowered = str.toLowerCase();\n if (str !== lowered && str !== str.toUpperCase())\n throw new Error(`String must be lowercase or uppercase`);\n const sepIndex = lowered.lastIndexOf('1');\n if (sepIndex === 0 || sepIndex === -1)\n throw new Error(`Letter \"1\" must be present between prefix and data only`);\n const prefix = lowered.slice(0, sepIndex);\n const data = lowered.slice(sepIndex + 1);\n if (data.length < 6)\n throw new Error('Data must be at least 6 characters long');\n const words = BECH_ALPHABET.decode(data).slice(0, -6);\n const sum = bechChecksum(prefix, words, ENCODING_CONST);\n if (!data.endsWith(sum))\n throw new Error(`Invalid checksum in ${str}: expected \"${sum}\"`);\n return { prefix, words };\n }\n const decodeUnsafe = unsafeWrapper(decode);\n function decodeToBytes(str) {\n const { prefix, words } = decode(str, false);\n return { prefix, words, bytes: fromWords(words) };\n }\n function encodeFromBytes(prefix, bytes) {\n return encode(prefix, toWords(bytes));\n }\n return {\n encode,\n decode,\n encodeFromBytes,\n decodeToBytes,\n decodeUnsafe,\n fromWords,\n fromWordsUnsafe,\n toWords,\n };\n}\n/**\n * bech32 from BIP 173. Operates on words.\n * For high-level, check out scure-btc-signer:\n * https://github.com/paulmillr/scure-btc-signer.\n */\nexport const bech32 = genBech32('bech32');\n/**\n * bech32m from BIP 350. Operates on words.\n * It was to mitigate `bech32` weaknesses.\n * For high-level, check out scure-btc-signer:\n * https://github.com/paulmillr/scure-btc-signer.\n */\nexport const bech32m = genBech32('bech32m');\n/**\n * UTF-8-to-byte decoder. Uses built-in TextDecoder / TextEncoder.\n * @example\n * ```js\n * const b = utf8.decode(\"hey\"); // => new Uint8Array([ 104, 101, 121 ])\n * const str = utf8.encode(b); // \"hey\"\n * ```\n */\nexport const utf8 = {\n encode: (data) => new TextDecoder().decode(data),\n decode: (str) => new TextEncoder().encode(str),\n};\n// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex\n// prettier-ignore\nconst hasHexBuiltin = /* @__PURE__ */ (() => typeof Uint8Array.from([]).toHex === 'function' &&\n typeof Uint8Array.fromHex === 'function')();\n// prettier-ignore\nconst hexBuiltin = {\n encode(data) { abytes(data); return data.toHex(); },\n decode(s) { astr('hex', s); return Uint8Array.fromHex(s); },\n};\n/**\n * hex string decoder. Uses built-in function, when available.\n * @example\n * ```js\n * const b = hex.decode(\"0102ff\"); // => new Uint8Array([ 1, 2, 255 ])\n * const str = hex.encode(b); // \"0102ff\"\n * ```\n */\nexport const hex = hasHexBuiltin\n ? hexBuiltin\n : chain(radix2(4), alphabet('0123456789abcdef'), join(''), normalize((s) => {\n if (typeof s !== 'string' || s.length % 2 !== 0)\n throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);\n return s.toLowerCase();\n }));\n// prettier-ignore\nconst CODERS = {\n utf8, hex, base16, base32, base64, base64url, base58, base58xmr\n};\nconst coderTypeError = 'Invalid encoding type. Available types: utf8, hex, base16, base32, base64, base64url, base58, base58xmr';\n/** @deprecated */\nexport const bytesToString = (type, bytes) => {\n if (typeof type !== 'string' || !CODERS.hasOwnProperty(type))\n throw new TypeError(coderTypeError);\n if (!isBytes(bytes))\n throw new TypeError('bytesToString() expects Uint8Array');\n return CODERS[type].encode(bytes);\n};\n/** @deprecated */\nexport const str = bytesToString; // as in python, but for bytes only\n/** @deprecated */\nexport const stringToBytes = (type, str) => {\n if (!CODERS.hasOwnProperty(type))\n throw new TypeError(coderTypeError);\n if (typeof str !== 'string')\n throw new TypeError('stringToBytes() expects string');\n return CODERS[type].decode(str);\n};\n/** @deprecated */\nexport const bytes = stringToBytes;\n//# sourceMappingURL=index.js.map","/// \nimport { bytesToHex, hexToBytes, randomBytes } from \"@noble/hashes/utils\";\nimport { Point } from \"@noble/secp256k1\";\nimport { base64 } from \"@scure/base\";\nimport { logger } from \"applesauce-core\";\nimport { createDefer } from \"applesauce-core/promise\";\nimport { getEventHash, verifyEvent } from \"nostr-tools\";\nconst sleep = (ms) => new Promise((r) => setTimeout(r, ms));\nfunction xOnlyToXY(p) {\n return Point.fromHex(p).toHex().substring(2);\n}\nconst utf8Decoder = new TextDecoder(\"utf-8\");\nconst utf8Encoder = new TextEncoder();\n/** A signer that works with [nostr-signing-device](https://github.com/lnbits/nostr-signing-device) */\nexport class SerialPortSigner {\n log = logger.extend(\"SerialPortSigner\");\n writer = null;\n pubkey;\n get isConnected() {\n return !!this.writer;\n }\n verifyEvent = verifyEvent;\n nip04;\n constructor() {\n this.nip04 = {\n encrypt: this.nip04Encrypt.bind(this),\n decrypt: this.nip04Decrypt.bind(this),\n };\n }\n lastCommand = null;\n async callMethodOnDevice(method, params, opts = {}) {\n if (!SerialPortSigner.SUPPORTED)\n throw new Error(\"Serial devices are not supported\");\n if (!this.writer)\n await this.connectToDevice(opts);\n // only one command can be pending at any time\n // but each will only wait 6 seconds\n if (this.lastCommand)\n throw new Error(\"Previous command to device still pending!\");\n const command = createDefer();\n this.lastCommand = command;\n // send actual command\n this.sendCommand(method, params);\n setTimeout(() => {\n command.reject(new Error(\"Device timeout\"));\n if (this.lastCommand === command)\n this.lastCommand = null;\n }, 6000);\n return this.lastCommand;\n }\n async connectToDevice({ onConnect, onDisconnect, onError, onDone }) {\n let port = await window.navigator.serial.requestPort();\n let reader;\n const startSerialPortReading = async () => {\n // reading responses\n while (port && port.readable) {\n const textDecoder = new window.TextDecoderStream();\n port.readable.pipeTo(textDecoder.writable);\n reader = textDecoder.readable.getReader();\n const readStringUntil = this.readFromSerialPort(reader);\n try {\n while (true) {\n const { value, done } = await readStringUntil(\"\\n\");\n if (value) {\n const { method, data } = this.parseResponse(value);\n // if (method === \"/log\") deviceLog(data);\n if (method === \"/ping\")\n this.log(\"Pong\");\n if (SerialPortSigner.PUBLIC_METHODS.indexOf(method) === -1) {\n // ignore /ping, /log responses\n continue;\n }\n this.log(\"Received: \", method, data);\n if (this.lastCommand) {\n this.lastCommand.resolve(data);\n this.lastCommand = null;\n }\n }\n if (done) {\n this.lastCommand = null;\n this.writer = null;\n if (onDone)\n onDone();\n return;\n }\n }\n }\n catch (error) {\n if (error instanceof Error) {\n this.writer = null;\n if (onError)\n onError(error);\n if (this.lastCommand) {\n this.lastCommand.reject(error);\n this.lastCommand = null;\n }\n throw error;\n }\n }\n }\n };\n await port.open({ baudRate: 9600 });\n // this `sleep()` is a hack, I know!\n // but `port.onconnect` is never called. I don't know why!\n await sleep(1000);\n startSerialPortReading();\n const textEncoder = new window.TextEncoderStream();\n textEncoder.readable.pipeTo(port.writable);\n this.writer = textEncoder.writable.getWriter();\n // send ping first\n await this.sendCommand(SerialPortSigner.METHOD_PING);\n await this.sendCommand(SerialPortSigner.METHOD_PING, [window.location.host]);\n if (onConnect)\n onConnect();\n port.addEventListener(\"disconnect\", () => {\n this.log(\"Disconnected\");\n this.lastCommand = null;\n this.writer = null;\n if (onDisconnect)\n onDisconnect();\n });\n }\n async sendCommand(method, params = []) {\n if (!this.writer)\n return;\n this.log(\"Send command\", method, params);\n const message = [method].concat(params).join(\" \");\n await this.writer.write(message + \"\\n\");\n }\n readFromSerialPort(reader) {\n let partialChunk;\n let fulliness = [];\n const readStringUntil = async (separator = \"\\n\") => {\n if (fulliness.length)\n return { value: fulliness.shift().trim(), done: false };\n const chunks = [];\n if (partialChunk) {\n // leftovers from previous read\n chunks.push(partialChunk);\n partialChunk = undefined;\n }\n while (true) {\n const { value, done } = await reader.read();\n if (value) {\n const values = value.split(separator);\n // found one or more separators\n if (values.length > 1) {\n chunks.push(values.shift()); // first element\n partialChunk = values.pop(); // last element\n fulliness = values; // full lines\n return { value: chunks.join(\"\").trim(), done: false };\n }\n chunks.push(value);\n }\n if (done)\n return { value: chunks.join(\"\").trim(), done: true };\n }\n };\n return readStringUntil;\n }\n parseResponse(value) {\n const method = value.split(\" \")[0];\n const data = value.substring(method.length).trim();\n return { method, data };\n }\n // NIP-04\n async nip04Encrypt(pubkey, text) {\n const sharedSecretStr = await this.callMethodOnDevice(SerialPortSigner.METHOD_SHARED_SECRET, [xOnlyToXY(pubkey)]);\n const sharedSecret = hexToBytes(sharedSecretStr);\n let iv = Uint8Array.from(randomBytes(16));\n let plaintext = utf8Encoder.encode(text);\n // @ts-ignore\n let cryptoKey = await crypto.subtle.importKey(\"raw\", sharedSecret, { name: \"AES-CBC\" }, false, [\"encrypt\"]);\n let ciphertext = await crypto.subtle.encrypt({ name: \"AES-CBC\", iv }, cryptoKey, plaintext);\n let ctb64 = base64.encode(new Uint8Array(ciphertext));\n let ivb64 = base64.encode(new Uint8Array(iv.buffer));\n return `${ctb64}?iv=${ivb64}`;\n }\n async nip04Decrypt(pubkey, data) {\n let [ctb64, ivb64] = data.split(\"?iv=\");\n const sharedSecretStr = await this.callMethodOnDevice(SerialPortSigner.METHOD_SHARED_SECRET, [xOnlyToXY(pubkey)]);\n const sharedSecret = hexToBytes(sharedSecretStr);\n // @ts-ignore\n let cryptoKey = await crypto.subtle.importKey(\"raw\", sharedSecret, { name: \"AES-CBC\" }, false, [\"decrypt\"]);\n let ciphertext = base64.decode(ctb64);\n let iv = base64.decode(ivb64);\n // @ts-ignore\n let plaintext = await crypto.subtle.decrypt({ name: \"AES-CBC\", iv }, cryptoKey, ciphertext);\n let text = utf8Decoder.decode(plaintext);\n return text;\n }\n /** Returns the public key on the device */\n async getPublicKey() {\n const pubkey = await this.callMethodOnDevice(SerialPortSigner.METHOD_PUBLIC_KEY, []);\n this.pubkey = pubkey;\n return pubkey;\n }\n /** Sets the secret key used on the device */\n async restore(secretKey) {\n await this.callMethodOnDevice(SerialPortSigner.METHOD_RESTORE, [bytesToHex(secretKey)]);\n }\n /** Requires the device to sign an event */\n async signEvent(draft) {\n const pubkey = draft.pubkey || this.pubkey;\n if (!pubkey)\n throw new Error(\"Unknown signer pubkey\");\n const draftWithId = { ...draft, id: getEventHash({ ...draft, pubkey }) };\n const sig = await this.callMethodOnDevice(SerialPortSigner.METHOD_SIGN_MESSAGE, [draftWithId.id]);\n const event = { ...draftWithId, sig, pubkey };\n if (!this.verifyEvent(event))\n throw new Error(\"Invalid signature\");\n return event;\n }\n /** Pings to device to see if the connection is open */\n ping() {\n this.sendCommand(SerialPortSigner.METHOD_PING, [window.location.host]);\n }\n // static const\n static SUPPORTED = \"navigator\" in globalThis && !!navigator.serial;\n static METHOD_PING = \"/ping\";\n static METHOD_LOG = \"/log\";\n static METHOD_SIGN_MESSAGE = \"/sign-message\";\n static METHOD_SHARED_SECRET = \"/shared-secret\";\n static METHOD_PUBLIC_KEY = \"/public-key\";\n static METHOD_RESTORE = \"/restore\";\n static PUBLIC_METHODS = [\n SerialPortSigner.METHOD_PUBLIC_KEY,\n SerialPortSigner.METHOD_SIGN_MESSAGE,\n SerialPortSigner.METHOD_SHARED_SECRET,\n SerialPortSigner.METHOD_RESTORE,\n ];\n}\n","import { noop, safe_not_equal, subscribe, run_all, is_function } from '../internal/index.mjs';\nexport { get_store_value as get } from '../internal/index.mjs';\n\nconst subscriber_queue = [];\n/**\n * Creates a `Readable` store that allows reading by subscription.\n * @param value initial value\n * @param {StartStopNotifier} [start]\n */\nfunction readable(value, start) {\n return {\n subscribe: writable(value, start).subscribe\n };\n}\n/**\n * Create a `Writable` store that allows both updating and reading by subscription.\n * @param {*=}value initial value\n * @param {StartStopNotifier=} start\n */\nfunction writable(value, start = noop) {\n let stop;\n const subscribers = new Set();\n function set(new_value) {\n if (safe_not_equal(value, new_value)) {\n value = new_value;\n if (stop) { // store is ready\n const run_queue = !subscriber_queue.length;\n for (const subscriber of subscribers) {\n subscriber[1]();\n subscriber_queue.push(subscriber, value);\n }\n if (run_queue) {\n for (let i = 0; i < subscriber_queue.length; i += 2) {\n subscriber_queue[i][0](subscriber_queue[i + 1]);\n }\n subscriber_queue.length = 0;\n }\n }\n }\n }\n function update(fn) {\n set(fn(value));\n }\n function subscribe(run, invalidate = noop) {\n const subscriber = [run, invalidate];\n subscribers.add(subscriber);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n run(value);\n return () => {\n subscribers.delete(subscriber);\n if (subscribers.size === 0 && stop) {\n stop();\n stop = null;\n }\n };\n }\n return { set, update, subscribe };\n}\nfunction derived(stores, fn, initial_value) {\n const single = !Array.isArray(stores);\n const stores_array = single\n ? [stores]\n : stores;\n const auto = fn.length < 2;\n return readable(initial_value, (set) => {\n let started = false;\n const values = [];\n let pending = 0;\n let cleanup = noop;\n const sync = () => {\n if (pending) {\n return;\n }\n cleanup();\n const result = fn(single ? values[0] : values, set);\n if (auto) {\n set(result);\n }\n else {\n cleanup = is_function(result) ? result : noop;\n }\n };\n const unsubscribers = stores_array.map((store, i) => subscribe(store, (value) => {\n values[i] = value;\n pending &= ~(1 << i);\n if (started) {\n sync();\n }\n }, () => {\n pending |= (1 << i);\n }));\n started = true;\n sync();\n return function stop() {\n run_all(unsubscribers);\n cleanup();\n // We need to set this to false because callbacks can still happen despite having unsubscribed:\n // Callbacks might already be placed in the queue which doesn't know it should no longer\n // invoke this derived store.\n started = false;\n };\n });\n}\n/**\n * Takes a store and returns a new one derived from the old one that is readable.\n *\n * @param store - store to make readonly\n */\nfunction readonly(store) {\n return {\n subscribe: store.subscribe.bind(store)\n };\n}\n\nexport { derived, readable, readonly, writable };\n","import { writable, derived } from 'svelte/store';\n\n// ==================== Relay Connection State ====================\n\n// Configured relay URL (empty = use same origin / embedded mode)\nexport const relayUrl = writable(localStorage.getItem(\"relayUrl\") || \"\");\nexport const isStandaloneMode = writable(false);\nexport const relayInfo = writable(null); // NIP-11 relay info\nexport const relayConnectionStatus = writable(\"disconnected\"); // disconnected, connecting, connected, error\nexport const isOrlyRelay = writable(true); // true if connected to ORLY relay with API endpoints\n\n// Saved relays list - each entry: { url: string, name: string, lastConnected?: number }\nconst storedRelays = localStorage.getItem(\"savedRelays\");\nexport const savedRelays = writable(storedRelays ? JSON.parse(storedRelays) : []);\n\n// Persist relay URL to localStorage\nrelayUrl.subscribe(url => {\n if (url) {\n localStorage.setItem(\"relayUrl\", url);\n } else {\n localStorage.removeItem(\"relayUrl\");\n }\n});\n\n// Persist saved relays to localStorage\nsavedRelays.subscribe(relays => {\n localStorage.setItem(\"savedRelays\", JSON.stringify(relays));\n});\n\n// ==================== User/Auth State ====================\n\nexport const isLoggedIn = writable(false);\nexport const userPubkey = writable(\"\");\nexport const userProfile = writable(null);\nexport const userRole = writable(\"\");\nexport const userSigner = writable(null);\nexport const authMethod = writable(\"\");\n\n// View-as role for permission testing\nexport const viewAsRole = writable(\"\");\n\n// Derived: effective role (actual or view-as)\nexport const currentEffectiveRole = derived(\n [userRole, viewAsRole],\n ([$userRole, $viewAsRole]) => $viewAsRole || $userRole\n);\n\n// ==================== UI State ====================\n\nexport const isDarkTheme = writable(false);\nexport const showLoginModal = writable(false);\nexport const showSettingsDrawer = writable(false);\nexport const selectedTab = writable(localStorage.getItem(\"selectedTab\") || \"export\");\nexport const showFilterBuilder = writable(false);\n\n// ==================== ACL State ====================\n\nexport const aclMode = writable(\"\");\nexport const isPolicyAdmin = writable(false);\nexport const policyEnabled = writable(false);\n\n// ==================== Events Cache ====================\n\nexport const globalEventsCache = writable([]);\nexport const globalCacheTimestamp = writable(0);\n\n// ==================== Search State ====================\n\nexport const searchQuery = writable(\"\");\nexport const searchTabs = writable([]);\nexport const searchResults = writable(new Map());\n\n// ==================== Helper Functions ====================\n\n/**\n * Reset all auth-related stores on logout\n */\nexport function resetAuthState() {\n isLoggedIn.set(false);\n userPubkey.set(\"\");\n userProfile.set(null);\n userRole.set(\"\");\n userSigner.set(null);\n authMethod.set(\"\");\n viewAsRole.set(\"\");\n isPolicyAdmin.set(false);\n}\n\n/**\n * Clear the events cache\n */\nexport function clearEventsCache() {\n globalEventsCache.set([]);\n globalCacheTimestamp.set(0);\n}\n\n/**\n * Update the events cache\n * @param {Array} events - Events to cache\n */\nexport function updateEventsCache(events) {\n globalEventsCache.set(events);\n globalCacheTimestamp.set(Date.now());\n}\n\n/**\n * Check if cache is still valid\n * @param {number} cacheDuration - Cache duration in ms\n * @returns {boolean}\n */\nexport function isCacheValid(cacheDuration = 5 * 60 * 1000) {\n let timestamp;\n globalCacheTimestamp.subscribe(v => timestamp = v)();\n return Date.now() - timestamp < cacheDuration;\n}\n\n/**\n * Clear relay connection and reset to embedded mode\n */\nexport function clearRelayConnection() {\n relayUrl.set(\"\");\n relayInfo.set(null);\n relayConnectionStatus.set(\"disconnected\");\n // Also clear auth state since we're changing relays\n resetAuthState();\n clearEventsCache();\n}\n\n/**\n * Add or update a relay in the saved relays list\n * @param {string} url - Relay URL\n * @param {string} name - Relay name (from NIP-11 or user input)\n */\nexport function saveRelay(url, name) {\n savedRelays.update(relays => {\n const existing = relays.findIndex(r => r.url === url);\n const entry = { url, name, lastConnected: Date.now() };\n if (existing >= 0) {\n relays[existing] = entry;\n } else {\n relays.unshift(entry);\n }\n return relays;\n });\n}\n\n/**\n * Remove a relay from the saved relays list\n * @param {string} url - Relay URL to remove\n */\nexport function removeRelay(url) {\n savedRelays.update(relays => relays.filter(r => r.url !== url));\n}\n\n/**\n * Update the last connected timestamp for a relay\n * @param {string} url - Relay URL\n */\nexport function touchRelay(url) {\n savedRelays.update(relays => {\n const relay = relays.find(r => r.url === url);\n if (relay) {\n relay.lastConnected = Date.now();\n }\n return relays;\n });\n}\n\n// ==================== Bunker Service State ====================\n\nexport const bunkerServiceActive = writable(false);\nexport const bunkerConnectedClients = writable([]);\n\n// Bunker worker instance (persists across component mounts)\nlet bunkerWorker = null;\n\n/**\n * Get or create the bunker worker\n */\nfunction getBunkerWorker() {\n if (!bunkerWorker) {\n bunkerWorker = new Worker(new URL('./bunker-worker.js', import.meta.url), { type: 'module' });\n bunkerWorker.onmessage = (event) => {\n const { type, ...data } = event.data;\n switch (type) {\n case 'status':\n bunkerServiceActive.set(data.status === 'connected');\n break;\n case 'clients':\n bunkerConnectedClients.set(data.clients || []);\n break;\n case 'error':\n console.error('[BunkerStore] Worker error:', data.error);\n break;\n case 'request':\n console.log('[BunkerStore] Request:', data.method, 'from:', data.from);\n break;\n }\n };\n }\n return bunkerWorker;\n}\n\n/**\n * Configure the bunker worker\n */\nexport function configureBunkerWorker(config) {\n const worker = getBunkerWorker();\n worker.postMessage({ type: 'configure', ...config });\n}\n\n/**\n * Connect the bunker worker\n */\nexport function connectBunkerWorker() {\n const worker = getBunkerWorker();\n worker.postMessage({ type: 'connect' });\n}\n\n/**\n * Disconnect the bunker worker\n */\nexport function disconnectBunkerWorker() {\n const worker = getBunkerWorker();\n worker.postMessage({ type: 'disconnect' });\n}\n\n/**\n * Add a secret to the bunker worker\n */\nexport function addBunkerSecret(secret) {\n const worker = getBunkerWorker();\n worker.postMessage({ type: 'addSecret', secret });\n}\n\n/**\n * Request current bunker status\n */\nexport function requestBunkerStatus() {\n const worker = getBunkerWorker();\n worker.postMessage({ type: 'getStatus' });\n}\n\n/**\n * Reset bunker state\n */\nexport function resetBunkerState() {\n disconnectBunkerWorker();\n bunkerServiceActive.set(false);\n bunkerConnectedClients.set([]);\n}\n","/**\n * Relay configuration module for dual-mode operation (embedded vs standalone)\n *\n * Embedded mode: Dashboard served from same origin as relay (no CORS needed)\n * Standalone mode: Dashboard hosted separately, connects to remote relay (CORS required)\n */\n\nimport { get } from 'svelte/store';\nimport { relayUrl, isStandaloneMode, relayInfo, relayConnectionStatus } from './stores.js';\n\n// Build-time configuration (set via rollup replace plugin)\nconst BUILD_STANDALONE_MODE = typeof process !== 'undefined' &&\n process.env && process.env.STANDALONE_MODE === 'true';\nconst BUILD_DEFAULT_RELAY_URL = typeof process !== 'undefined' &&\n process.env && process.env.DEFAULT_RELAY_URL || '';\n\n/**\n * Initialize configuration on app startup\n * Call this from main.js before rendering App\n */\nexport function initConfig() {\n // Detect standalone mode:\n // 1. Explicitly built as standalone\n // 2. Has a configured relay URL in localStorage\n // 3. Running from file:// protocol\n // 4. Not running on a typical relay port (3334) - likely a static server\n const hasStoredRelay = !!localStorage.getItem(\"relayUrl\");\n const isFileProtocol = window.location.protocol === 'file:';\n const isNonRelayPort = !['3334', '7777', '443', '80', ''].includes(window.location.port);\n\n const standalone = BUILD_STANDALONE_MODE || hasStoredRelay || isFileProtocol || isNonRelayPort;\n isStandaloneMode.set(standalone);\n\n // Set default relay URL from build config if not already set\n if (BUILD_DEFAULT_RELAY_URL && !get(relayUrl)) {\n relayUrl.set(BUILD_DEFAULT_RELAY_URL);\n }\n\n console.log('[config] Initialized:', {\n standaloneMode: standalone,\n buildStandalone: BUILD_STANDALONE_MODE,\n hasStoredRelay,\n isNonRelayPort,\n port: window.location.port,\n relayUrl: get(relayUrl) || '(same origin)'\n });\n}\n\n/**\n * Get the HTTP base URL for API calls\n * @returns {string} Base URL (e.g., \"https://relay.example.com\")\n */\nexport function getApiBase() {\n const url = get(relayUrl);\n if (url) {\n return normalizeHttpUrl(url);\n }\n return window.location.origin;\n}\n\n/**\n * Get the WebSocket URL for relay connection\n * @returns {string} WebSocket URL (e.g., \"wss://relay.example.com/\")\n */\nexport function getWsUrl() {\n const url = get(relayUrl);\n if (url) {\n return normalizeWsUrl(url);\n }\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';\n return `${protocol}//${window.location.host}/`;\n}\n\n/**\n * Get array of relay URLs for nostr-tools SimplePool\n * @returns {string[]} Array with single relay URL\n */\nexport function getRelayUrls() {\n return [getWsUrl()];\n}\n\n/**\n * Check if running in standalone mode\n * @returns {boolean}\n */\nexport function isStandalone() {\n return get(isStandaloneMode);\n}\n\n/**\n * Check if a relay URL is configured (either stored or same-origin)\n * @returns {boolean}\n */\nexport function hasRelayConfigured() {\n // In embedded mode, always configured (same origin)\n // In standalone mode, need explicit URL\n if (!get(isStandaloneMode)) {\n return true;\n }\n return !!get(relayUrl);\n}\n\n/**\n * Set the relay URL and trigger connection\n * @param {string} url - Relay URL (http/https/ws/wss)\n */\nexport function setRelayUrl(url) {\n const normalized = url ? normalizeHttpUrl(url) : '';\n relayUrl.set(normalized);\n\n if (normalized) {\n // Mark as standalone since we have an explicit URL\n isStandaloneMode.set(true);\n }\n}\n\n/**\n * Fetch and validate relay info via NIP-11\n * @param {string} [url] - Optional URL to check (defaults to current relay)\n * @returns {Promise