diff --git a/components/login-modal.html b/components/login-modal.html index 6ec0e560..f23494b2 100644 --- a/components/login-modal.html +++ b/components/login-modal.html @@ -47,27 +47,50 @@ >

- Choose how you'd like to sign in. Connect a browser extension, link a - remote signer, or work directly with your keys when you need to. + Sign in with a login name and password that works the same on every + BitLogin site, or use one of the other options below.

-
-- never + written by an innerHTML re-render (this markup never changes after + the page loads), so the element is only ever hidden/shown, never + destroyed and recreated. Removing it from the DOM tears down its + crypto Web Worker (see BitLogin's README). + --> +
-
-

Available methods

-

- Pick the option that matches how you manage your Nostr identity. -

-
+ +
- -
-
+
+ + Other login options + +
+
+

Available methods

+

+ Pick the option that matches how you manage your Nostr identity. +

+
+ + +
+
+
diff --git a/config/instance-config.js b/config/instance-config.js index dec628cf..183a3b90 100644 --- a/config/instance-config.js +++ b/config/instance-config.js @@ -276,6 +276,19 @@ export const FEATURE_AUDIO_INGEST = false; */ export const FEATURE_BITCOIN_CONNECT = true; +/** + * Whether the login modal offers BitLogin (a portable Nostr identity behind a + * login name/password, https://github.com/PR0M3TH3AN/bitlogin) as the primary + * sign-in method, with the NIP-07 extension, nsec, and NIP-46 options + * collapsed under "Other login options" (js/ui/bitloginModalIntegration.js). + * The vendored widget bundle (vendor/bitlogin/, scripts/build-bitlogin-widget.mjs) + * only lazy-loads once the login modal's HTML is present in the DOM. + * + * Unstable-branch experiment (AGENTS.md §1) -- reset to `false` before this + * reaches main until verified end-to-end against production relays. + */ +export const FEATURE_BITLOGIN = true; + /** * Whether this deployment offers Blossom (nostr-native blob storage) as a * first-class upload provider alongside Cloudflare R2 / generic S3 / Backblaze B2 diff --git a/css/tailwind.source.css b/css/tailwind.source.css index 258b6acb..d52ec7d6 100644 --- a/css/tailwind.source.css +++ b/css/tailwind.source.css @@ -880,6 +880,29 @@ position: relative; } + /* Maps the widget's own theming hooks onto bitvid's design + tokens (components/login-modal.html), so it reads as part of this site + rather than a foreign embed, and follows the light/dark theme toggle + automatically since every token below is itself theme-aware. */ + bitlogin-auth { + display: block; + --bl-accent: var(--color-accent-strong); + --bl-accent-hover: var(--color-accent); + --bl-accent-fg: rgb(255 255 255); + --bl-bg: var(--surface-panel); + --bl-fg: var(--text-primary); + --bl-muted: var(--text-muted); + --bl-border: var(--border-default); + --bl-input-bg: var(--surface-sunken); + --bl-danger: var(--status-danger); + --bl-danger-bg: var(--status-danger-surface); + --bl-warn: var(--status-warning); + --bl-warn-bg: var(--status-warning-surface); + --bl-radius: var(--radius-lg); + --bl-font-family: inherit; + --bl-max-width: none; + } + .btn-ghost[data-state="active"], .btn-ghost[aria-pressed="true"] { @apply border-transparent bg-primary text-white shadow-md; diff --git a/js/app.js b/js/app.js index 1b3dccb3..f07987e1 100644 --- a/js/app.js +++ b/js/app.js @@ -67,7 +67,7 @@ import { normalizeVideoNotePayload, } from "./services/videoNotePayload.js"; import getAuthProvider, { - providers as authProviders, + providersForModal as authProviders, } from "./services/authProviders/index.js"; import hashtagPreferences, { HASHTAG_PREFERENCES_EVENTS, diff --git a/js/config.js b/js/config.js index 1cc67536..07639a27 100644 --- a/js/config.js +++ b/js/config.js @@ -27,6 +27,7 @@ import { FEATURE_NIP71_INGEST, FEATURE_AUDIO_INGEST, FEATURE_BITCOIN_CONNECT, + FEATURE_BITLOGIN, FEATURE_BLOSSOM_STORAGE, FEATURE_BLOSSOM_TORRENT_METADATA, CARD_LIVENESS_POLICY, @@ -127,6 +128,7 @@ export { ALLOW_NSFW_CONTENT }; export { FEATURE_NIP71_INGEST }; export { FEATURE_AUDIO_INGEST }; export { FEATURE_BITCOIN_CONNECT }; +export { FEATURE_BITLOGIN }; export { FEATURE_BLOSSOM_STORAGE }; export { FEATURE_BLOSSOM_TORRENT_METADATA }; export { CARD_LIVENESS_POLICY }; diff --git a/js/constants.js b/js/constants.js index 68c23835..3a0a15a3 100644 --- a/js/constants.js +++ b/js/constants.js @@ -9,6 +9,7 @@ import { FEATURE_NIP71_INGEST as CONFIG_FEATURE_NIP71_INGEST, FEATURE_AUDIO_INGEST as CONFIG_FEATURE_AUDIO_INGEST, FEATURE_BITCOIN_CONNECT as CONFIG_FEATURE_BITCOIN_CONNECT, + FEATURE_BITLOGIN as CONFIG_FEATURE_BITLOGIN, FEATURE_BLOSSOM_STORAGE as CONFIG_FEATURE_BLOSSOM_STORAGE, FEATURE_BLOSSOM_TORRENT_METADATA as CONFIG_FEATURE_BLOSSOM_TORRENT_METADATA, CARD_LIVENESS_POLICY as CONFIG_CARD_LIVENESS_POLICY, @@ -205,6 +206,9 @@ const DEFAULT_FLAGS = Object.freeze({ // Bitcoin Connect NWC "Connect wallet" flow (docs/bitcoin-connect-plan.md, #61). // Default OFF; only an explicit `true` in the instance config enables it. FEATURE_BITCOIN_CONNECT: CONFIG_FEATURE_BITCOIN_CONNECT === true, + // BitLogin primary sign-in method (js/ui/bitloginModalIntegration.js). + // Default OFF; only an explicit `true` in the instance config enables it. + FEATURE_BITLOGIN: CONFIG_FEATURE_BITLOGIN === true, // Blossom (nostr-native blob storage) provider (docs/blossom-plan.md, #30). // Default OFF; only an explicit `true` in the instance config enables it. FEATURE_BLOSSOM_STORAGE: CONFIG_FEATURE_BLOSSOM_STORAGE === true, @@ -241,6 +245,7 @@ const runtimeFlags = (() => { FEATURE_NIP71_INGEST: DEFAULT_FLAGS.FEATURE_NIP71_INGEST, FEATURE_AUDIO_INGEST: DEFAULT_FLAGS.FEATURE_AUDIO_INGEST, FEATURE_BITCOIN_CONNECT: DEFAULT_FLAGS.FEATURE_BITCOIN_CONNECT, + FEATURE_BITLOGIN: DEFAULT_FLAGS.FEATURE_BITLOGIN, FEATURE_BLOSSOM_STORAGE: DEFAULT_FLAGS.FEATURE_BLOSSOM_STORAGE, FEATURE_BLOSSOM_TORRENT_METADATA: DEFAULT_FLAGS.FEATURE_BLOSSOM_TORRENT_METADATA, @@ -299,6 +304,11 @@ export let FEATURE_BITCOIN_CONNECT = coerceBoolean( DEFAULT_FLAGS.FEATURE_BITCOIN_CONNECT ); +export let FEATURE_BITLOGIN = coerceBoolean( + runtimeFlags.FEATURE_BITLOGIN, + DEFAULT_FLAGS.FEATURE_BITLOGIN +); + export let FEATURE_BLOSSOM_STORAGE = coerceBoolean( runtimeFlags.FEATURE_BLOSSOM_STORAGE, DEFAULT_FLAGS.FEATURE_BLOSSOM_STORAGE diff --git a/js/nostr/adapters/bitloginAdapter.js b/js/nostr/adapters/bitloginAdapter.js new file mode 100644 index 00000000..167c747a --- /dev/null +++ b/js/nostr/adapters/bitloginAdapter.js @@ -0,0 +1,38 @@ +// js/nostr/adapters/bitloginAdapter.js +// +// Wraps a live element (already signed in) as a signer matching +// the same shape as nip07Adapter/nsecAdapter/nip46Adapter. Never touches +// window.nostr and never sees the private key -- every call is proxied through +// the element's own crypto Web Worker (see BitLogin's README, "Embedding +// BitLogin" -> element-scoped methods). + +export function createBitloginAdapter(widgetElement, pubkey) { + const signer = { + type: "bitlogin", + pubkey: typeof pubkey === "string" ? pubkey : "", + metadata: async () => null, + relays: async () => null, + signEvent: async (event) => widgetElement.signEvent(event), + nip44Encrypt: async (peerPubkey, plaintext) => + widgetElement.nip44Encrypt(peerPubkey, plaintext), + nip44Decrypt: async (peerPubkey, payload) => + widgetElement.nip44Decrypt(peerPubkey, payload), + requestPermissions: async () => ({ ok: true }), + destroy: async () => { + try { + await widgetElement.logout(); + } catch (error) { + // The element is permanently mounted and reused for the next sign-in; + // a failed logout here shouldn't block switching to another signer. + } + }, + canSign: () => true, + capabilities: { + sign: true, + nip44: true, + nip04: false, + }, + }; + + return signer; +} diff --git a/js/services/authProviders/bitlogin.js b/js/services/authProviders/bitlogin.js new file mode 100644 index 00000000..91c5b0a1 --- /dev/null +++ b/js/services/authProviders/bitlogin.js @@ -0,0 +1,85 @@ +import { accessControl } from "../../accessControl.js"; + +const PROVIDER_ID = "bitlogin"; +const PROVIDER_LABEL = "BitLogin"; +const PROVIDER_DESCRIPTION = + "A portable Nostr identity behind a familiar login name and password."; +const PROVIDER_CAPABILITIES = Object.freeze([ + Object.freeze({ + id: "signing", + label: "Signs Nostr events", + variant: "info", + }), + Object.freeze({ + id: "portable", + label: "Works on every BitLogin site", + variant: "neutral", + }), +]); +const PROVIDER_BUTTON = Object.freeze({ + variant: "primary", +}); +const PROVIDER_MESSAGES = Object.freeze({ + loading: "Signing in with BitLogin…", + slow: "Still waiting on BitLogin…", + error: "Failed to sign in with BitLogin. Please try again.", +}); + +// Set by the widget's own "bitlogin-login" listener (js/ui/applicationBootstrap.js) +// right before it calls authService.requestLogin({ providerId: "bitlogin" }): by +// the time that reaches this provider's login(), the widget has already run its +// own multi-screen sign-in/create/recover flow and produced a pubkey + signer. +// This provider exists so that result goes through the exact same session- +// establishment path (AuthService.login -> handleAuthLogin) as every other +// signer, without BitLogin also rendering as a redundant button in the login +// grid -- see providersForModal in ./index.js. +let pendingResult = null; + +export function setPendingBitloginResult(result) { + pendingResult = result && typeof result === "object" ? result : null; +} + +export default { + id: PROVIDER_ID, + label: PROVIDER_LABEL, + description: PROVIDER_DESCRIPTION, + eyebrow: "Recommended", + tone: "accent", + badgeVariant: "info", + capabilities: PROVIDER_CAPABILITIES, + button: PROVIDER_BUTTON, + messages: PROVIDER_MESSAGES, + errorMessage: PROVIDER_MESSAGES.error, + async login({ nostrClient } = {}) { + const result = pendingResult; + pendingResult = null; + + if (!result || typeof result.pubkey !== "string" || !result.pubkey.trim()) { + const error = new Error("BitLogin sign-in hasn't completed yet."); + error.code = "provider-unavailable"; + throw error; + } + + const pubkey = result.pubkey.trim(); + + if (!accessControl.canAccess(pubkey)) { + if (accessControl.isBlacklisted(pubkey)) { + throw new Error("Your account has been blocked on this platform."); + } + throw new Error("Access restricted to admins and moderators users only."); + } + + if ( + nostrClient?.signerManager && + typeof nostrClient.signerManager.setActiveSigner === "function" + ) { + nostrClient.signerManager.setActiveSigner(result.signer); + } + + return { + authType: PROVIDER_ID, + pubkey, + signer: result.signer, + }; + }, +}; diff --git a/js/services/authProviders/index.js b/js/services/authProviders/index.js index 1cb0f65a..63c37823 100644 --- a/js/services/authProviders/index.js +++ b/js/services/authProviders/index.js @@ -2,6 +2,7 @@ import nip07 from "./nip07.js"; import nip46 from "./nip46.js"; import nsec from "./nsec.js"; import generate from "./generate.js"; +import bitlogin from "./bitlogin.js"; function normalizeProviderId(provider, fallbackId) { if (provider && typeof provider.id === "string") { @@ -39,7 +40,7 @@ function normalizeProviderMetadata(provider, fallbackId) { return Object.freeze({ id, label, description, badgeVariant }); } -const providerList = [nip07, nip46, nsec, generate].filter(Boolean); +const providerList = [nip07, nip46, nsec, generate, bitlogin].filter(Boolean); const providerMap = {}; const metadataMap = {}; @@ -97,6 +98,19 @@ builtInMetadata.forEach((entry) => { export const providers = Object.freeze({ ...providerMap }); export const providerMetadata = Object.freeze({ ...metadataMap }); +// BitLogin gets its own permanent, always-visible widget in the login modal +// (components/login-modal.html) rather than a grid button -- it isn't a single +// button-click-then-await-a-promise flow like the others, it's a whole +// multi-screen sign-in/create/recover UI. Excluding it here keeps the modal's +// provider grid ("Other login options") free of a redundant, do-nothing button +// for it, while `providers.bitlogin` above still resolves normally for +// AuthService.requestLogin({ providerId: "bitlogin" }). +export const providersForModal = Object.freeze( + Object.fromEntries( + Object.entries(providerMap).filter(([id]) => id !== "bitlogin"), + ), +); + const unknownMetadataCache = new Map(); function getFallbackMetadata(providerId) { diff --git a/js/services/authProviders/nip07.js b/js/services/authProviders/nip07.js index 1d425d2d..818eba00 100644 --- a/js/services/authProviders/nip07.js +++ b/js/services/authProviders/nip07.js @@ -49,7 +49,6 @@ export default { id: PROVIDER_ID, label: PROVIDER_LABEL, description: PROVIDER_DESCRIPTION, - eyebrow: "Recommended", tone: "accent", badgeVariant: "info", capabilities: PROVIDER_CAPABILITIES, diff --git a/js/ui/applicationBootstrap.js b/js/ui/applicationBootstrap.js index ebd96633..639b32ee 100644 --- a/js/ui/applicationBootstrap.js +++ b/js/ui/applicationBootstrap.js @@ -41,6 +41,7 @@ import ProfileIdentityController from "./profileIdentityController.js"; import VideoListViewController from "./videoListViewController.js"; import ProfileModalController from "./profileModalController.js"; import LoginModalController from "./loginModalController.js"; +import { wireBitloginLogin } from "./bitloginModalIntegration.js"; import { VideoListView } from "./views/VideoListView.js"; import MoreMenuController from "./moreMenuController.js"; import VideoSettingsMenuController from "./videoSettingsMenuController.js"; @@ -429,6 +430,7 @@ export default class ApplicationBootstrap { authProviders: this.services.authProviders || authProviders, getAuthProvider: this.services.getAuthProvider || getAuthProvider, }); + wireBitloginLogin(app); app.authEventUnsubscribes.push( app.authService.on("auth:login", (detail) => { const maybePromise = app.handleAuthLogin(detail); diff --git a/js/ui/bitloginModalIntegration.js b/js/ui/bitloginModalIntegration.js new file mode 100644 index 00000000..c71ba074 --- /dev/null +++ b/js/ui/bitloginModalIntegration.js @@ -0,0 +1,116 @@ +// js/ui/bitloginModalIntegration.js +// +// Wires the permanent element -- declared +// once, statically, in components/login-modal.html, never written by an +// innerHTML re-render -- into the exact same session-establishment path every +// other sign-in method uses (AuthService.requestLogin -> handleAuthLogin). +// BitLogin isn't a single button-click-then-await-a-promise flow like the +// other providers, it's a whole multi-screen sign-in/create/recover UI, so it +// gets its own widget in the modal instead of a grid button (see +// providersForModal in js/services/authProviders/index.js) and its own small +// integration module here rather than special-casing LoginModalController. +import { devLogger } from "../utils/logger.js"; +import { closeStaticModal } from "./components/staticModalAccessibility.js"; +import { setModalState as setGlobalModalState } from "../state/appState.js"; +import { createBitloginAdapter } from "../nostr/adapters/bitloginAdapter.js"; +import { setPendingBitloginResult } from "../services/authProviders/bitlogin.js"; +import { FEATURE_BITLOGIN } from "../constants.js"; + +// Vendored, pinned BitLogin widget bundle (scripts/build-bitlogin-widget.mjs). +// Lazy-imported so its ~350KB never weighs on the main bundle for visitors who +// never open the login modal, mirroring the existing Bitcoin Connect vendor +// step (js/ui/profileModal/ProfileWalletController.js). A plain dynamic +// import is enough: the bundle's only job is the customElements.define("bitlogin-auth") +// side effect, which retroactively upgrades the already-present +// tag in the modal's static HTML once it resolves. +const BITLOGIN_WIDGET_BUNDLE_URL = "../../vendor/bitlogin/bitlogin.js"; + +let widgetLoadPromise = null; + +function loadBitloginWidgetOnce() { + if (!widgetLoadPromise) { + widgetLoadPromise = import(BITLOGIN_WIDGET_BUNDLE_URL).catch((error) => { + widgetLoadPromise = null; + throw error; + }); + } + return widgetLoadPromise; +} + +function closeLoginModal() { + const modal = document.getElementById("loginModal"); + if (modal && closeStaticModal(modal)) { + setGlobalModalState("login", false); + } +} + +function attachWidget(app, widget) { + const mount = document.getElementById("bitloginMount"); + if (!FEATURE_BITLOGIN) { + // Unstable-branch experiment (AGENTS.md §1, config/instance-config.js) -- + // leave the permanent, statically-declared markup in place but never load + // the vendored bundle or show the (otherwise-empty, unupgraded) element. + if (mount instanceof HTMLElement) { + mount.hidden = true; + } + return; + } + if (mount instanceof HTMLElement) { + mount.hidden = false; + } + + loadBitloginWidgetOnce().catch((error) => { + devLogger.warn("[BitLogin] Failed to load the widget bundle:", error); + }); + + widget.addEventListener("bitlogin-login", async (event) => { + const pubkey = + event?.detail && typeof event.detail.publicKey === "string" + ? event.detail.publicKey.trim() + : ""; + if (!pubkey) { + return; + } + + setPendingBitloginResult({ + pubkey, + signer: createBitloginAdapter(widget, pubkey), + }); + + try { + await app.authService.requestLogin({ providerId: "bitlogin" }); + closeLoginModal(); + } catch (error) { + devLogger.warn("[BitLogin] Sign-in failed to apply:", error); + } + }); +} + +/** + * Call once during app bootstrap, after `app.authService` exists. The login + * modal's HTML (including the permanent #bitloginWidget element) loads + * asynchronously (js/index.js bootstrapInterface()) and isn't guaranteed to be + * in the DOM yet at this point, so this waits for it rather than requiring a + * specific call order between the two. + * @param {{ authService: { requestLogin: Function } }} app + */ +export function wireBitloginLogin(app) { + if (!app?.authService) { + return; + } + + const existing = document.getElementById("bitloginWidget"); + if (existing instanceof HTMLElement) { + attachWidget(app, existing); + return; + } + + const observer = new MutationObserver(() => { + const widget = document.getElementById("bitloginWidget"); + if (widget instanceof HTMLElement) { + observer.disconnect(); + attachWidget(app, widget); + } + }); + observer.observe(document.body, { childList: true, subtree: true }); +} diff --git a/scripts/build-bitlogin-widget.mjs b/scripts/build-bitlogin-widget.mjs new file mode 100644 index 00000000..8377a4c2 --- /dev/null +++ b/scripts/build-bitlogin-widget.mjs @@ -0,0 +1,68 @@ +// Vendor the sibling @bitlogin/widget build into a pinned, same-origin bundle. +// +// bitvid's CSP is script-src 'self' (plus a couple of pinned CDN fallbacks for +// nostr-tools) -- the same reasoning as the existing bitcoin-connect/blossom-sdk +// vendor steps. Unlike those, BitLogin ships its own Vite-built ESM output +// directly (bitlogin.js + cryptoWorker.js + a shared chunk they both import), +// so this script copies that output verbatim instead of re-bundling it with +// esbuild -- the worker's relative self-URL resolution depends on the three +// files staying exactly as built and sitting side by side (see BitRoad's and +// BitUnlock's identical vendor steps for this same reasoning). +// +// node scripts/build-bitlogin-widget.mjs +// BITLOGIN_ENTRY=/path/to/bitlogin node scripts/build-bitlogin-widget.mjs + +import { createHash } from "node:crypto"; +import { copyFile, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises"; +import { existsSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { execSync } from "node:child_process"; + +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const bitloginRoot = process.env.BITLOGIN_ENTRY + ? path.resolve(process.env.BITLOGIN_ENTRY) + : path.resolve(repoRoot, "../bitlogin"); +const widgetDir = path.join(bitloginRoot, "packages/widget"); +const widgetDist = path.join(widgetDir, "dist"); +const vendorDir = path.join(repoRoot, "vendor/bitlogin"); +const integrityFile = path.join(repoRoot, "vendor/bitlogin.integrity.json"); + +const packageJson = JSON.parse(await readFile(path.join(widgetDir, "package.json"), "utf8")); +if (packageJson.name !== "@bitlogin/widget") { + throw new Error("BITLOGIN_ENTRY must point to a BitLogin checkout (packages/widget/package.json not found there)."); +} + +if (!existsSync(widgetDist)) { + console.log("[build-bitlogin-widget] dist missing, building @bitlogin/core then @bitlogin/widget first..."); + execSync("npm run build -w @bitlogin/core", { cwd: bitloginRoot, stdio: "inherit" }); + execSync("npm run build -w @bitlogin/widget", { cwd: bitloginRoot, stdio: "inherit" }); +} + +await rm(vendorDir, { recursive: true, force: true }); +await mkdir(vendorDir, { recursive: true }); + +const distEntries = (await readdir(widgetDist)).filter((name) => name.endsWith(".js")); +if (!distEntries.includes("bitlogin.js") || !distEntries.includes("cryptoWorker.js")) { + throw new Error("Expected bitlogin.js and cryptoWorker.js in @bitlogin/widget dist -- did the build layout change?"); +} + +const files = {}; +for (const name of distEntries) { + await copyFile(path.join(widgetDist, name), path.join(vendorDir, name)); + const bytes = await readFile(path.join(widgetDist, name)); + files[name] = { sha256: createHash("sha256").update(bytes).digest("hex"), bytes: bytes.byteLength }; +} + +await writeFile( + integrityFile, + `${JSON.stringify({ package: packageJson.name, version: packageJson.version, files }, null, 2)}\n`, +); + +try { + await copyFile(path.join(bitloginRoot, "LICENSE"), path.join(repoRoot, "vendor/bitlogin.LICENSE")); +} catch (error) { + console.warn("[build-bitlogin-widget] could not copy LICENSE:", error.message); +} + +console.log("[build-bitlogin-widget] wrote", path.relative(repoRoot, vendorDir), `(${distEntries.length} files)`); diff --git a/tests/auth-providers-bitlogin.test.mjs b/tests/auth-providers-bitlogin.test.mjs new file mode 100644 index 00000000..938f781e --- /dev/null +++ b/tests/auth-providers-bitlogin.test.mjs @@ -0,0 +1,146 @@ +import "./test-helpers/setup-localstorage.mjs"; +import assert from "node:assert/strict"; +import { describe, it, beforeEach, afterEach } from "node:test"; + +import { + providers, + providersForModal, +} from "../js/services/authProviders/index.js"; +import bitloginProvider, { + setPendingBitloginResult, +} from "../js/services/authProviders/bitlogin.js"; +import { createBitloginAdapter } from "../js/nostr/adapters/bitloginAdapter.js"; +import { accessControl } from "../js/accessControl.js"; + +const HEX_PUBKEY = "a".repeat(64); + +describe("BitLogin auth provider", () => { + const originalCanAccess = accessControl.canAccess; + const originalIsBlacklisted = accessControl.isBlacklisted; + + afterEach(() => { + setPendingBitloginResult(null); + accessControl.canAccess = originalCanAccess; + accessControl.isBlacklisted = originalIsBlacklisted; + }); + + it("registers in the resolvable provider registry but not the modal grid", () => { + // AuthService.resolveAuthProvider() must be able to find "bitlogin" ... + assert.equal(providers.bitlogin, bitloginProvider); + // ... but the login modal's grid (LoginModalController) must never render + // a redundant button for it -- BitLogin gets its own permanent widget in + // components/login-modal.html instead. + assert.equal(providersForModal.bitlogin, undefined); + assert.equal(providersForModal.nip07, providers.nip07); + }); + + it("refuses to log in before the widget has actually produced a pubkey", async () => { + accessControl.canAccess = () => true; + setPendingBitloginResult(null); + + await assert.rejects( + () => bitloginProvider.login({ nostrClient: {} }), + /hasn't completed yet/i, + ); + }); + + it("activates the signer and resolves once the widget's result is pending", async () => { + accessControl.canAccess = () => true; + let activated = null; + const fakeSigner = { type: "bitlogin", pubkey: HEX_PUBKEY }; + const fakeNostrClient = { + signerManager: { + setActiveSigner: (signer) => { + activated = signer; + }, + }, + }; + + setPendingBitloginResult({ pubkey: HEX_PUBKEY, signer: fakeSigner }); + + const result = await bitloginProvider.login({ nostrClient: fakeNostrClient }); + + assert.equal(result.authType, "bitlogin"); + assert.equal(result.pubkey, HEX_PUBKEY); + assert.equal(result.signer, fakeSigner); + assert.equal(activated, fakeSigner); + }); + + it("consumes the pending result exactly once (no replay across calls)", async () => { + accessControl.canAccess = () => true; + const fakeNostrClient = { signerManager: { setActiveSigner: () => {} } }; + setPendingBitloginResult({ pubkey: HEX_PUBKEY, signer: {} }); + + await bitloginProvider.login({ nostrClient: fakeNostrClient }); + + await assert.rejects( + () => bitloginProvider.login({ nostrClient: fakeNostrClient }), + /hasn't completed yet/i, + ); + }); + + it("never activates a signer for a blacklisted pubkey", async () => { + accessControl.canAccess = () => false; + accessControl.isBlacklisted = () => true; + let activated = null; + const fakeNostrClient = { + signerManager: { + setActiveSigner: (signer) => { + activated = signer; + }, + }, + }; + + setPendingBitloginResult({ pubkey: HEX_PUBKEY, signer: { type: "bitlogin" } }); + + await assert.rejects( + () => bitloginProvider.login({ nostrClient: fakeNostrClient }), + /blocked/i, + ); + assert.equal(activated, null); + }); +}); + +describe("createBitloginAdapter", () => { + it("delegates signing and NIP-44 calls to the live widget element, never window.nostr", async () => { + const calls = []; + const fakeWidget = { + signEvent: async (event) => { + calls.push(["signEvent", event]); + return { ...event, id: "signed" }; + }, + nip44Encrypt: async (peer, plaintext) => { + calls.push(["nip44Encrypt", peer, plaintext]); + return "ciphertext"; + }, + nip44Decrypt: async (peer, payload) => { + calls.push(["nip44Decrypt", peer, payload]); + return "plaintext"; + }, + logout: async () => { + calls.push(["logout"]); + }, + }; + + const adapter = createBitloginAdapter(fakeWidget, HEX_PUBKEY); + + assert.equal(adapter.type, "bitlogin"); + assert.equal(adapter.pubkey, HEX_PUBKEY); + assert.equal(adapter.canSign(), true); + assert.deepEqual(adapter.capabilities, { sign: true, nip44: true, nip04: false }); + + const signed = await adapter.signEvent({ kind: 1, content: "hi" }); + assert.equal(signed.id, "signed"); + + await adapter.nip44Encrypt("peer-pubkey", "hello"); + await adapter.nip44Decrypt("peer-pubkey", "ciphertext"); + await adapter.destroy(); + + assert.deepEqual(calls, [ + ["signEvent", { kind: 1, content: "hi" }], + ["nip44Encrypt", "peer-pubkey", "hello"], + ["nip44Decrypt", "peer-pubkey", "ciphertext"], + ["logout"], + ]); + }); +}); diff --git a/vendor/bitlogin.LICENSE b/vendor/bitlogin.LICENSE new file mode 100644 index 00000000..3e927039 --- /dev/null +++ b/vendor/bitlogin.LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 PR0M3TH3AN + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/bitlogin.integrity.json b/vendor/bitlogin.integrity.json new file mode 100644 index 00000000..23dd37c9 --- /dev/null +++ b/vendor/bitlogin.integrity.json @@ -0,0 +1,18 @@ +{ + "package": "@bitlogin/widget", + "version": "0.1.0", + "files": { + "bitlogin-shared-QIBe5Omw.js": { + "sha256": "7ce4ed0a5c3c7f744e864f55745f7fa78482cbfa19cd30eb551f67a415f55191", + "bytes": 288275 + }, + "bitlogin.js": { + "sha256": "7bbe34092ff5c110d947ac4cec7500cd32824868e51118387566896660a31228", + "bytes": 65009 + }, + "cryptoWorker.js": { + "sha256": "31e2b32cbbb8a4223d6664d383b6de49a173406e14a409a4cf192be53ed9dd74", + "bytes": 64803 + } + } +} diff --git a/vendor/bitlogin/bitlogin-shared-QIBe5Omw.js b/vendor/bitlogin/bitlogin-shared-QIBe5Omw.js new file mode 100644 index 00000000..8f88c18b --- /dev/null +++ b/vendor/bitlogin/bitlogin-shared-QIBe5Omw.js @@ -0,0 +1,10837 @@ +function Kr(e) { + return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e; +} +var yt, or; +function En() { + return or || (or = 1, yt = { + 11111: "abacus", + 11112: "abdomen", + 11113: "abdominal", + 11114: "abide", + 11115: "abiding", + 11116: "ability", + 11121: "ablaze", + 11122: "able", + 11123: "abnormal", + 11124: "abrasion", + 11125: "abrasive", + 11126: "abreast", + 11131: "abridge", + 11132: "abroad", + 11133: "abruptly", + 11134: "absence", + 11135: "absentee", + 11136: "absently", + 11141: "absinthe", + 11142: "absolute", + 11143: "absolve", + 11144: "abstain", + 11145: "abstract", + 11146: "absurd", + 11151: "accent", + 11152: "acclaim", + 11153: "acclimate", + 11154: "accompany", + 11155: "account", + 11156: "accuracy", + 11161: "accurate", + 11162: "accustom", + 11163: "acetone", + 11164: "achiness", + 11165: "aching", + 11166: "acid", + 11211: "acorn", + 11212: "acquaint", + 11213: "acquire", + 11214: "acre", + 11215: "acrobat", + 11216: "acronym", + 11221: "acting", + 11222: "action", + 11223: "activate", + 11224: "activator", + 11225: "active", + 11226: "activism", + 11231: "activist", + 11232: "activity", + 11233: "actress", + 11234: "acts", + 11235: "acutely", + 11236: "acuteness", + 11241: "aeration", + 11242: "aerobics", + 11243: "aerosol", + 11244: "aerospace", + 11245: "afar", + 11246: "affair", + 11251: "affected", + 11252: "affecting", + 11253: "affection", + 11254: "affidavit", + 11255: "affiliate", + 11256: "affirm", + 11261: "affix", + 11262: "afflicted", + 11263: "affluent", + 11264: "afford", + 11265: "affront", + 11266: "aflame", + 11311: "afloat", + 11312: "aflutter", + 11313: "afoot", + 11314: "afraid", + 11315: "afterglow", + 11316: "afterlife", + 11321: "aftermath", + 11322: "aftermost", + 11323: "afternoon", + 11324: "aged", + 11325: "ageless", + 11326: "agency", + 11331: "agenda", + 11332: "agent", + 11333: "aggregate", + 11334: "aghast", + 11335: "agile", + 11336: "agility", + 11341: "aging", + 11342: "agnostic", + 11343: "agonize", + 11344: "agonizing", + 11345: "agony", + 11346: "agreeable", + 11351: "agreeably", + 11352: "agreed", + 11353: "agreeing", + 11354: "agreement", + 11355: "aground", + 11356: "ahead", + 11361: "ahoy", + 11362: "aide", + 11363: "aids", + 11364: "aim", + 11365: "ajar", + 11366: "alabaster", + 11411: "alarm", + 11412: "albatross", + 11413: "album", + 11414: "alfalfa", + 11415: "algebra", + 11416: "algorithm", + 11421: "alias", + 11422: "alibi", + 11423: "alienable", + 11424: "alienate", + 11425: "aliens", + 11426: "alike", + 11431: "alive", + 11432: "alkaline", + 11433: "alkalize", + 11434: "almanac", + 11435: "almighty", + 11436: "almost", + 11441: "aloe", + 11442: "aloft", + 11443: "aloha", + 11444: "alone", + 11445: "alongside", + 11446: "aloof", + 11451: "alphabet", + 11452: "alright", + 11453: "although", + 11454: "altitude", + 11455: "alto", + 11456: "aluminum", + 11461: "alumni", + 11462: "always", + 11463: "amaretto", + 11464: "amaze", + 11465: "amazingly", + 11466: "amber", + 11511: "ambiance", + 11512: "ambiguity", + 11513: "ambiguous", + 11514: "ambition", + 11515: "ambitious", + 11516: "ambulance", + 11521: "ambush", + 11522: "amendable", + 11523: "amendment", + 11524: "amends", + 11525: "amenity", + 11526: "amiable", + 11531: "amicably", + 11532: "amid", + 11533: "amigo", + 11534: "amino", + 11535: "amiss", + 11536: "ammonia", + 11541: "ammonium", + 11542: "amnesty", + 11543: "amniotic", + 11544: "among", + 11545: "amount", + 11546: "amperage", + 11551: "ample", + 11552: "amplifier", + 11553: "amplify", + 11554: "amply", + 11555: "amuck", + 11556: "amulet", + 11561: "amusable", + 11562: "amused", + 11563: "amusement", + 11564: "amuser", + 11565: "amusing", + 11566: "anaconda", + 11611: "anaerobic", + 11612: "anagram", + 11613: "anatomist", + 11614: "anatomy", + 11615: "anchor", + 11616: "anchovy", + 11621: "ancient", + 11622: "android", + 11623: "anemia", + 11624: "anemic", + 11625: "aneurism", + 11626: "anew", + 11631: "angelfish", + 11632: "angelic", + 11633: "anger", + 11634: "angled", + 11635: "angler", + 11636: "angles", + 11641: "angling", + 11642: "angrily", + 11643: "angriness", + 11644: "anguished", + 11645: "angular", + 11646: "animal", + 11651: "animate", + 11652: "animating", + 11653: "animation", + 11654: "animator", + 11655: "anime", + 11656: "animosity", + 11661: "ankle", + 11662: "annex", + 11663: "annotate", + 11664: "announcer", + 11665: "annoying", + 11666: "annually", + 12111: "annuity", + 12112: "anointer", + 12113: "another", + 12114: "answering", + 12115: "antacid", + 12116: "antarctic", + 12121: "anteater", + 12122: "antelope", + 12123: "antennae", + 12124: "anthem", + 12125: "anthill", + 12126: "anthology", + 12131: "antibody", + 12132: "antics", + 12133: "antidote", + 12134: "antihero", + 12135: "antiquely", + 12136: "antiques", + 12141: "antiquity", + 12142: "antirust", + 12143: "antitoxic", + 12144: "antitrust", + 12145: "antiviral", + 12146: "antivirus", + 12151: "antler", + 12152: "antonym", + 12153: "antsy", + 12154: "anvil", + 12155: "anybody", + 12156: "anyhow", + 12161: "anymore", + 12162: "anyone", + 12163: "anyplace", + 12164: "anything", + 12165: "anytime", + 12166: "anyway", + 12211: "anywhere", + 12212: "aorta", + 12213: "apache", + 12214: "apostle", + 12215: "appealing", + 12216: "appear", + 12221: "appease", + 12222: "appeasing", + 12223: "appendage", + 12224: "appendix", + 12225: "appetite", + 12226: "appetizer", + 12231: "applaud", + 12232: "applause", + 12233: "apple", + 12234: "appliance", + 12235: "applicant", + 12236: "applied", + 12241: "apply", + 12242: "appointee", + 12243: "appraisal", + 12244: "appraiser", + 12245: "apprehend", + 12246: "approach", + 12251: "approval", + 12252: "approve", + 12253: "apricot", + 12254: "april", + 12255: "apron", + 12256: "aptitude", + 12261: "aptly", + 12262: "aqua", + 12263: "aqueduct", + 12264: "arbitrary", + 12265: "arbitrate", + 12266: "ardently", + 12311: "area", + 12312: "arena", + 12313: "arguable", + 12314: "arguably", + 12315: "argue", + 12316: "arise", + 12321: "armadillo", + 12322: "armband", + 12323: "armchair", + 12324: "armed", + 12325: "armful", + 12326: "armhole", + 12331: "arming", + 12332: "armless", + 12333: "armoire", + 12334: "armored", + 12335: "armory", + 12336: "armrest", + 12341: "army", + 12342: "aroma", + 12343: "arose", + 12344: "around", + 12345: "arousal", + 12346: "arrange", + 12351: "array", + 12352: "arrest", + 12353: "arrival", + 12354: "arrive", + 12355: "arrogance", + 12356: "arrogant", + 12361: "arson", + 12362: "art", + 12363: "ascend", + 12364: "ascension", + 12365: "ascent", + 12366: "ascertain", + 12411: "ashamed", + 12412: "ashen", + 12413: "ashes", + 12414: "ashy", + 12415: "aside", + 12416: "askew", + 12421: "asleep", + 12422: "asparagus", + 12423: "aspect", + 12424: "aspirate", + 12425: "aspire", + 12426: "aspirin", + 12431: "astonish", + 12432: "astound", + 12433: "astride", + 12434: "astrology", + 12435: "astronaut", + 12436: "astronomy", + 12441: "astute", + 12442: "atlantic", + 12443: "atlas", + 12444: "atom", + 12445: "atonable", + 12446: "atop", + 12451: "atrium", + 12452: "atrocious", + 12453: "atrophy", + 12454: "attach", + 12455: "attain", + 12456: "attempt", + 12461: "attendant", + 12462: "attendee", + 12463: "attention", + 12464: "attentive", + 12465: "attest", + 12466: "attic", + 12511: "attire", + 12512: "attitude", + 12513: "attractor", + 12514: "attribute", + 12515: "atypical", + 12516: "auction", + 12521: "audacious", + 12522: "audacity", + 12523: "audible", + 12524: "audibly", + 12525: "audience", + 12526: "audio", + 12531: "audition", + 12532: "augmented", + 12533: "august", + 12534: "authentic", + 12535: "author", + 12536: "autism", + 12541: "autistic", + 12542: "autograph", + 12543: "automaker", + 12544: "automated", + 12545: "automatic", + 12546: "autopilot", + 12551: "available", + 12552: "avalanche", + 12553: "avatar", + 12554: "avenge", + 12555: "avenging", + 12556: "avenue", + 12561: "average", + 12562: "aversion", + 12563: "avert", + 12564: "aviation", + 12565: "aviator", + 12566: "avid", + 12611: "avoid", + 12612: "await", + 12613: "awaken", + 12614: "award", + 12615: "aware", + 12616: "awhile", + 12621: "awkward", + 12622: "awning", + 12623: "awoke", + 12624: "awry", + 12625: "axis", + 12626: "babble", + 12631: "babbling", + 12632: "babied", + 12633: "baboon", + 12634: "backache", + 12635: "backboard", + 12636: "backboned", + 12641: "backdrop", + 12642: "backed", + 12643: "backer", + 12644: "backfield", + 12645: "backfire", + 12646: "backhand", + 12651: "backing", + 12652: "backlands", + 12653: "backlash", + 12654: "backless", + 12655: "backlight", + 12656: "backlit", + 12661: "backlog", + 12662: "backpack", + 12663: "backpedal", + 12664: "backrest", + 12665: "backroom", + 12666: "backshift", + 13111: "backside", + 13112: "backslid", + 13113: "backspace", + 13114: "backspin", + 13115: "backstab", + 13116: "backstage", + 13121: "backtalk", + 13122: "backtrack", + 13123: "backup", + 13124: "backward", + 13125: "backwash", + 13126: "backwater", + 13131: "backyard", + 13132: "bacon", + 13133: "bacteria", + 13134: "bacterium", + 13135: "badass", + 13136: "badge", + 13141: "badland", + 13142: "badly", + 13143: "badness", + 13144: "baffle", + 13145: "baffling", + 13146: "bagel", + 13151: "bagful", + 13152: "baggage", + 13153: "bagged", + 13154: "baggie", + 13155: "bagginess", + 13156: "bagging", + 13161: "baggy", + 13162: "bagpipe", + 13163: "baguette", + 13164: "baked", + 13165: "bakery", + 13166: "bakeshop", + 13211: "baking", + 13212: "balance", + 13213: "balancing", + 13214: "balcony", + 13215: "balmy", + 13216: "balsamic", + 13221: "bamboo", + 13222: "banana", + 13223: "banish", + 13224: "banister", + 13225: "banjo", + 13226: "bankable", + 13231: "bankbook", + 13232: "banked", + 13233: "banker", + 13234: "banking", + 13235: "banknote", + 13236: "bankroll", + 13241: "banner", + 13242: "bannister", + 13243: "banshee", + 13244: "banter", + 13245: "barbecue", + 13246: "barbed", + 13251: "barbell", + 13252: "barber", + 13253: "barcode", + 13254: "barge", + 13255: "bargraph", + 13256: "barista", + 13261: "baritone", + 13262: "barley", + 13263: "barmaid", + 13264: "barman", + 13265: "barn", + 13266: "barometer", + 13311: "barrack", + 13312: "barracuda", + 13313: "barrel", + 13314: "barrette", + 13315: "barricade", + 13316: "barrier", + 13321: "barstool", + 13322: "bartender", + 13323: "barterer", + 13324: "bash", + 13325: "basically", + 13326: "basics", + 13331: "basil", + 13332: "basin", + 13333: "basis", + 13334: "basket", + 13335: "batboy", + 13336: "batch", + 13341: "bath", + 13342: "baton", + 13343: "bats", + 13344: "battalion", + 13345: "battered", + 13346: "battering", + 13351: "battery", + 13352: "batting", + 13353: "battle", + 13354: "bauble", + 13355: "bazooka", + 13356: "blabber", + 13361: "bladder", + 13362: "blade", + 13363: "blah", + 13364: "blame", + 13365: "blaming", + 13366: "blanching", + 13411: "blandness", + 13412: "blank", + 13413: "blaspheme", + 13414: "blasphemy", + 13415: "blast", + 13416: "blatancy", + 13421: "blatantly", + 13422: "blazer", + 13423: "blazing", + 13424: "bleach", + 13425: "bleak", + 13426: "bleep", + 13431: "blemish", + 13432: "blend", + 13433: "bless", + 13434: "blighted", + 13435: "blimp", + 13436: "bling", + 13441: "blinked", + 13442: "blinker", + 13443: "blinking", + 13444: "blinks", + 13445: "blip", + 13446: "blissful", + 13451: "blitz", + 13452: "blizzard", + 13453: "bloated", + 13454: "bloating", + 13455: "blob", + 13456: "blog", + 13461: "bloomers", + 13462: "blooming", + 13463: "blooper", + 13464: "blot", + 13465: "blouse", + 13466: "blubber", + 13511: "bluff", + 13512: "bluish", + 13513: "blunderer", + 13514: "blunt", + 13515: "blurb", + 13516: "blurred", + 13521: "blurry", + 13522: "blurt", + 13523: "blush", + 13524: "blustery", + 13525: "boaster", + 13526: "boastful", + 13531: "boasting", + 13532: "boat", + 13533: "bobbed", + 13534: "bobbing", + 13535: "bobble", + 13536: "bobcat", + 13541: "bobsled", + 13542: "bobtail", + 13543: "bodacious", + 13544: "body", + 13545: "bogged", + 13546: "boggle", + 13551: "bogus", + 13552: "boil", + 13553: "bok", + 13554: "bolster", + 13555: "bolt", + 13556: "bonanza", + 13561: "bonded", + 13562: "bonding", + 13563: "bondless", + 13564: "boned", + 13565: "bonehead", + 13566: "boneless", + 13611: "bonelike", + 13612: "boney", + 13613: "bonfire", + 13614: "bonnet", + 13615: "bonsai", + 13616: "bonus", + 13621: "bony", + 13622: "boogeyman", + 13623: "boogieman", + 13624: "book", + 13625: "boondocks", + 13626: "booted", + 13631: "booth", + 13632: "bootie", + 13633: "booting", + 13634: "bootlace", + 13635: "bootleg", + 13636: "boots", + 13641: "boozy", + 13642: "borax", + 13643: "boring", + 13644: "borough", + 13645: "borrower", + 13646: "borrowing", + 13651: "boss", + 13652: "botanical", + 13653: "botanist", + 13654: "botany", + 13655: "botch", + 13656: "both", + 13661: "bottle", + 13662: "bottling", + 13663: "bottom", + 13664: "bounce", + 13665: "bouncing", + 13666: "bouncy", + 14111: "bounding", + 14112: "boundless", + 14113: "bountiful", + 14114: "bovine", + 14115: "boxcar", + 14116: "boxer", + 14121: "boxing", + 14122: "boxlike", + 14123: "boxy", + 14124: "breach", + 14125: "breath", + 14126: "breeches", + 14131: "breeching", + 14132: "breeder", + 14133: "breeding", + 14134: "breeze", + 14135: "breezy", + 14136: "brethren", + 14141: "brewery", + 14142: "brewing", + 14143: "briar", + 14144: "bribe", + 14145: "brick", + 14146: "bride", + 14151: "bridged", + 14152: "brigade", + 14153: "bright", + 14154: "brilliant", + 14155: "brim", + 14156: "bring", + 14161: "brink", + 14162: "brisket", + 14163: "briskly", + 14164: "briskness", + 14165: "bristle", + 14166: "brittle", + 14211: "broadband", + 14212: "broadcast", + 14213: "broaden", + 14214: "broadly", + 14215: "broadness", + 14216: "broadside", + 14221: "broadways", + 14222: "broiler", + 14223: "broiling", + 14224: "broken", + 14225: "broker", + 14226: "bronchial", + 14231: "bronco", + 14232: "bronze", + 14233: "bronzing", + 14234: "brook", + 14235: "broom", + 14236: "brought", + 14241: "browbeat", + 14242: "brownnose", + 14243: "browse", + 14244: "browsing", + 14245: "bruising", + 14246: "brunch", + 14251: "brunette", + 14252: "brunt", + 14253: "brush", + 14254: "brussels", + 14255: "brute", + 14256: "brutishly", + 14261: "bubble", + 14262: "bubbling", + 14263: "bubbly", + 14264: "buccaneer", + 14265: "bucked", + 14266: "bucket", + 14311: "buckle", + 14312: "buckshot", + 14313: "buckskin", + 14314: "bucktooth", + 14315: "buckwheat", + 14316: "buddhism", + 14321: "buddhist", + 14322: "budding", + 14323: "buddy", + 14324: "budget", + 14325: "buffalo", + 14326: "buffed", + 14331: "buffer", + 14332: "buffing", + 14333: "buffoon", + 14334: "buggy", + 14335: "bulb", + 14336: "bulge", + 14341: "bulginess", + 14342: "bulgur", + 14343: "bulk", + 14344: "bulldog", + 14345: "bulldozer", + 14346: "bullfight", + 14351: "bullfrog", + 14352: "bullhorn", + 14353: "bullion", + 14354: "bullish", + 14355: "bullpen", + 14356: "bullring", + 14361: "bullseye", + 14362: "bullwhip", + 14363: "bully", + 14364: "bunch", + 14365: "bundle", + 14366: "bungee", + 14411: "bunion", + 14412: "bunkbed", + 14413: "bunkhouse", + 14414: "bunkmate", + 14415: "bunny", + 14416: "bunt", + 14421: "busboy", + 14422: "bush", + 14423: "busily", + 14424: "busload", + 14425: "bust", + 14426: "busybody", + 14431: "buzz", + 14432: "cabana", + 14433: "cabbage", + 14434: "cabbie", + 14435: "cabdriver", + 14436: "cable", + 14441: "caboose", + 14442: "cache", + 14443: "cackle", + 14444: "cacti", + 14445: "cactus", + 14446: "caddie", + 14451: "caddy", + 14452: "cadet", + 14453: "cadillac", + 14454: "cadmium", + 14455: "cage", + 14456: "cahoots", + 14461: "cake", + 14462: "calamari", + 14463: "calamity", + 14464: "calcium", + 14465: "calculate", + 14466: "calculus", + 14511: "caliber", + 14512: "calibrate", + 14513: "calm", + 14514: "caloric", + 14515: "calorie", + 14516: "calzone", + 14521: "camcorder", + 14522: "cameo", + 14523: "camera", + 14524: "camisole", + 14525: "camper", + 14526: "campfire", + 14531: "camping", + 14532: "campsite", + 14533: "campus", + 14534: "canal", + 14535: "canary", + 14536: "cancel", + 14541: "candied", + 14542: "candle", + 14543: "candy", + 14544: "cane", + 14545: "canine", + 14546: "canister", + 14551: "cannabis", + 14552: "canned", + 14553: "canning", + 14554: "cannon", + 14555: "cannot", + 14556: "canola", + 14561: "canon", + 14562: "canopener", + 14563: "canopy", + 14564: "canteen", + 14565: "canyon", + 14566: "capable", + 14611: "capably", + 14612: "capacity", + 14613: "cape", + 14614: "capillary", + 14615: "capital", + 14616: "capitol", + 14621: "capped", + 14622: "capricorn", + 14623: "capsize", + 14624: "capsule", + 14625: "caption", + 14626: "captivate", + 14631: "captive", + 14632: "captivity", + 14633: "capture", + 14634: "caramel", + 14635: "carat", + 14636: "caravan", + 14641: "carbon", + 14642: "cardboard", + 14643: "carded", + 14644: "cardiac", + 14645: "cardigan", + 14646: "cardinal", + 14651: "cardstock", + 14652: "carefully", + 14653: "caregiver", + 14654: "careless", + 14655: "caress", + 14656: "caretaker", + 14661: "cargo", + 14662: "caring", + 14663: "carless", + 14664: "carload", + 14665: "carmaker", + 14666: "carnage", + 15111: "carnation", + 15112: "carnival", + 15113: "carnivore", + 15114: "carol", + 15115: "carpenter", + 15116: "carpentry", + 15121: "carpool", + 15122: "carport", + 15123: "carried", + 15124: "carrot", + 15125: "carrousel", + 15126: "carry", + 15131: "cartel", + 15132: "cartload", + 15133: "carton", + 15134: "cartoon", + 15135: "cartridge", + 15136: "cartwheel", + 15141: "carve", + 15142: "carving", + 15143: "carwash", + 15144: "cascade", + 15145: "case", + 15146: "cash", + 15151: "casing", + 15152: "casino", + 15153: "casket", + 15154: "cassette", + 15155: "casually", + 15156: "casualty", + 15161: "catacomb", + 15162: "catalog", + 15163: "catalyst", + 15164: "catalyze", + 15165: "catapult", + 15166: "cataract", + 15211: "catatonic", + 15212: "catcall", + 15213: "catchable", + 15214: "catcher", + 15215: "catching", + 15216: "catchy", + 15221: "caterer", + 15222: "catering", + 15223: "catfight", + 15224: "catfish", + 15225: "cathedral", + 15226: "cathouse", + 15231: "catlike", + 15232: "catnap", + 15233: "catnip", + 15234: "catsup", + 15235: "cattail", + 15236: "cattishly", + 15241: "cattle", + 15242: "catty", + 15243: "catwalk", + 15244: "caucasian", + 15245: "caucus", + 15246: "causal", + 15251: "causation", + 15252: "cause", + 15253: "causing", + 15254: "cauterize", + 15255: "caution", + 15256: "cautious", + 15261: "cavalier", + 15262: "cavalry", + 15263: "caviar", + 15264: "cavity", + 15265: "cedar", + 15266: "celery", + 15311: "celestial", + 15312: "celibacy", + 15313: "celibate", + 15314: "celtic", + 15315: "cement", + 15316: "census", + 15321: "ceramics", + 15322: "ceremony", + 15323: "certainly", + 15324: "certainty", + 15325: "certified", + 15326: "certify", + 15331: "cesarean", + 15332: "cesspool", + 15333: "chafe", + 15334: "chaffing", + 15335: "chain", + 15336: "chair", + 15341: "chalice", + 15342: "challenge", + 15343: "chamber", + 15344: "chamomile", + 15345: "champion", + 15346: "chance", + 15351: "change", + 15352: "channel", + 15353: "chant", + 15354: "chaos", + 15355: "chaperone", + 15356: "chaplain", + 15361: "chapped", + 15362: "chaps", + 15363: "chapter", + 15364: "character", + 15365: "charbroil", + 15366: "charcoal", + 15411: "charger", + 15412: "charging", + 15413: "chariot", + 15414: "charity", + 15415: "charm", + 15416: "charred", + 15421: "charter", + 15422: "charting", + 15423: "chase", + 15424: "chasing", + 15425: "chaste", + 15426: "chastise", + 15431: "chastity", + 15432: "chatroom", + 15433: "chatter", + 15434: "chatting", + 15435: "chatty", + 15436: "cheating", + 15441: "cheddar", + 15442: "cheek", + 15443: "cheer", + 15444: "cheese", + 15445: "cheesy", + 15446: "chef", + 15451: "chemicals", + 15452: "chemist", + 15453: "chemo", + 15454: "cherisher", + 15455: "cherub", + 15456: "chess", + 15461: "chest", + 15462: "chevron", + 15463: "chevy", + 15464: "chewable", + 15465: "chewer", + 15466: "chewing", + 15511: "chewy", + 15512: "chief", + 15513: "chihuahua", + 15514: "childcare", + 15515: "childhood", + 15516: "childish", + 15521: "childless", + 15522: "childlike", + 15523: "chili", + 15524: "chill", + 15525: "chimp", + 15526: "chip", + 15531: "chirping", + 15532: "chirpy", + 15533: "chitchat", + 15534: "chivalry", + 15535: "chive", + 15536: "chloride", + 15541: "chlorine", + 15542: "choice", + 15543: "chokehold", + 15544: "choking", + 15545: "chomp", + 15546: "chooser", + 15551: "choosing", + 15552: "choosy", + 15553: "chop", + 15554: "chosen", + 15555: "chowder", + 15556: "chowtime", + 15561: "chrome", + 15562: "chubby", + 15563: "chuck", + 15564: "chug", + 15565: "chummy", + 15566: "chump", + 15611: "chunk", + 15612: "churn", + 15613: "chute", + 15614: "cider", + 15615: "cilantro", + 15616: "cinch", + 15621: "cinema", + 15622: "cinnamon", + 15623: "circle", + 15624: "circling", + 15625: "circular", + 15626: "circulate", + 15631: "circus", + 15632: "citable", + 15633: "citadel", + 15634: "citation", + 15635: "citizen", + 15636: "citric", + 15641: "citrus", + 15642: "city", + 15643: "civic", + 15644: "civil", + 15645: "clad", + 15646: "claim", + 15651: "clambake", + 15652: "clammy", + 15653: "clamor", + 15654: "clamp", + 15655: "clamshell", + 15656: "clang", + 15661: "clanking", + 15662: "clapped", + 15663: "clapper", + 15664: "clapping", + 15665: "clarify", + 15666: "clarinet", + 16111: "clarity", + 16112: "clash", + 16113: "clasp", + 16114: "class", + 16115: "clatter", + 16116: "clause", + 16121: "clavicle", + 16122: "claw", + 16123: "clay", + 16124: "clean", + 16125: "clear", + 16126: "cleat", + 16131: "cleaver", + 16132: "cleft", + 16133: "clench", + 16134: "clergyman", + 16135: "clerical", + 16136: "clerk", + 16141: "clever", + 16142: "clicker", + 16143: "client", + 16144: "climate", + 16145: "climatic", + 16146: "cling", + 16151: "clinic", + 16152: "clinking", + 16153: "clip", + 16154: "clique", + 16155: "cloak", + 16156: "clobber", + 16161: "clock", + 16162: "clone", + 16163: "cloning", + 16164: "closable", + 16165: "closure", + 16166: "clothes", + 16211: "clothing", + 16212: "cloud", + 16213: "clover", + 16214: "clubbed", + 16215: "clubbing", + 16216: "clubhouse", + 16221: "clump", + 16222: "clumsily", + 16223: "clumsy", + 16224: "clunky", + 16225: "clustered", + 16226: "clutch", + 16231: "clutter", + 16232: "coach", + 16233: "coagulant", + 16234: "coastal", + 16235: "coaster", + 16236: "coasting", + 16241: "coastland", + 16242: "coastline", + 16243: "coat", + 16244: "coauthor", + 16245: "cobalt", + 16246: "cobbler", + 16251: "cobweb", + 16252: "cocoa", + 16253: "coconut", + 16254: "cod", + 16255: "coeditor", + 16256: "coerce", + 16261: "coexist", + 16262: "coffee", + 16263: "cofounder", + 16264: "cognition", + 16265: "cognitive", + 16266: "cogwheel", + 16311: "coherence", + 16312: "coherent", + 16313: "cohesive", + 16314: "coil", + 16315: "coke", + 16316: "cola", + 16321: "cold", + 16322: "coleslaw", + 16323: "coliseum", + 16324: "collage", + 16325: "collapse", + 16326: "collar", + 16331: "collected", + 16332: "collector", + 16333: "collide", + 16334: "collie", + 16335: "collision", + 16336: "colonial", + 16341: "colonist", + 16342: "colonize", + 16343: "colony", + 16344: "colossal", + 16345: "colt", + 16346: "coma", + 16351: "come", + 16352: "comfort", + 16353: "comfy", + 16354: "comic", + 16355: "coming", + 16356: "comma", + 16361: "commence", + 16362: "commend", + 16363: "comment", + 16364: "commerce", + 16365: "commode", + 16366: "commodity", + 16411: "commodore", + 16412: "common", + 16413: "commotion", + 16414: "commute", + 16415: "commuting", + 16416: "compacted", + 16421: "compacter", + 16422: "compactly", + 16423: "compactor", + 16424: "companion", + 16425: "company", + 16426: "compare", + 16431: "compel", + 16432: "compile", + 16433: "comply", + 16434: "component", + 16435: "composed", + 16436: "composer", + 16441: "composite", + 16442: "compost", + 16443: "composure", + 16444: "compound", + 16445: "compress", + 16446: "comprised", + 16451: "computer", + 16452: "computing", + 16453: "comrade", + 16454: "concave", + 16455: "conceal", + 16456: "conceded", + 16461: "concept", + 16462: "concerned", + 16463: "concert", + 16464: "conch", + 16465: "concierge", + 16466: "concise", + 16511: "conclude", + 16512: "concrete", + 16513: "concur", + 16514: "condense", + 16515: "condiment", + 16516: "condition", + 16521: "condone", + 16522: "conducive", + 16523: "conductor", + 16524: "conduit", + 16525: "cone", + 16526: "confess", + 16531: "confetti", + 16532: "confidant", + 16533: "confident", + 16534: "confider", + 16535: "confiding", + 16536: "configure", + 16541: "confined", + 16542: "confining", + 16543: "confirm", + 16544: "conflict", + 16545: "conform", + 16546: "confound", + 16551: "confront", + 16552: "confused", + 16553: "confusing", + 16554: "confusion", + 16555: "congenial", + 16556: "congested", + 16561: "congrats", + 16562: "congress", + 16563: "conical", + 16564: "conjoined", + 16565: "conjure", + 16566: "conjuror", + 16611: "connected", + 16612: "connector", + 16613: "consensus", + 16614: "consent", + 16615: "console", + 16616: "consoling", + 16621: "consonant", + 16622: "constable", + 16623: "constant", + 16624: "constrain", + 16625: "constrict", + 16626: "construct", + 16631: "consult", + 16632: "consumer", + 16633: "consuming", + 16634: "contact", + 16635: "container", + 16636: "contempt", + 16641: "contend", + 16642: "contented", + 16643: "contently", + 16644: "contents", + 16645: "contest", + 16646: "context", + 16651: "contort", + 16652: "contour", + 16653: "contrite", + 16654: "control", + 16655: "contusion", + 16656: "convene", + 16661: "convent", + 16662: "copartner", + 16663: "cope", + 16664: "copied", + 16665: "copier", + 16666: "copilot", + 21111: "coping", + 21112: "copious", + 21113: "copper", + 21114: "copy", + 21115: "coral", + 21116: "cork", + 21121: "cornball", + 21122: "cornbread", + 21123: "corncob", + 21124: "cornea", + 21125: "corned", + 21126: "corner", + 21131: "cornfield", + 21132: "cornflake", + 21133: "cornhusk", + 21134: "cornmeal", + 21135: "cornstalk", + 21136: "corny", + 21141: "coronary", + 21142: "coroner", + 21143: "corporal", + 21144: "corporate", + 21145: "corral", + 21146: "correct", + 21151: "corridor", + 21152: "corrode", + 21153: "corroding", + 21154: "corrosive", + 21155: "corsage", + 21156: "corset", + 21161: "cortex", + 21162: "cosigner", + 21163: "cosmetics", + 21164: "cosmic", + 21165: "cosmos", + 21166: "cosponsor", + 21211: "cost", + 21212: "cottage", + 21213: "cotton", + 21214: "couch", + 21215: "cough", + 21216: "could", + 21221: "countable", + 21222: "countdown", + 21223: "counting", + 21224: "countless", + 21225: "country", + 21226: "county", + 21231: "courier", + 21232: "covenant", + 21233: "cover", + 21234: "coveted", + 21235: "coveting", + 21236: "coyness", + 21241: "cozily", + 21242: "coziness", + 21243: "cozy", + 21244: "crabbing", + 21245: "crabgrass", + 21246: "crablike", + 21251: "crabmeat", + 21252: "cradle", + 21253: "cradling", + 21254: "crafter", + 21255: "craftily", + 21256: "craftsman", + 21261: "craftwork", + 21262: "crafty", + 21263: "cramp", + 21264: "cranberry", + 21265: "crane", + 21266: "cranial", + 21311: "cranium", + 21312: "crank", + 21313: "crate", + 21314: "crave", + 21315: "craving", + 21316: "crawfish", + 21321: "crawlers", + 21322: "crawling", + 21323: "crayfish", + 21324: "crayon", + 21325: "crazed", + 21326: "crazily", + 21331: "craziness", + 21332: "crazy", + 21333: "creamed", + 21334: "creamer", + 21335: "creamlike", + 21336: "crease", + 21341: "creasing", + 21342: "creatable", + 21343: "create", + 21344: "creation", + 21345: "creative", + 21346: "creature", + 21351: "credible", + 21352: "credibly", + 21353: "credit", + 21354: "creed", + 21355: "creme", + 21356: "creole", + 21361: "crepe", + 21362: "crept", + 21363: "crescent", + 21364: "crested", + 21365: "cresting", + 21366: "crestless", + 21411: "crevice", + 21412: "crewless", + 21413: "crewman", + 21414: "crewmate", + 21415: "crib", + 21416: "cricket", + 21421: "cried", + 21422: "crier", + 21423: "crimp", + 21424: "crimson", + 21425: "cringe", + 21426: "cringing", + 21431: "crinkle", + 21432: "crinkly", + 21433: "crisped", + 21434: "crisping", + 21435: "crisply", + 21436: "crispness", + 21441: "crispy", + 21442: "criteria", + 21443: "critter", + 21444: "croak", + 21445: "crock", + 21446: "crook", + 21451: "croon", + 21452: "crop", + 21453: "cross", + 21454: "crouch", + 21455: "crouton", + 21456: "crowbar", + 21461: "crowd", + 21462: "crown", + 21463: "crucial", + 21464: "crudely", + 21465: "crudeness", + 21466: "cruelly", + 21511: "cruelness", + 21512: "cruelty", + 21513: "crumb", + 21514: "crummiest", + 21515: "crummy", + 21516: "crumpet", + 21521: "crumpled", + 21522: "cruncher", + 21523: "crunching", + 21524: "crunchy", + 21525: "crusader", + 21526: "crushable", + 21531: "crushed", + 21532: "crusher", + 21533: "crushing", + 21534: "crust", + 21535: "crux", + 21536: "crying", + 21541: "cryptic", + 21542: "crystal", + 21543: "cubbyhole", + 21544: "cube", + 21545: "cubical", + 21546: "cubicle", + 21551: "cucumber", + 21552: "cuddle", + 21553: "cuddly", + 21554: "cufflink", + 21555: "culinary", + 21556: "culminate", + 21561: "culpable", + 21562: "culprit", + 21563: "cultivate", + 21564: "cultural", + 21565: "culture", + 21566: "cupbearer", + 21611: "cupcake", + 21612: "cupid", + 21613: "cupped", + 21614: "cupping", + 21615: "curable", + 21616: "curator", + 21621: "curdle", + 21622: "cure", + 21623: "curfew", + 21624: "curing", + 21625: "curled", + 21626: "curler", + 21631: "curliness", + 21632: "curling", + 21633: "curly", + 21634: "curry", + 21635: "curse", + 21636: "cursive", + 21641: "cursor", + 21642: "curtain", + 21643: "curtly", + 21644: "curtsy", + 21645: "curvature", + 21646: "curve", + 21651: "curvy", + 21652: "cushy", + 21653: "cusp", + 21654: "cussed", + 21655: "custard", + 21656: "custodian", + 21661: "custody", + 21662: "customary", + 21663: "customer", + 21664: "customize", + 21665: "customs", + 21666: "cut", + 22111: "cycle", + 22112: "cyclic", + 22113: "cycling", + 22114: "cyclist", + 22115: "cylinder", + 22116: "cymbal", + 22121: "cytoplasm", + 22122: "cytoplast", + 22123: "dab", + 22124: "dad", + 22125: "daffodil", + 22126: "dagger", + 22131: "daily", + 22132: "daintily", + 22133: "dainty", + 22134: "dairy", + 22135: "daisy", + 22136: "dallying", + 22141: "dance", + 22142: "dancing", + 22143: "dandelion", + 22144: "dander", + 22145: "dandruff", + 22146: "dandy", + 22151: "danger", + 22152: "dangle", + 22153: "dangling", + 22154: "daredevil", + 22155: "dares", + 22156: "daringly", + 22161: "darkened", + 22162: "darkening", + 22163: "darkish", + 22164: "darkness", + 22165: "darkroom", + 22166: "darling", + 22211: "darn", + 22212: "dart", + 22213: "darwinism", + 22214: "dash", + 22215: "dastardly", + 22216: "data", + 22221: "datebook", + 22222: "dating", + 22223: "daughter", + 22224: "daunting", + 22225: "dawdler", + 22226: "dawn", + 22231: "daybed", + 22232: "daybreak", + 22233: "daycare", + 22234: "daydream", + 22235: "daylight", + 22236: "daylong", + 22241: "dayroom", + 22242: "daytime", + 22243: "dazzler", + 22244: "dazzling", + 22245: "deacon", + 22246: "deafening", + 22251: "deafness", + 22252: "dealer", + 22253: "dealing", + 22254: "dealmaker", + 22255: "dealt", + 22256: "dean", + 22261: "debatable", + 22262: "debate", + 22263: "debating", + 22264: "debit", + 22265: "debrief", + 22266: "debtless", + 22311: "debtor", + 22312: "debug", + 22313: "debunk", + 22314: "decade", + 22315: "decaf", + 22316: "decal", + 22321: "decathlon", + 22322: "decay", + 22323: "deceased", + 22324: "deceit", + 22325: "deceiver", + 22326: "deceiving", + 22331: "december", + 22332: "decency", + 22333: "decent", + 22334: "deception", + 22335: "deceptive", + 22336: "decibel", + 22341: "decidable", + 22342: "decimal", + 22343: "decimeter", + 22344: "decipher", + 22345: "deck", + 22346: "declared", + 22351: "decline", + 22352: "decode", + 22353: "decompose", + 22354: "decorated", + 22355: "decorator", + 22356: "decoy", + 22361: "decrease", + 22362: "decree", + 22363: "dedicate", + 22364: "dedicator", + 22365: "deduce", + 22366: "deduct", + 22411: "deed", + 22412: "deem", + 22413: "deepen", + 22414: "deeply", + 22415: "deepness", + 22416: "deface", + 22421: "defacing", + 22422: "defame", + 22423: "default", + 22424: "defeat", + 22425: "defection", + 22426: "defective", + 22431: "defendant", + 22432: "defender", + 22433: "defense", + 22434: "defensive", + 22435: "deferral", + 22436: "deferred", + 22441: "defiance", + 22442: "defiant", + 22443: "defile", + 22444: "defiling", + 22445: "define", + 22446: "definite", + 22451: "deflate", + 22452: "deflation", + 22453: "deflator", + 22454: "deflected", + 22455: "deflector", + 22456: "defog", + 22461: "deforest", + 22462: "defraud", + 22463: "defrost", + 22464: "deftly", + 22465: "defuse", + 22466: "defy", + 22511: "degraded", + 22512: "degrading", + 22513: "degrease", + 22514: "degree", + 22515: "dehydrate", + 22516: "deity", + 22521: "dejected", + 22522: "delay", + 22523: "delegate", + 22524: "delegator", + 22525: "delete", + 22526: "deletion", + 22531: "delicacy", + 22532: "delicate", + 22533: "delicious", + 22534: "delighted", + 22535: "delirious", + 22536: "delirium", + 22541: "deliverer", + 22542: "delivery", + 22543: "delouse", + 22544: "delta", + 22545: "deluge", + 22546: "delusion", + 22551: "deluxe", + 22552: "demanding", + 22553: "demeaning", + 22554: "demeanor", + 22555: "demise", + 22556: "democracy", + 22561: "democrat", + 22562: "demote", + 22563: "demotion", + 22564: "demystify", + 22565: "denatured", + 22566: "deniable", + 22611: "denial", + 22612: "denim", + 22613: "denote", + 22614: "dense", + 22615: "density", + 22616: "dental", + 22621: "dentist", + 22622: "denture", + 22623: "deny", + 22624: "deodorant", + 22625: "deodorize", + 22626: "departed", + 22631: "departure", + 22632: "depict", + 22633: "deplete", + 22634: "depletion", + 22635: "deplored", + 22636: "deploy", + 22641: "deport", + 22642: "depose", + 22643: "depraved", + 22644: "depravity", + 22645: "deprecate", + 22646: "depress", + 22651: "deprive", + 22652: "depth", + 22653: "deputize", + 22654: "deputy", + 22655: "derail", + 22656: "deranged", + 22661: "derby", + 22662: "derived", + 22663: "desecrate", + 22664: "deserve", + 22665: "deserving", + 22666: "designate", + 23111: "designed", + 23112: "designer", + 23113: "designing", + 23114: "deskbound", + 23115: "desktop", + 23116: "deskwork", + 23121: "desolate", + 23122: "despair", + 23123: "despise", + 23124: "despite", + 23125: "destiny", + 23126: "destitute", + 23131: "destruct", + 23132: "detached", + 23133: "detail", + 23134: "detection", + 23135: "detective", + 23136: "detector", + 23141: "detention", + 23142: "detergent", + 23143: "detest", + 23144: "detonate", + 23145: "detonator", + 23146: "detoxify", + 23151: "detract", + 23152: "deuce", + 23153: "devalue", + 23154: "deviancy", + 23155: "deviant", + 23156: "deviate", + 23161: "deviation", + 23162: "deviator", + 23163: "device", + 23164: "devious", + 23165: "devotedly", + 23166: "devotee", + 23211: "devotion", + 23212: "devourer", + 23213: "devouring", + 23214: "devoutly", + 23215: "dexterity", + 23216: "dexterous", + 23221: "diabetes", + 23222: "diabetic", + 23223: "diabolic", + 23224: "diagnoses", + 23225: "diagnosis", + 23226: "diagram", + 23231: "dial", + 23232: "diameter", + 23233: "diaper", + 23234: "diaphragm", + 23235: "diary", + 23236: "dice", + 23241: "dicing", + 23242: "dictate", + 23243: "dictation", + 23244: "dictator", + 23245: "difficult", + 23246: "diffused", + 23251: "diffuser", + 23252: "diffusion", + 23253: "diffusive", + 23254: "dig", + 23255: "dilation", + 23256: "diligence", + 23261: "diligent", + 23262: "dill", + 23263: "dilute", + 23264: "dime", + 23265: "diminish", + 23266: "dimly", + 23311: "dimmed", + 23312: "dimmer", + 23313: "dimness", + 23314: "dimple", + 23315: "diner", + 23316: "dingbat", + 23321: "dinghy", + 23322: "dinginess", + 23323: "dingo", + 23324: "dingy", + 23325: "dining", + 23326: "dinner", + 23331: "diocese", + 23332: "dioxide", + 23333: "diploma", + 23334: "dipped", + 23335: "dipper", + 23336: "dipping", + 23341: "directed", + 23342: "direction", + 23343: "directive", + 23344: "directly", + 23345: "directory", + 23346: "direness", + 23351: "dirtiness", + 23352: "disabled", + 23353: "disagree", + 23354: "disallow", + 23355: "disarm", + 23356: "disarray", + 23361: "disaster", + 23362: "disband", + 23363: "disbelief", + 23364: "disburse", + 23365: "discard", + 23366: "discern", + 23411: "discharge", + 23412: "disclose", + 23413: "discolor", + 23414: "discount", + 23415: "discourse", + 23416: "discover", + 23421: "discuss", + 23422: "disdain", + 23423: "disengage", + 23424: "disfigure", + 23425: "disgrace", + 23426: "dish", + 23431: "disinfect", + 23432: "disjoin", + 23433: "disk", + 23434: "dislike", + 23435: "disliking", + 23436: "dislocate", + 23441: "dislodge", + 23442: "disloyal", + 23443: "dismantle", + 23444: "dismay", + 23445: "dismiss", + 23446: "dismount", + 23451: "disobey", + 23452: "disorder", + 23453: "disown", + 23454: "disparate", + 23455: "disparity", + 23456: "dispatch", + 23461: "dispense", + 23462: "dispersal", + 23463: "dispersed", + 23464: "disperser", + 23465: "displace", + 23466: "display", + 23511: "displease", + 23512: "disposal", + 23513: "dispose", + 23514: "disprove", + 23515: "dispute", + 23516: "disregard", + 23521: "disrupt", + 23522: "dissuade", + 23523: "distance", + 23524: "distant", + 23525: "distaste", + 23526: "distill", + 23531: "distinct", + 23532: "distort", + 23533: "distract", + 23534: "distress", + 23535: "district", + 23536: "distrust", + 23541: "ditch", + 23542: "ditto", + 23543: "ditzy", + 23544: "dividable", + 23545: "divided", + 23546: "dividend", + 23551: "dividers", + 23552: "dividing", + 23553: "divinely", + 23554: "diving", + 23555: "divinity", + 23556: "divisible", + 23561: "divisibly", + 23562: "division", + 23563: "divisive", + 23564: "divorcee", + 23565: "dizziness", + 23566: "dizzy", + 23611: "doable", + 23612: "docile", + 23613: "dock", + 23614: "doctrine", + 23615: "document", + 23616: "dodge", + 23621: "dodgy", + 23622: "doily", + 23623: "doing", + 23624: "dole", + 23625: "dollar", + 23626: "dollhouse", + 23631: "dollop", + 23632: "dolly", + 23633: "dolphin", + 23634: "domain", + 23635: "domelike", + 23636: "domestic", + 23641: "dominion", + 23642: "dominoes", + 23643: "donated", + 23644: "donation", + 23645: "donator", + 23646: "donor", + 23651: "donut", + 23652: "doodle", + 23653: "doorbell", + 23654: "doorframe", + 23655: "doorknob", + 23656: "doorman", + 23661: "doormat", + 23662: "doornail", + 23663: "doorpost", + 23664: "doorstep", + 23665: "doorstop", + 23666: "doorway", + 24111: "doozy", + 24112: "dork", + 24113: "dormitory", + 24114: "dorsal", + 24115: "dosage", + 24116: "dose", + 24121: "dotted", + 24122: "doubling", + 24123: "douche", + 24124: "dove", + 24125: "down", + 24126: "dowry", + 24131: "doze", + 24132: "drab", + 24133: "dragging", + 24134: "dragonfly", + 24135: "dragonish", + 24136: "dragster", + 24141: "drainable", + 24142: "drainage", + 24143: "drained", + 24144: "drainer", + 24145: "drainpipe", + 24146: "dramatic", + 24151: "dramatize", + 24152: "drank", + 24153: "drapery", + 24154: "drastic", + 24155: "draw", + 24156: "dreaded", + 24161: "dreadful", + 24162: "dreadlock", + 24163: "dreamboat", + 24164: "dreamily", + 24165: "dreamland", + 24166: "dreamless", + 24211: "dreamlike", + 24212: "dreamt", + 24213: "dreamy", + 24214: "drearily", + 24215: "dreary", + 24216: "drench", + 24221: "dress", + 24222: "drew", + 24223: "dribble", + 24224: "dried", + 24225: "drier", + 24226: "drift", + 24231: "driller", + 24232: "drilling", + 24233: "drinkable", + 24234: "drinking", + 24235: "dripping", + 24236: "drippy", + 24241: "drivable", + 24242: "driven", + 24243: "driver", + 24244: "driveway", + 24245: "driving", + 24246: "drizzle", + 24251: "drizzly", + 24252: "drone", + 24253: "drool", + 24254: "droop", + 24255: "drop-down", + 24256: "dropbox", + 24261: "dropkick", + 24262: "droplet", + 24263: "dropout", + 24264: "dropper", + 24265: "drove", + 24266: "drown", + 24311: "drowsily", + 24312: "drudge", + 24313: "drum", + 24314: "dry", + 24315: "dubbed", + 24316: "dubiously", + 24321: "duchess", + 24322: "duckbill", + 24323: "ducking", + 24324: "duckling", + 24325: "ducktail", + 24326: "ducky", + 24331: "duct", + 24332: "dude", + 24333: "duffel", + 24334: "dugout", + 24335: "duh", + 24336: "duke", + 24341: "duller", + 24342: "dullness", + 24343: "duly", + 24344: "dumping", + 24345: "dumpling", + 24346: "dumpster", + 24351: "duo", + 24352: "dupe", + 24353: "duplex", + 24354: "duplicate", + 24355: "duplicity", + 24356: "durable", + 24361: "durably", + 24362: "duration", + 24363: "duress", + 24364: "during", + 24365: "dusk", + 24366: "dust", + 24411: "dutiful", + 24412: "duty", + 24413: "duvet", + 24414: "dwarf", + 24415: "dweeb", + 24416: "dwelled", + 24421: "dweller", + 24422: "dwelling", + 24423: "dwindle", + 24424: "dwindling", + 24425: "dynamic", + 24426: "dynamite", + 24431: "dynasty", + 24432: "dyslexia", + 24433: "dyslexic", + 24434: "each", + 24435: "eagle", + 24436: "earache", + 24441: "eardrum", + 24442: "earflap", + 24443: "earful", + 24444: "earlobe", + 24445: "early", + 24446: "earmark", + 24451: "earmuff", + 24452: "earphone", + 24453: "earpiece", + 24454: "earplugs", + 24455: "earring", + 24456: "earshot", + 24461: "earthen", + 24462: "earthlike", + 24463: "earthling", + 24464: "earthly", + 24465: "earthworm", + 24466: "earthy", + 24511: "earwig", + 24512: "easeful", + 24513: "easel", + 24514: "easiest", + 24515: "easily", + 24516: "easiness", + 24521: "easing", + 24522: "eastbound", + 24523: "eastcoast", + 24524: "easter", + 24525: "eastward", + 24526: "eatable", + 24531: "eaten", + 24532: "eatery", + 24533: "eating", + 24534: "eats", + 24535: "ebay", + 24536: "ebony", + 24541: "ebook", + 24542: "ecard", + 24543: "eccentric", + 24544: "echo", + 24545: "eclair", + 24546: "eclipse", + 24551: "ecologist", + 24552: "ecology", + 24553: "economic", + 24554: "economist", + 24555: "economy", + 24556: "ecosphere", + 24561: "ecosystem", + 24562: "edge", + 24563: "edginess", + 24564: "edging", + 24565: "edgy", + 24566: "edition", + 24611: "editor", + 24612: "educated", + 24613: "education", + 24614: "educator", + 24615: "eel", + 24616: "effective", + 24621: "effects", + 24622: "efficient", + 24623: "effort", + 24624: "eggbeater", + 24625: "egging", + 24626: "eggnog", + 24631: "eggplant", + 24632: "eggshell", + 24633: "egomaniac", + 24634: "egotism", + 24635: "egotistic", + 24636: "either", + 24641: "eject", + 24642: "elaborate", + 24643: "elastic", + 24644: "elated", + 24645: "elbow", + 24646: "eldercare", + 24651: "elderly", + 24652: "eldest", + 24653: "electable", + 24654: "election", + 24655: "elective", + 24656: "elephant", + 24661: "elevate", + 24662: "elevating", + 24663: "elevation", + 24664: "elevator", + 24665: "eleven", + 24666: "elf", + 25111: "eligible", + 25112: "eligibly", + 25113: "eliminate", + 25114: "elite", + 25115: "elitism", + 25116: "elixir", + 25121: "elk", + 25122: "ellipse", + 25123: "elliptic", + 25124: "elm", + 25125: "elongated", + 25126: "elope", + 25131: "eloquence", + 25132: "eloquent", + 25133: "elsewhere", + 25134: "elude", + 25135: "elusive", + 25136: "elves", + 25141: "email", + 25142: "embargo", + 25143: "embark", + 25144: "embassy", + 25145: "embattled", + 25146: "embellish", + 25151: "ember", + 25152: "embezzle", + 25153: "emblaze", + 25154: "emblem", + 25155: "embody", + 25156: "embolism", + 25161: "emboss", + 25162: "embroider", + 25163: "emcee", + 25164: "emerald", + 25165: "emergency", + 25166: "emission", + 25211: "emit", + 25212: "emote", + 25213: "emoticon", + 25214: "emotion", + 25215: "empathic", + 25216: "empathy", + 25221: "emperor", + 25222: "emphases", + 25223: "emphasis", + 25224: "emphasize", + 25225: "emphatic", + 25226: "empirical", + 25231: "employed", + 25232: "employee", + 25233: "employer", + 25234: "emporium", + 25235: "empower", + 25236: "emptier", + 25241: "emptiness", + 25242: "empty", + 25243: "emu", + 25244: "enable", + 25245: "enactment", + 25246: "enamel", + 25251: "enchanted", + 25252: "enchilada", + 25253: "encircle", + 25254: "enclose", + 25255: "enclosure", + 25256: "encode", + 25261: "encore", + 25262: "encounter", + 25263: "encourage", + 25264: "encroach", + 25265: "encrust", + 25266: "encrypt", + 25311: "endanger", + 25312: "endeared", + 25313: "endearing", + 25314: "ended", + 25315: "ending", + 25316: "endless", + 25321: "endnote", + 25322: "endocrine", + 25323: "endorphin", + 25324: "endorse", + 25325: "endowment", + 25326: "endpoint", + 25331: "endurable", + 25332: "endurance", + 25333: "enduring", + 25334: "energetic", + 25335: "energize", + 25336: "energy", + 25341: "enforced", + 25342: "enforcer", + 25343: "engaged", + 25344: "engaging", + 25345: "engine", + 25346: "engorge", + 25351: "engraved", + 25352: "engraver", + 25353: "engraving", + 25354: "engross", + 25355: "engulf", + 25356: "enhance", + 25361: "enigmatic", + 25362: "enjoyable", + 25363: "enjoyably", + 25364: "enjoyer", + 25365: "enjoying", + 25366: "enjoyment", + 25411: "enlarged", + 25412: "enlarging", + 25413: "enlighten", + 25414: "enlisted", + 25415: "enquirer", + 25416: "enrage", + 25421: "enrich", + 25422: "enroll", + 25423: "enslave", + 25424: "ensnare", + 25425: "ensure", + 25426: "entail", + 25431: "entangled", + 25432: "entering", + 25433: "entertain", + 25434: "enticing", + 25435: "entire", + 25436: "entitle", + 25441: "entity", + 25442: "entomb", + 25443: "entourage", + 25444: "entrap", + 25445: "entree", + 25446: "entrench", + 25451: "entrust", + 25452: "entryway", + 25453: "entwine", + 25454: "enunciate", + 25455: "envelope", + 25456: "enviable", + 25461: "enviably", + 25462: "envious", + 25463: "envision", + 25464: "envoy", + 25465: "envy", + 25466: "enzyme", + 25511: "epic", + 25512: "epidemic", + 25513: "epidermal", + 25514: "epidermis", + 25515: "epidural", + 25516: "epilepsy", + 25521: "epileptic", + 25522: "epilogue", + 25523: "epiphany", + 25524: "episode", + 25525: "equal", + 25526: "equate", + 25531: "equation", + 25532: "equator", + 25533: "equinox", + 25534: "equipment", + 25535: "equity", + 25536: "equivocal", + 25541: "eradicate", + 25542: "erasable", + 25543: "erased", + 25544: "eraser", + 25545: "erasure", + 25546: "ergonomic", + 25551: "errand", + 25552: "errant", + 25553: "erratic", + 25554: "error", + 25555: "erupt", + 25556: "escalate", + 25561: "escalator", + 25562: "escapable", + 25563: "escapade", + 25564: "escapist", + 25565: "escargot", + 25566: "eskimo", + 25611: "esophagus", + 25612: "espionage", + 25613: "espresso", + 25614: "esquire", + 25615: "essay", + 25616: "essence", + 25621: "essential", + 25622: "establish", + 25623: "estate", + 25624: "esteemed", + 25625: "estimate", + 25626: "estimator", + 25631: "estranged", + 25632: "estrogen", + 25633: "etching", + 25634: "eternal", + 25635: "eternity", + 25636: "ethanol", + 25641: "ether", + 25642: "ethically", + 25643: "ethics", + 25644: "euphemism", + 25645: "evacuate", + 25646: "evacuee", + 25651: "evade", + 25652: "evaluate", + 25653: "evaluator", + 25654: "evaporate", + 25655: "evasion", + 25656: "evasive", + 25661: "even", + 25662: "everglade", + 25663: "evergreen", + 25664: "everybody", + 25665: "everyday", + 25666: "everyone", + 26111: "evict", + 26112: "evidence", + 26113: "evident", + 26114: "evil", + 26115: "evoke", + 26116: "evolution", + 26121: "evolve", + 26122: "exact", + 26123: "exalted", + 26124: "example", + 26125: "excavate", + 26126: "excavator", + 26131: "exceeding", + 26132: "exception", + 26133: "excess", + 26134: "exchange", + 26135: "excitable", + 26136: "exciting", + 26141: "exclaim", + 26142: "exclude", + 26143: "excluding", + 26144: "exclusion", + 26145: "exclusive", + 26146: "excretion", + 26151: "excretory", + 26152: "excursion", + 26153: "excusable", + 26154: "excusably", + 26155: "excuse", + 26156: "exemplary", + 26161: "exemplify", + 26162: "exemption", + 26163: "exerciser", + 26164: "exert", + 26165: "exes", + 26166: "exfoliate", + 26211: "exhale", + 26212: "exhaust", + 26213: "exhume", + 26214: "exile", + 26215: "existing", + 26216: "exit", + 26221: "exodus", + 26222: "exonerate", + 26223: "exorcism", + 26224: "exorcist", + 26225: "expand", + 26226: "expanse", + 26231: "expansion", + 26232: "expansive", + 26233: "expectant", + 26234: "expedited", + 26235: "expediter", + 26236: "expel", + 26241: "expend", + 26242: "expenses", + 26243: "expensive", + 26244: "expert", + 26245: "expire", + 26246: "expiring", + 26251: "explain", + 26252: "expletive", + 26253: "explicit", + 26254: "explode", + 26255: "exploit", + 26256: "explore", + 26261: "exploring", + 26262: "exponent", + 26263: "exporter", + 26264: "exposable", + 26265: "expose", + 26266: "exposure", + 26311: "express", + 26312: "expulsion", + 26313: "exquisite", + 26314: "extended", + 26315: "extending", + 26316: "extent", + 26321: "extenuate", + 26322: "exterior", + 26323: "external", + 26324: "extinct", + 26325: "extortion", + 26326: "extradite", + 26331: "extras", + 26332: "extrovert", + 26333: "extrude", + 26334: "extruding", + 26335: "exuberant", + 26336: "fable", + 26341: "fabric", + 26342: "fabulous", + 26343: "facebook", + 26344: "facecloth", + 26345: "facedown", + 26346: "faceless", + 26351: "facelift", + 26352: "faceplate", + 26353: "faceted", + 26354: "facial", + 26355: "facility", + 26356: "facing", + 26361: "facsimile", + 26362: "faction", + 26363: "factoid", + 26364: "factor", + 26365: "factsheet", + 26366: "factual", + 26411: "faculty", + 26412: "fade", + 26413: "fading", + 26414: "failing", + 26415: "falcon", + 26416: "fall", + 26421: "false", + 26422: "falsify", + 26423: "fame", + 26424: "familiar", + 26425: "family", + 26426: "famine", + 26431: "famished", + 26432: "fanatic", + 26433: "fancied", + 26434: "fanciness", + 26435: "fancy", + 26436: "fanfare", + 26441: "fang", + 26442: "fanning", + 26443: "fantasize", + 26444: "fantastic", + 26445: "fantasy", + 26446: "fascism", + 26451: "fastball", + 26452: "faster", + 26453: "fasting", + 26454: "fastness", + 26455: "faucet", + 26456: "favorable", + 26461: "favorably", + 26462: "favored", + 26463: "favoring", + 26464: "favorite", + 26465: "fax", + 26466: "feast", + 26511: "federal", + 26512: "fedora", + 26513: "feeble", + 26514: "feed", + 26515: "feel", + 26516: "feisty", + 26521: "feline", + 26522: "felt-tip", + 26523: "feminine", + 26524: "feminism", + 26525: "feminist", + 26526: "feminize", + 26531: "femur", + 26532: "fence", + 26533: "fencing", + 26534: "fender", + 26535: "ferment", + 26536: "fernlike", + 26541: "ferocious", + 26542: "ferocity", + 26543: "ferret", + 26544: "ferris", + 26545: "ferry", + 26546: "fervor", + 26551: "fester", + 26552: "festival", + 26553: "festive", + 26554: "festivity", + 26555: "fetal", + 26556: "fetch", + 26561: "fever", + 26562: "fiber", + 26563: "fiction", + 26564: "fiddle", + 26565: "fiddling", + 26566: "fidelity", + 26611: "fidgeting", + 26612: "fidgety", + 26613: "fifteen", + 26614: "fifth", + 26615: "fiftieth", + 26616: "fifty", + 26621: "figment", + 26622: "figure", + 26623: "figurine", + 26624: "filing", + 26625: "filled", + 26626: "filler", + 26631: "filling", + 26632: "film", + 26633: "filter", + 26634: "filth", + 26635: "filtrate", + 26636: "finale", + 26641: "finalist", + 26642: "finalize", + 26643: "finally", + 26644: "finance", + 26645: "financial", + 26646: "finch", + 26651: "fineness", + 26652: "finer", + 26653: "finicky", + 26654: "finished", + 26655: "finisher", + 26656: "finishing", + 26661: "finite", + 26662: "finless", + 26663: "finlike", + 26664: "fiscally", + 26665: "fit", + 26666: "five", + 31111: "flaccid", + 31112: "flagman", + 31113: "flagpole", + 31114: "flagship", + 31115: "flagstick", + 31116: "flagstone", + 31121: "flail", + 31122: "flakily", + 31123: "flaky", + 31124: "flame", + 31125: "flammable", + 31126: "flanked", + 31131: "flanking", + 31132: "flannels", + 31133: "flap", + 31134: "flaring", + 31135: "flashback", + 31136: "flashbulb", + 31141: "flashcard", + 31142: "flashily", + 31143: "flashing", + 31144: "flashy", + 31145: "flask", + 31146: "flatbed", + 31151: "flatfoot", + 31152: "flatly", + 31153: "flatness", + 31154: "flatten", + 31155: "flattered", + 31156: "flatterer", + 31161: "flattery", + 31162: "flattop", + 31163: "flatware", + 31164: "flatworm", + 31165: "flavored", + 31166: "flavorful", + 31211: "flavoring", + 31212: "flaxseed", + 31213: "fled", + 31214: "fleshed", + 31215: "fleshy", + 31216: "flick", + 31221: "flier", + 31222: "flight", + 31223: "flinch", + 31224: "fling", + 31225: "flint", + 31226: "flip", + 31231: "flirt", + 31232: "float", + 31233: "flock", + 31234: "flogging", + 31235: "flop", + 31236: "floral", + 31241: "florist", + 31242: "floss", + 31243: "flounder", + 31244: "flyable", + 31245: "flyaway", + 31246: "flyer", + 31251: "flying", + 31252: "flyover", + 31253: "flypaper", + 31254: "foam", + 31255: "foe", + 31256: "fog", + 31261: "foil", + 31262: "folic", + 31263: "folk", + 31264: "follicle", + 31265: "follow", + 31266: "fondling", + 31311: "fondly", + 31312: "fondness", + 31313: "fondue", + 31314: "font", + 31315: "food", + 31316: "fool", + 31321: "footage", + 31322: "football", + 31323: "footbath", + 31324: "footboard", + 31325: "footer", + 31326: "footgear", + 31331: "foothill", + 31332: "foothold", + 31333: "footing", + 31334: "footless", + 31335: "footman", + 31336: "footnote", + 31341: "footpad", + 31342: "footpath", + 31343: "footprint", + 31344: "footrest", + 31345: "footsie", + 31346: "footsore", + 31351: "footwear", + 31352: "footwork", + 31353: "fossil", + 31354: "foster", + 31355: "founder", + 31356: "founding", + 31361: "fountain", + 31362: "fox", + 31363: "foyer", + 31364: "fraction", + 31365: "fracture", + 31366: "fragile", + 31411: "fragility", + 31412: "fragment", + 31413: "fragrance", + 31414: "fragrant", + 31415: "frail", + 31416: "frame", + 31421: "framing", + 31422: "frantic", + 31423: "fraternal", + 31424: "frayed", + 31425: "fraying", + 31426: "frays", + 31431: "freckled", + 31432: "freckles", + 31433: "freebase", + 31434: "freebee", + 31435: "freebie", + 31436: "freedom", + 31441: "freefall", + 31442: "freehand", + 31443: "freeing", + 31444: "freeload", + 31445: "freely", + 31446: "freemason", + 31451: "freeness", + 31452: "freestyle", + 31453: "freeware", + 31454: "freeway", + 31455: "freewill", + 31456: "freezable", + 31461: "freezing", + 31462: "freight", + 31463: "french", + 31464: "frenzied", + 31465: "frenzy", + 31466: "frequency", + 31511: "frequent", + 31512: "fresh", + 31513: "fretful", + 31514: "fretted", + 31515: "friction", + 31516: "friday", + 31521: "fridge", + 31522: "fried", + 31523: "friend", + 31524: "frighten", + 31525: "frightful", + 31526: "frigidity", + 31531: "frigidly", + 31532: "frill", + 31533: "fringe", + 31534: "frisbee", + 31535: "frisk", + 31536: "fritter", + 31541: "frivolous", + 31542: "frolic", + 31543: "from", + 31544: "front", + 31545: "frostbite", + 31546: "frosted", + 31551: "frostily", + 31552: "frosting", + 31553: "frostlike", + 31554: "frosty", + 31555: "froth", + 31556: "frown", + 31561: "frozen", + 31562: "fructose", + 31563: "frugality", + 31564: "frugally", + 31565: "fruit", + 31566: "frustrate", + 31611: "frying", + 31612: "gab", + 31613: "gaffe", + 31614: "gag", + 31615: "gainfully", + 31616: "gaining", + 31621: "gains", + 31622: "gala", + 31623: "gallantly", + 31624: "galleria", + 31625: "gallery", + 31626: "galley", + 31631: "gallon", + 31632: "gallows", + 31633: "gallstone", + 31634: "galore", + 31635: "galvanize", + 31636: "gambling", + 31641: "game", + 31642: "gaming", + 31643: "gamma", + 31644: "gander", + 31645: "gangly", + 31646: "gangrene", + 31651: "gangway", + 31652: "gap", + 31653: "garage", + 31654: "garbage", + 31655: "garden", + 31656: "gargle", + 31661: "garland", + 31662: "garlic", + 31663: "garment", + 31664: "garnet", + 31665: "garnish", + 31666: "garter", + 32111: "gas", + 32112: "gatherer", + 32113: "gathering", + 32114: "gating", + 32115: "gauging", + 32116: "gauntlet", + 32121: "gauze", + 32122: "gave", + 32123: "gawk", + 32124: "gazing", + 32125: "gear", + 32126: "gecko", + 32131: "geek", + 32132: "geiger", + 32133: "gem", + 32134: "gender", + 32135: "generic", + 32136: "generous", + 32141: "genetics", + 32142: "genre", + 32143: "gentile", + 32144: "gentleman", + 32145: "gently", + 32146: "gents", + 32151: "geography", + 32152: "geologic", + 32153: "geologist", + 32154: "geology", + 32155: "geometric", + 32156: "geometry", + 32161: "geranium", + 32162: "gerbil", + 32163: "geriatric", + 32164: "germicide", + 32165: "germinate", + 32166: "germless", + 32211: "germproof", + 32212: "gestate", + 32213: "gestation", + 32214: "gesture", + 32215: "getaway", + 32216: "getting", + 32221: "getup", + 32222: "giant", + 32223: "gibberish", + 32224: "giblet", + 32225: "giddily", + 32226: "giddiness", + 32231: "giddy", + 32232: "gift", + 32233: "gigabyte", + 32234: "gigahertz", + 32235: "gigantic", + 32236: "giggle", + 32241: "giggling", + 32242: "giggly", + 32243: "gigolo", + 32244: "gilled", + 32245: "gills", + 32246: "gimmick", + 32251: "girdle", + 32252: "giveaway", + 32253: "given", + 32254: "giver", + 32255: "giving", + 32256: "gizmo", + 32261: "gizzard", + 32262: "glacial", + 32263: "glacier", + 32264: "glade", + 32265: "gladiator", + 32266: "gladly", + 32311: "glamorous", + 32312: "glamour", + 32313: "glance", + 32314: "glancing", + 32315: "glandular", + 32316: "glare", + 32321: "glaring", + 32322: "glass", + 32323: "glaucoma", + 32324: "glazing", + 32325: "gleaming", + 32326: "gleeful", + 32331: "glider", + 32332: "gliding", + 32333: "glimmer", + 32334: "glimpse", + 32335: "glisten", + 32336: "glitch", + 32341: "glitter", + 32342: "glitzy", + 32343: "gloater", + 32344: "gloating", + 32345: "gloomily", + 32346: "gloomy", + 32351: "glorified", + 32352: "glorifier", + 32353: "glorify", + 32354: "glorious", + 32355: "glory", + 32356: "gloss", + 32361: "glove", + 32362: "glowing", + 32363: "glowworm", + 32364: "glucose", + 32365: "glue", + 32366: "gluten", + 32411: "glutinous", + 32412: "glutton", + 32413: "gnarly", + 32414: "gnat", + 32415: "goal", + 32416: "goatskin", + 32421: "goes", + 32422: "goggles", + 32423: "going", + 32424: "goldfish", + 32425: "goldmine", + 32426: "goldsmith", + 32431: "golf", + 32432: "goliath", + 32433: "gonad", + 32434: "gondola", + 32435: "gone", + 32436: "gong", + 32441: "good", + 32442: "gooey", + 32443: "goofball", + 32444: "goofiness", + 32445: "goofy", + 32446: "google", + 32451: "goon", + 32452: "gopher", + 32453: "gore", + 32454: "gorged", + 32455: "gorgeous", + 32456: "gory", + 32461: "gosling", + 32462: "gossip", + 32463: "gothic", + 32464: "gotten", + 32465: "gout", + 32466: "gown", + 32511: "grab", + 32512: "graceful", + 32513: "graceless", + 32514: "gracious", + 32515: "gradation", + 32516: "graded", + 32521: "grader", + 32522: "gradient", + 32523: "grading", + 32524: "gradually", + 32525: "graduate", + 32526: "graffiti", + 32531: "grafted", + 32532: "grafting", + 32533: "grain", + 32534: "granddad", + 32535: "grandkid", + 32536: "grandly", + 32541: "grandma", + 32542: "grandpa", + 32543: "grandson", + 32544: "granite", + 32545: "granny", + 32546: "granola", + 32551: "grant", + 32552: "granular", + 32553: "grape", + 32554: "graph", + 32555: "grapple", + 32556: "grappling", + 32561: "grasp", + 32562: "grass", + 32563: "gratified", + 32564: "gratify", + 32565: "grating", + 32566: "gratitude", + 32611: "gratuity", + 32612: "gravel", + 32613: "graveness", + 32614: "graves", + 32615: "graveyard", + 32616: "gravitate", + 32621: "gravity", + 32622: "gravy", + 32623: "gray", + 32624: "grazing", + 32625: "greasily", + 32626: "greedily", + 32631: "greedless", + 32632: "greedy", + 32633: "green", + 32634: "greeter", + 32635: "greeting", + 32636: "grew", + 32641: "greyhound", + 32642: "grid", + 32643: "grief", + 32644: "grievance", + 32645: "grieving", + 32646: "grievous", + 32651: "grill", + 32652: "grimace", + 32653: "grimacing", + 32654: "grime", + 32655: "griminess", + 32656: "grimy", + 32661: "grinch", + 32662: "grinning", + 32663: "grip", + 32664: "gristle", + 32665: "grit", + 32666: "groggily", + 33111: "groggy", + 33112: "groin", + 33113: "groom", + 33114: "groove", + 33115: "grooving", + 33116: "groovy", + 33121: "grope", + 33122: "ground", + 33123: "grouped", + 33124: "grout", + 33125: "grove", + 33126: "grower", + 33131: "growing", + 33132: "growl", + 33133: "grub", + 33134: "grudge", + 33135: "grudging", + 33136: "grueling", + 33141: "gruffly", + 33142: "grumble", + 33143: "grumbling", + 33144: "grumbly", + 33145: "grumpily", + 33146: "grunge", + 33151: "grunt", + 33152: "guacamole", + 33153: "guidable", + 33154: "guidance", + 33155: "guide", + 33156: "guiding", + 33161: "guileless", + 33162: "guise", + 33163: "gulf", + 33164: "gullible", + 33165: "gully", + 33166: "gulp", + 33211: "gumball", + 33212: "gumdrop", + 33213: "gumminess", + 33214: "gumming", + 33215: "gummy", + 33216: "gurgle", + 33221: "gurgling", + 33222: "guru", + 33223: "gush", + 33224: "gusto", + 33225: "gusty", + 33226: "gutless", + 33231: "guts", + 33232: "gutter", + 33233: "guy", + 33234: "guzzler", + 33235: "gyration", + 33236: "habitable", + 33241: "habitant", + 33242: "habitat", + 33243: "habitual", + 33244: "hacked", + 33245: "hacker", + 33246: "hacking", + 33251: "hacksaw", + 33252: "had", + 33253: "haggler", + 33254: "haiku", + 33255: "half", + 33256: "halogen", + 33261: "halt", + 33262: "halved", + 33263: "halves", + 33264: "hamburger", + 33265: "hamlet", + 33266: "hammock", + 33311: "hamper", + 33312: "hamster", + 33313: "hamstring", + 33314: "handbag", + 33315: "handball", + 33316: "handbook", + 33321: "handbrake", + 33322: "handcart", + 33323: "handclap", + 33324: "handclasp", + 33325: "handcraft", + 33326: "handcuff", + 33331: "handed", + 33332: "handful", + 33333: "handgrip", + 33334: "handgun", + 33335: "handheld", + 33336: "handiness", + 33341: "handiwork", + 33342: "handlebar", + 33343: "handled", + 33344: "handler", + 33345: "handling", + 33346: "handmade", + 33351: "handoff", + 33352: "handpick", + 33353: "handprint", + 33354: "handrail", + 33355: "handsaw", + 33356: "handset", + 33361: "handsfree", + 33362: "handshake", + 33363: "handstand", + 33364: "handwash", + 33365: "handwork", + 33366: "handwoven", + 33411: "handwrite", + 33412: "handyman", + 33413: "hangnail", + 33414: "hangout", + 33415: "hangover", + 33416: "hangup", + 33421: "hankering", + 33422: "hankie", + 33423: "hanky", + 33424: "haphazard", + 33425: "happening", + 33426: "happier", + 33431: "happiest", + 33432: "happily", + 33433: "happiness", + 33434: "happy", + 33435: "harbor", + 33436: "hardcopy", + 33441: "hardcore", + 33442: "hardcover", + 33443: "harddisk", + 33444: "hardened", + 33445: "hardener", + 33446: "hardening", + 33451: "hardhat", + 33452: "hardhead", + 33453: "hardiness", + 33454: "hardly", + 33455: "hardness", + 33456: "hardship", + 33461: "hardware", + 33462: "hardwired", + 33463: "hardwood", + 33464: "hardy", + 33465: "harmful", + 33466: "harmless", + 33511: "harmonica", + 33512: "harmonics", + 33513: "harmonize", + 33514: "harmony", + 33515: "harness", + 33516: "harpist", + 33521: "harsh", + 33522: "harvest", + 33523: "hash", + 33524: "hassle", + 33525: "haste", + 33526: "hastily", + 33531: "hastiness", + 33532: "hasty", + 33533: "hatbox", + 33534: "hatchback", + 33535: "hatchery", + 33536: "hatchet", + 33541: "hatching", + 33542: "hatchling", + 33543: "hate", + 33544: "hatless", + 33545: "hatred", + 33546: "haunt", + 33551: "haven", + 33552: "hazard", + 33553: "hazelnut", + 33554: "hazily", + 33555: "haziness", + 33556: "hazing", + 33561: "hazy", + 33562: "headache", + 33563: "headband", + 33564: "headboard", + 33565: "headcount", + 33566: "headdress", + 33611: "headed", + 33612: "header", + 33613: "headfirst", + 33614: "headgear", + 33615: "heading", + 33616: "headlamp", + 33621: "headless", + 33622: "headlock", + 33623: "headphone", + 33624: "headpiece", + 33625: "headrest", + 33626: "headroom", + 33631: "headscarf", + 33632: "headset", + 33633: "headsman", + 33634: "headstand", + 33635: "headstone", + 33636: "headway", + 33641: "headwear", + 33642: "heap", + 33643: "heat", + 33644: "heave", + 33645: "heavily", + 33646: "heaviness", + 33651: "heaving", + 33652: "hedge", + 33653: "hedging", + 33654: "heftiness", + 33655: "hefty", + 33656: "helium", + 33661: "helmet", + 33662: "helper", + 33663: "helpful", + 33664: "helping", + 33665: "helpless", + 33666: "helpline", + 34111: "hemlock", + 34112: "hemstitch", + 34113: "hence", + 34114: "henchman", + 34115: "henna", + 34116: "herald", + 34121: "herbal", + 34122: "herbicide", + 34123: "herbs", + 34124: "heritage", + 34125: "hermit", + 34126: "heroics", + 34131: "heroism", + 34132: "herring", + 34133: "herself", + 34134: "hertz", + 34135: "hesitancy", + 34136: "hesitant", + 34141: "hesitate", + 34142: "hexagon", + 34143: "hexagram", + 34144: "hubcap", + 34145: "huddle", + 34146: "huddling", + 34151: "huff", + 34152: "hug", + 34153: "hula", + 34154: "hulk", + 34155: "hull", + 34156: "human", + 34161: "humble", + 34162: "humbling", + 34163: "humbly", + 34164: "humid", + 34165: "humiliate", + 34166: "humility", + 34211: "humming", + 34212: "hummus", + 34213: "humongous", + 34214: "humorist", + 34215: "humorless", + 34216: "humorous", + 34221: "humpback", + 34222: "humped", + 34223: "humvee", + 34224: "hunchback", + 34225: "hundredth", + 34226: "hunger", + 34231: "hungrily", + 34232: "hungry", + 34233: "hunk", + 34234: "hunter", + 34235: "hunting", + 34236: "huntress", + 34241: "huntsman", + 34242: "hurdle", + 34243: "hurled", + 34244: "hurler", + 34245: "hurling", + 34246: "hurray", + 34251: "hurricane", + 34252: "hurried", + 34253: "hurry", + 34254: "hurt", + 34255: "husband", + 34256: "hush", + 34261: "husked", + 34262: "huskiness", + 34263: "hut", + 34264: "hybrid", + 34265: "hydrant", + 34266: "hydrated", + 34311: "hydration", + 34312: "hydrogen", + 34313: "hydroxide", + 34314: "hyperlink", + 34315: "hypertext", + 34316: "hyphen", + 34321: "hypnoses", + 34322: "hypnosis", + 34323: "hypnotic", + 34324: "hypnotism", + 34325: "hypnotist", + 34326: "hypnotize", + 34331: "hypocrisy", + 34332: "hypocrite", + 34333: "ibuprofen", + 34334: "ice", + 34335: "iciness", + 34336: "icing", + 34341: "icky", + 34342: "icon", + 34343: "icy", + 34344: "idealism", + 34345: "idealist", + 34346: "idealize", + 34351: "ideally", + 34352: "idealness", + 34353: "identical", + 34354: "identify", + 34355: "identity", + 34356: "ideology", + 34361: "idiocy", + 34362: "idiom", + 34363: "idly", + 34364: "igloo", + 34365: "ignition", + 34366: "ignore", + 34411: "iguana", + 34412: "illicitly", + 34413: "illusion", + 34414: "illusive", + 34415: "image", + 34416: "imaginary", + 34421: "imagines", + 34422: "imaging", + 34423: "imbecile", + 34424: "imitate", + 34425: "imitation", + 34426: "immature", + 34431: "immerse", + 34432: "immersion", + 34433: "imminent", + 34434: "immobile", + 34435: "immodest", + 34436: "immorally", + 34441: "immortal", + 34442: "immovable", + 34443: "immovably", + 34444: "immunity", + 34445: "immunize", + 34446: "impaired", + 34451: "impale", + 34452: "impart", + 34453: "impatient", + 34454: "impeach", + 34455: "impeding", + 34456: "impending", + 34461: "imperfect", + 34462: "imperial", + 34463: "impish", + 34464: "implant", + 34465: "implement", + 34466: "implicate", + 34511: "implicit", + 34512: "implode", + 34513: "implosion", + 34514: "implosive", + 34515: "imply", + 34516: "impolite", + 34521: "important", + 34522: "importer", + 34523: "impose", + 34524: "imposing", + 34525: "impotence", + 34526: "impotency", + 34531: "impotent", + 34532: "impound", + 34533: "imprecise", + 34534: "imprint", + 34535: "imprison", + 34536: "impromptu", + 34541: "improper", + 34542: "improve", + 34543: "improving", + 34544: "improvise", + 34545: "imprudent", + 34546: "impulse", + 34551: "impulsive", + 34552: "impure", + 34553: "impurity", + 34554: "iodine", + 34555: "iodize", + 34556: "ion", + 34561: "ipad", + 34562: "iphone", + 34563: "ipod", + 34564: "irate", + 34565: "irk", + 34566: "iron", + 34611: "irregular", + 34612: "irrigate", + 34613: "irritable", + 34614: "irritably", + 34615: "irritant", + 34616: "irritate", + 34621: "islamic", + 34622: "islamist", + 34623: "isolated", + 34624: "isolating", + 34625: "isolation", + 34626: "isotope", + 34631: "issue", + 34632: "issuing", + 34633: "italicize", + 34634: "italics", + 34635: "item", + 34636: "itinerary", + 34641: "itunes", + 34642: "ivory", + 34643: "ivy", + 34644: "jab", + 34645: "jackal", + 34646: "jacket", + 34651: "jackknife", + 34652: "jackpot", + 34653: "jailbird", + 34654: "jailbreak", + 34655: "jailer", + 34656: "jailhouse", + 34661: "jalapeno", + 34662: "jam", + 34663: "janitor", + 34664: "january", + 34665: "jargon", + 34666: "jarring", + 35111: "jasmine", + 35112: "jaundice", + 35113: "jaunt", + 35114: "java", + 35115: "jawed", + 35116: "jawless", + 35121: "jawline", + 35122: "jaws", + 35123: "jaybird", + 35124: "jaywalker", + 35125: "jazz", + 35126: "jeep", + 35131: "jeeringly", + 35132: "jellied", + 35133: "jelly", + 35134: "jersey", + 35135: "jester", + 35136: "jet", + 35141: "jiffy", + 35142: "jigsaw", + 35143: "jimmy", + 35144: "jingle", + 35145: "jingling", + 35146: "jinx", + 35151: "jitters", + 35152: "jittery", + 35153: "job", + 35154: "jockey", + 35155: "jockstrap", + 35156: "jogger", + 35161: "jogging", + 35162: "john", + 35163: "joining", + 35164: "jokester", + 35165: "jokingly", + 35166: "jolliness", + 35211: "jolly", + 35212: "jolt", + 35213: "jot", + 35214: "jovial", + 35215: "joyfully", + 35216: "joylessly", + 35221: "joyous", + 35222: "joyride", + 35223: "joystick", + 35224: "jubilance", + 35225: "jubilant", + 35226: "judge", + 35231: "judgingly", + 35232: "judicial", + 35233: "judiciary", + 35234: "judo", + 35235: "juggle", + 35236: "juggling", + 35241: "jugular", + 35242: "juice", + 35243: "juiciness", + 35244: "juicy", + 35245: "jujitsu", + 35246: "jukebox", + 35251: "july", + 35252: "jumble", + 35253: "jumbo", + 35254: "jump", + 35255: "junction", + 35256: "juncture", + 35261: "june", + 35262: "junior", + 35263: "juniper", + 35264: "junkie", + 35265: "junkman", + 35266: "junkyard", + 35311: "jurist", + 35312: "juror", + 35313: "jury", + 35314: "justice", + 35315: "justifier", + 35316: "justify", + 35321: "justly", + 35322: "justness", + 35323: "juvenile", + 35324: "kabob", + 35325: "kangaroo", + 35326: "karaoke", + 35331: "karate", + 35332: "karma", + 35333: "kebab", + 35334: "keenly", + 35335: "keenness", + 35336: "keep", + 35341: "keg", + 35342: "kelp", + 35343: "kennel", + 35344: "kept", + 35345: "kerchief", + 35346: "kerosene", + 35351: "kettle", + 35352: "kick", + 35353: "kiln", + 35354: "kilobyte", + 35355: "kilogram", + 35356: "kilometer", + 35361: "kilowatt", + 35362: "kilt", + 35363: "kimono", + 35364: "kindle", + 35365: "kindling", + 35366: "kindly", + 35411: "kindness", + 35412: "kindred", + 35413: "kinetic", + 35414: "kinfolk", + 35415: "king", + 35416: "kinship", + 35421: "kinsman", + 35422: "kinswoman", + 35423: "kissable", + 35424: "kisser", + 35425: "kissing", + 35426: "kitchen", + 35431: "kite", + 35432: "kitten", + 35433: "kitty", + 35434: "kiwi", + 35435: "kleenex", + 35436: "knapsack", + 35441: "knee", + 35442: "knelt", + 35443: "knickers", + 35444: "knoll", + 35445: "koala", + 35446: "kooky", + 35451: "kosher", + 35452: "krypton", + 35453: "kudos", + 35454: "kung", + 35455: "labored", + 35456: "laborer", + 35461: "laboring", + 35462: "laborious", + 35463: "labrador", + 35464: "ladder", + 35465: "ladies", + 35466: "ladle", + 35511: "ladybug", + 35512: "ladylike", + 35513: "lagged", + 35514: "lagging", + 35515: "lagoon", + 35516: "lair", + 35521: "lake", + 35522: "lance", + 35523: "landed", + 35524: "landfall", + 35525: "landfill", + 35526: "landing", + 35531: "landlady", + 35532: "landless", + 35533: "landline", + 35534: "landlord", + 35535: "landmark", + 35536: "landmass", + 35541: "landmine", + 35542: "landowner", + 35543: "landscape", + 35544: "landside", + 35545: "landslide", + 35546: "language", + 35551: "lankiness", + 35552: "lanky", + 35553: "lantern", + 35554: "lapdog", + 35555: "lapel", + 35556: "lapped", + 35561: "lapping", + 35562: "laptop", + 35563: "lard", + 35564: "large", + 35565: "lark", + 35566: "lash", + 35611: "lasso", + 35612: "last", + 35613: "latch", + 35614: "late", + 35615: "lather", + 35616: "latitude", + 35621: "latrine", + 35622: "latter", + 35623: "latticed", + 35624: "launch", + 35625: "launder", + 35626: "laundry", + 35631: "laurel", + 35632: "lavender", + 35633: "lavish", + 35634: "laxative", + 35635: "lazily", + 35636: "laziness", + 35641: "lazy", + 35642: "lecturer", + 35643: "left", + 35644: "legacy", + 35645: "legal", + 35646: "legend", + 35651: "legged", + 35652: "leggings", + 35653: "legible", + 35654: "legibly", + 35655: "legislate", + 35656: "lego", + 35661: "legroom", + 35662: "legume", + 35663: "legwarmer", + 35664: "legwork", + 35665: "lemon", + 35666: "lend", + 36111: "length", + 36112: "lens", + 36113: "lent", + 36114: "leotard", + 36115: "lesser", + 36116: "letdown", + 36121: "lethargic", + 36122: "lethargy", + 36123: "letter", + 36124: "lettuce", + 36125: "level", + 36126: "leverage", + 36131: "levers", + 36132: "levitate", + 36133: "levitator", + 36134: "liability", + 36135: "liable", + 36136: "liberty", + 36141: "librarian", + 36142: "library", + 36143: "licking", + 36144: "licorice", + 36145: "lid", + 36146: "life", + 36151: "lifter", + 36152: "lifting", + 36153: "liftoff", + 36154: "ligament", + 36155: "likely", + 36156: "likeness", + 36161: "likewise", + 36162: "liking", + 36163: "lilac", + 36164: "lilly", + 36165: "lily", + 36166: "limb", + 36211: "limeade", + 36212: "limelight", + 36213: "limes", + 36214: "limit", + 36215: "limping", + 36216: "limpness", + 36221: "line", + 36222: "lingo", + 36223: "linguini", + 36224: "linguist", + 36225: "lining", + 36226: "linked", + 36231: "linoleum", + 36232: "linseed", + 36233: "lint", + 36234: "lion", + 36235: "lip", + 36236: "liquefy", + 36241: "liqueur", + 36242: "liquid", + 36243: "lisp", + 36244: "list", + 36245: "litigate", + 36246: "litigator", + 36251: "litmus", + 36252: "litter", + 36253: "little", + 36254: "livable", + 36255: "lived", + 36256: "lively", + 36261: "liver", + 36262: "livestock", + 36263: "lividly", + 36264: "living", + 36265: "lizard", + 36266: "lubricant", + 36311: "lubricate", + 36312: "lucid", + 36313: "luckily", + 36314: "luckiness", + 36315: "luckless", + 36316: "lucrative", + 36321: "ludicrous", + 36322: "lugged", + 36323: "lukewarm", + 36324: "lullaby", + 36325: "lumber", + 36326: "luminance", + 36331: "luminous", + 36332: "lumpiness", + 36333: "lumping", + 36334: "lumpish", + 36335: "lunacy", + 36336: "lunar", + 36341: "lunchbox", + 36342: "luncheon", + 36343: "lunchroom", + 36344: "lunchtime", + 36345: "lung", + 36346: "lurch", + 36351: "lure", + 36352: "luridness", + 36353: "lurk", + 36354: "lushly", + 36355: "lushness", + 36356: "luster", + 36361: "lustfully", + 36362: "lustily", + 36363: "lustiness", + 36364: "lustrous", + 36365: "lusty", + 36366: "luxurious", + 36411: "luxury", + 36412: "lying", + 36413: "lyrically", + 36414: "lyricism", + 36415: "lyricist", + 36416: "lyrics", + 36421: "macarena", + 36422: "macaroni", + 36423: "macaw", + 36424: "mace", + 36425: "machine", + 36426: "machinist", + 36431: "magazine", + 36432: "magenta", + 36433: "maggot", + 36434: "magical", + 36435: "magician", + 36436: "magma", + 36441: "magnesium", + 36442: "magnetic", + 36443: "magnetism", + 36444: "magnetize", + 36445: "magnifier", + 36446: "magnify", + 36451: "magnitude", + 36452: "magnolia", + 36453: "mahogany", + 36454: "maimed", + 36455: "majestic", + 36456: "majesty", + 36461: "majorette", + 36462: "majority", + 36463: "makeover", + 36464: "maker", + 36465: "makeshift", + 36466: "making", + 36511: "malformed", + 36512: "malt", + 36513: "mama", + 36514: "mammal", + 36515: "mammary", + 36516: "mammogram", + 36521: "manager", + 36522: "managing", + 36523: "manatee", + 36524: "mandarin", + 36525: "mandate", + 36526: "mandatory", + 36531: "mandolin", + 36532: "manger", + 36533: "mangle", + 36534: "mango", + 36535: "mangy", + 36536: "manhandle", + 36541: "manhole", + 36542: "manhood", + 36543: "manhunt", + 36544: "manicotti", + 36545: "manicure", + 36546: "manifesto", + 36551: "manila", + 36552: "mankind", + 36553: "manlike", + 36554: "manliness", + 36555: "manly", + 36556: "manmade", + 36561: "manned", + 36562: "mannish", + 36563: "manor", + 36564: "manpower", + 36565: "mantis", + 36566: "mantra", + 36611: "manual", + 36612: "many", + 36613: "map", + 36614: "marathon", + 36615: "marauding", + 36616: "marbled", + 36621: "marbles", + 36622: "marbling", + 36623: "march", + 36624: "mardi", + 36625: "margarine", + 36626: "margarita", + 36631: "margin", + 36632: "marigold", + 36633: "marina", + 36634: "marine", + 36635: "marital", + 36636: "maritime", + 36641: "marlin", + 36642: "marmalade", + 36643: "maroon", + 36644: "married", + 36645: "marrow", + 36646: "marry", + 36651: "marshland", + 36652: "marshy", + 36653: "marsupial", + 36654: "marvelous", + 36655: "marxism", + 36656: "mascot", + 36661: "masculine", + 36662: "mashed", + 36663: "mashing", + 36664: "massager", + 36665: "masses", + 36666: "massive", + 41111: "mastiff", + 41112: "matador", + 41113: "matchbook", + 41114: "matchbox", + 41115: "matcher", + 41116: "matching", + 41121: "matchless", + 41122: "material", + 41123: "maternal", + 41124: "maternity", + 41125: "math", + 41126: "mating", + 41131: "matriarch", + 41132: "matrimony", + 41133: "matrix", + 41134: "matron", + 41135: "matted", + 41136: "matter", + 41141: "maturely", + 41142: "maturing", + 41143: "maturity", + 41144: "mauve", + 41145: "maverick", + 41146: "maximize", + 41151: "maximum", + 41152: "maybe", + 41153: "mayday", + 41154: "mayflower", + 41155: "moaner", + 41156: "moaning", + 41161: "mobile", + 41162: "mobility", + 41163: "mobilize", + 41164: "mobster", + 41165: "mocha", + 41166: "mocker", + 41211: "mockup", + 41212: "modified", + 41213: "modify", + 41214: "modular", + 41215: "modulator", + 41216: "module", + 41221: "moisten", + 41222: "moistness", + 41223: "moisture", + 41224: "molar", + 41225: "molasses", + 41226: "mold", + 41231: "molecular", + 41232: "molecule", + 41233: "molehill", + 41234: "mollusk", + 41235: "mom", + 41236: "monastery", + 41241: "monday", + 41242: "monetary", + 41243: "monetize", + 41244: "moneybags", + 41245: "moneyless", + 41246: "moneywise", + 41251: "mongoose", + 41252: "mongrel", + 41253: "monitor", + 41254: "monkhood", + 41255: "monogamy", + 41256: "monogram", + 41261: "monologue", + 41262: "monopoly", + 41263: "monorail", + 41264: "monotone", + 41265: "monotype", + 41266: "monoxide", + 41311: "monsieur", + 41312: "monsoon", + 41313: "monstrous", + 41314: "monthly", + 41315: "monument", + 41316: "moocher", + 41321: "moodiness", + 41322: "moody", + 41323: "mooing", + 41324: "moonbeam", + 41325: "mooned", + 41326: "moonlight", + 41331: "moonlike", + 41332: "moonlit", + 41333: "moonrise", + 41334: "moonscape", + 41335: "moonshine", + 41336: "moonstone", + 41341: "moonwalk", + 41342: "mop", + 41343: "morale", + 41344: "morality", + 41345: "morally", + 41346: "morbidity", + 41351: "morbidly", + 41352: "morphine", + 41353: "morphing", + 41354: "morse", + 41355: "mortality", + 41356: "mortally", + 41361: "mortician", + 41362: "mortified", + 41363: "mortify", + 41364: "mortuary", + 41365: "mosaic", + 41366: "mossy", + 41411: "most", + 41412: "mothball", + 41413: "mothproof", + 41414: "motion", + 41415: "motivate", + 41416: "motivator", + 41421: "motive", + 41422: "motocross", + 41423: "motor", + 41424: "motto", + 41425: "mountable", + 41426: "mountain", + 41431: "mounted", + 41432: "mounting", + 41433: "mourner", + 41434: "mournful", + 41435: "mouse", + 41436: "mousiness", + 41441: "moustache", + 41442: "mousy", + 41443: "mouth", + 41444: "movable", + 41445: "move", + 41446: "movie", + 41451: "moving", + 41452: "mower", + 41453: "mowing", + 41454: "much", + 41455: "muck", + 41456: "mud", + 41461: "mug", + 41462: "mulberry", + 41463: "mulch", + 41464: "mule", + 41465: "mulled", + 41466: "mullets", + 41511: "multiple", + 41512: "multiply", + 41513: "multitask", + 41514: "multitude", + 41515: "mumble", + 41516: "mumbling", + 41521: "mumbo", + 41522: "mummified", + 41523: "mummify", + 41524: "mummy", + 41525: "mumps", + 41526: "munchkin", + 41531: "mundane", + 41532: "municipal", + 41533: "muppet", + 41534: "mural", + 41535: "murkiness", + 41536: "murky", + 41541: "murmuring", + 41542: "muscular", + 41543: "museum", + 41544: "mushily", + 41545: "mushiness", + 41546: "mushroom", + 41551: "mushy", + 41552: "music", + 41553: "musket", + 41554: "muskiness", + 41555: "musky", + 41556: "mustang", + 41561: "mustard", + 41562: "muster", + 41563: "mustiness", + 41564: "musty", + 41565: "mutable", + 41566: "mutate", + 41611: "mutation", + 41612: "mute", + 41613: "mutilated", + 41614: "mutilator", + 41615: "mutiny", + 41616: "mutt", + 41621: "mutual", + 41622: "muzzle", + 41623: "myself", + 41624: "myspace", + 41625: "mystified", + 41626: "mystify", + 41631: "myth", + 41632: "nacho", + 41633: "nag", + 41634: "nail", + 41635: "name", + 41636: "naming", + 41641: "nanny", + 41642: "nanometer", + 41643: "nape", + 41644: "napkin", + 41645: "napped", + 41646: "napping", + 41651: "nappy", + 41652: "narrow", + 41653: "nastily", + 41654: "nastiness", + 41655: "national", + 41656: "native", + 41661: "nativity", + 41662: "natural", + 41663: "nature", + 41664: "naturist", + 41665: "nautical", + 41666: "navigate", + 42111: "navigator", + 42112: "navy", + 42113: "nearby", + 42114: "nearest", + 42115: "nearly", + 42116: "nearness", + 42121: "neatly", + 42122: "neatness", + 42123: "nebula", + 42124: "nebulizer", + 42125: "nectar", + 42126: "negate", + 42131: "negation", + 42132: "negative", + 42133: "neglector", + 42134: "negligee", + 42135: "negligent", + 42136: "negotiate", + 42141: "nemeses", + 42142: "nemesis", + 42143: "neon", + 42144: "nephew", + 42145: "nerd", + 42146: "nervous", + 42151: "nervy", + 42152: "nest", + 42153: "net", + 42154: "neurology", + 42155: "neuron", + 42156: "neurosis", + 42161: "neurotic", + 42162: "neuter", + 42163: "neutron", + 42164: "never", + 42165: "next", + 42166: "nibble", + 42211: "nickname", + 42212: "nicotine", + 42213: "niece", + 42214: "nifty", + 42215: "nimble", + 42216: "nimbly", + 42221: "nineteen", + 42222: "ninetieth", + 42223: "ninja", + 42224: "nintendo", + 42225: "ninth", + 42226: "nuclear", + 42231: "nuclei", + 42232: "nucleus", + 42233: "nugget", + 42234: "nullify", + 42235: "number", + 42236: "numbing", + 42241: "numbly", + 42242: "numbness", + 42243: "numeral", + 42244: "numerate", + 42245: "numerator", + 42246: "numeric", + 42251: "numerous", + 42252: "nuptials", + 42253: "nursery", + 42254: "nursing", + 42255: "nurture", + 42256: "nutcase", + 42261: "nutlike", + 42262: "nutmeg", + 42263: "nutrient", + 42264: "nutshell", + 42265: "nuttiness", + 42266: "nutty", + 42311: "nuzzle", + 42312: "nylon", + 42313: "oaf", + 42314: "oak", + 42315: "oasis", + 42316: "oat", + 42321: "obedience", + 42322: "obedient", + 42323: "obituary", + 42324: "object", + 42325: "obligate", + 42326: "obliged", + 42331: "oblivion", + 42332: "oblivious", + 42333: "oblong", + 42334: "obnoxious", + 42335: "oboe", + 42336: "obscure", + 42341: "obscurity", + 42342: "observant", + 42343: "observer", + 42344: "observing", + 42345: "obsessed", + 42346: "obsession", + 42351: "obsessive", + 42352: "obsolete", + 42353: "obstacle", + 42354: "obstinate", + 42355: "obstruct", + 42356: "obtain", + 42361: "obtrusive", + 42362: "obtuse", + 42363: "obvious", + 42364: "occultist", + 42365: "occupancy", + 42366: "occupant", + 42411: "occupier", + 42412: "occupy", + 42413: "ocean", + 42414: "ocelot", + 42415: "octagon", + 42416: "octane", + 42421: "october", + 42422: "octopus", + 42423: "ogle", + 42424: "oil", + 42425: "oink", + 42426: "ointment", + 42431: "okay", + 42432: "old", + 42433: "olive", + 42434: "olympics", + 42435: "omega", + 42436: "omen", + 42441: "ominous", + 42442: "omission", + 42443: "omit", + 42444: "omnivore", + 42445: "onboard", + 42446: "oncoming", + 42451: "ongoing", + 42452: "onion", + 42453: "online", + 42454: "onlooker", + 42455: "only", + 42456: "onscreen", + 42461: "onset", + 42462: "onshore", + 42463: "onslaught", + 42464: "onstage", + 42465: "onto", + 42466: "onward", + 42511: "onyx", + 42512: "oops", + 42513: "ooze", + 42514: "oozy", + 42515: "opacity", + 42516: "opal", + 42521: "open", + 42522: "operable", + 42523: "operate", + 42524: "operating", + 42525: "operation", + 42526: "operative", + 42531: "operator", + 42532: "opium", + 42533: "opossum", + 42534: "opponent", + 42535: "oppose", + 42536: "opposing", + 42541: "opposite", + 42542: "oppressed", + 42543: "oppressor", + 42544: "opt", + 42545: "opulently", + 42546: "osmosis", + 42551: "other", + 42552: "otter", + 42553: "ouch", + 42554: "ought", + 42555: "ounce", + 42556: "outage", + 42561: "outback", + 42562: "outbid", + 42563: "outboard", + 42564: "outbound", + 42565: "outbreak", + 42566: "outburst", + 42611: "outcast", + 42612: "outclass", + 42613: "outcome", + 42614: "outdated", + 42615: "outdoors", + 42616: "outer", + 42621: "outfield", + 42622: "outfit", + 42623: "outflank", + 42624: "outgoing", + 42625: "outgrow", + 42626: "outhouse", + 42631: "outing", + 42632: "outlast", + 42633: "outlet", + 42634: "outline", + 42635: "outlook", + 42636: "outlying", + 42641: "outmatch", + 42642: "outmost", + 42643: "outnumber", + 42644: "outplayed", + 42645: "outpost", + 42646: "outpour", + 42651: "output", + 42652: "outrage", + 42653: "outrank", + 42654: "outreach", + 42655: "outright", + 42656: "outscore", + 42661: "outsell", + 42662: "outshine", + 42663: "outshoot", + 42664: "outsider", + 42665: "outskirts", + 42666: "outsmart", + 43111: "outsource", + 43112: "outspoken", + 43113: "outtakes", + 43114: "outthink", + 43115: "outward", + 43116: "outweigh", + 43121: "outwit", + 43122: "oval", + 43123: "ovary", + 43124: "oven", + 43125: "overact", + 43126: "overall", + 43131: "overarch", + 43132: "overbid", + 43133: "overbill", + 43134: "overbite", + 43135: "overblown", + 43136: "overboard", + 43141: "overbook", + 43142: "overbuilt", + 43143: "overcast", + 43144: "overcoat", + 43145: "overcome", + 43146: "overcook", + 43151: "overcrowd", + 43152: "overdraft", + 43153: "overdrawn", + 43154: "overdress", + 43155: "overdrive", + 43156: "overdue", + 43161: "overeager", + 43162: "overeater", + 43163: "overexert", + 43164: "overfed", + 43165: "overfeed", + 43166: "overfill", + 43211: "overflow", + 43212: "overfull", + 43213: "overgrown", + 43214: "overhand", + 43215: "overhang", + 43216: "overhaul", + 43221: "overhead", + 43222: "overhear", + 43223: "overheat", + 43224: "overhung", + 43225: "overjoyed", + 43226: "overkill", + 43231: "overlabor", + 43232: "overlaid", + 43233: "overlap", + 43234: "overlay", + 43235: "overload", + 43236: "overlook", + 43241: "overlord", + 43242: "overlying", + 43243: "overnight", + 43244: "overpass", + 43245: "overpay", + 43246: "overplant", + 43251: "overplay", + 43252: "overpower", + 43253: "overprice", + 43254: "overrate", + 43255: "overreach", + 43256: "overreact", + 43261: "override", + 43262: "overripe", + 43263: "overrule", + 43264: "overrun", + 43265: "overshoot", + 43266: "overshot", + 43311: "oversight", + 43312: "oversized", + 43313: "oversleep", + 43314: "oversold", + 43315: "overspend", + 43316: "overstate", + 43321: "overstay", + 43322: "overstep", + 43323: "overstock", + 43324: "overstuff", + 43325: "oversweet", + 43326: "overtake", + 43331: "overthrow", + 43332: "overtime", + 43333: "overtly", + 43334: "overtone", + 43335: "overture", + 43336: "overturn", + 43341: "overuse", + 43342: "overvalue", + 43343: "overview", + 43344: "overwrite", + 43345: "owl", + 43346: "oxford", + 43351: "oxidant", + 43352: "oxidation", + 43353: "oxidize", + 43354: "oxidizing", + 43355: "oxygen", + 43356: "oxymoron", + 43361: "oyster", + 43362: "ozone", + 43363: "paced", + 43364: "pacemaker", + 43365: "pacific", + 43366: "pacifier", + 43411: "pacifism", + 43412: "pacifist", + 43413: "pacify", + 43414: "padded", + 43415: "padding", + 43416: "paddle", + 43421: "paddling", + 43422: "padlock", + 43423: "pagan", + 43424: "pager", + 43425: "paging", + 43426: "pajamas", + 43431: "palace", + 43432: "palatable", + 43433: "palm", + 43434: "palpable", + 43435: "palpitate", + 43436: "paltry", + 43441: "pampered", + 43442: "pamperer", + 43443: "pampers", + 43444: "pamphlet", + 43445: "panama", + 43446: "pancake", + 43451: "pancreas", + 43452: "panda", + 43453: "pandemic", + 43454: "pang", + 43455: "panhandle", + 43456: "panic", + 43461: "panning", + 43462: "panorama", + 43463: "panoramic", + 43464: "panther", + 43465: "pantomime", + 43466: "pantry", + 43511: "pants", + 43512: "pantyhose", + 43513: "paparazzi", + 43514: "papaya", + 43515: "paper", + 43516: "paprika", + 43521: "papyrus", + 43522: "parabola", + 43523: "parachute", + 43524: "parade", + 43525: "paradox", + 43526: "paragraph", + 43531: "parakeet", + 43532: "paralegal", + 43533: "paralyses", + 43534: "paralysis", + 43535: "paralyze", + 43536: "paramedic", + 43541: "parameter", + 43542: "paramount", + 43543: "parasail", + 43544: "parasite", + 43545: "parasitic", + 43546: "parcel", + 43551: "parched", + 43552: "parchment", + 43553: "pardon", + 43554: "parish", + 43555: "parka", + 43556: "parking", + 43561: "parkway", + 43562: "parlor", + 43563: "parmesan", + 43564: "parole", + 43565: "parrot", + 43566: "parsley", + 43611: "parsnip", + 43612: "partake", + 43613: "parted", + 43614: "parting", + 43615: "partition", + 43616: "partly", + 43621: "partner", + 43622: "partridge", + 43623: "party", + 43624: "passable", + 43625: "passably", + 43626: "passage", + 43631: "passcode", + 43632: "passenger", + 43633: "passerby", + 43634: "passing", + 43635: "passion", + 43636: "passive", + 43641: "passivism", + 43642: "passover", + 43643: "passport", + 43644: "password", + 43645: "pasta", + 43646: "pasted", + 43651: "pastel", + 43652: "pastime", + 43653: "pastor", + 43654: "pastrami", + 43655: "pasture", + 43656: "pasty", + 43661: "patchwork", + 43662: "patchy", + 43663: "paternal", + 43664: "paternity", + 43665: "path", + 43666: "patience", + 44111: "patient", + 44112: "patio", + 44113: "patriarch", + 44114: "patriot", + 44115: "patrol", + 44116: "patronage", + 44121: "patronize", + 44122: "pauper", + 44123: "pavement", + 44124: "paver", + 44125: "pavestone", + 44126: "pavilion", + 44131: "paving", + 44132: "pawing", + 44133: "payable", + 44134: "payback", + 44135: "paycheck", + 44136: "payday", + 44141: "payee", + 44142: "payer", + 44143: "paying", + 44144: "payment", + 44145: "payphone", + 44146: "payroll", + 44151: "pebble", + 44152: "pebbly", + 44153: "pecan", + 44154: "pectin", + 44155: "peculiar", + 44156: "peddling", + 44161: "pediatric", + 44162: "pedicure", + 44163: "pedigree", + 44164: "pedometer", + 44165: "pegboard", + 44166: "pelican", + 44211: "pellet", + 44212: "pelt", + 44213: "pelvis", + 44214: "penalize", + 44215: "penalty", + 44216: "pencil", + 44221: "pendant", + 44222: "pending", + 44223: "penholder", + 44224: "penknife", + 44225: "pennant", + 44226: "penniless", + 44231: "penny", + 44232: "penpal", + 44233: "pension", + 44234: "pentagon", + 44235: "pentagram", + 44236: "pep", + 44241: "perceive", + 44242: "percent", + 44243: "perch", + 44244: "percolate", + 44245: "perennial", + 44246: "perfected", + 44251: "perfectly", + 44252: "perfume", + 44253: "periscope", + 44254: "perish", + 44255: "perjurer", + 44256: "perjury", + 44261: "perkiness", + 44262: "perky", + 44263: "perm", + 44264: "peroxide", + 44265: "perpetual", + 44266: "perplexed", + 44311: "persecute", + 44312: "persevere", + 44313: "persuaded", + 44314: "persuader", + 44315: "pesky", + 44316: "peso", + 44321: "pessimism", + 44322: "pessimist", + 44323: "pester", + 44324: "pesticide", + 44325: "petal", + 44326: "petite", + 44331: "petition", + 44332: "petri", + 44333: "petroleum", + 44334: "petted", + 44335: "petticoat", + 44336: "pettiness", + 44341: "petty", + 44342: "petunia", + 44343: "phantom", + 44344: "phobia", + 44345: "phoenix", + 44346: "phonebook", + 44351: "phoney", + 44352: "phonics", + 44353: "phoniness", + 44354: "phony", + 44355: "phosphate", + 44356: "photo", + 44361: "phrase", + 44362: "phrasing", + 44363: "placard", + 44364: "placate", + 44365: "placidly", + 44366: "plank", + 44411: "planner", + 44412: "plant", + 44413: "plasma", + 44414: "plaster", + 44415: "plastic", + 44416: "plated", + 44421: "platform", + 44422: "plating", + 44423: "platinum", + 44424: "platonic", + 44425: "platter", + 44426: "platypus", + 44431: "plausible", + 44432: "plausibly", + 44433: "playable", + 44434: "playback", + 44435: "player", + 44436: "playful", + 44441: "playgroup", + 44442: "playhouse", + 44443: "playing", + 44444: "playlist", + 44445: "playmaker", + 44446: "playmate", + 44451: "playoff", + 44452: "playpen", + 44453: "playroom", + 44454: "playset", + 44455: "plaything", + 44456: "playtime", + 44461: "plaza", + 44462: "pleading", + 44463: "pleat", + 44464: "pledge", + 44465: "plentiful", + 44466: "plenty", + 44511: "plethora", + 44512: "plexiglas", + 44513: "pliable", + 44514: "plod", + 44515: "plop", + 44516: "plot", + 44521: "plow", + 44522: "ploy", + 44523: "pluck", + 44524: "plug", + 44525: "plunder", + 44526: "plunging", + 44531: "plural", + 44532: "plus", + 44533: "plutonium", + 44534: "plywood", + 44535: "poach", + 44536: "pod", + 44541: "poem", + 44542: "poet", + 44543: "pogo", + 44544: "pointed", + 44545: "pointer", + 44546: "pointing", + 44551: "pointless", + 44552: "pointy", + 44553: "poise", + 44554: "poison", + 44555: "poker", + 44556: "poking", + 44561: "polar", + 44562: "police", + 44563: "policy", + 44564: "polio", + 44565: "polish", + 44566: "politely", + 44611: "polka", + 44612: "polo", + 44613: "polyester", + 44614: "polygon", + 44615: "polygraph", + 44616: "polymer", + 44621: "poncho", + 44622: "pond", + 44623: "pony", + 44624: "popcorn", + 44625: "pope", + 44626: "poplar", + 44631: "popper", + 44632: "poppy", + 44633: "popsicle", + 44634: "populace", + 44635: "popular", + 44636: "populate", + 44641: "porcupine", + 44642: "pork", + 44643: "porous", + 44644: "porridge", + 44645: "portable", + 44646: "portal", + 44651: "portfolio", + 44652: "porthole", + 44653: "portion", + 44654: "portly", + 44655: "portside", + 44656: "poser", + 44661: "posh", + 44662: "posing", + 44663: "possible", + 44664: "possibly", + 44665: "possum", + 44666: "postage", + 45111: "postal", + 45112: "postbox", + 45113: "postcard", + 45114: "posted", + 45115: "poster", + 45116: "posting", + 45121: "postnasal", + 45122: "posture", + 45123: "postwar", + 45124: "pouch", + 45125: "pounce", + 45126: "pouncing", + 45131: "pound", + 45132: "pouring", + 45133: "pout", + 45134: "powdered", + 45135: "powdering", + 45136: "powdery", + 45141: "power", + 45142: "powwow", + 45143: "pox", + 45144: "praising", + 45145: "prance", + 45146: "prancing", + 45151: "pranker", + 45152: "prankish", + 45153: "prankster", + 45154: "prayer", + 45155: "praying", + 45156: "preacher", + 45161: "preaching", + 45162: "preachy", + 45163: "preamble", + 45164: "precinct", + 45165: "precise", + 45166: "precision", + 45211: "precook", + 45212: "precut", + 45213: "predator", + 45214: "predefine", + 45215: "predict", + 45216: "preface", + 45221: "prefix", + 45222: "preflight", + 45223: "preformed", + 45224: "pregame", + 45225: "pregnancy", + 45226: "pregnant", + 45231: "preheated", + 45232: "prelaunch", + 45233: "prelaw", + 45234: "prelude", + 45235: "premiere", + 45236: "premises", + 45241: "premium", + 45242: "prenatal", + 45243: "preoccupy", + 45244: "preorder", + 45245: "prepaid", + 45246: "prepay", + 45251: "preplan", + 45252: "preppy", + 45253: "preschool", + 45254: "prescribe", + 45255: "preseason", + 45256: "preset", + 45261: "preshow", + 45262: "president", + 45263: "presoak", + 45264: "press", + 45265: "presume", + 45266: "presuming", + 45311: "preteen", + 45312: "pretended", + 45313: "pretender", + 45314: "pretense", + 45315: "pretext", + 45316: "pretty", + 45321: "pretzel", + 45322: "prevail", + 45323: "prevalent", + 45324: "prevent", + 45325: "preview", + 45326: "previous", + 45331: "prewar", + 45332: "prewashed", + 45333: "prideful", + 45334: "pried", + 45335: "primal", + 45336: "primarily", + 45341: "primary", + 45342: "primate", + 45343: "primer", + 45344: "primp", + 45345: "princess", + 45346: "print", + 45351: "prior", + 45352: "prism", + 45353: "prison", + 45354: "prissy", + 45355: "pristine", + 45356: "privacy", + 45361: "private", + 45362: "privatize", + 45363: "prize", + 45364: "proactive", + 45365: "probable", + 45366: "probably", + 45411: "probation", + 45412: "probe", + 45413: "probing", + 45414: "probiotic", + 45415: "problem", + 45416: "procedure", + 45421: "process", + 45422: "proclaim", + 45423: "procreate", + 45424: "procurer", + 45425: "prodigal", + 45426: "prodigy", + 45431: "produce", + 45432: "product", + 45433: "profane", + 45434: "profanity", + 45435: "professed", + 45436: "professor", + 45441: "profile", + 45442: "profound", + 45443: "profusely", + 45444: "progeny", + 45445: "prognosis", + 45446: "program", + 45451: "progress", + 45452: "projector", + 45453: "prologue", + 45454: "prolonged", + 45455: "promenade", + 45456: "prominent", + 45461: "promoter", + 45462: "promotion", + 45463: "prompter", + 45464: "promptly", + 45465: "prone", + 45466: "prong", + 45511: "pronounce", + 45512: "pronto", + 45513: "proofing", + 45514: "proofread", + 45515: "proofs", + 45516: "propeller", + 45521: "properly", + 45522: "property", + 45523: "proponent", + 45524: "proposal", + 45525: "propose", + 45526: "props", + 45531: "prorate", + 45532: "protector", + 45533: "protegee", + 45534: "proton", + 45535: "prototype", + 45536: "protozoan", + 45541: "protract", + 45542: "protrude", + 45543: "proud", + 45544: "provable", + 45545: "proved", + 45546: "proven", + 45551: "provided", + 45552: "provider", + 45553: "providing", + 45554: "province", + 45555: "proving", + 45556: "provoke", + 45561: "provoking", + 45562: "provolone", + 45563: "prowess", + 45564: "prowler", + 45565: "prowling", + 45566: "proximity", + 45611: "proxy", + 45612: "prozac", + 45613: "prude", + 45614: "prudishly", + 45615: "prune", + 45616: "pruning", + 45621: "pry", + 45622: "psychic", + 45623: "public", + 45624: "publisher", + 45625: "pucker", + 45626: "pueblo", + 45631: "pug", + 45632: "pull", + 45633: "pulmonary", + 45634: "pulp", + 45635: "pulsate", + 45636: "pulse", + 45641: "pulverize", + 45642: "puma", + 45643: "pumice", + 45644: "pummel", + 45645: "punch", + 45646: "punctual", + 45651: "punctuate", + 45652: "punctured", + 45653: "pungent", + 45654: "punisher", + 45655: "punk", + 45656: "pupil", + 45661: "puppet", + 45662: "puppy", + 45663: "purchase", + 45664: "pureblood", + 45665: "purebred", + 45666: "purely", + 46111: "pureness", + 46112: "purgatory", + 46113: "purge", + 46114: "purging", + 46115: "purifier", + 46116: "purify", + 46121: "purist", + 46122: "puritan", + 46123: "purity", + 46124: "purple", + 46125: "purplish", + 46126: "purposely", + 46131: "purr", + 46132: "purse", + 46133: "pursuable", + 46134: "pursuant", + 46135: "pursuit", + 46136: "purveyor", + 46141: "pushcart", + 46142: "pushchair", + 46143: "pusher", + 46144: "pushiness", + 46145: "pushing", + 46146: "pushover", + 46151: "pushpin", + 46152: "pushup", + 46153: "pushy", + 46154: "putdown", + 46155: "putt", + 46156: "puzzle", + 46161: "puzzling", + 46162: "pyramid", + 46163: "pyromania", + 46164: "python", + 46165: "quack", + 46166: "quadrant", + 46211: "quail", + 46212: "quaintly", + 46213: "quake", + 46214: "quaking", + 46215: "qualified", + 46216: "qualifier", + 46221: "qualify", + 46222: "quality", + 46223: "qualm", + 46224: "quantum", + 46225: "quarrel", + 46226: "quarry", + 46231: "quartered", + 46232: "quarterly", + 46233: "quarters", + 46234: "quartet", + 46235: "quench", + 46236: "query", + 46241: "quicken", + 46242: "quickly", + 46243: "quickness", + 46244: "quicksand", + 46245: "quickstep", + 46246: "quiet", + 46251: "quill", + 46252: "quilt", + 46253: "quintet", + 46254: "quintuple", + 46255: "quirk", + 46256: "quit", + 46261: "quiver", + 46262: "quizzical", + 46263: "quotable", + 46264: "quotation", + 46265: "quote", + 46266: "rabid", + 46311: "race", + 46312: "racing", + 46313: "racism", + 46314: "rack", + 46315: "racoon", + 46316: "radar", + 46321: "radial", + 46322: "radiance", + 46323: "radiantly", + 46324: "radiated", + 46325: "radiation", + 46326: "radiator", + 46331: "radio", + 46332: "radish", + 46333: "raffle", + 46334: "raft", + 46335: "rage", + 46336: "ragged", + 46341: "raging", + 46342: "ragweed", + 46343: "raider", + 46344: "railcar", + 46345: "railing", + 46346: "railroad", + 46351: "railway", + 46352: "raisin", + 46353: "rake", + 46354: "raking", + 46355: "rally", + 46356: "ramble", + 46361: "rambling", + 46362: "ramp", + 46363: "ramrod", + 46364: "ranch", + 46365: "rancidity", + 46366: "random", + 46411: "ranged", + 46412: "ranger", + 46413: "ranging", + 46414: "ranked", + 46415: "ranking", + 46416: "ransack", + 46421: "ranting", + 46422: "rants", + 46423: "rare", + 46424: "rarity", + 46425: "rascal", + 46426: "rash", + 46431: "rasping", + 46432: "ravage", + 46433: "raven", + 46434: "ravine", + 46435: "raving", + 46436: "ravioli", + 46441: "ravishing", + 46442: "reabsorb", + 46443: "reach", + 46444: "reacquire", + 46445: "reaction", + 46446: "reactive", + 46451: "reactor", + 46452: "reaffirm", + 46453: "ream", + 46454: "reanalyze", + 46455: "reappear", + 46456: "reapply", + 46461: "reappoint", + 46462: "reapprove", + 46463: "rearrange", + 46464: "rearview", + 46465: "reason", + 46466: "reassign", + 46511: "reassure", + 46512: "reattach", + 46513: "reawake", + 46514: "rebalance", + 46515: "rebate", + 46516: "rebel", + 46521: "rebirth", + 46522: "reboot", + 46523: "reborn", + 46524: "rebound", + 46525: "rebuff", + 46526: "rebuild", + 46531: "rebuilt", + 46532: "reburial", + 46533: "rebuttal", + 46534: "recall", + 46535: "recant", + 46536: "recapture", + 46541: "recast", + 46542: "recede", + 46543: "recent", + 46544: "recess", + 46545: "recharger", + 46546: "recipient", + 46551: "recital", + 46552: "recite", + 46553: "reckless", + 46554: "reclaim", + 46555: "recliner", + 46556: "reclining", + 46561: "recluse", + 46562: "reclusive", + 46563: "recognize", + 46564: "recoil", + 46565: "recollect", + 46566: "recolor", + 46611: "reconcile", + 46612: "reconfirm", + 46613: "reconvene", + 46614: "recopy", + 46615: "record", + 46616: "recount", + 46621: "recoup", + 46622: "recovery", + 46623: "recreate", + 46624: "rectal", + 46625: "rectangle", + 46626: "rectified", + 46631: "rectify", + 46632: "recycled", + 46633: "recycler", + 46634: "recycling", + 46635: "reemerge", + 46636: "reenact", + 46641: "reenter", + 46642: "reentry", + 46643: "reexamine", + 46644: "referable", + 46645: "referee", + 46646: "reference", + 46651: "refill", + 46652: "refinance", + 46653: "refined", + 46654: "refinery", + 46655: "refining", + 46656: "refinish", + 46661: "reflected", + 46662: "reflector", + 46663: "reflex", + 46664: "reflux", + 46665: "refocus", + 46666: "refold", + 51111: "reforest", + 51112: "reformat", + 51113: "reformed", + 51114: "reformer", + 51115: "reformist", + 51116: "refract", + 51121: "refrain", + 51122: "refreeze", + 51123: "refresh", + 51124: "refried", + 51125: "refueling", + 51126: "refund", + 51131: "refurbish", + 51132: "refurnish", + 51133: "refusal", + 51134: "refuse", + 51135: "refusing", + 51136: "refutable", + 51141: "refute", + 51142: "regain", + 51143: "regalia", + 51144: "regally", + 51145: "reggae", + 51146: "regime", + 51151: "region", + 51152: "register", + 51153: "registrar", + 51154: "registry", + 51155: "regress", + 51156: "regretful", + 51161: "regroup", + 51162: "regular", + 51163: "regulate", + 51164: "regulator", + 51165: "rehab", + 51166: "reheat", + 51211: "rehire", + 51212: "rehydrate", + 51213: "reimburse", + 51214: "reissue", + 51215: "reiterate", + 51216: "rejoice", + 51221: "rejoicing", + 51222: "rejoin", + 51223: "rekindle", + 51224: "relapse", + 51225: "relapsing", + 51226: "relatable", + 51231: "related", + 51232: "relation", + 51233: "relative", + 51234: "relax", + 51235: "relay", + 51236: "relearn", + 51241: "release", + 51242: "relenting", + 51243: "reliable", + 51244: "reliably", + 51245: "reliance", + 51246: "reliant", + 51251: "relic", + 51252: "relieve", + 51253: "relieving", + 51254: "relight", + 51255: "relish", + 51256: "relive", + 51261: "reload", + 51262: "relocate", + 51263: "relock", + 51264: "reluctant", + 51265: "rely", + 51266: "remake", + 51311: "remark", + 51312: "remarry", + 51313: "rematch", + 51314: "remedial", + 51315: "remedy", + 51316: "remember", + 51321: "reminder", + 51322: "remindful", + 51323: "remission", + 51324: "remix", + 51325: "remnant", + 51326: "remodeler", + 51331: "remold", + 51332: "remorse", + 51333: "remote", + 51334: "removable", + 51335: "removal", + 51336: "removed", + 51341: "remover", + 51342: "removing", + 51343: "rename", + 51344: "renderer", + 51345: "rendering", + 51346: "rendition", + 51351: "renegade", + 51352: "renewable", + 51353: "renewably", + 51354: "renewal", + 51355: "renewed", + 51356: "renounce", + 51361: "renovate", + 51362: "renovator", + 51363: "rentable", + 51364: "rental", + 51365: "rented", + 51366: "renter", + 51411: "reoccupy", + 51412: "reoccur", + 51413: "reopen", + 51414: "reorder", + 51415: "repackage", + 51416: "repacking", + 51421: "repaint", + 51422: "repair", + 51423: "repave", + 51424: "repaying", + 51425: "repayment", + 51426: "repeal", + 51431: "repeated", + 51432: "repeater", + 51433: "repent", + 51434: "rephrase", + 51435: "replace", + 51436: "replay", + 51441: "replica", + 51442: "reply", + 51443: "reporter", + 51444: "repose", + 51445: "repossess", + 51446: "repost", + 51451: "repressed", + 51452: "reprimand", + 51453: "reprint", + 51454: "reprise", + 51455: "reproach", + 51456: "reprocess", + 51461: "reproduce", + 51462: "reprogram", + 51463: "reps", + 51464: "reptile", + 51465: "reptilian", + 51466: "repugnant", + 51511: "repulsion", + 51512: "repulsive", + 51513: "repurpose", + 51514: "reputable", + 51515: "reputably", + 51516: "request", + 51521: "require", + 51522: "requisite", + 51523: "reroute", + 51524: "rerun", + 51525: "resale", + 51526: "resample", + 51531: "rescuer", + 51532: "reseal", + 51533: "research", + 51534: "reselect", + 51535: "reseller", + 51536: "resemble", + 51541: "resend", + 51542: "resent", + 51543: "reset", + 51544: "reshape", + 51545: "reshoot", + 51546: "reshuffle", + 51551: "residence", + 51552: "residency", + 51553: "resident", + 51554: "residual", + 51555: "residue", + 51556: "resigned", + 51561: "resilient", + 51562: "resistant", + 51563: "resisting", + 51564: "resize", + 51565: "resolute", + 51566: "resolved", + 51611: "resonant", + 51612: "resonate", + 51613: "resort", + 51614: "resource", + 51615: "respect", + 51616: "resubmit", + 51621: "result", + 51622: "resume", + 51623: "resupply", + 51624: "resurface", + 51625: "resurrect", + 51626: "retail", + 51631: "retainer", + 51632: "retaining", + 51633: "retake", + 51634: "retaliate", + 51635: "retention", + 51636: "rethink", + 51641: "retinal", + 51642: "retired", + 51643: "retiree", + 51644: "retiring", + 51645: "retold", + 51646: "retool", + 51651: "retorted", + 51652: "retouch", + 51653: "retrace", + 51654: "retract", + 51655: "retrain", + 51656: "retread", + 51661: "retreat", + 51662: "retrial", + 51663: "retrieval", + 51664: "retriever", + 51665: "retry", + 51666: "return", + 52111: "retying", + 52112: "retype", + 52113: "reunion", + 52114: "reunite", + 52115: "reusable", + 52116: "reuse", + 52121: "reveal", + 52122: "reveler", + 52123: "revenge", + 52124: "revenue", + 52125: "reverb", + 52126: "revered", + 52131: "reverence", + 52132: "reverend", + 52133: "reversal", + 52134: "reverse", + 52135: "reversing", + 52136: "reversion", + 52141: "revert", + 52142: "revisable", + 52143: "revise", + 52144: "revision", + 52145: "revisit", + 52146: "revivable", + 52151: "revival", + 52152: "reviver", + 52153: "reviving", + 52154: "revocable", + 52155: "revoke", + 52156: "revolt", + 52161: "revolver", + 52162: "revolving", + 52163: "reward", + 52164: "rewash", + 52165: "rewind", + 52166: "rewire", + 52211: "reword", + 52212: "rework", + 52213: "rewrap", + 52214: "rewrite", + 52215: "rhyme", + 52216: "ribbon", + 52221: "ribcage", + 52222: "rice", + 52223: "riches", + 52224: "richly", + 52225: "richness", + 52226: "rickety", + 52231: "ricotta", + 52232: "riddance", + 52233: "ridden", + 52234: "ride", + 52235: "riding", + 52236: "rifling", + 52241: "rift", + 52242: "rigging", + 52243: "rigid", + 52244: "rigor", + 52245: "rimless", + 52246: "rimmed", + 52251: "rind", + 52252: "rink", + 52253: "rinse", + 52254: "rinsing", + 52255: "riot", + 52256: "ripcord", + 52261: "ripeness", + 52262: "ripening", + 52263: "ripping", + 52264: "ripple", + 52265: "rippling", + 52266: "riptide", + 52311: "rise", + 52312: "rising", + 52313: "risk", + 52314: "risotto", + 52315: "ritalin", + 52316: "ritzy", + 52321: "rival", + 52322: "riverbank", + 52323: "riverbed", + 52324: "riverboat", + 52325: "riverside", + 52326: "riveter", + 52331: "riveting", + 52332: "roamer", + 52333: "roaming", + 52334: "roast", + 52335: "robbing", + 52336: "robe", + 52341: "robin", + 52342: "robotics", + 52343: "robust", + 52344: "rockband", + 52345: "rocker", + 52346: "rocket", + 52351: "rockfish", + 52352: "rockiness", + 52353: "rocking", + 52354: "rocklike", + 52355: "rockslide", + 52356: "rockstar", + 52361: "rocky", + 52362: "rogue", + 52363: "roman", + 52364: "romp", + 52365: "rope", + 52366: "roping", + 52411: "roster", + 52412: "rosy", + 52413: "rotten", + 52414: "rotting", + 52415: "rotunda", + 52416: "roulette", + 52421: "rounding", + 52422: "roundish", + 52423: "roundness", + 52424: "roundup", + 52425: "roundworm", + 52426: "routine", + 52431: "routing", + 52432: "rover", + 52433: "roving", + 52434: "royal", + 52435: "rubbed", + 52436: "rubber", + 52441: "rubbing", + 52442: "rubble", + 52443: "rubdown", + 52444: "ruby", + 52445: "ruckus", + 52446: "rudder", + 52451: "rug", + 52452: "ruined", + 52453: "rule", + 52454: "rumble", + 52455: "rumbling", + 52456: "rummage", + 52461: "rumor", + 52462: "runaround", + 52463: "rundown", + 52464: "runner", + 52465: "running", + 52466: "runny", + 52511: "runt", + 52512: "runway", + 52513: "rupture", + 52514: "rural", + 52515: "ruse", + 52516: "rush", + 52521: "rust", + 52522: "rut", + 52523: "sabbath", + 52524: "sabotage", + 52525: "sacrament", + 52526: "sacred", + 52531: "sacrifice", + 52532: "sadden", + 52533: "saddlebag", + 52534: "saddled", + 52535: "saddling", + 52536: "sadly", + 52541: "sadness", + 52542: "safari", + 52543: "safeguard", + 52544: "safehouse", + 52545: "safely", + 52546: "safeness", + 52551: "saffron", + 52552: "saga", + 52553: "sage", + 52554: "sagging", + 52555: "saggy", + 52556: "said", + 52561: "saint", + 52562: "sake", + 52563: "salad", + 52564: "salami", + 52565: "salaried", + 52566: "salary", + 52611: "saline", + 52612: "salon", + 52613: "saloon", + 52614: "salsa", + 52615: "salt", + 52616: "salutary", + 52621: "salute", + 52622: "salvage", + 52623: "salvaging", + 52624: "salvation", + 52625: "same", + 52626: "sample", + 52631: "sampling", + 52632: "sanction", + 52633: "sanctity", + 52634: "sanctuary", + 52635: "sandal", + 52636: "sandbag", + 52641: "sandbank", + 52642: "sandbar", + 52643: "sandblast", + 52644: "sandbox", + 52645: "sanded", + 52646: "sandfish", + 52651: "sanding", + 52652: "sandlot", + 52653: "sandpaper", + 52654: "sandpit", + 52655: "sandstone", + 52656: "sandstorm", + 52661: "sandworm", + 52662: "sandy", + 52663: "sanitary", + 52664: "sanitizer", + 52665: "sank", + 52666: "santa", + 53111: "sapling", + 53112: "sappiness", + 53113: "sappy", + 53114: "sarcasm", + 53115: "sarcastic", + 53116: "sardine", + 53121: "sash", + 53122: "sasquatch", + 53123: "sassy", + 53124: "satchel", + 53125: "satiable", + 53126: "satin", + 53131: "satirical", + 53132: "satisfied", + 53133: "satisfy", + 53134: "saturate", + 53135: "saturday", + 53136: "sauciness", + 53141: "saucy", + 53142: "sauna", + 53143: "savage", + 53144: "savanna", + 53145: "saved", + 53146: "savings", + 53151: "savior", + 53152: "savor", + 53153: "saxophone", + 53154: "say", + 53155: "scabbed", + 53156: "scabby", + 53161: "scalded", + 53162: "scalding", + 53163: "scale", + 53164: "scaling", + 53165: "scallion", + 53166: "scallop", + 53211: "scalping", + 53212: "scam", + 53213: "scandal", + 53214: "scanner", + 53215: "scanning", + 53216: "scant", + 53221: "scapegoat", + 53222: "scarce", + 53223: "scarcity", + 53224: "scarecrow", + 53225: "scared", + 53226: "scarf", + 53231: "scarily", + 53232: "scariness", + 53233: "scarring", + 53234: "scary", + 53235: "scavenger", + 53236: "scenic", + 53241: "schedule", + 53242: "schematic", + 53243: "scheme", + 53244: "scheming", + 53245: "schilling", + 53246: "schnapps", + 53251: "scholar", + 53252: "science", + 53253: "scientist", + 53254: "scion", + 53255: "scoff", + 53256: "scolding", + 53261: "scone", + 53262: "scoop", + 53263: "scooter", + 53264: "scope", + 53265: "scorch", + 53266: "scorebook", + 53311: "scorecard", + 53312: "scored", + 53313: "scoreless", + 53314: "scorer", + 53315: "scoring", + 53316: "scorn", + 53321: "scorpion", + 53322: "scotch", + 53323: "scoundrel", + 53324: "scoured", + 53325: "scouring", + 53326: "scouting", + 53331: "scouts", + 53332: "scowling", + 53333: "scrabble", + 53334: "scraggly", + 53335: "scrambled", + 53336: "scrambler", + 53341: "scrap", + 53342: "scratch", + 53343: "scrawny", + 53344: "screen", + 53345: "scribble", + 53346: "scribe", + 53351: "scribing", + 53352: "scrimmage", + 53353: "script", + 53354: "scroll", + 53355: "scrooge", + 53356: "scrounger", + 53361: "scrubbed", + 53362: "scrubber", + 53363: "scruffy", + 53364: "scrunch", + 53365: "scrutiny", + 53366: "scuba", + 53411: "scuff", + 53412: "sculptor", + 53413: "sculpture", + 53414: "scurvy", + 53415: "scuttle", + 53416: "secluded", + 53421: "secluding", + 53422: "seclusion", + 53423: "second", + 53424: "secrecy", + 53425: "secret", + 53426: "sectional", + 53431: "sector", + 53432: "secular", + 53433: "securely", + 53434: "security", + 53435: "sedan", + 53436: "sedate", + 53441: "sedation", + 53442: "sedative", + 53443: "sediment", + 53444: "seduce", + 53445: "seducing", + 53446: "segment", + 53451: "seismic", + 53452: "seizing", + 53453: "seldom", + 53454: "selected", + 53455: "selection", + 53456: "selective", + 53461: "selector", + 53462: "self", + 53463: "seltzer", + 53464: "semantic", + 53465: "semester", + 53466: "semicolon", + 53511: "semifinal", + 53512: "seminar", + 53513: "semisoft", + 53514: "semisweet", + 53515: "senate", + 53516: "senator", + 53521: "send", + 53522: "senior", + 53523: "senorita", + 53524: "sensation", + 53525: "sensitive", + 53526: "sensitize", + 53531: "sensually", + 53532: "sensuous", + 53533: "sepia", + 53534: "september", + 53535: "septic", + 53536: "septum", + 53541: "sequel", + 53542: "sequence", + 53543: "sequester", + 53544: "series", + 53545: "sermon", + 53546: "serotonin", + 53551: "serpent", + 53552: "serrated", + 53553: "serve", + 53554: "service", + 53555: "serving", + 53556: "sesame", + 53561: "sessions", + 53562: "setback", + 53563: "setting", + 53564: "settle", + 53565: "settling", + 53566: "setup", + 53611: "sevenfold", + 53612: "seventeen", + 53613: "seventh", + 53614: "seventy", + 53615: "severity", + 53616: "shabby", + 53621: "shack", + 53622: "shaded", + 53623: "shadily", + 53624: "shadiness", + 53625: "shading", + 53626: "shadow", + 53631: "shady", + 53632: "shaft", + 53633: "shakable", + 53634: "shakily", + 53635: "shakiness", + 53636: "shaking", + 53641: "shaky", + 53642: "shale", + 53643: "shallot", + 53644: "shallow", + 53645: "shame", + 53646: "shampoo", + 53651: "shamrock", + 53652: "shank", + 53653: "shanty", + 53654: "shape", + 53655: "shaping", + 53656: "share", + 53661: "sharpener", + 53662: "sharper", + 53663: "sharpie", + 53664: "sharply", + 53665: "sharpness", + 53666: "shawl", + 54111: "sheath", + 54112: "shed", + 54113: "sheep", + 54114: "sheet", + 54115: "shelf", + 54116: "shell", + 54121: "shelter", + 54122: "shelve", + 54123: "shelving", + 54124: "sherry", + 54125: "shield", + 54126: "shifter", + 54131: "shifting", + 54132: "shiftless", + 54133: "shifty", + 54134: "shimmer", + 54135: "shimmy", + 54136: "shindig", + 54141: "shine", + 54142: "shingle", + 54143: "shininess", + 54144: "shining", + 54145: "shiny", + 54146: "ship", + 54151: "shirt", + 54152: "shivering", + 54153: "shock", + 54154: "shone", + 54155: "shoplift", + 54156: "shopper", + 54161: "shopping", + 54162: "shoptalk", + 54163: "shore", + 54164: "shortage", + 54165: "shortcake", + 54166: "shortcut", + 54211: "shorten", + 54212: "shorter", + 54213: "shorthand", + 54214: "shortlist", + 54215: "shortly", + 54216: "shortness", + 54221: "shorts", + 54222: "shortwave", + 54223: "shorty", + 54224: "shout", + 54225: "shove", + 54226: "showbiz", + 54231: "showcase", + 54232: "showdown", + 54233: "shower", + 54234: "showgirl", + 54235: "showing", + 54236: "showman", + 54241: "shown", + 54242: "showoff", + 54243: "showpiece", + 54244: "showplace", + 54245: "showroom", + 54246: "showy", + 54251: "shrank", + 54252: "shrapnel", + 54253: "shredder", + 54254: "shredding", + 54255: "shrewdly", + 54256: "shriek", + 54261: "shrill", + 54262: "shrimp", + 54263: "shrine", + 54264: "shrink", + 54265: "shrivel", + 54266: "shrouded", + 54311: "shrubbery", + 54312: "shrubs", + 54313: "shrug", + 54314: "shrunk", + 54315: "shucking", + 54316: "shudder", + 54321: "shuffle", + 54322: "shuffling", + 54323: "shun", + 54324: "shush", + 54325: "shut", + 54326: "shy", + 54331: "siamese", + 54332: "siberian", + 54333: "sibling", + 54334: "siding", + 54335: "sierra", + 54336: "siesta", + 54341: "sift", + 54342: "sighing", + 54343: "silenced", + 54344: "silencer", + 54345: "silent", + 54346: "silica", + 54351: "silicon", + 54352: "silk", + 54353: "silliness", + 54354: "silly", + 54355: "silo", + 54356: "silt", + 54361: "silver", + 54362: "similarly", + 54363: "simile", + 54364: "simmering", + 54365: "simple", + 54366: "simplify", + 54411: "simply", + 54412: "sincere", + 54413: "sincerity", + 54414: "singer", + 54415: "singing", + 54416: "single", + 54421: "singular", + 54422: "sinister", + 54423: "sinless", + 54424: "sinner", + 54425: "sinuous", + 54426: "sip", + 54431: "siren", + 54432: "sister", + 54433: "sitcom", + 54434: "sitter", + 54435: "sitting", + 54436: "situated", + 54441: "situation", + 54442: "sixfold", + 54443: "sixteen", + 54444: "sixth", + 54445: "sixties", + 54446: "sixtieth", + 54451: "sixtyfold", + 54452: "sizable", + 54453: "sizably", + 54454: "size", + 54455: "sizing", + 54456: "sizzle", + 54461: "sizzling", + 54462: "skater", + 54463: "skating", + 54464: "skedaddle", + 54465: "skeletal", + 54466: "skeleton", + 54511: "skeptic", + 54512: "sketch", + 54513: "skewed", + 54514: "skewer", + 54515: "skid", + 54516: "skied", + 54521: "skier", + 54522: "skies", + 54523: "skiing", + 54524: "skilled", + 54525: "skillet", + 54526: "skillful", + 54531: "skimmed", + 54532: "skimmer", + 54533: "skimming", + 54534: "skimpily", + 54535: "skincare", + 54536: "skinhead", + 54541: "skinless", + 54542: "skinning", + 54543: "skinny", + 54544: "skintight", + 54545: "skipper", + 54546: "skipping", + 54551: "skirmish", + 54552: "skirt", + 54553: "skittle", + 54554: "skydiver", + 54555: "skylight", + 54556: "skyline", + 54561: "skype", + 54562: "skyrocket", + 54563: "skyward", + 54564: "slab", + 54565: "slacked", + 54566: "slacker", + 54611: "slacking", + 54612: "slackness", + 54613: "slacks", + 54614: "slain", + 54615: "slam", + 54616: "slander", + 54621: "slang", + 54622: "slapping", + 54623: "slapstick", + 54624: "slashed", + 54625: "slashing", + 54626: "slate", + 54631: "slather", + 54632: "slaw", + 54633: "sled", + 54634: "sleek", + 54635: "sleep", + 54636: "sleet", + 54641: "sleeve", + 54642: "slept", + 54643: "sliceable", + 54644: "sliced", + 54645: "slicer", + 54646: "slicing", + 54651: "slick", + 54652: "slider", + 54653: "slideshow", + 54654: "sliding", + 54655: "slighted", + 54656: "slighting", + 54661: "slightly", + 54662: "slimness", + 54663: "slimy", + 54664: "slinging", + 54665: "slingshot", + 54666: "slinky", + 55111: "slip", + 55112: "slit", + 55113: "sliver", + 55114: "slobbery", + 55115: "slogan", + 55116: "sloped", + 55121: "sloping", + 55122: "sloppily", + 55123: "sloppy", + 55124: "slot", + 55125: "slouching", + 55126: "slouchy", + 55131: "sludge", + 55132: "slug", + 55133: "slum", + 55134: "slurp", + 55135: "slush", + 55136: "sly", + 55141: "small", + 55142: "smartly", + 55143: "smartness", + 55144: "smasher", + 55145: "smashing", + 55146: "smashup", + 55151: "smell", + 55152: "smelting", + 55153: "smile", + 55154: "smilingly", + 55155: "smirk", + 55156: "smite", + 55161: "smith", + 55162: "smitten", + 55163: "smock", + 55164: "smog", + 55165: "smoked", + 55166: "smokeless", + 55211: "smokiness", + 55212: "smoking", + 55213: "smoky", + 55214: "smolder", + 55215: "smooth", + 55216: "smother", + 55221: "smudge", + 55222: "smudgy", + 55223: "smuggler", + 55224: "smuggling", + 55225: "smugly", + 55226: "smugness", + 55231: "snack", + 55232: "snagged", + 55233: "snaking", + 55234: "snap", + 55235: "snare", + 55236: "snarl", + 55241: "snazzy", + 55242: "sneak", + 55243: "sneer", + 55244: "sneeze", + 55245: "sneezing", + 55246: "snide", + 55251: "sniff", + 55252: "snippet", + 55253: "snipping", + 55254: "snitch", + 55255: "snooper", + 55256: "snooze", + 55261: "snore", + 55262: "snoring", + 55263: "snorkel", + 55264: "snort", + 55265: "snout", + 55266: "snowbird", + 55311: "snowboard", + 55312: "snowbound", + 55313: "snowcap", + 55314: "snowdrift", + 55315: "snowdrop", + 55316: "snowfall", + 55321: "snowfield", + 55322: "snowflake", + 55323: "snowiness", + 55324: "snowless", + 55325: "snowman", + 55326: "snowplow", + 55331: "snowshoe", + 55332: "snowstorm", + 55333: "snowsuit", + 55334: "snowy", + 55335: "snub", + 55336: "snuff", + 55341: "snuggle", + 55342: "snugly", + 55343: "snugness", + 55344: "speak", + 55345: "spearfish", + 55346: "spearhead", + 55351: "spearman", + 55352: "spearmint", + 55353: "species", + 55354: "specimen", + 55355: "specked", + 55356: "speckled", + 55361: "specks", + 55362: "spectacle", + 55363: "spectator", + 55364: "spectrum", + 55365: "speculate", + 55366: "speech", + 55411: "speed", + 55412: "spellbind", + 55413: "speller", + 55414: "spelling", + 55415: "spendable", + 55416: "spender", + 55421: "spending", + 55422: "spent", + 55423: "spew", + 55424: "sphere", + 55425: "spherical", + 55426: "sphinx", + 55431: "spider", + 55432: "spied", + 55433: "spiffy", + 55434: "spill", + 55435: "spilt", + 55436: "spinach", + 55441: "spinal", + 55442: "spindle", + 55443: "spinner", + 55444: "spinning", + 55445: "spinout", + 55446: "spinster", + 55451: "spiny", + 55452: "spiral", + 55453: "spirited", + 55454: "spiritism", + 55455: "spirits", + 55456: "spiritual", + 55461: "splashed", + 55462: "splashing", + 55463: "splashy", + 55464: "splatter", + 55465: "spleen", + 55466: "splendid", + 55511: "splendor", + 55512: "splice", + 55513: "splicing", + 55514: "splinter", + 55515: "splotchy", + 55516: "splurge", + 55521: "spoilage", + 55522: "spoiled", + 55523: "spoiler", + 55524: "spoiling", + 55525: "spoils", + 55526: "spoken", + 55531: "spokesman", + 55532: "sponge", + 55533: "spongy", + 55534: "sponsor", + 55535: "spoof", + 55536: "spookily", + 55541: "spooky", + 55542: "spool", + 55543: "spoon", + 55544: "spore", + 55545: "sporting", + 55546: "sports", + 55551: "sporty", + 55552: "spotless", + 55553: "spotlight", + 55554: "spotted", + 55555: "spotter", + 55556: "spotting", + 55561: "spotty", + 55562: "spousal", + 55563: "spouse", + 55564: "spout", + 55565: "sprain", + 55566: "sprang", + 55611: "sprawl", + 55612: "spray", + 55613: "spree", + 55614: "sprig", + 55615: "spring", + 55616: "sprinkled", + 55621: "sprinkler", + 55622: "sprint", + 55623: "sprite", + 55624: "sprout", + 55625: "spruce", + 55626: "sprung", + 55631: "spry", + 55632: "spud", + 55633: "spur", + 55634: "sputter", + 55635: "spyglass", + 55636: "squabble", + 55641: "squad", + 55642: "squall", + 55643: "squander", + 55644: "squash", + 55645: "squatted", + 55646: "squatter", + 55651: "squatting", + 55652: "squeak", + 55653: "squealer", + 55654: "squealing", + 55655: "squeamish", + 55656: "squeegee", + 55661: "squeeze", + 55662: "squeezing", + 55663: "squid", + 55664: "squiggle", + 55665: "squiggly", + 55666: "squint", + 56111: "squire", + 56112: "squirt", + 56113: "squishier", + 56114: "squishy", + 56115: "stability", + 56116: "stabilize", + 56121: "stable", + 56122: "stack", + 56123: "stadium", + 56124: "staff", + 56125: "stage", + 56126: "staging", + 56131: "stagnant", + 56132: "stagnate", + 56133: "stainable", + 56134: "stained", + 56135: "staining", + 56136: "stainless", + 56141: "stalemate", + 56142: "staleness", + 56143: "stalling", + 56144: "stallion", + 56145: "stamina", + 56146: "stammer", + 56151: "stamp", + 56152: "stand", + 56153: "stank", + 56154: "staple", + 56155: "stapling", + 56156: "starboard", + 56161: "starch", + 56162: "stardom", + 56163: "stardust", + 56164: "starfish", + 56165: "stargazer", + 56166: "staring", + 56211: "stark", + 56212: "starless", + 56213: "starlet", + 56214: "starlight", + 56215: "starlit", + 56216: "starring", + 56221: "starry", + 56222: "starship", + 56223: "starter", + 56224: "starting", + 56225: "startle", + 56226: "startling", + 56231: "startup", + 56232: "starved", + 56233: "starving", + 56234: "stash", + 56235: "state", + 56236: "static", + 56241: "statistic", + 56242: "statue", + 56243: "stature", + 56244: "status", + 56245: "statute", + 56246: "statutory", + 56251: "staunch", + 56252: "stays", + 56253: "steadfast", + 56254: "steadier", + 56255: "steadily", + 56256: "steadying", + 56261: "steam", + 56262: "steed", + 56263: "steep", + 56264: "steerable", + 56265: "steering", + 56266: "steersman", + 56311: "stegosaur", + 56312: "stellar", + 56313: "stem", + 56314: "stench", + 56315: "stencil", + 56316: "step", + 56321: "stereo", + 56322: "sterile", + 56323: "sterility", + 56324: "sterilize", + 56325: "sterling", + 56326: "sternness", + 56331: "sternum", + 56332: "stew", + 56333: "stick", + 56334: "stiffen", + 56335: "stiffly", + 56336: "stiffness", + 56341: "stifle", + 56342: "stifling", + 56343: "stillness", + 56344: "stilt", + 56345: "stimulant", + 56346: "stimulate", + 56351: "stimuli", + 56352: "stimulus", + 56353: "stinger", + 56354: "stingily", + 56355: "stinging", + 56356: "stingray", + 56361: "stingy", + 56362: "stinking", + 56363: "stinky", + 56364: "stipend", + 56365: "stipulate", + 56366: "stir", + 56411: "stitch", + 56412: "stock", + 56413: "stoic", + 56414: "stoke", + 56415: "stole", + 56416: "stomp", + 56421: "stonewall", + 56422: "stoneware", + 56423: "stonework", + 56424: "stoning", + 56425: "stony", + 56426: "stood", + 56431: "stooge", + 56432: "stool", + 56433: "stoop", + 56434: "stoplight", + 56435: "stoppable", + 56436: "stoppage", + 56441: "stopped", + 56442: "stopper", + 56443: "stopping", + 56444: "stopwatch", + 56445: "storable", + 56446: "storage", + 56451: "storeroom", + 56452: "storewide", + 56453: "storm", + 56454: "stout", + 56455: "stove", + 56456: "stowaway", + 56461: "stowing", + 56462: "straddle", + 56463: "straggler", + 56464: "strained", + 56465: "strainer", + 56466: "straining", + 56511: "strangely", + 56512: "stranger", + 56513: "strangle", + 56514: "strategic", + 56515: "strategy", + 56516: "stratus", + 56521: "straw", + 56522: "stray", + 56523: "streak", + 56524: "stream", + 56525: "street", + 56526: "strength", + 56531: "strenuous", + 56532: "strep", + 56533: "stress", + 56534: "stretch", + 56535: "strewn", + 56536: "stricken", + 56541: "strict", + 56542: "stride", + 56543: "strife", + 56544: "strike", + 56545: "striking", + 56546: "strive", + 56551: "striving", + 56552: "strobe", + 56553: "strode", + 56554: "stroller", + 56555: "strongbox", + 56556: "strongly", + 56561: "strongman", + 56562: "struck", + 56563: "structure", + 56564: "strudel", + 56565: "struggle", + 56566: "strum", + 56611: "strung", + 56612: "strut", + 56613: "stubbed", + 56614: "stubble", + 56615: "stubbly", + 56616: "stubborn", + 56621: "stucco", + 56622: "stuck", + 56623: "student", + 56624: "studied", + 56625: "studio", + 56626: "study", + 56631: "stuffed", + 56632: "stuffing", + 56633: "stuffy", + 56634: "stumble", + 56635: "stumbling", + 56636: "stump", + 56641: "stung", + 56642: "stunned", + 56643: "stunner", + 56644: "stunning", + 56645: "stunt", + 56646: "stupor", + 56651: "sturdily", + 56652: "sturdy", + 56653: "styling", + 56654: "stylishly", + 56655: "stylist", + 56656: "stylized", + 56661: "stylus", + 56662: "suave", + 56663: "subarctic", + 56664: "subatomic", + 56665: "subdivide", + 56666: "subdued", + 61111: "subduing", + 61112: "subfloor", + 61113: "subgroup", + 61114: "subheader", + 61115: "subject", + 61116: "sublease", + 61121: "sublet", + 61122: "sublevel", + 61123: "sublime", + 61124: "submarine", + 61125: "submerge", + 61126: "submersed", + 61131: "submitter", + 61132: "subpanel", + 61133: "subpar", + 61134: "subplot", + 61135: "subprime", + 61136: "subscribe", + 61141: "subscript", + 61142: "subsector", + 61143: "subside", + 61144: "subsiding", + 61145: "subsidize", + 61146: "subsidy", + 61151: "subsoil", + 61152: "subsonic", + 61153: "substance", + 61154: "subsystem", + 61155: "subtext", + 61156: "subtitle", + 61161: "subtly", + 61162: "subtotal", + 61163: "subtract", + 61164: "subtype", + 61165: "suburb", + 61166: "subway", + 61211: "subwoofer", + 61212: "subzero", + 61213: "succulent", + 61214: "such", + 61215: "suction", + 61216: "sudden", + 61221: "sudoku", + 61222: "suds", + 61223: "sufferer", + 61224: "suffering", + 61225: "suffice", + 61226: "suffix", + 61231: "suffocate", + 61232: "suffrage", + 61233: "sugar", + 61234: "suggest", + 61235: "suing", + 61236: "suitable", + 61241: "suitably", + 61242: "suitcase", + 61243: "suitor", + 61244: "sulfate", + 61245: "sulfide", + 61246: "sulfite", + 61251: "sulfur", + 61252: "sulk", + 61253: "sullen", + 61254: "sulphate", + 61255: "sulphuric", + 61256: "sultry", + 61261: "superbowl", + 61262: "superglue", + 61263: "superhero", + 61264: "superior", + 61265: "superjet", + 61266: "superman", + 61311: "supermom", + 61312: "supernova", + 61313: "supervise", + 61314: "supper", + 61315: "supplier", + 61316: "supply", + 61321: "support", + 61322: "supremacy", + 61323: "supreme", + 61324: "surcharge", + 61325: "surely", + 61326: "sureness", + 61331: "surface", + 61332: "surfacing", + 61333: "surfboard", + 61334: "surfer", + 61335: "surgery", + 61336: "surgical", + 61341: "surging", + 61342: "surname", + 61343: "surpass", + 61344: "surplus", + 61345: "surprise", + 61346: "surreal", + 61351: "surrender", + 61352: "surrogate", + 61353: "surround", + 61354: "survey", + 61355: "survival", + 61356: "survive", + 61361: "surviving", + 61362: "survivor", + 61363: "sushi", + 61364: "suspect", + 61365: "suspend", + 61366: "suspense", + 61411: "sustained", + 61412: "sustainer", + 61413: "swab", + 61414: "swaddling", + 61415: "swagger", + 61416: "swampland", + 61421: "swan", + 61422: "swapping", + 61423: "swarm", + 61424: "sway", + 61425: "swear", + 61426: "sweat", + 61431: "sweep", + 61432: "swell", + 61433: "swept", + 61434: "swerve", + 61435: "swifter", + 61436: "swiftly", + 61441: "swiftness", + 61442: "swimmable", + 61443: "swimmer", + 61444: "swimming", + 61445: "swimsuit", + 61446: "swimwear", + 61451: "swinger", + 61452: "swinging", + 61453: "swipe", + 61454: "swirl", + 61455: "switch", + 61456: "swivel", + 61461: "swizzle", + 61462: "swooned", + 61463: "swoop", + 61464: "swoosh", + 61465: "swore", + 61466: "sworn", + 61511: "swung", + 61512: "sycamore", + 61513: "sympathy", + 61514: "symphonic", + 61515: "symphony", + 61516: "symptom", + 61521: "synapse", + 61522: "syndrome", + 61523: "synergy", + 61524: "synopses", + 61525: "synopsis", + 61526: "synthesis", + 61531: "synthetic", + 61532: "syrup", + 61533: "system", + 61534: "t-shirt", + 61535: "tabasco", + 61536: "tabby", + 61541: "tableful", + 61542: "tables", + 61543: "tablet", + 61544: "tableware", + 61545: "tabloid", + 61546: "tackiness", + 61551: "tacking", + 61552: "tackle", + 61553: "tackling", + 61554: "tacky", + 61555: "taco", + 61556: "tactful", + 61561: "tactical", + 61562: "tactics", + 61563: "tactile", + 61564: "tactless", + 61565: "tadpole", + 61566: "taekwondo", + 61611: "tag", + 61612: "tainted", + 61613: "take", + 61614: "taking", + 61615: "talcum", + 61616: "talisman", + 61621: "tall", + 61622: "talon", + 61623: "tamale", + 61624: "tameness", + 61625: "tamer", + 61626: "tamper", + 61631: "tank", + 61632: "tanned", + 61633: "tannery", + 61634: "tanning", + 61635: "tantrum", + 61636: "tapeless", + 61641: "tapered", + 61642: "tapering", + 61643: "tapestry", + 61644: "tapioca", + 61645: "tapping", + 61646: "taps", + 61651: "tarantula", + 61652: "target", + 61653: "tarmac", + 61654: "tarnish", + 61655: "tarot", + 61656: "tartar", + 61661: "tartly", + 61662: "tartness", + 61663: "task", + 61664: "tassel", + 61665: "taste", + 61666: "tastiness", + 62111: "tasting", + 62112: "tasty", + 62113: "tattered", + 62114: "tattle", + 62115: "tattling", + 62116: "tattoo", + 62121: "taunt", + 62122: "tavern", + 62123: "thank", + 62124: "that", + 62125: "thaw", + 62126: "theater", + 62131: "theatrics", + 62132: "thee", + 62133: "theft", + 62134: "theme", + 62135: "theology", + 62136: "theorize", + 62141: "thermal", + 62142: "thermos", + 62143: "thesaurus", + 62144: "these", + 62145: "thesis", + 62146: "thespian", + 62151: "thicken", + 62152: "thicket", + 62153: "thickness", + 62154: "thieving", + 62155: "thievish", + 62156: "thigh", + 62161: "thimble", + 62162: "thing", + 62163: "think", + 62164: "thinly", + 62165: "thinner", + 62166: "thinness", + 62211: "thinning", + 62212: "thirstily", + 62213: "thirsting", + 62214: "thirsty", + 62215: "thirteen", + 62216: "thirty", + 62221: "thong", + 62222: "thorn", + 62223: "those", + 62224: "thousand", + 62225: "thrash", + 62226: "thread", + 62231: "threaten", + 62232: "threefold", + 62233: "thrift", + 62234: "thrill", + 62235: "thrive", + 62236: "thriving", + 62241: "throat", + 62242: "throbbing", + 62243: "throng", + 62244: "throttle", + 62245: "throwaway", + 62246: "throwback", + 62251: "thrower", + 62252: "throwing", + 62253: "thud", + 62254: "thumb", + 62255: "thumping", + 62256: "thursday", + 62261: "thus", + 62262: "thwarting", + 62263: "thyself", + 62264: "tiara", + 62265: "tibia", + 62266: "tidal", + 62311: "tidbit", + 62312: "tidiness", + 62313: "tidings", + 62314: "tidy", + 62315: "tiger", + 62316: "tighten", + 62321: "tightly", + 62322: "tightness", + 62323: "tightrope", + 62324: "tightwad", + 62325: "tigress", + 62326: "tile", + 62331: "tiling", + 62332: "till", + 62333: "tilt", + 62334: "timid", + 62335: "timing", + 62336: "timothy", + 62341: "tinderbox", + 62342: "tinfoil", + 62343: "tingle", + 62344: "tingling", + 62345: "tingly", + 62346: "tinker", + 62351: "tinkling", + 62352: "tinsel", + 62353: "tinsmith", + 62354: "tint", + 62355: "tinwork", + 62356: "tiny", + 62361: "tipoff", + 62362: "tipped", + 62363: "tipper", + 62364: "tipping", + 62365: "tiptoeing", + 62366: "tiptop", + 62411: "tiring", + 62412: "tissue", + 62413: "trace", + 62414: "tracing", + 62415: "track", + 62416: "traction", + 62421: "tractor", + 62422: "trade", + 62423: "trading", + 62424: "tradition", + 62425: "traffic", + 62426: "tragedy", + 62431: "trailing", + 62432: "trailside", + 62433: "train", + 62434: "traitor", + 62435: "trance", + 62436: "tranquil", + 62441: "transfer", + 62442: "transform", + 62443: "translate", + 62444: "transpire", + 62445: "transport", + 62446: "transpose", + 62451: "trapdoor", + 62452: "trapeze", + 62453: "trapezoid", + 62454: "trapped", + 62455: "trapper", + 62456: "trapping", + 62461: "traps", + 62462: "trash", + 62463: "travel", + 62464: "traverse", + 62465: "travesty", + 62466: "tray", + 62511: "treachery", + 62512: "treading", + 62513: "treadmill", + 62514: "treason", + 62515: "treat", + 62516: "treble", + 62521: "tree", + 62522: "trekker", + 62523: "tremble", + 62524: "trembling", + 62525: "tremor", + 62526: "trench", + 62531: "trend", + 62532: "trespass", + 62533: "triage", + 62534: "trial", + 62535: "triangle", + 62536: "tribesman", + 62541: "tribunal", + 62542: "tribune", + 62543: "tributary", + 62544: "tribute", + 62545: "triceps", + 62546: "trickery", + 62551: "trickily", + 62552: "tricking", + 62553: "trickle", + 62554: "trickster", + 62555: "tricky", + 62556: "tricolor", + 62561: "tricycle", + 62562: "trident", + 62563: "tried", + 62564: "trifle", + 62565: "trifocals", + 62566: "trillion", + 62611: "trilogy", + 62612: "trimester", + 62613: "trimmer", + 62614: "trimming", + 62615: "trimness", + 62616: "trinity", + 62621: "trio", + 62622: "tripod", + 62623: "tripping", + 62624: "triumph", + 62625: "trivial", + 62626: "trodden", + 62631: "trolling", + 62632: "trombone", + 62633: "trophy", + 62634: "tropical", + 62635: "tropics", + 62636: "trouble", + 62641: "troubling", + 62642: "trough", + 62643: "trousers", + 62644: "trout", + 62645: "trowel", + 62646: "truce", + 62651: "truck", + 62652: "truffle", + 62653: "trump", + 62654: "trunks", + 62655: "trustable", + 62656: "trustee", + 62661: "trustful", + 62662: "trusting", + 62663: "trustless", + 62664: "truth", + 62665: "try", + 62666: "tubby", + 63111: "tubeless", + 63112: "tubular", + 63113: "tucking", + 63114: "tuesday", + 63115: "tug", + 63116: "tuition", + 63121: "tulip", + 63122: "tumble", + 63123: "tumbling", + 63124: "tummy", + 63125: "turban", + 63126: "turbine", + 63131: "turbofan", + 63132: "turbojet", + 63133: "turbulent", + 63134: "turf", + 63135: "turkey", + 63136: "turmoil", + 63141: "turret", + 63142: "turtle", + 63143: "tusk", + 63144: "tutor", + 63145: "tutu", + 63146: "tux", + 63151: "tweak", + 63152: "tweed", + 63153: "tweet", + 63154: "tweezers", + 63155: "twelve", + 63156: "twentieth", + 63161: "twenty", + 63162: "twerp", + 63163: "twice", + 63164: "twiddle", + 63165: "twiddling", + 63166: "twig", + 63211: "twilight", + 63212: "twine", + 63213: "twins", + 63214: "twirl", + 63215: "twistable", + 63216: "twisted", + 63221: "twister", + 63222: "twisting", + 63223: "twisty", + 63224: "twitch", + 63225: "twitter", + 63226: "tycoon", + 63231: "tying", + 63232: "tyke", + 63233: "udder", + 63234: "ultimate", + 63235: "ultimatum", + 63236: "ultra", + 63241: "umbilical", + 63242: "umbrella", + 63243: "umpire", + 63244: "unabashed", + 63245: "unable", + 63246: "unadorned", + 63251: "unadvised", + 63252: "unafraid", + 63253: "unaired", + 63254: "unaligned", + 63255: "unaltered", + 63256: "unarmored", + 63261: "unashamed", + 63262: "unaudited", + 63263: "unawake", + 63264: "unaware", + 63265: "unbaked", + 63266: "unbalance", + 63311: "unbeaten", + 63312: "unbend", + 63313: "unbent", + 63314: "unbiased", + 63315: "unbitten", + 63316: "unblended", + 63321: "unblessed", + 63322: "unblock", + 63323: "unbolted", + 63324: "unbounded", + 63325: "unboxed", + 63326: "unbraided", + 63331: "unbridle", + 63332: "unbroken", + 63333: "unbuckled", + 63334: "unbundle", + 63335: "unburned", + 63336: "unbutton", + 63341: "uncanny", + 63342: "uncapped", + 63343: "uncaring", + 63344: "uncertain", + 63345: "unchain", + 63346: "unchanged", + 63351: "uncharted", + 63352: "uncheck", + 63353: "uncivil", + 63354: "unclad", + 63355: "unclaimed", + 63356: "unclamped", + 63361: "unclasp", + 63362: "uncle", + 63363: "unclip", + 63364: "uncloak", + 63365: "unclog", + 63366: "unclothed", + 63411: "uncoated", + 63412: "uncoiled", + 63413: "uncolored", + 63414: "uncombed", + 63415: "uncommon", + 63416: "uncooked", + 63421: "uncork", + 63422: "uncorrupt", + 63423: "uncounted", + 63424: "uncouple", + 63425: "uncouth", + 63426: "uncover", + 63431: "uncross", + 63432: "uncrown", + 63433: "uncrushed", + 63434: "uncured", + 63435: "uncurious", + 63436: "uncurled", + 63441: "uncut", + 63442: "undamaged", + 63443: "undated", + 63444: "undaunted", + 63445: "undead", + 63446: "undecided", + 63451: "undefined", + 63452: "underage", + 63453: "underarm", + 63454: "undercoat", + 63455: "undercook", + 63456: "undercut", + 63461: "underdog", + 63462: "underdone", + 63463: "underfed", + 63464: "underfeed", + 63465: "underfoot", + 63466: "undergo", + 63511: "undergrad", + 63512: "underhand", + 63513: "underline", + 63514: "underling", + 63515: "undermine", + 63516: "undermost", + 63521: "underpaid", + 63522: "underpass", + 63523: "underpay", + 63524: "underrate", + 63525: "undertake", + 63526: "undertone", + 63531: "undertook", + 63532: "undertow", + 63533: "underuse", + 63534: "underwear", + 63535: "underwent", + 63536: "underwire", + 63541: "undesired", + 63542: "undiluted", + 63543: "undivided", + 63544: "undocked", + 63545: "undoing", + 63546: "undone", + 63551: "undrafted", + 63552: "undress", + 63553: "undrilled", + 63554: "undusted", + 63555: "undying", + 63556: "unearned", + 63561: "unearth", + 63562: "unease", + 63563: "uneasily", + 63564: "uneasy", + 63565: "uneatable", + 63566: "uneaten", + 63611: "unedited", + 63612: "unelected", + 63613: "unending", + 63614: "unengaged", + 63615: "unenvied", + 63616: "unequal", + 63621: "unethical", + 63622: "uneven", + 63623: "unexpired", + 63624: "unexposed", + 63625: "unfailing", + 63626: "unfair", + 63631: "unfasten", + 63632: "unfazed", + 63633: "unfeeling", + 63634: "unfiled", + 63635: "unfilled", + 63636: "unfitted", + 63641: "unfitting", + 63642: "unfixable", + 63643: "unfixed", + 63644: "unflawed", + 63645: "unfocused", + 63646: "unfold", + 63651: "unfounded", + 63652: "unframed", + 63653: "unfreeze", + 63654: "unfrosted", + 63655: "unfrozen", + 63656: "unfunded", + 63661: "unglazed", + 63662: "ungloved", + 63663: "unglue", + 63664: "ungodly", + 63665: "ungraded", + 63666: "ungreased", + 64111: "unguarded", + 64112: "unguided", + 64113: "unhappily", + 64114: "unhappy", + 64115: "unharmed", + 64116: "unhealthy", + 64121: "unheard", + 64122: "unhearing", + 64123: "unheated", + 64124: "unhelpful", + 64125: "unhidden", + 64126: "unhinge", + 64131: "unhitched", + 64132: "unholy", + 64133: "unhook", + 64134: "unicorn", + 64135: "unicycle", + 64136: "unified", + 64141: "unifier", + 64142: "uniformed", + 64143: "uniformly", + 64144: "unify", + 64145: "unimpeded", + 64146: "uninjured", + 64151: "uninstall", + 64152: "uninsured", + 64153: "uninvited", + 64154: "union", + 64155: "uniquely", + 64156: "unisexual", + 64161: "unison", + 64162: "unissued", + 64163: "unit", + 64164: "universal", + 64165: "universe", + 64166: "unjustly", + 64211: "unkempt", + 64212: "unkind", + 64213: "unknotted", + 64214: "unknowing", + 64215: "unknown", + 64216: "unlaced", + 64221: "unlatch", + 64222: "unlawful", + 64223: "unleaded", + 64224: "unlearned", + 64225: "unleash", + 64226: "unless", + 64231: "unleveled", + 64232: "unlighted", + 64233: "unlikable", + 64234: "unlimited", + 64235: "unlined", + 64236: "unlinked", + 64241: "unlisted", + 64242: "unlit", + 64243: "unlivable", + 64244: "unloaded", + 64245: "unloader", + 64246: "unlocked", + 64251: "unlocking", + 64252: "unlovable", + 64253: "unloved", + 64254: "unlovely", + 64255: "unloving", + 64256: "unluckily", + 64261: "unlucky", + 64262: "unmade", + 64263: "unmanaged", + 64264: "unmanned", + 64265: "unmapped", + 64266: "unmarked", + 64311: "unmasked", + 64312: "unmasking", + 64313: "unmatched", + 64314: "unmindful", + 64315: "unmixable", + 64316: "unmixed", + 64321: "unmolded", + 64322: "unmoral", + 64323: "unmovable", + 64324: "unmoved", + 64325: "unmoving", + 64326: "unnamable", + 64331: "unnamed", + 64332: "unnatural", + 64333: "unneeded", + 64334: "unnerve", + 64335: "unnerving", + 64336: "unnoticed", + 64341: "unopened", + 64342: "unopposed", + 64343: "unpack", + 64344: "unpadded", + 64345: "unpaid", + 64346: "unpainted", + 64351: "unpaired", + 64352: "unpaved", + 64353: "unpeeled", + 64354: "unpicked", + 64355: "unpiloted", + 64356: "unpinned", + 64361: "unplanned", + 64362: "unplanted", + 64363: "unpleased", + 64364: "unpledged", + 64365: "unplowed", + 64366: "unplug", + 64411: "unpopular", + 64412: "unproven", + 64413: "unquote", + 64414: "unranked", + 64415: "unrated", + 64416: "unraveled", + 64421: "unreached", + 64422: "unread", + 64423: "unreal", + 64424: "unreeling", + 64425: "unrefined", + 64426: "unrelated", + 64431: "unrented", + 64432: "unrest", + 64433: "unretired", + 64434: "unrevised", + 64435: "unrigged", + 64436: "unripe", + 64441: "unrivaled", + 64442: "unroasted", + 64443: "unrobed", + 64444: "unroll", + 64445: "unruffled", + 64446: "unruly", + 64451: "unrushed", + 64452: "unsaddle", + 64453: "unsafe", + 64454: "unsaid", + 64455: "unsalted", + 64456: "unsaved", + 64461: "unsavory", + 64462: "unscathed", + 64463: "unscented", + 64464: "unscrew", + 64465: "unsealed", + 64466: "unseated", + 64511: "unsecured", + 64512: "unseeing", + 64513: "unseemly", + 64514: "unseen", + 64515: "unselect", + 64516: "unselfish", + 64521: "unsent", + 64522: "unsettled", + 64523: "unshackle", + 64524: "unshaken", + 64525: "unshaved", + 64526: "unshaven", + 64531: "unsheathe", + 64532: "unshipped", + 64533: "unsightly", + 64534: "unsigned", + 64535: "unskilled", + 64536: "unsliced", + 64541: "unsmooth", + 64542: "unsnap", + 64543: "unsocial", + 64544: "unsoiled", + 64545: "unsold", + 64546: "unsolved", + 64551: "unsorted", + 64552: "unspoiled", + 64553: "unspoken", + 64554: "unstable", + 64555: "unstaffed", + 64556: "unstamped", + 64561: "unsteady", + 64562: "unsterile", + 64563: "unstirred", + 64564: "unstitch", + 64565: "unstopped", + 64566: "unstuck", + 64611: "unstuffed", + 64612: "unstylish", + 64613: "unsubtle", + 64614: "unsubtly", + 64615: "unsuited", + 64616: "unsure", + 64621: "unsworn", + 64622: "untagged", + 64623: "untainted", + 64624: "untaken", + 64625: "untamed", + 64626: "untangled", + 64631: "untapped", + 64632: "untaxed", + 64633: "unthawed", + 64634: "unthread", + 64635: "untidy", + 64636: "untie", + 64641: "until", + 64642: "untimed", + 64643: "untimely", + 64644: "untitled", + 64645: "untoasted", + 64646: "untold", + 64651: "untouched", + 64652: "untracked", + 64653: "untrained", + 64654: "untreated", + 64655: "untried", + 64656: "untrimmed", + 64661: "untrue", + 64662: "untruth", + 64663: "unturned", + 64664: "untwist", + 64665: "untying", + 64666: "unusable", + 65111: "unused", + 65112: "unusual", + 65113: "unvalued", + 65114: "unvaried", + 65115: "unvarying", + 65116: "unveiled", + 65121: "unveiling", + 65122: "unvented", + 65123: "unviable", + 65124: "unvisited", + 65125: "unvocal", + 65126: "unwanted", + 65131: "unwarlike", + 65132: "unwary", + 65133: "unwashed", + 65134: "unwatched", + 65135: "unweave", + 65136: "unwed", + 65141: "unwelcome", + 65142: "unwell", + 65143: "unwieldy", + 65144: "unwilling", + 65145: "unwind", + 65146: "unwired", + 65151: "unwitting", + 65152: "unwomanly", + 65153: "unworldly", + 65154: "unworn", + 65155: "unworried", + 65156: "unworthy", + 65161: "unwound", + 65162: "unwoven", + 65163: "unwrapped", + 65164: "unwritten", + 65165: "unzip", + 65166: "upbeat", + 65211: "upchuck", + 65212: "upcoming", + 65213: "upcountry", + 65214: "update", + 65215: "upfront", + 65216: "upgrade", + 65221: "upheaval", + 65222: "upheld", + 65223: "uphill", + 65224: "uphold", + 65225: "uplifted", + 65226: "uplifting", + 65231: "upload", + 65232: "upon", + 65233: "upper", + 65234: "upright", + 65235: "uprising", + 65236: "upriver", + 65241: "uproar", + 65242: "uproot", + 65243: "upscale", + 65244: "upside", + 65245: "upstage", + 65246: "upstairs", + 65251: "upstart", + 65252: "upstate", + 65253: "upstream", + 65254: "upstroke", + 65255: "upswing", + 65256: "uptake", + 65261: "uptight", + 65262: "uptown", + 65263: "upturned", + 65264: "upward", + 65265: "upwind", + 65266: "uranium", + 65311: "urban", + 65312: "urchin", + 65313: "urethane", + 65314: "urgency", + 65315: "urgent", + 65316: "urging", + 65321: "urologist", + 65322: "urology", + 65323: "usable", + 65324: "usage", + 65325: "useable", + 65326: "used", + 65331: "uselessly", + 65332: "user", + 65333: "usher", + 65334: "usual", + 65335: "utensil", + 65336: "utility", + 65341: "utilize", + 65342: "utmost", + 65343: "utopia", + 65344: "utter", + 65345: "vacancy", + 65346: "vacant", + 65351: "vacate", + 65352: "vacation", + 65353: "vagabond", + 65354: "vagrancy", + 65355: "vagrantly", + 65356: "vaguely", + 65361: "vagueness", + 65362: "valiant", + 65363: "valid", + 65364: "valium", + 65365: "valley", + 65366: "valuables", + 65411: "value", + 65412: "vanilla", + 65413: "vanish", + 65414: "vanity", + 65415: "vanquish", + 65416: "vantage", + 65421: "vaporizer", + 65422: "variable", + 65423: "variably", + 65424: "varied", + 65425: "variety", + 65426: "various", + 65431: "varmint", + 65432: "varnish", + 65433: "varsity", + 65434: "varying", + 65435: "vascular", + 65436: "vaseline", + 65441: "vastly", + 65442: "vastness", + 65443: "veal", + 65444: "vegan", + 65445: "veggie", + 65446: "vehicular", + 65451: "velcro", + 65452: "velocity", + 65453: "velvet", + 65454: "vendetta", + 65455: "vending", + 65456: "vendor", + 65461: "veneering", + 65462: "vengeful", + 65463: "venomous", + 65464: "ventricle", + 65465: "venture", + 65466: "venue", + 65511: "venus", + 65512: "verbalize", + 65513: "verbally", + 65514: "verbose", + 65515: "verdict", + 65516: "verify", + 65521: "verse", + 65522: "version", + 65523: "versus", + 65524: "vertebrae", + 65525: "vertical", + 65526: "vertigo", + 65531: "very", + 65532: "vessel", + 65533: "vest", + 65534: "veteran", + 65535: "veto", + 65536: "vexingly", + 65541: "viability", + 65542: "viable", + 65543: "vibes", + 65544: "vice", + 65545: "vicinity", + 65546: "victory", + 65551: "video", + 65552: "viewable", + 65553: "viewer", + 65554: "viewing", + 65555: "viewless", + 65556: "viewpoint", + 65561: "vigorous", + 65562: "village", + 65563: "villain", + 65564: "vindicate", + 65565: "vineyard", + 65566: "vintage", + 65611: "violate", + 65612: "violation", + 65613: "violator", + 65614: "violet", + 65615: "violin", + 65616: "viper", + 65621: "viral", + 65622: "virtual", + 65623: "virtuous", + 65624: "virus", + 65625: "visa", + 65626: "viscosity", + 65631: "viscous", + 65632: "viselike", + 65633: "visible", + 65634: "visibly", + 65635: "vision", + 65636: "visiting", + 65641: "visitor", + 65642: "visor", + 65643: "vista", + 65644: "vitality", + 65645: "vitalize", + 65646: "vitally", + 65651: "vitamins", + 65652: "vivacious", + 65653: "vividly", + 65654: "vividness", + 65655: "vixen", + 65656: "vocalist", + 65661: "vocalize", + 65662: "vocally", + 65663: "vocation", + 65664: "voice", + 65665: "voicing", + 65666: "void", + 66111: "volatile", + 66112: "volley", + 66113: "voltage", + 66114: "volumes", + 66115: "voter", + 66116: "voting", + 66121: "voucher", + 66122: "vowed", + 66123: "vowel", + 66124: "voyage", + 66125: "wackiness", + 66126: "wad", + 66131: "wafer", + 66132: "waffle", + 66133: "waged", + 66134: "wager", + 66135: "wages", + 66136: "waggle", + 66141: "wagon", + 66142: "wake", + 66143: "waking", + 66144: "walk", + 66145: "walmart", + 66146: "walnut", + 66151: "walrus", + 66152: "waltz", + 66153: "wand", + 66154: "wannabe", + 66155: "wanted", + 66156: "wanting", + 66161: "wasabi", + 66162: "washable", + 66163: "washbasin", + 66164: "washboard", + 66165: "washbowl", + 66166: "washcloth", + 66211: "washday", + 66212: "washed", + 66213: "washer", + 66214: "washhouse", + 66215: "washing", + 66216: "washout", + 66221: "washroom", + 66222: "washstand", + 66223: "washtub", + 66224: "wasp", + 66225: "wasting", + 66226: "watch", + 66231: "water", + 66232: "waviness", + 66233: "waving", + 66234: "wavy", + 66235: "whacking", + 66236: "whacky", + 66241: "wham", + 66242: "wharf", + 66243: "wheat", + 66244: "whenever", + 66245: "whiff", + 66246: "whimsical", + 66251: "whinny", + 66252: "whiny", + 66253: "whisking", + 66254: "whoever", + 66255: "whole", + 66256: "whomever", + 66261: "whoopee", + 66262: "whooping", + 66263: "whoops", + 66264: "why", + 66265: "wick", + 66266: "widely", + 66311: "widen", + 66312: "widget", + 66313: "widow", + 66314: "width", + 66315: "wieldable", + 66316: "wielder", + 66321: "wife", + 66322: "wifi", + 66323: "wikipedia", + 66324: "wildcard", + 66325: "wildcat", + 66326: "wilder", + 66331: "wildfire", + 66332: "wildfowl", + 66333: "wildland", + 66334: "wildlife", + 66335: "wildly", + 66336: "wildness", + 66341: "willed", + 66342: "willfully", + 66343: "willing", + 66344: "willow", + 66345: "willpower", + 66346: "wilt", + 66351: "wimp", + 66352: "wince", + 66353: "wincing", + 66354: "wind", + 66355: "wing", + 66356: "winking", + 66361: "winner", + 66362: "winnings", + 66363: "winter", + 66364: "wipe", + 66365: "wired", + 66366: "wireless", + 66411: "wiring", + 66412: "wiry", + 66413: "wisdom", + 66414: "wise", + 66415: "wish", + 66416: "wisplike", + 66421: "wispy", + 66422: "wistful", + 66423: "wizard", + 66424: "wobble", + 66425: "wobbling", + 66426: "wobbly", + 66431: "wok", + 66432: "wolf", + 66433: "wolverine", + 66434: "womanhood", + 66435: "womankind", + 66436: "womanless", + 66441: "womanlike", + 66442: "womanly", + 66443: "womb", + 66444: "woof", + 66445: "wooing", + 66446: "wool", + 66451: "woozy", + 66452: "word", + 66453: "work", + 66454: "worried", + 66455: "worrier", + 66456: "worrisome", + 66461: "worry", + 66462: "worsening", + 66463: "worshiper", + 66464: "worst", + 66465: "wound", + 66466: "woven", + 66511: "wow", + 66512: "wrangle", + 66513: "wrath", + 66514: "wreath", + 66515: "wreckage", + 66516: "wrecker", + 66521: "wrecking", + 66522: "wrench", + 66523: "wriggle", + 66524: "wriggly", + 66525: "wrinkle", + 66526: "wrinkly", + 66531: "wrist", + 66532: "writing", + 66533: "written", + 66534: "wrongdoer", + 66535: "wronged", + 66536: "wrongful", + 66541: "wrongly", + 66542: "wrongness", + 66543: "wrought", + 66544: "xbox", + 66545: "xerox", + 66546: "yahoo", + 66551: "yam", + 66552: "yanking", + 66553: "yapping", + 66554: "yard", + 66555: "yarn", + 66556: "yeah", + 66561: "yearbook", + 66562: "yearling", + 66563: "yearly", + 66564: "yearning", + 66565: "yeast", + 66566: "yelling", + 66611: "yelp", + 66612: "yen", + 66613: "yesterday", + 66614: "yiddish", + 66615: "yield", + 66616: "yin", + 66621: "yippee", + 66622: "yo-yo", + 66623: "yodel", + 66624: "yoga", + 66625: "yogurt", + 66626: "yonder", + 66631: "yoyo", + 66632: "yummy", + 66633: "zap", + 66634: "zealous", + 66635: "zebra", + 66636: "zen", + 66641: "zeppelin", + 66642: "zero", + 66643: "zestfully", + 66644: "zesty", + 66645: "zigzagged", + 66646: "zipfile", + 66651: "zipping", + 66652: "zippy", + 66653: "zips", + 66654: "zit", + 66655: "zodiac", + 66656: "zombie", + 66661: "zone", + 66662: "zoning", + 66663: "zookeeper", + 66664: "zoologist", + 66665: "zoology", + 66666: "zoom" + }), yt; +} +var xn = En(); +const sr = /* @__PURE__ */ Kr(xn), tt = Object.keys(sr).sort().map((e) => sr[e]); +if (tt.length !== 7776) + throw new Error(`EFF long wordlist must contain 7776 entries, found ${tt.length}.`); +function y1() { + return tt; +} +const b1 = Math.log2(tt.length); +function Dn() { + const e = globalThis.crypto; + if (!e || typeof e.getRandomValues != "function") + throw new Error("No cryptographically secure random source available in this environment."); + return e; +} +function qe(e) { + const t = new Uint8Array(e); + return Dn().getRandomValues(t), t; +} +function w1() { + return qe(16); +} +function C1() { + return qe(12); +} +function k1() { + return qe(16); +} +function v1(e) { + if (!Number.isInteger(e) || e <= 0 || e > 4294967296) + throw new Error("randomUniformInt: maxExclusive must be an integer in (0, 2^32]."); + const t = e <= 256 ? 1 : e <= 65536 ? 2 : 4, n = 256 ** t, r = n - n % e; + for (; ; ) { + const i = qe(t); + let a = 0; + for (const o of i) + a = a * 256 + o; + if (a < r) + return a % e; + } +} +const ve = typeof globalThis == "object" && "crypto" in globalThis ? globalThis.crypto : void 0; +/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +function At(e) { + return e instanceof Uint8Array || ArrayBuffer.isView(e) && e.constructor.name === "Uint8Array"; +} +function rt(e) { + if (!Number.isSafeInteger(e) || e < 0) + throw new Error("positive integer expected, got " + e); +} +function pe(e, ...t) { + if (!At(e)) + throw new Error("Uint8Array expected"); + if (t.length > 0 && !t.includes(e.length)) + throw new Error("Uint8Array expected of length " + t + ", got length=" + e.length); +} +function ht(e) { + if (typeof e != "function" || typeof e.create != "function") + throw new Error("Hash should be wrapped by utils.createHasher"); + rt(e.outputLen), rt(e.blockLen); +} +function nt(e, t = !0) { + if (e.destroyed) + throw new Error("Hash instance has been destroyed"); + if (t && e.finished) + throw new Error("Hash#digest() has already been called"); +} +function Sn(e, t) { + pe(e); + const n = t.outputLen; + if (e.length < n) + throw new Error("digestInto() expects output buffer of length at least " + n); +} +function Ce(...e) { + for (let t = 0; t < e.length; t++) + e[t].fill(0); +} +function bt(e) { + return new DataView(e.buffer, e.byteOffset, e.byteLength); +} +function re(e, t) { + return e << 32 - t | e >>> t; +} +const Or = /* @ts-ignore */ typeof Uint8Array.from([]).toHex == "function" && typeof Uint8Array.fromHex == "function", Fn = /* @__PURE__ */ Array.from({ length: 256 }, (e, t) => t.toString(16).padStart(2, "0")); +function Ee(e) { + if (pe(e), Or) + return e.toHex(); + let t = ""; + for (let n = 0; n < e.length; n++) + t += Fn[e[n]]; + return t; +} +const ie = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 }; +function lr(e) { + if (e >= ie._0 && e <= ie._9) + return e - ie._0; + if (e >= ie.A && e <= ie.F) + return e - (ie.A - 10); + if (e >= ie.a && e <= ie.f) + return e - (ie.a - 10); +} +function it(e) { + if (typeof e != "string") + throw new Error("hex string expected, got " + typeof e); + if (Or) + return Uint8Array.fromHex(e); + const t = e.length, n = t / 2; + if (t % 2) + throw new Error("hex string expected, got unpadded hex of length " + t); + const r = new Uint8Array(n); + for (let i = 0, a = 0; i < n; i++, a += 2) { + const o = lr(e.charCodeAt(a)), s = lr(e.charCodeAt(a + 1)); + if (o === void 0 || s === void 0) { + const l = e[a] + e[a + 1]; + throw new Error('hex string expected, got non-hex character "' + l + '" at index ' + a); + } + r[i] = o * 16 + s; + } + return r; +} +const Un = async () => { +}; +async function B1(e, t, n) { + let r = Date.now(); + for (let i = 0; i < e; i++) { + n(i); + const a = Date.now() - r; + a >= 0 && a < t || (await Un(), r += a); + } +} +function qt(e) { + if (typeof e != "string") + throw new Error("string expected"); + return new Uint8Array(new TextEncoder().encode(e)); +} +function Me(e) { + return typeof e == "string" && (e = qt(e)), pe(e), e; +} +function Q1(e) { + return typeof e == "string" && (e = qt(e)), pe(e), e; +} +function ne(...e) { + let t = 0; + for (let r = 0; r < e.length; r++) { + const i = e[r]; + pe(i), t += i.length; + } + const n = new Uint8Array(t); + for (let r = 0, i = 0; r < e.length; r++) { + const a = e[r]; + n.set(a, i), i += a.length; + } + return n; +} +function E1(e, t) { + if (t !== void 0 && {}.toString.call(t) !== "[object Object]") + throw new Error("options should be object or undefined"); + return Object.assign(e, t); +} +class Vr { +} +function zr(e) { + const t = (r) => e().update(Me(r)).digest(), n = e(); + return t.outputLen = n.outputLen, t.blockLen = n.blockLen, t.create = () => e(), t; +} +function ft(e = 32) { + if (ve && typeof ve.getRandomValues == "function") + return ve.getRandomValues(new Uint8Array(e)); + if (ve && typeof ve.randomBytes == "function") + return Uint8Array.from(ve.randomBytes(e)); + throw new Error("crypto.getRandomValues must be defined"); +} +function Gn(e, t, n, r) { + if (typeof e.setBigUint64 == "function") + return e.setBigUint64(t, n, r); + const i = BigInt(32), a = BigInt(4294967295), o = Number(n >> i & a), s = Number(n & a), l = r ? 4 : 0, u = r ? 0 : 4; + e.setUint32(t + l, o, r), e.setUint32(t + u, s, r); +} +function Hn(e, t, n) { + return e & t ^ ~e & n; +} +function Nn(e, t, n) { + return e & t ^ e & n ^ t & n; +} +class Jr extends Vr { + constructor(t, n, r, i) { + super(), this.finished = !1, this.length = 0, this.pos = 0, this.destroyed = !1, this.blockLen = t, this.outputLen = n, this.padOffset = r, this.isLE = i, this.buffer = new Uint8Array(t), this.view = bt(this.buffer); + } + update(t) { + nt(this), t = Me(t), pe(t); + const { view: n, buffer: r, blockLen: i } = this, a = t.length; + for (let o = 0; o < a; ) { + const s = Math.min(i - this.pos, a - o); + if (s === i) { + const l = bt(t); + for (; i <= a - o; o += i) + this.process(l, o); + continue; + } + r.set(t.subarray(o, o + s), this.pos), this.pos += s, o += s, this.pos === i && (this.process(n, 0), this.pos = 0); + } + return this.length += t.length, this.roundClean(), this; + } + digestInto(t) { + nt(this), Sn(t, this), this.finished = !0; + const { buffer: n, view: r, blockLen: i, isLE: a } = this; + let { pos: o } = this; + n[o++] = 128, Ce(this.buffer.subarray(o)), this.padOffset > i - o && (this.process(r, 0), o = 0); + for (let g = o; g < i; g++) + n[g] = 0; + Gn(r, i - 8, BigInt(this.length * 8), a), this.process(r, 0); + const s = bt(t), l = this.outputLen; + if (l % 4) + throw new Error("_sha2: outputLen should be aligned to 32bit"); + const u = l / 4, h = this.get(); + if (u > h.length) + throw new Error("_sha2: outputLen bigger than state"); + for (let g = 0; g < u; g++) + s.setUint32(4 * g, h[g], a); + } + digest() { + const { buffer: t, outputLen: n } = this; + this.digestInto(t); + const r = t.slice(0, n); + return this.destroy(), r; + } + _cloneInto(t) { + t || (t = new this.constructor()), t.set(...this.get()); + const { blockLen: n, buffer: r, length: i, finished: a, destroyed: o, pos: s } = this; + return t.destroyed = o, t.finished = a, t.length = i, t.pos = s, i % n && t.buffer.set(r), t; + } + clone() { + return this._cloneInto(); + } +} +const de = /* @__PURE__ */ Uint32Array.from([ + 1779033703, + 3144134277, + 1013904242, + 2773480762, + 1359893119, + 2600822924, + 528734635, + 1541459225 +]), _ = /* @__PURE__ */ Uint32Array.from([ + 1779033703, + 4089235720, + 3144134277, + 2227873595, + 1013904242, + 4271175723, + 2773480762, + 1595750129, + 1359893119, + 2917565137, + 2600822924, + 725511199, + 528734635, + 4215389547, + 1541459225, + 327033209 +]), Pe = /* @__PURE__ */ BigInt(2 ** 32 - 1), cr = /* @__PURE__ */ BigInt(32); +function Kn(e, t = !1) { + return t ? { h: Number(e & Pe), l: Number(e >> cr & Pe) } : { h: Number(e >> cr & Pe) | 0, l: Number(e & Pe) | 0 }; +} +function On(e, t = !1) { + const n = e.length; + let r = new Uint32Array(n), i = new Uint32Array(n); + for (let a = 0; a < n; a++) { + const { h: o, l: s } = Kn(e[a], t); + [r[a], i[a]] = [o, s]; + } + return [r, i]; +} +const ur = (e, t, n) => e >>> n, dr = (e, t, n) => e << 32 - n | t >>> n, Be = (e, t, n) => e >>> n | t << 32 - n, Qe = (e, t, n) => e << 32 - n | t >>> n, Le = (e, t, n) => e << 64 - n | t >>> n - 32, Te = (e, t, n) => e >>> n - 32 | t << 64 - n; +function ae(e, t, n, r) { + const i = (t >>> 0) + (r >>> 0); + return { h: e + n + (i / 2 ** 32 | 0) | 0, l: i | 0 }; +} +const Vn = (e, t, n) => (e >>> 0) + (t >>> 0) + (n >>> 0), zn = (e, t, n, r) => t + n + r + (e / 2 ** 32 | 0) | 0, Jn = (e, t, n, r) => (e >>> 0) + (t >>> 0) + (n >>> 0) + (r >>> 0), Yn = (e, t, n, r, i) => t + n + r + i + (e / 2 ** 32 | 0) | 0, Mn = (e, t, n, r, i) => (e >>> 0) + (t >>> 0) + (n >>> 0) + (r >>> 0) + (i >>> 0), qn = (e, t, n, r, i, a) => t + n + r + i + a + (e / 2 ** 32 | 0) | 0, jn = /* @__PURE__ */ Uint32Array.from([ + 1116352408, + 1899447441, + 3049323471, + 3921009573, + 961987163, + 1508970993, + 2453635748, + 2870763221, + 3624381080, + 310598401, + 607225278, + 1426881987, + 1925078388, + 2162078206, + 2614888103, + 3248222580, + 3835390401, + 4022224774, + 264347078, + 604807628, + 770255983, + 1249150122, + 1555081692, + 1996064986, + 2554220882, + 2821834349, + 2952996808, + 3210313671, + 3336571891, + 3584528711, + 113926993, + 338241895, + 666307205, + 773529912, + 1294757372, + 1396182291, + 1695183700, + 1986661051, + 2177026350, + 2456956037, + 2730485921, + 2820302411, + 3259730800, + 3345764771, + 3516065817, + 3600352804, + 4094571909, + 275423344, + 430227734, + 506948616, + 659060556, + 883997877, + 958139571, + 1322822218, + 1537002063, + 1747873779, + 1955562222, + 2024104815, + 2227730452, + 2361852424, + 2428436474, + 2756734187, + 3204031479, + 3329325298 +]), ge = /* @__PURE__ */ new Uint32Array(64); +class Rn extends Jr { + constructor(t = 32) { + super(64, t, 8, !1), this.A = de[0] | 0, this.B = de[1] | 0, this.C = de[2] | 0, this.D = de[3] | 0, this.E = de[4] | 0, this.F = de[5] | 0, this.G = de[6] | 0, this.H = de[7] | 0; + } + get() { + const { A: t, B: n, C: r, D: i, E: a, F: o, G: s, H: l } = this; + return [t, n, r, i, a, o, s, l]; + } + // prettier-ignore + set(t, n, r, i, a, o, s, l) { + this.A = t | 0, this.B = n | 0, this.C = r | 0, this.D = i | 0, this.E = a | 0, this.F = o | 0, this.G = s | 0, this.H = l | 0; + } + process(t, n) { + for (let g = 0; g < 16; g++, n += 4) + ge[g] = t.getUint32(n, !1); + for (let g = 16; g < 64; g++) { + const c = ge[g - 15], d = ge[g - 2], I = re(c, 7) ^ re(c, 18) ^ c >>> 3, m = re(d, 17) ^ re(d, 19) ^ d >>> 10; + ge[g] = m + ge[g - 7] + I + ge[g - 16] | 0; + } + let { A: r, B: i, C: a, D: o, E: s, F: l, G: u, H: h } = this; + for (let g = 0; g < 64; g++) { + const c = re(s, 6) ^ re(s, 11) ^ re(s, 25), d = h + c + Hn(s, l, u) + jn[g] + ge[g] | 0, m = (re(r, 2) ^ re(r, 13) ^ re(r, 22)) + Nn(r, i, a) | 0; + h = u, u = l, l = s, s = o + d | 0, o = a, a = i, i = r, r = d + m | 0; + } + r = r + this.A | 0, i = i + this.B | 0, a = a + this.C | 0, o = o + this.D | 0, s = s + this.E | 0, l = l + this.F | 0, u = u + this.G | 0, h = h + this.H | 0, this.set(r, i, a, o, s, l, u, h); + } + roundClean() { + Ce(ge); + } + destroy() { + this.set(0, 0, 0, 0, 0, 0, 0, 0), Ce(this.buffer); + } +} +const Yr = On([ + "0x428a2f98d728ae22", + "0x7137449123ef65cd", + "0xb5c0fbcfec4d3b2f", + "0xe9b5dba58189dbbc", + "0x3956c25bf348b538", + "0x59f111f1b605d019", + "0x923f82a4af194f9b", + "0xab1c5ed5da6d8118", + "0xd807aa98a3030242", + "0x12835b0145706fbe", + "0x243185be4ee4b28c", + "0x550c7dc3d5ffb4e2", + "0x72be5d74f27b896f", + "0x80deb1fe3b1696b1", + "0x9bdc06a725c71235", + "0xc19bf174cf692694", + "0xe49b69c19ef14ad2", + "0xefbe4786384f25e3", + "0x0fc19dc68b8cd5b5", + "0x240ca1cc77ac9c65", + "0x2de92c6f592b0275", + "0x4a7484aa6ea6e483", + "0x5cb0a9dcbd41fbd4", + "0x76f988da831153b5", + "0x983e5152ee66dfab", + "0xa831c66d2db43210", + "0xb00327c898fb213f", + "0xbf597fc7beef0ee4", + "0xc6e00bf33da88fc2", + "0xd5a79147930aa725", + "0x06ca6351e003826f", + "0x142929670a0e6e70", + "0x27b70a8546d22ffc", + "0x2e1b21385c26c926", + "0x4d2c6dfc5ac42aed", + "0x53380d139d95b3df", + "0x650a73548baf63de", + "0x766a0abb3c77b2a8", + "0x81c2c92e47edaee6", + "0x92722c851482353b", + "0xa2bfe8a14cf10364", + "0xa81a664bbc423001", + "0xc24b8b70d0f89791", + "0xc76c51a30654be30", + "0xd192e819d6ef5218", + "0xd69906245565a910", + "0xf40e35855771202a", + "0x106aa07032bbd1b8", + "0x19a4c116b8d2d0c8", + "0x1e376c085141ab53", + "0x2748774cdf8eeb99", + "0x34b0bcb5e19b48a8", + "0x391c0cb3c5c95a63", + "0x4ed8aa4ae3418acb", + "0x5b9cca4f7763e373", + "0x682e6ff3d6b2b8a3", + "0x748f82ee5defb2fc", + "0x78a5636f43172f60", + "0x84c87814a1f0ab72", + "0x8cc702081a6439ec", + "0x90befffa23631e28", + "0xa4506cebde82bde9", + "0xbef9a3f7b2c67915", + "0xc67178f2e372532b", + "0xca273eceea26619c", + "0xd186b8c721c0c207", + "0xeada7dd6cde0eb1e", + "0xf57d4f7fee6ed178", + "0x06f067aa72176fba", + "0x0a637dc5a2c898a6", + "0x113f9804bef90dae", + "0x1b710b35131c471b", + "0x28db77f523047d84", + "0x32caab7b40c72493", + "0x3c9ebe0a15c9bebc", + "0x431d67c49c100d4c", + "0x4cc5d4becb3e42b6", + "0x597f299cfc657e2a", + "0x5fcb6fab3ad6faec", + "0x6c44198c4a475817" +].map((e) => BigInt(e))), _n = Yr[0], Pn = Yr[1], Ae = /* @__PURE__ */ new Uint32Array(80), he = /* @__PURE__ */ new Uint32Array(80); +class Ln extends Jr { + constructor(t = 64) { + super(128, t, 16, !1), this.Ah = _[0] | 0, this.Al = _[1] | 0, this.Bh = _[2] | 0, this.Bl = _[3] | 0, this.Ch = _[4] | 0, this.Cl = _[5] | 0, this.Dh = _[6] | 0, this.Dl = _[7] | 0, this.Eh = _[8] | 0, this.El = _[9] | 0, this.Fh = _[10] | 0, this.Fl = _[11] | 0, this.Gh = _[12] | 0, this.Gl = _[13] | 0, this.Hh = _[14] | 0, this.Hl = _[15] | 0; + } + // prettier-ignore + get() { + const { Ah: t, Al: n, Bh: r, Bl: i, Ch: a, Cl: o, Dh: s, Dl: l, Eh: u, El: h, Fh: g, Fl: c, Gh: d, Gl: I, Hh: m, Hl: B } = this; + return [t, n, r, i, a, o, s, l, u, h, g, c, d, I, m, B]; + } + // prettier-ignore + set(t, n, r, i, a, o, s, l, u, h, g, c, d, I, m, B) { + this.Ah = t | 0, this.Al = n | 0, this.Bh = r | 0, this.Bl = i | 0, this.Ch = a | 0, this.Cl = o | 0, this.Dh = s | 0, this.Dl = l | 0, this.Eh = u | 0, this.El = h | 0, this.Fh = g | 0, this.Fl = c | 0, this.Gh = d | 0, this.Gl = I | 0, this.Hh = m | 0, this.Hl = B | 0; + } + process(t, n) { + for (let b = 0; b < 16; b++, n += 4) + Ae[b] = t.getUint32(n), he[b] = t.getUint32(n += 4); + for (let b = 16; b < 80; b++) { + const N = Ae[b - 15] | 0, K = he[b - 15] | 0, C = Be(N, K, 1) ^ Be(N, K, 8) ^ ur(N, K, 7), D = Qe(N, K, 1) ^ Qe(N, K, 8) ^ dr(N, K, 7), G = Ae[b - 2] | 0, v = he[b - 2] | 0, P = Be(G, v, 19) ^ Le(G, v, 61) ^ ur(G, v, 6), Z = Qe(G, v, 19) ^ Te(G, v, 61) ^ dr(G, v, 6), U = Jn(D, Z, he[b - 7], he[b - 16]), p = Yn(U, C, P, Ae[b - 7], Ae[b - 16]); + Ae[b] = p | 0, he[b] = U | 0; + } + let { Ah: r, Al: i, Bh: a, Bl: o, Ch: s, Cl: l, Dh: u, Dl: h, Eh: g, El: c, Fh: d, Fl: I, Gh: m, Gl: B, Hh: S, Hl: j } = this; + for (let b = 0; b < 80; b++) { + const N = Be(g, c, 14) ^ Be(g, c, 18) ^ Le(g, c, 41), K = Qe(g, c, 14) ^ Qe(g, c, 18) ^ Te(g, c, 41), C = g & d ^ ~g & m, D = c & I ^ ~c & B, G = Mn(j, K, D, Pn[b], he[b]), v = qn(G, S, N, C, _n[b], Ae[b]), P = G | 0, Z = Be(r, i, 28) ^ Le(r, i, 34) ^ Le(r, i, 39), U = Qe(r, i, 28) ^ Te(r, i, 34) ^ Te(r, i, 39), p = r & a ^ r & s ^ a & s, f = i & o ^ i & l ^ o & l; + S = m | 0, j = B | 0, m = d | 0, B = I | 0, d = g | 0, I = c | 0, { h: g, l: c } = ae(u | 0, h | 0, v | 0, P | 0), u = s | 0, h = l | 0, s = a | 0, l = o | 0, a = r | 0, o = i | 0; + const A = Vn(P, U, f); + r = zn(A, v, Z, p), i = A | 0; + } + ({ h: r, l: i } = ae(this.Ah | 0, this.Al | 0, r | 0, i | 0)), { h: a, l: o } = ae(this.Bh | 0, this.Bl | 0, a | 0, o | 0), { h: s, l } = ae(this.Ch | 0, this.Cl | 0, s | 0, l | 0), { h: u, l: h } = ae(this.Dh | 0, this.Dl | 0, u | 0, h | 0), { h: g, l: c } = ae(this.Eh | 0, this.El | 0, g | 0, c | 0), { h: d, l: I } = ae(this.Fh | 0, this.Fl | 0, d | 0, I | 0), { h: m, l: B } = ae(this.Gh | 0, this.Gl | 0, m | 0, B | 0), { h: S, l: j } = ae(this.Hh | 0, this.Hl | 0, S | 0, j | 0), this.set(r, i, a, o, s, l, u, h, g, c, d, I, m, B, S, j); + } + roundClean() { + Ce(Ae, he); + } + destroy() { + Ce(this.buffer), this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } +} +const fe = /* @__PURE__ */ zr(() => new Rn()), x1 = /* @__PURE__ */ zr(() => new Ln()); +class Mr extends Vr { + constructor(t, n) { + super(), this.finished = !1, this.destroyed = !1, ht(t); + const r = Me(n); + if (this.iHash = t.create(), typeof this.iHash.update != "function") + throw new Error("Expected instance of class which extends utils.Hash"); + this.blockLen = this.iHash.blockLen, this.outputLen = this.iHash.outputLen; + const i = this.blockLen, a = new Uint8Array(i); + a.set(r.length > i ? t.create().update(r).digest() : r); + for (let o = 0; o < a.length; o++) + a[o] ^= 54; + this.iHash.update(a), this.oHash = t.create(); + for (let o = 0; o < a.length; o++) + a[o] ^= 106; + this.oHash.update(a), Ce(a); + } + update(t) { + return nt(this), this.iHash.update(t), this; + } + digestInto(t) { + nt(this), pe(t, this.outputLen), this.finished = !0, this.iHash.digestInto(t), this.oHash.update(t), this.oHash.digestInto(t), this.destroy(); + } + digest() { + const t = new Uint8Array(this.oHash.outputLen); + return this.digestInto(t), t; + } + _cloneInto(t) { + t || (t = Object.create(Object.getPrototypeOf(this), {})); + const { oHash: n, iHash: r, finished: i, destroyed: a, blockLen: o, outputLen: s } = this; + return t = t, t.finished = i, t.destroyed = a, t.blockLen = o, t.outputLen = s, t.oHash = n._cloneInto(t.oHash), t.iHash = r._cloneInto(t.iHash), t; + } + clone() { + return this._cloneInto(); + } + destroy() { + this.destroyed = !0, this.oHash.destroy(), this.iHash.destroy(); + } +} +const pt = (e, t, n) => new Mr(e, t).update(n).digest(); +pt.create = (e, t) => new Mr(e, t); +function Tn(e, t, n) { + return ht(e), n === void 0 && (n = new Uint8Array(e.outputLen)), pt(e, Me(n), Me(t)); +} +const wt = /* @__PURE__ */ Uint8Array.from([0]), gr = /* @__PURE__ */ Uint8Array.of(); +function Xn(e, t, n, r = 32) { + ht(e), rt(r); + const i = e.outputLen; + if (r > 255 * i) + throw new Error("Length should be <= 255*HashLen"); + const a = Math.ceil(r / i); + n === void 0 && (n = gr); + const o = new Uint8Array(a * i), s = pt.create(e, t), l = s._cloneInto(), u = new Uint8Array(s.outputLen); + for (let h = 0; h < a; h++) + wt[0] = h + 1, l.update(h === 0 ? gr : u).update(n).update(wt).digestInto(u), o.set(u, i * h), s._cloneInto(l); + return s.destroy(), l.destroy(), Ce(u, wt), o.slice(0, r); +} +function jt(e) { + let t = ""; + for (const n of e) + t += n.toString(16).padStart(2, "0"); + return t; +} +function Je(e) { + if (e.length % 2 !== 0) + throw new Error("Invalid hex string length."); + const t = new Uint8Array(e.length / 2); + for (let n = 0; n < t.length; n++) + t[n] = parseInt(e.slice(n * 2, n * 2 + 2), 16); + return t; +} +const ee = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; +function D1(e) { + let t = "", n = 0; + for (; n + 2 < e.length; n += 3) { + const i = e[n], a = e[n + 1], o = e[n + 2]; + t += ee[i >> 2], t += ee[(i & 3) << 4 | a >> 4], t += ee[(a & 15) << 2 | o >> 6], t += ee[o & 63]; + } + const r = e.length - n; + if (r === 1) { + const i = e[n]; + t += ee[i >> 2], t += ee[(i & 3) << 4]; + } else if (r === 2) { + const i = e[n], a = e[n + 1]; + t += ee[i >> 2], t += ee[(i & 3) << 4 | a >> 4], t += ee[(a & 15) << 2]; + } + return t; +} +const Zn = (() => { + const e = {}; + for (let t = 0; t < ee.length; t++) + e[ee[t]] = t; + return e; +})(); +function S1(e) { + const t = e.replace(/=+$/u, ""), n = []; + let r = 0, i = 0; + for (const a of t) { + const o = Zn[a]; + if (o === void 0) + throw new Error("Invalid base64url character."); + r = r << 6 | o, i += 6, i >= 8 && (i -= 8, n.push(r >> i & 255)); + } + return new Uint8Array(n); +} +function De(e) { + return new TextEncoder().encode(e); +} +function F1(e) { + return new TextDecoder("utf-8", { fatal: !0 }).decode(e); +} +function qr(...e) { + const t = e.reduce((i, a) => i + a.length, 0), n = new Uint8Array(t); + let r = 0; + for (const i of e) + n.set(i, r), r += i.length; + return n; +} +function U1(e, t) { + if (e.length !== t.length) + return !1; + let n = 0; + for (let r = 0; r < e.length; r++) + n |= e[r] ^ t[r]; + return n === 0; +} +function jr(e, t) { + return Tn(fe, t, e); +} +function Rt(e, t, n) { + const r = typeof t == "string" ? De(t) : t; + return Xn(fe, e, r, n); +} +function Rr(e) { + return fe(De(e)); +} +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const _t = /* @__PURE__ */ BigInt(0), Gt = /* @__PURE__ */ BigInt(1); +function at(e, t = "") { + if (typeof e != "boolean") { + const n = t && `"${t}"`; + throw new Error(n + "expected boolean, got type=" + typeof e); + } + return e; +} +function Ie(e, t, n = "") { + const r = At(e), i = e?.length, a = t !== void 0; + if (!r || a && i !== t) { + const o = n && `"${n}" `, s = a ? ` of length ${t}` : "", l = r ? `length=${i}` : `type=${typeof e}`; + throw new Error(o + "expected Uint8Array" + s + ", got " + l); + } + return e; +} +function Xe(e) { + const t = e.toString(16); + return t.length & 1 ? "0" + t : t; +} +function _r(e) { + if (typeof e != "string") + throw new Error("hex string expected, got " + typeof e); + return e === "" ? _t : BigInt("0x" + e); +} +function Ge(e) { + return _r(Ee(e)); +} +function Pr(e) { + return pe(e), _r(Ee(Uint8Array.from(e).reverse())); +} +function It(e, t) { + return it(e.toString(16).padStart(t * 2, "0")); +} +function Lr(e, t) { + return It(e, t).reverse(); +} +function q(e, t, n) { + let r; + if (typeof t == "string") + try { + r = it(t); + } catch (a) { + throw new Error(e + " must be hex string or Uint8Array, cause: " + a); + } + else if (At(t)) + r = Uint8Array.from(t); + else + throw new Error(e + " must be hex string or Uint8Array"); + const i = r.length; + if (typeof n == "number" && i !== n) + throw new Error(e + " of length " + n + " expected, got " + i); + return r; +} +const Ct = (e) => typeof e == "bigint" && _t <= e; +function Ht(e, t, n) { + return Ct(e) && Ct(t) && Ct(n) && t <= e && e < n; +} +function $n(e, t, n, r) { + if (!Ht(t, n, r)) + throw new Error("expected valid " + e + ": " + n + " <= n < " + r + ", got " + t); +} +function Tr(e) { + let t; + for (t = 0; e > _t; e >>= Gt, t += 1) + ; + return t; +} +const je = (e) => (Gt << BigInt(e)) - Gt; +function Wn(e, t, n) { + if (typeof e != "number" || e < 2) + throw new Error("hashLen must be a number"); + if (typeof t != "number" || t < 2) + throw new Error("qByteLen must be a number"); + if (typeof n != "function") + throw new Error("hmacFn must be a function"); + const r = (d) => new Uint8Array(d), i = (d) => Uint8Array.of(d); + let a = r(e), o = r(e), s = 0; + const l = () => { + a.fill(1), o.fill(0), s = 0; + }, u = (...d) => n(o, a, ...d), h = (d = r(0)) => { + o = u(i(0), d), a = u(), d.length !== 0 && (o = u(i(1), d), a = u()); + }, g = () => { + if (s++ >= 1e3) + throw new Error("drbg: tried 1000 values"); + let d = 0; + const I = []; + for (; d < t; ) { + a = u(); + const m = a.slice(); + I.push(m), d += a.length; + } + return ne(...I); + }; + return (d, I) => { + l(), h(d); + let m; + for (; !(m = I(g())); ) + h(); + return l(), m; + }; +} +function Pt(e, t, n = {}) { + if (!e || typeof e != "object") + throw new Error("expected valid options object"); + function r(i, a, o) { + const s = e[i]; + if (o && s === void 0) + return; + const l = typeof s; + if (l !== a || s === null) + throw new Error(`param "${i}" is invalid: expected ${a}, got ${l}`); + } + Object.entries(t).forEach(([i, a]) => r(i, a, !1)), Object.entries(n).forEach(([i, a]) => r(i, a, !0)); +} +function Ar(e) { + const t = /* @__PURE__ */ new WeakMap(); + return (n, ...r) => { + const i = t.get(n); + if (i !== void 0) + return i; + const a = e(n, ...r); + return t.set(n, a), a; + }; +} +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const X = BigInt(0), L = BigInt(1), me = /* @__PURE__ */ BigInt(2), Xr = /* @__PURE__ */ BigInt(3), Zr = /* @__PURE__ */ BigInt(4), $r = /* @__PURE__ */ BigInt(5), ei = /* @__PURE__ */ BigInt(7), Wr = /* @__PURE__ */ BigInt(8), ti = /* @__PURE__ */ BigInt(9), en = /* @__PURE__ */ BigInt(16); +function W(e, t) { + const n = e % t; + return n >= X ? n : t + n; +} +function $(e, t, n) { + let r = e; + for (; t-- > X; ) + r *= r, r %= n; + return r; +} +function hr(e, t) { + if (e === X) + throw new Error("invert: expected non-zero number"); + if (t <= X) + throw new Error("invert: expected positive modulus, got " + t); + let n = W(e, t), r = t, i = X, a = L; + for (; n !== X; ) { + const s = r / n, l = r % n, u = i - a * s; + r = n, n = l, i = a, a = u; + } + if (r !== L) + throw new Error("invert: does not exist"); + return W(i, t); +} +function Lt(e, t, n) { + if (!e.eql(e.sqr(t), n)) + throw new Error("Cannot find square root"); +} +function tn(e, t) { + const n = (e.ORDER + L) / Zr, r = e.pow(t, n); + return Lt(e, r, t), r; +} +function ri(e, t) { + const n = (e.ORDER - $r) / Wr, r = e.mul(t, me), i = e.pow(r, n), a = e.mul(t, i), o = e.mul(e.mul(a, me), i), s = e.mul(a, e.sub(o, e.ONE)); + return Lt(e, s, t), s; +} +function ni(e) { + const t = Re(e), n = rn(e), r = n(t, t.neg(t.ONE)), i = n(t, r), a = n(t, t.neg(r)), o = (e + ei) / en; + return (s, l) => { + let u = s.pow(l, o), h = s.mul(u, r); + const g = s.mul(u, i), c = s.mul(u, a), d = s.eql(s.sqr(h), l), I = s.eql(s.sqr(g), l); + u = s.cmov(u, h, d), h = s.cmov(c, g, I); + const m = s.eql(s.sqr(h), l), B = s.cmov(u, h, m); + return Lt(s, B, l), B; + }; +} +function rn(e) { + if (e < Xr) + throw new Error("sqrt is not defined for small field"); + let t = e - L, n = 0; + for (; t % me === X; ) + t /= me, n++; + let r = me; + const i = Re(e); + for (; fr(i, r) === 1; ) + if (r++ > 1e3) + throw new Error("Cannot find square root: probably non-prime P"); + if (n === 1) + return tn; + let a = i.pow(r, t); + const o = (t + L) / me; + return function(l, u) { + if (l.is0(u)) + return u; + if (fr(l, u) !== 1) + throw new Error("Cannot find square root"); + let h = n, g = l.mul(l.ONE, a), c = l.pow(u, t), d = l.pow(u, o); + for (; !l.eql(c, l.ONE); ) { + if (l.is0(c)) + return l.ZERO; + let I = 1, m = l.sqr(c); + for (; !l.eql(m, l.ONE); ) + if (I++, m = l.sqr(m), I === h) + throw new Error("Cannot find square root"); + const B = L << BigInt(h - I - 1), S = l.pow(g, B); + h = I, g = l.sqr(S), c = l.mul(c, g), d = l.mul(d, S); + } + return d; + }; +} +function ii(e) { + return e % Zr === Xr ? tn : e % Wr === $r ? ri : e % en === ti ? ni(e) : rn(e); +} +const ai = [ + "create", + "isValid", + "is0", + "neg", + "inv", + "sqrt", + "sqr", + "eql", + "add", + "sub", + "mul", + "pow", + "div", + "addN", + "subN", + "mulN", + "sqrN" +]; +function oi(e) { + const t = { + ORDER: "bigint", + MASK: "bigint", + BYTES: "number", + BITS: "number" + }, n = ai.reduce((r, i) => (r[i] = "function", r), t); + return Pt(e, n), e; +} +function si(e, t, n) { + if (n < X) + throw new Error("invalid exponent, negatives unsupported"); + if (n === X) + return e.ONE; + if (n === L) + return t; + let r = e.ONE, i = t; + for (; n > X; ) + n & L && (r = e.mul(r, i)), i = e.sqr(i), n >>= L; + return r; +} +function nn(e, t, n = !1) { + const r = new Array(t.length).fill(n ? e.ZERO : void 0), i = t.reduce((o, s, l) => e.is0(s) ? o : (r[l] = o, e.mul(o, s)), e.ONE), a = e.inv(i); + return t.reduceRight((o, s, l) => e.is0(s) ? o : (r[l] = e.mul(o, r[l]), e.mul(o, s)), a), r; +} +function fr(e, t) { + const n = (e.ORDER - L) / me, r = e.pow(t, n), i = e.eql(r, e.ONE), a = e.eql(r, e.ZERO), o = e.eql(r, e.neg(e.ONE)); + if (!i && !a && !o) + throw new Error("invalid Legendre symbol result"); + return i ? 1 : a ? 0 : -1; +} +function an(e, t) { + t !== void 0 && rt(t); + const n = t !== void 0 ? t : e.toString(2).length, r = Math.ceil(n / 8); + return { nBitLength: n, nByteLength: r }; +} +function Re(e, t, n = !1, r = {}) { + if (e <= X) + throw new Error("invalid field: expected ORDER > 0, got " + e); + let i, a, o = !1, s; + if (typeof t == "object" && t != null) { + if (r.sqrt || n) + throw new Error("cannot specify opts in two arguments"); + const c = t; + c.BITS && (i = c.BITS), c.sqrt && (a = c.sqrt), typeof c.isLE == "boolean" && (n = c.isLE), typeof c.modFromBytes == "boolean" && (o = c.modFromBytes), s = c.allowedLengths; + } else + typeof t == "number" && (i = t), r.sqrt && (a = r.sqrt); + const { nBitLength: l, nByteLength: u } = an(e, i); + if (u > 2048) + throw new Error("invalid field: expected ORDER of <= 2048 bytes"); + let h; + const g = Object.freeze({ + ORDER: e, + isLE: n, + BITS: l, + BYTES: u, + MASK: je(l), + ZERO: X, + ONE: L, + allowedLengths: s, + create: (c) => W(c, e), + isValid: (c) => { + if (typeof c != "bigint") + throw new Error("invalid field element: expected bigint, got " + typeof c); + return X <= c && c < e; + }, + is0: (c) => c === X, + // is valid and invertible + isValidNot0: (c) => !g.is0(c) && g.isValid(c), + isOdd: (c) => (c & L) === L, + neg: (c) => W(-c, e), + eql: (c, d) => c === d, + sqr: (c) => W(c * c, e), + add: (c, d) => W(c + d, e), + sub: (c, d) => W(c - d, e), + mul: (c, d) => W(c * d, e), + pow: (c, d) => si(g, c, d), + div: (c, d) => W(c * hr(d, e), e), + // Same as above, but doesn't normalize + sqrN: (c) => c * c, + addN: (c, d) => c + d, + subN: (c, d) => c - d, + mulN: (c, d) => c * d, + inv: (c) => hr(c, e), + sqrt: a || ((c) => (h || (h = ii(e)), h(g, c))), + toBytes: (c) => n ? Lr(c, u) : It(c, u), + fromBytes: (c, d = !0) => { + if (s) { + if (!s.includes(c.length) || c.length > u) + throw new Error("Field.fromBytes: expected " + s + " bytes, got " + c.length); + const m = new Uint8Array(u); + m.set(c, n ? 0 : m.length - c.length), c = m; + } + if (c.length !== u) + throw new Error("Field.fromBytes: expected " + u + " bytes, got " + c.length); + let I = n ? Pr(c) : Ge(c); + if (o && (I = W(I, e)), !d && !g.isValid(I)) + throw new Error("invalid field element: outside of range 0..ORDER"); + return I; + }, + // TODO: we don't need it here, move out to separate fn + invertBatch: (c) => nn(g, c), + // We can't move this out because Fp6, Fp12 implement it + // and it's unclear what to return in there. + cmov: (c, d, I) => I ? d : c + }); + return Object.freeze(g); +} +function on(e) { + if (typeof e != "bigint") + throw new Error("field order must be bigint"); + const t = e.toString(2).length; + return Math.ceil(t / 8); +} +function sn(e) { + const t = on(e); + return t + Math.ceil(t / 2); +} +function ln(e, t, n = !1) { + const r = e.length, i = on(t), a = sn(t); + if (r < 16 || r < a || r > 1024) + throw new Error("expected " + a + "-1024 bytes of input, got " + r); + const o = n ? Pr(e) : Ge(e), s = W(o, t - L) + L; + return n ? Lr(s, i) : It(s, i); +} +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const Se = BigInt(0), ye = BigInt(1); +function ot(e, t) { + const n = t.negate(); + return e ? n : t; +} +function kt(e, t) { + const n = nn(e.Fp, t.map((r) => r.Z)); + return t.map((r, i) => e.fromAffine(r.toAffine(n[i]))); +} +function cn(e, t) { + if (!Number.isSafeInteger(e) || e <= 0 || e > t) + throw new Error("invalid window size, expected [1.." + t + "], got W=" + e); +} +function vt(e, t) { + cn(e, t); + const n = Math.ceil(t / e) + 1, r = 2 ** (e - 1), i = 2 ** e, a = je(e), o = BigInt(e); + return { windows: n, windowSize: r, mask: a, maxNumber: i, shiftBy: o }; +} +function pr(e, t, n) { + const { windowSize: r, mask: i, maxNumber: a, shiftBy: o } = n; + let s = Number(e & i), l = e >> o; + s > r && (s -= a, l += ye); + const u = t * r, h = u + Math.abs(s) - 1, g = s === 0, c = s < 0, d = t % 2 !== 0; + return { nextN: l, offset: h, isZero: g, isNeg: c, isNegF: d, offsetF: u }; +} +function li(e, t) { + if (!Array.isArray(e)) + throw new Error("array expected"); + e.forEach((n, r) => { + if (!(n instanceof t)) + throw new Error("invalid point at index " + r); + }); +} +function ci(e, t) { + if (!Array.isArray(e)) + throw new Error("array of scalars expected"); + e.forEach((n, r) => { + if (!t.isValid(n)) + throw new Error("invalid scalar at index " + r); + }); +} +const Bt = /* @__PURE__ */ new WeakMap(), un = /* @__PURE__ */ new WeakMap(); +function Qt(e) { + return un.get(e) || 1; +} +function Ir(e) { + if (e !== Se) + throw new Error("invalid wNAF"); +} +class ui { + // Parametrized with a given Point class (not individual point) + constructor(t, n) { + this.BASE = t.BASE, this.ZERO = t.ZERO, this.Fn = t.Fn, this.bits = n; + } + // non-const time multiplication ladder + _unsafeLadder(t, n, r = this.ZERO) { + let i = t; + for (; n > Se; ) + n & ye && (r = r.add(i)), i = i.double(), n >>= ye; + return r; + } + /** + * Creates a wNAF precomputation window. Used for caching. + * Default window size is set by `utils.precompute()` and is equal to 8. + * Number of precomputed points depends on the curve size: + * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: + * - 𝑊 is the window size + * - 𝑛 is the bitlength of the curve order. + * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. + * @param point Point instance + * @param W window size + * @returns precomputed point tables flattened to a single array + */ + precomputeWindow(t, n) { + const { windows: r, windowSize: i } = vt(n, this.bits), a = []; + let o = t, s = o; + for (let l = 0; l < r; l++) { + s = o, a.push(s); + for (let u = 1; u < i; u++) + s = s.add(o), a.push(s); + o = s.double(); + } + return a; + } + /** + * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. + * More compact implementation: + * https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541 + * @returns real and fake (for const-time) points + */ + wNAF(t, n, r) { + if (!this.Fn.isValid(r)) + throw new Error("invalid scalar"); + let i = this.ZERO, a = this.BASE; + const o = vt(t, this.bits); + for (let s = 0; s < o.windows; s++) { + const { nextN: l, offset: u, isZero: h, isNeg: g, isNegF: c, offsetF: d } = pr(r, s, o); + r = l, h ? a = a.add(ot(c, n[d])) : i = i.add(ot(g, n[u])); + } + return Ir(r), { p: i, f: a }; + } + /** + * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form. + * @param acc accumulator point to add result of multiplication + * @returns point + */ + wNAFUnsafe(t, n, r, i = this.ZERO) { + const a = vt(t, this.bits); + for (let o = 0; o < a.windows && r !== Se; o++) { + const { nextN: s, offset: l, isZero: u, isNeg: h } = pr(r, o, a); + if (r = s, !u) { + const g = n[l]; + i = i.add(h ? g.negate() : g); + } + } + return Ir(r), i; + } + getPrecomputes(t, n, r) { + let i = Bt.get(n); + return i || (i = this.precomputeWindow(n, t), t !== 1 && (typeof r == "function" && (i = r(i)), Bt.set(n, i))), i; + } + cached(t, n, r) { + const i = Qt(t); + return this.wNAF(i, this.getPrecomputes(i, t, r), n); + } + unsafe(t, n, r, i) { + const a = Qt(t); + return a === 1 ? this._unsafeLadder(t, n, i) : this.wNAFUnsafe(a, this.getPrecomputes(a, t, r), n, i); + } + // We calculate precomputes for elliptic curve point multiplication + // using windowed method. This specifies window size and + // stores precomputed values. Usually only base point would be precomputed. + createCache(t, n) { + cn(n, this.bits), un.set(t, n), Bt.delete(t); + } + hasCache(t) { + return Qt(t) !== 1; + } +} +function di(e, t, n, r) { + let i = t, a = e.ZERO, o = e.ZERO; + for (; n > Se || r > Se; ) + n & ye && (a = a.add(i)), r & ye && (o = o.add(i)), i = i.double(), n >>= ye, r >>= ye; + return { p1: a, p2: o }; +} +function gi(e, t, n, r) { + li(n, e), ci(r, t); + const i = n.length, a = r.length; + if (i !== a) + throw new Error("arrays of points and scalars must have equal length"); + const o = e.ZERO, s = Tr(BigInt(i)); + let l = 1; + s > 12 ? l = s - 3 : s > 4 ? l = s - 2 : s > 0 && (l = 2); + const u = je(l), h = new Array(Number(u) + 1).fill(o), g = Math.floor((t.BITS - 1) / l) * l; + let c = o; + for (let d = g; d >= 0; d -= l) { + h.fill(o); + for (let m = 0; m < a; m++) { + const B = r[m], S = Number(B >> BigInt(d) & u); + h[S] = h[S].add(n[m]); + } + let I = o; + for (let m = h.length - 1, B = o; m > 0; m--) + B = B.add(h[m]), I = I.add(B); + if (c = c.add(I), d !== 0) + for (let m = 0; m < l; m++) + c = c.double(); + } + return c; +} +function mr(e, t, n) { + if (t) { + if (t.ORDER !== e) + throw new Error("Field.ORDER must match order: Fp == p, Fn == n"); + return oi(t), t; + } else + return Re(e, { isLE: n }); +} +function Ai(e, t, n = {}, r) { + if (r === void 0 && (r = e === "edwards"), !t || typeof t != "object") + throw new Error(`expected valid ${e} CURVE object`); + for (const l of ["p", "n", "h"]) { + const u = t[l]; + if (!(typeof u == "bigint" && u > Se)) + throw new Error(`CURVE.${l} must be positive bigint`); + } + const i = mr(t.p, n.Fp, r), a = mr(t.n, n.Fn, r), s = ["Gx", "Gy", "a", "b"]; + for (const l of s) + if (!i.isValid(t[l])) + throw new Error(`CURVE.${l} must be valid field element of CURVE.Fp`); + return t = Object.freeze(Object.assign({}, t)), { CURVE: t, Fp: i, Fn: a }; +} +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const yr = (e, t) => (e + (e >= 0 ? t : -t) / dn) / t; +function hi(e, t, n) { + const [[r, i], [a, o]] = t, s = yr(o * e, n), l = yr(-i * e, n); + let u = e - s * r - l * a, h = -s * i - l * o; + const g = u < ce, c = h < ce; + g && (u = -u), c && (h = -h); + const d = je(Math.ceil(Tr(n) / 2)) + xe; + if (u < ce || u >= d || h < ce || h >= d) + throw new Error("splitScalar (endomorphism): failed, k=" + e); + return { k1neg: g, k1: u, k2neg: c, k2: h }; +} +function Nt(e) { + if (!["compact", "recovered", "der"].includes(e)) + throw new Error('Signature format must be "compact", "recovered", or "der"'); + return e; +} +function Et(e, t) { + const n = {}; + for (let r of Object.keys(t)) + n[r] = e[r] === void 0 ? t[r] : e[r]; + return at(n.lowS, "lowS"), at(n.prehash, "prehash"), n.format !== void 0 && Nt(n.format), n; +} +class fi extends Error { + constructor(t = "") { + super(t); + } +} +const le = { + // asn.1 DER encoding utils + Err: fi, + // Basic building block is TLV (Tag-Length-Value) + _tlv: { + encode: (e, t) => { + const { Err: n } = le; + if (e < 0 || e > 256) + throw new n("tlv.encode: wrong tag"); + if (t.length & 1) + throw new n("tlv.encode: unpadded data"); + const r = t.length / 2, i = Xe(r); + if (i.length / 2 & 128) + throw new n("tlv.encode: long form length too big"); + const a = r > 127 ? Xe(i.length / 2 | 128) : ""; + return Xe(e) + a + i + t; + }, + // v - value, l - left bytes (unparsed) + decode(e, t) { + const { Err: n } = le; + let r = 0; + if (e < 0 || e > 256) + throw new n("tlv.encode: wrong tag"); + if (t.length < 2 || t[r++] !== e) + throw new n("tlv.decode: wrong tlv"); + const i = t[r++], a = !!(i & 128); + let o = 0; + if (!a) + o = i; + else { + const l = i & 127; + if (!l) + throw new n("tlv.decode(long): indefinite length not supported"); + if (l > 4) + throw new n("tlv.decode(long): byte length is too big"); + const u = t.subarray(r, r + l); + if (u.length !== l) + throw new n("tlv.decode: length bytes not complete"); + if (u[0] === 0) + throw new n("tlv.decode(long): zero leftmost byte"); + for (const h of u) + o = o << 8 | h; + if (r += l, o < 128) + throw new n("tlv.decode(long): not minimal encoding"); + } + const s = t.subarray(r, r + o); + if (s.length !== o) + throw new n("tlv.decode: wrong value length"); + return { v: s, l: t.subarray(r + o) }; + } + }, + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + _int: { + encode(e) { + const { Err: t } = le; + if (e < ce) + throw new t("integer: negative integers are not allowed"); + let n = Xe(e); + if (Number.parseInt(n[0], 16) & 8 && (n = "00" + n), n.length & 1) + throw new t("unexpected DER parsing assertion: unpadded hex"); + return n; + }, + decode(e) { + const { Err: t } = le; + if (e[0] & 128) + throw new t("invalid signature integer: negative"); + if (e[0] === 0 && !(e[1] & 128)) + throw new t("invalid signature integer: unnecessary leading zero"); + return Ge(e); + } + }, + toSig(e) { + const { Err: t, _int: n, _tlv: r } = le, i = q("signature", e), { v: a, l: o } = r.decode(48, i); + if (o.length) + throw new t("invalid signature: left bytes after parsing"); + const { v: s, l } = r.decode(2, a), { v: u, l: h } = r.decode(2, l); + if (h.length) + throw new t("invalid signature: left bytes after parsing"); + return { r: n.decode(s), s: n.decode(u) }; + }, + hexFromSig(e) { + const { _tlv: t, _int: n } = le, r = t.encode(2, n.encode(e.r)), i = t.encode(2, n.encode(e.s)), a = r + i; + return t.encode(48, a); + } +}, ce = BigInt(0), xe = BigInt(1), dn = BigInt(2), Ze = BigInt(3), pi = BigInt(4); +function be(e, t) { + const { BYTES: n } = e; + let r; + if (typeof t == "bigint") + r = t; + else { + let i = q("private key", t); + try { + r = e.fromBytes(i); + } catch { + throw new Error(`invalid private key: expected ui8a of size ${n}, got ${typeof t}`); + } + } + if (!e.isValidNot0(r)) + throw new Error("invalid private key: out of range [1..N-1]"); + return r; +} +function Ii(e, t = {}) { + const n = Ai("weierstrass", e, t), { Fp: r, Fn: i } = n; + let a = n.CURVE; + const { h: o, n: s } = a; + Pt(t, {}, { + allowInfinityPoint: "boolean", + clearCofactor: "function", + isTorsionFree: "function", + fromBytes: "function", + toBytes: "function", + endo: "object", + wrapPrivateKey: "boolean" + }); + const { endo: l } = t; + if (l && (!r.is0(a.a) || typeof l.beta != "bigint" || !Array.isArray(l.basises))) + throw new Error('invalid endo: expected "beta": bigint and "basises": array'); + const u = An(r, i); + function h() { + if (!r.isOdd) + throw new Error("compression is not supported: Field does not have .isOdd()"); + } + function g(U, p, f) { + const { x: A, y } = p.toAffine(), w = r.toBytes(A); + if (at(f, "isCompressed"), f) { + h(); + const E = !r.isOdd(y); + return ne(gn(E), w); + } else + return ne(Uint8Array.of(4), w, r.toBytes(y)); + } + function c(U) { + Ie(U, void 0, "Point"); + const { publicKey: p, publicKeyUncompressed: f } = u, A = U.length, y = U[0], w = U.subarray(1); + if (A === p && (y === 2 || y === 3)) { + const E = r.fromBytes(w); + if (!r.isValid(E)) + throw new Error("bad point: is not on curve, wrong x"); + const Q = m(E); + let k; + try { + k = r.sqrt(Q); + } catch (Y) { + const O = Y instanceof Error ? ": " + Y.message : ""; + throw new Error("bad point: is not on curve, sqrt error" + O); + } + h(); + const x = r.isOdd(k); + return (y & 1) === 1 !== x && (k = r.neg(k)), { x: E, y: k }; + } else if (A === f && y === 4) { + const E = r.BYTES, Q = r.fromBytes(w.subarray(0, E)), k = r.fromBytes(w.subarray(E, E * 2)); + if (!B(Q, k)) + throw new Error("bad point: is not on curve"); + return { x: Q, y: k }; + } else + throw new Error(`bad point: got length ${A}, expected compressed=${p} or uncompressed=${f}`); + } + const d = t.toBytes || g, I = t.fromBytes || c; + function m(U) { + const p = r.sqr(U), f = r.mul(p, U); + return r.add(r.add(f, r.mul(U, a.a)), a.b); + } + function B(U, p) { + const f = r.sqr(p), A = m(U); + return r.eql(f, A); + } + if (!B(a.Gx, a.Gy)) + throw new Error("bad curve params: generator point"); + const S = r.mul(r.pow(a.a, Ze), pi), j = r.mul(r.sqr(a.b), BigInt(27)); + if (r.is0(r.add(S, j))) + throw new Error("bad curve params: a or b"); + function b(U, p, f = !1) { + if (!r.isValid(p) || f && r.is0(p)) + throw new Error(`bad point coordinate ${U}`); + return p; + } + function N(U) { + if (!(U instanceof v)) + throw new Error("ProjectivePoint expected"); + } + function K(U) { + if (!l || !l.basises) + throw new Error("no endo"); + return hi(U, l.basises, i.ORDER); + } + const C = Ar((U, p) => { + const { X: f, Y: A, Z: y } = U; + if (r.eql(y, r.ONE)) + return { x: f, y: A }; + const w = U.is0(); + p == null && (p = w ? r.ONE : r.inv(y)); + const E = r.mul(f, p), Q = r.mul(A, p), k = r.mul(y, p); + if (w) + return { x: r.ZERO, y: r.ZERO }; + if (!r.eql(k, r.ONE)) + throw new Error("invZ was invalid"); + return { x: E, y: Q }; + }), D = Ar((U) => { + if (U.is0()) { + if (t.allowInfinityPoint && !r.is0(U.Y)) + return; + throw new Error("bad point: ZERO"); + } + const { x: p, y: f } = U.toAffine(); + if (!r.isValid(p) || !r.isValid(f)) + throw new Error("bad point: x or y not field elements"); + if (!B(p, f)) + throw new Error("bad point: equation left != right"); + if (!U.isTorsionFree()) + throw new Error("bad point: not in prime-order subgroup"); + return !0; + }); + function G(U, p, f, A, y) { + return f = new v(r.mul(f.X, U), f.Y, f.Z), p = ot(A, p), f = ot(y, f), p.add(f); + } + class v { + /** Does NOT validate if the point is valid. Use `.assertValidity()`. */ + constructor(p, f, A) { + this.X = b("x", p), this.Y = b("y", f, !0), this.Z = b("z", A), Object.freeze(this); + } + static CURVE() { + return a; + } + /** Does NOT validate if the point is valid. Use `.assertValidity()`. */ + static fromAffine(p) { + const { x: f, y: A } = p || {}; + if (!p || !r.isValid(f) || !r.isValid(A)) + throw new Error("invalid affine point"); + if (p instanceof v) + throw new Error("projective point not allowed"); + return r.is0(f) && r.is0(A) ? v.ZERO : new v(f, A, r.ONE); + } + static fromBytes(p) { + const f = v.fromAffine(I(Ie(p, void 0, "point"))); + return f.assertValidity(), f; + } + static fromHex(p) { + return v.fromBytes(q("pointHex", p)); + } + get x() { + return this.toAffine().x; + } + get y() { + return this.toAffine().y; + } + /** + * + * @param windowSize + * @param isLazy true will defer table computation until the first multiplication + * @returns + */ + precompute(p = 8, f = !0) { + return Z.createCache(this, p), f || this.multiply(Ze), this; + } + // TODO: return `this` + /** A point on curve is valid if it conforms to equation. */ + assertValidity() { + D(this); + } + hasEvenY() { + const { y: p } = this.toAffine(); + if (!r.isOdd) + throw new Error("Field doesn't support isOdd"); + return !r.isOdd(p); + } + /** Compare one point to another. */ + equals(p) { + N(p); + const { X: f, Y: A, Z: y } = this, { X: w, Y: E, Z: Q } = p, k = r.eql(r.mul(f, Q), r.mul(w, y)), x = r.eql(r.mul(A, Q), r.mul(E, y)); + return k && x; + } + /** Flips point to one corresponding to (x, -y) in Affine coordinates. */ + negate() { + return new v(this.X, r.neg(this.Y), this.Z); + } + // Renes-Costello-Batina exception-free doubling formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 3 + // Cost: 8M + 3S + 3*a + 2*b3 + 15add. + double() { + const { a: p, b: f } = a, A = r.mul(f, Ze), { X: y, Y: w, Z: E } = this; + let Q = r.ZERO, k = r.ZERO, x = r.ZERO, F = r.mul(y, y), Y = r.mul(w, w), O = r.mul(E, E), H = r.mul(y, w); + return H = r.add(H, H), x = r.mul(y, E), x = r.add(x, x), Q = r.mul(p, x), k = r.mul(A, O), k = r.add(Q, k), Q = r.sub(Y, k), k = r.add(Y, k), k = r.mul(Q, k), Q = r.mul(H, Q), x = r.mul(A, x), O = r.mul(p, O), H = r.sub(F, O), H = r.mul(p, H), H = r.add(H, x), x = r.add(F, F), F = r.add(x, F), F = r.add(F, O), F = r.mul(F, H), k = r.add(k, F), O = r.mul(w, E), O = r.add(O, O), F = r.mul(O, H), Q = r.sub(Q, F), x = r.mul(O, Y), x = r.add(x, x), x = r.add(x, x), new v(Q, k, x); + } + // Renes-Costello-Batina exception-free addition formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 1 + // Cost: 12M + 0S + 3*a + 3*b3 + 23add. + add(p) { + N(p); + const { X: f, Y: A, Z: y } = this, { X: w, Y: E, Z: Q } = p; + let k = r.ZERO, x = r.ZERO, F = r.ZERO; + const Y = a.a, O = r.mul(a.b, Ze); + let H = r.mul(f, w), z = r.mul(A, E), M = r.mul(y, Q), T = r.add(f, A), J = r.add(w, E); + T = r.mul(T, J), J = r.add(H, z), T = r.sub(T, J), J = r.add(f, y); + let R = r.add(w, Q); + return J = r.mul(J, R), R = r.add(H, M), J = r.sub(J, R), R = r.add(A, y), k = r.add(E, Q), R = r.mul(R, k), k = r.add(z, M), R = r.sub(R, k), F = r.mul(Y, J), k = r.mul(O, M), F = r.add(k, F), k = r.sub(z, F), F = r.add(z, F), x = r.mul(k, F), z = r.add(H, H), z = r.add(z, H), M = r.mul(Y, M), J = r.mul(O, J), z = r.add(z, M), M = r.sub(H, M), M = r.mul(Y, M), J = r.add(J, M), H = r.mul(z, J), x = r.add(x, H), H = r.mul(R, J), k = r.mul(T, k), k = r.sub(k, H), H = r.mul(T, z), F = r.mul(R, F), F = r.add(F, H), new v(k, x, F); + } + subtract(p) { + return this.add(p.negate()); + } + is0() { + return this.equals(v.ZERO); + } + /** + * Constant time multiplication. + * Uses wNAF method. Windowed method may be 10% faster, + * but takes 2x longer to generate and consumes 2x memory. + * Uses precomputes when available. + * Uses endomorphism for Koblitz curves. + * @param scalar by which the point would be multiplied + * @returns New point + */ + multiply(p) { + const { endo: f } = t; + if (!i.isValidNot0(p)) + throw new Error("invalid scalar: out of range"); + let A, y; + const w = (E) => Z.cached(this, E, (Q) => kt(v, Q)); + if (f) { + const { k1neg: E, k1: Q, k2neg: k, k2: x } = K(p), { p: F, f: Y } = w(Q), { p: O, f: H } = w(x); + y = Y.add(H), A = G(f.beta, F, O, E, k); + } else { + const { p: E, f: Q } = w(p); + A = E, y = Q; + } + return kt(v, [A, y])[0]; + } + /** + * Non-constant-time multiplication. Uses double-and-add algorithm. + * It's faster, but should only be used when you don't care about + * an exposed secret key e.g. sig verification, which works over *public* keys. + */ + multiplyUnsafe(p) { + const { endo: f } = t, A = this; + if (!i.isValid(p)) + throw new Error("invalid scalar: out of range"); + if (p === ce || A.is0()) + return v.ZERO; + if (p === xe) + return A; + if (Z.hasCache(this)) + return this.multiply(p); + if (f) { + const { k1neg: y, k1: w, k2neg: E, k2: Q } = K(p), { p1: k, p2: x } = di(v, A, w, Q); + return G(f.beta, k, x, y, E); + } else + return Z.unsafe(A, p); + } + multiplyAndAddUnsafe(p, f, A) { + const y = this.multiplyUnsafe(f).add(p.multiplyUnsafe(A)); + return y.is0() ? void 0 : y; + } + /** + * Converts Projective point to affine (x, y) coordinates. + * @param invertedZ Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch + */ + toAffine(p) { + return C(this, p); + } + /** + * Checks whether Point is free of torsion elements (is in prime subgroup). + * Always torsion-free for cofactor=1 curves. + */ + isTorsionFree() { + const { isTorsionFree: p } = t; + return o === xe ? !0 : p ? p(v, this) : Z.unsafe(this, s).is0(); + } + clearCofactor() { + const { clearCofactor: p } = t; + return o === xe ? this : p ? p(v, this) : this.multiplyUnsafe(o); + } + isSmallOrder() { + return this.multiplyUnsafe(o).is0(); + } + toBytes(p = !0) { + return at(p, "isCompressed"), this.assertValidity(), d(v, this, p); + } + toHex(p = !0) { + return Ee(this.toBytes(p)); + } + toString() { + return ``; + } + // TODO: remove + get px() { + return this.X; + } + get py() { + return this.X; + } + get pz() { + return this.Z; + } + toRawBytes(p = !0) { + return this.toBytes(p); + } + _setWindowSize(p) { + this.precompute(p); + } + static normalizeZ(p) { + return kt(v, p); + } + static msm(p, f) { + return gi(v, i, p, f); + } + static fromPrivateKey(p) { + return v.BASE.multiply(be(i, p)); + } + } + v.BASE = new v(a.Gx, a.Gy, r.ONE), v.ZERO = new v(r.ZERO, r.ONE, r.ZERO), v.Fp = r, v.Fn = i; + const P = i.BITS, Z = new ui(v, t.endo ? Math.ceil(P / 2) : P); + return v.BASE.precompute(8), v; +} +function gn(e) { + return Uint8Array.of(e ? 2 : 3); +} +function An(e, t) { + return { + secretKey: t.BYTES, + publicKey: 1 + e.BYTES, + publicKeyUncompressed: 1 + 2 * e.BYTES, + publicKeyHasPrefix: !0, + signature: 2 * t.BYTES + }; +} +function mi(e, t = {}) { + const { Fn: n } = e, r = t.randomBytes || ft, i = Object.assign(An(e.Fp, n), { seed: sn(n.ORDER) }); + function a(d) { + try { + return !!be(n, d); + } catch { + return !1; + } + } + function o(d, I) { + const { publicKey: m, publicKeyUncompressed: B } = i; + try { + const S = d.length; + return I === !0 && S !== m || I === !1 && S !== B ? !1 : !!e.fromBytes(d); + } catch { + return !1; + } + } + function s(d = r(i.seed)) { + return ln(Ie(d, i.seed, "seed"), n.ORDER); + } + function l(d, I = !0) { + return e.BASE.multiply(be(n, d)).toBytes(I); + } + function u(d) { + const I = s(d); + return { secretKey: I, publicKey: l(I) }; + } + function h(d) { + if (typeof d == "bigint") + return !1; + if (d instanceof e) + return !0; + const { secretKey: I, publicKey: m, publicKeyUncompressed: B } = i; + if (n.allowedLengths || I === m) + return; + const S = q("key", d).length; + return S === m || S === B; + } + function g(d, I, m = !0) { + if (h(d) === !0) + throw new Error("first arg must be private key"); + if (h(I) === !1) + throw new Error("second arg must be public key"); + const B = be(n, d); + return e.fromHex(I).multiply(B).toBytes(m); + } + return Object.freeze({ getPublicKey: l, getSharedSecret: g, keygen: u, Point: e, utils: { + isValidSecretKey: a, + isValidPublicKey: o, + randomSecretKey: s, + // TODO: remove + isValidPrivateKey: a, + randomPrivateKey: s, + normPrivateKeyToScalar: (d) => be(n, d), + precompute(d = 8, I = e.BASE) { + return I.precompute(d, !1); + } + }, lengths: i }); +} +function yi(e, t, n = {}) { + ht(t), Pt(n, {}, { + hmac: "function", + lowS: "boolean", + randomBytes: "function", + bits2int: "function", + bits2int_modN: "function" + }); + const r = n.randomBytes || ft, i = n.hmac || ((f, ...A) => pt(t, f, ne(...A))), { Fp: a, Fn: o } = e, { ORDER: s, BITS: l } = o, { keygen: u, getPublicKey: h, getSharedSecret: g, utils: c, lengths: d } = mi(e, n), I = { + prehash: !1, + lowS: typeof n.lowS == "boolean" ? n.lowS : !1, + format: void 0, + //'compact' as ECDSASigFormat, + extraEntropy: !1 + }, m = "compact"; + function B(f) { + const A = s >> xe; + return f > A; + } + function S(f, A) { + if (!o.isValidNot0(A)) + throw new Error(`invalid signature ${f}: out of range 1..Point.Fn.ORDER`); + return A; + } + function j(f, A) { + Nt(A); + const y = d.signature, w = A === "compact" ? y : A === "recovered" ? y + 1 : void 0; + return Ie(f, w, `${A} signature`); + } + class b { + constructor(A, y, w) { + this.r = S("r", A), this.s = S("s", y), w != null && (this.recovery = w), Object.freeze(this); + } + static fromBytes(A, y = m) { + j(A, y); + let w; + if (y === "der") { + const { r: x, s: F } = le.toSig(Ie(A)); + return new b(x, F); + } + y === "recovered" && (w = A[0], y = "compact", A = A.subarray(1)); + const E = o.BYTES, Q = A.subarray(0, E), k = A.subarray(E, E * 2); + return new b(o.fromBytes(Q), o.fromBytes(k), w); + } + static fromHex(A, y) { + return this.fromBytes(it(A), y); + } + addRecoveryBit(A) { + return new b(this.r, this.s, A); + } + recoverPublicKey(A) { + const y = a.ORDER, { r: w, s: E, recovery: Q } = this; + if (Q == null || ![0, 1, 2, 3].includes(Q)) + throw new Error("recovery id invalid"); + if (s * dn < y && Q > 1) + throw new Error("recovery id is ambiguous for h>1 curve"); + const x = Q === 2 || Q === 3 ? w + s : w; + if (!a.isValid(x)) + throw new Error("recovery id 2 or 3 invalid"); + const F = a.toBytes(x), Y = e.fromBytes(ne(gn((Q & 1) === 0), F)), O = o.inv(x), H = K(q("msgHash", A)), z = o.create(-H * O), M = o.create(E * O), T = e.BASE.multiplyUnsafe(z).add(Y.multiplyUnsafe(M)); + if (T.is0()) + throw new Error("point at infinify"); + return T.assertValidity(), T; + } + // Signatures should be low-s, to prevent malleability. + hasHighS() { + return B(this.s); + } + toBytes(A = m) { + if (Nt(A), A === "der") + return it(le.hexFromSig(this)); + const y = o.toBytes(this.r), w = o.toBytes(this.s); + if (A === "recovered") { + if (this.recovery == null) + throw new Error("recovery bit must be present"); + return ne(Uint8Array.of(this.recovery), y, w); + } + return ne(y, w); + } + toHex(A) { + return Ee(this.toBytes(A)); + } + // TODO: remove + assertValidity() { + } + static fromCompact(A) { + return b.fromBytes(q("sig", A), "compact"); + } + static fromDER(A) { + return b.fromBytes(q("sig", A), "der"); + } + normalizeS() { + return this.hasHighS() ? new b(this.r, o.neg(this.s), this.recovery) : this; + } + toDERRawBytes() { + return this.toBytes("der"); + } + toDERHex() { + return Ee(this.toBytes("der")); + } + toCompactRawBytes() { + return this.toBytes("compact"); + } + toCompactHex() { + return Ee(this.toBytes("compact")); + } + } + const N = n.bits2int || function(A) { + if (A.length > 8192) + throw new Error("input is too large"); + const y = Ge(A), w = A.length * 8 - l; + return w > 0 ? y >> BigInt(w) : y; + }, K = n.bits2int_modN || function(A) { + return o.create(N(A)); + }, C = je(l); + function D(f) { + return $n("num < 2^" + l, f, ce, C), o.toBytes(f); + } + function G(f, A) { + return Ie(f, void 0, "message"), A ? Ie(t(f), void 0, "prehashed message") : f; + } + function v(f, A, y) { + if (["recovered", "canonical"].some((z) => z in y)) + throw new Error("sign() legacy options not supported"); + const { lowS: w, prehash: E, extraEntropy: Q } = Et(y, I); + f = G(f, E); + const k = K(f), x = be(o, A), F = [D(x), D(k)]; + if (Q != null && Q !== !1) { + const z = Q === !0 ? r(d.secretKey) : Q; + F.push(q("extraEntropy", z)); + } + const Y = ne(...F), O = k; + function H(z) { + const M = N(z); + if (!o.isValidNot0(M)) + return; + const T = o.inv(M), J = e.BASE.multiply(M).toAffine(), R = o.create(J.x); + if (R === ce) + return; + const _e = o.create(T * o.create(O + R * x)); + if (_e === ce) + return; + let ir = (J.x === R ? 0 : 2) | Number(J.y & xe), ar = _e; + return w && B(_e) && (ar = o.neg(_e), ir ^= 1), new b(R, ar, ir); + } + return { seed: Y, k2sig: H }; + } + function P(f, A, y = {}) { + f = q("message", f); + const { seed: w, k2sig: E } = v(f, A, y); + return Wn(t.outputLen, o.BYTES, i)(w, E); + } + function Z(f) { + let A; + const y = typeof f == "string" || At(f), w = !y && f !== null && typeof f == "object" && typeof f.r == "bigint" && typeof f.s == "bigint"; + if (!y && !w) + throw new Error("invalid signature, expected Uint8Array, hex string or Signature instance"); + if (w) + A = new b(f.r, f.s); + else if (y) { + try { + A = b.fromBytes(q("sig", f), "der"); + } catch (E) { + if (!(E instanceof le.Err)) + throw E; + } + if (!A) + try { + A = b.fromBytes(q("sig", f), "compact"); + } catch { + return !1; + } + } + return A || !1; + } + function U(f, A, y, w = {}) { + const { lowS: E, prehash: Q, format: k } = Et(w, I); + if (y = q("publicKey", y), A = G(q("message", A), Q), "strict" in w) + throw new Error("options.strict was renamed to lowS"); + const x = k === void 0 ? Z(f) : b.fromBytes(q("sig", f), k); + if (x === !1) + return !1; + try { + const F = e.fromBytes(y); + if (E && x.hasHighS()) + return !1; + const { r: Y, s: O } = x, H = K(A), z = o.inv(O), M = o.create(H * z), T = o.create(Y * z), J = e.BASE.multiplyUnsafe(M).add(F.multiplyUnsafe(T)); + return J.is0() ? !1 : o.create(J.x) === Y; + } catch { + return !1; + } + } + function p(f, A, y = {}) { + const { prehash: w } = Et(y, I); + return A = G(A, w), b.fromBytes(f, "recovered").recoverPublicKey(A).toBytes(); + } + return Object.freeze({ + keygen: u, + getPublicKey: h, + getSharedSecret: g, + utils: c, + lengths: d, + Point: e, + sign: P, + verify: U, + recoverPublicKey: p, + Signature: b, + hash: t + }); +} +function bi(e) { + const t = { + a: e.a, + b: e.b, + p: e.Fp.ORDER, + n: e.n, + h: e.h, + Gx: e.Gx, + Gy: e.Gy + }, n = e.Fp; + let r = e.allowedPrivateKeyLengths ? Array.from(new Set(e.allowedPrivateKeyLengths.map((o) => Math.ceil(o / 2)))) : void 0; + const i = Re(t.n, { + BITS: e.nBitLength, + allowedLengths: r, + modFromBytes: e.wrapPrivateKey + }), a = { + Fp: n, + Fn: i, + allowInfinityPoint: e.allowInfinityPoint, + endo: e.endo, + isTorsionFree: e.isTorsionFree, + clearCofactor: e.clearCofactor, + fromBytes: e.fromBytes, + toBytes: e.toBytes + }; + return { CURVE: t, curveOpts: a }; +} +function wi(e) { + const { CURVE: t, curveOpts: n } = bi(e), r = { + hmac: e.hmac, + randomBytes: e.randomBytes, + lowS: e.lowS, + bits2int: e.bits2int, + bits2int_modN: e.bits2int_modN + }; + return { CURVE: t, curveOpts: n, hash: e.hash, ecdsaOpts: r }; +} +function Ci(e, t) { + const n = t.Point; + return Object.assign({}, t, { + ProjectivePoint: n, + CURVE: Object.assign({}, e, an(n.Fn.ORDER, n.Fn.BITS)) + }); +} +function ki(e) { + const { CURVE: t, curveOpts: n, hash: r, ecdsaOpts: i } = wi(e), a = Ii(t, n), o = yi(a, r, i); + return Ci(e, o); +} +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +function vi(e, t) { + const n = (r) => ki({ ...e, hash: r }); + return { ...n(t), create: n }; +} +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const Fe = { + p: BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"), + n: BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"), + h: BigInt(1), + a: BigInt(0), + b: BigInt(7), + Gx: BigInt("0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"), + Gy: BigInt("0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8") +}, Bi = { + beta: BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"), + basises: [ + [BigInt("0x3086d221a7d46bcde86c90e49284eb15"), -BigInt("0xe4437ed6010e88286f547fa90abfe4c3")], + [BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8"), BigInt("0x3086d221a7d46bcde86c90e49284eb15")] + ] +}, Qi = /* @__PURE__ */ BigInt(0), br = /* @__PURE__ */ BigInt(1), Kt = /* @__PURE__ */ BigInt(2); +function Ei(e) { + const t = Fe.p, n = BigInt(3), r = BigInt(6), i = BigInt(11), a = BigInt(22), o = BigInt(23), s = BigInt(44), l = BigInt(88), u = e * e * e % t, h = u * u * e % t, g = $(h, n, t) * h % t, c = $(g, n, t) * h % t, d = $(c, Kt, t) * u % t, I = $(d, i, t) * d % t, m = $(I, a, t) * I % t, B = $(m, s, t) * m % t, S = $(B, l, t) * B % t, j = $(S, s, t) * m % t, b = $(j, n, t) * h % t, N = $(b, o, t) * I % t, K = $(N, r, t) * u % t, C = $(K, Kt, t); + if (!st.eql(st.sqr(C), e)) + throw new Error("Cannot find square root"); + return C; +} +const st = Re(Fe.p, { sqrt: Ei }), mt = vi({ ...Fe, Fp: st, lowS: !0, endo: Bi }, fe), wr = {}; +function lt(e, ...t) { + let n = wr[e]; + if (n === void 0) { + const r = fe(qt(e)); + n = ne(r, r), wr[e] = n; + } + return fe(ne(n, ...t)); +} +const Tt = (e) => e.toBytes(!0).slice(1), He = mt.Point, Xt = (e) => e % Kt === Qi; +function Ot(e) { + const { Fn: t, BASE: n } = He, r = be(t, e), i = n.multiply(r); + return { scalar: Xt(i.y) ? r : t.neg(r), bytes: Tt(i) }; +} +function hn(e) { + const t = st; + if (!t.isValidNot0(e)) + throw new Error("invalid x: Fail if x ≥ p"); + const n = t.create(e * e), r = t.create(n * e + BigInt(7)); + let i = t.sqrt(r); + Xt(i) || (i = t.neg(i)); + const a = He.fromAffine({ x: e, y: i }); + return a.assertValidity(), a; +} +const Ye = Ge; +function fn(...e) { + return He.Fn.create(Ye(lt("BIP0340/challenge", ...e))); +} +function Cr(e) { + return Ot(e).bytes; +} +function xi(e, t, n = ft(32)) { + const { Fn: r } = He, i = q("message", e), { bytes: a, scalar: o } = Ot(t), s = q("auxRand", n, 32), l = r.toBytes(o ^ Ye(lt("BIP0340/aux", s))), u = lt("BIP0340/nonce", l, a, i), { bytes: h, scalar: g } = Ot(u), c = fn(h, a, i), d = new Uint8Array(64); + if (d.set(h, 0), d.set(r.toBytes(r.create(g + c * o)), 32), !pn(d, i, a)) + throw new Error("sign: Invalid signature produced"); + return d; +} +function pn(e, t, n) { + const { Fn: r, BASE: i } = He, a = q("signature", e, 64), o = q("message", t), s = q("publicKey", n, 32); + try { + const l = hn(Ye(s)), u = Ye(a.subarray(0, 32)); + if (!Ht(u, br, Fe.p)) + return !1; + const h = Ye(a.subarray(32, 64)); + if (!Ht(h, br, Fe.n)) + return !1; + const g = fn(r.toBytes(u), Tt(l), o), c = i.multiplyUnsafe(h).add(l.multiplyUnsafe(r.neg(g))), { x: d, y: I } = c.toAffine(); + return !(c.is0() || !Xt(I) || d !== u); + } catch { + return !1; + } +} +const Zt = /* @__PURE__ */ (() => { + const n = (i = ft(48)) => ln(i, Fe.n); + mt.utils.randomSecretKey; + function r(i) { + const a = n(i); + return { secretKey: a, publicKey: Cr(a) }; + } + return { + keygen: r, + getPublicKey: Cr, + sign: xi, + verify: pn, + Point: He, + utils: { + randomSecretKey: n, + randomPrivateKey: n, + taggedHash: lt, + // TODO: remove + lift_x: hn, + pointToBytes: Tt, + numberToBytesBE: It, + bytesToNumberBE: Ge, + mod: W + }, + lengths: { + secretKey: 32, + publicKey: 32, + publicKeyHasPrefix: !1, + signature: 64, + seed: 48 + } + }; +})(), Di = mt.CURVE.n; +function Si(e) { + let t = 0n; + for (const n of e) + t = t << 8n | BigInt(n); + return t; +} +function Fi(e) { + const t = new Uint8Array(32); + let n = e; + for (let r = 31; r >= 0; r--) + t[r] = Number(n & 0xffn), n >>= 8n; + return t; +} +function In(e, t) { + const n = De(t); + for (let r = 0; r <= 255; r++) { + const i = qr(n, new Uint8Array([0, r])), a = Rt(e, i, 32), o = Si(a); + if (o >= 1n && o < Di) + return { scalar: Fi(o), counter: r }; + } + throw new Error("ScalarExpand: exhausted 256 counters without a valid scalar (should not happen in practice)."); +} +/*! + * hash-wasm (https://www.npmjs.com/package/hash-wasm) + * (c) Dani Biro + * @license MIT + */ +function we(e, t, n, r) { + function i(a) { + return a instanceof n ? a : new n(function(o) { + o(a); + }); + } + return new (n || (n = Promise))(function(a, o) { + function s(h) { + try { + u(r.next(h)); + } catch (g) { + o(g); + } + } + function l(h) { + try { + u(r.throw(h)); + } catch (g) { + o(g); + } + } + function u(h) { + h.done ? a(h.value) : i(h.value).then(s, l); + } + u((r = r.apply(e, [])).next()); + }); +} +class V { + constructor() { + this.mutex = Promise.resolve(); + } + lock() { + let t = () => { + }; + return this.mutex = this.mutex.then(() => new Promise(t)), new Promise((n) => { + t = n; + }); + } + dispatch(t) { + return we(this, void 0, void 0, function* () { + const n = yield this.lock(); + try { + return yield Promise.resolve(t()); + } finally { + n(); + } + }); + } +} +var xt; +function Ui() { + return typeof globalThis < "u" ? globalThis : typeof self < "u" ? self : typeof window < "u" ? window : global; +} +const Vt = Ui(), Dt = (xt = Vt.Buffer) !== null && xt !== void 0 ? xt : null, Gi = Vt.TextEncoder ? new Vt.TextEncoder() : null; +function mn(e, t) { + return (e & 15) + (e >> 6 | e >> 3 & 8) << 4 | (t & 15) + (t >> 6 | t >> 3 & 8); +} +function yn(e, t) { + const n = t.length >> 1; + for (let r = 0; r < n; r++) { + const i = r << 1; + e[r] = mn(t.charCodeAt(i), t.charCodeAt(i + 1)); + } +} +function Hi(e, t) { + if (e.length !== t.length * 2) + return !1; + for (let n = 0; n < t.length; n++) { + const r = n << 1; + if (t[n] !== mn(e.charCodeAt(r), e.charCodeAt(r + 1))) + return !1; + } + return !0; +} +const kr = 87, vr = 48; +function zt(e, t, n) { + let r = 0; + for (let i = 0; i < n; i++) { + let a = t[i] >>> 4; + e[r++] = a > 9 ? a + kr : a + vr, a = t[i] & 15, e[r++] = a > 9 ? a + kr : a + vr; + } + return String.fromCharCode.apply(null, e); +} +const ue = Dt !== null ? (e) => { + if (typeof e == "string") { + const t = Dt.from(e, "utf8"); + return new Uint8Array(t.buffer, t.byteOffset, t.length); + } + if (Dt.isBuffer(e)) + return new Uint8Array(e.buffer, e.byteOffset, e.length); + if (ArrayBuffer.isView(e)) + return new Uint8Array(e.buffer, e.byteOffset, e.byteLength); + throw new Error("Invalid data type!"); +} : (e) => { + if (typeof e == "string") + return Gi.encode(e); + if (ArrayBuffer.isView(e)) + return new Uint8Array(e.buffer, e.byteOffset, e.byteLength); + throw new Error("Invalid data type!"); +}, te = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", ze = new Uint8Array(256); +for (let e = 0; e < te.length; e++) + ze[te.charCodeAt(e)] = e; +function Br(e, t = !0) { + const n = e.length, r = n % 3, i = [], a = n - r; + for (let o = 0; o < a; o += 3) { + const s = (e[o] << 16 & 16711680) + (e[o + 1] << 8 & 65280) + (e[o + 2] & 255), l = te.charAt(s >> 18 & 63) + te.charAt(s >> 12 & 63) + te.charAt(s >> 6 & 63) + te.charAt(s & 63); + i.push(l); + } + if (r === 1) { + const o = e[n - 1], s = te.charAt(o >> 2), l = te.charAt(o << 4 & 63); + i.push(`${s}${l}`), t && i.push("=="); + } else if (r === 2) { + const o = (e[n - 2] << 8) + e[n - 1], s = te.charAt(o >> 10), l = te.charAt(o >> 4 & 63), u = te.charAt(o << 2 & 63); + i.push(`${s}${l}${u}`), t && i.push("="); + } + return i.join(""); +} +function Ni(e) { + let t = Math.floor(e.length * 0.75); + const n = e.length; + return e[n - 1] === "=" && (t -= 1, e[n - 2] === "=" && (t -= 1)), t; +} +function Ki(e) { + const t = Ni(e), n = e.length, r = new Uint8Array(t); + let i = 0; + for (let a = 0; a < n; a += 4) { + const o = ze[e.charCodeAt(a)], s = ze[e.charCodeAt(a + 1)], l = ze[e.charCodeAt(a + 2)], u = ze[e.charCodeAt(a + 3)]; + r[i] = o << 2 | s >> 4, i += 1, r[i] = (s & 15) << 4 | l >> 2, i += 1, r[i] = (l & 3) << 6 | u & 63, i += 1; + } + return r; +} +const $e = 16 * 1024, Ke = 4, Oi = new V(), St = /* @__PURE__ */ new Map(); +function bn(e, t) { + return we(this, void 0, void 0, function* () { + let n = null, r = null, i = !1; + if (typeof WebAssembly > "u") + throw new Error("WebAssembly is not supported in this environment!"); + const a = (C, D = 0) => { + r.set(C, D); + }, o = () => r, s = () => n.exports, l = (C) => { + n.exports.Hash_SetMemorySize(C); + const D = n.exports.Hash_GetBuffer(), G = n.exports.memory.buffer; + r = new Uint8Array(G, D, C); + }, u = () => new DataView(n.exports.memory.buffer).getUint32(n.exports.STATE_SIZE, !0), h = Oi.dispatch(() => we(this, void 0, void 0, function* () { + if (!St.has(e.name)) { + const D = Ki(e.data), G = WebAssembly.compile(D); + St.set(e.name, G); + } + const C = yield St.get(e.name); + n = yield WebAssembly.instantiate(C, { + // env: { + // emscripten_memcpy_big: (dest, src, num) => { + // const memoryBuffer = wasmInstance.exports.memory.buffer; + // const memView = new Uint8Array(memoryBuffer, 0); + // memView.set(memView.subarray(src, src + num), dest); + // }, + // print_memory: (offset, len) => { + // const memoryBuffer = wasmInstance.exports.memory.buffer; + // const memView = new Uint8Array(memoryBuffer, 0); + // console.log('print_int32', memView.subarray(offset, offset + len)); + // }, + // }, + }); + })), g = () => we(this, void 0, void 0, function* () { + n || (yield h); + const C = n.exports.Hash_GetBuffer(), D = n.exports.memory.buffer; + r = new Uint8Array(D, C, $e); + }), c = (C = null) => { + i = !0, n.exports.Hash_Init(C); + }, d = (C) => { + let D = 0; + for (; D < C.length; ) { + const G = C.subarray(D, D + $e); + D += G.length, r.set(G), n.exports.Hash_Update(G.length); + } + }, I = (C) => { + if (!i) + throw new Error("update() called before init()"); + const D = ue(C); + d(D); + }, m = new Uint8Array(t * 2), B = (C, D = null) => { + if (!i) + throw new Error("digest() called before init()"); + return i = !1, n.exports.Hash_Final(D), C === "binary" ? r.slice(0, t) : zt(m, r, t); + }, S = () => { + if (!i) + throw new Error("save() can only be called after init() and before digest()"); + const C = n.exports.Hash_GetState(), D = u(), G = n.exports.memory.buffer, v = new Uint8Array(G, C, D), P = new Uint8Array(Ke + D); + return yn(P, e.hash), P.set(v, Ke), P; + }, j = (C) => { + if (!(C instanceof Uint8Array)) + throw new Error("load() expects an Uint8Array generated by save()"); + const D = n.exports.Hash_GetState(), G = u(), v = Ke + G, P = n.exports.memory.buffer; + if (C.length !== v) + throw new Error(`Bad state length (expected ${v} bytes, got ${C.length})`); + if (!Hi(e.hash, C.subarray(0, Ke))) + throw new Error("This state was written by an incompatible hash implementation"); + const Z = C.subarray(Ke); + new Uint8Array(P, D, G).set(Z), i = !0; + }, b = (C) => typeof C == "string" ? C.length < $e / 4 : C.byteLength < $e; + let N = b; + switch (e.name) { + case "argon2": + case "scrypt": + N = () => !0; + break; + case "blake2b": + case "blake2s": + N = (C, D) => D <= 512 && b(C); + break; + case "blake3": + N = (C, D) => D === 0 && b(C); + break; + case "xxhash64": + // cannot simplify + case "xxhash3": + case "xxhash128": + case "crc64": + N = () => !1; + break; + } + const K = (C, D = null, G = null) => { + if (!N(C, D)) + return c(D), I(C), B("hex", G); + const v = ue(C); + return r.set(v), n.exports.Hash_Calculate(v.length, D, G), zt(m, r, t); + }; + return yield g(), { + getMemory: o, + writeMemory: a, + getExports: s, + setMemorySize: l, + init: c, + update: I, + digest: B, + save: S, + load: j, + calculate: K, + hashLength: t + }; + }); +} +new V(); +var Vi = "argon2", zi = "AGFzbQEAAAABKQVgAX8Bf2AAAX9gEH9/f39/f39/f39/f39/f38AYAR/f39/AGACf38AAwYFAAECAwQFBgEBAoCAAgYIAX8BQZCoBAsHQQQGbWVtb3J5AgASSGFzaF9TZXRNZW1vcnlTaXplAAAOSGFzaF9HZXRCdWZmZXIAAQ5IYXNoX0NhbGN1bGF0ZQAECvEyBVgBAn9BACEBAkAgAEEAKAKICCICRg0AAkAgACACayIAQRB2IABBgIB8cSAASWoiAEAAQX9HDQBB/wHADwtBACEBQQBBACkDiAggAEEQdK18NwOICAsgAcALcAECfwJAQQAoAoAIIgANAEEAPwBBEHQiADYCgAhBACgCiAgiAUGAgCBGDQACQEGAgCAgAWsiAEEQdiAAQYCAfHEgAElqIgBAAEF/Rw0AQQAPC0EAQQApA4gIIABBEHStfDcDiAhBACgCgAghAAsgAAvcDgECfiAAIAQpAwAiECAAKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAMIBAgDCkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgBCAQIAQpAwCFQiiJIhA3AwAgACAQIAApAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAwgECAMKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAEIBAgBCkDAIVCAYk3AwAgASAFKQMAIhAgASkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDSAQIA0pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAEgECABKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACANIBAgDSkDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAIgBikDACIQIAIpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIA4gECAOKQMAhUIgiSIQNwMAIAogECAKKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACACIBAgAikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDiAQIA4pAwCFQjCJIhA3AwAgCiAQIAopAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACADIAcpAwAiECADKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAPIBAgDykDAIVCIIkiEDcDACALIBAgCykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAyAQIAMpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA8gECAPKQMAhUIwiSIQNwMAIAsgECALKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgACAFKQMAIhAgACkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDyAQIA8pAwCFQiCJIhA3AwAgCiAQIAopAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAAgECAAKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAPIBAgDykDAIVCMIkiEDcDACAKIBAgCikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAEgBikDACIQIAEpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAwgECAMKQMAhUIgiSIQNwMAIAsgECALKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACABIBAgASkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDCAQIAwpAwCFQjCJIhA3AwAgCyAQIAspAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACACIAcpAwAiECACKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACANIBAgDSkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAiAQIAIpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA0gECANKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgAyAEKQMAIhAgAykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDiAQIA4pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAQgECAEKQMAhUIoiSIQNwMAIAMgECADKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAOIBAgDikDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBCAQIAQpAwCFQgGJNwMAC98aAQN/QQAhBEEAIAIpAwAgASkDAIU3A5AIQQAgAikDCCABKQMIhTcDmAhBACACKQMQIAEpAxCFNwOgCEEAIAIpAxggASkDGIU3A6gIQQAgAikDICABKQMghTcDsAhBACACKQMoIAEpAyiFNwO4CEEAIAIpAzAgASkDMIU3A8AIQQAgAikDOCABKQM4hTcDyAhBACACKQNAIAEpA0CFNwPQCEEAIAIpA0ggASkDSIU3A9gIQQAgAikDUCABKQNQhTcD4AhBACACKQNYIAEpA1iFNwPoCEEAIAIpA2AgASkDYIU3A/AIQQAgAikDaCABKQNohTcD+AhBACACKQNwIAEpA3CFNwOACUEAIAIpA3ggASkDeIU3A4gJQQAgAikDgAEgASkDgAGFNwOQCUEAIAIpA4gBIAEpA4gBhTcDmAlBACACKQOQASABKQOQAYU3A6AJQQAgAikDmAEgASkDmAGFNwOoCUEAIAIpA6ABIAEpA6ABhTcDsAlBACACKQOoASABKQOoAYU3A7gJQQAgAikDsAEgASkDsAGFNwPACUEAIAIpA7gBIAEpA7gBhTcDyAlBACACKQPAASABKQPAAYU3A9AJQQAgAikDyAEgASkDyAGFNwPYCUEAIAIpA9ABIAEpA9ABhTcD4AlBACACKQPYASABKQPYAYU3A+gJQQAgAikD4AEgASkD4AGFNwPwCUEAIAIpA+gBIAEpA+gBhTcD+AlBACACKQPwASABKQPwAYU3A4AKQQAgAikD+AEgASkD+AGFNwOICkEAIAIpA4ACIAEpA4AChTcDkApBACACKQOIAiABKQOIAoU3A5gKQQAgAikDkAIgASkDkAKFNwOgCkEAIAIpA5gCIAEpA5gChTcDqApBACACKQOgAiABKQOgAoU3A7AKQQAgAikDqAIgASkDqAKFNwO4CkEAIAIpA7ACIAEpA7AChTcDwApBACACKQO4AiABKQO4AoU3A8gKQQAgAikDwAIgASkDwAKFNwPQCkEAIAIpA8gCIAEpA8gChTcD2ApBACACKQPQAiABKQPQAoU3A+AKQQAgAikD2AIgASkD2AKFNwPoCkEAIAIpA+ACIAEpA+AChTcD8ApBACACKQPoAiABKQPoAoU3A/gKQQAgAikD8AIgASkD8AKFNwOAC0EAIAIpA/gCIAEpA/gChTcDiAtBACACKQOAAyABKQOAA4U3A5ALQQAgAikDiAMgASkDiAOFNwOYC0EAIAIpA5ADIAEpA5ADhTcDoAtBACACKQOYAyABKQOYA4U3A6gLQQAgAikDoAMgASkDoAOFNwOwC0EAIAIpA6gDIAEpA6gDhTcDuAtBACACKQOwAyABKQOwA4U3A8ALQQAgAikDuAMgASkDuAOFNwPIC0EAIAIpA8ADIAEpA8ADhTcD0AtBACACKQPIAyABKQPIA4U3A9gLQQAgAikD0AMgASkD0AOFNwPgC0EAIAIpA9gDIAEpA9gDhTcD6AtBACACKQPgAyABKQPgA4U3A/ALQQAgAikD6AMgASkD6AOFNwP4C0EAIAIpA/ADIAEpA/ADhTcDgAxBACACKQP4AyABKQP4A4U3A4gMQQAgAikDgAQgASkDgASFNwOQDEEAIAIpA4gEIAEpA4gEhTcDmAxBACACKQOQBCABKQOQBIU3A6AMQQAgAikDmAQgASkDmASFNwOoDEEAIAIpA6AEIAEpA6AEhTcDsAxBACACKQOoBCABKQOoBIU3A7gMQQAgAikDsAQgASkDsASFNwPADEEAIAIpA7gEIAEpA7gEhTcDyAxBACACKQPABCABKQPABIU3A9AMQQAgAikDyAQgASkDyASFNwPYDEEAIAIpA9AEIAEpA9AEhTcD4AxBACACKQPYBCABKQPYBIU3A+gMQQAgAikD4AQgASkD4ASFNwPwDEEAIAIpA+gEIAEpA+gEhTcD+AxBACACKQPwBCABKQPwBIU3A4ANQQAgAikD+AQgASkD+ASFNwOIDUEAIAIpA4AFIAEpA4AFhTcDkA1BACACKQOIBSABKQOIBYU3A5gNQQAgAikDkAUgASkDkAWFNwOgDUEAIAIpA5gFIAEpA5gFhTcDqA1BACACKQOgBSABKQOgBYU3A7ANQQAgAikDqAUgASkDqAWFNwO4DUEAIAIpA7AFIAEpA7AFhTcDwA1BACACKQO4BSABKQO4BYU3A8gNQQAgAikDwAUgASkDwAWFNwPQDUEAIAIpA8gFIAEpA8gFhTcD2A1BACACKQPQBSABKQPQBYU3A+ANQQAgAikD2AUgASkD2AWFNwPoDUEAIAIpA+AFIAEpA+AFhTcD8A1BACACKQPoBSABKQPoBYU3A/gNQQAgAikD8AUgASkD8AWFNwOADkEAIAIpA/gFIAEpA/gFhTcDiA5BACACKQOABiABKQOABoU3A5AOQQAgAikDiAYgASkDiAaFNwOYDkEAIAIpA5AGIAEpA5AGhTcDoA5BACACKQOYBiABKQOYBoU3A6gOQQAgAikDoAYgASkDoAaFNwOwDkEAIAIpA6gGIAEpA6gGhTcDuA5BACACKQOwBiABKQOwBoU3A8AOQQAgAikDuAYgASkDuAaFNwPIDkEAIAIpA8AGIAEpA8AGhTcD0A5BACACKQPIBiABKQPIBoU3A9gOQQAgAikD0AYgASkD0AaFNwPgDkEAIAIpA9gGIAEpA9gGhTcD6A5BACACKQPgBiABKQPgBoU3A/AOQQAgAikD6AYgASkD6AaFNwP4DkEAIAIpA/AGIAEpA/AGhTcDgA9BACACKQP4BiABKQP4BoU3A4gPQQAgAikDgAcgASkDgAeFNwOQD0EAIAIpA4gHIAEpA4gHhTcDmA9BACACKQOQByABKQOQB4U3A6APQQAgAikDmAcgASkDmAeFNwOoD0EAIAIpA6AHIAEpA6AHhTcDsA9BACACKQOoByABKQOoB4U3A7gPQQAgAikDsAcgASkDsAeFNwPAD0EAIAIpA7gHIAEpA7gHhTcDyA9BACACKQPAByABKQPAB4U3A9APQQAgAikDyAcgASkDyAeFNwPYD0EAIAIpA9AHIAEpA9AHhTcD4A9BACACKQPYByABKQPYB4U3A+gPQQAgAikD4AcgASkD4AeFNwPwD0EAIAIpA+gHIAEpA+gHhTcD+A9BACACKQPwByABKQPwB4U3A4AQQQAgAikD+AcgASkD+AeFNwOIEEGQCEGYCEGgCEGoCEGwCEG4CEHACEHICEHQCEHYCEHgCEHoCEHwCEH4CEGACUGICRACQZAJQZgJQaAJQagJQbAJQbgJQcAJQcgJQdAJQdgJQeAJQegJQfAJQfgJQYAKQYgKEAJBkApBmApBoApBqApBsApBuApBwApByApB0ApB2ApB4ApB6ApB8ApB+ApBgAtBiAsQAkGQC0GYC0GgC0GoC0GwC0G4C0HAC0HIC0HQC0HYC0HgC0HoC0HwC0H4C0GADEGIDBACQZAMQZgMQaAMQagMQbAMQbgMQcAMQcgMQdAMQdgMQeAMQegMQfAMQfgMQYANQYgNEAJBkA1BmA1BoA1BqA1BsA1BuA1BwA1ByA1B0A1B2A1B4A1B6A1B8A1B+A1BgA5BiA4QAkGQDkGYDkGgDkGoDkGwDkG4DkHADkHIDkHQDkHYDkHgDkHoDkHwDkH4DkGAD0GIDxACQZAPQZgPQaAPQagPQbAPQbgPQcAPQcgPQdAPQdgPQeAPQegPQfAPQfgPQYAQQYgQEAJBkAhBmAhBkAlBmAlBkApBmApBkAtBmAtBkAxBmAxBkA1BmA1BkA5BmA5BkA9BmA8QAkGgCEGoCEGgCUGoCUGgCkGoCkGgC0GoC0GgDEGoDEGgDUGoDUGgDkGoDkGgD0GoDxACQbAIQbgIQbAJQbgJQbAKQbgKQbALQbgLQbAMQbgMQbANQbgNQbAOQbgOQbAPQbgPEAJBwAhByAhBwAlByAlBwApByApBwAtByAtBwAxByAxBwA1ByA1BwA5ByA5BwA9ByA8QAkHQCEHYCEHQCUHYCUHQCkHYCkHQC0HYC0HQDEHYDEHQDUHYDUHQDkHYDkHQD0HYDxACQeAIQegIQeAJQegJQeAKQegKQeALQegLQeAMQegMQeANQegNQeAOQegOQeAPQegPEAJB8AhB+AhB8AlB+AlB8ApB+ApB8AtB+AtB8AxB+AxB8A1B+A1B8A5B+A5B8A9B+A8QAkGACUGICUGACkGICkGAC0GIC0GADEGIDEGADUGIDUGADkGIDkGAD0GID0GAEEGIEBACAkACQCADRQ0AA0AgACAEaiIDIAIgBGoiBSkDACABIARqIgYpAwCFIARBkAhqKQMAhSADKQMAhTcDACADQQhqIgMgBUEIaikDACAGQQhqKQMAhSAEQZgIaikDAIUgAykDAIU3AwAgBEEQaiIEQYAIRw0ADAILC0EAIQQDQCAAIARqIgMgAiAEaiIFKQMAIAEgBGoiBikDAIUgBEGQCGopAwCFNwMAIANBCGogBUEIaikDACAGQQhqKQMAhSAEQZgIaikDAIU3AwAgBEEQaiIEQYAIRw0ACwsL5QcMBX8BfgR/An4BfwF+AX8Bfgd/AX4DfwF+AkBBACgCgAgiAiABQQp0aiIDKAIIIAFHDQAgAygCDCEEIAMoAgAhBUEAIAMoAhQiBq03A7gQQQAgBK0iBzcDsBBBACAFIAEgBUECdG4iCGwiCUECdK03A6gQAkACQAJAAkAgBEUNAEF/IQogBUUNASAIQQNsIQsgCEECdCIErSEMIAWtIQ0gBkF/akECSSEOQgAhDwNAQQAgDzcDkBAgD6chEEIAIRFBACEBA0BBACARNwOgECAPIBGEUCIDIA5xIRIgBkEBRiAPUCITIAZBAkYgEUICVHFxciEUQX8gAUEBakEDcSAIbEF/aiATGyEVIAEgEHIhFiABIAhsIRcgA0EBdCEYQgAhGQNAQQBCADcDwBBBACAZNwOYECAYIQECQCASRQ0AQQBCATcDwBBBkBhBkBBBkCBBABADQZAYQZAYQZAgQQAQA0ECIQELAkAgASAITw0AIAQgGaciGmwgF2ogAWohAwNAIANBACAEIAEbQQAgEVAiGxtqQX9qIRwCQAJAIBQNAEEAKAKACCICIBxBCnQiHGohCgwBCwJAIAFB/wBxIgINAEEAQQApA8AQQgF8NwPAEEGQGEGQEEGQIEEAEANBkBhBkBhBkCBBABADCyAcQQp0IRwgAkEDdEGQGGohCkEAKAKACCECCyACIANBCnRqIAIgHGogAiAKKQMAIh1CIIinIAVwIBogFhsiHCAEbCABIAFBACAZIBytUSIcGyIKIBsbIBdqIAogC2ogExsgAUUgHHJrIhsgFWqtIB1C/////w+DIh0gHX5CIIggG61+QiCIfSAMgqdqQQp0akEBEAMgA0EBaiEDIAggAUEBaiIBRw0ACwsgGUIBfCIZIA1SDQALIBFCAXwiEachASARQgRSDQALIA9CAXwiDyAHUg0AC0EAKAKACCECCyAJQQx0QYB4aiEXIAVBf2oiCkUNAgwBC0EAQgM3A6AQQQAgBEF/aq03A5AQQYB4IRcLIAIgF2ohGyAIQQx0IQhBACEcA0AgCCAcQQFqIhxsQYB4aiEEQQAhAQNAIBsgAWoiAyADKQMAIAIgBCABamopAwCFNwMAIANBCGoiAyADKQMAIAIgBCABQQhyamopAwCFNwMAIAFBCGohAyABQRBqIQEgA0H4B0kNAAsgHCAKRw0ACwsgAiAXaiEbQXghAQNAIAIgAWoiA0EIaiAbIAFqIgRBCGopAwA3AwAgA0EQaiAEQRBqKQMANwMAIANBGGogBEEYaikDADcDACADQSBqIARBIGopAwA3AwAgAUEgaiIBQfgHSQ0ACwsL", Ji = "e4cdc523", Yi = { + name: Vi, + data: zi, + hash: Ji +}, Mi = "blake2b", qi = "AGFzbQEAAAABEQRgAAF/YAJ/fwBgAX8AYAAAAwoJAAECAwECAgABBQQBAQICBg4CfwFBsIsFC38AQYAICwdwCAZtZW1vcnkCAA5IYXNoX0dldEJ1ZmZlcgAACkhhc2hfRmluYWwAAwlIYXNoX0luaXQABQtIYXNoX1VwZGF0ZQAGDUhhc2hfR2V0U3RhdGUABw5IYXNoX0NhbGN1bGF0ZQAIClNUQVRFX1NJWkUDAQrTOAkFAEGACQvrAgIFfwF+AkAgAUEBSA0AAkACQAJAIAFBgAFBACgC4IoBIgJrIgNKDQAgASEEDAELQQBBADYC4IoBAkAgAkH/AEoNACACQeCJAWohBSAAIQRBACEGA0AgBSAELQAAOgAAIARBAWohBCAFQQFqIQUgAyAGQQFqIgZB/wFxSg0ACwtBAEEAKQPAiQEiB0KAAXw3A8CJAUEAQQApA8iJASAHQv9+Vq18NwPIiQFB4IkBEAIgACADaiEAAkAgASADayIEQYEBSA0AIAIgAWohBQNAQQBBACkDwIkBIgdCgAF8NwPAiQFBAEEAKQPIiQEgB0L/flatfDcDyIkBIAAQAiAAQYABaiEAIAVBgH9qIgVBgAJLDQALIAVBgH9qIQQMAQsgBEEATA0BC0EAIQUDQCAFQQAoAuCKAWpB4IkBaiAAIAVqLQAAOgAAIAQgBUEBaiIFQf8BcUoNAAsLQQBBACgC4IoBIARqNgLgigELC78uASR+QQBBACkD0IkBQQApA7CJASIBQQApA5CJAXwgACkDICICfCIDhULr+obav7X2wR+FQiCJIgRCq/DT9K/uvLc8fCIFIAGFQiiJIgYgA3wgACkDKCIBfCIHIASFQjCJIgggBXwiCSAGhUIBiSIKQQApA8iJAUEAKQOoiQEiBEEAKQOIiQF8IAApAxAiA3wiBYVCn9j52cKR2oKbf4VCIIkiC0K7zqqm2NDrs7t/fCIMIASFQiiJIg0gBXwgACkDGCIEfCIOfCAAKQNQIgV8Ig9BACkDwIkBQQApA6CJASIQQQApA4CJASIRfCAAKQMAIgZ8IhKFQtGFmu/6z5SH0QCFQiCJIhNCiJLznf/M+YTqAHwiFCAQhUIoiSIVIBJ8IAApAwgiEHwiFiAThUIwiSIXhUIgiSIYQQApA9iJAUEAKQO4iQEiE0EAKQOYiQF8IAApAzAiEnwiGYVC+cL4m5Gjs/DbAIVCIIkiGkLx7fT4paf9p6V/fCIbIBOFQiiJIhwgGXwgACkDOCITfCIZIBqFQjCJIhogG3wiG3wiHSAKhUIoiSIeIA98IAApA1giCnwiDyAYhUIwiSIYIB18Ih0gDiALhUIwiSIOIAx8Ih8gDYVCAYkiDCAWfCAAKQNAIgt8Ig0gGoVCIIkiFiAJfCIaIAyFQiiJIiAgDXwgACkDSCIJfCIhIBaFQjCJIhYgGyAchUIBiSIMIAd8IAApA2AiB3wiDSAOhUIgiSIOIBcgFHwiFHwiFyAMhUIoiSIbIA18IAApA2giDHwiHCAOhUIwiSIOIBd8IhcgG4VCAYkiGyAZIBQgFYVCAYkiFHwgACkDcCINfCIVIAiFQiCJIhkgH3wiHyAUhUIoiSIUIBV8IAApA3giCHwiFXwgDHwiIoVCIIkiI3wiJCAbhUIoiSIbICJ8IBJ8IiIgFyAYIBUgGYVCMIkiFSAffCIZIBSFQgGJIhQgIXwgDXwiH4VCIIkiGHwiFyAUhUIoiSIUIB98IAV8Ih8gGIVCMIkiGCAXfCIXIBSFQgGJIhR8IAF8IiEgFiAafCIWIBUgHSAehUIBiSIaIBx8IAl8IhyFQiCJIhV8Ih0gGoVCKIkiGiAcfCAIfCIcIBWFQjCJIhWFQiCJIh4gGSAOIBYgIIVCAYkiFiAPfCACfCIPhUIgiSIOfCIZIBaFQiiJIhYgD3wgC3wiDyAOhUIwiSIOIBl8Ihl8IiAgFIVCKIkiFCAhfCAEfCIhIB6FQjCJIh4gIHwiICAiICOFQjCJIiIgJHwiIyAbhUIBiSIbIBx8IAp8IhwgDoVCIIkiDiAXfCIXIBuFQiiJIhsgHHwgE3wiHCAOhUIwiSIOIBkgFoVCAYkiFiAffCAQfCIZICKFQiCJIh8gFSAdfCIVfCIdIBaFQiiJIhYgGXwgB3wiGSAfhUIwiSIfIB18Ih0gFoVCAYkiFiAVIBqFQgGJIhUgD3wgBnwiDyAYhUIgiSIYICN8IhogFYVCKIkiFSAPfCADfCIPfCAHfCIihUIgiSIjfCIkIBaFQiiJIhYgInwgBnwiIiAjhUIwiSIjICR8IiQgFoVCAYkiFiAOIBd8Ig4gDyAYhUIwiSIPICAgFIVCAYkiFCAZfCAKfCIXhUIgiSIYfCIZIBSFQiiJIhQgF3wgC3wiF3wgBXwiICAPIBp8Ig8gHyAOIBuFQgGJIg4gIXwgCHwiGoVCIIkiG3wiHyAOhUIoiSIOIBp8IAx8IhogG4VCMIkiG4VCIIkiISAdIB4gDyAVhUIBiSIPIBx8IAF8IhWFQiCJIhx8Ih0gD4VCKIkiDyAVfCADfCIVIByFQjCJIhwgHXwiHXwiHiAWhUIoiSIWICB8IA18IiAgIYVCMIkiISAefCIeIBogFyAYhUIwiSIXIBl8IhggFIVCAYkiFHwgCXwiGSAchUIgiSIaICR8IhwgFIVCKIkiFCAZfCACfCIZIBqFQjCJIhogHSAPhUIBiSIPICJ8IAR8Ih0gF4VCIIkiFyAbIB98Iht8Ih8gD4VCKIkiDyAdfCASfCIdIBeFQjCJIhcgH3wiHyAPhUIBiSIPIBsgDoVCAYkiDiAVfCATfCIVICOFQiCJIhsgGHwiGCAOhUIoiSIOIBV8IBB8IhV8IAx8IiKFQiCJIiN8IiQgD4VCKIkiDyAifCAHfCIiICOFQjCJIiMgJHwiJCAPhUIBiSIPIBogHHwiGiAVIBuFQjCJIhUgHiAWhUIBiSIWIB18IAR8IhuFQiCJIhx8Ih0gFoVCKIkiFiAbfCAQfCIbfCABfCIeIBUgGHwiFSAXIBogFIVCAYkiFCAgfCATfCIYhUIgiSIXfCIaIBSFQiiJIhQgGHwgCXwiGCAXhUIwiSIXhUIgiSIgIB8gISAVIA6FQgGJIg4gGXwgCnwiFYVCIIkiGXwiHyAOhUIoiSIOIBV8IA18IhUgGYVCMIkiGSAffCIffCIhIA+FQiiJIg8gHnwgBXwiHiAghUIwiSIgICF8IiEgGyAchUIwiSIbIB18IhwgFoVCAYkiFiAYfCADfCIYIBmFQiCJIhkgJHwiHSAWhUIoiSIWIBh8IBJ8IhggGYVCMIkiGSAfIA6FQgGJIg4gInwgAnwiHyAbhUIgiSIbIBcgGnwiF3wiGiAOhUIoiSIOIB98IAZ8Ih8gG4VCMIkiGyAafCIaIA6FQgGJIg4gFSAXIBSFQgGJIhR8IAh8IhUgI4VCIIkiFyAcfCIcIBSFQiiJIhQgFXwgC3wiFXwgBXwiIoVCIIkiI3wiJCAOhUIoiSIOICJ8IAh8IiIgGiAgIBUgF4VCMIkiFSAcfCIXIBSFQgGJIhQgGHwgCXwiGIVCIIkiHHwiGiAUhUIoiSIUIBh8IAZ8IhggHIVCMIkiHCAafCIaIBSFQgGJIhR8IAR8IiAgGSAdfCIZIBUgISAPhUIBiSIPIB98IAN8Ih2FQiCJIhV8Ih8gD4VCKIkiDyAdfCACfCIdIBWFQjCJIhWFQiCJIiEgFyAbIBkgFoVCAYkiFiAefCABfCIZhUIgiSIbfCIXIBaFQiiJIhYgGXwgE3wiGSAbhUIwiSIbIBd8Ihd8Ih4gFIVCKIkiFCAgfCAMfCIgICGFQjCJIiEgHnwiHiAiICOFQjCJIiIgJHwiIyAOhUIBiSIOIB18IBJ8Ih0gG4VCIIkiGyAafCIaIA6FQiiJIg4gHXwgC3wiHSAbhUIwiSIbIBcgFoVCAYkiFiAYfCANfCIXICKFQiCJIhggFSAffCIVfCIfIBaFQiiJIhYgF3wgEHwiFyAYhUIwiSIYIB98Ih8gFoVCAYkiFiAVIA+FQgGJIg8gGXwgCnwiFSAchUIgiSIZICN8IhwgD4VCKIkiDyAVfCAHfCIVfCASfCIihUIgiSIjfCIkIBaFQiiJIhYgInwgBXwiIiAjhUIwiSIjICR8IiQgFoVCAYkiFiAbIBp8IhogFSAZhUIwiSIVIB4gFIVCAYkiFCAXfCADfCIXhUIgiSIZfCIbIBSFQiiJIhQgF3wgB3wiF3wgAnwiHiAVIBx8IhUgGCAaIA6FQgGJIg4gIHwgC3wiGoVCIIkiGHwiHCAOhUIoiSIOIBp8IAR8IhogGIVCMIkiGIVCIIkiICAfICEgFSAPhUIBiSIPIB18IAZ8IhWFQiCJIh18Ih8gD4VCKIkiDyAVfCAKfCIVIB2FQjCJIh0gH3wiH3wiISAWhUIoiSIWIB58IAx8Ih4gIIVCMIkiICAhfCIhIBogFyAZhUIwiSIXIBt8IhkgFIVCAYkiFHwgEHwiGiAdhUIgiSIbICR8Ih0gFIVCKIkiFCAafCAJfCIaIBuFQjCJIhsgHyAPhUIBiSIPICJ8IBN8Ih8gF4VCIIkiFyAYIBx8Ihh8IhwgD4VCKIkiDyAffCABfCIfIBeFQjCJIhcgHHwiHCAPhUIBiSIPIBggDoVCAYkiDiAVfCAIfCIVICOFQiCJIhggGXwiGSAOhUIoiSIOIBV8IA18IhV8IA18IiKFQiCJIiN8IiQgD4VCKIkiDyAifCAMfCIiICOFQjCJIiMgJHwiJCAPhUIBiSIPIBsgHXwiGyAVIBiFQjCJIhUgISAWhUIBiSIWIB98IBB8IhiFQiCJIh18Ih8gFoVCKIkiFiAYfCAIfCIYfCASfCIhIBUgGXwiFSAXIBsgFIVCAYkiFCAefCAHfCIZhUIgiSIXfCIbIBSFQiiJIhQgGXwgAXwiGSAXhUIwiSIXhUIgiSIeIBwgICAVIA6FQgGJIg4gGnwgAnwiFYVCIIkiGnwiHCAOhUIoiSIOIBV8IAV8IhUgGoVCMIkiGiAcfCIcfCIgIA+FQiiJIg8gIXwgBHwiISAehUIwiSIeICB8IiAgGCAdhUIwiSIYIB98Ih0gFoVCAYkiFiAZfCAGfCIZIBqFQiCJIhogJHwiHyAWhUIoiSIWIBl8IBN8IhkgGoVCMIkiGiAcIA6FQgGJIg4gInwgCXwiHCAYhUIgiSIYIBcgG3wiF3wiGyAOhUIoiSIOIBx8IAN8IhwgGIVCMIkiGCAbfCIbIA6FQgGJIg4gFSAXIBSFQgGJIhR8IAt8IhUgI4VCIIkiFyAdfCIdIBSFQiiJIhQgFXwgCnwiFXwgBHwiIoVCIIkiI3wiJCAOhUIoiSIOICJ8IAl8IiIgGyAeIBUgF4VCMIkiFSAdfCIXIBSFQgGJIhQgGXwgDHwiGYVCIIkiHXwiGyAUhUIoiSIUIBl8IAp8IhkgHYVCMIkiHSAbfCIbIBSFQgGJIhR8IAN8Ih4gGiAffCIaIBUgICAPhUIBiSIPIBx8IAd8IhyFQiCJIhV8Ih8gD4VCKIkiDyAcfCAQfCIcIBWFQjCJIhWFQiCJIiAgFyAYIBogFoVCAYkiFiAhfCATfCIahUIgiSIYfCIXIBaFQiiJIhYgGnwgDXwiGiAYhUIwiSIYIBd8Ihd8IiEgFIVCKIkiFCAefCAFfCIeICCFQjCJIiAgIXwiISAiICOFQjCJIiIgJHwiIyAOhUIBiSIOIBx8IAt8IhwgGIVCIIkiGCAbfCIbIA6FQiiJIg4gHHwgEnwiHCAYhUIwiSIYIBcgFoVCAYkiFiAZfCABfCIXICKFQiCJIhkgFSAffCIVfCIfIBaFQiiJIhYgF3wgBnwiFyAZhUIwiSIZIB98Ih8gFoVCAYkiFiAVIA+FQgGJIg8gGnwgCHwiFSAdhUIgiSIaICN8Ih0gD4VCKIkiDyAVfCACfCIVfCANfCIihUIgiSIjfCIkIBaFQiiJIhYgInwgCXwiIiAjhUIwiSIjICR8IiQgFoVCAYkiFiAYIBt8IhggFSAahUIwiSIVICEgFIVCAYkiFCAXfCASfCIXhUIgiSIafCIbIBSFQiiJIhQgF3wgCHwiF3wgB3wiISAVIB18IhUgGSAYIA6FQgGJIg4gHnwgBnwiGIVCIIkiGXwiHSAOhUIoiSIOIBh8IAt8IhggGYVCMIkiGYVCIIkiHiAfICAgFSAPhUIBiSIPIBx8IAp8IhWFQiCJIhx8Ih8gD4VCKIkiDyAVfCAEfCIVIByFQjCJIhwgH3wiH3wiICAWhUIoiSIWICF8IAN8IiEgHoVCMIkiHiAgfCIgIBggFyAahUIwiSIXIBt8IhogFIVCAYkiFHwgBXwiGCAchUIgiSIbICR8IhwgFIVCKIkiFCAYfCABfCIYIBuFQjCJIhsgHyAPhUIBiSIPICJ8IAx8Ih8gF4VCIIkiFyAZIB18Ihl8Ih0gD4VCKIkiDyAffCATfCIfIBeFQjCJIhcgHXwiHSAPhUIBiSIPIBkgDoVCAYkiDiAVfCAQfCIVICOFQiCJIhkgGnwiGiAOhUIoiSIOIBV8IAJ8IhV8IBN8IiKFQiCJIiN8IiQgD4VCKIkiDyAifCASfCIiICOFQjCJIiMgJHwiJCAPhUIBiSIPIBsgHHwiGyAVIBmFQjCJIhUgICAWhUIBiSIWIB98IAt8IhmFQiCJIhx8Ih8gFoVCKIkiFiAZfCACfCIZfCAJfCIgIBUgGnwiFSAXIBsgFIVCAYkiFCAhfCAFfCIahUIgiSIXfCIbIBSFQiiJIhQgGnwgA3wiGiAXhUIwiSIXhUIgiSIhIB0gHiAVIA6FQgGJIg4gGHwgEHwiFYVCIIkiGHwiHSAOhUIoiSIOIBV8IAF8IhUgGIVCMIkiGCAdfCIdfCIeIA+FQiiJIg8gIHwgDXwiICAhhUIwiSIhIB58Ih4gGSAchUIwiSIZIB98IhwgFoVCAYkiFiAafCAIfCIaIBiFQiCJIhggJHwiHyAWhUIoiSIWIBp8IAp8IhogGIVCMIkiGCAdIA6FQgGJIg4gInwgBHwiHSAZhUIgiSIZIBcgG3wiF3wiGyAOhUIoiSIOIB18IAd8Ih0gGYVCMIkiGSAbfCIbIA6FQgGJIg4gFSAXIBSFQgGJIhR8IAx8IhUgI4VCIIkiFyAcfCIcIBSFQiiJIhQgFXwgBnwiFXwgEnwiIoVCIIkiI3wiJCAOhUIoiSIOICJ8IBN8IiIgGyAhIBUgF4VCMIkiFSAcfCIXIBSFQgGJIhQgGnwgBnwiGoVCIIkiHHwiGyAUhUIoiSIUIBp8IBB8IhogHIVCMIkiHCAbfCIbIBSFQgGJIhR8IA18IiEgGCAffCIYIBUgHiAPhUIBiSIPIB18IAJ8Ih2FQiCJIhV8Ih4gD4VCKIkiDyAdfCABfCIdIBWFQjCJIhWFQiCJIh8gFyAZIBggFoVCAYkiFiAgfCADfCIYhUIgiSIZfCIXIBaFQiiJIhYgGHwgBHwiGCAZhUIwiSIZIBd8Ihd8IiAgFIVCKIkiFCAhfCAIfCIhIB+FQjCJIh8gIHwiICAiICOFQjCJIiIgJHwiIyAOhUIBiSIOIB18IAd8Ih0gGYVCIIkiGSAbfCIbIA6FQiiJIg4gHXwgDHwiHSAZhUIwiSIZIBcgFoVCAYkiFiAafCALfCIXICKFQiCJIhogFSAefCIVfCIeIBaFQiiJIhYgF3wgCXwiFyAahUIwiSIaIB58Ih4gFoVCAYkiFiAVIA+FQgGJIg8gGHwgBXwiFSAchUIgiSIYICN8IhwgD4VCKIkiDyAVfCAKfCIVfCACfCIChUIgiSIifCIjIBaFQiiJIhYgAnwgC3wiAiAihUIwiSILICN8IiIgFoVCAYkiFiAZIBt8IhkgFSAYhUIwiSIVICAgFIVCAYkiFCAXfCANfCINhUIgiSIXfCIYIBSFQiiJIhQgDXwgBXwiBXwgEHwiECAVIBx8Ig0gGiAZIA6FQgGJIg4gIXwgDHwiDIVCIIkiFXwiGSAOhUIoiSIOIAx8IBJ8IhIgFYVCMIkiDIVCIIkiFSAeIB8gDSAPhUIBiSINIB18IAl8IgmFQiCJIg98IhogDYVCKIkiDSAJfCAIfCIJIA+FQjCJIgggGnwiD3wiGiAWhUIoiSIWIBB8IAd8IhAgEYUgDCAZfCIHIA6FQgGJIgwgCXwgCnwiCiALhUIgiSILIAUgF4VCMIkiBSAYfCIJfCIOIAyFQiiJIgwgCnwgE3wiEyALhUIwiSIKIA58IguFNwOAiQFBACADIAYgDyANhUIBiSINIAJ8fCICIAWFQiCJIgUgB3wiBiANhUIoiSIHIAJ8fCICQQApA4iJAYUgBCABIBIgCSAUhUIBiSIDfHwiASAIhUIgiSISICJ8IgkgA4VCKIkiAyABfHwiASAShUIwiSIEIAl8IhKFNwOIiQFBACATQQApA5CJAYUgECAVhUIwiSIQIBp8IhOFNwOQiQFBACABQQApA5iJAYUgAiAFhUIwiSICIAZ8IgGFNwOYiQFBACASIAOFQgGJQQApA6CJAYUgAoU3A6CJAUEAIBMgFoVCAYlBACkDqIkBhSAKhTcDqIkBQQAgASAHhUIBiUEAKQOwiQGFIASFNwOwiQFBACALIAyFQgGJQQApA7iJAYUgEIU3A7iJAQvdAgUBfwF+AX8BfgJ/IwBBwABrIgAkAAJAQQApA9CJAUIAUg0AQQBBACkDwIkBIgFBACgC4IoBIgKsfCIDNwPAiQFBAEEAKQPIiQEgAyABVK18NwPIiQECQEEALQDoigFFDQBBAEJ/NwPYiQELQQBCfzcD0IkBAkAgAkH/AEoNAEEAIQQDQCACIARqQeCJAWpBADoAACAEQQFqIgRBgAFBACgC4IoBIgJrSA0ACwtB4IkBEAIgAEEAKQOAiQE3AwAgAEEAKQOIiQE3AwggAEEAKQOQiQE3AxAgAEEAKQOYiQE3AxggAEEAKQOgiQE3AyAgAEEAKQOoiQE3AyggAEEAKQOwiQE3AzAgAEEAKQO4iQE3AzhBACgC5IoBIgVBAUgNAEEAIQRBACECA0AgBEGACWogACAEai0AADoAACAEQQFqIQQgBSACQQFqIgJB/wFxSg0ACwsgAEHAAGokAAv9AwMBfwF+AX8jAEGAAWsiAiQAQQBBgQI7AfKKAUEAIAE6APGKAUEAIAA6APCKAUGQfiEAA0AgAEGAiwFqQgA3AAAgAEH4igFqQgA3AAAgAEHwigFqQgA3AAAgAEEYaiIADQALQQAhAEEAQQApA/CKASIDQoiS853/zPmE6gCFNwOAiQFBAEEAKQP4igFCu86qptjQ67O7f4U3A4iJAUEAQQApA4CLAUKr8NP0r+68tzyFNwOQiQFBAEEAKQOIiwFC8e30+KWn/aelf4U3A5iJAUEAQQApA5CLAULRhZrv+s+Uh9EAhTcDoIkBQQBBACkDmIsBQp/Y+dnCkdqCm3+FNwOoiQFBAEEAKQOgiwFC6/qG2r+19sEfhTcDsIkBQQBBACkDqIsBQvnC+JuRo7Pw2wCFNwO4iQFBACADp0H/AXE2AuSKAQJAIAFBAUgNACACQgA3A3ggAkIANwNwIAJCADcDaCACQgA3A2AgAkIANwNYIAJCADcDUCACQgA3A0ggAkIANwNAIAJCADcDOCACQgA3AzAgAkIANwMoIAJCADcDICACQgA3AxggAkIANwMQIAJCADcDCCACQgA3AwBBACEEA0AgAiAAaiAAQYAJai0AADoAACAAQQFqIQAgBEEBaiIEQf8BcSABSA0ACyACQYABEAELIAJBgAFqJAALEgAgAEEDdkH/P3EgAEEQdhAECwkAQYAJIAAQAQsGAEGAiQELGwAgAUEDdkH/P3EgAUEQdhAEQYAJIAAQARADCwsLAQBBgAgLBPAAAAA=", ji = "c6f286e6", Ri = { + name: Mi, + data: qi, + hash: ji +}; +new V(); +function Qr(e) { + return !Number.isInteger(e) || e < 8 || e > 512 || e % 8 !== 0 ? new Error("Invalid variant! Valid values: 8, 16, ..., 512") : null; +} +function _i(e, t) { + return e | t << 16; +} +function Jt(e = 512, t = null) { + if (Qr(e)) + return Promise.reject(Qr(e)); + let n = null, r = e; + if (t !== null) { + if (n = ue(t), n.length > 64) + return Promise.reject(new Error("Max key length is 64 bytes")); + r = _i(e, n.length); + } + const i = e / 8; + return bn(Ri, i).then((a) => { + r > 512 && a.writeMemory(n), a.init(r); + const o = { + init: r > 512 ? () => (a.writeMemory(n), a.init(r), o) : () => (a.init(r), o), + update: (s) => (a.update(s), o), + // biome-ignore lint/suspicious/noExplicitAny: Conflict with IHasher type + digest: (s) => a.digest(s), + save: () => a.save(), + load: (s) => (a.load(s), o), + blockSize: 128, + digestSize: i + }; + return o; + }); +} +function Pi(e, t, n) { + const r = [ + `m=${t.memorySize}`, + `t=${t.iterations}`, + `p=${t.parallelism}` + ].join(","); + return `$argon2${t.hashType}$v=19$${r}$${Br(e, !1)}$${Br(n, !1)}`; +} +const Er = new DataView(new ArrayBuffer(4)); +function se(e) { + return Er.setInt32(0, e, !0), new Uint8Array(Er.buffer); +} +function Ft(e, t, n) { + return we(this, void 0, void 0, function* () { + if (n <= 64) { + const l = yield Jt(n * 8); + return l.update(se(n)), l.update(t), l.digest("binary"); + } + const r = Math.ceil(n / 32) - 2, i = new Uint8Array(n); + e.init(), e.update(se(n)), e.update(t); + let a = e.digest("binary"); + i.set(a.subarray(0, 32), 0); + for (let l = 1; l < r; l++) + e.init(), e.update(a), a = e.digest("binary"), i.set(a.subarray(0, 32), l * 32); + const o = n - 32 * r; + let s; + return o === 64 ? (s = e, s.init()) : s = yield Jt(o * 8), s.update(a), a = s.digest("binary"), i.set(a.subarray(0, o), r * 32), i; + }); +} +function Li(e) { + switch (e) { + case "d": + return 0; + case "i": + return 1; + default: + return 2; + } +} +function Ti(e) { + return we(this, void 0, void 0, function* () { + var t; + const { parallelism: n, iterations: r, hashLength: i } = e, a = ue(e.password), o = ue(e.salt), s = 19, l = Li(e.hashType), { memorySize: u } = e, h = ue((t = e.secret) !== null && t !== void 0 ? t : ""), [g, c] = yield Promise.all([ + bn(Yi, 1024), + Jt(512) + ]); + g.setMemorySize(u * 1024 + 1024); + const d = new Uint8Array(24), I = new DataView(d.buffer); + I.setInt32(0, n, !0), I.setInt32(4, i, !0), I.setInt32(8, u, !0), I.setInt32(12, r, !0), I.setInt32(16, s, !0), I.setInt32(20, l, !0), g.writeMemory(d, u * 1024), c.init(), c.update(d), c.update(se(a.length)), c.update(a), c.update(se(o.length)), c.update(o), c.update(se(h.length)), c.update(h), c.update(se(0)); + const B = Math.floor(u / (n * 4)) * 4, S = new Uint8Array(72), j = c.digest("binary"); + S.set(j); + for (let K = 0; K < n; K++) { + S.set(se(0), 64), S.set(se(K), 68); + let C = K * B, D = yield Ft(c, S, 1024); + g.writeMemory(D, C * 1024), C += 1, S.set(se(1), 64), D = yield Ft(c, S, 1024), g.writeMemory(D, C * 1024); + } + const b = new Uint8Array(1024); + yn(b, g.calculate(new Uint8Array([]), u)); + const N = yield Ft(c, b, i); + if (e.outputType === "hex") { + const K = new Uint8Array(i * 2); + return zt(K, N, i); + } + return e.outputType === "encoded" ? Pi(o, e, N) : N; + }); +} +const Xi = (e) => { + var t; + if (!e || typeof e != "object") + throw new Error("Invalid options parameter. It requires an object."); + if (!e.password) + throw new Error("Password must be specified"); + if (e.password = ue(e.password), e.password.length < 1) + throw new Error("Password must be specified"); + if (!e.salt) + throw new Error("Salt must be specified"); + if (e.salt = ue(e.salt), e.salt.length < 8) + throw new Error("Salt should be at least 8 bytes long"); + if (e.secret = ue((t = e.secret) !== null && t !== void 0 ? t : ""), !Number.isInteger(e.iterations) || e.iterations < 1) + throw new Error("Iterations should be a positive number"); + if (!Number.isInteger(e.parallelism) || e.parallelism < 1) + throw new Error("Parallelism should be a positive number"); + if (!Number.isInteger(e.hashLength) || e.hashLength < 4) + throw new Error("Hash length should be at least 4 bytes."); + if (!Number.isInteger(e.memorySize)) + throw new Error("Memory size should be specified."); + if (e.memorySize < 8 * e.parallelism) + throw new Error("Memory size should be at least 8 * parallelism."); + if (e.outputType === void 0 && (e.outputType = "hex"), !["hex", "binary", "encoded"].includes(e.outputType)) + throw new Error(`Insupported output type ${e.outputType}. Valid values: ['hex', 'binary', 'encoded']`); +}; +function Zi(e) { + return we(this, void 0, void 0, function* () { + return Xi(e), Ti(Object.assign(Object.assign({}, e), { hashType: "id" })); + }); +} +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +new V(); +const We = { + id: "bitlogin-argon2id-v1", + memoryKiB: 64 * 1024, + iterations: 3, + parallelism: 1, + hashLength: 32 +}; +async function $i(e, t) { + if (t.length < 8) + throw new Error("Argon2id salt must be at least 8 bytes."); + const n = await Zi({ + password: e, + salt: t, + parallelism: We.parallelism, + iterations: We.iterations, + memorySize: We.memoryKiB, + hashLength: We.hashLength, + outputType: "binary" + }); + return n instanceof Uint8Array ? n : new Uint8Array(n); +} +function Wi(e) { + return new TextEncoder().encode(e.normalize("NFKC")); +} +class Oe extends Error { + constructor(t) { + super(t), this.name = "LoginNameError"; + } +} +const xr = 3, Dr = 32, e1 = /^[\x00-\x7F]*$/u, t1 = /^[a-z0-9._-]+$/u, r1 = /[._-]{2,}/u, Sr = /[a-z0-9]/u; +function n1(e) { + const t = e.trim().toLowerCase(); + if (!e1.test(t)) + throw new Oe("Login name must contain ASCII characters only."); + if (t.length < xr || t.length > Dr) + throw new Oe(`Login name must be between ${xr} and ${Dr} characters.`); + if (!t1.test(t)) + throw new Oe("Login name may only contain a-z, 0-9, '.', '_', and '-'."); + const n = t[0], r = t[t.length - 1]; + if (!Sr.test(n) || !Sr.test(r)) + throw new Oe("Login name must not begin or end with punctuation."); + if (r1.test(t)) + throw new Oe("Login name must not contain consecutive punctuation."); + return t; +} +function G1(e) { + try { + return n1(e), !0; + } catch { + return !1; + } +} +function i1(e) { + return fe(qr(De("bitlogin/password-salt/v1"), new Uint8Array([0]), De(e))).slice(0, 16); +} +async function H1(e, t) { + const n = i1(t), r = Wi(e), i = await $i(r, n), a = jr(Rr("bitlogin/password-root/v1"), i), o = In(a, "bitlogin/password-locator-signing/v1"), s = Rt(a, "bitlogin/password-capsule-encryption/v1", 32); + return { locatorPrivateKey: o.scalar, capsuleKey: s }; +} +function N1(e) { + const t = jr(Rr("bitlogin/recovery-root/v1"), e), n = In(t, "bitlogin/recovery-signing/v1"), r = Rt(t, "bitlogin/recovery-capsule-encryption/v1", 32); + return { recoveryPrivateKey: n.scalar, capsuleKey: r }; +} +const a1 = mt.CURVE.n; +function o1(e) { + if (e.length !== 32) + return !1; + let t = 0n; + for (const n of e) + t = t << 8n | BigInt(n); + return t >= 1n && t < a1; +} +function K1() { + for (; ; ) { + const e = qe(32); + if (o1(e)) + return e; + } +} +function s1(e) { + return Zt.getPublicKey(e); +} +function O1(e) { + return jt(s1(e)); +} +function l1(e, t) { + return Zt.sign(e, t); +} +function c1(e, t, n) { + try { + return Zt.verify(e, t, n); + } catch { + return !1; + } +} +function u1(e) { + return JSON.stringify([0, e.pubkey, e.created_at, e.kind, e.tags, e.content]); +} +function wn(e) { + return jt(fe(De(u1(e)))); +} +function V1(e, t) { + const n = wn(e), r = jt(l1(Je(n), t)); + return { ...e, id: n, sig: r }; +} +function Fr(e) { + if (!/^[0-9a-f]{64}$/u.test(e.id) || !/^[0-9a-f]{64}$/u.test(e.pubkey) || !/^[0-9a-f]{128}$/u.test(e.sig) || wn(e) !== e.id) + return !1; + try { + return c1(Je(e.sig), Je(e.id), Je(e.pubkey)); + } catch { + return !1; + } +} +const z1 = 0, J1 = 5, Y1 = 10002, M1 = 10050, q1 = 22242, j1 = 30078, R1 = "bitlogin:password:v1", _1 = "bitlogin:recovery:v1", P1 = "bitlogin.credential.v1", L1 = "bitlogin.recovery.v1", Cn = "bitlogin.recovery-export.v3"; +var Ut, Ur; +function d1() { + return Ur || (Ur = 1, Ut = function e(t) { + if (typeof t == "number" && isNaN(t)) + throw new Error("NaN is not allowed"); + if (typeof t == "number" && !isFinite(t)) + throw new Error("Infinity is not allowed"); + return t === null || typeof t != "object" ? JSON.stringify(t) : t.toJSON instanceof Function ? e(t.toJSON()) : Array.isArray(t) ? `[${t.reduce((i, a, o) => `${i}${o === 0 ? "" : ","}${e(a === void 0 || typeof a == "symbol" ? null : a)}`, "")}]` : `{${Object.keys(t).sort().reduce((r, i) => { + if (t[i] === void 0 || typeof t[i] == "symbol") + return r; + const a = r.length === 0 ? "" : ","; + return `${r}${a}${e(i)}:${e(t[i])}`; + }, "")}}`; + }), Ut; +} +var g1 = d1(); +const T1 = /* @__PURE__ */ Kr(g1); +/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +function Ue(e) { + return e instanceof Uint8Array || ArrayBuffer.isView(e) && e.constructor.name === "Uint8Array"; +} +function A1(e, ...t) { + if (!Ue(e)) + throw new Error("Uint8Array expected"); + if (t.length > 0 && !t.includes(e.length)) + throw new Error("Uint8Array expected of length " + t + ", got length=" + e.length); +} +function kn(e, t) { + return Array.isArray(t) ? t.length === 0 ? !0 : e ? t.every((n) => typeof n == "string") : t.every((n) => Number.isSafeInteger(n)) : !1; +} +function vn(e) { + if (typeof e != "function") + throw new Error("function expected"); + return !0; +} +function ke(e, t) { + if (typeof t != "string") + throw new Error(`${e}: string expected`); + return !0; +} +function Ne(e) { + if (!Number.isSafeInteger(e)) + throw new Error(`invalid integer: ${e}`); +} +function ct(e) { + if (!Array.isArray(e)) + throw new Error("array expected"); +} +function ut(e, t) { + if (!kn(!0, t)) + throw new Error(`${e}: array of strings expected`); +} +function $t(e, t) { + if (!kn(!1, t)) + throw new Error(`${e}: array of numbers expected`); +} +// @__NO_SIDE_EFFECTS__ +function Wt(...e) { + const t = (a) => a, n = (a, o) => (s) => a(o(s)), r = e.map((a) => a.encode).reduceRight(n, t), i = e.map((a) => a.decode).reduce(n, t); + return { encode: r, decode: i }; +} +// @__NO_SIDE_EFFECTS__ +function er(e) { + const t = typeof e == "string" ? e.split("") : e, n = t.length; + ut("alphabet", t); + const r = new Map(t.map((i, a) => [i, a])); + return { + encode: (i) => (ct(i), i.map((a) => { + if (!Number.isSafeInteger(a) || a < 0 || a >= n) + throw new Error(`alphabet.encode: digit index outside alphabet "${a}". Allowed: ${e}`); + return t[a]; + })), + decode: (i) => (ct(i), i.map((a) => { + ke("alphabet.decode", a); + const o = r.get(a); + if (o === void 0) + throw new Error(`Unknown letter: "${a}". Allowed: ${e}`); + return o; + })) + }; +} +// @__NO_SIDE_EFFECTS__ +function tr(e = "") { + return ke("join", e), { + encode: (t) => (ut("join.decode", t), t.join(e)), + decode: (t) => (ke("join.decode", t), t.split(e)) + }; +} +// @__NO_SIDE_EFFECTS__ +function Bn(e, t = "=") { + return Ne(e), ke("padding", t), { + encode(n) { + for (ut("padding.encode", n); n.length * e % 8; ) + n.push(t); + return n; + }, + decode(n) { + ut("padding.decode", n); + let r = n.length; + if (r * e % 8) + throw new Error("padding: invalid, string should have whole number of bytes"); + for (; r > 0 && n[r - 1] === t; r--) + if ((r - 1) * e % 8 === 0) + throw new Error("padding: invalid, string has too much padding"); + return n.slice(0, r); + } + }; +} +function Yt(e, t, n) { + if (t < 2) + throw new Error(`convertRadix: invalid from=${t}, base cannot be less than 2`); + if (n < 2) + throw new Error(`convertRadix: invalid to=${n}, base cannot be less than 2`); + if (ct(e), !e.length) + return []; + let r = 0; + const i = [], a = Array.from(e, (s) => { + if (Ne(s), s < 0 || s >= t) + throw new Error(`invalid integer: ${s}`); + return s; + }), o = a.length; + for (; ; ) { + let s = 0, l = !0; + for (let u = r; u < o; u++) { + const h = a[u], g = t * s, c = g + h; + if (!Number.isSafeInteger(c) || g / t !== s || c - h !== g) + throw new Error("convertRadix: carry overflow"); + const d = c / n; + s = c % n; + const I = Math.floor(d); + if (a[u] = I, !Number.isSafeInteger(I) || I * n + s !== c) + throw new Error("convertRadix: carry overflow"); + if (l) + I ? l = !1 : r = u; + else continue; + } + if (i.push(s), l) + break; + } + for (let s = 0; s < e.length - 1 && e[s] === 0; s++) + i.push(0); + return i.reverse(); +} +const Qn = (e, t) => t === 0 ? e : Qn(t, e % t), dt = /* @__NO_SIDE_EFFECTS__ */ (e, t) => e + (t - Qn(e, t)), et = /* @__PURE__ */ (() => { + let e = []; + for (let t = 0; t < 40; t++) + e.push(2 ** t); + return e; +})(); +function gt(e, t, n, r) { + if (ct(e), t <= 0 || t > 32) + throw new Error(`convertRadix2: wrong from=${t}`); + if (n <= 0 || n > 32) + throw new Error(`convertRadix2: wrong to=${n}`); + if (/* @__PURE__ */ dt(t, n) > 32) + throw new Error(`convertRadix2: carry overflow from=${t} to=${n} carryBits=${/* @__PURE__ */ dt(t, n)}`); + let i = 0, a = 0; + const o = et[t], s = et[n] - 1, l = []; + for (const u of e) { + if (Ne(u), u >= o) + throw new Error(`convertRadix2: invalid data word=${u} from=${t}`); + if (i = i << t | u, a + t > 32) + throw new Error(`convertRadix2: carry overflow pos=${a} from=${t}`); + for (a += t; a >= n; a -= n) + l.push((i >> a - n & s) >>> 0); + const h = et[a]; + if (h === void 0) + throw new Error("invalid carry"); + i &= h - 1; + } + if (i = i << n - a & s, !r && a >= t) + throw new Error("Excess padding"); + if (!r && i > 0) + throw new Error(`Non-zero padding: ${i}`); + return r && a > 0 && l.push(i >>> 0), l; +} +// @__NO_SIDE_EFFECTS__ +function h1(e) { + Ne(e); + const t = 2 ** 8; + return { + encode: (n) => { + if (!Ue(n)) + throw new Error("radix.encode input should be Uint8Array"); + return Yt(Array.from(n), t, e); + }, + decode: (n) => ($t("radix.decode", n), Uint8Array.from(Yt(n, e, t))) + }; +} +// @__NO_SIDE_EFFECTS__ +function rr(e, t = !1) { + if (Ne(e), e <= 0 || e > 32) + throw new Error("radix2: bits should be in (0..32]"); + if (/* @__PURE__ */ dt(8, e) > 32 || /* @__PURE__ */ dt(e, 8) > 32) + throw new Error("radix2: carry overflow"); + return { + encode: (n) => { + if (!Ue(n)) + throw new Error("radix2.encode input should be Uint8Array"); + return gt(Array.from(n), 8, e, !t); + }, + decode: (n) => ($t("radix2.decode", n), Uint8Array.from(gt(n, e, 8, t))) + }; +} +function Gr(e) { + return vn(e), function(...t) { + try { + return e.apply(null, t); + } catch { + } + }; +} +function f1(e, t) { + return Ne(e), vn(t), { + encode(n) { + if (!Ue(n)) + throw new Error("checksum.encode: input should be Uint8Array"); + const r = t(n).slice(0, e), i = new Uint8Array(n.length + e); + return i.set(n), i.set(r, n.length), i; + }, + decode(n) { + if (!Ue(n)) + throw new Error("checksum.decode: input should be Uint8Array"); + const r = n.slice(0, -e), i = n.slice(-e), a = t(r).slice(0, e); + for (let o = 0; o < e; o++) + if (a[o] !== i[o]) + throw new Error("Invalid checksum"); + return r; + } + }; +} +const X1 = { + alphabet: er, + chain: Wt, + checksum: f1, + convertRadix: Yt, + convertRadix2: gt, + radix: h1, + radix2: rr, + join: tr, + padding: Bn +}, p1 = typeof Uint8Array.from([]).toBase64 == "function" && typeof Uint8Array.fromBase64 == "function", I1 = (e, t) => { + ke("base64", e); + const n = /^[A-Za-z0-9=+/]+$/, r = "base64"; + if (e.length > 0 && !n.test(e)) + throw new Error("invalid base64"); + return Uint8Array.fromBase64(e, { alphabet: r, lastChunkHandling: "strict" }); +}, Z1 = p1 ? { + encode(e) { + return A1(e), e.toBase64(); + }, + decode(e) { + return I1(e); + } +} : /* @__PURE__ */ Wt(/* @__PURE__ */ rr(6), /* @__PURE__ */ er("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), /* @__PURE__ */ Bn(6), /* @__PURE__ */ tr("")), Mt = /* @__PURE__ */ Wt(/* @__PURE__ */ er("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ tr("")), Hr = [996825010, 642813549, 513874426, 1027748829, 705979059]; +function Ve(e) { + const t = e >> 25; + let n = (e & 33554431) << 5; + for (let r = 0; r < Hr.length; r++) + (t >> r & 1) === 1 && (n ^= Hr[r]); + return n; +} +function Nr(e, t, n = 1) { + const r = e.length; + let i = 1; + for (let a = 0; a < r; a++) { + const o = e.charCodeAt(a); + if (o < 33 || o > 126) + throw new Error(`Invalid prefix (${e})`); + i = Ve(i) ^ o >> 5; + } + i = Ve(i); + for (let a = 0; a < r; a++) + i = Ve(i) ^ e.charCodeAt(a) & 31; + for (let a of t) + i = Ve(i) ^ a; + for (let a = 0; a < 6; a++) + i = Ve(i); + return i ^= n, Mt.encode(gt([i % et[30]], 30, 5, !1)); +} +// @__NO_SIDE_EFFECTS__ +function m1(e) { + const t = e === "bech32" ? 1 : 734539939, n = /* @__PURE__ */ rr(5), r = n.decode, i = n.encode, a = Gr(r); + function o(g, c, d = 90) { + ke("bech32.encode prefix", g), Ue(c) && (c = Array.from(c)), $t("bech32.encode", c); + const I = g.length; + if (I === 0) + throw new TypeError(`Invalid prefix length ${I}`); + const m = I + 7 + c.length; + if (d !== !1 && m > d) + throw new TypeError(`Length ${m} exceeds limit ${d}`); + const B = g.toLowerCase(), S = Nr(B, c, t); + return `${B}1${Mt.encode(c)}${S}`; + } + function s(g, c = 90) { + ke("bech32.decode input", g); + const d = g.length; + if (d < 8 || c !== !1 && d > c) + throw new TypeError(`invalid string length: ${d} (${g}). Expected (8..${c})`); + const I = g.toLowerCase(); + if (g !== I && g !== g.toUpperCase()) + throw new Error("String must be lowercase or uppercase"); + const m = I.lastIndexOf("1"); + if (m === 0 || m === -1) + throw new Error('Letter "1" must be present between prefix and data only'); + const B = I.slice(0, m), S = I.slice(m + 1); + if (S.length < 6) + throw new Error("Data must be at least 6 characters long"); + const j = Mt.decode(S).slice(0, -6), b = Nr(B, j, t); + if (!S.endsWith(b)) + throw new Error(`Invalid checksum in ${g}: expected "${b}"`); + return { prefix: B, words: j }; + } + const l = Gr(s); + function u(g) { + const { prefix: c, words: d } = s(g, !1); + return { prefix: c, words: d, bytes: r(d) }; + } + function h(g, c) { + return o(g, i(c)); + } + return { + encode: o, + decode: s, + encodeFromBytes: h, + decodeToBytes: u, + decodeUnsafe: l, + fromWords: r, + fromWordsUnsafe: a, + toWords: i + }; +} +const nr = /* @__PURE__ */ m1("bech32"); +function $1(e) { + return nr.encodeFromBytes("npub", Je(e)); +} +function W1(e) { + return nr.encodeFromBytes("nsec", e); +} +function e2(e) { + const { prefix: t, bytes: n } = nr.decodeToBytes(e); + if (t !== "nsec" || n.length !== 32) + throw new Error("Not a valid nsec."); + return n; +} +function t2(e) { + return { + schema: Cn, + recovery_public_key: e.recoveryPublicKeyHex, + vault_relays: e.vaultRelayUrls, + recovery_capsule_events: e.recoveryCapsuleEvents, + relay_list_events: e.relayListEvents, + created_at: e.now ?? Math.floor(Date.now() / 1e3) + }; +} +class oe extends Error { + constructor(t) { + super(t), this.name = "RecoveryExportParseError"; + } +} +function r2(e) { + if (typeof e != "object" || e === null) + throw new oe("Recovery export must be a JSON object."); + const t = e; + if (t.schema !== Cn) + throw new oe(`Unsupported recovery export schema: ${String(t.schema)}`); + if (typeof t.recovery_public_key != "string" || !/^[0-9a-f]{64}$/u.test(t.recovery_public_key)) + throw new oe("recovery_public_key must be lowercase 64-char hex."); + if (!Array.isArray(t.vault_relays)) + throw new oe("vault_relays must be an array."); + if (!Array.isArray(t.recovery_capsule_events) || t.recovery_capsule_events.length === 0) + throw new oe("recovery_capsule_events must be a non-empty array."); + for (const n of t.recovery_capsule_events) + if (!Fr(n)) + throw new oe("An embedded recovery_capsule_event has an invalid id or signature."); + if (!Array.isArray(t.relay_list_events)) + throw new oe("relay_list_events must be an array."); + for (const n of t.relay_list_events) + if (!Fr(n)) + throw new oe("An embedded relay_list_event has an invalid id or signature."); + if (typeof t.created_at != "number") + throw new oe("created_at must be a number."); + return t; +} +export { + jr as $, + rt as A, + Q1 as B, + pt as C, + R1 as D, + b1 as E, + Ce as F, + x1 as G, + pe as H, + X1 as I, + fe as J, + q1 as K, + We as L, + e2 as M, + Je as N, + n1 as O, + H1 as P, + w1 as Q, + oe as R, + L1 as S, + N1 as T, + K1 as U, + k1 as V, + J1 as W, + qe as X, + Z1 as Y, + qr as Z, + mt as _, + $1 as a, + U1 as a0, + Rt as a1, + t2 as a2, + W1 as a3, + z1 as b, + wn as c, + Y1 as d, + y1 as e, + M1 as f, + O1 as g, + j1 as h, + G1 as i, + T1 as j, + C1 as k, + D1 as l, + S1 as m, + F1 as n, + o1 as o, + r2 as p, + P1 as q, + v1 as r, + V1 as s, + _1 as t, + De as u, + Fr as v, + bt as w, + B1 as x, + ht as y, + E1 as z +}; diff --git a/vendor/bitlogin/bitlogin.js b/vendor/bitlogin/bitlogin.js new file mode 100644 index 00000000..ff55bb27 --- /dev/null +++ b/vendor/bitlogin/bitlogin.js @@ -0,0 +1,1253 @@ +import { r as y, e as w, E as v, p as Q, R as k, i as h, a as u } from "./bitlogin-shared-QIBe5Omw.js"; +const x = 6, p = 64; +function c(a = x) { + const e = w(), t = []; + for (let r = 0; r < a; r++) + t.push(e[y(e.length)]); + const s = a * v; + if (s < p) + throw new Error(`Passphrase of ${a} words provides only ~${s.toFixed(1)} bits; must exceed ${p}.`); + return { kind: "passphrase", secret: t.join(" "), entropyBits: s }; +} +const b = 64, m = 12, P = /* @__PURE__ */ new Set([ + "password", + "password1", + "password123", + "123456", + "123456789", + "12345678", + "qwerty", + "qwerty123", + "letmein", + "welcome", + "monkey", + "dragon", + "master", + "abc123", + "iloveyou", + "admin", + "login", + "starwars", + "sunshine", + "princess", + "football", + "baseball", + "trustno1", + "000000", + "111111", + "123123", + "1234567890", + "changeme", + "passw0rd", + "correcthorsebatterystaple" +]); +function L(a) { + let e = 0; + return /[a-z]/u.test(a) && (e += 26), /[A-Z]/u.test(a) && (e += 26), /[0-9]/u.test(a) && (e += 10), /[^a-zA-Z0-9]/u.test(a) && (e += 33), e || 1; +} +function C(a) { + return a.length * Math.log2(L(a)); +} +function S(a) { + if (/^(.)\1*$/u.test(a) || /(.)\1{2,}/u.test(a)) + return !0; + const e = a.toLowerCase(), t = ["0123456789", "abcdefghijklmnopqrstuvwxyz"]; + for (const s of t) + for (let r = 0; r + 4 <= s.length; r++) { + const o = s.slice(r, r + 4), n = [...o].reverse().join(""); + if (e.includes(o) || e.includes(n)) + return !0; + } + return !1; +} +function f(a, e) { + const t = C(a); + return a.length < m ? { ok: !1, entropyBits: t, reason: `Must be at least ${m} characters.` } : P.has(a.toLowerCase()) ? { ok: !1, entropyBits: t, reason: "This is on a list of extremely common passwords." } : e.length >= 3 && a.toLowerCase().includes(e) ? { ok: !1, entropyBits: t, reason: "Must not contain your login name." } : S(a) ? { ok: !1, entropyBits: t, reason: "Too predictable (repeated characters or a simple sequence)." } : t < b ? { + ok: !1, + entropyBits: t, + reason: `Estimated entropy (~${t.toFixed(0)} bits) is below the required ${b}. Use a longer password or mix character types.` + } : { ok: !0, entropyBits: t }; +} +class E { + worker; + pending = /* @__PURE__ */ new Map(); + counter = 0; + constructor() { + const e = ["cryptoWorker", ".js"].join(""), t = new URL(e, import.meta.url); + this.worker = new Worker(t, { type: "module" }), this.worker.addEventListener("message", (s) => { + const r = s.data, o = this.pending.get(r.id); + if (o) + if (this.pending.delete(r.id), r.ok) + o.resolve(r.result); + else { + const n = new Error(r.error); + n.name = r.errorName ?? "Error", o.reject(n); + } + }); + } + call(e, t) { + const s = `${Date.now().toString(36)}-${(this.counter++).toString(36)}`; + return new Promise((r, o) => { + this.pending.set(s, { resolve: r, reject: o }); + const n = { id: s, action: e, payload: t }; + this.worker.postMessage(n); + }); + } + configure(e) { + return this.call("configure", e); + } + register(e) { + return this.call("register", e); + } + previewImportKey(e) { + return this.call("previewImportKey", e); + } + login(e) { + return this.call("login", e); + } + recover(e) { + return this.call("recover", e); + } + completeRecovery(e) { + return this.call("completeRecovery", e); + } + changePassword(e) { + return this.call("changePassword", e); + } + publishProfileAndRelayLists(e) { + return this.call("publishProfileAndRelayLists", e); + } + getPublicKey() { + return this.call("getPublicKey", {}); + } + signEvent(e) { + return this.call("signEvent", e); + } + nip44Encrypt(e) { + return this.call("nip44Encrypt", e); + } + nip44Decrypt(e) { + return this.call("nip44Decrypt", e); + } + exportIdentity() { + return this.call("exportIdentity", {}); + } + buildRecoveryExport() { + return this.call("buildRecoveryExport", {}); + } + repairReplicas() { + return this.call("repairReplicas", {}); + } + getSessionStatus() { + return this.call("getSessionStatus", {}); + } + logout() { + return this.call("logout", {}); + } + terminate() { + this.worker.terminate(); + } +} +const N = "BitLogin: no identity is unlocked yet. Add to the page and let the user sign in, or call it programmatically before invoking window.nostr."; +function d(a) { + return a.catch((e) => { + throw e.message.includes("No identity is unlocked") ? new Error(N) : e; + }); +} +function $(a, e) { + return { + async getPublicKey() { + const { publicKey: t } = await d(a.getPublicKey()); + return t; + }, + async signEvent(t) { + return d(a.signEvent(t)); + }, + async getRelays() { + const t = {}; + for (const s of e()) t[s] = { read: !0, write: !0 }; + return t; + }, + nip44: { + async encrypt(t, s) { + const { ciphertext: r } = await d(a.nip44Encrypt({ peerPublicKey: t, plaintext: s })); + return r; + }, + async decrypt(t, s) { + const { plaintext: r } = await d(a.nip44Decrypt({ peerPublicKey: t, payload: s })); + return r; + } + }, + _bitlogin: !0 + }; +} +function R(a) { + const e = a.getAttribute("vault-relays"), t = a.getAttribute("discovery-relays"); + return { + vaultRelayUrls: e ? e.split(",").map((s) => s.trim()).filter(Boolean) : void 0, + discoveryRelayUrls: t ? t.split(",").map((s) => s.trim()).filter(Boolean) : void 0 + }; +} +const M = ( + /* css */ + ` +:host { + --bl-accent: #6d28d9; + --bl-accent-hover: #5b21b6; + --bl-accent-fg: white; + --bl-bg: #ffffff; + --bl-fg: #16151a; + --bl-muted: #6b7280; + --bl-border: #e5e7eb; + --bl-input-bg: #f9fafb; + --bl-danger: #b91c1c; + --bl-danger-bg: #fef2f2; + --bl-warn: #92400e; + --bl-warn-bg: #fffbeb; + --bl-radius: 14px; + /* Caps the widget's own width; a host page that wants it to fill a wider + container (rather than stay a fixed-width card) overrides this to a + larger value or "none". */ + --bl-max-width: 380px; + --bl-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + all: initial; + display: inline-block; + width: 100%; + max-width: var(--bl-max-width); + font-family: var(--bl-font-family); + color-scheme: light dark; +} +@media (prefers-color-scheme: dark) { + :host { + --bl-bg: #17151f; + --bl-fg: #f4f2f8; + --bl-muted: #9a94ab; + --bl-border: #322d40; + --bl-input-bg: #201d2b; + --bl-danger: #fca5a5; + --bl-danger-bg: #3a1414; + --bl-warn: #fcd34d; + --bl-warn-bg: #3a2a0a; + } +} +:host([data-theme="dark"]) { + --bl-bg: #17151f; + --bl-fg: #f4f2f8; + --bl-muted: #9a94ab; + --bl-border: #322d40; + --bl-input-bg: #201d2b; +} +:host([data-theme="light"]) { + --bl-bg: #ffffff; + --bl-fg: #16151a; + --bl-muted: #6b7280; + --bl-border: #e5e7eb; + --bl-input-bg: #f9fafb; +} +* { box-sizing: border-box; } +.card { + position: relative; + width: 100%; + background: var(--bl-bg); + color: var(--bl-fg); + border: 1px solid var(--bl-border); + border-radius: var(--bl-radius); + padding: 24px; + font-size: 14px; + line-height: 1.5; +} +h2 { + font-size: 18px; + font-weight: 600; + margin: 0 0 4px; +} +/* One fixed SVG (icon + wordmark, same file as the marketing site's assets/lockup.svg) + with the relative size and spacing between them baked in -- only the overall height + is ever set here, so the lockup can never end up looking different in one place than + another the way independently-sized icon + text elements could drift apart. */ +.brand-lockup { + display: block; + height: 20px; + width: auto; + margin: 0 0 6px; + color: var(--bl-fg); +} +/* Brief confirmation stamp shown over the destination screen right after a real + security-relevant success (see flashSuccess() in element.ts) -- the same brass ring + and checkmark as the brand mark, so a successful sign-in/create/recover/rotate reads + as "sealed," not just a silent screen change. Never blocks interaction, and fades out + on its own; the JS timer that removes it entirely doesn't depend on the animation. */ +.success-overlay { + position: absolute; + inset: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 12px; + background: var(--bl-bg); + border-radius: var(--bl-radius); + pointer-events: none; + animation: bl-overlay-fade-out 0.4s ease 0.7s both; +} +.success-stamp svg { + width: 56px; + height: 56px; + animation: bl-stamp-in 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both; +} +.success-label { + margin: 0; + font-size: 14px; + font-weight: 600; + color: var(--bl-fg); + opacity: 0; + animation: bl-label-in 0.3s ease 0.35s both; +} +@keyframes bl-stamp-in { + 0% { transform: scale(0.5); opacity: 0; } + 60% { transform: scale(1.15); opacity: 1; } + 100% { transform: scale(1); opacity: 1; } +} +@keyframes bl-label-in { + to { opacity: 1; } +} +@keyframes bl-overlay-fade-out { + 0% { opacity: 1; } + 100% { opacity: 0; } +} +@media (prefers-reduced-motion: reduce) { + .success-overlay { animation: none; } + .success-stamp svg { animation: none; } + .success-label { animation: none; opacity: 1; } +} +p.sub { + color: var(--bl-muted); + margin: 0 0 18px; + font-size: 13px; +} +label { + display: block; + font-size: 13px; + font-weight: 500; + margin: 14px 0 6px; +} +input[type="text"], input[type="password"] { + width: 100%; + padding: 10px 12px; + border-radius: 9px; + border: 1px solid var(--bl-border); + background: var(--bl-input-bg); + color: var(--bl-fg); + font-size: 14px; + font-family: inherit; +} +input:focus { outline: 2px solid var(--bl-accent); outline-offset: 1px; } +.credential-box { + background: var(--bl-input-bg); + border: 1px solid var(--bl-border); + border-radius: 9px; + padding: 12px; + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 13.5px; + word-break: break-word; + margin: 6px 0 2px; + user-select: all; +} +.phrase-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 6px; + margin: 10px 0; +} +.phrase-word { + background: var(--bl-input-bg); + border: 1px solid var(--bl-border); + border-radius: 7px; + padding: 6px 8px; + font-size: 12.5px; + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + display: flex; + gap: 4px; +} +.phrase-word span { color: var(--bl-muted); } +button { + font-family: inherit; + font-size: 14px; + font-weight: 600; + border-radius: 9px; + border: none; + padding: 11px 14px; + cursor: pointer; + width: 100%; + margin-top: 14px; +} +button.primary { background: var(--bl-accent); color: var(--bl-accent-fg); } +button.primary:hover { background: var(--bl-accent-hover); } +button.primary:disabled { opacity: 0.55; cursor: default; } +button.secondary { background: transparent; color: var(--bl-fg); border: 1px solid var(--bl-border); } +button.secondary:hover { background: var(--bl-input-bg); } +button.link { + display: block; + background: none; + color: var(--bl-accent); + width: auto; + padding: 0; + margin: 12px 0 0; + font-weight: 500; + font-size: 13px; +} +.row { display: flex; gap: 8px; } +.row > * { flex: 1; } +.notice { + border-radius: 9px; + padding: 10px 12px; + font-size: 13px; + margin: 12px 0; +} +.notice.warn { background: var(--bl-warn-bg); color: var(--bl-warn); } +.notice.error { background: var(--bl-danger-bg); color: var(--bl-danger); } +.notice.info { background: var(--bl-input-bg); color: var(--bl-fg); border: 1px solid var(--bl-border); } +.pubkey { + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 12px; + color: var(--bl-muted); + word-break: break-all; +} +.divider { border-top: 1px solid var(--bl-border); margin: 18px 0; } +.small { font-size: 12px; color: var(--bl-muted); } +.checkbox-row { display: flex; align-items: flex-start; gap: 8px; margin: 14px 0; font-size: 13px; } +.checkbox-row input { margin-top: 3px; } +.spinner { + display: inline-block; + width: 14px; height: 14px; + border: 2px solid rgba(255,255,255,0.4); + border-top-color: white; + border-radius: 50%; + animation: bl-spin 0.7s linear infinite; + vertical-align: -2px; + margin-right: 6px; +} +@keyframes bl-spin { to { transform: rotate(360deg); } } +` +); +class F extends HTMLElement { + root; + worker; + vaultRelayUrls = []; + discoveryRelayUrls = []; + installedProvider = null; + screen = "welcome"; + busy = !1; + errorMessage; + loginName = ""; + generatedCredential = ""; + savedCheckbox = !1; + recoveryPhrase = ""; + confirmSlots = []; + // Manual password opt-in (§9.3). Off by default; the generated passphrase remains the + // recommendation. manualPasswordFeedback is updated on every keystroke WITHOUT a full + // re-render (see onInput) so the field never loses focus while the user is typing. + // manualPasswordDraft/manualPasswordConfirmDraft re-populate the fields' value attribute + // across a validation-failure re-render, so a rejected password isn't silently wiped, + // forcing the user to retype it (and re-check "I saved it") from scratch. + manualPasswordMode = !1; + manualPasswordFeedback = null; + manualPasswordDraft = ""; + manualPasswordConfirmDraft = ""; + // Import flow (§SF10). importKey holds the pasted nsec/hex only until registration completes. + importKey = ""; + importPreviewNpub = ""; + recoverPhraseInput = ""; + recoveredPreview = null; + newCredentialAfterRecovery = ""; + // Optional recovery-export-file fallback (§19.5) for when live relays can't be reached. + // Never a substitute for the phrase -- the file never contains it or any phrase-derived key. + offlineExportFile = null; + offlineExportFileNotice; + session = null; + sessionWarnings = []; + lastSignedEventJson = ""; + exportedNsec = ""; + changePasswordNewCredential = ""; + // Brief animated brass-seal stamp (matching the widget's own brand mark) shown once over + // the destination screen right after a real security-relevant success -- see flashSuccess(). + pendingSuccessLabel = null; + successDismissTimer = null; + // Rollback confirmation (§16.2 step 6). A RollbackDetectedError from either login or + // password-change means this device has already seen a newer credential generation than the + // one just read -- most likely a rotated-away password being replayed from a relay that never + // processed its tombstone. Rather than a passive dashboard banner shown after the fact (which + // let an old, "revoked" password fully unlock a session), this blocks BEFORE claiming the + // signer or dispatching bitlogin-login, and requires an explicit second step to proceed. + pendingRollback = null; + rollbackMessage = ""; + constructor() { + super(), this.root = this.attachShadow({ mode: "open" }), this.worker = new E(); + } + connectedCallback() { + const e = R(this); + if (this.vaultRelayUrls = e.vaultRelayUrls ?? [], this.discoveryRelayUrls = e.discoveryRelayUrls ?? [], this.worker.configure({ vaultRelayUrls: this.vaultRelayUrls, discoveryRelayUrls: this.discoveryRelayUrls }), this.root.addEventListener("click", (t) => this.onClick(t)), this.root.addEventListener("submit", (t) => this.onSubmit(t)), this.root.addEventListener("input", (t) => this.onInput(t)), this.root.addEventListener("change", (t) => void this.onFileChange(t)), this.render(), this.installedProvider = $(this.worker, () => this.vaultRelayUrls), !window.nostr) + try { + window.nostr = this.installedProvider; + } catch { + } + } + disconnectedCallback() { + this.successDismissTimer !== null && clearTimeout(this.successDismissTimer), this.releaseSigner(), this.worker.terminate(); + } + // ---- Public API mirroring window.nostr, scoped to this element instance ---- + async getPublicKey() { + return (await this.worker.getPublicKey()).publicKey; + } + async signEvent(e) { + return this.worker.signEvent(e); + } + /** + * Element-scoped NIP-44 encryption, matching getPublicKey/signEvent above. A host page + * embedding multiple signing methods (its own extension detection, another widget) should + * prefer this over reaching through `window.nostr.nip44` -- window.nostr is a single global + * slot that whichever provider signed in last currently owns, so a host holding a direct + * reference to ITS OWN `` element can talk to it deterministically instead of + * racing other providers for that slot. + */ + async nip44Encrypt(e, t) { + return (await this.worker.nip44Encrypt({ peerPublicKey: e, plaintext: t })).ciphertext; + } + async nip44Decrypt(e, t) { + return (await this.worker.nip44Decrypt({ peerPublicKey: e, payload: t })).plaintext; + } + async logout() { + await this.worker.logout(), this.session = null, this.releaseSigner(), this.dispatchEvent(new CustomEvent("bitlogin-logout")), this.goto("welcome"); + } + /** + * (Re)installs this element's own provider as window.nostr, taking over from whatever is + * currently there (an extension, a different BitLogin instance, or nothing). Called + * automatically whenever a user completes sign-in through this widget — that's an + * explicit signal they want BitLogin active. Also public: a host page offering several + * signing methods can call it directly (e.g. `document.querySelector('bitlogin-auth').claimSigner()`) + * when the user re-selects BitLogin from its own method picker, without a page reload. + * + * Best-effort: some NIP-07 extensions install window.nostr as a non-configurable, + * non-writable property specifically to prevent another script from overwriting it, and + * the plain assignment below throws a TypeError in that case ("Cannot assign to read only + * property 'nostr'..."). This is never fatal to BitLogin's own session -- a host page + * holding a reference to this element (getPublicKey/signEvent/nip44Encrypt/nip44Decrypt + * above) never depends on window.nostr at all -- so the failure is caught and reported + * through the returned boolean and the event detail rather than thrown, and every caller + * below proceeds to complete sign-in regardless. Only a host page that reads window.nostr + * directly (instead of talking to this element) is actually affected, and only for as long + * as the other extension holds the slot. + */ + claimSigner() { + try { + return window.nostr = this.installedProvider, this.dispatchEvent(new CustomEvent("bitlogin-signer-claimed", { detail: { windowNostrClaimed: !0 } })), !0; + } catch (e) { + const t = e instanceof Error ? e.message : String(e); + return this.dispatchEvent(new CustomEvent("bitlogin-signer-claimed", { detail: { windowNostrClaimed: !1, error: t } })), !1; + } + } + /** + * Surfaces a claimSigner() failure on the dashboard itself (not just the event detail), + * using the same sessionWarnings/renderWarnings mechanism already shown for rollback and + * relay-disagreement warnings -- so a user isn't left wondering why some other app still + * seems to be using a different signer. + */ + noteSignerClaim(e) { + e || (this.sessionWarnings = [ + ...this.sessionWarnings, + "Another Nostr signer (browser extension) is active in this browser and couldn't be replaced. You're signed in to BitLogin, but any app that reads window.nostr directly may still use that other signer instead of this one." + ]); + } + /** + * Releases window.nostr back to undefined, but only if it's still this element's own + * provider — never clobbers a different signing method a host page (or another widget + * instance) may have since taken over. Called automatically on logout and on removal from + * the DOM, so a page offering multiple signing methods (an extension, a NIP-46 bunker, + * BitLogin) can let a user switch away from BitLogin without a full page reload — before + * this existed, window.nostr stayed pointed at a signed-out BitLogin provider forever. + * Returns whether it actually released anything. Best-effort for the same reason as + * claimSigner above: a property some other extension made non-configurable can also fail + * to `delete`, and that must not block logout either. + */ + releaseSigner() { + const e = window; + if (this.installedProvider && e.nostr === this.installedProvider) { + try { + delete e.nostr; + } catch { + return !1; + } + return this.dispatchEvent(new CustomEvent("bitlogin-signer-released")), !0; + } + return !1; + } + goto(e) { + this.screen = e, this.errorMessage = void 0, this.render(); + } + setBusy(e) { + this.busy = e, this.render(); + } + fail(e) { + this.errorMessage = e instanceof Error ? e.message : String(e), this.busy = !1, this.render(); + } + field(e) { + return this.root.querySelector(`[name="${e}"]`)?.value ?? ""; + } + /** + * Shared manual-password field markup (§9.3), reused on every screen that lets a user set + * their own password (initial creation, phrase recovery, and password rotation) so the + * option isn't only available at signup. + */ + renderManualPasswordFields() { + return ` + + +
+ + +
+ `; + } + /** + * Reads and validates the manual-password fields against a caller-supplied login name. + * Always stashes what was typed into manualPasswordDraft/manualPasswordConfirmDraft so a + * validation-failure re-render can restore it (see renderManualPasswordFields). + */ + readManualPassword(e) { + const t = this.field("manualPassword"), s = this.field("manualPasswordConfirm"); + this.manualPasswordDraft = t, this.manualPasswordConfirmDraft = s; + const r = f(t, e); + return r.ok ? t !== s ? { password: "", error: "Passwords do not match. Please re-enter both." } : { password: t } : { password: "", error: `Password not accepted: ${r.reason}` }; + } + /** + * Explicitly asks the browser to offer saving this credential via the Credential + * Management API (Chromium-based browsers only — Firefox and Safari never implemented + * `PasswordCredential`). This is the primary fix for password-manager integration here, + * not just a nice-to-have: the generated-password screen never puts the password into a + * real `` for a browser to observe being filled (it's shown as text), and even on + * the login screen — which does use real, correctly-`autocomplete`d inputs — save/autofill + * heuristics are unreliable inside a shadow root, and this widget's JS-driven submit + * (`preventDefault`, no real form POST) doesn't produce the passive signal most heuristics + * expect anyway. An explicit `navigator.credentials.store()` call sidesteps all of that. + * Best-effort only: never blocks or fails the surrounding flow. + */ + async offerToSaveCredential(e, t) { + try { + const s = window.PasswordCredential; + if (!s || !navigator.credentials?.store) return; + const r = new s({ id: e, password: t, name: e }); + await navigator.credentials.store(r); + } catch { + } + } + async onClick(e) { + const t = e.target.closest("[data-action]"); + if (!t) return; + switch (t.dataset.action) { + case "goto-create": + this.loginName = "", this.importKey = "", this.importPreviewNpub = "", this.goto("create-name"); + return; + case "goto-import": + this.importKey = "", this.importPreviewNpub = "", this.goto("import-key"); + return; + case "preview-import": + return this.handlePreviewImport(); + case "import-continue": + return this.handleImportContinue(); + case "goto-login": + this.goto("login"); + return; + case "goto-recover": + this.offlineExportFile = null, this.offlineExportFileNotice = void 0, this.goto("recover-phrase"); + return; + case "goto-welcome": + this.pendingRollback = null, this.goto("welcome"); + return; + case "goto-dashboard": + this.goto("dashboard"); + return; + case "goto-verify-phrase": + this.goto("verify-phrase"); + return; + case "goto-confirm-phrase": + this.goto("confirm-phrase"); + return; + case "goto-change-password": + this.changePasswordNewCredential = c().secret, this.manualPasswordMode = !1, this.manualPasswordFeedback = null, this.manualPasswordDraft = "", this.manualPasswordConfirmDraft = "", this.goto("change-password"); + return; + case "goto-export": + this.goto("export"); + return; + case "regenerate-credential": + this.generatedCredential = c().secret, this.savedCheckbox = !1, this.render(); + return; + case "toggle-manual-password": + this.manualPasswordMode = !this.manualPasswordMode, this.manualPasswordFeedback = null, this.manualPasswordDraft = "", this.manualPasswordConfirmDraft = "", this.savedCheckbox = !1, this.render(); + return; + case "copy-credential": { + const r = this.root.querySelector("#credential-box"), o = t, n = o.textContent ?? "Copy", l = (g) => { + o.textContent = g, setTimeout(() => { + o.isConnected && (o.textContent = n); + }, 2e3); + }; + if (!r || !navigator.clipboard?.writeText) { + l("Copy not available — select the text manually"); + return; + } + navigator.clipboard.writeText(r.textContent ?? "").then( + () => l("Copied"), + () => l("Copy failed — select the text manually") + ); + return; + } + case "download-recovery-export": + return this.handleDownloadRecoveryExport(); + case "sign-test-event": + return this.handleSignTestEvent(); + case "reveal-nsec": + return this.handleRevealNsec(); + case "logout": + return this.logout(); + case "rollback-retry": { + const r = this.pendingRollback?.kind; + this.pendingRollback = null, this.goto(r === "change-password" ? "change-password" : "login"); + return; + } + case "rollback-continue": + return this.handleRollbackContinue(); + default: + return; + } + } + async onSubmit(e) { + e.preventDefault(); + const s = e.target.dataset.form; + try { + switch (s) { + case "import-key": + return await this.handlePreviewImport(); + case "create-name": + return this.handleCreateNameSubmit(); + case "create-credential": + return await this.handleCreateCredentialSubmit(); + case "verify-phrase": + return this.handleVerifyPhraseSubmit(); + case "login": + return await this.handleLoginSubmit(); + case "recover-phrase": + return await this.handleRecoverPhraseSubmit(); + case "recover-new-credentials": + return await this.handleRecoverNewCredentialsSubmit(); + case "change-password": + return await this.handleChangePasswordSubmit(); + default: + return; + } + } catch (r) { + this.fail(r); + } + } + /** + * Live entropy/strength and match feedback for the manual-password fields, updated by + * DIRECTLY patching feedback elements' text — never calling this.render() — so neither + * input loses focus or cursor position while the user is typing (§9.3). + */ + onInput(e) { + const t = e.target; + if (!(t instanceof HTMLInputElement) || t.name !== "manualPassword" && t.name !== "manualPasswordConfirm") return; + const s = this.root.querySelector('input[name="manualPassword"]')?.value ?? "", r = this.root.querySelector('input[name="manualPasswordConfirm"]')?.value ?? ""; + this.manualPasswordFeedback = s ? f(s, this.loginName) : null; + const o = this.root.querySelector("#manual-password-feedback"); + if (o) + if (!this.manualPasswordFeedback) + o.textContent = "", o.className = "notice info"; + else { + const l = this.manualPasswordFeedback.entropyBits.toFixed(0); + this.manualPasswordFeedback.ok ? (o.textContent = `Looks good (~${l} bits estimated).`, o.className = "notice info") : (o.textContent = `${this.manualPasswordFeedback.reason} (~${l} bits estimated)`, o.className = "notice warn"); + } + const n = this.root.querySelector("#manual-password-match-feedback"); + n && (r ? r === s ? (n.textContent = "Passwords match.", n.className = "notice info") : (n.textContent = "Passwords do not match.", n.className = "notice warn") : (n.textContent = "", n.className = "notice info")); + } + /** + * Reads and validates an optional recovery-export file (§19.5) for the recover-phrase + * screen. Purely a relay-outage fallback -- the file never contains the phrase or any + * phrase-derived key, so it's ignored entirely unless the user also enters their phrase. + */ + async onFileChange(e) { + const t = e.target; + if (!(t instanceof HTMLInputElement) || t.name !== "offlineExportFile" || t.type !== "file") return; + const s = t.files?.[0]; + if (!s) { + this.offlineExportFile = null, this.offlineExportFileNotice = void 0, this.render(); + return; + } + try { + const r = await s.text(); + this.offlineExportFile = Q(JSON.parse(r)), this.offlineExportFileNotice = `Loaded recovery export from ${new Date(this.offlineExportFile.created_at * 1e3).toLocaleString()}.`; + } catch (r) { + this.offlineExportFile = null, this.offlineExportFileNotice = r instanceof k || r instanceof SyntaxError ? `Couldn't read that file: ${r.message}` : `Couldn't read that file: ${String(r)}`; + } + this.render(); + } + async handlePreviewImport() { + const e = this.field("importKey").trim(); + if (!e) { + this.errorMessage = "Paste your nsec or hex private key first.", this.render(); + return; + } + this.setBusy(!0); + try { + const t = await this.worker.previewImportKey({ nsecOrHex: e }); + this.importKey = e, this.importPreviewNpub = t.npub, this.busy = !1, this.render(); + } catch (t) { + this.importKey = "", this.importPreviewNpub = "", this.fail(t); + } + } + handleImportContinue() { + if (!this.importKey || !this.importPreviewNpub) { + this.errorMessage = "Check your key before continuing.", this.render(); + return; + } + this.loginName = "", this.goto("create-name"); + } + handleCreateNameSubmit() { + const e = this.field("loginName").trim().toLowerCase(); + if (!h(e)) { + this.errorMessage = "Login name must be 3-32 characters: a-z, 0-9, '.', '_', '-', and not start/end with punctuation.", this.render(); + return; + } + this.loginName = e, this.generatedCredential = c().secret, this.savedCheckbox = !1, this.manualPasswordMode = !1, this.manualPasswordFeedback = null, this.manualPasswordDraft = "", this.manualPasswordConfirmDraft = "", this.goto("create-credential"); + } + async handleCreateCredentialSubmit() { + this.savedCheckbox = this.root.querySelector("#saved-check")?.checked ?? !1; + let e = this.generatedCredential; + if (this.manualPasswordMode) { + const { password: o, error: n } = this.readManualPassword(this.loginName); + if (n) { + this.errorMessage = n, this.render(); + return; + } + e = o; + } + if (!this.savedCheckbox) { + this.errorMessage = this.manualPasswordMode ? "Please confirm you've saved your password (or written it down) before continuing." : "Please confirm you saved your password before continuing.", this.render(); + return; + } + this.setBusy(!0); + const t = await this.worker.register({ + loginName: this.loginName, + password: e, + importKey: this.importKey || void 0 + }); + this.importKey = "", this.importPreviewNpub = "", this.recoveryPhrase = t.recoveryPhrase; + const s = this.recoveryPhrase.split(" "), r = T(s.length, 3); + this.confirmSlots = r.map((o) => ({ index: o, value: "" })), this.session = { publicKey: t.everydayPublicKey, npub: u(t.everydayPublicKey), accountId: t.accountId }, this.busy = !1, this.goto("confirm-phrase"), this.worker.publishProfileAndRelayLists({ + name: this.loginName, + generalRelays: this.vaultRelayUrls, + dmRelays: this.vaultRelayUrls + }), this.offerToSaveCredential(this.loginName, e); + } + handleVerifyPhraseSubmit() { + const e = this.recoveryPhrase.split(" "); + for (const t of this.confirmSlots) + if (this.field(`confirm-${t.index}`).trim().toLowerCase() !== e[t.index]) { + this.errorMessage = `Word #${t.index + 1} doesn't match. Please check your saved phrase and try again.`, this.render(); + return; + } + this.sessionWarnings = [], this.noteSignerClaim(this.claimSigner()), this.dispatchEvent(new CustomEvent("bitlogin-login", { detail: { publicKey: this.session?.publicKey } })), this.flashSuccess("dashboard", "Account created"); + } + async handleLoginSubmit() { + const e = this.field("loginName").trim().toLowerCase(), t = this.field("password"); + await this.attemptLogin(e, t); + } + /** + * Shared by the login form and the "continue anyway" rollback-confirmation step so both + * paths grant a session identically -- claimSigner() and the bitlogin-login event only ever + * fire once a RollbackDetectedError (if any) has been resolved one way or the other. + */ + async attemptLogin(e, t, s = !1) { + this.setBusy(!0); + try { + const r = await this.worker.login({ loginName: e, password: t, acknowledgeRollback: s }); + this.loginName = e, this.session = { publicKey: r.everydayPublicKey, npub: u(r.everydayPublicKey), accountId: r.accountId }, this.sessionWarnings = [r.rollbackWarning, r.relayDisagreementWarning].filter((o) => !!o), this.busy = !1, this.noteSignerClaim(this.claimSigner()), this.dispatchEvent(new CustomEvent("bitlogin-login", { detail: { publicKey: r.everydayPublicKey } })), this.flashSuccess("dashboard", "Signed in"), this.offerToSaveCredential(e, t); + } catch (r) { + if (r instanceof Error && r.name === "RollbackDetectedError") { + this.pendingRollback = { kind: "login", loginName: e, password: t }, this.rollbackMessage = r.message, this.busy = !1, this.goto("rollback-confirm"); + return; + } + this.fail(r); + } + } + async handleRollbackContinue() { + const e = this.pendingRollback; + if (this.pendingRollback = null, !e) { + this.goto("welcome"); + return; + } + e.kind === "login" ? await this.attemptLogin(e.loginName, e.password, !0) : await this.attemptChangePassword(e.oldPassword, e.newPassword, !0); + } + async handleRecoverPhraseSubmit() { + const e = this.field("phrase").trim(); + this.setBusy(!0); + const t = await this.worker.recover({ phrase: e, offlineExportFile: this.offlineExportFile ?? void 0 }); + this.recoverPhraseInput = e, this.recoveredPreview = { + generalRelaysCount: t.generalRelays.length, + dmRelaysCount: t.dmRelays.length, + chainWarning: t.chainWarning + }, this.session = { publicKey: t.everydayPublicKey, npub: u(t.everydayPublicKey), accountId: t.accountId }, this.newCredentialAfterRecovery = c().secret, this.manualPasswordMode = !1, this.manualPasswordFeedback = null, this.manualPasswordDraft = "", this.manualPasswordConfirmDraft = "", this.busy = !1, this.goto("recover-new-credentials"); + } + async handleRecoverNewCredentialsSubmit() { + const e = this.field("newLoginName").trim().toLowerCase(); + if (!h(e)) { + this.errorMessage = "Login name must be 3-32 characters: a-z, 0-9, '.', '_', '-', and not start/end with punctuation.", this.render(); + return; + } + let t = this.newCredentialAfterRecovery; + if (this.manualPasswordMode) { + const { password: s, error: r } = this.readManualPassword(e); + if (r) { + this.errorMessage = r, this.render(); + return; + } + t = s; + } + this.setBusy(!0), await this.worker.completeRecovery({ newLoginName: e, newPassword: t }), this.loginName = e, this.busy = !1, this.sessionWarnings = [], this.noteSignerClaim(this.claimSigner()), this.dispatchEvent(new CustomEvent("bitlogin-login", { detail: { publicKey: this.session?.publicKey } })), this.flashSuccess("dashboard", "Account recovered"), this.offerToSaveCredential(e, t); + } + async handleChangePasswordSubmit() { + const e = this.field("oldPassword"); + let t = this.changePasswordNewCredential; + if (this.manualPasswordMode) { + const { password: s, error: r } = this.readManualPassword(this.loginName); + if (r) { + this.errorMessage = r, this.render(); + return; + } + t = s; + } + await this.attemptChangePassword(e, t); + } + /** Shared by the rotation form and the "continue anyway" rollback-confirmation step; see attemptLogin. */ + async attemptChangePassword(e, t, s = !1) { + this.setBusy(!0); + try { + await this.worker.changePassword({ + loginName: this.loginName, + oldPassword: e, + newPassword: t, + acknowledgeRollback: s + }), this.busy = !1, this.sessionWarnings = [], this.noteSignerClaim(this.claimSigner()), this.flashSuccess("dashboard", "Password updated"), this.offerToSaveCredential(this.loginName, t); + } catch (r) { + if (r instanceof Error && r.name === "RollbackDetectedError") { + this.pendingRollback = { kind: "change-password", oldPassword: e, newPassword: t }, this.rollbackMessage = r.message, this.busy = !1, this.goto("rollback-confirm"); + return; + } + this.fail(r); + } + } + async handleDownloadRecoveryExport() { + const e = await this.worker.buildRecoveryExport(), t = new Blob([JSON.stringify(e, null, 2)], { type: "application/json" }), s = URL.createObjectURL(t), r = document.createElement("a"); + r.href = s, r.download = "bitlogin-recovery-export.json", r.click(), URL.revokeObjectURL(s); + } + async handleSignTestEvent() { + const e = await this.worker.signEvent({ kind: 1, content: `Hello from BitLogin at ${(/* @__PURE__ */ new Date()).toISOString()}` }); + this.lastSignedEventJson = JSON.stringify(e, null, 2), this.render(); + } + async handleRevealNsec() { + const { nsec: e } = await this.worker.exportIdentity(); + this.exportedNsec = e, this.render(); + } + render() { + const e = this.pendingSuccessLabel ? this.renderSuccessOverlay(this.pendingSuccessLabel) : ""; + this.root.innerHTML = `
${this.renderScreen()}${e}
`; + } + renderSuccessOverlay(e) { + return ` +
+ + + +

${i(e)}

+
+ `; + } + /** + * Navigates to `screen` and briefly stamps it with the same brass-ring-and-checkmark mark + * used in the logo, for the handful of moments that are a genuine security-relevant success + * -- signing in, creating an account, recovering one, or rotating a password -- rather than + * every validation step or navigation. Purely decorative: `pointer-events: none` (see + * styles.ts) means it never blocks interacting with the screen underneath, and a JS timer + * (not just the CSS animation) guarantees it's removed even if the animation can't run. + */ + flashSuccess(e, t) { + this.goto(e), this.successDismissTimer !== null && clearTimeout(this.successDismissTimer), this.pendingSuccessLabel = t, this.render(), this.successDismissTimer = setTimeout(() => { + this.pendingSuccessLabel = null, this.successDismissTimer = null, this.root.querySelector("[data-success-overlay]")?.remove(); + }, 1100); + } + renderError() { + return this.errorMessage ? `
${i(this.errorMessage)}
` : ""; + } + renderWarnings() { + return this.sessionWarnings.map((e) => `
${i(e)}
`).join(""); + } + /** The widget's own brand lockup (mark + wordmark), inlined as vector paths rather than + * relying on the host page having loaded any particular font -- shown once, on the + * welcome screen, as the widget's one branding moment. */ + renderBrandLockup() { + return ' '; + } + renderScreen() { + switch (this.screen) { + case "welcome": + return ` + ${this.renderBrandLockup()} +

A portable Nostr identity with a familiar login name and password.

+ ${this.renderError()} + + + + + `; + case "import-key": { + const e = !!this.importPreviewNpub; + return ` +

Import an existing Nostr key

+

Wrap a Nostr identity you already control in a BitLogin login name and password. Your key never changes — you just get a friendlier way in.

+
Pasting a private key into any web page is risky. Only do this on a BitLogin build you trust, and clear your clipboard afterward. BitLogin can't secure copies of this key that already exist elsewhere.
+ ${this.renderError()} +
+ + + +
+ ${e ? `
This key's public identity:
+
${i(this.importPreviewNpub)}
+ ` : ""} + + `; + } + case "create-name": + return ` +

${this.importKey ? "Set up your login" : "Create your BitLogin"}

+

${this.importKey ? "Choose a login name for your imported identity. It's a convenience, not a secret." : "Choose a login name. It's a convenience, not a secret (it contributes no security)."}

+ ${this.renderError()} +
+ + + +
+ + `; + case "create-credential": { + const e = this.busy ? `${this.importKey ? "Importing…" : "Creating account…"}` : this.importKey ? "Import account" : "Create account"; + return this.manualPasswordMode ? ` +

Choose your own password

+

Not recommended: a downloadable encrypted file can be guessed against forever, offline, with no rate limit. BitLogin can only run basic checks here — not a breach-database lookup — so weak or reused passwords are still your risk to carry.

+
Offline guessing against this password can never be fully prevented. The generated passphrase remains the safer default.
+ ${this.renderError()} +
+ ${this.renderManualPasswordFields()} + + +
+ + ` : ` +

Your generated password

+

BitLogin generates your password because no server can rate-limit guesses against a downloadable encrypted file.

+
${i(this.generatedCredential)}
+ + + ${this.renderError()} +
+ + + +
+ + `; + } + case "confirm-phrase": + return ` +

Save your recovery phrase

+

These 12 words can recover your identity if you forget your password or lose all your devices. We cannot recover these words for you.

+

Do not enter a Bitcoin or other cryptocurrency-wallet recovery phrase into BitLogin. This is a BitLogin-only phrase.

+
+ ${this.recoveryPhrase.split(" ").map((e, t) => `
${t + 1}.${i(e)}
`).join("")} +
+ ${this.renderError()} + + `; + case "verify-phrase": + return ` +

Verify your recovery phrase

+

Your phrase is hidden now so you can confirm you actually saved it. Enter the requested words below.

+ ${this.renderError()} +
+ ${this.confirmSlots.map( + (e) => ` + + + ` + ).join("")} + +
+ + `; + case "login": + return ` +

Sign in

+ ${this.renderError()} +
+ + + + + +
+ + + `; + case "recover-phrase": + return ` +

Recover with phrase

+

Enter your 12-word BitLogin recovery phrase.

+

Do not enter a Bitcoin or other cryptocurrency-wallet recovery phrase into BitLogin.

+ ${this.renderError()} +
+ + + + +

Only needed if relays are unreachable -- the phrase above is still required either way. The file alone can never recover an account by itself.

+ ${this.offlineExportFileNotice ? `
${i(this.offlineExportFileNotice)}
` : ""} + +
+ + `; + case "recover-new-credentials": { + const e = this.recoveredPreview?.chainWarning ? `
${i(this.recoveredPreview.chainWarning)}
` : "", t = this.busy ? 'Finishing recovery…' : "Finish recovery"; + return ` +

Identity recovered

+

Found your account. Restored ${this.recoveredPreview?.generalRelaysCount ?? 0} general relay(s) and ${this.recoveredPreview?.dmRelaysCount ?? 0} DM relay(s) from your public events.

+ ${e} +

Now set a new login name and password.

+ ${this.manualPasswordMode ? '
Offline guessing against this password can never be fully prevented. The generated passphrase remains the safer default.
' : `
${i(this.newCredentialAfterRecovery)}
`} + ${this.renderError()} +
+ + + ${this.manualPasswordMode ? this.renderManualPasswordFields() : ""} + +
+ + `; + } + case "dashboard": + return ` +

Signed in

+ ${this.renderWarnings()} +

${this.session?.npub ?? ""}

+ ${this.renderError()} + + ${this.lastSignedEventJson ? `
${i(this.lastSignedEventJson)}
` : ""} +
+ + + + `; + case "rollback-confirm": + return ` +

This looks like a stale or revoked credential

+
${i(this.rollbackMessage)}
+

This usually means the password just entered was rotated away in an earlier session on this device, and a relay hasn't caught up with that change. If you rotated your password, use the new one instead. Only continue if you're confident this is relay lag, not a stale credential.

+ + + + `; + case "change-password": + return ` +

Rotate password

+

Your old password's capsule will be tombstoned and a deletion request issued. This does not erase copies an attacker may already have downloaded, and a relay that hasn't processed the deletion may keep serving the old password's capsule until a device that has already seen the new generation refuses it.

+ ${this.manualPasswordMode ? '
Offline guessing against this password can never be fully prevented. The generated passphrase remains the safer default.
' : `
${i(this.changePasswordNewCredential)}
`} + ${this.renderError()} +
+ + + ${this.manualPasswordMode ? this.renderManualPasswordFields() : ""} + +
+ + + `; + case "export": + return ` +

Export identity

+

Your public identity (npub) is safe to share. Your private key (nsec) is not.

+ +
${i(this.session?.npub ?? "")}
+ + ${this.renderError()} + + ${this.exportedNsec ? `
Never share this. Anyone with it controls your identity.
${i( + this.exportedNsec + )}
` : ""} + + `; + default: + return ""; + } + } +} +function T(a, e) { + const t = Array.from({ length: a }, (r, o) => o), s = []; + for (let r = 0; r < e && t.length > 0; r++) { + const o = Math.floor(Math.random() * t.length); + s.push(t.splice(o, 1)[0]); + } + return s.sort((r, o) => r - o); +} +function i(a) { + return a.replace(/[&<>"']/gu, (e) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[e]); +} +customElements.get("bitlogin-auth") || customElements.define("bitlogin-auth", F); +window.bitlogin = { + version: "0.1.0", + isActiveSigner() { + return window.nostr?._bitlogin === !0; + }, + releaseSigner() { + const a = window; + return a.nostr?._bitlogin === !0 ? (delete a.nostr, window.dispatchEvent(new CustomEvent("bitlogin-signer-released")), !0) : !1; + } +}; +export { + F as BitLoginAuthElement, + E as WorkerClient, + $ as createNip07Provider +}; diff --git a/vendor/bitlogin/cryptoWorker.js b/vendor/bitlogin/cryptoWorker.js new file mode 100644 index 00000000..5895b0af --- /dev/null +++ b/vendor/bitlogin/cryptoWorker.js @@ -0,0 +1,3446 @@ +import { v as ee, g as E, s as W, c as Ot, K as Dt, b as Je, d as Ce, f as Le, h as ae, u as ye, j as qt, k as zt, l as X, m as ne, n as Ye, S as Ne, o as Te, q as we, D as ie, t as be, w as jt, x as $t, y as Gt, z as Vt, A as _e, B as ze, C as Qe, F as Bt, G as Wt, H as Ht, I as he, J as Xe, L as Ft, M as Jt, N as Ze, O as ke, P as ce, Q as Yt, T as et, U as Qt, V as Xt, W as Zt, X as er, Y as tt, Z as Ie, _ as tr, $ as rr, a0 as nr, a1 as or, a2 as ar, a as je, a3 as ir } from "./bitlogin-shared-QIBe5Omw.js"; +class oe extends Error { + reason; + constructor(t) { + super("Account not found or credentials incorrect."), this.name = "AccountNotFoundError", this.reason = t; + } +} +class Z extends Error { + constructor(t) { + super(t), this.name = "RegistrationFailedError"; + } +} +class rt extends Error { + constructor(t = "An account already exists with this login name and password. Sign in instead, or choose different credentials.") { + super(t), this.name = "AccountAlreadyExistsError"; + } +} +class nt extends Error { + constructor(t) { + super(t), this.name = "RecoveryFailedError"; + } +} +class ot extends Error { + seenGeneration; + capsuleGeneration; + constructor(t, r) { + super(`This credential capsule reports generation ${r}, but this device has already seen generation ${t}. Refusing to log in with older, possibly-revoked credentials.`), this.name = "RollbackDetectedError", this.seenGeneration = t, this.capsuleGeneration = r; + } +} +function at(e, t) { + const r = t ?? Math.floor(Date.now() / 1e3); + return e == null ? r : Math.max(r, e + 1); +} +const sr = { generation: -1, recoveryGeneration: -1 }; +function it(e) { + return `bitlogin:hwm:${e}`; +} +async function Se(e, t) { + const r = await e.get(it(t)); + return r ? JSON.parse(r) : sr; +} +async function st(e, t, r) { + const n = await Se(e, t), o = { + generation: Math.max(n.generation, r.generation ?? -1), + recoveryGeneration: Math.max(n.recoveryGeneration, r.recoveryGeneration ?? -1) + }; + return await e.set(it(t), JSON.stringify(o)), o; +} +function cr() { + const e = globalThis.WebSocket; + if (!e) + throw new Error("No global WebSocket implementation is available in this environment."); + return e; +} +class lr { + url; + ws = null; + connectPromise = null; + subs = /* @__PURE__ */ new Map(); + pendingPublishes = /* @__PURE__ */ new Map(); + authPrivateKey; + connectTimeoutMs; + authenticated = !1; + constructor(t, r = {}) { + this.url = t, this.authPrivateKey = r.authPrivateKey, this.connectTimeoutMs = r.connectTimeoutMs ?? 8e3; + } + async connect() { + return this.connectPromise ? this.connectPromise : (this.connectPromise = new Promise((t, r) => { + const n = cr(), o = new n(this.url); + this.ws = o; + const a = setTimeout(() => { + r(new Error(`Timed out connecting to relay ${this.url}`)); + }, this.connectTimeoutMs); + o.addEventListener("open", () => { + clearTimeout(a), t(); + }), o.addEventListener("error", () => { + clearTimeout(a), r(new Error(`WebSocket error connecting to relay ${this.url}`)); + }), o.addEventListener("close", () => { + this.connectPromise = null; + }), o.addEventListener("message", (i) => { + this.handleMessage(String(i.data)); + }); + }), this.connectPromise); + } + close() { + this.ws?.close(), this.ws = null, this.connectPromise = null, this.subs.clear(), this.pendingPublishes.clear(); + } + send(t) { + if (!this.ws) + throw new Error("Not connected to relay."); + this.ws.send(JSON.stringify(t)); + } + handleMessage(t) { + let r; + try { + r = JSON.parse(t); + } catch { + return; + } + if (!Array.isArray(r) || typeof r[0] != "string") + return; + const [n, ...o] = r; + if (n === "EVENT") { + const [a, i] = o, s = this.subs.get(a); + s && ee(i) && s.events.push(i); + return; + } + if (n === "EOSE") { + const [a] = o; + this.subs.get(a)?.onEose(); + return; + } + if (n === "OK") { + const [a, i, s] = o; + this.pendingPublishes.get(a)?.({ ok: i, message: s ?? "" }), this.pendingPublishes.delete(a); + return; + } + if (n === "AUTH") { + const [a] = o; + this.respondToAuthChallenge(a); + return; + } + } + async respondToAuthChallenge(t) { + if (!this.authPrivateKey) + return; + const r = E(this.authPrivateKey), n = W({ + pubkey: r, + created_at: Math.floor(Date.now() / 1e3), + kind: Dt, + tags: [ + ["relay", this.url], + ["challenge", t] + ], + content: "" + }, this.authPrivateKey); + this.authenticated = !0, this.send(["AUTH", n]); + } + isAuthenticated() { + return this.authenticated; + } + async publish(t, r = 8e3) { + return await this.connect(), new Promise((n) => { + const o = setTimeout(() => { + this.pendingPublishes.delete(t.id), n({ ok: !1, message: "timeout: no OK received from relay" }); + }, r); + this.pendingPublishes.set(t.id, (a) => { + clearTimeout(o), n(a); + }), this.send(["EVENT", t]); + }); + } + async queryOnce(t, r = 8e3) { + await this.connect(); + const n = Ot({ + pubkey: "0".repeat(64), + created_at: Date.now(), + kind: 0, + tags: [], + content: JSON.stringify(t) + Math.random() + }).slice(0, 16); + return new Promise((o) => { + const a = [], i = () => { + clearTimeout(s), this.subs.delete(n), this.send(["CLOSE", n]), o(a); + }, s = setTimeout(i, r); + this.subs.set(n, { events: a, onEose: i }), this.send(["REQ", n, t]); + }); + } +} +class C { + connections = /* @__PURE__ */ new Map(); + constructor(t, r = {}) { + for (const n of new Set(t)) + this.connections.set(n, new lr(n, r)); + } + get relayUrls() { + return [...this.connections.keys()]; + } + /** Queries every configured relay and waits for a quorum of responses (or all timeouts) before returning (§16.2). */ + async queryQuorum(t, r = 8e3) { + const n = [...this.connections.entries()], o = await Promise.all(n.map(async ([s, c]) => { + try { + const d = await c.queryOnce(t, r); + return { relayUrl: s, events: d, responded: !0 }; + } catch (d) { + return { relayUrl: s, events: [], responded: !1, error: d.message }; + } + })), a = o.filter((s) => s.responded).length, i = o.length; + return { + outcomes: o, + quorumMet: a >= Math.ceil(i / 2), + respondedCount: a, + totalCount: i + }; + } + /** Publishes an event to every configured relay, best-effort (§15.6, §24.4). */ + async publishAll(t, r = 8e3) { + const n = [...this.connections.entries()]; + return Promise.all(n.map(async ([o, a]) => { + try { + const i = await a.publish(t, r); + return { relayUrl: o, result: i }; + } catch (i) { + return { relayUrl: o, result: { ok: !1, message: i.message } }; + } + })); + } + closeAll() { + for (const t of this.connections.values()) + t.close(); + } +} +function F(e) { + return e.filter((t) => t.result.ok).length; +} +function ur(e, t, r) { + return W({ pubkey: E(e), created_at: r, kind: Je, tags: [], content: JSON.stringify(t) }, e); +} +function dr(e, t, r) { + const n = t.map((o) => { + const a = ["r", o.url]; + return o.read && !o.write && a.push("read"), o.write && !o.read && a.push("write"), a; + }); + return W({ pubkey: E(e), created_at: r, kind: Ce, tags: n, content: "" }, e); +} +function yr(e, t, r) { + return W({ + pubkey: E(e), + created_at: r, + kind: Le, + tags: t.map((n) => ["relay", n]), + content: "" + }, e); +} +function hr(e) { + return e.tags.filter((t) => t[0] === "r" && t[1]).map((t) => t[1]); +} +function pr(e) { + return e.tags.filter((t) => t[0] === "relay" && t[1]).map((t) => t[1]); +} +async function vr(e) { + const t = E(e.everydayPrivateKey), r = Math.floor(Date.now() / 1e3), n = [.../* @__PURE__ */ new Set([...e.generalRelays, ...e.dmRelays, ...e.discoveryRelays])], o = new C(n), [a, i, s] = await Promise.all([ + o.queryQuorum({ authors: [t], kinds: [Je] }), + o.queryQuorum({ authors: [t], kinds: [Ce] }), + o.queryQuorum({ authors: [t], kinds: [Le] }) + ]); + o.closeAll(); + const c = a.outcomes.some((u) => u.events.length > 0), d = i.outcomes.some((u) => u.events.length > 0), h = s.outcomes.some((u) => u.events.length > 0), m = new C(n); + let p = null, g = null, v = null; + const f = []; + if (!c && (e.name || e.about || e.picture)) { + const u = ur(e.everydayPrivateKey, { name: e.name, about: e.about, picture: e.picture }, r); + f.push(m.publishAll(u).then((y) => void (p = y))); + } + if (!d) { + const u = dr(e.everydayPrivateKey, e.generalRelays.map((y) => ({ url: y, read: !0, write: !0 })), r); + f.push(m.publishAll(u).then((y) => void (g = y))); + } + if (!h) { + const u = yr(e.everydayPrivateKey, e.dmRelays, r); + f.push(m.publishAll(u).then((y) => void (v = y))); + } + return await Promise.all(f), m.closeAll(), { + profilePublished: p !== null && F(p) > 0, + relayListAcknowledgedCount: g !== null ? F(g) : 0, + dmRelayListAcknowledgedCount: v !== null ? F(v) : 0, + profileSkippedExisting: c, + relayListSkippedExisting: d, + dmRelayListSkippedExisting: h + }; +} +async function le(e, t, r) { + const n = r.minAcks ?? 2, o = r.minReadbacks ?? 2, a = await e.publishAll(t, r.timeoutMs), i = F(a), c = (await e.queryQuorum({ kinds: [ae], authors: [t.pubkey], "#d": [r.dTag], limit: 5 }, r.timeoutMs)).outcomes.filter((d) => d.events.some((h) => h.id === t.id)).length; + return { + acknowledgedCount: i, + readbackVerifiedCount: c, + success: i >= n && c >= o + }; +} +function gr(e) { + const t = qt(e); + if (t === void 0) + throw new Error("Value is not JSON-serializable for canonicalization."); + return t; +} +function fr(e) { + return ye(gr(e)); +} +const ve = [1024, 2048, 4096], Y = 4; +function mr(e) { + const t = Y + e.length, r = ve.find((a) => a >= t); + if (r === void 0) + throw new Error(`Payload of ${e.length} bytes exceeds the largest padding bucket (${ve[ve.length - 1]} bytes minus ${Y}-byte length prefix).`); + const n = new Uint8Array(r); + return new DataView(n.buffer).setUint32(0, e.length, !1), n.set(e, Y), n; +} +function wr(e) { + if (!ve.includes(e.length)) + throw new Error(`Padded plaintext length ${e.length} does not match a known bucket.`); + const r = new DataView(e.buffer, e.byteOffset, e.byteLength).getUint32(0, !1); + if (r > e.length - Y) + throw new Error("Declared payload length exceeds the padded bucket size."); + const n = e.slice(Y, Y + r), o = e.slice(Y + r); + for (const a of o) + if (a !== 0) + throw new Error("Padding bytes are not all zero; capsule plaintext is malformed."); + return n; +} +function Me() { + const e = globalThis.crypto; + if (!e || !e.subtle) + throw new Error("WebCrypto SubtleCrypto is not available in this environment."); + return e; +} +async function ct(e) { + if (e.length !== 32) + throw new Error("AES-256-GCM key must be exactly 32 bytes."); + return Me().subtle.importKey("raw", e, "AES-GCM", !1, ["encrypt", "decrypt"]); +} +async function br(e, t, r) { + const n = zt(), o = await ct(e), a = await Me().subtle.encrypt({ name: "AES-GCM", iv: n, additionalData: r, tagLength: 128 }, o, t); + return { nonce: n, ciphertext: new Uint8Array(a) }; +} +async function kr(e, t, r, n) { + const o = await ct(e); + try { + const a = await Me().subtle.decrypt({ name: "AES-GCM", iv: t, additionalData: n, tagLength: 128 }, o, r); + return new Uint8Array(a); + } catch { + throw new Error("AES-256-GCM authentication failed: capsule is corrupted, tampered, or the wrong key was used."); + } +} +function lt(e) { + return ye(`bitlogin|password-capsule|v1|${e}|30078|bitlogin:password:v1`); +} +function ut(e) { + return ye(`bitlogin|recovery-capsule|v1|${e}|30078|bitlogin:recovery:v1`); +} +async function dt(e, t, r) { + const n = fr(e), o = mr(n), a = await br(t, o, r); + return { + version: 1, + algorithm: "aes-256-gcm", + nonce: X(a.nonce), + ciphertext: X(a.ciphertext) + }; +} +async function yt(e, t, r) { + if (e.version !== 1 || e.algorithm !== "aes-256-gcm") + throw new Error(`Unsupported capsule envelope version/algorithm: ${e.version}/${e.algorithm}`); + const n = ne(e.nonce), o = ne(e.ciphertext), a = await kr(t, n, o, r), i = wr(a); + return JSON.parse(Ye(i)); +} +class Ue extends Error { + constructor(t) { + super(t), this.name = "CapsuleValidationError"; + } +} +const _r = /* @__PURE__ */ new Set(["wss:", "ws:"]), Er = 1e6, Pr = /^[0-9a-f]{64}$/u; +function P(e, t) { + if (!e) + throw new Ue(t); +} +function ge(e) { + return typeof e == "string" && Pr.test(e); +} +function ht(e) { + P(Array.isArray(e), "vault_relay_hints must be an array (§12.4.7)."); + for (const t of e) { + P(typeof t == "string", "Each relay hint must be a string (§12.4.7)."); + let r; + try { + r = new URL(t); + } catch { + throw new Ue(`Invalid relay URL: ${String(t)} (§12.4.7)`); + } + P(_r.has(r.protocol), `Relay URL uses a disallowed scheme: ${t} (§12.4.7)`); + } +} +function pt(e) { + P(typeof e == "string", "account_id must be a string (§12.4.2)."); + let t; + try { + t = ne(e); + } catch { + throw new Ue("account_id is not valid base64url (§12.4.2)."); + } + P(t.length === 16, "account_id must decode to exactly 128 bits (§12.4.2)."); +} +function vt(e, t) { + P(typeof e == "string", "operational_private_key must be a string (§12.4.3)."); + const r = ne(e); + P(r.length === 32, "operational_private_key must be exactly 32 bytes (§12.4.3)."), P(Te(r), "operational_private_key is not a valid secp256k1 scalar (§12.4.3)."), P(ge(t), "operational_public_key must be lowercase 64-char hex (§12.4.4)."); + const n = E(r); + P(n === t, "operational_public_key does not match the derived public key (§12.4.4)."); +} +function gt(e, t) { + P(Number.isInteger(e) && e >= 0 && e <= Er, `${t} is out of supported bounds (§12.4.8).`); +} +function Kr(e) { + P(e.schema === we, `Unsupported or unknown schema: ${String(e.schema)} (§12.4.1)`), pt(e.account_id), gt(e.generation, "generation"), vt(e.operational_private_key, e.operational_public_key), P(ge(e.recovery_public_key), "recovery_public_key must be lowercase 64-char hex (§12.4.5)."), ht(e.vault_relay_hints); + const t = e.recovery_capsule_event; + P(!!t && typeof t == "object", "recovery_capsule_event must be present (§12.4.6)."), P(ee(t), "Embedded recovery_capsule_event has an invalid event id or signature (§12.4.6)."), P(t.pubkey === e.recovery_public_key, "Embedded recovery_capsule_event author does not match recovery_public_key (§12.4.5)."); +} +function Rr(e) { + P(e.schema === Ne, `Unsupported or unknown schema: ${String(e.schema)} (§12.4.1)`), pt(e.account_id), gt(e.recovery_generation, "recovery_generation"), P(e.previous_recovery_event_id === null || ge(e.previous_recovery_event_id), "previous_recovery_event_id must be null or lowercase 64-char hex (§12.3)."), vt(e.operational_private_key, e.operational_public_key), P(ge(e.recovery_public_key), "recovery_public_key must be lowercase 64-char hex."), ht(e.vault_relay_hints); +} +function xr(e) { + const t = new Map(e.map((n) => [n.recoveryGeneration, n])), r = [...e].sort((n, o) => n.recoveryGeneration - o.recoveryGeneration); + for (let n = 1; n < r.length; n++) { + const o = r[n], a = t.get(o.recoveryGeneration - 1); + if (o.previousRecoveryEventId === null) + return { consistent: !1, warning: `Generation ${o.recoveryGeneration} has a null previous-event link but is not the first generation.` }; + if (a && o.previousRecoveryEventId !== a.eventId) + return { + consistent: !1, + warning: `Recovery generation chain is broken between generation ${a.recoveryGeneration} and ${o.recoveryGeneration}: possible replay or relay misbehavior.` + }; + } + return { consistent: !0 }; +} +async function Oe(e) { + const t = E(e.locatorPrivateKey), r = await dt(e.payload, e.capsuleKey, lt(t)); + return W({ + pubkey: t, + created_at: e.payload.created_at, + kind: ae, + tags: [["d", ie]], + content: JSON.stringify(r) + }, e.locatorPrivateKey); +} +function Ar(e) { + const t = E(e.oldLocatorPrivateKey); + return W({ + pubkey: t, + created_at: e.createdAt, + kind: ae, + tags: [["d", ie]], + content: "" + }, e.oldLocatorPrivateKey); +} +async function Cr(e, t) { + if (!ee(e)) + throw new Error("Credential capsule event has an invalid id or signature."); + const r = JSON.parse(e.content), n = await yt(r, t, lt(e.pubkey)); + return Kr(n), n; +} +async function ft(e) { + const t = E(e.recoveryPrivateKey), r = await dt(e.payload, e.capsuleKey, ut(t)); + return W({ + pubkey: t, + created_at: e.payload.created_at, + kind: ae, + tags: [["d", be]], + content: JSON.stringify(r) + }, e.recoveryPrivateKey); +} +async function mt(e, t) { + if (!ee(e)) + throw new Error("Recovery capsule event has an invalid id or signature."); + const r = JSON.parse(e.content), n = await yt(r, t, ut(e.pubkey)); + return Rr(n), n; +} +function Lr(e) { + const t = /* @__PURE__ */ new Map(); + for (const r of e) + ee(r) && t.set(r.id, r); + return [...t.values()].sort((r, n) => n.created_at - r.created_at); +} +async function wt(e, t, r, n, o) { + const a = await e.queryQuorum({ kinds: [ae], authors: [t], "#d": [r], limit: 5 }, o), i = a.outcomes.flatMap((p) => p.events), s = Lr(i), c = []; + for (const p of s) + try { + const g = await n(p); + c.push({ event: p, payload: g }); + } catch (g) { + c.push({ event: p, payload: null, error: g.message }); + } + const d = c.find((p) => p.payload !== null) ?? null, h = a.outcomes.filter((p) => p.responded && p.events.length > 0).map((p) => p.events.slice().sort((g, v) => v.created_at - g.created_at)[0].id), m = new Set(h).size > 1; + return { + quorumMet: a.quorumMet, + respondedCount: a.respondedCount, + totalCount: a.totalCount, + candidates: c, + best: d, + relayDisagreement: m + }; +} +async function fe(e, t, r, n = 8e3) { + return wt(e, t, ie, (o) => Cr(o, r), n); +} +async function Nr(e, t, r, n = 8e3) { + return wt(e, t, be, (o) => mt(o, r), n); +} +function Tr(e) { + const t = e.filter((r) => r.payload !== null); + return t.length < 2 ? { consistent: !0 } : xr(t.map((r) => ({ + eventId: r.event.id, + recoveryGeneration: r.payload.recovery_generation, + previousRecoveryEventId: r.payload.previous_recovery_event_id + }))); +} +async function Ir(e, t, r, n) { + const [o, a] = await Promise.all([ + e.publishAll(t, n), + e.publishAll(r, n) + ]); + return { + credentialAcknowledgedCount: F(o), + recoveryAcknowledgedCount: F(a), + relaysTried: e.relayUrls.length + }; +} +const bt = `abandon +ability +able +about +above +absent +absorb +abstract +absurd +abuse +access +accident +account +accuse +achieve +acid +acoustic +acquire +across +act +action +actor +actress +actual +adapt +add +addict +address +adjust +admit +adult +advance +advice +aerobic +affair +afford +afraid +again +age +agent +agree +ahead +aim +air +airport +aisle +alarm +album +alcohol +alert +alien +all +alley +allow +almost +alone +alpha +already +also +alter +always +amateur +amazing +among +amount +amused +analyst +anchor +ancient +anger +angle +angry +animal +ankle +announce +annual +another +answer +antenna +antique +anxiety +any +apart +apology +appear +apple +approve +april +arch +arctic +area +arena +argue +arm +armed +armor +army +around +arrange +arrest +arrive +arrow +art +artefact +artist +artwork +ask +aspect +assault +asset +assist +assume +asthma +athlete +atom +attack +attend +attitude +attract +auction +audit +august +aunt +author +auto +autumn +average +avocado +avoid +awake +aware +away +awesome +awful +awkward +axis +baby +bachelor +bacon +badge +bag +balance +balcony +ball +bamboo +banana +banner +bar +barely +bargain +barrel +base +basic +basket +battle +beach +bean +beauty +because +become +beef +before +begin +behave +behind +believe +below +belt +bench +benefit +best +betray +better +between +beyond +bicycle +bid +bike +bind +biology +bird +birth +bitter +black +blade +blame +blanket +blast +bleak +bless +blind +blood +blossom +blouse +blue +blur +blush +board +boat +body +boil +bomb +bone +bonus +book +boost +border +boring +borrow +boss +bottom +bounce +box +boy +bracket +brain +brand +brass +brave +bread +breeze +brick +bridge +brief +bright +bring +brisk +broccoli +broken +bronze +broom +brother +brown +brush +bubble +buddy +budget +buffalo +build +bulb +bulk +bullet +bundle +bunker +burden +burger +burst +bus +business +busy +butter +buyer +buzz +cabbage +cabin +cable +cactus +cage +cake +call +calm +camera +camp +can +canal +cancel +candy +cannon +canoe +canvas +canyon +capable +capital +captain +car +carbon +card +cargo +carpet +carry +cart +case +cash +casino +castle +casual +cat +catalog +catch +category +cattle +caught +cause +caution +cave +ceiling +celery +cement +census +century +cereal +certain +chair +chalk +champion +change +chaos +chapter +charge +chase +chat +cheap +check +cheese +chef +cherry +chest +chicken +chief +child +chimney +choice +choose +chronic +chuckle +chunk +churn +cigar +cinnamon +circle +citizen +city +civil +claim +clap +clarify +claw +clay +clean +clerk +clever +click +client +cliff +climb +clinic +clip +clock +clog +close +cloth +cloud +clown +club +clump +cluster +clutch +coach +coast +coconut +code +coffee +coil +coin +collect +color +column +combine +come +comfort +comic +common +company +concert +conduct +confirm +congress +connect +consider +control +convince +cook +cool +copper +copy +coral +core +corn +correct +cost +cotton +couch +country +couple +course +cousin +cover +coyote +crack +cradle +craft +cram +crane +crash +crater +crawl +crazy +cream +credit +creek +crew +cricket +crime +crisp +critic +crop +cross +crouch +crowd +crucial +cruel +cruise +crumble +crunch +crush +cry +crystal +cube +culture +cup +cupboard +curious +current +curtain +curve +cushion +custom +cute +cycle +dad +damage +damp +dance +danger +daring +dash +daughter +dawn +day +deal +debate +debris +decade +december +decide +decline +decorate +decrease +deer +defense +define +defy +degree +delay +deliver +demand +demise +denial +dentist +deny +depart +depend +deposit +depth +deputy +derive +describe +desert +design +desk +despair +destroy +detail +detect +develop +device +devote +diagram +dial +diamond +diary +dice +diesel +diet +differ +digital +dignity +dilemma +dinner +dinosaur +direct +dirt +disagree +discover +disease +dish +dismiss +disorder +display +distance +divert +divide +divorce +dizzy +doctor +document +dog +doll +dolphin +domain +donate +donkey +donor +door +dose +double +dove +draft +dragon +drama +drastic +draw +dream +dress +drift +drill +drink +drip +drive +drop +drum +dry +duck +dumb +dune +during +dust +dutch +duty +dwarf +dynamic +eager +eagle +early +earn +earth +easily +east +easy +echo +ecology +economy +edge +edit +educate +effort +egg +eight +either +elbow +elder +electric +elegant +element +elephant +elevator +elite +else +embark +embody +embrace +emerge +emotion +employ +empower +empty +enable +enact +end +endless +endorse +enemy +energy +enforce +engage +engine +enhance +enjoy +enlist +enough +enrich +enroll +ensure +enter +entire +entry +envelope +episode +equal +equip +era +erase +erode +erosion +error +erupt +escape +essay +essence +estate +eternal +ethics +evidence +evil +evoke +evolve +exact +example +excess +exchange +excite +exclude +excuse +execute +exercise +exhaust +exhibit +exile +exist +exit +exotic +expand +expect +expire +explain +expose +express +extend +extra +eye +eyebrow +fabric +face +faculty +fade +faint +faith +fall +false +fame +family +famous +fan +fancy +fantasy +farm +fashion +fat +fatal +father +fatigue +fault +favorite +feature +february +federal +fee +feed +feel +female +fence +festival +fetch +fever +few +fiber +fiction +field +figure +file +film +filter +final +find +fine +finger +finish +fire +firm +first +fiscal +fish +fit +fitness +fix +flag +flame +flash +flat +flavor +flee +flight +flip +float +flock +floor +flower +fluid +flush +fly +foam +focus +fog +foil +fold +follow +food +foot +force +forest +forget +fork +fortune +forum +forward +fossil +foster +found +fox +fragile +frame +frequent +fresh +friend +fringe +frog +front +frost +frown +frozen +fruit +fuel +fun +funny +furnace +fury +future +gadget +gain +galaxy +gallery +game +gap +garage +garbage +garden +garlic +garment +gas +gasp +gate +gather +gauge +gaze +general +genius +genre +gentle +genuine +gesture +ghost +giant +gift +giggle +ginger +giraffe +girl +give +glad +glance +glare +glass +glide +glimpse +globe +gloom +glory +glove +glow +glue +goat +goddess +gold +good +goose +gorilla +gospel +gossip +govern +gown +grab +grace +grain +grant +grape +grass +gravity +great +green +grid +grief +grit +grocery +group +grow +grunt +guard +guess +guide +guilt +guitar +gun +gym +habit +hair +half +hammer +hamster +hand +happy +harbor +hard +harsh +harvest +hat +have +hawk +hazard +head +health +heart +heavy +hedgehog +height +hello +helmet +help +hen +hero +hidden +high +hill +hint +hip +hire +history +hobby +hockey +hold +hole +holiday +hollow +home +honey +hood +hope +horn +horror +horse +hospital +host +hotel +hour +hover +hub +huge +human +humble +humor +hundred +hungry +hunt +hurdle +hurry +hurt +husband +hybrid +ice +icon +idea +identify +idle +ignore +ill +illegal +illness +image +imitate +immense +immune +impact +impose +improve +impulse +inch +include +income +increase +index +indicate +indoor +industry +infant +inflict +inform +inhale +inherit +initial +inject +injury +inmate +inner +innocent +input +inquiry +insane +insect +inside +inspire +install +intact +interest +into +invest +invite +involve +iron +island +isolate +issue +item +ivory +jacket +jaguar +jar +jazz +jealous +jeans +jelly +jewel +job +join +joke +journey +joy +judge +juice +jump +jungle +junior +junk +just +kangaroo +keen +keep +ketchup +key +kick +kid +kidney +kind +kingdom +kiss +kit +kitchen +kite +kitten +kiwi +knee +knife +knock +know +lab +label +labor +ladder +lady +lake +lamp +language +laptop +large +later +latin +laugh +laundry +lava +law +lawn +lawsuit +layer +lazy +leader +leaf +learn +leave +lecture +left +leg +legal +legend +leisure +lemon +lend +length +lens +leopard +lesson +letter +level +liar +liberty +library +license +life +lift +light +like +limb +limit +link +lion +liquid +list +little +live +lizard +load +loan +lobster +local +lock +logic +lonely +long +loop +lottery +loud +lounge +love +loyal +lucky +luggage +lumber +lunar +lunch +luxury +lyrics +machine +mad +magic +magnet +maid +mail +main +major +make +mammal +man +manage +mandate +mango +mansion +manual +maple +marble +march +margin +marine +market +marriage +mask +mass +master +match +material +math +matrix +matter +maximum +maze +meadow +mean +measure +meat +mechanic +medal +media +melody +melt +member +memory +mention +menu +mercy +merge +merit +merry +mesh +message +metal +method +middle +midnight +milk +million +mimic +mind +minimum +minor +minute +miracle +mirror +misery +miss +mistake +mix +mixed +mixture +mobile +model +modify +mom +moment +monitor +monkey +monster +month +moon +moral +more +morning +mosquito +mother +motion +motor +mountain +mouse +move +movie +much +muffin +mule +multiply +muscle +museum +mushroom +music +must +mutual +myself +mystery +myth +naive +name +napkin +narrow +nasty +nation +nature +near +neck +need +negative +neglect +neither +nephew +nerve +nest +net +network +neutral +never +news +next +nice +night +noble +noise +nominee +noodle +normal +north +nose +notable +note +nothing +notice +novel +now +nuclear +number +nurse +nut +oak +obey +object +oblige +obscure +observe +obtain +obvious +occur +ocean +october +odor +off +offer +office +often +oil +okay +old +olive +olympic +omit +once +one +onion +online +only +open +opera +opinion +oppose +option +orange +orbit +orchard +order +ordinary +organ +orient +original +orphan +ostrich +other +outdoor +outer +output +outside +oval +oven +over +own +owner +oxygen +oyster +ozone +pact +paddle +page +pair +palace +palm +panda +panel +panic +panther +paper +parade +parent +park +parrot +party +pass +patch +path +patient +patrol +pattern +pause +pave +payment +peace +peanut +pear +peasant +pelican +pen +penalty +pencil +people +pepper +perfect +permit +person +pet +phone +photo +phrase +physical +piano +picnic +picture +piece +pig +pigeon +pill +pilot +pink +pioneer +pipe +pistol +pitch +pizza +place +planet +plastic +plate +play +please +pledge +pluck +plug +plunge +poem +poet +point +polar +pole +police +pond +pony +pool +popular +portion +position +possible +post +potato +pottery +poverty +powder +power +practice +praise +predict +prefer +prepare +present +pretty +prevent +price +pride +primary +print +priority +prison +private +prize +problem +process +produce +profit +program +project +promote +proof +property +prosper +protect +proud +provide +public +pudding +pull +pulp +pulse +pumpkin +punch +pupil +puppy +purchase +purity +purpose +purse +push +put +puzzle +pyramid +quality +quantum +quarter +question +quick +quit +quiz +quote +rabbit +raccoon +race +rack +radar +radio +rail +rain +raise +rally +ramp +ranch +random +range +rapid +rare +rate +rather +raven +raw +razor +ready +real +reason +rebel +rebuild +recall +receive +recipe +record +recycle +reduce +reflect +reform +refuse +region +regret +regular +reject +relax +release +relief +rely +remain +remember +remind +remove +render +renew +rent +reopen +repair +repeat +replace +report +require +rescue +resemble +resist +resource +response +result +retire +retreat +return +reunion +reveal +review +reward +rhythm +rib +ribbon +rice +rich +ride +ridge +rifle +right +rigid +ring +riot +ripple +risk +ritual +rival +river +road +roast +robot +robust +rocket +romance +roof +rookie +room +rose +rotate +rough +round +route +royal +rubber +rude +rug +rule +run +runway +rural +sad +saddle +sadness +safe +sail +salad +salmon +salon +salt +salute +same +sample +sand +satisfy +satoshi +sauce +sausage +save +say +scale +scan +scare +scatter +scene +scheme +school +science +scissors +scorpion +scout +scrap +screen +script +scrub +sea +search +season +seat +second +secret +section +security +seed +seek +segment +select +sell +seminar +senior +sense +sentence +series +service +session +settle +setup +seven +shadow +shaft +shallow +share +shed +shell +sheriff +shield +shift +shine +ship +shiver +shock +shoe +shoot +shop +short +shoulder +shove +shrimp +shrug +shuffle +shy +sibling +sick +side +siege +sight +sign +silent +silk +silly +silver +similar +simple +since +sing +siren +sister +situate +six +size +skate +sketch +ski +skill +skin +skirt +skull +slab +slam +sleep +slender +slice +slide +slight +slim +slogan +slot +slow +slush +small +smart +smile +smoke +smooth +snack +snake +snap +sniff +snow +soap +soccer +social +sock +soda +soft +solar +soldier +solid +solution +solve +someone +song +soon +sorry +sort +soul +sound +soup +source +south +space +spare +spatial +spawn +speak +special +speed +spell +spend +sphere +spice +spider +spike +spin +spirit +split +spoil +sponsor +spoon +sport +spot +spray +spread +spring +spy +square +squeeze +squirrel +stable +stadium +staff +stage +stairs +stamp +stand +start +state +stay +steak +steel +stem +step +stereo +stick +still +sting +stock +stomach +stone +stool +story +stove +strategy +street +strike +strong +struggle +student +stuff +stumble +style +subject +submit +subway +success +such +sudden +suffer +sugar +suggest +suit +summer +sun +sunny +sunset +super +supply +supreme +sure +surface +surge +surprise +surround +survey +suspect +sustain +swallow +swamp +swap +swarm +swear +sweet +swift +swim +swing +switch +sword +symbol +symptom +syrup +system +table +tackle +tag +tail +talent +talk +tank +tape +target +task +taste +tattoo +taxi +teach +team +tell +ten +tenant +tennis +tent +term +test +text +thank +that +theme +then +theory +there +they +thing +this +thought +three +thrive +throw +thumb +thunder +ticket +tide +tiger +tilt +timber +time +tiny +tip +tired +tissue +title +toast +tobacco +today +toddler +toe +together +toilet +token +tomato +tomorrow +tone +tongue +tonight +tool +tooth +top +topic +topple +torch +tornado +tortoise +toss +total +tourist +toward +tower +town +toy +track +trade +traffic +tragic +train +transfer +trap +trash +travel +tray +treat +tree +trend +trial +tribe +trick +trigger +trim +trip +trophy +trouble +truck +true +truly +trumpet +trust +truth +try +tube +tuition +tumble +tuna +tunnel +turkey +turn +turtle +twelve +twenty +twice +twin +twist +two +type +typical +ugly +umbrella +unable +unaware +uncle +uncover +under +undo +unfair +unfold +unhappy +uniform +unique +unit +universe +unknown +unlock +until +unusual +unveil +update +upgrade +uphold +upon +upper +upset +urban +urge +usage +use +used +useful +useless +usual +utility +vacant +vacuum +vague +valid +valley +valve +van +vanish +vapor +various +vast +vault +vehicle +velvet +vendor +venture +venue +verb +verify +version +very +vessel +veteran +viable +vibrant +vicious +victory +video +view +village +vintage +violin +virtual +virus +visa +visit +visual +vital +vivid +vocal +voice +void +volcano +volume +vote +voyage +wage +wagon +wait +walk +wall +walnut +want +warfare +warm +warrior +wash +wasp +waste +water +wave +way +wealth +weapon +wear +weasel +weather +web +wedding +weekend +weird +welcome +west +wet +whale +what +wheat +wheel +when +where +whip +whisper +wide +width +wife +wild +will +win +window +wine +wing +wink +winner +winter +wire +wisdom +wise +wish +witness +wolf +woman +wonder +wood +wool +word +work +world +worry +worth +wrap +wreck +wrestle +wrist +write +wrong +yard +year +yellow +you +young +youth +zebra +zero +zone +zoo`.split(` +`); +function Sr(e, t, r, n) { + Gt(e); + const o = Vt({ dkLen: 32, asyncTick: 10 }, n), { c: a, dkLen: i, asyncTick: s } = o; + if (_e(a), _e(i), _e(s), a < 1) + throw new Error("iterations (c) should be >= 1"); + const c = ze(t), d = ze(r), h = new Uint8Array(i), m = Qe.create(e, c), p = m._cloneInto().update(d); + return { c: a, dkLen: i, asyncTick: s, DK: h, PRF: m, PRFSalt: p }; +} +function Mr(e, t, r, n, o) { + return e.destroy(), t.destroy(), n && n.destroy(), Bt(o), r; +} +async function Ur(e, t, r, n) { + const { c: o, dkLen: a, asyncTick: i, DK: s, PRF: c, PRFSalt: d } = Sr(e, t, r, n); + let h; + const m = new Uint8Array(4), p = jt(m), g = new Uint8Array(c.outputLen); + for (let v = 1, f = 0; f < a; v++, f += c.outputLen) { + const u = s.subarray(f, f + c.outputLen); + p.setInt32(0, v, !1), (h = d._cloneInto(h)).update(m).digestInto(g), u.set(g.subarray(0, u.length)), await $t(o - 1, i, () => { + c._cloneInto(h).update(g).digestInto(g); + for (let y = 0; y < u.length; y++) + u[y] ^= g[y]; + }); + } + return Mr(c, d, s, h, g); +} +/*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) */ +const Or = (e) => e[0] === "あいこくしん"; +function kt(e) { + if (typeof e != "string") + throw new TypeError("invalid mnemonic type: " + typeof e); + return e.normalize("NFKD"); +} +function _t(e) { + const t = kt(e), r = t.split(" "); + if (![12, 15, 18, 21, 24].includes(r.length)) + throw new Error("Invalid mnemonic"); + return { nfkd: t, words: r }; +} +function Et(e) { + Ht(e, 16, 20, 24, 28, 32); +} +const Dr = (e) => { + const t = 8 - e.length / 4; + return new Uint8Array([Xe(e)[0] >> t << t]); +}; +function Pt(e) { + if (!Array.isArray(e) || e.length !== 2048 || typeof e[0] != "string") + throw new Error("Wordlist: expected array of 2048 strings"); + return e.forEach((t) => { + if (typeof t != "string") + throw new Error("wordlist: non-string element: " + t); + }), he.chain(he.checksum(1, Dr), he.radix2(11, !0), he.alphabet(e)); +} +function qr(e, t) { + const { words: r } = _t(e), n = Pt(t).decode(r); + return Et(n), n; +} +function zr(e, t) { + return Et(e), Pt(t).encode(e).join(Or(t) ? " " : " "); +} +function jr(e, t) { + try { + qr(e, t); + } catch { + return !1; + } + return !0; +} +const $r = (e) => kt("mnemonic" + e); +function Gr(e, t = "") { + return Ur(Wt, _t(e).nfkd, $r(t), { c: 2048, dkLen: 64 }); +} +function Vr(e) { + if (e.length !== 16) + throw new Error("Recovery phrase entropy must be exactly 128 bits (16 bytes)."); + return zr(e, bt); +} +function Br(e) { + try { + return jr(Kt(e), bt); + } catch { + return !1; + } +} +function Kt(e) { + return e.trim().normalize("NFKD").split(/\s+/u).join(" "); +} +async function Rt(e) { + return Gr(Kt(e), ""); +} +const De = Ft.id, ue = "aes-256-gcm-v1", de = "bitlogin-bip39-hkdf-v1"; +async function xt(e) { + const t = ke(e.loginName), r = e.now ?? Math.floor(Date.now() / 1e3), { locatorPrivateKey: n, capsuleKey: o } = await ce(e.password, t), a = E(n), i = new C(e.vaultRelayUrls, { authPrivateKey: n }); + let s; + try { + s = await fe(i, a, o, e.timeoutMs); + } finally { + i.closeAll(); + } + if (!s.quorumMet) + throw new Z("Couldn't verify this login name and password aren't already registered. Please retry, or add more vault relays."); + if (s.candidates.length > 0) + throw new rt(); + const c = Vr(Yt()), d = await Rt(c), { recoveryPrivateKey: h, capsuleKey: m } = et(d), p = E(h), g = e.everydayPrivateKey !== void 0; + if (g && !Te(e.everydayPrivateKey)) + throw new Z("The provided key is not a valid secp256k1 private key."); + const v = g ? e.everydayPrivateKey : Qt(), f = E(v), u = X(Xt()), y = { + schema: Ne, + account_id: u, + recovery_generation: 0, + previous_recovery_event_id: null, + operational_private_key: X(v), + operational_public_key: f, + recovery_public_key: p, + created_at: r, + vault_relay_hints: e.vaultRelayUrls, + protocol: { capsule_encryption: ue, recovery_derivation: de } + }, k = await ft({ + recoveryPrivateKey: h, + capsuleKey: m, + payload: y + }), b = { + schema: we, + account_id: u, + generation: 0, + operational_private_key: X(v), + operational_public_key: f, + recovery_public_key: p, + recovery_capsule_event: k, + created_at: r, + vault_relay_hints: e.vaultRelayUrls, + protocol: { + password_kdf: De, + capsule_encryption: ue, + recovery_derivation: de + } + }, K = await Oe({ + locatorPrivateKey: n, + capsuleKey: o, + payload: b + }), G = new C(e.vaultRelayUrls, { authPrivateKey: h }), _ = await le(G, k, { + dTag: be, + minAcks: e.minAcknowledgements, + timeoutMs: e.timeoutMs + }); + G.closeAll(); + const R = new C(e.vaultRelayUrls, { authPrivateKey: n }), x = await le(R, K, { + dTag: ie, + minAcks: e.minAcknowledgements, + timeoutMs: e.timeoutMs + }); + if (R.closeAll(), !_.success || !x.success) + throw new Z("Registration did not reach the required relay acknowledgement and readback quorum. Please retry, or add more vault relays."); + return { + normalizedLoginName: t, + recoveryPhrase: c, + everydayPrivateKey: v, + everydayPublicKey: f, + recoveryPublicKey: p, + locatorPublicKey: a, + accountId: u, + imported: g, + credentialEvent: K, + recoveryEvent: k, + credentialPublish: x, + recoveryPublish: _ + }; +} +async function Wr(e) { + const { nsecOrHex: t, ...r } = e, n = At(t); + return xt({ ...r, everydayPrivateKey: n }); +} +function At(e) { + const t = e.trim(); + let r; + if (t.startsWith("nsec1")) + r = Jt(t); + else if (/^[0-9a-fA-F]{64}$/u.test(t)) + r = Ze(t.toLowerCase()); + else + throw new Z("Enter a valid nsec (nsec1…) or a 64-character hex private key."); + if (!Te(r)) + throw new Z("The provided key is not a valid secp256k1 private key."); + return r; +} +class Ct { + map = /* @__PURE__ */ new Map(); + async get(t) { + return this.map.get(t); + } + async set(t, r) { + this.map.set(t, r); + } + async delete(t) { + this.map.delete(t); + } +} +async function Hr(e) { + const t = ke(e.loginName), { locatorPrivateKey: r, capsuleKey: n } = await ce(e.password, t), o = E(r), a = new C(e.vaultRelayUrls, { authPrivateKey: r }); + try { + const i = await fe(a, o, n, e.timeoutMs); + if (!i.quorumMet) + throw new oe("quorum-not-met"); + if (!i.best) + throw new oe(i.candidates.length > 0 ? "no-valid-candidate" : "no-matching-event"); + const s = i.best.payload, c = e.store ?? new Ct(), d = await Se(c, s.operational_public_key), h = s.generation < d.generation; + if (h && !e.acknowledgeRollback) + throw new ot(d.generation, s.generation); + const m = h ? `This device previously saw credential generation ${d.generation}, but the accepted capsule is generation ${s.generation}. Relays may be serving stale data, or an old capsule is being replayed.` : void 0; + await st(c, s.operational_public_key, { generation: s.generation }); + const p = i.relayDisagreement ? 'Configured relays returned different credential capsules as "latest" for this account. Some relays may be stale, censored, or malicious.' : void 0; + return { + everydayPrivateKey: ne(s.operational_private_key), + everydayPublicKey: s.operational_public_key, + recoveryPublicKey: s.recovery_public_key, + accountId: s.account_id, + generation: s.generation, + credentialEvent: i.best.event, + recoveryCapsuleEvent: s.recovery_capsule_event, + rollbackWarning: m, + relayDisagreementWarning: p + }; + } finally { + a.closeAll(); + } +} +function $e(e) { + return e.filter((t) => ee(t)).sort((t, r) => r.created_at - t.created_at)[0]; +} +async function Fr(e) { + if (!Br(e.phrase)) + throw new nt("This does not look like a valid 12-word BitLogin recovery phrase."); + const t = await Rt(e.phrase), { recoveryPrivateKey: r, capsuleKey: n } = et(t), o = E(r), a = new C(e.vaultRelayUrls, { authPrivateKey: r }); + let i; + try { + i = await Nr(a, o, n, e.timeoutMs); + } finally { + a.closeAll(); + } + if (e.offlineRecoveryCapsuleEvents?.length) { + const f = []; + for (const b of e.offlineRecoveryCapsuleEvents) + if (ee(b)) + try { + f.push({ event: b, payload: await mt(b, n) }); + } catch (K) { + f.push({ event: b, payload: null, error: K.message }); + } + const u = /* @__PURE__ */ new Map(); + for (const b of [...i.candidates, ...f]) + u.set(b.event.id, b); + const y = [...u.values()].sort((b, K) => K.event.created_at - b.event.created_at), k = y.find((b) => b.payload !== null) ?? null; + i = { ...i, candidates: y, best: k, quorumMet: i.quorumMet || k !== null }; + } + if (!i.quorumMet) + throw new oe("quorum-not-met"); + if (!i.best) + throw new oe(i.candidates.length > 0 ? "no-valid-candidate" : "no-matching-event"); + const s = i.best.payload, c = Tr(i.candidates), d = ne(s.operational_private_key), h = s.operational_public_key, m = [.../* @__PURE__ */ new Set([...e.discoveryRelayUrls, ...s.vault_relay_hints])], p = new C(m); + let g = [], v = []; + try { + const f = await p.queryQuorum({ kinds: [Ce], authors: [h], limit: 5 }, e.timeoutMs), u = $e(f.outcomes.flatMap((b) => b.events)); + u && (g = hr(u)); + const y = await p.queryQuorum({ kinds: [Le], authors: [h], limit: 5 }, e.timeoutMs), k = $e(y.outcomes.flatMap((b) => b.events)); + k && (v = pr(k)); + } finally { + p.closeAll(); + } + return { + everydayPrivateKey: d, + everydayPublicKey: h, + recoveryPrivateKey: r, + recoveryPublicKey: o, + recoveryCapsuleKey: n, + accountId: s.account_id, + currentRecoveryEvent: i.best.event, + currentRecoveryPayload: s, + generalRelays: g, + dmRelays: v, + chainWarning: c.consistent ? void 0 : c.warning + }; +} +async function Jr(e) { + const t = e.now ?? Math.floor(Date.now() / 1e3), r = ke(e.newLoginName), { recovered: n } = e, o = { + schema: Ne, + account_id: n.accountId, + recovery_generation: n.currentRecoveryPayload.recovery_generation + 1, + previous_recovery_event_id: n.currentRecoveryEvent.id, + operational_private_key: X(n.everydayPrivateKey), + operational_public_key: n.everydayPublicKey, + recovery_public_key: n.recoveryPublicKey, + created_at: at(n.currentRecoveryEvent.created_at, t), + vault_relay_hints: e.vaultRelayUrls, + protocol: { capsule_encryption: ue, recovery_derivation: de } + }, a = await ft({ + recoveryPrivateKey: n.recoveryPrivateKey, + capsuleKey: n.recoveryCapsuleKey, + payload: o + }), i = new C(e.vaultRelayUrls, { authPrivateKey: n.recoveryPrivateKey }), s = await le(i, a, { + dTag: be, + minAcks: e.minAcknowledgements, + timeoutMs: e.timeoutMs + }); + i.closeAll(); + const { locatorPrivateKey: c, capsuleKey: d } = await ce(e.newPassword, r), h = E(c), m = { + schema: we, + account_id: n.accountId, + generation: 0, + operational_private_key: X(n.everydayPrivateKey), + operational_public_key: n.everydayPublicKey, + recovery_public_key: n.recoveryPublicKey, + recovery_capsule_event: a, + created_at: t, + vault_relay_hints: e.vaultRelayUrls, + protocol: { + password_kdf: De, + capsule_encryption: ue, + recovery_derivation: de + } + }, p = await Oe({ locatorPrivateKey: c, capsuleKey: d, payload: m }), g = new C(e.vaultRelayUrls, { authPrivateKey: c }), v = await le(g, p, { + dTag: ie, + minAcks: e.minAcknowledgements, + timeoutMs: e.timeoutMs + }); + if (g.closeAll(), !s.success || !v.success) + throw new nt("Could not publish the refreshed recovery and credential capsules to enough relays. Please retry."); + return { normalizedLoginName: r, locatorPublicKey: h, credentialEvent: p, refreshedRecoveryEvent: a, credentialPublish: v, recoveryPublish: s }; +} +function Yr(e) { + const t = E(e.privateKey); + return W({ + pubkey: t, + created_at: e.createdAt, + kind: Zt, + tags: [ + ["e", e.eventIdToDelete], + ["k", String(e.deletedEventKind)] + ], + content: e.reason ?? "" + }, e.privateKey); +} +async function Qr(e) { + const t = e.now ?? Math.floor(Date.now() / 1e3), r = ke(e.loginName), n = await ce(e.oldPassword, r), o = E(n.locatorPrivateKey), a = new C(e.vaultRelayUrls, { authPrivateKey: n.locatorPrivateKey }); + let i; + try { + i = await fe(a, o, n.capsuleKey, e.timeoutMs); + } finally { + a.closeAll(); + } + if (!i.quorumMet) + throw new oe("quorum-not-met"); + if (!i.best) + throw new oe(i.candidates.length > 0 ? "no-valid-candidate" : "no-matching-event"); + const s = i.best.payload, c = i.best.event, d = e.store ?? new Ct(), h = await Se(d, s.operational_public_key); + if (s.generation < h.generation && !e.acknowledgeRollback) + throw new ot(h.generation, s.generation); + const m = await ce(e.newPassword, r), p = E(m.locatorPrivateKey), g = new C(e.vaultRelayUrls, { authPrivateKey: m.locatorPrivateKey }); + let v; + try { + v = await fe(g, p, m.capsuleKey, e.timeoutMs); + } finally { + g.closeAll(); + } + if (!v.quorumMet) + throw new Z("Couldn't verify the new password isn't already registered under this login name. Please retry, or add more vault relays."); + if (v.candidates.length > 0) + throw new rt("Another account is already registered with this login name and the new password you chose. Pick a different new password."); + const f = s.generation + 1, u = { + schema: we, + account_id: s.account_id, + generation: f, + operational_private_key: s.operational_private_key, + operational_public_key: s.operational_public_key, + recovery_public_key: s.recovery_public_key, + recovery_capsule_event: s.recovery_capsule_event, + created_at: t, + vault_relay_hints: e.vaultRelayUrls, + protocol: { + password_kdf: De, + capsule_encryption: ue, + recovery_derivation: de + } + }, y = await Oe({ + locatorPrivateKey: m.locatorPrivateKey, + capsuleKey: m.capsuleKey, + payload: u + }), k = new C(e.vaultRelayUrls, { authPrivateKey: m.locatorPrivateKey }), b = await le(k, y, { + dTag: ie, + minAcks: e.minAcknowledgements, + timeoutMs: e.timeoutMs + }); + k.closeAll(); + const K = Ar({ + oldLocatorPrivateKey: n.locatorPrivateKey, + createdAt: at(c.created_at, t) + }), G = Yr({ + privateKey: n.locatorPrivateKey, + eventIdToDelete: c.id, + deletedEventKind: ae, + createdAt: t + }), _ = new C(e.vaultRelayUrls, { authPrivateKey: n.locatorPrivateKey }), [R, x] = await Promise.all([ + _.publishAll(K, e.timeoutMs), + _.publishAll(G, e.timeoutMs) + ]); + if (_.closeAll(), !b.success) + throw new Z("The new credential capsule did not reach the required relay acknowledgement and readback quorum. Please retry."); + return await st(d, s.operational_public_key, { generation: f }), { + normalizedLoginName: r, + oldLocatorPublicKey: o, + newLocatorPublicKey: p, + newGeneration: f, + recoveryPublicKey: s.recovery_public_key, + recoveryCapsuleEvent: s.recovery_capsule_event, + newCredentialEvent: y, + tombstoneEvent: K, + deletionRequestEvent: G, + newCredentialPublish: b, + tombstoneAcknowledgedCount: F(R), + deletionAcknowledgedCount: F(x) + }; +} +/*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */ +function Xr(e) { + return e instanceof Uint8Array || ArrayBuffer.isView(e) && e.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in e && e.BYTES_PER_ELEMENT === 1; +} +function Ge(e) { + if (typeof e != "boolean") + throw new TypeError(`boolean expected, not ${e}`); +} +function Ee(e) { + if (typeof e != "number") + throw new TypeError("number expected, got " + typeof e); + if (!Number.isSafeInteger(e) || e < 0) + throw new RangeError("positive integer expected, got " + e); +} +function te(e, t, r = "") { + const n = Xr(e), o = e?.length, a = t !== void 0; + if (!n || a && o !== t) { + const i = r && `"${r}" `, s = a ? ` of length ${t}` : "", c = n ? `length=${o}` : `type=${typeof e}`, d = i + "expected Uint8Array" + s + ", got " + c; + throw n ? new RangeError(d) : new TypeError(d); + } + return e; +} +function B(e) { + return new Uint32Array(e.buffer, e.byteOffset, Math.floor(e.byteLength / 4)); +} +function Ve(...e) { + for (let t = 0; t < e.length; t++) + e[t].fill(0); +} +const re = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68, Zr = (e) => e << 24 & 4278190080 | e << 8 & 16711680 | e >>> 8 & 65280 | e >>> 24 & 255, en = (e) => { + for (let t = 0; t < e.length; t++) + e[t] = Zr(e[t]); + return e; +}, Q = re ? (e) => e : en; +function tn(e, t) { + if (t == null || typeof t != "object") + throw new Error("options must be defined"); + return Object.assign(e, t); +} +function rn(e, t, r = !0) { + if (t === void 0) + return new Uint8Array(e); + if (te(t, void 0, "output"), t.length !== e) + throw new Error('"output" expected Uint8Array of length ' + e + ", got: " + t.length); + if (r && !me(t)) + throw new Error("invalid output, must be aligned"); + return t; +} +function me(e) { + return e.byteOffset % 4 === 0; +} +function Be(e) { + return Uint8Array.from(te(e)); +} +const Lt = (e) => Uint8Array.from(e.split(""), (t) => t.charCodeAt(0)), nn = Q(B(Lt("expand 16-byte k"))), on = Q(B(Lt("expand 32-byte k"))); +function w(e, t) { + return e << t | e >>> 32 - t; +} +const se = 64, an = 16, Re = 2 ** 32 - 1, We = /* @__PURE__ */ Uint32Array.of(); +function sn(e, t, r, n, o, a, i, s) { + const c = o.length, d = new Uint8Array(se), h = B(d), m = re && me(o) && me(a), p = m ? B(o) : We, g = m ? B(a) : We; + if (!re) { + for (let v = 0; v < c; i++) { + if (e(t, r, n, h, i, s), Q(h), i >= Re) + throw new Error("arx: counter overflow"); + const f = Math.min(se, c - v); + for (let u = 0, y; u < f; u++) + y = v + u, a[y] = o[y] ^ d[u]; + v += f; + } + return; + } + for (let v = 0; v < c; i++) { + if (e(t, r, n, h, i, s), i >= Re) + throw new Error("arx: counter overflow"); + const f = Math.min(se, c - v); + if (m && f === se) { + const u = v / 4; + if (v % 4 !== 0) + throw new Error("arx: invalid block position"); + for (let y = 0, k; y < an; y++) + k = u + y, g[k] = p[k] ^ h[y]; + v += se; + continue; + } + for (let u = 0, y; u < f; u++) + y = v + u, a[y] = o[y] ^ d[u]; + v += f; + } +} +function cn(e, t) { + const { allowShortKeys: r, extendNonceFn: n, counterLength: o, counterRight: a, rounds: i } = tn({ allowShortKeys: !1, counterLength: 8, counterRight: !1, rounds: 20 }, t); + if (typeof e != "function") + throw new Error("core must be a function"); + return Ee(o), Ee(i), Ge(a), Ge(r), (s, c, d, h, m = 0) => { + te(s, void 0, "key"), te(c, void 0, "nonce"), te(d, void 0, "data"); + const p = d.length; + if (h = rn(p, h, !1), Ee(m), m < 0 || m >= Re) + throw new Error("arx: counter overflow"); + const g = []; + let v = s.length, f, u; + if (v === 32) + g.push(f = Be(s)), u = on; + else if (v === 16 && r) + f = new Uint8Array(32), f.set(s), f.set(s, 16), u = nn, g.push(f); + else + throw te(s, 32, "arx key"), new Error("invalid key size"); + (!re || !me(c)) && g.push(c = Be(c)); + let y = B(f); + if (n) { + if (c.length !== 24) + throw new Error("arx: extended nonce must be 24 bytes"); + const K = c.subarray(0, 16); + if (re) + n(u, y, B(K), y); + else { + const G = Q(Uint32Array.from(u)); + n(G, y, B(K), y), Ve(G), Q(y); + } + c = c.subarray(16); + } else re || Q(y); + const k = 16 - o; + if (k !== c.length) + throw new Error(`arx: nonce must be ${k} or 16 bytes`); + if (k !== 12) { + const K = new Uint8Array(12); + K.set(c, a ? 0 : 12 - c.length), c = K, g.push(c); + } + const b = Q(B(c)); + try { + return sn(e, u, y, b, d, h, m, i), h; + } finally { + Ve(...g); + } + }; +} +function ln(e, t, r, n, o, a = 20) { + let i = e[0], s = e[1], c = e[2], d = e[3], h = t[0], m = t[1], p = t[2], g = t[3], v = t[4], f = t[5], u = t[6], y = t[7], k = o, b = r[0], K = r[1], G = r[2], _ = i, R = s, x = c, L = d, N = h, T = m, I = p, S = g, M = v, U = f, O = u, D = y, q = k, z = b, j = K, $ = G; + for (let qe = 0; qe < a; qe += 2) + _ = _ + N | 0, q = w(q ^ _, 16), M = M + q | 0, N = w(N ^ M, 12), _ = _ + N | 0, q = w(q ^ _, 8), M = M + q | 0, N = w(N ^ M, 7), R = R + T | 0, z = w(z ^ R, 16), U = U + z | 0, T = w(T ^ U, 12), R = R + T | 0, z = w(z ^ R, 8), U = U + z | 0, T = w(T ^ U, 7), x = x + I | 0, j = w(j ^ x, 16), O = O + j | 0, I = w(I ^ O, 12), x = x + I | 0, j = w(j ^ x, 8), O = O + j | 0, I = w(I ^ O, 7), L = L + S | 0, $ = w($ ^ L, 16), D = D + $ | 0, S = w(S ^ D, 12), L = L + S | 0, $ = w($ ^ L, 8), D = D + $ | 0, S = w(S ^ D, 7), _ = _ + T | 0, $ = w($ ^ _, 16), O = O + $ | 0, T = w(T ^ O, 12), _ = _ + T | 0, $ = w($ ^ _, 8), O = O + $ | 0, T = w(T ^ O, 7), R = R + I | 0, q = w(q ^ R, 16), D = D + q | 0, I = w(I ^ D, 12), R = R + I | 0, q = w(q ^ R, 8), D = D + q | 0, I = w(I ^ D, 7), x = x + S | 0, z = w(z ^ x, 16), M = M + z | 0, S = w(S ^ M, 12), x = x + S | 0, z = w(z ^ x, 8), M = M + z | 0, S = w(S ^ M, 7), L = L + N | 0, j = w(j ^ L, 16), U = U + j | 0, N = w(N ^ U, 12), L = L + N | 0, j = w(j ^ L, 8), U = U + j | 0, N = w(N ^ U, 7); + let A = 0; + n[A++] = i + _ | 0, n[A++] = s + R | 0, n[A++] = c + x | 0, n[A++] = d + L | 0, n[A++] = h + N | 0, n[A++] = m + T | 0, n[A++] = p + I | 0, n[A++] = g + S | 0, n[A++] = v + M | 0, n[A++] = f + U | 0, n[A++] = u + O | 0, n[A++] = y + D | 0, n[A++] = k + q | 0, n[A++] = b + z | 0, n[A++] = K + j | 0, n[A++] = G + $ | 0; +} +const Nt = /* @__PURE__ */ cn(ln, { + counterRight: !1, + counterLength: 4, + allowShortKeys: !1 +}), Tt = 2, xe = 1, It = 65536, Ae = 4294967295; +function He(e, t) { + const r = Ie(new Uint8Array([2]), Ze(t)), o = tr.getSharedSecret(e, r, !0).slice(1, 33); + return rr(ye("nip44-v2"), o); +} +function St(e, t) { + const r = or(e, t, 76); + return { + chachaKey: r.slice(0, 32), + chachaNonce: r.slice(32, 44), + hmacKey: r.slice(44, 76) + }; +} +function Mt(e) { + if (e <= 32) + return 32; + const t = 2 ** Math.floor(Math.log2(e - 1) + 1), r = t <= 256 ? 32 : t / 8; + return r * (Math.floor((e - 1) / r) + 1); +} +function un(e) { + if (e < It) { + const r = new Uint8Array(2); + return new DataView(r.buffer).setUint16(0, e, !1), r; + } + const t = new Uint8Array(6); + return new DataView(t.buffer).setUint32(2, e, !1), t; +} +function dn(e) { + const t = e.length; + if (t < xe || t > Ae) + throw new Error(`NIP-44 plaintext length must be between ${xe} and ${Ae} bytes.`); + const r = un(t), n = Mt(t), o = new Uint8Array(r.length + n); + return o.set(r, 0), o.set(e, r.length), o; +} +function yn(e) { + const t = new DataView(e.buffer, e.byteOffset, e.byteLength), r = t.getUint16(0, !1); + let n, o; + if (r === 0) { + if (n = t.getUint32(2, !1), o = 6, n < It) + throw new Error("NIP-44 payload has inconsistent padding."); + } else + n = r, o = 2; + if (n < xe || n > Ae || e.length !== o + Mt(n)) + throw new Error("NIP-44 payload has inconsistent padding."); + return e.slice(o, o + n); +} +function Ut(e, t, r) { + return Qe(Xe, e, Ie(t, r)); +} +function hn(e, t, r) { + const n = er(32), { chachaKey: o, chachaNonce: a, hmacKey: i } = St(e, n), s = dn(ye(t)), c = Nt(o, a, s), d = Ut(i, n, c); + return tt.encode(Ie(new Uint8Array([Tt]), n, c, d)); +} +function pn(e, t) { + const r = tt.decode(t); + if (r[0] !== Tt) + throw new Error(`Unsupported NIP-44 version: ${r[0]}`); + const n = r.slice(1, 33), o = r.slice(r.length - 32), a = r.slice(33, r.length - 32), { chachaKey: i, chachaNonce: s, hmacKey: c } = St(e, n), d = Ut(c, n, a); + if (!nr(o, d)) + throw new Error("NIP-44 MAC verification failed: payload is corrupted, tampered, or uses the wrong key."); + const h = Nt(i, s, a); + return Ye(yn(h)); +} +function vn(...e) { + for (const t of e) + t && t.fill(0); +} +class Pe { + privateKey; + publicKeyHex; + destroyed = !1; + constructor(t) { + this.privateKey = t, this.publicKeyHex = E(t); + } + assertAlive() { + if (this.destroyed) + throw new Error("This signer has been destroyed (session locked or logged out)."); + } + getPublicKey() { + return this.assertAlive(), this.publicKeyHex; + } + signEvent(t) { + return this.assertAlive(), W({ + pubkey: this.publicKeyHex, + created_at: t.created_at ?? Math.floor(Date.now() / 1e3), + kind: t.kind, + tags: t.tags ?? [], + content: t.content + }, this.privateKey); + } + nip44Encrypt(t, r) { + return this.assertAlive(), hn(He(this.privateKey, t), r); + } + nip44Decrypt(t, r) { + return this.assertAlive(), pn(He(this.privateKey, t), r); + } + /** Best-practical secret wipe (§11.10, §21.4): overwrites the private key buffer in place. */ + destroy() { + vn(this.privateKey), this.destroyed = !0; + } +} +const gn = [ + "wss://relay.damus.io", + "wss://nos.lol", + "wss://relay.nostr.band" +], fn = [ + "wss://purplepag.es", + "wss://relay.nostr.band" +], mn = "bitlogin", H = "kv", wn = 1; +function bn() { + return new Promise((e, t) => { + const r = indexedDB.open(mn, wn); + r.onupgradeneeded = () => { + const n = r.result; + n.objectStoreNames.contains(H) || n.createObjectStore(H); + }, r.onsuccess = () => e(r.result), r.onerror = () => t(r.error); + }); +} +class kn { + dbPromise = null; + db() { + return this.dbPromise || (this.dbPromise = bn()), this.dbPromise; + } + async get(t) { + const r = await this.db(); + return new Promise((n, o) => { + const i = r.transaction(H, "readonly").objectStore(H).get(t); + i.onsuccess = () => n(i.result), i.onerror = () => o(i.error); + }); + } + async set(t, r) { + const n = await this.db(); + return new Promise((o, a) => { + const i = n.transaction(H, "readwrite"); + i.objectStore(H).put(r, t), i.oncomplete = () => o(), i.onerror = () => a(i.error); + }); + } + async delete(t) { + const r = await this.db(); + return new Promise((n, o) => { + const a = r.transaction(H, "readwrite"); + a.objectStore(H).delete(t), a.oncomplete = () => n(), a.onerror = () => o(a.error); + }); + } +} +const l = { + signer: null, + everydayPrivateKey: null, + accountId: null, + recoveryPublicKey: null, + activeCredentialEvent: null, + activeRecoveryEvent: null, + pendingRecovery: null +}; +let V = [...gn], Ke = [...fn]; +const Fe = new kn(); +function J() { + if (!l.signer || !l.everydayPrivateKey) + throw new Error("No identity is unlocked in this session."); + return { signer: l.signer, everydayPrivateKey: l.everydayPrivateKey }; +} +function pe() { + l.signer?.destroy(), l.everydayPrivateKey && l.everydayPrivateKey.fill(0), l.signer = null, l.everydayPrivateKey = null, l.accountId = null, l.recoveryPublicKey = null, l.activeCredentialEvent = null, l.activeRecoveryEvent = null, l.pendingRecovery && (l.pendingRecovery.recoveryPrivateKey.fill(0), l.pendingRecovery.everydayPrivateKey.fill(0), l.pendingRecovery = null); +} +async function _n(e, t) { + switch (e) { + case "configure": { + const r = t; + return r.vaultRelayUrls?.length && (V = r.vaultRelayUrls), r.discoveryRelayUrls?.length && (Ke = r.discoveryRelayUrls), {}; + } + case "register": { + const r = t, n = r.importKey ? await Wr({ nsecOrHex: r.importKey, loginName: r.loginName, password: r.password, vaultRelayUrls: V }) : await xt({ loginName: r.loginName, password: r.password, vaultRelayUrls: V }); + return pe(), l.signer = new Pe(n.everydayPrivateKey), l.everydayPrivateKey = n.everydayPrivateKey, l.accountId = n.accountId, l.recoveryPublicKey = n.recoveryPublicKey, l.activeCredentialEvent = n.credentialEvent, l.activeRecoveryEvent = n.recoveryEvent, { + recoveryPhrase: n.recoveryPhrase, + everydayPublicKey: n.everydayPublicKey, + recoveryPublicKey: n.recoveryPublicKey, + accountId: n.accountId, + imported: n.imported, + credentialEventId: n.credentialEvent.id, + recoveryEventId: n.recoveryEvent.id + }; + } + case "previewImportKey": { + const n = At(t.nsecOrHex), o = E(n), a = { everydayPublicKey: o, npub: je(o) }; + return n.fill(0), a; + } + case "login": { + const r = t, n = await Hr({ + loginName: r.loginName, + password: r.password, + vaultRelayUrls: V, + store: Fe, + acknowledgeRollback: r.acknowledgeRollback + }); + return pe(), l.signer = new Pe(n.everydayPrivateKey), l.everydayPrivateKey = n.everydayPrivateKey, l.accountId = n.accountId, l.recoveryPublicKey = n.recoveryPublicKey, l.activeCredentialEvent = n.credentialEvent, l.activeRecoveryEvent = n.recoveryCapsuleEvent, { + everydayPublicKey: n.everydayPublicKey, + accountId: n.accountId, + generation: n.generation, + rollbackWarning: n.rollbackWarning, + relayDisagreementWarning: n.relayDisagreementWarning + }; + } + case "recover": { + const r = t, n = await Fr({ + phrase: r.phrase, + vaultRelayUrls: V, + discoveryRelayUrls: Ke, + offlineRecoveryCapsuleEvents: r.offlineExportFile?.recovery_capsule_events + }); + return pe(), l.pendingRecovery = n, l.signer = new Pe(n.everydayPrivateKey), l.everydayPrivateKey = n.everydayPrivateKey, l.accountId = n.accountId, l.recoveryPublicKey = n.recoveryPublicKey, l.activeRecoveryEvent = n.currentRecoveryEvent, { + everydayPublicKey: n.everydayPublicKey, + accountId: n.accountId, + generalRelays: n.generalRelays, + dmRelays: n.dmRelays, + chainWarning: n.chainWarning + }; + } + case "completeRecovery": { + const r = t; + if (!l.pendingRecovery) throw new Error("No recovery is in progress in this session."); + const n = await Jr({ + recovered: l.pendingRecovery, + newLoginName: r.newLoginName, + newPassword: r.newPassword, + vaultRelayUrls: V + }); + return l.activeCredentialEvent = n.credentialEvent, l.activeRecoveryEvent = n.refreshedRecoveryEvent, l.pendingRecovery.recoveryPrivateKey.fill(0), l.pendingRecovery = null, { + locatorPublicKey: n.locatorPublicKey, + credentialEventId: n.credentialEvent.id, + refreshedRecoveryEventId: n.refreshedRecoveryEvent.id + }; + } + case "changePassword": { + const r = t, n = await Qr({ + loginName: r.loginName, + oldPassword: r.oldPassword, + newPassword: r.newPassword, + vaultRelayUrls: V, + store: Fe, + acknowledgeRollback: r.acknowledgeRollback + }); + return l.activeCredentialEvent = n.newCredentialEvent, l.recoveryPublicKey = n.recoveryPublicKey, l.activeRecoveryEvent = n.recoveryCapsuleEvent, { + newLocatorPublicKey: n.newLocatorPublicKey, + newGeneration: n.newGeneration, + tombstoneAcknowledgedCount: n.tombstoneAcknowledgedCount, + deletionAcknowledgedCount: n.deletionAcknowledgedCount + }; + } + case "publishProfileAndRelayLists": { + const r = t, { everydayPrivateKey: n } = J(); + return vr({ + everydayPrivateKey: n, + name: r.name, + about: r.about, + picture: r.picture, + generalRelays: r.generalRelays, + dmRelays: r.dmRelays, + discoveryRelays: Ke + }); + } + case "getPublicKey": { + const { signer: r } = J(); + return { publicKey: r.getPublicKey() }; + } + case "signEvent": { + const { signer: r } = J(), n = t; + return r.signEvent({ kind: n.kind, tags: n.tags, content: n.content, created_at: n.created_at }); + } + case "nip44Encrypt": { + const { signer: r } = J(), n = t; + return { ciphertext: r.nip44Encrypt(n.peerPublicKey, n.plaintext) }; + } + case "nip44Decrypt": { + const { signer: r } = J(), n = t; + return { plaintext: r.nip44Decrypt(n.peerPublicKey, n.payload) }; + } + case "exportIdentity": { + const { everydayPrivateKey: r, signer: n } = J(); + return { nsec: ir(r), npub: je(n.getPublicKey()) }; + } + case "buildRecoveryExport": { + if (J(), !l.recoveryPublicKey || !l.activeRecoveryEvent) + throw new Error("No recovery capsule is known in this session yet."); + return ar({ + recoveryPublicKeyHex: l.recoveryPublicKey, + vaultRelayUrls: V, + recoveryCapsuleEvents: [l.activeRecoveryEvent], + relayListEvents: [] + }); + } + case "repairReplicas": { + if (!l.activeCredentialEvent || !l.activeRecoveryEvent) + throw new Error("No active capsule events are known in this session yet."); + const r = new C(V), n = await Ir(r, l.activeCredentialEvent, l.activeRecoveryEvent); + return r.closeAll(), n; + } + case "getSessionStatus": + return { unlocked: !!l.signer, everydayPublicKey: l.signer?.getPublicKey() }; + case "logout": + return pe(), {}; + default: + throw new Error(`Unknown worker action: ${e}`); + } +} +self.addEventListener("message", (e) => { + const { id: t, action: r, payload: n } = e.data; + _n(r, n).then( + (o) => { + const a = { id: t, ok: !0, result: o }; + self.postMessage(a); + }, + (o) => { + const a = o instanceof Error ? o : new Error(String(o)), i = { id: t, ok: !1, error: a.message, errorName: a.name }; + self.postMessage(i); + } + ); +});