import { v as le, g as x, s as Z, K as ln, c as un, b as vt, d as Be, f as Ge, h as he, u as ve, j as dn, k as yn, l as ae, m as de, n as Ve, S as He, o as We, q as Le, D as fe, t as Ne, w as pn, x as hn, y as vn, z as fn, A as Oe, B as at, C as ft, F as gn, G as wn, H as bn, I as Ke, J as gt, L as mn, M as kn, N as Fe, O as Ie, P as me, Q as En, T as wt, U as Pn, V as _n, W as Kn, X as bt, Y as ye, Z as Te, _ as mt, $ as xn, a0 as Rn, a1 as An, a2 as Cn, a as it, a3 as Sn } from "./bitlogin-shared-QIBe5Omw.js"; class pe extends Error { reason; constructor(t) { super("Account not found or credentials incorrect."), this.name = "AccountNotFoundError", this.reason = t; } } class ie extends Error { constructor(t) { super(t), this.name = "RegistrationFailedError"; } } class kt 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 Et extends Error { constructor(t) { super(t), this.name = "RecoveryFailedError"; } } class Pt extends Error { seenGeneration; capsuleGeneration; constructor(t, n) { super(`This credential capsule reports generation ${n}, 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 = n; } } function _t(e, t) { const n = t ?? Math.floor(Date.now() / 1e3); return e == null ? n : Math.max(n, e + 1); } const Ln = { generation: -1, recoveryGeneration: -1 }; function Kt(e) { return `bitlogin:hwm:${e}`; } async function Je(e, t) { const n = await e.get(Kt(t)); return n ? JSON.parse(n) : Ln; } async function xt(e, t, n) { const r = await Je(e, t), o = { generation: Math.max(r.generation, n.generation ?? -1), recoveryGeneration: Math.max(r.recoveryGeneration, n.recoveryGeneration ?? -1) }; return await e.set(Kt(t), JSON.stringify(o)), o; } function Nn() { const e = globalThis.WebSocket; if (!e) throw new Error("No global WebSocket implementation is available in this environment."); return e; } class In { url; ws = null; connectPromise = null; subs = /* @__PURE__ */ new Map(); pendingPublishes = /* @__PURE__ */ new Map(); authPrivateKey; connectTimeoutMs; authenticated = !1; constructor(t, n = {}) { this.url = t, this.authPrivateKey = n.authPrivateKey, this.connectTimeoutMs = n.connectTimeoutMs ?? 8e3; } async connect() { return this.connectPromise ? this.connectPromise : (this.connectPromise = new Promise((t, n) => { const r = Nn(), o = new r(this.url); this.ws = o; const a = setTimeout(() => { n(new Error(`Timed out connecting to relay ${this.url}`)); }, this.connectTimeoutMs); o.addEventListener("open", () => { clearTimeout(a), t(); }), o.addEventListener("error", () => { clearTimeout(a), n(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 n; try { n = JSON.parse(t); } catch { return; } if (!Array.isArray(n) || typeof n[0] != "string") return; const [r, ...o] = n; if (r === "EVENT") { const [a, i] = o, s = this.subs.get(a); s && le(i) && s.events.push(i); return; } if (r === "EOSE") { const [a] = o; this.subs.get(a)?.onEose(); return; } if (r === "OK") { const [a, i, s] = o; this.pendingPublishes.get(a)?.({ ok: i, message: s ?? "" }), this.pendingPublishes.delete(a); return; } if (r === "AUTH") { const [a] = o; this.respondToAuthChallenge(a); return; } } async respondToAuthChallenge(t) { if (!this.authPrivateKey) return; const n = x(this.authPrivateKey), r = Z({ pubkey: n, created_at: Math.floor(Date.now() / 1e3), kind: ln, tags: [ ["relay", this.url], ["challenge", t] ], content: "" }, this.authPrivateKey); this.authenticated = !0, this.send(["AUTH", r]); } isAuthenticated() { return this.authenticated; } async publish(t, n = 8e3) { return await this.connect(), new Promise((r) => { const o = setTimeout(() => { this.pendingPublishes.delete(t.id), r({ ok: !1, message: "timeout: no OK received from relay" }); }, n); this.pendingPublishes.set(t.id, (a) => { clearTimeout(o), r(a); }), this.send(["EVENT", t]); }); } async queryOnce(t, n = 8e3) { await this.connect(); const r = un({ 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(r), this.send(["CLOSE", r]), o(a); }, s = setTimeout(i, n); this.subs.set(r, { events: a, onEose: i }), this.send(["REQ", r, t]); }); } } class I { connections = /* @__PURE__ */ new Map(); constructor(t, n = {}) { for (const r of new Set(t)) this.connections.set(r, new In(r, n)); } 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, n = 8e3) { const r = [...this.connections.entries()], o = await Promise.all(r.map(async ([s, c]) => { try { const l = await c.queryOnce(t, n); return { relayUrl: s, events: l, responded: !0 }; } catch (l) { return { relayUrl: s, events: [], responded: !1, error: l.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, n = 8e3) { const r = [...this.connections.entries()]; return Promise.all(r.map(async ([o, a]) => { try { const i = await a.publish(t, n); 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 ne(e) { return e.filter((t) => t.result.ok).length; } function Tn(e, t, n) { return Z({ pubkey: x(e), created_at: n, kind: vt, tags: [], content: JSON.stringify(t) }, e); } function On(e, t, n) { const r = 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 Z({ pubkey: x(e), created_at: n, kind: Be, tags: r, content: "" }, e); } function Mn(e, t, n) { return Z({ pubkey: x(e), created_at: n, kind: Ge, tags: t.map((r) => ["relay", r]), content: "" }, e); } function Un(e) { return e.tags.filter((t) => t[0] === "r" && t[1]).map((t) => t[1]); } function Dn(e) { return e.tags.filter((t) => t[0] === "relay" && t[1]).map((t) => t[1]); } async function qn(e) { const t = x(e.everydayPrivateKey), n = Math.floor(Date.now() / 1e3), r = [.../* @__PURE__ */ new Set([...e.generalRelays, ...e.dmRelays, ...e.discoveryRelays])], o = new I(r), [a, i, s] = await Promise.all([ o.queryQuorum({ authors: [t], kinds: [vt] }), o.queryQuorum({ authors: [t], kinds: [Be] }), o.queryQuorum({ authors: [t], kinds: [Ge] }) ]); o.closeAll(); const c = a.outcomes.some((h) => h.events.length > 0), l = i.outcomes.some((h) => h.events.length > 0), u = s.outcomes.some((h) => h.events.length > 0), d = new I(r); let g = null, w = null, v = null; const f = []; if (!c && (e.name || e.about || e.picture)) { const h = Tn(e.everydayPrivateKey, { name: e.name, about: e.about, picture: e.picture }, n); f.push(d.publishAll(h).then((p) => void (g = p))); } if (!l) { const h = On(e.everydayPrivateKey, e.generalRelays.map((p) => ({ url: p, read: !0, write: !0 })), n); f.push(d.publishAll(h).then((p) => void (w = p))); } if (!u) { const h = Mn(e.everydayPrivateKey, e.dmRelays, n); f.push(d.publishAll(h).then((p) => void (v = p))); } return await Promise.all(f), d.closeAll(), { profilePublished: g !== null && ne(g) > 0, relayListAcknowledgedCount: w !== null ? ne(w) : 0, dmRelayListAcknowledgedCount: v !== null ? ne(v) : 0, profileSkippedExisting: c, relayListSkippedExisting: l, dmRelayListSkippedExisting: u }; } async function ke(e, t, n) { const r = n.minAcks ?? 2, o = n.minReadbacks ?? 2, a = await e.publishAll(t, n.timeoutMs), i = ne(a), c = (await e.queryQuorum({ kinds: [he], authors: [t.pubkey], "#d": [n.dTag], limit: 5 }, n.timeoutMs)).outcomes.filter((l) => l.events.some((u) => u.id === t.id)).length; return { acknowledgedCount: i, readbackVerifiedCount: c, success: i >= r && c >= o }; } function jn(e) { const t = dn(e); if (t === void 0) throw new Error("Value is not JSON-serializable for canonicalization."); return t; } function zn(e) { return ve(jn(e)); } const Ae = [1024, 2048, 4096], oe = 4; function $n(e) { const t = oe + e.length, n = Ae.find((a) => a >= t); if (n === void 0) throw new Error(`Payload of ${e.length} bytes exceeds the largest padding bucket (${Ae[Ae.length - 1]} bytes minus ${oe}-byte length prefix).`); const r = new Uint8Array(n); return new DataView(r.buffer).setUint32(0, e.length, !1), r.set(e, oe), r; } function Bn(e) { if (!Ae.includes(e.length)) throw new Error(`Padded plaintext length ${e.length} does not match a known bucket.`); const n = new DataView(e.buffer, e.byteOffset, e.byteLength).getUint32(0, !1); if (n > e.length - oe) throw new Error("Declared payload length exceeds the padded bucket size."); const r = e.slice(oe, oe + n), o = e.slice(oe + n); for (const a of o) if (a !== 0) throw new Error("Padding bytes are not all zero; capsule plaintext is malformed."); return r; } function Ye() { const e = globalThis.crypto; if (!e || !e.subtle) throw new Error("WebCrypto SubtleCrypto is not available in this environment."); return e; } async function Rt(e) { if (e.length !== 32) throw new Error("AES-256-GCM key must be exactly 32 bytes."); return Ye().subtle.importKey("raw", e, "AES-GCM", !1, ["encrypt", "decrypt"]); } async function Gn(e, t, n) { const r = yn(), o = await Rt(e), a = await Ye().subtle.encrypt({ name: "AES-GCM", iv: r, additionalData: n, tagLength: 128 }, o, t); return { nonce: r, ciphertext: new Uint8Array(a) }; } async function Vn(e, t, n, r) { const o = await Rt(e); try { const a = await Ye().subtle.decrypt({ name: "AES-GCM", iv: t, additionalData: r, tagLength: 128 }, o, n); return new Uint8Array(a); } catch { throw new Error("AES-256-GCM authentication failed: capsule is corrupted, tampered, or the wrong key was used."); } } function At(e) { return ve(`bitlogin|password-capsule|v1|${e}|30078|bitlogin:password:v1`); } function Ct(e) { return ve(`bitlogin|recovery-capsule|v1|${e}|30078|bitlogin:recovery:v1`); } async function St(e, t, n) { const r = zn(e), o = $n(r), a = await Gn(t, o, n); return { version: 1, algorithm: "aes-256-gcm", nonce: ae(a.nonce), ciphertext: ae(a.ciphertext) }; } async function Lt(e, t, n) { if (e.version !== 1 || e.algorithm !== "aes-256-gcm") throw new Error(`Unsupported capsule envelope version/algorithm: ${e.version}/${e.algorithm}`); const r = de(e.nonce), o = de(e.ciphertext), a = await Vn(t, r, o, n), i = Bn(a); return JSON.parse(Ve(i)); } class Qe extends Error { constructor(t) { super(t), this.name = "CapsuleValidationError"; } } const Hn = /* @__PURE__ */ new Set(["wss:", "ws:"]), Wn = 1e6, Fn = /^[0-9a-f]{64}$/u; function R(e, t) { if (!e) throw new Qe(t); } function Ce(e) { return typeof e == "string" && Fn.test(e); } function Nt(e) { R(Array.isArray(e), "vault_relay_hints must be an array (§12.4.7)."); for (const t of e) { R(typeof t == "string", "Each relay hint must be a string (§12.4.7)."); let n; try { n = new URL(t); } catch { throw new Qe(`Invalid relay URL: ${String(t)} (§12.4.7)`); } R(Hn.has(n.protocol), `Relay URL uses a disallowed scheme: ${t} (§12.4.7)`); } } function It(e) { R(typeof e == "string", "account_id must be a string (§12.4.2)."); let t; try { t = de(e); } catch { throw new Qe("account_id is not valid base64url (§12.4.2)."); } R(t.length === 16, "account_id must decode to exactly 128 bits (§12.4.2)."); } function Tt(e, t) { R(typeof e == "string", "operational_private_key must be a string (§12.4.3)."); const n = de(e); R(n.length === 32, "operational_private_key must be exactly 32 bytes (§12.4.3)."), R(We(n), "operational_private_key is not a valid secp256k1 scalar (§12.4.3)."), R(Ce(t), "operational_public_key must be lowercase 64-char hex (§12.4.4)."); const r = x(n); R(r === t, "operational_public_key does not match the derived public key (§12.4.4)."); } function Ot(e, t) { R(Number.isInteger(e) && e >= 0 && e <= Wn, `${t} is out of supported bounds (§12.4.8).`); } function Jn(e) { R(e.schema === Le, `Unsupported or unknown schema: ${String(e.schema)} (§12.4.1)`), It(e.account_id), Ot(e.generation, "generation"), Tt(e.operational_private_key, e.operational_public_key), R(Ce(e.recovery_public_key), "recovery_public_key must be lowercase 64-char hex (§12.4.5)."), Nt(e.vault_relay_hints); const t = e.recovery_capsule_event; R(!!t && typeof t == "object", "recovery_capsule_event must be present (§12.4.6)."), R(le(t), "Embedded recovery_capsule_event has an invalid event id or signature (§12.4.6)."), R(t.pubkey === e.recovery_public_key, "Embedded recovery_capsule_event author does not match recovery_public_key (§12.4.5)."); } function Yn(e) { R(e.schema === He, `Unsupported or unknown schema: ${String(e.schema)} (§12.4.1)`), It(e.account_id), Ot(e.recovery_generation, "recovery_generation"), R(e.previous_recovery_event_id === null || Ce(e.previous_recovery_event_id), "previous_recovery_event_id must be null or lowercase 64-char hex (§12.3)."), Tt(e.operational_private_key, e.operational_public_key), R(Ce(e.recovery_public_key), "recovery_public_key must be lowercase 64-char hex."), Nt(e.vault_relay_hints); } function Qn(e) { const t = new Map(e.map((r) => [r.recoveryGeneration, r])), n = [...e].sort((r, o) => r.recoveryGeneration - o.recoveryGeneration); for (let r = 1; r < n.length; r++) { const o = n[r], 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 Xe(e) { const t = x(e.locatorPrivateKey), n = await St(e.payload, e.capsuleKey, At(t)); return Z({ pubkey: t, created_at: e.payload.created_at, kind: he, tags: [["d", fe]], content: JSON.stringify(n) }, e.locatorPrivateKey); } function Xn(e) { const t = x(e.oldLocatorPrivateKey); return Z({ pubkey: t, created_at: e.createdAt, kind: he, tags: [["d", fe]], content: "" }, e.oldLocatorPrivateKey); } async function Zn(e, t) { if (!le(e)) throw new Error("Credential capsule event has an invalid id or signature."); const n = JSON.parse(e.content), r = await Lt(n, t, At(e.pubkey)); return Jn(r), r; } async function Mt(e) { const t = x(e.recoveryPrivateKey), n = await St(e.payload, e.capsuleKey, Ct(t)); return Z({ pubkey: t, created_at: e.payload.created_at, kind: he, tags: [["d", Ne]], content: JSON.stringify(n) }, e.recoveryPrivateKey); } async function Ut(e, t) { if (!le(e)) throw new Error("Recovery capsule event has an invalid id or signature."); const n = JSON.parse(e.content), r = await Lt(n, t, Ct(e.pubkey)); return Yn(r), r; } function er(e) { const t = /* @__PURE__ */ new Map(); for (const n of e) le(n) && t.set(n.id, n); return [...t.values()].sort((n, r) => r.created_at - n.created_at); } async function Dt(e, t, n, r, o) { const a = await e.queryQuorum({ kinds: [he], authors: [t], "#d": [n], limit: 5 }, o), i = a.outcomes.flatMap((g) => g.events), s = er(i), c = []; for (const g of s) try { const w = await r(g); c.push({ event: g, payload: w }); } catch (w) { c.push({ event: g, payload: null, error: w.message }); } const l = c.find((g) => g.payload !== null) ?? null, u = a.outcomes.filter((g) => g.responded && g.events.length > 0).map((g) => g.events.slice().sort((w, v) => v.created_at - w.created_at)[0].id), d = new Set(u).size > 1; return { quorumMet: a.quorumMet, respondedCount: a.respondedCount, totalCount: a.totalCount, candidates: c, best: l, relayDisagreement: d }; } async function Se(e, t, n, r = 8e3) { return Dt(e, t, fe, (o) => Zn(o, n), r); } async function tr(e, t, n, r = 8e3) { return Dt(e, t, Ne, (o) => Ut(o, n), r); } function nr(e) { const t = e.filter((n) => n.payload !== null); return t.length < 2 ? { consistent: !0 } : Qn(t.map((n) => ({ eventId: n.event.id, recoveryGeneration: n.payload.recovery_generation, previousRecoveryEventId: n.payload.previous_recovery_event_id }))); } async function rr(e, t, n, r) { const [o, a] = await Promise.all([ e.publishAll(t, r), e.publishAll(n, r) ]); return { credentialAcknowledgedCount: ne(o), recoveryAcknowledgedCount: ne(a), relaysTried: e.relayUrls.length }; } const qt = `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 or(e, t, n, r) { vn(e); const o = fn({ dkLen: 32, asyncTick: 10 }, r), { c: a, dkLen: i, asyncTick: s } = o; if (Oe(a), Oe(i), Oe(s), a < 1) throw new Error("iterations (c) should be >= 1"); const c = at(t), l = at(n), u = new Uint8Array(i), d = ft.create(e, c), g = d._cloneInto().update(l); return { c: a, dkLen: i, asyncTick: s, DK: u, PRF: d, PRFSalt: g }; } function ar(e, t, n, r, o) { return e.destroy(), t.destroy(), r && r.destroy(), gn(o), n; } async function ir(e, t, n, r) { const { c: o, dkLen: a, asyncTick: i, DK: s, PRF: c, PRFSalt: l } = or(e, t, n, r); let u; const d = new Uint8Array(4), g = pn(d), w = new Uint8Array(c.outputLen); for (let v = 1, f = 0; f < a; v++, f += c.outputLen) { const h = s.subarray(f, f + c.outputLen); g.setInt32(0, v, !1), (u = l._cloneInto(u)).update(d).digestInto(w), h.set(w.subarray(0, h.length)), await hn(o - 1, i, () => { c._cloneInto(u).update(w).digestInto(w); for (let p = 0; p < h.length; p++) h[p] ^= w[p]; }); } return ar(c, l, s, u, w); } /*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) */ const sr = (e) => e[0] === "あいこくしん"; function jt(e) { if (typeof e != "string") throw new TypeError("invalid mnemonic type: " + typeof e); return e.normalize("NFKD"); } function zt(e) { const t = jt(e), n = t.split(" "); if (![12, 15, 18, 21, 24].includes(n.length)) throw new Error("Invalid mnemonic"); return { nfkd: t, words: n }; } function $t(e) { bn(e, 16, 20, 24, 28, 32); } const cr = (e) => { const t = 8 - e.length / 4; return new Uint8Array([gt(e)[0] >> t << t]); }; function Bt(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); }), Ke.chain(Ke.checksum(1, cr), Ke.radix2(11, !0), Ke.alphabet(e)); } function lr(e, t) { const { words: n } = zt(e), r = Bt(t).decode(n); return $t(r), r; } function ur(e, t) { return $t(e), Bt(t).encode(e).join(sr(t) ? " " : " "); } function dr(e, t) { try { lr(e, t); } catch { return !1; } return !0; } const yr = (e) => jt("mnemonic" + e); function pr(e, t = "") { return ir(wn, zt(e).nfkd, yr(t), { c: 2048, dkLen: 64 }); } function hr(e) { if (e.length !== 16) throw new Error("Recovery phrase entropy must be exactly 128 bits (16 bytes)."); return ur(e, qt); } function vr(e) { try { return dr(Gt(e), qt); } catch { return !1; } } function Gt(e) { return e.trim().normalize("NFKD").split(/\s+/u).join(" "); } async function Vt(e) { return pr(Gt(e), ""); } const Ze = mn.id, Ee = "aes-256-gcm-v1", Pe = "bitlogin-bip39-hkdf-v1"; async function Ht(e) { const t = Ie(e.loginName), n = e.now ?? Math.floor(Date.now() / 1e3), { locatorPrivateKey: r, capsuleKey: o } = await me(e.password, t), a = x(r), i = new I(e.vaultRelayUrls, { authPrivateKey: r }); let s; try { s = await Se(i, a, o, e.timeoutMs); } finally { i.closeAll(); } if (!s.quorumMet) throw new ie("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 kt(); const c = hr(En()), l = await Vt(c), { recoveryPrivateKey: u, capsuleKey: d } = wt(l), g = x(u), w = e.everydayPrivateKey !== void 0; if (w && !We(e.everydayPrivateKey)) throw new ie("The provided key is not a valid secp256k1 private key."); const v = w ? e.everydayPrivateKey : Pn(), f = x(v), h = ae(_n()), p = { schema: He, account_id: h, recovery_generation: 0, previous_recovery_event_id: null, operational_private_key: ae(v), operational_public_key: f, recovery_public_key: g, created_at: n, vault_relay_hints: e.vaultRelayUrls, protocol: { capsule_encryption: Ee, recovery_derivation: Pe } }, b = await Mt({ recoveryPrivateKey: u, capsuleKey: d, payload: p }), m = { schema: Le, account_id: h, generation: 0, operational_private_key: ae(v), operational_public_key: f, recovery_public_key: g, recovery_capsule_event: b, created_at: n, vault_relay_hints: e.vaultRelayUrls, protocol: { password_kdf: Ze, capsule_encryption: Ee, recovery_derivation: Pe } }, P = await Xe({ locatorPrivateKey: r, capsuleKey: o, payload: m }), T = new I(e.vaultRelayUrls, { authPrivateKey: u }), E = await ke(T, b, { dTag: Ne, minAcks: e.minAcknowledgements, timeoutMs: e.timeoutMs }); T.closeAll(); const _ = new I(e.vaultRelayUrls, { authPrivateKey: r }), K = await ke(_, P, { dTag: fe, minAcks: e.minAcknowledgements, timeoutMs: e.timeoutMs }); if (_.closeAll(), !E.success || !K.success) throw new ie("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: g, locatorPublicKey: a, accountId: h, imported: w, credentialEvent: P, recoveryEvent: b, credentialPublish: K, recoveryPublish: E }; } async function fr(e) { const { nsecOrHex: t, ...n } = e, r = Wt(t); return Ht({ ...n, everydayPrivateKey: r }); } function Wt(e) { const t = e.trim(); let n; if (t.startsWith("nsec1")) n = kn(t); else if (/^[0-9a-fA-F]{64}$/u.test(t)) n = Fe(t.toLowerCase()); else throw new ie("Enter a valid nsec (nsec1…) or a 64-character hex private key."); if (!We(n)) throw new ie("The provided key is not a valid secp256k1 private key."); return n; } class Ft { map = /* @__PURE__ */ new Map(); async get(t) { return this.map.get(t); } async set(t, n) { this.map.set(t, n); } async delete(t) { this.map.delete(t); } } async function gr(e) { const t = Ie(e.loginName), { locatorPrivateKey: n, capsuleKey: r } = await me(e.password, t), o = x(n), a = new I(e.vaultRelayUrls, { authPrivateKey: n }); try { const i = await Se(a, o, r, e.timeoutMs); if (!i.quorumMet) throw new pe("quorum-not-met"); if (!i.best) throw new pe(i.candidates.length > 0 ? "no-valid-candidate" : "no-matching-event"); const s = i.best.payload, c = e.store ?? new Ft(), l = await Je(c, s.operational_public_key), u = s.generation < l.generation; if (u && !e.acknowledgeRollback) throw new Pt(l.generation, s.generation); const d = u ? `This device previously saw credential generation ${l.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 xt(c, s.operational_public_key, { generation: s.generation }); const g = 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: de(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: d, relayDisagreementWarning: g }; } finally { a.closeAll(); } } function st(e) { return e.filter((t) => le(t)).sort((t, n) => n.created_at - t.created_at)[0]; } async function wr(e) { if (!vr(e.phrase)) throw new Et("This does not look like a valid 12-word BitLogin recovery phrase."); const t = await Vt(e.phrase), { recoveryPrivateKey: n, capsuleKey: r } = wt(t), o = x(n), a = new I(e.vaultRelayUrls, { authPrivateKey: n }); let i; try { i = await tr(a, o, r, e.timeoutMs); } finally { a.closeAll(); } if (e.offlineRecoveryCapsuleEvents?.length) { const f = []; for (const m of e.offlineRecoveryCapsuleEvents) if (le(m)) try { f.push({ event: m, payload: await Ut(m, r) }); } catch (P) { f.push({ event: m, payload: null, error: P.message }); } const h = /* @__PURE__ */ new Map(); for (const m of [...i.candidates, ...f]) h.set(m.event.id, m); const p = [...h.values()].sort((m, P) => P.event.created_at - m.event.created_at), b = p.find((m) => m.payload !== null) ?? null; i = { ...i, candidates: p, best: b, quorumMet: i.quorumMet || b !== null }; } if (!i.quorumMet) throw new pe("quorum-not-met"); if (!i.best) throw new pe(i.candidates.length > 0 ? "no-valid-candidate" : "no-matching-event"); const s = i.best.payload, c = nr(i.candidates), l = de(s.operational_private_key), u = s.operational_public_key, d = [.../* @__PURE__ */ new Set([...e.discoveryRelayUrls, ...s.vault_relay_hints])], g = new I(d); let w = [], v = []; try { const f = await g.queryQuorum({ kinds: [Be], authors: [u], limit: 5 }, e.timeoutMs), h = st(f.outcomes.flatMap((m) => m.events)); h && (w = Un(h)); const p = await g.queryQuorum({ kinds: [Ge], authors: [u], limit: 5 }, e.timeoutMs), b = st(p.outcomes.flatMap((m) => m.events)); b && (v = Dn(b)); } finally { g.closeAll(); } return { everydayPrivateKey: l, everydayPublicKey: u, recoveryPrivateKey: n, recoveryPublicKey: o, recoveryCapsuleKey: r, accountId: s.account_id, currentRecoveryEvent: i.best.event, currentRecoveryPayload: s, generalRelays: w, dmRelays: v, chainWarning: c.consistent ? void 0 : c.warning }; } async function br(e) { const t = e.now ?? Math.floor(Date.now() / 1e3), n = Ie(e.newLoginName), { recovered: r } = e, o = { schema: He, account_id: r.accountId, recovery_generation: r.currentRecoveryPayload.recovery_generation + 1, previous_recovery_event_id: r.currentRecoveryEvent.id, operational_private_key: ae(r.everydayPrivateKey), operational_public_key: r.everydayPublicKey, recovery_public_key: r.recoveryPublicKey, created_at: _t(r.currentRecoveryEvent.created_at, t), vault_relay_hints: e.vaultRelayUrls, protocol: { capsule_encryption: Ee, recovery_derivation: Pe } }, a = await Mt({ recoveryPrivateKey: r.recoveryPrivateKey, capsuleKey: r.recoveryCapsuleKey, payload: o }), i = new I(e.vaultRelayUrls, { authPrivateKey: r.recoveryPrivateKey }), s = await ke(i, a, { dTag: Ne, minAcks: e.minAcknowledgements, timeoutMs: e.timeoutMs }); i.closeAll(); const { locatorPrivateKey: c, capsuleKey: l } = await me(e.newPassword, n), u = x(c), d = { schema: Le, account_id: r.accountId, generation: 0, operational_private_key: ae(r.everydayPrivateKey), operational_public_key: r.everydayPublicKey, recovery_public_key: r.recoveryPublicKey, recovery_capsule_event: a, created_at: t, vault_relay_hints: e.vaultRelayUrls, protocol: { password_kdf: Ze, capsule_encryption: Ee, recovery_derivation: Pe } }, g = await Xe({ locatorPrivateKey: c, capsuleKey: l, payload: d }), w = new I(e.vaultRelayUrls, { authPrivateKey: c }), v = await ke(w, g, { dTag: fe, minAcks: e.minAcknowledgements, timeoutMs: e.timeoutMs }); if (w.closeAll(), !s.success || !v.success) throw new Et("Could not publish the refreshed recovery and credential capsules to enough relays. Please retry."); return { normalizedLoginName: n, locatorPublicKey: u, credentialEvent: g, refreshedRecoveryEvent: a, credentialPublish: v, recoveryPublish: s }; } function mr(e) { const t = x(e.privateKey); return Z({ pubkey: t, created_at: e.createdAt, kind: Kn, tags: [ ["e", e.eventIdToDelete], ["k", String(e.deletedEventKind)] ], content: e.reason ?? "" }, e.privateKey); } async function kr(e) { const t = e.now ?? Math.floor(Date.now() / 1e3), n = Ie(e.loginName), r = await me(e.oldPassword, n), o = x(r.locatorPrivateKey), a = new I(e.vaultRelayUrls, { authPrivateKey: r.locatorPrivateKey }); let i; try { i = await Se(a, o, r.capsuleKey, e.timeoutMs); } finally { a.closeAll(); } if (!i.quorumMet) throw new pe("quorum-not-met"); if (!i.best) throw new pe(i.candidates.length > 0 ? "no-valid-candidate" : "no-matching-event"); const s = i.best.payload, c = i.best.event, l = e.store ?? new Ft(), u = await Je(l, s.operational_public_key); if (s.generation < u.generation && !e.acknowledgeRollback) throw new Pt(u.generation, s.generation); const d = await me(e.newPassword, n), g = x(d.locatorPrivateKey), w = new I(e.vaultRelayUrls, { authPrivateKey: d.locatorPrivateKey }); let v; try { v = await Se(w, g, d.capsuleKey, e.timeoutMs); } finally { w.closeAll(); } if (!v.quorumMet) throw new ie("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 kt("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, h = { schema: Le, 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: Ze, capsule_encryption: Ee, recovery_derivation: Pe } }, p = await Xe({ locatorPrivateKey: d.locatorPrivateKey, capsuleKey: d.capsuleKey, payload: h }), b = new I(e.vaultRelayUrls, { authPrivateKey: d.locatorPrivateKey }), m = await ke(b, p, { dTag: fe, minAcks: e.minAcknowledgements, timeoutMs: e.timeoutMs }); b.closeAll(); const P = Xn({ oldLocatorPrivateKey: r.locatorPrivateKey, createdAt: _t(c.created_at, t) }), T = mr({ privateKey: r.locatorPrivateKey, eventIdToDelete: c.id, deletedEventKind: he, createdAt: t }), E = new I(e.vaultRelayUrls, { authPrivateKey: r.locatorPrivateKey }), [_, K] = await Promise.all([ E.publishAll(P, e.timeoutMs), E.publishAll(T, e.timeoutMs) ]); if (E.closeAll(), !m.success) throw new ie("The new credential capsule did not reach the required relay acknowledgement and readback quorum. Please retry."); return await xt(l, s.operational_public_key, { generation: f }), { normalizedLoginName: n, oldLocatorPublicKey: o, newLocatorPublicKey: g, newGeneration: f, recoveryPublicKey: s.recovery_public_key, recoveryCapsuleEvent: s.recovery_capsule_event, newCredentialEvent: p, tombstoneEvent: P, deletionRequestEvent: T, newCredentialPublish: m, tombstoneAcknowledgedCount: ne(_), deletionAcknowledgedCount: ne(K) }; } /*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */ function Er(e) { return e instanceof Uint8Array || ArrayBuffer.isView(e) && e.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in e && e.BYTES_PER_ELEMENT === 1; } function ct(e) { if (typeof e != "boolean") throw new TypeError(`boolean expected, not ${e}`); } function Me(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 L(e, t, n = "") { const r = Er(e), o = e?.length, a = t !== void 0; if (!r || a && o !== t) { const i = n && `"${n}" `, s = a ? ` of length ${t}` : "", c = r ? `length=${o}` : `type=${typeof e}`, l = i + "expected Uint8Array" + s + ", got " + c; throw r ? new RangeError(l) : new TypeError(l); } return e; } function A(e) { return new Uint32Array(e.buffer, e.byteOffset, Math.floor(e.byteLength / 4)); } function ce(...e) { for (let t = 0; t < e.length; t++) e[t].fill(0); } const W = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68, Pr = (e) => e << 24 & 4278190080 | e << 8 & 16711680 | e >>> 8 & 65280 | e >>> 24 & 255, _r = (e) => { for (let t = 0; t < e.length; t++) e[t] = Pr(e[t]); return e; }, N = W ? (e) => e : _r; function Kr(e, t) { return !e.byteLength || !t.byteLength ? !1 : e.buffer === t.buffer && // best we can do, may fail with an obscure Proxy e.byteOffset < t.byteOffset + t.byteLength && // a starts before b end t.byteOffset < e.byteOffset + e.byteLength; } function Jt(e, t) { if (Kr(e, t) && e.byteOffset < t.byteOffset) throw new Error("complex overlap of input and output is not supported"); } function xr(e, t) { if (t == null || typeof t != "object") throw new Error("options must be defined"); return Object.assign(e, t); } const Rr = /* @__NO_SIDE_EFFECTS__ */ (e, t) => { function n(r, ...o) { if (L(r, void 0, "key"), e.nonceLength !== void 0) { const u = o[0]; L(u, e.varSizeNonce ? void 0 : e.nonceLength, "nonce"); } const a = e.tagLength; a && o[1] !== void 0 && L(o[1], void 0, "AAD"); const i = t(r, ...o), s = (u, d) => { if (d !== void 0) { if (u !== 2) throw new Error("cipher output not supported"); L(d, void 0, "output"); } }; let c = !1; return { encrypt(u, d) { if (c) throw new Error("cannot encrypt() twice with same key + nonce"); return c = !0, L(u), s(i.encrypt.length, d), i.encrypt(u, d); }, decrypt(u, d) { if (L(u), a && u.length < a) throw new Error('"ciphertext" expected length bigger than tagLength=' + a); return s(i.decrypt.length, d), i.decrypt(u, d); } }; } return Object.assign(n, e), n; }; function et(e, t, n = !0) { if (t === void 0) return new Uint8Array(e); if (L(t, void 0, "output"), t.length !== e) throw new Error('"output" expected Uint8Array of length ' + e + ", got: " + t.length); if (n && !X(t)) throw new Error("invalid output, must be aligned"); return t; } function X(e) { return e.byteOffset % 4 === 0; } function se(e) { return Uint8Array.from(L(e)); } const Yt = (e) => Uint8Array.from(e.split(""), (t) => t.charCodeAt(0)), Ar = N(A(Yt("expand 16-byte k"))), Cr = N(A(Yt("expand 32-byte k"))); function k(e, t) { return e << t | e >>> 32 - t; } const ge = 64, Sr = 16, qe = 2 ** 32 - 1, lt = /* @__PURE__ */ Uint32Array.of(); function Lr(e, t, n, r, o, a, i, s) { const c = o.length, l = new Uint8Array(ge), u = A(l), d = W && X(o) && X(a), g = d ? A(o) : lt, w = d ? A(a) : lt; if (!W) { for (let v = 0; v < c; i++) { if (e(t, n, r, u, i, s), N(u), i >= qe) throw new Error("arx: counter overflow"); const f = Math.min(ge, c - v); for (let h = 0, p; h < f; h++) p = v + h, a[p] = o[p] ^ l[h]; v += f; } return; } for (let v = 0; v < c; i++) { if (e(t, n, r, u, i, s), i >= qe) throw new Error("arx: counter overflow"); const f = Math.min(ge, c - v); if (d && f === ge) { const h = v / 4; if (v % 4 !== 0) throw new Error("arx: invalid block position"); for (let p = 0, b; p < Sr; p++) b = h + p, w[b] = g[b] ^ u[p]; v += ge; continue; } for (let h = 0, p; h < f; h++) p = v + h, a[p] = o[p] ^ l[h]; v += f; } } function Nr(e, t) { const { allowShortKeys: n, extendNonceFn: r, counterLength: o, counterRight: a, rounds: i } = xr({ allowShortKeys: !1, counterLength: 8, counterRight: !1, rounds: 20 }, t); if (typeof e != "function") throw new Error("core must be a function"); return Me(o), Me(i), ct(a), ct(n), (s, c, l, u, d = 0) => { L(s, void 0, "key"), L(c, void 0, "nonce"), L(l, void 0, "data"); const g = l.length; if (u = et(g, u, !1), Me(d), d < 0 || d >= qe) throw new Error("arx: counter overflow"); const w = []; let v = s.length, f, h; if (v === 32) w.push(f = se(s)), h = Cr; else if (v === 16 && n) f = new Uint8Array(32), f.set(s), f.set(s, 16), h = Ar, w.push(f); else throw L(s, 32, "arx key"), new Error("invalid key size"); (!W || !X(c)) && w.push(c = se(c)); let p = A(f); if (r) { if (c.length !== 24) throw new Error("arx: extended nonce must be 24 bytes"); const P = c.subarray(0, 16); if (W) r(h, p, A(P), p); else { const T = N(Uint32Array.from(h)); r(T, p, A(P), p), ce(T), N(p); } c = c.subarray(16); } else W || N(p); const b = 16 - o; if (b !== c.length) throw new Error(`arx: nonce must be ${b} or 16 bytes`); if (b !== 12) { const P = new Uint8Array(12); P.set(c, a ? 0 : 12 - c.length), c = P, w.push(c); } const m = N(A(c)); try { return Lr(e, h, p, m, l, u, d, i), u; } finally { ce(...w); } }; } function Ir(e, t, n, r, o, a = 20) { let i = e[0], s = e[1], c = e[2], l = e[3], u = t[0], d = t[1], g = t[2], w = t[3], v = t[4], f = t[5], h = t[6], p = t[7], b = o, m = n[0], P = n[1], T = n[2], E = i, _ = s, K = c, S = l, O = u, M = d, U = g, D = w, q = v, j = f, z = h, $ = p, B = b, G = m, V = P, H = T; for (let ot = 0; ot < a; ot += 2) E = E + O | 0, B = k(B ^ E, 16), q = q + B | 0, O = k(O ^ q, 12), E = E + O | 0, B = k(B ^ E, 8), q = q + B | 0, O = k(O ^ q, 7), _ = _ + M | 0, G = k(G ^ _, 16), j = j + G | 0, M = k(M ^ j, 12), _ = _ + M | 0, G = k(G ^ _, 8), j = j + G | 0, M = k(M ^ j, 7), K = K + U | 0, V = k(V ^ K, 16), z = z + V | 0, U = k(U ^ z, 12), K = K + U | 0, V = k(V ^ K, 8), z = z + V | 0, U = k(U ^ z, 7), S = S + D | 0, H = k(H ^ S, 16), $ = $ + H | 0, D = k(D ^ $, 12), S = S + D | 0, H = k(H ^ S, 8), $ = $ + H | 0, D = k(D ^ $, 7), E = E + M | 0, H = k(H ^ E, 16), z = z + H | 0, M = k(M ^ z, 12), E = E + M | 0, H = k(H ^ E, 8), z = z + H | 0, M = k(M ^ z, 7), _ = _ + U | 0, B = k(B ^ _, 16), $ = $ + B | 0, U = k(U ^ $, 12), _ = _ + U | 0, B = k(B ^ _, 8), $ = $ + B | 0, U = k(U ^ $, 7), K = K + D | 0, G = k(G ^ K, 16), q = q + G | 0, D = k(D ^ q, 12), K = K + D | 0, G = k(G ^ K, 8), q = q + G | 0, D = k(D ^ q, 7), S = S + O | 0, V = k(V ^ S, 16), j = j + V | 0, O = k(O ^ j, 12), S = S + O | 0, V = k(V ^ S, 8), j = j + V | 0, O = k(O ^ j, 7); let C = 0; r[C++] = i + E | 0, r[C++] = s + _ | 0, r[C++] = c + K | 0, r[C++] = l + S | 0, r[C++] = u + O | 0, r[C++] = d + M | 0, r[C++] = g + U | 0, r[C++] = w + D | 0, r[C++] = v + q | 0, r[C++] = f + j | 0, r[C++] = h + z | 0, r[C++] = p + $ | 0, r[C++] = b + B | 0, r[C++] = m + G | 0, r[C++] = P + V | 0, r[C++] = T + H | 0; } const Qt = /* @__PURE__ */ Nr(Ir, { counterRight: !1, counterLength: 4, allowShortKeys: !1 }), Xt = 2, je = 1, Zt = 65536, ze = 4294967295; function ut(e, t) { const n = Te(new Uint8Array([2]), Fe(t)), o = mt.getSharedSecret(e, n, !0).slice(1, 33); return xn(ve("nip44-v2"), o); } function en(e, t) { const n = An(e, t, 76); return { chachaKey: n.slice(0, 32), chachaNonce: n.slice(32, 44), hmacKey: n.slice(44, 76) }; } function tn(e) { if (e <= 32) return 32; const t = 2 ** Math.floor(Math.log2(e - 1) + 1), n = t <= 256 ? 32 : t / 8; return n * (Math.floor((e - 1) / n) + 1); } function Tr(e) { if (e < Zt) { const n = new Uint8Array(2); return new DataView(n.buffer).setUint16(0, e, !1), n; } const t = new Uint8Array(6); return new DataView(t.buffer).setUint32(2, e, !1), t; } function Or(e) { const t = e.length; if (t < je || t > ze) throw new Error(`NIP-44 plaintext length must be between ${je} and ${ze} bytes.`); const n = Tr(t), r = tn(t), o = new Uint8Array(n.length + r); return o.set(n, 0), o.set(e, n.length), o; } function Mr(e) { const t = new DataView(e.buffer, e.byteOffset, e.byteLength), n = t.getUint16(0, !1); let r, o; if (n === 0) { if (r = t.getUint32(2, !1), o = 6, r < Zt) throw new Error("NIP-44 payload has inconsistent padding."); } else r = n, o = 2; if (r < je || r > ze || e.length !== o + tn(r)) throw new Error("NIP-44 payload has inconsistent padding."); return e.slice(o, o + r); } function nn(e, t, n) { return ft(gt, e, Te(t, n)); } function Ur(e, t, n) { const r = bt(32), { chachaKey: o, chachaNonce: a, hmacKey: i } = en(e, r), s = Or(ve(t)), c = Qt(o, a, s), l = nn(i, r, c); return ye.encode(Te(new Uint8Array([Xt]), r, c, l)); } function Dr(e, t) { const n = ye.decode(t); if (n[0] !== Xt) throw new Error(`Unsupported NIP-44 version: ${n[0]}`); const r = n.slice(1, 33), o = n.slice(n.length - 32), a = n.slice(33, n.length - 32), { chachaKey: i, chachaNonce: s, hmacKey: c } = en(e, r), l = nn(c, r, a); if (!Rn(o, l)) throw new Error("NIP-44 MAC verification failed: payload is corrupted, tampered, or uses the wrong key."); const u = Qt(i, s, a); return Ve(Mr(u)); } const re = 16, qr = 283; function jr(e) { if (![16, 24, 32].includes(e.length)) throw new Error('"aes key" expected Uint8Array of length 16/24/32, got length=' + e.length); } function tt(e) { return e << 1 ^ qr & -(e >> 7); } function ue(e, t) { let n = 0; for (; t > 0; t >>= 1) n ^= e & -(t & 1), e = tt(e); return n; } const $e = /* @__PURE__ */ (() => { const e = new Uint8Array(256); for (let n = 0, r = 1; n < 256; n++, r ^= tt(r)) e[n] = r; const t = new Uint8Array(256); t[0] = 99; for (let n = 0; n < 255; n++) { let r = e[255 - n]; r |= r << 8, t[e[n]] = (r ^ r >> 4 ^ r >> 5 ^ r >> 6 ^ r >> 7 ^ 99) & 255; } return ce(e), t; })(), zr = /* @__PURE__ */ $e.map((e, t) => $e.indexOf(t)), $r = (e) => e << 24 | e >>> 8, Ue = (e) => e << 8 | e >>> 24; function rn(e, t) { if (e.length !== 256) throw new Error("Wrong sbox length"); const n = new Uint32Array(256).map((l, u) => t(e[u])), r = n.map(Ue), o = r.map(Ue), a = o.map(Ue), i = new Uint32Array(256 * 256), s = new Uint32Array(256 * 256), c = new Uint16Array(256 * 256); for (let l = 0; l < 256; l++) for (let u = 0; u < 256; u++) { const d = l * 256 + u; i[d] = n[l] ^ r[u], s[d] = o[l] ^ a[u], c[d] = e[l] << 8 | e[u]; } return { sbox: e, sbox2: c, T0: n, T1: r, T2: o, T3: a, T01: i, T23: s }; } const nt = /* @__PURE__ */ rn($e, (e) => ue(e, 3) << 24 | e << 16 | e << 8 | ue(e, 2)), on = /* @__PURE__ */ rn(zr, (e) => ue(e, 11) << 24 | ue(e, 13) << 16 | ue(e, 9) << 8 | ue(e, 14)), Br = /* @__PURE__ */ (() => { const e = new Uint8Array(16); for (let t = 0, n = 1; t < 16; t++, n = tt(n)) e[t] = n; return e; })(); function an(e) { L(e); const t = e.length; jr(e); const { sbox2: n } = nt, r = []; (!W || !X(e)) && r.push(e = se(e)); const o = N(A(e)), a = o.length, i = (c) => J(n, c, c, c, c), s = new Uint32Array(t + 28); s.set(o); for (let c = a; c < s.length; c++) { let l = s[c - 1]; c % a === 0 ? l = i($r(l)) ^ Br[c / a - 1] : a > 6 && c % a === 4 && (l = i(l)), s[c] = s[c - a] ^ l; } return ce(...r), s; } function Gr(e) { const t = an(e), n = t.slice(), r = t.length, { sbox2: o } = nt, { T0: a, T1: i, T2: s, T3: c } = on; for (let l = 0; l < r; l += 4) for (let u = 0; u < 4; u++) n[l + u] = t[r - l - 4 + u]; ce(t); for (let l = 4; l < r - 4; l++) { const u = n[l], d = J(o, u, u, u, u); n[l] = a[d & 255] ^ i[d >>> 8 & 255] ^ s[d >>> 16 & 255] ^ c[d >>> 24]; } return n; } function te(e, t, n, r, o, a) { return e[n << 8 & 65280 | r >>> 8 & 255] ^ t[o >>> 8 & 65280 | a >>> 24 & 255]; } function J(e, t, n, r, o) { return e[t & 255 | n & 65280] | e[r >>> 16 & 255 | o >>> 16 & 65280] << 16; } function dt(e, t, n, r, o) { const { sbox2: a, T01: i, T23: s } = nt; let c = 0; t ^= e[c++], n ^= e[c++], r ^= e[c++], o ^= e[c++]; const l = e.length / 4 - 2; for (let v = 0; v < l; v++) { const f = e[c++] ^ te(i, s, t, n, r, o), h = e[c++] ^ te(i, s, n, r, o, t), p = e[c++] ^ te(i, s, r, o, t, n), b = e[c++] ^ te(i, s, o, t, n, r); t = f, n = h, r = p, o = b; } const u = e[c++] ^ J(a, t, n, r, o), d = e[c++] ^ J(a, n, r, o, t), g = e[c++] ^ J(a, r, o, t, n), w = e[c++] ^ J(a, o, t, n, r); return { s0: u, s1: d, s2: g, s3: w }; } function Vr(e, t, n, r, o) { const { sbox2: a, T01: i, T23: s } = on; let c = 0; t ^= e[c++], n ^= e[c++], r ^= e[c++], o ^= e[c++]; const l = e.length / 4 - 2; for (let v = 0; v < l; v++) { const f = e[c++] ^ te(i, s, t, o, r, n), h = e[c++] ^ te(i, s, n, t, o, r), p = e[c++] ^ te(i, s, r, n, t, o), b = e[c++] ^ te(i, s, o, r, n, t); t = f, n = h, r = p, o = b; } const u = e[c++] ^ J(a, t, o, r, n), d = e[c++] ^ J(a, n, t, o, r), g = e[c++] ^ J(a, r, n, t, o), w = e[c++] ^ J(a, o, r, n, t); return { s0: u, s1: d, s2: g, s3: w }; } function Hr(e) { if (L(e), e.length % re !== 0) throw new Error("aes-(cbc/ecb).decrypt ciphertext should consist of blocks with size " + re); } function Wr(e, t, n) { L(e); let r = e.length; const o = r % re; if (!t && o !== 0) throw new Error("aec/(cbc-ecb): unpadded plaintext with disabled padding"); if (t) { let s = re - o; s || (s = re), r = r + s; } n = et(r, n), Jt(e, n), (!W || !X(e)) && (e = se(e)); const a = A(e); N(a); const i = A(n); return { b: a, o: i, out: n }; } function Fr(e, t) { if (!t) return e; const n = e.length; if (n === 0) throw new Error("aes/pkcs7: empty ciphertext not allowed"); const r = e[n - 1]; let o = 1; o &= r - 1 >>> 31 ^ 1, o &= 16 - r >>> 31 ^ 1; for (let a = 0; a < 16; a++) { const i = a - r >>> 31, s = (e[n - 1 - a] ^ r) === 0 ? 1 : 0; o &= s | i ^ 1; } if (!o) throw new Error("aes/pkcs7: wrong padding"); return e.subarray(0, n - r); } function Jr(e) { const t = new Uint8Array(16), n = A(t); t.set(e); const r = re - e.length; for (let o = re - r; o < re; o++) t[o] = r; return n; } const sn = /* @__PURE__ */ Rr({ blockSize: 16, nonceLength: 16 }, function(t, n, r = {}) { const o = !r.disablePadding; return { encrypt(a, i) { const s = an(t), { b: c, o: l, out: u } = Wr(a, o, i); let d = n; const g = [s]; (!W || !X(d)) && g.push(d = se(d)); const w = A(d); N(w); let v = w[0], f = w[1], h = w[2], p = w[3], b = 0; for (; b + 4 <= c.length; ) v ^= c[b + 0], f ^= c[b + 1], h ^= c[b + 2], p ^= c[b + 3], { s0: v, s1: f, s2: h, s3: p } = dt(s, v, f, h, p), l[b++] = v, l[b++] = f, l[b++] = h, l[b++] = p; if (o) { const m = Jr(a.subarray(b * 4)); N(m), v ^= m[0], f ^= m[1], h ^= m[2], p ^= m[3], { s0: v, s1: f, s2: h, s3: p } = dt(s, v, f, h, p), l[b++] = v, l[b++] = f, l[b++] = h, l[b++] = p; } return N(l), ce(...g), u; }, decrypt(a, i) { Hr(a); const s = Gr(t); let c = n; const l = [s]; (!W || !X(c)) && l.push(c = se(c)); const u = A(c); N(u), i = et(a.length, i), Jt(a, i), (!W || !X(a)) && l.push(a = se(a)); const d = A(a), g = A(i); N(d); let w = u[0], v = u[1], f = u[2], h = u[3]; for (let p = 0; p + 4 <= d.length; ) { const b = w, m = v, P = f, T = h; w = d[p + 0], v = d[p + 1], f = d[p + 2], h = d[p + 3]; const { s0: E, s1: _, s2: K, s3: S } = Vr(s, w, v, f, h); g[p++] = E ^ b, g[p++] = _ ^ m, g[p++] = K ^ P, g[p++] = S ^ T; } return N(g), ce(...l), Fr(i, o); } }; }); function cn(e, t) { const n = Te(new Uint8Array([2]), Fe(t)); return mt.getSharedSecret(e, n, !0).slice(1, 33); } function Yr(e, t, n, r) { const o = cn(e, t), a = bt(16), i = sn(o, a).encrypt(ve(n)); return `${ye.encode(i)}?iv=${ye.encode(a)}`; } function Qr(e, t, n) { const r = n.indexOf("?iv="); if (r === -1) throw new Error('NIP-04 payload is missing its "?iv=" suffix.'); const o = ye.decode(n.slice(0, r)), a = ye.decode(n.slice(r + 4)), i = cn(e, t), s = sn(i, a).decrypt(o); return Ve(s); } function Xr(...e) { for (const t of e) t && t.fill(0); } class xe { privateKey; publicKeyHex; destroyed = !1; constructor(t) { this.privateKey = t, this.publicKeyHex = x(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(), Z({ 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, n) { return this.assertAlive(), Ur(ut(this.privateKey, t), n); } nip44Decrypt(t, n) { return this.assertAlive(), Dr(ut(this.privateKey, t), n); } /** Legacy relative to nip44Encrypt above, but still what a real NIP-07 extension exposes as * window.nostr.nip04.encrypt -- implemented for drop-in parity. */ nip04Encrypt(t, n) { return this.assertAlive(), Yr(this.privateKey, t, n); } nip04Decrypt(t, n) { return this.assertAlive(), Qr(this.privateKey, t, n); } /** Best-practical secret wipe (§11.10, §21.4): overwrites the private key buffer in place. */ destroy() { Xr(this.privateKey), this.destroyed = !0; } } const Zr = [ "wss://relay.damus.io", "wss://nos.lol", "wss://relay.nostr.band", "wss://nostr.wine", "wss://relay.snort.social" ], eo = [ "wss://purplepag.es", "wss://relay.nostr.band", "wss://nostr-pub.wellorder.net" ], to = "bitlogin", ee = "kv", F = "device-keys", no = 2; function ro() { return new Promise((e, t) => { const n = indexedDB.open(to, no); n.onupgradeneeded = () => { const r = n.result; r.objectStoreNames.contains(ee) || r.createObjectStore(ee), r.objectStoreNames.contains(F) || r.createObjectStore(F); }, n.onsuccess = () => e(n.result), n.onerror = () => t(n.error); }); } class oo { dbPromise = null; db() { return this.dbPromise || (this.dbPromise = ro()), this.dbPromise; } async get(t) { const n = await this.db(); return new Promise((r, o) => { const i = n.transaction(ee, "readonly").objectStore(ee).get(t); i.onsuccess = () => r(i.result), i.onerror = () => o(i.error); }); } async set(t, n) { const r = await this.db(); return new Promise((o, a) => { const i = r.transaction(ee, "readwrite"); i.objectStore(ee).put(n, t), i.oncomplete = () => o(), i.onerror = () => a(i.error); }); } async delete(t) { const n = await this.db(); return new Promise((r, o) => { const a = n.transaction(ee, "readwrite"); a.objectStore(ee).delete(t), a.oncomplete = () => r(), a.onerror = () => o(a.error); }); } /** * Returns a non-extractable AES-GCM key kept by the browser's IndexedDB * implementation. The key is deliberately separate from the string-only KV * API so callers cannot accidentally serialize it as application data. */ async getOrCreateDeviceKey(t) { const n = await this.db(), r = await new Promise((a, i) => { const s = n.transaction(F, "readonly").objectStore(F).get(t); s.onsuccess = () => a(s.result), s.onerror = () => i(s.error); }); if (r) return r; const o = await crypto.subtle.generateKey( { name: "AES-GCM", length: 256 }, !1, ["encrypt", "decrypt"] ); try { return await new Promise((a, i) => { const s = n.transaction(F, "readwrite"); s.objectStore(F).add(o, t), s.oncomplete = () => a(), s.onerror = () => i(s.error); }), o; } catch { const a = await new Promise((i, s) => { const c = n.transaction(F, "readonly").objectStore(F).get(t); c.onsuccess = () => i(c.result), c.onerror = () => s(c.error); }); if (a) return a; throw new Error("Unable to create the browser-bound session key."); } } async deleteDeviceKey(t) { const n = await this.db(); return new Promise((r, o) => { const a = n.transaction(F, "readwrite"); a.objectStore(F).delete(t), a.oncomplete = () => r(), a.onerror = () => o(a.error); }); } } const _e = "bitlogin:session:v1", rt = "bitlogin:session-device-key:v1"; function yt(e) { let t = ""; for (const n of e) t += String.fromCharCode(n); return btoa(t); } function pt(e) { const t = atob(e); return Uint8Array.from(t, (n) => n.charCodeAt(0)); } function ht(e) { const t = new Uint8Array(e.byteLength); return t.set(e), t.buffer; } function ao(e) { return !!(e && typeof e == "object" && e.v === 2 && typeof e.iv == "string" && typeof e.ciphertext == "string"); } async function io(e, t) { const n = { everydayPrivateKeyHex: Array.from(t.everydayPrivateKey, (r) => r.toString(16).padStart(2, "0")).join(""), accountId: t.accountId, recoveryPublicKey: t.recoveryPublicKey, activeCredentialEvent: t.activeCredentialEvent, activeRecoveryEvent: t.activeRecoveryEvent }; try { if (typeof e.getOrCreateDeviceKey != "function") { await e.delete(_e); return; } const r = await e.getOrCreateDeviceKey(rt), o = crypto.getRandomValues(new Uint8Array(12)), a = new TextEncoder().encode(JSON.stringify(n)), i = await crypto.subtle.encrypt({ name: "AES-GCM", iv: o }, r, a), s = { v: 2, iv: yt(o), ciphertext: yt(new Uint8Array(i)) }; await e.set(_e, JSON.stringify(s)); } catch { } } async function so(e) { let t; try { t = await e.get(_e); } catch { return null; } if (!t) return null; try { const n = JSON.parse(t); if (!ao(n) || typeof e.getOrCreateDeviceKey != "function") return await e.delete(_e), null; const r = await e.getOrCreateDeviceKey(rt), o = await crypto.subtle.decrypt( { name: "AES-GCM", iv: ht(pt(n.iv)) }, r, ht(pt(n.ciphertext)) ), a = JSON.parse(new TextDecoder().decode(o)); return typeof a.everydayPrivateKeyHex != "string" || typeof a.accountId != "string" || typeof a.recoveryPublicKey != "string" || !a.activeCredentialEvent || !a.activeRecoveryEvent ? null : { everydayPrivateKey: Uint8Array.from( a.everydayPrivateKeyHex.match(/.{1,2}/g) || [], (i) => Number.parseInt(i, 16) ), accountId: a.accountId, recoveryPublicKey: a.recoveryPublicKey, activeCredentialEvent: a.activeCredentialEvent, activeRecoveryEvent: a.activeRecoveryEvent }; } catch { return null; } } async function co(e) { try { await e.delete(_e), typeof e.deleteDeviceKey == "function" && await e.deleteDeviceKey(rt); } catch { } } const y = { signer: null, everydayPrivateKey: null, accountId: null, recoveryPublicKey: null, activeCredentialEvent: null, activeRecoveryEvent: null, pendingRecovery: null }; let Y = [...Zr], De = [...eo]; const be = new oo(); function Q() { if (!y.signer || !y.everydayPrivateKey) throw new Error("No identity is unlocked in this session."); return { signer: y.signer, everydayPrivateKey: y.everydayPrivateKey }; } function we() { y.signer?.destroy(), y.everydayPrivateKey && y.everydayPrivateKey.fill(0), y.signer = null, y.everydayPrivateKey = null, y.accountId = null, y.recoveryPublicKey = null, y.activeCredentialEvent = null, y.activeRecoveryEvent = null, y.pendingRecovery && (y.pendingRecovery.recoveryPrivateKey.fill(0), y.pendingRecovery.everydayPrivateKey.fill(0), y.pendingRecovery = null); } async function Re() { !y.everydayPrivateKey || !y.accountId || !y.recoveryPublicKey || !y.activeCredentialEvent || !y.activeRecoveryEvent || await io(be, { everydayPrivateKey: y.everydayPrivateKey, accountId: y.accountId, recoveryPublicKey: y.recoveryPublicKey, activeCredentialEvent: y.activeCredentialEvent, activeRecoveryEvent: y.activeRecoveryEvent }); } async function lo(e, t) { switch (e) { case "configure": { const n = t; return n.vaultRelayUrls?.length && (Y = n.vaultRelayUrls), n.discoveryRelayUrls?.length && (De = n.discoveryRelayUrls), {}; } case "register": { const n = t, r = n.importKey ? await fr({ nsecOrHex: n.importKey, loginName: n.loginName, password: n.password, vaultRelayUrls: Y }) : await Ht({ loginName: n.loginName, password: n.password, vaultRelayUrls: Y }); return we(), y.signer = new xe(r.everydayPrivateKey), y.everydayPrivateKey = r.everydayPrivateKey, y.accountId = r.accountId, y.recoveryPublicKey = r.recoveryPublicKey, y.activeCredentialEvent = r.credentialEvent, y.activeRecoveryEvent = r.recoveryEvent, await Re(), { recoveryPhrase: r.recoveryPhrase, everydayPublicKey: r.everydayPublicKey, recoveryPublicKey: r.recoveryPublicKey, accountId: r.accountId, imported: r.imported, credentialEventId: r.credentialEvent.id, recoveryEventId: r.recoveryEvent.id }; } case "previewImportKey": { const r = Wt(t.nsecOrHex), o = x(r), a = { everydayPublicKey: o, npub: it(o) }; return r.fill(0), a; } case "login": { const n = t, r = await gr({ loginName: n.loginName, password: n.password, vaultRelayUrls: Y, store: be, acknowledgeRollback: n.acknowledgeRollback }); return we(), y.signer = new xe(r.everydayPrivateKey), y.everydayPrivateKey = r.everydayPrivateKey, y.accountId = r.accountId, y.recoveryPublicKey = r.recoveryPublicKey, y.activeCredentialEvent = r.credentialEvent, y.activeRecoveryEvent = r.recoveryCapsuleEvent, await Re(), { everydayPublicKey: r.everydayPublicKey, accountId: r.accountId, generation: r.generation, rollbackWarning: r.rollbackWarning, relayDisagreementWarning: r.relayDisagreementWarning }; } case "recover": { const n = t, r = await wr({ phrase: n.phrase, vaultRelayUrls: Y, discoveryRelayUrls: De, offlineRecoveryCapsuleEvents: n.offlineExportFile?.recovery_capsule_events }); return we(), y.pendingRecovery = r, y.signer = new xe(r.everydayPrivateKey), y.everydayPrivateKey = r.everydayPrivateKey, y.accountId = r.accountId, y.recoveryPublicKey = r.recoveryPublicKey, y.activeRecoveryEvent = r.currentRecoveryEvent, { everydayPublicKey: r.everydayPublicKey, accountId: r.accountId, generalRelays: r.generalRelays, dmRelays: r.dmRelays, chainWarning: r.chainWarning }; } case "completeRecovery": { const n = t; if (!y.pendingRecovery) throw new Error("No recovery is in progress in this session."); const r = await br({ recovered: y.pendingRecovery, newLoginName: n.newLoginName, newPassword: n.newPassword, vaultRelayUrls: Y }); return y.activeCredentialEvent = r.credentialEvent, y.activeRecoveryEvent = r.refreshedRecoveryEvent, y.pendingRecovery.recoveryPrivateKey.fill(0), y.pendingRecovery = null, await Re(), { locatorPublicKey: r.locatorPublicKey, credentialEventId: r.credentialEvent.id, refreshedRecoveryEventId: r.refreshedRecoveryEvent.id }; } case "changePassword": { const n = t, r = await kr({ loginName: n.loginName, oldPassword: n.oldPassword, newPassword: n.newPassword, vaultRelayUrls: Y, store: be, acknowledgeRollback: n.acknowledgeRollback }); return y.activeCredentialEvent = r.newCredentialEvent, y.recoveryPublicKey = r.recoveryPublicKey, y.activeRecoveryEvent = r.recoveryCapsuleEvent, await Re(), { newLocatorPublicKey: r.newLocatorPublicKey, newGeneration: r.newGeneration, tombstoneAcknowledgedCount: r.tombstoneAcknowledgedCount, deletionAcknowledgedCount: r.deletionAcknowledgedCount }; } case "publishProfileAndRelayLists": { const n = t, { everydayPrivateKey: r } = Q(); return qn({ everydayPrivateKey: r, name: n.name, about: n.about, picture: n.picture, generalRelays: n.generalRelays, dmRelays: n.dmRelays, discoveryRelays: De }); } case "getPublicKey": { const { signer: n } = Q(); return { publicKey: n.getPublicKey() }; } case "signEvent": { const { signer: n } = Q(), r = t; return n.signEvent({ kind: r.kind, tags: r.tags, content: r.content, created_at: r.created_at }); } case "nip44Encrypt": { const { signer: n } = Q(), r = t; return { ciphertext: n.nip44Encrypt(r.peerPublicKey, r.plaintext) }; } case "nip44Decrypt": { const { signer: n } = Q(), r = t; return { plaintext: n.nip44Decrypt(r.peerPublicKey, r.payload) }; } case "nip04Encrypt": { const { signer: n } = Q(), r = t; return { ciphertext: n.nip04Encrypt(r.peerPublicKey, r.plaintext) }; } case "nip04Decrypt": { const { signer: n } = Q(), r = t; return { plaintext: n.nip04Decrypt(r.peerPublicKey, r.payload) }; } case "exportIdentity": { const { everydayPrivateKey: n, signer: r } = Q(); return { nsec: Sn(n), npub: it(r.getPublicKey()) }; } case "buildRecoveryExport": { if (Q(), !y.recoveryPublicKey || !y.activeRecoveryEvent) throw new Error("No recovery capsule is known in this session yet."); return Cn({ recoveryPublicKeyHex: y.recoveryPublicKey, vaultRelayUrls: Y, recoveryCapsuleEvents: [y.activeRecoveryEvent], relayListEvents: [] }); } case "repairReplicas": { if (!y.activeCredentialEvent || !y.activeRecoveryEvent) throw new Error("No active capsule events are known in this session yet."); const n = new I(Y), r = await rr(n, y.activeCredentialEvent, y.activeRecoveryEvent); return n.closeAll(), r; } case "getSessionStatus": return { unlocked: !!y.signer, everydayPublicKey: y.signer?.getPublicKey() }; // Called once, right after "configure", before the widget renders its welcome // screen -- restores whatever persistSession() last cached for this origin, so // a page reload doesn't ask for the login name + password again. A missing or // corrupt cache is not an error: it just means the widget falls through to its // normal welcome screen, exactly like it always has. case "restoreSession": { const n = await so(be); return n ? (we(), y.signer = new xe(n.everydayPrivateKey), y.everydayPrivateKey = n.everydayPrivateKey, y.accountId = n.accountId, y.recoveryPublicKey = n.recoveryPublicKey, y.activeCredentialEvent = n.activeCredentialEvent, y.activeRecoveryEvent = n.activeRecoveryEvent, { restored: !0, everydayPublicKey: y.signer.getPublicKey(), accountId: n.accountId }) : { restored: !1 }; } case "logout": return we(), await co(be), {}; default: throw new Error(`Unknown worker action: ${e}`); } } self.addEventListener("message", (e) => { const { id: t, action: n, payload: r } = e.data; lo(n, r).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); } ); });