{"version":3,"sources":["jsdelivr-header.js","/npm/kernel/src/channel.ts","/node_modules/@noble/hashes/src/_assert.ts","/node_modules/@noble/hashes/src/crypto.ts","/node_modules/@noble/hashes/src/utils.ts","/node_modules/@noble/hashes/src/_md.ts","/node_modules/@noble/hashes/src/sha256.ts","/node_modules/@noble/curves/src/abstract/utils.ts","/node_modules/@noble/curves/src/abstract/modular.ts","/node_modules/@noble/curves/src/abstract/curve.ts","/node_modules/@noble/curves/src/abstract/weierstrass.ts","/node_modules/@noble/hashes/src/hmac.ts","/node_modules/@noble/curves/src/_shortw_utils.ts","/node_modules/@noble/curves/src/secp256k1.ts","/npm/kernel/src/crypto.ts","/npm/kernel/src/debugLogger.ts","/npm/kernel/src/fetcherBackend.ts","/npm/kernel/src/nostr.ts","/npm/kernel/src/utils.ts","/npm/nostr-fetch@0.17.0/src/relay.ts","/npm/nostr-fetch@0.17.0/src/relayPool.ts","/npm/nostr-fetch@0.17.0/src/fetcherBackend.ts","/npm/nostr-fetch@0.17.0/src/types.ts","/npm/nostr-fetch@0.17.0/src/fetcherHelper.ts","/npm/nostr-fetch@0.17.0/src/fetcher.ts"],"names":[],"mappings":"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","file":"/npm/nostr-fetch@0.17.0/dist/index.mjs/+esm","sourceRoot":"","sourcesContent":["/**\n * Bundled by jsDelivr using Rollup v2.79.2 and Terser v5.39.0.\n * Original file: /npm/nostr-fetch@0.17.0/dist/index.mjs\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","export interface Deferred<T> {\n  resolve(v: T | PromiseLike<T>): void;\n  reject(e?: unknown): void;\n}\n\n// biome-ignore lint/suspicious/noUnsafeDeclarationMerging: this is necessary\nexport class Deferred<T> {\n  promise: Promise<T>;\n  constructor() {\n    this.promise = new Promise((resolve, reject) => {\n      this.resolve = (v) => {\n        resolve(v);\n      };\n      this.reject = (e) => {\n        reject(e);\n      };\n    });\n  }\n}\n\nexport interface ChannelSender<T> {\n  send(v: T): void;\n  error(e: unknown): void;\n  close(): void;\n\n  waitUntilDrained(): Promise<void>;\n  numBufferedItems(): number;\n}\n\ninterface ChannelIter<T> {\n  [Symbol.asyncIterator](): AsyncIterator<T, void, undefined>;\n}\n\nclass ChannelCloseSignal extends Error {\n  constructor() {\n    super(\"channel closed\");\n  }\n}\n\ntype ChannelMakeOptions = {\n  highWaterMark?: number | undefined;\n};\n\nexport class Channel<T> {\n  #sendQ: (() => Promise<T>)[] = [];\n  #recvQ: Deferred<T> | undefined;\n  #closed = false;\n\n  #iterAlreadyStarted = false;\n\n  // backpressure mode related\n  #highWaterMark: number;\n  #drainWaiter: Deferred<void> | undefined;\n\n  private constructor({ highWaterMark = undefined }: ChannelMakeOptions) {\n    this.#highWaterMark = highWaterMark ?? Number.POSITIVE_INFINITY;\n  }\n\n  /**\n   * Makes an asynchronous channel.\n   *\n   * Return a pair of a sender endpoint and an iterator which iterate over items sent to the channel.\n   *\n   * Specifying `highWaterMark` option enables the \"backpressure mode\".\n   * In this mode, a sender can wait until internal queue is free enough.\n   */\n  static make<T>(options?: ChannelMakeOptions): [ChannelSender<T>, ChannelIter<T>] {\n    const c = new Channel<T>(options ?? {});\n    return [c as ChannelSender<T>, c as ChannelIter<T>];\n  }\n\n  send(v: T) {\n    if (this.#recvQ !== undefined) {\n      this.#recvQ.resolve(v);\n      this.#recvQ = undefined;\n      return;\n    }\n    if (this.#closed) {\n      return;\n    }\n    this.#sendQ.push(() => Promise.resolve(v));\n  }\n\n  error(e?: unknown) {\n    if (this.#recvQ !== undefined) {\n      this.#recvQ.reject(e);\n      this.#recvQ = undefined;\n      return;\n    }\n    if (this.#closed) {\n      return;\n    }\n    this.#sendQ.push(() => Promise.reject(e));\n  }\n\n  close() {\n    if (!this.#closed) {\n      this.#closed = true;\n\n      if (this.#recvQ !== undefined) {\n        // cancel reception\n        this.#recvQ.reject(new ChannelCloseSignal());\n        this.#recvQ = undefined;\n      }\n    }\n  }\n\n  waitUntilDrained(): Promise<void> {\n    if (this.#drainWaiter !== undefined) {\n      return this.#drainWaiter.promise;\n    }\n\n    if (this.#sendQ.length <= this.#highWaterMark) {\n      return Promise.resolve();\n    }\n    // sendQ have overflowed -> wait until drained\n    this.#drainWaiter = new Deferred();\n    return this.#drainWaiter.promise;\n  }\n\n  numBufferedItems(): number {\n    return this.#sendQ.length;\n  }\n\n  private get isCompleted(): boolean {\n    return this.#closed && this.#sendQ.length === 0;\n  }\n\n  private recv(): () => Promise<T> {\n    if (this.#sendQ.length > 0) {\n      const next = this.#sendQ.shift() as () => Promise<T>;\n\n      if (this.#drainWaiter !== undefined && this.#sendQ.length <= this.#highWaterMark) {\n        // notify to sender that sendQ have been drained enough\n        this.#drainWaiter.resolve();\n        this.#drainWaiter = undefined;\n      }\n\n      return next;\n    }\n    if (this.#recvQ !== undefined) {\n      return () => Promise.reject(Error(\"Double receive is not allowed\"));\n    }\n    const d = new Deferred<T>();\n    this.#recvQ = d;\n    return () => d.promise;\n  }\n\n  async *[Symbol.asyncIterator]() {\n    if (this.#iterAlreadyStarted) {\n      throw Error(\"Iterating a single channel in multiple location is not allowed\");\n    }\n\n    this.#iterAlreadyStarted = true;\n    while (true) {\n      try {\n        if (this.isCompleted) {\n          break;\n        }\n        yield await this.recv()();\n      } catch (err) {\n        if (err instanceof ChannelCloseSignal) {\n          // closed while awaiting fulfillment of recv queue\n          break;\n        }\n        throw err;\n      }\n    }\n  }\n}\n","function number(n: number) {\n  if (!Number.isSafeInteger(n) || n < 0) throw new Error(`positive integer expected, not ${n}`);\n}\n\nfunction bool(b: boolean) {\n  if (typeof b !== 'boolean') throw new Error(`boolean expected, not ${b}`);\n}\n\n// copied from utils\nexport function isBytes(a: unknown): a is Uint8Array {\n  return (\n    a instanceof Uint8Array ||\n    (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')\n  );\n}\n\nfunction bytes(b: Uint8Array | undefined, ...lengths: number[]) {\n  if (!isBytes(b)) throw new Error('Uint8Array expected');\n  if (lengths.length > 0 && !lengths.includes(b.length))\n    throw new Error(`Uint8Array expected of length ${lengths}, not of length=${b.length}`);\n}\n\ntype Hash = {\n  (data: Uint8Array): Uint8Array;\n  blockLen: number;\n  outputLen: number;\n  create: any;\n};\nfunction hash(h: Hash) {\n  if (typeof h !== 'function' || typeof h.create !== 'function')\n    throw new Error('Hash should be wrapped by utils.wrapConstructor');\n  number(h.outputLen);\n  number(h.blockLen);\n}\n\nfunction exists(instance: any, checkFinished = true) {\n  if (instance.destroyed) throw new Error('Hash instance has been destroyed');\n  if (checkFinished && instance.finished) throw new Error('Hash#digest() has already been called');\n}\nfunction output(out: any, instance: any) {\n  bytes(out);\n  const min = instance.outputLen;\n  if (out.length < min) {\n    throw new Error(`digestInto() expects output buffer of length at least ${min}`);\n  }\n}\n\nexport { number, bool, bytes, hash, exists, output };\n\nconst assert = { number, bool, bytes, hash, exists, output };\nexport default assert;\n","// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// See utils.ts for details.\ndeclare const globalThis: Record<string, any> | undefined;\nexport const crypto =\n  typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;\n","/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n\n// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// node.js versions earlier than v19 don't declare it in global scope.\n// For node.js, package.json#exports field mapping rewrites import\n// from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated (2025-04-30), we can just drop the import.\nimport { crypto } from '@noble/hashes/crypto';\nimport { bytes as abytes } from './_assert.js';\n// export { isBytes } from './_assert.js';\n// We can't reuse isBytes from _assert, because somehow this causes huge perf issues\nexport function isBytes(a: unknown): a is Uint8Array {\n  return (\n    a instanceof Uint8Array ||\n    (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')\n  );\n}\n\n// prettier-ignore\nexport type TypedArray = Int8Array | Uint8ClampedArray | Uint8Array |\n  Uint16Array | Int16Array | Uint32Array | Int32Array;\n\n// Cast array to different type\nexport const u8 = (arr: TypedArray) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\nexport const u32 = (arr: TypedArray) =>\n  new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n\n// Cast array to view\nexport const createView = (arr: TypedArray) =>\n  new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n\n// The rotate right (circular right shift) operation for uint32\nexport const rotr = (word: number, shift: number) => (word << (32 - shift)) | (word >>> shift);\n// The rotate left (circular left shift) operation for uint32\nexport const rotl = (word: number, shift: number) =>\n  (word << shift) | ((word >>> (32 - shift)) >>> 0);\n\nexport const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;\n// The byte swap operation for uint32\nexport const byteSwap = (word: number) =>\n  ((word << 24) & 0xff000000) |\n  ((word << 8) & 0xff0000) |\n  ((word >>> 8) & 0xff00) |\n  ((word >>> 24) & 0xff);\n// Conditionally byte swap if on a big-endian platform\nexport const byteSwapIfBE = isLE ? (n: number) => n : (n: number) => byteSwap(n);\n\n// In place byte swap for Uint32Array\nexport function byteSwap32(arr: Uint32Array) {\n  for (let i = 0; i < arr.length; i++) {\n    arr[i] = byteSwap(arr[i]);\n  }\n}\n\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>\n  i.toString(16).padStart(2, '0')\n);\n/**\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n  abytes(bytes);\n  // pre-caching improves the speed 6x\n  let hex = '';\n  for (let i = 0; i < bytes.length; i++) {\n    hex += hexes[bytes[i]];\n  }\n  return hex;\n}\n\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 } as const;\nfunction asciiToBase16(char: number): number | undefined {\n  if (char >= asciis._0 && char <= asciis._9) return char - asciis._0;\n  if (char >= asciis._A && char <= asciis._F) return char - (asciis._A - 10);\n  if (char >= asciis._a && char <= asciis._f) return char - (asciis._a - 10);\n  return;\n}\n\n/**\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex: string): Uint8Array {\n  if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);\n  const hl = hex.length;\n  const al = hl / 2;\n  if (hl % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + hl);\n  const array = new Uint8Array(al);\n  for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n    const n1 = asciiToBase16(hex.charCodeAt(hi));\n    const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n    if (n1 === undefined || n2 === undefined) {\n      const char = hex[hi] + hex[hi + 1];\n      throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n    }\n    array[ai] = n1 * 16 + n2;\n  }\n  return array;\n}\n\n// There is no setImmediate in browser and setTimeout is slow.\n// call of async fn will return Promise, which will be fullfiled only on\n// next scheduler queue processing step and this is exactly what we need.\nexport const nextTick = async () => {};\n\n// Returns control to thread each 'tick' ms to avoid blocking\nexport async function asyncLoop(iters: number, tick: number, cb: (i: number) => void) {\n  let ts = Date.now();\n  for (let i = 0; i < iters; i++) {\n    cb(i);\n    // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n    const diff = Date.now() - ts;\n    if (diff >= 0 && diff < tick) continue;\n    await nextTick();\n    ts += diff;\n  }\n}\n\n// Global symbols in both browsers and Node.js since v11\n// See https://github.com/microsoft/TypeScript/issues/31535\ndeclare const TextEncoder: any;\n\n/**\n * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])\n */\nexport function utf8ToBytes(str: string): Uint8Array {\n  if (typeof str !== 'string') throw new Error(`utf8ToBytes expected string, got ${typeof str}`);\n  return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n\nexport type Input = Uint8Array | string;\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data: Input): Uint8Array {\n  if (typeof data === 'string') data = utf8ToBytes(data);\n  abytes(data);\n  return data;\n}\n\n/**\n * Copies several Uint8Arrays into one.\n */\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\n  let sum = 0;\n  for (let i = 0; i < arrays.length; i++) {\n    const a = arrays[i];\n    abytes(a);\n    sum += a.length;\n  }\n  const res = new Uint8Array(sum);\n  for (let i = 0, pad = 0; i < arrays.length; i++) {\n    const a = arrays[i];\n    res.set(a, pad);\n    pad += a.length;\n  }\n  return res;\n}\n\n// For runtime check if class implements interface\nexport abstract class Hash<T extends Hash<T>> {\n  abstract blockLen: number; // Bytes per block\n  abstract outputLen: number; // Bytes in output\n  abstract update(buf: Input): this;\n  // Writes digest into buf\n  abstract digestInto(buf: Uint8Array): void;\n  abstract digest(): Uint8Array;\n  /**\n   * Resets internal state. Makes Hash instance unusable.\n   * Reset is impossible for keyed hashes if key is consumed into state. If digest is not consumed\n   * by user, they will need to manually call `destroy()` when zeroing is necessary.\n   */\n  abstract destroy(): void;\n  /**\n   * Clones hash instance. Unsafe: doesn't check whether `to` is valid. Can be used as `clone()`\n   * when no options are passed.\n   * Reasons to use `_cloneInto` instead of clone: 1) performance 2) reuse instance => all internal\n   * buffers are overwritten => causes buffer overwrite which is used for digest in some cases.\n   * There are no guarantees for clean-up because it's impossible in JS.\n   */\n  abstract _cloneInto(to?: T): T;\n  // Safe version that clones internal state\n  clone(): T {\n    return this._cloneInto();\n  }\n}\n\n/**\n * XOF: streaming API to read digest in chunks.\n * Same as 'squeeze' in keccak/k12 and 'seek' in blake3, but more generic name.\n * When hash used in XOF mode it is up to user to call '.destroy' afterwards, since we cannot\n * destroy state, next call can require more bytes.\n */\nexport type HashXOF<T extends Hash<T>> = Hash<T> & {\n  xof(bytes: number): Uint8Array; // Read 'bytes' bytes from digest stream\n  xofInto(buf: Uint8Array): Uint8Array; // read buf.length bytes from digest stream into buf\n};\n\nconst toStr = {}.toString;\ntype EmptyObj = {};\nexport function checkOpts<T1 extends EmptyObj, T2 extends EmptyObj>(\n  defaults: T1,\n  opts?: T2\n): T1 & T2 {\n  if (opts !== undefined && toStr.call(opts) !== '[object Object]')\n    throw new Error('Options should be object or undefined');\n  const merged = Object.assign(defaults, opts);\n  return merged as T1 & T2;\n}\n\nexport type CHash = ReturnType<typeof wrapConstructor>;\n\nexport function wrapConstructor<T extends Hash<T>>(hashCons: () => Hash<T>) {\n  const hashC = (msg: Input): Uint8Array => hashCons().update(toBytes(msg)).digest();\n  const tmp = hashCons();\n  hashC.outputLen = tmp.outputLen;\n  hashC.blockLen = tmp.blockLen;\n  hashC.create = () => hashCons();\n  return hashC;\n}\n\nexport function wrapConstructorWithOpts<H extends Hash<H>, T extends Object>(\n  hashCons: (opts?: T) => Hash<H>\n) {\n  const hashC = (msg: Input, opts?: T): Uint8Array => hashCons(opts).update(toBytes(msg)).digest();\n  const tmp = hashCons({} as T);\n  hashC.outputLen = tmp.outputLen;\n  hashC.blockLen = tmp.blockLen;\n  hashC.create = (opts: T) => hashCons(opts);\n  return hashC;\n}\n\nexport function wrapXOFConstructorWithOpts<H extends HashXOF<H>, T extends Object>(\n  hashCons: (opts?: T) => HashXOF<H>\n) {\n  const hashC = (msg: Input, opts?: T): Uint8Array => hashCons(opts).update(toBytes(msg)).digest();\n  const tmp = hashCons({} as T);\n  hashC.outputLen = tmp.outputLen;\n  hashC.blockLen = tmp.blockLen;\n  hashC.create = (opts: T) => hashCons(opts);\n  return hashC;\n}\n\n/**\n * Secure PRNG. Uses `crypto.getRandomValues`, which defers to OS.\n */\nexport function randomBytes(bytesLength = 32): Uint8Array {\n  if (crypto && typeof crypto.getRandomValues === 'function') {\n    return crypto.getRandomValues(new Uint8Array(bytesLength));\n  }\n  throw new Error('crypto.getRandomValues must be defined');\n}\n","import { exists, output } from './_assert.js';\nimport { Hash, createView, Input, toBytes } from './utils.js';\n\n// Polyfill for Safari 14\nfunction setBigUint64(view: DataView, byteOffset: number, value: bigint, isLE: boolean): void {\n  if (typeof view.setBigUint64 === 'function') return view.setBigUint64(byteOffset, value, isLE);\n  const _32n = BigInt(32);\n  const _u32_max = BigInt(0xffffffff);\n  const wh = Number((value >> _32n) & _u32_max);\n  const wl = Number(value & _u32_max);\n  const h = isLE ? 4 : 0;\n  const l = isLE ? 0 : 4;\n  view.setUint32(byteOffset + h, wh, isLE);\n  view.setUint32(byteOffset + l, wl, isLE);\n}\n\n// Choice: a ? b : c\nexport const Chi = (a: number, b: number, c: number) => (a & b) ^ (~a & c);\n// Majority function, true if any two inpust is true\nexport const Maj = (a: number, b: number, c: number) => (a & b) ^ (a & c) ^ (b & c);\n\n/**\n * Merkle-Damgard hash construction base class.\n * Could be used to create MD5, RIPEMD, SHA1, SHA2.\n */\nexport abstract class HashMD<T extends HashMD<T>> extends Hash<T> {\n  protected abstract process(buf: DataView, offset: number): void;\n  protected abstract get(): number[];\n  protected abstract set(...args: number[]): void;\n  abstract destroy(): void;\n  protected abstract roundClean(): void;\n  // For partial updates less than block size\n  protected buffer: Uint8Array;\n  protected view: DataView;\n  protected finished = false;\n  protected length = 0;\n  protected pos = 0;\n  protected destroyed = false;\n\n  constructor(\n    readonly blockLen: number,\n    public outputLen: number,\n    readonly padOffset: number,\n    readonly isLE: boolean\n  ) {\n    super();\n    this.buffer = new Uint8Array(blockLen);\n    this.view = createView(this.buffer);\n  }\n  update(data: Input): this {\n    exists(this);\n    const { view, buffer, blockLen } = this;\n    data = toBytes(data);\n    const len = data.length;\n    for (let pos = 0; pos < len; ) {\n      const take = Math.min(blockLen - this.pos, len - pos);\n      // Fast path: we have at least one block in input, cast it to view and process\n      if (take === blockLen) {\n        const dataView = createView(data);\n        for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos);\n        continue;\n      }\n      buffer.set(data.subarray(pos, pos + take), this.pos);\n      this.pos += take;\n      pos += take;\n      if (this.pos === blockLen) {\n        this.process(view, 0);\n        this.pos = 0;\n      }\n    }\n    this.length += data.length;\n    this.roundClean();\n    return this;\n  }\n  digestInto(out: Uint8Array) {\n    exists(this);\n    output(out, this);\n    this.finished = true;\n    // Padding\n    // We can avoid allocation of buffer for padding completely if it\n    // was previously not allocated here. But it won't change performance.\n    const { buffer, view, blockLen, isLE } = this;\n    let { pos } = this;\n    // append the bit '1' to the message\n    buffer[pos++] = 0b10000000;\n    this.buffer.subarray(pos).fill(0);\n    // we have less than padOffset left in buffer, so we cannot put length in\n    // current block, need process it and pad again\n    if (this.padOffset > blockLen - pos) {\n      this.process(view, 0);\n      pos = 0;\n    }\n    // Pad until full block byte with zeros\n    for (let i = pos; i < blockLen; i++) buffer[i] = 0;\n    // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that\n    // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.\n    // So we just write lowest 64 bits of that value.\n    setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);\n    this.process(view, 0);\n    const oview = createView(out);\n    const len = this.outputLen;\n    // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT\n    if (len % 4) throw new Error('_sha2: outputLen should be aligned to 32bit');\n    const outLen = len / 4;\n    const state = this.get();\n    if (outLen > state.length) throw new Error('_sha2: outputLen bigger than state');\n    for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE);\n  }\n  digest() {\n    const { buffer, outputLen } = this;\n    this.digestInto(buffer);\n    const res = buffer.slice(0, outputLen);\n    this.destroy();\n    return res;\n  }\n  _cloneInto(to?: T): T {\n    to ||= new (this.constructor as any)() as T;\n    to.set(...this.get());\n    const { blockLen, buffer, length, finished, destroyed, pos } = this;\n    to.length = length;\n    to.pos = pos;\n    to.finished = finished;\n    to.destroyed = destroyed;\n    if (length % blockLen) to.buffer.set(buffer);\n    return to;\n  }\n}\n","import { HashMD, Chi, Maj } from './_md.js';\nimport { rotr, wrapConstructor } from './utils.js';\n\n// SHA2-256 need to try 2^128 hashes to execute birthday attack.\n// BTC network is doing 2^67 hashes/sec as per early 2023.\n\n// Round constants:\n// first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)\n// prettier-ignore\nconst SHA256_K = /* @__PURE__ */ new Uint32Array([\n  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n]);\n\n// Initial state:\n// first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19\n// prettier-ignore\nconst SHA256_IV = /* @__PURE__ */ new Uint32Array([\n  0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19\n]);\n\n// Temporary buffer, not used to store anything between runs\n// Named this way because it matches specification.\nconst SHA256_W = /* @__PURE__ */ new Uint32Array(64);\nclass SHA256 extends HashMD<SHA256> {\n  // We cannot use array here since array allows indexing by variable\n  // which means optimizer/compiler cannot use registers.\n  A = SHA256_IV[0] | 0;\n  B = SHA256_IV[1] | 0;\n  C = SHA256_IV[2] | 0;\n  D = SHA256_IV[3] | 0;\n  E = SHA256_IV[4] | 0;\n  F = SHA256_IV[5] | 0;\n  G = SHA256_IV[6] | 0;\n  H = SHA256_IV[7] | 0;\n\n  constructor() {\n    super(64, 32, 8, false);\n  }\n  protected get(): [number, number, number, number, number, number, number, number] {\n    const { A, B, C, D, E, F, G, H } = this;\n    return [A, B, C, D, E, F, G, H];\n  }\n  // prettier-ignore\n  protected set(\n    A: number, B: number, C: number, D: number, E: number, F: number, G: number, H: number\n  ) {\n    this.A = A | 0;\n    this.B = B | 0;\n    this.C = C | 0;\n    this.D = D | 0;\n    this.E = E | 0;\n    this.F = F | 0;\n    this.G = G | 0;\n    this.H = H | 0;\n  }\n  protected process(view: DataView, offset: number): void {\n    // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array\n    for (let i = 0; i < 16; i++, offset += 4) SHA256_W[i] = view.getUint32(offset, false);\n    for (let i = 16; i < 64; i++) {\n      const W15 = SHA256_W[i - 15];\n      const W2 = SHA256_W[i - 2];\n      const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);\n      const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);\n      SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;\n    }\n    // Compression function main loop, 64 rounds\n    let { A, B, C, D, E, F, G, H } = this;\n    for (let i = 0; i < 64; i++) {\n      const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);\n      const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n      const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);\n      const T2 = (sigma0 + Maj(A, B, C)) | 0;\n      H = G;\n      G = F;\n      F = E;\n      E = (D + T1) | 0;\n      D = C;\n      C = B;\n      B = A;\n      A = (T1 + T2) | 0;\n    }\n    // Add the compressed chunk to the current hash value\n    A = (A + this.A) | 0;\n    B = (B + this.B) | 0;\n    C = (C + this.C) | 0;\n    D = (D + this.D) | 0;\n    E = (E + this.E) | 0;\n    F = (F + this.F) | 0;\n    G = (G + this.G) | 0;\n    H = (H + this.H) | 0;\n    this.set(A, B, C, D, E, F, G, H);\n  }\n  protected roundClean() {\n    SHA256_W.fill(0);\n  }\n  destroy() {\n    this.set(0, 0, 0, 0, 0, 0, 0, 0);\n    this.buffer.fill(0);\n  }\n}\n// Constants from https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf\nclass SHA224 extends SHA256 {\n  A = 0xc1059ed8 | 0;\n  B = 0x367cd507 | 0;\n  C = 0x3070dd17 | 0;\n  D = 0xf70e5939 | 0;\n  E = 0xffc00b31 | 0;\n  F = 0x68581511 | 0;\n  G = 0x64f98fa7 | 0;\n  H = 0xbefa4fa4 | 0;\n  constructor() {\n    super();\n    this.outputLen = 28;\n  }\n}\n\n/**\n * SHA2-256 hash function\n * @param message - data that would be hashed\n */\nexport const sha256 = /* @__PURE__ */ wrapConstructor(() => new SHA256());\nexport const sha224 = /* @__PURE__ */ wrapConstructor(() => new SHA224());\n","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// 100 lines of code in the file are duplicated from noble-hashes (utils).\n// This is OK: `abstract` directory does not use noble-hashes.\n// User may opt-in into using different hashing library. This way, noble-hashes\n// won't be included into their bundle.\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nexport type Hex = Uint8Array | string; // hex strings are accepted for simplicity\nexport type PrivKey = Hex | bigint; // bigints are accepted to ease learning curve\nexport type CHash = {\n  (message: Uint8Array | string): Uint8Array;\n  blockLen: number;\n  outputLen: number;\n  create(opts?: { dkLen?: number }): any; // For shake\n};\nexport type FHash = (message: Uint8Array | string) => Uint8Array;\n\nexport function isBytes(a: unknown): a is Uint8Array {\n  return (\n    a instanceof Uint8Array ||\n    (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')\n  );\n}\n\nexport function abytes(item: unknown): void {\n  if (!isBytes(item)) throw new Error('Uint8Array expected');\n}\n\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>\n  i.toString(16).padStart(2, '0')\n);\n/**\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n  abytes(bytes);\n  // pre-caching improves the speed 6x\n  let hex = '';\n  for (let i = 0; i < bytes.length; i++) {\n    hex += hexes[bytes[i]];\n  }\n  return hex;\n}\n\nexport function numberToHexUnpadded(num: number | bigint): string {\n  const hex = num.toString(16);\n  return hex.length & 1 ? `0${hex}` : hex;\n}\n\nexport function hexToNumber(hex: string): bigint {\n  if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);\n  // Big Endian\n  return BigInt(hex === '' ? '0' : `0x${hex}`);\n}\n\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 } as const;\nfunction asciiToBase16(char: number): number | undefined {\n  if (char >= asciis._0 && char <= asciis._9) return char - asciis._0;\n  if (char >= asciis._A && char <= asciis._F) return char - (asciis._A - 10);\n  if (char >= asciis._a && char <= asciis._f) return char - (asciis._a - 10);\n  return;\n}\n\n/**\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex: string): Uint8Array {\n  if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);\n  const hl = hex.length;\n  const al = hl / 2;\n  if (hl % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + hl);\n  const array = new Uint8Array(al);\n  for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n    const n1 = asciiToBase16(hex.charCodeAt(hi));\n    const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n    if (n1 === undefined || n2 === undefined) {\n      const char = hex[hi] + hex[hi + 1];\n      throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n    }\n    array[ai] = n1 * 16 + n2;\n  }\n  return array;\n}\n\n// BE: Big Endian, LE: Little Endian\nexport function bytesToNumberBE(bytes: Uint8Array): bigint {\n  return hexToNumber(bytesToHex(bytes));\n}\nexport function bytesToNumberLE(bytes: Uint8Array): bigint {\n  abytes(bytes);\n  return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));\n}\n\nexport function numberToBytesBE(n: number | bigint, len: number): Uint8Array {\n  return hexToBytes(n.toString(16).padStart(len * 2, '0'));\n}\nexport function numberToBytesLE(n: number | bigint, len: number): Uint8Array {\n  return numberToBytesBE(n, len).reverse();\n}\n// Unpadded, rarely used\nexport function numberToVarBytesBE(n: number | bigint): Uint8Array {\n  return hexToBytes(numberToHexUnpadded(n));\n}\n\n/**\n * Takes hex string or Uint8Array, converts to Uint8Array.\n * Validates output length.\n * Will throw error for other types.\n * @param title descriptive title for an error e.g. 'private key'\n * @param hex hex string or Uint8Array\n * @param expectedLength optional, will compare to result array's length\n * @returns\n */\nexport function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array {\n  let res: Uint8Array;\n  if (typeof hex === 'string') {\n    try {\n      res = hexToBytes(hex);\n    } catch (e) {\n      throw new Error(`${title} must be valid hex string, got \"${hex}\". Cause: ${e}`);\n    }\n  } else if (isBytes(hex)) {\n    // Uint8Array.from() instead of hash.slice() because node.js Buffer\n    // is instance of Uint8Array, and its slice() creates **mutable** copy\n    res = Uint8Array.from(hex);\n  } else {\n    throw new Error(`${title} must be hex string or Uint8Array`);\n  }\n  const len = res.length;\n  if (typeof expectedLength === 'number' && len !== expectedLength)\n    throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);\n  return res;\n}\n\n/**\n * Copies several Uint8Arrays into one.\n */\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\n  let sum = 0;\n  for (let i = 0; i < arrays.length; i++) {\n    const a = arrays[i];\n    abytes(a);\n    sum += a.length;\n  }\n  const res = new Uint8Array(sum);\n  for (let i = 0, pad = 0; i < arrays.length; i++) {\n    const a = arrays[i];\n    res.set(a, pad);\n    pad += a.length;\n  }\n  return res;\n}\n\n// Compares 2 u8a-s in kinda constant time\nexport function equalBytes(a: Uint8Array, b: Uint8Array) {\n  if (a.length !== b.length) return false;\n  let diff = 0;\n  for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];\n  return diff === 0;\n}\n\n// Global symbols in both browsers and Node.js since v11\n// See https://github.com/microsoft/TypeScript/issues/31535\ndeclare const TextEncoder: any;\n\n/**\n * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])\n */\nexport function utf8ToBytes(str: string): Uint8Array {\n  if (typeof str !== 'string') throw new Error(`utf8ToBytes expected string, got ${typeof str}`);\n  return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n\n// Bit operations\n\n/**\n * Calculates amount of bits in a bigint.\n * Same as `n.toString(2).length`\n */\nexport function bitLen(n: bigint) {\n  let len;\n  for (len = 0; n > _0n; n >>= _1n, len += 1);\n  return len;\n}\n\n/**\n * Gets single bit at position.\n * NOTE: first bit position is 0 (same as arrays)\n * Same as `!!+Array.from(n.toString(2)).reverse()[pos]`\n */\nexport function bitGet(n: bigint, pos: number) {\n  return (n >> BigInt(pos)) & _1n;\n}\n\n/**\n * Sets single bit at position.\n */\nexport function bitSet(n: bigint, pos: number, value: boolean) {\n  return n | ((value ? _1n : _0n) << BigInt(pos));\n}\n\n/**\n * Calculate mask for N bits. Not using ** operator with bigints because of old engines.\n * Same as BigInt(`0b${Array(i).fill('1').join('')}`)\n */\nexport const bitMask = (n: number) => (_2n << BigInt(n - 1)) - _1n;\n\n// DRBG\n\nconst u8n = (data?: any) => new Uint8Array(data); // creates Uint8Array\nconst u8fr = (arr: any) => Uint8Array.from(arr); // another shortcut\ntype Pred<T> = (v: Uint8Array) => T | undefined;\n/**\n * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.\n * @returns function that will call DRBG until 2nd arg returns something meaningful\n * @example\n *   const drbg = createHmacDRBG<Key>(32, 32, hmac);\n *   drbg(seed, bytesToKey); // bytesToKey must return Key or undefined\n */\nexport function createHmacDrbg<T>(\n  hashLen: number,\n  qByteLen: number,\n  hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array\n): (seed: Uint8Array, predicate: Pred<T>) => T {\n  if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number');\n  if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number');\n  if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function');\n  // Step B, Step C: set hashLen to 8*ceil(hlen/8)\n  let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.\n  let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same\n  let i = 0; // Iterations counter, will throw when over 1000\n  const reset = () => {\n    v.fill(1);\n    k.fill(0);\n    i = 0;\n  };\n  const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)\n  const reseed = (seed = u8n()) => {\n    // HMAC-DRBG reseed() function. Steps D-G\n    k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)\n    v = h(); // v = hmac(k || v)\n    if (seed.length === 0) return;\n    k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)\n    v = h(); // v = hmac(k || v)\n  };\n  const gen = () => {\n    // HMAC-DRBG generate() function\n    if (i++ >= 1000) throw new Error('drbg: tried 1000 values');\n    let len = 0;\n    const out: Uint8Array[] = [];\n    while (len < qByteLen) {\n      v = h();\n      const sl = v.slice();\n      out.push(sl);\n      len += v.length;\n    }\n    return concatBytes(...out);\n  };\n  const genUntil = (seed: Uint8Array, pred: Pred<T>): T => {\n    reset();\n    reseed(seed); // Steps D-G\n    let res: T | undefined = undefined; // Step H: grind until k is in [1..n-1]\n    while (!(res = pred(gen()))) reseed();\n    reset();\n    return res;\n  };\n  return genUntil;\n}\n\n// Validating curves and fields\n\nconst validatorFns = {\n  bigint: (val: any) => typeof val === 'bigint',\n  function: (val: any) => typeof val === 'function',\n  boolean: (val: any) => typeof val === 'boolean',\n  string: (val: any) => typeof val === 'string',\n  stringOrUint8Array: (val: any) => typeof val === 'string' || isBytes(val),\n  isSafeInteger: (val: any) => Number.isSafeInteger(val),\n  array: (val: any) => Array.isArray(val),\n  field: (val: any, object: any) => (object as any).Fp.isValid(val),\n  hash: (val: any) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),\n} as const;\ntype Validator = keyof typeof validatorFns;\ntype ValMap<T extends Record<string, any>> = { [K in keyof T]?: Validator };\n// type Record<K extends string | number | symbol, T> = { [P in K]: T; }\n\nexport function validateObject<T extends Record<string, any>>(\n  object: T,\n  validators: ValMap<T>,\n  optValidators: ValMap<T> = {}\n) {\n  const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => {\n    const checkVal = validatorFns[type];\n    if (typeof checkVal !== 'function')\n      throw new Error(`Invalid validator \"${type}\", expected function`);\n\n    const val = object[fieldName as keyof typeof object];\n    if (isOptional && val === undefined) return;\n    if (!checkVal(val, object)) {\n      throw new Error(\n        `Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`\n      );\n    }\n  };\n  for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type!, false);\n  for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type!, true);\n  return object;\n}\n// validate type tests\n// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };\n// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!\n// // Should fail type-check\n// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });\n// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });\n// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });\n// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });\n","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Utilities for modular arithmetics and finite fields\nimport {\n  bitMask,\n  numberToBytesBE,\n  numberToBytesLE,\n  bytesToNumberBE,\n  bytesToNumberLE,\n  ensureBytes,\n  validateObject,\n} from './utils.js';\n// prettier-ignore\nconst _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);\n// prettier-ignore\nconst _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);\n// prettier-ignore\nconst _9n = BigInt(9), _16n = BigInt(16);\n\n// Calculates a modulo b\nexport function mod(a: bigint, b: bigint): bigint {\n  const result = a % b;\n  return result >= _0n ? result : b + result;\n}\n/**\n * Efficiently raise num to power and do modular division.\n * Unsafe in some contexts: uses ladder, so can expose bigint bits.\n * @example\n * pow(2n, 6n, 11n) // 64n % 11n == 9n\n */\n// TODO: use field version && remove\nexport function pow(num: bigint, power: bigint, modulo: bigint): bigint {\n  if (modulo <= _0n || power < _0n) throw new Error('Expected power/modulo > 0');\n  if (modulo === _1n) return _0n;\n  let res = _1n;\n  while (power > _0n) {\n    if (power & _1n) res = (res * num) % modulo;\n    num = (num * num) % modulo;\n    power >>= _1n;\n  }\n  return res;\n}\n\n// Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)\nexport function pow2(x: bigint, power: bigint, modulo: bigint): bigint {\n  let res = x;\n  while (power-- > _0n) {\n    res *= res;\n    res %= modulo;\n  }\n  return res;\n}\n\n// Inverses number over modulo\nexport function invert(number: bigint, modulo: bigint): bigint {\n  if (number === _0n || modulo <= _0n) {\n    throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);\n  }\n  // Euclidean GCD https://brilliant.org/wiki/extended-euclidean-algorithm/\n  // Fermat's little theorem \"CT-like\" version inv(n) = n^(m-2) mod m is 30x slower.\n  let a = mod(number, modulo);\n  let b = modulo;\n  // prettier-ignore\n  let x = _0n, y = _1n, u = _1n, v = _0n;\n  while (a !== _0n) {\n    // JIT applies optimization if those two lines follow each other\n    const q = b / a;\n    const r = b % a;\n    const m = x - u * q;\n    const n = y - v * q;\n    // prettier-ignore\n    b = a, a = r, x = u, y = v, u = m, v = n;\n  }\n  const gcd = b;\n  if (gcd !== _1n) throw new Error('invert: does not exist');\n  return mod(x, modulo);\n}\n\n/**\n * Tonelli-Shanks square root search algorithm.\n * 1. https://eprint.iacr.org/2012/685.pdf (page 12)\n * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks\n * Will start an infinite loop if field order P is not prime.\n * @param P field order\n * @returns function that takes field Fp (created from P) and number n\n */\nexport function tonelliShanks(P: bigint) {\n  // Legendre constant: used to calculate Legendre symbol (a | p),\n  // which denotes the value of a^((p-1)/2) (mod p).\n  // (a | p) ≡ 1    if a is a square (mod p)\n  // (a | p) ≡ -1   if a is not a square (mod p)\n  // (a | p) ≡ 0    if a ≡ 0 (mod p)\n  const legendreC = (P - _1n) / _2n;\n\n  let Q: bigint, S: number, Z: bigint;\n  // Step 1: By factoring out powers of 2 from p - 1,\n  // find q and s such that p - 1 = q*(2^s) with q odd\n  for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++);\n\n  // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq\n  for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++);\n\n  // Fast-path\n  if (S === 1) {\n    const p1div4 = (P + _1n) / _4n;\n    return function tonelliFast<T>(Fp: IField<T>, n: T) {\n      const root = Fp.pow(n, p1div4);\n      if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root');\n      return root;\n    };\n  }\n\n  // Slow-path\n  const Q1div2 = (Q + _1n) / _2n;\n  return function tonelliSlow<T>(Fp: IField<T>, n: T): T {\n    // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1\n    if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root');\n    let r = S;\n    // TODO: will fail at Fp2/etc\n    let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q); // will update both x and b\n    let x = Fp.pow(n, Q1div2); // first guess at the square root\n    let b = Fp.pow(n, Q); // first guess at the fudge factor\n\n    while (!Fp.eql(b, Fp.ONE)) {\n      if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO; // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0)\n      // Find m such b^(2^m)==1\n      let m = 1;\n      for (let t2 = Fp.sqr(b); m < r; m++) {\n        if (Fp.eql(t2, Fp.ONE)) break;\n        t2 = Fp.sqr(t2); // t2 *= t2\n      }\n      // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow\n      const ge = Fp.pow(g, _1n << BigInt(r - m - 1)); // ge = 2^(r-m-1)\n      g = Fp.sqr(ge); // g = ge * ge\n      x = Fp.mul(x, ge); // x *= ge\n      b = Fp.mul(b, g); // b *= g\n      r = m;\n    }\n    return x;\n  };\n}\n\nexport function FpSqrt(P: bigint) {\n  // NOTE: different algorithms can give different roots, it is up to user to decide which one they want.\n  // For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).\n\n  // P ≡ 3 (mod 4)\n  // √n = n^((P+1)/4)\n  if (P % _4n === _3n) {\n    // Not all roots possible!\n    // const ORDER =\n    //   0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;\n    // const NUM = 72057594037927816n;\n    const p1div4 = (P + _1n) / _4n;\n    return function sqrt3mod4<T>(Fp: IField<T>, n: T) {\n      const root = Fp.pow(n, p1div4);\n      // Throw if root**2 != n\n      if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root');\n      return root;\n    };\n  }\n\n  // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10)\n  if (P % _8n === _5n) {\n    const c1 = (P - _5n) / _8n;\n    return function sqrt5mod8<T>(Fp: IField<T>, n: T) {\n      const n2 = Fp.mul(n, _2n);\n      const v = Fp.pow(n2, c1);\n      const nv = Fp.mul(n, v);\n      const i = Fp.mul(Fp.mul(nv, _2n), v);\n      const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));\n      if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root');\n      return root;\n    };\n  }\n\n  // P ≡ 9 (mod 16)\n  if (P % _16n === _9n) {\n    // NOTE: tonelli is too slow for bls-Fp2 calculations even on start\n    // Means we cannot use sqrt for constants at all!\n    //\n    // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); //  1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F\n    // const c2 = Fp.sqrt(c1);                //  2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F\n    // const c3 = Fp.sqrt(Fp.negate(c1));     //  3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F\n    // const c4 = (P + _7n) / _16n;           //  4. c4 = (q + 7) / 16        # Integer arithmetic\n    // sqrt = (x) => {\n    //   let tv1 = Fp.pow(x, c4);             //  1. tv1 = x^c4\n    //   let tv2 = Fp.mul(c1, tv1);           //  2. tv2 = c1 * tv1\n    //   const tv3 = Fp.mul(c2, tv1);         //  3. tv3 = c2 * tv1\n    //   let tv4 = Fp.mul(c3, tv1);           //  4. tv4 = c3 * tv1\n    //   const e1 = Fp.equals(Fp.square(tv2), x); //  5.  e1 = (tv2^2) == x\n    //   const e2 = Fp.equals(Fp.square(tv3), x); //  6.  e2 = (tv3^2) == x\n    //   tv1 = Fp.cmov(tv1, tv2, e1); //  7. tv1 = CMOV(tv1, tv2, e1)  # Select tv2 if (tv2^2) == x\n    //   tv2 = Fp.cmov(tv4, tv3, e2); //  8. tv2 = CMOV(tv4, tv3, e2)  # Select tv3 if (tv3^2) == x\n    //   const e3 = Fp.equals(Fp.square(tv2), x); //  9.  e3 = (tv2^2) == x\n    //   return Fp.cmov(tv1, tv2, e3); //  10.  z = CMOV(tv1, tv2, e3)  # Select the sqrt from tv1 and tv2\n    // }\n  }\n\n  // Other cases: Tonelli-Shanks algorithm\n  return tonelliShanks(P);\n}\n\n// Little-endian check for first LE bit (last BE bit);\nexport const isNegativeLE = (num: bigint, modulo: bigint) => (mod(num, modulo) & _1n) === _1n;\n\n// Field is not always over prime: for example, Fp2 has ORDER(q)=p^m\nexport interface IField<T> {\n  ORDER: bigint;\n  BYTES: number;\n  BITS: number;\n  MASK: bigint;\n  ZERO: T;\n  ONE: T;\n  // 1-arg\n  create: (num: T) => T;\n  isValid: (num: T) => boolean;\n  is0: (num: T) => boolean;\n  neg(num: T): T;\n  inv(num: T): T;\n  sqrt(num: T): T;\n  sqr(num: T): T;\n  // 2-args\n  eql(lhs: T, rhs: T): boolean;\n  add(lhs: T, rhs: T): T;\n  sub(lhs: T, rhs: T): T;\n  mul(lhs: T, rhs: T | bigint): T;\n  pow(lhs: T, power: bigint): T;\n  div(lhs: T, rhs: T | bigint): T;\n  // N for NonNormalized (for now)\n  addN(lhs: T, rhs: T): T;\n  subN(lhs: T, rhs: T): T;\n  mulN(lhs: T, rhs: T | bigint): T;\n  sqrN(num: T): T;\n\n  // Optional\n  // Should be same as sgn0 function in\n  // [RFC9380](https://www.rfc-editor.org/rfc/rfc9380#section-4.1).\n  // NOTE: sgn0 is 'negative in LE', which is same as odd. And negative in LE is kinda strange definition anyway.\n  isOdd?(num: T): boolean; // Odd instead of even since we have it for Fp2\n  // legendre?(num: T): T;\n  pow(lhs: T, power: bigint): T;\n  invertBatch: (lst: T[]) => T[];\n  toBytes(num: T): Uint8Array;\n  fromBytes(bytes: Uint8Array): T;\n  // If c is False, CMOV returns a, otherwise it returns b.\n  cmov(a: T, b: T, c: boolean): T;\n}\n// prettier-ignore\nconst FIELD_FIELDS = [\n  'create', 'isValid', 'is0', 'neg', 'inv', 'sqrt', 'sqr',\n  'eql', 'add', 'sub', 'mul', 'pow', 'div',\n  'addN', 'subN', 'mulN', 'sqrN'\n] as const;\nexport function validateField<T>(field: IField<T>) {\n  const initial = {\n    ORDER: 'bigint',\n    MASK: 'bigint',\n    BYTES: 'isSafeInteger',\n    BITS: 'isSafeInteger',\n  } as Record<string, string>;\n  const opts = FIELD_FIELDS.reduce((map, val: string) => {\n    map[val] = 'function';\n    return map;\n  }, initial);\n  return validateObject(field, opts);\n}\n\n// Generic field functions\n\n/**\n * Same as `pow` but for Fp: non-constant-time.\n * Unsafe in some contexts: uses ladder, so can expose bigint bits.\n */\nexport function FpPow<T>(f: IField<T>, num: T, power: bigint): T {\n  // Should have same speed as pow for bigints\n  // TODO: benchmark!\n  if (power < _0n) throw new Error('Expected power > 0');\n  if (power === _0n) return f.ONE;\n  if (power === _1n) return num;\n  let p = f.ONE;\n  let d = num;\n  while (power > _0n) {\n    if (power & _1n) p = f.mul(p, d);\n    d = f.sqr(d);\n    power >>= _1n;\n  }\n  return p;\n}\n\n/**\n * Efficiently invert an array of Field elements.\n * `inv(0)` will return `undefined` here: make sure to throw an error.\n */\nexport function FpInvertBatch<T>(f: IField<T>, nums: T[]): T[] {\n  const tmp = new Array(nums.length);\n  // Walk from first to last, multiply them by each other MOD p\n  const lastMultiplied = nums.reduce((acc, num, i) => {\n    if (f.is0(num)) return acc;\n    tmp[i] = acc;\n    return f.mul(acc, num);\n  }, f.ONE);\n  // Invert last element\n  const inverted = f.inv(lastMultiplied);\n  // Walk from last to first, multiply them by inverted each other MOD p\n  nums.reduceRight((acc, num, i) => {\n    if (f.is0(num)) return acc;\n    tmp[i] = f.mul(acc, tmp[i]);\n    return f.mul(acc, num);\n  }, inverted);\n  return tmp;\n}\n\nexport function FpDiv<T>(f: IField<T>, lhs: T, rhs: T | bigint): T {\n  return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs));\n}\n\n// This function returns True whenever the value x is a square in the field F.\nexport function FpIsSquare<T>(f: IField<T>) {\n  const legendreConst = (f.ORDER - _1n) / _2n; // Integer arithmetic\n  return (x: T): boolean => {\n    const p = f.pow(x, legendreConst);\n    return f.eql(p, f.ZERO) || f.eql(p, f.ONE);\n  };\n}\n\n// CURVE.n lengths\nexport function nLength(n: bigint, nBitLength?: number) {\n  // Bit size, byte size of CURVE.n\n  const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;\n  const nByteLength = Math.ceil(_nBitLength / 8);\n  return { nBitLength: _nBitLength, nByteLength };\n}\n\ntype FpField = IField<bigint> & Required<Pick<IField<bigint>, 'isOdd'>>;\n/**\n * Initializes a finite field over prime. **Non-primes are not supported.**\n * Do not init in loop: slow. Very fragile: always run a benchmark on a change.\n * Major performance optimizations:\n * * a) denormalized operations like mulN instead of mul\n * * b) same object shape: never add or remove keys\n * * c) Object.freeze\n * @param ORDER prime positive bigint\n * @param bitLen how many bits the field consumes\n * @param isLE (def: false) if encoding / decoding should be in little-endian\n * @param redef optional faster redefinitions of sqrt and other methods\n */\nexport function Field(\n  ORDER: bigint,\n  bitLen?: number,\n  isLE = false,\n  redef: Partial<IField<bigint>> = {}\n): Readonly<FpField> {\n  if (ORDER <= _0n) throw new Error(`Expected Field ORDER > 0, got ${ORDER}`);\n  const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen);\n  if (BYTES > 2048) throw new Error('Field lengths over 2048 bytes are not supported');\n  const sqrtP = FpSqrt(ORDER);\n  const f: Readonly<FpField> = Object.freeze({\n    ORDER,\n    BITS,\n    BYTES,\n    MASK: bitMask(BITS),\n    ZERO: _0n,\n    ONE: _1n,\n    create: (num) => mod(num, ORDER),\n    isValid: (num) => {\n      if (typeof num !== 'bigint')\n        throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);\n      return _0n <= num && num < ORDER; // 0 is valid element, but it's not invertible\n    },\n    is0: (num) => num === _0n,\n    isOdd: (num) => (num & _1n) === _1n,\n    neg: (num) => mod(-num, ORDER),\n    eql: (lhs, rhs) => lhs === rhs,\n\n    sqr: (num) => mod(num * num, ORDER),\n    add: (lhs, rhs) => mod(lhs + rhs, ORDER),\n    sub: (lhs, rhs) => mod(lhs - rhs, ORDER),\n    mul: (lhs, rhs) => mod(lhs * rhs, ORDER),\n    pow: (num, power) => FpPow(f, num, power),\n    div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),\n\n    // Same as above, but doesn't normalize\n    sqrN: (num) => num * num,\n    addN: (lhs, rhs) => lhs + rhs,\n    subN: (lhs, rhs) => lhs - rhs,\n    mulN: (lhs, rhs) => lhs * rhs,\n\n    inv: (num) => invert(num, ORDER),\n    sqrt: redef.sqrt || ((n) => sqrtP(f, n)),\n    invertBatch: (lst) => FpInvertBatch(f, lst),\n    // TODO: do we really need constant cmov?\n    // We don't have const-time bigints anyway, so probably will be not very useful\n    cmov: (a, b, c) => (c ? b : a),\n    toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),\n    fromBytes: (bytes) => {\n      if (bytes.length !== BYTES)\n        throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`);\n      return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);\n    },\n  } as FpField);\n  return Object.freeze(f);\n}\n\nexport function FpSqrtOdd<T>(Fp: IField<T>, elm: T) {\n  if (!Fp.isOdd) throw new Error(`Field doesn't have isOdd`);\n  const root = Fp.sqrt(elm);\n  return Fp.isOdd(root) ? root : Fp.neg(root);\n}\n\nexport function FpSqrtEven<T>(Fp: IField<T>, elm: T) {\n  if (!Fp.isOdd) throw new Error(`Field doesn't have isOdd`);\n  const root = Fp.sqrt(elm);\n  return Fp.isOdd(root) ? Fp.neg(root) : root;\n}\n\n/**\n * \"Constant-time\" private key generation utility.\n * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field).\n * Which makes it slightly more biased, less secure.\n * @deprecated use mapKeyToField instead\n */\nexport function hashToPrivateScalar(\n  hash: string | Uint8Array,\n  groupOrder: bigint,\n  isLE = false\n): bigint {\n  hash = ensureBytes('privateHash', hash);\n  const hashLen = hash.length;\n  const minLen = nLength(groupOrder).nByteLength + 8;\n  if (minLen < 24 || hashLen < minLen || hashLen > 1024)\n    throw new Error(`hashToPrivateScalar: expected ${minLen}-1024 bytes of input, got ${hashLen}`);\n  const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);\n  return mod(num, groupOrder - _1n) + _1n;\n}\n\n/**\n * Returns total number of bytes consumed by the field element.\n * For example, 32 bytes for usual 256-bit weierstrass curve.\n * @param fieldOrder number of field elements, usually CURVE.n\n * @returns byte length of field\n */\nexport function getFieldBytesLength(fieldOrder: bigint): number {\n  if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint');\n  const bitLength = fieldOrder.toString(2).length;\n  return Math.ceil(bitLength / 8);\n}\n\n/**\n * Returns minimal amount of bytes that can be safely reduced\n * by field order.\n * Should be 2^-128 for 128-bit curve such as P256.\n * @param fieldOrder number of field elements, usually CURVE.n\n * @returns byte length of target hash\n */\nexport function getMinHashLength(fieldOrder: bigint): number {\n  const length = getFieldBytesLength(fieldOrder);\n  return length + Math.ceil(length / 2);\n}\n\n/**\n * \"Constant-time\" private key generation utility.\n * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF\n * and convert them into private scalar, with the modulo bias being negligible.\n * Needs at least 48 bytes of input for 32-byte private key.\n * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/\n * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final\n * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5\n * @param hash hash output from SHA3 or a similar function\n * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n)\n * @param isLE interpret hash bytes as LE num\n * @returns valid private scalar\n */\nexport function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE = false): Uint8Array {\n  const len = key.length;\n  const fieldLen = getFieldBytesLength(fieldOrder);\n  const minLen = getMinHashLength(fieldOrder);\n  // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.\n  if (len < 16 || len < minLen || len > 1024)\n    throw new Error(`expected ${minLen}-1024 bytes of input, got ${len}`);\n  const num = isLE ? bytesToNumberBE(key) : bytesToNumberLE(key);\n  // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0\n  const reduced = mod(num, fieldOrder - _1n) + _1n;\n  return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);\n}\n","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Abelian group utilities\nimport { IField, validateField, nLength } from './modular.js';\nimport { validateObject } from './utils.js';\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\n\nexport type AffinePoint<T> = {\n  x: T;\n  y: T;\n} & { z?: never; t?: never };\n\nexport interface Group<T extends Group<T>> {\n  double(): T;\n  negate(): T;\n  add(other: T): T;\n  subtract(other: T): T;\n  equals(other: T): boolean;\n  multiply(scalar: bigint): T;\n}\n\nexport type GroupConstructor<T> = {\n  BASE: T;\n  ZERO: T;\n};\nexport type Mapper<T> = (i: T[]) => T[];\n\n// Elliptic curve multiplication of Point by scalar. Fragile.\n// Scalars should always be less than curve order: this should be checked inside of a curve itself.\n// Creates precomputation tables for fast multiplication:\n// - private scalar is split by fixed size windows of W bits\n// - every window point is collected from window's table & added to accumulator\n// - since windows are different, same point inside tables won't be accessed more than once per calc\n// - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)\n// - +1 window is neccessary for wNAF\n// - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication\n// TODO: Research returning 2d JS array of windows, instead of a single window. This would allow\n// windows to be in different memory locations\nexport function wNAF<T extends Group<T>>(c: GroupConstructor<T>, bits: number) {\n  const constTimeNegate = (condition: boolean, item: T): T => {\n    const neg = item.negate();\n    return condition ? neg : item;\n  };\n  const opts = (W: number) => {\n    const windows = Math.ceil(bits / W) + 1; // +1, because\n    const windowSize = 2 ** (W - 1); // -1 because we skip zero\n    return { windows, windowSize };\n  };\n  return {\n    constTimeNegate,\n    // non-const time multiplication ladder\n    unsafeLadder(elm: T, n: bigint) {\n      let p = c.ZERO;\n      let d: T = elm;\n      while (n > _0n) {\n        if (n & _1n) p = p.add(d);\n        d = d.double();\n        n >>= _1n;\n      }\n      return p;\n    },\n\n    /**\n     * Creates a wNAF precomputation window. Used for caching.\n     * Default window size is set by `utils.precompute()` and is equal to 8.\n     * Number of precomputed points depends on the curve size:\n     * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:\n     * - 𝑊 is the window size\n     * - 𝑛 is the bitlength of the curve order.\n     * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.\n     * @returns precomputed point tables flattened to a single array\n     */\n    precomputeWindow(elm: T, W: number): Group<T>[] {\n      const { windows, windowSize } = opts(W);\n      const points: T[] = [];\n      let p: T = elm;\n      let base = p;\n      for (let window = 0; window < windows; window++) {\n        base = p;\n        points.push(base);\n        // =1, because we skip zero\n        for (let i = 1; i < windowSize; i++) {\n          base = base.add(p);\n          points.push(base);\n        }\n        p = base.double();\n      }\n      return points;\n    },\n\n    /**\n     * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.\n     * @param W window size\n     * @param precomputes precomputed tables\n     * @param n scalar (we don't check here, but should be less than curve order)\n     * @returns real and fake (for const-time) points\n     */\n    wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } {\n      // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise\n      // But need to carefully remove other checks before wNAF. ORDER == bits here\n      const { windows, windowSize } = opts(W);\n\n      let p = c.ZERO;\n      let f = c.BASE;\n\n      const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc.\n      const maxNumber = 2 ** W;\n      const shiftBy = BigInt(W);\n\n      for (let window = 0; window < windows; window++) {\n        const offset = window * windowSize;\n        // Extract W bits.\n        let wbits = Number(n & mask);\n\n        // Shift number by W bits.\n        n >>= shiftBy;\n\n        // If the bits are bigger than max size, we'll split those.\n        // +224 => 256 - 32\n        if (wbits > windowSize) {\n          wbits -= maxNumber;\n          n += _1n;\n        }\n\n        // This code was first written with assumption that 'f' and 'p' will never be infinity point:\n        // since each addition is multiplied by 2 ** W, it cannot cancel each other. However,\n        // there is negate now: it is possible that negated element from low value\n        // would be the same as high element, which will create carry into next window.\n        // It's not obvious how this can fail, but still worth investigating later.\n\n        // Check if we're onto Zero point.\n        // Add random point inside current window to f.\n        const offset1 = offset;\n        const offset2 = offset + Math.abs(wbits) - 1; // -1 because we skip zero\n        const cond1 = window % 2 !== 0;\n        const cond2 = wbits < 0;\n        if (wbits === 0) {\n          // The most important part for const-time getPublicKey\n          f = f.add(constTimeNegate(cond1, precomputes[offset1]));\n        } else {\n          p = p.add(constTimeNegate(cond2, precomputes[offset2]));\n        }\n      }\n      // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ()\n      // Even if the variable is still unused, there are some checks which will\n      // throw an exception, so compiler needs to prove they won't happen, which is hard.\n      // At this point there is a way to F be infinity-point even if p is not,\n      // which makes it less const-time: around 1 bigint multiply.\n      return { p, f };\n    },\n\n    wNAFCached(P: T, precomputesMap: Map<T, T[]>, n: bigint, transform: Mapper<T>): { p: T; f: T } {\n      // @ts-ignore\n      const W: number = P._WINDOW_SIZE || 1;\n      // Calculate precomputes on a first run, reuse them after\n      let comp = precomputesMap.get(P);\n      if (!comp) {\n        comp = this.precomputeWindow(P, W) as T[];\n        if (W !== 1) {\n          precomputesMap.set(P, transform(comp));\n        }\n      }\n      return this.wNAF(W, comp, n);\n    },\n  };\n}\n\n// Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok.\n// Though generator can be different (Fp2 / Fp6 for BLS).\nexport type BasicCurve<T> = {\n  Fp: IField<T>; // Field over which we'll do calculations (Fp)\n  n: bigint; // Curve order, total count of valid points in the field\n  nBitLength?: number; // bit length of curve order\n  nByteLength?: number; // byte length of curve order\n  h: bigint; // cofactor. we can assign default=1, but users will just ignore it w/o validation\n  hEff?: bigint; // Number to multiply to clear cofactor\n  Gx: T; // base point X coordinate\n  Gy: T; // base point Y coordinate\n  allowInfinityPoint?: boolean; // bls12-381 requires it. ZERO point is valid, but invalid pubkey\n};\n\nexport function validateBasic<FP, T>(curve: BasicCurve<FP> & T) {\n  validateField(curve.Fp);\n  validateObject(\n    curve,\n    {\n      n: 'bigint',\n      h: 'bigint',\n      Gx: 'field',\n      Gy: 'field',\n    },\n    {\n      nBitLength: 'isSafeInteger',\n      nByteLength: 'isSafeInteger',\n    }\n  );\n  // Set defaults\n  return Object.freeze({\n    ...nLength(curve.n, curve.nBitLength),\n    ...curve,\n    ...{ p: curve.Fp.ORDER },\n  } as const);\n}\n","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Short Weierstrass curve. The formula is: y² = x³ + ax + b\nimport * as mod from './modular.js';\nimport * as ut from './utils.js';\nimport { CHash, Hex, PrivKey, ensureBytes } from './utils.js';\nimport { Group, GroupConstructor, wNAF, BasicCurve, validateBasic, AffinePoint } from './curve.js';\n\nexport type { AffinePoint };\ntype HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;\ntype EndomorphismOpts = {\n  beta: bigint;\n  splitScalar: (k: bigint) => { k1neg: boolean; k1: bigint; k2neg: boolean; k2: bigint };\n};\nexport type BasicWCurve<T> = BasicCurve<T> & {\n  // Params: a, b\n  a: T;\n  b: T;\n\n  // Optional params\n  allowedPrivateKeyLengths?: readonly number[]; // for P521\n  wrapPrivateKey?: boolean; // bls12-381 requires mod(n) instead of rejecting keys >= n\n  endo?: EndomorphismOpts; // Endomorphism options for Koblitz curves\n  // When a cofactor != 1, there can be an effective methods to:\n  // 1. Determine whether a point is torsion-free\n  isTorsionFree?: (c: ProjConstructor<T>, point: ProjPointType<T>) => boolean;\n  // 2. Clear torsion component\n  clearCofactor?: (c: ProjConstructor<T>, point: ProjPointType<T>) => ProjPointType<T>;\n};\n\ntype Entropy = Hex | boolean;\nexport type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean };\nexport type VerOpts = { lowS?: boolean; prehash?: boolean };\n\n/**\n * ### Design rationale for types\n *\n * * Interaction between classes from different curves should fail:\n *   `k256.Point.BASE.add(p256.Point.BASE)`\n * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime\n * * Different calls of `curve()` would return different classes -\n *   `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve,\n *   it won't affect others\n *\n * TypeScript can't infer types for classes created inside a function. Classes is one instance of nominative types in TypeScript and interfaces only check for shape, so it's hard to create unique type for every function call.\n *\n * We can use generic types via some param, like curve opts, but that would:\n *     1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params)\n *     which is hard to debug.\n *     2. Params can be generic and we can't enforce them to be constant value:\n *     if somebody creates curve from non-constant params,\n *     it would be allowed to interact with other curves with non-constant params\n *\n * TODO: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol\n */\n\n// Instance for 3d XYZ points\nexport interface ProjPointType<T> extends Group<ProjPointType<T>> {\n  readonly px: T;\n  readonly py: T;\n  readonly pz: T;\n  get x(): T;\n  get y(): T;\n  multiply(scalar: bigint): ProjPointType<T>;\n  toAffine(iz?: T): AffinePoint<T>;\n  isTorsionFree(): boolean;\n  clearCofactor(): ProjPointType<T>;\n  assertValidity(): void;\n  hasEvenY(): boolean;\n  toRawBytes(isCompressed?: boolean): Uint8Array;\n  toHex(isCompressed?: boolean): string;\n\n  multiplyUnsafe(scalar: bigint): ProjPointType<T>;\n  multiplyAndAddUnsafe(Q: ProjPointType<T>, a: bigint, b: bigint): ProjPointType<T> | undefined;\n  _setWindowSize(windowSize: number): void;\n}\n// Static methods for 3d XYZ points\nexport interface ProjConstructor<T> extends GroupConstructor<ProjPointType<T>> {\n  new (x: T, y: T, z: T): ProjPointType<T>;\n  fromAffine(p: AffinePoint<T>): ProjPointType<T>;\n  fromHex(hex: Hex): ProjPointType<T>;\n  fromPrivateKey(privateKey: PrivKey): ProjPointType<T>;\n  normalizeZ(points: ProjPointType<T>[]): ProjPointType<T>[];\n}\n\nexport type CurvePointsType<T> = BasicWCurve<T> & {\n  // Bytes\n  fromBytes?: (bytes: Uint8Array) => AffinePoint<T>;\n  toBytes?: (c: ProjConstructor<T>, point: ProjPointType<T>, isCompressed: boolean) => Uint8Array;\n};\n\nfunction validatePointOpts<T>(curve: CurvePointsType<T>) {\n  const opts = validateBasic(curve);\n  ut.validateObject(\n    opts,\n    {\n      a: 'field',\n      b: 'field',\n    },\n    {\n      allowedPrivateKeyLengths: 'array',\n      wrapPrivateKey: 'boolean',\n      isTorsionFree: 'function',\n      clearCofactor: 'function',\n      allowInfinityPoint: 'boolean',\n      fromBytes: 'function',\n      toBytes: 'function',\n    }\n  );\n  const { endo, Fp, a } = opts;\n  if (endo) {\n    if (!Fp.eql(a, Fp.ZERO)) {\n      throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0');\n    }\n    if (\n      typeof endo !== 'object' ||\n      typeof endo.beta !== 'bigint' ||\n      typeof endo.splitScalar !== 'function'\n    ) {\n      throw new Error('Expected endomorphism with beta: bigint and splitScalar: function');\n    }\n  }\n  return Object.freeze({ ...opts } as const);\n}\n\nexport type CurvePointsRes<T> = {\n  CURVE: ReturnType<typeof validatePointOpts<T>>;\n  ProjectivePoint: ProjConstructor<T>;\n  normPrivateKeyToScalar: (key: PrivKey) => bigint;\n  weierstrassEquation: (x: T) => T;\n  isWithinCurveOrder: (num: bigint) => boolean;\n};\n\n// ASN.1 DER encoding utilities\nconst { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;\nexport const DER = {\n  // asn.1 DER encoding utils\n  Err: class DERErr extends Error {\n    constructor(m = '') {\n      super(m);\n    }\n  },\n  _parseInt(data: Uint8Array): { d: bigint; l: Uint8Array } {\n    const { Err: E } = DER;\n    if (data.length < 2 || data[0] !== 0x02) throw new E('Invalid signature integer tag');\n    const len = data[1];\n    const res = data.subarray(2, len + 2);\n    if (!len || res.length !== len) throw new E('Invalid signature integer: wrong length');\n    // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,\n    // since we always use positive integers here. It must always be empty:\n    // - add zero byte if exists\n    // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)\n    if (res[0] & 0b10000000) throw new E('Invalid signature integer: negative');\n    if (res[0] === 0x00 && !(res[1] & 0b10000000))\n      throw new E('Invalid signature integer: unnecessary leading zero');\n    return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left\n  },\n  toSig(hex: string | Uint8Array): { r: bigint; s: bigint } {\n    // parse DER signature\n    const { Err: E } = DER;\n    const data = typeof hex === 'string' ? h2b(hex) : hex;\n    ut.abytes(data);\n    let l = data.length;\n    if (l < 2 || data[0] != 0x30) throw new E('Invalid signature tag');\n    if (data[1] !== l - 2) throw new E('Invalid signature: incorrect length');\n    const { d: r, l: sBytes } = DER._parseInt(data.subarray(2));\n    const { d: s, l: rBytesLeft } = DER._parseInt(sBytes);\n    if (rBytesLeft.length) throw new E('Invalid signature: left bytes after parsing');\n    return { r, s };\n  },\n  hexFromSig(sig: { r: bigint; s: bigint }): string {\n    // Add leading zero if first byte has negative bit enabled. More details in '_parseInt'\n    const slice = (s: string): string => (Number.parseInt(s[0], 16) & 0b1000 ? '00' + s : s);\n    const h = (num: number | bigint) => {\n      const hex = num.toString(16);\n      return hex.length & 1 ? `0${hex}` : hex;\n    };\n    const s = slice(h(sig.s));\n    const r = slice(h(sig.r));\n    const shl = s.length / 2;\n    const rhl = r.length / 2;\n    const sl = h(shl);\n    const rl = h(rhl);\n    return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`;\n  },\n};\n\n// Be friendly to bad ECMAScript parsers by not using bigint literals\n// prettier-ignore\nconst _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);\n\nexport function weierstrassPoints<T>(opts: CurvePointsType<T>): CurvePointsRes<T> {\n  const CURVE = validatePointOpts(opts);\n  const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ\n\n  const toBytes =\n    CURVE.toBytes ||\n    ((_c: ProjConstructor<T>, point: ProjPointType<T>, _isCompressed: boolean) => {\n      const a = point.toAffine();\n      return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y));\n    });\n  const fromBytes =\n    CURVE.fromBytes ||\n    ((bytes: Uint8Array) => {\n      // const head = bytes[0];\n      const tail = bytes.subarray(1);\n      // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported');\n      const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));\n      const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));\n      return { x, y };\n    });\n\n  /**\n   * y² = x³ + ax + b: Short weierstrass curve formula\n   * @returns y²\n   */\n  function weierstrassEquation(x: T): T {\n    const { a, b } = CURVE;\n    const x2 = Fp.sqr(x); // x * x\n    const x3 = Fp.mul(x2, x); // x2 * x\n    return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x3 + a * x + b\n  }\n  // Validate whether the passed curve params are valid.\n  // We check if curve equation works for generator point.\n  // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381.\n  // ProjectivePoint class has not been initialized yet.\n  if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))\n    throw new Error('bad generator point: equation left != right');\n\n  // Valid group elements reside in range 1..n-1\n  function isWithinCurveOrder(num: bigint): boolean {\n    return typeof num === 'bigint' && _0n < num && num < CURVE.n;\n  }\n  function assertGE(num: bigint) {\n    if (!isWithinCurveOrder(num)) throw new Error('Expected valid bigint: 0 < bigint < curve.n');\n  }\n  // Validates if priv key is valid and converts it to bigint.\n  // Supports options allowedPrivateKeyLengths and wrapPrivateKey.\n  function normPrivateKeyToScalar(key: PrivKey): bigint {\n    const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;\n    if (lengths && typeof key !== 'bigint') {\n      if (ut.isBytes(key)) key = ut.bytesToHex(key);\n      // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes\n      if (typeof key !== 'string' || !lengths.includes(key.length)) throw new Error('Invalid key');\n      key = key.padStart(nByteLength * 2, '0');\n    }\n    let num: bigint;\n    try {\n      num =\n        typeof key === 'bigint'\n          ? key\n          : ut.bytesToNumberBE(ensureBytes('private key', key, nByteLength));\n    } catch (error) {\n      throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);\n    }\n    if (wrapPrivateKey) num = mod.mod(num, n); // disabled by default, enabled for BLS\n    assertGE(num); // num in range [1..N-1]\n    return num;\n  }\n\n  const pointPrecomputes = new Map<Point, Point[]>();\n  function assertPrjPoint(other: unknown) {\n    if (!(other instanceof Point)) throw new Error('ProjectivePoint expected');\n  }\n  /**\n   * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)\n   * Default Point works in 2d / affine coordinates: (x, y)\n   * We're doing calculations in projective, because its operations don't require costly inversion.\n   */\n  class Point implements ProjPointType<T> {\n    static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);\n    static readonly ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO);\n\n    constructor(\n      readonly px: T,\n      readonly py: T,\n      readonly pz: T\n    ) {\n      if (px == null || !Fp.isValid(px)) throw new Error('x required');\n      if (py == null || !Fp.isValid(py)) throw new Error('y required');\n      if (pz == null || !Fp.isValid(pz)) throw new Error('z required');\n    }\n\n    // Does not validate if the point is on-curve.\n    // Use fromHex instead, or call assertValidity() later.\n    static fromAffine(p: AffinePoint<T>): Point {\n      const { x, y } = p || {};\n      if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point');\n      if (p instanceof Point) throw new Error('projective point not allowed');\n      const is0 = (i: T) => Fp.eql(i, Fp.ZERO);\n      // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0)\n      if (is0(x) && is0(y)) return Point.ZERO;\n      return new Point(x, y, Fp.ONE);\n    }\n\n    get x(): T {\n      return this.toAffine().x;\n    }\n    get y(): T {\n      return this.toAffine().y;\n    }\n\n    /**\n     * Takes a bunch of Projective Points but executes only one\n     * inversion on all of them. Inversion is very slow operation,\n     * so this improves performance massively.\n     * Optimization: converts a list of projective points to a list of identical points with Z=1.\n     */\n    static normalizeZ(points: Point[]): Point[] {\n      const toInv = Fp.invertBatch(points.map((p) => p.pz));\n      return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);\n    }\n\n    /**\n     * Converts hash string or Uint8Array to Point.\n     * @param hex short/long ECDSA hex\n     */\n    static fromHex(hex: Hex): Point {\n      const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex)));\n      P.assertValidity();\n      return P;\n    }\n\n    // Multiplies generator point by privateKey.\n    static fromPrivateKey(privateKey: PrivKey) {\n      return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));\n    }\n\n    // We calculate precomputes for elliptic curve point multiplication\n    // using windowed method. This specifies window size and\n    // stores precomputed values. Usually only base point would be precomputed.\n    _WINDOW_SIZE?: number;\n\n    // \"Private method\", don't use it directly\n    _setWindowSize(windowSize: number) {\n      this._WINDOW_SIZE = windowSize;\n      pointPrecomputes.delete(this);\n    }\n\n    // A point on curve is valid if it conforms to equation.\n    assertValidity(): void {\n      if (this.is0()) {\n        // (0, 1, 0) aka ZERO is invalid in most contexts.\n        // In BLS, ZERO can be serialized, so we allow it.\n        // (0, 0, 0) is wrong representation of ZERO and is always invalid.\n        if (CURVE.allowInfinityPoint && !Fp.is0(this.py)) return;\n        throw new Error('bad point: ZERO');\n      }\n      // Some 3rd-party test vectors require different wording between here & `fromCompressedHex`\n      const { x, y } = this.toAffine();\n      // Check if x, y are valid field elements\n      if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE');\n      const left = Fp.sqr(y); // y²\n      const right = weierstrassEquation(x); // x³ + ax + b\n      if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right');\n      if (!this.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup');\n    }\n    hasEvenY(): boolean {\n      const { y } = this.toAffine();\n      if (Fp.isOdd) return !Fp.isOdd(y);\n      throw new Error(\"Field doesn't support isOdd\");\n    }\n\n    /**\n     * Compare one point to another.\n     */\n    equals(other: Point): boolean {\n      assertPrjPoint(other);\n      const { px: X1, py: Y1, pz: Z1 } = this;\n      const { px: X2, py: Y2, pz: Z2 } = other;\n      const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));\n      const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));\n      return U1 && U2;\n    }\n\n    /**\n     * Flips point to one corresponding to (x, -y) in Affine coordinates.\n     */\n    negate(): Point {\n      return new Point(this.px, Fp.neg(this.py), this.pz);\n    }\n\n    // Renes-Costello-Batina exception-free doubling formula.\n    // There is 30% faster Jacobian formula, but it is not complete.\n    // https://eprint.iacr.org/2015/1060, algorithm 3\n    // Cost: 8M + 3S + 3*a + 2*b3 + 15add.\n    double() {\n      const { a, b } = CURVE;\n      const b3 = Fp.mul(b, _3n);\n      const { px: X1, py: Y1, pz: Z1 } = this;\n      let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore\n      let t0 = Fp.mul(X1, X1); // step 1\n      let t1 = Fp.mul(Y1, Y1);\n      let t2 = Fp.mul(Z1, Z1);\n      let t3 = Fp.mul(X1, Y1);\n      t3 = Fp.add(t3, t3); // step 5\n      Z3 = Fp.mul(X1, Z1);\n      Z3 = Fp.add(Z3, Z3);\n      X3 = Fp.mul(a, Z3);\n      Y3 = Fp.mul(b3, t2);\n      Y3 = Fp.add(X3, Y3); // step 10\n      X3 = Fp.sub(t1, Y3);\n      Y3 = Fp.add(t1, Y3);\n      Y3 = Fp.mul(X3, Y3);\n      X3 = Fp.mul(t3, X3);\n      Z3 = Fp.mul(b3, Z3); // step 15\n      t2 = Fp.mul(a, t2);\n      t3 = Fp.sub(t0, t2);\n      t3 = Fp.mul(a, t3);\n      t3 = Fp.add(t3, Z3);\n      Z3 = Fp.add(t0, t0); // step 20\n      t0 = Fp.add(Z3, t0);\n      t0 = Fp.add(t0, t2);\n      t0 = Fp.mul(t0, t3);\n      Y3 = Fp.add(Y3, t0);\n      t2 = Fp.mul(Y1, Z1); // step 25\n      t2 = Fp.add(t2, t2);\n      t0 = Fp.mul(t2, t3);\n      X3 = Fp.sub(X3, t0);\n      Z3 = Fp.mul(t2, t1);\n      Z3 = Fp.add(Z3, Z3); // step 30\n      Z3 = Fp.add(Z3, Z3);\n      return new Point(X3, Y3, Z3);\n    }\n\n    // Renes-Costello-Batina exception-free addition formula.\n    // There is 30% faster Jacobian formula, but it is not complete.\n    // https://eprint.iacr.org/2015/1060, algorithm 1\n    // Cost: 12M + 0S + 3*a + 3*b3 + 23add.\n    add(other: Point): Point {\n      assertPrjPoint(other);\n      const { px: X1, py: Y1, pz: Z1 } = this;\n      const { px: X2, py: Y2, pz: Z2 } = other;\n      let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore\n      const a = CURVE.a;\n      const b3 = Fp.mul(CURVE.b, _3n);\n      let t0 = Fp.mul(X1, X2); // step 1\n      let t1 = Fp.mul(Y1, Y2);\n      let t2 = Fp.mul(Z1, Z2);\n      let t3 = Fp.add(X1, Y1);\n      let t4 = Fp.add(X2, Y2); // step 5\n      t3 = Fp.mul(t3, t4);\n      t4 = Fp.add(t0, t1);\n      t3 = Fp.sub(t3, t4);\n      t4 = Fp.add(X1, Z1);\n      let t5 = Fp.add(X2, Z2); // step 10\n      t4 = Fp.mul(t4, t5);\n      t5 = Fp.add(t0, t2);\n      t4 = Fp.sub(t4, t5);\n      t5 = Fp.add(Y1, Z1);\n      X3 = Fp.add(Y2, Z2); // step 15\n      t5 = Fp.mul(t5, X3);\n      X3 = Fp.add(t1, t2);\n      t5 = Fp.sub(t5, X3);\n      Z3 = Fp.mul(a, t4);\n      X3 = Fp.mul(b3, t2); // step 20\n      Z3 = Fp.add(X3, Z3);\n      X3 = Fp.sub(t1, Z3);\n      Z3 = Fp.add(t1, Z3);\n      Y3 = Fp.mul(X3, Z3);\n      t1 = Fp.add(t0, t0); // step 25\n      t1 = Fp.add(t1, t0);\n      t2 = Fp.mul(a, t2);\n      t4 = Fp.mul(b3, t4);\n      t1 = Fp.add(t1, t2);\n      t2 = Fp.sub(t0, t2); // step 30\n      t2 = Fp.mul(a, t2);\n      t4 = Fp.add(t4, t2);\n      t0 = Fp.mul(t1, t4);\n      Y3 = Fp.add(Y3, t0);\n      t0 = Fp.mul(t5, t4); // step 35\n      X3 = Fp.mul(t3, X3);\n      X3 = Fp.sub(X3, t0);\n      t0 = Fp.mul(t3, t1);\n      Z3 = Fp.mul(t5, Z3);\n      Z3 = Fp.add(Z3, t0); // step 40\n      return new Point(X3, Y3, Z3);\n    }\n\n    subtract(other: Point) {\n      return this.add(other.negate());\n    }\n\n    private is0() {\n      return this.equals(Point.ZERO);\n    }\n    private wNAF(n: bigint): { p: Point; f: Point } {\n      return wnaf.wNAFCached(this, pointPrecomputes, n, (comp: Point[]) => {\n        const toInv = Fp.invertBatch(comp.map((p) => p.pz));\n        return comp.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);\n      });\n    }\n\n    /**\n     * Non-constant-time multiplication. Uses double-and-add algorithm.\n     * It's faster, but should only be used when you don't care about\n     * an exposed private key e.g. sig verification, which works over *public* keys.\n     */\n    multiplyUnsafe(n: bigint): Point {\n      const I = Point.ZERO;\n      if (n === _0n) return I;\n      assertGE(n); // Will throw on 0\n      if (n === _1n) return this;\n      const { endo } = CURVE;\n      if (!endo) return wnaf.unsafeLadder(this, n);\n\n      // Apply endomorphism\n      let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);\n      let k1p = I;\n      let k2p = I;\n      let d: Point = this;\n      while (k1 > _0n || k2 > _0n) {\n        if (k1 & _1n) k1p = k1p.add(d);\n        if (k2 & _1n) k2p = k2p.add(d);\n        d = d.double();\n        k1 >>= _1n;\n        k2 >>= _1n;\n      }\n      if (k1neg) k1p = k1p.negate();\n      if (k2neg) k2p = k2p.negate();\n      k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);\n      return k1p.add(k2p);\n    }\n\n    /**\n     * Constant time multiplication.\n     * Uses wNAF method. Windowed method may be 10% faster,\n     * but takes 2x longer to generate and consumes 2x memory.\n     * Uses precomputes when available.\n     * Uses endomorphism for Koblitz curves.\n     * @param scalar by which the point would be multiplied\n     * @returns New point\n     */\n    multiply(scalar: bigint): Point {\n      assertGE(scalar);\n      let n = scalar;\n      let point: Point, fake: Point; // Fake point is used to const-time mult\n      const { endo } = CURVE;\n      if (endo) {\n        const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);\n        let { p: k1p, f: f1p } = this.wNAF(k1);\n        let { p: k2p, f: f2p } = this.wNAF(k2);\n        k1p = wnaf.constTimeNegate(k1neg, k1p);\n        k2p = wnaf.constTimeNegate(k2neg, k2p);\n        k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);\n        point = k1p.add(k2p);\n        fake = f1p.add(f2p);\n      } else {\n        const { p, f } = this.wNAF(n);\n        point = p;\n        fake = f;\n      }\n      // Normalize `z` for both points, but return only real one\n      return Point.normalizeZ([point, fake])[0];\n    }\n\n    /**\n     * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.\n     * Not using Strauss-Shamir trick: precomputation tables are faster.\n     * The trick could be useful if both P and Q are not G (not in our case).\n     * @returns non-zero affine point\n     */\n    multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined {\n      const G = Point.BASE; // No Strauss-Shamir trick: we have 10% faster G precomputes\n      const mul = (\n        P: Point,\n        a: bigint // Select faster multiply() method\n      ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a));\n      const sum = mul(this, a).add(mul(Q, b));\n      return sum.is0() ? undefined : sum;\n    }\n\n    // Converts Projective point to affine (x, y) coordinates.\n    // Can accept precomputed Z^-1 - for example, from invertBatch.\n    // (x, y, z) ∋ (x=x/z, y=y/z)\n    toAffine(iz?: T): AffinePoint<T> {\n      const { px: x, py: y, pz: z } = this;\n      const is0 = this.is0();\n      // If invZ was 0, we return zero point. However we still want to execute\n      // all operations, so we replace invZ with a random number, 1.\n      if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z);\n      const ax = Fp.mul(x, iz);\n      const ay = Fp.mul(y, iz);\n      const zz = Fp.mul(z, iz);\n      if (is0) return { x: Fp.ZERO, y: Fp.ZERO };\n      if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid');\n      return { x: ax, y: ay };\n    }\n    isTorsionFree(): boolean {\n      const { h: cofactor, isTorsionFree } = CURVE;\n      if (cofactor === _1n) return true; // No subgroups, always torsion-free\n      if (isTorsionFree) return isTorsionFree(Point, this);\n      throw new Error('isTorsionFree() has not been declared for the elliptic curve');\n    }\n    clearCofactor(): Point {\n      const { h: cofactor, clearCofactor } = CURVE;\n      if (cofactor === _1n) return this; // Fast-path\n      if (clearCofactor) return clearCofactor(Point, this) as Point;\n      return this.multiplyUnsafe(CURVE.h);\n    }\n\n    toRawBytes(isCompressed = true): Uint8Array {\n      this.assertValidity();\n      return toBytes(Point, this, isCompressed);\n    }\n\n    toHex(isCompressed = true): string {\n      return ut.bytesToHex(this.toRawBytes(isCompressed));\n    }\n  }\n  const _bits = CURVE.nBitLength;\n  const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);\n  // Validate if generator point is on curve\n  return {\n    CURVE,\n    ProjectivePoint: Point as ProjConstructor<T>,\n    normPrivateKeyToScalar,\n    weierstrassEquation,\n    isWithinCurveOrder,\n  };\n}\n\n// Instance\nexport interface SignatureType {\n  readonly r: bigint;\n  readonly s: bigint;\n  readonly recovery?: number;\n  assertValidity(): void;\n  addRecoveryBit(recovery: number): RecoveredSignatureType;\n  hasHighS(): boolean;\n  normalizeS(): SignatureType;\n  recoverPublicKey(msgHash: Hex): ProjPointType<bigint>;\n  toCompactRawBytes(): Uint8Array;\n  toCompactHex(): string;\n  // DER-encoded\n  toDERRawBytes(isCompressed?: boolean): Uint8Array;\n  toDERHex(isCompressed?: boolean): string;\n}\nexport type RecoveredSignatureType = SignatureType & {\n  readonly recovery: number;\n};\n// Static methods\nexport type SignatureConstructor = {\n  new (r: bigint, s: bigint): SignatureType;\n  fromCompact(hex: Hex): SignatureType;\n  fromDER(hex: Hex): SignatureType;\n};\ntype SignatureLike = { r: bigint; s: bigint };\n\nexport type PubKey = Hex | ProjPointType<bigint>;\n\nexport type CurveType = BasicWCurve<bigint> & {\n  hash: CHash; // CHash not FHash because we need outputLen for DRBG\n  hmac: HmacFnSync;\n  randomBytes: (bytesLength?: number) => Uint8Array;\n  lowS?: boolean;\n  bits2int?: (bytes: Uint8Array) => bigint;\n  bits2int_modN?: (bytes: Uint8Array) => bigint;\n};\n\nfunction validateOpts(curve: CurveType) {\n  const opts = validateBasic(curve);\n  ut.validateObject(\n    opts,\n    {\n      hash: 'hash',\n      hmac: 'function',\n      randomBytes: 'function',\n    },\n    {\n      bits2int: 'function',\n      bits2int_modN: 'function',\n      lowS: 'boolean',\n    }\n  );\n  return Object.freeze({ lowS: true, ...opts } as const);\n}\n\nexport type CurveFn = {\n  CURVE: ReturnType<typeof validateOpts>;\n  getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;\n  getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array;\n  sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType;\n  verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean;\n  ProjectivePoint: ProjConstructor<bigint>;\n  Signature: SignatureConstructor;\n  utils: {\n    normPrivateKeyToScalar: (key: PrivKey) => bigint;\n    isValidPrivateKey(privateKey: PrivKey): boolean;\n    randomPrivateKey: () => Uint8Array;\n    precompute: (windowSize?: number, point?: ProjPointType<bigint>) => ProjPointType<bigint>;\n  };\n};\n\nexport function weierstrass(curveDef: CurveType): CurveFn {\n  const CURVE = validateOpts(curveDef) as ReturnType<typeof validateOpts>;\n  const { Fp, n: CURVE_ORDER } = CURVE;\n  const compressedLen = Fp.BYTES + 1; // e.g. 33 for 32\n  const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32\n\n  function isValidFieldElement(num: bigint): boolean {\n    return _0n < num && num < Fp.ORDER; // 0 is banned since it's not invertible FE\n  }\n  function modN(a: bigint) {\n    return mod.mod(a, CURVE_ORDER);\n  }\n  function invN(a: bigint) {\n    return mod.invert(a, CURVE_ORDER);\n  }\n\n  const {\n    ProjectivePoint: Point,\n    normPrivateKeyToScalar,\n    weierstrassEquation,\n    isWithinCurveOrder,\n  } = weierstrassPoints({\n    ...CURVE,\n    toBytes(_c, point, isCompressed: boolean): Uint8Array {\n      const a = point.toAffine();\n      const x = Fp.toBytes(a.x);\n      const cat = ut.concatBytes;\n      if (isCompressed) {\n        return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);\n      } else {\n        return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));\n      }\n    },\n    fromBytes(bytes: Uint8Array) {\n      const len = bytes.length;\n      const head = bytes[0];\n      const tail = bytes.subarray(1);\n      // this.assertValidity() is done inside of fromHex\n      if (len === compressedLen && (head === 0x02 || head === 0x03)) {\n        const x = ut.bytesToNumberBE(tail);\n        if (!isValidFieldElement(x)) throw new Error('Point is not on curve');\n        const y2 = weierstrassEquation(x); // y² = x³ + ax + b\n        let y: bigint;\n        try {\n          y = Fp.sqrt(y2); // y = y² ^ (p+1)/4\n        } catch (sqrtError) {\n          const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '';\n          throw new Error('Point is not on curve' + suffix);\n        }\n        const isYOdd = (y & _1n) === _1n;\n        // ECDSA\n        const isHeadOdd = (head & 1) === 1;\n        if (isHeadOdd !== isYOdd) y = Fp.neg(y);\n        return { x, y };\n      } else if (len === uncompressedLen && head === 0x04) {\n        const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));\n        const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));\n        return { x, y };\n      } else {\n        throw new Error(\n          `Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`\n        );\n      }\n    },\n  });\n  const numToNByteStr = (num: bigint): string =>\n    ut.bytesToHex(ut.numberToBytesBE(num, CURVE.nByteLength));\n\n  function isBiggerThanHalfOrder(number: bigint) {\n    const HALF = CURVE_ORDER >> _1n;\n    return number > HALF;\n  }\n\n  function normalizeS(s: bigint) {\n    return isBiggerThanHalfOrder(s) ? modN(-s) : s;\n  }\n  // slice bytes num\n  const slcNum = (b: Uint8Array, from: number, to: number) => ut.bytesToNumberBE(b.slice(from, to));\n\n  /**\n   * ECDSA signature with its (r, s) properties. Supports DER & compact representations.\n   */\n  class Signature implements SignatureType {\n    constructor(\n      readonly r: bigint,\n      readonly s: bigint,\n      readonly recovery?: number\n    ) {\n      this.assertValidity();\n    }\n\n    // pair (bytes of r, bytes of s)\n    static fromCompact(hex: Hex) {\n      const l = CURVE.nByteLength;\n      hex = ensureBytes('compactSignature', hex, l * 2);\n      return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l));\n    }\n\n    // DER encoded ECDSA signature\n    // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script\n    static fromDER(hex: Hex) {\n      const { r, s } = DER.toSig(ensureBytes('DER', hex));\n      return new Signature(r, s);\n    }\n\n    assertValidity(): void {\n      // can use assertGE here\n      if (!isWithinCurveOrder(this.r)) throw new Error('r must be 0 < r < CURVE.n');\n      if (!isWithinCurveOrder(this.s)) throw new Error('s must be 0 < s < CURVE.n');\n    }\n\n    addRecoveryBit(recovery: number): RecoveredSignature {\n      return new Signature(this.r, this.s, recovery) as RecoveredSignature;\n    }\n\n    recoverPublicKey(msgHash: Hex): typeof Point.BASE {\n      const { r, s, recovery: rec } = this;\n      const h = bits2int_modN(ensureBytes('msgHash', msgHash)); // Truncate hash\n      if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid');\n      const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;\n      if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid');\n      const prefix = (rec & 1) === 0 ? '02' : '03';\n      const R = Point.fromHex(prefix + numToNByteStr(radj));\n      const ir = invN(radj); // r^-1\n      const u1 = modN(-h * ir); // -hr^-1\n      const u2 = modN(s * ir); // sr^-1\n      const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)\n      if (!Q) throw new Error('point at infinify'); // unsafe is fine: no priv data leaked\n      Q.assertValidity();\n      return Q;\n    }\n\n    // Signatures should be low-s, to prevent malleability.\n    hasHighS(): boolean {\n      return isBiggerThanHalfOrder(this.s);\n    }\n\n    normalizeS() {\n      return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this;\n    }\n\n    // DER-encoded\n    toDERRawBytes() {\n      return ut.hexToBytes(this.toDERHex());\n    }\n    toDERHex() {\n      return DER.hexFromSig({ r: this.r, s: this.s });\n    }\n\n    // padded bytes of r, then padded bytes of s\n    toCompactRawBytes() {\n      return ut.hexToBytes(this.toCompactHex());\n    }\n    toCompactHex() {\n      return numToNByteStr(this.r) + numToNByteStr(this.s);\n    }\n  }\n  type RecoveredSignature = Signature & { recovery: number };\n\n  const utils = {\n    isValidPrivateKey(privateKey: PrivKey) {\n      try {\n        normPrivateKeyToScalar(privateKey);\n        return true;\n      } catch (error) {\n        return false;\n      }\n    },\n    normPrivateKeyToScalar: normPrivateKeyToScalar,\n\n    /**\n     * Produces cryptographically secure private key from random of size\n     * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.\n     */\n    randomPrivateKey: (): Uint8Array => {\n      const length = mod.getMinHashLength(CURVE.n);\n      return mod.mapHashToField(CURVE.randomBytes(length), CURVE.n);\n    },\n\n    /**\n     * Creates precompute table for an arbitrary EC point. Makes point \"cached\".\n     * Allows to massively speed-up `point.multiply(scalar)`.\n     * @returns cached point\n     * @example\n     * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));\n     * fast.multiply(privKey); // much faster ECDH now\n     */\n    precompute(windowSize = 8, point = Point.BASE): typeof Point.BASE {\n      point._setWindowSize(windowSize);\n      point.multiply(BigInt(3)); // 3 is arbitrary, just need any number here\n      return point;\n    },\n  };\n\n  /**\n   * Computes public key for a private key. Checks for validity of the private key.\n   * @param privateKey private key\n   * @param isCompressed whether to return compact (default), or full key\n   * @returns Public key, full when isCompressed=false; short when isCompressed=true\n   */\n  function getPublicKey(privateKey: PrivKey, isCompressed = true): Uint8Array {\n    return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed);\n  }\n\n  /**\n   * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.\n   */\n  function isProbPub(item: PrivKey | PubKey): boolean {\n    const arr = ut.isBytes(item);\n    const str = typeof item === 'string';\n    const len = (arr || str) && (item as Hex).length;\n    if (arr) return len === compressedLen || len === uncompressedLen;\n    if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen;\n    if (item instanceof Point) return true;\n    return false;\n  }\n\n  /**\n   * ECDH (Elliptic Curve Diffie Hellman).\n   * Computes shared public key from private key and public key.\n   * Checks: 1) private key validity 2) shared key is on-curve.\n   * Does NOT hash the result.\n   * @param privateA private key\n   * @param publicB different public key\n   * @param isCompressed whether to return compact (default), or full key\n   * @returns shared public key\n   */\n  function getSharedSecret(privateA: PrivKey, publicB: Hex, isCompressed = true): Uint8Array {\n    if (isProbPub(privateA)) throw new Error('first arg must be private key');\n    if (!isProbPub(publicB)) throw new Error('second arg must be public key');\n    const b = Point.fromHex(publicB); // check for being on-curve\n    return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);\n  }\n\n  // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.\n  // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.\n  // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same.\n  // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors\n  const bits2int =\n    CURVE.bits2int ||\n    function (bytes: Uint8Array): bigint {\n      // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)\n      // for some cases, since bytes.length * 8 is not actual bitLength.\n      const num = ut.bytesToNumberBE(bytes); // check for == u8 done here\n      const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits\n      return delta > 0 ? num >> BigInt(delta) : num;\n    };\n  const bits2int_modN =\n    CURVE.bits2int_modN ||\n    function (bytes: Uint8Array): bigint {\n      return modN(bits2int(bytes)); // can't use bytesToNumberBE here\n    };\n  // NOTE: pads output with zero as per spec\n  const ORDER_MASK = ut.bitMask(CURVE.nBitLength);\n  /**\n   * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.\n   */\n  function int2octets(num: bigint): Uint8Array {\n    if (typeof num !== 'bigint') throw new Error('bigint expected');\n    if (!(_0n <= num && num < ORDER_MASK))\n      throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);\n    // works with order, can have different size than numToField!\n    return ut.numberToBytesBE(num, CURVE.nByteLength);\n  }\n\n  // Steps A, D of RFC6979 3.2\n  // Creates RFC6979 seed; converts msg/privKey to numbers.\n  // Used only in sign, not in verify.\n  // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, this will be wrong at least for P521.\n  // Also it can be bigger for P224 + SHA256\n  function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) {\n    if (['recovered', 'canonical'].some((k) => k in opts))\n      throw new Error('sign() legacy options not supported');\n    const { hash, randomBytes } = CURVE;\n    let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default\n    if (lowS == null) lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash\n    msgHash = ensureBytes('msgHash', msgHash);\n    if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash));\n\n    // We can't later call bits2octets, since nested bits2int is broken for curves\n    // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.\n    // const bits2octets = (bits) => int2octets(bits2int_modN(bits))\n    const h1int = bits2int_modN(msgHash);\n    const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint\n    const seedArgs = [int2octets(d), int2octets(h1int)];\n    // extraEntropy. RFC6979 3.6: additional k' (optional).\n    if (ent != null && ent !== false) {\n      // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')\n      const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is\n      seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes\n    }\n    const seed = ut.concatBytes(...seedArgs); // Step D of RFC6979 3.2\n    const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!\n    // Converts signature params into point w r/s, checks result for validity.\n    function k2sig(kBytes: Uint8Array): RecoveredSignature | undefined {\n      // RFC 6979 Section 3.2, step 3: k = bits2int(T)\n      const k = bits2int(kBytes); // Cannot use fields methods, since it is group element\n      if (!isWithinCurveOrder(k)) return; // Important: all mod() calls here must be done over N\n      const ik = invN(k); // k^-1 mod n\n      const q = Point.BASE.multiply(k).toAffine(); // q = Gk\n      const r = modN(q.x); // r = q.x mod n\n      if (r === _0n) return;\n      // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to\n      // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:\n      // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT\n      const s = modN(ik * modN(m + r * d)); // Not using blinding here\n      if (s === _0n) return;\n      let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n); // recovery bit (2 or 3, when q.x > n)\n      let normS = s;\n      if (lowS && isBiggerThanHalfOrder(s)) {\n        normS = normalizeS(s); // if lowS was passed, ensure s is always\n        recovery ^= 1; // // in the bottom half of N\n      }\n      return new Signature(r, normS, recovery) as RecoveredSignature; // use normS, not s\n    }\n    return { seed, k2sig };\n  }\n  const defaultSigOpts: SignOpts = { lowS: CURVE.lowS, prehash: false };\n  const defaultVerOpts: VerOpts = { lowS: CURVE.lowS, prehash: false };\n\n  /**\n   * Signs message hash with a private key.\n   * ```\n   * sign(m, d, k) where\n   *   (x, y) = G × k\n   *   r = x mod n\n   *   s = (m + dr)/k mod n\n   * ```\n   * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`.\n   * @param privKey private key\n   * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg.\n   * @returns signature with recovery param\n   */\n  function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): RecoveredSignature {\n    const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.\n    const C = CURVE;\n    const drbg = ut.createHmacDrbg<RecoveredSignature>(C.hash.outputLen, C.nByteLength, C.hmac);\n    return drbg(seed, k2sig); // Steps B, C, D, E, F, G\n  }\n\n  // Enable precomputes. Slows down first publicKey computation by 20ms.\n  Point.BASE._setWindowSize(8);\n  // utils.precompute(8, ProjectivePoint.BASE)\n\n  /**\n   * Verifies a signature against message hash and public key.\n   * Rejects lowS signatures by default: to override,\n   * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf:\n   *\n   * ```\n   * verify(r, s, h, P) where\n   *   U1 = hs^-1 mod n\n   *   U2 = rs^-1 mod n\n   *   R = U1⋅G - U2⋅P\n   *   mod(R.x, n) == r\n   * ```\n   */\n  function verify(\n    signature: Hex | SignatureLike,\n    msgHash: Hex,\n    publicKey: Hex,\n    opts = defaultVerOpts\n  ): boolean {\n    const sg = signature;\n    msgHash = ensureBytes('msgHash', msgHash);\n    publicKey = ensureBytes('publicKey', publicKey);\n    if ('strict' in opts) throw new Error('options.strict was renamed to lowS');\n    const { lowS, prehash } = opts;\n\n    let _sig: Signature | undefined = undefined;\n    let P: ProjPointType<bigint>;\n    try {\n      if (typeof sg === 'string' || ut.isBytes(sg)) {\n        // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).\n        // Since DER can also be 2*nByteLength bytes, we check for it first.\n        try {\n          _sig = Signature.fromDER(sg);\n        } catch (derError) {\n          if (!(derError instanceof DER.Err)) throw derError;\n          _sig = Signature.fromCompact(sg);\n        }\n      } else if (typeof sg === 'object' && typeof sg.r === 'bigint' && typeof sg.s === 'bigint') {\n        const { r, s } = sg;\n        _sig = new Signature(r, s);\n      } else {\n        throw new Error('PARSE');\n      }\n      P = Point.fromHex(publicKey);\n    } catch (error) {\n      if ((error as Error).message === 'PARSE')\n        throw new Error(`signature must be Signature instance, Uint8Array or hex string`);\n      return false;\n    }\n    if (lowS && _sig.hasHighS()) return false;\n    if (prehash) msgHash = CURVE.hash(msgHash);\n    const { r, s } = _sig;\n    const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element\n    const is = invN(s); // s^-1\n    const u1 = modN(h * is); // u1 = hs^-1 mod n\n    const u2 = modN(r * is); // u2 = rs^-1 mod n\n    const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine(); // R = u1⋅G + u2⋅P\n    if (!R) return false;\n    const v = modN(R.x);\n    return v === r;\n  }\n  return {\n    CURVE,\n    getPublicKey,\n    getSharedSecret,\n    sign,\n    verify,\n    ProjectivePoint: Point,\n    Signature,\n    utils,\n  };\n}\n\n/**\n * Implementation of the Shallue and van de Woestijne method for any weierstrass curve.\n * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular.\n * b = True and y = sqrt(u / v) if (u / v) is square in F, and\n * b = False and y = sqrt(Z * (u / v)) otherwise.\n * @param Fp\n * @param Z\n * @returns\n */\nexport function SWUFpSqrtRatio<T>(Fp: mod.IField<T>, Z: T) {\n  // Generic implementation\n  const q = Fp.ORDER;\n  let l = _0n;\n  for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n;\n  const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.\n  // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<.\n  // 2n ** c1 == 2n << (c1-1)\n  const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n);\n  const _2n_pow_c1 = _2n_pow_c1_1 * _2n;\n  const c2 = (q - _1n) / _2n_pow_c1; // 2. c2 = (q - 1) / (2^c1)  # Integer arithmetic\n  const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2            # Integer arithmetic\n  const c4 = _2n_pow_c1 - _1n; // 4. c4 = 2^c1 - 1                # Integer arithmetic\n  const c5 = _2n_pow_c1_1; // 5. c5 = 2^(c1 - 1)                  # Integer arithmetic\n  const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2\n  const c7 = Fp.pow(Z, (c2 + _1n) / _2n); // 7. c7 = Z^((c2 + 1) / 2)\n  let sqrtRatio = (u: T, v: T): { isValid: boolean; value: T } => {\n    let tv1 = c6; // 1. tv1 = c6\n    let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4\n    let tv3 = Fp.sqr(tv2); // 3. tv3 = tv2^2\n    tv3 = Fp.mul(tv3, v); // 4. tv3 = tv3 * v\n    let tv5 = Fp.mul(u, tv3); // 5. tv5 = u * tv3\n    tv5 = Fp.pow(tv5, c3); // 6. tv5 = tv5^c3\n    tv5 = Fp.mul(tv5, tv2); // 7. tv5 = tv5 * tv2\n    tv2 = Fp.mul(tv5, v); // 8. tv2 = tv5 * v\n    tv3 = Fp.mul(tv5, u); // 9. tv3 = tv5 * u\n    let tv4 = Fp.mul(tv3, tv2); // 10. tv4 = tv3 * tv2\n    tv5 = Fp.pow(tv4, c5); // 11. tv5 = tv4^c5\n    let isQR = Fp.eql(tv5, Fp.ONE); // 12. isQR = tv5 == 1\n    tv2 = Fp.mul(tv3, c7); // 13. tv2 = tv3 * c7\n    tv5 = Fp.mul(tv4, tv1); // 14. tv5 = tv4 * tv1\n    tv3 = Fp.cmov(tv2, tv3, isQR); // 15. tv3 = CMOV(tv2, tv3, isQR)\n    tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)\n    // 17. for i in (c1, c1 - 1, ..., 2):\n    for (let i = c1; i > _1n; i--) {\n      let tv5 = i - _2n; // 18.    tv5 = i - 2\n      tv5 = _2n << (tv5 - _1n); // 19.    tv5 = 2^tv5\n      let tvv5 = Fp.pow(tv4, tv5); // 20.    tv5 = tv4^tv5\n      const e1 = Fp.eql(tvv5, Fp.ONE); // 21.    e1 = tv5 == 1\n      tv2 = Fp.mul(tv3, tv1); // 22.    tv2 = tv3 * tv1\n      tv1 = Fp.mul(tv1, tv1); // 23.    tv1 = tv1 * tv1\n      tvv5 = Fp.mul(tv4, tv1); // 24.    tv5 = tv4 * tv1\n      tv3 = Fp.cmov(tv2, tv3, e1); // 25.    tv3 = CMOV(tv2, tv3, e1)\n      tv4 = Fp.cmov(tvv5, tv4, e1); // 26.    tv4 = CMOV(tv5, tv4, e1)\n    }\n    return { isValid: isQR, value: tv3 };\n  };\n  if (Fp.ORDER % _4n === _3n) {\n    // sqrt_ratio_3mod4(u, v)\n    const c1 = (Fp.ORDER - _3n) / _4n; // 1. c1 = (q - 3) / 4     # Integer arithmetic\n    const c2 = Fp.sqrt(Fp.neg(Z)); // 2. c2 = sqrt(-Z)\n    sqrtRatio = (u: T, v: T) => {\n      let tv1 = Fp.sqr(v); // 1. tv1 = v^2\n      const tv2 = Fp.mul(u, v); // 2. tv2 = u * v\n      tv1 = Fp.mul(tv1, tv2); // 3. tv1 = tv1 * tv2\n      let y1 = Fp.pow(tv1, c1); // 4. y1 = tv1^c1\n      y1 = Fp.mul(y1, tv2); // 5. y1 = y1 * tv2\n      const y2 = Fp.mul(y1, c2); // 6. y2 = y1 * c2\n      const tv3 = Fp.mul(Fp.sqr(y1), v); // 7. tv3 = y1^2; 8. tv3 = tv3 * v\n      const isQR = Fp.eql(tv3, u); // 9. isQR = tv3 == u\n      let y = Fp.cmov(y2, y1, isQR); // 10. y = CMOV(y2, y1, isQR)\n      return { isValid: isQR, value: y }; // 11. return (isQR, y) isQR ? y : y*c2\n    };\n  }\n  // No curves uses that\n  // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8\n  return sqrtRatio;\n}\n/**\n * Simplified Shallue-van de Woestijne-Ulas Method\n * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2\n */\nexport function mapToCurveSimpleSWU<T>(\n  Fp: mod.IField<T>,\n  opts: {\n    A: T;\n    B: T;\n    Z: T;\n  }\n) {\n  mod.validateField(Fp);\n  if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z))\n    throw new Error('mapToCurveSimpleSWU: invalid opts');\n  const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z);\n  if (!Fp.isOdd) throw new Error('Fp.isOdd is not implemented!');\n  // Input: u, an element of F.\n  // Output: (x, y), a point on E.\n  return (u: T): { x: T; y: T } => {\n    // prettier-ignore\n    let tv1, tv2, tv3, tv4, tv5, tv6, x, y;\n    tv1 = Fp.sqr(u); // 1.  tv1 = u^2\n    tv1 = Fp.mul(tv1, opts.Z); // 2.  tv1 = Z * tv1\n    tv2 = Fp.sqr(tv1); // 3.  tv2 = tv1^2\n    tv2 = Fp.add(tv2, tv1); // 4.  tv2 = tv2 + tv1\n    tv3 = Fp.add(tv2, Fp.ONE); // 5.  tv3 = tv2 + 1\n    tv3 = Fp.mul(tv3, opts.B); // 6.  tv3 = B * tv3\n    tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)); // 7.  tv4 = CMOV(Z, -tv2, tv2 != 0)\n    tv4 = Fp.mul(tv4, opts.A); // 8.  tv4 = A * tv4\n    tv2 = Fp.sqr(tv3); // 9.  tv2 = tv3^2\n    tv6 = Fp.sqr(tv4); // 10. tv6 = tv4^2\n    tv5 = Fp.mul(tv6, opts.A); // 11. tv5 = A * tv6\n    tv2 = Fp.add(tv2, tv5); // 12. tv2 = tv2 + tv5\n    tv2 = Fp.mul(tv2, tv3); // 13. tv2 = tv2 * tv3\n    tv6 = Fp.mul(tv6, tv4); // 14. tv6 = tv6 * tv4\n    tv5 = Fp.mul(tv6, opts.B); // 15. tv5 = B * tv6\n    tv2 = Fp.add(tv2, tv5); // 16. tv2 = tv2 + tv5\n    x = Fp.mul(tv1, tv3); // 17.   x = tv1 * tv3\n    const { isValid, value } = sqrtRatio(tv2, tv6); // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)\n    y = Fp.mul(tv1, u); // 19.   y = tv1 * u  -> Z * u^3 * y1\n    y = Fp.mul(y, value); // 20.   y = y * y1\n    x = Fp.cmov(x, tv3, isValid); // 21.   x = CMOV(x, tv3, is_gx1_square)\n    y = Fp.cmov(y, value, isValid); // 22.   y = CMOV(y, y1, is_gx1_square)\n    const e1 = Fp.isOdd!(u) === Fp.isOdd!(y); // 23.  e1 = sgn0(u) == sgn0(y)\n    y = Fp.cmov(Fp.neg(y), y, e1); // 24.   y = CMOV(-y, y, e1)\n    x = Fp.div(x, tv4); // 25.   x = x / tv4\n    return { x, y };\n  };\n}\n","import { hash as assertHash, bytes as assertBytes, exists as assertExists } from './_assert.js';\nimport { Hash, CHash, Input, toBytes } from './utils.js';\n// HMAC (RFC 2104)\nexport class HMAC<T extends Hash<T>> extends Hash<HMAC<T>> {\n  oHash: T;\n  iHash: T;\n  blockLen: number;\n  outputLen: number;\n  private finished = false;\n  private destroyed = false;\n\n  constructor(hash: CHash, _key: Input) {\n    super();\n    assertHash(hash);\n    const key = toBytes(_key);\n    this.iHash = hash.create() as T;\n    if (typeof this.iHash.update !== 'function')\n      throw new Error('Expected instance of class which extends utils.Hash');\n    this.blockLen = this.iHash.blockLen;\n    this.outputLen = this.iHash.outputLen;\n    const blockLen = this.blockLen;\n    const pad = new Uint8Array(blockLen);\n    // blockLen can be bigger than outputLen\n    pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);\n    for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36;\n    this.iHash.update(pad);\n    // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone\n    this.oHash = hash.create() as T;\n    // Undo internal XOR && apply outer XOR\n    for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36 ^ 0x5c;\n    this.oHash.update(pad);\n    pad.fill(0);\n  }\n  update(buf: Input) {\n    assertExists(this);\n    this.iHash.update(buf);\n    return this;\n  }\n  digestInto(out: Uint8Array) {\n    assertExists(this);\n    assertBytes(out, this.outputLen);\n    this.finished = true;\n    this.iHash.digestInto(out);\n    this.oHash.update(out);\n    this.oHash.digestInto(out);\n    this.destroy();\n  }\n  digest() {\n    const out = new Uint8Array(this.oHash.outputLen);\n    this.digestInto(out);\n    return out;\n  }\n  _cloneInto(to?: HMAC<T>): HMAC<T> {\n    // Create new instance without calling constructor since key already in state and we don't know it.\n    to ||= Object.create(Object.getPrototypeOf(this), {});\n    const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;\n    to = to as this;\n    to.finished = finished;\n    to.destroyed = destroyed;\n    to.blockLen = blockLen;\n    to.outputLen = outputLen;\n    to.oHash = oHash._cloneInto(to.oHash);\n    to.iHash = iHash._cloneInto(to.iHash);\n    return to;\n  }\n  destroy() {\n    this.destroyed = true;\n    this.oHash.destroy();\n    this.iHash.destroy();\n  }\n}\n\n/**\n * HMAC: RFC2104 message authentication code.\n * @param hash - function that would be used e.g. sha256\n * @param key - message key\n * @param message - message data\n */\nexport const hmac = (hash: CHash, key: Input, message: Input): Uint8Array =>\n  new HMAC<any>(hash, key).update(message).digest();\nhmac.create = (hash: CHash, key: Input) => new HMAC<any>(hash, key);\n","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nimport { hmac } from '@noble/hashes/hmac';\nimport { concatBytes, randomBytes } from '@noble/hashes/utils';\nimport { weierstrass, CurveType } from './abstract/weierstrass.js';\nimport { CHash } from './abstract/utils.js';\n\n// connects noble-curves to noble-hashes\nexport function getHash(hash: CHash) {\n  return {\n    hash,\n    hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(hash, key, concatBytes(...msgs)),\n    randomBytes,\n  };\n}\n// Same API as @noble/hashes, with ability to create curve with custom hash\ntype CurveDef = Readonly<Omit<CurveType, 'hash' | 'hmac' | 'randomBytes'>>;\nexport function createCurve(curveDef: CurveDef, defHash: CHash) {\n  const create = (hash: CHash) => weierstrass({ ...curveDef, ...getHash(hash) });\n  return Object.freeze({ ...create(defHash), create });\n}\n","/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nimport { sha256 } from '@noble/hashes/sha256';\nimport { randomBytes } from '@noble/hashes/utils';\nimport { Field, mod, pow2 } from './abstract/modular.js';\nimport { ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.js';\nimport type { Hex, PrivKey } from './abstract/utils.js';\nimport { bytesToNumberBE, concatBytes, ensureBytes, numberToBytesBE } from './abstract/utils.js';\nimport { createHasher, isogenyMap } from './abstract/hash-to-curve.js';\nimport { createCurve } from './_shortw_utils.js';\n\nconst secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');\nconst secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nconst divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b;\n\n/**\n * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit.\n * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]\n */\nfunction sqrtMod(y: bigint): bigint {\n  const P = secp256k1P;\n  // prettier-ignore\n  const _3n = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);\n  // prettier-ignore\n  const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88);\n  const b2 = (y * y * y) % P; // x^3, 11\n  const b3 = (b2 * b2 * y) % P; // x^7\n  const b6 = (pow2(b3, _3n, P) * b3) % P;\n  const b9 = (pow2(b6, _3n, P) * b3) % P;\n  const b11 = (pow2(b9, _2n, P) * b2) % P;\n  const b22 = (pow2(b11, _11n, P) * b11) % P;\n  const b44 = (pow2(b22, _22n, P) * b22) % P;\n  const b88 = (pow2(b44, _44n, P) * b44) % P;\n  const b176 = (pow2(b88, _88n, P) * b88) % P;\n  const b220 = (pow2(b176, _44n, P) * b44) % P;\n  const b223 = (pow2(b220, _3n, P) * b3) % P;\n  const t1 = (pow2(b223, _23n, P) * b22) % P;\n  const t2 = (pow2(t1, _6n, P) * b2) % P;\n  const root = pow2(t2, _2n, P);\n  if (!Fp.eql(Fp.sqr(root), y)) throw new Error('Cannot find square root');\n  return root;\n}\n\nconst Fp = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod });\n\nexport const secp256k1 = createCurve(\n  {\n    a: BigInt(0), // equation params: a, b\n    b: BigInt(7), // Seem to be rigid: bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975\n    Fp, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n\n    n: secp256k1N, // Curve order, total count of valid points in the field\n    // Base point (x, y) aka generator point\n    Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),\n    Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),\n    h: BigInt(1), // Cofactor\n    lowS: true, // Allow only low-S signatures by default in sign() and verify()\n    /**\n     * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.\n     * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.\n     * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.\n     * Explanation: https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066\n     */\n    endo: {\n      beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),\n      splitScalar: (k: bigint) => {\n        const n = secp256k1N;\n        const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');\n        const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');\n        const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');\n        const b2 = a1;\n        const POW_2_128 = BigInt('0x100000000000000000000000000000000'); // (2n**128n).toString(16)\n\n        const c1 = divNearest(b2 * k, n);\n        const c2 = divNearest(-b1 * k, n);\n        let k1 = mod(k - c1 * a1 - c2 * a2, n);\n        let k2 = mod(-c1 * b1 - c2 * b2, n);\n        const k1neg = k1 > POW_2_128;\n        const k2neg = k2 > POW_2_128;\n        if (k1neg) k1 = n - k1;\n        if (k2neg) k2 = n - k2;\n        if (k1 > POW_2_128 || k2 > POW_2_128) {\n          throw new Error('splitScalar: Endomorphism failed, k=' + k);\n        }\n        return { k1neg, k1, k2neg, k2 };\n      },\n    },\n  },\n  sha256\n);\n\n// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.\n// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki\nconst _0n = BigInt(0);\nconst fe = (x: bigint) => typeof x === 'bigint' && _0n < x && x < secp256k1P;\nconst ge = (x: bigint) => typeof x === 'bigint' && _0n < x && x < secp256k1N;\n/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */\nconst TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {};\nfunction taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array {\n  let tagP = TAGGED_HASH_PREFIXES[tag];\n  if (tagP === undefined) {\n    const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0)));\n    tagP = concatBytes(tagH, tagH);\n    TAGGED_HASH_PREFIXES[tag] = tagP;\n  }\n  return sha256(concatBytes(tagP, ...messages));\n}\n\n// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03\nconst pointToBytes = (point: PointType<bigint>) => point.toRawBytes(true).slice(1);\nconst numTo32b = (n: bigint) => numberToBytesBE(n, 32);\nconst modP = (x: bigint) => mod(x, secp256k1P);\nconst modN = (x: bigint) => mod(x, secp256k1N);\nconst Point = secp256k1.ProjectivePoint;\nconst GmulAdd = (Q: PointType<bigint>, a: bigint, b: bigint) =>\n  Point.BASE.multiplyAndAddUnsafe(Q, a, b);\n\n// Calculate point, scalar and bytes\nfunction schnorrGetExtPubKey(priv: PrivKey) {\n  let d_ = secp256k1.utils.normPrivateKeyToScalar(priv); // same method executed in fromPrivateKey\n  let p = Point.fromPrivateKey(d_); // P = d'⋅G; 0 < d' < n check is done inside\n  const scalar = p.hasEvenY() ? d_ : modN(-d_);\n  return { scalar: scalar, bytes: pointToBytes(p) };\n}\n/**\n * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point.\n * @returns valid point checked for being on-curve\n */\nfunction lift_x(x: bigint): PointType<bigint> {\n  if (!fe(x)) throw new Error('bad x: need 0 < x < p'); // Fail if x ≥ p.\n  const xx = modP(x * x);\n  const c = modP(xx * x + BigInt(7)); // Let c = x³ + 7 mod p.\n  let y = sqrtMod(c); // Let y = c^(p+1)/4 mod p.\n  if (y % _2n !== _0n) y = modP(-y); // Return the unique point P such that x(P) = x and\n  const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.\n  p.assertValidity();\n  return p;\n}\n/**\n * Create tagged hash, convert it to bigint, reduce modulo-n.\n */\nfunction challenge(...args: Uint8Array[]): bigint {\n  return modN(bytesToNumberBE(taggedHash('BIP0340/challenge', ...args)));\n}\n\n/**\n * Schnorr public key is just `x` coordinate of Point as per BIP340.\n */\nfunction schnorrGetPublicKey(privateKey: Hex): Uint8Array {\n  return schnorrGetExtPubKey(privateKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)\n}\n\n/**\n * Creates Schnorr signature as per BIP340. Verifies itself before returning anything.\n * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous.\n */\nfunction schnorrSign(\n  message: Hex,\n  privateKey: PrivKey,\n  auxRand: Hex = randomBytes(32)\n): Uint8Array {\n  const m = ensureBytes('message', message);\n  const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey); // checks for isWithinCurveOrder\n  const a = ensureBytes('auxRand', auxRand, 32); // Auxiliary random data a: a 32-byte array\n  const t = numTo32b(d ^ bytesToNumberBE(taggedHash('BIP0340/aux', a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)\n  const rand = taggedHash('BIP0340/nonce', t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)\n  const k_ = modN(bytesToNumberBE(rand)); // Let k' = int(rand) mod n\n  if (k_ === _0n) throw new Error('sign failed: k is zero'); // Fail if k' = 0.\n  const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.\n  const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.\n  const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).\n  sig.set(rx, 0);\n  sig.set(numTo32b(modN(k + e * d)), 32);\n  // If Verify(bytes(P), m, sig) (see below) returns failure, abort\n  if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced');\n  return sig;\n}\n\n/**\n * Verifies Schnorr signature.\n * Will swallow errors & return false except for initial type validation of arguments.\n */\nfunction schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean {\n  const sig = ensureBytes('signature', signature, 64);\n  const m = ensureBytes('message', message);\n  const pub = ensureBytes('publicKey', publicKey, 32);\n  try {\n    const P = lift_x(bytesToNumberBE(pub)); // P = lift_x(int(pk)); fail if that fails\n    const r = bytesToNumberBE(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.\n    if (!fe(r)) return false;\n    const s = bytesToNumberBE(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.\n    if (!ge(s)) return false;\n    const e = challenge(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m))%n\n    const R = GmulAdd(P, s, modN(-e)); // R = s⋅G - e⋅P\n    if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false; // -eP == (n-e)P\n    return true; // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r.\n  } catch (error) {\n    return false;\n  }\n}\n\nexport const schnorr = /* @__PURE__ */ (() => ({\n  getPublicKey: schnorrGetPublicKey,\n  sign: schnorrSign,\n  verify: schnorrVerify,\n  utils: {\n    randomPrivateKey: secp256k1.utils.randomPrivateKey,\n    lift_x,\n    pointToBytes,\n    numberToBytesBE,\n    bytesToNumberBE,\n    taggedHash,\n    mod,\n  },\n}))();\n\nconst isoMap = /* @__PURE__ */ (() =>\n  isogenyMap(\n    Fp,\n    [\n      // xNum\n      [\n        '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7',\n        '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581',\n        '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262',\n        '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c',\n      ],\n      // xDen\n      [\n        '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b',\n        '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14',\n        '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1\n      ],\n      // yNum\n      [\n        '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c',\n        '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3',\n        '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931',\n        '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84',\n      ],\n      // yDen\n      [\n        '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b',\n        '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573',\n        '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f',\n        '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1\n      ],\n    ].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]]\n  ))();\nconst mapSWU = /* @__PURE__ */ (() =>\n  mapToCurveSimpleSWU(Fp, {\n    A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'),\n    B: BigInt('1771'),\n    Z: Fp.create(BigInt('-11')),\n  }))();\nconst htf = /* @__PURE__ */ (() =>\n  createHasher(\n    secp256k1.ProjectivePoint,\n    (scalars: bigint[]) => {\n      const { x, y } = mapSWU(Fp.create(scalars[0]));\n      return isoMap(x, y);\n    },\n    {\n      DST: 'secp256k1_XMD:SHA-256_SSWU_RO_',\n      encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_',\n      p: Fp.ORDER,\n      m: 1,\n      k: 128,\n      expand: 'xmd',\n      hash: sha256,\n    }\n  ))();\nexport const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)();\nexport const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)();\n","import { schnorr } from \"@noble/curves/secp256k1\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { bytesToHex } from \"@noble/hashes/utils\";\nimport type { NostrEvent } from \"./nostr\";\n\nconst utf8Encoder = new TextEncoder();\n\n// verifies the signature of the Nostr event\nexport const verifyEventSig = (ev: NostrEvent): boolean => {\n  const serializedEv = JSON.stringify([0, ev.pubkey, ev.created_at, ev.kind, ev.tags, ev.content]);\n  const evHash = bytesToHex(sha256(utf8Encoder.encode(serializedEv)));\n  if (ev.id !== evHash) {\n    return false;\n  }\n  return schnorr.verify(ev.sig, evHash, ev.pubkey);\n};\n","type BasicLogLevel = \"verbose\" | \"info\" | \"warn\" | \"error\";\nexport type LogLevel = BasicLogLevel | \"all\" | \"none\";\n\nconst scoreForlogLevel = {\n  all: 0,\n  verbose: 10,\n  info: 20,\n  warn: 30,\n  error: 40,\n  none: 50,\n} satisfies Record<LogLevel, number>;\n\nconst logFnForlogLevel = {\n  verbose: console.debug,\n  info: console.info,\n  warn: console.warn,\n  error: console.error,\n} satisfies Record<BasicLogLevel, typeof console.log>;\n\n/**\n * Logger for debug logs.\n */\nexport class DebugLogger {\n  #minLevel: LogLevel;\n  #prefix: string;\n  #renderedPrefix: string;\n\n  /**\n   * Instantiates a logger.\n   *\n   * @param minLevel minimum log level\n   * @param prefix   prefix for log lines from this logger (optional)\n   */\n  public constructor(minLevel: LogLevel, prefix?: string) {\n    this.#minLevel = minLevel;\n    this.#prefix = prefix ?? \"\";\n    this.#renderedPrefix = prefix ? `[${prefix}]` : \"\";\n  }\n\n  /**\n   * Derives a sub-logger from this logger.\n   *\n   * Prefix of new logger will inherit prefix of this logger, and `subPrefix` will be appended to it.\n   */\n  public subLogger(subPrefix: string): DebugLogger {\n    return this.#prefix\n      ? new DebugLogger(this.#minLevel, `${this.#prefix}:${subPrefix}`)\n      : new DebugLogger(this.#minLevel, subPrefix);\n  }\n\n  /**\n   * Emits log with the specified level.\n   */\n  public log(lv: BasicLogLevel, msg: unknown, ...optionalParams: unknown[]) {\n    if (scoreForlogLevel[lv] < scoreForlogLevel[this.#minLevel]) {\n      return;\n    }\n    this.#renderedPrefix\n      ? logFnForlogLevel[lv](`${this.#renderedPrefix} ${msg}`, ...optionalParams)\n      : logFnForlogLevel[lv](msg, ...optionalParams);\n  }\n}\n","import type { LogLevel } from \"./debugLogger\";\nimport type { EventVerifier, Filter, NostrEvent } from \"./nostr\";\n\nexport type EnsureRelaysOptions = {\n  connectTimeoutMs: number;\n};\n\nexport type FetchTillEoseOptions = {\n  subId?: string;\n  eventVerifier: EventVerifier;\n  skipVerification: boolean;\n  skipFilterMatching: boolean;\n  connectTimeoutMs: number;\n  abortSubBeforeEoseTimeoutMs: number;\n  signal: AbortSignal | undefined;\n};\n\n/**\n * Set of APIs to fetch past events from nostr relays.\n *\n * `NostrFetcher` implements its functions on top of this.\n */\nexport interface NostrFetcherBackend {\n  /**\n   * Ensures connections to the relays prior to an event subscription.\n   *\n   * Returns URLs of relays *successfully connected to*.\n   *\n   * It should *normalize* the passed `relayUrls` before establishing connections to relays.\n   *\n   * Hint:\n   * You should make use of the function `normalizeRelayUrlSet` from `@nostr-fetch/kernel/utils` to normalize a set of relay URLs.\n   *\n   */\n  ensureRelays(relayUrls: string[], options: EnsureRelaysOptions): Promise<string[]>;\n\n  /**\n   * Fetches Nostr events matching `filters` from the relay specified by `relayUrl` until EOSE.\n   *\n   * The result is an `AsyncIterable` of Nostr events.\n   * You can think that it's an asynchronous channel which conveys events.\n   * The channel will be closed once EOSE is reached.\n   *\n   * If one of the following situations occurs, it is regarded as \"failure\".\n   * In such a case, it should throw `FetchTillEoseFailedSignal`.\n   *\n   * - It couldn't establish connection to the relay\n   * - Received a NOTICE message during the fetch\n   * - A WebSocket error occurred during the fetch\n   *\n   *\n   * If the fetch was aborted (due to AbortController or auto abortion timer), it should throw `FetchTillEoseAbortedSignal`.\n   *\n   * Hint:\n   * You can make use of a `Channel` to convert \"push\" style code (bunch of event listers) to `AsyncIterable`.\n   */\n  fetchTillEose(\n    relayUrl: string,\n    filter: Filter,\n    options: FetchTillEoseOptions,\n  ): AsyncIterable<NostrEvent>;\n\n  /**\n   * Cleans up all the internal states of the fetcher.\n   */\n  shutdown(): void;\n}\n\n/**\n * Error type signaling that `NostrFetcherBackend#fetchTillEose()` failed\n * (connection was not established / NOTICE received / WebSocket error occurred)\n */\nexport class FetchTillEoseFailedSignal extends Error {\n  static {\n    FetchTillEoseFailedSignal.prototype.name = \"FetchTillEoseFailedSignal\";\n  }\n}\n\n/**\n * Error type signaling that `NostrFetcherBackend#fetchTillEose()` is aborted (due to AbortController or auto abortion)\n */\nexport class FetchTillEoseAbortedSignal extends Error {\n  static {\n    FetchTillEoseAbortedSignal.prototype.name = \"FetchTillEoseAbortedSignal\";\n  }\n}\n\n/**\n * Check if `err` is {@linkcode FetchTillEoseFailedSignal}.\n *\n * Note that you can't check that using `instanceof` operator.\n */\nexport const isFetchTillEoseFailedSignal = (err: unknown): err is FetchTillEoseFailedSignal =>\n  err instanceof Error && err.name === \"FetchTillEoseFailedSignal\";\n\n/**\n * Check if `err` is {@linkcode FetchTillEoseAbortedSignal}.\n *\n * Note that you can't check that using `instanceof` operator.\n */\nexport const isFetchTillEoseAbortedSignal = (err: unknown): err is FetchTillEoseAbortedSignal =>\n  err instanceof Error && err.name === \"FetchTillEoseAbortedSignal\";\n\n/**\n * Common options for `NostrFetcher` and all `NostrFetcherBackend` implementations.\n */\nexport type NostrFetcherCommonOptions = {\n  minLogLevel?: LogLevel;\n};\n\n/**\n * Default values of `NostrFetcherCommonOptions`.\n */\nexport const defaultFetcherCommonOptions: Required<NostrFetcherCommonOptions> = {\n  minLogLevel: \"warn\",\n};\n\n/**\n * Type of initializer functions of `NostrFetcherBackend`s.  Takes `NostrFetcherCommonOptions` and initialize a `NostrFetcherBackend` impl.\n *\n * A \"relay pool adapter\" should return initializer function of this type.\n */\nexport type NostrFetcherBackendInitializer = (\n  commonOpts: Required<NostrFetcherCommonOptions>,\n) => NostrFetcherBackend;\n","/**\n * The data structure of Nostr event.\n */\nexport type NostrEvent = {\n  id: string;\n  pubkey: string;\n  created_at: number;\n  kind: number;\n  tags: string[][];\n  content: string;\n  sig: string;\n};\n\n/**\n * Standardized Nostr event kinds.\n * cf. https://github.com/nostr-protocol/nips#event-kinds\n *\n * @deprecated use literal kind numbers instead.\n */\nexport const eventKind = {\n  metadata: 0,\n  text: 1,\n  recommendRelay: 2,\n  contacts: 3,\n  encryptedDirectMessage: 4,\n  eventDeletion: 5,\n  repost: 6,\n  reaction: 7,\n  badgeAward: 8,\n  genericRepost: 16,\n  channelCreation: 40,\n  channelMetadata: 41,\n  channelMessage: 42,\n  channelHideMessage: 43,\n  channelMuteUser: 44,\n  fileMetadata: 1063,\n  liveChatMessage: 1311,\n  report: 1984,\n  label: 1985,\n  communityPostApproval: 4550,\n  zapRequest: 9734,\n  zap: 9735,\n  muteList: 10000,\n  pinList: 10001,\n  relayList: 10002,\n  walletInfo: 13194,\n  clientAuth: 22242,\n  walletRequest: 23194,\n  walletResponse: 23195,\n  nostrConnect: 24133,\n  httpAuth: 27235,\n  categorizedPeopleList: 30000,\n  categorizedBookmarkList: 30001,\n  profileBadges: 30008,\n  badgeDefinition: 30009,\n  marketplaceStall: 30017,\n  marketplaceProduct: 30018,\n  article: 30023,\n  draftArticle: 30024,\n  appSpecificData: 30078,\n  liveEvent: 30311,\n  classifiedListing: 30402,\n  draftClassifiedListing: 30403,\n  dateBasedCalendarEvent: 31922,\n  timeBasedCalendarEvent: 31923,\n  calendar: 31924,\n  calendarEventRsvp: 31925,\n  handlerRecommendation: 31989,\n  handlerInformation: 31990,\n  communityDefinition: 34550,\n} as const;\n\n/**\n * Keys of filter props for tag queries.\n */\ntype TagQueryKey = `#${string}`;\n\n// [A-Za-z]\nconst isLatinAlphabet = (charCode: number) =>\n  (0x41 <= charCode && charCode <= 0x5a) || (0x61 <= charCode && charCode <= 0x7a);\n\n/**\n * Checks if the given string is a \"queryable\" tag name.\n */\nconst isQueryableTagName = (s: string): boolean =>\n  s.length === 1 && isLatinAlphabet(s.charCodeAt(0));\n\n/**\n * Checks if the given string is a valid key of tag query in filter.\n *\n * A valid tag query key is a string that starts with `#` and followed by a single Latin alphabet (`[A-Za-z]`).\n */\nexport const isValidTagQueryKey = (s: string): boolean =>\n  s.startsWith(\"#\") && isQueryableTagName(s.substring(1));\n\n/**\n * Filter for Nostr event subscription.\n */\nexport type Filter = {\n  ids?: string[];\n  kinds?: number[];\n  authors?: string[];\n  since?: number;\n  until?: number;\n  limit?: number;\n  search?: string;\n} & {\n  [tag in TagQueryKey]: string[];\n};\n\n// client to relay messages\ntype C2RReq = [type: \"REQ\", subId: string, ...filters: Filter[]];\ntype C2RClose = [type: \"CLOSE\", subId: string];\n\nexport type C2RMessage = C2RReq | C2RClose;\nexport type C2RMessageType = C2RMessage[0];\n\n// relay to client messages\ntype R2CEvent = [type: \"EVENT\", subId: string, event: NostrEvent];\ntype R2CEose = [type: \"EOSE\", subId: string];\ntype R2CClosed = [type: \"CLOSED\", subId: string, message: string];\ntype R2CNotice = [type: \"NOTICE\", notice: string];\n\nexport type R2CMessage = R2CEvent | R2CEose | R2CClosed | R2CNotice;\nexport type R2CMessageType = R2CMessage[0];\n\nexport type R2CSubMessage = R2CEvent | R2CEose;\nexport type R2CSubMessageType = R2CSubMessage[0];\n\nconst supportedR2CMsgTypes: R2CMessageType[] = [\"EVENT\", \"EOSE\", \"CLOSED\", \"NOTICE\"];\nconst isSupportedR2CMsgType = (s: string): s is R2CMessageType =>\n  (supportedR2CMsgTypes as string[]).includes(s);\n\nexport const parseR2CMessage = (rawMsg: string): R2CMessage | undefined => {\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(rawMsg) as unknown;\n  } catch (err) {\n    console.error(\"failed to parse R2C message as JSON:\", err);\n    return undefined;\n  }\n\n  if (!Array.isArray(parsed) || parsed.length === 0 || typeof parsed[0] !== \"string\") {\n    console.error(\"malformed R2C message\");\n    return undefined;\n  }\n\n  const msgType = parsed[0] as string;\n  if (!isSupportedR2CMsgType(msgType)) {\n    console.error(\"unsupported R2C message type:\", parsed[0]);\n    return undefined;\n  }\n  switch (msgType) {\n    case \"EVENT\": {\n      if (parsed.length !== 3) {\n        console.error(\"malformed R2C EVENT\");\n        return undefined;\n      }\n      const [, subId, ev] = parsed;\n      if (typeof subId !== \"string\" || typeof ev !== \"object\" || ev === null) {\n        console.error(\"malformed R2C EVENT\");\n        return undefined;\n      }\n      if (!validateEvent(ev)) {\n        console.error(\"malformed event in R2C EVENT\");\n        return undefined;\n      }\n      return parsed as R2CEvent;\n    }\n    case \"EOSE\": {\n      if (parsed.length !== 2 || typeof parsed[1] !== \"string\") {\n        console.error(\"malformed R2C EOSE\");\n        return undefined;\n      }\n      return parsed as R2CEose;\n    }\n    case \"CLOSED\": {\n      if (parsed.length !== 3 || typeof parsed[1] !== \"string\" || typeof parsed[2] !== \"string\") {\n        console.error(\"malformed R2C CLOSED\");\n        return undefined;\n      }\n      return parsed as R2CClosed;\n    }\n    case \"NOTICE\": {\n      if (parsed.length !== 2) {\n        console.error(\"malformed R2C NOTICE\");\n        return undefined;\n      }\n      return parsed as R2CNotice;\n    }\n    default:\n      return undefined;\n  }\n};\n\n// schema validation for Nostr events\nexport const validateEvent = (rawEv: Record<string, unknown>): rawEv is NostrEvent => {\n  // id: 32-bytes lowercase hex-encoded sha256\n  if (!(\"id\" in rawEv) || typeof rawEv[\"id\"] !== \"string\" || !is32BytesHexStr(rawEv[\"id\"])) {\n    return false;\n  }\n\n  // pubkey: 32-bytes lowercase hex-encoded public key\n  if (\n    !(\"pubkey\" in rawEv) ||\n    typeof rawEv[\"pubkey\"] !== \"string\" ||\n    !is32BytesHexStr(rawEv[\"pubkey\"])\n  ) {\n    return false;\n  }\n\n  // created_at: unix timestamp in seconds\n  if (!(\"created_at\" in rawEv) || typeof rawEv[\"created_at\"] !== \"number\") {\n    return false;\n  }\n\n  // kind: integer\n  if (!(\"kind\" in rawEv) || typeof rawEv[\"kind\"] !== \"number\") {\n    return false;\n  }\n\n  // tags: array of arrays of non-null strings\n  if (!(\"tags\" in rawEv) || !Array.isArray(rawEv[\"tags\"])) {\n    return false;\n  }\n  if (rawEv[\"tags\"].some((tag) => !Array.isArray(tag) || tag.some((e) => typeof e !== \"string\"))) {\n    return false;\n  }\n\n  // content: string\n  if (!(\"content\" in rawEv) || typeof rawEv[\"content\"] !== \"string\") {\n    return false;\n  }\n\n  // sig: 64-bytes hex of the signature\n  if (!(\"sig\" in rawEv) || typeof rawEv[\"sig\"] !== \"string\" || !is64BytesHexStr(rawEv[\"sig\"])) {\n    return false;\n  }\n\n  return true;\n};\n\nconst is32BytesHexStr = (s: string): boolean => {\n  return /^[a-f0-9]{64}$/.test(s);\n};\n\nconst is64BytesHexStr = (s: string): boolean => {\n  return /^[a-f0-9]{128}$/.test(s);\n};\n\n/**\n * Type of functions that verify the signature of the Nostr event.\n */\nexport type EventVerifier = (event: NostrEvent) => boolean | Promise<boolean>;\n\n/**\n * no-op `EventVerifier` which regards all events have a valid signature.\n *\n * @example\n * // emulating `skipVerification: true`\n * import { NostrFetcher, noopVerifier } from \"nostr-fetch\";\n *\n * const fetcher = NostrFetcher.init();\n * const events = fetcher.allEventsIterator({ ... }, { ... }, { eventVerifier: noopVerifier });\n */\nexport const noopVerifier: EventVerifier = (_: NostrEvent) => true;\n\ntype CompiledFilter = {\n  ids: Set<string> | undefined;\n  kinds: Set<number> | undefined;\n  authors: Set<string> | undefined;\n  tags: [string, Set<string>][];\n  since: number | undefined;\n  until: number | undefined;\n};\n\nconst compileFilter = (f: Filter): CompiledFilter => {\n  const ids = f.ids ? new Set(f.ids) : undefined;\n  const kinds = f.kinds ? new Set(f.kinds) : undefined;\n  const authors = f.authors ? new Set(f.authors) : undefined;\n\n  const tags: [string, Set<string>][] = [];\n  for (const k of Object.keys(f)) {\n    if (k.startsWith(\"#\") && k.length === 2) {\n      tags.push([k.charAt(1), new Set(f[k as TagQueryKey] ?? [])] as [string, Set<string>]);\n    }\n  }\n  return { ids, kinds, authors, tags, since: f.since, until: f.until };\n};\n\nconst getTagValuesByName = (ev: NostrEvent, tagName: string): string[] =>\n  ev.tags.filter((t) => t[0] === tagName).map((t) => t[1] ?? \"\");\n\nconst matchWithCompiledFilter = (f: CompiledFilter, ev: NostrEvent): boolean => {\n  if (f.ids !== undefined && !f.ids.has(ev.id)) {\n    return false;\n  }\n  if (f.kinds !== undefined && !f.kinds.has(ev.kind)) {\n    return false;\n  }\n  if (f.authors !== undefined && !f.authors.has(ev.pubkey)) {\n    return false;\n  }\n  if (f.since !== undefined && ev.created_at < f.since) {\n    return false;\n  }\n  if (f.until !== undefined && ev.created_at > f.until) {\n    return false;\n  }\n  const tagMatched = f.tags.every(([tagName, queryVals]) => {\n    const tagVals = getTagValuesByName(ev, tagName);\n    if (tagVals.length === 0) {\n      // required tag is missing\n      return false;\n    }\n    return tagVals.some((e) => queryVals.has(e));\n  });\n  return tagMatched;\n};\n\nexport class FilterMatcher {\n  #filters: CompiledFilter[];\n\n  constructor(filters: Filter[]) {\n    this.#filters = filters.map(compileFilter);\n  }\n\n  public match(ev: NostrEvent): boolean {\n    return this.#filters.some((f) => matchWithCompiledFilter(f, ev));\n  }\n}\n\n/* Check Relay's Capabilities */\n/**\n * Queries supported NIP numbers of the given relay.\n */\nexport const querySupportedNips = async (relayUrl: string): Promise<Set<number>> => {\n  try {\n    const httpUrl = toHttpUrl(relayUrl);\n\n    const resp = await fetch(httpUrl, {\n      headers: { Accept: \"application/nostr+json\" },\n      signal: AbortSignal.timeout(5000),\n    });\n\n    if (!resp.ok) {\n      console.error(\"relay information response is not ok\");\n      return new Set();\n    }\n\n    const relayInfo = await resp.json();\n    if (!relayInfoHasSupportedNips(relayInfo)) {\n      console.error(\"relay information document doesn't have proper 'supported_nips' property\");\n      return new Set();\n    }\n    return new Set(relayInfo.supported_nips);\n  } catch (err) {\n    console.error(err);\n    return new Set();\n  }\n};\n\nconst toHttpUrl = (url: string): string => {\n  const u = new URL(url);\n  switch (u.protocol) {\n    case \"wss:\":\n      u.protocol = \"https:\";\n      break;\n    case \"ws:\":\n      u.protocol = \"http:\";\n      break;\n  }\n  return u.toString();\n};\n\ntype RelayInfoWithSupportedNips = {\n  supported_nips: number[];\n};\n\nconst relayInfoHasSupportedNips = (relayInfo: unknown): relayInfo is RelayInfoWithSupportedNips =>\n  typeof relayInfo === \"object\" &&\n  relayInfo !== null &&\n  \"supported_nips\" in relayInfo &&\n  Array.isArray(relayInfo.supported_nips) &&\n  (relayInfo.supported_nips.length === 0 ||\n    relayInfo.supported_nips.every((e: unknown) => typeof e === \"number\"));\n\n/* Utilities */\n// utility to generate a random subscription ID\nexport const generateSubId = () => {\n  return Date.now().toString() + Math.random().toString(32).substring(2, 4);\n};\n\nconst reqErrRegexps = [\n  /^too many concurrent REQs$/i,\n  /^Subscription rejected/i,\n  /^invalid:(.*)must (contain|be) less than or equal to/i,\n  /^message too large$/i,\n  /^Maximum concurrent subscription count reached$/i,\n];\n\n/**\n * Checks if the NOTICE message seems to have to do with REQs by fetcher.\n *\n * Considers following relay implementations:\n *\n * - strfry\n * - nostream\n * - nostr-rs-relay\n * - relayer\n */\nexport const isNoticeForReqError = (notice: string): boolean =>\n  reqErrRegexps.some((r) => r.test(notice));\n","/**\n * Current unxitime in milliseconds.\n */\nexport const currUnixtimeMilli = (now = new Date()): number => now.getTime();\n\n/**\n * Current unixtime in seconds.\n */\nexport const currUnixtimeSec = (now = new Date()): number =>\n  Math.floor(currUnixtimeMilli(now) / 1000);\n\n// borrowed from nostr-tools (https://github.com/nbd-wtf/nostr-tools).\n/**\n * Normalizes single URL of relay (WebSocket endpoint).\n * @param urlStr\n * @returns\n */\nexport const normalizeRelayUrl = (urlStr: string): string => {\n  const url = new URL(urlStr);\n\n  url.pathname = url.pathname.replace(/\\/+/g, \"/\");\n  if (url.pathname.endsWith(\"/\")) {\n    url.pathname = url.pathname.slice(0, -1);\n  }\n\n  if (\n    (url.port === \"80\" && url.protocol === \"ws:\") ||\n    (url.port === \"443\" && url.protocol === \"wss:\")\n  ) {\n    url.port = \"\";\n  }\n\n  url.searchParams.sort();\n  url.hash = \"\";\n  return url.toString();\n};\n\nconst dedup = <T>(items: T[]): T[] => {\n  return Array.from(new Set(items));\n};\n\n/**\n * Normalizes all relay URLs, then removes duplications.\n *\n * It also filters out malformed URLs.\n */\nexport const normalizeRelayUrlSet = (relayUrls: string[]): string[] => {\n  return dedup(\n    relayUrls\n      .filter((u) => {\n        try {\n          new URL(u);\n          return true;\n        } catch {\n          return false;\n        }\n      })\n      .map((u) => normalizeRelayUrl(u)),\n  );\n};\n\n/**\n *  Empty AsyncGenerator\n */\n// biome-ignore lint/correctness/useYield: we want empty generator so it's fine\nexport async function* emptyAsyncGen() {\n  return;\n}\n\n/**\n * Abbreviates strings as:\n * <first `affixLen` chars of `s`> + \":\" + <last `affixLen` chars of `s`>\n *\n * if `s.length` is less than `affixLen * 2` or `affixLen` is not positive, just returns original string.\n */\nexport const abbreviate = (s: string, affixLen: number): string => {\n  if (s.length <= affixLen * 2 || affixLen <= 0) {\n    return s;\n  }\n  const len = s.length;\n  return `${s.slice(0, affixLen)}:${s.slice(len - affixLen)}`;\n};\n\n/**\n * Attaches timeout to the `promise`.\n *\n * If the `promise` is not settled by the time limit, returned promise rejects with the error which has the specified message.\n */\nexport const withTimeout = async <T>(\n  promise: Promise<T>,\n  timeoutMs: number,\n  msgOnTimeout: string,\n): Promise<T> => {\n  let timer: ReturnType<typeof setTimeout>;\n  const timeout = new Promise<never>((_, reject) => {\n    timer = setTimeout(() => reject(Error(msgOnTimeout)), timeoutMs);\n  });\n\n  return Promise.race([promise.finally(() => clearTimeout(timer)), timeout]);\n};\n","import type { C2RMessage, EventVerifier, Filter, NostrEvent } from \"@nostr-fetch/kernel/nostr\";\nimport { FilterMatcher, generateSubId, parseR2CMessage } from \"@nostr-fetch/kernel/nostr\";\nimport {\n  type WSCloseEvent,\n  type WSMessageEvent,\n  type WebSocketMin,\n  type WebSocketMinCtor,\n  WebSocketReadyState,\n} from \"@nostr-fetch/kernel/webSocket\";\n\ntype Callback<E> = E extends void ? () => void : (ev: E) => void;\n\nexport interface Relay {\n  url: string;\n  wsReadyState: number;\n\n  connect(): Promise<Relay>;\n  close(): void;\n  prepareSub(filters: Filter[], options: SubscriptionOptions): Subscription;\n\n  on<E extends RelayEventTypes>(type: E, cb: RelayEventCbTypes[E]): void;\n  off<E extends RelayEventTypes>(type: E, cb: RelayEventCbTypes[E]): void;\n}\n\nexport type RelayOptions = {\n  connectTimeoutMs: number;\n  webSocketConstructor: WebSocketMinCtor;\n};\n\nexport const initRelay = (relayUrl: string, options: RelayOptions): Relay => {\n  return new RelayImpl(relayUrl, options);\n};\n\nexport type RelayConnectCb = Callback<void>;\nexport type RelayDisconnectCb = Callback<WSCloseEvent | undefined>;\nexport type RelayNoticeCb = Callback<string>;\nexport type RelayErrorCb = Callback<void>;\n\nexport type RelayEventCbTypes = {\n  connect: RelayConnectCb;\n  disconnect: RelayDisconnectCb;\n  notice: RelayNoticeCb;\n  error: RelayErrorCb;\n};\n\nexport type RelayEventTypes = keyof RelayEventCbTypes;\n\ntype RelayListenersTable = {\n  [E in RelayEventTypes]: Set<RelayEventCbTypes[E]>;\n};\n\nclass RelayImpl implements Relay {\n  #relayUrl: string;\n  #ws: WebSocketMin | undefined;\n\n  #options: Required<RelayOptions>;\n\n  #listeners: RelayListenersTable = {\n    connect: new Set(),\n    disconnect: new Set(),\n    notice: new Set(),\n    error: new Set(),\n  };\n  #subscriptions: Map<string, RelaySubscription> = new Map();\n\n  #msgQueue: string[] = [];\n  #handleMsgsInterval: ReturnType<typeof setInterval> | undefined;\n\n  constructor(relayUrl: string, options: RelayOptions) {\n    this.#relayUrl = relayUrl;\n    this.#options = options;\n  }\n\n  public get url(): string {\n    return this.#relayUrl;\n  }\n\n  public get wsReadyState(): number {\n    return this.#ws?.readyState ?? WebSocketReadyState.CONNECTING;\n  }\n\n  private async forwardToSubAsync(\n    subId: string,\n    forwardFn: (sub: RelaySubscription) => Promise<void>,\n  ) {\n    const targSub = this.#subscriptions.get(subId);\n    if (targSub !== undefined) {\n      await forwardFn(targSub);\n    }\n  }\n\n  private async forwardToSub(subId: string, forwardFn: (sub: RelaySubscription) => void) {\n    const targSub = this.#subscriptions.get(subId);\n    if (targSub !== undefined) {\n      forwardFn(targSub);\n    }\n  }\n\n  private async handleMsgs() {\n    if (this.#msgQueue.length === 0) {\n      clearInterval(this.#handleMsgsInterval);\n      this.#handleMsgsInterval = undefined;\n      return;\n    }\n\n    const dispatchStartedAt = performance.now();\n\n    while (this.#msgQueue.length > 0 && performance.now() - dispatchStartedAt < 5.0) {\n      const rawMsg = this.#msgQueue.shift() as string;\n      const parsed = parseR2CMessage(rawMsg);\n      if (parsed === undefined) {\n        continue;\n      }\n\n      switch (parsed[0]) {\n        case \"EVENT\": {\n          const [, subId, ev] = parsed;\n          await this.forwardToSubAsync(subId, (sub) => sub._forwardEvent(ev));\n          break;\n        }\n        case \"EOSE\": {\n          const [, subId] = parsed;\n          this.forwardToSub(subId, (sub) => sub._forwardEose());\n          break;\n        }\n        case \"CLOSED\": {\n          const [, subId, msg] = parsed;\n          this.forwardToSub(subId, (sub) => sub._forwardClosed(msg));\n          break;\n        }\n        case \"NOTICE\": {\n          const [, notice] = parsed;\n          this.#listeners.notice.forEach((cb) => cb(notice));\n          break;\n        }\n      }\n    }\n  }\n\n  public async connect(): Promise<Relay> {\n    return new Promise<Relay>((resolve, reject) => {\n      let isTimedout = false;\n      const timeout = setTimeout(() => {\n        isTimedout = true;\n        reject(Error(`attempt to connect to the relay '${this.#relayUrl}' timed out`));\n      }, this.#options.connectTimeoutMs);\n\n      const onErrorBeforeOpen = () => {\n        reject(Error(\"WebSocket error\"));\n        clearTimeout(timeout);\n      };\n\n      const ws = new this.#options.webSocketConstructor(this.#relayUrl);\n\n      ws.addEventListener(\"open\", () => {\n        if (!isTimedout) {\n          this.#listeners.connect.forEach((cb) => cb());\n          this.#ws = ws;\n\n          // set error listeners after the connection opened successfully\n          ws.removeEventListener(\"error\", onErrorBeforeOpen);\n          ws.addEventListener(\"error\", () => {\n            this.#listeners.error.forEach((cb) => cb());\n          });\n\n          resolve(this);\n\n          clearTimeout(timeout);\n        }\n      });\n\n      // error listeners are *not* activated while attempt to connect is in progress\n      ws.addEventListener(\"error\", onErrorBeforeOpen);\n\n      ws.addEventListener(\"close\", (e: WSCloseEvent) => {\n        const reducted = {\n          code: e.code,\n          reason: e.reason,\n          wasClean: e.wasClean,\n        };\n        this.#listeners.disconnect.forEach((cb) => cb(reducted));\n      });\n\n      ws.addEventListener(\"message\", (e: WSMessageEvent) => {\n        this.#msgQueue.push(e.data);\n        if (this.#handleMsgsInterval === undefined) {\n          this.#handleMsgsInterval = setInterval(() => this.handleMsgs(), 0);\n        }\n      });\n    });\n  }\n\n  public close() {\n    if (this.#ws !== undefined) {\n      this.#ws.close();\n    }\n  }\n\n  public prepareSub(filters: Filter[], options: SubscriptionOptions): Subscription {\n    const subId = options.subId ?? generateSubId();\n    const sub = new RelaySubscription(this, subId, filters, options);\n    this.#subscriptions.set(subId, sub);\n\n    return sub;\n  }\n\n  _removeSub(subId: string) {\n    this.#subscriptions.delete(subId);\n  }\n\n  public on<E extends RelayEventTypes>(type: E, cb: RelayEventCbTypes[E]) {\n    this.#listeners[type].add(cb);\n  }\n\n  public off<E extends RelayEventTypes>(type: E, cb: RelayEventCbTypes[E]) {\n    this.#listeners[type].delete(cb);\n  }\n\n  _sendC2RMessage(msg: C2RMessage) {\n    if (this.#ws === undefined || this.#ws.readyState !== WebSocketReadyState.OPEN) {\n      throw Error(\"not connected to the relay\");\n    }\n    this.#ws.send(JSON.stringify(msg));\n  }\n}\n\ntype EoseEventPayload = {\n  aborted: boolean;\n};\n\nexport type SubEventCb = Callback<NostrEvent>;\nexport type SubEoseCb = Callback<EoseEventPayload>;\nexport type SubClosedCb = Callback<string>;\n\nexport type SubEventCbTypes = {\n  event: SubEventCb;\n  eose: SubEoseCb;\n  closed: SubClosedCb;\n};\n\nexport type SubEventTypes = keyof SubEventCbTypes;\n\nexport interface Subscription {\n  subId: string;\n  req(): void;\n  close(): void;\n  on<E extends SubEventTypes>(type: E, cb: SubEventCbTypes[E]): void;\n  off<E extends SubEventTypes>(type: E, cb: SubEventCbTypes[E]): void;\n}\n\nexport interface SubscriptionOptions {\n  subId?: string;\n  eventVerifier: EventVerifier;\n  skipVerification: boolean;\n  skipFilterMatching: boolean;\n  abortSubBeforeEoseTimeoutMs: number;\n}\n\ntype SubListenersTable = {\n  [E in SubEventTypes]: Set<SubEventCbTypes[E]>;\n};\n\nclass RelaySubscription implements Subscription {\n  #relay: RelayImpl;\n  #subId: string;\n  #filters: Filter[];\n  #filterMatcher: FilterMatcher;\n  #options: SubscriptionOptions;\n\n  #listeners: SubListenersTable = {\n    event: new Set(),\n    eose: new Set(),\n    closed: new Set(),\n  };\n\n  #abortSubTimer: ReturnType<typeof setTimeout> | undefined;\n\n  constructor(relay: RelayImpl, subId: string, filters: Filter[], options: SubscriptionOptions) {\n    this.#relay = relay;\n    this.#subId = subId;\n    this.#filters = filters;\n    this.#filterMatcher = new FilterMatcher(filters);\n    this.#options = options;\n  }\n\n  public get subId(): string {\n    return this.#subId;\n  }\n\n  public req() {\n    this.#relay._sendC2RMessage([\"REQ\", this.#subId, ...this.#filters]);\n    this.#resetAbortSubTimer();\n  }\n\n  public close() {\n    this.#clearListeners();\n    this.#relay._removeSub(this.#subId);\n\n    this.#relay._sendC2RMessage([\"CLOSE\", this.#subId]);\n  }\n\n  public on<E extends SubEventTypes>(type: E, cb: SubEventCbTypes[E]) {\n    this.#listeners[type].add(cb);\n  }\n\n  public off<E extends SubEventTypes>(type: E, cb: SubEventCbTypes[E]) {\n    this.#listeners[type].delete(cb);\n  }\n\n  #clearListeners() {\n    for (const s of Object.values(this.#listeners)) {\n      s.clear();\n    }\n    if (this.#abortSubTimer !== undefined) {\n      clearTimeout(this.#abortSubTimer);\n    }\n  }\n\n  #resetAbortSubTimer() {\n    if (this.#abortSubTimer !== undefined) {\n      clearTimeout(this.#abortSubTimer);\n      this.#abortSubTimer = undefined;\n    }\n\n    this.#abortSubTimer = setTimeout(() => {\n      this.#listeners.eose.forEach((cb) => cb({ aborted: true }));\n    }, this.#options.abortSubBeforeEoseTimeoutMs);\n  }\n\n  async _forwardEvent(ev: NostrEvent) {\n    this.#resetAbortSubTimer();\n\n    if (!this.#options.skipVerification && !(await this.#options.eventVerifier(ev))) {\n      return;\n    }\n    if (!this.#options.skipFilterMatching && !this.#filterMatcher.match(ev)) {\n      return;\n    }\n    this.#listeners.event.forEach((cb) => cb(ev));\n  }\n\n  _forwardEose() {\n    if (this.#abortSubTimer !== undefined) {\n      clearTimeout(this.#abortSubTimer);\n    }\n    this.#listeners.eose.forEach((cb) => cb({ aborted: false }));\n  }\n\n  _forwardClosed(msg: string) {\n    this.#listeners.closed.forEach((cb) => cb(msg));\n\n    // subscription has been closed by the relay -> clean up things\n    this.#clearListeners();\n    this.#relay._removeSub(this.#subId);\n  }\n}\n","import type { Relay, RelayOptions } from \"./relay\";\nimport { initRelay } from \"./relay\";\n\nimport { Deferred } from \"@nostr-fetch/kernel/channel\";\nimport { DebugLogger, type LogLevel } from \"@nostr-fetch/kernel/debugLogger\";\nimport {\n  currUnixtimeMilli,\n  normalizeRelayUrl,\n  normalizeRelayUrlSet,\n} from \"@nostr-fetch/kernel/utils\";\nimport { type WebSocketMinCtor, WebSocketReadyState } from \"@nostr-fetch/kernel/webSocket\";\n\nexport interface RelayPool {\n  ensureRelays(relayUrls: string[], relayOpts: RelayOptions): Promise<string[]>;\n  ensureSingleRelay(relayUrl: string, relayOpts: RelayOptions): Promise<Relay | undefined>;\n  shutdown(): void;\n}\n\nexport type RelayPoolOptions = {\n  minLogLevel: LogLevel;\n  webSocketConstructor: WebSocketMinCtor;\n};\n\nexport const initRelayPool = (opts: RelayPoolOptions): RelayPool => {\n  return new RelayPoolImpl(opts);\n};\n\ntype AliveRelay = {\n  state: \"alive\";\n  relayUrl: string;\n  relay: Relay;\n};\ntype ConnectingRelay = {\n  state: \"connecting\";\n  relayUrl: string;\n  wait: Promise<void>;\n};\ntype ConnectFailedRelay = {\n  state: \"connectFailed\";\n  relayUrl: string;\n  failedAt: number; // unixtime(ms)\n};\ntype DisconnectedRelay = {\n  state: \"disconnected\";\n  relayUrl: string;\n};\ntype ManagedRelay = AliveRelay | ConnectingRelay | ConnectFailedRelay | DisconnectedRelay;\n\nconst WATCHDOG_INTERVAL = 30 * 1000;\nconst WATCHDOG_CONN_TIMEOUT = 10 * 1000;\n\nclass RelayPoolImpl implements RelayPool {\n  // keys are **normalized** relay URLs\n  #relays: Map<string, ManagedRelay> = new Map();\n\n  #watchdogTimer: ReturnType<typeof setInterval>;\n  #debugLogger: DebugLogger | undefined;\n\n  constructor(options: Required<RelayPoolOptions>) {\n    if (options.minLogLevel !== \"none\") {\n      this.#debugLogger = new DebugLogger(options.minLogLevel);\n    }\n\n    // initiate a watchdog timer for relay connections\n    this.#watchdogTimer = setInterval(() => {\n      this.#debugLogger?.log(\"info\", \"watchdog started\");\n\n      const rurls = Array.from(this.#relays.keys());\n      this.addRelays(rurls, {\n        connectTimeoutMs: WATCHDOG_CONN_TIMEOUT,\n        webSocketConstructor: options.webSocketConstructor,\n      }).then(() => {\n        this.#debugLogger?.log(\"info\", \"watchdog completed\");\n      });\n    }, WATCHDOG_INTERVAL);\n  }\n\n  #relayShouldBeReconnected(relay: ManagedRelay): boolean {\n    return (\n      // TODO: make the threshold configuarable\n      (relay.state === \"connectFailed\" && currUnixtimeMilli() - relay.failedAt > 30 * 1000) ||\n      relay.state === \"disconnected\" ||\n      (relay.state === \"alive\" && relay.relay.wsReadyState === WebSocketReadyState.CLOSED) // is it possible?\n    );\n  }\n\n  // `relayUrls` should be normalized in advance.\n  private async addRelays(relayUrls: string[], relayOpts: RelayOptions): Promise<void> {\n    const relaysToConnect: string[] = [];\n    const waitsForConnect: Promise<void>[] = [];\n\n    for (const rurl of relayUrls) {\n      const r = this.#relays.get(rurl);\n      if (r === undefined || this.#relayShouldBeReconnected(r)) {\n        relaysToConnect.push(rurl);\n      } else if (r.state === \"connecting\") {\n        waitsForConnect.push(r.wait);\n      }\n    }\n\n    await Promise.all([\n      ...relaysToConnect.map(async (rurl): Promise<void> => {\n        const logger = this.#debugLogger?.subLogger(rurl);\n\n        const deferred = new Deferred<void>();\n        try {\n          this.#relays.set(rurl, { state: \"connecting\", relayUrl: rurl, wait: deferred.promise });\n\n          const r = initRelay(rurl, relayOpts);\n          r.on(\"connect\", () => logger?.log(\"info\", \"connected\"));\n          r.on(\"disconnect\", (ev) => {\n            logger?.log(\"info\", `disconnected: ${JSON.stringify(ev)}`);\n            this.#relays.set(r.url, { state: \"disconnected\", relayUrl: r.url });\n          });\n          r.on(\"error\", () => {\n            logger?.log(\"error\", \"WebSocket error\");\n            this.#relays.set(r.url, { state: \"disconnected\", relayUrl: r.url });\n          });\n          r.on(\"notice\", (notice) => logger?.log(\"warn\", `NOTICE: ${notice}`));\n\n          await r.connect();\n          this.#relays.set(rurl, { state: \"alive\", relayUrl: rurl, relay: r });\n        } catch {\n          logger?.log(\"error\", \"failed to connect to the relay\");\n          this.#relays.set(rurl, {\n            state: \"connectFailed\",\n            relayUrl: rurl,\n            failedAt: currUnixtimeMilli(),\n          });\n        } finally {\n          deferred.resolve();\n        }\n      }),\n      ...waitsForConnect,\n    ]);\n  }\n\n  public async ensureRelays(relayUrls: string[], relayOpts: RelayOptions): Promise<string[]> {\n    const normalizedUrls = normalizeRelayUrlSet(relayUrls);\n    await this.addRelays(normalizedUrls, relayOpts);\n\n    const connectedRelays: string[] = [];\n    for (const rurl of normalizedUrls) {\n      const r = this.#relays.get(rurl);\n      if (r !== undefined && r.state === \"alive\") {\n        connectedRelays.push(r.relay.url);\n      }\n    }\n    return connectedRelays;\n  }\n\n  public async ensureSingleRelay(\n    relayUrl: string,\n    relayOpts: RelayOptions,\n  ): Promise<Relay | undefined> {\n    const normalizedUrl = normalizeRelayUrl(relayUrl);\n    await this.addRelays([normalizedUrl], relayOpts);\n\n    const r = this.#relays.get(normalizedUrl);\n    if (r !== undefined && r.state === \"alive\") {\n      return r.relay;\n    }\n    return undefined;\n  }\n\n  /**\n   * Cleans up all the internal states of the fetcher.\n   *\n   * It also closes all the connections to the relays.\n   */\n  public shutdown() {\n    clearInterval(this.#watchdogTimer);\n\n    for (const [, r] of this.#relays) {\n      if (r.state === \"alive\") {\n        r.relay.close();\n      }\n    }\n    this.#relays.clear();\n  }\n}\n","import { Channel } from \"@nostr-fetch/kernel/channel\";\nimport { DebugLogger } from \"@nostr-fetch/kernel/debugLogger\";\nimport {\n  type EnsureRelaysOptions,\n  FetchTillEoseAbortedSignal,\n  FetchTillEoseFailedSignal,\n  type FetchTillEoseOptions,\n  type NostrFetcherBackend,\n  type NostrFetcherCommonOptions,\n} from \"@nostr-fetch/kernel/fetcherBackend\";\nimport { type Filter, type NostrEvent, isNoticeForReqError } from \"@nostr-fetch/kernel/nostr\";\nimport type { WebSocketMinCtor } from \"@nostr-fetch/kernel/webSocket\";\nimport { type RelayPool, initRelayPool } from \"./relayPool\";\n\nexport type DefaultFetcherBackendOptions = {\n  webSocketConstructor?: WebSocketMinCtor;\n};\n\nexport const defaultDefaultFetcherBackendOptions: Required<DefaultFetcherBackendOptions> = {\n  webSocketConstructor: globalThis.WebSocket,\n};\n\n/**\n * Default implementation of `NostrFetchBackend`.\n */\nexport class DefaultFetcherBackend implements NostrFetcherBackend {\n  #relayPool: RelayPool;\n  #wsCtor: WebSocketMinCtor;\n  #debugLogger: DebugLogger | undefined;\n\n  public constructor(opts: Required<NostrFetcherCommonOptions & DefaultFetcherBackendOptions>) {\n    this.#relayPool = initRelayPool(opts);\n    this.#wsCtor = opts.webSocketConstructor;\n    if (opts.minLogLevel !== \"none\") {\n      this.#debugLogger = new DebugLogger(opts.minLogLevel);\n    }\n  }\n\n  /**\n   * Ensures connections to the relays prior to an event subscription.\n   *\n   * Returns URLs of relays *successfully connected to*.\n   *\n   * It should *normalize* the passed `relayUrls` before establishing connections to relays.\n   */\n  public async ensureRelays(relayUrls: string[], options: EnsureRelaysOptions): Promise<string[]> {\n    return this.#relayPool.ensureRelays(relayUrls, {\n      ...options,\n      webSocketConstructor: this.#wsCtor,\n    });\n  }\n\n  /**\n   * Closes all the connections to relays and clean up the internal relay pool.\n   */\n  public shutdown(): void {\n    this.#relayPool.shutdown();\n  }\n\n  /**\n   * Fetches Nostr events matching `filters` from the relay specified by `relayUrl` until EOSE.\n   *\n   * The result is an `AsyncIterable` of Nostr events.\n   * You can think that it's an asynchronous channel which conveys events.\n   * The channel will be closed once EOSE is reached.\n   *\n   * If one of the following situations occurs, it is regarded as \"failure\".\n   * In such a case, it should throw `FetchTillEoseFailedSignal`.\n   *\n   * - It couldn't establish connection to the relay\n   * - Received a NOTICE message during the fetch\n   * - A WebSocket error occurred during the fetch\n   *\n   * If the fetch was aborted (due to AbortController or auto abortion timer), it should throw `FetchTillEoseAbortedSignal`.\n   */\n  public async *fetchTillEose(\n    relayUrl: string,\n    filter: Filter,\n    options: FetchTillEoseOptions,\n  ): AsyncIterable<NostrEvent> {\n    const logger = this.#debugLogger?.subLogger(relayUrl);\n\n    const relay = await this.#relayPool.ensureSingleRelay(relayUrl, {\n      connectTimeoutMs: options.connectTimeoutMs,\n      webSocketConstructor: this.#wsCtor,\n    });\n    if (relay === undefined) {\n      throw new FetchTillEoseFailedSignal(\"failed to ensure connection to the relay\");\n    }\n\n    const [tx, chIter] = Channel.make<NostrEvent>();\n\n    // relay error handlings\n    const onNotice = (n: string) => {\n      // ignore if the message seems to have nothing to do with REQs by fetcher\n      if (!isNoticeForReqError(n)) {\n        return;\n      }\n\n      try {\n        sub.close();\n      } catch (err) {\n        logger?.log(\"error\", `failed to close subscription (id: ${sub.subId}): ${err}`);\n      }\n      removeRelayListeners();\n      tx.error(new FetchTillEoseFailedSignal(`NOTICE: ${n}`));\n    };\n    const onError = () => {\n      // WebSocket error closes the connection, so calling close() is meaningless\n      removeRelayListeners();\n      tx.error(new FetchTillEoseFailedSignal(\"WebSocket error\"));\n    };\n    const removeRelayListeners = () => {\n      relay.off(\"notice\", onNotice);\n      relay.off(\"error\", onError);\n    };\n\n    relay.on(\"notice\", onNotice);\n    relay.on(\"error\", onError);\n\n    // prepare a subscription\n    const sub = relay.prepareSub([filter], options);\n\n    // handle subscription events\n    sub.on(\"event\", (ev: NostrEvent) => {\n      tx.send(ev);\n    });\n    sub.on(\"eose\", ({ aborted }) => {\n      closeSub();\n      if (aborted) {\n        tx.error(\n          new FetchTillEoseAbortedSignal(\n            `subscription (id: ${sub.subId}) aborted before EOSE due to timeout`,\n          ),\n        );\n      } else {\n        tx.close();\n      }\n    });\n    sub.on(\"closed\", (msg) => {\n      tx.error(\n        new FetchTillEoseFailedSignal(`subscription (id: ${sub.subId}) closed by relay: ${msg}`),\n      );\n    });\n\n    // common process to close subscription\n    const closeSub = () => {\n      try {\n        sub.close();\n      } catch (err) {\n        logger?.log(\"error\", `failed to close subscription (id: ${sub.subId}): ${err}`);\n      }\n      removeRelayListeners();\n      logger?.log(\"verbose\", `CLOSE: subId=${options.subId ?? \"<auto>\"}`);\n    };\n\n    // start the subscription\n    logger?.log(\"verbose\", `REQ: subId=${options.subId ?? \"<auto>\"}, filter=%O`, filter);\n    try {\n      sub.req();\n    } catch (err) {\n      tx.error(new FetchTillEoseFailedSignal(\"failed to send REQ\", { cause: err }));\n      removeRelayListeners();\n    }\n\n    // handle abortion\n    if (options.signal?.aborted) {\n      closeSub();\n      tx.error(\n        new FetchTillEoseAbortedSignal(\n          `subscription (id: ${sub.subId}) aborted by AbortController`,\n        ),\n      );\n    }\n    options.signal?.addEventListener(\"abort\", () => {\n      closeSub();\n      tx.error(\n        new FetchTillEoseAbortedSignal(\n          `subscription (id: ${sub.subId}) aborted by AbortController`,\n        ),\n      );\n    });\n\n    yield* chIter;\n  }\n}\n","import type { Filter } from \"@nostr-fetch/kernel/nostr\";\n\n/**\n * Structure of Nostr event filter except `limit`, `since` and `until`.\n */\nexport type FetchFilter = Omit<Filter, \"limit\" | \"since\" | \"until\">;\n\nexport type FetchFilterKeyName = keyof Omit<FetchFilter, \"search\">;\n\nexport type FetchFilterKeyElem<K extends FetchFilterKeyName> = Exclude<\n  FetchFilter[K],\n  undefined\n>[number];\n\n/**\n * Pair of timestamps which specifies time range of events to fetch.\n */\nexport type FetchTimeRangeFilter = Pick<Filter, \"since\" | \"until\">;\n\n/**\n * Type of errors that can be thrown from `NostrFetcher` methods.\n */\nexport class NostrFetchError extends Error {\n  static {\n    NostrFetchError.prototype.name = \"NostrFetchError\";\n  }\n}\n\n/* stats */\n\n/**\n * Status of relays during a fetch.\n *\n * Legend:\n *\n * - `fetching`: the fetcher is actively fetching events from the relay\n * - `completed`: the fetcher have fetched enough events from the relay\n * - `aborted`: Fetching from the relay is aborted\n * - `failed`: An error occurred during fetching from the relay\n * - `connection-failed`: An error occurred during connecting to the relay\n */\nexport type RelayStatus = \"fetching\" | \"completed\" | \"aborted\" | \"failed\" | \"connection-failed\";\n\n/**\n * Per-relay fetch statistics.\n */\nexport type RelayFetchStats = {\n  /** Status of relays during a fetch. */\n  status: RelayStatus;\n\n  /** Number of events fetched from the relay. */\n  numFetchedEvents: number;\n\n  /**\n   * \"Frontier\" of the event fetching.\n   * In other words, `created_at` of the oldest events fetched from the relay.\n   */\n  frontier: number;\n};\n\n/**\n * Various statistics of the event fetching.\n */\nexport type FetchStats = {\n  /** Elapsed time in millisecond */\n  elapsedTimeMs: number;\n  /** Overall progress of the event fetching. */\n  progress: {\n    max: number;\n    current: number;\n  };\n  /** Events and subscriptions counts. */\n  counts: {\n    /** Number of events fetched from relays so far. */\n    fetchedEvents: number;\n    /** Number of events buffered in the internal buffer. */\n    bufferedEvents: number;\n    /** Number of subscriptions opened so far. */\n    openedSubs: number;\n    /** Number of subscriptions that is running. */\n    runningSubs: number;\n  };\n  /** Per-relay fetch statistics. */\n  relays: {\n    [relayUrl: string]: RelayFetchStats;\n  };\n};\n\n/**\n * Type of functions for listening fetch statistics.\n */\nexport type FetchStatsListener = (stats: FetchStats) => void;\n","import { DebugLogger } from \"@nostr-fetch/kernel/debugLogger\";\nimport type { NostrFetcherCommonOptions } from \"@nostr-fetch/kernel/fetcherBackend\";\nimport { type NostrEvent, isValidTagQueryKey, querySupportedNips } from \"@nostr-fetch/kernel/nostr\";\nimport { normalizeRelayUrlSet } from \".\";\nimport {\n  type FetchFilter,\n  type FetchFilterKeyElem,\n  type FetchFilterKeyName,\n  type FetchStats,\n  type FetchStatsListener,\n  NostrFetchError,\n  type RelayFetchStats,\n  type RelayStatus,\n} from \"./types\";\n\ntype AssertionResult =\n  | {\n      severity: \"error\" | \"warn\";\n      msg: string;\n    }\n  | {\n      severity: \"none\";\n    };\n\n/**\n * assert `req` by `assertions`.\n *\n * If there are some errors, throws `NostrFetchError` which includes all error messages raised from assertions.\n * If there are some warnings, just log them.\n */\nexport const assertReq = <T>(\n  req: T,\n  assertions: ((req: T) => AssertionResult)[],\n  logger: DebugLogger | undefined,\n): void => {\n  const errors = [];\n  for (const assert of assertions) {\n    const res = assert(req);\n\n    switch (res.severity) {\n      case \"error\":\n        logger?.log(\"error\", `assertion error: ${res.msg}`);\n        errors.push(res.msg);\n        break;\n      case \"warn\":\n        logger?.log(\"warn\", `warning: ${res.msg}`);\n        break;\n    }\n  }\n  if (errors.length > 0) {\n    const lines = errors.map((e) => `- ${e}`).join(\"\\n\");\n    throw new NostrFetchError(`Invalid request!\\n${lines}`);\n  }\n};\n\nexport function checkIfTrue<T>(\n  predicate: (req: T) => boolean,\n  severity: \"error\" | \"warn\",\n  msg: string,\n): (req: T) => AssertionResult {\n  return (req: T) => (predicate(req) ? { severity: \"none\" } : { severity, msg });\n}\n\nexport function checkIfNonEmpty<T, U>(\n  getArray: (req: T) => U[],\n  severity: \"error\" | \"warn\",\n  msg: string,\n): (req: T) => AssertionResult {\n  return (req: T) => (getArray(req).length !== 0 ? { severity: \"none\" } : { severity, msg });\n}\n\nexport function checkIfTimeRangeIsValid<T>(\n  getTimeRange: (req: T) => { since?: number; until?: number },\n  severity: \"error\" | \"warn\",\n): (req: T) => AssertionResult {\n  return (req: T) => {\n    const { since, until } = getTimeRange(req);\n\n    if (since === undefined || until === undefined) {\n      // time range is always valid if at least one of the bounds is unbounded.\n      return { severity: \"none\" };\n    }\n    return since <= until\n      ? { severity: \"none\" }\n      : { severity, msg: \"Invalid time range (since > until)\" };\n  };\n}\n\nexport function checkIfTagQueriesAreValid<T>(\n  getFilter: (req: T) => FetchFilter,\n  severity: \"error\" | \"warn\",\n): (req: T) => AssertionResult {\n  return (req: T) => {\n    const invalidTqks = Object.keys(getFilter(req)).filter(\n      (k) => k.startsWith(\"#\") && !isValidTagQueryKey(k),\n    );\n    if (invalidTqks.length > 0) {\n      return { severity, msg: `Filter has invalid tag queries: ${invalidTqks.join(\", \")}` };\n    }\n    return { severity: \"none\" };\n  };\n}\n\n/**\n * The comparator for Nostr events. Pass it into `sort()` to sort Nostr events in \"newest to oldest\" order.\n *\n * If two events have the same `created_at`, the event with the lexicographically lower `id` should come first.\n */\nexport const compareNostrEvents = (a: NostrEvent, b: NostrEvent): number => {\n  if (a.created_at !== b.created_at) {\n    return b.created_at - a.created_at;\n  }\n  return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;\n};\n\n/**\n * get keys corresponds to `keyName` from the event.\n */\nexport const getKeysOfEvent = <K extends FetchFilterKeyName>(\n  keyName: K,\n  ev: NostrEvent,\n): FetchFilterKeyElem<K>[] => {\n  switch (keyName) {\n    case \"ids\":\n      return [ev.id];\n    case \"authors\":\n      return [ev.pubkey];\n    case \"kinds\":\n      return [ev.kind];\n  }\n  // tag key -> values of tags with the target name\n  const tagVals = ev.tags.filter((t) => t[0] === keyName.charAt(1)).map((t) => t[1] ?? \"\");\n  return [...new Set(tagVals)];\n};\n\n// type of a result of EventBuckets#add\ntype EventBucketAddResult =\n  | { state: \"open\" }\n  | { state: \"fulfilled\"; events: NostrEvent[] }\n  | { state: \"dropped\" };\n\n/**\n * Set of event buckets for each `key`, with limit on the number of events.\n */\nexport class EventBuckets<K> {\n  #buckets: Map<K, NostrEvent[]>;\n  #limitPerKey: number;\n\n  // pre-condition: `keys` should be deduped in advance.\n  constructor(keys: K[], limit: number) {\n    this.#buckets = new Map(keys.map((k) => [k, []]));\n    this.#limitPerKey = limit;\n  }\n\n  public getBucket(key: K): NostrEvent[] | undefined {\n    return this.#buckets.get(key);\n  }\n\n  /**\n   * Adds an event (`ev`) to the bucket for `key` if there is space.\n   *\n   * Returns a result with `state: \"fulfilled\"` and events if the bucket is just fulfilled by the addition, otherwise returns `state: \"open\"`.\n   *\n   * If the bucket is already full, drops the event and returns `state: \"dropped\"`.\n   */\n  public add(key: K, ev: NostrEvent): EventBucketAddResult {\n    const bucket = this.#buckets.get(key);\n    if (bucket === undefined) {\n      console.error(`bucket not found for key: ${key}`);\n      return { state: \"dropped\" };\n    }\n\n    if (bucket.length >= this.#limitPerKey) {\n      // bucket is already full\n      return { state: \"dropped\" };\n    }\n\n    // adding event\n    bucket.push(ev);\n    if (bucket.length === this.#limitPerKey) {\n      // just fulfilled!\n      return { state: \"fulfilled\", events: bucket };\n    }\n    return { state: \"open\" };\n  }\n\n  /**\n   * Calculates keys and limit for next request to a relay.\n   *\n   * * `keys`: (all keys) - (keys correspond to a full bucket)\n   * * `limit`: SUM( #(limit per key) - #(events in bucket) )\n   */\n  public calcKeysAndLimitForNextReq(): { keys: K[]; limit: number } {\n    return [...this.#buckets.entries()].reduce(\n      ({ keys, limit }, [key, bucket]) => {\n        const numEvents = bucket.length;\n        return {\n          keys: numEvents < this.#limitPerKey ? [...keys, key] : keys,\n          limit: limit + (this.#limitPerKey - numEvents),\n        };\n      },\n      { keys: [] as K[], limit: 0 },\n    );\n  }\n}\n\n/**\n * Map from all combinations of keys per relay URL in `keysPerRelay` to a value of type `V`.\n *\n * This has additional mapping from `key` in `keys` to array of values.\n */\nexport class KeyRelayMatrix<K extends string | number, V> {\n  #matrix: Map<string, V>;\n  #byKey: Map<K, V[]>;\n\n  // pre-condition: each array of `relayToKeys.values()` should be deduped in advance.\n  constructor(relayToKeys: Map<string, K[]>, initVal: () => V) {\n    this.#matrix = new Map();\n\n    const allKeys = [...new Set([...relayToKeys.values()].flat())]; // relayToKeys.values(): K[][]\n    this.#byKey = new Map(allKeys.map((k) => [k, []]));\n\n    for (const [r, keys] of relayToKeys) {\n      for (const k of keys) {\n        const v = initVal();\n\n        this.#matrix.set(this.#getKey(k, r), v);\n        this.#byKey.get(k)?.push(v);\n      }\n    }\n  }\n\n  #getKey(key: K, relayUrl: string): string {\n    return `${key}|${relayUrl}`;\n  }\n\n  public get(key: K, relayUrl: string): V | undefined {\n    return this.#matrix.get(this.#getKey(key, relayUrl));\n  }\n\n  public itemsByKey(key: K): V[] | undefined {\n    return this.#byKey.get(key);\n  }\n}\n\n/**\n * Takes an `AbortSignal` and makes a new `AbortSignal` and a \"breaker\" function.\n *\n * The signal returned is aborted when:\n * - the original signal is aborted, or\n * - the \"breaker\" function is called.\n *\n * The \"breaker\" function is designed to be called in a `finally` block:\n * ```ts\n * const f = (origSignal: AbortSignal) => {\n *   const [signal, breakSignal] = makeBreakableSignal(origSignal);\n *   try {\n *     // ...\n *   } finally {\n *     breakSignal();\n *   }\n * }\n */\nexport const makeBreakableSignal = (signal?: AbortSignal): [AbortSignal, () => void] => {\n  const ac = new AbortController();\n\n  if (signal === undefined) {\n    return [ac.signal, () => ac.abort()];\n  }\n\n  if (AbortSignal.any !== undefined) {\n    const breakable = AbortSignal.any([signal, ac.signal]);\n    return [breakable, () => ac.abort()];\n  }\n\n  const onAbort = () => {\n    ac.abort();\n  };\n  signal.addEventListener(\"abort\", onAbort, { once: true });\n  ac.signal.addEventListener(\"abort\", () => {\n    signal.removeEventListener(\"abort\", onAbort);\n  });\n  return [ac.signal, () => ac.abort()];\n};\n\nexport interface RelayCapabilityChecker {\n  relaySupportsNips(relayUrl: string, requiredNips: number[]): Promise<boolean>;\n}\n\nclass DefaultRelayCapChecker implements RelayCapabilityChecker {\n  #supportedNipsCache: Map<string, Set<number>> = new Map();\n  #debugLogger: DebugLogger | undefined;\n\n  constructor(opts: Required<NostrFetcherCommonOptions>) {\n    if (opts.minLogLevel !== \"none\") {\n      this.#debugLogger = new DebugLogger(opts.minLogLevel);\n    }\n  }\n\n  async relaySupportsNips(relayUrl: string, requiredNips: number[]): Promise<boolean> {\n    const logger = this.#debugLogger?.subLogger(relayUrl);\n\n    if (requiredNips.length === 0) {\n      return true;\n    }\n\n    const supportSetFromCache = this.#supportedNipsCache.get(relayUrl);\n    if (supportSetFromCache !== undefined) {\n      return requiredNips.every((nip) => supportSetFromCache.has(nip));\n    }\n\n    // query supported NIP's of the relay if cache doesn't have information\n    const supportSet = await querySupportedNips(relayUrl);\n    logger?.log(\"info\", `supported NIPs: ${supportSet}`);\n\n    this.#supportedNipsCache.set(relayUrl, supportSet);\n    return requiredNips.every((nip) => supportSet.has(nip));\n  }\n}\n\nexport type RelayCapCheckerInitializer = (\n  opts: Required<NostrFetcherCommonOptions>,\n) => RelayCapabilityChecker;\n\nexport const initDefaultRelayCapChecker = (opts: Required<NostrFetcherCommonOptions>) =>\n  new DefaultRelayCapChecker(opts);\n\ntype SeenEventsReportResult<SeenOn extends boolean> = {\n  hasSeen: boolean;\n  seenOn: SeenOn extends true ? string[] : undefined;\n};\n\nexport interface SeenEvents<SeenOn extends boolean> {\n  report(event: NostrEvent, relayUrl: string): SeenEventsReportResult<SeenOn>;\n  getSeenOn(eventId: string): string[];\n}\n\nexport const initSeenEvents = <SeenOn extends boolean>(withSeenOn: SeenOn): SeenEvents<SeenOn> =>\n  withSeenOn\n    ? (new SeenOnTable() as SeenEvents<SeenOn>)\n    : (new SeenEventsSet() as SeenEvents<SeenOn>);\n\nclass SeenOnTable implements SeenEvents<true> {\n  #table = new Map<string, Set<string>>();\n\n  report(event: NostrEvent, relayUrl: string): SeenEventsReportResult<true> {\n    const seenOn = this.#table.get(event.id);\n    if (seenOn !== undefined) {\n      const updated = seenOn.add(relayUrl);\n      return { hasSeen: true, seenOn: [...updated] };\n    }\n    this.#table.set(event.id, new Set([relayUrl]));\n    return { hasSeen: false, seenOn: [relayUrl] };\n  }\n\n  getSeenOn(eventId: string): string[] {\n    return [...(this.#table.get(eventId) ?? [])];\n  }\n}\n\nclass SeenEventsSet implements SeenEvents<false> {\n  #seenIds = new Set<string>();\n\n  report(event: NostrEvent, _: string): SeenEventsReportResult<false> {\n    if (this.#seenIds.has(event.id)) {\n      return { hasSeen: true, seenOn: undefined };\n    }\n    this.#seenIds.add(event.id);\n    return { hasSeen: false, seenOn: undefined };\n  }\n\n  getSeenOn(_: string): string[] {\n    return [];\n  }\n}\n\nexport class FetchStatsManager {\n  #stats: Omit<FetchStats, \"relays\" | \"elapsedTimeMs\"> = {\n    progress: {\n      max: 1, // prevent division by 0\n      current: 0,\n    },\n    counts: {\n      fetchedEvents: 0,\n      bufferedEvents: 0,\n      openedSubs: 0,\n      runningSubs: 0,\n    },\n  };\n  #startedAt: number = performance.now();\n  #relayStatsMap: Map<string, RelayFetchStats> = new Map();\n  #cb: FetchStatsListener;\n  #timer: ReturnType<typeof setInterval> | undefined;\n\n  private constructor(cb: FetchStatsListener, notifInterval: number) {\n    this.#cb = cb;\n    this.#timer = setInterval(() => {\n      this.#cb(this.#renderStats());\n    }, notifInterval);\n  }\n\n  #renderStats(): FetchStats {\n    return {\n      ...this.#stats,\n      elapsedTimeMs: performance.now() - this.#startedAt,\n      relays: Object.fromEntries(this.#relayStatsMap),\n    };\n  }\n\n  static init(\n    cb: FetchStatsListener | undefined,\n    notifIntervalMs: number,\n  ): FetchStatsManager | undefined {\n    return cb !== undefined ? new FetchStatsManager(cb, notifIntervalMs) : undefined;\n  }\n\n  /* progress */\n  setProgressMax(max: number): void {\n    this.#stats.progress.max = Math.max(max, 1);\n  }\n\n  addProgress(delta: number): void {\n    this.#stats.progress.current += delta;\n  }\n\n  setCurrentProgress(p: number): void {\n    this.#stats.progress.current = p;\n  }\n\n  /* counts */\n  eventFetched(rurl: string): void {\n    this.#stats.counts.fetchedEvents++;\n\n    // update event count of relay\n    const rs = this.#relayStatsMap.get(rurl);\n    if (rs !== undefined) {\n      rs.numFetchedEvents++;\n    }\n  }\n\n  setNumBufferedEvents(n: number): void {\n    this.#stats.counts.bufferedEvents = n;\n  }\n\n  subOpened(): void {\n    this.#stats.counts.openedSubs++;\n    this.#stats.counts.runningSubs++;\n  }\n\n  subClosed(): void {\n    this.#stats.counts.runningSubs--;\n  }\n\n  /* relay stats */\n  initRelayStats(allReleys: string[], connectedRelays: string[], initUntil: number): void {\n    const connectedSet = new Set(connectedRelays);\n    const failedRelays = normalizeRelayUrlSet(allReleys).filter((r) => !connectedSet.has(r));\n\n    console.log(allReleys, connectedRelays, failedRelays);\n\n    const connectedEntries: [string, RelayFetchStats][] = connectedRelays.map((rurl) => [\n      rurl,\n      {\n        status: \"fetching\",\n        numFetchedEvents: 0,\n        frontier: initUntil,\n      },\n    ]);\n    const failedEntries: [string, RelayFetchStats][] = failedRelays.map((rurl) => [\n      rurl,\n      {\n        status: \"connection-failed\",\n        numFetchedEvents: 0,\n        frontier: 0,\n      },\n    ]);\n\n    this.#relayStatsMap = new Map([...connectedEntries, ...failedEntries]);\n  }\n\n  setRelayStatus(rurl: string, status: RelayStatus): void {\n    const rs = this.#relayStatsMap.get(rurl);\n    if (rs !== undefined) {\n      rs.status = status;\n    }\n  }\n\n  setRelayFrontier(rurl: string, frontier: number): void {\n    const rs = this.#relayStatsMap.get(rurl);\n    if (rs !== undefined) {\n      rs.frontier = frontier;\n    }\n  }\n\n  stop(): void {\n    if (this.#timer !== undefined) {\n      clearInterval(this.#timer);\n    }\n    // notify last stats before stopped\n    this.#cb(this.#renderStats());\n  }\n}\n\n// tracks per-relay fetch progress\nexport class ProgressTracker {\n  #progressPerRelay: Map<string, number>;\n\n  constructor(relayUrls: string[]) {\n    this.#progressPerRelay = new Map(relayUrls.map((rurl) => [rurl, 0]));\n  }\n\n  addProgress(relayUrl: string, delta: number) {\n    const prev = this.#progressPerRelay.get(relayUrl) ?? 0;\n    this.#progressPerRelay.set(relayUrl, prev + delta);\n  }\n\n  setProgress(relayUrl: string, prog: number) {\n    this.#progressPerRelay.set(relayUrl, prog);\n  }\n\n  calcTotalProgress(): number {\n    return [...this.#progressPerRelay.values()].reduce((total, prog) => total + prog);\n  }\n}\n","import { Channel, Deferred } from \"@nostr-fetch/kernel/channel\";\nimport { verifyEventSig } from \"@nostr-fetch/kernel/crypto\";\nimport { DebugLogger } from \"@nostr-fetch/kernel/debugLogger\";\nimport {\n  type EnsureRelaysOptions,\n  type FetchTillEoseOptions,\n  type NostrFetcherBackend,\n  type NostrFetcherBackendInitializer,\n  type NostrFetcherCommonOptions,\n  defaultFetcherCommonOptions,\n  isFetchTillEoseAbortedSignal,\n  isFetchTillEoseFailedSignal,\n} from \"@nostr-fetch/kernel/fetcherBackend\";\nimport { type EventVerifier, type NostrEvent, isValidTagQueryKey } from \"@nostr-fetch/kernel/nostr\";\nimport { abbreviate, currUnixtimeSec, normalizeRelayUrlSet } from \"@nostr-fetch/kernel/utils\";\n\nimport {\n  DefaultFetcherBackend,\n  type DefaultFetcherBackendOptions,\n  defaultDefaultFetcherBackendOptions,\n} from \"./fetcherBackend\";\nimport {\n  EventBuckets,\n  FetchStatsManager,\n  KeyRelayMatrix,\n  ProgressTracker,\n  type RelayCapCheckerInitializer,\n  type RelayCapabilityChecker,\n  assertReq,\n  checkIfNonEmpty,\n  checkIfTagQueriesAreValid,\n  checkIfTimeRangeIsValid,\n  checkIfTrue,\n  compareNostrEvents,\n  getKeysOfEvent,\n  initDefaultRelayCapChecker,\n  initSeenEvents,\n  makeBreakableSignal,\n} from \"./fetcherHelper\";\nimport {\n  type FetchFilter,\n  type FetchFilterKeyElem,\n  type FetchFilterKeyName,\n  type FetchStatsListener,\n  type FetchTimeRangeFilter,\n  NostrFetchError,\n} from \"./types\";\n\nconst MAX_LIMIT_PER_REQ = 5000;\nconst MAX_LIMIT_PER_REQ_IN_BACKPRESSURE = 500;\n\nconst MIN_HIGH_WATER_MARK = 5000;\n\n/**\n * Nostr event with extra fields.\n */\nexport type NostrEventExt<SeenOn extends boolean = false> = NostrEvent & {\n  seenOn: SeenOn extends true ? string[] : undefined;\n};\n\n/**\n * Pair of the \"key\" of events and list of events which have that key.\n *\n * It is the type of elements of `AsyncIterable` returned from {@linkcode NostrFetcher.fetchLatestEventsPerKey}.\n */\nexport type NostrEventListWithKey<K extends FetchFilterKeyName, SeenOn extends boolean> = {\n  key: FetchFilterKeyElem<K>;\n  events: NostrEventExt<SeenOn>[];\n};\n\n/**\n * Pair of the \"key\" of an event and the event which has that key. If no event found matching the key, it will be `undefined`.\n *\n * It is the type of elements of `AsyncIterable` returned from {@linkcode NostrFetcher.fetchLastEventPerKey}.\n */\nexport type NostrEventWithKey<K extends FetchFilterKeyName, SeenOn extends boolean> = {\n  key: FetchFilterKeyElem<K>;\n  event: NostrEventExt<SeenOn> | undefined;\n};\n\n/**\n * Pair of the pubkey of event author and list of events from that author.\n *\n * It is the type of elements of `AsyncIterable` returned from {@linkcode NostrFetcher.fetchLatestEventsPerAuthor}.\n */\nexport type NostrEventListWithAuthor<SeenOn extends boolean> = {\n  author: string;\n  events: NostrEventExt<SeenOn>[];\n};\n\n/**\n * Pair of the pubkye of event author and an event from that author. If no event found from the author, it will be `undefined`.\n *\n * It is the type of elements of `AsyncIterable` returned from {@linkcode NostrFetcher.fetchLastEventPerAuthor}.\n */\nexport type NostrEventWithAuthor<SeenOn extends boolean> = {\n  author: string;\n  event: NostrEventExt<SeenOn> | undefined;\n};\n\n/**\n * Common options for all the fetch methods.\n */\nexport type FetchOptions<SeenOn extends boolean = false> = {\n  /**\n   * If specified, the fetcher uses the given function as an event signature verifier instead of the default one.\n   *\n   * The function must return `true` if the event signature is valid. Otherwise, it should return `false`.\n   *\n   * @example\n   * // How to use nostr-wasm's verifyEvent() with nostr-fetch\n   * import { NostrFetcher, type NostrEvent } from \"nostr-fetch\";\n   * import { initNostrWasm } from \"nostr-wasm\";\n   *\n   * const nw = await initNostrWasm();\n   * const nwVerifyEvent = (ev: NostrEvent) => {\n   *   try {\n   *     nw.verifyEvent(ev);\n   *     return true;\n   *   } catch {\n   *     return false;\n   *   }\n   * };\n   * const fetcher = NostrFetcher.init({\n   *   eventVerifier: nwVerifyEvent,\n   * });\n   */\n  eventVerifier?: EventVerifier;\n\n  /**\n   * If true, the fetcher skips event signature verification.\n   *\n   * Note: This option has no effect under some relay pool adapters.\n   * Check the document of the relay pool adapter you want to use.\n   *\n   * @default false\n   *\n   * @deprecated This option will be removed in nostr-fetch v1. Set the `noopVerifier` to the `eventVerifier` option instead of turning this on.\n   */\n  skipVerification?: boolean;\n\n  /**\n   * If true, the fetcher skips a check that events from relays are certainly match with filters in REQuest.\n   *\n   * By default, fetchers perform the check to protect clients from malicious relays.\n   *\n   * @default false\n   */\n  skipFilterMatching?: boolean;\n\n  /**\n   * If true, `seenOn` property is appended to every returned events.\n   * The value of `seenOn` is array of relay URLs on which the event have been seen.\n   *\n   * @default false\n   */\n  withSeenOn?: SeenOn;\n\n  /**\n   * The function for listening fetch statistics.\n   *\n   * @default undefined\n   */\n  statsListener?: FetchStatsListener | undefined;\n\n  /**\n   * How often fetch statistics is notified to the listener (specified via `statsListener`), in milliseconds.\n   *\n   * @default 1000\n   */\n  statsNotifIntervalMs?: number;\n\n  /**\n   * The maximum amount of time allowed to attempt to connect to relays, in milliseconds.\n   *\n   * @default 5000\n   */\n  connectTimeoutMs?: number;\n\n  /**\n   * The `AbortSignal` used to abort an event fetching.\n   *\n   * @default undefined\n   */\n  signal?: AbortSignal | undefined;\n\n  /**\n   * The `AbortSignal` used to abort an event fetching.\n   *\n   * @default undefined\n   *\n   * @deprecated Set `signal` option instead.\n   */\n  abortSignal?: AbortSignal | undefined;\n\n  /**\n   * The maximum amount of time to wait for events from relay before a subscription is automatically aborted before EOSE, in milliseconds.\n   *\n   * @default 10000\n   */\n  abortSubBeforeEoseTimeoutMs?: number;\n\n  /**\n   * `limit` value to be used in internal subscriptions.\n   * You may want to lower this value if relays you use have limit on value of `limit`.\n   *\n   * @default 5000\n   */\n  limitPerReq?: number;\n};\n\nconst defaultFetchOptions: Required<FetchOptions> = {\n  eventVerifier: verifyEventSig,\n  skipVerification: false,\n  skipFilterMatching: false,\n  withSeenOn: false,\n  statsListener: undefined,\n  statsNotifIntervalMs: 1000,\n  connectTimeoutMs: 5000,\n  signal: undefined,\n  abortSignal: undefined,\n  abortSubBeforeEoseTimeoutMs: 10000,\n  limitPerReq: MAX_LIMIT_PER_REQ,\n};\n\n/**\n * Options for {@linkcode NostrFetcher.allEventsIterator}.\n */\nexport type AllEventsIterOptions<SeenOn extends boolean = false> = FetchOptions<SeenOn> & {\n  /**\n   * If true, the backpressure mode is enabled.\n   *\n   * In the backpressure mode, a fetcher is automatically slowed down when the consumer of events is slower than the fetcher (producer of events).\n   *\n   * This feature may be useful for jobs like transferring events from relays to other relays.\n   *\n   * @default false\n   */\n  enableBackpressure?: boolean;\n};\n\nconst defaultAllEventsIterOptions: Required<AllEventsIterOptions> = {\n  ...defaultFetchOptions,\n  enableBackpressure: false,\n};\n\n/**\n * Options for {@linkcode NostrFetcher.fetchAllEvents}.\n */\nexport type FetchAllOptions<SeenOn extends boolean = false> = FetchOptions<SeenOn> & {\n  /**\n   * If true, resulting events are sorted in \"newest to oldest\" order.\n   *\n   * @default false\n   */\n  sort?: boolean;\n};\n\nconst defaultFetchAllOptions: Required<FetchAllOptions> = {\n  ...defaultFetchOptions,\n  sort: false,\n};\n\n/**\n * Options for \"fetch latest N events\" kind of fetchers, such as {@linkcode NostrFetcher.fetchLatestEvents}.\n */\nexport type FetchLatestOptions<SeenOn extends boolean = false> = FetchOptions<SeenOn> & {\n  /**\n   * Takes unixtime in second.  If specified, fetch latest events **as of the time**.\n   *\n   * Note: it is useful only for fetching *regular* events. Using this for replaceable events will result in an unexpected behavior.\n   */\n  asOf?: number | undefined;\n\n  /**\n   * If true, the \"reduced verification\" mode is enabled.\n   *\n   * In the reduced verification mode, event signature verification is performed only to minimum amount of events enough to ensure validity.\n   *\n   * @default false\n   *\n   * @deprecated This option will be removed in nostr-fetch v1. Fetch with `eventVerifier: noopVerifier` first, then verify fetched events by yourself.\n   */\n  reduceVerification?: boolean;\n};\n\nconst defaultFetchLatestOptions: Required<FetchLatestOptions> = {\n  ...defaultFetchOptions,\n  asOf: undefined,\n  reduceVerification: false,\n};\n\n/**\n * Type of the first argument of {@linkcode NostrFetcher.fetchLatestEventsPerAuthor}/{@linkcode NostrFetcher.fetchLastEventPerAuthor}.\n */\nexport type KeysAndRelays<K extends FetchFilterKeyName> =\n  | {\n      keys: FetchFilterKeyElem<K>[];\n      relayUrls: string[];\n    }\n  | Iterable<[key: FetchFilterKeyElem<K>, relayUrls: string[]]>;\n\n/**\n * Use same relay set for all authors\n */\ntype RelaySetForAllKeys<K extends FetchFilterKeyName> = {\n  keys: FetchFilterKeyElem<K>[];\n  relayUrls: string[];\n};\n\n/**\n * Use saperate relay set for each author.  Typically `Map<string, string[]>`\n */\ntype RelaySetsPerKey<K extends FetchFilterKeyName> = Iterable<\n  [key: FetchFilterKeyElem<K>, relayUrls: string[]]\n>;\n\nconst isRelaySetForAllKeys = <K extends FetchFilterKeyName>(\n  kr: KeysAndRelays<K>,\n): kr is RelaySetForAllKeys<K> => {\n  return \"relayUrls\" in kr && \"keys\" in kr;\n};\nconst isRelaySetsPerKey = <K extends FetchFilterKeyName>(\n  kr: KeysAndRelays<K>,\n): kr is RelaySetsPerKey<K> => {\n  return Symbol.iterator in Object(kr);\n};\n\n/**\n * Type of the first argument of {@linkcode NostrFetcher.fetchLatestEventsPerAuthor}/{@linkcode NostrFetcher.fetchLastEventPerAuthor}.\n */\nexport type AuthorsAndRelays = RelaySetForAllAuthors | RelaySetsPerAuthor;\n\n/**\n * Use same relay set for all authors\n */\ntype RelaySetForAllAuthors = {\n  authors: string[];\n  relayUrls: string[];\n};\n\n/**\n * Use saperate relay set for each author.  Typically `Map<string, string[]>`\n */\ntype RelaySetsPerAuthor = Iterable<[author: string, relayUrls: string[]]>;\n\nconst isRelaySetForAllAuthors = (a2rs: AuthorsAndRelays): a2rs is RelaySetForAllAuthors => {\n  return \"relayUrls\" in a2rs && \"authors\" in a2rs;\n};\nconst isRelaySetsPerAuthor = (a2rs: AuthorsAndRelays): a2rs is RelaySetsPerAuthor => {\n  return Symbol.iterator in Object(a2rs);\n};\n\nconst adaptAuthorsAndRelays = (ar: AuthorsAndRelays): KeysAndRelays<\"authors\"> => {\n  if (isRelaySetForAllAuthors(ar)) {\n    return { keys: ar.authors, relayUrls: ar.relayUrls };\n  }\n  if (isRelaySetsPerAuthor(ar)) {\n    return ar;\n  }\n  throw Error(\"adaptAuthorsAndRelays: unreachable\");\n};\n\n/**\n * The entry point of the Nostr event fetching.\n *\n * It sits on top of a Nostr relay pool implementation which manages connections to Nostr relays. It is recommended to reuse single `NostrFetcher` instance in entire app.\n *\n * You must instantiate `NostrFetcher` with static methods like {@linkcode NostrFetcher.init} or {@linkcode NostrFetcher.withCustomPool} instead of the constructor.\n */\nexport class NostrFetcher {\n  #backend: NostrFetcherBackend;\n  #relayCapChecker: RelayCapabilityChecker;\n  #debugLogger: DebugLogger | undefined;\n\n  private constructor(\n    backend: NostrFetcherBackend,\n    relayCapChecker: RelayCapabilityChecker,\n    initOpts: Required<NostrFetcherCommonOptions>,\n  ) {\n    this.#backend = backend;\n    this.#relayCapChecker = relayCapChecker;\n\n    if (initOpts.minLogLevel !== \"none\") {\n      this.#debugLogger = new DebugLogger(initOpts.minLogLevel);\n    }\n  }\n\n  /**\n   * Initializes {@linkcode NostrFetcher} with the default relay pool implementation.\n   *\n   * If you are on an runtime that doesn't have a native WebSocket implementation (e.g. Node.js < v22),\n   * you may want to set custom `WebSocket` constructor imported from an external package as follows:\n   *\n   * ```ts\n   * import { NostrFetcher } from \"nostr-fetch\";\n   * import WebSocket from \"ws\";\n   *\n   * const fetcher = NostrFetcher.init({\n   *   webSocketConstructor: WebSocket\n   * });\n   * ```\n   */\n  public static init(\n    options: NostrFetcherCommonOptions & DefaultFetcherBackendOptions = {},\n    initRelayCapChecker: RelayCapCheckerInitializer = initDefaultRelayCapChecker,\n  ): NostrFetcher {\n    const finalOpts = {\n      ...defaultFetcherCommonOptions,\n      ...defaultDefaultFetcherBackendOptions,\n      ...options,\n    };\n    if (finalOpts.webSocketConstructor === undefined) {\n      throw Error(\n        \"No WebSocket implementation found. Please explicitly set a custom `WebSocket` constructor to the `webSocketConstructor` option.\",\n      );\n    }\n    const backend = new DefaultFetcherBackend(finalOpts);\n    const relayCapChecker = initRelayCapChecker(finalOpts);\n    return new NostrFetcher(backend, relayCapChecker, finalOpts);\n  }\n\n  /**\n   * Initializes {@linkcode NostrFetcher} with the given adapted custom relay pool implementation.\n   *\n   * @example\n   * ```ts\n   * const pool = new SimplePool();\n   * const fetcher = NostrFetcher.withCustomPool(simplePoolAdapter(pool));\n   * ```\n   */\n  public static withCustomPool(\n    poolAdapter: NostrFetcherBackendInitializer,\n    options: NostrFetcherCommonOptions = {},\n    initRelayCapChecker: RelayCapCheckerInitializer = initDefaultRelayCapChecker,\n  ): NostrFetcher {\n    const finalOpts = { ...defaultFetcherCommonOptions, ...options };\n    const relayCapChecker = initRelayCapChecker(finalOpts);\n    return new NostrFetcher(poolAdapter(finalOpts), relayCapChecker, finalOpts);\n  }\n\n  async #ensureRelaysWithCapCheck(\n    relayUrls: string[],\n    opts: EnsureRelaysOptions,\n    requiredNips: number[],\n  ): Promise<string[]> {\n    const connectedRelays = await this.#backend.ensureRelays(relayUrls, opts);\n\n    if (requiredNips.length === 0) {\n      // if capability check is not needed, return early\n      return connectedRelays;\n    }\n\n    this.#debugLogger?.log(\"info\", `required NIPs: ${requiredNips}`);\n\n    const res: string[] = [];\n    await Promise.all(\n      connectedRelays.map(async (rurl) => {\n        if (await this.#relayCapChecker.relaySupportsNips(rurl, requiredNips)) {\n          res.push(rurl);\n        }\n      }),\n    );\n\n    this.#debugLogger?.log(\"info\", `eligible relays: ${res}`);\n    return res;\n  }\n\n  #calcRequiredNips(filter: { search?: string }): number[] {\n    const res: number[] = [];\n    if (\"search\" in filter) {\n      res.push(50); // NIP-50: Search Capability\n    }\n    return res;\n  }\n\n  /**\n   * Returns an async iterable of all events matching the filter from Nostr relays specified by the array of URLs.\n   *\n   * You can iterate over events using `for-await-of` loop.\n   *\n   * Note: there are no guarantees about the order of returned events.\n   *\n   * Throws {@linkcode NostrFetchError} if `timeRangeFilter` is invalid (`since` > `until`).\n   */\n  public allEventsIterator<SeenOn extends boolean = false>(\n    relayUrls: string[],\n    filter: FetchFilter,\n    timeRangeFilter: FetchTimeRangeFilter,\n    options: AllEventsIterOptions<SeenOn> = {},\n  ): AsyncIterable<NostrEventExt<SeenOn>> {\n    assertReq(\n      { relayUrls, filter, timeRangeFilter },\n      [\n        checkIfNonEmpty((r) => r.relayUrls, \"warn\", \"Specify at least 1 relay URL\"),\n        checkIfTagQueriesAreValid((r) => r.filter, \"error\"),\n        checkIfTimeRangeIsValid((r) => r.timeRangeFilter, \"error\"),\n      ],\n      this.#debugLogger,\n    );\n\n    const filledOpts = {\n      ...defaultAllEventsIterOptions,\n      ...options,\n    } as Required<AllEventsIterOptions<SeenOn>>;\n\n    const finalOpts: Required<AllEventsIterOptions<SeenOn>> = {\n      ...filledOpts,\n      // if only `abortSignal` is specified, copy it to `signal`\n      signal: filledOpts.signal ?? filledOpts.abortSignal,\n      // use smaller limit if backpressure is enabled\n      limitPerReq: filledOpts.enableBackpressure\n        ? Math.min(filledOpts.limitPerReq, MAX_LIMIT_PER_REQ_IN_BACKPRESSURE)\n        : filledOpts.limitPerReq,\n    };\n    this.#debugLogger?.log(\"verbose\", \"finalOpts=%O\", finalOpts);\n\n    return this.#allEventsIterWithCleanupOnBreak(relayUrls, filter, timeRangeFilter, finalOpts);\n  }\n\n  async *#allEventsIterWithCleanupOnBreak<SeenOn extends boolean>(\n    relayUrls: string[],\n    filter: FetchFilter,\n    timeRangeFilter: FetchTimeRangeFilter,\n    options: Required<AllEventsIterOptions<SeenOn>>,\n  ): AsyncIterable<NostrEventExt<SeenOn>> {\n    const [breakableSig, breakSignal] = makeBreakableSignal(options.signal);\n    try {\n      yield* this.#allEventsIterBody(relayUrls, filter, timeRangeFilter, {\n        ...options,\n        signal: breakableSig,\n      });\n    } finally {\n      // this block will be executed when:\n      // - iteration is finished normally (whether throws or not)\n      // - iteration is terminated early by break/return in a for-await-of loop\n      //\n      // in second case, breakSignal() causes the \"cleanup\" (abortion of event fetching by backend).\n      breakSignal();\n    }\n  }\n\n  async *#allEventsIterBody<SeenOn extends boolean>(\n    relayUrls: string[],\n    filter: FetchFilter,\n    timeRangeFilter: FetchTimeRangeFilter,\n    options: Required<AllEventsIterOptions<SeenOn>>,\n  ): AsyncIterable<NostrEventExt<SeenOn>> {\n    const statsMngr = FetchStatsManager.init(options.statsListener, options.statsNotifIntervalMs);\n\n    const reqNips = this.#calcRequiredNips(filter);\n    const eligibleRelayUrls = await this.#ensureRelaysWithCapCheck(relayUrls, options, reqNips);\n\n    const highWaterMark = options.enableBackpressure\n      ? Math.max(options.limitPerReq * eligibleRelayUrls.length, MIN_HIGH_WATER_MARK)\n      : undefined;\n\n    const [tx, chIter] = Channel.make<NostrEventExt<SeenOn>>({ highWaterMark });\n    const globalSeenEvents = initSeenEvents(options.withSeenOn);\n    const initialUntil = timeRangeFilter.until ?? currUnixtimeSec();\n\n    // codes for tracking progress\n    // if `since` is undefined, duration is infinite (represented by undefined)\n    const timeRangeDur =\n      timeRangeFilter.since !== undefined\n        ? Math.max(initialUntil - timeRangeFilter.since + 1, 1)\n        : undefined;\n    const progTracker = new ProgressTracker(eligibleRelayUrls);\n    statsMngr?.setProgressMax(eligibleRelayUrls.length);\n    statsMngr?.initRelayStats(relayUrls, eligibleRelayUrls, initialUntil);\n\n    // fetch events from each relay\n    Promise.all(\n      eligibleRelayUrls.map(async (rurl) => {\n        // repeat subscription until one of the following conditions is met:\n        // 1. the relay didn't return new event\n        // 2. aborted by AbortController\n        // E. an error occurred while fetching events\n\n        const logger = this.#debugLogger?.subLogger(rurl);\n\n        let nextUntil = initialUntil;\n        const localSeenEventIds = new Set<string>();\n\n        while (true) {\n          const refinedFilter = {\n            ...timeRangeFilter,\n            ...filter,\n            until: nextUntil,\n            // relays are supposed to return *latest* events by specifying `limit` explicitly (cf. [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md)).\n            // nostream doesn't accept a filter which has `limit` grater than 5000, so limit `limit` to this threshold or less.\n            limit: Math.min(options.limitPerReq, MAX_LIMIT_PER_REQ),\n          };\n          logger?.log(\"verbose\", \"refinedFilter=%O\", refinedFilter);\n\n          let gotNewEvent = false;\n          let oldestCreatedAt = Number.MAX_SAFE_INTEGER;\n\n          let isAboutToAbort = false;\n\n          try {\n            statsMngr?.subOpened();\n            for await (const e of this.#backend.fetchTillEose(rurl, refinedFilter, options)) {\n              // eliminate duplicated events\n              if (!localSeenEventIds.has(e.id)) {\n                // hasn't seen the event on this relay\n                gotNewEvent = true;\n                localSeenEventIds.add(e.id);\n                if (e.created_at < oldestCreatedAt) {\n                  oldestCreatedAt = e.created_at;\n                }\n\n                const { hasSeen, seenOn } = globalSeenEvents.report(e, rurl);\n                // `withSeenOn`: true  -> send the event even if it has already been seen in order to update seenOn\n                // `withSeenOn`: false -> send the event only if it hasn't been seen yet\n                if (options.withSeenOn || !hasSeen) {\n                  tx.send({ ...e, seenOn });\n                }\n\n                statsMngr?.eventFetched(rurl);\n                statsMngr?.setNumBufferedEvents(tx.numBufferedItems());\n              }\n            }\n          } catch (err) {\n            if (isFetchTillEoseFailedSignal(err)) {\n              // an error occurred while fetching events\n              logger?.log(\"error\", err);\n              statsMngr?.setRelayStatus(rurl, \"failed\");\n              break;\n            }\n            if (isFetchTillEoseAbortedSignal(err)) {\n              // fetch aborted\n              logger?.log(\"info\", err.message);\n              isAboutToAbort = true;\n            } else {\n              logger?.log(\"error\", \"unexpected error:\", err);\n              statsMngr?.setRelayStatus(rurl, \"failed\");\n              break;\n            }\n          } finally {\n            statsMngr?.subClosed();\n          }\n\n          if (!gotNewEvent) {\n            // termination contidion 1\n            logger?.log(\"info\", `got ${localSeenEventIds.size} events`);\n            statsMngr?.setRelayStatus(rurl, isAboutToAbort ? \"aborted\" : \"completed\");\n            break;\n          }\n\n          // set next `until` to `created_at` of the oldest event returned in this time.\n          nextUntil = oldestCreatedAt;\n          statsMngr?.setRelayFrontier(rurl, oldestCreatedAt);\n\n          // update progress\n          if (timeRangeDur !== undefined) {\n            progTracker.setProgress(rurl, (initialUntil - oldestCreatedAt) / timeRangeDur);\n            statsMngr?.setCurrentProgress(progTracker.calcTotalProgress());\n          }\n\n          if (options.signal?.aborted) {\n            // termination contidion 2\n            logger?.log(\"info\", \"aborted\");\n            statsMngr?.setRelayStatus(rurl, \"aborted\");\n            break;\n          }\n\n          // receive backpressure: wait until the channel is drained enough\n          await tx.waitUntilDrained();\n        }\n        // subscription loop for the relay terminated\n        progTracker.setProgress(rurl, 1);\n        statsMngr?.setCurrentProgress(progTracker.calcTotalProgress());\n      }),\n    ).then(() => {\n      // all subscription loops have been terminated\n      tx.close();\n      statsMngr?.stop();\n    });\n\n    yield* chIter;\n  }\n\n  /**\n   * Fetches all events matching the filter from Nostr relays specified by the array of URLs,\n   * and collect them into an array.\n   *\n   * Note: there are no guarantees about the order of returned events if `sort` options is not specified.\n   *\n   * Throws {@linkcode NostrFetchError} if `timeRangeFilter` is invalid (`since` > `until`).\n   */\n  public async fetchAllEvents<SeenOn extends boolean = false>(\n    relayUrls: string[],\n    filter: FetchFilter,\n    timeRangeFilter: FetchTimeRangeFilter,\n    options: FetchAllOptions<SeenOn> = {},\n  ): Promise<NostrEventExt<SeenOn>[]> {\n    assertReq(\n      { relayUrls, filter, timeRangeFilter },\n      [\n        checkIfNonEmpty((r) => r.relayUrls, \"warn\", \"Specify at least 1 relay URL\"),\n        checkIfTagQueriesAreValid((r) => r.filter, \"error\"),\n        checkIfTimeRangeIsValid((r) => r.timeRangeFilter, \"error\"),\n      ],\n      this.#debugLogger,\n    );\n\n    const finalOpts = {\n      ...defaultFetchAllOptions,\n      ...options,\n    } as Required<FetchAllOptions<SeenOn>>;\n\n    const allEvents = this.allEventsIterator(relayUrls, filter, timeRangeFilter, {\n      ...finalOpts,\n      enableBackpressure: false,\n    });\n\n    // collect events\n    const res = await (async () => {\n      if (finalOpts.withSeenOn) {\n        const evs: Map<string, NostrEventExt<SeenOn>> = new Map();\n        for await (const ev of allEvents) {\n          evs.set(ev.id, ev);\n        }\n        return [...evs.values()];\n      }\n\n      const evs: NostrEventExt<SeenOn>[] = [];\n      for await (const ev of allEvents) {\n        evs.push(ev);\n      }\n      return evs;\n    })();\n\n    // sort events in \"newest to oldest\" order if `sort` options is specified\n    if (finalOpts.sort) {\n      res.sort(compareNostrEvents);\n    }\n    return res;\n  }\n\n  /**\n   * Fetches latest events matching the filter from Nostr relays specified by the array of URLs.\n   *\n   * Events are sorted in \"newest to oldest\" order.\n   *\n   * Throws {@linkcode NostrFetchError} if `limit` is a non-positive number.\n   */\n  public async fetchLatestEvents<SeenOn extends boolean = false>(\n    relayUrls: string[],\n    filter: FetchFilter,\n    limit: number,\n    options: FetchLatestOptions<SeenOn> = {},\n  ): Promise<NostrEventExt<SeenOn>[]> {\n    assertReq(\n      { relayUrls, filter, limit },\n      [\n        checkIfNonEmpty((r) => r.relayUrls, \"warn\", \"Specify at least 1 relay URL\"),\n        checkIfTagQueriesAreValid((r) => r.filter, \"error\"),\n        checkIfTrue((r) => r.limit > 0, \"error\", '\"limit\" should be positive number'),\n      ],\n      this.#debugLogger,\n    );\n\n    const finalOpts = {\n      ...defaultFetchLatestOptions,\n      ...options,\n      // if only `abortSignal` is specified, copy it to `signal`\n      signal: options.signal ?? options.abortSignal,\n    } as Required<FetchLatestOptions<SeenOn>>;\n    this.#debugLogger?.log(\"verbose\", \"finalOpts=%O\", finalOpts);\n\n    // options for subscription\n    const subOpts: FetchTillEoseOptions = {\n      ...finalOpts,\n      // skip \"full\" verification if `reduceVerification` is enabled\n      skipVerification: finalOpts.skipVerification || finalOpts.reduceVerification,\n    };\n\n    const statsMngr = FetchStatsManager.init(\n      finalOpts.statsListener,\n      finalOpts.statsNotifIntervalMs,\n    );\n\n    const reqNips = this.#calcRequiredNips(filter);\n    const eligibleRelayUrls = await this.#ensureRelaysWithCapCheck(relayUrls, finalOpts, reqNips);\n\n    const [tx, chIter] = Channel.make<NostrEvent>();\n    const globalSeenEvents = initSeenEvents(finalOpts.withSeenOn);\n    const initialUntil = finalOpts.asOf ?? currUnixtimeSec();\n\n    const progTracker = new ProgressTracker(eligibleRelayUrls);\n    statsMngr?.setProgressMax(eligibleRelayUrls.length * limit);\n    statsMngr?.initRelayStats(relayUrls, eligibleRelayUrls, initialUntil);\n\n    // fetch at most `limit` events from each relay\n    Promise.all(\n      eligibleRelayUrls.map(async (rurl) => {\n        // repeat subscription until one of the following conditions is met:\n        // 1. got enough amount of events\n        // 2. the relay didn't return new event\n        // 3. aborted by AbortController\n        // E. an error occurred while fetching events\n\n        const logger = this.#debugLogger?.subLogger(rurl);\n\n        let nextUntil = initialUntil;\n        let remainingLimit = limit;\n        const localSeenEventIds = new Set<string>();\n\n        while (true) {\n          const refinedFilter = {\n            ...filter,\n            until: nextUntil,\n            // relays are supposed to return *latest* events by specifying `limit` explicitly (cf. [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md)).\n            // nostream doesn't accept a filter which has `limit` grater than 5000, so limit `limit` to this threshold or less.\n            limit: Math.min(remainingLimit, MAX_LIMIT_PER_REQ),\n          };\n          logger?.log(\"verbose\", \"refinedFilter=%O\", refinedFilter);\n\n          let numNewEvents = 0;\n          let oldestCreatedAt = Number.MAX_SAFE_INTEGER;\n\n          let isAboutToAbort = false;\n\n          try {\n            statsMngr?.subOpened();\n            for await (const e of this.#backend.fetchTillEose(rurl, refinedFilter, subOpts)) {\n              // eliminate duplicated events\n              if (!localSeenEventIds.has(e.id)) {\n                // hasn't seen the event on this relay\n                numNewEvents++;\n                localSeenEventIds.add(e.id);\n                if (e.created_at < oldestCreatedAt) {\n                  oldestCreatedAt = e.created_at;\n                }\n\n                const { hasSeen } = globalSeenEvents.report(e, rurl);\n                if (!hasSeen) {\n                  tx.send(e);\n                }\n\n                statsMngr?.eventFetched(rurl);\n                statsMngr?.setNumBufferedEvents(tx.numBufferedItems());\n              }\n            }\n          } catch (err) {\n            if (isFetchTillEoseFailedSignal(err)) {\n              // an error occurred while fetching events\n              logger?.log(\"error\", err);\n              statsMngr?.setRelayStatus(rurl, \"failed\");\n              break;\n            }\n            if (isFetchTillEoseAbortedSignal(err)) {\n              // fetch aborted\n              logger?.log(\"info\", err.message);\n              isAboutToAbort = true;\n            } else {\n              logger?.log(\"error\", \"unexpected error:\", err);\n              statsMngr?.setRelayStatus(rurl, \"failed\");\n              break;\n            }\n          } finally {\n            statsMngr?.subClosed();\n          }\n\n          progTracker.addProgress(rurl, Math.min(numNewEvents, remainingLimit));\n          statsMngr?.setCurrentProgress(progTracker.calcTotalProgress());\n\n          remainingLimit -= numNewEvents;\n          if (numNewEvents === 0 || remainingLimit <= 0) {\n            // termination condition 1, 2\n            logger?.log(\"info\", `got ${localSeenEventIds.size} events`);\n            statsMngr?.setRelayStatus(rurl, isAboutToAbort ? \"aborted\" : \"completed\");\n            break;\n          }\n          if (finalOpts.signal?.aborted) {\n            // termination condition 3\n            logger?.log(\"info\", \"aborted\");\n            statsMngr?.setRelayStatus(rurl, \"aborted\");\n            break;\n          }\n\n          // set next `until` to `created_at` of the oldest event returned in this time.\n          nextUntil = oldestCreatedAt;\n          statsMngr?.setRelayFrontier(rurl, oldestCreatedAt);\n        }\n        // subscription loop for the relay terminated\n        progTracker.setProgress(rurl, limit);\n        statsMngr?.setCurrentProgress(progTracker.calcTotalProgress());\n      }),\n    ).then(() => {\n      // all subnscription loops have been terminated\n      tx.close();\n      statsMngr?.stop();\n    });\n\n    // collect events from relays. events are already deduped\n    const evs: NostrEvent[] = [];\n    for await (const ev of chIter) {\n      evs.push(ev);\n    }\n    evs.sort(compareNostrEvents);\n\n    // take latest events\n    const res = (async () => {\n      // return latest `limit` events if not \"reduced verification mode\"\n      if (finalOpts.skipVerification || !finalOpts.reduceVerification) {\n        return evs.slice(0, limit);\n      }\n      // reduced verification: return latest `limit` events whose signature is valid\n      const verified: NostrEvent[] = [];\n      for (const ev of evs) {\n        if (await finalOpts.eventVerifier(ev)) {\n          verified.push(ev);\n          if (verified.length >= limit) {\n            break;\n          }\n        }\n      }\n      return verified;\n    })();\n\n    if (!finalOpts.withSeenOn) {\n      return (await res) as NostrEventExt<SeenOn>[];\n    }\n    // append \"seen on\" data to events if `withSeenOn` is true.\n    return (await res).map((e) => {\n      return { ...e, seenOn: globalSeenEvents.getSeenOn(e.id) };\n    }) as NostrEventExt<SeenOn>[];\n  }\n\n  /**\n   * Fetches the last event matching the filter from Nostr relays specified by the array of URLs.\n   *\n   * Returns `undefined` if no event matching the filter exists in any relay.\n   */\n  public async fetchLastEvent<SeenOn extends boolean = false>(\n    relayUrls: string[],\n    filter: FetchFilter,\n    options: FetchLatestOptions<SeenOn> = {},\n  ): Promise<NostrEventExt<SeenOn> | undefined> {\n    const finalOpts = {\n      ...defaultFetchLatestOptions,\n      ...{\n        // override default value of `abortSubBeforeEoseTimeoutMs` (10000 -> 1000)\n        abortSubBeforeEoseTimeoutMs: 1000,\n        ...options,\n      },\n    } as Required<FetchLatestOptions<SeenOn>>;\n    const latest1 = await this.fetchLatestEvents(relayUrls, filter, 1, finalOpts);\n    return latest1[0];\n  }\n\n  // creates mapping of available relays to keys.\n  // returns triple: the mapping, array of all keys, and array of all relay URLs.\n  // these arrays are guaranteed to be deduped.\n  async #mapAvailableRelayToKeys<K extends FetchFilterKeyName>(\n    kr: KeysAndRelays<K>,\n    ensureOpts: EnsureRelaysOptions,\n    reqNips: number[],\n  ): Promise<\n    [\n      relayToKeys: Map<string, FetchFilterKeyElem<K>[]>,\n      allKeys: FetchFilterKeyElem<K>[],\n      allRelays: string[],\n    ]\n  > {\n    if (isRelaySetForAllKeys(kr)) {\n      assertReq(\n        kr,\n        [\n          checkIfNonEmpty((r) => r.relayUrls, \"warn\", \"Specify at least 1 relay URL\"),\n          checkIfNonEmpty((r) => r.keys as unknown[], \"warn\", \"Specify at least 1 key\"),\n        ],\n        this.#debugLogger,\n      );\n      const dedupedKeys = [...new Set(kr.keys)];\n      const eligibleRelays = await this.#ensureRelaysWithCapCheck(\n        kr.relayUrls,\n        ensureOpts,\n        reqNips,\n      );\n      return [\n        new Map(eligibleRelays.map((rurl) => [rurl, dedupedKeys])),\n        dedupedKeys,\n        eligibleRelays,\n      ];\n    }\n\n    if (isRelaySetsPerKey(kr)) {\n      const krArr = [...kr];\n      assertReq(\n        krArr,\n        [\n          checkIfNonEmpty((kr) => kr, \"warn\", \"Specify at least 1 key\"),\n          checkIfTrue(\n            (kr) => kr.every(([, relays]) => relays.length > 0),\n            \"warn\",\n            \"Specify at least 1 relay URL for all keys\",\n          ),\n        ],\n        this.#debugLogger,\n      );\n\n      const dedupedKeys = [...new Set(krArr.map(([key]) => key))];\n\n      // transpose: key to rurls -> rurl to keys\n      const rurl2keys = new Map<string, Set<FetchFilterKeyElem<K>>>();\n      for (const [key, rurls] of krArr) {\n        const normalized = normalizeRelayUrlSet(rurls);\n        for (const rurl of normalized) {\n          const keys = rurl2keys.get(rurl);\n          rurl2keys.set(rurl, keys ? keys.add(key) : new Set([key]));\n        }\n      }\n      const allRelays = [...rurl2keys.keys()];\n      const eligibleRelays = await this.#ensureRelaysWithCapCheck(allRelays, ensureOpts, reqNips);\n\n      // retain eligible relays only\n      return [\n        // biome-ignore lint/style/noNonNullAssertion: rurl2keys should have all relay URLs in eligibleRelays\n        new Map(eligibleRelays.map((rurl) => [rurl, [...rurl2keys.get(rurl)!]])),\n        dedupedKeys,\n        eligibleRelays,\n      ];\n    }\n\n    throw new NostrFetchError(\n      \"malformed first argument for fetchLatestEventsPerKey/fetchLastEventPerKey\",\n    );\n  }\n\n  /**\n   * Fetches latest up to `limit` events **for each key specified by `keyName` and `keysAndRelays`**.\n   *\n   * `keysAndRelays` can be either of two types:\n   *\n   * - `{ keys: K[], relayUrls: string[] }`: The fetcher will use the same relay set (`relayUrls`) for all `keys` to fetch events.\n   * - `Map<K, string[]>`: Key must be the key of event and value must be relay set for that key. The fetcher will use separate relay set for each key to fetch events.\n   *\n   * Result is an async iterable of `{ key: <key of events>, events: <events which have that key> }` pairs.\n   *\n   * Each array of events in the result are sorted in \"newest to oldest\" order.\n   *\n   * Throws {@linkcode NostrFetchError} if `limit` is a non-positive number.\n   */\n  public fetchLatestEventsPerKey<K extends FetchFilterKeyName, SeenOn extends boolean = false>(\n    keyName: K,\n    keysAndRelays: KeysAndRelays<K>,\n    otherFilter: FetchFilter,\n    limit: number,\n    options: FetchLatestOptions<SeenOn> = {},\n  ): AsyncIterable<NostrEventListWithKey<K, SeenOn>> {\n    assertReq(\n      { limit, keyName, otherFilter },\n      [\n        checkIfTrue((r) => r.limit > 0, \"error\", '\"limit\" should be positive number'),\n        checkIfTrue(\n          (r) => !r.keyName.startsWith(\"#\") || isValidTagQueryKey(r.keyName),\n          \"error\",\n          `Specified key '${keyName}' is invalid tag query key`,\n        ),\n        checkIfTagQueriesAreValid((r) => r.otherFilter, \"error\"),\n        checkIfTrue(\n          ({ keyName, otherFilter }) => !(keyName in otherFilter),\n          \"warn\",\n          `'${keyName}' field in \"otherFilter\" will be ignored because it is specified as main key`,\n        ),\n      ],\n      this.#debugLogger,\n    );\n\n    const filledOpts = {\n      ...defaultFetchLatestOptions,\n      ...options,\n    } as Required<FetchLatestOptions<SeenOn>>;\n    this.#debugLogger?.log(\"verbose\", \"finalOpts=%O\", filledOpts);\n\n    // options for subscription\n    const finalOpts = {\n      ...filledOpts,\n      // skip \"full\" verification if `reduceVerification` is enabled\n      skipVerification: filledOpts.skipVerification || filledOpts.reduceVerification,\n      // if only `abortSignal` is specified, copy it to `signal`\n      signal: filledOpts.signal ?? filledOpts.abortSignal,\n    };\n\n    return this.#fetchLatestEventPerKeyWithCleanupOnBreak(\n      keyName,\n      keysAndRelays,\n      otherFilter,\n      limit,\n      finalOpts,\n    );\n  }\n\n  async *#fetchLatestEventPerKeyWithCleanupOnBreak<\n    K extends FetchFilterKeyName,\n    SeenOn extends boolean = false,\n  >(\n    keyName: K,\n    keysAndRelays: KeysAndRelays<K>,\n    otherFilter: FetchFilter,\n    limit: number,\n    options: Required<FetchLatestOptions<SeenOn>>,\n  ): AsyncIterable<NostrEventListWithKey<K, SeenOn>> {\n    const [breakableSig, breakSignal] = makeBreakableSignal(options.signal);\n    try {\n      yield* this.#fetchLatestEventPerKeyBody(keyName, keysAndRelays, otherFilter, limit, {\n        ...options,\n        signal: breakableSig,\n      });\n    } finally {\n      // this block will be executed when:\n      // - iteration is finished normally (whether throws or not)\n      // - iteration is terminated early by break/return in a for-await-of loop\n      //\n      // in second case, breakSignal() causes the \"cleanup\" (abortion of event fetching by backend).\n      breakSignal();\n    }\n  }\n\n  async *#fetchLatestEventPerKeyBody<K extends FetchFilterKeyName, SeenOn extends boolean = false>(\n    keyName: K,\n    keysAndRelays: KeysAndRelays<K>,\n    otherFilter: FetchFilter,\n    limit: number,\n    options: Required<FetchLatestOptions<SeenOn>>,\n  ): AsyncIterable<NostrEventListWithKey<K, SeenOn>> {\n    const statsMngr = FetchStatsManager.init(options.statsListener, options.statsNotifIntervalMs);\n\n    // get mapping of available relay to keys and list of all keys\n    const reqNips = this.#calcRequiredNips(otherFilter);\n    const [relayToKeys, allKeys, allRelays] = await this.#mapAvailableRelayToKeys(\n      keysAndRelays,\n      options,\n      reqNips,\n    );\n    this.#debugLogger?.log(\"verbose\", \"relayToKeys=%O\", relayToKeys);\n\n    const [tx, chIter] = Channel.make<NostrEventListWithKey<K, SeenOn>>();\n    const globalSeenEvents = initSeenEvents(options.withSeenOn);\n    const initialUntil = options.asOf ?? currUnixtimeSec();\n\n    statsMngr?.setProgressMax(allKeys.length);\n    statsMngr?.initRelayStats(allRelays, [...relayToKeys.keys()], initialUntil);\n\n    // for each pair of key and relay URL, create a promise that act as \"latch\", so that the \"merger\" can wait for a subscription to complete\n    const latches = new KeyRelayMatrix(relayToKeys, () => new Deferred<NostrEvent[]>());\n\n    // the \"fetcher\" fetches events from each relay\n    Promise.all(\n      [...relayToKeys].map(async ([rurl, keys]) => {\n        // repeat subscription until one of the following conditions is met:\n        // 1. have fetched required number of events for all keys\n        // 2. the relay didn't return new event\n        // 3. aborted by AbortController\n        // E. an error occurred while fetching events\n\n        const logger = this.#debugLogger?.subLogger(rurl);\n\n        let nextUntil = initialUntil;\n        const evBucketsPerKey = new EventBuckets(keys, limit);\n        const localSeenEventIds = new Set<string>();\n\n        // procedure to complete the subscription in the middle, resolving all remaining promises.\n        // resolve() is called even if a promise is already resolved, but it's not a problem.\n        const resolveAllOnEarlyBreak = () => {\n          logger?.log(\"verbose\", \"resolving bucket on early return\");\n          for (const pk of keys) {\n            latches.get(pk, rurl)?.resolve(evBucketsPerKey.getBucket(pk) ?? []);\n          }\n        };\n\n        while (true) {\n          const { keys: nextKeys, limit: nextLimit } = evBucketsPerKey.calcKeysAndLimitForNextReq();\n\n          if (nextKeys.length === 0) {\n            // termination condition 1\n            logger?.log(\"verbose\", \"fulfilled buckets for all keys\");\n            statsMngr?.setRelayStatus(rurl, \"completed\");\n            break;\n          }\n\n          const refinedFilter = {\n            ...otherFilter,\n            [keyName]: nextKeys,\n            until: nextUntil,\n            limit: Math.min(nextLimit, MAX_LIMIT_PER_REQ),\n          };\n          logger?.log(\"verbose\", \"refinedFilter=%O\", refinedFilter);\n\n          let gotNewEvent = false;\n          let oldestCreatedAt = Number.MAX_SAFE_INTEGER;\n\n          let isAboutToAbort = false;\n\n          try {\n            statsMngr?.subOpened();\n            for await (const e of this.#backend.fetchTillEose(rurl, refinedFilter, options)) {\n              if (!localSeenEventIds.has(e.id)) {\n                // hasn't seen the event on this relay\n                gotNewEvent = true;\n                localSeenEventIds.add(e.id);\n                if (e.created_at < oldestCreatedAt) {\n                  oldestCreatedAt = e.created_at;\n                }\n\n                globalSeenEvents.report(e, rurl);\n\n                // add the event to the bucket for the keys\n                for (const evKey of getKeysOfEvent(keyName, e)) {\n                  const addRes = evBucketsPerKey.add(evKey, e);\n                  if (addRes.state === \"fulfilled\") {\n                    // notify that event fetching is completed for the key at this relay\n                    // by resolveing the Promise corresponds to the key and the relay\n                    latches.get(evKey, rurl)?.resolve(addRes.events);\n                    logger?.log(\"verbose\", `fulfilled a bucket for key=${evKey}`);\n                  }\n                }\n\n                statsMngr?.eventFetched(rurl);\n                statsMngr?.setNumBufferedEvents(tx.numBufferedItems());\n              }\n            }\n          } catch (err) {\n            if (isFetchTillEoseFailedSignal(err)) {\n              // an error occurred while fetching events\n              logger?.log(\"error\", err);\n              statsMngr?.setRelayStatus(rurl, \"failed\");\n              resolveAllOnEarlyBreak();\n              break;\n            }\n            if (isFetchTillEoseAbortedSignal(err)) {\n              // fetch aborted\n              logger?.log(\"info\", err.message);\n              isAboutToAbort = true;\n            } else {\n              logger?.log(\"error\", \"unexpected error:\", err);\n              statsMngr?.setRelayStatus(rurl, \"failed\");\n              resolveAllOnEarlyBreak();\n              break;\n            }\n          } finally {\n            statsMngr?.subClosed();\n          }\n\n          if (!gotNewEvent) {\n            // termination condition 2\n            logger?.log(\"info\", `got ${localSeenEventIds.size} events`);\n            statsMngr?.setRelayStatus(rurl, isAboutToAbort ? \"aborted\" : \"completed\");\n            resolveAllOnEarlyBreak();\n            break;\n          }\n          if (options.signal?.aborted) {\n            // termination condition 3\n            logger?.log(\"info\", \"aborted\");\n            statsMngr?.setRelayStatus(rurl, isAboutToAbort ? \"aborted\" : \"completed\");\n            resolveAllOnEarlyBreak();\n            break;\n          }\n\n          // set next `until` to `created_at` of the oldest event returned in this time.\n          nextUntil = oldestCreatedAt;\n          statsMngr?.setRelayFrontier(rurl, oldestCreatedAt);\n        }\n      }),\n    );\n\n    // the \"merger\".\n    // for each key: merges result from relays, sorts events, takes latest events and sends it to the result channel.\n    Promise.all(\n      allKeys.map(async (key) => {\n        const logger = this.#debugLogger?.subLogger(abbreviate(String(key), 6));\n\n        // wait for all the buckets for the key to fulfilled\n        const evsPerRelay = await Promise.all(latches.itemsByKey(key)?.map((d) => d.promise) ?? []);\n        logger?.log(\"verbose\", \"fulfilled all buckets for this key\");\n\n        // merge and sort\n        const evsDeduped = (() => {\n          const res = [];\n          const seenIds = new Set();\n\n          for (const evs of evsPerRelay) {\n            for (const ev of evs) {\n              if (!seenIds.has(ev.id)) {\n                res.push(ev);\n                seenIds.add(ev.id);\n              }\n            }\n          }\n          return res;\n        })();\n        evsDeduped.sort(compareNostrEvents);\n\n        // take latest events\n        const res = (async () => {\n          // return latest `limit` events if not \"reduced verification mode\"\n          if (options.skipVerification || !options.reduceVerification) {\n            return evsDeduped.slice(0, limit);\n          }\n\n          // reduced verification: return latest `limit` events whose signature is valid\n          const verified = [];\n          for (const ev of evsDeduped) {\n            if (await options.eventVerifier(ev)) {\n              verified.push(ev);\n              if (verified.length >= limit) {\n                break;\n              }\n            }\n          }\n          return verified;\n        })();\n\n        // send result\n        if (options.withSeenOn) {\n          // append \"seen on\" data to events if `withSeenOn` is true.\n          tx.send({\n            key,\n            events: (await res).map((e) => {\n              return { ...e, seenOn: globalSeenEvents.getSeenOn(e.id) };\n            }) as NostrEventExt<SeenOn>[],\n          });\n        } else {\n          tx.send({ key, events: (await res) as NostrEventExt<SeenOn>[] });\n        }\n        statsMngr?.addProgress(1);\n      }),\n    ).then(() => {\n      // finished to fetch events for all keys\n      tx.close();\n      statsMngr?.stop();\n    });\n\n    yield* chIter;\n  }\n\n  /**\n   * Fetches the last event **for each key specified by `keysAndRelays`**.\n   *\n   * `keysAndRelays` can be either of two types:\n   *\n   * - `{ keys: K[], relayUrls: string[] }`: The fetcher will use the same relay set (`relayUrls`) for all `keys` to fetch events.\n   * - `Map<K, string[]>`: Key must be key of the event and value must be relay set for that key. The fetcher will use separate relay set for each key to fetch events.\n   *\n   * Result is an async iterable of `{ key: <key of events>, event: <the latest event which have that key> }` pairs.\n   *\n   * `event` in result will be `undefined` if no event matching the filter exists in any relay.\n   */\n  public async *fetchLastEventPerKey<K extends FetchFilterKeyName, SeenOn extends boolean = false>(\n    keyName: K,\n    keysAndRelays: KeysAndRelays<K>,\n    otherFilter: FetchFilter,\n    options: FetchLatestOptions<SeenOn> = {},\n  ): AsyncIterable<NostrEventWithKey<K, SeenOn>> {\n    const finalOpts = {\n      ...defaultFetchLatestOptions,\n      ...{\n        // override default value of `abortSubBeforeEoseTimeoutMs` (10000 -> 1000)\n        abortSubBeforeEoseTimeoutMs: 1000,\n        ...options,\n      },\n    } as Required<FetchLatestOptions<SeenOn>>;\n\n    const latest1Iter = this.fetchLatestEventsPerKey(\n      keyName,\n      keysAndRelays,\n      otherFilter,\n      1,\n      finalOpts,\n    );\n    for await (const { key, events } of latest1Iter) {\n      yield { key, event: events[0] };\n    }\n  }\n\n  /**\n   * Fetches latest up to `limit` events **for each author specified by `authorsAndRelays`**.\n   *\n   * `authorsAndRelays` can be either of two types:\n   *\n   * - `{ authors: string[], relayUrls: string[] }`: The fetcher will use the same relay set (`relayUrls`) for all `authors` to fetch events.\n   * - `Map<string, string[]>`: Key must be author's pubkey and value must be relay set for that author. The fetcher will use separate relay set for each author to fetch events.\n   *\n   * Result is an async iterable of `{ author: <author's pubkey>, events: <events from the author> }` pairs.\n   *\n   * Each array of events in the result are sorted in \"newest to oldest\" order.\n   *\n   * Throws {@linkcode NostrFetchError} if `limit` is a non-positive number.\n   *\n   * Note: it's just an wrapper of `fetchLatestEventsPerKey`.\n   */\n  public async *fetchLatestEventsPerAuthor<SeenOn extends boolean = false>(\n    authorsAndRelays: AuthorsAndRelays,\n    otherFilter: Omit<FetchFilter, \"authors\">,\n    limit: number,\n    options: FetchLatestOptions<SeenOn> = {},\n  ): AsyncIterable<NostrEventListWithAuthor<SeenOn>> {\n    for await (const { key, events } of this.fetchLatestEventsPerKey(\n      \"authors\",\n      adaptAuthorsAndRelays(authorsAndRelays),\n      otherFilter,\n      limit,\n      options,\n    )) {\n      yield { author: key, events };\n    }\n  }\n\n  /**\n   * Fetches the last event **for each author specified by `authorsAndRelays`**.\n   *\n   * `authorsAndRelays` can be either of two types:\n   *\n   * - `{ authors: string[], relayUrls: string[] }`: The fetcher will use the same relay set (`relayUrls`) for all `authors` to fetch events.\n   * - `Map<string, string[]>`: Key must be author's pubkey and value must be relay set for that author. The fetcher will use separate relay set for each author to fetch events.\n   *\n   * Result is an async iterable of `{ author: <author's pubkey>, event: <the latest event from the author> }` pairs.\n   *\n   * `event` in result will be `undefined` if no event matching the filter for the author exists in any relay.\n   *\n   * Note: it's just a wrapper of `fetchLastEventPerKey`.\n   */\n  public async *fetchLastEventPerAuthor<SeenOn extends boolean = false>(\n    authorsAndRelays: AuthorsAndRelays,\n    otherFilter: Omit<FetchFilter, \"authors\">,\n    options: FetchLatestOptions<SeenOn> = {},\n  ): AsyncIterable<NostrEventWithAuthor<SeenOn>> {\n    for await (const { key, event } of this.fetchLastEventPerKey(\n      \"authors\",\n      adaptAuthorsAndRelays(authorsAndRelays),\n      otherFilter,\n      options,\n    )) {\n      yield { author: key, event };\n    }\n  }\n\n  /**\n   * Cleans up all the internal states of the fetcher.\n   */\n  public shutdown() {\n    this.#backend.shutdown();\n  }\n\n  /**\n   * Enables [explicit resource management](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management) for `NostrFetcher` instances.\n   *\n   * If you bind a `NostrFetcher` instance to a variable with `using` keyword, it will be automatically shut down when the scope of the variable ends.\n   */\n  public [Symbol.dispose]() {\n    this.shutdown();\n  }\n}\n"]}