689d5af17fdbea06b700c7d411dceeff47d91c7c777a9e1cee373b0e43c52066.json raw

   1  {"ast":null,"code":"import _asyncToGenerator from \"/home/mleku/src/orly.dev/next/signer/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js\";\n// pure.ts\nimport { schnorr } from \"@noble/curves/secp256k1\";\nimport { bytesToHex } from \"@noble/hashes/utils\";\n\n// core.ts\nvar verifiedSymbol = Symbol(\"verified\");\nvar isRecord = obj => obj instanceof Object;\nfunction validateEvent(event) {\n  if (!isRecord(event)) return false;\n  if (typeof event.kind !== \"number\") return false;\n  if (typeof event.content !== \"string\") return false;\n  if (typeof event.created_at !== \"number\") return false;\n  if (typeof event.pubkey !== \"string\") return false;\n  if (!event.pubkey.match(/^[a-f0-9]{64}$/)) return false;\n  if (!Array.isArray(event.tags)) return false;\n  for (let i2 = 0; i2 < event.tags.length; i2++) {\n    let tag = event.tags[i2];\n    if (!Array.isArray(tag)) return false;\n    for (let j = 0; j < tag.length; j++) {\n      if (typeof tag[j] === \"object\") return false;\n    }\n  }\n  return true;\n}\n\n// pure.ts\nimport { sha256 } from \"@noble/hashes/sha256\";\n\n// utils.ts\nvar utf8Decoder = new TextDecoder(\"utf-8\");\nvar utf8Encoder = new TextEncoder();\nfunction normalizeURL(url) {\n  if (url.indexOf(\"://\") === -1) url = \"wss://\" + url;\n  let p = new URL(url);\n  p.pathname = p.pathname.replace(/\\/+/g, \"/\");\n  if (p.pathname.endsWith(\"/\")) p.pathname = p.pathname.slice(0, -1);\n  if (p.port === \"80\" && p.protocol === \"ws:\" || p.port === \"443\" && p.protocol === \"wss:\") p.port = \"\";\n  p.searchParams.sort();\n  p.hash = \"\";\n  return p.toString();\n}\nvar QueueNode = class {\n  value;\n  next = null;\n  prev = null;\n  constructor(message) {\n    this.value = message;\n  }\n};\nvar Queue = class {\n  first;\n  last;\n  constructor() {\n    this.first = null;\n    this.last = null;\n  }\n  enqueue(value) {\n    const newNode = new QueueNode(value);\n    if (!this.last) {\n      this.first = newNode;\n      this.last = newNode;\n    } else if (this.last === this.first) {\n      this.last = newNode;\n      this.last.prev = this.first;\n      this.first.next = newNode;\n    } else {\n      newNode.prev = this.last;\n      this.last.next = newNode;\n      this.last = newNode;\n    }\n    return true;\n  }\n  dequeue() {\n    if (!this.first) return null;\n    if (this.first === this.last) {\n      const target2 = this.first;\n      this.first = null;\n      this.last = null;\n      return target2.value;\n    }\n    const target = this.first;\n    this.first = target.next;\n    return target.value;\n  }\n};\n\n// pure.ts\nvar JS = class {\n  generateSecretKey() {\n    return schnorr.utils.randomPrivateKey();\n  }\n  getPublicKey(secretKey) {\n    return bytesToHex(schnorr.getPublicKey(secretKey));\n  }\n  finalizeEvent(t, secretKey) {\n    const event = t;\n    event.pubkey = bytesToHex(schnorr.getPublicKey(secretKey));\n    event.id = getEventHash(event);\n    event.sig = bytesToHex(schnorr.sign(getEventHash(event), secretKey));\n    event[verifiedSymbol] = true;\n    return event;\n  }\n  verifyEvent(event) {\n    if (typeof event[verifiedSymbol] === \"boolean\") return event[verifiedSymbol];\n    const hash = getEventHash(event);\n    if (hash !== event.id) {\n      event[verifiedSymbol] = false;\n      return false;\n    }\n    try {\n      const valid = schnorr.verify(event.sig, hash, event.pubkey);\n      event[verifiedSymbol] = valid;\n      return valid;\n    } catch (err) {\n      event[verifiedSymbol] = false;\n      return false;\n    }\n  }\n};\nfunction serializeEvent(evt) {\n  if (!validateEvent(evt)) throw new Error(\"can't serialize event with wrong or missing properties\");\n  return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);\n}\nfunction getEventHash(event) {\n  let eventHash = sha256(utf8Encoder.encode(serializeEvent(event)));\n  return bytesToHex(eventHash);\n}\nvar i = new JS();\nvar generateSecretKey = i.generateSecretKey;\nvar getPublicKey = i.getPublicKey;\nvar finalizeEvent = i.finalizeEvent;\nvar verifyEvent = i.verifyEvent;\n\n// kinds.ts\nvar ClientAuth = 22242;\n\n// filter.ts\nfunction matchFilter(filter, event) {\n  if (filter.ids && filter.ids.indexOf(event.id) === -1) {\n    return false;\n  }\n  if (filter.kinds && filter.kinds.indexOf(event.kind) === -1) {\n    return false;\n  }\n  if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {\n    return false;\n  }\n  for (let f in filter) {\n    if (f[0] === \"#\") {\n      let tagName = f.slice(1);\n      let values = filter[`#${tagName}`];\n      if (values && !event.tags.find(([t, v]) => t === f.slice(1) && values.indexOf(v) !== -1)) return false;\n    }\n  }\n  if (filter.since && event.created_at < filter.since) return false;\n  if (filter.until && event.created_at > filter.until) return false;\n  return true;\n}\nfunction matchFilters(filters, event) {\n  for (let i2 = 0; i2 < filters.length; i2++) {\n    if (matchFilter(filters[i2], event)) {\n      return true;\n    }\n  }\n  return false;\n}\n\n// fakejson.ts\nfunction getHex64(json, field) {\n  let len = field.length + 3;\n  let idx = json.indexOf(`\"${field}\":`) + len;\n  let s = json.slice(idx).indexOf(`\"`) + idx + 1;\n  return json.slice(s, s + 64);\n}\nfunction getSubscriptionId(json) {\n  let idx = json.slice(0, 22).indexOf(`\"EVENT\"`);\n  if (idx === -1) return null;\n  let pstart = json.slice(idx + 7 + 1).indexOf(`\"`);\n  if (pstart === -1) return null;\n  let start = idx + 7 + 1 + pstart;\n  let pend = json.slice(start + 1, 80).indexOf(`\"`);\n  if (pend === -1) return null;\n  let end = start + 1 + pend;\n  return json.slice(start + 1, end);\n}\n\n// nip42.ts\nfunction makeAuthEvent(relayURL, challenge) {\n  return {\n    kind: ClientAuth,\n    created_at: Math.floor(Date.now() / 1e3),\n    tags: [[\"relay\", relayURL], [\"challenge\", challenge]],\n    content: \"\"\n  };\n}\n\n// helpers.ts\nfunction yieldThread() {\n  return _yieldThread.apply(this, arguments);\n}\nfunction _yieldThread() {\n  _yieldThread = _asyncToGenerator(function* () {\n    return new Promise(resolve => {\n      const ch = new MessageChannel();\n      const handler = () => {\n        ch.port1.removeEventListener(\"message\", handler);\n        resolve();\n      };\n      ch.port1.addEventListener(\"message\", handler);\n      ch.port2.postMessage(0);\n      ch.port1.start();\n    });\n  });\n  return _yieldThread.apply(this, arguments);\n}\nvar alwaysTrue = t => {\n  t[verifiedSymbol] = true;\n  return true;\n};\n\n// abstract-relay.ts\nvar AbstractRelay = class {\n  url;\n  _connected = false;\n  onclose = null;\n  onnotice = msg => console.debug(`NOTICE from ${this.url}: ${msg}`);\n  _onauth = null;\n  baseEoseTimeout = 4400;\n  connectionTimeout = 4400;\n  openSubs = /* @__PURE__ */new Map();\n  connectionTimeoutHandle;\n  connectionPromise;\n  openCountRequests = /* @__PURE__ */new Map();\n  openEventPublishes = /* @__PURE__ */new Map();\n  ws;\n  incomingMessageQueue = new Queue();\n  queueRunning = false;\n  challenge;\n  serial = 0;\n  verifyEvent;\n  _WebSocket;\n  constructor(url, opts) {\n    this.url = normalizeURL(url);\n    this.verifyEvent = opts.verifyEvent;\n    this._WebSocket = opts.websocketImplementation || WebSocket;\n  }\n  static connect(url, opts) {\n    return _asyncToGenerator(function* () {\n      const relay = new AbstractRelay(url, opts);\n      yield relay.connect();\n      return relay;\n    })();\n  }\n  closeAllSubscriptions(reason) {\n    for (let [_, sub] of this.openSubs) {\n      sub.close(reason);\n    }\n    this.openSubs.clear();\n    for (let [_, ep] of this.openEventPublishes) {\n      ep.reject(new Error(reason));\n    }\n    this.openEventPublishes.clear();\n    for (let [_, cr] of this.openCountRequests) {\n      cr.reject(new Error(reason));\n    }\n    this.openCountRequests.clear();\n  }\n  get connected() {\n    return this._connected;\n  }\n  connect() {\n    var _this = this;\n    return _asyncToGenerator(function* () {\n      if (_this.connectionPromise) return _this.connectionPromise;\n      _this.challenge = void 0;\n      _this.connectionPromise = new Promise((resolve, reject) => {\n        _this.connectionTimeoutHandle = setTimeout(() => {\n          reject(\"connection timed out\");\n          _this.connectionPromise = void 0;\n          _this.onclose?.();\n          _this.closeAllSubscriptions(\"relay connection timed out\");\n        }, _this.connectionTimeout);\n        try {\n          _this.ws = new _this._WebSocket(_this.url);\n        } catch (err) {\n          reject(err);\n          return;\n        }\n        _this.ws.onopen = () => {\n          clearTimeout(_this.connectionTimeoutHandle);\n          _this._connected = true;\n          resolve();\n        };\n        _this.ws.onerror = ev => {\n          reject(ev.message);\n          if (_this._connected) {\n            _this._connected = false;\n            _this.connectionPromise = void 0;\n            _this.onclose?.();\n            _this.closeAllSubscriptions(\"relay connection errored\");\n          }\n        };\n        _this.ws.onclose = /*#__PURE__*/_asyncToGenerator(function* () {\n          if (_this._connected) {\n            _this._connected = false;\n            _this.connectionPromise = void 0;\n            _this.onclose?.();\n            _this.closeAllSubscriptions(\"relay connection closed\");\n          }\n        });\n        _this.ws.onmessage = _this._onmessage.bind(_this);\n      });\n      return _this.connectionPromise;\n    })();\n  }\n  runQueue() {\n    var _this2 = this;\n    return _asyncToGenerator(function* () {\n      _this2.queueRunning = true;\n      while (true) {\n        if (false === _this2.handleNext()) {\n          break;\n        }\n        yield yieldThread();\n      }\n      _this2.queueRunning = false;\n    })();\n  }\n  handleNext() {\n    const json = this.incomingMessageQueue.dequeue();\n    if (!json) {\n      return false;\n    }\n    const subid = getSubscriptionId(json);\n    if (subid) {\n      const so = this.openSubs.get(subid);\n      if (!so) {\n        return;\n      }\n      const id = getHex64(json, \"id\");\n      const alreadyHave = so.alreadyHaveEvent?.(id);\n      so.receivedEvent?.(this, id);\n      if (alreadyHave) {\n        return;\n      }\n    }\n    try {\n      let data = JSON.parse(json);\n      switch (data[0]) {\n        case \"EVENT\":\n          {\n            const so = this.openSubs.get(data[1]);\n            const event = data[2];\n            if (this.verifyEvent(event) && matchFilters(so.filters, event)) {\n              so.onevent(event);\n            }\n            return;\n          }\n        case \"COUNT\":\n          {\n            const id = data[1];\n            const payload = data[2];\n            const cr = this.openCountRequests.get(id);\n            if (cr) {\n              cr.resolve(payload.count);\n              this.openCountRequests.delete(id);\n            }\n            return;\n          }\n        case \"EOSE\":\n          {\n            const so = this.openSubs.get(data[1]);\n            if (!so) return;\n            so.receivedEose();\n            return;\n          }\n        case \"OK\":\n          {\n            const id = data[1];\n            const ok = data[2];\n            const reason = data[3];\n            const ep = this.openEventPublishes.get(id);\n            if (ok) ep.resolve(reason);else ep.reject(new Error(reason));\n            this.openEventPublishes.delete(id);\n            return;\n          }\n        case \"CLOSED\":\n          {\n            const id = data[1];\n            const so = this.openSubs.get(id);\n            if (!so) return;\n            so.closed = true;\n            so.close(data[2]);\n            return;\n          }\n        case \"NOTICE\":\n          this.onnotice(data[1]);\n          return;\n        case \"AUTH\":\n          {\n            this.challenge = data[1];\n            this._onauth?.(data[1]);\n            return;\n          }\n      }\n    } catch (err) {\n      return;\n    }\n  }\n  send(message) {\n    var _this3 = this;\n    return _asyncToGenerator(function* () {\n      if (!_this3.connectionPromise) throw new Error(\"sending on closed connection\");\n      _this3.connectionPromise.then(() => {\n        _this3.ws?.send(message);\n      });\n    })();\n  }\n  auth(signAuthEvent) {\n    var _this4 = this;\n    return _asyncToGenerator(function* () {\n      if (!_this4.challenge) throw new Error(\"can't perform auth, no challenge was received\");\n      const evt = yield signAuthEvent(makeAuthEvent(_this4.url, _this4.challenge));\n      const ret = new Promise((resolve, reject) => {\n        _this4.openEventPublishes.set(evt.id, {\n          resolve,\n          reject\n        });\n      });\n      _this4.send('[\"AUTH\",' + JSON.stringify(evt) + \"]\");\n      return ret;\n    })();\n  }\n  publish(event) {\n    var _this5 = this;\n    return _asyncToGenerator(function* () {\n      const ret = new Promise((resolve, reject) => {\n        _this5.openEventPublishes.set(event.id, {\n          resolve,\n          reject\n        });\n      });\n      _this5.send('[\"EVENT\",' + JSON.stringify(event) + \"]\");\n      return ret;\n    })();\n  }\n  count(filters, params) {\n    var _this6 = this;\n    return _asyncToGenerator(function* () {\n      _this6.serial++;\n      const id = params?.id || \"count:\" + _this6.serial;\n      const ret = new Promise((resolve, reject) => {\n        _this6.openCountRequests.set(id, {\n          resolve,\n          reject\n        });\n      });\n      _this6.send('[\"COUNT\",\"' + id + '\",' + JSON.stringify(filters).substring(1));\n      return ret;\n    })();\n  }\n  subscribe(filters, params) {\n    const subscription = this.prepareSubscription(filters, params);\n    subscription.fire();\n    return subscription;\n  }\n  prepareSubscription(filters, params) {\n    this.serial++;\n    const id = params.id || \"sub:\" + this.serial;\n    const subscription = new Subscription(this, id, filters, params);\n    this.openSubs.set(id, subscription);\n    return subscription;\n  }\n  close() {\n    this.closeAllSubscriptions(\"relay connection closed by us\");\n    this._connected = false;\n    this.ws?.close();\n  }\n  _onmessage(ev) {\n    this.incomingMessageQueue.enqueue(ev.data);\n    if (!this.queueRunning) {\n      this.runQueue();\n    }\n  }\n};\nvar Subscription = class {\n  relay;\n  id;\n  closed = false;\n  eosed = false;\n  filters;\n  alreadyHaveEvent;\n  receivedEvent;\n  onevent;\n  oneose;\n  onclose;\n  eoseTimeout;\n  eoseTimeoutHandle;\n  constructor(relay, id, filters, params) {\n    this.relay = relay;\n    this.filters = filters;\n    this.id = id;\n    this.alreadyHaveEvent = params.alreadyHaveEvent;\n    this.receivedEvent = params.receivedEvent;\n    this.eoseTimeout = params.eoseTimeout || relay.baseEoseTimeout;\n    this.oneose = params.oneose;\n    this.onclose = params.onclose;\n    this.onevent = params.onevent || (event => {\n      console.warn(`onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`, event);\n    });\n  }\n  fire() {\n    this.relay.send('[\"REQ\",\"' + this.id + '\",' + JSON.stringify(this.filters).substring(1));\n    this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout);\n  }\n  receivedEose() {\n    if (this.eosed) return;\n    clearTimeout(this.eoseTimeoutHandle);\n    this.eosed = true;\n    this.oneose?.();\n  }\n  close(reason = \"closed by caller\") {\n    if (!this.closed && this.relay.connected) {\n      this.relay.send('[\"CLOSE\",' + JSON.stringify(this.id) + \"]\");\n      this.closed = true;\n    }\n    this.relay.openSubs.delete(this.id);\n    this.onclose?.(reason);\n  }\n};\n\n// abstract-pool.ts\nvar AbstractSimplePool = class {\n  relays = /* @__PURE__ */new Map();\n  seenOn = /* @__PURE__ */new Map();\n  trackRelays = false;\n  verifyEvent;\n  trustedRelayURLs = /* @__PURE__ */new Set();\n  _WebSocket;\n  constructor(opts) {\n    this.verifyEvent = opts.verifyEvent;\n    this._WebSocket = opts.websocketImplementation;\n  }\n  ensureRelay(url, params) {\n    var _this7 = this;\n    return _asyncToGenerator(function* () {\n      url = normalizeURL(url);\n      let relay = _this7.relays.get(url);\n      if (!relay) {\n        relay = new AbstractRelay(url, {\n          verifyEvent: _this7.trustedRelayURLs.has(url) ? alwaysTrue : _this7.verifyEvent,\n          websocketImplementation: _this7._WebSocket\n        });\n        if (params?.connectionTimeout) relay.connectionTimeout = params.connectionTimeout;\n        _this7.relays.set(url, relay);\n      }\n      yield relay.connect();\n      return relay;\n    })();\n  }\n  close(relays) {\n    relays.map(normalizeURL).forEach(url => {\n      this.relays.get(url)?.close();\n    });\n  }\n  subscribeMany(relays, filters, params) {\n    return this.subscribeManyMap(Object.fromEntries(relays.map(url => [url, filters])), params);\n  }\n  subscribeManyMap(requests, params) {\n    var _this8 = this;\n    if (this.trackRelays) {\n      params.receivedEvent = (relay, id) => {\n        let set = this.seenOn.get(id);\n        if (!set) {\n          set = /* @__PURE__ */new Set();\n          this.seenOn.set(id, set);\n        }\n        set.add(relay);\n      };\n    }\n    const _knownIds = /* @__PURE__ */new Set();\n    const subs = [];\n    const relaysLength = Object.keys(requests).length;\n    const eosesReceived = [];\n    let handleEose = i2 => {\n      eosesReceived[i2] = true;\n      if (eosesReceived.filter(a => a).length === relaysLength) {\n        params.oneose?.();\n        handleEose = () => {};\n      }\n    };\n    const closesReceived = [];\n    let handleClose = (i2, reason) => {\n      handleEose(i2);\n      closesReceived[i2] = reason;\n      if (closesReceived.filter(a => a).length === relaysLength) {\n        params.onclose?.(closesReceived);\n        handleClose = () => {};\n      }\n    };\n    const localAlreadyHaveEventHandler = id => {\n      if (params.alreadyHaveEvent?.(id)) {\n        return true;\n      }\n      const have = _knownIds.has(id);\n      _knownIds.add(id);\n      return have;\n    };\n    const allOpened = Promise.all(Object.entries(requests).map(/*#__PURE__*/function () {\n      var _ref2 = _asyncToGenerator(function* (req, i2, arr) {\n        if (arr.indexOf(req) !== i2) {\n          handleClose(i2, \"duplicate url\");\n          return;\n        }\n        let [url, filters] = req;\n        url = normalizeURL(url);\n        let relay;\n        try {\n          relay = yield _this8.ensureRelay(url, {\n            connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : void 0\n          });\n        } catch (err) {\n          handleClose(i2, err?.message || String(err));\n          return;\n        }\n        let subscription = relay.subscribe(filters, {\n          ...params,\n          oneose: () => handleEose(i2),\n          onclose: reason => handleClose(i2, reason),\n          alreadyHaveEvent: localAlreadyHaveEventHandler,\n          eoseTimeout: params.maxWait\n        });\n        subs.push(subscription);\n      });\n      return function (_x, _x2, _x3) {\n        return _ref2.apply(this, arguments);\n      };\n    }()));\n    return {\n      close() {\n        return _asyncToGenerator(function* () {\n          yield allOpened;\n          subs.forEach(sub => {\n            sub.close();\n          });\n        })();\n      }\n    };\n  }\n  subscribeManyEose(relays, filters, params) {\n    const subcloser = this.subscribeMany(relays, filters, {\n      ...params,\n      oneose() {\n        subcloser.close();\n      }\n    });\n    return subcloser;\n  }\n  querySync(relays, filter, params) {\n    var _this9 = this;\n    return _asyncToGenerator(function* () {\n      return new Promise(/*#__PURE__*/function () {\n        var _ref3 = _asyncToGenerator(function* (resolve) {\n          const events = [];\n          _this9.subscribeManyEose(relays, [filter], {\n            ...params,\n            onevent(event) {\n              events.push(event);\n            },\n            onclose(_) {\n              resolve(events);\n            }\n          });\n        });\n        return function (_x4) {\n          return _ref3.apply(this, arguments);\n        };\n      }());\n    })();\n  }\n  get(relays, filter, params) {\n    var _this0 = this;\n    return _asyncToGenerator(function* () {\n      filter.limit = 1;\n      const events = yield _this0.querySync(relays, filter, params);\n      events.sort((a, b) => b.created_at - a.created_at);\n      return events[0] || null;\n    })();\n  }\n  publish(relays, event) {\n    var _this1 = this;\n    return relays.map(normalizeURL).map(/*#__PURE__*/function () {\n      var _ref4 = _asyncToGenerator(function* (url, i2, arr) {\n        if (arr.indexOf(url) !== i2) {\n          return Promise.reject(\"duplicate url\");\n        }\n        let r = yield _this1.ensureRelay(url);\n        return r.publish(event);\n      });\n      return function (_x5, _x6, _x7) {\n        return _ref4.apply(this, arguments);\n      };\n    }());\n  }\n};\n\n// pool.ts\nvar _WebSocket;\ntry {\n  _WebSocket = WebSocket;\n} catch {}\nfunction useWebSocketImplementation(websocketImplementation) {\n  _WebSocket = websocketImplementation;\n}\nvar SimplePool = class extends AbstractSimplePool {\n  constructor() {\n    super({\n      verifyEvent,\n      websocketImplementation: _WebSocket\n    });\n  }\n};\nexport { AbstractSimplePool, SimplePool, useWebSocketImplementation };","map":null,"metadata":{},"sourceType":"module","externalDependencies":[]}