nostr-tools 2.3.0 → 2.3.2

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.
Files changed (89) hide show
  1. package/README.md +5 -1
  2. package/lib/cjs/abstract-pool.js +9 -6
  3. package/lib/cjs/abstract-pool.js.map +2 -2
  4. package/lib/cjs/abstract-relay.js +9 -6
  5. package/lib/cjs/abstract-relay.js.map +2 -2
  6. package/lib/cjs/filter.js.map +2 -2
  7. package/lib/cjs/index.js +60 -53
  8. package/lib/cjs/index.js.map +3 -3
  9. package/lib/cjs/kinds.js.map +2 -2
  10. package/lib/cjs/nip04.js.map +2 -2
  11. package/lib/cjs/nip11.js.map +2 -2
  12. package/lib/cjs/nip13.js.map +2 -2
  13. package/lib/cjs/nip18.js.map +2 -2
  14. package/lib/cjs/nip19.js.map +2 -2
  15. package/lib/cjs/nip21.js.map +2 -2
  16. package/lib/cjs/nip25.js.map +2 -2
  17. package/lib/cjs/nip27.js.map +2 -2
  18. package/lib/cjs/nip28.js.map +2 -2
  19. package/lib/cjs/nip29.js.map +2 -2
  20. package/lib/cjs/nip30.js.map +2 -2
  21. package/lib/cjs/nip42.js.map +1 -1
  22. package/lib/cjs/nip44.js +51 -47
  23. package/lib/cjs/nip44.js.map +2 -2
  24. package/lib/cjs/nip46.js +20 -9
  25. package/lib/cjs/nip46.js.map +3 -3
  26. package/lib/cjs/nip47.js.map +2 -2
  27. package/lib/cjs/nip57.js.map +2 -2
  28. package/lib/cjs/nip75.js.map +1 -1
  29. package/lib/cjs/nip94.js.map +1 -1
  30. package/lib/cjs/nip96.js +3 -5
  31. package/lib/cjs/nip96.js.map +2 -2
  32. package/lib/cjs/nip98.js.map +2 -2
  33. package/lib/cjs/nip99.js.map +1 -1
  34. package/lib/cjs/pool.js +9 -6
  35. package/lib/cjs/pool.js.map +2 -2
  36. package/lib/cjs/pure.js.map +2 -2
  37. package/lib/cjs/references.js.map +2 -2
  38. package/lib/cjs/relay.js +9 -6
  39. package/lib/cjs/relay.js.map +2 -2
  40. package/lib/cjs/utils.js.map +2 -2
  41. package/lib/esm/abstract-pool.js +9 -6
  42. package/lib/esm/abstract-pool.js.map +2 -2
  43. package/lib/esm/abstract-relay.js +9 -6
  44. package/lib/esm/abstract-relay.js.map +2 -2
  45. package/lib/esm/filter.js.map +2 -2
  46. package/lib/esm/index.js +60 -53
  47. package/lib/esm/index.js.map +3 -3
  48. package/lib/esm/kinds.js.map +2 -2
  49. package/lib/esm/nip04.js.map +2 -2
  50. package/lib/esm/nip11.js.map +2 -2
  51. package/lib/esm/nip13.js.map +2 -2
  52. package/lib/esm/nip18.js.map +2 -2
  53. package/lib/esm/nip19.js.map +2 -2
  54. package/lib/esm/nip21.js.map +2 -2
  55. package/lib/esm/nip25.js.map +2 -2
  56. package/lib/esm/nip27.js.map +2 -2
  57. package/lib/esm/nip28.js.map +2 -2
  58. package/lib/esm/nip29.js.map +2 -2
  59. package/lib/esm/nip30.js.map +2 -2
  60. package/lib/esm/nip42.js.map +1 -1
  61. package/lib/esm/nip44.js +53 -47
  62. package/lib/esm/nip44.js.map +2 -2
  63. package/lib/esm/nip46.js +20 -9
  64. package/lib/esm/nip46.js.map +3 -3
  65. package/lib/esm/nip47.js.map +2 -2
  66. package/lib/esm/nip57.js.map +2 -2
  67. package/lib/esm/nip75.js.map +1 -1
  68. package/lib/esm/nip94.js.map +1 -1
  69. package/lib/esm/nip96.js +5 -5
  70. package/lib/esm/nip96.js.map +3 -3
  71. package/lib/esm/nip98.js.map +2 -2
  72. package/lib/esm/nip99.js.map +1 -1
  73. package/lib/esm/pool.js +9 -6
  74. package/lib/esm/pool.js.map +2 -2
  75. package/lib/esm/pure.js.map +2 -2
  76. package/lib/esm/references.js.map +2 -2
  77. package/lib/esm/relay.js +9 -6
  78. package/lib/esm/relay.js.map +2 -2
  79. package/lib/esm/utils.js.map +2 -2
  80. package/lib/nostr.bundle.js +60 -53
  81. package/lib/nostr.bundle.js.map +3 -3
  82. package/lib/types/abstract-relay.d.ts +1 -0
  83. package/lib/types/nip44.d.ts +27 -53
  84. package/lib/types/nip46.d.ts +2 -1
  85. package/lib/types/nip47.d.ts +6 -3
  86. package/lib/types/nip96.d.ts +2 -0
  87. package/lib/types/test-helpers.d.ts +0 -1
  88. package/lib/types/utils.d.ts +1 -0
  89. package/package.json +1 -1
package/lib/esm/nip46.js CHANGED
@@ -353,16 +353,19 @@ var AbstractRelay = class {
353
353
  this.ws.onerror = (ev) => {
354
354
  reject(ev.message);
355
355
  if (this._connected) {
356
+ this._connected = false;
357
+ this.connectionPromise = void 0;
356
358
  this.onclose?.();
357
359
  this.closeAllSubscriptions("relay connection errored");
358
- this._connected = false;
359
360
  }
360
361
  };
361
362
  this.ws.onclose = async () => {
362
- this.connectionPromise = void 0;
363
- this.onclose?.();
364
- this.closeAllSubscriptions("relay connection closed");
365
- this._connected = false;
363
+ if (this._connected) {
364
+ this._connected = false;
365
+ this.connectionPromise = void 0;
366
+ this.onclose?.();
367
+ this.closeAllSubscriptions("relay connection closed");
368
+ }
366
369
  };
367
370
  this.ws.onmessage = this._onmessage.bind(this);
368
371
  });
@@ -555,7 +558,7 @@ var Subscription = class {
555
558
  this.oneose?.();
556
559
  }
