@openclaw/nostr 2026.7.2-beta.7 → 2026.7.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{channel-O6-jXoT5.js → .setup/channel-B4SX7Iq6.mjs} +554 -877
- package/dist/{config-schema-CelPzg1N.js → .setup/config-schema-DIiXiBKr.mjs} +1 -1
- package/dist/.setup/inbound-direct-dm-runtime-EdLLVtkh.mjs +2 -0
- package/dist/{setup-adapter-BjKmSwdW.js → .setup/setup-adapter-DEU3o8MF.mjs} +1 -31
- package/dist/.setup/setup-plugin-api-DzlCumkz.mjs +2 -0
- package/dist/.setup/setup-plugin-api-csfJrRxD.mjs +111 -0
- package/dist/{setup-surface-BJCFpe02.js → .setup/setup-surface-DWa6-9ku.mjs} +70 -41
- package/dist/api.js +72 -61
- package/dist/channel-plugin-api.js +1 -1
- package/dist/doctor-contract-api.js +3 -2
- package/dist/setup-api.js +1 -1
- package/dist/setup-entry.js +2 -1
- package/dist/setup-plugin-api.js +1 -112
- package/node_modules/nostr-tools/lib/cjs/abstract-pool.js +28 -59
- package/node_modules/nostr-tools/lib/cjs/abstract-pool.js.map +3 -3
- package/node_modules/nostr-tools/lib/cjs/abstract-relay.js +7 -44
- package/node_modules/nostr-tools/lib/cjs/abstract-relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/core.js +1 -17
- package/node_modules/nostr-tools/lib/cjs/core.js.map +3 -3
- package/node_modules/nostr-tools/lib/cjs/filter.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/index.js +130 -172
- package/node_modules/nostr-tools/lib/cjs/index.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/kinds.js +1 -17
- package/node_modules/nostr-tools/lib/cjs/kinds.js.map +3 -3
- package/node_modules/nostr-tools/lib/cjs/nip04.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip10.js +5 -20
- package/node_modules/nostr-tools/lib/cjs/nip10.js.map +3 -3
- package/node_modules/nostr-tools/lib/cjs/nip13.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip17.js +23 -30
- package/node_modules/nostr-tools/lib/cjs/nip17.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip18.js +14 -21
- package/node_modules/nostr-tools/lib/cjs/nip18.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip19.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip21.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip22.js +7 -22
- package/node_modules/nostr-tools/lib/cjs/nip22.js.map +3 -3
- package/node_modules/nostr-tools/lib/cjs/nip25.js +14 -21
- package/node_modules/nostr-tools/lib/cjs/nip25.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip27.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip28.js +14 -21
- package/node_modules/nostr-tools/lib/cjs/nip28.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip29.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip30.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip42.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip44.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip45.js +9 -22
- package/node_modules/nostr-tools/lib/cjs/nip45.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip46.js +70 -111
- package/node_modules/nostr-tools/lib/cjs/nip46.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip47.js +18 -25
- package/node_modules/nostr-tools/lib/cjs/nip47.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip57.js +16 -23
- package/node_modules/nostr-tools/lib/cjs/nip57.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip58.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip59.js +7 -16
- package/node_modules/nostr-tools/lib/cjs/nip59.js.map +3 -3
- package/node_modules/nostr-tools/lib/cjs/nip75.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip94.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip98.js +16 -23
- package/node_modules/nostr-tools/lib/cjs/nip98.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip99.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nipb0.js +17 -38
- package/node_modules/nostr-tools/lib/cjs/nipb0.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nipb7.js +7 -13
- package/node_modules/nostr-tools/lib/cjs/nipb7.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/pool.js +61 -102
- package/node_modules/nostr-tools/lib/cjs/pool.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/pure.js +14 -21
- package/node_modules/nostr-tools/lib/cjs/pure.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/references.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/relay.js +42 -86
- package/node_modules/nostr-tools/lib/cjs/relay.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/signer.js +14 -21
- package/node_modules/nostr-tools/lib/cjs/signer.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/utils.js +0 -10
- package/node_modules/nostr-tools/lib/cjs/utils.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/wasm.js +2 -16
- package/node_modules/nostr-tools/lib/cjs/wasm.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/abstract-pool.js +28 -59
- package/node_modules/nostr-tools/lib/esm/abstract-pool.js.map +3 -3
- package/node_modules/nostr-tools/lib/esm/abstract-relay.js +7 -44
- package/node_modules/nostr-tools/lib/esm/abstract-relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/core.js +1 -15
- package/node_modules/nostr-tools/lib/esm/core.js.map +3 -3
- package/node_modules/nostr-tools/lib/esm/filter.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/index.js +80 -122
- package/node_modules/nostr-tools/lib/esm/index.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/kinds.js +1 -17
- package/node_modules/nostr-tools/lib/esm/kinds.js.map +3 -3
- package/node_modules/nostr-tools/lib/esm/nip04.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip10.js +5 -18
- package/node_modules/nostr-tools/lib/esm/nip10.js.map +3 -3
- package/node_modules/nostr-tools/lib/esm/nip13.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip17.js +8 -15
- package/node_modules/nostr-tools/lib/esm/nip17.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip18.js +8 -15
- package/node_modules/nostr-tools/lib/esm/nip18.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip19.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip21.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip22.js +7 -20
- package/node_modules/nostr-tools/lib/esm/nip22.js.map +3 -3
- package/node_modules/nostr-tools/lib/esm/nip25.js +8 -15
- package/node_modules/nostr-tools/lib/esm/nip25.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip27.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip28.js +8 -15
- package/node_modules/nostr-tools/lib/esm/nip28.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip29.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip30.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip42.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip44.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip45.js +10 -23
- package/node_modules/nostr-tools/lib/esm/nip45.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip46.js +54 -95
- package/node_modules/nostr-tools/lib/esm/nip46.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip47.js +8 -15
- package/node_modules/nostr-tools/lib/esm/nip47.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip57.js +10 -17
- package/node_modules/nostr-tools/lib/esm/nip57.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip58.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip59.js +1 -10
- package/node_modules/nostr-tools/lib/esm/nip59.js.map +3 -3
- package/node_modules/nostr-tools/lib/esm/nip75.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip94.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip98.js +8 -15
- package/node_modules/nostr-tools/lib/esm/nip98.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip99.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nipb0.js +18 -39
- package/node_modules/nostr-tools/lib/esm/nipb0.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nipb7.js +7 -13
- package/node_modules/nostr-tools/lib/esm/nipb7.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/pool.js +54 -95
- package/node_modules/nostr-tools/lib/esm/pool.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/pure.js +8 -15
- package/node_modules/nostr-tools/lib/esm/pure.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/references.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/relay.js +36 -80
- package/node_modules/nostr-tools/lib/esm/relay.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/signer.js +8 -15
- package/node_modules/nostr-tools/lib/esm/signer.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/utils.js +0 -10
- package/node_modules/nostr-tools/lib/esm/utils.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/wasm.js +3 -17
- package/node_modules/nostr-tools/lib/esm/wasm.js.map +4 -4
- package/node_modules/nostr-tools/lib/nostr.bundle.js +77 -121
- package/node_modules/nostr-tools/lib/nostr.bundle.js.map +4 -4
- package/node_modules/nostr-tools/lib/types/abstract-pool.d.ts +4 -7
- package/node_modules/nostr-tools/lib/types/abstract-relay.d.ts +2 -7
- package/node_modules/nostr-tools/lib/types/helpers.d.ts +2 -0
- package/node_modules/nostr-tools/lib/types/kinds.d.ts +0 -2
- package/node_modules/nostr-tools/lib/types/nipb0.d.ts +1 -0
- package/node_modules/nostr-tools/lib/types/nipb7.d.ts +1 -0
- package/node_modules/nostr-tools/lib/types/relay.d.ts +2 -2
- package/node_modules/nostr-tools/lib/types/utils.d.ts +0 -4
- package/node_modules/nostr-tools/package.json +1 -1
- package/openclaw.plugin.json +5 -0
- package/package.json +15 -41
- package/dist/inbound-direct-dm-runtime-DHn9NoYN.js +0 -2
- package/node_modules/nostr-tools/lib/types/nipb0.test.d.ts +0 -1
- /package/dist/{state-account-id-CvBZ9s6P.js → .setup/state-account-id-CvBZ9s6P.mjs} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../nip19.ts", "../../utils.ts", "../../references.ts"],
|
|
4
|
-
"sourcesContent": ["import { bytesToHex, concatBytes, hexToBytes } from '@noble/hashes/utils.js'\nimport { bech32 } from '@scure/base'\n\nimport { utf8Decoder, utf8Encoder } from './utils.ts'\n\nexport type NProfile = `nprofile1${string}`\nexport type NEvent = `nevent1${string}`\nexport type NAddr = `naddr1${string}`\nexport type NSec = `nsec1${string}`\nexport type NPub = `npub1${string}`\nexport type Note = `note1${string}`\nexport type Ncryptsec = `ncryptsec1${string}`\n\nexport const NostrTypeGuard = {\n isNProfile: (value?: string | null): value is NProfile => /^nprofile1[a-z\\d]+$/.test(value || ''),\n isNEvent: (value?: string | null): value is NEvent => /^nevent1[a-z\\d]+$/.test(value || ''),\n isNAddr: (value?: string | null): value is NAddr => /^naddr1[a-z\\d]+$/.test(value || ''),\n isNSec: (value?: string | null): value is NSec => /^nsec1[a-z\\d]{58}$/.test(value || ''),\n isNPub: (value?: string | null): value is NPub => /^npub1[a-z\\d]{58}$/.test(value || ''),\n isNote: (value?: string | null): value is Note => /^note1[a-z\\d]+$/.test(value || ''),\n isNcryptsec: (value?: string | null): value is Ncryptsec => /^ncryptsec1[a-z\\d]+$/.test(value || ''),\n}\n\nexport const Bech32MaxSize = 5000\n\n/**\n * Bech32 regex.\n * @see https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32\n */\nexport const BECH32_REGEX = /[\\x21-\\x7E]{1,83}1[023456789acdefghjklmnpqrstuvwxyz]{6,}/\n\nfunction integerToUint8Array(number: number) {\n // Create a Uint8Array with enough space to hold a 32-bit integer (4 bytes).\n const uint8Array = new Uint8Array(4)\n\n // Use bitwise operations to extract the bytes.\n uint8Array[0] = (number >> 24) & 0xff // Most significant byte (MSB)\n uint8Array[1] = (number >> 16) & 0xff\n uint8Array[2] = (number >> 8) & 0xff\n uint8Array[3] = number & 0xff // Least significant byte (LSB)\n\n return uint8Array\n}\n\nexport type ProfilePointer = {\n pubkey: string // hex\n relays?: string[]\n}\n\nexport type EventPointer = {\n id: string // hex\n relays?: string[]\n author?: string\n kind?: number\n}\n\nexport type AddressPointer = {\n identifier: string\n pubkey: string\n kind: number\n relays?: string[]\n}\n\nexport function decodeNostrURI(nip19code: string): ReturnType<typeof decode> | { type: 'invalid'; data: null } {\n try {\n if (nip19code.startsWith('nostr:')) nip19code = nip19code.substring(6)\n return decode(nip19code)\n } catch (_err) {\n return { type: 'invalid', data: null }\n }\n}\n\nexport type DecodedNevent = {\n type: 'nevent'\n data: EventPointer\n}\n\nexport type DecodedNprofile = {\n type: 'nprofile'\n data: ProfilePointer\n}\n\nexport type DecodedNaddr = {\n type: 'naddr'\n data: AddressPointer\n}\n\nexport type DecodedNsec = {\n type: 'nsec'\n data: Uint8Array\n}\n\nexport type DecodedNpub = {\n type: 'npub'\n data: string\n}\n\nexport type DecodedNote = {\n type: 'note'\n data: string\n}\n\nexport type DecodedResult = DecodedNevent | DecodedNprofile | DecodedNaddr | DecodedNpub | DecodedNsec | DecodedNote\n\nexport function decode(nip19: NEvent): DecodedNevent\nexport function decode(nip19: NProfile): DecodedNprofile\nexport function decode(nip19: NAddr): DecodedNaddr\nexport function decode(nip19: NSec): DecodedNsec\nexport function decode(nip19: NPub): DecodedNpub\nexport function decode(nip19: Note): DecodedNote\nexport function decode(code: string): DecodedResult\nexport function decode(code: string): DecodedResult {\n let { prefix, words } = bech32.decode(code as `${string}1${string}`, Bech32MaxSize)\n let data = new Uint8Array(bech32.fromWords(words))\n\n switch (prefix) {\n case 'nprofile': {\n let tlv = parseTLV(data)\n if (!tlv[0]?.[0]) throw new Error('missing TLV 0 for nprofile')\n if (tlv[0][0].length !== 32) throw new Error('TLV 0 should be 32 bytes')\n\n return {\n type: 'nprofile',\n data: {\n pubkey: bytesToHex(tlv[0][0]),\n relays: tlv[1] ? tlv[1].map(d => utf8Decoder.decode(d)) : [],\n },\n }\n }\n case 'nevent': {\n let tlv = parseTLV(data)\n if (!tlv[0]?.[0]) throw new Error('missing TLV 0 for nevent')\n if (tlv[0][0].length !== 32) throw new Error('TLV 0 should be 32 bytes')\n if (tlv[2] && tlv[2][0].length !== 32) throw new Error('TLV 2 should be 32 bytes')\n if (tlv[3] && tlv[3][0].length !== 4) throw new Error('TLV 3 should be 4 bytes')\n\n return {\n type: 'nevent',\n data: {\n id: bytesToHex(tlv[0][0]),\n relays: tlv[1] ? tlv[1].map(d => utf8Decoder.decode(d)) : [],\n author: tlv[2]?.[0] ? bytesToHex(tlv[2][0]) : undefined,\n kind: tlv[3]?.[0] ? parseInt(bytesToHex(tlv[3][0]), 16) : undefined,\n },\n }\n }\n\n case 'naddr': {\n let tlv = parseTLV(data)\n if (!tlv[0]?.[0]) throw new Error('missing TLV 0 for naddr')\n if (!tlv[2]?.[0]) throw new Error('missing TLV 2 for naddr')\n if (tlv[2][0].length !== 32) throw new Error('TLV 2 should be 32 bytes')\n if (!tlv[3]?.[0]) throw new Error('missing TLV 3 for naddr')\n if (tlv[3][0].length !== 4) throw new Error('TLV 3 should be 4 bytes')\n\n return {\n type: 'naddr',\n data: {\n identifier: utf8Decoder.decode(tlv[0][0]),\n pubkey: bytesToHex(tlv[2][0]),\n kind: parseInt(bytesToHex(tlv[3][0]), 16),\n relays: tlv[1] ? tlv[1].map(d => utf8Decoder.decode(d)) : [],\n },\n }\n }\n\n case 'nsec':\n return { type: prefix, data }\n\n case 'npub':\n case 'note':\n return { type: prefix, data: bytesToHex(data) }\n\n default:\n throw new Error(`unknown prefix ${prefix}`)\n }\n}\n\ntype TLV = { [t: number]: Uint8Array[] }\n\nfunction parseTLV(data: Uint8Array): TLV {\n let result: TLV = {}\n let rest = data\n while (rest.length > 0) {\n if (rest.length < 2) throw new Error('not enough data to read TLV')\n let t = rest[0]\n let l = rest[1]\n let v = rest.slice(2, 2 + l)\n rest = rest.slice(2 + l)\n if (v.length < l) throw new Error(`not enough data to read on TLV ${t}`)\n result[t] = result[t] || []\n result[t].push(v)\n }\n return result\n}\n\nexport function nsecEncode(key: Uint8Array): NSec {\n return encodeBytes('nsec', key)\n}\n\nexport function npubEncode(hex: string): NPub {\n return encodeBytes('npub', hexToBytes(hex))\n}\n\nexport function noteEncode(hex: string): Note {\n return encodeBytes('note', hexToBytes(hex))\n}\n\nfunction encodeBech32<Prefix extends string>(prefix: Prefix, data: Uint8Array): `${Prefix}1${string}` {\n let words = bech32.toWords(data)\n return bech32.encode(prefix, words, Bech32MaxSize) as `${Prefix}1${string}`\n}\n\nexport function encodeBytes<Prefix extends string>(prefix: Prefix, bytes: Uint8Array): `${Prefix}1${string}` {\n return encodeBech32(prefix, bytes)\n}\n\nexport function nprofileEncode(profile: ProfilePointer): NProfile {\n let data = encodeTLV({\n 0: [hexToBytes(profile.pubkey)],\n 1: (profile.relays || []).map(url => utf8Encoder.encode(url)),\n })\n return encodeBech32('nprofile', data)\n}\n\nexport function neventEncode(event: EventPointer): NEvent {\n let kindArray\n if (event.kind !== undefined) {\n kindArray = integerToUint8Array(event.kind)\n }\n\n let data = encodeTLV({\n 0: [hexToBytes(event.id)],\n 1: (event.relays || []).map(url => utf8Encoder.encode(url)),\n 2: event.author ? [hexToBytes(event.author)] : [],\n 3: kindArray ? [new Uint8Array(kindArray)] : [],\n })\n\n return encodeBech32('nevent', data)\n}\n\nexport function naddrEncode(addr: AddressPointer): NAddr {\n let kind = new ArrayBuffer(4)\n new DataView(kind).setUint32(0, addr.kind, false)\n\n let data = encodeTLV({\n 0: [utf8Encoder.encode(addr.identifier)],\n 1: (addr.relays || []).map(url => utf8Encoder.encode(url)),\n 2: [hexToBytes(addr.pubkey)],\n 3: [new Uint8Array(kind)],\n })\n return encodeBech32('naddr', data)\n}\n\nfunction encodeTLV(tlv: TLV): Uint8Array {\n let entries: Uint8Array[] = []\n\n Object.entries(tlv)\n .reverse()\n .forEach(([t, vs]) => {\n vs.forEach(v => {\n let entry = new Uint8Array(v.length + 2)\n entry.set([parseInt(t)], 0)\n entry.set([v.length], 1)\n entry.set(v, 2)\n entries.push(entry)\n })\n })\n\n return concatBytes(...entries)\n}\n", "import type { NostrEvent } from './core.ts'\n\nexport const utf8Decoder: TextDecoder = new TextDecoder('utf-8')\nexport const utf8Encoder: TextEncoder = new TextEncoder()\n\nexport { bytesToHex, hexToBytes } from '@noble/hashes/utils.js'\n\nexport function normalizeURL(url: string): string {\n try {\n if (url.indexOf('://') === -1) url = 'wss://' + url\n let p = new URL(url)\n if (p.protocol === 'http:') p.protocol = 'ws:'\n else if (p.protocol === 'https:') p.protocol = 'wss:'\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 } catch (e) {\n throw new Error(`Invalid URL: ${url}`)\n }\n}\n\nexport function insertEventIntoDescendingList(sortedArray: NostrEvent[], event: NostrEvent): NostrEvent[] {\n const [idx, found] = binarySearch(sortedArray, b => {\n if (event.id === b.id) return 0\n if (event.created_at === b.created_at) return -1\n return b.created_at - event.created_at\n })\n if (!found) {\n sortedArray.splice(idx, 0, event)\n }\n return sortedArray\n}\n\nexport function insertEventIntoAscendingList(sortedArray: NostrEvent[], event: NostrEvent): NostrEvent[] {\n const [idx, found] = binarySearch(sortedArray, b => {\n if (event.id === b.id) return 0\n if (event.created_at === b.created_at) return -1\n return event.created_at - b.created_at\n })\n if (!found) {\n sortedArray.splice(idx, 0, event)\n }\n return sortedArray\n}\n\nexport function binarySearch<T>(arr: T[], compare: (b: T) => number): [number, boolean] {\n let start = 0\n let end = arr.length - 1\n\n while (start <= end) {\n const mid = Math.floor((start + end) / 2)\n const cmp = compare(arr[mid])\n\n if (cmp === 0) {\n return [mid, true]\n }\n\n if (cmp < 0) {\n end = mid - 1\n } else {\n start = mid + 1\n }\n }\n\n return [start, false]\n}\n\nexport function mergeReverseSortedLists(list1: NostrEvent[], list2: NostrEvent[]): NostrEvent[] {\n const result: NostrEvent[] = new Array(list1.length + list2.length)\n result.length = 0\n let i1 = 0\n let i2 = 0\n let sameTimestampIds: string[] = []\n\n while (i1 < list1.length && i2 < list2.length) {\n let next: NostrEvent\n if (list1[i1]?.created_at > list2[i2]?.created_at) {\n next = list1[i1]\n i1++\n } else {\n next = list2[i2]\n i2++\n }\n\n if (result.length > 0 && result[result.length - 1].created_at === next.created_at) {\n if (sameTimestampIds.includes(next.id)) continue\n } else {\n sameTimestampIds.length = 0\n }\n\n result.push(next)\n sameTimestampIds.push(next.id)\n }\n\n while (i1 < list1.length) {\n const next = list1[i1]\n i1++\n\n if (result.length > 0 && result[result.length - 1].created_at === next.created_at) {\n if (sameTimestampIds.includes(next.id)) continue\n } else {\n sameTimestampIds.length = 0\n }\n result.push(next)\n sameTimestampIds.push(next.id)\n }\n\n while (i2 < list2.length) {\n const next = list2[i2]\n i2++\n\n if (result.length > 0 && result[result.length - 1].created_at === next.created_at) {\n if (sameTimestampIds.includes(next.id)) continue\n } else {\n sameTimestampIds.length = 0\n }\n result.push(next)\n sameTimestampIds.push(next.id)\n }\n\n return result\n}\n\n/**\n * Checks if a string is a 64-char lowercase hex string as most Nostr ids and pubkeys.\n */\nexport function isHex32(input: string): boolean {\n for (let i = 0; i < 64; i++) {\n let cc = input.charCodeAt(i)\n if (isNaN(cc) || cc < 48 || cc > 102 || (cc > 57 && cc < 97)) {\n return false\n }\n }\n return true\n}\n", "import { decode, type AddressPointer, type ProfilePointer, type EventPointer } from './nip19.ts'\n\nimport type { Event } from './core.ts'\n\ntype Reference = {\n text: string\n profile?: ProfilePointer\n event?: EventPointer\n address?: AddressPointer\n}\n\nconst mentionRegex = /\\bnostr:((note|npub|naddr|nevent|nprofile)1\\w+)\\b|#\\[(\\d+)\\]/g\n\nexport function parseReferences(evt: Event): Reference[] {\n let references: Reference[] = []\n for (let ref of evt.content.matchAll(mentionRegex)) {\n if (ref[2]) {\n // it's a NIP-27 mention\n try {\n let { type, data } = decode(ref[1])\n switch (type) {\n case 'npub': {\n references.push({\n text: ref[0],\n profile: { pubkey: data as string, relays: [] },\n })\n break\n }\n case 'nprofile': {\n references.push({\n text: ref[0],\n profile: data as ProfilePointer,\n })\n break\n }\n case 'note': {\n references.push({\n text: ref[0],\n event: { id: data as string, relays: [] },\n })\n break\n }\n case 'nevent': {\n references.push({\n text: ref[0],\n event: data as EventPointer,\n })\n break\n }\n case 'naddr': {\n references.push({\n text: ref[0],\n address: data as AddressPointer,\n })\n break\n }\n }\n } catch (err) {\n /***/\n }\n } else if (ref[3]) {\n // it's a NIP-10 mention\n let idx = parseInt(ref[3], 10)\n let tag = evt.tags[idx]\n if (!tag) continue\n\n switch (tag[0]) {\n case 'p': {\n references.push({\n text: ref[0],\n profile: { pubkey: tag[1], relays: tag[2] ? [tag[2]] : [] },\n })\n break\n }\n case 'e': {\n references.push({\n text: ref[0],\n event: { id: tag[1], relays: tag[2] ? [tag[2]] : [] },\n })\n break\n }\n case 'a': {\n try {\n let [kind, pubkey, identifier] = tag[1].split(':')\n references.push({\n text: ref[0],\n address: {\n identifier,\n pubkey,\n kind: parseInt(kind, 10),\n relays: tag[2] ? [tag[2]] : [],\n },\n })\n } catch (err) {\n /***/\n }\n break\n }\n }\n }\n }\n\n return references\n}\n"],
|
|
4
|
+
"sourcesContent": ["import { bytesToHex, concatBytes, hexToBytes } from '@noble/hashes/utils.js'\nimport { bech32 } from '@scure/base'\n\nimport { utf8Decoder, utf8Encoder } from './utils.ts'\n\nexport type NProfile = `nprofile1${string}`\nexport type NEvent = `nevent1${string}`\nexport type NAddr = `naddr1${string}`\nexport type NSec = `nsec1${string}`\nexport type NPub = `npub1${string}`\nexport type Note = `note1${string}`\nexport type Ncryptsec = `ncryptsec1${string}`\n\nexport const NostrTypeGuard = {\n isNProfile: (value?: string | null): value is NProfile => /^nprofile1[a-z\\d]+$/.test(value || ''),\n isNEvent: (value?: string | null): value is NEvent => /^nevent1[a-z\\d]+$/.test(value || ''),\n isNAddr: (value?: string | null): value is NAddr => /^naddr1[a-z\\d]+$/.test(value || ''),\n isNSec: (value?: string | null): value is NSec => /^nsec1[a-z\\d]{58}$/.test(value || ''),\n isNPub: (value?: string | null): value is NPub => /^npub1[a-z\\d]{58}$/.test(value || ''),\n isNote: (value?: string | null): value is Note => /^note1[a-z\\d]+$/.test(value || ''),\n isNcryptsec: (value?: string | null): value is Ncryptsec => /^ncryptsec1[a-z\\d]+$/.test(value || ''),\n}\n\nexport const Bech32MaxSize = 5000\n\n/**\n * Bech32 regex.\n * @see https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32\n */\nexport const BECH32_REGEX = /[\\x21-\\x7E]{1,83}1[023456789acdefghjklmnpqrstuvwxyz]{6,}/\n\nfunction integerToUint8Array(number: number) {\n // Create a Uint8Array with enough space to hold a 32-bit integer (4 bytes).\n const uint8Array = new Uint8Array(4)\n\n // Use bitwise operations to extract the bytes.\n uint8Array[0] = (number >> 24) & 0xff // Most significant byte (MSB)\n uint8Array[1] = (number >> 16) & 0xff\n uint8Array[2] = (number >> 8) & 0xff\n uint8Array[3] = number & 0xff // Least significant byte (LSB)\n\n return uint8Array\n}\n\nexport type ProfilePointer = {\n pubkey: string // hex\n relays?: string[]\n}\n\nexport type EventPointer = {\n id: string // hex\n relays?: string[]\n author?: string\n kind?: number\n}\n\nexport type AddressPointer = {\n identifier: string\n pubkey: string\n kind: number\n relays?: string[]\n}\n\nexport function decodeNostrURI(nip19code: string): ReturnType<typeof decode> | { type: 'invalid'; data: null } {\n try {\n if (nip19code.startsWith('nostr:')) nip19code = nip19code.substring(6)\n return decode(nip19code)\n } catch (_err) {\n return { type: 'invalid', data: null }\n }\n}\n\nexport type DecodedNevent = {\n type: 'nevent'\n data: EventPointer\n}\n\nexport type DecodedNprofile = {\n type: 'nprofile'\n data: ProfilePointer\n}\n\nexport type DecodedNaddr = {\n type: 'naddr'\n data: AddressPointer\n}\n\nexport type DecodedNsec = {\n type: 'nsec'\n data: Uint8Array\n}\n\nexport type DecodedNpub = {\n type: 'npub'\n data: string\n}\n\nexport type DecodedNote = {\n type: 'note'\n data: string\n}\n\nexport type DecodedResult = DecodedNevent | DecodedNprofile | DecodedNaddr | DecodedNpub | DecodedNsec | DecodedNote\n\nexport function decode(nip19: NEvent): DecodedNevent\nexport function decode(nip19: NProfile): DecodedNprofile\nexport function decode(nip19: NAddr): DecodedNaddr\nexport function decode(nip19: NSec): DecodedNsec\nexport function decode(nip19: NPub): DecodedNpub\nexport function decode(nip19: Note): DecodedNote\nexport function decode(code: string): DecodedResult\nexport function decode(code: string): DecodedResult {\n let { prefix, words } = bech32.decode(code as `${string}1${string}`, Bech32MaxSize)\n let data = new Uint8Array(bech32.fromWords(words))\n\n switch (prefix) {\n case 'nprofile': {\n let tlv = parseTLV(data)\n if (!tlv[0]?.[0]) throw new Error('missing TLV 0 for nprofile')\n if (tlv[0][0].length !== 32) throw new Error('TLV 0 should be 32 bytes')\n\n return {\n type: 'nprofile',\n data: {\n pubkey: bytesToHex(tlv[0][0]),\n relays: tlv[1] ? tlv[1].map(d => utf8Decoder.decode(d)) : [],\n },\n }\n }\n case 'nevent': {\n let tlv = parseTLV(data)\n if (!tlv[0]?.[0]) throw new Error('missing TLV 0 for nevent')\n if (tlv[0][0].length !== 32) throw new Error('TLV 0 should be 32 bytes')\n if (tlv[2] && tlv[2][0].length !== 32) throw new Error('TLV 2 should be 32 bytes')\n if (tlv[3] && tlv[3][0].length !== 4) throw new Error('TLV 3 should be 4 bytes')\n\n return {\n type: 'nevent',\n data: {\n id: bytesToHex(tlv[0][0]),\n relays: tlv[1] ? tlv[1].map(d => utf8Decoder.decode(d)) : [],\n author: tlv[2]?.[0] ? bytesToHex(tlv[2][0]) : undefined,\n kind: tlv[3]?.[0] ? parseInt(bytesToHex(tlv[3][0]), 16) : undefined,\n },\n }\n }\n\n case 'naddr': {\n let tlv = parseTLV(data)\n if (!tlv[0]?.[0]) throw new Error('missing TLV 0 for naddr')\n if (!tlv[2]?.[0]) throw new Error('missing TLV 2 for naddr')\n if (tlv[2][0].length !== 32) throw new Error('TLV 2 should be 32 bytes')\n if (!tlv[3]?.[0]) throw new Error('missing TLV 3 for naddr')\n if (tlv[3][0].length !== 4) throw new Error('TLV 3 should be 4 bytes')\n\n return {\n type: 'naddr',\n data: {\n identifier: utf8Decoder.decode(tlv[0][0]),\n pubkey: bytesToHex(tlv[2][0]),\n kind: parseInt(bytesToHex(tlv[3][0]), 16),\n relays: tlv[1] ? tlv[1].map(d => utf8Decoder.decode(d)) : [],\n },\n }\n }\n\n case 'nsec':\n return { type: prefix, data }\n\n case 'npub':\n case 'note':\n return { type: prefix, data: bytesToHex(data) }\n\n default:\n throw new Error(`unknown prefix ${prefix}`)\n }\n}\n\ntype TLV = { [t: number]: Uint8Array[] }\n\nfunction parseTLV(data: Uint8Array): TLV {\n let result: TLV = {}\n let rest = data\n while (rest.length > 0) {\n if (rest.length < 2) throw new Error('not enough data to read TLV')\n let t = rest[0]\n let l = rest[1]\n let v = rest.slice(2, 2 + l)\n rest = rest.slice(2 + l)\n if (v.length < l) throw new Error(`not enough data to read on TLV ${t}`)\n result[t] = result[t] || []\n result[t].push(v)\n }\n return result\n}\n\nexport function nsecEncode(key: Uint8Array): NSec {\n return encodeBytes('nsec', key)\n}\n\nexport function npubEncode(hex: string): NPub {\n return encodeBytes('npub', hexToBytes(hex))\n}\n\nexport function noteEncode(hex: string): Note {\n return encodeBytes('note', hexToBytes(hex))\n}\n\nfunction encodeBech32<Prefix extends string>(prefix: Prefix, data: Uint8Array): `${Prefix}1${string}` {\n let words = bech32.toWords(data)\n return bech32.encode(prefix, words, Bech32MaxSize) as `${Prefix}1${string}`\n}\n\nexport function encodeBytes<Prefix extends string>(prefix: Prefix, bytes: Uint8Array): `${Prefix}1${string}` {\n return encodeBech32(prefix, bytes)\n}\n\nexport function nprofileEncode(profile: ProfilePointer): NProfile {\n let data = encodeTLV({\n 0: [hexToBytes(profile.pubkey)],\n 1: (profile.relays || []).map(url => utf8Encoder.encode(url)),\n })\n return encodeBech32('nprofile', data)\n}\n\nexport function neventEncode(event: EventPointer): NEvent {\n let kindArray\n if (event.kind !== undefined) {\n kindArray = integerToUint8Array(event.kind)\n }\n\n let data = encodeTLV({\n 0: [hexToBytes(event.id)],\n 1: (event.relays || []).map(url => utf8Encoder.encode(url)),\n 2: event.author ? [hexToBytes(event.author)] : [],\n 3: kindArray ? [new Uint8Array(kindArray)] : [],\n })\n\n return encodeBech32('nevent', data)\n}\n\nexport function naddrEncode(addr: AddressPointer): NAddr {\n let kind = new ArrayBuffer(4)\n new DataView(kind).setUint32(0, addr.kind, false)\n\n let data = encodeTLV({\n 0: [utf8Encoder.encode(addr.identifier)],\n 1: (addr.relays || []).map(url => utf8Encoder.encode(url)),\n 2: [hexToBytes(addr.pubkey)],\n 3: [new Uint8Array(kind)],\n })\n return encodeBech32('naddr', data)\n}\n\nfunction encodeTLV(tlv: TLV): Uint8Array {\n let entries: Uint8Array[] = []\n\n Object.entries(tlv)\n .reverse()\n .forEach(([t, vs]) => {\n vs.forEach(v => {\n let entry = new Uint8Array(v.length + 2)\n entry.set([parseInt(t)], 0)\n entry.set([v.length], 1)\n entry.set(v, 2)\n entries.push(entry)\n })\n })\n\n return concatBytes(...entries)\n}\n", "import type { NostrEvent } from './core.ts'\n\nexport const utf8Decoder: TextDecoder = new TextDecoder('utf-8')\nexport const utf8Encoder: TextEncoder = new TextEncoder()\n\nexport { bytesToHex, hexToBytes } from '@noble/hashes/utils.js'\n\nexport function normalizeURL(url: string): string {\n try {\n if (url.indexOf('://') === -1) url = 'wss://' + url\n let p = new URL(url)\n if (p.protocol === 'http:') p.protocol = 'ws:'\n else if (p.protocol === 'https:') p.protocol = 'wss:'\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 } catch (e) {\n throw new Error(`Invalid URL: ${url}`)\n }\n}\n\nexport function insertEventIntoDescendingList(sortedArray: NostrEvent[], event: NostrEvent): NostrEvent[] {\n const [idx, found] = binarySearch(sortedArray, b => {\n if (event.id === b.id) return 0\n if (event.created_at === b.created_at) return -1\n return b.created_at - event.created_at\n })\n if (!found) {\n sortedArray.splice(idx, 0, event)\n }\n return sortedArray\n}\n\nexport function insertEventIntoAscendingList(sortedArray: NostrEvent[], event: NostrEvent): NostrEvent[] {\n const [idx, found] = binarySearch(sortedArray, b => {\n if (event.id === b.id) return 0\n if (event.created_at === b.created_at) return -1\n return event.created_at - b.created_at\n })\n if (!found) {\n sortedArray.splice(idx, 0, event)\n }\n return sortedArray\n}\n\nexport function binarySearch<T>(arr: T[], compare: (b: T) => number): [number, boolean] {\n let start = 0\n let end = arr.length - 1\n\n while (start <= end) {\n const mid = Math.floor((start + end) / 2)\n const cmp = compare(arr[mid])\n\n if (cmp === 0) {\n return [mid, true]\n }\n\n if (cmp < 0) {\n end = mid - 1\n } else {\n start = mid + 1\n }\n }\n\n return [start, false]\n}\n\nexport function mergeReverseSortedLists(list1: NostrEvent[], list2: NostrEvent[]): NostrEvent[] {\n const result: NostrEvent[] = new Array(list1.length + list2.length)\n result.length = 0\n let i1 = 0\n let i2 = 0\n let sameTimestampIds: string[] = []\n\n while (i1 < list1.length && i2 < list2.length) {\n let next: NostrEvent\n if (list1[i1]?.created_at > list2[i2]?.created_at) {\n next = list1[i1]\n i1++\n } else {\n next = list2[i2]\n i2++\n }\n\n if (result.length > 0 && result[result.length - 1].created_at === next.created_at) {\n if (sameTimestampIds.includes(next.id)) continue\n } else {\n sameTimestampIds.length = 0\n }\n\n result.push(next)\n sameTimestampIds.push(next.id)\n }\n\n while (i1 < list1.length) {\n const next = list1[i1]\n i1++\n\n if (result.length > 0 && result[result.length - 1].created_at === next.created_at) {\n if (sameTimestampIds.includes(next.id)) continue\n } else {\n sameTimestampIds.length = 0\n }\n result.push(next)\n sameTimestampIds.push(next.id)\n }\n\n while (i2 < list2.length) {\n const next = list2[i2]\n i2++\n\n if (result.length > 0 && result[result.length - 1].created_at === next.created_at) {\n if (sameTimestampIds.includes(next.id)) continue\n } else {\n sameTimestampIds.length = 0\n }\n result.push(next)\n sameTimestampIds.push(next.id)\n }\n\n return result\n}\n", "import { decode, type AddressPointer, type ProfilePointer, type EventPointer } from './nip19.ts'\n\nimport type { Event } from './core.ts'\n\ntype Reference = {\n text: string\n profile?: ProfilePointer\n event?: EventPointer\n address?: AddressPointer\n}\n\nconst mentionRegex = /\\bnostr:((note|npub|naddr|nevent|nprofile)1\\w+)\\b|#\\[(\\d+)\\]/g\n\nexport function parseReferences(evt: Event): Reference[] {\n let references: Reference[] = []\n for (let ref of evt.content.matchAll(mentionRegex)) {\n if (ref[2]) {\n // it's a NIP-27 mention\n try {\n let { type, data } = decode(ref[1])\n switch (type) {\n case 'npub': {\n references.push({\n text: ref[0],\n profile: { pubkey: data as string, relays: [] },\n })\n break\n }\n case 'nprofile': {\n references.push({\n text: ref[0],\n profile: data as ProfilePointer,\n })\n break\n }\n case 'note': {\n references.push({\n text: ref[0],\n event: { id: data as string, relays: [] },\n })\n break\n }\n case 'nevent': {\n references.push({\n text: ref[0],\n event: data as EventPointer,\n })\n break\n }\n case 'naddr': {\n references.push({\n text: ref[0],\n address: data as AddressPointer,\n })\n break\n }\n }\n } catch (err) {\n /***/\n }\n } else if (ref[3]) {\n // it's a NIP-10 mention\n let idx = parseInt(ref[3], 10)\n let tag = evt.tags[idx]\n if (!tag) continue\n\n switch (tag[0]) {\n case 'p': {\n references.push({\n text: ref[0],\n profile: { pubkey: tag[1], relays: tag[2] ? [tag[2]] : [] },\n })\n break\n }\n case 'e': {\n references.push({\n text: ref[0],\n event: { id: tag[1], relays: tag[2] ? [tag[2]] : [] },\n })\n break\n }\n case 'a': {\n try {\n let [kind, pubkey, identifier] = tag[1].split(':')\n references.push({\n text: ref[0],\n address: {\n identifier,\n pubkey,\n kind: parseInt(kind, 10),\n relays: tag[2] ? [tag[2]] : [],\n },\n })\n } catch (err) {\n /***/\n }\n break\n }\n }\n }\n }\n\n return references\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["bytesToHex", "hexToBytes", "bytesToHex"]
|
|
7
7
|
}
|
|
@@ -2,41 +2,6 @@
|
|
|
2
2
|
import { schnorr } from "@noble/curves/secp256k1.js";
|
|
3
3
|
import { bytesToHex as bytesToHex2, hexToBytes as hexToBytes2 } from "@noble/hashes/utils.js";
|
|
4
4
|
|
|
5
|
-
// utils.ts
|
|
6
|
-
import { bytesToHex, hexToBytes } from "@noble/hashes/utils.js";
|
|
7
|
-
var utf8Decoder = new TextDecoder("utf-8");
|
|
8
|
-
var utf8Encoder = new TextEncoder();
|
|
9
|
-
function normalizeURL(url) {
|
|
10
|
-
try {
|
|
11
|
-
if (url.indexOf("://") === -1)
|
|
12
|
-
url = "wss://" + url;
|
|
13
|
-
let p = new URL(url);
|
|
14
|
-
if (p.protocol === "http:")
|
|
15
|
-
p.protocol = "ws:";
|
|
16
|
-
else if (p.protocol === "https:")
|
|
17
|
-
p.protocol = "wss:";
|
|
18
|
-
p.pathname = p.pathname.replace(/\/+/g, "/");
|
|
19
|
-
if (p.pathname.endsWith("/"))
|
|
20
|
-
p.pathname = p.pathname.slice(0, -1);
|
|
21
|
-
if (p.port === "80" && p.protocol === "ws:" || p.port === "443" && p.protocol === "wss:")
|
|
22
|
-
p.port = "";
|
|
23
|
-
p.searchParams.sort();
|
|
24
|
-
p.hash = "";
|
|
25
|
-
return p.toString();
|
|
26
|
-
} catch (e) {
|
|
27
|
-
throw new Error(`Invalid URL: ${url}`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function isHex32(input) {
|
|
31
|
-
for (let i2 = 0; i2 < 64; i2++) {
|
|
32
|
-
let cc = input.charCodeAt(i2);
|
|
33
|
-
if (isNaN(cc) || cc < 48 || cc > 102 || cc > 57 && cc < 97) {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
5
|
// core.ts
|
|
41
6
|
var verifiedSymbol = Symbol("verified");
|
|
42
7
|
var isRecord = (obj) => obj instanceof Object;
|
|
@@ -51,7 +16,7 @@ function validateEvent(event) {
|
|
|
51
16
|
return false;
|
|
52
17
|
if (typeof event.pubkey !== "string")
|
|
53
18
|
return false;
|
|
54
|
-
if (!
|
|
19
|
+
if (!event.pubkey.match(/^[a-f0-9]{64}$/))
|
|
55
20
|
return false;
|
|
56
21
|
if (!Array.isArray(event.tags))
|
|
57
22
|
return false;
|
|
@@ -69,6 +34,34 @@ function validateEvent(event) {
|
|
|
69
34
|
|
|
70
35
|
// pure.ts
|
|
71
36
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
37
|
+
|
|
38
|
+
// utils.ts
|
|
39
|
+
import { bytesToHex, hexToBytes } from "@noble/hashes/utils.js";
|
|
40
|
+
var utf8Decoder = new TextDecoder("utf-8");
|
|
41
|
+
var utf8Encoder = new TextEncoder();
|
|
42
|
+
function normalizeURL(url) {
|
|
43
|
+
try {
|
|
44
|
+
if (url.indexOf("://") === -1)
|
|
45
|
+
url = "wss://" + url;
|
|
46
|
+
let p = new URL(url);
|
|
47
|
+
if (p.protocol === "http:")
|
|
48
|
+
p.protocol = "ws:";
|
|
49
|
+
else if (p.protocol === "https:")
|
|
50
|
+
p.protocol = "wss:";
|
|
51
|
+
p.pathname = p.pathname.replace(/\/+/g, "/");
|
|
52
|
+
if (p.pathname.endsWith("/"))
|
|
53
|
+
p.pathname = p.pathname.slice(0, -1);
|
|
54
|
+
if (p.port === "80" && p.protocol === "ws:" || p.port === "443" && p.protocol === "wss:")
|
|
55
|
+
p.port = "";
|
|
56
|
+
p.searchParams.sort();
|
|
57
|
+
p.hash = "";
|
|
58
|
+
return p.toString();
|
|
59
|
+
} catch (e) {
|
|
60
|
+
throw new Error(`Invalid URL: ${url}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// pure.ts
|
|
72
65
|
var JS = class {
|
|
73
66
|
generateSecretKey() {
|
|
74
67
|
return schnorr.utils.randomSecretKey();
|
|
@@ -210,14 +203,12 @@ var AbstractRelay = class {
|
|
|
210
203
|
openSubs = /* @__PURE__ */ new Map();
|
|
211
204
|
enablePing;
|
|
212
205
|
enableReconnect;
|
|
213
|
-
idleTimeout = 0;
|
|
214
206
|
idleSince = Date.now();
|
|
215
207
|
ongoingOperations = 0;
|
|
216
208
|
reconnectTimeoutHandle;
|
|
217
209
|
pingIntervalHandle;
|
|
218
210
|
reconnectAttempts = 0;
|
|
219
211
|
skipReconnection = false;
|
|
220
|
-
idleTimeoutHandle;
|
|
221
212
|
connectionPromise;
|
|
222
213
|
openCountRequests = /* @__PURE__ */ new Map();
|
|
223
214
|
openEventPublishes = /* @__PURE__ */ new Map();
|
|
@@ -233,8 +224,6 @@ var AbstractRelay = class {
|
|
|
233
224
|
this._WebSocket = opts.websocketImplementation || WebSocket;
|
|
234
225
|
this.enablePing = opts.enablePing;
|
|
235
226
|
this.enableReconnect = opts.enableReconnect || false;
|
|
236
|
-
if (opts.idleTimeout)
|
|
237
|
-
this.idleTimeout = opts.idleTimeout;
|
|
238
227
|
}
|
|
239
228
|
static async connect(url, opts) {
|
|
240
229
|
const relay = new AbstractRelay(url, opts);
|
|
@@ -258,22 +247,6 @@ var AbstractRelay = class {
|
|
|
258
247
|
get connected() {
|
|
259
248
|
return this._connected;
|
|
260
249
|
}
|
|
261
|
-
clearIdleTimeout() {
|
|
262
|
-
if (this.idleTimeoutHandle) {
|
|
263
|
-
clearTimeout(this.idleTimeoutHandle);
|
|
264
|
-
this.idleTimeoutHandle = void 0;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
scheduleIdleClose() {
|
|
268
|
-
this.clearIdleTimeout();
|
|
269
|
-
if (this.idleTimeout > 0) {
|
|
270
|
-
this.idleTimeoutHandle = setTimeout(() => {
|
|
271
|
-
if (this.ongoingOperations === 0 && this.idleSince) {
|
|
272
|
-
this.close();
|
|
273
|
-
}
|
|
274
|
-
}, this.idleTimeout);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
250
|
async reconnect() {
|
|
278
251
|
const backoff = this.resubscribeBackoff[Math.min(this.reconnectAttempts, this.resubscribeBackoff.length - 1)];
|
|
279
252
|
this.reconnectAttempts++;
|
|
@@ -285,11 +258,6 @@ var AbstractRelay = class {
|
|
|
285
258
|
}, backoff);
|
|
286
259
|
}
|
|
287
260
|
handleHardClose(reason) {
|
|
288
|
-
if (this.ws) {
|
|
289
|
-
this.ws.onopen = null;
|
|
290
|
-
this.ws.onerror = null;
|
|
291
|
-
this.ws.onclose = null;
|
|
292
|
-
}
|
|
293
261
|
if (this.pingIntervalHandle) {
|
|
294
262
|
clearInterval(this.pingIntervalHandle);
|
|
295
263
|
this.pingIntervalHandle = void 0;
|
|
@@ -297,7 +265,6 @@ var AbstractRelay = class {
|
|
|
297
265
|
this._connected = false;
|
|
298
266
|
this.connectionPromise = void 0;
|
|
299
267
|
this.idleSince = void 0;
|
|
300
|
-
this.clearIdleTimeout();
|
|
301
268
|
if (this.enableReconnect && !this.skipReconnection) {
|
|
302
269
|
this.reconnect();
|
|
303
270
|
} else {
|
|
@@ -320,6 +287,7 @@ var AbstractRelay = class {
|
|
|
320
287
|
if (this.reconnectAttempts === 0) {
|
|
321
288
|
this.skipReconnection = true;
|
|
322
289
|
}
|
|
290
|
+
this.onclose?.();
|
|
323
291
|
this.handleHardClose("relay connection timed out");
|
|
324
292
|
}, opts.timeout);
|
|
325
293
|
}
|
|
@@ -365,6 +333,7 @@ var AbstractRelay = class {
|
|
|
365
333
|
if (this.reconnectAttempts === 0) {
|
|
366
334
|
this.skipReconnection = true;
|
|
367
335
|
}
|
|
336
|
+
this.onclose?.();
|
|
368
337
|
this.handleHardClose("relay connection failed");
|
|
369
338
|
};
|
|
370
339
|
this.ws.onclose = (ev) => {
|
|
@@ -453,7 +422,6 @@ var AbstractRelay = class {
|
|
|
453
422
|
}
|
|
454
423
|
async publish(event) {
|
|
455
424
|
this.idleSince = void 0;
|
|
456
|
-
this.clearIdleTimeout();
|
|
457
425
|
this.ongoingOperations++;
|
|
458
426
|
const ret = new Promise((resolve, reject) => {
|
|
459
427
|
const timeout = setTimeout(() => {
|
|
@@ -475,10 +443,8 @@ var AbstractRelay = class {
|
|
|
475
443
|
}
|
|
476
444
|
}
|
|
477
445
|
this.ongoingOperations--;
|
|
478
|
-
if (this.ongoingOperations === 0)
|
|
446
|
+
if (this.ongoingOperations === 0)
|
|
479
447
|
this.idleSince = Date.now();
|
|
480
|
-
this.scheduleIdleClose();
|
|
481
|
-
}
|
|
482
448
|
return ret;
|
|
483
449
|
}
|
|
484
450
|
async count(filters, params) {
|
|
@@ -504,7 +470,6 @@ var AbstractRelay = class {
|
|
|
504
470
|
subscribe(filters, params) {
|
|
505
471
|
if (params.label !== "<forced-ping>") {
|
|
506
472
|
this.idleSince = void 0;
|
|
507
|
-
this.clearIdleTimeout();
|
|
508
473
|
this.ongoingOperations++;
|
|
509
474
|
}
|
|
510
475
|
const sub = this.prepareSubscription(filters, params);
|
|
@@ -533,17 +498,10 @@ var AbstractRelay = class {
|
|
|
533
498
|
}
|
|
534
499
|
this.closeAllSubscriptions("relay connection closed by us");
|
|
535
500
|
this._connected = false;
|
|
536
|
-
this.connectionPromise = void 0;
|
|
537
501
|
this.idleSince = void 0;
|
|
538
|
-
this.clearIdleTimeout();
|
|
539
502
|
this.onclose?.();
|
|
540
|
-
if (this.ws) {
|
|
541
|
-
this.ws
|
|
542
|
-
this.ws.onerror = null;
|
|
543
|
-
this.ws.onclose = null;
|
|
544
|
-
if (this.ws.readyState !== this._WebSocket.CLOSING && this.ws.readyState !== this._WebSocket.CLOSED) {
|
|
545
|
-
this.ws.close();
|
|
546
|
-
}
|
|
503
|
+
if (this.ws?.readyState === this._WebSocket.OPEN) {
|
|
504
|
+
this.ws?.close();
|
|
547
505
|
}
|
|
548
506
|
}
|
|
549
507
|
_onmessage(ev) {
|
|
@@ -570,7 +528,7 @@ var AbstractRelay = class {
|
|
|
570
528
|
case "EVENT": {
|
|
571
529
|
const so = this.openSubs.get(data[1]);
|
|
572
530
|
const event = data[2];
|
|
573
|
-
if (
|
|
531
|
+
if (this.verifyEvent(event) && matchFilters(so.filters, event)) {
|
|
574
532
|
so.onevent(event);
|
|
575
533
|
} else {
|
|
576
534
|
so.oninvalidevent?.(event);
|
|
@@ -718,10 +676,8 @@ var Subscription = class {
|
|
|
718
676
|
}
|
|
719
677
|
this.relay.openSubs.delete(this.id);
|
|
720
678
|
this.relay.ongoingOperations--;
|
|
721
|
-
if (this.relay.ongoingOperations === 0)
|
|
679
|
+
if (this.relay.ongoingOperations === 0)
|
|
722
680
|
this.relay.idleSince = Date.now();
|
|
723
|
-
this.relay.scheduleIdleClose();
|
|
724
|
-
}
|
|
725
681
|
this.onclose?.(reason);
|
|
726
682
|
}
|
|
727
683
|
};
|