nostr-tools 2.23.4 → 2.23.5
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/lib/cjs/abstract-pool.js +5 -1
- package/lib/cjs/abstract-pool.js.map +2 -2
- package/lib/cjs/abstract-relay.js +5 -1
- package/lib/cjs/abstract-relay.js.map +2 -2
- package/lib/cjs/index.js +5 -1
- package/lib/cjs/index.js.map +2 -2
- package/lib/cjs/nip46.js +5 -1
- package/lib/cjs/nip46.js.map +2 -2
- package/lib/cjs/nip47.js.map +2 -2
- package/lib/cjs/pool.js +5 -1
- package/lib/cjs/pool.js.map +2 -2
- package/lib/cjs/relay.js +5 -1
- package/lib/cjs/relay.js.map +2 -2
- package/lib/esm/abstract-pool.js +5 -1
- package/lib/esm/abstract-pool.js.map +2 -2
- package/lib/esm/abstract-relay.js +5 -1
- package/lib/esm/abstract-relay.js.map +2 -2
- package/lib/esm/index.js +5 -1
- package/lib/esm/index.js.map +2 -2
- package/lib/esm/nip46.js +5 -1
- package/lib/esm/nip46.js.map +2 -2
- package/lib/esm/nip47.js.map +2 -2
- package/lib/esm/pool.js +5 -1
- package/lib/esm/pool.js.map +2 -2
- package/lib/esm/relay.js +5 -1
- package/lib/esm/relay.js.map +2 -2
- package/lib/nostr.bundle.js +5 -1
- package/lib/nostr.bundle.js.map +2 -2
- package/lib/types/abstract-pool.d.ts +60 -0
- package/lib/types/abstract-relay.d.ts +110 -0
- package/lib/types/benchmarks.d.ts +1 -0
- package/lib/types/core.d.ts +32 -0
- package/lib/types/core.test.d.ts +1 -0
- package/lib/types/fakejson.d.ts +6 -0
- package/lib/types/fakejson.test.d.ts +1 -0
- package/lib/types/filter.d.ts +19 -0
- package/lib/types/filter.test.d.ts +1 -0
- package/lib/types/helpers.d.ts +2 -0
- package/lib/types/index.d.ts +31 -0
- package/lib/types/kinds.d.ts +200 -0
- package/lib/types/kinds.test.d.ts +1 -0
- package/lib/types/nip04.d.ts +2 -0
- package/lib/types/nip04.test.d.ts +1 -0
- package/lib/types/nip05.d.ts +17 -0
- package/lib/types/nip05.test.d.ts +1 -0
- package/lib/types/nip06.d.ts +15 -0
- package/lib/types/nip06.test.d.ts +1 -0
- package/lib/types/nip07.d.ts +13 -0
- package/lib/types/nip10.d.ts +24 -0
- package/lib/types/nip10.test.d.ts +1 -0
- package/lib/types/nip11.d.ts +266 -0
- package/lib/types/nip11.test.d.ts +1 -0
- package/lib/types/nip13.d.ts +8 -0
- package/lib/types/nip13.test.d.ts +1 -0
- package/lib/types/nip17.d.ts +15 -0
- package/lib/types/nip17.test.d.ts +1 -0
- package/lib/types/nip18.d.ts +22 -0
- package/lib/types/nip18.test.d.ts +1 -0
- package/lib/types/nip19.d.ts +81 -0
- package/lib/types/nip19.test.d.ts +1 -0
- package/lib/types/nip21.d.ts +34 -0
- package/lib/types/nip21.test.d.ts +1 -0
- package/lib/types/nip22.d.ts +36 -0
- package/lib/types/nip22.test.d.ts +1 -0
- package/lib/types/nip25.d.ts +15 -0
- package/lib/types/nip25.test.d.ts +1 -0
- package/lib/types/nip27.d.ts +32 -0
- package/lib/types/nip27.test.d.ts +1 -0
- package/lib/types/nip28.d.ts +46 -0
- package/lib/types/nip28.test.d.ts +1 -0
- package/lib/types/nip29.d.ts +265 -0
- package/lib/types/nip30.d.ts +22 -0
- package/lib/types/nip30.test.d.ts +1 -0
- package/lib/types/nip39.d.ts +2 -0
- package/lib/types/nip39.test.d.ts +1 -0
- package/lib/types/nip40.d.ts +10 -0
- package/lib/types/nip40.test.d.ts +1 -0
- package/lib/types/nip42.d.ts +5 -0
- package/lib/types/nip42.test.d.ts +1 -0
- package/lib/types/nip44.d.ts +18 -0
- package/lib/types/nip44.test.d.ts +1 -0
- package/lib/types/nip46.d.ts +119 -0
- package/lib/types/nip47.d.ts +11 -0
- package/lib/types/nip47.test.d.ts +1 -0
- package/lib/types/nip49.d.ts +3 -0
- package/lib/types/nip49.test.d.ts +1 -0
- package/lib/types/nip54.d.ts +1 -0
- package/lib/types/nip54.test.d.ts +1 -0
- package/lib/types/nip55.d.ts +30 -0
- package/lib/types/nip55.test.d.ts +1 -0
- package/lib/types/nip57.d.ts +25 -0
- package/lib/types/nip57.test.d.ts +1 -0
- package/lib/types/nip58.d.ts +134 -0
- package/lib/types/nip58.test.d.ts +1 -0
- package/lib/types/nip59.d.ts +12 -0
- package/lib/types/nip59.test.d.ts +1 -0
- package/lib/types/nip75.d.ts +61 -0
- package/lib/types/nip75.test.d.ts +1 -0
- package/lib/types/nip77.d.ts +102 -0
- package/lib/types/nip77.test.d.ts +1 -0
- package/lib/types/nip94.d.ts +87 -0
- package/lib/types/nip94.test.d.ts +1 -0
- package/lib/types/nip98.d.ts +74 -0
- package/lib/types/nip98.test.d.ts +1 -0
- package/lib/types/nip99.d.ts +92 -0
- package/lib/types/nip99.test.d.ts +1 -0
- package/lib/types/nipb7.d.ts +23 -0
- package/lib/types/nipb7.test.d.ts +1 -0
- package/lib/types/pool.d.ts +6 -0
- package/lib/types/pool.test.d.ts +1 -0
- package/lib/types/pure.d.ts +8 -0
- package/lib/types/pure.test.d.ts +1 -0
- package/lib/types/references.d.ts +10 -0
- package/lib/types/references.test.d.ts +1 -0
- package/lib/types/relay.d.ts +11 -0
- package/lib/types/relay.test.d.ts +1 -0
- package/lib/types/signer.d.ts +11 -0
- package/lib/types/test-helpers.d.ts +14 -0
- package/lib/types/utils.d.ts +9 -0
- package/lib/types/utils.test.d.ts +1 -0
- package/lib/types/wasm.d.ts +8 -0
- package/package.json +1 -1
package/lib/cjs/nip46.js
CHANGED
|
@@ -731,7 +731,11 @@ var AbstractRelay = class {
|
|
|
731
731
|
case "AUTH": {
|
|
732
732
|
this.challenge = data[1];
|
|
733
733
|
if (this.onauth) {
|
|
734
|
-
this.auth(this.onauth)
|
|
734
|
+
this.auth(this.onauth).catch((err) => {
|
|
735
|
+
if (!(err instanceof SendingOnClosedConnection)) {
|
|
736
|
+
throw err;
|
|
737
|
+
}
|
|
738
|
+
});
|
|
735
739
|
}
|
|
736
740
|
return;
|
|
737
741
|
}
|
package/lib/cjs/nip46.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../nip46.ts", "../../pure.ts", "../../core.ts", "../../utils.ts", "../../nip44.ts", "../../nip05.ts", "../../kinds.ts", "../../filter.ts", "../../fakejson.ts", "../../nip42.ts", "../../abstract-relay.ts", "../../helpers.ts", "../../abstract-pool.ts", "../../pool.ts"],
|
|
4
|
-
"sourcesContent": ["import { EventTemplate, NostrEvent, VerifiedEvent } from './core.ts'\nimport { generateSecretKey, finalizeEvent, getPublicKey, verifyEvent } from './pure.ts'\nimport { AbstractSimplePool, SubCloser } from './abstract-pool.ts'\nimport { getConversationKey, decrypt, encrypt } from './nip44.ts'\nimport { NIP05_REGEX } from './nip05.ts'\nimport { SimplePool } from './pool.ts'\nimport { Handlerinformation, NostrConnect } from './kinds.ts'\nimport { Signer } from './signer.ts'\n\nvar _fetch: any\n\ntry {\n _fetch = fetch\n} catch {}\n\nexport function useFetchImplementation(fetchImplementation: any) {\n _fetch = fetchImplementation\n}\n\nexport const BUNKER_REGEX = /^bunker:\\/\\/([0-9a-f]{64})\\??([?\\/\\w:.=&%-]*)$/\nconst EMAIL_REGEX = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\nexport type BunkerPointer = {\n relays: string[]\n pubkey: string\n secret: null | string\n}\n\nexport function toBunkerURL(bunkerPointer: BunkerPointer): string {\n let bunkerURL = new URL(`bunker://${bunkerPointer.pubkey}`)\n bunkerPointer.relays.forEach(relay => {\n bunkerURL.searchParams.append('relay', relay)\n })\n if (bunkerPointer.secret) {\n bunkerURL.searchParams.set('secret', bunkerPointer.secret)\n }\n return bunkerURL.toString()\n}\n\n/** This takes either a bunker:// URL or a name@domain.com NIP-05 identifier\n and returns a BunkerPointer -- or null in case of error */\nexport async function parseBunkerInput(input: string): Promise<BunkerPointer | null> {\n let match = input.match(BUNKER_REGEX)\n if (match) {\n try {\n const pubkey = match[1]\n const qs = new URLSearchParams(match[2])\n return {\n pubkey,\n relays: qs.getAll('relay'),\n secret: qs.get('secret'),\n }\n } catch (_err) {\n /* just move to the next case */\n }\n }\n\n return queryBunkerProfile(input)\n}\n\nexport async function queryBunkerProfile(nip05: string): Promise<BunkerPointer | null> {\n const match = nip05.match(NIP05_REGEX)\n if (!match) return null\n\n const [_, name = '_', domain] = match\n\n try {\n const url = `https://${domain}/.well-known/nostr.json?name=${name}`\n const res = await (await _fetch(url, { redirect: 'error' })).json()\n\n let pubkey = res.names[name]\n let relays = res.nip46[pubkey] || []\n\n return { pubkey, relays, secret: null }\n } catch (_err) {\n return null\n }\n}\n\nexport type NostrConnectParams = {\n clientPubkey: string\n relays: string[]\n secret: string\n perms?: string[]\n name?: string\n url?: string\n image?: string\n}\n\nexport function createNostrConnectURI(params: NostrConnectParams): string {\n const queryParams = new URLSearchParams()\n\n params.relays.forEach(relay => {\n queryParams.append('relay', relay)\n })\n\n queryParams.append('secret', params.secret)\n\n if (params.perms && params.perms.length > 0) {\n queryParams.append('perms', params.perms.join(','))\n }\n if (params.name) {\n queryParams.append('name', params.name)\n }\n if (params.url) {\n queryParams.append('url', params.url)\n }\n if (params.image) {\n queryParams.append('image', params.image)\n }\n\n return `nostrconnect://${params.clientPubkey}?${queryParams.toString()}`\n}\n\nexport type BunkerSignerParams = {\n pool?: AbstractSimplePool\n onauth?: (url: string) => void\n /** Skip automatic switchRelays() call in fromURI. Useful when you want to call it manually at your own pace. */\n skipSwitchRelays?: boolean\n}\n\nexport class BunkerSigner implements Signer {\n private params: BunkerSignerParams\n private pool: AbstractSimplePool\n private subCloser: SubCloser | undefined\n private isOpen: boolean\n private serial: number\n private idPrefix: string\n private listeners: {\n [id: string]: {\n resolve: (_: string) => void\n reject: (_: string) => void\n }\n }\n private waitingForAuth: { [id: string]: boolean }\n private secretKey: Uint8Array\n // If the client initiates the connection, the two variables below can be filled in later.\n private conversationKey!: Uint8Array\n public bp!: BunkerPointer\n\n private cachedPubKey: string | undefined\n\n /**\n * Creates a new instance of the Nip46 class.\n * @param relays - An array of relay addresses.\n * @param remotePubkey - An optional remote public key. This is the key you want to sign as.\n * @param secretKey - An optional key pair.\n */\n private constructor(clientSecretKey: Uint8Array, params: BunkerSignerParams) {\n this.params = params\n this.pool = params.pool || new SimplePool()\n this.secretKey = clientSecretKey\n this.isOpen = false\n this.idPrefix = Math.random().toString(36).substring(7)\n this.serial = 0\n this.listeners = {}\n this.waitingForAuth = {}\n }\n\n /**\n * [Factory Method 1] Creates a Signer using bunker information (bunker:// URL or NIP-05).\n * This method is used when the public key of the bunker is known in advance.\n */\n public static fromBunker(\n clientSecretKey: Uint8Array,\n bp: BunkerPointer,\n params: BunkerSignerParams = {},\n ): BunkerSigner {\n if (bp.relays.length === 0) {\n throw new Error('no relays specified for this bunker')\n }\n\n const signer = new BunkerSigner(clientSecretKey, params)\n\n signer.conversationKey = getConversationKey(clientSecretKey, bp.pubkey)\n signer.bp = bp\n\n signer.setupSubscription()\n return signer\n }\n\n /**\n * [Factory Method 2] Creates a Signer using a nostrconnect:// URI generated by the client.\n * In this method, the bunker initiates the connection by scanning the URI.\n */\n public static async fromURI(\n clientSecretKey: Uint8Array,\n connectionURI: string,\n bunkerParams: BunkerSignerParams = {},\n maxWaitOrAbort: number | AbortSignal = 300_000,\n ): Promise<BunkerSigner> {\n const signer = new BunkerSigner(clientSecretKey, bunkerParams)\n const uri = new URL(connectionURI)\n const clientPubkey = getPublicKey(clientSecretKey)\n\n return new Promise((resolve, reject) => {\n let success = false\n const sub = signer.pool.subscribe(\n uri.searchParams.getAll('relay'),\n {\n kinds: [NostrConnect],\n '#p': [clientPubkey],\n limit: 0,\n },\n {\n onevent: async (event: NostrEvent) => {\n try {\n const tempConvKey = getConversationKey(clientSecretKey, event.pubkey)\n const decryptedContent = decrypt(event.content, tempConvKey)\n\n const response = JSON.parse(decryptedContent)\n\n if (response.result === uri.searchParams.get('secret')) {\n sub.close()\n\n signer.bp = {\n pubkey: event.pubkey,\n relays: uri.searchParams.getAll('relay'),\n secret: uri.searchParams.get('secret'),\n }\n signer.conversationKey = getConversationKey(clientSecretKey, event.pubkey)\n signer.setupSubscription()\n\n success = true\n if (!bunkerParams.skipSwitchRelays) {\n await Promise.race([new Promise(resolve => setTimeout(resolve, 1000)), signer.switchRelays()])\n }\n resolve(signer)\n }\n } catch (e) {\n console.warn('failed to process potential connection event', e)\n }\n },\n onclose: () => {\n if (!success) reject(new Error('subscription closed before connection was established.'))\n },\n maxWait: typeof maxWaitOrAbort === 'number' ? maxWaitOrAbort : undefined,\n abort: typeof maxWaitOrAbort !== 'number' ? maxWaitOrAbort : undefined,\n },\n )\n })\n }\n\n private setupSubscription() {\n const listeners = this.listeners\n const waitingForAuth = this.waitingForAuth\n const convKey = this.conversationKey\n\n this.subCloser = this.pool.subscribe(\n this.bp.relays,\n {\n kinds: [NostrConnect],\n authors: [this.bp.pubkey],\n '#p': [getPublicKey(this.secretKey)],\n limit: 0,\n },\n {\n onevent: async (event: NostrEvent) => {\n const o = JSON.parse(decrypt(event.content, convKey))\n const { id, result, error } = o\n\n if (result === 'auth_url' && waitingForAuth[id]) {\n delete waitingForAuth[id]\n\n if (this.params.onauth) {\n this.params.onauth(error)\n } else {\n console.warn(\n `nostr-tools/nip46: remote signer ${this.bp.pubkey} tried to send an \"auth_url\"='${error}' but there was no onauth() callback configured.`,\n )\n }\n return\n }\n\n let handler = listeners[id]\n if (handler) {\n if (error) handler.reject(error)\n else if (result) handler.resolve(result)\n delete listeners[id]\n }\n },\n onclose: () => {\n this.subCloser = undefined\n },\n },\n )\n this.isOpen = true\n }\n\n async switchRelays(): Promise<boolean> {\n try {\n const switchResp = await this.sendRequest('switch_relays', [])\n let relays = JSON.parse(switchResp) as string[] | null\n if (!relays) return false\n if (JSON.stringify(relays.sort()) === JSON.stringify(this.bp.relays)) return false\n\n this.bp.relays = relays\n let previousCloser = this.subCloser!\n setTimeout(() => {\n previousCloser.close()\n }, 5000)\n\n this.subCloser = undefined\n this.setupSubscription()\n return true\n } catch {\n return false\n }\n }\n\n // closes the subscription -- this object can't be used anymore after this\n async close() {\n this.isOpen = false\n this.subCloser!.close()\n }\n\n async sendRequest(method: string, params: string[]): Promise<string> {\n return new Promise(async (resolve, reject) => {\n try {\n if (!this.isOpen) throw new Error('this signer is not open anymore, create a new one')\n if (!this.subCloser) this.setupSubscription()\n\n this.serial++\n const id = `${this.idPrefix}-${this.serial}`\n\n const encryptedContent = encrypt(JSON.stringify({ id, method, params }), this.conversationKey)\n\n // the request event\n const verifiedEvent: VerifiedEvent = finalizeEvent(\n {\n kind: NostrConnect,\n tags: [['p', this.bp.pubkey]],\n content: encryptedContent,\n created_at: Math.floor(Date.now() / 1000),\n },\n this.secretKey,\n )\n\n // setup callback listener\n this.listeners[id] = { resolve, reject }\n this.waitingForAuth[id] = true\n\n // publish the event\n await Promise.any(this.pool.publish(this.bp.relays, verifiedEvent))\n } catch (err) {\n reject(err)\n }\n })\n }\n\n /**\n * Calls the \"connect\" method on the bunker.\n * The promise will be rejected if the response is not \"pong\".\n */\n async ping(): Promise<void> {\n let resp = await this.sendRequest('ping', [])\n if (resp !== 'pong') throw new Error(`result is not pong: ${resp}`)\n }\n\n /**\n * Calls the \"connect\" method on the bunker.\n */\n async connect(): Promise<void> {\n await this.sendRequest('connect', [this.bp.pubkey, this.bp.secret || ''])\n }\n\n /**\n * Calls the \"get_public_key\" method on the bunker.\n * (before we would return the public key hardcoded in the bunker parameters, but\n * that is not correct as that may be the bunker pubkey and the actual signer\n * pubkey may be different.)\n */\n async getPublicKey(): Promise<string> {\n if (!this.cachedPubKey) {\n this.cachedPubKey = await this.sendRequest('get_public_key', [])\n }\n return this.cachedPubKey\n }\n\n /**\n * Signs an event using the remote private key.\n * @param event - The event to sign.\n * @returns A Promise that resolves to the signed event.\n */\n async signEvent(event: EventTemplate): Promise<VerifiedEvent> {\n let resp = await this.sendRequest('sign_event', [JSON.stringify(event)])\n let signed: NostrEvent = JSON.parse(resp)\n if (verifyEvent(signed)) {\n return signed\n } else {\n throw new Error(`event returned from bunker is improperly signed: ${JSON.stringify(signed)}`)\n }\n }\n\n async nip04Encrypt(thirdPartyPubkey: string, plaintext: string): Promise<string> {\n return await this.sendRequest('nip04_encrypt', [thirdPartyPubkey, plaintext])\n }\n\n async nip04Decrypt(thirdPartyPubkey: string, ciphertext: string): Promise<string> {\n return await this.sendRequest('nip04_decrypt', [thirdPartyPubkey, ciphertext])\n }\n\n async nip44Encrypt(thirdPartyPubkey: string, plaintext: string): Promise<string> {\n return await this.sendRequest('nip44_encrypt', [thirdPartyPubkey, plaintext])\n }\n\n async nip44Decrypt(thirdPartyPubkey: string, ciphertext: string): Promise<string> {\n return await this.sendRequest('nip44_decrypt', [thirdPartyPubkey, ciphertext])\n }\n}\n\n/**\n * Creates an account with the specified username, domain, and optional email.\n * @param bunkerPubkey - The public key of the bunker to use for the create_account call.\n * @param username - The username for the account.\n * @param domain - The domain for the account.\n * @param email - The optional email for the account.\n * @param localSecretKey - Optionally pass a local secret key that will be used to communicate with the bunker,\n this will default to generating a random key.\n * @throws Error if the email is present but invalid.\n * @returns A Promise that resolves to the auth_url that the client should follow to create an account.\n */\nexport async function createAccount(\n bunker: BunkerProfile,\n params: BunkerSignerParams,\n username: string,\n domain: string,\n email?: string,\n localSecretKey: Uint8Array = generateSecretKey(),\n): Promise<BunkerSigner> {\n if (email && !EMAIL_REGEX.test(email)) throw new Error('invalid email')\n\n let rpc = BunkerSigner.fromBunker(localSecretKey, bunker.bunkerPointer, params)\n\n let pubkey = await rpc.sendRequest('create_account', [username, domain, email || ''])\n\n // once we get the newly created pubkey back, we hijack this signer instance\n // and turn it into the main instance for this newly created pubkey\n rpc.bp.pubkey = pubkey\n await rpc.connect()\n\n return rpc\n}\n\n/**\n * Fetches info on available providers that announce themselves using NIP-89 events.\n * @returns A promise that resolves to an array of available bunker objects.\n */\nexport async function fetchBunkerProviders(pool: AbstractSimplePool, relays: string[]): Promise<BunkerProfile[]> {\n const events = await pool.querySync(relays, {\n kinds: [Handlerinformation],\n '#k': [NostrConnect.toString()],\n })\n\n events.sort((a, b) => b.created_at - a.created_at)\n\n // validate bunkers by checking their NIP-05 and pubkey\n // map to a more useful object\n const validatedBunkers = await Promise.all(\n events.map(async (event, i) => {\n try {\n const content = JSON.parse(event.content)\n\n // skip duplicates\n try {\n if (events.findIndex(ev => JSON.parse(ev.content).nip05 === content.nip05) !== i) return undefined\n } catch (err) {\n /***/\n }\n\n const bp = await queryBunkerProfile(content.nip05)\n if (bp && bp.pubkey === event.pubkey && bp.relays.length) {\n return {\n bunkerPointer: bp,\n nip05: content.nip05,\n domain: content.nip05.split('@')[1],\n name: content.name || content.display_name,\n picture: content.picture,\n about: content.about,\n website: content.website,\n local: false,\n }\n }\n } catch (err) {\n return undefined\n }\n }),\n )\n\n return validatedBunkers.filter(b => b !== undefined) as BunkerProfile[]\n}\n\nexport type BunkerProfile = {\n bunkerPointer: BunkerPointer\n domain: string\n nip05: string\n name: string\n picture: string\n about: string\n website: string\n local: boolean\n}\n", "import { schnorr } from '@noble/curves/secp256k1.js'\nimport { bytesToHex, hexToBytes } from '@noble/hashes/utils.js'\nimport { Nostr, Event, EventTemplate, UnsignedEvent, VerifiedEvent, verifiedSymbol, validateEvent } from './core.ts'\nimport { sha256 } from '@noble/hashes/sha2.js'\n\nimport { utf8Encoder } from './utils.ts'\n\nclass JS implements Nostr {\n generateSecretKey(): Uint8Array {\n return schnorr.utils.randomSecretKey()\n }\n getPublicKey(secretKey: Uint8Array): string {\n return bytesToHex(schnorr.getPublicKey(secretKey))\n }\n finalizeEvent(t: EventTemplate, secretKey: Uint8Array): VerifiedEvent {\n const event = t as VerifiedEvent\n event.pubkey = bytesToHex(schnorr.getPublicKey(secretKey))\n event.id = getEventHash(event)\n event.sig = bytesToHex(schnorr.sign(hexToBytes(getEventHash(event)), secretKey))\n event[verifiedSymbol] = true\n return event\n }\n verifyEvent(event: Event): event is VerifiedEvent {\n if (typeof event[verifiedSymbol] === 'boolean') return event[verifiedSymbol]\n\n try {\n const hash = getEventHash(event)\n if (hash !== event.id) {\n event[verifiedSymbol] = false\n return false\n }\n\n const valid = schnorr.verify(hexToBytes(event.sig), hexToBytes(hash), hexToBytes(event.pubkey))\n event[verifiedSymbol] = valid\n return valid\n } catch (err) {\n event[verifiedSymbol] = false\n return false\n }\n }\n}\n\nexport function serializeEvent(evt: UnsignedEvent): string {\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}\n\nexport function getEventHash(event: UnsignedEvent): string {\n let eventHash = sha256(utf8Encoder.encode(serializeEvent(event)))\n return bytesToHex(eventHash)\n}\n\nconst i: JS = new JS()\n\nexport const generateSecretKey = i.generateSecretKey\nexport const getPublicKey = i.getPublicKey\nexport const finalizeEvent = i.finalizeEvent\nexport const verifyEvent = i.verifyEvent\nexport * from './core.ts'\n", "export interface Nostr {\n generateSecretKey(): Uint8Array\n getPublicKey(secretKey: Uint8Array): string\n finalizeEvent(event: EventTemplate, secretKey: Uint8Array): VerifiedEvent\n verifyEvent(event: Event): event is VerifiedEvent\n}\n\n/** Designates a verified event signature. */\nexport const verifiedSymbol = Symbol('verified')\n\nexport type NostrEvent = {\n kind: number\n tags: string[][]\n content: string\n created_at: number\n pubkey: string\n id: string\n sig: string\n [verifiedSymbol]?: boolean\n}\n\nexport type Event = NostrEvent\nexport type EventTemplate = Pick<Event, 'kind' | 'tags' | 'content' | 'created_at'>\nexport type UnsignedEvent = Pick<Event, 'kind' | 'tags' | 'content' | 'created_at' | 'pubkey'>\n\n/** An event whose signature has been verified. */\nexport interface VerifiedEvent extends Event {\n [verifiedSymbol]: true\n}\n\nconst isRecord = (obj: unknown): obj is Record<string, unknown> => obj instanceof Object\n\nexport function validateEvent<T>(event: T): event is T & UnsignedEvent {\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\n if (!Array.isArray(event.tags)) return false\n for (let i = 0; i < event.tags.length; i++) {\n let tag = event.tags[i]\n if (!Array.isArray(tag)) return false\n for (let j = 0; j < tag.length; j++) {\n if (typeof tag[j] !== 'string') return false\n }\n }\n\n return true\n}\n\n/**\n * Sort events in reverse-chronological order by the `created_at` timestamp,\n * and then by the event `id` (lexicographically) in case of ties.\n * This mutates the array.\n */\nexport function sortEvents(events: Event[]): Event[] {\n return events.sort((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.localeCompare(b.id)\n })\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 { chacha20 } from '@noble/ciphers/chacha.js'\nimport { equalBytes } from '@noble/ciphers/utils.js'\nimport { secp256k1 } from '@noble/curves/secp256k1.js'\nimport { extract as hkdf_extract, expand as hkdf_expand } from '@noble/hashes/hkdf.js'\nimport { hmac } from '@noble/hashes/hmac.js'\nimport { sha256 } from '@noble/hashes/sha2.js'\nimport { concatBytes, hexToBytes, randomBytes } from '@noble/hashes/utils.js'\nimport { base64 } from '@scure/base'\n\nimport { utf8Decoder, utf8Encoder } from './utils.ts'\n\nconst minPlaintextSize = 0x0001 // 1b msg => padded to 32b\nconst maxPlaintextSize = 0xffffffff // 4294967295 (2^32-1)\nconst extendedPrefixThreshold = 0x10000 // 65536: lengths below use 2-byte u16 prefix, at or above use 6-byte prefix\n\nexport function getConversationKey(privkeyA: Uint8Array, pubkeyB: string): Uint8Array {\n const sharedX = secp256k1.getSharedSecret(privkeyA, hexToBytes('02' + pubkeyB)).subarray(1, 33)\n return hkdf_extract(sha256, sharedX, utf8Encoder.encode('nip44-v2'))\n}\n\nfunction getMessageKeys(\n conversationKey: Uint8Array,\n nonce: Uint8Array,\n): { chacha_key: Uint8Array; chacha_nonce: Uint8Array; hmac_key: Uint8Array } {\n const keys = hkdf_expand(sha256, conversationKey, nonce, 76)\n return {\n chacha_key: keys.subarray(0, 32),\n chacha_nonce: keys.subarray(32, 44),\n hmac_key: keys.subarray(44, 76),\n }\n}\n\nfunction calcPaddedLen(len: number): number {\n if (!Number.isSafeInteger(len) || len < 1) throw new Error('expected positive integer')\n if (len <= 32) return 32\n const nextPower = 2 ** (Math.floor(Math.log2(len - 1)) + 1)\n const chunk = nextPower <= 256 ? 32 : nextPower / 8\n return chunk * (Math.floor((len - 1) / chunk) + 1)\n}\n\nfunction writeU16BE(num: number): Uint8Array {\n if (!Number.isSafeInteger(num) || num < minPlaintextSize || num > 0xffff)\n throw new Error('invalid plaintext size: must be between 1 and 65535 bytes')\n const arr = new Uint8Array(2)\n new DataView(arr.buffer).setUint16(0, num, false)\n return arr\n}\n\nfunction writeU32BE(num: number): Uint8Array {\n if (!Number.isSafeInteger(num) || num < extendedPrefixThreshold || num > maxPlaintextSize)\n throw new Error('invalid plaintext size: must be between 65536 and 4294967295 bytes')\n const arr = new Uint8Array(4)\n new DataView(arr.buffer).setUint32(0, num, false)\n return arr\n}\n\nfunction pad(plaintext: string): Uint8Array {\n const unpadded = utf8Encoder.encode(plaintext)\n const unpaddedLen = unpadded.length\n if (unpaddedLen < minPlaintextSize || unpaddedLen > maxPlaintextSize)\n throw new Error('invalid plaintext size: must be between 1 and 4294967295 bytes')\n const prefix =\n unpaddedLen >= extendedPrefixThreshold\n ? concatBytes(new Uint8Array([0, 0]), writeU32BE(unpaddedLen)) // 6 bytes\n : writeU16BE(unpaddedLen) // 2 bytes\n const suffix = new Uint8Array(calcPaddedLen(unpaddedLen) - unpaddedLen)\n return concatBytes(prefix, unpadded, suffix)\n}\n\nfunction unpad(padded: Uint8Array): string {\n const dv = new DataView(padded.buffer, padded.byteOffset, padded.byteLength)\n const firstTwo = dv.getUint16(0)\n let unpaddedLen: number\n let prefixLen: number\n if (firstTwo === 0) {\n // Extended format: 2 zero bytes + 4-byte u32 length\n unpaddedLen = dv.getUint32(2)\n if (unpaddedLen < extendedPrefixThreshold) throw new Error('invalid padding')\n prefixLen = 6\n } else {\n unpaddedLen = firstTwo\n prefixLen = 2\n }\n const unpadded = padded.subarray(prefixLen, prefixLen + unpaddedLen)\n if (\n unpaddedLen < minPlaintextSize ||\n unpaddedLen > maxPlaintextSize ||\n unpadded.length !== unpaddedLen ||\n padded.length !== prefixLen + calcPaddedLen(unpaddedLen)\n )\n throw new Error('invalid padding')\n return utf8Decoder.decode(unpadded)\n}\n\nfunction hmacAad(key: Uint8Array, message: Uint8Array, aad: Uint8Array): Uint8Array {\n if (aad.length !== 32) throw new Error('AAD associated data must be 32 bytes')\n const combined = concatBytes(aad, message)\n return hmac(sha256, key, combined)\n}\n\n// metadata: always 65b (version: 1b, nonce: 32b, mac: 32b)\n// plaintext: 1b to 0xffffffff\n// padded plaintext (small, <65536): 32b to 0x10000, with 2b prefix -> 34b to 0x10000+2\n// padded plaintext (large, >=65536): 0x10000 to 0x100000000, with 6b prefix -> 0x10006 to 0x100000000+6\n// ciphertext: same as padded plaintext (chacha20 doesn't change length)\n// raw payload (small): 99 (65+34) to 65603 (65+0x10000+2)\n// raw payload (large): 65607 (65+0x10006) to 4294967367 (65+0x100000000+6)\nfunction decodePayload(payload: string): { nonce: Uint8Array; ciphertext: Uint8Array; mac: Uint8Array } {\n if (typeof payload !== 'string') throw new Error('payload must be a valid string')\n const plen = payload.length\n if (plen < 132) throw new Error('invalid payload length: ' + plen)\n if (payload[0] === '#') throw new Error('unknown encryption version')\n let data: Uint8Array\n try {\n data = base64.decode(payload)\n } catch (error) {\n throw new Error('invalid base64: ' + (error as any).message)\n }\n const dlen = data.length\n if (dlen < 99) throw new Error('invalid data length: ' + dlen)\n const vers = data[0]\n if (vers !== 2) throw new Error('unknown encryption version ' + vers)\n return {\n nonce: data.subarray(1, 33),\n ciphertext: data.subarray(33, -32),\n mac: data.subarray(-32),\n }\n}\n\nexport function encrypt(plaintext: string, conversationKey: Uint8Array, nonce: Uint8Array = randomBytes(32)): string {\n const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce)\n const padded = pad(plaintext)\n const ciphertext = chacha20(chacha_key, chacha_nonce, padded)\n const mac = hmacAad(hmac_key, ciphertext, nonce)\n return base64.encode(concatBytes(new Uint8Array([2]), nonce, ciphertext, mac))\n}\n\n/** Callers should validate payload size before calling to prevent DoS from oversized inputs. */\nexport function decrypt(payload: string, conversationKey: Uint8Array): string {\n const { nonce, ciphertext, mac } = decodePayload(payload)\n const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce)\n const calculatedMac = hmacAad(hmac_key, ciphertext, nonce)\n if (!equalBytes(calculatedMac, mac)) throw new Error('invalid MAC')\n const padded = chacha20(chacha_key, chacha_nonce, ciphertext)\n return unpad(padded)\n}\n\nexport const v2 = {\n utils: {\n getConversationKey,\n calcPaddedLen,\n pad,\n unpad,\n },\n encrypt,\n decrypt,\n}\n", "import { ProfilePointer } from './nip19.ts'\n\nexport type Nip05 = `${string}@${string}`\n\n/**\n * NIP-05 regex. The localpart is optional, and should be assumed to be `_` otherwise.\n *\n * - 0: full match\n * - 1: name (optional)\n * - 2: domain\n */\nexport const NIP05_REGEX = /^(?:([\\w.+-]+)@)?([\\w_-]+(\\.[\\w_-]+)+)$/\nexport const isNip05 = (value?: string | null): value is Nip05 => NIP05_REGEX.test(value || '')\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _fetch: any\n\ntry {\n _fetch = fetch\n} catch (_) {\n null\n}\n\nexport function useFetchImplementation(fetchImplementation: unknown) {\n _fetch = fetchImplementation\n}\n\nexport async function searchDomain(domain: string, query = ''): Promise<{ [name: string]: string }> {\n try {\n const url = `https://${domain}/.well-known/nostr.json?name=${query}`\n const res = await _fetch(url, { redirect: 'manual' })\n if (res.status !== 200) {\n throw Error('Wrong response code')\n }\n const json = await res.json()\n return json.names\n } catch (_) {\n return {}\n }\n}\n\nexport async function queryProfile(fullname: string): Promise<ProfilePointer | null> {\n const match = fullname.match(NIP05_REGEX)\n if (!match) return null\n\n const [, name = '_', domain] = match\n\n try {\n const url = `https://${domain}/.well-known/nostr.json?name=${name}`\n const res = await _fetch(url, { redirect: 'manual' })\n if (res.status !== 200) {\n throw Error('Wrong response code')\n }\n const json = await res.json()\n\n const pubkey = json.names[name]\n return pubkey ? { pubkey, relays: json.relays?.[pubkey] } : null\n } catch (_e) {\n return null\n }\n}\n\nexport async function isValid(pubkey: string, nip05: Nip05): Promise<boolean> {\n const res = await queryProfile(nip05)\n return res ? res.pubkey === pubkey : false\n}\n", "import { NostrEvent, validateEvent } from './pure.ts'\n\n/** Events are **regular**, which means they're all expected to be stored by relays. */\nexport function isRegularKind(kind: number): boolean {\n return kind < 10000 && kind !== 0 && kind !== 3\n}\n\n/** Events are **replaceable**, which means that, for each combination of `pubkey` and `kind`, only the latest event is expected to (SHOULD) be stored by relays, older versions are expected to be discarded. */\nexport function isReplaceableKind(kind: number): boolean {\n return kind === 0 || kind === 3 || (10000 <= kind && kind < 20000)\n}\n\n/** Events are **ephemeral**, which means they are not expected to be stored by relays. */\nexport function isEphemeralKind(kind: number): boolean {\n return 20000 <= kind && kind < 30000\n}\n\n/** Events are **addressable**, which means that, for each combination of `pubkey`, `kind` and the `d` tag, only the latest event is expected to be stored by relays, older versions are expected to be discarded. */\nexport function isAddressableKind(kind: number): boolean {\n return 30000 <= kind && kind < 40000\n}\n\n/** Classification of the event kind. */\nexport type KindClassification = 'regular' | 'replaceable' | 'ephemeral' | 'parameterized' | 'unknown'\n\n/** Determine the classification of this kind of event if known, or `unknown`. */\nexport function classifyKind(kind: number): KindClassification {\n if (isRegularKind(kind)) return 'regular'\n if (isReplaceableKind(kind)) return 'replaceable'\n if (isEphemeralKind(kind)) return 'ephemeral'\n if (isAddressableKind(kind)) return 'parameterized'\n return 'unknown'\n}\n\nexport function isKind<T extends number>(event: unknown, kind: T | Array<T>): event is NostrEvent & { kind: T } {\n const kindAsArray: number[] = kind instanceof Array ? kind : [kind]\n return (validateEvent(event) && kindAsArray.includes(event.kind)) || false\n}\n\nexport const Metadata = 0\nexport type Metadata = typeof Metadata\nexport const ShortTextNote = 1\nexport type ShortTextNote = typeof ShortTextNote\nexport const RecommendRelay = 2\nexport type RecommendRelay = typeof RecommendRelay\nexport const Contacts = 3\nexport type Contacts = typeof Contacts\nexport const EncryptedDirectMessage = 4\nexport type EncryptedDirectMessage = typeof EncryptedDirectMessage\nexport const EventDeletion = 5\nexport type EventDeletion = typeof EventDeletion\nexport const Repost = 6\nexport type Repost = typeof Repost\nexport const Reaction = 7\nexport type Reaction = typeof Reaction\nexport const BadgeAward = 8\nexport type BadgeAward = typeof BadgeAward\nexport const ChatMessage = 9\nexport type ChatMessage = typeof ChatMessage\nexport const ForumThread = 11\nexport type ForumThread = typeof ForumThread\nexport const Seal = 13\nexport type Seal = typeof Seal\nexport const PrivateDirectMessage = 14\nexport type PrivateDirectMessage = typeof PrivateDirectMessage\nexport const FileMessage = 15\nexport type FileMessage = typeof FileMessage\nexport const GenericRepost = 16\nexport type GenericRepost = typeof GenericRepost\nexport const Photo = 20\nexport type Photo = typeof Photo\nexport const NormalVideo = 21\nexport type NormalVideo = typeof NormalVideo\nexport const ShortVideo = 22\nexport type ShortVideo = typeof ShortVideo\nexport const ChannelCreation = 40\nexport type ChannelCreation = typeof ChannelCreation\nexport const ChannelMetadata = 41\nexport type ChannelMetadata = typeof ChannelMetadata\nexport const ChannelMessage = 42\nexport type ChannelMessage = typeof ChannelMessage\nexport const ChannelHideMessage = 43\nexport type ChannelHideMessage = typeof ChannelHideMessage\nexport const ChannelMuteUser = 44\nexport type ChannelMuteUser = typeof ChannelMuteUser\nexport const OpenTimestamps = 1040\nexport type OpenTimestamps = typeof OpenTimestamps\nexport const GiftWrap = 1059\nexport type GiftWrap = typeof GiftWrap\nexport const Poll = 1068\nexport type Poll = typeof Poll\nexport const FileMetadata = 1063\nexport type FileMetadata = typeof FileMetadata\nexport const Comment = 1111\nexport type Comment = typeof Comment\nexport const LiveChatMessage = 1311\nexport type LiveChatMessage = typeof LiveChatMessage\nexport const Voice = 1222\nexport type Voice = typeof Voice\nexport const VoiceComment = 1244\nexport type VoiceComment = typeof VoiceComment\nexport const ProblemTracker = 1971\nexport type ProblemTracker = typeof ProblemTracker\nexport const Report = 1984\nexport type Report = typeof Report\nexport const Reporting = 1984\nexport type Reporting = typeof Reporting\nexport const Label = 1985\nexport type Label = typeof Label\nexport const CommunityPostApproval = 4550\nexport type CommunityPostApproval = typeof CommunityPostApproval\nexport const JobRequest = 5999\nexport type JobRequest = typeof JobRequest\nexport const JobResult = 6999\nexport type JobResult = typeof JobResult\nexport const JobFeedback = 7000\nexport type JobFeedback = typeof JobFeedback\nexport const ZapGoal = 9041\nexport type ZapGoal = typeof ZapGoal\nexport const ZapRequest = 9734\nexport type ZapRequest = typeof ZapRequest\nexport const Zap = 9735\nexport type Zap = typeof Zap\nexport const Highlights = 9802\nexport type Highlights = typeof Highlights\nexport const PollResponse = 1018\nexport type PollResponse = typeof PollResponse\nexport const Mutelist = 10000\nexport type Mutelist = typeof Mutelist\nexport const Pinlist = 10001\nexport type Pinlist = typeof Pinlist\nexport const RelayList = 10002\nexport type RelayList = typeof RelayList\nexport const BookmarkList = 10003\nexport type BookmarkList = typeof BookmarkList\nexport const CommunitiesList = 10004\nexport type CommunitiesList = typeof CommunitiesList\nexport const PublicChatsList = 10005\nexport type PublicChatsList = typeof PublicChatsList\nexport const BlockedRelaysList = 10006\nexport type BlockedRelaysList = typeof BlockedRelaysList\nexport const SearchRelaysList = 10007\nexport type SearchRelaysList = typeof SearchRelaysList\nexport const FavoriteRelays = 10012\nexport type FavoriteRelays = typeof FavoriteRelays\nexport const InterestsList = 10015\nexport type InterestsList = typeof InterestsList\nexport const UserEmojiList = 10030\nexport type UserEmojiList = typeof UserEmojiList\nexport const DirectMessageRelaysList = 10050\nexport type DirectMessageRelaysList = typeof DirectMessageRelaysList\nexport const FileServerPreference = 10096\nexport type FileServerPreference = typeof FileServerPreference\nexport const BlossomServerList = 10063\nexport type BlossomServerList = typeof BlossomServerList\nexport const NWCWalletInfo = 13194\nexport type NWCWalletInfo = typeof NWCWalletInfo\nexport const LightningPubRPC = 21000\nexport type LightningPubRPC = typeof LightningPubRPC\nexport const ClientAuth = 22242\nexport type ClientAuth = typeof ClientAuth\nexport const NWCWalletRequest = 23194\nexport type NWCWalletRequest = typeof NWCWalletRequest\nexport const NWCWalletResponse = 23195\nexport type NWCWalletResponse = typeof NWCWalletResponse\nexport const NostrConnect = 24133\nexport type NostrConnect = typeof NostrConnect\nexport const HTTPAuth = 27235\nexport type HTTPAuth = typeof HTTPAuth\nexport const Followsets = 30000\nexport type Followsets = typeof Followsets\nexport const Genericlists = 30001\nexport type Genericlists = typeof Genericlists\nexport const Relaysets = 30002\nexport type Relaysets = typeof Relaysets\nexport const Bookmarksets = 30003\nexport type Bookmarksets = typeof Bookmarksets\nexport const Curationsets = 30004\nexport type Curationsets = typeof Curationsets\nexport const ProfileBadges = 30008\nexport type ProfileBadges = typeof ProfileBadges\nexport const BadgeDefinition = 30009\nexport type BadgeDefinition = typeof BadgeDefinition\nexport const Interestsets = 30015\nexport type Interestsets = typeof Interestsets\nexport const CreateOrUpdateStall = 30017\nexport type CreateOrUpdateStall = typeof CreateOrUpdateStall\nexport const CreateOrUpdateProduct = 30018\nexport type CreateOrUpdateProduct = typeof CreateOrUpdateProduct\nexport const LongFormArticle = 30023\nexport type LongFormArticle = typeof LongFormArticle\nexport const DraftLong = 30024\nexport type DraftLong = typeof DraftLong\nexport const Emojisets = 30030\nexport type Emojisets = typeof Emojisets\nexport const Application = 30078\nexport type Application = typeof Application\nexport const LiveEvent = 30311\nexport type LiveEvent = typeof LiveEvent\nexport const UserStatuses = 30315\nexport type UserStatuses = typeof UserStatuses\nexport const ClassifiedListing = 30402\nexport type ClassifiedListing = typeof ClassifiedListing\nexport const DraftClassifiedListing = 30403\nexport type DraftClassifiedListing = typeof DraftClassifiedListing\nexport const Date = 31922\nexport type Date = typeof Date\nexport const Time = 31923\nexport type Time = typeof Time\nexport const Calendar = 31924\nexport type Calendar = typeof Calendar\nexport const CalendarEventRSVP = 31925\nexport type CalendarEventRSVP = typeof CalendarEventRSVP\nexport const RelayReview = 31987\nexport type RelayReview = typeof RelayReview\nexport const Handlerrecommendation = 31989\nexport type Handlerrecommendation = typeof Handlerrecommendation\nexport const Handlerinformation = 31990\nexport type Handlerinformation = typeof Handlerinformation\nexport const CommunityDefinition = 34550\nexport type CommunityDefinition = typeof CommunityDefinition\nexport const GroupMetadata = 39000\nexport type GroupMetadata = typeof GroupMetadata\n", "import { Event } from './core.ts'\nimport { isAddressableKind, isReplaceableKind } from './kinds.ts'\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 [key: `#${string}`]: string[] | undefined\n}\n\nexport function matchFilter(filter: Filter, event: Event): boolean {\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\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\n if (filter.since && event.created_at < filter.since) return false\n if (filter.until && event.created_at > filter.until) return false\n\n return true\n}\n\nexport function matchFilters(filters: Filter[], event: Event): boolean {\n for (let i = 0; i < filters.length; i++) {\n if (matchFilter(filters[i], event)) {\n return true\n }\n }\n return false\n}\n\nexport function mergeFilters(...filters: Filter[]): Filter {\n let result: Filter = {}\n for (let i = 0; i < filters.length; i++) {\n let filter = filters[i]\n Object.entries(filter).forEach(([property, values]) => {\n if (property === 'kinds' || property === 'ids' || property === 'authors' || property[0] === '#') {\n // @ts-ignore\n result[property] = result[property] || []\n // @ts-ignore\n for (let v = 0; v < values.length; v++) {\n // @ts-ignore\n let value = values[v]\n // @ts-ignore\n if (!result[property].includes(value)) result[property].push(value)\n }\n }\n })\n\n if (filter.limit && (!result.limit || filter.limit > result.limit)) result.limit = filter.limit\n if (filter.until && (!result.until || filter.until > result.until)) result.until = filter.until\n if (filter.since && (!result.since || filter.since < result.since)) result.since = filter.since\n }\n\n return result\n}\n\n/**\n * Calculate the intrinsic limit of a filter.\n * This function returns a positive integer, or `Infinity` if there is no intrinsic limit.\n */\nexport function getFilterLimit(filter: Filter): number {\n if (filter.ids && !filter.ids.length) return 0\n if (filter.kinds && !filter.kinds.length) return 0\n if (filter.authors && !filter.authors.length) return 0\n\n for (const [key, value] of Object.entries(filter)) {\n if (key[0] === '#' && Array.isArray(value) && !value.length) return 0\n }\n\n return Math.min(\n // The `limit` property creates an artificial limit.\n Math.max(0, filter.limit ?? Infinity),\n\n // There can only be one event per `id`.\n filter.ids?.length ?? Infinity,\n\n // Replaceable events are limited by the number of authors and kinds.\n filter.authors?.length && filter.kinds?.every(kind => isReplaceableKind(kind))\n ? filter.authors.length * filter.kinds.length\n : Infinity,\n\n // Parameterized replaceable events are limited by the number of authors, kinds, and \"d\" tags.\n filter.authors?.length && filter.kinds?.every(kind => isAddressableKind(kind)) && filter['#d']?.length\n ? filter.authors.length * filter.kinds.length * filter['#d'].length\n : Infinity,\n )\n}\n", "export function getHex64(json: string, field: string): string {\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}\n\nexport function getInt(json: string, field: string): number {\n let len = field.length\n let idx = json.indexOf(`\"${field}\":`) + len + 3\n let sliced = json.slice(idx)\n let end = Math.min(sliced.indexOf(','), sliced.indexOf('}'))\n return parseInt(sliced.slice(0, end), 10)\n}\n\nexport function getSubscriptionId(json: string): string | null {\n let idx = json.slice(0, 22).indexOf(`\"EVENT\"`)\n if (idx === -1) return null\n\n let pstart = json.slice(idx + 7 + 1).indexOf(`\"`)\n if (pstart === -1) return null\n let start = idx + 7 + 1 + pstart\n\n let pend = json.slice(start + 1, 80).indexOf(`\"`)\n if (pend === -1) return null\n let end = start + 1 + pend\n\n return json.slice(start + 1, end)\n}\n\nexport function matchEventId(json: string, id: string): boolean {\n return id === getHex64(json, 'id')\n}\n\nexport function matchEventPubkey(json: string, pubkey: string): boolean {\n return pubkey === getHex64(json, 'pubkey')\n}\n\nexport function matchEventKind(json: string, kind: number): boolean {\n return kind === getInt(json, 'kind')\n}\n", "import { EventTemplate } from './core.ts'\nimport { ClientAuth } from './kinds.ts'\n\n/**\n * creates an EventTemplate for an AUTH event to be signed.\n */\nexport function makeAuthEvent(relayURL: string, challenge: string): EventTemplate {\n return {\n kind: ClientAuth,\n created_at: Math.floor(Date.now() / 1000),\n tags: [\n ['relay', relayURL],\n ['challenge', challenge],\n ],\n content: '',\n }\n}\n", "/* global WebSocket */\n\nimport type { Event, EventTemplate, VerifiedEvent, Nostr, NostrEvent } from './core.ts'\nimport { matchFilters, type Filter } from './filter.ts'\nimport { getHex64, getSubscriptionId } from './fakejson.ts'\nimport { normalizeURL } from './utils.ts'\nimport { makeAuthEvent } from './nip42.ts'\n\ntype RelayWebSocket = WebSocket & {\n ping?(): void\n on?(event: 'pong', listener: () => void): any\n}\n\nexport type AbstractRelayConstructorOptions = {\n verifyEvent: Nostr['verifyEvent']\n websocketImplementation?: typeof WebSocket\n enablePing?: boolean\n enableReconnect?: boolean\n}\n\nexport class SendingOnClosedConnection extends Error {\n constructor(message: string, relay: string) {\n super(`Tried to send message '${message} on a closed connection to ${relay}.`)\n this.name = 'SendingOnClosedConnection'\n }\n}\n\nexport class AbstractRelay {\n public readonly url: string\n private _connected: boolean = false\n\n public onclose: (() => void) | null = null\n public onnotice: (msg: string) => void = msg => console.debug(`NOTICE from ${this.url}: ${msg}`)\n public onauth: undefined | ((evt: EventTemplate) => Promise<VerifiedEvent>)\n\n public baseEoseTimeout: number = 4400\n public publishTimeout: number = 4400\n public pingFrequency: number = 29000\n public pingTimeout: number = 20000\n public resubscribeBackoff: number[] = [10000, 10000, 10000, 20000, 20000, 30000, 60000]\n public openSubs: Map<string, Subscription> = new Map()\n public enablePing: boolean | undefined\n public enableReconnect: boolean\n public idleSince: number | undefined = Date.now() // when undefined that means it isn't idle\n public ongoingOperations: number = 0 // used to compute idleness\n private reconnectTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n private pingIntervalHandle: ReturnType<typeof setInterval> | undefined\n private reconnectAttempts: number = 0\n private skipReconnection: boolean = false\n\n private connectionPromise: Promise<void> | undefined\n private openCountRequests = new Map<string, CountResolver>()\n private openEventPublishes = new Map<string, EventPublishResolver>()\n private ws: RelayWebSocket | undefined\n private challenge: string | undefined\n private authPromise: Promise<string> | undefined\n private serial: number = 0\n private verifyEvent: Nostr['verifyEvent']\n\n private _WebSocket: typeof WebSocket\n\n constructor(url: string, opts: AbstractRelayConstructorOptions) {\n this.url = normalizeURL(url)\n this.verifyEvent = opts.verifyEvent\n this._WebSocket = opts.websocketImplementation || WebSocket\n this.enablePing = opts.enablePing\n this.enableReconnect = opts.enableReconnect || false\n }\n\n static async connect(\n url: string,\n opts: AbstractRelayConstructorOptions & Parameters<AbstractRelay['connect']>[0],\n ): Promise<AbstractRelay> {\n const relay = new AbstractRelay(url, opts)\n await relay.connect(opts)\n return relay\n }\n\n private closeAllSubscriptions(reason: string) {\n for (let [_, sub] of this.openSubs) {\n sub.close(reason)\n }\n this.openSubs.clear()\n\n for (let [_, ep] of this.openEventPublishes) {\n ep.reject(new Error(reason))\n }\n this.openEventPublishes.clear()\n\n for (let [_, cr] of this.openCountRequests) {\n cr.reject(new Error(reason))\n }\n this.openCountRequests.clear()\n }\n\n public get connected(): boolean {\n return this._connected\n }\n\n private async reconnect(): Promise<void> {\n const backoff = this.resubscribeBackoff[Math.min(this.reconnectAttempts, this.resubscribeBackoff.length - 1)]\n this.reconnectAttempts++\n\n this.reconnectTimeoutHandle = setTimeout(async () => {\n try {\n await this.connect()\n } catch (err) {\n // this will be called again through onclose/onerror\n }\n }, backoff)\n }\n\n private handleHardClose(reason: string) {\n if (this.pingIntervalHandle) {\n clearInterval(this.pingIntervalHandle)\n this.pingIntervalHandle = undefined\n }\n\n this._connected = false\n this.connectionPromise = undefined\n this.idleSince = undefined\n\n if (this.enableReconnect && !this.skipReconnection) {\n this.reconnect()\n } else {\n this.onclose?.()\n this.closeAllSubscriptions(reason)\n }\n }\n\n public async connect(opts?: { timeout?: number; abort?: AbortSignal }): Promise<void> {\n let connectionTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n if (this.connectionPromise) return this.connectionPromise\n\n this.challenge = undefined\n this.authPromise = undefined\n this.skipReconnection = false\n this.connectionPromise = new Promise((resolve, reject) => {\n if (opts?.timeout) {\n connectionTimeoutHandle = setTimeout(() => {\n reject('connection timed out')\n this.connectionPromise = undefined\n this.skipReconnection = true\n this.onclose?.()\n this.handleHardClose('relay connection timed out')\n }, opts.timeout)\n }\n\n if (opts?.abort) {\n opts.abort.onabort = reject\n }\n\n try {\n this.ws = new this._WebSocket(this.url)\n } catch (err) {\n clearTimeout(connectionTimeoutHandle)\n reject(err)\n return\n }\n\n this.ws.onopen = () => {\n if (this.reconnectTimeoutHandle) {\n clearTimeout(this.reconnectTimeoutHandle)\n this.reconnectTimeoutHandle = undefined\n }\n clearTimeout(connectionTimeoutHandle)\n this._connected = true\n\n const isReconnection = this.reconnectAttempts > 0\n this.reconnectAttempts = 0\n\n // resubscribe to all open subscriptions\n for (const sub of this.openSubs.values()) {\n sub.eosed = false\n if (isReconnection) {\n for (let f = 0; f < sub.filters.length; f++) {\n if (sub.lastEmitted) {\n sub.filters[f].since = sub.lastEmitted + 1\n }\n }\n }\n sub.fire()\n }\n\n if (this.enablePing) {\n this.pingIntervalHandle = setInterval(() => this.pingpong(), this.pingFrequency)\n }\n resolve()\n }\n\n this.ws.onerror = () => {\n clearTimeout(connectionTimeoutHandle)\n reject('connection failed')\n this.connectionPromise = undefined\n this.skipReconnection = true\n this.onclose?.()\n this.handleHardClose('relay connection failed')\n }\n\n this.ws.onclose = ev => {\n clearTimeout(connectionTimeoutHandle)\n reject((ev as any).message || 'websocket closed')\n this.handleHardClose('relay connection closed')\n }\n\n this.ws.onmessage = this._onmessage.bind(this)\n })\n\n return this.connectionPromise\n }\n\n private waitForPingPong() {\n return new Promise(resolve => {\n // listen for pong\n ;(this.ws as any).once('pong', () => resolve(true))\n // send a ping\n this.ws!.ping!()\n })\n }\n\n private waitForDummyReq() {\n return new Promise((resolve, reject) => {\n if (!this.connectionPromise) return reject(new Error(`no connection to ${this.url}, can't ping`))\n\n // make a dummy request with expected empty eose reply\n // [\"REQ\", \"_\", {\"ids\":[\"aaaa...aaaa\"], \"limit\": 0}]\n try {\n const sub = this.subscribe(\n [{ ids: ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'], limit: 0 }],\n {\n label: '<forced-ping>',\n oneose: () => {\n resolve(true)\n sub.close()\n },\n onclose() {\n // if we get a CLOSED it's because the relay is alive\n resolve(true)\n },\n eoseTimeout: this.pingTimeout + 1000,\n },\n )\n } catch (err) {\n reject(err)\n }\n })\n }\n\n // nodejs requires this magic here to ensure connections are closed when internet goes off and stuff\n // in browsers it's done automatically. see https://github.com/nbd-wtf/nostr-tools/issues/491\n private async pingpong() {\n // if the websocket is connected\n if (this.ws?.readyState === 1) {\n // wait for either a ping-pong reply or a timeout\n const result = await Promise.any([\n // browsers don't have ping so use a dummy req\n this.ws && this.ws.ping && (this.ws as any).once ? this.waitForPingPong() : this.waitForDummyReq(),\n new Promise(res => setTimeout(() => res(false), this.pingTimeout)),\n ])\n\n if (!result) {\n // pingpong closing socket\n if (this.ws?.readyState === this._WebSocket.OPEN) {\n this.ws?.close()\n }\n }\n }\n }\n\n public async send(message: string) {\n if (!this.connectionPromise) throw new SendingOnClosedConnection(message, this.url)\n\n this.connectionPromise.then(() => {\n this.ws?.send(message)\n })\n }\n\n public async auth(signAuthEvent: (evt: EventTemplate) => Promise<VerifiedEvent>): Promise<string> {\n const challenge = this.challenge\n if (!challenge) throw new Error(\"can't perform auth, no challenge was received\")\n if (this.authPromise) return this.authPromise\n\n this.authPromise = new Promise<string>(async (resolve, reject) => {\n try {\n let evt = await signAuthEvent(makeAuthEvent(this.url, challenge))\n let timeout = setTimeout(() => {\n let ep = this.openEventPublishes.get(evt.id) as EventPublishResolver\n if (ep) {\n ep.reject(new Error('auth timed out'))\n this.openEventPublishes.delete(evt.id)\n }\n }, this.publishTimeout)\n this.openEventPublishes.set(evt.id, { resolve, reject, timeout })\n this.send('[\"AUTH\",' + JSON.stringify(evt) + ']')\n } catch (err) {\n console.warn('subscribe auth function failed:', err)\n }\n })\n return this.authPromise\n }\n\n public async publish(event: Event): Promise<string> {\n this.idleSince = undefined\n this.ongoingOperations++\n\n const ret = new Promise<string>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const ep = this.openEventPublishes.get(event.id) as EventPublishResolver\n if (ep) {\n ep.reject(new Error('publish timed out'))\n this.openEventPublishes.delete(event.id)\n }\n }, this.publishTimeout)\n this.openEventPublishes.set(event.id, { resolve, reject, timeout })\n })\n this.send('[\"EVENT\",' + JSON.stringify(event) + ']')\n\n // compute idleness state\n this.ongoingOperations--\n if (this.ongoingOperations === 0) this.idleSince = Date.now()\n\n return ret\n }\n\n public async count(filters: Filter[], params: { id?: string | null }): Promise<number> {\n this.serial++\n const id = params?.id || 'count:' + this.serial\n const ret = new Promise<number>((resolve, reject) => {\n this.openCountRequests.set(id, { resolve, reject })\n })\n this.send('[\"COUNT\",\"' + id + '\",' + JSON.stringify(filters).substring(1))\n return ret\n }\n\n public subscribe(\n filters: Filter[],\n params: Partial<SubscriptionParams> & { label?: string; id?: string },\n ): Subscription {\n if (params.label !== '<forced-ping>') {\n this.idleSince = undefined\n this.ongoingOperations++\n }\n\n const sub = this.prepareSubscription(filters, params)\n sub.fire()\n\n if (params.abort) {\n params.abort.onabort = () => sub.close(String(params.abort!.reason || '<aborted>'))\n }\n\n return sub\n }\n\n public prepareSubscription(\n filters: Filter[],\n params: Partial<SubscriptionParams> & { label?: string; id?: string },\n ): Subscription {\n this.serial++\n const id = params.id || (params.label ? params.label + ':' : 'sub:') + this.serial\n const sub = new Subscription(this, id, filters, params)\n this.openSubs.set(id, sub)\n return sub\n }\n\n public close() {\n this.skipReconnection = true\n if (this.reconnectTimeoutHandle) {\n clearTimeout(this.reconnectTimeoutHandle)\n this.reconnectTimeoutHandle = undefined\n }\n if (this.pingIntervalHandle) {\n clearInterval(this.pingIntervalHandle)\n this.pingIntervalHandle = undefined\n }\n this.closeAllSubscriptions('relay connection closed by us')\n this._connected = false\n this.idleSince = undefined\n this.onclose?.()\n if (this.ws?.readyState === this._WebSocket.OPEN) {\n this.ws?.close()\n }\n }\n\n // this is the function assigned to this.ws.onmessage\n // it's exposed for testing and debugging purposes\n public _onmessage(ev: MessageEvent<any>): void {\n const json = ev.data\n if (!json) {\n return\n }\n\n // shortcut EVENT sub\n const subid = getSubscriptionId(json)\n if (subid) {\n const so = this.openSubs.get(subid as string)\n if (!so) {\n // this is an EVENT message, but for a subscription we don't have, so just stop here\n return\n }\n\n // this will be called only when this message is a EVENT message for a subscription we have\n // we do this before parsing the JSON to not have to do that for duplicate events\n // since JSON parsing is slow\n const id = getHex64(json, 'id')\n const alreadyHave = so.alreadyHaveEvent?.(id)\n\n // notify any interested client that the relay has this event\n // (do this after alreadyHaveEvent() because the client may rely on this to answer that)\n so.receivedEvent?.(this, id)\n\n if (alreadyHave) {\n // if we had already seen this event we can just stop here\n return\n }\n }\n\n try {\n let data = JSON.parse(json)\n // we won't do any checks against the data since all failures (i.e. invalid messages from relays)\n // will naturally be caught by the encompassing try..catch block\n\n switch (data[0]) {\n case 'EVENT': {\n const so = this.openSubs.get(data[1] as string) as Subscription\n const event = data[2] as NostrEvent\n if (this.verifyEvent(event) && matchFilters(so.filters, event)) {\n so.onevent(event)\n } else {\n so.oninvalidevent?.(event)\n }\n if (!so.lastEmitted || so.lastEmitted < event.created_at) so.lastEmitted = event.created_at\n return\n }\n case 'COUNT': {\n const id: string = data[1]\n const payload = data[2] as { count: number }\n const cr = this.openCountRequests.get(id) as CountResolver\n if (cr) {\n cr.resolve(payload.count)\n this.openCountRequests.delete(id)\n }\n return\n }\n case 'EOSE': {\n const so = this.openSubs.get(data[1] as string)\n if (!so) return\n so.receivedEose()\n return\n }\n case 'OK': {\n const id: string = data[1]\n const ok: boolean = data[2]\n const reason: string = data[3]\n const ep = this.openEventPublishes.get(id) as EventPublishResolver\n if (ep) {\n clearTimeout(ep.timeout)\n if (ok) ep.resolve(reason)\n else ep.reject(new Error(reason))\n this.openEventPublishes.delete(id)\n }\n return\n }\n case 'CLOSED': {\n const id: string = data[1]\n const so = this.openSubs.get(id)\n if (!so) return\n so.closed = true\n so.close(data[2] as string)\n return\n }\n case 'NOTICE': {\n this.onnotice(data[1] as string)\n return\n }\n case 'AUTH': {\n this.challenge = data[1] as string\n if (this.onauth) {\n this.auth(this.onauth)\n }\n return\n }\n default: {\n const so = this.openSubs.get(data[1])\n so?.oncustom?.(data)\n return\n }\n }\n } catch (err) {\n try {\n const [_, __, event] = JSON.parse(json)\n console.warn(`[nostr] relay ${this.url} error processing message:`, err, event)\n } catch (_) {\n console.warn(`[nostr] relay ${this.url} error processing message:`, err)\n }\n return\n }\n }\n}\n\nexport class Subscription {\n public readonly relay: AbstractRelay\n public readonly id: string\n\n public lastEmitted: number | undefined\n public closed: boolean = false\n public eosed: boolean = false\n public filters: Filter[]\n public alreadyHaveEvent: ((id: string) => boolean) | undefined\n public receivedEvent: ((relay: AbstractRelay, id: string) => void) | undefined\n\n public onevent: (evt: Event) => void\n public oninvalidevent: ((evt: unknown) => void) | undefined\n public oneose: (() => void) | undefined\n public onclose: ((reason: string) => void) | undefined\n\n // will get any messages that have this subscription id as their second item and are not default standard\n public oncustom: ((msg: string[]) => void) | undefined\n\n public eoseTimeout: number\n private eoseTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n constructor(relay: AbstractRelay, id: string, filters: Filter[], params: SubscriptionParams) {\n if (filters.length === 0) throw new Error(\"subscription can't be created with zero filters\")\n\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\n this.oneose = params.oneose\n this.onclose = params.onclose\n this.oninvalidevent = params.oninvalidevent\n this.onevent =\n params.onevent ||\n (event => {\n console.warn(\n `onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`,\n event,\n )\n })\n }\n\n public fire() {\n this.relay.send('[\"REQ\",\"' + this.id + '\",' + JSON.stringify(this.filters).substring(1))\n\n // only now we start counting the eoseTimeout\n this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout)\n }\n\n public receivedEose() {\n if (this.eosed) return\n clearTimeout(this.eoseTimeoutHandle)\n this.eosed = true\n this.oneose?.()\n }\n\n public close(reason: string = 'closed by caller') {\n if (!this.closed && this.relay.connected) {\n // if the connection was closed by the user calling .close() we will send a CLOSE message\n // otherwise this._open will be already set to false so we will skip this\n try {\n this.relay.send('[\"CLOSE\",' + JSON.stringify(this.id) + ']')\n } catch (err) {\n if (err instanceof SendingOnClosedConnection) {\n /* doesn't matter, it's ok */\n } else {\n throw err\n }\n }\n this.closed = true\n }\n this.relay.openSubs.delete(this.id)\n\n // compute idleness state\n this.relay.ongoingOperations--\n if (this.relay.ongoingOperations === 0) this.relay.idleSince = Date.now()\n\n this.onclose?.(reason)\n }\n}\n\nexport type SubscriptionParams = {\n onevent?: (evt: Event) => void\n oninvalidevent?: (evt: unknown) => void\n oneose?: () => void\n onclose?: (reason: string) => void\n alreadyHaveEvent?: (id: string) => boolean\n receivedEvent?: (relay: AbstractRelay, id: string) => void\n eoseTimeout?: number\n abort?: AbortSignal\n}\n\nexport type CountResolver = {\n resolve: (count: number) => void\n reject: (err: Error) => void\n}\n\nexport type EventPublishResolver = {\n resolve: (reason: string) => void\n reject: (err: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n", "import { verifiedSymbol, type Event, type Nostr, VerifiedEvent } from './core.ts'\n\nexport const alwaysTrue: Nostr['verifyEvent'] = (t: Event): t is VerifiedEvent => {\n t[verifiedSymbol] = true\n return true\n}\n", "/* global WebSocket */\n\nimport {\n AbstractRelay as AbstractRelay,\n SubscriptionParams,\n Subscription,\n type AbstractRelayConstructorOptions,\n} from './abstract-relay.ts'\nimport { normalizeURL } from './utils.ts'\n\nimport type { Event, EventTemplate, Nostr, VerifiedEvent } from './core.ts'\nimport { type Filter } from './filter.ts'\nimport { alwaysTrue } from './helpers.ts'\nimport { Relay } from './relay.ts'\n\nexport type SubCloser = { close: (reason?: string) => void }\n\nexport type AbstractPoolConstructorOptions = AbstractRelayConstructorOptions & {\n // automaticallyAuth takes a relay URL and should return null in case that relay shouldn't be authenticated against\n // or a function to sign the AUTH event template otherwise (that function may still throw in case of failure)\n automaticallyAuth?: (relayURL: string) => null | ((event: EventTemplate) => Promise<VerifiedEvent>)\n // onRelayConnectionFailure is called with the URL of a relay that failed the initial connection\n onRelayConnectionFailure?: (url: string) => void\n // onRelayConnectionSuccess is called with the URL of a relay that succeeds the initial connection\n onRelayConnectionSuccess?: (url: string) => void\n // allowConnectingToRelay takes a relay URL and the operation being performed\n // return false to skip connecting to that relay\n allowConnectingToRelay?: (url: string, operation: ['read', Filter[]] | ['write', Event]) => boolean\n // maxWaitForConnection takes a number in milliseconds that will be given to ensureRelay such that we\n // don't get stuck forever when attempting to connect to a relay, it is 3000 (3 seconds) by default\n maxWaitForConnection: number\n}\n\nexport type SubscribeManyParams = Omit<SubscriptionParams, 'onclose'> & {\n maxWait?: number\n abort?: AbortSignal\n onclose?: (reasons: string[]) => void\n onauth?: (event: EventTemplate) => Promise<VerifiedEvent>\n id?: string\n label?: string\n}\n\nexport class AbstractSimplePool {\n protected relays: Map<string, AbstractRelay> = new Map()\n public seenOn: Map<string, Set<AbstractRelay>> = new Map()\n public trackRelays: boolean = false\n\n public verifyEvent: Nostr['verifyEvent']\n public enablePing: boolean | undefined\n public enableReconnect: boolean\n public automaticallyAuth?: (relayURL: string) => null | ((event: EventTemplate) => Promise<VerifiedEvent>)\n public trustedRelayURLs: Set<string> = new Set()\n public onRelayConnectionFailure?: (url: string) => void\n public onRelayConnectionSuccess?: (url: string) => void\n public allowConnectingToRelay?: (url: string, operation: ['read', Filter[]] | ['write', Event]) => boolean\n public maxWaitForConnection: number\n\n private _WebSocket?: typeof WebSocket\n\n constructor(opts: AbstractPoolConstructorOptions) {\n this.verifyEvent = opts.verifyEvent\n this._WebSocket = opts.websocketImplementation\n this.enablePing = opts.enablePing\n this.enableReconnect = opts.enableReconnect || false\n this.automaticallyAuth = opts.automaticallyAuth\n this.onRelayConnectionFailure = opts.onRelayConnectionFailure\n this.onRelayConnectionSuccess = opts.onRelayConnectionSuccess\n this.allowConnectingToRelay = opts.allowConnectingToRelay\n this.maxWaitForConnection = opts.maxWaitForConnection || 3000\n }\n\n async ensureRelay(\n url: string,\n params?: {\n connectionTimeout?: number\n abort?: AbortSignal\n },\n ): Promise<AbstractRelay> {\n url = normalizeURL(url)\n\n let relay = this.relays.get(url)\n if (!relay) {\n relay = new AbstractRelay(url, {\n verifyEvent: this.trustedRelayURLs.has(url) ? alwaysTrue : this.verifyEvent,\n websocketImplementation: this._WebSocket,\n enablePing: this.enablePing,\n enableReconnect: this.enableReconnect,\n })\n relay.onclose = () => {\n this.relays.delete(url)\n }\n this.relays.set(url, relay)\n }\n\n if (this.automaticallyAuth) {\n const authSignerFn = this.automaticallyAuth(url)\n if (authSignerFn) {\n relay.onauth = authSignerFn\n }\n }\n\n try {\n await relay.connect({\n timeout: params?.connectionTimeout,\n abort: params?.abort,\n })\n } catch (err) {\n this.relays.delete(url)\n throw err\n }\n\n return relay\n }\n\n close(relays: string[]) {\n relays.map(normalizeURL).forEach(url => {\n this.relays.get(url)?.close()\n this.relays.delete(url)\n })\n }\n\n subscribe(relays: string[], filter: Filter, params: SubscribeManyParams): SubCloser {\n const request: { url: string; filter: Filter }[] = []\n const uniqUrls: string[] = []\n for (let i = 0; i < relays.length; i++) {\n const url = normalizeURL(relays[i])\n if (!request.find(r => r.url === url)) {\n if (uniqUrls.indexOf(url) === -1) {\n uniqUrls.push(url)\n request.push({ url, filter: filter })\n }\n }\n }\n\n return this.subscribeMap(request, params)\n }\n\n subscribeMany(relays: string[], filter: Filter, params: SubscribeManyParams): SubCloser {\n return this.subscribe(relays, filter, params)\n }\n\n subscribeMap(requests: { url: string; filter: Filter }[], params: SubscribeManyParams): SubCloser {\n const grouped = new Map<string, Filter[]>()\n for (const req of requests) {\n const { url, filter } = req\n if (!grouped.has(url)) grouped.set(url, [])\n grouped.get(url)!.push(filter)\n }\n const groupedRequests = Array.from(grouped.entries()).map(([url, filters]) => ({ url, filters }))\n\n if (this.trackRelays) {\n params.receivedEvent = (relay: AbstractRelay, id: string) => {\n let set = this.seenOn.get(id)\n if (!set) {\n set = new Set()\n this.seenOn.set(id, set)\n }\n set.add(relay)\n }\n }\n\n const _knownIds = new Set<string>()\n const subs: Subscription[] = []\n\n // batch all EOSEs into a single\n const eosesReceived: boolean[] = []\n let handleEose = (i: number) => {\n if (eosesReceived[i]) return // do not act twice for the same relay\n eosesReceived[i] = true\n if (eosesReceived.filter(a => a).length === groupedRequests.length) {\n params.oneose?.()\n handleEose = () => {}\n }\n }\n // batch all closes into a single\n const closesReceived: string[] = []\n let handleClose = (i: number, reason: string) => {\n if (closesReceived[i]) return // do not act twice for the same relay\n handleEose(i)\n closesReceived[i] = reason\n if (closesReceived.filter(a => a).length === groupedRequests.length) {\n params.onclose?.(closesReceived)\n handleClose = () => {}\n }\n }\n\n const localAlreadyHaveEventHandler = (id: string) => {\n if (params.alreadyHaveEvent?.(id)) {\n return true\n }\n const have = _knownIds.has(id)\n _knownIds.add(id)\n return have\n }\n\n // open a subscription in all given relays\n const allOpened = Promise.all(\n groupedRequests.map(async ({ url, filters }, i) => {\n if (this.allowConnectingToRelay?.(url, ['read', filters]) === false) {\n handleClose(i, 'connection skipped by allowConnectingToRelay')\n return\n }\n\n let relay: AbstractRelay\n try {\n relay = await this.ensureRelay(url, {\n connectionTimeout:\n this.maxWaitForConnection < (params.maxWait || 0)\n ? Math.max(params.maxWait! * 0.8, params.maxWait! - 1000)\n : this.maxWaitForConnection,\n abort: params.abort,\n })\n } catch (err) {\n this.onRelayConnectionFailure?.(url)\n handleClose(i, (err as any)?.message || String(err))\n return\n }\n\n this.onRelayConnectionSuccess?.(url)\n\n let subscription = relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i),\n onclose: reason => {\n if (reason.startsWith('auth-required: ') && params.onauth) {\n relay\n .auth(params.onauth)\n .then(() => {\n relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i),\n onclose: reason => {\n handleClose(i, reason) // the second time we won't try to auth anymore\n },\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait,\n abort: params.abort,\n })\n })\n .catch(err => {\n handleClose(i, `auth was required and attempted, but failed with: ${err}`)\n })\n } else {\n handleClose(i, reason)\n }\n },\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait,\n abort: params.abort,\n })\n\n subs.push(subscription)\n }),\n )\n\n return {\n async close(reason?: string) {\n await allOpened\n subs.forEach(sub => {\n sub.close(reason)\n })\n },\n }\n }\n\n subscribeEose(\n relays: string[],\n filter: Filter,\n params: Pick<SubscribeManyParams, 'label' | 'id' | 'onevent' | 'oninvalidevent' | 'onclose' | 'maxWait' | 'onauth'>,\n ): SubCloser {\n let subcloser: SubCloser\n subcloser = this.subscribe(relays, filter, {\n ...params,\n oneose() {\n const reason = 'closed automatically on eose'\n if (subcloser) subcloser.close(reason)\n else params.onclose?.(relays.map(_ => reason))\n },\n })\n return subcloser\n }\n\n subscribeManyEose(\n relays: string[],\n filter: Filter,\n params: Pick<SubscribeManyParams, 'label' | 'id' | 'onevent' | 'oninvalidevent' | 'onclose' | 'maxWait' | 'onauth'>,\n ): SubCloser {\n return this.subscribeEose(relays, filter, params)\n }\n\n async querySync(\n relays: string[],\n filter: Filter,\n params?: Pick<SubscribeManyParams, 'label' | 'id' | 'maxWait'>,\n ): Promise<Event[]> {\n return new Promise(async resolve => {\n const events: Event[] = []\n this.subscribeEose(relays, filter, {\n ...params,\n onevent(event: Event) {\n events.push(event)\n },\n onclose(_: string[]) {\n resolve(events)\n },\n })\n })\n }\n\n async get(\n relays: string[],\n filter: Filter,\n params?: Pick<SubscribeManyParams, 'label' | 'id' | 'maxWait'>,\n ): Promise<Event | null> {\n filter.limit = 1\n const events = await this.querySync(relays, filter, params)\n events.sort((a, b) => b.created_at - a.created_at)\n return events[0] || null\n }\n\n publish(\n relays: string[],\n event: Event,\n params?: {\n onauth?: (evt: EventTemplate) => Promise<VerifiedEvent>\n maxWait?: number\n abort?: AbortSignal\n },\n ): Promise<string>[] {\n return relays.map(normalizeURL).map(async (url, i, arr) => {\n if (arr.indexOf(url) !== i) {\n // duplicate\n return Promise.reject('duplicate url')\n }\n\n if (this.allowConnectingToRelay?.(url, ['write', event]) === false) {\n return Promise.reject('connection skipped by allowConnectingToRelay')\n }\n\n let r: Relay\n try {\n r = await this.ensureRelay(url, {\n connectionTimeout:\n this.maxWaitForConnection < (params?.maxWait || 0)\n ? Math.max(params!.maxWait! * 0.8, params!.maxWait! - 1000)\n : this.maxWaitForConnection,\n abort: params?.abort,\n })\n } catch (err) {\n this.onRelayConnectionFailure?.(url)\n return String('connection failure: ' + String(err))\n }\n\n return r\n .publish(event)\n .catch(async err => {\n if (err instanceof Error && err.message.startsWith('auth-required: ') && params?.onauth) {\n await r.auth(params.onauth)\n return r.publish(event) // retry\n }\n throw err\n })\n .then(reason => {\n if (this.trackRelays) {\n let set = this.seenOn.get(event.id)\n if (!set) {\n set = new Set()\n this.seenOn.set(event.id, set)\n }\n set.add(r)\n }\n return reason\n })\n })\n }\n\n listConnectionStatus(): Map<string, boolean> {\n const map = new Map<string, boolean>()\n this.relays.forEach((relay, url) => map.set(url, relay.connected))\n\n return map\n }\n\n destroy(): void {\n this.relays.forEach(conn => conn.close())\n this.relays = new Map()\n }\n\n pruneIdleRelays(idleThresholdMs: number = 10000): string[] {\n const prunedUrls: string[] = []\n\n // check each relay's idle status and prune if over threshold\n for (const [url, relay] of this.relays) {\n if (relay.idleSince && Date.now() - relay.idleSince >= idleThresholdMs) {\n this.relays.delete(url)\n prunedUrls.push(url)\n relay.close()\n }\n }\n\n return prunedUrls\n }\n}\n", "/* global WebSocket */\n\nimport { verifyEvent } from './pure.ts'\nimport { AbstractSimplePool, type AbstractPoolConstructorOptions } from './abstract-pool.ts'\n\nvar _WebSocket: typeof WebSocket\n\ntry {\n _WebSocket = WebSocket\n} catch {}\n\nexport function useWebSocketImplementation(websocketImplementation: any) {\n _WebSocket = websocketImplementation\n}\n\nexport class SimplePool extends AbstractSimplePool {\n constructor(options?: Pick<AbstractPoolConstructorOptions, 'enablePing' | 'enableReconnect'>) {\n super({ verifyEvent, websocketImplementation: _WebSocket, maxWaitForConnection: 3000, ...options })\n }\n}\n\nexport * from './abstract-pool.ts'\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { EventTemplate, NostrEvent, VerifiedEvent } from './core.ts'\nimport { generateSecretKey, finalizeEvent, getPublicKey, verifyEvent } from './pure.ts'\nimport { AbstractSimplePool, SubCloser } from './abstract-pool.ts'\nimport { getConversationKey, decrypt, encrypt } from './nip44.ts'\nimport { NIP05_REGEX } from './nip05.ts'\nimport { SimplePool } from './pool.ts'\nimport { Handlerinformation, NostrConnect } from './kinds.ts'\nimport { Signer } from './signer.ts'\n\nvar _fetch: any\n\ntry {\n _fetch = fetch\n} catch {}\n\nexport function useFetchImplementation(fetchImplementation: any) {\n _fetch = fetchImplementation\n}\n\nexport const BUNKER_REGEX = /^bunker:\\/\\/([0-9a-f]{64})\\??([?\\/\\w:.=&%-]*)$/\nconst EMAIL_REGEX = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\nexport type BunkerPointer = {\n relays: string[]\n pubkey: string\n secret: null | string\n}\n\nexport function toBunkerURL(bunkerPointer: BunkerPointer): string {\n let bunkerURL = new URL(`bunker://${bunkerPointer.pubkey}`)\n bunkerPointer.relays.forEach(relay => {\n bunkerURL.searchParams.append('relay', relay)\n })\n if (bunkerPointer.secret) {\n bunkerURL.searchParams.set('secret', bunkerPointer.secret)\n }\n return bunkerURL.toString()\n}\n\n/** This takes either a bunker:// URL or a name@domain.com NIP-05 identifier\n and returns a BunkerPointer -- or null in case of error */\nexport async function parseBunkerInput(input: string): Promise<BunkerPointer | null> {\n let match = input.match(BUNKER_REGEX)\n if (match) {\n try {\n const pubkey = match[1]\n const qs = new URLSearchParams(match[2])\n return {\n pubkey,\n relays: qs.getAll('relay'),\n secret: qs.get('secret'),\n }\n } catch (_err) {\n /* just move to the next case */\n }\n }\n\n return queryBunkerProfile(input)\n}\n\nexport async function queryBunkerProfile(nip05: string): Promise<BunkerPointer | null> {\n const match = nip05.match(NIP05_REGEX)\n if (!match) return null\n\n const [_, name = '_', domain] = match\n\n try {\n const url = `https://${domain}/.well-known/nostr.json?name=${name}`\n const res = await (await _fetch(url, { redirect: 'error' })).json()\n\n let pubkey = res.names[name]\n let relays = res.nip46[pubkey] || []\n\n return { pubkey, relays, secret: null }\n } catch (_err) {\n return null\n }\n}\n\nexport type NostrConnectParams = {\n clientPubkey: string\n relays: string[]\n secret: string\n perms?: string[]\n name?: string\n url?: string\n image?: string\n}\n\nexport function createNostrConnectURI(params: NostrConnectParams): string {\n const queryParams = new URLSearchParams()\n\n params.relays.forEach(relay => {\n queryParams.append('relay', relay)\n })\n\n queryParams.append('secret', params.secret)\n\n if (params.perms && params.perms.length > 0) {\n queryParams.append('perms', params.perms.join(','))\n }\n if (params.name) {\n queryParams.append('name', params.name)\n }\n if (params.url) {\n queryParams.append('url', params.url)\n }\n if (params.image) {\n queryParams.append('image', params.image)\n }\n\n return `nostrconnect://${params.clientPubkey}?${queryParams.toString()}`\n}\n\nexport type BunkerSignerParams = {\n pool?: AbstractSimplePool\n onauth?: (url: string) => void\n /** Skip automatic switchRelays() call in fromURI. Useful when you want to call it manually at your own pace. */\n skipSwitchRelays?: boolean\n}\n\nexport class BunkerSigner implements Signer {\n private params: BunkerSignerParams\n private pool: AbstractSimplePool\n private subCloser: SubCloser | undefined\n private isOpen: boolean\n private serial: number\n private idPrefix: string\n private listeners: {\n [id: string]: {\n resolve: (_: string) => void\n reject: (_: string) => void\n }\n }\n private waitingForAuth: { [id: string]: boolean }\n private secretKey: Uint8Array\n // If the client initiates the connection, the two variables below can be filled in later.\n private conversationKey!: Uint8Array\n public bp!: BunkerPointer\n\n private cachedPubKey: string | undefined\n\n /**\n * Creates a new instance of the Nip46 class.\n * @param relays - An array of relay addresses.\n * @param remotePubkey - An optional remote public key. This is the key you want to sign as.\n * @param secretKey - An optional key pair.\n */\n private constructor(clientSecretKey: Uint8Array, params: BunkerSignerParams) {\n this.params = params\n this.pool = params.pool || new SimplePool()\n this.secretKey = clientSecretKey\n this.isOpen = false\n this.idPrefix = Math.random().toString(36).substring(7)\n this.serial = 0\n this.listeners = {}\n this.waitingForAuth = {}\n }\n\n /**\n * [Factory Method 1] Creates a Signer using bunker information (bunker:// URL or NIP-05).\n * This method is used when the public key of the bunker is known in advance.\n */\n public static fromBunker(\n clientSecretKey: Uint8Array,\n bp: BunkerPointer,\n params: BunkerSignerParams = {},\n ): BunkerSigner {\n if (bp.relays.length === 0) {\n throw new Error('no relays specified for this bunker')\n }\n\n const signer = new BunkerSigner(clientSecretKey, params)\n\n signer.conversationKey = getConversationKey(clientSecretKey, bp.pubkey)\n signer.bp = bp\n\n signer.setupSubscription()\n return signer\n }\n\n /**\n * [Factory Method 2] Creates a Signer using a nostrconnect:// URI generated by the client.\n * In this method, the bunker initiates the connection by scanning the URI.\n */\n public static async fromURI(\n clientSecretKey: Uint8Array,\n connectionURI: string,\n bunkerParams: BunkerSignerParams = {},\n maxWaitOrAbort: number | AbortSignal = 300_000,\n ): Promise<BunkerSigner> {\n const signer = new BunkerSigner(clientSecretKey, bunkerParams)\n const uri = new URL(connectionURI)\n const clientPubkey = getPublicKey(clientSecretKey)\n\n return new Promise((resolve, reject) => {\n let success = false\n const sub = signer.pool.subscribe(\n uri.searchParams.getAll('relay'),\n {\n kinds: [NostrConnect],\n '#p': [clientPubkey],\n limit: 0,\n },\n {\n onevent: async (event: NostrEvent) => {\n try {\n const tempConvKey = getConversationKey(clientSecretKey, event.pubkey)\n const decryptedContent = decrypt(event.content, tempConvKey)\n\n const response = JSON.parse(decryptedContent)\n\n if (response.result === uri.searchParams.get('secret')) {\n sub.close()\n\n signer.bp = {\n pubkey: event.pubkey,\n relays: uri.searchParams.getAll('relay'),\n secret: uri.searchParams.get('secret'),\n }\n signer.conversationKey = getConversationKey(clientSecretKey, event.pubkey)\n signer.setupSubscription()\n\n success = true\n if (!bunkerParams.skipSwitchRelays) {\n await Promise.race([new Promise(resolve => setTimeout(resolve, 1000)), signer.switchRelays()])\n }\n resolve(signer)\n }\n } catch (e) {\n console.warn('failed to process potential connection event', e)\n }\n },\n onclose: () => {\n if (!success) reject(new Error('subscription closed before connection was established.'))\n },\n maxWait: typeof maxWaitOrAbort === 'number' ? maxWaitOrAbort : undefined,\n abort: typeof maxWaitOrAbort !== 'number' ? maxWaitOrAbort : undefined,\n },\n )\n })\n }\n\n private setupSubscription() {\n const listeners = this.listeners\n const waitingForAuth = this.waitingForAuth\n const convKey = this.conversationKey\n\n this.subCloser = this.pool.subscribe(\n this.bp.relays,\n {\n kinds: [NostrConnect],\n authors: [this.bp.pubkey],\n '#p': [getPublicKey(this.secretKey)],\n limit: 0,\n },\n {\n onevent: async (event: NostrEvent) => {\n const o = JSON.parse(decrypt(event.content, convKey))\n const { id, result, error } = o\n\n if (result === 'auth_url' && waitingForAuth[id]) {\n delete waitingForAuth[id]\n\n if (this.params.onauth) {\n this.params.onauth(error)\n } else {\n console.warn(\n `nostr-tools/nip46: remote signer ${this.bp.pubkey} tried to send an \"auth_url\"='${error}' but there was no onauth() callback configured.`,\n )\n }\n return\n }\n\n let handler = listeners[id]\n if (handler) {\n if (error) handler.reject(error)\n else if (result) handler.resolve(result)\n delete listeners[id]\n }\n },\n onclose: () => {\n this.subCloser = undefined\n },\n },\n )\n this.isOpen = true\n }\n\n async switchRelays(): Promise<boolean> {\n try {\n const switchResp = await this.sendRequest('switch_relays', [])\n let relays = JSON.parse(switchResp) as string[] | null\n if (!relays) return false\n if (JSON.stringify(relays.sort()) === JSON.stringify(this.bp.relays)) return false\n\n this.bp.relays = relays\n let previousCloser = this.subCloser!\n setTimeout(() => {\n previousCloser.close()\n }, 5000)\n\n this.subCloser = undefined\n this.setupSubscription()\n return true\n } catch {\n return false\n }\n }\n\n // closes the subscription -- this object can't be used anymore after this\n async close() {\n this.isOpen = false\n this.subCloser!.close()\n }\n\n async sendRequest(method: string, params: string[]): Promise<string> {\n return new Promise(async (resolve, reject) => {\n try {\n if (!this.isOpen) throw new Error('this signer is not open anymore, create a new one')\n if (!this.subCloser) this.setupSubscription()\n\n this.serial++\n const id = `${this.idPrefix}-${this.serial}`\n\n const encryptedContent = encrypt(JSON.stringify({ id, method, params }), this.conversationKey)\n\n // the request event\n const verifiedEvent: VerifiedEvent = finalizeEvent(\n {\n kind: NostrConnect,\n tags: [['p', this.bp.pubkey]],\n content: encryptedContent,\n created_at: Math.floor(Date.now() / 1000),\n },\n this.secretKey,\n )\n\n // setup callback listener\n this.listeners[id] = { resolve, reject }\n this.waitingForAuth[id] = true\n\n // publish the event\n await Promise.any(this.pool.publish(this.bp.relays, verifiedEvent))\n } catch (err) {\n reject(err)\n }\n })\n }\n\n /**\n * Calls the \"connect\" method on the bunker.\n * The promise will be rejected if the response is not \"pong\".\n */\n async ping(): Promise<void> {\n let resp = await this.sendRequest('ping', [])\n if (resp !== 'pong') throw new Error(`result is not pong: ${resp}`)\n }\n\n /**\n * Calls the \"connect\" method on the bunker.\n */\n async connect(): Promise<void> {\n await this.sendRequest('connect', [this.bp.pubkey, this.bp.secret || ''])\n }\n\n /**\n * Calls the \"get_public_key\" method on the bunker.\n * (before we would return the public key hardcoded in the bunker parameters, but\n * that is not correct as that may be the bunker pubkey and the actual signer\n * pubkey may be different.)\n */\n async getPublicKey(): Promise<string> {\n if (!this.cachedPubKey) {\n this.cachedPubKey = await this.sendRequest('get_public_key', [])\n }\n return this.cachedPubKey\n }\n\n /**\n * Signs an event using the remote private key.\n * @param event - The event to sign.\n * @returns A Promise that resolves to the signed event.\n */\n async signEvent(event: EventTemplate): Promise<VerifiedEvent> {\n let resp = await this.sendRequest('sign_event', [JSON.stringify(event)])\n let signed: NostrEvent = JSON.parse(resp)\n if (verifyEvent(signed)) {\n return signed\n } else {\n throw new Error(`event returned from bunker is improperly signed: ${JSON.stringify(signed)}`)\n }\n }\n\n async nip04Encrypt(thirdPartyPubkey: string, plaintext: string): Promise<string> {\n return await this.sendRequest('nip04_encrypt', [thirdPartyPubkey, plaintext])\n }\n\n async nip04Decrypt(thirdPartyPubkey: string, ciphertext: string): Promise<string> {\n return await this.sendRequest('nip04_decrypt', [thirdPartyPubkey, ciphertext])\n }\n\n async nip44Encrypt(thirdPartyPubkey: string, plaintext: string): Promise<string> {\n return await this.sendRequest('nip44_encrypt', [thirdPartyPubkey, plaintext])\n }\n\n async nip44Decrypt(thirdPartyPubkey: string, ciphertext: string): Promise<string> {\n return await this.sendRequest('nip44_decrypt', [thirdPartyPubkey, ciphertext])\n }\n}\n\n/**\n * Creates an account with the specified username, domain, and optional email.\n * @param bunkerPubkey - The public key of the bunker to use for the create_account call.\n * @param username - The username for the account.\n * @param domain - The domain for the account.\n * @param email - The optional email for the account.\n * @param localSecretKey - Optionally pass a local secret key that will be used to communicate with the bunker,\n this will default to generating a random key.\n * @throws Error if the email is present but invalid.\n * @returns A Promise that resolves to the auth_url that the client should follow to create an account.\n */\nexport async function createAccount(\n bunker: BunkerProfile,\n params: BunkerSignerParams,\n username: string,\n domain: string,\n email?: string,\n localSecretKey: Uint8Array = generateSecretKey(),\n): Promise<BunkerSigner> {\n if (email && !EMAIL_REGEX.test(email)) throw new Error('invalid email')\n\n let rpc = BunkerSigner.fromBunker(localSecretKey, bunker.bunkerPointer, params)\n\n let pubkey = await rpc.sendRequest('create_account', [username, domain, email || ''])\n\n // once we get the newly created pubkey back, we hijack this signer instance\n // and turn it into the main instance for this newly created pubkey\n rpc.bp.pubkey = pubkey\n await rpc.connect()\n\n return rpc\n}\n\n/**\n * Fetches info on available providers that announce themselves using NIP-89 events.\n * @returns A promise that resolves to an array of available bunker objects.\n */\nexport async function fetchBunkerProviders(pool: AbstractSimplePool, relays: string[]): Promise<BunkerProfile[]> {\n const events = await pool.querySync(relays, {\n kinds: [Handlerinformation],\n '#k': [NostrConnect.toString()],\n })\n\n events.sort((a, b) => b.created_at - a.created_at)\n\n // validate bunkers by checking their NIP-05 and pubkey\n // map to a more useful object\n const validatedBunkers = await Promise.all(\n events.map(async (event, i) => {\n try {\n const content = JSON.parse(event.content)\n\n // skip duplicates\n try {\n if (events.findIndex(ev => JSON.parse(ev.content).nip05 === content.nip05) !== i) return undefined\n } catch (err) {\n /***/\n }\n\n const bp = await queryBunkerProfile(content.nip05)\n if (bp && bp.pubkey === event.pubkey && bp.relays.length) {\n return {\n bunkerPointer: bp,\n nip05: content.nip05,\n domain: content.nip05.split('@')[1],\n name: content.name || content.display_name,\n picture: content.picture,\n about: content.about,\n website: content.website,\n local: false,\n }\n }\n } catch (err) {\n return undefined\n }\n }),\n )\n\n return validatedBunkers.filter(b => b !== undefined) as BunkerProfile[]\n}\n\nexport type BunkerProfile = {\n bunkerPointer: BunkerPointer\n domain: string\n nip05: string\n name: string\n picture: string\n about: string\n website: string\n local: boolean\n}\n", "import { schnorr } from '@noble/curves/secp256k1.js'\nimport { bytesToHex, hexToBytes } from '@noble/hashes/utils.js'\nimport { Nostr, Event, EventTemplate, UnsignedEvent, VerifiedEvent, verifiedSymbol, validateEvent } from './core.ts'\nimport { sha256 } from '@noble/hashes/sha2.js'\n\nimport { utf8Encoder } from './utils.ts'\n\nclass JS implements Nostr {\n generateSecretKey(): Uint8Array {\n return schnorr.utils.randomSecretKey()\n }\n getPublicKey(secretKey: Uint8Array): string {\n return bytesToHex(schnorr.getPublicKey(secretKey))\n }\n finalizeEvent(t: EventTemplate, secretKey: Uint8Array): VerifiedEvent {\n const event = t as VerifiedEvent\n event.pubkey = bytesToHex(schnorr.getPublicKey(secretKey))\n event.id = getEventHash(event)\n event.sig = bytesToHex(schnorr.sign(hexToBytes(getEventHash(event)), secretKey))\n event[verifiedSymbol] = true\n return event\n }\n verifyEvent(event: Event): event is VerifiedEvent {\n if (typeof event[verifiedSymbol] === 'boolean') return event[verifiedSymbol]\n\n try {\n const hash = getEventHash(event)\n if (hash !== event.id) {\n event[verifiedSymbol] = false\n return false\n }\n\n const valid = schnorr.verify(hexToBytes(event.sig), hexToBytes(hash), hexToBytes(event.pubkey))\n event[verifiedSymbol] = valid\n return valid\n } catch (err) {\n event[verifiedSymbol] = false\n return false\n }\n }\n}\n\nexport function serializeEvent(evt: UnsignedEvent): string {\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}\n\nexport function getEventHash(event: UnsignedEvent): string {\n let eventHash = sha256(utf8Encoder.encode(serializeEvent(event)))\n return bytesToHex(eventHash)\n}\n\nconst i: JS = new JS()\n\nexport const generateSecretKey = i.generateSecretKey\nexport const getPublicKey = i.getPublicKey\nexport const finalizeEvent = i.finalizeEvent\nexport const verifyEvent = i.verifyEvent\nexport * from './core.ts'\n", "export interface Nostr {\n generateSecretKey(): Uint8Array\n getPublicKey(secretKey: Uint8Array): string\n finalizeEvent(event: EventTemplate, secretKey: Uint8Array): VerifiedEvent\n verifyEvent(event: Event): event is VerifiedEvent\n}\n\n/** Designates a verified event signature. */\nexport const verifiedSymbol = Symbol('verified')\n\nexport type NostrEvent = {\n kind: number\n tags: string[][]\n content: string\n created_at: number\n pubkey: string\n id: string\n sig: string\n [verifiedSymbol]?: boolean\n}\n\nexport type Event = NostrEvent\nexport type EventTemplate = Pick<Event, 'kind' | 'tags' | 'content' | 'created_at'>\nexport type UnsignedEvent = Pick<Event, 'kind' | 'tags' | 'content' | 'created_at' | 'pubkey'>\n\n/** An event whose signature has been verified. */\nexport interface VerifiedEvent extends Event {\n [verifiedSymbol]: true\n}\n\nconst isRecord = (obj: unknown): obj is Record<string, unknown> => obj instanceof Object\n\nexport function validateEvent<T>(event: T): event is T & UnsignedEvent {\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\n if (!Array.isArray(event.tags)) return false\n for (let i = 0; i < event.tags.length; i++) {\n let tag = event.tags[i]\n if (!Array.isArray(tag)) return false\n for (let j = 0; j < tag.length; j++) {\n if (typeof tag[j] !== 'string') return false\n }\n }\n\n return true\n}\n\n/**\n * Sort events in reverse-chronological order by the `created_at` timestamp,\n * and then by the event `id` (lexicographically) in case of ties.\n * This mutates the array.\n */\nexport function sortEvents(events: Event[]): Event[] {\n return events.sort((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.localeCompare(b.id)\n })\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 { chacha20 } from '@noble/ciphers/chacha.js'\nimport { equalBytes } from '@noble/ciphers/utils.js'\nimport { secp256k1 } from '@noble/curves/secp256k1.js'\nimport { extract as hkdf_extract, expand as hkdf_expand } from '@noble/hashes/hkdf.js'\nimport { hmac } from '@noble/hashes/hmac.js'\nimport { sha256 } from '@noble/hashes/sha2.js'\nimport { concatBytes, hexToBytes, randomBytes } from '@noble/hashes/utils.js'\nimport { base64 } from '@scure/base'\n\nimport { utf8Decoder, utf8Encoder } from './utils.ts'\n\nconst minPlaintextSize = 0x0001 // 1b msg => padded to 32b\nconst maxPlaintextSize = 0xffffffff // 4294967295 (2^32-1)\nconst extendedPrefixThreshold = 0x10000 // 65536: lengths below use 2-byte u16 prefix, at or above use 6-byte prefix\n\nexport function getConversationKey(privkeyA: Uint8Array, pubkeyB: string): Uint8Array {\n const sharedX = secp256k1.getSharedSecret(privkeyA, hexToBytes('02' + pubkeyB)).subarray(1, 33)\n return hkdf_extract(sha256, sharedX, utf8Encoder.encode('nip44-v2'))\n}\n\nfunction getMessageKeys(\n conversationKey: Uint8Array,\n nonce: Uint8Array,\n): { chacha_key: Uint8Array; chacha_nonce: Uint8Array; hmac_key: Uint8Array } {\n const keys = hkdf_expand(sha256, conversationKey, nonce, 76)\n return {\n chacha_key: keys.subarray(0, 32),\n chacha_nonce: keys.subarray(32, 44),\n hmac_key: keys.subarray(44, 76),\n }\n}\n\nfunction calcPaddedLen(len: number): number {\n if (!Number.isSafeInteger(len) || len < 1) throw new Error('expected positive integer')\n if (len <= 32) return 32\n const nextPower = 2 ** (Math.floor(Math.log2(len - 1)) + 1)\n const chunk = nextPower <= 256 ? 32 : nextPower / 8\n return chunk * (Math.floor((len - 1) / chunk) + 1)\n}\n\nfunction writeU16BE(num: number): Uint8Array {\n if (!Number.isSafeInteger(num) || num < minPlaintextSize || num > 0xffff)\n throw new Error('invalid plaintext size: must be between 1 and 65535 bytes')\n const arr = new Uint8Array(2)\n new DataView(arr.buffer).setUint16(0, num, false)\n return arr\n}\n\nfunction writeU32BE(num: number): Uint8Array {\n if (!Number.isSafeInteger(num) || num < extendedPrefixThreshold || num > maxPlaintextSize)\n throw new Error('invalid plaintext size: must be between 65536 and 4294967295 bytes')\n const arr = new Uint8Array(4)\n new DataView(arr.buffer).setUint32(0, num, false)\n return arr\n}\n\nfunction pad(plaintext: string): Uint8Array {\n const unpadded = utf8Encoder.encode(plaintext)\n const unpaddedLen = unpadded.length\n if (unpaddedLen < minPlaintextSize || unpaddedLen > maxPlaintextSize)\n throw new Error('invalid plaintext size: must be between 1 and 4294967295 bytes')\n const prefix =\n unpaddedLen >= extendedPrefixThreshold\n ? concatBytes(new Uint8Array([0, 0]), writeU32BE(unpaddedLen)) // 6 bytes\n : writeU16BE(unpaddedLen) // 2 bytes\n const suffix = new Uint8Array(calcPaddedLen(unpaddedLen) - unpaddedLen)\n return concatBytes(prefix, unpadded, suffix)\n}\n\nfunction unpad(padded: Uint8Array): string {\n const dv = new DataView(padded.buffer, padded.byteOffset, padded.byteLength)\n const firstTwo = dv.getUint16(0)\n let unpaddedLen: number\n let prefixLen: number\n if (firstTwo === 0) {\n // Extended format: 2 zero bytes + 4-byte u32 length\n unpaddedLen = dv.getUint32(2)\n if (unpaddedLen < extendedPrefixThreshold) throw new Error('invalid padding')\n prefixLen = 6\n } else {\n unpaddedLen = firstTwo\n prefixLen = 2\n }\n const unpadded = padded.subarray(prefixLen, prefixLen + unpaddedLen)\n if (\n unpaddedLen < minPlaintextSize ||\n unpaddedLen > maxPlaintextSize ||\n unpadded.length !== unpaddedLen ||\n padded.length !== prefixLen + calcPaddedLen(unpaddedLen)\n )\n throw new Error('invalid padding')\n return utf8Decoder.decode(unpadded)\n}\n\nfunction hmacAad(key: Uint8Array, message: Uint8Array, aad: Uint8Array): Uint8Array {\n if (aad.length !== 32) throw new Error('AAD associated data must be 32 bytes')\n const combined = concatBytes(aad, message)\n return hmac(sha256, key, combined)\n}\n\n// metadata: always 65b (version: 1b, nonce: 32b, mac: 32b)\n// plaintext: 1b to 0xffffffff\n// padded plaintext (small, <65536): 32b to 0x10000, with 2b prefix -> 34b to 0x10000+2\n// padded plaintext (large, >=65536): 0x10000 to 0x100000000, with 6b prefix -> 0x10006 to 0x100000000+6\n// ciphertext: same as padded plaintext (chacha20 doesn't change length)\n// raw payload (small): 99 (65+34) to 65603 (65+0x10000+2)\n// raw payload (large): 65607 (65+0x10006) to 4294967367 (65+0x100000000+6)\nfunction decodePayload(payload: string): { nonce: Uint8Array; ciphertext: Uint8Array; mac: Uint8Array } {\n if (typeof payload !== 'string') throw new Error('payload must be a valid string')\n const plen = payload.length\n if (plen < 132) throw new Error('invalid payload length: ' + plen)\n if (payload[0] === '#') throw new Error('unknown encryption version')\n let data: Uint8Array\n try {\n data = base64.decode(payload)\n } catch (error) {\n throw new Error('invalid base64: ' + (error as any).message)\n }\n const dlen = data.length\n if (dlen < 99) throw new Error('invalid data length: ' + dlen)\n const vers = data[0]\n if (vers !== 2) throw new Error('unknown encryption version ' + vers)\n return {\n nonce: data.subarray(1, 33),\n ciphertext: data.subarray(33, -32),\n mac: data.subarray(-32),\n }\n}\n\nexport function encrypt(plaintext: string, conversationKey: Uint8Array, nonce: Uint8Array = randomBytes(32)): string {\n const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce)\n const padded = pad(plaintext)\n const ciphertext = chacha20(chacha_key, chacha_nonce, padded)\n const mac = hmacAad(hmac_key, ciphertext, nonce)\n return base64.encode(concatBytes(new Uint8Array([2]), nonce, ciphertext, mac))\n}\n\n/** Callers should validate payload size before calling to prevent DoS from oversized inputs. */\nexport function decrypt(payload: string, conversationKey: Uint8Array): string {\n const { nonce, ciphertext, mac } = decodePayload(payload)\n const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce)\n const calculatedMac = hmacAad(hmac_key, ciphertext, nonce)\n if (!equalBytes(calculatedMac, mac)) throw new Error('invalid MAC')\n const padded = chacha20(chacha_key, chacha_nonce, ciphertext)\n return unpad(padded)\n}\n\nexport const v2 = {\n utils: {\n getConversationKey,\n calcPaddedLen,\n pad,\n unpad,\n },\n encrypt,\n decrypt,\n}\n", "import { ProfilePointer } from './nip19.ts'\n\nexport type Nip05 = `${string}@${string}`\n\n/**\n * NIP-05 regex. The localpart is optional, and should be assumed to be `_` otherwise.\n *\n * - 0: full match\n * - 1: name (optional)\n * - 2: domain\n */\nexport const NIP05_REGEX = /^(?:([\\w.+-]+)@)?([\\w_-]+(\\.[\\w_-]+)+)$/\nexport const isNip05 = (value?: string | null): value is Nip05 => NIP05_REGEX.test(value || '')\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _fetch: any\n\ntry {\n _fetch = fetch\n} catch (_) {\n null\n}\n\nexport function useFetchImplementation(fetchImplementation: unknown) {\n _fetch = fetchImplementation\n}\n\nexport async function searchDomain(domain: string, query = ''): Promise<{ [name: string]: string }> {\n try {\n const url = `https://${domain}/.well-known/nostr.json?name=${query}`\n const res = await _fetch(url, { redirect: 'manual' })\n if (res.status !== 200) {\n throw Error('Wrong response code')\n }\n const json = await res.json()\n return json.names\n } catch (_) {\n return {}\n }\n}\n\nexport async function queryProfile(fullname: string): Promise<ProfilePointer | null> {\n const match = fullname.match(NIP05_REGEX)\n if (!match) return null\n\n const [, name = '_', domain] = match\n\n try {\n const url = `https://${domain}/.well-known/nostr.json?name=${name}`\n const res = await _fetch(url, { redirect: 'manual' })\n if (res.status !== 200) {\n throw Error('Wrong response code')\n }\n const json = await res.json()\n\n const pubkey = json.names[name]\n return pubkey ? { pubkey, relays: json.relays?.[pubkey] } : null\n } catch (_e) {\n return null\n }\n}\n\nexport async function isValid(pubkey: string, nip05: Nip05): Promise<boolean> {\n const res = await queryProfile(nip05)\n return res ? res.pubkey === pubkey : false\n}\n", "import { NostrEvent, validateEvent } from './pure.ts'\n\n/** Events are **regular**, which means they're all expected to be stored by relays. */\nexport function isRegularKind(kind: number): boolean {\n return kind < 10000 && kind !== 0 && kind !== 3\n}\n\n/** Events are **replaceable**, which means that, for each combination of `pubkey` and `kind`, only the latest event is expected to (SHOULD) be stored by relays, older versions are expected to be discarded. */\nexport function isReplaceableKind(kind: number): boolean {\n return kind === 0 || kind === 3 || (10000 <= kind && kind < 20000)\n}\n\n/** Events are **ephemeral**, which means they are not expected to be stored by relays. */\nexport function isEphemeralKind(kind: number): boolean {\n return 20000 <= kind && kind < 30000\n}\n\n/** Events are **addressable**, which means that, for each combination of `pubkey`, `kind` and the `d` tag, only the latest event is expected to be stored by relays, older versions are expected to be discarded. */\nexport function isAddressableKind(kind: number): boolean {\n return 30000 <= kind && kind < 40000\n}\n\n/** Classification of the event kind. */\nexport type KindClassification = 'regular' | 'replaceable' | 'ephemeral' | 'parameterized' | 'unknown'\n\n/** Determine the classification of this kind of event if known, or `unknown`. */\nexport function classifyKind(kind: number): KindClassification {\n if (isRegularKind(kind)) return 'regular'\n if (isReplaceableKind(kind)) return 'replaceable'\n if (isEphemeralKind(kind)) return 'ephemeral'\n if (isAddressableKind(kind)) return 'parameterized'\n return 'unknown'\n}\n\nexport function isKind<T extends number>(event: unknown, kind: T | Array<T>): event is NostrEvent & { kind: T } {\n const kindAsArray: number[] = kind instanceof Array ? kind : [kind]\n return (validateEvent(event) && kindAsArray.includes(event.kind)) || false\n}\n\nexport const Metadata = 0\nexport type Metadata = typeof Metadata\nexport const ShortTextNote = 1\nexport type ShortTextNote = typeof ShortTextNote\nexport const RecommendRelay = 2\nexport type RecommendRelay = typeof RecommendRelay\nexport const Contacts = 3\nexport type Contacts = typeof Contacts\nexport const EncryptedDirectMessage = 4\nexport type EncryptedDirectMessage = typeof EncryptedDirectMessage\nexport const EventDeletion = 5\nexport type EventDeletion = typeof EventDeletion\nexport const Repost = 6\nexport type Repost = typeof Repost\nexport const Reaction = 7\nexport type Reaction = typeof Reaction\nexport const BadgeAward = 8\nexport type BadgeAward = typeof BadgeAward\nexport const ChatMessage = 9\nexport type ChatMessage = typeof ChatMessage\nexport const ForumThread = 11\nexport type ForumThread = typeof ForumThread\nexport const Seal = 13\nexport type Seal = typeof Seal\nexport const PrivateDirectMessage = 14\nexport type PrivateDirectMessage = typeof PrivateDirectMessage\nexport const FileMessage = 15\nexport type FileMessage = typeof FileMessage\nexport const GenericRepost = 16\nexport type GenericRepost = typeof GenericRepost\nexport const Photo = 20\nexport type Photo = typeof Photo\nexport const NormalVideo = 21\nexport type NormalVideo = typeof NormalVideo\nexport const ShortVideo = 22\nexport type ShortVideo = typeof ShortVideo\nexport const ChannelCreation = 40\nexport type ChannelCreation = typeof ChannelCreation\nexport const ChannelMetadata = 41\nexport type ChannelMetadata = typeof ChannelMetadata\nexport const ChannelMessage = 42\nexport type ChannelMessage = typeof ChannelMessage\nexport const ChannelHideMessage = 43\nexport type ChannelHideMessage = typeof ChannelHideMessage\nexport const ChannelMuteUser = 44\nexport type ChannelMuteUser = typeof ChannelMuteUser\nexport const OpenTimestamps = 1040\nexport type OpenTimestamps = typeof OpenTimestamps\nexport const GiftWrap = 1059\nexport type GiftWrap = typeof GiftWrap\nexport const Poll = 1068\nexport type Poll = typeof Poll\nexport const FileMetadata = 1063\nexport type FileMetadata = typeof FileMetadata\nexport const Comment = 1111\nexport type Comment = typeof Comment\nexport const LiveChatMessage = 1311\nexport type LiveChatMessage = typeof LiveChatMessage\nexport const Voice = 1222\nexport type Voice = typeof Voice\nexport const VoiceComment = 1244\nexport type VoiceComment = typeof VoiceComment\nexport const ProblemTracker = 1971\nexport type ProblemTracker = typeof ProblemTracker\nexport const Report = 1984\nexport type Report = typeof Report\nexport const Reporting = 1984\nexport type Reporting = typeof Reporting\nexport const Label = 1985\nexport type Label = typeof Label\nexport const CommunityPostApproval = 4550\nexport type CommunityPostApproval = typeof CommunityPostApproval\nexport const JobRequest = 5999\nexport type JobRequest = typeof JobRequest\nexport const JobResult = 6999\nexport type JobResult = typeof JobResult\nexport const JobFeedback = 7000\nexport type JobFeedback = typeof JobFeedback\nexport const ZapGoal = 9041\nexport type ZapGoal = typeof ZapGoal\nexport const ZapRequest = 9734\nexport type ZapRequest = typeof ZapRequest\nexport const Zap = 9735\nexport type Zap = typeof Zap\nexport const Highlights = 9802\nexport type Highlights = typeof Highlights\nexport const PollResponse = 1018\nexport type PollResponse = typeof PollResponse\nexport const Mutelist = 10000\nexport type Mutelist = typeof Mutelist\nexport const Pinlist = 10001\nexport type Pinlist = typeof Pinlist\nexport const RelayList = 10002\nexport type RelayList = typeof RelayList\nexport const BookmarkList = 10003\nexport type BookmarkList = typeof BookmarkList\nexport const CommunitiesList = 10004\nexport type CommunitiesList = typeof CommunitiesList\nexport const PublicChatsList = 10005\nexport type PublicChatsList = typeof PublicChatsList\nexport const BlockedRelaysList = 10006\nexport type BlockedRelaysList = typeof BlockedRelaysList\nexport const SearchRelaysList = 10007\nexport type SearchRelaysList = typeof SearchRelaysList\nexport const FavoriteRelays = 10012\nexport type FavoriteRelays = typeof FavoriteRelays\nexport const InterestsList = 10015\nexport type InterestsList = typeof InterestsList\nexport const UserEmojiList = 10030\nexport type UserEmojiList = typeof UserEmojiList\nexport const DirectMessageRelaysList = 10050\nexport type DirectMessageRelaysList = typeof DirectMessageRelaysList\nexport const FileServerPreference = 10096\nexport type FileServerPreference = typeof FileServerPreference\nexport const BlossomServerList = 10063\nexport type BlossomServerList = typeof BlossomServerList\nexport const NWCWalletInfo = 13194\nexport type NWCWalletInfo = typeof NWCWalletInfo\nexport const LightningPubRPC = 21000\nexport type LightningPubRPC = typeof LightningPubRPC\nexport const ClientAuth = 22242\nexport type ClientAuth = typeof ClientAuth\nexport const NWCWalletRequest = 23194\nexport type NWCWalletRequest = typeof NWCWalletRequest\nexport const NWCWalletResponse = 23195\nexport type NWCWalletResponse = typeof NWCWalletResponse\nexport const NostrConnect = 24133\nexport type NostrConnect = typeof NostrConnect\nexport const HTTPAuth = 27235\nexport type HTTPAuth = typeof HTTPAuth\nexport const Followsets = 30000\nexport type Followsets = typeof Followsets\nexport const Genericlists = 30001\nexport type Genericlists = typeof Genericlists\nexport const Relaysets = 30002\nexport type Relaysets = typeof Relaysets\nexport const Bookmarksets = 30003\nexport type Bookmarksets = typeof Bookmarksets\nexport const Curationsets = 30004\nexport type Curationsets = typeof Curationsets\nexport const ProfileBadges = 30008\nexport type ProfileBadges = typeof ProfileBadges\nexport const BadgeDefinition = 30009\nexport type BadgeDefinition = typeof BadgeDefinition\nexport const Interestsets = 30015\nexport type Interestsets = typeof Interestsets\nexport const CreateOrUpdateStall = 30017\nexport type CreateOrUpdateStall = typeof CreateOrUpdateStall\nexport const CreateOrUpdateProduct = 30018\nexport type CreateOrUpdateProduct = typeof CreateOrUpdateProduct\nexport const LongFormArticle = 30023\nexport type LongFormArticle = typeof LongFormArticle\nexport const DraftLong = 30024\nexport type DraftLong = typeof DraftLong\nexport const Emojisets = 30030\nexport type Emojisets = typeof Emojisets\nexport const Application = 30078\nexport type Application = typeof Application\nexport const LiveEvent = 30311\nexport type LiveEvent = typeof LiveEvent\nexport const UserStatuses = 30315\nexport type UserStatuses = typeof UserStatuses\nexport const ClassifiedListing = 30402\nexport type ClassifiedListing = typeof ClassifiedListing\nexport const DraftClassifiedListing = 30403\nexport type DraftClassifiedListing = typeof DraftClassifiedListing\nexport const Date = 31922\nexport type Date = typeof Date\nexport const Time = 31923\nexport type Time = typeof Time\nexport const Calendar = 31924\nexport type Calendar = typeof Calendar\nexport const CalendarEventRSVP = 31925\nexport type CalendarEventRSVP = typeof CalendarEventRSVP\nexport const RelayReview = 31987\nexport type RelayReview = typeof RelayReview\nexport const Handlerrecommendation = 31989\nexport type Handlerrecommendation = typeof Handlerrecommendation\nexport const Handlerinformation = 31990\nexport type Handlerinformation = typeof Handlerinformation\nexport const CommunityDefinition = 34550\nexport type CommunityDefinition = typeof CommunityDefinition\nexport const GroupMetadata = 39000\nexport type GroupMetadata = typeof GroupMetadata\n", "import { Event } from './core.ts'\nimport { isAddressableKind, isReplaceableKind } from './kinds.ts'\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 [key: `#${string}`]: string[] | undefined\n}\n\nexport function matchFilter(filter: Filter, event: Event): boolean {\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\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\n if (filter.since && event.created_at < filter.since) return false\n if (filter.until && event.created_at > filter.until) return false\n\n return true\n}\n\nexport function matchFilters(filters: Filter[], event: Event): boolean {\n for (let i = 0; i < filters.length; i++) {\n if (matchFilter(filters[i], event)) {\n return true\n }\n }\n return false\n}\n\nexport function mergeFilters(...filters: Filter[]): Filter {\n let result: Filter = {}\n for (let i = 0; i < filters.length; i++) {\n let filter = filters[i]\n Object.entries(filter).forEach(([property, values]) => {\n if (property === 'kinds' || property === 'ids' || property === 'authors' || property[0] === '#') {\n // @ts-ignore\n result[property] = result[property] || []\n // @ts-ignore\n for (let v = 0; v < values.length; v++) {\n // @ts-ignore\n let value = values[v]\n // @ts-ignore\n if (!result[property].includes(value)) result[property].push(value)\n }\n }\n })\n\n if (filter.limit && (!result.limit || filter.limit > result.limit)) result.limit = filter.limit\n if (filter.until && (!result.until || filter.until > result.until)) result.until = filter.until\n if (filter.since && (!result.since || filter.since < result.since)) result.since = filter.since\n }\n\n return result\n}\n\n/**\n * Calculate the intrinsic limit of a filter.\n * This function returns a positive integer, or `Infinity` if there is no intrinsic limit.\n */\nexport function getFilterLimit(filter: Filter): number {\n if (filter.ids && !filter.ids.length) return 0\n if (filter.kinds && !filter.kinds.length) return 0\n if (filter.authors && !filter.authors.length) return 0\n\n for (const [key, value] of Object.entries(filter)) {\n if (key[0] === '#' && Array.isArray(value) && !value.length) return 0\n }\n\n return Math.min(\n // The `limit` property creates an artificial limit.\n Math.max(0, filter.limit ?? Infinity),\n\n // There can only be one event per `id`.\n filter.ids?.length ?? Infinity,\n\n // Replaceable events are limited by the number of authors and kinds.\n filter.authors?.length && filter.kinds?.every(kind => isReplaceableKind(kind))\n ? filter.authors.length * filter.kinds.length\n : Infinity,\n\n // Parameterized replaceable events are limited by the number of authors, kinds, and \"d\" tags.\n filter.authors?.length && filter.kinds?.every(kind => isAddressableKind(kind)) && filter['#d']?.length\n ? filter.authors.length * filter.kinds.length * filter['#d'].length\n : Infinity,\n )\n}\n", "export function getHex64(json: string, field: string): string {\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}\n\nexport function getInt(json: string, field: string): number {\n let len = field.length\n let idx = json.indexOf(`\"${field}\":`) + len + 3\n let sliced = json.slice(idx)\n let end = Math.min(sliced.indexOf(','), sliced.indexOf('}'))\n return parseInt(sliced.slice(0, end), 10)\n}\n\nexport function getSubscriptionId(json: string): string | null {\n let idx = json.slice(0, 22).indexOf(`\"EVENT\"`)\n if (idx === -1) return null\n\n let pstart = json.slice(idx + 7 + 1).indexOf(`\"`)\n if (pstart === -1) return null\n let start = idx + 7 + 1 + pstart\n\n let pend = json.slice(start + 1, 80).indexOf(`\"`)\n if (pend === -1) return null\n let end = start + 1 + pend\n\n return json.slice(start + 1, end)\n}\n\nexport function matchEventId(json: string, id: string): boolean {\n return id === getHex64(json, 'id')\n}\n\nexport function matchEventPubkey(json: string, pubkey: string): boolean {\n return pubkey === getHex64(json, 'pubkey')\n}\n\nexport function matchEventKind(json: string, kind: number): boolean {\n return kind === getInt(json, 'kind')\n}\n", "import { EventTemplate } from './core.ts'\nimport { ClientAuth } from './kinds.ts'\n\n/**\n * creates an EventTemplate for an AUTH event to be signed.\n */\nexport function makeAuthEvent(relayURL: string, challenge: string): EventTemplate {\n return {\n kind: ClientAuth,\n created_at: Math.floor(Date.now() / 1000),\n tags: [\n ['relay', relayURL],\n ['challenge', challenge],\n ],\n content: '',\n }\n}\n", "/* global WebSocket */\n\nimport type { Event, EventTemplate, VerifiedEvent, Nostr, NostrEvent } from './core.ts'\nimport { matchFilters, type Filter } from './filter.ts'\nimport { getHex64, getSubscriptionId } from './fakejson.ts'\nimport { normalizeURL } from './utils.ts'\nimport { makeAuthEvent } from './nip42.ts'\n\ntype RelayWebSocket = WebSocket & {\n ping?(): void\n on?(event: 'pong', listener: () => void): any\n}\n\nexport type AbstractRelayConstructorOptions = {\n verifyEvent: Nostr['verifyEvent']\n websocketImplementation?: typeof WebSocket\n enablePing?: boolean\n enableReconnect?: boolean\n}\n\nexport class SendingOnClosedConnection extends Error {\n constructor(message: string, relay: string) {\n super(`Tried to send message '${message} on a closed connection to ${relay}.`)\n this.name = 'SendingOnClosedConnection'\n }\n}\n\nexport class AbstractRelay {\n public readonly url: string\n private _connected: boolean = false\n\n public onclose: (() => void) | null = null\n public onnotice: (msg: string) => void = msg => console.debug(`NOTICE from ${this.url}: ${msg}`)\n public onauth: undefined | ((evt: EventTemplate) => Promise<VerifiedEvent>)\n\n public baseEoseTimeout: number = 4400\n public publishTimeout: number = 4400\n public pingFrequency: number = 29000\n public pingTimeout: number = 20000\n public resubscribeBackoff: number[] = [10000, 10000, 10000, 20000, 20000, 30000, 60000]\n public openSubs: Map<string, Subscription> = new Map()\n public enablePing: boolean | undefined\n public enableReconnect: boolean\n public idleSince: number | undefined = Date.now() // when undefined that means it isn't idle\n public ongoingOperations: number = 0 // used to compute idleness\n private reconnectTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n private pingIntervalHandle: ReturnType<typeof setInterval> | undefined\n private reconnectAttempts: number = 0\n private skipReconnection: boolean = false\n\n private connectionPromise: Promise<void> | undefined\n private openCountRequests = new Map<string, CountResolver>()\n private openEventPublishes = new Map<string, EventPublishResolver>()\n private ws: RelayWebSocket | undefined\n private challenge: string | undefined\n private authPromise: Promise<string> | undefined\n private serial: number = 0\n private verifyEvent: Nostr['verifyEvent']\n\n private _WebSocket: typeof WebSocket\n\n constructor(url: string, opts: AbstractRelayConstructorOptions) {\n this.url = normalizeURL(url)\n this.verifyEvent = opts.verifyEvent\n this._WebSocket = opts.websocketImplementation || WebSocket\n this.enablePing = opts.enablePing\n this.enableReconnect = opts.enableReconnect || false\n }\n\n static async connect(\n url: string,\n opts: AbstractRelayConstructorOptions & Parameters<AbstractRelay['connect']>[0],\n ): Promise<AbstractRelay> {\n const relay = new AbstractRelay(url, opts)\n await relay.connect(opts)\n return relay\n }\n\n private closeAllSubscriptions(reason: string) {\n for (let [_, sub] of this.openSubs) {\n sub.close(reason)\n }\n this.openSubs.clear()\n\n for (let [_, ep] of this.openEventPublishes) {\n ep.reject(new Error(reason))\n }\n this.openEventPublishes.clear()\n\n for (let [_, cr] of this.openCountRequests) {\n cr.reject(new Error(reason))\n }\n this.openCountRequests.clear()\n }\n\n public get connected(): boolean {\n return this._connected\n }\n\n private async reconnect(): Promise<void> {\n const backoff = this.resubscribeBackoff[Math.min(this.reconnectAttempts, this.resubscribeBackoff.length - 1)]\n this.reconnectAttempts++\n\n this.reconnectTimeoutHandle = setTimeout(async () => {\n try {\n await this.connect()\n } catch (err) {\n // this will be called again through onclose/onerror\n }\n }, backoff)\n }\n\n private handleHardClose(reason: string) {\n if (this.pingIntervalHandle) {\n clearInterval(this.pingIntervalHandle)\n this.pingIntervalHandle = undefined\n }\n\n this._connected = false\n this.connectionPromise = undefined\n this.idleSince = undefined\n\n if (this.enableReconnect && !this.skipReconnection) {\n this.reconnect()\n } else {\n this.onclose?.()\n this.closeAllSubscriptions(reason)\n }\n }\n\n public async connect(opts?: { timeout?: number; abort?: AbortSignal }): Promise<void> {\n let connectionTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n if (this.connectionPromise) return this.connectionPromise\n\n this.challenge = undefined\n this.authPromise = undefined\n this.skipReconnection = false\n this.connectionPromise = new Promise((resolve, reject) => {\n if (opts?.timeout) {\n connectionTimeoutHandle = setTimeout(() => {\n reject('connection timed out')\n this.connectionPromise = undefined\n this.skipReconnection = true\n this.onclose?.()\n this.handleHardClose('relay connection timed out')\n }, opts.timeout)\n }\n\n if (opts?.abort) {\n opts.abort.onabort = reject\n }\n\n try {\n this.ws = new this._WebSocket(this.url)\n } catch (err) {\n clearTimeout(connectionTimeoutHandle)\n reject(err)\n return\n }\n\n this.ws.onopen = () => {\n if (this.reconnectTimeoutHandle) {\n clearTimeout(this.reconnectTimeoutHandle)\n this.reconnectTimeoutHandle = undefined\n }\n clearTimeout(connectionTimeoutHandle)\n this._connected = true\n\n const isReconnection = this.reconnectAttempts > 0\n this.reconnectAttempts = 0\n\n // resubscribe to all open subscriptions\n for (const sub of this.openSubs.values()) {\n sub.eosed = false\n if (isReconnection) {\n for (let f = 0; f < sub.filters.length; f++) {\n if (sub.lastEmitted) {\n sub.filters[f].since = sub.lastEmitted + 1\n }\n }\n }\n sub.fire()\n }\n\n if (this.enablePing) {\n this.pingIntervalHandle = setInterval(() => this.pingpong(), this.pingFrequency)\n }\n resolve()\n }\n\n this.ws.onerror = () => {\n clearTimeout(connectionTimeoutHandle)\n reject('connection failed')\n this.connectionPromise = undefined\n this.skipReconnection = true\n this.onclose?.()\n this.handleHardClose('relay connection failed')\n }\n\n this.ws.onclose = ev => {\n clearTimeout(connectionTimeoutHandle)\n reject((ev as any).message || 'websocket closed')\n this.handleHardClose('relay connection closed')\n }\n\n this.ws.onmessage = this._onmessage.bind(this)\n })\n\n return this.connectionPromise\n }\n\n private waitForPingPong() {\n return new Promise(resolve => {\n // listen for pong\n ;(this.ws as any).once('pong', () => resolve(true))\n // send a ping\n this.ws!.ping!()\n })\n }\n\n private waitForDummyReq() {\n return new Promise((resolve, reject) => {\n if (!this.connectionPromise) return reject(new Error(`no connection to ${this.url}, can't ping`))\n\n // make a dummy request with expected empty eose reply\n // [\"REQ\", \"_\", {\"ids\":[\"aaaa...aaaa\"], \"limit\": 0}]\n try {\n const sub = this.subscribe(\n [{ ids: ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'], limit: 0 }],\n {\n label: '<forced-ping>',\n oneose: () => {\n resolve(true)\n sub.close()\n },\n onclose() {\n // if we get a CLOSED it's because the relay is alive\n resolve(true)\n },\n eoseTimeout: this.pingTimeout + 1000,\n },\n )\n } catch (err) {\n reject(err)\n }\n })\n }\n\n // nodejs requires this magic here to ensure connections are closed when internet goes off and stuff\n // in browsers it's done automatically. see https://github.com/nbd-wtf/nostr-tools/issues/491\n private async pingpong() {\n // if the websocket is connected\n if (this.ws?.readyState === 1) {\n // wait for either a ping-pong reply or a timeout\n const result = await Promise.any([\n // browsers don't have ping so use a dummy req\n this.ws && this.ws.ping && (this.ws as any).once ? this.waitForPingPong() : this.waitForDummyReq(),\n new Promise(res => setTimeout(() => res(false), this.pingTimeout)),\n ])\n\n if (!result) {\n // pingpong closing socket\n if (this.ws?.readyState === this._WebSocket.OPEN) {\n this.ws?.close()\n }\n }\n }\n }\n\n public async send(message: string) {\n if (!this.connectionPromise) throw new SendingOnClosedConnection(message, this.url)\n\n this.connectionPromise.then(() => {\n this.ws?.send(message)\n })\n }\n\n public async auth(signAuthEvent: (evt: EventTemplate) => Promise<VerifiedEvent>): Promise<string> {\n const challenge = this.challenge\n if (!challenge) throw new Error(\"can't perform auth, no challenge was received\")\n if (this.authPromise) return this.authPromise\n\n this.authPromise = new Promise<string>(async (resolve, reject) => {\n try {\n let evt = await signAuthEvent(makeAuthEvent(this.url, challenge))\n let timeout = setTimeout(() => {\n let ep = this.openEventPublishes.get(evt.id) as EventPublishResolver\n if (ep) {\n ep.reject(new Error('auth timed out'))\n this.openEventPublishes.delete(evt.id)\n }\n }, this.publishTimeout)\n this.openEventPublishes.set(evt.id, { resolve, reject, timeout })\n this.send('[\"AUTH\",' + JSON.stringify(evt) + ']')\n } catch (err) {\n console.warn('subscribe auth function failed:', err)\n }\n })\n return this.authPromise\n }\n\n public async publish(event: Event): Promise<string> {\n this.idleSince = undefined\n this.ongoingOperations++\n\n const ret = new Promise<string>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const ep = this.openEventPublishes.get(event.id) as EventPublishResolver\n if (ep) {\n ep.reject(new Error('publish timed out'))\n this.openEventPublishes.delete(event.id)\n }\n }, this.publishTimeout)\n this.openEventPublishes.set(event.id, { resolve, reject, timeout })\n })\n this.send('[\"EVENT\",' + JSON.stringify(event) + ']')\n\n // compute idleness state\n this.ongoingOperations--\n if (this.ongoingOperations === 0) this.idleSince = Date.now()\n\n return ret\n }\n\n public async count(filters: Filter[], params: { id?: string | null }): Promise<number> {\n this.serial++\n const id = params?.id || 'count:' + this.serial\n const ret = new Promise<number>((resolve, reject) => {\n this.openCountRequests.set(id, { resolve, reject })\n })\n this.send('[\"COUNT\",\"' + id + '\",' + JSON.stringify(filters).substring(1))\n return ret\n }\n\n public subscribe(\n filters: Filter[],\n params: Partial<SubscriptionParams> & { label?: string; id?: string },\n ): Subscription {\n if (params.label !== '<forced-ping>') {\n this.idleSince = undefined\n this.ongoingOperations++\n }\n\n const sub = this.prepareSubscription(filters, params)\n sub.fire()\n\n if (params.abort) {\n params.abort.onabort = () => sub.close(String(params.abort!.reason || '<aborted>'))\n }\n\n return sub\n }\n\n public prepareSubscription(\n filters: Filter[],\n params: Partial<SubscriptionParams> & { label?: string; id?: string },\n ): Subscription {\n this.serial++\n const id = params.id || (params.label ? params.label + ':' : 'sub:') + this.serial\n const sub = new Subscription(this, id, filters, params)\n this.openSubs.set(id, sub)\n return sub\n }\n\n public close() {\n this.skipReconnection = true\n if (this.reconnectTimeoutHandle) {\n clearTimeout(this.reconnectTimeoutHandle)\n this.reconnectTimeoutHandle = undefined\n }\n if (this.pingIntervalHandle) {\n clearInterval(this.pingIntervalHandle)\n this.pingIntervalHandle = undefined\n }\n this.closeAllSubscriptions('relay connection closed by us')\n this._connected = false\n this.idleSince = undefined\n this.onclose?.()\n if (this.ws?.readyState === this._WebSocket.OPEN) {\n this.ws?.close()\n }\n }\n\n // this is the function assigned to this.ws.onmessage\n // it's exposed for testing and debugging purposes\n public _onmessage(ev: MessageEvent<any>): void {\n const json = ev.data\n if (!json) {\n return\n }\n\n // shortcut EVENT sub\n const subid = getSubscriptionId(json)\n if (subid) {\n const so = this.openSubs.get(subid as string)\n if (!so) {\n // this is an EVENT message, but for a subscription we don't have, so just stop here\n return\n }\n\n // this will be called only when this message is a EVENT message for a subscription we have\n // we do this before parsing the JSON to not have to do that for duplicate events\n // since JSON parsing is slow\n const id = getHex64(json, 'id')\n const alreadyHave = so.alreadyHaveEvent?.(id)\n\n // notify any interested client that the relay has this event\n // (do this after alreadyHaveEvent() because the client may rely on this to answer that)\n so.receivedEvent?.(this, id)\n\n if (alreadyHave) {\n // if we had already seen this event we can just stop here\n return\n }\n }\n\n try {\n let data = JSON.parse(json)\n // we won't do any checks against the data since all failures (i.e. invalid messages from relays)\n // will naturally be caught by the encompassing try..catch block\n\n switch (data[0]) {\n case 'EVENT': {\n const so = this.openSubs.get(data[1] as string) as Subscription\n const event = data[2] as NostrEvent\n if (this.verifyEvent(event) && matchFilters(so.filters, event)) {\n so.onevent(event)\n } else {\n so.oninvalidevent?.(event)\n }\n if (!so.lastEmitted || so.lastEmitted < event.created_at) so.lastEmitted = event.created_at\n return\n }\n case 'COUNT': {\n const id: string = data[1]\n const payload = data[2] as { count: number }\n const cr = this.openCountRequests.get(id) as CountResolver\n if (cr) {\n cr.resolve(payload.count)\n this.openCountRequests.delete(id)\n }\n return\n }\n case 'EOSE': {\n const so = this.openSubs.get(data[1] as string)\n if (!so) return\n so.receivedEose()\n return\n }\n case 'OK': {\n const id: string = data[1]\n const ok: boolean = data[2]\n const reason: string = data[3]\n const ep = this.openEventPublishes.get(id) as EventPublishResolver\n if (ep) {\n clearTimeout(ep.timeout)\n if (ok) ep.resolve(reason)\n else ep.reject(new Error(reason))\n this.openEventPublishes.delete(id)\n }\n return\n }\n case 'CLOSED': {\n const id: string = data[1]\n const so = this.openSubs.get(id)\n if (!so) return\n so.closed = true\n so.close(data[2] as string)\n return\n }\n case 'NOTICE': {\n this.onnotice(data[1] as string)\n return\n }\n case 'AUTH': {\n this.challenge = data[1] as string\n if (this.onauth) {\n this.auth(this.onauth).catch(err => {\n // If the connection closed before auth could be sent, just ignore it.\n // This is a race condition when relays close connections quickly\n // (e.g., WoT-enforced relays that reject unknown pubkeys).\n if (!(err instanceof SendingOnClosedConnection)) {\n throw err // re-throw other errors\n }\n })\n }\n return\n }\n default: {\n const so = this.openSubs.get(data[1])\n so?.oncustom?.(data)\n return\n }\n }\n } catch (err) {\n try {\n const [_, __, event] = JSON.parse(json)\n console.warn(`[nostr] relay ${this.url} error processing message:`, err, event)\n } catch (_) {\n console.warn(`[nostr] relay ${this.url} error processing message:`, err)\n }\n return\n }\n }\n}\n\nexport class Subscription {\n public readonly relay: AbstractRelay\n public readonly id: string\n\n public lastEmitted: number | undefined\n public closed: boolean = false\n public eosed: boolean = false\n public filters: Filter[]\n public alreadyHaveEvent: ((id: string) => boolean) | undefined\n public receivedEvent: ((relay: AbstractRelay, id: string) => void) | undefined\n\n public onevent: (evt: Event) => void\n public oninvalidevent: ((evt: unknown) => void) | undefined\n public oneose: (() => void) | undefined\n public onclose: ((reason: string) => void) | undefined\n\n // will get any messages that have this subscription id as their second item and are not default standard\n public oncustom: ((msg: string[]) => void) | undefined\n\n public eoseTimeout: number\n private eoseTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n constructor(relay: AbstractRelay, id: string, filters: Filter[], params: SubscriptionParams) {\n if (filters.length === 0) throw new Error(\"subscription can't be created with zero filters\")\n\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\n this.oneose = params.oneose\n this.onclose = params.onclose\n this.oninvalidevent = params.oninvalidevent\n this.onevent =\n params.onevent ||\n (event => {\n console.warn(\n `onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`,\n event,\n )\n })\n }\n\n public fire() {\n this.relay.send('[\"REQ\",\"' + this.id + '\",' + JSON.stringify(this.filters).substring(1))\n\n // only now we start counting the eoseTimeout\n this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout)\n }\n\n public receivedEose() {\n if (this.eosed) return\n clearTimeout(this.eoseTimeoutHandle)\n this.eosed = true\n this.oneose?.()\n }\n\n public close(reason: string = 'closed by caller') {\n if (!this.closed && this.relay.connected) {\n // if the connection was closed by the user calling .close() we will send a CLOSE message\n // otherwise this._open will be already set to false so we will skip this\n try {\n this.relay.send('[\"CLOSE\",' + JSON.stringify(this.id) + ']')\n } catch (err) {\n if (err instanceof SendingOnClosedConnection) {\n /* doesn't matter, it's ok */\n } else {\n throw err\n }\n }\n this.closed = true\n }\n this.relay.openSubs.delete(this.id)\n\n // compute idleness state\n this.relay.ongoingOperations--\n if (this.relay.ongoingOperations === 0) this.relay.idleSince = Date.now()\n\n this.onclose?.(reason)\n }\n}\n\nexport type SubscriptionParams = {\n onevent?: (evt: Event) => void\n oninvalidevent?: (evt: unknown) => void\n oneose?: () => void\n onclose?: (reason: string) => void\n alreadyHaveEvent?: (id: string) => boolean\n receivedEvent?: (relay: AbstractRelay, id: string) => void\n eoseTimeout?: number\n abort?: AbortSignal\n}\n\nexport type CountResolver = {\n resolve: (count: number) => void\n reject: (err: Error) => void\n}\n\nexport type EventPublishResolver = {\n resolve: (reason: string) => void\n reject: (err: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n", "import { verifiedSymbol, type Event, type Nostr, VerifiedEvent } from './core.ts'\n\nexport const alwaysTrue: Nostr['verifyEvent'] = (t: Event): t is VerifiedEvent => {\n t[verifiedSymbol] = true\n return true\n}\n", "/* global WebSocket */\n\nimport {\n AbstractRelay as AbstractRelay,\n SubscriptionParams,\n Subscription,\n type AbstractRelayConstructorOptions,\n} from './abstract-relay.ts'\nimport { normalizeURL } from './utils.ts'\n\nimport type { Event, EventTemplate, Nostr, VerifiedEvent } from './core.ts'\nimport { type Filter } from './filter.ts'\nimport { alwaysTrue } from './helpers.ts'\nimport { Relay } from './relay.ts'\n\nexport type SubCloser = { close: (reason?: string) => void }\n\nexport type AbstractPoolConstructorOptions = AbstractRelayConstructorOptions & {\n // automaticallyAuth takes a relay URL and should return null in case that relay shouldn't be authenticated against\n // or a function to sign the AUTH event template otherwise (that function may still throw in case of failure)\n automaticallyAuth?: (relayURL: string) => null | ((event: EventTemplate) => Promise<VerifiedEvent>)\n // onRelayConnectionFailure is called with the URL of a relay that failed the initial connection\n onRelayConnectionFailure?: (url: string) => void\n // onRelayConnectionSuccess is called with the URL of a relay that succeeds the initial connection\n onRelayConnectionSuccess?: (url: string) => void\n // allowConnectingToRelay takes a relay URL and the operation being performed\n // return false to skip connecting to that relay\n allowConnectingToRelay?: (url: string, operation: ['read', Filter[]] | ['write', Event]) => boolean\n // maxWaitForConnection takes a number in milliseconds that will be given to ensureRelay such that we\n // don't get stuck forever when attempting to connect to a relay, it is 3000 (3 seconds) by default\n maxWaitForConnection: number\n}\n\nexport type SubscribeManyParams = Omit<SubscriptionParams, 'onclose'> & {\n maxWait?: number\n abort?: AbortSignal\n onclose?: (reasons: string[]) => void\n onauth?: (event: EventTemplate) => Promise<VerifiedEvent>\n id?: string\n label?: string\n}\n\nexport class AbstractSimplePool {\n protected relays: Map<string, AbstractRelay> = new Map()\n public seenOn: Map<string, Set<AbstractRelay>> = new Map()\n public trackRelays: boolean = false\n\n public verifyEvent: Nostr['verifyEvent']\n public enablePing: boolean | undefined\n public enableReconnect: boolean\n public automaticallyAuth?: (relayURL: string) => null | ((event: EventTemplate) => Promise<VerifiedEvent>)\n public trustedRelayURLs: Set<string> = new Set()\n public onRelayConnectionFailure?: (url: string) => void\n public onRelayConnectionSuccess?: (url: string) => void\n public allowConnectingToRelay?: (url: string, operation: ['read', Filter[]] | ['write', Event]) => boolean\n public maxWaitForConnection: number\n\n private _WebSocket?: typeof WebSocket\n\n constructor(opts: AbstractPoolConstructorOptions) {\n this.verifyEvent = opts.verifyEvent\n this._WebSocket = opts.websocketImplementation\n this.enablePing = opts.enablePing\n this.enableReconnect = opts.enableReconnect || false\n this.automaticallyAuth = opts.automaticallyAuth\n this.onRelayConnectionFailure = opts.onRelayConnectionFailure\n this.onRelayConnectionSuccess = opts.onRelayConnectionSuccess\n this.allowConnectingToRelay = opts.allowConnectingToRelay\n this.maxWaitForConnection = opts.maxWaitForConnection || 3000\n }\n\n async ensureRelay(\n url: string,\n params?: {\n connectionTimeout?: number\n abort?: AbortSignal\n },\n ): Promise<AbstractRelay> {\n url = normalizeURL(url)\n\n let relay = this.relays.get(url)\n if (!relay) {\n relay = new AbstractRelay(url, {\n verifyEvent: this.trustedRelayURLs.has(url) ? alwaysTrue : this.verifyEvent,\n websocketImplementation: this._WebSocket,\n enablePing: this.enablePing,\n enableReconnect: this.enableReconnect,\n })\n relay.onclose = () => {\n this.relays.delete(url)\n }\n this.relays.set(url, relay)\n }\n\n if (this.automaticallyAuth) {\n const authSignerFn = this.automaticallyAuth(url)\n if (authSignerFn) {\n relay.onauth = authSignerFn\n }\n }\n\n try {\n await relay.connect({\n timeout: params?.connectionTimeout,\n abort: params?.abort,\n })\n } catch (err) {\n this.relays.delete(url)\n throw err\n }\n\n return relay\n }\n\n close(relays: string[]) {\n relays.map(normalizeURL).forEach(url => {\n this.relays.get(url)?.close()\n this.relays.delete(url)\n })\n }\n\n subscribe(relays: string[], filter: Filter, params: SubscribeManyParams): SubCloser {\n const request: { url: string; filter: Filter }[] = []\n const uniqUrls: string[] = []\n for (let i = 0; i < relays.length; i++) {\n const url = normalizeURL(relays[i])\n if (!request.find(r => r.url === url)) {\n if (uniqUrls.indexOf(url) === -1) {\n uniqUrls.push(url)\n request.push({ url, filter: filter })\n }\n }\n }\n\n return this.subscribeMap(request, params)\n }\n\n subscribeMany(relays: string[], filter: Filter, params: SubscribeManyParams): SubCloser {\n return this.subscribe(relays, filter, params)\n }\n\n subscribeMap(requests: { url: string; filter: Filter }[], params: SubscribeManyParams): SubCloser {\n const grouped = new Map<string, Filter[]>()\n for (const req of requests) {\n const { url, filter } = req\n if (!grouped.has(url)) grouped.set(url, [])\n grouped.get(url)!.push(filter)\n }\n const groupedRequests = Array.from(grouped.entries()).map(([url, filters]) => ({ url, filters }))\n\n if (this.trackRelays) {\n params.receivedEvent = (relay: AbstractRelay, id: string) => {\n let set = this.seenOn.get(id)\n if (!set) {\n set = new Set()\n this.seenOn.set(id, set)\n }\n set.add(relay)\n }\n }\n\n const _knownIds = new Set<string>()\n const subs: Subscription[] = []\n\n // batch all EOSEs into a single\n const eosesReceived: boolean[] = []\n let handleEose = (i: number) => {\n if (eosesReceived[i]) return // do not act twice for the same relay\n eosesReceived[i] = true\n if (eosesReceived.filter(a => a).length === groupedRequests.length) {\n params.oneose?.()\n handleEose = () => {}\n }\n }\n // batch all closes into a single\n const closesReceived: string[] = []\n let handleClose = (i: number, reason: string) => {\n if (closesReceived[i]) return // do not act twice for the same relay\n handleEose(i)\n closesReceived[i] = reason\n if (closesReceived.filter(a => a).length === groupedRequests.length) {\n params.onclose?.(closesReceived)\n handleClose = () => {}\n }\n }\n\n const localAlreadyHaveEventHandler = (id: string) => {\n if (params.alreadyHaveEvent?.(id)) {\n return true\n }\n const have = _knownIds.has(id)\n _knownIds.add(id)\n return have\n }\n\n // open a subscription in all given relays\n const allOpened = Promise.all(\n groupedRequests.map(async ({ url, filters }, i) => {\n if (this.allowConnectingToRelay?.(url, ['read', filters]) === false) {\n handleClose(i, 'connection skipped by allowConnectingToRelay')\n return\n }\n\n let relay: AbstractRelay\n try {\n relay = await this.ensureRelay(url, {\n connectionTimeout:\n this.maxWaitForConnection < (params.maxWait || 0)\n ? Math.max(params.maxWait! * 0.8, params.maxWait! - 1000)\n : this.maxWaitForConnection,\n abort: params.abort,\n })\n } catch (err) {\n this.onRelayConnectionFailure?.(url)\n handleClose(i, (err as any)?.message || String(err))\n return\n }\n\n this.onRelayConnectionSuccess?.(url)\n\n let subscription = relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i),\n onclose: reason => {\n if (reason.startsWith('auth-required: ') && params.onauth) {\n relay\n .auth(params.onauth)\n .then(() => {\n relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i),\n onclose: reason => {\n handleClose(i, reason) // the second time we won't try to auth anymore\n },\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait,\n abort: params.abort,\n })\n })\n .catch(err => {\n handleClose(i, `auth was required and attempted, but failed with: ${err}`)\n })\n } else {\n handleClose(i, reason)\n }\n },\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait,\n abort: params.abort,\n })\n\n subs.push(subscription)\n }),\n )\n\n return {\n async close(reason?: string) {\n await allOpened\n subs.forEach(sub => {\n sub.close(reason)\n })\n },\n }\n }\n\n subscribeEose(\n relays: string[],\n filter: Filter,\n params: Pick<SubscribeManyParams, 'label' | 'id' | 'onevent' | 'oninvalidevent' | 'onclose' | 'maxWait' | 'onauth'>,\n ): SubCloser {\n let subcloser: SubCloser\n subcloser = this.subscribe(relays, filter, {\n ...params,\n oneose() {\n const reason = 'closed automatically on eose'\n if (subcloser) subcloser.close(reason)\n else params.onclose?.(relays.map(_ => reason))\n },\n })\n return subcloser\n }\n\n subscribeManyEose(\n relays: string[],\n filter: Filter,\n params: Pick<SubscribeManyParams, 'label' | 'id' | 'onevent' | 'oninvalidevent' | 'onclose' | 'maxWait' | 'onauth'>,\n ): SubCloser {\n return this.subscribeEose(relays, filter, params)\n }\n\n async querySync(\n relays: string[],\n filter: Filter,\n params?: Pick<SubscribeManyParams, 'label' | 'id' | 'maxWait'>,\n ): Promise<Event[]> {\n return new Promise(async resolve => {\n const events: Event[] = []\n this.subscribeEose(relays, filter, {\n ...params,\n onevent(event: Event) {\n events.push(event)\n },\n onclose(_: string[]) {\n resolve(events)\n },\n })\n })\n }\n\n async get(\n relays: string[],\n filter: Filter,\n params?: Pick<SubscribeManyParams, 'label' | 'id' | 'maxWait'>,\n ): Promise<Event | null> {\n filter.limit = 1\n const events = await this.querySync(relays, filter, params)\n events.sort((a, b) => b.created_at - a.created_at)\n return events[0] || null\n }\n\n publish(\n relays: string[],\n event: Event,\n params?: {\n onauth?: (evt: EventTemplate) => Promise<VerifiedEvent>\n maxWait?: number\n abort?: AbortSignal\n },\n ): Promise<string>[] {\n return relays.map(normalizeURL).map(async (url, i, arr) => {\n if (arr.indexOf(url) !== i) {\n // duplicate\n return Promise.reject('duplicate url')\n }\n\n if (this.allowConnectingToRelay?.(url, ['write', event]) === false) {\n return Promise.reject('connection skipped by allowConnectingToRelay')\n }\n\n let r: Relay\n try {\n r = await this.ensureRelay(url, {\n connectionTimeout:\n this.maxWaitForConnection < (params?.maxWait || 0)\n ? Math.max(params!.maxWait! * 0.8, params!.maxWait! - 1000)\n : this.maxWaitForConnection,\n abort: params?.abort,\n })\n } catch (err) {\n this.onRelayConnectionFailure?.(url)\n return String('connection failure: ' + String(err))\n }\n\n return r\n .publish(event)\n .catch(async err => {\n if (err instanceof Error && err.message.startsWith('auth-required: ') && params?.onauth) {\n await r.auth(params.onauth)\n return r.publish(event) // retry\n }\n throw err\n })\n .then(reason => {\n if (this.trackRelays) {\n let set = this.seenOn.get(event.id)\n if (!set) {\n set = new Set()\n this.seenOn.set(event.id, set)\n }\n set.add(r)\n }\n return reason\n })\n })\n }\n\n listConnectionStatus(): Map<string, boolean> {\n const map = new Map<string, boolean>()\n this.relays.forEach((relay, url) => map.set(url, relay.connected))\n\n return map\n }\n\n destroy(): void {\n this.relays.forEach(conn => conn.close())\n this.relays = new Map()\n }\n\n pruneIdleRelays(idleThresholdMs: number = 10000): string[] {\n const prunedUrls: string[] = []\n\n // check each relay's idle status and prune if over threshold\n for (const [url, relay] of this.relays) {\n if (relay.idleSince && Date.now() - relay.idleSince >= idleThresholdMs) {\n this.relays.delete(url)\n prunedUrls.push(url)\n relay.close()\n }\n }\n\n return prunedUrls\n }\n}\n", "/* global WebSocket */\n\nimport { verifyEvent } from './pure.ts'\nimport { AbstractSimplePool, type AbstractPoolConstructorOptions } from './abstract-pool.ts'\n\nvar _WebSocket: typeof WebSocket\n\ntry {\n _WebSocket = WebSocket\n} catch {}\n\nexport function useWebSocketImplementation(websocketImplementation: any) {\n _WebSocket = websocketImplementation\n}\n\nexport class SimplePool extends AbstractSimplePool {\n constructor(options?: Pick<AbstractPoolConstructorOptions, 'enablePing' | 'enableReconnect'>) {\n super({ verifyEvent, websocketImplementation: _WebSocket, maxWaitForConnection: 3000, ...options })\n }\n}\n\nexport * from './abstract-pool.ts'\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_utils", "i", "import_utils", "import_secp256k1", "import_sha2", "hkdf_extract", "hkdf_expand", "i", "i", "reason", "_fetch", "resolve", "i"]
|
|
7
7
|
}
|