var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __esm = (fn, res, err) => function __init() { if (err) throw err[0]; try { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; } catch (e) { throw err = [e], e; } }; var __commonJS = (cb, mod2) => function __require() { try { return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports; } catch (e) { throw mod2 = 0, e; } }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target, mod2 )); // node_modules/@wizardconnect/core/dist/primitives.js function unwrap(value) { if (typeof value === "string") { throw new Error(`unwrap: ${value}`); } if (value instanceof Error) { throw value; } return value; } var throwUnless; var init_primitives = __esm({ "node_modules/@wizardconnect/core/dist/primitives.js"() { throwUnless = (x, what) => { if (!x) { throw Error(`Internal application error: ${what}`); } }; } }); // node_modules/@noble/hashes/utils.js function isBytes(a) { return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array"; } function anumber(n, title = "") { if (!Number.isSafeInteger(n) || n < 0) { const prefix = title && `"${title}" `; throw new Error(`${prefix}expected integer >= 0, got ${n}`); } } function abytes(value, length, title = "") { const bytes = isBytes(value); const len = value?.length; const needsLen = length !== void 0; if (!bytes || needsLen && len !== length) { const prefix = title && `"${title}" `; const ofLen = needsLen ? ` of length ${length}` : ""; const got = bytes ? `length=${len}` : `type=${typeof value}`; throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got); } return value; } function ahash(h) { if (typeof h !== "function" || typeof h.create !== "function") throw new Error("Hash must wrapped by utils.createHasher"); anumber(h.outputLen); anumber(h.blockLen); } function aexists(instance, checkFinished = true) { if (instance.destroyed) throw new Error("Hash instance has been destroyed"); if (checkFinished && instance.finished) throw new Error("Hash#digest() has already been called"); } function aoutput(out, instance) { abytes(out, void 0, "digestInto() output"); const min = instance.outputLen; if (out.length < min) { throw new Error('"digestInto() output" expected to be of length >=' + min); } } function clean(...arrays) { for (let i3 = 0; i3 < arrays.length; i3++) { arrays[i3].fill(0); } } function createView(arr) { return new DataView(arr.buffer, arr.byteOffset, arr.byteLength); } function rotr(word, shift) { return word << 32 - shift | word >>> shift; } function bytesToHex(bytes) { abytes(bytes); if (hasHexBuiltin) return bytes.toHex(); let hex = ""; for (let i3 = 0; i3 < bytes.length; i3++) { hex += hexes[bytes[i3]]; } return hex; } function asciiToBase16(ch) { if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0; if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10); if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10); return; } function hexToBytes(hex) { if (typeof hex !== "string") throw new Error("hex string expected, got " + typeof hex); if (hasHexBuiltin) return Uint8Array.fromHex(hex); const hl = hex.length; const al = hl / 2; if (hl % 2) throw new Error("hex string expected, got unpadded hex of length " + hl); const array = new Uint8Array(al); for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { const n1 = asciiToBase16(hex.charCodeAt(hi)); const n2 = asciiToBase16(hex.charCodeAt(hi + 1)); if (n1 === void 0 || n2 === void 0) { const char = hex[hi] + hex[hi + 1]; throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi); } array[ai] = n1 * 16 + n2; } return array; } function concatBytes(...arrays) { let sum = 0; for (let i3 = 0; i3 < arrays.length; i3++) { const a = arrays[i3]; abytes(a); sum += a.length; } const res = new Uint8Array(sum); for (let i3 = 0, pad2 = 0; i3 < arrays.length; i3++) { const a = arrays[i3]; res.set(a, pad2); pad2 += a.length; } return res; } function createHasher(hashCons, info = {}) { const hashC = (msg, opts) => hashCons(opts).update(msg).digest(); const tmp = hashCons(void 0); hashC.outputLen = tmp.outputLen; hashC.blockLen = tmp.blockLen; hashC.create = (opts) => hashCons(opts); Object.assign(hashC, info); return Object.freeze(hashC); } function randomBytes(bytesLength = 32) { const cr = typeof globalThis === "object" ? globalThis.crypto : null; if (typeof cr?.getRandomValues !== "function") throw new Error("crypto.getRandomValues must be defined"); return cr.getRandomValues(new Uint8Array(bytesLength)); } var hasHexBuiltin, hexes, asciis, oidNist; var init_utils = __esm({ "node_modules/@noble/hashes/utils.js"() { hasHexBuiltin = /* @__PURE__ */ (() => ( // @ts-ignore typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function" ))(); hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i3) => i3.toString(16).padStart(2, "0")); asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 }; oidNist = (suffix) => ({ oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix]) }); } }); // node_modules/@noble/hashes/_md.js function Chi(a, b, c) { return a & b ^ ~a & c; } function Maj(a, b, c) { return a & b ^ a & c ^ b & c; } var HashMD, SHA256_IV; var init_md = __esm({ "node_modules/@noble/hashes/_md.js"() { init_utils(); HashMD = class { blockLen; outputLen; padOffset; isLE; // For partial updates less than block size buffer; view; finished = false; length = 0; pos = 0; destroyed = false; constructor(blockLen, outputLen, padOffset, isLE2) { this.blockLen = blockLen; this.outputLen = outputLen; this.padOffset = padOffset; this.isLE = isLE2; this.buffer = new Uint8Array(blockLen); this.view = createView(this.buffer); } update(data) { aexists(this); abytes(data); const { view, buffer, blockLen } = this; const len = data.length; for (let pos = 0; pos < len; ) { const take = Math.min(blockLen - this.pos, len - pos); if (take === blockLen) { const dataView = createView(data); for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos); continue; } buffer.set(data.subarray(pos, pos + take), this.pos); this.pos += take; pos += take; if (this.pos === blockLen) { this.process(view, 0); this.pos = 0; } } this.length += data.length; this.roundClean(); return this; } digestInto(out) { aexists(this); aoutput(out, this); this.finished = true; const { buffer, view, blockLen, isLE: isLE2 } = this; let { pos } = this; buffer[pos++] = 128; clean(this.buffer.subarray(pos)); if (this.padOffset > blockLen - pos) { this.process(view, 0); pos = 0; } for (let i3 = pos; i3 < blockLen; i3++) buffer[i3] = 0; view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE2); this.process(view, 0); const oview = createView(out); const len = this.outputLen; if (len % 4) throw new Error("_sha2: outputLen must be aligned to 32bit"); const outLen = len / 4; const state = this.get(); if (outLen > state.length) throw new Error("_sha2: outputLen bigger than state"); for (let i3 = 0; i3 < outLen; i3++) oview.setUint32(4 * i3, state[i3], isLE2); } digest() { const { buffer, outputLen } = this; this.digestInto(buffer); const res = buffer.slice(0, outputLen); this.destroy(); return res; } _cloneInto(to) { to ||= new this.constructor(); to.set(...this.get()); const { blockLen, buffer, length, finished, destroyed, pos } = this; to.destroyed = destroyed; to.finished = finished; to.length = length; to.pos = pos; if (length % blockLen) to.buffer.set(buffer); return to; } clone() { return this._cloneInto(); } }; SHA256_IV = /* @__PURE__ */ Uint32Array.from([ 1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225 ]); } }); // node_modules/@noble/hashes/sha2.js var SHA256_K, SHA256_W, SHA2_32B, _SHA256, sha256; var init_sha2 = __esm({ "node_modules/@noble/hashes/sha2.js"() { init_md(); init_utils(); SHA256_K = /* @__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 ]); SHA256_W = /* @__PURE__ */ new Uint32Array(64); SHA2_32B = class extends HashMD { constructor(outputLen) { super(64, outputLen, 8, false); } get() { const { A, B, C, D, E, F, G, H } = this; return [A, B, C, D, E, F, G, H]; } // prettier-ignore set(A, B, C, D, E, F, G, H) { this.A = A | 0; this.B = B | 0; this.C = C | 0; this.D = D | 0; this.E = E | 0; this.F = F | 0; this.G = G | 0; this.H = H | 0; } process(view, offset) { for (let i3 = 0; i3 < 16; i3++, offset += 4) SHA256_W[i3] = view.getUint32(offset, false); for (let i3 = 16; i3 < 64; i3++) { const W15 = SHA256_W[i3 - 15]; const W2 = SHA256_W[i3 - 2]; const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3; const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10; SHA256_W[i3] = s1 + SHA256_W[i3 - 7] + s0 + SHA256_W[i3 - 16] | 0; } let { A, B, C, D, E, F, G, H } = this; for (let i3 = 0; i3 < 64; i3++) { const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25); const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i3] + SHA256_W[i3] | 0; const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22); const T2 = sigma0 + Maj(A, B, C) | 0; H = G; G = F; F = E; E = D + T1 | 0; D = C; C = B; B = A; A = T1 + T2 | 0; } A = A + this.A | 0; B = B + this.B | 0; C = C + this.C | 0; D = D + this.D | 0; E = E + this.E | 0; F = F + this.F | 0; G = G + this.G | 0; H = H + this.H | 0; this.set(A, B, C, D, E, F, G, H); } roundClean() { clean(SHA256_W); } destroy() { this.set(0, 0, 0, 0, 0, 0, 0, 0); clean(this.buffer); } }; _SHA256 = class extends SHA2_32B { // We cannot use array here since array allows indexing by variable // which means optimizer/compiler cannot use registers. A = SHA256_IV[0] | 0; B = SHA256_IV[1] | 0; C = SHA256_IV[2] | 0; D = SHA256_IV[3] | 0; E = SHA256_IV[4] | 0; F = SHA256_IV[5] | 0; G = SHA256_IV[6] | 0; H = SHA256_IV[7] | 0; constructor() { super(32); } }; sha256 = /* @__PURE__ */ createHasher( () => new _SHA256(), /* @__PURE__ */ oidNist(1) ); } }); // node_modules/@noble/curves/utils.js function abool(value, title = "") { if (typeof value !== "boolean") { const prefix = title && `"${title}" `; throw new Error(prefix + "expected boolean, got type=" + typeof value); } return value; } function abignumber(n) { if (typeof n === "bigint") { if (!isPosBig(n)) throw new Error("positive bigint expected, got " + n); } else anumber(n); return n; } function numberToHexUnpadded(num2) { const hex = abignumber(num2).toString(16); return hex.length & 1 ? "0" + hex : hex; } function hexToNumber(hex) { if (typeof hex !== "string") throw new Error("hex string expected, got " + typeof hex); return hex === "" ? _0n : BigInt("0x" + hex); } function bytesToNumberBE(bytes) { return hexToNumber(bytesToHex(bytes)); } function bytesToNumberLE(bytes) { return hexToNumber(bytesToHex(copyBytes(abytes(bytes)).reverse())); } function numberToBytesBE(n, len) { anumber(len); n = abignumber(n); const res = hexToBytes(n.toString(16).padStart(len * 2, "0")); if (res.length !== len) throw new Error("number too large"); return res; } function numberToBytesLE(n, len) { return numberToBytesBE(n, len).reverse(); } function copyBytes(bytes) { return Uint8Array.from(bytes); } function asciiToBytes(ascii) { return Uint8Array.from(ascii, (c, i3) => { const charCode = c.charCodeAt(0); if (c.length !== 1 || charCode > 127) { throw new Error(`string contains non-ASCII character "${ascii[i3]}" with code ${charCode} at position ${i3}`); } return charCode; }); } function inRange(n, min, max) { return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max; } function aInRange(title, n, min, max) { if (!inRange(n, min, max)) throw new Error("expected valid " + title + ": " + min + " <= n < " + max + ", got " + n); } function bitLen(n) { let len; for (len = 0; n > _0n; n >>= _1n, len += 1) ; return len; } function createHmacDrbg(hashLen, qByteLen, hmacFn) { anumber(hashLen, "hashLen"); anumber(qByteLen, "qByteLen"); if (typeof hmacFn !== "function") throw new Error("hmacFn must be a function"); const u8n = (len) => new Uint8Array(len); const NULL = Uint8Array.of(); const byte0 = Uint8Array.of(0); const byte1 = Uint8Array.of(1); const _maxDrbgIters = 1e3; let v = u8n(hashLen); let k = u8n(hashLen); let i3 = 0; const reset = () => { v.fill(1); k.fill(0); i3 = 0; }; const h = (...msgs) => hmacFn(k, concatBytes(v, ...msgs)); const reseed = (seed = NULL) => { k = h(byte0, seed); v = h(); if (seed.length === 0) return; k = h(byte1, seed); v = h(); }; const gen = () => { if (i3++ >= _maxDrbgIters) throw new Error("drbg: tried max amount of iterations"); let len = 0; const out = []; while (len < qByteLen) { v = h(); const sl = v.slice(); out.push(sl); len += v.length; } return concatBytes(...out); }; const genUntil = (seed, pred) => { reset(); reseed(seed); let res = void 0; while (!(res = pred(gen()))) reseed(); reset(); return res; }; return genUntil; } function validateObject(object, fields = {}, optFields = {}) { if (!object || typeof object !== "object") throw new Error("expected valid options object"); function checkField(fieldName, expectedType, isOpt) { const val = object[fieldName]; if (isOpt && val === void 0) return; const current = typeof val; if (current !== expectedType || val === null) throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`); } const iter = (f, isOpt) => Object.entries(f).forEach(([k, v]) => checkField(k, v, isOpt)); iter(fields, false); iter(optFields, true); } function memoized(fn) { const map = /* @__PURE__ */ new WeakMap(); return (arg, ...args) => { const val = map.get(arg); if (val !== void 0) return val; const computed = fn(arg, ...args); map.set(arg, computed); return computed; }; } var _0n, _1n, isPosBig, bitMask; var init_utils2 = __esm({ "node_modules/@noble/curves/utils.js"() { init_utils(); init_utils(); _0n = /* @__PURE__ */ BigInt(0); _1n = /* @__PURE__ */ BigInt(1); isPosBig = (n) => typeof n === "bigint" && _0n <= n; bitMask = (n) => (_1n << BigInt(n)) - _1n; } }); // node_modules/@noble/curves/abstract/modular.js function mod(a, b) { const result = a % b; return result >= _0n2 ? result : b + result; } function pow2(x, power, modulo) { let res = x; while (power-- > _0n2) { res *= res; res %= modulo; } return res; } function invert(number, modulo) { if (number === _0n2) throw new Error("invert: expected non-zero number"); if (modulo <= _0n2) throw new Error("invert: expected positive modulus, got " + modulo); let a = mod(number, modulo); let b = modulo; let x = _0n2, y = _1n2, u = _1n2, v = _0n2; while (a !== _0n2) { const q = b / a; const r = b % a; const m = x - u * q; const n = y - v * q; b = a, a = r, x = u, y = v, u = m, v = n; } const gcd2 = b; if (gcd2 !== _1n2) throw new Error("invert: does not exist"); return mod(x, modulo); } function assertIsSquare(Fp, root, n) { if (!Fp.eql(Fp.sqr(root), n)) throw new Error("Cannot find square root"); } function sqrt3mod4(Fp, n) { const p1div4 = (Fp.ORDER + _1n2) / _4n; const root = Fp.pow(n, p1div4); assertIsSquare(Fp, root, n); return root; } function sqrt5mod8(Fp, n) { const p5div8 = (Fp.ORDER - _5n) / _8n; const n2 = Fp.mul(n, _2n); const v = Fp.pow(n2, p5div8); const nv = Fp.mul(n, v); const i3 = Fp.mul(Fp.mul(nv, _2n), v); const root = Fp.mul(nv, Fp.sub(i3, Fp.ONE)); assertIsSquare(Fp, root, n); return root; } function sqrt9mod16(P) { const Fp_ = Field(P); const tn = tonelliShanks(P); const c1 = tn(Fp_, Fp_.neg(Fp_.ONE)); const c2 = tn(Fp_, c1); const c3 = tn(Fp_, Fp_.neg(c1)); const c4 = (P + _7n) / _16n; return (Fp, n) => { let tv1 = Fp.pow(n, c4); let tv2 = Fp.mul(tv1, c1); const tv3 = Fp.mul(tv1, c2); const tv4 = Fp.mul(tv1, c3); const e1 = Fp.eql(Fp.sqr(tv2), n); const e2 = Fp.eql(Fp.sqr(tv3), n); tv1 = Fp.cmov(tv1, tv2, e1); tv2 = Fp.cmov(tv4, tv3, e2); const e3 = Fp.eql(Fp.sqr(tv2), n); const root = Fp.cmov(tv1, tv2, e3); assertIsSquare(Fp, root, n); return root; }; } function tonelliShanks(P) { if (P < _3n) throw new Error("sqrt is not defined for small field"); let Q = P - _1n2; let S = 0; while (Q % _2n === _0n2) { Q /= _2n; S++; } let Z = _2n; const _Fp = Field(P); while (FpLegendre(_Fp, Z) === 1) { if (Z++ > 1e3) throw new Error("Cannot find square root: probably non-prime P"); } if (S === 1) return sqrt3mod4; let cc = _Fp.pow(Z, Q); const Q1div2 = (Q + _1n2) / _2n; return function tonelliSlow(Fp, n) { if (Fp.is0(n)) return n; if (FpLegendre(Fp, n) !== 1) throw new Error("Cannot find square root"); let M2 = S; let c = Fp.mul(Fp.ONE, cc); let t = Fp.pow(n, Q); let R = Fp.pow(n, Q1div2); while (!Fp.eql(t, Fp.ONE)) { if (Fp.is0(t)) return Fp.ZERO; let i3 = 1; let t_tmp = Fp.sqr(t); while (!Fp.eql(t_tmp, Fp.ONE)) { i3++; t_tmp = Fp.sqr(t_tmp); if (i3 === M2) throw new Error("Cannot find square root"); } const exponent = _1n2 << BigInt(M2 - i3 - 1); const b = Fp.pow(c, exponent); M2 = i3; c = Fp.sqr(b); t = Fp.mul(t, c); R = Fp.mul(R, b); } return R; }; } function FpSqrt(P) { if (P % _4n === _3n) return sqrt3mod4; if (P % _8n === _5n) return sqrt5mod8; if (P % _16n === _9n) return sqrt9mod16(P); return tonelliShanks(P); } function validateField(field) { const initial = { ORDER: "bigint", BYTES: "number", BITS: "number" }; const opts = FIELD_FIELDS.reduce((map, val) => { map[val] = "function"; return map; }, initial); validateObject(field, opts); return field; } function FpPow(Fp, num2, power) { if (power < _0n2) throw new Error("invalid exponent, negatives unsupported"); if (power === _0n2) return Fp.ONE; if (power === _1n2) return num2; let p = Fp.ONE; let d = num2; while (power > _0n2) { if (power & _1n2) p = Fp.mul(p, d); d = Fp.sqr(d); power >>= _1n2; } return p; } function FpInvertBatch(Fp, nums, passZero = false) { const inverted = new Array(nums.length).fill(passZero ? Fp.ZERO : void 0); const multipliedAcc = nums.reduce((acc, num2, i3) => { if (Fp.is0(num2)) return acc; inverted[i3] = acc; return Fp.mul(acc, num2); }, Fp.ONE); const invertedAcc = Fp.inv(multipliedAcc); nums.reduceRight((acc, num2, i3) => { if (Fp.is0(num2)) return acc; inverted[i3] = Fp.mul(acc, inverted[i3]); return Fp.mul(acc, num2); }, invertedAcc); return inverted; } function FpLegendre(Fp, n) { const p1mod2 = (Fp.ORDER - _1n2) / _2n; const powered = Fp.pow(n, p1mod2); const yes = Fp.eql(powered, Fp.ONE); const zero = Fp.eql(powered, Fp.ZERO); const no = Fp.eql(powered, Fp.neg(Fp.ONE)); if (!yes && !zero && !no) throw new Error("invalid Legendre symbol result"); return yes ? 1 : zero ? 0 : -1; } function nLength(n, nBitLength) { if (nBitLength !== void 0) anumber(nBitLength); const _nBitLength = nBitLength !== void 0 ? nBitLength : n.toString(2).length; const nByteLength = Math.ceil(_nBitLength / 8); return { nBitLength: _nBitLength, nByteLength }; } function Field(ORDER, opts = {}) { return new _Field(ORDER, opts); } function getFieldBytesLength(fieldOrder) { if (typeof fieldOrder !== "bigint") throw new Error("field order must be bigint"); const bitLength = fieldOrder.toString(2).length; return Math.ceil(bitLength / 8); } function getMinHashLength(fieldOrder) { const length = getFieldBytesLength(fieldOrder); return length + Math.ceil(length / 2); } function mapHashToField(key, fieldOrder, isLE2 = false) { abytes(key); const len = key.length; const fieldLen = getFieldBytesLength(fieldOrder); const minLen = getMinHashLength(fieldOrder); if (len < 16 || len < minLen || len > 1024) throw new Error("expected " + minLen + "-1024 bytes of input, got " + len); const num2 = isLE2 ? bytesToNumberLE(key) : bytesToNumberBE(key); const reduced = mod(num2, fieldOrder - _1n2) + _1n2; return isLE2 ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen); } var _0n2, _1n2, _2n, _3n, _4n, _5n, _7n, _8n, _9n, _16n, FIELD_FIELDS, _Field; var init_modular = __esm({ "node_modules/@noble/curves/abstract/modular.js"() { init_utils2(); _0n2 = /* @__PURE__ */ BigInt(0); _1n2 = /* @__PURE__ */ BigInt(1); _2n = /* @__PURE__ */ BigInt(2); _3n = /* @__PURE__ */ BigInt(3); _4n = /* @__PURE__ */ BigInt(4); _5n = /* @__PURE__ */ BigInt(5); _7n = /* @__PURE__ */ BigInt(7); _8n = /* @__PURE__ */ BigInt(8); _9n = /* @__PURE__ */ BigInt(9); _16n = /* @__PURE__ */ BigInt(16); FIELD_FIELDS = [ "create", "isValid", "is0", "neg", "inv", "sqrt", "sqr", "eql", "add", "sub", "mul", "pow", "div", "addN", "subN", "mulN", "sqrN" ]; _Field = class { ORDER; BITS; BYTES; isLE; ZERO = _0n2; ONE = _1n2; _lengths; _sqrt; // cached sqrt _mod; constructor(ORDER, opts = {}) { if (ORDER <= _0n2) throw new Error("invalid field: expected ORDER > 0, got " + ORDER); let _nbitLength = void 0; this.isLE = false; if (opts != null && typeof opts === "object") { if (typeof opts.BITS === "number") _nbitLength = opts.BITS; if (typeof opts.sqrt === "function") this.sqrt = opts.sqrt; if (typeof opts.isLE === "boolean") this.isLE = opts.isLE; if (opts.allowedLengths) this._lengths = opts.allowedLengths?.slice(); if (typeof opts.modFromBytes === "boolean") this._mod = opts.modFromBytes; } const { nBitLength, nByteLength } = nLength(ORDER, _nbitLength); if (nByteLength > 2048) throw new Error("invalid field: expected ORDER of <= 2048 bytes"); this.ORDER = ORDER; this.BITS = nBitLength; this.BYTES = nByteLength; this._sqrt = void 0; Object.preventExtensions(this); } create(num2) { return mod(num2, this.ORDER); } isValid(num2) { if (typeof num2 !== "bigint") throw new Error("invalid field element: expected bigint, got " + typeof num2); return _0n2 <= num2 && num2 < this.ORDER; } is0(num2) { return num2 === _0n2; } // is valid and invertible isValidNot0(num2) { return !this.is0(num2) && this.isValid(num2); } isOdd(num2) { return (num2 & _1n2) === _1n2; } neg(num2) { return mod(-num2, this.ORDER); } eql(lhs, rhs) { return lhs === rhs; } sqr(num2) { return mod(num2 * num2, this.ORDER); } add(lhs, rhs) { return mod(lhs + rhs, this.ORDER); } sub(lhs, rhs) { return mod(lhs - rhs, this.ORDER); } mul(lhs, rhs) { return mod(lhs * rhs, this.ORDER); } pow(num2, power) { return FpPow(this, num2, power); } div(lhs, rhs) { return mod(lhs * invert(rhs, this.ORDER), this.ORDER); } // Same as above, but doesn't normalize sqrN(num2) { return num2 * num2; } addN(lhs, rhs) { return lhs + rhs; } subN(lhs, rhs) { return lhs - rhs; } mulN(lhs, rhs) { return lhs * rhs; } inv(num2) { return invert(num2, this.ORDER); } sqrt(num2) { if (!this._sqrt) this._sqrt = FpSqrt(this.ORDER); return this._sqrt(this, num2); } toBytes(num2) { return this.isLE ? numberToBytesLE(num2, this.BYTES) : numberToBytesBE(num2, this.BYTES); } fromBytes(bytes, skipValidation = false) { abytes(bytes); const { _lengths: allowedLengths, BYTES, isLE: isLE2, ORDER, _mod: modFromBytes } = this; if (allowedLengths) { if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) { throw new Error("Field.fromBytes: expected " + allowedLengths + " bytes, got " + bytes.length); } const padded = new Uint8Array(BYTES); padded.set(bytes, isLE2 ? 0 : padded.length - bytes.length); bytes = padded; } if (bytes.length !== BYTES) throw new Error("Field.fromBytes: expected " + BYTES + " bytes, got " + bytes.length); let scalar = isLE2 ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes); if (modFromBytes) scalar = mod(scalar, ORDER); if (!skipValidation) { if (!this.isValid(scalar)) throw new Error("invalid field element: outside of range 0..ORDER"); } return scalar; } // TODO: we don't need it here, move out to separate fn invertBatch(lst) { return FpInvertBatch(this, lst); } // We can't move this out because Fp6, Fp12 implement it // and it's unclear what to return in there. cmov(a, b, condition) { return condition ? b : a; } }; } }); // node_modules/@noble/curves/abstract/curve.js function negateCt(condition, item) { const neg = item.negate(); return condition ? neg : item; } function normalizeZ(c, points) { const invertedZs = FpInvertBatch(c.Fp, points.map((p) => p.Z)); return points.map((p, i3) => c.fromAffine(p.toAffine(invertedZs[i3]))); } function validateW(W, bits) { if (!Number.isSafeInteger(W) || W <= 0 || W > bits) throw new Error("invalid window size, expected [1.." + bits + "], got W=" + W); } function calcWOpts(W, scalarBits) { validateW(W, scalarBits); const windows = Math.ceil(scalarBits / W) + 1; const windowSize = 2 ** (W - 1); const maxNumber = 2 ** W; const mask = bitMask(W); const shiftBy = BigInt(W); return { windows, windowSize, mask, maxNumber, shiftBy }; } function calcOffsets(n, window2, wOpts) { const { windowSize, mask, maxNumber, shiftBy } = wOpts; let wbits = Number(n & mask); let nextN = n >> shiftBy; if (wbits > windowSize) { wbits -= maxNumber; nextN += _1n3; } const offsetStart = window2 * windowSize; const offset = offsetStart + Math.abs(wbits) - 1; const isZero = wbits === 0; const isNeg = wbits < 0; const isNegF = window2 % 2 !== 0; const offsetF = offsetStart; return { nextN, offset, isZero, isNeg, isNegF, offsetF }; } function getW(P) { return pointWindowSizes.get(P) || 1; } function assert0(n) { if (n !== _0n3) throw new Error("invalid wNAF"); } function mulEndoUnsafe(Point, point, k1, k2) { let acc = point; let p1 = Point.ZERO; let p2 = Point.ZERO; while (k1 > _0n3 || k2 > _0n3) { if (k1 & _1n3) p1 = p1.add(acc); if (k2 & _1n3) p2 = p2.add(acc); acc = acc.double(); k1 >>= _1n3; k2 >>= _1n3; } return { p1, p2 }; } function createField(order, field, isLE2) { if (field) { if (field.ORDER !== order) throw new Error("Field.ORDER must match order: Fp == p, Fn == n"); validateField(field); return field; } else { return Field(order, { isLE: isLE2 }); } } function createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) { if (FpFnLE === void 0) FpFnLE = type === "edwards"; if (!CURVE || typeof CURVE !== "object") throw new Error(`expected valid ${type} CURVE object`); for (const p of ["p", "n", "h"]) { const val = CURVE[p]; if (!(typeof val === "bigint" && val > _0n3)) throw new Error(`CURVE.${p} must be positive bigint`); } const Fp = createField(CURVE.p, curveOpts.Fp, FpFnLE); const Fn = createField(CURVE.n, curveOpts.Fn, FpFnLE); const _b = type === "weierstrass" ? "b" : "d"; const params = ["Gx", "Gy", "a", _b]; for (const p of params) { if (!Fp.isValid(CURVE[p])) throw new Error(`CURVE.${p} must be valid field element of CURVE.Fp`); } CURVE = Object.freeze(Object.assign({}, CURVE)); return { CURVE, Fp, Fn }; } function createKeygen(randomSecretKey, getPublicKey3) { return function keygen(seed) { const secretKey = randomSecretKey(seed); return { secretKey, publicKey: getPublicKey3(secretKey) }; }; } var _0n3, _1n3, pointPrecomputes, pointWindowSizes, wNAF; var init_curve = __esm({ "node_modules/@noble/curves/abstract/curve.js"() { init_utils2(); init_modular(); _0n3 = /* @__PURE__ */ BigInt(0); _1n3 = /* @__PURE__ */ BigInt(1); pointPrecomputes = /* @__PURE__ */ new WeakMap(); pointWindowSizes = /* @__PURE__ */ new WeakMap(); wNAF = class { BASE; ZERO; Fn; bits; // Parametrized with a given Point class (not individual point) constructor(Point, bits) { this.BASE = Point.BASE; this.ZERO = Point.ZERO; this.Fn = Point.Fn; this.bits = bits; } // non-const time multiplication ladder _unsafeLadder(elm, n, p = this.ZERO) { let d = elm; while (n > _0n3) { if (n & _1n3) p = p.add(d); d = d.double(); n >>= _1n3; } return p; } /** * Creates a wNAF precomputation window. Used for caching. * Default window size is set by `utils.precompute()` and is equal to 8. * Number of precomputed points depends on the curve size: * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: * - 𝑊 is the window size * - 𝑛 is the bitlength of the curve order. * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. * @param point Point instance * @param W window size * @returns precomputed point tables flattened to a single array */ precomputeWindow(point, W) { const { windows, windowSize } = calcWOpts(W, this.bits); const points = []; let p = point; let base = p; for (let window2 = 0; window2 < windows; window2++) { base = p; points.push(base); for (let i3 = 1; i3 < windowSize; i3++) { base = base.add(p); points.push(base); } p = base.double(); } return points; } /** * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. * More compact implementation: * https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541 * @returns real and fake (for const-time) points */ wNAF(W, precomputes, n) { if (!this.Fn.isValid(n)) throw new Error("invalid scalar"); let p = this.ZERO; let f = this.BASE; const wo = calcWOpts(W, this.bits); for (let window2 = 0; window2 < wo.windows; window2++) { const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window2, wo); n = nextN; if (isZero) { f = f.add(negateCt(isNegF, precomputes[offsetF])); } else { p = p.add(negateCt(isNeg, precomputes[offset])); } } assert0(n); return { p, f }; } /** * 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(W, precomputes, n, acc = this.ZERO) { const wo = calcWOpts(W, this.bits); for (let window2 = 0; window2 < wo.windows; window2++) { if (n === _0n3) break; const { nextN, offset, isZero, isNeg } = calcOffsets(n, window2, wo); n = nextN; if (isZero) { continue; } else { const item = precomputes[offset]; acc = acc.add(isNeg ? item.negate() : item); } } assert0(n); return acc; } getPrecomputes(W, point, transform) { let comp = pointPrecomputes.get(point); if (!comp) { comp = this.precomputeWindow(point, W); if (W !== 1) { if (typeof transform === "function") comp = transform(comp); pointPrecomputes.set(point, comp); } } return comp; } cached(point, scalar, transform) { const W = getW(point); return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar); } unsafe(point, scalar, transform, prev) { const W = getW(point); if (W === 1) return this._unsafeLadder(point, scalar, prev); return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev); } // 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(P, W) { validateW(W, this.bits); pointWindowSizes.set(P, W); pointPrecomputes.delete(P); } hasCache(elm) { return getW(elm) !== 1; } }; } }); // node_modules/@noble/hashes/hmac.js var _HMAC, hmac; var init_hmac = __esm({ "node_modules/@noble/hashes/hmac.js"() { init_utils(); _HMAC = class { oHash; iHash; blockLen; outputLen; finished = false; destroyed = false; constructor(hash, key) { ahash(hash); abytes(key, void 0, "key"); this.iHash = hash.create(); if (typeof this.iHash.update !== "function") throw new Error("Expected instance of class which extends utils.Hash"); this.blockLen = this.iHash.blockLen; this.outputLen = this.iHash.outputLen; const blockLen = this.blockLen; const pad2 = new Uint8Array(blockLen); pad2.set(key.length > blockLen ? hash.create().update(key).digest() : key); for (let i3 = 0; i3 < pad2.length; i3++) pad2[i3] ^= 54; this.iHash.update(pad2); this.oHash = hash.create(); for (let i3 = 0; i3 < pad2.length; i3++) pad2[i3] ^= 54 ^ 92; this.oHash.update(pad2); clean(pad2); } update(buf) { aexists(this); this.iHash.update(buf); return this; } digestInto(out) { aexists(this); abytes(out, this.outputLen, "output"); this.finished = true; this.iHash.digestInto(out); this.oHash.update(out); this.oHash.digestInto(out); this.destroy(); } digest() { const out = new Uint8Array(this.oHash.outputLen); this.digestInto(out); return out; } _cloneInto(to) { to ||= Object.create(Object.getPrototypeOf(this), {}); const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this; to = to; to.finished = finished; to.destroyed = destroyed; to.blockLen = blockLen; to.outputLen = outputLen; to.oHash = oHash._cloneInto(to.oHash); to.iHash = iHash._cloneInto(to.iHash); return to; } clone() { return this._cloneInto(); } destroy() { this.destroyed = true; this.oHash.destroy(); this.iHash.destroy(); } }; hmac = (hash, key, message) => new _HMAC(hash, key).update(message).digest(); hmac.create = (hash, key) => new _HMAC(hash, key); } }); // node_modules/@noble/curves/abstract/weierstrass.js function _splitEndoScalar(k, basis, n) { const [[a1, b1], [a2, b2]] = basis; const c1 = divNearest(b2 * k, n); const c2 = divNearest(-b1 * k, n); let k1 = k - c1 * a1 - c2 * a2; let k2 = -c1 * b1 - c2 * b2; const k1neg = k1 < _0n4; const k2neg = k2 < _0n4; if (k1neg) k1 = -k1; if (k2neg) k2 = -k2; const MAX_NUM = bitMask(Math.ceil(bitLen(n) / 2)) + _1n4; if (k1 < _0n4 || k1 >= MAX_NUM || k2 < _0n4 || k2 >= MAX_NUM) { throw new Error("splitScalar (endomorphism): failed, k=" + k); } return { k1neg, k1, k2neg, k2 }; } function validateSigFormat(format) { if (!["compact", "recovered", "der"].includes(format)) throw new Error('Signature format must be "compact", "recovered", or "der"'); return format; } function validateSigOpts(opts, def) { const optsn = {}; for (let optName of Object.keys(def)) { optsn[optName] = opts[optName] === void 0 ? def[optName] : opts[optName]; } abool(optsn.lowS, "lowS"); abool(optsn.prehash, "prehash"); if (optsn.format !== void 0) validateSigFormat(optsn.format); return optsn; } function weierstrass(params, extraOpts = {}) { const validated = createCurveFields("weierstrass", params, extraOpts); const { Fp, Fn } = validated; let CURVE = validated.CURVE; const { h: cofactor, n: CURVE_ORDER } = CURVE; validateObject(extraOpts, {}, { allowInfinityPoint: "boolean", clearCofactor: "function", isTorsionFree: "function", fromBytes: "function", toBytes: "function", endo: "object" }); const { endo } = extraOpts; if (endo) { if (!Fp.is0(CURVE.a) || typeof endo.beta !== "bigint" || !Array.isArray(endo.basises)) { throw new Error('invalid endo: expected "beta": bigint and "basises": array'); } } const lengths = getWLengths(Fp, Fn); function assertCompressionIsSupported() { if (!Fp.isOdd) throw new Error("compression is not supported: Field does not have .isOdd()"); } function pointToBytes2(_c, point, isCompressed) { const { x, y } = point.toAffine(); const bx = Fp.toBytes(x); abool(isCompressed, "isCompressed"); if (isCompressed) { assertCompressionIsSupported(); const hasEvenY = !Fp.isOdd(y); return concatBytes(pprefix(hasEvenY), bx); } else { return concatBytes(Uint8Array.of(4), bx, Fp.toBytes(y)); } } function pointFromBytes(bytes) { abytes(bytes, void 0, "Point"); const { publicKey: comp, publicKeyUncompressed: uncomp } = lengths; const length = bytes.length; const head = bytes[0]; const tail = bytes.subarray(1); if (length === comp && (head === 2 || head === 3)) { const x = Fp.fromBytes(tail); if (!Fp.isValid(x)) throw new Error("bad point: is not on curve, wrong x"); const y2 = weierstrassEquation(x); let y; try { y = Fp.sqrt(y2); } catch (sqrtError) { const err = sqrtError instanceof Error ? ": " + sqrtError.message : ""; throw new Error("bad point: is not on curve, sqrt error" + err); } assertCompressionIsSupported(); const evenY = Fp.isOdd(y); const evenH = (head & 1) === 1; if (evenH !== evenY) y = Fp.neg(y); return { x, y }; } else if (length === uncomp && head === 4) { const L = Fp.BYTES; const x = Fp.fromBytes(tail.subarray(0, L)); const y = Fp.fromBytes(tail.subarray(L, L * 2)); if (!isValidXY(x, y)) throw new Error("bad point: is not on curve"); return { x, y }; } else { throw new Error(`bad point: got length ${length}, expected compressed=${comp} or uncompressed=${uncomp}`); } } const encodePoint = extraOpts.toBytes || pointToBytes2; const decodePoint = extraOpts.fromBytes || pointFromBytes; function weierstrassEquation(x) { const x2 = Fp.sqr(x); const x3 = Fp.mul(x2, x); return Fp.add(Fp.add(x3, Fp.mul(x, CURVE.a)), CURVE.b); } function isValidXY(x, y) { const left = Fp.sqr(y); const right = weierstrassEquation(x); return Fp.eql(left, right); } if (!isValidXY(CURVE.Gx, CURVE.Gy)) throw new Error("bad curve params: generator point"); const _4a3 = Fp.mul(Fp.pow(CURVE.a, _3n2), _4n2); const _27b2 = Fp.mul(Fp.sqr(CURVE.b), BigInt(27)); if (Fp.is0(Fp.add(_4a3, _27b2))) throw new Error("bad curve params: a or b"); function acoord(title, n, banZero = false) { if (!Fp.isValid(n) || banZero && Fp.is0(n)) throw new Error(`bad point coordinate ${title}`); return n; } function aprjpoint(other) { if (!(other instanceof Point)) throw new Error("Weierstrass Point expected"); } function splitEndoScalarN(k) { if (!endo || !endo.basises) throw new Error("no endo"); return _splitEndoScalar(k, endo.basises, Fn.ORDER); } const toAffineMemo = memoized((p, iz) => { const { X, Y, Z } = p; if (Fp.eql(Z, Fp.ONE)) return { x: X, y: Y }; const is0 = p.is0(); if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(Z); const x = Fp.mul(X, iz); const y = Fp.mul(Y, iz); const zz = Fp.mul(Z, iz); if (is0) return { x: Fp.ZERO, y: Fp.ZERO }; if (!Fp.eql(zz, Fp.ONE)) throw new Error("invZ was invalid"); return { x, y }; }); const assertValidMemo = memoized((p) => { if (p.is0()) { if (extraOpts.allowInfinityPoint && !Fp.is0(p.Y)) return; throw new Error("bad point: ZERO"); } const { x, y } = p.toAffine(); if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error("bad point: x or y not field elements"); if (!isValidXY(x, y)) throw new Error("bad point: equation left != right"); if (!p.isTorsionFree()) throw new Error("bad point: not in prime-order subgroup"); return true; }); function finishEndo(endoBeta, k1p, k2p, k1neg, k2neg) { k2p = new Point(Fp.mul(k2p.X, endoBeta), k2p.Y, k2p.Z); k1p = negateCt(k1neg, k1p); k2p = negateCt(k2neg, k2p); return k1p.add(k2p); } class Point { // base / generator point static BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE); // zero / infinity / identity point static ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO); // 0, 1, 0 // math field static Fp = Fp; // scalar field static Fn = Fn; X; Y; Z; /** Does NOT validate if the point is valid. Use `.assertValidity()`. */ constructor(X, Y, Z) { this.X = acoord("x", X); this.Y = acoord("y", Y, true); this.Z = acoord("z", Z); Object.freeze(this); } static CURVE() { return CURVE; } /** Does NOT validate if the point is valid. Use `.assertValidity()`. */ static fromAffine(p) { const { x, y } = p || {}; if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error("invalid affine point"); if (p instanceof Point) throw new Error("projective point not allowed"); if (Fp.is0(x) && Fp.is0(y)) return Point.ZERO; return new Point(x, y, Fp.ONE); } static fromBytes(bytes) { const P = Point.fromAffine(decodePoint(abytes(bytes, void 0, "point"))); P.assertValidity(); return P; } static fromHex(hex) { return Point.fromBytes(hexToBytes(hex)); } 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(windowSize = 8, isLazy = true) { wnaf.createCache(this, windowSize); if (!isLazy) this.multiply(_3n2); return this; } // TODO: return `this` /** A point on curve is valid if it conforms to equation. */ assertValidity() { assertValidMemo(this); } hasEvenY() { const { y } = this.toAffine(); if (!Fp.isOdd) throw new Error("Field doesn't support isOdd"); return !Fp.isOdd(y); } /** Compare one point to another. */ equals(other) { aprjpoint(other); const { X: X1, Y: Y1, Z: Z1 } = this; const { X: X2, Y: Y2, Z: Z2 } = other; const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)); const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)); return U1 && U2; } /** Flips point to one corresponding to (x, -y) in Affine coordinates. */ negate() { return new Point(this.X, Fp.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, b } = CURVE; const b3 = Fp.mul(b, _3n2); const { X: X1, Y: Y1, Z: Z1 } = this; let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; let t0 = Fp.mul(X1, X1); let t1 = Fp.mul(Y1, Y1); let t2 = Fp.mul(Z1, Z1); let t3 = Fp.mul(X1, Y1); t3 = Fp.add(t3, t3); Z3 = Fp.mul(X1, Z1); Z3 = Fp.add(Z3, Z3); X3 = Fp.mul(a, Z3); Y3 = Fp.mul(b3, t2); Y3 = Fp.add(X3, Y3); X3 = Fp.sub(t1, Y3); Y3 = Fp.add(t1, Y3); Y3 = Fp.mul(X3, Y3); X3 = Fp.mul(t3, X3); Z3 = Fp.mul(b3, Z3); t2 = Fp.mul(a, t2); t3 = Fp.sub(t0, t2); t3 = Fp.mul(a, t3); t3 = Fp.add(t3, Z3); Z3 = Fp.add(t0, t0); t0 = Fp.add(Z3, t0); t0 = Fp.add(t0, t2); t0 = Fp.mul(t0, t3); Y3 = Fp.add(Y3, t0); t2 = Fp.mul(Y1, Z1); t2 = Fp.add(t2, t2); t0 = Fp.mul(t2, t3); X3 = Fp.sub(X3, t0); Z3 = Fp.mul(t2, t1); Z3 = Fp.add(Z3, Z3); Z3 = Fp.add(Z3, Z3); return new Point(X3, Y3, Z3); } // Renes-Costello-Batina exception-free addition formula. // There is 30% faster Jacobian formula, but it is not complete. // https://eprint.iacr.org/2015/1060, algorithm 1 // Cost: 12M + 0S + 3*a + 3*b3 + 23add. add(other) { aprjpoint(other); const { X: X1, Y: Y1, Z: Z1 } = this; const { X: X2, Y: Y2, Z: Z2 } = other; let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; const a = CURVE.a; const b3 = Fp.mul(CURVE.b, _3n2); let t0 = Fp.mul(X1, X2); let t1 = Fp.mul(Y1, Y2); let t2 = Fp.mul(Z1, Z2); let t3 = Fp.add(X1, Y1); let t4 = Fp.add(X2, Y2); t3 = Fp.mul(t3, t4); t4 = Fp.add(t0, t1); t3 = Fp.sub(t3, t4); t4 = Fp.add(X1, Z1); let t5 = Fp.add(X2, Z2); t4 = Fp.mul(t4, t5); t5 = Fp.add(t0, t2); t4 = Fp.sub(t4, t5); t5 = Fp.add(Y1, Z1); X3 = Fp.add(Y2, Z2); t5 = Fp.mul(t5, X3); X3 = Fp.add(t1, t2); t5 = Fp.sub(t5, X3); Z3 = Fp.mul(a, t4); X3 = Fp.mul(b3, t2); Z3 = Fp.add(X3, Z3); X3 = Fp.sub(t1, Z3); Z3 = Fp.add(t1, Z3); Y3 = Fp.mul(X3, Z3); t1 = Fp.add(t0, t0); t1 = Fp.add(t1, t0); t2 = Fp.mul(a, t2); t4 = Fp.mul(b3, t4); t1 = Fp.add(t1, t2); t2 = Fp.sub(t0, t2); t2 = Fp.mul(a, t2); t4 = Fp.add(t4, t2); t0 = Fp.mul(t1, t4); Y3 = Fp.add(Y3, t0); t0 = Fp.mul(t5, t4); X3 = Fp.mul(t3, X3); X3 = Fp.sub(X3, t0); t0 = Fp.mul(t3, t1); Z3 = Fp.mul(t5, Z3); Z3 = Fp.add(Z3, t0); return new Point(X3, Y3, Z3); } subtract(other) { return this.add(other.negate()); } is0() { return this.equals(Point.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(scalar) { const { endo: endo2 } = extraOpts; if (!Fn.isValidNot0(scalar)) throw new Error("invalid scalar: out of range"); let point, fake; const mul = (n) => wnaf.cached(this, n, (p) => normalizeZ(Point, p)); if (endo2) { const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(scalar); const { p: k1p, f: k1f } = mul(k1); const { p: k2p, f: k2f } = mul(k2); fake = k1f.add(k2f); point = finishEndo(endo2.beta, k1p, k2p, k1neg, k2neg); } else { const { p, f } = mul(scalar); point = p; fake = f; } return normalizeZ(Point, [point, fake])[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(sc) { const { endo: endo2 } = extraOpts; const p = this; if (!Fn.isValid(sc)) throw new Error("invalid scalar: out of range"); if (sc === _0n4 || p.is0()) return Point.ZERO; if (sc === _1n4) return p; if (wnaf.hasCache(this)) return this.multiply(sc); if (endo2) { const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(sc); const { p1, p2 } = mulEndoUnsafe(Point, p, k1, k2); return finishEndo(endo2.beta, p1, p2, k1neg, k2neg); } else { return wnaf.unsafe(p, sc); } } /** * Converts Projective point to affine (x, y) coordinates. * @param invertedZ Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch */ toAffine(invertedZ) { return toAffineMemo(this, invertedZ); } /** * Checks whether Point is free of torsion elements (is in prime subgroup). * Always torsion-free for cofactor=1 curves. */ isTorsionFree() { const { isTorsionFree } = extraOpts; if (cofactor === _1n4) return true; if (isTorsionFree) return isTorsionFree(Point, this); return wnaf.unsafe(this, CURVE_ORDER).is0(); } clearCofactor() { const { clearCofactor } = extraOpts; if (cofactor === _1n4) return this; if (clearCofactor) return clearCofactor(Point, this); return this.multiplyUnsafe(cofactor); } isSmallOrder() { return this.multiplyUnsafe(cofactor).is0(); } toBytes(isCompressed = true) { abool(isCompressed, "isCompressed"); this.assertValidity(); return encodePoint(Point, this, isCompressed); } toHex(isCompressed = true) { return bytesToHex(this.toBytes(isCompressed)); } toString() { return ``; } } const bits = Fn.BITS; const wnaf = new wNAF(Point, extraOpts.endo ? Math.ceil(bits / 2) : bits); Point.BASE.precompute(8); return Point; } function pprefix(hasEvenY) { return Uint8Array.of(hasEvenY ? 2 : 3); } function getWLengths(Fp, Fn) { return { secretKey: Fn.BYTES, publicKey: 1 + Fp.BYTES, publicKeyUncompressed: 1 + 2 * Fp.BYTES, publicKeyHasPrefix: true, signature: 2 * Fn.BYTES }; } function ecdh(Point, ecdhOpts = {}) { const { Fn } = Point; const randomBytes_ = ecdhOpts.randomBytes || randomBytes; const lengths = Object.assign(getWLengths(Point.Fp, Fn), { seed: getMinHashLength(Fn.ORDER) }); function isValidSecretKey(secretKey) { try { const num2 = Fn.fromBytes(secretKey); return Fn.isValidNot0(num2); } catch (error2) { return false; } } function isValidPublicKey(publicKey, isCompressed) { const { publicKey: comp, publicKeyUncompressed } = lengths; try { const l = publicKey.length; if (isCompressed === true && l !== comp) return false; if (isCompressed === false && l !== publicKeyUncompressed) return false; return !!Point.fromBytes(publicKey); } catch (error2) { return false; } } function randomSecretKey(seed = randomBytes_(lengths.seed)) { return mapHashToField(abytes(seed, lengths.seed, "seed"), Fn.ORDER); } function getPublicKey3(secretKey, isCompressed = true) { return Point.BASE.multiply(Fn.fromBytes(secretKey)).toBytes(isCompressed); } function isProbPub(item) { const { secretKey, publicKey, publicKeyUncompressed } = lengths; if (!isBytes(item)) return void 0; if ("_lengths" in Fn && Fn._lengths || secretKey === publicKey) return void 0; const l = abytes(item, void 0, "key").length; return l === publicKey || l === publicKeyUncompressed; } function getSharedSecret(secretKeyA, publicKeyB, isCompressed = true) { if (isProbPub(secretKeyA) === true) throw new Error("first arg must be private key"); if (isProbPub(publicKeyB) === false) throw new Error("second arg must be public key"); const s = Fn.fromBytes(secretKeyA); const b = Point.fromBytes(publicKeyB); return b.multiply(s).toBytes(isCompressed); } const utils = { isValidSecretKey, isValidPublicKey, randomSecretKey }; const keygen = createKeygen(randomSecretKey, getPublicKey3); return Object.freeze({ getPublicKey: getPublicKey3, getSharedSecret, keygen, Point, utils, lengths }); } function ecdsa(Point, hash, ecdsaOpts = {}) { ahash(hash); validateObject(ecdsaOpts, {}, { hmac: "function", lowS: "boolean", randomBytes: "function", bits2int: "function", bits2int_modN: "function" }); ecdsaOpts = Object.assign({}, ecdsaOpts); const randomBytes3 = ecdsaOpts.randomBytes || randomBytes; const hmac2 = ecdsaOpts.hmac || ((key, msg) => hmac(hash, key, msg)); const { Fp, Fn } = Point; const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn; const { keygen, getPublicKey: getPublicKey3, getSharedSecret, utils, lengths } = ecdh(Point, ecdsaOpts); const defaultSigOpts = { prehash: true, lowS: typeof ecdsaOpts.lowS === "boolean" ? ecdsaOpts.lowS : true, format: "compact", extraEntropy: false }; const hasLargeCofactor = CURVE_ORDER * _2n2 < Fp.ORDER; function isBiggerThanHalfOrder(number) { const HALF = CURVE_ORDER >> _1n4; return number > HALF; } function validateRS(title, num2) { if (!Fn.isValidNot0(num2)) throw new Error(`invalid signature ${title}: out of range 1..Point.Fn.ORDER`); return num2; } function assertSmallCofactor() { if (hasLargeCofactor) throw new Error('"recovered" sig type is not supported for cofactor >2 curves'); } function validateSigLength(bytes, format) { validateSigFormat(format); const size = lengths.signature; const sizer = format === "compact" ? size : format === "recovered" ? size + 1 : void 0; return abytes(bytes, sizer); } class Signature { r; s; recovery; constructor(r, s, recovery) { this.r = validateRS("r", r); this.s = validateRS("s", s); if (recovery != null) { assertSmallCofactor(); if (![0, 1, 2, 3].includes(recovery)) throw new Error("invalid recovery id"); this.recovery = recovery; } Object.freeze(this); } static fromBytes(bytes, format = defaultSigOpts.format) { validateSigLength(bytes, format); let recid; if (format === "der") { const { r: r2, s: s2 } = DER.toSig(abytes(bytes)); return new Signature(r2, s2); } if (format === "recovered") { recid = bytes[0]; format = "compact"; bytes = bytes.subarray(1); } const L = lengths.signature / 2; const r = bytes.subarray(0, L); const s = bytes.subarray(L, L * 2); return new Signature(Fn.fromBytes(r), Fn.fromBytes(s), recid); } static fromHex(hex, format) { return this.fromBytes(hexToBytes(hex), format); } assertRecovery() { const { recovery } = this; if (recovery == null) throw new Error("invalid recovery id: must be present"); return recovery; } addRecoveryBit(recovery) { return new Signature(this.r, this.s, recovery); } recoverPublicKey(messageHash) { const { r, s } = this; const recovery = this.assertRecovery(); const radj = recovery === 2 || recovery === 3 ? r + CURVE_ORDER : r; if (!Fp.isValid(radj)) throw new Error("invalid recovery id: sig.r+curve.n != R.x"); const x = Fp.toBytes(radj); const R = Point.fromBytes(concatBytes(pprefix((recovery & 1) === 0), x)); const ir = Fn.inv(radj); const h = bits2int_modN(abytes(messageHash, void 0, "msgHash")); const u1 = Fn.create(-h * ir); const u2 = Fn.create(s * ir); const Q = Point.BASE.multiplyUnsafe(u1).add(R.multiplyUnsafe(u2)); if (Q.is0()) throw new Error("invalid recovery: point at infinify"); Q.assertValidity(); return Q; } // Signatures should be low-s, to prevent malleability. hasHighS() { return isBiggerThanHalfOrder(this.s); } toBytes(format = defaultSigOpts.format) { validateSigFormat(format); if (format === "der") return hexToBytes(DER.hexFromSig(this)); const { r, s } = this; const rb = Fn.toBytes(r); const sb = Fn.toBytes(s); if (format === "recovered") { assertSmallCofactor(); return concatBytes(Uint8Array.of(this.assertRecovery()), rb, sb); } return concatBytes(rb, sb); } toHex(format) { return bytesToHex(this.toBytes(format)); } } const bits2int = ecdsaOpts.bits2int || function bits2int_def(bytes) { if (bytes.length > 8192) throw new Error("input is too large"); const num2 = bytesToNumberBE(bytes); const delta = bytes.length * 8 - fnBits; return delta > 0 ? num2 >> BigInt(delta) : num2; }; const bits2int_modN = ecdsaOpts.bits2int_modN || function bits2int_modN_def(bytes) { return Fn.create(bits2int(bytes)); }; const ORDER_MASK = bitMask(fnBits); function int2octets(num2) { aInRange("num < 2^" + fnBits, num2, _0n4, ORDER_MASK); return Fn.toBytes(num2); } function validateMsgAndHash(message, prehash) { abytes(message, void 0, "message"); return prehash ? abytes(hash(message), void 0, "prehashed message") : message; } function prepSig(message, secretKey, opts) { const { lowS, prehash, extraEntropy } = validateSigOpts(opts, defaultSigOpts); message = validateMsgAndHash(message, prehash); const h1int = bits2int_modN(message); const d = Fn.fromBytes(secretKey); if (!Fn.isValidNot0(d)) throw new Error("invalid private key"); const seedArgs = [int2octets(d), int2octets(h1int)]; if (extraEntropy != null && extraEntropy !== false) { const e = extraEntropy === true ? randomBytes3(lengths.secretKey) : extraEntropy; seedArgs.push(abytes(e, void 0, "extraEntropy")); } const seed = concatBytes(...seedArgs); const m = h1int; function k2sig(kBytes) { const k = bits2int(kBytes); if (!Fn.isValidNot0(k)) return; const ik = Fn.inv(k); const q = Point.BASE.multiply(k).toAffine(); const r = Fn.create(q.x); if (r === _0n4) return; const s = Fn.create(ik * Fn.create(m + r * d)); if (s === _0n4) return; let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n4); let normS = s; if (lowS && isBiggerThanHalfOrder(s)) { normS = Fn.neg(s); recovery ^= 1; } return new Signature(r, normS, hasLargeCofactor ? void 0 : recovery); } return { seed, k2sig }; } function sign(message, secretKey, opts = {}) { const { seed, k2sig } = prepSig(message, secretKey, opts); const drbg = createHmacDrbg(hash.outputLen, Fn.BYTES, hmac2); const sig = drbg(seed, k2sig); return sig.toBytes(opts.format); } function verify(signature, message, publicKey, opts = {}) { const { lowS, prehash, format } = validateSigOpts(opts, defaultSigOpts); publicKey = abytes(publicKey, void 0, "publicKey"); message = validateMsgAndHash(message, prehash); if (!isBytes(signature)) { const end = signature instanceof Signature ? ", use sig.toBytes()" : ""; throw new Error("verify expects Uint8Array signature" + end); } validateSigLength(signature, format); try { const sig = Signature.fromBytes(signature, format); const P = Point.fromBytes(publicKey); if (lowS && sig.hasHighS()) return false; const { r, s } = sig; const h = bits2int_modN(message); const is = Fn.inv(s); const u1 = Fn.create(h * is); const u2 = Fn.create(r * is); const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2)); if (R.is0()) return false; const v = Fn.create(R.x); return v === r; } catch (e) { return false; } } function recoverPublicKey(signature, message, opts = {}) { const { prehash } = validateSigOpts(opts, defaultSigOpts); message = validateMsgAndHash(message, prehash); return Signature.fromBytes(signature, "recovered").recoverPublicKey(message).toBytes(); } return Object.freeze({ keygen, getPublicKey: getPublicKey3, getSharedSecret, utils, lengths, Point, sign, verify, recoverPublicKey, Signature, hash }); } var divNearest, DERErr, DER, _0n4, _1n4, _2n2, _3n2, _4n2; var init_weierstrass = __esm({ "node_modules/@noble/curves/abstract/weierstrass.js"() { init_hmac(); init_utils(); init_utils2(); init_curve(); init_modular(); divNearest = (num2, den) => (num2 + (num2 >= 0 ? den : -den) / _2n2) / den; DERErr = class extends Error { constructor(m = "") { super(m); } }; DER = { // asn.1 DER encoding utils Err: DERErr, // Basic building block is TLV (Tag-Length-Value) _tlv: { encode: (tag, data) => { const { Err: E } = DER; if (tag < 0 || tag > 256) throw new E("tlv.encode: wrong tag"); if (data.length & 1) throw new E("tlv.encode: unpadded data"); const dataLen = data.length / 2; const len = numberToHexUnpadded(dataLen); if (len.length / 2 & 128) throw new E("tlv.encode: long form length too big"); const lenLen = dataLen > 127 ? numberToHexUnpadded(len.length / 2 | 128) : ""; const t = numberToHexUnpadded(tag); return t + lenLen + len + data; }, // v - value, l - left bytes (unparsed) decode(tag, data) { const { Err: E } = DER; let pos = 0; if (tag < 0 || tag > 256) throw new E("tlv.encode: wrong tag"); if (data.length < 2 || data[pos++] !== tag) throw new E("tlv.decode: wrong tlv"); const first = data[pos++]; const isLong = !!(first & 128); let length = 0; if (!isLong) length = first; else { const lenLen = first & 127; if (!lenLen) throw new E("tlv.decode(long): indefinite length not supported"); if (lenLen > 4) throw new E("tlv.decode(long): byte length is too big"); const lengthBytes = data.subarray(pos, pos + lenLen); if (lengthBytes.length !== lenLen) throw new E("tlv.decode: length bytes not complete"); if (lengthBytes[0] === 0) throw new E("tlv.decode(long): zero leftmost byte"); for (const b of lengthBytes) length = length << 8 | b; pos += lenLen; if (length < 128) throw new E("tlv.decode(long): not minimal encoding"); } const v = data.subarray(pos, pos + length); if (v.length !== length) throw new E("tlv.decode: wrong value length"); return { v, l: data.subarray(pos + length) }; } }, // 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(num2) { const { Err: E } = DER; if (num2 < _0n4) throw new E("integer: negative integers are not allowed"); let hex = numberToHexUnpadded(num2); if (Number.parseInt(hex[0], 16) & 8) hex = "00" + hex; if (hex.length & 1) throw new E("unexpected DER parsing assertion: unpadded hex"); return hex; }, decode(data) { const { Err: E } = DER; if (data[0] & 128) throw new E("invalid signature integer: negative"); if (data[0] === 0 && !(data[1] & 128)) throw new E("invalid signature integer: unnecessary leading zero"); return bytesToNumberBE(data); } }, toSig(bytes) { const { Err: E, _int: int, _tlv: tlv } = DER; const data = abytes(bytes, void 0, "signature"); const { v: seqBytes, l: seqLeftBytes } = tlv.decode(48, data); if (seqLeftBytes.length) throw new E("invalid signature: left bytes after parsing"); const { v: rBytes, l: rLeftBytes } = tlv.decode(2, seqBytes); const { v: sBytes, l: sLeftBytes } = tlv.decode(2, rLeftBytes); if (sLeftBytes.length) throw new E("invalid signature: left bytes after parsing"); return { r: int.decode(rBytes), s: int.decode(sBytes) }; }, hexFromSig(sig) { const { _tlv: tlv, _int: int } = DER; const rs = tlv.encode(2, int.encode(sig.r)); const ss = tlv.encode(2, int.encode(sig.s)); const seq = rs + ss; return tlv.encode(48, seq); } }; _0n4 = BigInt(0); _1n4 = BigInt(1); _2n2 = BigInt(2); _3n2 = BigInt(3); _4n2 = BigInt(4); } }); // node_modules/@noble/curves/secp256k1.js function sqrtMod(y) { const P = secp256k1_CURVE.p; const _3n3 = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22); const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88); const b2 = y * y * y % P; const b3 = b2 * b2 * y % P; const b6 = pow2(b3, _3n3, P) * b3 % P; const b9 = pow2(b6, _3n3, P) * b3 % P; const b11 = pow2(b9, _2n3, P) * b2 % P; const b22 = pow2(b11, _11n, P) * b11 % P; const b44 = pow2(b22, _22n, P) * b22 % P; const b88 = pow2(b44, _44n, P) * b44 % P; const b176 = pow2(b88, _88n, P) * b88 % P; const b220 = pow2(b176, _44n, P) * b44 % P; const b223 = pow2(b220, _3n3, P) * b3 % P; const t1 = pow2(b223, _23n, P) * b22 % P; const t2 = pow2(t1, _6n, P) * b2 % P; const root = pow2(t2, _2n3, P); if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error("Cannot find square root"); return root; } function taggedHash(tag, ...messages) { let tagP = TAGGED_HASH_PREFIXES[tag]; if (tagP === void 0) { const tagH = sha256(asciiToBytes(tag)); tagP = concatBytes(tagH, tagH); TAGGED_HASH_PREFIXES[tag] = tagP; } return sha256(concatBytes(tagP, ...messages)); } function schnorrGetExtPubKey(priv) { const { Fn, BASE } = Pointk1; const d_ = Fn.fromBytes(priv); const p = BASE.multiply(d_); const scalar = hasEven(p.y) ? d_ : Fn.neg(d_); return { scalar, bytes: pointToBytes(p) }; } function lift_x(x) { const Fp = Fpk1; if (!Fp.isValidNot0(x)) throw new Error("invalid x: Fail if x \u2265 p"); const xx = Fp.create(x * x); const c = Fp.create(xx * x + BigInt(7)); let y = Fp.sqrt(c); if (!hasEven(y)) y = Fp.neg(y); const p = Pointk1.fromAffine({ x, y }); p.assertValidity(); return p; } function challenge(...args) { return Pointk1.Fn.create(num(taggedHash("BIP0340/challenge", ...args))); } function schnorrGetPublicKey(secretKey) { return schnorrGetExtPubKey(secretKey).bytes; } function schnorrSign(message, secretKey, auxRand = randomBytes(32)) { const { Fn } = Pointk1; const m = abytes(message, void 0, "message"); const { bytes: px, scalar: d } = schnorrGetExtPubKey(secretKey); const a = abytes(auxRand, 32, "auxRand"); const t = Fn.toBytes(d ^ num(taggedHash("BIP0340/aux", a))); const rand = taggedHash("BIP0340/nonce", t, px, m); const { bytes: rx, scalar: k } = schnorrGetExtPubKey(rand); const e = challenge(rx, px, m); const sig = new Uint8Array(64); sig.set(rx, 0); sig.set(Fn.toBytes(Fn.create(k + e * d)), 32); if (!schnorrVerify(sig, m, px)) throw new Error("sign: Invalid signature produced"); return sig; } function schnorrVerify(signature, message, publicKey) { const { Fp, Fn, BASE } = Pointk1; const sig = abytes(signature, 64, "signature"); const m = abytes(message, void 0, "message"); const pub = abytes(publicKey, 32, "publicKey"); try { const P = lift_x(num(pub)); const r = num(sig.subarray(0, 32)); if (!Fp.isValidNot0(r)) return false; const s = num(sig.subarray(32, 64)); if (!Fn.isValidNot0(s)) return false; const e = challenge(Fn.toBytes(r), pointToBytes(P), m); const R = BASE.multiplyUnsafe(s).add(P.multiplyUnsafe(Fn.neg(e))); const { x, y } = R.toAffine(); if (R.is0() || !hasEven(y) || x !== r) return false; return true; } catch (error2) { return false; } } var secp256k1_CURVE, secp256k1_ENDO, _0n5, _2n3, Fpk1, Pointk1, secp256k1, TAGGED_HASH_PREFIXES, pointToBytes, hasEven, num, schnorr; var init_secp256k1 = __esm({ "node_modules/@noble/curves/secp256k1.js"() { init_sha2(); init_utils(); init_curve(); init_modular(); init_weierstrass(); init_utils2(); secp256k1_CURVE = { p: BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"), n: BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"), h: BigInt(1), a: BigInt(0), b: BigInt(7), Gx: BigInt("0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"), Gy: BigInt("0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8") }; secp256k1_ENDO = { beta: BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"), basises: [ [BigInt("0x3086d221a7d46bcde86c90e49284eb15"), -BigInt("0xe4437ed6010e88286f547fa90abfe4c3")], [BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8"), BigInt("0x3086d221a7d46bcde86c90e49284eb15")] ] }; _0n5 = /* @__PURE__ */ BigInt(0); _2n3 = /* @__PURE__ */ BigInt(2); Fpk1 = Field(secp256k1_CURVE.p, { sqrt: sqrtMod }); Pointk1 = /* @__PURE__ */ weierstrass(secp256k1_CURVE, { Fp: Fpk1, endo: secp256k1_ENDO }); secp256k1 = /* @__PURE__ */ ecdsa(Pointk1, sha256); TAGGED_HASH_PREFIXES = {}; pointToBytes = (point) => point.toBytes(true).slice(1); hasEven = (y) => y % _2n3 === _0n5; num = bytesToNumberBE; schnorr = /* @__PURE__ */ (() => { const size = 32; const seedLength = 48; const randomSecretKey = (seed = randomBytes(seedLength)) => { return mapHashToField(seed, secp256k1_CURVE.n); }; return { keygen: createKeygen(randomSecretKey, schnorrGetPublicKey), getPublicKey: schnorrGetPublicKey, sign: schnorrSign, verify: schnorrVerify, Point: Pointk1, utils: { randomSecretKey, taggedHash, lift_x, pointToBytes }, lengths: { secretKey: size, publicKey: size, publicKeyHasPrefix: false, signature: size * 2, seed: seedLength } }; })(); } }); // node_modules/nostr-tools/lib/esm/pool.js function normalizeURL(url) { try { if (url.indexOf("://") === -1) url = "wss://" + url; let p = new URL(url); if (p.protocol === "http:") p.protocol = "ws:"; else if (p.protocol === "https:") p.protocol = "wss:"; p.pathname = p.pathname.replace(/\/+/g, "/"); if (p.pathname.endsWith("/")) p.pathname = p.pathname.slice(0, -1); if (p.port === "80" && p.protocol === "ws:" || p.port === "443" && p.protocol === "wss:") p.port = ""; p.searchParams.sort(); p.hash = ""; return p.toString(); } catch (e) { throw new Error(`Invalid URL: ${url}`); } } function isHex32(input) { if (input.length !== 64) return false; for (let i22 = 0; i22 < 64; i22++) { let cc = input.charCodeAt(i22); if (isNaN(cc) || cc < 48 || cc > 102 || cc > 57 && cc < 97) { return false; } } return true; } function validateEvent(event) { if (!isRecord(event)) return false; if (typeof event.kind !== "number") return false; if (typeof event.content !== "string") return false; if (typeof event.created_at !== "number") return false; if (typeof event.pubkey !== "string") return false; if (!isHex32(event.pubkey)) return false; if (!Array.isArray(event.tags)) return false; for (let i22 = 0; i22 < event.tags.length; i22++) { let tag = event.tags[i22]; if (!Array.isArray(tag)) return false; for (let j = 0; j < tag.length; j++) { if (typeof tag[j] !== "string") return false; } } return true; } function serializeEvent(evt) { if (!validateEvent(evt)) throw new Error("can't serialize event with wrong or missing properties"); return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]); } function getEventHash(event) { let eventHash = sha256(utf8Encoder.encode(serializeEvent(event))); return bytesToHex(eventHash); } function matchFilter(filter, event) { if (filter.ids && filter.ids.indexOf(event.id) === -1) { return false; } if (filter.kinds && filter.kinds.indexOf(event.kind) === -1) { return false; } if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) { return false; } for (let f in filter) { if (f[0] === "#") { let tagName = f.slice(1); let values = filter[`#${tagName}`]; if (values && !event.tags.find(([t, v]) => t === f.slice(1) && values.indexOf(v) !== -1)) return false; } } if (filter.since && event.created_at < filter.since) return false; if (filter.until && event.created_at > filter.until) return false; return true; } function matchFilters(filters, event) { for (let i22 = 0; i22 < filters.length; i22++) { if (matchFilter(filters[i22], event)) { return true; } } return false; } function getHex64(json, field) { let len = field.length + 3; let idx = json.indexOf(`"${field}":`) + len; let s = json.slice(idx).indexOf(`"`) + idx + 1; return json.slice(s, s + 64); } function getSubscriptionId(json) { let idx = json.slice(0, 22).indexOf(`"EVENT"`); if (idx === -1) return null; let pstart = json.slice(idx + 7 + 1).indexOf(`"`); if (pstart === -1) return null; let start = idx + 7 + 1 + pstart; let pend = json.slice(start + 1, 80).indexOf(`"`); if (pend === -1) return null; let end = start + 1 + pend; return json.slice(start + 1, end); } function makeAuthEvent(relayURL, challenge2) { return { kind: ClientAuth, created_at: Math.floor(Date.now() / 1e3), tags: [ ["relay", relayURL], ["challenge", challenge2] ], content: "" }; } function getCountManyFilter(target, directive) { switch (directive) { case "reactions": return { "#e": [target], kinds: [7] }; case "reposts": return { "#e": [target], kinds: [6] }; case "quotes": return { "#q": [target], kinds: [1, 1111] }; case "replies": return { "#e": [target], kinds: [1] }; case "comments": return { "#E": [target], kinds: [1111] }; case "followers": return { "#p": [target], kinds: [3] }; } } function newHll() { return new Uint8Array(M); } function hllDecode(hex) { if (hex.length !== HLL_HEX_LENGTH || !/^[0-9a-f]+$/.test(hex)) return void 0; const registers = new Uint8Array(M); for (let i22 = 0; i22 < M; i22++) { registers[i22] = parseInt(hex.slice(i22 * 2, i22 * 2 + 2), 16); } return registers; } function hllEncode(registers) { if (registers.length !== M) throw new Error(`invalid number of registers ${registers.length}`); let hex = ""; for (let i22 = 0; i22 < M; i22++) { hex += registers[i22].toString(16).padStart(2, "0"); } return hex; } function mergeHll(target, source) { if (target.length === 0) target = newHll(); if (target.length !== M) throw new Error(`invalid number of registers ${target.length}`); if (source.length !== M) throw new Error(`invalid number of registers ${source.length}`); for (let i22 = 0; i22 < M; i22++) { if (source[i22] > target[i22]) target[i22] = source[i22]; } return target; } function useWebSocketImplementation(websocketImplementation) { _WebSocket = websocketImplementation; } var utf8Decoder, utf8Encoder, verifiedSymbol, isRecord, JS, i, generateSecretKey, getPublicKey, finalizeEvent, verifyEvent, ClientAuth, SendingOnClosedConnection, AbstractRelay, Subscription, M, HLL_HEX_LENGTH, utf8Encoder2, AbstractSimplePool, _WebSocket, SimplePool; var init_pool = __esm({ "node_modules/nostr-tools/lib/esm/pool.js"() { init_secp256k1(); init_utils(); init_sha2(); utf8Decoder = new TextDecoder("utf-8"); utf8Encoder = new TextEncoder(); verifiedSymbol = /* @__PURE__ */ Symbol("verified"); isRecord = (obj) => obj instanceof Object; JS = class { generateSecretKey() { return schnorr.utils.randomSecretKey(); } getPublicKey(secretKey) { return bytesToHex(schnorr.getPublicKey(secretKey)); } finalizeEvent(t, secretKey) { const event = t; event.pubkey = bytesToHex(schnorr.getPublicKey(secretKey)); event.id = getEventHash(event); event.sig = bytesToHex(schnorr.sign(hexToBytes(getEventHash(event)), secretKey)); event[verifiedSymbol] = true; return event; } verifyEvent(event) { if (typeof event[verifiedSymbol] === "boolean") return event[verifiedSymbol]; try { const hash = getEventHash(event); if (hash !== event.id) { event[verifiedSymbol] = false; return false; } const valid = schnorr.verify(hexToBytes(event.sig), hexToBytes(hash), hexToBytes(event.pubkey)); event[verifiedSymbol] = valid; return valid; } catch (err) { event[verifiedSymbol] = false; return false; } } }; i = new JS(); generateSecretKey = i.generateSecretKey; getPublicKey = i.getPublicKey; finalizeEvent = i.finalizeEvent; verifyEvent = i.verifyEvent; ClientAuth = 22242; SendingOnClosedConnection = class extends Error { constructor(message, relay) { super(`Tried to send message '${message} on a closed connection to ${relay}.`); this.name = "SendingOnClosedConnection"; } }; AbstractRelay = class { url; _connected = false; onclose = null; onnotice = (msg) => console.debug(`NOTICE from ${this.url}: ${msg}`); onauth; baseEoseTimeout = 4400; publishTimeout = 4400; pingFrequency = 29e3; pingTimeout = 2e4; resubscribeBackoff = [1e4, 1e4, 1e4, 2e4, 2e4, 3e4, 6e4]; openSubs = /* @__PURE__ */ new Map(); enablePing; enableReconnect; idleTimeout = 0; idleSince = Date.now(); ongoingOperations = 0; reconnectTimeoutHandle; pingIntervalHandle; reconnectAttempts = 0; skipReconnection = false; idleTimeoutHandle; connectionPromise; openCountRequests = /* @__PURE__ */ new Map(); openEventPublishes = /* @__PURE__ */ new Map(); ws; challenge; authPromise; serial = 0; verifyEvent; _WebSocket; constructor(url, opts) { this.url = normalizeURL(url); this.verifyEvent = opts.verifyEvent; this._WebSocket = opts.websocketImplementation || WebSocket; this.enablePing = opts.enablePing; this.enableReconnect = opts.enableReconnect || false; if (opts.idleTimeout) this.idleTimeout = opts.idleTimeout; } static async connect(url, opts) { const relay = new AbstractRelay(url, opts); await relay.connect(opts); return relay; } closeAllSubscriptions(reason) { for (let [_, sub] of this.openSubs) { sub.close(reason); } this.openSubs.clear(); for (let [_, ep] of this.openEventPublishes) { ep.reject(new Error(reason)); } this.openEventPublishes.clear(); for (let [_, cr] of this.openCountRequests) { cr.reject(new Error(reason)); } this.openCountRequests.clear(); } get connected() { return this._connected; } clearIdleTimeout() { if (this.idleTimeoutHandle) { clearTimeout(this.idleTimeoutHandle); this.idleTimeoutHandle = void 0; } } scheduleIdleClose() { this.clearIdleTimeout(); if (this.idleTimeout > 0) { this.idleTimeoutHandle = setTimeout(() => { if (this.ongoingOperations === 0 && this.idleSince) { this.close(); } }, this.idleTimeout); } } async reconnect() { const backoff = this.resubscribeBackoff[Math.min(this.reconnectAttempts, this.resubscribeBackoff.length - 1)]; this.reconnectAttempts++; this.reconnectTimeoutHandle = setTimeout(async () => { try { await this.connect(); } catch (err) { } }, backoff); } handleHardClose(reason) { if (this.ws) { this.ws.onopen = null; this.ws.onerror = null; this.ws.onclose = null; } if (this.pingIntervalHandle) { clearInterval(this.pingIntervalHandle); this.pingIntervalHandle = void 0; } this._connected = false; this.connectionPromise = void 0; this.idleSince = void 0; this.clearIdleTimeout(); if (this.enableReconnect && !this.skipReconnection) { this.reconnect(); } else { this.onclose?.(); this.closeAllSubscriptions(reason); } } async connect(opts) { let connectionTimeoutHandle; if (this.connectionPromise) return this.connectionPromise; this.challenge = void 0; this.authPromise = void 0; this.skipReconnection = false; this.connectionPromise = new Promise((resolve, reject) => { if (opts?.timeout) { connectionTimeoutHandle = setTimeout(() => { reject("connection timed out"); this.connectionPromise = void 0; if (this.reconnectAttempts === 0) { this.skipReconnection = true; } this.handleHardClose("relay connection timed out"); }, opts.timeout); } if (opts?.abort) { opts.abort.onabort = reject; } try { this.ws = new this._WebSocket(this.url); } catch (err) { clearTimeout(connectionTimeoutHandle); reject(err); return; } this.ws.onopen = () => { if (this.reconnectTimeoutHandle) { clearTimeout(this.reconnectTimeoutHandle); this.reconnectTimeoutHandle = void 0; } clearTimeout(connectionTimeoutHandle); this._connected = true; const isReconnection = this.reconnectAttempts > 0; this.reconnectAttempts = 0; for (const sub of this.openSubs.values()) { sub.eosed = false; if (isReconnection) { for (let f = 0; f < sub.filters.length; f++) { if (sub.lastEmitted) { sub.filters[f].since = sub.lastEmitted + 1; } } } sub.fire(); } if (this.enablePing) { this.pingIntervalHandle = setInterval(() => this.pingpong(), this.pingFrequency); } resolve(); }; this.ws.onerror = () => { clearTimeout(connectionTimeoutHandle); reject("connection failed"); this.connectionPromise = void 0; if (this.reconnectAttempts === 0) { this.skipReconnection = true; } this.handleHardClose("relay connection failed"); }; this.ws.onclose = (ev) => { clearTimeout(connectionTimeoutHandle); reject(ev.message || "websocket closed"); this.handleHardClose("relay connection closed"); }; this.ws.onmessage = this._onmessage.bind(this); }); return this.connectionPromise; } waitForPingPong() { return new Promise((resolve) => { ; this.ws.once("pong", () => resolve(true)); this.ws.ping(); }); } waitForDummyReq() { return new Promise((resolve, reject) => { if (!this.connectionPromise) return reject(new Error(`no connection to ${this.url}, can't ping`)); try { const sub = this.subscribe( [{ ids: ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], limit: 0 }], { label: "", oneose: () => { resolve(true); sub.close(); }, onclose() { resolve(true); }, eoseTimeout: this.pingTimeout + 1e3 } ); } catch (err) { reject(err); } }); } async pingpong() { if (this.ws?.readyState === 1) { const result = await Promise.any([ this.ws && this.ws.ping && this.ws.once ? this.waitForPingPong() : this.waitForDummyReq(), new Promise((res) => setTimeout(() => res(false), this.pingTimeout)) ]); if (!result) { if (this.ws?.readyState === this._WebSocket.OPEN) { this.ws?.close(); } } } } async send(message) { if (!this.connectionPromise) throw new SendingOnClosedConnection(message, this.url); this.connectionPromise.then(() => { this.ws?.send(message); }); } async auth(signAuthEvent) { const challenge2 = this.challenge; if (!challenge2) throw new Error("can't perform auth, no challenge was received"); if (this.authPromise) return this.authPromise; this.authPromise = new Promise(async (resolve, reject) => { try { let evt = await signAuthEvent(makeAuthEvent(this.url, challenge2)); let timeout = setTimeout(() => { let ep = this.openEventPublishes.get(evt.id); if (ep) { ep.reject(new Error("auth timed out")); this.openEventPublishes.delete(evt.id); } }, this.publishTimeout); this.openEventPublishes.set(evt.id, { resolve, reject, timeout }); this.send('["AUTH",' + JSON.stringify(evt) + "]"); } catch (err) { console.warn("subscribe auth function failed:", err); } }); return this.authPromise; } async publish(event) { this.idleSince = void 0; this.clearIdleTimeout(); this.ongoingOperations++; const ret = new Promise((resolve, reject) => { const timeout = setTimeout(() => { const ep = this.openEventPublishes.get(event.id); if (ep) { ep.reject(new Error("publish timed out")); this.openEventPublishes.delete(event.id); } }, this.publishTimeout); this.openEventPublishes.set(event.id, { resolve, reject, timeout }); }); try { await this.send('["EVENT",' + JSON.stringify(event) + "]"); } catch (err) { const ep = this.openEventPublishes.get(event.id); if (ep) { ep.reject(err); this.openEventPublishes.delete(event.id); } } this.ongoingOperations--; if (this.ongoingOperations === 0) { this.idleSince = Date.now(); this.scheduleIdleClose(); } return ret; } async count(filters, params) { return (await this.countWithHLL(filters, params)).count; } async countWithHLL(filters, params) { this.serial++; const id = params?.id || "count:" + this.serial; const ret = new Promise((resolve, reject) => { this.openCountRequests.set(id, { resolve, reject }); }); try { await this.send('["COUNT","' + id + '",' + JSON.stringify(filters).substring(1)); } catch (err) { const cr = this.openCountRequests.get(id); if (cr) { cr.reject(err); this.openCountRequests.delete(id); } } return ret; } subscribe(filters, params) { if (params.label !== "") { this.idleSince = void 0; this.clearIdleTimeout(); this.ongoingOperations++; } const sub = this.prepareSubscription(filters, params); sub.fire(); if (params.abort) { params.abort.onabort = () => sub.close(String(params.abort.reason || "")); } return sub; } prepareSubscription(filters, params) { this.serial++; const id = params.id || (params.label ? params.label + ":" : "sub:") + this.serial; const sub = new Subscription(this, id, filters, params); this.openSubs.set(id, sub); return sub; } close() { this.skipReconnection = true; if (this.reconnectTimeoutHandle) { clearTimeout(this.reconnectTimeoutHandle); this.reconnectTimeoutHandle = void 0; } if (this.pingIntervalHandle) { clearInterval(this.pingIntervalHandle); this.pingIntervalHandle = void 0; } this.closeAllSubscriptions("relay connection closed by us"); this._connected = false; this.connectionPromise = void 0; this.idleSince = void 0; this.clearIdleTimeout(); this.onclose?.(); if (this.ws) { this.ws.onopen = null; this.ws.onerror = null; this.ws.onclose = null; if (this.ws.readyState !== this._WebSocket.CLOSING && this.ws.readyState !== this._WebSocket.CLOSED) { this.ws.close(); } } } _onmessage(ev) { const json = ev.data; if (!json) { return; } const subid = getSubscriptionId(json); if (subid) { const so = this.openSubs.get(subid); if (!so) { return; } const id = getHex64(json, "id"); const alreadyHave = so.alreadyHaveEvent?.(id); so.receivedEvent?.(this, id); if (alreadyHave) { return; } } try { let data = JSON.parse(json); switch (data[0]) { case "EVENT": { const so = this.openSubs.get(data[1]); const event = data[2]; if (matchFilters(so.filters, event) && this.verifyEvent(event, this.url)) { so.onevent(event); } else { so.oninvalidevent?.(event); } if (!so.lastEmitted || so.lastEmitted < event.created_at) so.lastEmitted = event.created_at; return; } case "COUNT": { const id = data[1]; const payload = data[2]; const cr = this.openCountRequests.get(id); if (cr) { cr.resolve(payload); this.openCountRequests.delete(id); } return; } case "EOSE": { const so = this.openSubs.get(data[1]); if (!so) return; so.receivedEose(); return; } case "OK": { const id = data[1]; const ok = data[2]; const reason = data[3]; const ep = this.openEventPublishes.get(id); if (ep) { clearTimeout(ep.timeout); if (ok) ep.resolve(reason); else ep.reject(new Error(reason)); this.openEventPublishes.delete(id); } return; } case "CLOSED": { const id = data[1]; const so = this.openSubs.get(id); if (!so) { const cr = this.openCountRequests.get(id); if (cr) { cr.reject(new Error(data[2])); this.openCountRequests.delete(id); } return; } so.closed = true; so.close(data[2]); return; } case "NOTICE": { this.onnotice(data[1]); return; } case "AUTH": { this.challenge = data[1]; if (this.onauth) { this.auth(this.onauth).catch((err) => { if (!(err instanceof SendingOnClosedConnection)) { throw err; } }); } return; } default: { const so = this.openSubs.get(data[1]); so?.oncustom?.(data); return; } } } catch (err) { try { const [_, __, event] = JSON.parse(json); console.warn(`[nostr] relay ${this.url} error processing message:`, err, event); } catch (_) { console.warn(`[nostr] relay ${this.url} error processing message:`, err); } return; } } }; Subscription = class { relay; id; lastEmitted; closed = false; eosed = false; filters; alreadyHaveEvent; receivedEvent; onevent; oninvalidevent; oneose; onclose; oncustom; eoseTimeout; eoseTimeoutHandle; constructor(relay, id, filters, params) { if (filters.length === 0) throw new Error("subscription can't be created with zero filters"); this.relay = relay; this.filters = filters; this.id = id; this.alreadyHaveEvent = params.alreadyHaveEvent; this.receivedEvent = params.receivedEvent; this.eoseTimeout = params.eoseTimeout || relay.baseEoseTimeout; this.oneose = params.oneose; this.onclose = params.onclose; this.oninvalidevent = params.oninvalidevent; this.onevent = params.onevent || ((event) => { console.warn( `onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`, event ); }); } fire() { this.relay.send('["REQ","' + this.id + '",' + JSON.stringify(this.filters).substring(1)); this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout); } receivedEose() { if (this.eosed) return; clearTimeout(this.eoseTimeoutHandle); this.eosed = true; this.oneose?.(); } close(reason = "closed by caller") { if (!this.closed && this.relay.connected) { try { this.relay.send('["CLOSE",' + JSON.stringify(this.id) + "]"); } catch (err) { if (err instanceof SendingOnClosedConnection) { } else { throw err; } } this.closed = true; } this.relay.openSubs.delete(this.id); if (!this.id.startsWith("")) { this.relay.ongoingOperations--; if (this.relay.ongoingOperations === 0) { this.relay.idleSince = Date.now(); this.relay.scheduleIdleClose(); } } this.onclose?.(reason); } }; M = 256; HLL_HEX_LENGTH = M * 2; utf8Encoder2 = new TextEncoder(); AbstractSimplePool = class { relays = /* @__PURE__ */ new Map(); seenOn = /* @__PURE__ */ new Map(); trackRelays = false; verifyEvent; enablePing; enableReconnect; idleTimeout = 2e4; automaticallyAuth; onRelayConnectionFailure; onRelayConnectionSuccess; allowConnectingToRelay; maxWaitForConnection; _WebSocket; constructor(opts) { this.verifyEvent = opts.verifyEvent; this._WebSocket = opts.websocketImplementation; this.enablePing = opts.enablePing; this.enableReconnect = opts.enableReconnect || false; if (opts.idleTimeout) this.idleTimeout = opts.idleTimeout; this.automaticallyAuth = opts.automaticallyAuth; this.onRelayConnectionFailure = opts.onRelayConnectionFailure; this.onRelayConnectionSuccess = opts.onRelayConnectionSuccess; this.allowConnectingToRelay = opts.allowConnectingToRelay; this.maxWaitForConnection = opts.maxWaitForConnection || 3e3; } async ensureRelay(url, params) { url = normalizeURL(url); let relay = this.relays.get(url); if (!relay) { relay = new AbstractRelay(url, { verifyEvent: this.verifyEvent, websocketImplementation: this._WebSocket, enablePing: this.enablePing, enableReconnect: this.enableReconnect, idleTimeout: this.idleTimeout }); relay.onclose = () => { this.relays.delete(url); }; this.relays.set(url, relay); } if (this.automaticallyAuth) { const authSignerFn = this.automaticallyAuth(url); if (authSignerFn) { relay.onauth = authSignerFn; } } try { await relay.connect({ timeout: params?.connectionTimeout, abort: params?.abort }); } catch (err) { this.relays.delete(url); throw err; } return relay; } close(relays) { relays.map(normalizeURL).forEach((url) => { this.relays.get(url)?.close(); this.relays.delete(url); }); } subscribe(relays, filter, params) { const request = []; const uniqUrls = []; for (let i22 = 0; i22 < relays.length; i22++) { const url = normalizeURL(relays[i22]); if (!request.find((r) => r.url === url)) { if (uniqUrls.indexOf(url) === -1) { uniqUrls.push(url); request.push({ url, filter }); } } } return this.subscribeMap(request, params); } subscribeMany(relays, filter, params) { return this.subscribe(relays, filter, params); } subscribeMap(requests, params) { const grouped = /* @__PURE__ */ new Map(); for (const req of requests) { const { url, filter } = req; if (!grouped.has(url)) grouped.set(url, []); grouped.get(url).push(filter); } const groupedRequests = Array.from(grouped.entries()).map(([url, filters]) => ({ url, filters })); if (this.trackRelays) { params.receivedEvent = (relay, id) => { let set = this.seenOn.get(id); if (!set) { set = /* @__PURE__ */ new Set(); this.seenOn.set(id, set); } set.add(relay); }; } const _knownIds = /* @__PURE__ */ new Set(); const subs = []; const eosesReceived = []; let handleEose = (i22) => { if (eosesReceived[i22]) return; eosesReceived[i22] = true; if (eosesReceived.filter((a) => a).length === groupedRequests.length) { params.oneose?.(); handleEose = () => { }; } }; const closesReceived = []; let handleClose = (i22, url, reason) => { if (closesReceived[i22]) return; handleEose(i22); closesReceived[i22] = { url, reason }; if (closesReceived.filter((a) => a).length === groupedRequests.length) { params.onclose?.(closesReceived); handleClose = () => { }; } }; const localAlreadyHaveEventHandler = (id) => { if (params.alreadyHaveEvent?.(id)) { return true; } const have = _knownIds.has(id); _knownIds.add(id); return have; }; const allOpened = Promise.all( groupedRequests.map(async ({ url, filters }, i22) => { if (this.allowConnectingToRelay?.(url, ["read", filters]) === false) { handleClose(i22, url, "connection skipped by allowConnectingToRelay"); return; } let relay; try { relay = await this.ensureRelay(url, { connectionTimeout: this.maxWaitForConnection < (params.maxWait || 0) ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : this.maxWaitForConnection, abort: params.abort }); } catch (err) { this.onRelayConnectionFailure?.(url); handleClose(i22, url, err?.message || String(err)); return; } this.onRelayConnectionSuccess?.(url); let subscription = relay.subscribe(filters, { ...params, oneose: () => handleEose(i22), onclose: (reason) => { if (reason.startsWith("auth-required: ") && params.onauth) { relay.auth(params.onauth).then(() => { relay.subscribe(filters, { ...params, oneose: () => handleEose(i22), onclose: (reason2) => { handleClose(i22, url, reason2); }, alreadyHaveEvent: localAlreadyHaveEventHandler, eoseTimeout: params.maxWait, abort: params.abort }); }).catch((err) => { handleClose(i22, url, `auth was required and attempted, but failed with: ${err}`); }); } else { handleClose(i22, url, reason); } }, alreadyHaveEvent: localAlreadyHaveEventHandler, eoseTimeout: params.maxWait, abort: params.abort }); subs.push(subscription); }) ); return { async close(reason) { await allOpened; subs.forEach((sub) => { sub.close(reason); }); } }; } subscribeEose(relays, filter, params) { let subcloser; subcloser = this.subscribe(relays, filter, { ...params, oneose() { const reason = "closed automatically on eose"; if (subcloser) subcloser.close(reason); else params.onclose?.(relays.map((url) => ({ url, reason }))); } }); return subcloser; } subscribeManyEose(relays, filter, params) { return this.subscribeEose(relays, filter, params); } async querySync(relays, filter, params) { return new Promise(async (resolve) => { const events = []; this.subscribeEose(relays, filter, { ...params, onevent(event) { events.push(event); }, onclose(_) { resolve(events); } }); }); } async get(relays, filter, params) { filter.limit = 1; const events = await this.querySync(relays, filter, params); events.sort((a, b) => b.created_at - a.created_at); return events[0] || null; } async countMany(relays, target, directive, params) { const filter = getCountManyFilter(target, directive); const urls = []; for (let i22 = 0; i22 < relays.length; i22++) { const url = normalizeURL(relays[i22]); if (urls.indexOf(url) === -1) urls.push(url); } const responses = await Promise.all( urls.map(async (url) => { if (this.allowConnectingToRelay?.(url, ["read", [filter]]) === false) return null; let relay; try { relay = await this.ensureRelay(url, { connectionTimeout: this.maxWaitForConnection < (params?.maxWait || 0) ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : this.maxWaitForConnection, abort: params?.abort }); } catch (err) { this.onRelayConnectionFailure?.(url); return null; } this.onRelayConnectionSuccess?.(url); return relay.countWithHLL([filter], { id: params?.id }).catch(() => null); }) ); let count = 0; let hll; for (const response of responses) { if (!response) continue; if (response.count > count) count = response.count; if (!response.hll || response.hll.length !== 512) continue; const registers = hllDecode(response.hll); if (!registers) continue; hll = mergeHll(hll || new Uint8Array(0), registers); } return hll ? { count, hll: hllEncode(hll) } : { count }; } publish(relays, event, params) { return relays.map(normalizeURL).map(async (url, i22, arr) => { if (arr.indexOf(url) !== i22) { return Promise.reject("duplicate url"); } if (this.allowConnectingToRelay?.(url, ["write", event]) === false) { return Promise.reject("connection skipped by allowConnectingToRelay"); } let r; try { r = await this.ensureRelay(url, { connectionTimeout: this.maxWaitForConnection < (params?.maxWait || 0) ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : this.maxWaitForConnection, abort: params?.abort }); } catch (err) { this.onRelayConnectionFailure?.(url); return Promise.reject("connection failure: " + String(err)); } return r.publish(event).catch(async (err) => { if (err instanceof Error && err.message.startsWith("auth-required: ") && params?.onauth) { await r.auth(params.onauth); return r.publish(event); } throw err; }).then((reason) => { if (this.trackRelays) { let set = this.seenOn.get(event.id); if (!set) { set = /* @__PURE__ */ new Set(); this.seenOn.set(event.id, set); } set.add(r); } return reason; }); }); } listConnectionStatus() { const map = /* @__PURE__ */ new Map(); this.relays.forEach((relay, url) => map.set(url, relay.connected)); return map; } destroy() { this.relays.forEach((conn) => conn.close()); this.relays = /* @__PURE__ */ new Map(); } pruneIdleRelays(idleThresholdMs = 1e4) { const prunedUrls = []; for (const [url, relay] of this.relays) { if (relay.idleSince && Date.now() - relay.idleSince >= idleThresholdMs) { this.relays.delete(url); prunedUrls.push(url); relay.close(); } } return prunedUrls; } }; try { _WebSocket = WebSocket; } catch { } SimplePool = class extends AbstractSimplePool { constructor(options) { super({ verifyEvent, websocketImplementation: _WebSocket, maxWaitForConnection: 3e3, ...options }); } }; } }); // node_modules/@noble/ciphers/utils.js function isBytes2(a) { return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array"; } function abool2(b) { if (typeof b !== "boolean") throw new Error(`boolean expected, not ${b}`); } function anumber2(n) { if (!Number.isSafeInteger(n) || n < 0) throw new Error("positive integer expected, got " + n); } function abytes2(value, length, title = "") { const bytes = isBytes2(value); const len = value?.length; const needsLen = length !== void 0; if (!bytes || needsLen && len !== length) { const prefix = title && `"${title}" `; const ofLen = needsLen ? ` of length ${length}` : ""; const got = bytes ? `length=${len}` : `type=${typeof value}`; throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got); } return value; } function aexists2(instance, checkFinished = true) { if (instance.destroyed) throw new Error("Hash instance has been destroyed"); if (checkFinished && instance.finished) throw new Error("Hash#digest() has already been called"); } function aoutput2(out, instance) { abytes2(out, void 0, "output"); const min = instance.outputLen; if (out.length < min) { throw new Error("digestInto() expects output buffer of length at least " + min); } } function u32(arr) { return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4)); } function clean2(...arrays) { for (let i3 = 0; i3 < arrays.length; i3++) { arrays[i3].fill(0); } } function createView2(arr) { return new DataView(arr.buffer, arr.byteOffset, arr.byteLength); } function checkOpts(defaults, opts) { if (opts == null || typeof opts !== "object") throw new Error("options must be defined"); const merged = Object.assign(defaults, opts); return merged; } function equalBytes(a, b) { if (a.length !== b.length) return false; let diff = 0; for (let i3 = 0; i3 < a.length; i3++) diff |= a[i3] ^ b[i3]; return diff === 0; } function getOutput(expectedLength, out, onlyAligned = true) { if (out === void 0) return new Uint8Array(expectedLength); if (out.length !== expectedLength) throw new Error('"output" expected Uint8Array of length ' + expectedLength + ", got: " + out.length); if (onlyAligned && !isAligned32(out)) throw new Error("invalid output, must be aligned"); return out; } function u64Lengths(dataLength, aadLength, isLE2) { abool2(isLE2); const num2 = new Uint8Array(16); const view = createView2(num2); view.setBigUint64(0, BigInt(aadLength), isLE2); view.setBigUint64(8, BigInt(dataLength), isLE2); return num2; } function isAligned32(bytes) { return bytes.byteOffset % 4 === 0; } function copyBytes2(bytes) { return Uint8Array.from(bytes); } var isLE, wrapCipher; var init_utils3 = __esm({ "node_modules/@noble/ciphers/utils.js"() { isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68)(); wrapCipher = /* @__NO_SIDE_EFFECTS__ */ (params, constructor) => { function wrappedCipher(key, ...args) { abytes2(key, void 0, "key"); if (!isLE) throw new Error("Non little-endian hardware is not yet supported"); if (params.nonceLength !== void 0) { const nonce = args[0]; abytes2(nonce, params.varSizeNonce ? void 0 : params.nonceLength, "nonce"); } const tagl = params.tagLength; if (tagl && args[1] !== void 0) abytes2(args[1], void 0, "AAD"); const cipher = constructor(key, ...args); const checkOutput = (fnLength, output) => { if (output !== void 0) { if (fnLength !== 2) throw new Error("cipher output not supported"); abytes2(output, void 0, "output"); } }; let called = false; const wrCipher = { encrypt(data, output) { if (called) throw new Error("cannot encrypt() twice with same key + nonce"); called = true; abytes2(data); checkOutput(cipher.encrypt.length, output); return cipher.encrypt(data, output); }, decrypt(data, output) { abytes2(data); if (tagl && data.length < tagl) throw new Error('"ciphertext" expected length bigger than tagLength=' + tagl); checkOutput(cipher.decrypt.length, output); return cipher.decrypt(data, output); } }; return wrCipher; } Object.assign(wrappedCipher, params); return wrappedCipher; }; } }); // node_modules/@noble/ciphers/_arx.js function rotl(a, b) { return a << b | a >>> 32 - b; } function isAligned322(b) { return b.byteOffset % 4 === 0; } function runCipher(core, sigma, key, nonce, data, output, counter, rounds) { const len = data.length; const block = new Uint8Array(BLOCK_LEN); const b32 = u32(block); const isAligned = isAligned322(data) && isAligned322(output); const d32 = isAligned ? u32(data) : U32_EMPTY; const o32 = isAligned ? u32(output) : U32_EMPTY; for (let pos = 0; pos < len; counter++) { core(sigma, key, nonce, b32, counter, rounds); if (counter >= MAX_COUNTER) throw new Error("arx: counter overflow"); const take = Math.min(BLOCK_LEN, len - pos); if (isAligned && take === BLOCK_LEN) { const pos32 = pos / 4; if (pos % 4 !== 0) throw new Error("arx: invalid block position"); for (let j = 0, posj; j < BLOCK_LEN32; j++) { posj = pos32 + j; o32[posj] = d32[posj] ^ b32[j]; } pos += BLOCK_LEN; continue; } for (let j = 0, posj; j < take; j++) { posj = pos + j; output[posj] = data[posj] ^ block[j]; } pos += take; } } function createCipher(core, opts) { const { allowShortKeys, extendNonceFn, counterLength, counterRight, rounds } = checkOpts({ allowShortKeys: false, counterLength: 8, counterRight: false, rounds: 20 }, opts); if (typeof core !== "function") throw new Error("core must be a function"); anumber2(counterLength); anumber2(rounds); abool2(counterRight); abool2(allowShortKeys); return (key, nonce, data, output, counter = 0) => { abytes2(key, void 0, "key"); abytes2(nonce, void 0, "nonce"); abytes2(data, void 0, "data"); const len = data.length; if (output === void 0) output = new Uint8Array(len); abytes2(output, void 0, "output"); anumber2(counter); if (counter < 0 || counter >= MAX_COUNTER) throw new Error("arx: counter overflow"); if (output.length < len) throw new Error(`arx: output (${output.length}) is shorter than data (${len})`); const toClean = []; let l = key.length; let k; let sigma; if (l === 32) { toClean.push(k = copyBytes2(key)); sigma = sigma32_32; } else if (l === 16 && allowShortKeys) { k = new Uint8Array(32); k.set(key); k.set(key, 16); sigma = sigma16_32; toClean.push(k); } else { abytes2(key, 32, "arx key"); throw new Error("invalid key size"); } if (!isAligned322(nonce)) toClean.push(nonce = copyBytes2(nonce)); const k32 = u32(k); if (extendNonceFn) { if (nonce.length !== 24) throw new Error(`arx: extended nonce must be 24 bytes`); extendNonceFn(sigma, k32, u32(nonce.subarray(0, 16)), k32); nonce = nonce.subarray(16); } const nonceNcLen = 16 - counterLength; if (nonceNcLen !== nonce.length) throw new Error(`arx: nonce must be ${nonceNcLen} or 16 bytes`); if (nonceNcLen !== 12) { const nc = new Uint8Array(12); nc.set(nonce, counterRight ? 0 : 12 - nonce.length); nonce = nc; toClean.push(nonce); } const n32 = u32(nonce); runCipher(core, sigma, k32, n32, data, output, counter, rounds); clean2(...toClean); return output; }; } var encodeStr, sigma16, sigma32, sigma16_32, sigma32_32, BLOCK_LEN, BLOCK_LEN32, MAX_COUNTER, U32_EMPTY; var init_arx = __esm({ "node_modules/@noble/ciphers/_arx.js"() { init_utils3(); encodeStr = (str) => Uint8Array.from(str.split(""), (c) => c.charCodeAt(0)); sigma16 = encodeStr("expand 16-byte k"); sigma32 = encodeStr("expand 32-byte k"); sigma16_32 = u32(sigma16); sigma32_32 = u32(sigma32); BLOCK_LEN = 64; BLOCK_LEN32 = 16; MAX_COUNTER = 2 ** 32 - 1; U32_EMPTY = Uint32Array.of(); } }); // node_modules/@noble/ciphers/_poly1305.js function u8to16(a, i3) { return a[i3++] & 255 | (a[i3++] & 255) << 8; } function wrapConstructorWithKey(hashCons) { const hashC = (msg, key) => hashCons(key).update(msg).digest(); const tmp = hashCons(new Uint8Array(32)); hashC.outputLen = tmp.outputLen; hashC.blockLen = tmp.blockLen; hashC.create = (key) => hashCons(key); return hashC; } var Poly1305, poly1305; var init_poly1305 = __esm({ "node_modules/@noble/ciphers/_poly1305.js"() { init_utils3(); Poly1305 = class { blockLen = 16; outputLen = 16; buffer = new Uint8Array(16); r = new Uint16Array(10); // Allocating 1 array with .subarray() here is slower than 3 h = new Uint16Array(10); pad = new Uint16Array(8); pos = 0; finished = false; // Can be speed-up using BigUint64Array, at the cost of complexity constructor(key) { key = copyBytes2(abytes2(key, 32, "key")); const t0 = u8to16(key, 0); const t1 = u8to16(key, 2); const t2 = u8to16(key, 4); const t3 = u8to16(key, 6); const t4 = u8to16(key, 8); const t5 = u8to16(key, 10); const t6 = u8to16(key, 12); const t7 = u8to16(key, 14); this.r[0] = t0 & 8191; this.r[1] = (t0 >>> 13 | t1 << 3) & 8191; this.r[2] = (t1 >>> 10 | t2 << 6) & 7939; this.r[3] = (t2 >>> 7 | t3 << 9) & 8191; this.r[4] = (t3 >>> 4 | t4 << 12) & 255; this.r[5] = t4 >>> 1 & 8190; this.r[6] = (t4 >>> 14 | t5 << 2) & 8191; this.r[7] = (t5 >>> 11 | t6 << 5) & 8065; this.r[8] = (t6 >>> 8 | t7 << 8) & 8191; this.r[9] = t7 >>> 5 & 127; for (let i3 = 0; i3 < 8; i3++) this.pad[i3] = u8to16(key, 16 + 2 * i3); } process(data, offset, isLast = false) { const hibit = isLast ? 0 : 1 << 11; const { h, r } = this; const r0 = r[0]; const r1 = r[1]; const r2 = r[2]; const r3 = r[3]; const r4 = r[4]; const r5 = r[5]; const r6 = r[6]; const r7 = r[7]; const r8 = r[8]; const r9 = r[9]; const t0 = u8to16(data, offset + 0); const t1 = u8to16(data, offset + 2); const t2 = u8to16(data, offset + 4); const t3 = u8to16(data, offset + 6); const t4 = u8to16(data, offset + 8); const t5 = u8to16(data, offset + 10); const t6 = u8to16(data, offset + 12); const t7 = u8to16(data, offset + 14); let h0 = h[0] + (t0 & 8191); let h1 = h[1] + ((t0 >>> 13 | t1 << 3) & 8191); let h2 = h[2] + ((t1 >>> 10 | t2 << 6) & 8191); let h3 = h[3] + ((t2 >>> 7 | t3 << 9) & 8191); let h4 = h[4] + ((t3 >>> 4 | t4 << 12) & 8191); let h5 = h[5] + (t4 >>> 1 & 8191); let h6 = h[6] + ((t4 >>> 14 | t5 << 2) & 8191); let h7 = h[7] + ((t5 >>> 11 | t6 << 5) & 8191); let h8 = h[8] + ((t6 >>> 8 | t7 << 8) & 8191); let h9 = h[9] + (t7 >>> 5 | hibit); let c = 0; let d0 = c + h0 * r0 + h1 * (5 * r9) + h2 * (5 * r8) + h3 * (5 * r7) + h4 * (5 * r6); c = d0 >>> 13; d0 &= 8191; d0 += h5 * (5 * r5) + h6 * (5 * r4) + h7 * (5 * r3) + h8 * (5 * r2) + h9 * (5 * r1); c += d0 >>> 13; d0 &= 8191; let d1 = c + h0 * r1 + h1 * r0 + h2 * (5 * r9) + h3 * (5 * r8) + h4 * (5 * r7); c = d1 >>> 13; d1 &= 8191; d1 += h5 * (5 * r6) + h6 * (5 * r5) + h7 * (5 * r4) + h8 * (5 * r3) + h9 * (5 * r2); c += d1 >>> 13; d1 &= 8191; let d2 = c + h0 * r2 + h1 * r1 + h2 * r0 + h3 * (5 * r9) + h4 * (5 * r8); c = d2 >>> 13; d2 &= 8191; d2 += h5 * (5 * r7) + h6 * (5 * r6) + h7 * (5 * r5) + h8 * (5 * r4) + h9 * (5 * r3); c += d2 >>> 13; d2 &= 8191; let d3 = c + h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * (5 * r9); c = d3 >>> 13; d3 &= 8191; d3 += h5 * (5 * r8) + h6 * (5 * r7) + h7 * (5 * r6) + h8 * (5 * r5) + h9 * (5 * r4); c += d3 >>> 13; d3 &= 8191; let d4 = c + h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0; c = d4 >>> 13; d4 &= 8191; d4 += h5 * (5 * r9) + h6 * (5 * r8) + h7 * (5 * r7) + h8 * (5 * r6) + h9 * (5 * r5); c += d4 >>> 13; d4 &= 8191; let d5 = c + h0 * r5 + h1 * r4 + h2 * r3 + h3 * r2 + h4 * r1; c = d5 >>> 13; d5 &= 8191; d5 += h5 * r0 + h6 * (5 * r9) + h7 * (5 * r8) + h8 * (5 * r7) + h9 * (5 * r6); c += d5 >>> 13; d5 &= 8191; let d6 = c + h0 * r6 + h1 * r5 + h2 * r4 + h3 * r3 + h4 * r2; c = d6 >>> 13; d6 &= 8191; d6 += h5 * r1 + h6 * r0 + h7 * (5 * r9) + h8 * (5 * r8) + h9 * (5 * r7); c += d6 >>> 13; d6 &= 8191; let d7 = c + h0 * r7 + h1 * r6 + h2 * r5 + h3 * r4 + h4 * r3; c = d7 >>> 13; d7 &= 8191; d7 += h5 * r2 + h6 * r1 + h7 * r0 + h8 * (5 * r9) + h9 * (5 * r8); c += d7 >>> 13; d7 &= 8191; let d8 = c + h0 * r8 + h1 * r7 + h2 * r6 + h3 * r5 + h4 * r4; c = d8 >>> 13; d8 &= 8191; d8 += h5 * r3 + h6 * r2 + h7 * r1 + h8 * r0 + h9 * (5 * r9); c += d8 >>> 13; d8 &= 8191; let d9 = c + h0 * r9 + h1 * r8 + h2 * r7 + h3 * r6 + h4 * r5; c = d9 >>> 13; d9 &= 8191; d9 += h5 * r4 + h6 * r3 + h7 * r2 + h8 * r1 + h9 * r0; c += d9 >>> 13; d9 &= 8191; c = (c << 2) + c | 0; c = c + d0 | 0; d0 = c & 8191; c = c >>> 13; d1 += c; h[0] = d0; h[1] = d1; h[2] = d2; h[3] = d3; h[4] = d4; h[5] = d5; h[6] = d6; h[7] = d7; h[8] = d8; h[9] = d9; } finalize() { const { h, pad: pad2 } = this; const g = new Uint16Array(10); let c = h[1] >>> 13; h[1] &= 8191; for (let i3 = 2; i3 < 10; i3++) { h[i3] += c; c = h[i3] >>> 13; h[i3] &= 8191; } h[0] += c * 5; c = h[0] >>> 13; h[0] &= 8191; h[1] += c; c = h[1] >>> 13; h[1] &= 8191; h[2] += c; g[0] = h[0] + 5; c = g[0] >>> 13; g[0] &= 8191; for (let i3 = 1; i3 < 10; i3++) { g[i3] = h[i3] + c; c = g[i3] >>> 13; g[i3] &= 8191; } g[9] -= 1 << 13; let mask = (c ^ 1) - 1; for (let i3 = 0; i3 < 10; i3++) g[i3] &= mask; mask = ~mask; for (let i3 = 0; i3 < 10; i3++) h[i3] = h[i3] & mask | g[i3]; h[0] = (h[0] | h[1] << 13) & 65535; h[1] = (h[1] >>> 3 | h[2] << 10) & 65535; h[2] = (h[2] >>> 6 | h[3] << 7) & 65535; h[3] = (h[3] >>> 9 | h[4] << 4) & 65535; h[4] = (h[4] >>> 12 | h[5] << 1 | h[6] << 14) & 65535; h[5] = (h[6] >>> 2 | h[7] << 11) & 65535; h[6] = (h[7] >>> 5 | h[8] << 8) & 65535; h[7] = (h[8] >>> 8 | h[9] << 5) & 65535; let f = h[0] + pad2[0]; h[0] = f & 65535; for (let i3 = 1; i3 < 8; i3++) { f = (h[i3] + pad2[i3] | 0) + (f >>> 16) | 0; h[i3] = f & 65535; } clean2(g); } update(data) { aexists2(this); abytes2(data); data = copyBytes2(data); const { buffer, blockLen } = this; const len = data.length; for (let pos = 0; pos < len; ) { const take = Math.min(blockLen - this.pos, len - pos); if (take === blockLen) { for (; blockLen <= len - pos; pos += blockLen) this.process(data, pos); continue; } buffer.set(data.subarray(pos, pos + take), this.pos); this.pos += take; pos += take; if (this.pos === blockLen) { this.process(buffer, 0, false); this.pos = 0; } } return this; } destroy() { clean2(this.h, this.r, this.buffer, this.pad); } digestInto(out) { aexists2(this); aoutput2(out, this); this.finished = true; const { buffer, h } = this; let { pos } = this; if (pos) { buffer[pos++] = 1; for (; pos < 16; pos++) buffer[pos] = 0; this.process(buffer, 0, true); } this.finalize(); let opos = 0; for (let i3 = 0; i3 < 8; i3++) { out[opos++] = h[i3] >>> 0; out[opos++] = h[i3] >>> 8; } return out; } digest() { const { buffer, outputLen } = this; this.digestInto(buffer); const res = buffer.slice(0, outputLen); this.destroy(); return res; } }; poly1305 = /* @__PURE__ */ (() => wrapConstructorWithKey((key) => new Poly1305(key)))(); } }); // node_modules/@noble/ciphers/chacha.js function chachaCore(s, k, n, out, cnt, rounds = 20) { let y00 = s[0], y01 = s[1], y02 = s[2], y03 = s[3], y04 = k[0], y05 = k[1], y06 = k[2], y07 = k[3], y08 = k[4], y09 = k[5], y10 = k[6], y11 = k[7], y12 = cnt, y13 = n[0], y14 = n[1], y15 = n[2]; let x00 = y00, x01 = y01, x02 = y02, x03 = y03, x04 = y04, x05 = y05, x06 = y06, x07 = y07, x08 = y08, x09 = y09, x10 = y10, x11 = y11, x12 = y12, x13 = y13, x14 = y14, x15 = y15; for (let r = 0; r < rounds; r += 2) { x00 = x00 + x04 | 0; x12 = rotl(x12 ^ x00, 16); x08 = x08 + x12 | 0; x04 = rotl(x04 ^ x08, 12); x00 = x00 + x04 | 0; x12 = rotl(x12 ^ x00, 8); x08 = x08 + x12 | 0; x04 = rotl(x04 ^ x08, 7); x01 = x01 + x05 | 0; x13 = rotl(x13 ^ x01, 16); x09 = x09 + x13 | 0; x05 = rotl(x05 ^ x09, 12); x01 = x01 + x05 | 0; x13 = rotl(x13 ^ x01, 8); x09 = x09 + x13 | 0; x05 = rotl(x05 ^ x09, 7); x02 = x02 + x06 | 0; x14 = rotl(x14 ^ x02, 16); x10 = x10 + x14 | 0; x06 = rotl(x06 ^ x10, 12); x02 = x02 + x06 | 0; x14 = rotl(x14 ^ x02, 8); x10 = x10 + x14 | 0; x06 = rotl(x06 ^ x10, 7); x03 = x03 + x07 | 0; x15 = rotl(x15 ^ x03, 16); x11 = x11 + x15 | 0; x07 = rotl(x07 ^ x11, 12); x03 = x03 + x07 | 0; x15 = rotl(x15 ^ x03, 8); x11 = x11 + x15 | 0; x07 = rotl(x07 ^ x11, 7); x00 = x00 + x05 | 0; x15 = rotl(x15 ^ x00, 16); x10 = x10 + x15 | 0; x05 = rotl(x05 ^ x10, 12); x00 = x00 + x05 | 0; x15 = rotl(x15 ^ x00, 8); x10 = x10 + x15 | 0; x05 = rotl(x05 ^ x10, 7); x01 = x01 + x06 | 0; x12 = rotl(x12 ^ x01, 16); x11 = x11 + x12 | 0; x06 = rotl(x06 ^ x11, 12); x01 = x01 + x06 | 0; x12 = rotl(x12 ^ x01, 8); x11 = x11 + x12 | 0; x06 = rotl(x06 ^ x11, 7); x02 = x02 + x07 | 0; x13 = rotl(x13 ^ x02, 16); x08 = x08 + x13 | 0; x07 = rotl(x07 ^ x08, 12); x02 = x02 + x07 | 0; x13 = rotl(x13 ^ x02, 8); x08 = x08 + x13 | 0; x07 = rotl(x07 ^ x08, 7); x03 = x03 + x04 | 0; x14 = rotl(x14 ^ x03, 16); x09 = x09 + x14 | 0; x04 = rotl(x04 ^ x09, 12); x03 = x03 + x04 | 0; x14 = rotl(x14 ^ x03, 8); x09 = x09 + x14 | 0; x04 = rotl(x04 ^ x09, 7); } let oi = 0; out[oi++] = y00 + x00 | 0; out[oi++] = y01 + x01 | 0; out[oi++] = y02 + x02 | 0; out[oi++] = y03 + x03 | 0; out[oi++] = y04 + x04 | 0; out[oi++] = y05 + x05 | 0; out[oi++] = y06 + x06 | 0; out[oi++] = y07 + x07 | 0; out[oi++] = y08 + x08 | 0; out[oi++] = y09 + x09 | 0; out[oi++] = y10 + x10 | 0; out[oi++] = y11 + x11 | 0; out[oi++] = y12 + x12 | 0; out[oi++] = y13 + x13 | 0; out[oi++] = y14 + x14 | 0; out[oi++] = y15 + x15 | 0; } function hchacha(s, k, i3, out) { let x00 = s[0], x01 = s[1], x02 = s[2], x03 = s[3], x04 = k[0], x05 = k[1], x06 = k[2], x07 = k[3], x08 = k[4], x09 = k[5], x10 = k[6], x11 = k[7], x12 = i3[0], x13 = i3[1], x14 = i3[2], x15 = i3[3]; for (let r = 0; r < 20; r += 2) { x00 = x00 + x04 | 0; x12 = rotl(x12 ^ x00, 16); x08 = x08 + x12 | 0; x04 = rotl(x04 ^ x08, 12); x00 = x00 + x04 | 0; x12 = rotl(x12 ^ x00, 8); x08 = x08 + x12 | 0; x04 = rotl(x04 ^ x08, 7); x01 = x01 + x05 | 0; x13 = rotl(x13 ^ x01, 16); x09 = x09 + x13 | 0; x05 = rotl(x05 ^ x09, 12); x01 = x01 + x05 | 0; x13 = rotl(x13 ^ x01, 8); x09 = x09 + x13 | 0; x05 = rotl(x05 ^ x09, 7); x02 = x02 + x06 | 0; x14 = rotl(x14 ^ x02, 16); x10 = x10 + x14 | 0; x06 = rotl(x06 ^ x10, 12); x02 = x02 + x06 | 0; x14 = rotl(x14 ^ x02, 8); x10 = x10 + x14 | 0; x06 = rotl(x06 ^ x10, 7); x03 = x03 + x07 | 0; x15 = rotl(x15 ^ x03, 16); x11 = x11 + x15 | 0; x07 = rotl(x07 ^ x11, 12); x03 = x03 + x07 | 0; x15 = rotl(x15 ^ x03, 8); x11 = x11 + x15 | 0; x07 = rotl(x07 ^ x11, 7); x00 = x00 + x05 | 0; x15 = rotl(x15 ^ x00, 16); x10 = x10 + x15 | 0; x05 = rotl(x05 ^ x10, 12); x00 = x00 + x05 | 0; x15 = rotl(x15 ^ x00, 8); x10 = x10 + x15 | 0; x05 = rotl(x05 ^ x10, 7); x01 = x01 + x06 | 0; x12 = rotl(x12 ^ x01, 16); x11 = x11 + x12 | 0; x06 = rotl(x06 ^ x11, 12); x01 = x01 + x06 | 0; x12 = rotl(x12 ^ x01, 8); x11 = x11 + x12 | 0; x06 = rotl(x06 ^ x11, 7); x02 = x02 + x07 | 0; x13 = rotl(x13 ^ x02, 16); x08 = x08 + x13 | 0; x07 = rotl(x07 ^ x08, 12); x02 = x02 + x07 | 0; x13 = rotl(x13 ^ x02, 8); x08 = x08 + x13 | 0; x07 = rotl(x07 ^ x08, 7); x03 = x03 + x04 | 0; x14 = rotl(x14 ^ x03, 16); x09 = x09 + x14 | 0; x04 = rotl(x04 ^ x09, 12); x03 = x03 + x04 | 0; x14 = rotl(x14 ^ x03, 8); x09 = x09 + x14 | 0; x04 = rotl(x04 ^ x09, 7); } let oi = 0; out[oi++] = x00; out[oi++] = x01; out[oi++] = x02; out[oi++] = x03; out[oi++] = x12; out[oi++] = x13; out[oi++] = x14; out[oi++] = x15; } function computeTag(fn, key, nonce, ciphertext, AAD) { if (AAD !== void 0) abytes2(AAD, void 0, "AAD"); const authKey = fn(key, nonce, ZEROS32); const lengths = u64Lengths(ciphertext.length, AAD ? AAD.length : 0, true); const h = poly1305.create(authKey); if (AAD) updatePadded(h, AAD); updatePadded(h, ciphertext); h.update(lengths); const res = h.digest(); clean2(authKey, lengths); return res; } var chacha20, xchacha20, ZEROS16, updatePadded, ZEROS32, _poly1305_aead, chacha20poly1305, xchacha20poly1305; var init_chacha = __esm({ "node_modules/@noble/ciphers/chacha.js"() { init_arx(); init_poly1305(); init_utils3(); chacha20 = /* @__PURE__ */ createCipher(chachaCore, { counterRight: false, counterLength: 4, allowShortKeys: false }); xchacha20 = /* @__PURE__ */ createCipher(chachaCore, { counterRight: false, counterLength: 8, extendNonceFn: hchacha, allowShortKeys: false }); ZEROS16 = /* @__PURE__ */ new Uint8Array(16); updatePadded = (h, msg) => { h.update(msg); const leftover = msg.length % 16; if (leftover) h.update(ZEROS16.subarray(leftover)); }; ZEROS32 = /* @__PURE__ */ new Uint8Array(32); _poly1305_aead = (xorStream) => (key, nonce, AAD) => { const tagLength = 16; return { encrypt(plaintext, output) { const plength = plaintext.length; output = getOutput(plength + tagLength, output, false); output.set(plaintext); const oPlain = output.subarray(0, -tagLength); xorStream(key, nonce, oPlain, oPlain, 1); const tag = computeTag(xorStream, key, nonce, oPlain, AAD); output.set(tag, plength); clean2(tag); return output; }, decrypt(ciphertext, output) { output = getOutput(ciphertext.length - tagLength, output, false); const data = ciphertext.subarray(0, -tagLength); const passedTag = ciphertext.subarray(-tagLength); const tag = computeTag(xorStream, key, nonce, data, AAD); if (!equalBytes(passedTag, tag)) throw new Error("invalid tag"); output.set(ciphertext.subarray(0, -tagLength)); xorStream(key, nonce, output, output, 1); clean2(tag); return output; } }; }; chacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 12, tagLength: 16 }, _poly1305_aead(chacha20)); xchacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 24, tagLength: 16 }, _poly1305_aead(xchacha20)); } }); // node_modules/@noble/hashes/hkdf.js function extract(hash, ikm, salt) { ahash(hash); if (salt === void 0) salt = new Uint8Array(hash.outputLen); return hmac(hash, salt, ikm); } function expand(hash, prk, info, length = 32) { ahash(hash); anumber(length, "length"); const olen = hash.outputLen; if (length > 255 * olen) throw new Error("Length must be <= 255*HashLen"); const blocks = Math.ceil(length / olen); if (info === void 0) info = EMPTY_BUFFER; else abytes(info, void 0, "info"); const okm = new Uint8Array(blocks * olen); const HMAC = hmac.create(hash, prk); const HMACTmp = HMAC._cloneInto(); const T = new Uint8Array(HMAC.outputLen); for (let counter = 0; counter < blocks; counter++) { HKDF_COUNTER[0] = counter + 1; HMACTmp.update(counter === 0 ? EMPTY_BUFFER : T).update(info).update(HKDF_COUNTER).digestInto(T); okm.set(T, olen * counter); HMAC._cloneInto(HMACTmp); } HMAC.destroy(); HMACTmp.destroy(); clean(T, HKDF_COUNTER); return okm.slice(0, length); } var HKDF_COUNTER, EMPTY_BUFFER; var init_hkdf = __esm({ "node_modules/@noble/hashes/hkdf.js"() { init_hmac(); init_utils(); HKDF_COUNTER = /* @__PURE__ */ Uint8Array.of(0); EMPTY_BUFFER = /* @__PURE__ */ Uint8Array.of(); } }); // node_modules/@scure/base/index.js function isBytes3(a) { return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array"; } function abytes3(b) { if (!isBytes3(b)) throw new Error("Uint8Array expected"); } function isArrayOf(isString, arr) { if (!Array.isArray(arr)) return false; if (arr.length === 0) return true; if (isString) { return arr.every((item) => typeof item === "string"); } else { return arr.every((item) => Number.isSafeInteger(item)); } } function astr(label, input) { if (typeof input !== "string") throw new Error(`${label}: string expected`); return true; } function anumber3(n) { if (!Number.isSafeInteger(n)) throw new Error(`invalid integer: ${n}`); } function aArr(input) { if (!Array.isArray(input)) throw new Error("array expected"); } function astrArr(label, input) { if (!isArrayOf(true, input)) throw new Error(`${label}: array of strings expected`); } function anumArr(label, input) { if (!isArrayOf(false, input)) throw new Error(`${label}: array of numbers expected`); } // @__NO_SIDE_EFFECTS__ function chain(...args) { const id = (a) => a; const wrap = (a, b) => (c) => a(b(c)); const encode = args.map((x) => x.encode).reduceRight(wrap, id); const decode = args.map((x) => x.decode).reduce(wrap, id); return { encode, decode }; } // @__NO_SIDE_EFFECTS__ function alphabet(letters) { const lettersA = typeof letters === "string" ? letters.split("") : letters; const len = lettersA.length; astrArr("alphabet", lettersA); const indexes = new Map(lettersA.map((l, i3) => [l, i3])); return { encode: (digits) => { aArr(digits); return digits.map((i3) => { if (!Number.isSafeInteger(i3) || i3 < 0 || i3 >= len) throw new Error(`alphabet.encode: digit index outside alphabet "${i3}". Allowed: ${letters}`); return lettersA[i3]; }); }, decode: (input) => { aArr(input); return input.map((letter) => { astr("alphabet.decode", letter); const i3 = indexes.get(letter); if (i3 === void 0) throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`); return i3; }); } }; } // @__NO_SIDE_EFFECTS__ function join(separator = "") { astr("join", separator); return { encode: (from) => { astrArr("join.decode", from); return from.join(separator); }, decode: (to) => { astr("join.decode", to); return to.split(separator); } }; } // @__NO_SIDE_EFFECTS__ function padding(bits, chr = "=") { anumber3(bits); astr("padding", chr); return { encode(data) { astrArr("padding.encode", data); while (data.length * bits % 8) data.push(chr); return data; }, decode(input) { astrArr("padding.decode", input); let end = input.length; if (end * bits % 8) throw new Error("padding: invalid, string should have whole number of bytes"); for (; end > 0 && input[end - 1] === chr; end--) { const last = end - 1; const byte = last * bits; if (byte % 8 === 0) throw new Error("padding: invalid, string has too much padding"); } return input.slice(0, end); } }; } function convertRadix2(data, from, to, padding2) { aArr(data); if (from <= 0 || from > 32) throw new Error(`convertRadix2: wrong from=${from}`); if (to <= 0 || to > 32) throw new Error(`convertRadix2: wrong to=${to}`); if (/* @__PURE__ */ radix2carry(from, to) > 32) { throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`); } let carry = 0; let pos = 0; const max = powers[from]; const mask = powers[to] - 1; const res = []; for (const n of data) { anumber3(n); if (n >= max) throw new Error(`convertRadix2: invalid data word=${n} from=${from}`); carry = carry << from | n; if (pos + from > 32) throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`); pos += from; for (; pos >= to; pos -= to) res.push((carry >> pos - to & mask) >>> 0); const pow = powers[pos]; if (pow === void 0) throw new Error("invalid carry"); carry &= pow - 1; } carry = carry << to - pos & mask; if (!padding2 && pos >= from) throw new Error("Excess padding"); if (!padding2 && carry > 0) throw new Error(`Non-zero padding: ${carry}`); if (padding2 && pos > 0) res.push(carry >>> 0); return res; } // @__NO_SIDE_EFFECTS__ function radix2(bits, revPadding = false) { anumber3(bits); if (bits <= 0 || bits > 32) throw new Error("radix2: bits should be in (0..32]"); if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32) throw new Error("radix2: carry overflow"); return { encode: (bytes) => { if (!isBytes3(bytes)) throw new Error("radix2.encode input should be Uint8Array"); return convertRadix2(Array.from(bytes), 8, bits, !revPadding); }, decode: (digits) => { anumArr("radix2.decode", digits); return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding)); } }; } var gcd, radix2carry, powers, hasBase64Builtin, decodeBase64Builtin, base64; var init_base = __esm({ "node_modules/@scure/base/index.js"() { gcd = (a, b) => b === 0 ? a : gcd(b, a % b); radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to)); powers = /* @__PURE__ */ (() => { let res = []; for (let i3 = 0; i3 < 40; i3++) res.push(2 ** i3); return res; })(); hasBase64Builtin = /* @__PURE__ */ (() => typeof Uint8Array.from([]).toBase64 === "function" && typeof Uint8Array.fromBase64 === "function")(); decodeBase64Builtin = (s, isUrl) => { astr("base64", s); const re = isUrl ? /^[A-Za-z0-9=_-]+$/ : /^[A-Za-z0-9=+/]+$/; const alphabet2 = isUrl ? "base64url" : "base64"; if (s.length > 0 && !re.test(s)) throw new Error("invalid base64"); return Uint8Array.fromBase64(s, { alphabet: alphabet2, lastChunkHandling: "strict" }); }; base64 = hasBase64Builtin ? { encode(b) { abytes3(b); return b.toBase64(); }, decode(s) { return decodeBase64Builtin(s, false); } } : /* @__PURE__ */ chain(/* @__PURE__ */ radix2(6), /* @__PURE__ */ alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), /* @__PURE__ */ padding(6), /* @__PURE__ */ join("")); } }); // node_modules/nostr-tools/lib/esm/nip59.js function isHex322(input) { if (input.length !== 64) return false; for (let i22 = 0; i22 < 64; i22++) { let cc = input.charCodeAt(i22); if (isNaN(cc) || cc < 48 || cc > 102 || cc > 57 && cc < 97) { return false; } } return true; } function getConversationKey(privkeyA, pubkeyB) { const sharedX = secp256k1.getSharedSecret(privkeyA, hexToBytes("02" + pubkeyB)).subarray(1, 33); return extract(sha256, sharedX, utf8Encoder3.encode("nip44-v2")); } function getMessageKeys(conversationKey, nonce) { const keys = expand(sha256, conversationKey, nonce, 76); return { chacha_key: keys.subarray(0, 32), chacha_nonce: keys.subarray(32, 44), hmac_key: keys.subarray(44, 76) }; } function calcPaddedLen(len) { if (!Number.isSafeInteger(len) || len < 1) throw new Error("expected positive integer"); if (len <= 32) return 32; const nextPower = 2 ** (Math.floor(Math.log2(len - 1)) + 1); const chunk = nextPower <= 256 ? 32 : nextPower / 8; return chunk * (Math.floor((len - 1) / chunk) + 1); } function writeU16BE(num2) { if (!Number.isSafeInteger(num2) || num2 < minPlaintextSize || num2 > 65535) throw new Error("invalid plaintext size: must be between 1 and 65535 bytes"); const arr = new Uint8Array(2); new DataView(arr.buffer).setUint16(0, num2, false); return arr; } function writeU32BE(num2) { if (!Number.isSafeInteger(num2) || num2 < extendedPrefixThreshold || num2 > maxPlaintextSize) throw new Error("invalid plaintext size: must be between 65536 and 4294967295 bytes"); const arr = new Uint8Array(4); new DataView(arr.buffer).setUint32(0, num2, false); return arr; } function pad(plaintext) { const unpadded = utf8Encoder3.encode(plaintext); const unpaddedLen = unpadded.length; if (unpaddedLen < minPlaintextSize || unpaddedLen > maxPlaintextSize) throw new Error("invalid plaintext size: must be between 1 and 4294967295 bytes"); const prefix = unpaddedLen >= extendedPrefixThreshold ? concatBytes(new Uint8Array([0, 0]), writeU32BE(unpaddedLen)) : writeU16BE(unpaddedLen); const suffix = new Uint8Array(calcPaddedLen(unpaddedLen) - unpaddedLen); return concatBytes(prefix, unpadded, suffix); } function unpad(padded) { const dv = new DataView(padded.buffer, padded.byteOffset, padded.byteLength); const firstTwo = dv.getUint16(0); let unpaddedLen; let prefixLen; if (firstTwo === 0) { unpaddedLen = dv.getUint32(2); if (unpaddedLen < extendedPrefixThreshold) throw new Error("invalid padding"); prefixLen = 6; } else { unpaddedLen = firstTwo; prefixLen = 2; } const unpadded = padded.subarray(prefixLen, prefixLen + unpaddedLen); if (unpaddedLen < minPlaintextSize || unpaddedLen > maxPlaintextSize || unpadded.length !== unpaddedLen || padded.length !== prefixLen + calcPaddedLen(unpaddedLen)) throw new Error("invalid padding"); return utf8Decoder2.decode(unpadded); } function hmacAad(key, message, aad) { if (aad.length !== 32) throw new Error("AAD associated data must be 32 bytes"); const combined = concatBytes(aad, message); return hmac(sha256, key, combined); } function decodePayload(payload) { if (typeof payload !== "string") throw new Error("payload must be a valid string"); const plen = payload.length; if (plen < 132) throw new Error("invalid payload length: " + plen); if (payload[0] === "#") throw new Error("unknown encryption version"); let data; try { data = base64.decode(payload); } catch (error2) { throw new Error("invalid base64: " + error2.message); } const dlen = data.length; if (dlen < 99) throw new Error("invalid data length: " + dlen); const vers = data[0]; if (vers !== 2) throw new Error("unknown encryption version " + vers); return { nonce: data.subarray(1, 33), ciphertext: data.subarray(33, -32), mac: data.subarray(-32) }; } function encrypt(plaintext, conversationKey, nonce = randomBytes(32)) { const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce); const padded = pad(plaintext); const ciphertext = chacha20(chacha_key, chacha_nonce, padded); const mac = hmacAad(hmac_key, ciphertext, nonce); return base64.encode(concatBytes(new Uint8Array([2]), nonce, ciphertext, mac)); } function decrypt(payload, conversationKey) { const { nonce, ciphertext, mac } = decodePayload(payload); const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce); const calculatedMac = hmacAad(hmac_key, ciphertext, nonce); if (!equalBytes(calculatedMac, mac)) throw new Error("invalid MAC"); const padded = chacha20(chacha_key, chacha_nonce, ciphertext); return unpad(padded); } function validateEvent2(event) { if (!isRecord2(event)) return false; if (typeof event.kind !== "number") return false; if (typeof event.content !== "string") return false; if (typeof event.created_at !== "number") return false; if (typeof event.pubkey !== "string") return false; if (!isHex322(event.pubkey)) return false; if (!Array.isArray(event.tags)) return false; for (let i22 = 0; i22 < event.tags.length; i22++) { let tag = event.tags[i22]; if (!Array.isArray(tag)) return false; for (let j = 0; j < tag.length; j++) { if (typeof tag[j] !== "string") return false; } } return true; } function serializeEvent2(evt) { if (!validateEvent2(evt)) throw new Error("can't serialize event with wrong or missing properties"); return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]); } function getEventHash2(event) { let eventHash = sha256(utf8Encoder3.encode(serializeEvent2(event))); return bytesToHex(eventHash); } function createRumor(event, privateKey) { const rumor = { created_at: now(), content: "", tags: [], ...event, pubkey: getPublicKey2(privateKey) }; rumor.id = getEventHash2(rumor); return rumor; } function createSeal(rumor, privateKey, recipientPublicKey) { return finalizeEvent2( { kind: Seal, content: nip44Encrypt(rumor, privateKey, recipientPublicKey), created_at: randomNow(), tags: [] }, privateKey ); } function createWrap(seal, recipientPublicKey) { const randomKey = generateSecretKey2(); return finalizeEvent2( { kind: GiftWrap, content: nip44Encrypt(seal, randomKey, recipientPublicKey), created_at: randomNow(), tags: [["p", recipientPublicKey]] }, randomKey ); } function wrapEvent(event, senderPrivateKey, recipientPublicKey) { const rumor = createRumor(event, senderPrivateKey); const seal = createSeal(rumor, senderPrivateKey, recipientPublicKey); return createWrap(seal, recipientPublicKey); } function unwrapEvent(wrap, recipientPrivateKey) { if (wrap.kind !== GiftWrap) { throw new Error(`unexpected wrap kind ${wrap.kind}, expected ${GiftWrap}`); } const seal = nip44Decrypt(wrap, recipientPrivateKey); if (seal.kind !== Seal) { throw new Error(`unexpected seal kind ${seal.kind}, expected ${Seal}`); } if (!verifyEvent2(seal)) { throw new Error("seal signature is invalid"); } const rumor = nip44Decrypt(seal, recipientPrivateKey); if (rumor.pubkey !== seal.pubkey) { throw new Error(`rumor pubkey ${rumor.pubkey} does not match seal pubkey ${seal.pubkey}`); } return rumor; } var utf8Decoder2, utf8Encoder3, minPlaintextSize, maxPlaintextSize, extendedPrefixThreshold, verifiedSymbol2, isRecord2, JS2, i2, generateSecretKey2, getPublicKey2, finalizeEvent2, verifyEvent2, Seal, GiftWrap, TWO_DAYS, now, randomNow, nip44ConversationKey, nip44Encrypt, nip44Decrypt; var init_nip59 = __esm({ "node_modules/nostr-tools/lib/esm/nip59.js"() { init_chacha(); init_utils3(); init_secp256k1(); init_hkdf(); init_hmac(); init_sha2(); init_utils(); init_base(); init_secp256k1(); init_utils(); init_sha2(); utf8Decoder2 = new TextDecoder("utf-8"); utf8Encoder3 = new TextEncoder(); minPlaintextSize = 1; maxPlaintextSize = 4294967295; extendedPrefixThreshold = 65536; verifiedSymbol2 = /* @__PURE__ */ Symbol("verified"); isRecord2 = (obj) => obj instanceof Object; JS2 = class { generateSecretKey() { return schnorr.utils.randomSecretKey(); } getPublicKey(secretKey) { return bytesToHex(schnorr.getPublicKey(secretKey)); } finalizeEvent(t, secretKey) { const event = t; event.pubkey = bytesToHex(schnorr.getPublicKey(secretKey)); event.id = getEventHash2(event); event.sig = bytesToHex(schnorr.sign(hexToBytes(getEventHash2(event)), secretKey)); event[verifiedSymbol2] = true; return event; } verifyEvent(event) { if (typeof event[verifiedSymbol2] === "boolean") return event[verifiedSymbol2]; try { const hash = getEventHash2(event); if (hash !== event.id) { event[verifiedSymbol2] = false; return false; } const valid = schnorr.verify(hexToBytes(event.sig), hexToBytes(hash), hexToBytes(event.pubkey)); event[verifiedSymbol2] = valid; return valid; } catch (err) { event[verifiedSymbol2] = false; return false; } } }; i2 = new JS2(); generateSecretKey2 = i2.generateSecretKey; getPublicKey2 = i2.getPublicKey; finalizeEvent2 = i2.finalizeEvent; verifyEvent2 = i2.verifyEvent; Seal = 13; GiftWrap = 1059; TWO_DAYS = 2 * 24 * 60 * 60; now = () => Math.round(Date.now() / 1e3); randomNow = () => Math.round(now() - Math.random() * TWO_DAYS); nip44ConversationKey = (privateKey, publicKey) => getConversationKey(privateKey, publicKey); nip44Encrypt = (data, privateKey, publicKey) => encrypt(JSON.stringify(data), nip44ConversationKey(privateKey, publicKey)); nip44Decrypt = (data, privateKey) => JSON.parse(decrypt(data.content, nip44ConversationKey(privateKey, data.pubkey))); } }); // node_modules/isomorphic-ws/browser.js var ws, browser_default; var init_browser = __esm({ "node_modules/isomorphic-ws/browser.js"() { ws = null; if (typeof WebSocket !== "undefined") { ws = WebSocket; } else if (typeof MozWebSocket !== "undefined") { ws = MozWebSocket; } else if (typeof global !== "undefined") { ws = global.WebSocket || global.MozWebSocket; } else if (typeof window !== "undefined") { ws = window.WebSocket || window.MozWebSocket; } else if (typeof self !== "undefined") { ws = self.WebSocket || self.MozWebSocket; } browser_default = ws; } }); // node_modules/eventemitter3/index.js var require_eventemitter3 = __commonJS({ "node_modules/eventemitter3/index.js"(exports, module) { "use strict"; var has = Object.prototype.hasOwnProperty; var prefix = "~"; function Events() { } if (Object.create) { Events.prototype = /* @__PURE__ */ Object.create(null); if (!new Events().__proto__) prefix = false; } function EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; } function addListener(emitter, event, fn, context, once) { if (typeof fn !== "function") { throw new TypeError("The listener must be a function"); } var listener = new EE(fn, context || emitter, once), evt = prefix ? prefix + event : event; if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); else emitter._events[evt] = [emitter._events[evt], listener]; return emitter; } function clearEvent(emitter, evt) { if (--emitter._eventsCount === 0) emitter._events = new Events(); else delete emitter._events[evt]; } function EventEmitter2() { this._events = new Events(); this._eventsCount = 0; } EventEmitter2.prototype.eventNames = function eventNames() { var names = [], events, name; if (this._eventsCount === 0) return names; for (name in events = this._events) { if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); } if (Object.getOwnPropertySymbols) { return names.concat(Object.getOwnPropertySymbols(events)); } return names; }; EventEmitter2.prototype.listeners = function listeners(event) { var evt = prefix ? prefix + event : event, handlers = this._events[evt]; if (!handlers) return []; if (handlers.fn) return [handlers.fn]; for (var i3 = 0, l = handlers.length, ee = new Array(l); i3 < l; i3++) { ee[i3] = handlers[i3].fn; } return ee; }; EventEmitter2.prototype.listenerCount = function listenerCount(event) { var evt = prefix ? prefix + event : event, listeners = this._events[evt]; if (!listeners) return 0; if (listeners.fn) return 1; return listeners.length; }; EventEmitter2.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return false; var listeners = this._events[evt], len = arguments.length, args, i3; if (listeners.fn) { if (listeners.once) this.removeListener(event, listeners.fn, void 0, true); switch (len) { case 1: return listeners.fn.call(listeners.context), true; case 2: return listeners.fn.call(listeners.context, a1), true; case 3: return listeners.fn.call(listeners.context, a1, a2), true; case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; } for (i3 = 1, args = new Array(len - 1); i3 < len; i3++) { args[i3 - 1] = arguments[i3]; } listeners.fn.apply(listeners.context, args); } else { var length = listeners.length, j; for (i3 = 0; i3 < length; i3++) { if (listeners[i3].once) this.removeListener(event, listeners[i3].fn, void 0, true); switch (len) { case 1: listeners[i3].fn.call(listeners[i3].context); break; case 2: listeners[i3].fn.call(listeners[i3].context, a1); break; case 3: listeners[i3].fn.call(listeners[i3].context, a1, a2); break; case 4: listeners[i3].fn.call(listeners[i3].context, a1, a2, a3); break; default: if (!args) for (j = 1, args = new Array(len - 1); j < len; j++) { args[j - 1] = arguments[j]; } listeners[i3].fn.apply(listeners[i3].context, args); } } } return true; }; EventEmitter2.prototype.on = function on(event, fn, context) { return addListener(this, event, fn, context, false); }; EventEmitter2.prototype.once = function once(event, fn, context) { return addListener(this, event, fn, context, true); }; EventEmitter2.prototype.removeListener = function removeListener(event, fn, context, once) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return this; if (!fn) { clearEvent(this, evt); return this; } var listeners = this._events[evt]; if (listeners.fn) { if (listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context)) { clearEvent(this, evt); } } else { for (var i3 = 0, events = [], length = listeners.length; i3 < length; i3++) { if (listeners[i3].fn !== fn || once && !listeners[i3].once || context && listeners[i3].context !== context) { events.push(listeners[i3]); } } if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; else clearEvent(this, evt); } return this; }; EventEmitter2.prototype.removeAllListeners = function removeAllListeners(event) { var evt; if (event) { evt = prefix ? prefix + event : event; if (this._events[evt]) clearEvent(this, evt); } else { this._events = new Events(); this._eventsCount = 0; } return this; }; EventEmitter2.prototype.off = EventEmitter2.prototype.removeListener; EventEmitter2.prototype.addListener = EventEmitter2.prototype.on; EventEmitter2.prefixed = prefix; EventEmitter2.EventEmitter = EventEmitter2; if ("undefined" !== typeof module) { module.exports = EventEmitter2; } } }); // node_modules/eventemitter3/index.mjs var import_index; var init_eventemitter3 = __esm({ "node_modules/eventemitter3/index.mjs"() { import_index = __toESM(require_eventemitter3(), 1); } }); // node_modules/@wizardconnect/core/dist/protocols/hdwalletv1.js function isPathXpub(obj) { return obj && typeof obj === "object" && typeof obj.name === "string" && typeof obj.xpub === "string"; } function childIndexOfPathName(name) { switch (name) { case PATH_RECEIVE: return 0; case PATH_CHANGE: return 1; case PATH_DEFI: return 7; default: return void 0; } } function isHdwalletv1Session(obj) { const s = obj; return obj !== null && typeof obj === "object" && Array.isArray(s.paths) && s.paths.every((p) => isPathXpub(p)) && (s.extensions === void 0 || typeof s.extensions === "object" && s.extensions !== null); } function isProtocolMessage(payload) { return payload && typeof payload === "object" && typeof payload.action === "string" && typeof payload.time === "number"; } function isErrorMessage(payload) { return payload && typeof payload === "object" && typeof payload.error === "string"; } function isSignTransactionRequest(msg) { return msg && typeof msg === "object" && msg.action === RelayMsgAction.SignTransactionRequest && msg.transaction && typeof msg.transaction === "object" && typeof msg.sequence === "number" && Array.isArray(msg.inputPaths) && msg.inputPaths.every((p) => Array.isArray(p) && p.length === 3 && typeof p[0] === "number" && typeof p[1] === "string" && typeof p[2] === "number"); } function isSignCancelMessage(msg) { return msg && typeof msg === "object" && msg.action === RelayMsgAction.SignCancel && typeof msg.sequence === "number"; } function isChunkMessage(msg) { return msg && typeof msg === "object" && msg.action === RelayMsgAction.Chunk && typeof msg.msgId === "string" && typeof msg.index === "number" && typeof msg.total === "number" && typeof msg.data === "string" && Number.isInteger(msg.index) && Number.isInteger(msg.total) && msg.total >= 1 && msg.index >= 0 && msg.index < msg.total; } var PROTOCOL_NAME, RelayMsgAction, PATH_RECEIVE, PATH_CHANGE, PATH_DEFI; var init_hdwalletv1 = __esm({ "node_modules/@wizardconnect/core/dist/protocols/hdwalletv1.js"() { PROTOCOL_NAME = "hdwalletv1"; (function(RelayMsgAction2) { RelayMsgAction2["DappReady"] = "dapp_ready"; RelayMsgAction2["WalletReady"] = "wallet_ready"; RelayMsgAction2["SignTransactionRequest"] = "sign_transaction_request"; RelayMsgAction2["SignTransactionResponse"] = "sign_transaction_response"; RelayMsgAction2["SignCancel"] = "sign_cancel"; RelayMsgAction2["Disconnect"] = "disconnect"; RelayMsgAction2["Chunk"] = "chunk"; RelayMsgAction2["Ping"] = "ping"; RelayMsgAction2["Pong"] = "pong"; })(RelayMsgAction || (RelayMsgAction = {})); PATH_RECEIVE = "receive"; PATH_CHANGE = "change"; PATH_DEFI = "defi"; } }); // node_modules/@wizardconnect/core/dist/utilnostr.js import { binToHex, secp256k1 as secp256k12 } from "@bitauth/libauth"; function deriveNostrPublicKey(privateKey) { const publicKeyCompressed = unwrap(secp256k12.derivePublicKeyCompressed(privateKey)); const publicKeyNostr = publicKeyCompressed.slice(1); return binToHex(publicKeyNostr); } function deriveNostrPublicKeyBytes(privateKey) { const publicKeyCompressed = unwrap(secp256k12.derivePublicKeyCompressed(privateKey)); return publicKeyCompressed.slice(1); } var init_utilnostr = __esm({ "node_modules/@wizardconnect/core/dist/utilnostr.js"() { init_primitives(); } }); // node_modules/@wizardconnect/core/dist/log.js function debug(scope, ...args) { console.log(`[${scope}]`, ...args); } function warn(scope, ...args) { console.warn(`[${scope}]`, ...args); } function error(scope, ...args) { console.error(`[${scope}]`, ...args); } var Scope; var init_log = __esm({ "node_modules/@wizardconnect/core/dist/log.js"() { (function(Scope2) { Scope2["Relay"] = "relay"; Scope2["Network"] = "network"; Scope2["Misc"] = "misc"; })(Scope || (Scope = {})); } }); // node_modules/@wizardconnect/core/dist/message-queue.js var MessageQueue; var init_message_queue = __esm({ "node_modules/@wizardconnect/core/dist/message-queue.js"() { init_log(); MessageQueue = class { queue = []; isReady = false; logActivity = false; constructor(options) { this.logActivity = options?.logActivity ?? false; } getReady() { return this.isReady; } getQueueLength() { return this.queue.length; } enqueue(message) { if (this.isReady) { return Promise.resolve(); } if (this.logActivity) { debug(Scope.Relay, `net: Relays not ready, queuing message ${message.action}`); } return new Promise((resolve, reject) => { this.queue.push({ message, resolve, reject }); }); } async setReady(publishFn) { this.isReady = true; const queuedMessages = [...this.queue]; this.queue = []; if (queuedMessages.length > 0 && this.logActivity) { debug(Scope.Relay, `Processing ${queuedMessages.length} queued messages`); } for (const queued of queuedMessages) { try { await publishFn(queued.message); queued.resolve(); } catch (error2) { queued.reject(error2); } } } setNotReady(errorMessage = "Connection closed before message could be sent") { this.isReady = false; const queuedMessages = [...this.queue]; this.queue = []; for (const queued of queuedMessages) { queued.reject(new Error(errorMessage)); } } clear() { const queuedMessages = [...this.queue]; this.queue = []; for (const queued of queuedMessages) { queued.reject(new Error("Queue cleared")); } } }; } }); // node_modules/@wizardconnect/core/dist/transforms/chunk.js function chunkExtensionAdvertisement() { return { version: CHUNK_EXTENSION_VERSION }; } function peerSupportsChunk(extensions) { return !!extensions && extensions[CHUNK_EXTENSION_NAME] !== void 0; } function utf8ByteLength(s) { return new TextEncoder().encode(s).length; } function needsChunking(serialized) { return utf8ByteLength(serialized) > CHUNK_REQUIRED_BYTES; } function splitIntoChunks(serialized, opts) { const msgId = opts?.msgId ?? newMsgId(); const time = opts?.time ?? Math.floor(Date.now() / 1e3); const utf8 = new TextEncoder().encode(serialized); const b64 = bytesToBase64(utf8); const sliceChars = Math.ceil(CHUNK_RAW_BYTES * 4 / 3); const total = Math.max(1, Math.ceil(b64.length / sliceChars)); const chunks = []; for (let i3 = 0; i3 < total; i3++) { chunks.push({ action: RelayMsgAction.Chunk, time, msgId, index: i3, total, data: b64.slice(i3 * sliceChars, (i3 + 1) * sliceChars) }); } return chunks; } function bytesToBase64(bytes) { const CHUNK = 32768; let binary = ""; for (let i3 = 0; i3 < bytes.length; i3 += CHUNK) { const slice = bytes.subarray(i3, i3 + CHUNK); binary += String.fromCharCode.apply(null, slice); } return btoa(binary); } function base64ToBytes(b64) { const binary = atob(b64); const out = new Uint8Array(binary.length); for (let i3 = 0; i3 < binary.length; i3++) { out[i3] = binary.charCodeAt(i3); } return out; } function newMsgId() { const g = globalThis; if (g.crypto?.randomUUID) return g.crypto.randomUUID(); const bytes = new Uint8Array(16); const cryptoObj = globalThis.crypto; if (cryptoObj?.getRandomValues) cryptoObj.getRandomValues(bytes); else for (let i3 = 0; i3 < 16; i3++) bytes[i3] = Math.floor(Math.random() * 256); return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(""); } var CHUNK_EXTENSION_NAME, CHUNK_EXTENSION_VERSION, CHUNK_RAW_BYTES, CHUNK_REQUIRED_BYTES, REASSEMBLY_TTL_MS, SWEEP_INTERVAL_MS, ChunkReassembler; var init_chunk = __esm({ "node_modules/@wizardconnect/core/dist/transforms/chunk.js"() { init_hdwalletv1(); init_log(); CHUNK_EXTENSION_NAME = "chunk"; CHUNK_EXTENSION_VERSION = 1; CHUNK_RAW_BYTES = 3e4; CHUNK_REQUIRED_BYTES = 4e4; REASSEMBLY_TTL_MS = 12e4; SWEEP_INTERVAL_MS = 1e4; ChunkReassembler = class { onComplete; logActivity; now; buffers = /* @__PURE__ */ new Map(); /// msgIds that have already been delivered, kept for a short grace period /// so late-arriving duplicate chunks (e.g. cross-subscription replay after /// reconnect) don't spawn a second reassembly and double-deliver. completed = /* @__PURE__ */ new Map(); sweeperId = null; constructor(onComplete, logActivity = true, now2 = () => Date.now()) { this.onComplete = onComplete; this.logActivity = logActivity; this.now = now2; } start() { if (this.sweeperId !== null) return; this.sweeperId = setInterval(() => this.sweep(), SWEEP_INTERVAL_MS); } stop() { if (this.sweeperId !== null) { clearInterval(this.sweeperId); this.sweeperId = null; } this.buffers.clear(); this.completed.clear(); } /// For tests. Otherwise start() schedules this automatically. sweep() { const now2 = this.now(); for (const [id, entry] of this.buffers) { if (entry.expiresAt <= now2) { this.buffers.delete(id); if (this.logActivity) { debug(Scope.Relay, `Chunk reassembly timeout: ${id} (${entry.received}/${entry.total} received)`); } } } for (const [id, expiresAt] of this.completed) { if (expiresAt <= now2) this.completed.delete(id); } } /// Ingest one chunk. If this completes the message, onComplete fires. /// Duplicate chunks (same msgId/index) are idempotent. Malformed chunks /// are dropped silently. ingest(chunk) { if (this.completed.has(chunk.msgId)) { return; } let entry = this.buffers.get(chunk.msgId); if (!entry) { entry = { total: chunk.total, chunks: new Array(chunk.total), received: 0, expiresAt: this.now() + REASSEMBLY_TTL_MS }; this.buffers.set(chunk.msgId, entry); } else if (entry.total !== chunk.total) { if (this.logActivity) { error(Scope.Relay, `Chunk total mismatch for ${chunk.msgId}: ${chunk.total} vs expected ${entry.total}`); } return; } if (entry.chunks[chunk.index] !== void 0) { return; } entry.chunks[chunk.index] = chunk.data; entry.received++; if (entry.received !== entry.total) return; this.buffers.delete(chunk.msgId); this.completed.set(chunk.msgId, this.now() + REASSEMBLY_TTL_MS); let reassembled; try { const fullB64 = entry.chunks.join(""); const bytes = base64ToBytes(fullB64); const json = new TextDecoder().decode(bytes); const parsed = JSON.parse(json); if (!isProtocolMessage(parsed)) { if (this.logActivity) { error(Scope.Relay, `Reassembled chunk msgId=${chunk.msgId} is not a valid ProtocolMessage`); } return; } reassembled = parsed; } catch (e) { if (this.logActivity) { error(Scope.Relay, `Chunk reassembly failed for msgId=${chunk.msgId}:`, e); } return; } if (this.logActivity) { debug(Scope.Relay, `Reassembled chunked message: action=${reassembled.action} chunks=${entry.total}`); } this.onComplete(reassembled); } /// Test helper: number of in-flight partial messages. get bufferCount() { return this.buffers.size; } }; } }); // node_modules/@wizardconnect/core/dist/relay-client.js import { binToHex as binToHex2, hash256, secp256k1 as secp256k13 } from "@bitauth/libauth"; var KIND_GIFT_WRAP, KIND_PRIVATE_DIRECT_MESSAGE, RelayClient; var init_relay_client = __esm({ "node_modules/@wizardconnect/core/dist/relay-client.js"() { init_primitives(); init_pool(); init_nip59(); init_browser(); init_eventemitter3(); init_hdwalletv1(); init_utilnostr(); init_message_queue(); init_log(); init_chunk(); useWebSocketImplementation(browser_default); KIND_GIFT_WRAP = 1059; KIND_PRIVATE_DIRECT_MESSAGE = 14; RelayClient = class _RelayClient extends import_index.default { // Keyed by "walletPubkeyHex:dappPubkeyHex". Persists the high-water mark // across RelayClient instance teardowns within the same JS session so that // reconnects after an explicit disconnect()+connect() still filter // relay-replayed messages from the prior session. static sessionTimestamps = /* @__PURE__ */ new Map(); pool; sharedPool; pairedPubkeyHex; config; subscription = null; myPubkey; myPubkeyHex; lastProcessedTimestamp = 0; messageQueue; readyTimeoutId = null; disconnecting = false; /// Capability flag: peer advertised support for the `chunk` transport /// extension in its dapp_ready / wallet_ready. Set via setPeerCapabilities. peerSupportsChunk = false; /// Receiver-side reassembly buffer. Always active — if no chunks arrive it /// stays empty. Started in connect(), stopped in disconnect(). reassembler; sequence = Math.floor(Math.random() * (Number.MAX_SAFE_INTEGER - 5e5)); pendingCalls = /* @__PURE__ */ new Map(); pendingDeliveries = /* @__PURE__ */ new Map(); get sessionKey() { return this.pairedPubkeyHex ? `${this.myPubkeyHex}:${this.pairedPubkeyHex}` : null; } constructor(config, pool) { super(); this.config = { logNetworkActivity: true, ...config }; this.pool = pool ?? new SimplePool({ enablePing: true }); this.sharedPool = pool !== void 0; this.messageQueue = new MessageQueue({ logActivity: this.config.logNetworkActivity }); this.reassembler = new ChunkReassembler((msg) => this.handleRelayMessage(msg), !!this.config.logNetworkActivity); this.myPubkey = unwrap(secp256k13.derivePublicKeyCompressed(this.config.signerPrivateKey)); this.myPubkeyHex = deriveNostrPublicKey(this.config.signerPrivateKey); if (this.config.pairedPublicKey) { const pairedNostrPubkey = this.config.pairedPublicKey.length === 33 ? this.config.pairedPublicKey.slice(1) : this.config.pairedPublicKey; this.pairedPubkeyHex = binToHex2(pairedNostrPubkey); } else { this.pairedPubkeyHex = ""; } const saved = this.sessionKey ? _RelayClient.sessionTimestamps.get(this.sessionKey) : void 0; if (saved) this.lastProcessedTimestamp = saved; } setPairedPublicKey(pairedPublicKey) { this.config.pairedPublicKey = pairedPublicKey; const pairedNostrPubkey = pairedPublicKey.length === 33 ? pairedPublicKey.slice(1) : pairedPublicKey; this.pairedPubkeyHex = binToHex2(pairedNostrPubkey); const saved = _RelayClient.sessionTimestamps.get(this.sessionKey); if (saved && saved > this.lastProcessedTimestamp) { this.lastProcessedTimestamp = saved; } this.emit("paired"); } /// Set transport-level capability flags based on the peer's advertisement in /// its dapp_ready / wallet_ready `extensions` field. Called by the connection /// manager after the handshake. New capability keys are additive — callers /// may omit any they don't set. setPeerCapabilities(caps) { if (caps.chunk !== void 0) { this.peerSupportsChunk = caps.chunk; } } getPublicKey() { return this.myPubkey; } getPublicKeyHex() { return this.myPubkeyHex; } isKeyExchangeComplete() { if (!this.config.pairedPublicKey) { return false; } return !this.config.pairedPublicKey.every((byte) => byte === 0); } emitDisconnect(error2) { if (this.disconnecting) return; this.disconnecting = true; this.emit("disconnect", error2); } async connect() { if (this.config.logNetworkActivity) { debug(Scope.Relay, `Connecting to relay...`); } this.disconnecting = false; this.reassembler.start(); if (this.lastProcessedTimestamp === 0) { this.lastProcessedTimestamp = Math.floor(Date.now() / 1e3) - 2; } try { this.subscription = this.pool.subscribeMany(this.config.explicitRelayUrls, { kinds: [KIND_GIFT_WRAP], "#p": [this.myPubkeyHex] }, { onevent: (event) => this.handleWrappedEvent(event), oneose: () => { if (this.readyTimeoutId) { clearTimeout(this.readyTimeoutId); this.readyTimeoutId = null; } if (this.config.logNetworkActivity) { debug(Scope.Relay, `EOSE received, relay connected`); } this.messageQueue.setReady((msg) => this.publishMessage(msg)); this.emit("connection"); }, onclose: (reasons) => { if (this.config.logNetworkActivity) { debug(Scope.Relay, `Subscription closed: ${reasons.join(", ")}`); } this.emitDisconnect(new Error("Subscription closed")); } }); this.readyTimeoutId = setTimeout(() => { if (!this.messageQueue.getReady()) { if (this.config.logNetworkActivity) { debug(Scope.Relay, `EOSE timeout, assuming ready`); } this.messageQueue.setReady((msg) => this.publishMessage(msg)); this.emit("connection"); } this.readyTimeoutId = null; }, 5e3); if (this.config.logNetworkActivity) { debug(Scope.Relay, `Subscription created, waiting for relay connection`); } } catch (error2) { if (this.config.logNetworkActivity) { error(Scope.Relay, `Connection failed:`, error2); } throw error2; } } async disconnect() { this.lastProcessedTimestamp = Math.floor(Date.now() / 1e3); const key = this.sessionKey; if (key) _RelayClient.sessionTimestamps.set(key, this.lastProcessedTimestamp); this.messageQueue.setNotReady(); this.reassembler.stop(); if (this.readyTimeoutId) { clearTimeout(this.readyTimeoutId); this.readyTimeoutId = null; } if (this.subscription) { this.subscription.close(); this.subscription = null; } if (!this.sharedPool) { this.pool.close(this.config.explicitRelayUrls); } } getLastProcessedTimestamp() { return this.lastProcessedTimestamp; } setLastProcessedTimestamp(timestamp) { this.lastProcessedTimestamp = timestamp; } async relay(message) { if (!this.config.pairedPublicKey) { throw new Error("Cannot relay message: paired public key not set. Call setPairedPublicKey() first."); } if (!this.messageQueue.getReady()) { return this.messageQueue.enqueue(message); } return this.publishMessage(message); } async publishMessage(message) { const serialized = JSON.stringify(message); if (!needsChunking(serialized)) { return this.publishSerialized(message.action, serialized); } if (!this.peerSupportsChunk) { const err = new Error(`Cannot send ${message.action}: message is larger than NIP-44's 65,535-byte ceiling and the peer does not advertise the 'chunk' transport extension. Please update the connected wallet/dapp to a version that supports chunked messages.`); if (this.config.logNetworkActivity) { error(Scope.Relay, err.message); } throw err; } const chunks = splitIntoChunks(serialized); if (this.config.logNetworkActivity) { debug(Scope.Relay, `Chunking ${message.action}: ${chunks.length} chunks (serialized ~${serialized.length} bytes)`); } for (const chunk of chunks) { await this.publishSerialized(`${message.action}[chunk ${chunk.index + 1}/${chunk.total}]`, JSON.stringify(chunk)); } } /// Wrap and publish one gift-wrap event. Used for both unchunked messages /// and individual chunks. `displayAction` is only used for logs. async publishSerialized(displayAction, serialized) { this.netlog("send", displayAction); const wrapped = wrapEvent({ kind: KIND_PRIVATE_DIRECT_MESSAGE, content: serialized, created_at: Math.floor(Date.now() / 1e3), tags: [["p", this.pairedPubkeyHex]] }, this.config.signerPrivateKey, this.pairedPubkeyHex); const results = await Promise.allSettled(this.pool.publish(this.config.explicitRelayUrls, wrapped)); const fulfilled = results.filter((r) => r.status === "fulfilled"); const rejected = results.filter((r) => r.status === "rejected"); if (rejected.length > 0 && this.config.logNetworkActivity) { for (const r of rejected) { error(Scope.Relay, `Failed to publish ${displayAction} to a relay:`, r.reason); } } if (fulfilled.length === 0) { const error2 = new Error(`Failed to publish ${displayAction} to all relays`); if (this.config.logNetworkActivity) { error(Scope.Relay, error2.message); } this.emitDisconnect(error2); throw error2; } if (this.config.logNetworkActivity) { debug(Scope.Relay, `Published message ${displayAction} to ${fulfilled.length}/${results.length} relay(s)`); } } handleWrappedEvent(wrappedEvent) { try { const rumor = unwrapEvent(wrappedEvent, this.config.signerPrivateKey); if (rumor.kind !== KIND_PRIVATE_DIRECT_MESSAGE) { if (this.config.logNetworkActivity) { debug(Scope.Relay, `Ignoring non-PrivateDirectMessage, kind: ${rumor.kind}`); } return; } let payload; try { payload = JSON.parse(rumor.content); } catch (e) { if (this.config.logNetworkActivity) { error(Scope.Relay, "Failed to parse message content as JSON:", e); } return; } this.routeIncoming(payload, rumor.pubkey); } catch (error2) { if (this.config.logNetworkActivity) { error(Scope.Relay, "Error handling incoming message:", error2); } this.emitError(error2); } } /// Apply timestamp dedup + peer filter, then dispatch to chunk reassembly /// or the application-level handler. Called from handleWrappedEvent (one /// path: unwrap → route). Kept separate to keep handleWrappedEvent focused /// on decryption and to allow future transport-layer transforms to invoke /// this path with already-decoded payloads. routeIncoming(payload, fromPubkey) { if (!payload.time || this.lastProcessedTimestamp > 0 && payload.time < this.lastProcessedTimestamp) { if (this.config.logNetworkActivity) { debug(Scope.Relay, `Ignoring already-processed message (time: ${payload.time}, action: ${payload.action}, last processed: ${this.lastProcessedTimestamp})`); } return; } if (payload.time > this.lastProcessedTimestamp) { this.lastProcessedTimestamp = payload.time; const key = this.sessionKey; if (key) _RelayClient.sessionTimestamps.set(key, this.lastProcessedTimestamp); } const isKeyExchangeMessage = payload.action === RelayMsgAction.WalletReady; if (!isKeyExchangeMessage && this.config.pairedPublicKey) { const pairedNostrPubkey = this.config.pairedPublicKey.length === 33 ? binToHex2(this.config.pairedPublicKey.slice(1)) : binToHex2(this.config.pairedPublicKey); if (fromPubkey !== pairedNostrPubkey) { if (this.config.logNetworkActivity) { debug(Scope.Relay, `Ignoring '${payload.action}' message from unknown peer: ${fromPubkey} (expected: ${pairedNostrPubkey})`); } return; } } if (isChunkMessage(payload)) { if (this.config.logNetworkActivity) { debug(Scope.Relay, `Received chunk ${payload.index + 1}/${payload.total} (msgId=${payload.msgId})`); } this.reassembler.ingest(payload); return; } if (this.config.logNetworkActivity) { debug(Scope.Relay, `Received message ${payload.action} from relay`); } this.handleRelayMessage(payload); } isConnected() { return this.subscription !== null; } netlog(direction, what, sequence) { if (!this.config.logNetworkActivity) { return; } const us = binToHex2(hash256(this.config.signerPrivateKey)).slice(-6); const them = this.config.pairedPublicKey ? binToHex2(this.config.pairedPublicKey).slice(-6) : "??????"; const pending = `c${this.pendingCalls.size} d${this.pendingDeliveries.size}`; if (direction === "send") { debug(Scope.Relay, `net [${sequence ?? "?"} ${pending}] ${us} -> ${them}: ${what}`); } else { debug(Scope.Relay, `net [${sequence ?? "?"} ${pending}] ${us} <- ${them}: ${what}`); } } async handleRelayMessage(message) { throwUnless(isProtocolMessage(message), `Invalid protocol message: ${message}`); this.emit("message", message); } nextSequence() { const current = this.sequence; this.sequence += 2; return current; } emitError(error2) { this.emit("error", error2); } }; } }); // node_modules/@wizardconnect/core/dist/connection-manager.js async function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } var createConnectionManager; var init_connection_manager = __esm({ "node_modules/@wizardconnect/core/dist/connection-manager.js"() { init_log(); createConnectionManager = (client, callbacks, events, options = {}) => { const { reconnectInterval = 5e3, maxReconnectAttempts = Infinity, enableVisibilityHandling = true, scope = Scope.Network, onVisibilityChange } = options; let isPaused = false; let reconnectLoop = null; let visibilityChangeHandler = null; const triggerReconnect = (reason) => { if (!isPaused) { callbacks.onReconnecting(client, reason); reconnectLoop = null; startConnectionLoop(); } }; const onConnected = () => callbacks.onConnected(client); client.on(events.connected, onConnected); const onDisconnected = (...args) => { const err = args[0] instanceof Error ? args[0].message : null; debug(scope, "Disconnected event received", err); triggerReconnect(err); }; const onError = (err) => { const errorMsg = err?.message || String(err); debug(scope, "Error event received", errorMsg); triggerReconnect(errorMsg); if (callbacks.onError) { callbacks.onError(client, err); } }; client.on(events.disconnected, onDisconnected); if (events.error) { client.on(events.error, onError); } const setupVisibilityHandling = () => { if (typeof document === "undefined") { return; } visibilityChangeHandler = () => { const state = document.visibilityState; if (onVisibilityChange) { const context = { client, state, setPaused: (value) => { isPaused = value; }, isPaused: () => isPaused, startConnectionLoop }; (async () => { try { await onVisibilityChange(context); } catch (err) { debug(scope, "Error in custom visibility change handler:", err); } })(); return; } if (state === "hidden") { isPaused = true; (async () => { try { await client.disconnect(); callbacks.onDisconnected(client); } catch (err) { debug(scope, "Error disconnecting on visibility change:", err); } })(); } else if (state === "visible") { if (isPaused) { isPaused = false; startConnectionLoop(); } } }; document.addEventListener("visibilitychange", visibilityChangeHandler); }; const startConnectionLoop = () => { if (reconnectLoop) { return; } reconnectLoop = (async () => { let reconnectAttempts = 0; let wasConnected = false; while (true) { if (isPaused) { await sleep(1e3); continue; } try { await client.connect(); reconnectAttempts = 0; wasConnected = true; reconnectLoop = null; return; } catch (e) { reconnectAttempts++; if (wasConnected || reconnectAttempts === 1) { callbacks.onReconnecting(client, `${e}`); wasConnected = false; } if (reconnectAttempts > maxReconnectAttempts) { callbacks.onDisconnected(client); reconnectLoop = null; return; } try { await client.disconnect(); } catch (disconnectError) { debug(scope, "Failed to disconnect client", disconnectError); } await sleep(reconnectInterval); } } })(); }; if (enableVisibilityHandling) { setupVisibilityHandling(); } const cleanup = async () => { isPaused = true; if (typeof document !== "undefined" && visibilityChangeHandler !== null) { document.removeEventListener("visibilitychange", visibilityChangeHandler); } client.off(events.connected, onConnected); client.off(events.disconnected, onDisconnected); if (events.error) { client.off(events.error, onError); } callbacks.onDisconnected(client); try { await client.disconnect(); } catch (e) { debug(scope, "Failed to disconnect client during cleanup", e); } }; return { cleanup, startConnectionLoop }; }; } }); // node_modules/@wizardconnect/core/dist/relay-handler.js var RelayStatus, initiateRelay; var init_relay_handler = __esm({ "node_modules/@wizardconnect/core/dist/relay-handler.js"() { init_relay_client(); init_connection_manager(); init_log(); RelayStatus = class _RelayStatus { status; error; sessionId; constructor(status, error2, sessionId = null) { this.status = status; this.error = error2; this.sessionId = sessionId; } static connected(sessionId) { return new _RelayStatus("connected", null, sessionId || null); } static reconnecting(reason, sessionId) { return new _RelayStatus("reconnecting", reason, sessionId || null); } static disconnected() { return new _RelayStatus("disconnected", null, null); } static sessionDeleted() { return new _RelayStatus("session_deleted", null, null); } }; initiateRelay = (dispatchCallback, signerPrivateKey, pairPublicKey, options) => { const client = new RelayClient({ explicitRelayUrls: options?.explicitRelayUrls ?? [], signerPrivateKey, pairedPublicKey: pairPublicKey }); let lastProcessedTimestamp = 0; const connectionManager = createConnectionManager(client, { onConnected: () => { if (lastProcessedTimestamp > 0) { client.setLastProcessedTimestamp(lastProcessedTimestamp); } else { lastProcessedTimestamp = client.getLastProcessedTimestamp(); } dispatchCallback({ client, status: RelayStatus.connected() }); }, onReconnecting: (_client, reason) => { dispatchCallback({ client, status: RelayStatus.reconnecting(reason) }); }, onDisconnected: () => { dispatchCallback({ client, status: RelayStatus.disconnected() }); }, onError: (_client, _error) => { } }, { connected: "connection", disconnected: "disconnect", error: "error" }, { reconnectInterval: options?.reconnectInterval, maxReconnectAttempts: options?.maxReconnectAttempts, enableVisibilityHandling: options?.enableVisibilityHandling ?? true, scope: Scope.Relay, onVisibilityChange: async (context) => { if (context.state === "hidden") { debug(Scope.Relay, "Page hidden, disconnecting relay"); context.setPaused(true); try { await client.disconnect(); lastProcessedTimestamp = client.getLastProcessedTimestamp(); debug(Scope.Relay, `Disconnected, last processed timestamp: ${lastProcessedTimestamp}`); dispatchCallback({ client, status: RelayStatus.disconnected() }); } catch (error2) { error(Scope.Relay, "Error disconnecting on visibility change:", error2); } } else if (context.state === "visible") { if (context.isPaused()) { debug(Scope.Relay, "Page visible, reconnecting relay"); context.setPaused(false); context.startConnectionLoop(); } } } }); connectionManager.startConnectionLoop(); return () => { dispatchCallback({ client, status: RelayStatus.disconnected() }); (async () => { try { await connectionManager.cleanup(); } catch { } })(); }; }; } }); // node_modules/@wizardconnect/core/dist/key-exchange.js import { generatePrivateKey, binToHex as binToHex3, hexToBin, binToBech32Padded, bech32PaddedToBin } from "@bitauth/libauth"; function generateKeyExchangeCredentials() { const privateKey = generatePrivateKey(); const privateKeyHex = binToHex3(privateKey); const publicKeyHex = deriveNostrPublicKey(privateKey); const secretBytes = generatePrivateKey(); const secretShort = secretBytes.slice(0, 8); const secret = binToHex3(secretShort); return { privateKey: privateKeyHex, publicKey: publicKeyHex, secret }; } function encodeKeyExchangeURI(publicKey, secret, options = {}) { const publicKeyBin = hexToBin(publicKey); const secretBin = hexToBin(secret); if (publicKeyBin.length !== 32) { throw new Error(`Invalid public key length: expected 32 bytes, got ${publicKeyBin.length}`); } if (secretBin.length !== 8) { throw new Error(`Invalid secret length: expected 8 bytes, got ${secretBin.length}`); } const publicKeyBech32 = binToBech32Padded(publicKeyBin).toLowerCase(); const secretBech32 = binToBech32Padded(secretBin).toLowerCase(); const hostname = options.hostname || DEFAULT_RELAY_HOSTNAME; const port = options.port ?? DEFAULT_RELAY_PORT; const protocol = options.protocol || DEFAULT_RELAY_PROTOCOL; const isDefaultHostname = hostname === DEFAULT_RELAY_HOSTNAME; const defaultPort = protocol === "wss" ? 443 : 80; const isDefaultPort = port === defaultPort; const isDefaultProtocol = protocol === DEFAULT_RELAY_PROTOCOL; let uri; if (isDefaultHostname && isDefaultPort && isDefaultProtocol) { uri = `wiz://?p=${publicKeyBech32}&s=${secretBech32}`; } else { const portPart = isDefaultPort ? "" : `:${port}`; const authority = `${hostname}${portPart}`; uri = `wiz://${authority}?p=${publicKeyBech32}&s=${secretBech32}`; if (!isDefaultProtocol) { uri += `&pr=${protocol}`; } } const qrUri = uri.toUpperCase().replace("?", "%3F").replace(/=/g, "%3D").replace(/&/g, "%26"); return { uri, qrUri }; } function decodeKeyExchangeURI(uri) { let url; try { const lower = uri.toLowerCase(); const isQr = lower.includes("%3f") && !lower.includes("?"); const toParse = isQr ? lower.replace("%3f", "?").replace(/%3d/g, "=").replace(/%26/g, "&") : lower; url = new URL(toParse); } catch (error2) { throw new Error(`Invalid URI format: ${error2 instanceof Error ? error2.message : "unknown error"}`, { cause: error2 }); } if (url.protocol !== "wiz:") { throw new Error("Invalid URI scheme. Expected: wiz://"); } let hostname = url.hostname || DEFAULT_RELAY_HOSTNAME; let port; if (url.port) { const parsedPort = parseInt(url.port, 10); if (isNaN(parsedPort) || parsedPort < 1 || parsedPort > 65535) { throw new Error(`Invalid port number: ${url.port}`); } port = parsedPort; } else { port = DEFAULT_RELAY_PORT; } const publicKeyBech32 = url.searchParams.get("p"); const secretBech32 = url.searchParams.get("s"); if (!publicKeyBech32 || !secretBech32) { throw new Error("Invalid URI format. Missing required parameters: p (public key) or s (secret)"); } const protocol = url.searchParams.get("pr"); const publicKeyBech32Normalized = publicKeyBech32.toLowerCase(); const secretBech32Normalized = secretBech32.toLowerCase(); let publicKeyBin; let secretBin; try { const pubkeyResult = bech32PaddedToBin(publicKeyBech32Normalized); const secretResult = bech32PaddedToBin(secretBech32Normalized); if (pubkeyResult instanceof Uint8Array && secretResult instanceof Uint8Array) { publicKeyBin = pubkeyResult; secretBin = secretResult; } else { const pubkeyError = typeof pubkeyResult === "string" ? pubkeyResult : "Unknown error"; const secretError = typeof secretResult === "string" ? secretResult : "Unknown error"; throw new Error(`Bech32 decoding failed: pubkey=${pubkeyError}, secret=${secretError}`); } } catch (error2) { throw new Error(`Invalid bech32 encoding: ${error2 instanceof Error ? error2.message : "unknown error"}`, { cause: error2 }); } if (publicKeyBin.length !== 32) { throw new Error(`Invalid public key length: expected 32 bytes, got ${publicKeyBin.length}`); } if (secretBin.length !== 8) { throw new Error(`Invalid secret length: expected 8 bytes, got ${secretBin.length}`); } if (protocol && protocol !== "ws" && protocol !== "wss") { throw new Error(`Invalid protocol: ${protocol}. Must be 'ws' or 'wss'`); } if (!url.port && protocol === "ws") { port = 80; } return { publicKey: binToHex3(publicKeyBin), secret: binToHex3(secretBin), hostname, port, protocol: protocol || DEFAULT_RELAY_PROTOCOL }; } var DEFAULT_RELAY_HOSTNAME, DEFAULT_RELAY_PORT, DEFAULT_RELAY_PROTOCOL, DEFAULT_RELAY_URLS; var init_key_exchange = __esm({ "node_modules/@wizardconnect/core/dist/key-exchange.js"() { init_utilnostr(); DEFAULT_RELAY_HOSTNAME = "relay.riften.net"; DEFAULT_RELAY_PORT = 443; DEFAULT_RELAY_PROTOCOL = "wss"; DEFAULT_RELAY_URLS = [ "wss://relay.riften.net:443", "wss://relay.cauldron.quest:443" ]; } }); // node_modules/@wizardconnect/core/dist/dapp-relay.js import { hexToBin as hexToBin2, binToHex as binToHex4 } from "@bitauth/libauth"; function initiateDappRelay(statusCallback, options = {}) { const events = new import_index.default(); let credentials; let dappPrivateKey; if (options.existingCredentials) { const privateKeyHex = options.existingCredentials.privateKey; if (privateKeyHex.length !== 64) { throw new Error("Private key must be 64 hex characters (32 bytes)"); } dappPrivateKey = hexToBin2(privateKeyHex); const dappPublicKeyHex = deriveNostrPublicKey(dappPrivateKey); credentials = { privateKey: privateKeyHex, publicKey: dappPublicKeyHex, secret: options.existingCredentials.secret }; } else { credentials = generateKeyExchangeCredentials(); dappPrivateKey = hexToBin2(credentials.privateKey); } let uriOptions = {}; if (options.explicitRelayUrls && options.explicitRelayUrls.length > 0) { const relayUrl = options.explicitRelayUrls[0]; const hostMatch = relayUrl.match(/^wss?:\/\/([^:/]+)/); const portMatch = relayUrl.match(/:(\d+)/); if (hostMatch) { uriOptions.hostname = hostMatch[1]; } if (portMatch) { uriOptions.port = parseInt(portMatch[1], 10); } if (relayUrl.startsWith("wss://")) { uriOptions.protocol = "wss"; } else if (relayUrl.startsWith("ws://")) { uriOptions.protocol = "ws"; } } const { uri, qrUri } = encodeKeyExchangeURI(credentials.publicKey, credentials.secret, uriOptions); let relayClient = null; let keyExchanged = false; let walletPublicKeyNostr = null; if (options.existingCredentials) { walletPublicKeyNostr = hexToBin2(options.existingCredentials.walletPublicKey); keyExchanged = true; } const wrappedCallback = (payload) => { if (!relayClient) { relayClient = payload.client; relayClient.on("message", async (message) => { if (message.action === RelayMsgAction.WalletReady) { const walletReady = message; if (walletReady.secret !== credentials.secret) { if (!keyExchanged) { error(Scope.Relay, "Key exchange failed: secret mismatch"); } return; } const receivedWalletKey = hexToBin2(walletReady.public_key); if (receivedWalletKey.length !== 32) { error(Scope.Relay, "Invalid wallet public key length"); return; } if (keyExchanged && walletPublicKeyNostr) { if (binToHex4(receivedWalletKey) !== binToHex4(walletPublicKeyNostr)) { warn(Scope.Relay, "Different wallet connected (different public key)"); } } walletPublicKeyNostr = receivedWalletKey; relayClient.setPairedPublicKey(receivedWalletKey); if (!keyExchanged) { keyExchanged = true; events.emit("keyexchangecomplete", receivedWalletKey); } } }); } if (payload.status.status === "connected") { if (walletPublicKeyNostr && relayClient) { relayClient.setPairedPublicKey(walletPublicKeyNostr); keyExchanged = true; } } statusCallback(payload); }; const relayUrls = options.explicitRelayUrls && options.explicitRelayUrls.length > 0 ? options.explicitRelayUrls : [...DEFAULT_RELAY_URLS]; const cleanup = initiateRelay(wrappedCallback, dappPrivateKey, walletPublicKeyNostr ?? new Uint8Array(33), { explicitRelayUrls: relayUrls, reconnectInterval: options.reconnectInterval, maxReconnectAttempts: options.maxReconnectAttempts }); return { client: relayClient, uri, qrUri, credentials, events, cleanup }; } var init_dapp_relay = __esm({ "node_modules/@wizardconnect/core/dist/dapp-relay.js"() { init_relay_handler(); init_hdwalletv1(); init_key_exchange(); init_eventemitter3(); init_utilnostr(); init_log(); } }); // node_modules/@wizardconnect/core/dist/wallet-relay.js import { hexToBin as hexToBin3 } from "@bitauth/libauth"; function initiateWalletRelay(statusCallback, options) { let decoded; try { decoded = decodeKeyExchangeURI(options.uri); } catch (err) { throw new Error(`Failed to decode connection URI: ${err.message}`, { cause: err }); } const dappPublicKeyHex = decoded.publicKey; const secret = decoded.secret; const dappPublicKeyNostr = hexToBin3(dappPublicKeyHex); const hostname = decoded.hostname; const protocol = decoded.protocol; const port = decoded.port; const relayUrl = `${protocol}://${hostname}:${port}`; const walletPublicKeyNostr = deriveNostrPublicKeyBytes(options.walletPrivateKey); let relayClient = null; const wrappedCallback = (payload) => { if (!relayClient) { relayClient = payload.client; } if (payload.status.status === "connected") { relayClient.setPairedPublicKey(dappPublicKeyNostr); } statusCallback(payload); }; const relayUrls = [relayUrl]; const isDefaultRelay = DEFAULT_RELAY_URLS.includes(relayUrl); if (isDefaultRelay) { for (const defaultUrl of DEFAULT_RELAY_URLS) { if (!relayUrls.includes(defaultUrl)) { relayUrls.push(defaultUrl); } } } if (options.explicitRelayUrls && options.explicitRelayUrls.length > 0) { for (const explicitUrl of options.explicitRelayUrls) { if (!relayUrls.includes(explicitUrl)) { relayUrls.push(explicitUrl); } } } const cleanup = initiateRelay(wrappedCallback, options.walletPrivateKey, dappPublicKeyNostr, { explicitRelayUrls: relayUrls, reconnectInterval: options.reconnectInterval, maxReconnectAttempts: options.maxReconnectAttempts }); const result = { get client() { if (!relayClient) { throw new Error("Relay client not yet initialized. Wait for connection status callback."); } return relayClient; }, dappPublicKey: dappPublicKeyNostr, walletPublicKey: walletPublicKeyNostr, secret, cleanup }; return result; } var init_wallet_relay = __esm({ "node_modules/@wizardconnect/core/dist/wallet-relay.js"() { init_relay_handler(); init_key_exchange(); init_utilnostr(); } }); // node_modules/@wizardconnect/core/dist/protocols/base.js function isDappReadyMessage(msg) { return isProtocolMessage(msg) && msg.action === RelayMsgAction.DappReady && Array.isArray(msg.supported_protocols) && typeof msg.wallet_discovered === "boolean"; } function isWalletReadyMessage(msg) { const m = msg; return isProtocolMessage(msg) && msg.action === RelayMsgAction.WalletReady && typeof m.wallet_name === "string" && typeof m.wallet_icon === "string" && typeof m.dapp_discovered === "boolean" && Array.isArray(m.supported_protocols) && m.session !== null && typeof m.session === "object" && typeof m.public_key === "string" && typeof m.secret === "string"; } function isDisconnectMessage(msg) { return isProtocolMessage(msg) && msg.action === RelayMsgAction.Disconnect && typeof msg.reason === "string"; } var DisconnectReason; var init_base2 = __esm({ "node_modules/@wizardconnect/core/dist/protocols/base.js"() { init_hdwalletv1(); (function(DisconnectReason2) { DisconnectReason2["ProtocolMismatch"] = "protocol_mismatch"; DisconnectReason2["UserDisconnect"] = "user_disconnect"; })(DisconnectReason || (DisconnectReason = {})); } }); // node_modules/@wizardconnect/core/dist/serialize.js import { hexToBin as hexToBin4 } from "@bitauth/libauth"; function parseExtendedJson(jsonString) { return JSON.parse(jsonString, (_key, value) => { if (typeof value === "string") { const bigintMatch = value.match(BIGINT_RE); if (bigintMatch) return BigInt(bigintMatch[1]); const uint8Match = value.match(UINT8_RE); if (uint8Match) return hexToBin4(uint8Match[1]); } return value; }); } function isExtendedJsonFormat(str) { return UINT8_RE.test(str) || BIGINT_RE.test(str); } function parseExtendedJsonValue(value) { const bigintMatch = value.match(BIGINT_RE); if (bigintMatch) return BigInt(bigintMatch[1]); const uint8Match = value.match(UINT8_RE); if (uint8Match) return hexToBin4(uint8Match[1]); return value; } function toUint8Array(value) { if (value instanceof Uint8Array) return value; if (isExtendedJsonFormat(value)) return parseExtendedJsonValue(value); return hexToBin4(value); } function toBigInt(value) { if (typeof value === "bigint") return value; if (typeof value === "string") { if (isExtendedJsonFormat(value)) return parseExtendedJsonValue(value); return BigInt(value); } return BigInt(value); } var BIGINT_RE, UINT8_RE; var init_serialize = __esm({ "node_modules/@wizardconnect/core/dist/serialize.js"() { BIGINT_RE = /^[0-9]*)n>$/; UINT8_RE = /^[0-9a-f]*)>$/u; } }); // node_modules/@wizardconnect/core/dist/index.js var dist_exports = {}; __export(dist_exports, { CHUNK_EXTENSION_NAME: () => CHUNK_EXTENSION_NAME, CHUNK_EXTENSION_VERSION: () => CHUNK_EXTENSION_VERSION, DEFAULT_RELAY_HOSTNAME: () => DEFAULT_RELAY_HOSTNAME, DEFAULT_RELAY_PORT: () => DEFAULT_RELAY_PORT, DEFAULT_RELAY_PROTOCOL: () => DEFAULT_RELAY_PROTOCOL, DEFAULT_RELAY_URLS: () => DEFAULT_RELAY_URLS, DisconnectReason: () => DisconnectReason, PATH_CHANGE: () => PATH_CHANGE, PATH_DEFI: () => PATH_DEFI, PATH_RECEIVE: () => PATH_RECEIVE, PROTOCOL_NAME: () => PROTOCOL_NAME, RelayClient: () => RelayClient, RelayMsgAction: () => RelayMsgAction, RelayStatus: () => RelayStatus, SimplePool: () => SimplePool, bech32PaddedToBin: () => bech32PaddedToBin2, binToBech32Padded: () => binToBech32Padded2, binToHex: () => binToHex5, childIndexOfPathName: () => childIndexOfPathName, chunkExtensionAdvertisement: () => chunkExtensionAdvertisement, decodeKeyExchangeURI: () => decodeKeyExchangeURI, encodeKeyExchangeURI: () => encodeKeyExchangeURI, generateKeyExchangeCredentials: () => generateKeyExchangeCredentials, hexToBin: () => hexToBin5, initiateDappRelay: () => initiateDappRelay, initiateRelay: () => initiateRelay, initiateWalletRelay: () => initiateWalletRelay, isChunkMessage: () => isChunkMessage, isDappReadyMessage: () => isDappReadyMessage, isDisconnectMessage: () => isDisconnectMessage, isErrorMessage: () => isErrorMessage, isExtendedJsonFormat: () => isExtendedJsonFormat, isHdwalletv1Session: () => isHdwalletv1Session, isPathXpub: () => isPathXpub, isProtocolMessage: () => isProtocolMessage, isSignCancelMessage: () => isSignCancelMessage, isSignTransactionRequest: () => isSignTransactionRequest, isWalletReadyMessage: () => isWalletReadyMessage, parseExtendedJson: () => parseExtendedJson, parseExtendedJsonValue: () => parseExtendedJsonValue, peerSupportsChunk: () => peerSupportsChunk, toBigInt: () => toBigInt, toUint8Array: () => toUint8Array }); import { binToHex as binToHex5, hexToBin as hexToBin5, binToBech32Padded as binToBech32Padded2, bech32PaddedToBin as bech32PaddedToBin2 } from "@bitauth/libauth"; var init_dist = __esm({ "node_modules/@wizardconnect/core/dist/index.js"() { init_relay_client(); init_pool(); init_relay_handler(); init_dapp_relay(); init_wallet_relay(); init_key_exchange(); init_hdwalletv1(); init_base2(); init_chunk(); init_serialize(); } }); // node_modules/@wizardconnect/dapp/dist/pubkey-state-manager.js import { deriveHdPublicNodeChild } from "@bitauth/libauth"; var DappPubkeyStateManager; var init_pubkey_state_manager = __esm({ "node_modules/@wizardconnect/dapp/dist/pubkey-state-manager.js"() { DappPubkeyStateManager = class { // xpub nodes for on-demand pubkey derivation xpubNodes = /* @__PURE__ */ new Map(); /** Derive a pubkey on demand from the stored xpub node. */ getPubkey(childIndex, index) { const xpubNode = this.xpubNodes.get(childIndex); if (!xpubNode) return void 0; const child = deriveHdPublicNodeChild(xpubNode, Number(index)); if (typeof child === "string") return void 0; return child.publicKey; } /** Returns true if an xpub node is available for this child index. */ hasPath(childIndex) { return this.xpubNodes.has(childIndex); } setXpubNode(childIndex, node) { this.xpubNodes.set(childIndex, node); } getXpubNode(childIndex) { return this.xpubNodes.get(childIndex); } }; } }); // node_modules/@wizardconnect/dapp/dist/session.js function defaultStorage() { if (typeof localStorage !== "undefined" && typeof localStorage.getItem === "function") return localStorage; return null; } function resolveStorage(storage) { return storage ?? defaultStorage(); } function loadSession(key = DEFAULT_SESSION_KEY, storage) { const s = resolveStorage(storage); if (!s) return null; const raw = s.getItem(key); if (!raw) return null; try { const parsed = JSON.parse(raw); if (!parsed.privateKey || !parsed.secret) return null; return parsed; } catch { return null; } } function saveSession(key = DEFAULT_SESSION_KEY, data, storage) { const s = resolveStorage(storage); if (!s) return; const existing = loadSession(key, s); const merged = { ...existing, ...data }; s.setItem(key, JSON.stringify(merged)); } function clearSession(key = DEFAULT_SESSION_KEY, storage) { const s = resolveStorage(storage); if (!s) return; s.removeItem(key); } var DEFAULT_SESSION_KEY; var init_session = __esm({ "node_modules/@wizardconnect/dapp/dist/session.js"() { DEFAULT_SESSION_KEY = "wizardconnect-session"; } }); // node_modules/@wizardconnect/dapp/dist/dapp-connection-manager.js import { decodeHdPublicKey } from "@bitauth/libauth"; var DappConnectionManager; var init_dapp_connection_manager = __esm({ "node_modules/@wizardconnect/dapp/dist/dapp-connection-manager.js"() { init_eventemitter3(); init_dist(); init_pubkey_state_manager(); init_session(); DappConnectionManager = class extends import_index.default { dappName; dappIcon; conn = null; listenerAttached = false; /** Pubkey state — exposed for callers that need to query by index. */ pubkeyState; walletName = null; walletIcon = null; protocol = null; /** Protocols this dapp supports, in preference order. */ supportedProtocols = [PROTOCOL_NAME]; walletDiscovered = false; disconnectGraceTimer = null; pingInterval = null; /** Timestamp (ms) of the last pong or wallet_ready received. Used for liveness detection. */ lastPongTime = 0; sessionPaths = []; pendingSignatureRequests = /* @__PURE__ */ new Map(); sessionOptions = null; /** * @param dappName Optional display name of the dapp (sent in dapp_ready). * @param dappIcon Optional icon URL/data-URI of the dapp (sent in dapp_ready). * @param options Optional configuration. Session persistence is enabled by * default (key: "wizardconnect-session", storage: localStorage). * Pass `session: false` to disable. */ constructor(dappName, dappIcon, options) { super(); this.dappName = dappName; this.dappIcon = dappIcon; this.pubkeyState = new DappPubkeyStateManager(); if (options?.session !== false) { const sessionConf = options?.session ?? {}; this.sessionOptions = { key: sessionConf.key ?? DEFAULT_SESSION_KEY, storage: sessionConf.storage }; const stored = loadSession(this.sessionOptions.key, this.sessionOptions.storage); if (stored) { if (stored.walletName) this.walletName = stored.walletName; if (stored.walletIcon) this.walletIcon = stored.walletIcon; if (stored.paths?.length) { try { this.restoreSessionPaths(stored.paths); } catch { } } } } } // --- Session persistence (public API) ---------------------------------------- /** * Attach a relay result from `initiateDappRelay()`. Automatically: * - Saves relay credentials (privateKey, secret) to the session * - Listens for `keyexchangecomplete` and saves the wallet public key * * No-op if session persistence is disabled. */ attachRelay(relay) { if (!this.sessionOptions) return; saveSession(this.sessionOptions.key, { privateKey: relay.credentials.privateKey, secret: relay.credentials.secret }, this.sessionOptions.storage); relay.events.on("keyexchangecomplete", (walletPublicKey) => { if (!this.sessionOptions) return; saveSession(this.sessionOptions.key, { walletPublicKey: binToHex5(walletPublicKey) }, this.sessionOptions.storage); }); } /** * Load the stored session (e.g. for reconnection). * Returns null if session persistence is disabled or no session exists. */ loadStoredSession() { if (!this.sessionOptions) return null; return loadSession(this.sessionOptions.key, this.sessionOptions.storage); } /** * Clear the stored session. Call on disconnect. * No-op if session persistence is disabled. */ clearStoredSession() { if (!this.sessionOptions) return; clearSession(this.sessionOptions.key, this.sessionOptions.storage); } // --- Relay connection ------------------------------------------------------- /** * Call this from the RelayStatusCallback passed to `initiateDappRelay`. * Attaches the message listener exactly once and re-sends dapp_ready * each time the connection is established (handles reconnects). */ updateConnection(client, status) { if (client) { if (!this.listenerAttached) { this.listenerAttached = true; client.on("message", (msg) => this.handleMessage(msg)); } this.conn = client; } if (status.status === "connected" && this.conn) { this.onConnected(); } else if (status.status === "reconnecting" || status.status === "disconnected") { this.stopPingInterval(); if (status.status === "reconnecting") { this.emit("reconnecting"); } } } isWalletDiscovered() { return this.walletDiscovered; } /** * Get a sequence number from the relay client. * Use this to populate the `sequence` field of a SignTransactionRequest. */ nextSequence() { if (!this.conn) throw new Error("[wizardconnect/dapp] Not connected"); return this.conn.nextSequence(); } /** * Send a sign transaction request and wait for the wallet's response. * The caller is responsible for creating the full SignTransactionRequest * (including sequence from `nextSequence()`). */ async sendSignRequest(request) { if (!this.conn) throw new Error("[wizardconnect/dapp] Not connected"); return new Promise((resolve, reject) => { this.pendingSignatureRequests.set(request.sequence, { request, resolve, reject }); this.conn.relay(request).then(() => { this.emit("messagesent", request); }).catch((err) => { this.pendingSignatureRequests.delete(request.sequence); reject(err instanceof Error ? err : new Error(String(err))); }); }); } /** * Cancel an in-flight sign request. * Immediately rejects the pending Promise and sends sign_cancel to the wallet. */ async sendSignCancel(sequence, reason) { const handlers = this.pendingSignatureRequests.get(sequence); if (handlers) { this.pendingSignatureRequests.delete(sequence); handlers.reject(new Error(reason ?? "Sign request cancelled")); } if (!this.conn) return; const msg = { action: RelayMsgAction.SignCancel, sequence, ...reason !== void 0 && { reason }, time: Math.floor(Date.now() / 1e3) }; await this.conn.relay(msg); this.emit("messagesent", msg); } /** * Send a disconnect message to the wallet (courtesy notification). * The caller is responsible for calling dappRelay.cleanup() afterwards. */ async sendDisconnect(message) { if (!this.conn) return; const msg = { action: RelayMsgAction.Disconnect, reason: DisconnectReason.UserDisconnect, time: Math.floor(Date.now() / 1e3), ...message !== void 0 && { message } }; await this.conn.relay(msg); this.emit("messagesent", msg); } /** * Convenience method: build and send a sign transaction request. * Auto-fills `action`, `sequence`, and `time`. Supports cancellation via * AbortSignal — when aborted, sendSignCancel is called automatically. */ async signTransaction(request, options) { const sequence = this.nextSequence(); const fullRequest = { action: RelayMsgAction.SignTransactionRequest, time: Math.floor(Date.now() / 1e3), sequence, ...request }; const signPromise = this.sendSignRequest(fullRequest); if (!options?.signal) return signPromise; signPromise.catch(() => { }); return new Promise((resolve, reject) => { const onAbort = () => { const reason = options.signal.reason instanceof Error ? options.signal.reason.message : typeof options.signal.reason === "string" ? options.signal.reason : "Sign request cancelled"; this.sendSignCancel(sequence, reason).catch(() => { }); reject(new DOMException(reason, "AbortError")); }; if (options.signal.aborted) { onAbort(); return; } options.signal.addEventListener("abort", onAbort, { once: true }); signPromise.then(resolve).catch(reject).finally(() => { options.signal.removeEventListener("abort", onAbort); }); }); } // --- Pubkey state delegation ------------------------------------------------ // Convenience methods that forward to pubkeyState. getPubkey(childIndex, index) { return this.pubkeyState.getPubkey(childIndex, index); } /** Returns true if an xpub node is available for this child index. */ hasPath(childIndex) { return this.pubkeyState.hasPath(childIndex); } /** * Returns the stored xpub node for the given child index. * Available after wallet_ready is received. */ getXpubNode(childIndex) { return this.pubkeyState.getXpubNode(childIndex); } /** * Returns the raw PathXpub entries received from the wallet. * Available after wallet_ready is received. */ getSessionPaths() { return [...this.sessionPaths]; } /** * Restore session paths from a previous session (e.g. from localStorage). * Decodes xpub strings and populates pubkeyState so getPubkey() works * without waiting for wallet_ready. */ restoreSessionPaths(paths) { this.sessionPaths = [...paths]; for (const pathInfo of paths) { const decoded = decodeHdPublicKey(pathInfo.xpub); if (typeof decoded === "string") { throw new Error(`[wizardconnect/dapp] Invalid xpub for path "${pathInfo.name}": ${decoded}`); } const ci = childIndexOfPathName(pathInfo.name); if (ci !== void 0) { this.pubkeyState.setXpubNode(ci, decoded.node); } } } // --- Private protocol handling ------------------------------------------- onConnected() { (async () => { const deadline = Date.now() + 3e4; while (this.conn && !this.conn.isKeyExchangeComplete()) { if (Date.now() >= deadline) { console.error("[wizardconnect/dapp] Key exchange timed out"); return; } await new Promise((r) => setTimeout(r, 100)); } if (!this.conn) return; await this.pushDappReady(); })().catch((e) => console.error("[wizardconnect/dapp] Error in onConnected:", e)); } startPingInterval() { this.stopPingInterval(); this.lastPongTime = Date.now(); this.pingInterval = setInterval(() => { if (!this.conn || !this.walletDiscovered) return; if (Date.now() - this.lastPongTime > 75e3) { this.stopPingInterval(); this.emit("reconnecting"); return; } const ping = { action: RelayMsgAction.Ping, time: Math.floor(Date.now() / 1e3) }; this.conn.relay(ping).catch(() => { }); }, 1e4); } stopPingInterval() { if (this.pingInterval !== null) { clearInterval(this.pingInterval); this.pingInterval = null; } } destroy() { this.stopPingInterval(); if (this.disconnectGraceTimer !== null) { clearTimeout(this.disconnectGraceTimer); this.disconnectGraceTimer = null; } } async pushDappReady() { if (!this.conn) return; const msg = { action: RelayMsgAction.DappReady, supported_protocols: this.supportedProtocols, wallet_discovered: this.walletDiscovered, time: Math.floor(Date.now() / 1e3), // Include selected_protocol on the reactive send (after the dapp has seen the wallet) ...this.walletDiscovered && this.protocol && { selected_protocol: this.protocol }, ...this.dappName !== void 0 && { dapp_name: this.dappName }, ...this.dappIcon !== void 0 && { dapp_icon: this.dappIcon }, // Transport-level: advertise chunking so the wallet can send large // SignTransactionResponses (signed tx hex can reach ~2 MB) that exceed // NIP-44's plaintext ceiling. extensions: { chunk: chunkExtensionAdvertisement() } }; await this.conn.relay(msg); this.emit("messagesent", msg); } handleMessage(msg) { this.emit("messagereceived", msg); switch (msg.action) { case RelayMsgAction.WalletReady: this.handleWalletReady(msg).catch((e) => console.error("[wizardconnect/dapp] Error handling wallet_ready:", e)); break; case RelayMsgAction.SignTransactionResponse: this.handleSignTransactionResponse(msg); break; case RelayMsgAction.Disconnect: this.handleRemoteDisconnect(msg); break; case RelayMsgAction.Pong: this.lastPongTime = Date.now(); break; case RelayMsgAction.DappReady: break; default: break; } } handleRemoteDisconnect(msg) { if (this.disconnectGraceTimer !== null) { clearTimeout(this.disconnectGraceTimer); } this.disconnectGraceTimer = setTimeout(() => { this.disconnectGraceTimer = null; this.stopPingInterval(); this.emit("disconnect", msg.reason, msg.message); }, 8e3); } async handleWalletReady(msg) { if (this.disconnectGraceTimer !== null) { clearTimeout(this.disconnectGraceTimer); this.disconnectGraceTimer = null; } this.lastPongTime = Date.now(); this.walletDiscovered = true; this.walletName = msg.wallet_name; this.walletIcon = msg.wallet_icon; const agreed = this.supportedProtocols.find((p) => msg.supported_protocols.includes(p)); if (!agreed) { const detail = `No protocol overlap. Wallet: [${msg.supported_protocols}], Dapp: [${this.supportedProtocols}]`; const disconnectMsg = { action: RelayMsgAction.Disconnect, reason: DisconnectReason.ProtocolMismatch, message: detail, time: Math.floor(Date.now() / 1e3) }; this.conn?.relay(disconnectMsg).catch(() => { }); this.stopPingInterval(); this.emit("disconnect", DisconnectReason.ProtocolMismatch, detail); return; } this.protocol = agreed; const sessionData = msg.session[agreed]; if (!isHdwalletv1Session(sessionData)) { console.error("[wizardconnect/dapp] Invalid hdwalletv1 session data:", sessionData); return; } if (this.conn) { this.conn.setPeerCapabilities({ chunk: peerSupportsChunk(msg.extensions) }); } this.sessionPaths = [...sessionData.paths]; for (const pathInfo of sessionData.paths) { const decoded = decodeHdPublicKey(pathInfo.xpub); if (typeof decoded === "string") { console.warn("[wizardconnect/dapp] Bad xpub for path", pathInfo.name, decoded); continue; } const ci = childIndexOfPathName(pathInfo.name); if (ci !== void 0) { this.pubkeyState.setXpubNode(ci, decoded.node); } } if (!msg.dapp_discovered) { await this.pushDappReady().catch((e) => console.error("[wizardconnect/dapp] Error pushing dapp_ready:", e)); } this.emit("walletready", msg); if (this.pendingSignatureRequests.size > 0) { const now2 = Math.floor(Date.now() / 1e3); for (const [, entry] of this.pendingSignatureRequests) { const refreshed = { ...entry.request, time: now2 }; this.conn.relay(refreshed).then(() => this.emit("messagesent", refreshed)).catch((err) => { this.pendingSignatureRequests.delete(entry.request.sequence); entry.reject(err instanceof Error ? err : new Error(String(err))); }); } } if (this.sessionOptions) { const sessionUpdate = { walletName: this.walletName ?? void 0, walletIcon: this.walletIcon ?? void 0, paths: this.getSessionPaths() }; saveSession(this.sessionOptions.key, sessionUpdate, this.sessionOptions.storage); } this.startPingInterval(); } handleSignTransactionResponse(response) { const handlers = this.pendingSignatureRequests.get(response.sequence); if (!handlers) { console.warn("[wizardconnect/dapp] No pending request for sequence:", response.sequence); return; } this.pendingSignatureRequests.delete(response.sequence); if (response.error) { handlers.reject(new Error(response.error)); } else { handlers.resolve(response); } } }; } }); // node_modules/@wizardconnect/dapp/dist/index.js var dist_exports2 = {}; __export(dist_exports2, { DEFAULT_SESSION_KEY: () => DEFAULT_SESSION_KEY, DappConnectionManager: () => DappConnectionManager, DappPubkeyStateManager: () => DappPubkeyStateManager, clearSession: () => clearSession, loadSession: () => loadSession, saveSession: () => saveSession }); var init_dist2 = __esm({ "node_modules/@wizardconnect/dapp/dist/index.js"() { init_dapp_connection_manager(); init_pubkey_state_manager(); init_session(); } }); // src/lib/connect/wizardconnect.js var PATHS = { receive: 0, change: 1, defi: 7 }; var ADDRESS_WINDOW = 20; async function openWizardSession({ dappName, dappIcon, prefix = "bchtest", crypto } = {}) { const { pubkeyToAddress, pubkeyToLockingBytecode, binToHex: binToHex6, txidOfHex } = crypto ?? {}; if (!pubkeyToAddress || !pubkeyToLockingBytecode || !binToHex6 || !txidOfHex) { throw new Error( "openWizardSession needs `crypto: { pubkeyToAddress, pubkeyToLockingBytecode, binToHex, txidOfHex }` injected from the main bundle \u2014 see the note at the top of this file" ); } const [{ initiateDappRelay: initiateDappRelay2 }, { DappConnectionManager: DappConnectionManager2 }] = await Promise.all([ Promise.resolve().then(() => (init_dist(), dist_exports)), Promise.resolve().then(() => (init_dist2(), dist_exports2)) ]); const manager = new DappConnectionManager2(dappName, dappIcon); const relay = initiateDappRelay2((payload) => { manager.updateConnection(payload.client, payload.status); }); manager.attachRelay(relay); let resolveReady, rejectReady; const ready = new Promise((res, rej) => { resolveReady = res; rejectReady = rej; }); manager.once("walletready", (msg) => resolveReady({ walletName: msg?.wallet_name ?? null })); manager.once("disconnect", (reason, message) => rejectReady(new Error(`wallet disconnected: ${message ?? reason}`))); const addressAt = (pathName, index) => { const pubkey = manager.getPubkey(PATHS[pathName], BigInt(index)); if (!pubkey) return null; return { pathName, index, publicKey: pubkey, address: pubkeyToAddress(pubkey, prefix, false), tokenAddress: pubkeyToAddress(pubkey, prefix, true), lockingBytecode: pubkeyToLockingBytecode(pubkey) }; }; const derivedAddresses = (window2 = ADDRESS_WINDOW) => { const out = []; for (const pathName of ["receive", "change"]) { if (!manager.hasPath(PATHS[pathName])) continue; for (let i3 = 0; i3 < window2; i3++) { const a = addressAt(pathName, i3); if (a) out.push(a); } } return out; }; return { label: "WizardConnect", protocol: "hdwalletv1", uri: relay.uri, // wiz://?p=…&s=… qrUri: relay.qrUri, // QR-alphanumeric-safe variant ready, manager, // hdwalletv1's `sign_transaction_response` carries ONLY `signedTransaction` // (+ optional `error`) — there is no `signedTransactionHash`, and the wallet // SDK has no broadcast step at all. So the dApp broadcasts, and we ask for // `broadcast: false` to stop a wallet that reads the WC2-shaped payload's // flag from doing it too. The registrar tolerates a duplicate anyway. walletBroadcasts: false, async getAddresses() { if (!manager.isWalletDiscovered()) await ready; return derivedAddresses().map((a) => a.address); }, /** The full derived set, with the HD metadata `inputPaths` needs. */ async getDerivedAddresses(window2) { if (!manager.isWalletDiscovered()) await ready; return derivedAddresses(window2); }, /** * Sign a transaction built by register-tx.js. * * WizardConnect's differentiator is `inputPaths`: rather than the wallet * guessing which key owns each input, we state it — [inputIndex, pathName, * addressIndex]. The wallet re-derives each child key and checks it really * does produce the source output's locking bytecode before signing, so a * wrong triplet is a hard reject rather than a silent mis-sign. * * Note the wallet signs with SIGHASH_ALL|FORKID|UTXOS (stricter than WC2's * ALL|FORKID). That is the wallet's business — our transaction is unchanged. */ async signTransaction(built, { userPrompt } = {}) { if (!manager.isWalletDiscovered()) await ready; const known = new Map(derivedAddresses().map((a) => [binToHex6(a.lockingBytecode), a])); const inputPaths = built.sourceOutputs.map((src, inputIndex) => { const a = known.get(binToHex6(src.lockingBytecode)); if (!a) { throw new Error( `input ${inputIndex} is not from this wallet \u2014 refusing to ask it to sign a coin it does not own` ); } return [inputIndex, a.pathName, a.index]; }); const response = await manager.signTransaction({ transaction: { transaction: built.transaction, sourceOutputs: built.sourceOutputs, broadcast: false, // we broadcast — see `walletBroadcasts` above ...userPrompt ? { userPrompt } : {} }, inputPaths }); if (response?.error) throw new Error(`wallet refused to sign: ${response.error}`); if (!response?.signedTransaction) throw new Error("wallet returned no signed transaction"); return { signedTransaction: response.signedTransaction, // Derived locally: hdwalletv1 does not send the txid back. signedTransactionHash: txidOfHex(response.signedTransaction) }; }, async disconnect() { try { manager.clearStoredSession(); } catch { } try { await manager.sendDisconnect("registration finished"); } catch { } try { manager.destroy(); } catch { } try { relay.cleanup(); } catch { } } }; } export { ADDRESS_WINDOW, PATHS, openWizardSession };