nostr-tools 1.2.0 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -120,6 +120,22 @@ To use this on Node.js you first must install `websocket-polyfill` and import it
120
120
  import 'websocket-polyfill'
121
121
  ```
122
122
 
123
+ ### Interacting with multiple relays
124
+
125
+ ```js
126
+ import {pool} from 'nostr-tools'
127
+
128
+ const p = pool()
129
+
130
+ ["wss://relay.example.com", "wss://relay.example2.com"].forEach(async url => {
131
+ let relay = pool.ensureRelay(url)
132
+ await relay.connect()
133
+
134
+ relay.sub(...) // same as above
135
+ relay.publish(...) // etc
136
+ })
137
+ ```
138
+
123
139
  ### Querying profile data from a NIP-05 address
124
140
 
125
141
  ```js
@@ -195,7 +211,7 @@ let event = {
195
211
  sendEvent(event)
196
212
 
197
213
  // on the receiver side
198
- sub.on('event', (event) => {
214
+ sub.on('event', event => {
199
215
  let sender = event.tags.find(([k, v]) => k === 'p' && v && v !== '')[1]
200
216
  pk1 === sender
201
217
  let plaintext = await nip04.decrypt(sk2, pk1, event.content)
package/index.ts CHANGED
@@ -2,8 +2,7 @@ export * from './keys'
2
2
  export * from './relay'
3
3
  export * from './event'
4
4
  export * from './filter'
5
-
6
- export * as fj from './fakejson'
5
+ export * from './pool'
7
6
 
8
7
  export * as nip04 from './nip04'
9
8
  export * as nip05 from './nip05'
@@ -11,6 +10,9 @@ export * as nip06 from './nip06'
11
10
  export * as nip19 from './nip19'
12
11
  export * as nip26 from './nip26'
13
12
 
13
+ export * as fj from './fakejson'
14
+ export * as utils from './utils'
15
+
14
16
  // monkey patch secp256k1
15
17
  import * as secp256k1 from '@noble/secp256k1'
16
18
  import {hmac} from '@noble/hashes/hmac'
@@ -3558,7 +3558,7 @@ zoo`.split("\n");
3558
3558
  return new Uint8Array([(0, sha256_1.sha256)(entropy)[0] >> bitsLeft << bitsLeft]);
3559
3559
  };
3560
3560
  function getCoder(wordlist2) {
3561
- if (!Array.isArray(wordlist2) || wordlist2.length !== 2 ** 11 || typeof wordlist2[0] !== "string")
3561
+ if (!Array.isArray(wordlist2) || wordlist2.length !== 2048 || typeof wordlist2[0] !== "string")
3562
3562
  throw new Error("Worlist: expected array of 2048 strings");
3563
3563
  wordlist2.forEach((i) => {
3564
3564
  if (typeof i !== "string")
@@ -3616,9 +3616,11 @@ zoo`.split("\n");
3616
3616
  nip06: () => nip06_exports,
3617
3617
  nip19: () => nip19_exports,
3618
3618
  nip26: () => nip26_exports,
3619
+ pool: () => pool,
3619
3620
  relayInit: () => relayInit,
3620
3621
  serializeEvent: () => serializeEvent,
3621
3622
  signEvent: () => signEvent,
3623
+ utils: () => utils_exports,
3622
3624
  validateEvent: () => validateEvent,
3623
3625
  verifySignature: () => verifySignature
3624
3626
  });
@@ -5159,9 +5161,100 @@ zoo`.split("\n");
5159
5161
  var sha256 = wrapConstructor(() => new SHA256());
5160
5162
 
5161
5163
  // utils.ts
5164
+ var utils_exports = {};
5165
+ __export(utils_exports, {
5166
+ insertEventIntoAscendingList: () => insertEventIntoAscendingList,
5167
+ insertEventIntoDescendingList: () => insertEventIntoDescendingList,
5168
+ normalizeURL: () => normalizeURL,
5169
+ utf8Decoder: () => utf8Decoder,
5170
+ utf8Encoder: () => utf8Encoder
5171
+ });
5162
5172
  init_define_process();
5163
5173
  var utf8Decoder = new TextDecoder("utf-8");
5164
5174
  var utf8Encoder = new TextEncoder();
5175
+ function normalizeURL(url) {
5176
+ let p = new URL(url);
5177
+ p.pathname = p.pathname.replace(/\/+/g, "/");
5178
+ if (p.pathname.endsWith("/"))
5179
+ p.pathname = p.pathname.slice(0, -1);
5180
+ if (p.port === "80" && p.protocol === "ws:" || p.port === "443" && p.protocol === "wss:")
5181
+ p.port = "";
5182
+ p.searchParams.sort();
5183
+ p.hash = "";
5184
+ return p.toString();
5185
+ }
5186
+ function insertEventIntoDescendingList(sortedArray, event) {
5187
+ let start = 0;
5188
+ let end = sortedArray.length - 1;
5189
+ let midPoint;
5190
+ let position = start;
5191
+ if (end < 0) {
5192
+ position = 0;
5193
+ } else if (event.created_at < sortedArray[end].created_at) {
5194
+ position = end + 1;
5195
+ } else if (event.created_at >= sortedArray[start].created_at) {
5196
+ position = start;
5197
+ } else
5198
+ while (true) {
5199
+ if (end <= start + 1) {
5200
+ position = end;
5201
+ break;
5202
+ }
5203
+ midPoint = Math.floor(start + (end - start) / 2);
5204
+ if (sortedArray[midPoint].created_at > event.created_at) {
5205
+ start = midPoint;
5206
+ } else if (sortedArray[midPoint].created_at < event.created_at) {
5207
+ end = midPoint;
5208
+ } else {
5209
+ position = midPoint;
5210
+ break;
5211
+ }
5212
+ }
5213
+ if (sortedArray[position]?.id !== event.id) {
5214
+ return [
5215
+ ...sortedArray.slice(0, position),
5216
+ event,
5217
+ ...sortedArray.slice(position)
5218
+ ];
5219
+ }
5220
+ return sortedArray;
5221
+ }
5222
+ function insertEventIntoAscendingList(sortedArray, event) {
5223
+ let start = 0;
5224
+ let end = sortedArray.length - 1;
5225
+ let midPoint;
5226
+ let position = start;
5227
+ if (end < 0) {
5228
+ position = 0;
5229
+ } else if (event.created_at > sortedArray[end].created_at) {
5230
+ position = end + 1;
5231
+ } else if (event.created_at <= sortedArray[start].created_at) {
5232
+ position = start;
5233
+ } else
5234
+ while (true) {
5235
+ if (end <= start + 1) {
5236
+ position = end;
5237
+ break;
5238
+ }
5239
+ midPoint = Math.floor(start + (end - start) / 2);
5240
+ if (sortedArray[midPoint].created_at < event.created_at) {
5241
+ start = midPoint;
5242
+ } else if (sortedArray[midPoint].created_at > event.created_at) {
5243
+ end = midPoint;
5244
+ } else {
5245
+ position = midPoint;
5246
+ break;
5247
+ }
5248
+ }
5249
+ if (sortedArray[position]?.id !== event.id) {
5250
+ return [
5251
+ ...sortedArray.slice(0, position),
5252
+ event,
5253
+ ...sortedArray.slice(position)
5254
+ ];
5255
+ }
5256
+ return sortedArray;
5257
+ }
5165
5258
 
5166
5259
  // event.ts
5167
5260
  var Kind = /* @__PURE__ */ ((Kind2) => {
@@ -5330,9 +5423,9 @@ zoo`.split("\n");
5330
5423
  setOpen();
5331
5424
  resolve();
5332
5425
  };
5333
- ws.onerror = () => {
5334
- listeners.error.forEach((cb) => cb());
5335
- reject();
5426
+ ws.onerror = (e) => {
5427
+ listeners.error.forEach((cb) => cb(e));
5428
+ reject(e);
5336
5429
  };
5337
5430
  ws.onclose = async () => {
5338
5431
  listeners.disconnect.forEach((cb) => cb());
@@ -5525,6 +5618,30 @@ zoo`.split("\n");
5525
5618
  };
5526
5619
  }
5527
5620
 
5621
+ // pool.ts
5622
+ init_define_process();
5623
+ function pool(defaultRelays = []) {
5624
+ return new SimplePool(defaultRelays);
5625
+ }
5626
+ var SimplePool = class {
5627
+ _conn;
5628
+ _knownIds = /* @__PURE__ */ new Set();
5629
+ constructor(defaultRelays) {
5630
+ this._conn = {};
5631
+ defaultRelays.forEach(this.ensureRelay);
5632
+ }
5633
+ ensureRelay(url) {
5634
+ const nm = normalizeURL(url);
5635
+ const existing = this._conn[nm];
5636
+ if (existing)
5637
+ return existing;
5638
+ const hasEventId = (id) => this._knownIds.has(id);
5639
+ const relay = relayInit(nm, hasEventId);
5640
+ this._conn[nm] = relay;
5641
+ return relay;
5642
+ }
5643
+ };
5644
+
5528
5645
  // nip04.ts
5529
5646
  var nip04_exports = {};
5530
5647
  __export(nip04_exports, {
@@ -5992,7 +6109,7 @@ zoo`.split("\n");
5992
6109
  domain = name;
5993
6110
  name = "_";
5994
6111
  }
5995
- if (!name.match(/^[a-z0-9-_]+$/))
6112
+ if (!name.match(/^[A-Za-z0-9-_]+$/))
5996
6113
  return null;
5997
6114
  let res = await (await _fetch(`https://${domain}/.well-known/nostr.json?name=${name}`)).json();
5998
6115
  if (!res?.names?.[name])