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":[]}