557
560
  close(reason = "closed by caller") {
558
- if (!this.closed) {
561
+ if (!this.closed && this.relay.connected) {
559
562
  this.relay.send('["CLOSE",' + JSON.stringify(this.id) + "]");
560
563
  this.closed = true;
561
564
  }
@@ -788,7 +791,7 @@ var BunkerSigner = class {
788
791
  async onevent(event) {
789
792
  const { id, result, error } = JSON.parse(await decrypt(clientSecretKey, event.pubkey, event.content));
790
793
  if (result === "auth_url" && waitingForAuth[id]) {
791
- delete listeners[id];
794
+ delete waitingForAuth[id];
792
795
  if (params.onauth) {
793
796
  params.onauth(error);
794
797
  } else {
@@ -890,15 +893,22 @@ async function createAccount(bunker, params, username, domain, email) {
890
893
  await rpc.connect();
891
894
  return rpc;
892
895
  }
893
- async function fetchCustodialBunkers(pool, relays) {
896
+ var fetchCustodialBunkers = fetchBunkerProviders;
897
+ async function fetchBunkerProviders(pool, relays) {
894
898
  const events = await pool.querySync(relays, {
895
899
  kinds: [Handlerinformation],
896
900
  "#k": [NostrConnect.toString()]
897
901
  });
902
+ events.sort((a, b) => b.created_at - a.created_at);
898
903
  const validatedBunkers = await Promise.all(
899
- events.map(async (event) => {
904
+ events.map(async (event, i2) => {
900
905
  try {
901
906
  const content = JSON.parse(event.content);
907
+ try {
908
+ if (events.findIndex((ev) => JSON.parse(ev.content).nip05 === content.nip05) !== i2)
909
+ return void 0;
910
+ } catch (err) {
911
+ }
902
912
  const bp = await queryBunkerProfile(content.nip05);
903
913
  if (bp && bp.pubkey === event.pubkey && bp.relays.length) {
904
914
  return {
@@ -923,6 +933,7 @@ export {
923
933
  BUNKER_REGEX,
924
934
  BunkerSigner,
925
935
  createAccount,
936
+ fetchBunkerProviders,
926
937
  fetchCustodialBunkers,
927
938
  parseBunkerInput,
928
939
  useFetchImplementation
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../pure.ts", "../../core.ts", "../../utils.ts", "../../nip04.ts", "../../nip05.ts", "../../kinds.ts", "../../filter.ts", "../../fakejson.ts", "../../nip42.ts", "../../helpers.ts", "../../abstract-relay.ts", "../../abstract-pool.ts", "../../pool.ts", "../../nip46.ts"],
4
- "sourcesContent": ["import { schnorr } from '@noble/curves/secp256k1'\nimport { bytesToHex } from '@noble/hashes/utils'\nimport { Nostr, Event, EventTemplate, UnsignedEvent, VerifiedEvent, verifiedSymbol, validateEvent } from './core.ts'\nimport { sha256 } from '@noble/hashes/sha256'\n\nimport { utf8Encoder } from './utils.ts'\n\nclass JS implements Nostr {\n generateSecretKey(): Uint8Array {\n return schnorr.utils.randomPrivateKey()\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(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 const hash = getEventHash(event)\n if (hash !== event.id) {\n event[verifiedSymbol] = false\n return false\n }\n\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey)\n event[verifiedSymbol] = valid\n return valid\n } catch (err) {\n event[verifiedSymbol] = false\n return false\n }\n }\n}\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 = 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 interface Event {\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 NostrEvent = Event\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] === 'object') return false\n }\n }\n\n return true\n}\n", "import type { Event } from './core.ts'\n\nexport const utf8Decoder = new TextDecoder('utf-8')\nexport const utf8Encoder = new TextEncoder()\n\nexport function normalizeURL(url: string): string {\n if (url.indexOf('://') === -1) url = 'wss://' + url\n let p = new URL(url)\n p.pathname = p.pathname.replace(/\\/+/g, '/')\n if (p.pathname.endsWith('/')) p.pathname = p.pathname.slice(0, -1)\n if ((p.port === '80' && p.protocol === 'ws:') || (p.port === '443' && p.protocol === 'wss:')) p.port = ''\n p.searchParams.sort()\n p.hash = ''\n return p.toString()\n}\n\nexport function insertEventIntoDescendingList(sortedArray: Event[], event: Event) {\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: Event[], event: Event) {\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 class QueueNode<V> {\n public value: V\n public next: QueueNode<V> | null = null\n public prev: QueueNode<V> | null = null\n\n constructor(message: V) {\n this.value = message\n }\n}\n\nexport class Queue<V> {\n public first: QueueNode<V> | null\n public last: QueueNode<V> | null\n\n constructor() {\n this.first = null\n this.last = null\n }\n\n enqueue(value: V): boolean {\n const newNode = new QueueNode(value)\n if (!this.last) {\n // list is empty\n this.first = newNode\n this.last = newNode\n } else if (this.last === this.first) {\n // list has a single element\n this.last = newNode\n this.last.prev = this.first\n this.first.next = newNode\n } else {\n // list has elements, add as last\n newNode.prev = this.last\n this.last.next = newNode\n this.last = newNode\n }\n return true\n }\n\n dequeue(): V | null {\n if (!this.first) return null\n\n if (this.first === this.last) {\n const target = this.first\n this.first = null\n this.last = null\n return target.value\n }\n\n const target = this.first\n this.first = target.next\n\n return target.value\n }\n}\n", "import { bytesToHex, randomBytes } from '@noble/hashes/utils'\nimport { secp256k1 } from '@noble/curves/secp256k1'\nimport { cbc } from '@noble/ciphers/aes'\nimport { base64 } from '@scure/base'\n\nimport { utf8Decoder, utf8Encoder } from './utils.ts'\n\nexport async function encrypt(secretKey: string | Uint8Array, pubkey: string, text: string): Promise<string> {\n const privkey: string = secretKey instanceof Uint8Array ? bytesToHex(secretKey) : secretKey\n const key = secp256k1.getSharedSecret(privkey, '02' + pubkey)\n const normalizedKey = getNormalizedX(key)\n\n let iv = Uint8Array.from(randomBytes(16))\n let plaintext = utf8Encoder.encode(text)\n\n let ciphertext = cbc(normalizedKey, iv).encrypt(plaintext)\n\n let ctb64 = base64.encode(new Uint8Array(ciphertext))\n let ivb64 = base64.encode(new Uint8Array(iv.buffer))\n\n return `${ctb64}?iv=${ivb64}`\n}\n\nexport async function decrypt(secretKey: string | Uint8Array, pubkey: string, data: string): Promise<string> {\n const privkey: string = secretKey instanceof Uint8Array ? bytesToHex(secretKey) : secretKey\n let [ctb64, ivb64] = data.split('?iv=')\n let key = secp256k1.getSharedSecret(privkey, '02' + pubkey)\n let normalizedKey = getNormalizedX(key)\n\n let iv = base64.decode(ivb64)\n let ciphertext = base64.decode(ctb64)\n\n let plaintext = cbc(normalizedKey, iv).decrypt(ciphertext)\n\n return utf8Decoder.decode(plaintext)\n}\n\nfunction getNormalizedX(key: Uint8Array): Uint8Array {\n return key.slice(1, 33)\n}\n", "import { ProfilePointer } from './nip19.ts'\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_-]+)+)$/\n\nvar _fetch: any\n\ntry {\n _fetch = fetch\n} catch {}\n\nexport function useFetchImplementation(fetchImplementation: any) {\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: 'error' })\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 (await _fetch(url, { redirect: 'error' })).json()\n\n let pubkey = res.names[name]\n return pubkey ? { pubkey, relays: res.relays?.[pubkey] } : null\n } catch (_e) {\n return null\n }\n}\n\nexport async function isValid(pubkey: string, nip05: string): Promise<boolean> {\n let res = await queryProfile(nip05)\n return res ? res.pubkey === pubkey : false\n}\n", "/** Events are **regular**, which means they're all expected to be stored by relays. */\nexport function isRegularKind(kind: number) {\n return (1000 <= kind && kind < 10000) || [1, 2, 4, 5, 6, 7, 8, 16, 40, 41, 42, 43, 44].includes(kind)\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) {\n return [0, 3].includes(kind) || (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) {\n return 20000 <= kind && kind < 30000\n}\n\n/** Events are **parameterized replaceable**, 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 isParameterizedReplaceableKind(kind: number) {\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 (isParameterizedReplaceableKind(kind)) return 'parameterized'\n return 'unknown'\n}\n\nexport const Metadata = 0\nexport const ShortTextNote = 1\nexport const RecommendRelay = 2\nexport const Contacts = 3\nexport const EncryptedDirectMessage = 4\nexport const EncryptedDirectMessages = 4\nexport const EventDeletion = 5\nexport const Repost = 6\nexport const Reaction = 7\nexport const BadgeAward = 8\nexport const GenericRepost = 16\nexport const ChannelCreation = 40\nexport const ChannelMetadata = 41\nexport const ChannelMessage = 42\nexport const ChannelHideMessage = 43\nexport const ChannelMuteUser = 44\nexport const OpenTimestamps = 1040\nexport const FileMetadata = 1063\nexport const LiveChatMessage = 1311\nexport const ProblemTracker = 1971\nexport const Report = 1984\nexport const Reporting = 1984\nexport const Label = 1985\nexport const CommunityPostApproval = 4550\nexport const JobRequest = 5999\nexport const JobResult = 6999\nexport const JobFeedback = 7000\nexport const ZapGoal = 9041\nexport const ZapRequest = 9734\nexport const Zap = 9735\nexport const Highlights = 9802\nexport const Mutelist = 10000\nexport const Pinlist = 10001\nexport const RelayList = 10002\nexport const BookmarkList = 10003\nexport const CommunitiesList = 10004\nexport const PublicChatsList = 10005\nexport const BlockedRelaysList = 10006\nexport const SearchRelaysList = 10007\nexport const InterestsList = 10015\nexport const UserEmojiList = 10030\nexport const FileServerPreference = 10096\nexport const NWCWalletInfo = 13194\nexport const LightningPubRPC = 21000\nexport const ClientAuth = 22242\nexport const NWCWalletRequest = 23194\nexport const NWCWalletResponse = 23195\nexport const NostrConnect = 24133\nexport const HTTPAuth = 27235\nexport const Followsets = 30000\nexport const Genericlists = 30001\nexport const Relaysets = 30002\nexport const Bookmarksets = 30003\nexport const Curationsets = 30004\nexport const ProfileBadges = 30008\nexport const BadgeDefinition = 30009\nexport const Interestsets = 30015\nexport const CreateOrUpdateStall = 30017\nexport const CreateOrUpdateProduct = 30018\nexport const LongFormArticle = 30023\nexport const DraftLong = 30024\nexport const Emojisets = 30030\nexport const Application = 30078\nexport const LiveEvent = 30311\nexport const UserStatuses = 30315\nexport const ClassifiedListing = 30402\nexport const DraftClassifiedListing = 30403\nexport const Date = 31922\nexport const Time = 31923\nexport const Calendar = 31924\nexport const CalendarEventRSVP = 31925\nexport const Handlerrecommendation = 31989\nexport const Handlerinformation = 31990\nexport const CommunityDefinition = 34550\n", "import { Event } from './core.ts'\nimport { 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 if (!filter.ids.some(prefix => event.id.startsWith(prefix))) {\n return false\n }\n }\n if (filter.kinds && filter.kinds.indexOf(event.kind) === -1) return false\n if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {\n if (!filter.authors.some(prefix => event.pubkey.startsWith(prefix))) {\n return false\n }\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)) return true\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/** Calculate the intrinsic limit of a filter. This function may return `Infinity`. */\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 return Math.min(\n Math.max(0, filter.limit ?? Infinity),\n filter.ids?.length ?? Infinity,\n filter.authors?.length && filter.kinds?.every(kind => isReplaceableKind(kind))\n ? filter.authors.length * filter.kinds.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", "import { verifiedSymbol, type Event, type Nostr, VerifiedEvent } from './core.ts'\n\nexport async function yieldThread() {\n return new Promise<void>(resolve => {\n const ch = new MessageChannel()\n const handler = () => {\n // @ts-ignore (typescript thinks this property should be called `removeListener`, but in fact it's `removeEventListener`)\n ch.port1.removeEventListener('message', handler)\n resolve()\n }\n // @ts-ignore (typescript thinks this property should be called `addListener`, but in fact it's `addEventListener`)\n ch.port1.addEventListener('message', handler)\n ch.port2.postMessage(0)\n ch.port1.start()\n })\n}\n\nexport const alwaysTrue: Nostr['verifyEvent'] = (t: Event): t is VerifiedEvent => {\n t[verifiedSymbol] = true\n return true\n}\n", "/* global WebSocket */\n\nimport type { Event, EventTemplate, VerifiedEvent, Nostr } from './core.ts'\nimport { matchFilters, type Filter } from './filter.ts'\nimport { getHex64, getSubscriptionId } from './fakejson.ts'\nimport { Queue, normalizeURL } from './utils.ts'\nimport { makeAuthEvent } from './nip42.ts'\nimport { yieldThread } from './helpers.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 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\n public baseEoseTimeout: number = 4400\n public connectionTimeout: number = 4400\n public openSubs = new Map<string, Subscription>()\n private connectionTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n private connectionPromise: Promise<void> | undefined\n private openCountRequests = new Map<string, CountResolver>()\n private openEventPublishes = new Map<string, EventPublishResolver>()\n private ws: WebSocket | undefined\n private incomingMessageQueue = new Queue<string>()\n private queueRunning = false\n private challenge: string | undefined\n private serial: number = 0\n private verifyEvent: Nostr['verifyEvent']\n\n constructor(url: string, opts: { verifyEvent: Nostr['verifyEvent'] }) {\n this.url = normalizeURL(url)\n this.verifyEvent = opts.verifyEvent\n }\n\n static async connect(url: string, opts: { verifyEvent: Nostr['verifyEvent'] }) {\n const relay = new AbstractRelay(url, opts)\n await relay.connect()\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 public async connect(): Promise<void> {\n if (this.connectionPromise) return this.connectionPromise\n\n this.challenge = undefined\n this.connectionPromise = new Promise((resolve, reject) => {\n this.connectionTimeoutHandle = setTimeout(() => {\n reject('connection timed out')\n this.connectionPromise = undefined\n this.onclose?.()\n this.closeAllSubscriptions('relay connection timed out')\n }, this.connectionTimeout)\n\n try {\n this.ws = new _WebSocket(this.url)\n } catch (err) {\n reject(err)\n return\n }\n\n this.ws.onopen = () => {\n clearTimeout(this.connectionTimeoutHandle)\n this._connected = true\n resolve()\n }\n\n this.ws.onerror = ev => {\n reject((ev as any).message)\n if (this._connected) {\n this.onclose?.()\n this.closeAllSubscriptions('relay connection errored')\n this._connected = false\n }\n }\n\n this.ws.onclose = async () => {\n this.connectionPromise = undefined\n this.onclose?.()\n this.closeAllSubscriptions('relay connection closed')\n this._connected = false\n }\n\n this.ws.onmessage = this._onmessage.bind(this)\n })\n\n return this.connectionPromise\n }\n\n private async runQueue() {\n this.queueRunning = true\n while (true) {\n if (false === this.handleNext()) {\n break\n }\n await yieldThread()\n }\n this.queueRunning = false\n }\n\n private handleNext(): undefined | false {\n const json = this.incomingMessageQueue.dequeue()\n if (!json) {\n return false\n }\n\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 Event\n if (this.verifyEvent(event) && matchFilters(so.filters, event)) {\n so.onevent(event)\n }\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 (ok) ep.resolve(reason)\n else ep.reject(new Error(reason))\n this.openEventPublishes.delete(id)\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 case 'AUTH': {\n this.challenge = data[1] as string\n return\n }\n }\n } catch (err) {\n return\n }\n }\n\n public async send(message: string) {\n if (!this.connectionPromise) throw new Error('sending on closed connection')\n\n this.connectionPromise.then(() => {\n this.ws?.send(message)\n })\n }\n\n public async auth(signAuthEvent: (evt: EventTemplate) => Promise<VerifiedEvent>) {\n if (!this.challenge) throw new Error(\"can't perform auth, no challenge was received\")\n const evt = await signAuthEvent(makeAuthEvent(this.url, this.challenge))\n const ret = new Promise<string>((resolve, reject) => {\n this.openEventPublishes.set(evt.id, { resolve, reject })\n })\n this.send('[\"AUTH\",' + JSON.stringify(evt) + ']')\n return ret\n }\n\n public async publish(event: Event): Promise<string> {\n const ret = new Promise<string>((resolve, reject) => {\n this.openEventPublishes.set(event.id, { resolve, reject })\n })\n this.send('[\"EVENT\",' + JSON.stringify(event) + ']')\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) + ']')\n return ret\n }\n\n public subscribe(filters: Filter[], params: Partial<SubscriptionParams>): Subscription {\n const subscription = this.prepareSubscription(filters, params)\n subscription.fire()\n return subscription\n }\n\n public prepareSubscription(filters: Filter[], params: Partial<SubscriptionParams> & { id?: string }): Subscription {\n this.serial++\n const id = params.id || 'sub:' + this.serial\n const subscription = new Subscription(this, id, filters, params)\n this.openSubs.set(id, subscription)\n return subscription\n }\n\n public close() {\n this.closeAllSubscriptions('relay connection closed by us')\n this._connected = false\n this.ws?.close()\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>) {\n this.incomingMessageQueue.enqueue(ev.data as string)\n if (!this.queueRunning) {\n this.runQueue()\n }\n }\n}\n\nexport class Subscription {\n public readonly relay: AbstractRelay\n public readonly id: string\n\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 oneose: (() => void) | undefined\n public onclose: ((reason: 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 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.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) {\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 this.relay.send('[\"CLOSE\",' + JSON.stringify(this.id) + ']')\n this.closed = true\n }\n this.relay.openSubs.delete(this.id)\n this.onclose?.(reason)\n }\n}\n\nexport type SubscriptionParams = {\n onevent?: (evt: Event) => 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}\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}\n", "import { AbstractRelay as AbstractRelay, SubscriptionParams, Subscription } from './abstract-relay.ts'\nimport { normalizeURL } from './utils.ts'\n\nimport type { Event, Nostr } from './core.ts'\nimport { type Filter } from './filter.ts'\nimport { alwaysTrue } from './helpers.ts'\n\nexport type SubCloser = { close: () => void }\n\nexport type SubscribeManyParams = Omit<SubscriptionParams, 'onclose' | 'id'> & {\n maxWait?: number\n onclose?: (reasons: string[]) => void\n id?: string\n}\n\nexport class AbstractSimplePool {\n private relays = new Map<string, AbstractRelay>()\n public seenOn = new Map<string, Set<AbstractRelay>>()\n public trackRelays: boolean = false\n\n public verifyEvent: Nostr['verifyEvent']\n public trustedRelayURLs = new Set<string>()\n\n constructor(opts: { verifyEvent: Nostr['verifyEvent'] }) {\n this.verifyEvent = opts.verifyEvent\n }\n\n async ensureRelay(url: string, params?: { connectionTimeout?: number }): 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 })\n if (params?.connectionTimeout) relay.connectionTimeout = params.connectionTimeout\n this.relays.set(url, relay)\n }\n await relay.connect()\n\n return relay\n }\n\n close(relays: string[]) {\n relays.map(normalizeURL).forEach(url => {\n this.relays.get(url)?.close()\n })\n }\n\n subscribeMany(relays: string[], filters: Filter[], params: SubscribeManyParams): SubCloser {\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 eosesReceived[i] = true\n if (eosesReceived.filter(a => a).length === relays.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 handleEose(i)\n closesReceived[i] = reason\n if (closesReceived.filter(a => a).length === relays.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 relays.map(normalizeURL).map(async (url, i, arr) => {\n if (arr.indexOf(url) !== i) {\n // duplicate\n handleClose(i, 'duplicate url')\n return\n }\n\n let relay: AbstractRelay\n try {\n relay = await this.ensureRelay(url, {\n connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1000) : undefined,\n })\n } catch (err) {\n handleClose(i, (err as any)?.message || String(err))\n return\n }\n\n let subscription = relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i),\n onclose: reason => handleClose(i, reason),\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait,\n })\n\n subs.push(subscription)\n }),\n )\n\n return {\n async close() {\n await allOpened\n subs.forEach(sub => {\n sub.close()\n })\n },\n }\n }\n\n subscribeManyEose(\n relays: string[],\n filters: Filter[],\n params: Pick<SubscribeManyParams, 'id' | 'onevent' | 'onclose' | 'maxWait'>,\n ): SubCloser {\n const subcloser = this.subscribeMany(relays, filters, {\n ...params,\n oneose() {\n subcloser.close()\n },\n })\n return subcloser\n }\n\n async querySync(\n relays: string[],\n filter: Filter,\n params?: Pick<SubscribeManyParams, 'id' | 'maxWait'>,\n ): Promise<Event[]> {\n return new Promise(async resolve => {\n const events: Event[] = []\n this.subscribeManyEose(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, '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(relays: string[], event: Event): 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 let r = await this.ensureRelay(url)\n return r.publish(event)\n })\n }\n}\n", "import { verifyEvent } from './pure.ts'\nimport { AbstractSimplePool } from './abstract-pool.ts'\n\nexport class SimplePool extends AbstractSimplePool {\n constructor() {\n super({ verifyEvent })\n }\n}\n\nexport * from './abstract-pool.ts'\n", "import { NostrEvent, UnsignedEvent, VerifiedEvent } from './core.ts'\nimport { generateSecretKey, finalizeEvent, getPublicKey, verifyEvent } from './pure.ts'\nimport { AbstractSimplePool, SubCloser } from './abstract-pool.ts'\nimport { decrypt, encrypt } from './nip04.ts'\nimport { NIP05_REGEX } from './nip05.ts'\nimport { SimplePool } from './pool.ts'\nimport { Handlerinformation, NostrConnect } from './kinds.ts'\nimport { hexToBytes } from '@noble/hashes/utils'\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\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\nasync 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 BunkerSignerParams = {\n pool?: AbstractSimplePool\n onauth?: (url: string) => void\n}\n\nexport class BunkerSigner {\n private pool: AbstractSimplePool\n private subCloser: SubCloser\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 public bp: BunkerPointer\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 public constructor(clientSecretKey: Uint8Array, bp: BunkerPointer, params: BunkerSignerParams = {}) {\n if (bp.relays.length === 0) {\n throw new Error('no relays are specified for this bunker')\n }\n\n this.pool = params.pool || new SimplePool()\n this.secretKey = clientSecretKey\n this.bp = bp\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 const listeners = this.listeners\n const waitingForAuth = this.waitingForAuth\n\n this.subCloser = this.pool.subscribeMany(\n this.bp.relays,\n [{ kinds: [NostrConnect], '#p': [getPublicKey(this.secretKey)] }],\n {\n async onevent(event: NostrEvent) {\n const { id, result, error } = JSON.parse(await decrypt(clientSecretKey, event.pubkey, event.content))\n\n if (result === 'auth_url' && waitingForAuth[id]) {\n delete listeners[id]\n\n if (params.onauth) {\n params.onauth(error)\n } else {\n console.warn(\n `nostr-tools/nip46: remote signer ${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 },\n )\n this.isOpen = true\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 this.serial++\n const id = `${this.idPrefix}-${this.serial}`\n\n const encryptedContent = await encrypt(this.secretKey, this.bp.pubkey, JSON.stringify({ id, method, params }))\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', [getPublicKey(this.secretKey), this.bp.secret || ''])\n }\n\n /**\n * This was supposed to call the \"get_public_key\" method on the bunker,\n * but instead we just returns the public key we already know.\n */\n async getPublicKey(): Promise<string> {\n return this.bp.pubkey\n }\n\n /**\n * Calls the \"get_relays\" method on the bunker.\n */\n async getRelays(): Promise<{ [relay: string]: { read: boolean; write: boolean } }> {\n return JSON.parse(await this.sendRequest('get_relays', []))\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: UnsignedEvent): Promise<VerifiedEvent> {\n let resp = await this.sendRequest('sign_event', [JSON.stringify(event)])\n let signed: NostrEvent = JSON.parse(resp)\n if (signed.pubkey === this.bp.pubkey && 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 nip44GetKey(thirdPartyPubkey: string): Promise<Uint8Array> {\n let resp = await this.sendRequest('nip44_get_key', [thirdPartyPubkey])\n return hexToBytes(resp)\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_encrypt', [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 * @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): Promise<BunkerSigner> {\n if (email && !EMAIL_REGEX.test(email)) throw new Error('Invalid email')\n\n let sk = generateSecretKey()\n let rpc = new BunkerSigner(sk, 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 fetchCustodialBunkers(pool: AbstractSimplePool, relays: string[]): Promise<BunkerProfile[]> {\n const events = await pool.querySync(relays, {\n kinds: [Handlerinformation],\n '#k': [NostrConnect.toString()],\n })\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 => {\n try {\n const content = JSON.parse(event.content)\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"],
5
- "mappings": "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",
6
- "names": ["i", "target", "bytesToHex", "bytesToHex", "i", "i", "_fetch"]
4
+ "sourcesContent": ["import { schnorr } from '@noble/curves/secp256k1'\nimport { bytesToHex } from '@noble/hashes/utils'\nimport { Nostr, Event, EventTemplate, UnsignedEvent, VerifiedEvent, verifiedSymbol, validateEvent } from './core.ts'\nimport { sha256 } from '@noble/hashes/sha256'\n\nimport { utf8Encoder } from './utils.ts'\n\nclass JS implements Nostr {\n generateSecretKey(): Uint8Array {\n return schnorr.utils.randomPrivateKey()\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(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 const hash = getEventHash(event)\n if (hash !== event.id) {\n event[verifiedSymbol] = false\n return false\n }\n\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey)\n event[verifiedSymbol] = valid\n return valid\n } catch (err) {\n event[verifiedSymbol] = false\n return false\n }\n }\n}\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 interface Event {\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 NostrEvent = Event\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] === 'object') return false\n }\n }\n\n return true\n}\n", "import type { Event } from './core.ts'\n\nexport const utf8Decoder: TextDecoder = new TextDecoder('utf-8')\nexport const utf8Encoder: TextEncoder = new TextEncoder()\n\nexport function normalizeURL(url: string): string {\n if (url.indexOf('://') === -1) url = 'wss://' + url\n let p = new URL(url)\n p.pathname = p.pathname.replace(/\\/+/g, '/')\n if (p.pathname.endsWith('/')) p.pathname = p.pathname.slice(0, -1)\n if ((p.port === '80' && p.protocol === 'ws:') || (p.port === '443' && p.protocol === 'wss:')) p.port = ''\n p.searchParams.sort()\n p.hash = ''\n return p.toString()\n}\n\nexport function insertEventIntoDescendingList(sortedArray: Event[], event: Event): Event[] {\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: Event[], event: Event): Event[] {\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 class QueueNode<V> {\n public value: V\n public next: QueueNode<V> | null = null\n public prev: QueueNode<V> | null = null\n\n constructor(message: V) {\n this.value = message\n }\n}\n\nexport class Queue<V> {\n public first: QueueNode<V> | null\n public last: QueueNode<V> | null\n\n constructor() {\n this.first = null\n this.last = null\n }\n\n enqueue(value: V): boolean {\n const newNode = new QueueNode(value)\n if (!this.last) {\n // list is empty\n this.first = newNode\n this.last = newNode\n } else if (this.last === this.first) {\n // list has a single element\n this.last = newNode\n this.last.prev = this.first\n this.first.next = newNode\n } else {\n // list has elements, add as last\n newNode.prev = this.last\n this.last.next = newNode\n this.last = newNode\n }\n return true\n }\n\n dequeue(): V | null {\n if (!this.first) return null\n\n if (this.first === this.last) {\n const target = this.first\n this.first = null\n this.last = null\n return target.value\n }\n\n const target = this.first\n this.first = target.next\n\n return target.value\n }\n}\n", "import { bytesToHex, randomBytes } from '@noble/hashes/utils'\nimport { secp256k1 } from '@noble/curves/secp256k1'\nimport { cbc } from '@noble/ciphers/aes'\nimport { base64 } from '@scure/base'\n\nimport { utf8Decoder, utf8Encoder } from './utils.ts'\n\nexport async function encrypt(secretKey: string | Uint8Array, pubkey: string, text: string): Promise<string> {\n const privkey: string = secretKey instanceof Uint8Array ? bytesToHex(secretKey) : secretKey\n const key = secp256k1.getSharedSecret(privkey, '02' + pubkey)\n const normalizedKey = getNormalizedX(key)\n\n let iv = Uint8Array.from(randomBytes(16))\n let plaintext = utf8Encoder.encode(text)\n\n let ciphertext = cbc(normalizedKey, iv).encrypt(plaintext)\n\n let ctb64 = base64.encode(new Uint8Array(ciphertext))\n let ivb64 = base64.encode(new Uint8Array(iv.buffer))\n\n return `${ctb64}?iv=${ivb64}`\n}\n\nexport async function decrypt(secretKey: string | Uint8Array, pubkey: string, data: string): Promise<string> {\n const privkey: string = secretKey instanceof Uint8Array ? bytesToHex(secretKey) : secretKey\n let [ctb64, ivb64] = data.split('?iv=')\n let key = secp256k1.getSharedSecret(privkey, '02' + pubkey)\n let normalizedKey = getNormalizedX(key)\n\n let iv = base64.decode(ivb64)\n let ciphertext = base64.decode(ctb64)\n\n let plaintext = cbc(normalizedKey, iv).decrypt(ciphertext)\n\n return utf8Decoder.decode(plaintext)\n}\n\nfunction getNormalizedX(key: Uint8Array): Uint8Array {\n return key.slice(1, 33)\n}\n", "import { ProfilePointer } from './nip19.ts'\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_-]+)+)$/\n\nvar _fetch: any\n\ntry {\n _fetch = fetch\n} catch {}\n\nexport function useFetchImplementation(fetchImplementation: any) {\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: 'error' })\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 (await _fetch(url, { redirect: 'error' })).json()\n\n let pubkey = res.names[name]\n return pubkey ? { pubkey, relays: res.relays?.[pubkey] } : null\n } catch (_e) {\n return null\n }\n}\n\nexport async function isValid(pubkey: string, nip05: string): Promise<boolean> {\n let res = await queryProfile(nip05)\n return res ? res.pubkey === pubkey : false\n}\n", "/** Events are **regular**, which means they're all expected to be stored by relays. */\nexport function isRegularKind(kind: number): boolean {\n return (1000 <= kind && kind < 10000) || [1, 2, 4, 5, 6, 7, 8, 16, 40, 41, 42, 43, 44].includes(kind)\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 [0, 3].includes(kind) || (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 **parameterized replaceable**, 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 isParameterizedReplaceableKind(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 (isParameterizedReplaceableKind(kind)) return 'parameterized'\n return 'unknown'\n}\n\nexport const Metadata = 0\nexport const ShortTextNote = 1\nexport const RecommendRelay = 2\nexport const Contacts = 3\nexport const EncryptedDirectMessage = 4\nexport const EncryptedDirectMessages = 4\nexport const EventDeletion = 5\nexport const Repost = 6\nexport const Reaction = 7\nexport const BadgeAward = 8\nexport const GenericRepost = 16\nexport const ChannelCreation = 40\nexport const ChannelMetadata = 41\nexport const ChannelMessage = 42\nexport const ChannelHideMessage = 43\nexport const ChannelMuteUser = 44\nexport const OpenTimestamps = 1040\nexport const FileMetadata = 1063\nexport const LiveChatMessage = 1311\nexport const ProblemTracker = 1971\nexport const Report = 1984\nexport const Reporting = 1984\nexport const Label = 1985\nexport const CommunityPostApproval = 4550\nexport const JobRequest = 5999\nexport const JobResult = 6999\nexport const JobFeedback = 7000\nexport const ZapGoal = 9041\nexport const ZapRequest = 9734\nexport const Zap = 9735\nexport const Highlights = 9802\nexport const Mutelist = 10000\nexport const Pinlist = 10001\nexport const RelayList = 10002\nexport const BookmarkList = 10003\nexport const CommunitiesList = 10004\nexport const PublicChatsList = 10005\nexport const BlockedRelaysList = 10006\nexport const SearchRelaysList = 10007\nexport const InterestsList = 10015\nexport const UserEmojiList = 10030\nexport const FileServerPreference = 10096\nexport const NWCWalletInfo = 13194\nexport const LightningPubRPC = 21000\nexport const ClientAuth = 22242\nexport const NWCWalletRequest = 23194\nexport const NWCWalletResponse = 23195\nexport const NostrConnect = 24133\nexport const HTTPAuth = 27235\nexport const Followsets = 30000\nexport const Genericlists = 30001\nexport const Relaysets = 30002\nexport const Bookmarksets = 30003\nexport const Curationsets = 30004\nexport const ProfileBadges = 30008\nexport const BadgeDefinition = 30009\nexport const Interestsets = 30015\nexport const CreateOrUpdateStall = 30017\nexport const CreateOrUpdateProduct = 30018\nexport const LongFormArticle = 30023\nexport const DraftLong = 30024\nexport const Emojisets = 30030\nexport const Application = 30078\nexport const LiveEvent = 30311\nexport const UserStatuses = 30315\nexport const ClassifiedListing = 30402\nexport const DraftClassifiedListing = 30403\nexport const Date = 31922\nexport const Time = 31923\nexport const Calendar = 31924\nexport const CalendarEventRSVP = 31925\nexport const Handlerrecommendation = 31989\nexport const Handlerinformation = 31990\nexport const CommunityDefinition = 34550\n", "import { Event } from './core.ts'\nimport { 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 if (!filter.ids.some(prefix => event.id.startsWith(prefix))) {\n return false\n }\n }\n if (filter.kinds && filter.kinds.indexOf(event.kind) === -1) return false\n if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {\n if (!filter.authors.some(prefix => event.pubkey.startsWith(prefix))) {\n return false\n }\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)) return true\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/** Calculate the intrinsic limit of a filter. This function may return `Infinity`. */\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 return Math.min(\n Math.max(0, filter.limit ?? Infinity),\n filter.ids?.length ?? Infinity,\n filter.authors?.length && filter.kinds?.every(kind => isReplaceableKind(kind))\n ? filter.authors.length * filter.kinds.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", "import { verifiedSymbol, type Event, type Nostr, VerifiedEvent } from './core.ts'\n\nexport async function yieldThread() {\n return new Promise<void>(resolve => {\n const ch = new MessageChannel()\n const handler = () => {\n // @ts-ignore (typescript thinks this property should be called `removeListener`, but in fact it's `removeEventListener`)\n ch.port1.removeEventListener('message', handler)\n resolve()\n }\n // @ts-ignore (typescript thinks this property should be called `addListener`, but in fact it's `addEventListener`)\n ch.port1.addEventListener('message', handler)\n ch.port2.postMessage(0)\n ch.port1.start()\n })\n}\n\nexport const alwaysTrue: Nostr['verifyEvent'] = (t: Event): t is VerifiedEvent => {\n t[verifiedSymbol] = true\n return true\n}\n", "/* global WebSocket */\n\nimport type { Event, EventTemplate, VerifiedEvent, Nostr } from './core.ts'\nimport { matchFilters, type Filter } from './filter.ts'\nimport { getHex64, getSubscriptionId } from './fakejson.ts'\nimport { Queue, normalizeURL } from './utils.ts'\nimport { makeAuthEvent } from './nip42.ts'\nimport { yieldThread } from './helpers.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 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\n public baseEoseTimeout: number = 4400\n public connectionTimeout: number = 4400\n public openSubs: Map<string, Subscription> = new Map()\n private connectionTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n private connectionPromise: Promise<void> | undefined\n private openCountRequests = new Map<string, CountResolver>()\n private openEventPublishes = new Map<string, EventPublishResolver>()\n private ws: WebSocket | undefined\n private incomingMessageQueue = new Queue<string>()\n private queueRunning = false\n private challenge: string | undefined\n private serial: number = 0\n private verifyEvent: Nostr['verifyEvent']\n\n constructor(url: string, opts: { verifyEvent: Nostr['verifyEvent'] }) {\n this.url = normalizeURL(url)\n this.verifyEvent = opts.verifyEvent\n }\n\n static async connect(url: string, opts: { verifyEvent: Nostr['verifyEvent'] }): Promise<AbstractRelay> {\n const relay = new AbstractRelay(url, opts)\n await relay.connect()\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 public async connect(): Promise<void> {\n if (this.connectionPromise) return this.connectionPromise\n\n this.challenge = undefined\n this.connectionPromise = new Promise((resolve, reject) => {\n this.connectionTimeoutHandle = setTimeout(() => {\n reject('connection timed out')\n this.connectionPromise = undefined\n this.onclose?.()\n this.closeAllSubscriptions('relay connection timed out')\n }, this.connectionTimeout)\n\n try {\n this.ws = new _WebSocket(this.url)\n } catch (err) {\n reject(err)\n return\n }\n\n this.ws.onopen = () => {\n clearTimeout(this.connectionTimeoutHandle)\n this._connected = true\n resolve()\n }\n\n this.ws.onerror = ev => {\n reject((ev as any).message)\n if (this._connected) {\n this._connected = false\n this.connectionPromise = undefined\n this.onclose?.()\n this.closeAllSubscriptions('relay connection errored')\n }\n }\n\n this.ws.onclose = async () => {\n if (this._connected) {\n this._connected = false\n this.connectionPromise = undefined\n this.onclose?.()\n this.closeAllSubscriptions('relay connection closed')\n }\n }\n\n this.ws.onmessage = this._onmessage.bind(this)\n })\n\n return this.connectionPromise\n }\n\n private async runQueue() {\n this.queueRunning = true\n while (true) {\n if (false === this.handleNext()) {\n break\n }\n await yieldThread()\n }\n this.queueRunning = false\n }\n\n private handleNext(): undefined | false {\n const json = this.incomingMessageQueue.dequeue()\n if (!json) {\n return false\n }\n\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 Event\n if (this.verifyEvent(event) && matchFilters(so.filters, event)) {\n so.onevent(event)\n }\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 (ok) ep.resolve(reason)\n else ep.reject(new Error(reason))\n this.openEventPublishes.delete(id)\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 case 'AUTH': {\n this.challenge = data[1] as string\n return\n }\n }\n } catch (err) {\n return\n }\n }\n\n public async send(message: string) {\n if (!this.connectionPromise) throw new Error('sending on closed connection')\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 if (!this.challenge) throw new Error(\"can't perform auth, no challenge was received\")\n const evt = await signAuthEvent(makeAuthEvent(this.url, this.challenge))\n const ret = new Promise<string>((resolve, reject) => {\n this.openEventPublishes.set(evt.id, { resolve, reject })\n })\n this.send('[\"AUTH\",' + JSON.stringify(evt) + ']')\n return ret\n }\n\n public async publish(event: Event): Promise<string> {\n const ret = new Promise<string>((resolve, reject) => {\n this.openEventPublishes.set(event.id, { resolve, reject })\n })\n this.send('[\"EVENT\",' + JSON.stringify(event) + ']')\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) + ']')\n return ret\n }\n\n public subscribe(filters: Filter[], params: Partial<SubscriptionParams>): Subscription {\n const subscription = this.prepareSubscription(filters, params)\n subscription.fire()\n return subscription\n }\n\n public prepareSubscription(filters: Filter[], params: Partial<SubscriptionParams> & { id?: string }): Subscription {\n this.serial++\n const id = params.id || 'sub:' + this.serial\n const subscription = new Subscription(this, id, filters, params)\n this.openSubs.set(id, subscription)\n return subscription\n }\n\n public close() {\n this.closeAllSubscriptions('relay connection closed by us')\n this._connected = false\n this.ws?.close()\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>) {\n this.incomingMessageQueue.enqueue(ev.data as string)\n if (!this.queueRunning) {\n this.runQueue()\n }\n }\n}\n\nexport class Subscription {\n public readonly relay: AbstractRelay\n public readonly id: string\n\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 oneose: (() => void) | undefined\n public onclose: ((reason: 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 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.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 this.relay.send('[\"CLOSE\",' + JSON.stringify(this.id) + ']')\n this.closed = true\n }\n this.relay.openSubs.delete(this.id)\n this.onclose?.(reason)\n }\n}\n\nexport type SubscriptionParams = {\n onevent?: (evt: Event) => 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}\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}\n", "import { AbstractRelay as AbstractRelay, SubscriptionParams, Subscription } from './abstract-relay.ts'\nimport { normalizeURL } from './utils.ts'\n\nimport type { Event, Nostr } from './core.ts'\nimport { type Filter } from './filter.ts'\nimport { alwaysTrue } from './helpers.ts'\n\nexport type SubCloser = { close: () => void }\n\nexport type SubscribeManyParams = Omit<SubscriptionParams, 'onclose' | 'id'> & {\n maxWait?: number\n onclose?: (reasons: string[]) => void\n id?: string\n}\n\nexport class AbstractSimplePool {\n private relays = new Map<string, AbstractRelay>()\n public seenOn: Map<string, Set<AbstractRelay>> = new Map()\n public trackRelays: boolean = false\n\n public verifyEvent: Nostr['verifyEvent']\n public trustedRelayURLs: Set<string> = new Set()\n\n constructor(opts: { verifyEvent: Nostr['verifyEvent'] }) {\n this.verifyEvent = opts.verifyEvent\n }\n\n async ensureRelay(url: string, params?: { connectionTimeout?: number }): 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 })\n if (params?.connectionTimeout) relay.connectionTimeout = params.connectionTimeout\n this.relays.set(url, relay)\n }\n await relay.connect()\n\n return relay\n }\n\n close(relays: string[]) {\n relays.map(normalizeURL).forEach(url => {\n this.relays.get(url)?.close()\n })\n }\n\n subscribeMany(relays: string[], filters: Filter[], params: SubscribeManyParams): SubCloser {\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 eosesReceived[i] = true\n if (eosesReceived.filter(a => a).length === relays.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 handleEose(i)\n closesReceived[i] = reason\n if (closesReceived.filter(a => a).length === relays.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 relays.map(normalizeURL).map(async (url, i, arr) => {\n if (arr.indexOf(url) !== i) {\n // duplicate\n handleClose(i, 'duplicate url')\n return\n }\n\n let relay: AbstractRelay\n try {\n relay = await this.ensureRelay(url, {\n connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1000) : undefined,\n })\n } catch (err) {\n handleClose(i, (err as any)?.message || String(err))\n return\n }\n\n let subscription = relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i),\n onclose: reason => handleClose(i, reason),\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait,\n })\n\n subs.push(subscription)\n }),\n )\n\n return {\n async close() {\n await allOpened\n subs.forEach(sub => {\n sub.close()\n })\n },\n }\n }\n\n subscribeManyEose(\n relays: string[],\n filters: Filter[],\n params: Pick<SubscribeManyParams, 'id' | 'onevent' | 'onclose' | 'maxWait'>,\n ): SubCloser {\n const subcloser = this.subscribeMany(relays, filters, {\n ...params,\n oneose() {\n subcloser.close()\n },\n })\n return subcloser\n }\n\n async querySync(\n relays: string[],\n filter: Filter,\n params?: Pick<SubscribeManyParams, 'id' | 'maxWait'>,\n ): Promise<Event[]> {\n return new Promise(async resolve => {\n const events: Event[] = []\n this.subscribeManyEose(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, '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(relays: string[], event: Event): 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 let r = await this.ensureRelay(url)\n return r.publish(event)\n })\n }\n}\n", "import { verifyEvent } from './pure.ts'\nimport { AbstractSimplePool } from './abstract-pool.ts'\n\nexport class SimplePool extends AbstractSimplePool {\n constructor() {\n super({ verifyEvent })\n }\n}\n\nexport * from './abstract-pool.ts'\n", "import { NostrEvent, UnsignedEvent, VerifiedEvent } from './core.ts'\nimport { generateSecretKey, finalizeEvent, getPublicKey, verifyEvent } from './pure.ts'\nimport { AbstractSimplePool, SubCloser } from './abstract-pool.ts'\nimport { decrypt, encrypt } from './nip04.ts'\nimport { NIP05_REGEX } from './nip05.ts'\nimport { SimplePool } from './pool.ts'\nimport { Handlerinformation, NostrConnect } from './kinds.ts'\nimport { hexToBytes } from '@noble/hashes/utils'\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\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\nasync 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 BunkerSignerParams = {\n pool?: AbstractSimplePool\n onauth?: (url: string) => void\n}\n\nexport class BunkerSigner {\n private pool: AbstractSimplePool\n private subCloser: SubCloser\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 public bp: BunkerPointer\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 public constructor(clientSecretKey: Uint8Array, bp: BunkerPointer, params: BunkerSignerParams = {}) {\n if (bp.relays.length === 0) {\n throw new Error('no relays are specified for this bunker')\n }\n\n this.pool = params.pool || new SimplePool()\n this.secretKey = clientSecretKey\n this.bp = bp\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 const listeners = this.listeners\n const waitingForAuth = this.waitingForAuth\n\n this.subCloser = this.pool.subscribeMany(\n this.bp.relays,\n [{ kinds: [NostrConnect], '#p': [getPublicKey(this.secretKey)] }],\n {\n async onevent(event: NostrEvent) {\n const { id, result, error } = JSON.parse(await decrypt(clientSecretKey, event.pubkey, event.content))\n\n if (result === 'auth_url' && waitingForAuth[id]) {\n delete waitingForAuth[id]\n\n if (params.onauth) {\n params.onauth(error)\n } else {\n console.warn(\n `nostr-tools/nip46: remote signer ${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 },\n )\n this.isOpen = true\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 this.serial++\n const id = `${this.idPrefix}-${this.serial}`\n\n const encryptedContent = await encrypt(this.secretKey, this.bp.pubkey, JSON.stringify({ id, method, params }))\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', [getPublicKey(this.secretKey), this.bp.secret || ''])\n }\n\n /**\n * This was supposed to call the \"get_public_key\" method on the bunker,\n * but instead we just returns the public key we already know.\n */\n async getPublicKey(): Promise<string> {\n return this.bp.pubkey\n }\n\n /**\n * Calls the \"get_relays\" method on the bunker.\n */\n async getRelays(): Promise<{ [relay: string]: { read: boolean; write: boolean } }> {\n return JSON.parse(await this.sendRequest('get_relays', []))\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: UnsignedEvent): Promise<VerifiedEvent> {\n let resp = await this.sendRequest('sign_event', [JSON.stringify(event)])\n let signed: NostrEvent = JSON.parse(resp)\n if (signed.pubkey === this.bp.pubkey && 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 nip44GetKey(thirdPartyPubkey: string): Promise<Uint8Array> {\n let resp = await this.sendRequest('nip44_get_key', [thirdPartyPubkey])\n return hexToBytes(resp)\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_encrypt', [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 * @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): Promise<BunkerSigner> {\n if (email && !EMAIL_REGEX.test(email)) throw new Error('Invalid email')\n\n let sk = generateSecretKey()\n let rpc = new BunkerSigner(sk, 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// @deprecated use fetchBunkerProviders instead\nexport const fetchCustodialBunkers = fetchBunkerProviders\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"],
5
+ "mappings": "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",
6
+ "names": ["i", "target", "bytesToHex", "bytesToHex", "i", "i", "_fetch", "i"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../pure.ts", "../../core.ts", "../../utils.ts", "../../kinds.ts", "../../nip04.ts", "../../nip47.ts"],
4
- "sourcesContent": ["import { schnorr } from '@noble/curves/secp256k1'\nimport { bytesToHex } from '@noble/hashes/utils'\nimport { Nostr, Event, EventTemplate, UnsignedEvent, VerifiedEvent, verifiedSymbol, validateEvent } from './core.ts'\nimport { sha256 } from '@noble/hashes/sha256'\n\nimport { utf8Encoder } from './utils.ts'\n\nclass JS implements Nostr {\n generateSecretKey(): Uint8Array {\n return schnorr.utils.randomPrivateKey()\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(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 const hash = getEventHash(event)\n if (hash !== event.id) {\n event[verifiedSymbol] = false\n return false\n }\n\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey)\n event[verifiedSymbol] = valid\n return valid\n } catch (err) {\n event[verifiedSymbol] = false\n return false\n }\n }\n}\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 = 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 interface Event {\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 NostrEvent = Event\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] === 'object') return false\n }\n }\n\n return true\n}\n", "import type { Event } from './core.ts'\n\nexport const utf8Decoder = new TextDecoder('utf-8')\nexport const utf8Encoder = new TextEncoder()\n\nexport function normalizeURL(url: string): string {\n if (url.indexOf('://') === -1) url = 'wss://' + url\n let p = new URL(url)\n p.pathname = p.pathname.replace(/\\/+/g, '/')\n if (p.pathname.endsWith('/')) p.pathname = p.pathname.slice(0, -1)\n if ((p.port === '80' && p.protocol === 'ws:') || (p.port === '443' && p.protocol === 'wss:')) p.port = ''\n p.searchParams.sort()\n p.hash = ''\n return p.toString()\n}\n\nexport function insertEventIntoDescendingList(sortedArray: Event[], event: Event) {\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: Event[], event: Event) {\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 class QueueNode<V> {\n public value: V\n public next: QueueNode<V> | null = null\n public prev: QueueNode<V> | null = null\n\n constructor(message: V) {\n this.value = message\n }\n}\n\nexport class Queue<V> {\n public first: QueueNode<V> | null\n public last: QueueNode<V> | null\n\n constructor() {\n this.first = null\n this.last = null\n }\n\n enqueue(value: V): boolean {\n const newNode = new QueueNode(value)\n if (!this.last) {\n // list is empty\n this.first = newNode\n this.last = newNode\n } else if (this.last === this.first) {\n // list has a single element\n this.last = newNode\n this.last.prev = this.first\n this.first.next = newNode\n } else {\n // list has elements, add as last\n newNode.prev = this.last\n this.last.next = newNode\n this.last = newNode\n }\n return true\n }\n\n dequeue(): V | null {\n if (!this.first) return null\n\n if (this.first === this.last) {\n const target = this.first\n this.first = null\n this.last = null\n return target.value\n }\n\n const target = this.first\n this.first = target.next\n\n return target.value\n }\n}\n", "/** Events are **regular**, which means they're all expected to be stored by relays. */\nexport function isRegularKind(kind: number) {\n return (1000 <= kind && kind < 10000) || [1, 2, 4, 5, 6, 7, 8, 16, 40, 41, 42, 43, 44].includes(kind)\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) {\n return [0, 3].includes(kind) || (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) {\n return 20000 <= kind && kind < 30000\n}\n\n/** Events are **parameterized replaceable**, 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 isParameterizedReplaceableKind(kind: number) {\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 (isParameterizedReplaceableKind(kind)) return 'parameterized'\n return 'unknown'\n}\n\nexport const Metadata = 0\nexport const ShortTextNote = 1\nexport const RecommendRelay = 2\nexport const Contacts = 3\nexport const EncryptedDirectMessage = 4\nexport const EncryptedDirectMessages = 4\nexport const EventDeletion = 5\nexport const Repost = 6\nexport const Reaction = 7\nexport const BadgeAward = 8\nexport const GenericRepost = 16\nexport const ChannelCreation = 40\nexport const ChannelMetadata = 41\nexport const ChannelMessage = 42\nexport const ChannelHideMessage = 43\nexport const ChannelMuteUser = 44\nexport const OpenTimestamps = 1040\nexport const FileMetadata = 1063\nexport const LiveChatMessage = 1311\nexport const ProblemTracker = 1971\nexport const Report = 1984\nexport const Reporting = 1984\nexport const Label = 1985\nexport const CommunityPostApproval = 4550\nexport const JobRequest = 5999\nexport const JobResult = 6999\nexport const JobFeedback = 7000\nexport const ZapGoal = 9041\nexport const ZapRequest = 9734\nexport const Zap = 9735\nexport const Highlights = 9802\nexport const Mutelist = 10000\nexport const Pinlist = 10001\nexport const RelayList = 10002\nexport const BookmarkList = 10003\nexport const CommunitiesList = 10004\nexport const PublicChatsList = 10005\nexport const BlockedRelaysList = 10006\nexport const SearchRelaysList = 10007\nexport const InterestsList = 10015\nexport const UserEmojiList = 10030\nexport const FileServerPreference = 10096\nexport const NWCWalletInfo = 13194\nexport const LightningPubRPC = 21000\nexport const ClientAuth = 22242\nexport const NWCWalletRequest = 23194\nexport const NWCWalletResponse = 23195\nexport const NostrConnect = 24133\nexport const HTTPAuth = 27235\nexport const Followsets = 30000\nexport const Genericlists = 30001\nexport const Relaysets = 30002\nexport const Bookmarksets = 30003\nexport const Curationsets = 30004\nexport const ProfileBadges = 30008\nexport const BadgeDefinition = 30009\nexport const Interestsets = 30015\nexport const CreateOrUpdateStall = 30017\nexport const CreateOrUpdateProduct = 30018\nexport const LongFormArticle = 30023\nexport const DraftLong = 30024\nexport const Emojisets = 30030\nexport const Application = 30078\nexport const LiveEvent = 30311\nexport const UserStatuses = 30315\nexport const ClassifiedListing = 30402\nexport const DraftClassifiedListing = 30403\nexport const Date = 31922\nexport const Time = 31923\nexport const Calendar = 31924\nexport const CalendarEventRSVP = 31925\nexport const Handlerrecommendation = 31989\nexport const Handlerinformation = 31990\nexport const CommunityDefinition = 34550\n", "import { bytesToHex, randomBytes } from '@noble/hashes/utils'\nimport { secp256k1 } from '@noble/curves/secp256k1'\nimport { cbc } from '@noble/ciphers/aes'\nimport { base64 } from '@scure/base'\n\nimport { utf8Decoder, utf8Encoder } from './utils.ts'\n\nexport async function encrypt(secretKey: string | Uint8Array, pubkey: string, text: string): Promise<string> {\n const privkey: string = secretKey instanceof Uint8Array ? bytesToHex(secretKey) : secretKey\n const key = secp256k1.getSharedSecret(privkey, '02' + pubkey)\n const normalizedKey = getNormalizedX(key)\n\n let iv = Uint8Array.from(randomBytes(16))\n let plaintext = utf8Encoder.encode(text)\n\n let ciphertext = cbc(normalizedKey, iv).encrypt(plaintext)\n\n let ctb64 = base64.encode(new Uint8Array(ciphertext))\n let ivb64 = base64.encode(new Uint8Array(iv.buffer))\n\n return `${ctb64}?iv=${ivb64}`\n}\n\nexport async function decrypt(secretKey: string | Uint8Array, pubkey: string, data: string): Promise<string> {\n const privkey: string = secretKey instanceof Uint8Array ? bytesToHex(secretKey) : secretKey\n let [ctb64, ivb64] = data.split('?iv=')\n let key = secp256k1.getSharedSecret(privkey, '02' + pubkey)\n let normalizedKey = getNormalizedX(key)\n\n let iv = base64.decode(ivb64)\n let ciphertext = base64.decode(ctb64)\n\n let plaintext = cbc(normalizedKey, iv).decrypt(ciphertext)\n\n return utf8Decoder.decode(plaintext)\n}\n\nfunction getNormalizedX(key: Uint8Array): Uint8Array {\n return key.slice(1, 33)\n}\n", "import { finalizeEvent } from './pure.ts'\nimport { NWCWalletRequest } from './kinds.ts'\nimport { encrypt } from './nip04.ts'\n\nexport function parseConnectionString(connectionString: string) {\n const { pathname, searchParams } = new URL(connectionString)\n const pubkey = pathname\n const relay = searchParams.get('relay')\n const secret = searchParams.get('secret')\n\n if (!pubkey || !relay || !secret) {\n throw new Error('invalid connection string')\n }\n\n return { pubkey, relay, secret }\n}\n\nexport async function makeNwcRequestEvent(pubkey: string, secretKey: Uint8Array, invoice: string) {\n const content = {\n method: 'pay_invoice',\n params: {\n invoice,\n },\n }\n const encryptedContent = await encrypt(secretKey, pubkey, JSON.stringify(content))\n const eventTemplate = {\n kind: NWCWalletRequest,\n created_at: Math.round(Date.now() / 1000),\n content: encryptedContent,\n tags: [['p', pubkey]],\n }\n\n return finalizeEvent(eventTemplate, secretKey)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { schnorr } from '@noble/curves/secp256k1'\nimport { bytesToHex } from '@noble/hashes/utils'\nimport { Nostr, Event, EventTemplate, UnsignedEvent, VerifiedEvent, verifiedSymbol, validateEvent } from './core.ts'\nimport { sha256 } from '@noble/hashes/sha256'\n\nimport { utf8Encoder } from './utils.ts'\n\nclass JS implements Nostr {\n generateSecretKey(): Uint8Array {\n return schnorr.utils.randomPrivateKey()\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(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 const hash = getEventHash(event)\n if (hash !== event.id) {\n event[verifiedSymbol] = false\n return false\n }\n\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey)\n event[verifiedSymbol] = valid\n return valid\n } catch (err) {\n event[verifiedSymbol] = false\n return false\n }\n }\n}\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 interface Event {\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 NostrEvent = Event\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] === 'object') return false\n }\n }\n\n return true\n}\n", "import type { Event } from './core.ts'\n\nexport const utf8Decoder: TextDecoder = new TextDecoder('utf-8')\nexport const utf8Encoder: TextEncoder = new TextEncoder()\n\nexport function normalizeURL(url: string): string {\n if (url.indexOf('://') === -1) url = 'wss://' + url\n let p = new URL(url)\n p.pathname = p.pathname.replace(/\\/+/g, '/')\n if (p.pathname.endsWith('/')) p.pathname = p.pathname.slice(0, -1)\n if ((p.port === '80' && p.protocol === 'ws:') || (p.port === '443' && p.protocol === 'wss:')) p.port = ''\n p.searchParams.sort()\n p.hash = ''\n return p.toString()\n}\n\nexport function insertEventIntoDescendingList(sortedArray: Event[], event: Event): Event[] {\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: Event[], event: Event): Event[] {\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 class QueueNode<V> {\n public value: V\n public next: QueueNode<V> | null = null\n public prev: QueueNode<V> | null = null\n\n constructor(message: V) {\n this.value = message\n }\n}\n\nexport class Queue<V> {\n public first: QueueNode<V> | null\n public last: QueueNode<V> | null\n\n constructor() {\n this.first = null\n this.last = null\n }\n\n enqueue(value: V): boolean {\n const newNode = new QueueNode(value)\n if (!this.last) {\n // list is empty\n this.first = newNode\n this.last = newNode\n } else if (this.last === this.first) {\n // list has a single element\n this.last = newNode\n this.last.prev = this.first\n this.first.next = newNode\n } else {\n // list has elements, add as last\n newNode.prev = this.last\n this.last.next = newNode\n this.last = newNode\n }\n return true\n }\n\n dequeue(): V | null {\n if (!this.first) return null\n\n if (this.first === this.last) {\n const target = this.first\n this.first = null\n this.last = null\n return target.value\n }\n\n const target = this.first\n this.first = target.next\n\n return target.value\n }\n}\n", "/** Events are **regular**, which means they're all expected to be stored by relays. */\nexport function isRegularKind(kind: number): boolean {\n return (1000 <= kind && kind < 10000) || [1, 2, 4, 5, 6, 7, 8, 16, 40, 41, 42, 43, 44].includes(kind)\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 [0, 3].includes(kind) || (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 **parameterized replaceable**, 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 isParameterizedReplaceableKind(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 (isParameterizedReplaceableKind(kind)) return 'parameterized'\n return 'unknown'\n}\n\nexport const Metadata = 0\nexport const ShortTextNote = 1\nexport const RecommendRelay = 2\nexport const Contacts = 3\nexport const EncryptedDirectMessage = 4\nexport const EncryptedDirectMessages = 4\nexport const EventDeletion = 5\nexport const Repost = 6\nexport const Reaction = 7\nexport const BadgeAward = 8\nexport const GenericRepost = 16\nexport const ChannelCreation = 40\nexport const ChannelMetadata = 41\nexport const ChannelMessage = 42\nexport const ChannelHideMessage = 43\nexport const ChannelMuteUser = 44\nexport const OpenTimestamps = 1040\nexport const FileMetadata = 1063\nexport const LiveChatMessage = 1311\nexport const ProblemTracker = 1971\nexport const Report = 1984\nexport const Reporting = 1984\nexport const Label = 1985\nexport const CommunityPostApproval = 4550\nexport const JobRequest = 5999\nexport const JobResult = 6999\nexport const JobFeedback = 7000\nexport const ZapGoal = 9041\nexport const ZapRequest = 9734\nexport const Zap = 9735\nexport const Highlights = 9802\nexport const Mutelist = 10000\nexport const Pinlist = 10001\nexport const RelayList = 10002\nexport const BookmarkList = 10003\nexport const CommunitiesList = 10004\nexport const PublicChatsList = 10005\nexport const BlockedRelaysList = 10006\nexport const SearchRelaysList = 10007\nexport const InterestsList = 10015\nexport const UserEmojiList = 10030\nexport const FileServerPreference = 10096\nexport const NWCWalletInfo = 13194\nexport const LightningPubRPC = 21000\nexport const ClientAuth = 22242\nexport const NWCWalletRequest = 23194\nexport const NWCWalletResponse = 23195\nexport const NostrConnect = 24133\nexport const HTTPAuth = 27235\nexport const Followsets = 30000\nexport const Genericlists = 30001\nexport const Relaysets = 30002\nexport const Bookmarksets = 30003\nexport const Curationsets = 30004\nexport const ProfileBadges = 30008\nexport const BadgeDefinition = 30009\nexport const Interestsets = 30015\nexport const CreateOrUpdateStall = 30017\nexport const CreateOrUpdateProduct = 30018\nexport const LongFormArticle = 30023\nexport const DraftLong = 30024\nexport const Emojisets = 30030\nexport const Application = 30078\nexport const LiveEvent = 30311\nexport const UserStatuses = 30315\nexport const ClassifiedListing = 30402\nexport const DraftClassifiedListing = 30403\nexport const Date = 31922\nexport const Time = 31923\nexport const Calendar = 31924\nexport const CalendarEventRSVP = 31925\nexport const Handlerrecommendation = 31989\nexport const Handlerinformation = 31990\nexport const CommunityDefinition = 34550\n", "import { bytesToHex, randomBytes } from '@noble/hashes/utils'\nimport { secp256k1 } from '@noble/curves/secp256k1'\nimport { cbc } from '@noble/ciphers/aes'\nimport { base64 } from '@scure/base'\n\nimport { utf8Decoder, utf8Encoder } from './utils.ts'\n\nexport async function encrypt(secretKey: string | Uint8Array, pubkey: string, text: string): Promise<string> {\n const privkey: string = secretKey instanceof Uint8Array ? bytesToHex(secretKey) : secretKey\n const key = secp256k1.getSharedSecret(privkey, '02' + pubkey)\n const normalizedKey = getNormalizedX(key)\n\n let iv = Uint8Array.from(randomBytes(16))\n let plaintext = utf8Encoder.encode(text)\n\n let ciphertext = cbc(normalizedKey, iv).encrypt(plaintext)\n\n let ctb64 = base64.encode(new Uint8Array(ciphertext))\n let ivb64 = base64.encode(new Uint8Array(iv.buffer))\n\n return `${ctb64}?iv=${ivb64}`\n}\n\nexport async function decrypt(secretKey: string | Uint8Array, pubkey: string, data: string): Promise<string> {\n const privkey: string = secretKey instanceof Uint8Array ? bytesToHex(secretKey) : secretKey\n let [ctb64, ivb64] = data.split('?iv=')\n let key = secp256k1.getSharedSecret(privkey, '02' + pubkey)\n let normalizedKey = getNormalizedX(key)\n\n let iv = base64.decode(ivb64)\n let ciphertext = base64.decode(ctb64)\n\n let plaintext = cbc(normalizedKey, iv).decrypt(ciphertext)\n\n return utf8Decoder.decode(plaintext)\n}\n\nfunction getNormalizedX(key: Uint8Array): Uint8Array {\n return key.slice(1, 33)\n}\n", "import { type VerifiedEvent, finalizeEvent } from './pure.ts'\nimport { NWCWalletRequest } from './kinds.ts'\nimport { encrypt } from './nip04.ts'\n\ninterface NWCConnection {\n pubkey: string\n relay: string\n secret: string\n}\n\nexport function parseConnectionString(connectionString: string): NWCConnection {\n const { pathname, searchParams } = new URL(connectionString)\n const pubkey = pathname\n const relay = searchParams.get('relay')\n const secret = searchParams.get('secret')\n\n if (!pubkey || !relay || !secret) {\n throw new Error('invalid connection string')\n }\n\n return { pubkey, relay, secret }\n}\n\nexport async function makeNwcRequestEvent(\n pubkey: string,\n secretKey: Uint8Array,\n invoice: string,\n): Promise<VerifiedEvent> {\n const content = {\n method: 'pay_invoice',\n params: {\n invoice,\n },\n }\n const encryptedContent = await encrypt(secretKey, pubkey, JSON.stringify(content))\n const eventTemplate = {\n kind: NWCWalletRequest,\n created_at: Math.round(Date.now() / 1000),\n content: encryptedContent,\n tags: [['p', pubkey]],\n }\n\n return finalizeEvent(eventTemplate, secretKey)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["i", "bytesToHex", "bytesToHex"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../nip57.ts", "../../pure.ts", "../../core.ts", "../../utils.ts"],
4
- "sourcesContent": ["import { bech32 } from '@scure/base'\n\nimport { validateEvent, verifyEvent, type Event, type EventTemplate } from './pure.ts'\nimport { utf8Decoder } from './utils.ts'\n\nvar _fetch: any\n\ntry {\n _fetch = fetch\n} catch {}\n\nexport function useFetchImplementation(fetchImplementation: any) {\n _fetch = fetchImplementation\n}\n\nexport async function getZapEndpoint(metadata: Event): Promise<null | string> {\n try {\n let lnurl: string = ''\n let { lud06, lud16 } = JSON.parse(metadata.content)\n if (lud06) {\n let { words } = bech32.decode(lud06, 1000)\n let data = bech32.fromWords(words)\n lnurl = utf8Decoder.decode(data)\n } else if (lud16) {\n let [name, domain] = lud16.split('@')\n lnurl = new URL(`/.well-known/lnurlp/${name}`, `https://${domain}`).toString()\n } else {\n return null\n }\n\n let res = await _fetch(lnurl)\n let body = await res.json()\n\n if (body.allowsNostr && body.nostrPubkey) {\n return body.callback\n }\n } catch (err) {\n /*-*/\n }\n\n return null\n}\n\nexport function makeZapRequest({\n profile,\n event,\n amount,\n relays,\n comment = '',\n}: {\n profile: string\n event: string | null\n amount: number\n comment: string\n relays: string[]\n}): EventTemplate {\n if (!amount) throw new Error('amount not given')\n if (!profile) throw new Error('profile not given')\n\n let zr: EventTemplate = {\n kind: 9734,\n created_at: Math.round(Date.now() / 1000),\n content: comment,\n tags: [\n ['p', profile],\n ['amount', amount.toString()],\n ['relays', ...relays],\n ],\n }\n\n if (event) {\n zr.tags.push(['e', event])\n }\n\n return zr\n}\n\nexport function validateZapRequest(zapRequestString: string): string | null {\n let zapRequest: Event\n\n try {\n zapRequest = JSON.parse(zapRequestString)\n } catch (err) {\n return 'Invalid zap request JSON.'\n }\n\n if (!validateEvent(zapRequest)) return 'Zap request is not a valid Nostr event.'\n\n if (!verifyEvent(zapRequest)) return 'Invalid signature on zap request.'\n\n let p = zapRequest.tags.find(([t, v]) => t === 'p' && v)\n if (!p) return \"Zap request doesn't have a 'p' tag.\"\n if (!p[1].match(/^[a-f0-9]{64}$/)) return \"Zap request 'p' tag is not valid hex.\"\n\n let e = zapRequest.tags.find(([t, v]) => t === 'e' && v)\n if (e && !e[1].match(/^[a-f0-9]{64}$/)) return \"Zap request 'e' tag is not valid hex.\"\n\n let relays = zapRequest.tags.find(([t, v]) => t === 'relays' && v)\n if (!relays) return \"Zap request doesn't have a 'relays' tag.\"\n\n return null\n}\n\nexport function makeZapReceipt({\n zapRequest,\n preimage,\n bolt11,\n paidAt,\n}: {\n zapRequest: string\n preimage?: string\n bolt11: string\n paidAt: Date\n}): EventTemplate {\n let zr: Event = JSON.parse(zapRequest)\n let tagsFromZapRequest = zr.tags.filter(([t]) => t === 'e' || t === 'p' || t === 'a')\n\n let zap: EventTemplate = {\n kind: 9735,\n created_at: Math.round(paidAt.getTime() / 1000),\n content: '',\n tags: [...tagsFromZapRequest, ['P', zr.pubkey], ['bolt11', bolt11], ['description', zapRequest]],\n }\n\n if (preimage) {\n zap.tags.push(['preimage', preimage])\n }\n\n return zap\n}\n", "import { schnorr } from '@noble/curves/secp256k1'\nimport { bytesToHex } from '@noble/hashes/utils'\nimport { Nostr, Event, EventTemplate, UnsignedEvent, VerifiedEvent, verifiedSymbol, validateEvent } from './core.ts'\nimport { sha256 } from '@noble/hashes/sha256'\n\nimport { utf8Encoder } from './utils.ts'\n\nclass JS implements Nostr {\n generateSecretKey(): Uint8Array {\n return schnorr.utils.randomPrivateKey()\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(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 const hash = getEventHash(event)\n if (hash !== event.id) {\n event[verifiedSymbol] = false\n return false\n }\n\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey)\n event[verifiedSymbol] = valid\n return valid\n } catch (err) {\n event[verifiedSymbol] = false\n return false\n }\n }\n}\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 = 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 interface Event {\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 NostrEvent = Event\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] === 'object') return false\n }\n }\n\n return true\n}\n", "import type { Event } from './core.ts'\n\nexport const utf8Decoder = new TextDecoder('utf-8')\nexport const utf8Encoder = new TextEncoder()\n\nexport function normalizeURL(url: string): string {\n if (url.indexOf('://') === -1) url = 'wss://' + url\n let p = new URL(url)\n p.pathname = p.pathname.replace(/\\/+/g, '/')\n if (p.pathname.endsWith('/')) p.pathname = p.pathname.slice(0, -1)\n if ((p.port === '80' && p.protocol === 'ws:') || (p.port === '443' && p.protocol === 'wss:')) p.port = ''\n p.searchParams.sort()\n p.hash = ''\n return p.toString()\n}\n\nexport function insertEventIntoDescendingList(sortedArray: Event[], event: Event) {\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: Event[], event: Event) {\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 class QueueNode<V> {\n public value: V\n public next: QueueNode<V> | null = null\n public prev: QueueNode<V> | null = null\n\n constructor(message: V) {\n this.value = message\n }\n}\n\nexport class Queue<V> {\n public first: QueueNode<V> | null\n public last: QueueNode<V> | null\n\n constructor() {\n this.first = null\n this.last = null\n }\n\n enqueue(value: V): boolean {\n const newNode = new QueueNode(value)\n if (!this.last) {\n // list is empty\n this.first = newNode\n this.last = newNode\n } else if (this.last === this.first) {\n // list has a single element\n this.last = newNode\n this.last.prev = this.first\n this.first.next = newNode\n } else {\n // list has elements, add as last\n newNode.prev = this.last\n this.last.next = newNode\n this.last = newNode\n }\n return true\n }\n\n dequeue(): V | null {\n if (!this.first) return null\n\n if (this.first === this.last) {\n const target = this.first\n this.first = null\n this.last = null\n return target.value\n }\n\n const target = this.first\n this.first = target.next\n\n return target.value\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { bech32 } from '@scure/base'\n\nimport { validateEvent, verifyEvent, type Event, type EventTemplate } from './pure.ts'\nimport { utf8Decoder } from './utils.ts'\n\nvar _fetch: any\n\ntry {\n _fetch = fetch\n} catch {}\n\nexport function useFetchImplementation(fetchImplementation: any) {\n _fetch = fetchImplementation\n}\n\nexport async function getZapEndpoint(metadata: Event): Promise<null | string> {\n try {\n let lnurl: string = ''\n let { lud06, lud16 } = JSON.parse(metadata.content)\n if (lud06) {\n let { words } = bech32.decode(lud06, 1000)\n let data = bech32.fromWords(words)\n lnurl = utf8Decoder.decode(data)\n } else if (lud16) {\n let [name, domain] = lud16.split('@')\n lnurl = new URL(`/.well-known/lnurlp/${name}`, `https://${domain}`).toString()\n } else {\n return null\n }\n\n let res = await _fetch(lnurl)\n let body = await res.json()\n\n if (body.allowsNostr && body.nostrPubkey) {\n return body.callback\n }\n } catch (err) {\n /*-*/\n }\n\n return null\n}\n\nexport function makeZapRequest({\n profile,\n event,\n amount,\n relays,\n comment = '',\n}: {\n profile: string\n event: string | null\n amount: number\n comment: string\n relays: string[]\n}): EventTemplate {\n if (!amount) throw new Error('amount not given')\n if (!profile) throw new Error('profile not given')\n\n let zr: EventTemplate = {\n kind: 9734,\n created_at: Math.round(Date.now() / 1000),\n content: comment,\n tags: [\n ['p', profile],\n ['amount', amount.toString()],\n ['relays', ...relays],\n ],\n }\n\n if (event) {\n zr.tags.push(['e', event])\n }\n\n return zr\n}\n\nexport function validateZapRequest(zapRequestString: string): string | null {\n let zapRequest: Event\n\n try {\n zapRequest = JSON.parse(zapRequestString)\n } catch (err) {\n return 'Invalid zap request JSON.'\n }\n\n if (!validateEvent(zapRequest)) return 'Zap request is not a valid Nostr event.'\n\n if (!verifyEvent(zapRequest)) return 'Invalid signature on zap request.'\n\n let p = zapRequest.tags.find(([t, v]) => t === 'p' && v)\n if (!p) return \"Zap request doesn't have a 'p' tag.\"\n if (!p[1].match(/^[a-f0-9]{64}$/)) return \"Zap request 'p' tag is not valid hex.\"\n\n let e = zapRequest.tags.find(([t, v]) => t === 'e' && v)\n if (e && !e[1].match(/^[a-f0-9]{64}$/)) return \"Zap request 'e' tag is not valid hex.\"\n\n let relays = zapRequest.tags.find(([t, v]) => t === 'relays' && v)\n if (!relays) return \"Zap request doesn't have a 'relays' tag.\"\n\n return null\n}\n\nexport function makeZapReceipt({\n zapRequest,\n preimage,\n bolt11,\n paidAt,\n}: {\n zapRequest: string\n preimage?: string\n bolt11: string\n paidAt: Date\n}): EventTemplate {\n let zr: Event = JSON.parse(zapRequest)\n let tagsFromZapRequest = zr.tags.filter(([t]) => t === 'e' || t === 'p' || t === 'a')\n\n let zap: EventTemplate = {\n kind: 9735,\n created_at: Math.round(paidAt.getTime() / 1000),\n content: '',\n tags: [...tagsFromZapRequest, ['P', zr.pubkey], ['bolt11', bolt11], ['description', zapRequest]],\n }\n\n if (preimage) {\n zap.tags.push(['preimage', preimage])\n }\n\n return zap\n}\n", "import { schnorr } from '@noble/curves/secp256k1'\nimport { bytesToHex } from '@noble/hashes/utils'\nimport { Nostr, Event, EventTemplate, UnsignedEvent, VerifiedEvent, verifiedSymbol, validateEvent } from './core.ts'\nimport { sha256 } from '@noble/hashes/sha256'\n\nimport { utf8Encoder } from './utils.ts'\n\nclass JS implements Nostr {\n generateSecretKey(): Uint8Array {\n return schnorr.utils.randomPrivateKey()\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(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 const hash = getEventHash(event)\n if (hash !== event.id) {\n event[verifiedSymbol] = false\n return false\n }\n\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey)\n event[verifiedSymbol] = valid\n return valid\n } catch (err) {\n event[verifiedSymbol] = false\n return false\n }\n }\n}\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 interface Event {\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 NostrEvent = Event\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] === 'object') return false\n }\n }\n\n return true\n}\n", "import type { Event } from './core.ts'\n\nexport const utf8Decoder: TextDecoder = new TextDecoder('utf-8')\nexport const utf8Encoder: TextEncoder = new TextEncoder()\n\nexport function normalizeURL(url: string): string {\n if (url.indexOf('://') === -1) url = 'wss://' + url\n let p = new URL(url)\n p.pathname = p.pathname.replace(/\\/+/g, '/')\n if (p.pathname.endsWith('/')) p.pathname = p.pathname.slice(0, -1)\n if ((p.port === '80' && p.protocol === 'ws:') || (p.port === '443' && p.protocol === 'wss:')) p.port = ''\n p.searchParams.sort()\n p.hash = ''\n return p.toString()\n}\n\nexport function insertEventIntoDescendingList(sortedArray: Event[], event: Event): Event[] {\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: Event[], event: Event): Event[] {\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 class QueueNode<V> {\n public value: V\n public next: QueueNode<V> | null = null\n public prev: QueueNode<V> | null = null\n\n constructor(message: V) {\n this.value = message\n }\n}\n\nexport class Queue<V> {\n public first: QueueNode<V> | null\n public last: QueueNode<V> | null\n\n constructor() {\n this.first = null\n this.last = null\n }\n\n enqueue(value: V): boolean {\n const newNode = new QueueNode(value)\n if (!this.last) {\n // list is empty\n this.first = newNode\n this.last = newNode\n } else if (this.last === this.first) {\n // list has a single element\n this.last = newNode\n this.last.prev = this.first\n this.first.next = newNode\n } else {\n // list has elements, add as last\n newNode.prev = this.last\n this.last.next = newNode\n this.last = newNode\n }\n return true\n }\n\n dequeue(): V | null {\n if (!this.first) return null\n\n if (this.first === this.last) {\n const target = this.first\n this.first = null\n this.last = null\n return target.value\n }\n\n const target = this.first\n this.first = target.next\n\n return target.value\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["i"]
7
7
  }