nostr-tools 2.22.0 → 2.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/abstract-pool.js +182 -225
- package/lib/cjs/abstract-pool.js.map +4 -4
- package/lib/cjs/abstract-relay.js +117 -191
- package/lib/cjs/abstract-relay.js.map +4 -4
- package/lib/cjs/index.js +229 -223
- package/lib/cjs/index.js.map +4 -4
- package/lib/cjs/nip04.js.map +1 -1
- package/lib/cjs/nip13.js.map +1 -1
- package/lib/cjs/nip17.js.map +1 -1
- package/lib/cjs/nip18.js.map +1 -1
- package/lib/cjs/nip19.js.map +1 -1
- package/lib/cjs/nip21.js.map +1 -1
- package/lib/cjs/nip25.js.map +1 -1
- package/lib/cjs/nip27.js +1 -1
- package/lib/cjs/nip27.js.map +2 -2
- package/lib/cjs/nip28.js.map +1 -1
- package/lib/cjs/nip29.js.map +1 -1
- package/lib/cjs/nip44.js.map +1 -1
- package/lib/cjs/nip46.js +183 -226
- package/lib/cjs/nip46.js.map +4 -4
- package/lib/cjs/nip47.js.map +1 -1
- package/lib/cjs/nip57.js.map +1 -1
- package/lib/cjs/nip59.js.map +1 -1
- package/lib/cjs/nip98.js.map +1 -1
- package/lib/cjs/nipb7.js.map +1 -1
- package/lib/cjs/pool.js +183 -226
- package/lib/cjs/pool.js.map +4 -4
- package/lib/cjs/pure.js.map +1 -1
- package/lib/cjs/references.js.map +1 -1
- package/lib/cjs/relay.js +117 -191
- package/lib/cjs/relay.js.map +4 -4
- package/lib/cjs/signer.js.map +1 -1
- package/lib/cjs/utils.js +45 -44
- package/lib/cjs/utils.js.map +3 -3
- package/lib/esm/abstract-pool.js +182 -225
- package/lib/esm/abstract-pool.js.map +4 -4
- package/lib/esm/abstract-relay.js +117 -191
- package/lib/esm/abstract-relay.js.map +4 -4
- package/lib/esm/index.js +229 -223
- package/lib/esm/index.js.map +4 -4
- package/lib/esm/nip04.js.map +1 -1
- package/lib/esm/nip13.js.map +1 -1
- package/lib/esm/nip17.js.map +1 -1
- package/lib/esm/nip18.js.map +1 -1
- package/lib/esm/nip19.js.map +1 -1
- package/lib/esm/nip21.js.map +1 -1
- package/lib/esm/nip25.js.map +1 -1
- package/lib/esm/nip27.js +1 -1
- package/lib/esm/nip27.js.map +2 -2
- package/lib/esm/nip28.js.map +1 -1
- package/lib/esm/nip29.js.map +1 -1
- package/lib/esm/nip44.js.map +1 -1
- package/lib/esm/nip46.js +183 -226
- package/lib/esm/nip46.js.map +4 -4
- package/lib/esm/nip47.js.map +1 -1
- package/lib/esm/nip57.js.map +1 -1
- package/lib/esm/nip59.js.map +1 -1
- package/lib/esm/nip98.js.map +1 -1
- package/lib/esm/nipb7.js.map +1 -1
- package/lib/esm/pool.js +183 -226
- package/lib/esm/pool.js.map +4 -4
- package/lib/esm/pure.js.map +1 -1
- package/lib/esm/references.js.map +1 -1
- package/lib/esm/relay.js +117 -191
- package/lib/esm/relay.js.map +4 -4
- package/lib/esm/signer.js.map +1 -1
- package/lib/esm/utils.js +45 -44
- package/lib/esm/utils.js.map +3 -3
- package/lib/nostr.bundle.js +237 -231
- package/lib/nostr.bundle.js.map +4 -4
- package/lib/types/abstract-pool.d.ts +12 -1
- package/lib/types/abstract-relay.d.ts +3 -5
- package/lib/types/helpers.d.ts +0 -1
- package/lib/types/utils.d.ts +4 -16
- package/package.json +44 -1
package/lib/cjs/abstract-pool.js
CHANGED
|
@@ -52,54 +52,6 @@ function normalizeURL(url) {
|
|
|
52
52
|
throw new Error(`Invalid URL: ${url}`);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
var QueueNode = class {
|
|
56
|
-
value;
|
|
57
|
-
next = null;
|
|
58
|
-
prev = null;
|
|
59
|
-
constructor(message) {
|
|
60
|
-
this.value = message;
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
var Queue = class {
|
|
64
|
-
first;
|
|
65
|
-
last;
|
|
66
|
-
constructor() {
|
|
67
|
-
this.first = null;
|
|
68
|
-
this.last = null;
|
|
69
|
-
}
|
|
70
|
-
enqueue(value) {
|
|
71
|
-
const newNode = new QueueNode(value);
|
|
72
|
-
if (!this.last) {
|
|
73
|
-
this.first = newNode;
|
|
74
|
-
this.last = newNode;
|
|
75
|
-
} else if (this.last === this.first) {
|
|
76
|
-
this.last = newNode;
|
|
77
|
-
this.last.prev = this.first;
|
|
78
|
-
this.first.next = newNode;
|
|
79
|
-
} else {
|
|
80
|
-
newNode.prev = this.last;
|
|
81
|
-
this.last.next = newNode;
|
|
82
|
-
this.last = newNode;
|
|
83
|
-
}
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
dequeue() {
|
|
87
|
-
if (!this.first)
|
|
88
|
-
return null;
|
|
89
|
-
if (this.first === this.last) {
|
|
90
|
-
const target2 = this.first;
|
|
91
|
-
this.first = null;
|
|
92
|
-
this.last = null;
|
|
93
|
-
return target2.value;
|
|
94
|
-
}
|
|
95
|
-
const target = this.first;
|
|
96
|
-
this.first = target.next;
|
|
97
|
-
if (this.first) {
|
|
98
|
-
this.first.prev = null;
|
|
99
|
-
}
|
|
100
|
-
return target.value;
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
55
|
|
|
104
56
|
// kinds.ts
|
|
105
57
|
var ClientAuth = 22242;
|
|
@@ -173,39 +125,6 @@ function makeAuthEvent(relayURL, challenge) {
|
|
|
173
125
|
};
|
|
174
126
|
}
|
|
175
127
|
|
|
176
|
-
// helpers.ts
|
|
177
|
-
async function yieldThread() {
|
|
178
|
-
return new Promise((resolve, reject) => {
|
|
179
|
-
try {
|
|
180
|
-
if (typeof MessageChannel !== "undefined") {
|
|
181
|
-
const ch = new MessageChannel();
|
|
182
|
-
const handler = () => {
|
|
183
|
-
ch.port1.removeEventListener("message", handler);
|
|
184
|
-
resolve();
|
|
185
|
-
};
|
|
186
|
-
ch.port1.addEventListener("message", handler);
|
|
187
|
-
ch.port2.postMessage(0);
|
|
188
|
-
ch.port1.start();
|
|
189
|
-
} else {
|
|
190
|
-
if (typeof setImmediate !== "undefined") {
|
|
191
|
-
setImmediate(resolve);
|
|
192
|
-
} else if (typeof setTimeout !== "undefined") {
|
|
193
|
-
setTimeout(resolve, 0);
|
|
194
|
-
} else {
|
|
195
|
-
resolve();
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
} catch (e) {
|
|
199
|
-
console.error("during yield: ", e);
|
|
200
|
-
reject(e);
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
var alwaysTrue = (t) => {
|
|
205
|
-
t[verifiedSymbol] = true;
|
|
206
|
-
return true;
|
|
207
|
-
};
|
|
208
|
-
|
|
209
128
|
// abstract-relay.ts
|
|
210
129
|
var SendingOnClosedConnection = class extends Error {
|
|
211
130
|
constructor(message, relay) {
|
|
@@ -227,16 +146,16 @@ var AbstractRelay = class {
|
|
|
227
146
|
openSubs = /* @__PURE__ */ new Map();
|
|
228
147
|
enablePing;
|
|
229
148
|
enableReconnect;
|
|
149
|
+
idleSince = Date.now();
|
|
150
|
+
ongoingOperations = 0;
|
|
230
151
|
reconnectTimeoutHandle;
|
|
231
152
|
pingIntervalHandle;
|
|
232
153
|
reconnectAttempts = 0;
|
|
233
|
-
|
|
154
|
+
skipReconnection = false;
|
|
234
155
|
connectionPromise;
|
|
235
156
|
openCountRequests = /* @__PURE__ */ new Map();
|
|
236
157
|
openEventPublishes = /* @__PURE__ */ new Map();
|
|
237
158
|
ws;
|
|
238
|
-
incomingMessageQueue = new Queue();
|
|
239
|
-
queueRunning = false;
|
|
240
159
|
challenge;
|
|
241
160
|
authPromise;
|
|
242
161
|
serial = 0;
|
|
@@ -288,12 +207,11 @@ var AbstractRelay = class {
|
|
|
288
207
|
}
|
|
289
208
|
this._connected = false;
|
|
290
209
|
this.connectionPromise = void 0;
|
|
291
|
-
|
|
292
|
-
this.
|
|
293
|
-
this.onclose?.();
|
|
294
|
-
if (this.enableReconnect && !wasIntentional) {
|
|
210
|
+
this.idleSince = void 0;
|
|
211
|
+
if (this.enableReconnect && !this.skipReconnection) {
|
|
295
212
|
this.reconnect();
|
|
296
213
|
} else {
|
|
214
|
+
this.onclose?.();
|
|
297
215
|
this.closeAllSubscriptions(reason);
|
|
298
216
|
}
|
|
299
217
|
}
|
|
@@ -303,13 +221,15 @@ var AbstractRelay = class {
|
|
|
303
221
|
return this.connectionPromise;
|
|
304
222
|
this.challenge = void 0;
|
|
305
223
|
this.authPromise = void 0;
|
|
224
|
+
this.skipReconnection = false;
|
|
306
225
|
this.connectionPromise = new Promise((resolve, reject) => {
|
|
307
226
|
if (opts?.timeout) {
|
|
308
227
|
connectionTimeoutHandle = setTimeout(() => {
|
|
309
228
|
reject("connection timed out");
|
|
310
229
|
this.connectionPromise = void 0;
|
|
230
|
+
this.skipReconnection = true;
|
|
311
231
|
this.onclose?.();
|
|
312
|
-
this.
|
|
232
|
+
this.handleHardClose("relay connection timed out");
|
|
313
233
|
}, opts.timeout);
|
|
314
234
|
}
|
|
315
235
|
if (opts?.abort) {
|
|
@@ -347,10 +267,13 @@ var AbstractRelay = class {
|
|
|
347
267
|
}
|
|
348
268
|
resolve();
|
|
349
269
|
};
|
|
350
|
-
this.ws.onerror = (
|
|
270
|
+
this.ws.onerror = () => {
|
|
351
271
|
clearTimeout(connectionTimeoutHandle);
|
|
352
|
-
reject(
|
|
353
|
-
this.
|
|
272
|
+
reject("connection failed");
|
|
273
|
+
this.connectionPromise = void 0;
|
|
274
|
+
this.skipReconnection = true;
|
|
275
|
+
this.onclose?.();
|
|
276
|
+
this.handleHardClose("relay connection failed");
|
|
354
277
|
};
|
|
355
278
|
this.ws.onclose = (ev) => {
|
|
356
279
|
clearTimeout(connectionTimeoutHandle);
|
|
@@ -376,7 +299,7 @@ var AbstractRelay = class {
|
|
|
376
299
|
const sub = this.subscribe(
|
|
377
300
|
[{ ids: ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], limit: 0 }],
|
|
378
301
|
{
|
|
379
|
-
label: "forced-ping",
|
|
302
|
+
label: "<forced-ping>",
|
|
380
303
|
oneose: () => {
|
|
381
304
|
resolve(true);
|
|
382
305
|
sub.close();
|
|
@@ -405,20 +328,106 @@ var AbstractRelay = class {
|
|
|
405
328
|
}
|
|
406
329
|
}
|
|
407
330
|
}
|
|
408
|
-
async
|
|
409
|
-
this.
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
331
|
+
async send(message) {
|
|
332
|
+
if (!this.connectionPromise)
|
|
333
|
+
throw new SendingOnClosedConnection(message, this.url);
|
|
334
|
+
this.connectionPromise.then(() => {
|
|
335
|
+
this.ws?.send(message);
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
async auth(signAuthEvent) {
|
|
339
|
+
const challenge = this.challenge;
|
|
340
|
+
if (!challenge)
|
|
341
|
+
throw new Error("can't perform auth, no challenge was received");
|
|
342
|
+
if (this.authPromise)
|
|
343
|
+
return this.authPromise;
|
|
344
|
+
this.authPromise = new Promise(async (resolve, reject) => {
|
|
345
|
+
try {
|
|
346
|
+
let evt = await signAuthEvent(makeAuthEvent(this.url, challenge));
|
|
347
|
+
let timeout = setTimeout(() => {
|
|
348
|
+
let ep = this.openEventPublishes.get(evt.id);
|
|
349
|
+
if (ep) {
|
|
350
|
+
ep.reject(new Error("auth timed out"));
|
|
351
|
+
this.openEventPublishes.delete(evt.id);
|
|
352
|
+
}
|
|
353
|
+
}, this.publishTimeout);
|
|
354
|
+
this.openEventPublishes.set(evt.id, { resolve, reject, timeout });
|
|
355
|
+
this.send('["AUTH",' + JSON.stringify(evt) + "]");
|
|
356
|
+
} catch (err) {
|
|
357
|
+
console.warn("subscribe auth function failed:", err);
|
|
413
358
|
}
|
|
414
|
-
|
|
359
|
+
});
|
|
360
|
+
return this.authPromise;
|
|
361
|
+
}
|
|
362
|
+
async publish(event) {
|
|
363
|
+
this.idleSince = void 0;
|
|
364
|
+
this.ongoingOperations++;
|
|
365
|
+
const ret = new Promise((resolve, reject) => {
|
|
366
|
+
const timeout = setTimeout(() => {
|
|
367
|
+
const ep = this.openEventPublishes.get(event.id);
|
|
368
|
+
if (ep) {
|
|
369
|
+
ep.reject(new Error("publish timed out"));
|
|
370
|
+
this.openEventPublishes.delete(event.id);
|
|
371
|
+
}
|
|
372
|
+
}, this.publishTimeout);
|
|
373
|
+
this.openEventPublishes.set(event.id, { resolve, reject, timeout });
|
|
374
|
+
});
|
|
375
|
+
this.send('["EVENT",' + JSON.stringify(event) + "]");
|
|
376
|
+
this.ongoingOperations--;
|
|
377
|
+
if (this.ongoingOperations === 0)
|
|
378
|
+
this.idleSince = Date.now();
|
|
379
|
+
return ret;
|
|
380
|
+
}
|
|
381
|
+
async count(filters, params) {
|
|
382
|
+
this.serial++;
|
|
383
|
+
const id = params?.id || "count:" + this.serial;
|
|
384
|
+
const ret = new Promise((resolve, reject) => {
|
|
385
|
+
this.openCountRequests.set(id, { resolve, reject });
|
|
386
|
+
});
|
|
387
|
+
this.send('["COUNT","' + id + '",' + JSON.stringify(filters).substring(1));
|
|
388
|
+
return ret;
|
|
389
|
+
}
|
|
390
|
+
subscribe(filters, params) {
|
|
391
|
+
if (params.label !== "<forced-ping>") {
|
|
392
|
+
this.idleSince = void 0;
|
|
393
|
+
this.ongoingOperations++;
|
|
394
|
+
}
|
|
395
|
+
const sub = this.prepareSubscription(filters, params);
|
|
396
|
+
sub.fire();
|
|
397
|
+
if (params.abort) {
|
|
398
|
+
params.abort.onabort = () => sub.close(String(params.abort.reason || "<aborted>"));
|
|
415
399
|
}
|
|
416
|
-
|
|
400
|
+
return sub;
|
|
417
401
|
}
|
|
418
|
-
|
|
419
|
-
|
|
402
|
+
prepareSubscription(filters, params) {
|
|
403
|
+
this.serial++;
|
|
404
|
+
const id = params.id || (params.label ? params.label + ":" : "sub:") + this.serial;
|
|
405
|
+
const sub = new Subscription(this, id, filters, params);
|
|
406
|
+
this.openSubs.set(id, sub);
|
|
407
|
+
return sub;
|
|
408
|
+
}
|
|
409
|
+
close() {
|
|
410
|
+
this.skipReconnection = true;
|
|
411
|
+
if (this.reconnectTimeoutHandle) {
|
|
412
|
+
clearTimeout(this.reconnectTimeoutHandle);
|
|
413
|
+
this.reconnectTimeoutHandle = void 0;
|
|
414
|
+
}
|
|
415
|
+
if (this.pingIntervalHandle) {
|
|
416
|
+
clearInterval(this.pingIntervalHandle);
|
|
417
|
+
this.pingIntervalHandle = void 0;
|
|
418
|
+
}
|
|
419
|
+
this.closeAllSubscriptions("relay connection closed by us");
|
|
420
|
+
this._connected = false;
|
|
421
|
+
this.idleSince = void 0;
|
|
422
|
+
this.onclose?.();
|
|
423
|
+
if (this.ws?.readyState === this._WebSocket.OPEN) {
|
|
424
|
+
this.ws?.close();
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
_onmessage(ev) {
|
|
428
|
+
const json = ev.data;
|
|
420
429
|
if (!json) {
|
|
421
|
-
return
|
|
430
|
+
return;
|
|
422
431
|
}
|
|
423
432
|
const subid = getSubscriptionId(json);
|
|
424
433
|
if (subid) {
|
|
@@ -505,101 +514,11 @@ var AbstractRelay = class {
|
|
|
505
514
|
}
|
|
506
515
|
}
|
|
507
516
|
} catch (err) {
|
|
517
|
+
const [_, __, event] = JSON.parse(json);
|
|
518
|
+
window.printer.maybe(event.pubkey, ":: caught err", event, this.url, err);
|
|
508
519
|
return;
|
|
509
520
|
}
|
|
510
521
|
}
|
|
511
|
-
async send(message) {
|
|
512
|
-
if (!this.connectionPromise)
|
|
513
|
-
throw new SendingOnClosedConnection(message, this.url);
|
|
514
|
-
this.connectionPromise.then(() => {
|
|
515
|
-
this.ws?.send(message);
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
async auth(signAuthEvent) {
|
|
519
|
-
const challenge = this.challenge;
|
|
520
|
-
if (!challenge)
|
|
521
|
-
throw new Error("can't perform auth, no challenge was received");
|
|
522
|
-
if (this.authPromise)
|
|
523
|
-
return this.authPromise;
|
|
524
|
-
this.authPromise = new Promise(async (resolve, reject) => {
|
|
525
|
-
try {
|
|
526
|
-
let evt = await signAuthEvent(makeAuthEvent(this.url, challenge));
|
|
527
|
-
let timeout = setTimeout(() => {
|
|
528
|
-
let ep = this.openEventPublishes.get(evt.id);
|
|
529
|
-
if (ep) {
|
|
530
|
-
ep.reject(new Error("auth timed out"));
|
|
531
|
-
this.openEventPublishes.delete(evt.id);
|
|
532
|
-
}
|
|
533
|
-
}, this.publishTimeout);
|
|
534
|
-
this.openEventPublishes.set(evt.id, { resolve, reject, timeout });
|
|
535
|
-
this.send('["AUTH",' + JSON.stringify(evt) + "]");
|
|
536
|
-
} catch (err) {
|
|
537
|
-
console.warn("subscribe auth function failed:", err);
|
|
538
|
-
}
|
|
539
|
-
});
|
|
540
|
-
return this.authPromise;
|
|
541
|
-
}
|
|
542
|
-
async publish(event) {
|
|
543
|
-
const ret = new Promise((resolve, reject) => {
|
|
544
|
-
const timeout = setTimeout(() => {
|
|
545
|
-
const ep = this.openEventPublishes.get(event.id);
|
|
546
|
-
if (ep) {
|
|
547
|
-
ep.reject(new Error("publish timed out"));
|
|
548
|
-
this.openEventPublishes.delete(event.id);
|
|
549
|
-
}
|
|
550
|
-
}, this.publishTimeout);
|
|
551
|
-
this.openEventPublishes.set(event.id, { resolve, reject, timeout });
|
|
552
|
-
});
|
|
553
|
-
this.send('["EVENT",' + JSON.stringify(event) + "]");
|
|
554
|
-
return ret;
|
|
555
|
-
}
|
|
556
|
-
async count(filters, params) {
|
|
557
|
-
this.serial++;
|
|
558
|
-
const id = params?.id || "count:" + this.serial;
|
|
559
|
-
const ret = new Promise((resolve, reject) => {
|
|
560
|
-
this.openCountRequests.set(id, { resolve, reject });
|
|
561
|
-
});
|
|
562
|
-
this.send('["COUNT","' + id + '",' + JSON.stringify(filters).substring(1));
|
|
563
|
-
return ret;
|
|
564
|
-
}
|
|
565
|
-
subscribe(filters, params) {
|
|
566
|
-
const sub = this.prepareSubscription(filters, params);
|
|
567
|
-
sub.fire();
|
|
568
|
-
if (params.abort) {
|
|
569
|
-
params.abort.onabort = () => sub.close(String(params.abort.reason || "<aborted>"));
|
|
570
|
-
}
|
|
571
|
-
return sub;
|
|
572
|
-
}
|
|
573
|
-
prepareSubscription(filters, params) {
|
|
574
|
-
this.serial++;
|
|
575
|
-
const id = params.id || (params.label ? params.label + ":" : "sub:") + this.serial;
|
|
576
|
-
const subscription = new Subscription(this, id, filters, params);
|
|
577
|
-
this.openSubs.set(id, subscription);
|
|
578
|
-
return subscription;
|
|
579
|
-
}
|
|
580
|
-
close() {
|
|
581
|
-
this.closedIntentionally = true;
|
|
582
|
-
if (this.reconnectTimeoutHandle) {
|
|
583
|
-
clearTimeout(this.reconnectTimeoutHandle);
|
|
584
|
-
this.reconnectTimeoutHandle = void 0;
|
|
585
|
-
}
|
|
586
|
-
if (this.pingIntervalHandle) {
|
|
587
|
-
clearInterval(this.pingIntervalHandle);
|
|
588
|
-
this.pingIntervalHandle = void 0;
|
|
589
|
-
}
|
|
590
|
-
this.closeAllSubscriptions("relay connection closed by us");
|
|
591
|
-
this._connected = false;
|
|
592
|
-
this.onclose?.();
|
|
593
|
-
if (this.ws?.readyState === this._WebSocket.OPEN) {
|
|
594
|
-
this.ws?.close();
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
_onmessage(ev) {
|
|
598
|
-
this.incomingMessageQueue.enqueue(ev.data);
|
|
599
|
-
if (!this.queueRunning) {
|
|
600
|
-
this.runQueue();
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
522
|
};
|
|
604
523
|
var Subscription = class {
|
|
605
524
|
relay;
|
|
@@ -658,10 +577,19 @@ var Subscription = class {
|
|
|
658
577
|
this.closed = true;
|
|
659
578
|
}
|
|
660
579
|
this.relay.openSubs.delete(this.id);
|
|
580
|
+
this.relay.ongoingOperations--;
|
|
581
|
+
if (this.relay.ongoingOperations === 0)
|
|
582
|
+
this.relay.idleSince = Date.now();
|
|
661
583
|
this.onclose?.(reason);
|
|
662
584
|
}
|
|
663
585
|
};
|
|
664
586
|
|
|
587
|
+
// helpers.ts
|
|
588
|
+
var alwaysTrue = (t) => {
|
|
589
|
+
t[verifiedSymbol] = true;
|
|
590
|
+
return true;
|
|
591
|
+
};
|
|
592
|
+
|
|
665
593
|
// abstract-pool.ts
|
|
666
594
|
var AbstractSimplePool = class {
|
|
667
595
|
relays = /* @__PURE__ */ new Map();
|
|
@@ -672,6 +600,10 @@ var AbstractSimplePool = class {
|
|
|
672
600
|
enableReconnect;
|
|
673
601
|
automaticallyAuth;
|
|
674
602
|
trustedRelayURLs = /* @__PURE__ */ new Set();
|
|
603
|
+
onRelayConnectionFailure;
|
|
604
|
+
onRelayConnectionSuccess;
|
|
605
|
+
allowConnectingToRelay;
|
|
606
|
+
maxWaitForConnection;
|
|
675
607
|
_WebSocket;
|
|
676
608
|
constructor(opts) {
|
|
677
609
|
this.verifyEvent = opts.verifyEvent;
|
|
@@ -679,6 +611,10 @@ var AbstractSimplePool = class {
|
|
|
679
611
|
this.enablePing = opts.enablePing;
|
|
680
612
|
this.enableReconnect = opts.enableReconnect || false;
|
|
681
613
|
this.automaticallyAuth = opts.automaticallyAuth;
|
|
614
|
+
this.onRelayConnectionFailure = opts.onRelayConnectionFailure;
|
|
615
|
+
this.onRelayConnectionSuccess = opts.onRelayConnectionSuccess;
|
|
616
|
+
this.allowConnectingToRelay = opts.allowConnectingToRelay;
|
|
617
|
+
this.maxWaitForConnection = opts.maxWaitForConnection || 3e3;
|
|
682
618
|
}
|
|
683
619
|
async ensureRelay(url, params) {
|
|
684
620
|
url = normalizeURL(url);
|
|
@@ -691,9 +627,7 @@ var AbstractSimplePool = class {
|
|
|
691
627
|
enableReconnect: this.enableReconnect
|
|
692
628
|
});
|
|
693
629
|
relay.onclose = () => {
|
|
694
|
-
|
|
695
|
-
this.relays.delete(url);
|
|
696
|
-
}
|
|
630
|
+
this.relays.delete(url);
|
|
697
631
|
};
|
|
698
632
|
this.relays.set(url, relay);
|
|
699
633
|
}
|
|
@@ -703,10 +637,15 @@ var AbstractSimplePool = class {
|
|
|
703
637
|
relay.onauth = authSignerFn;
|
|
704
638
|
}
|
|
705
639
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
640
|
+
try {
|
|
641
|
+
await relay.connect({
|
|
642
|
+
timeout: params?.connectionTimeout,
|
|
643
|
+
abort: params?.abort
|
|
644
|
+
});
|
|
645
|
+
} catch (err) {
|
|
646
|
+
this.relays.delete(url);
|
|
647
|
+
throw err;
|
|
648
|
+
}
|
|
710
649
|
return relay;
|
|
711
650
|
}
|
|
712
651
|
close(relays) {
|
|
@@ -717,25 +656,20 @@ var AbstractSimplePool = class {
|
|
|
717
656
|
}
|
|
718
657
|
subscribe(relays, filter, params) {
|
|
719
658
|
const request = [];
|
|
659
|
+
const uniqUrls = [];
|
|
720
660
|
for (let i = 0; i < relays.length; i++) {
|
|
721
661
|
const url = normalizeURL(relays[i]);
|
|
722
662
|
if (!request.find((r) => r.url === url)) {
|
|
723
|
-
|
|
663
|
+
if (uniqUrls.indexOf(url) === -1) {
|
|
664
|
+
uniqUrls.push(url);
|
|
665
|
+
request.push({ url, filter });
|
|
666
|
+
}
|
|
724
667
|
}
|
|
725
668
|
}
|
|
726
669
|
return this.subscribeMap(request, params);
|
|
727
670
|
}
|
|
728
671
|
subscribeMany(relays, filter, params) {
|
|
729
|
-
|
|
730
|
-
const uniqUrls = [];
|
|
731
|
-
for (let i = 0; i < relays.length; i++) {
|
|
732
|
-
const url = normalizeURL(relays[i]);
|
|
733
|
-
if (uniqUrls.indexOf(url) === -1) {
|
|
734
|
-
uniqUrls.push(url);
|
|
735
|
-
request.push({ url, filter });
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
return this.subscribeMap(request, params);
|
|
672
|
+
return this.subscribe(relays, filter, params);
|
|
739
673
|
}
|
|
740
674
|
subscribeMap(requests, params) {
|
|
741
675
|
const grouped = /* @__PURE__ */ new Map();
|
|
@@ -791,16 +725,22 @@ var AbstractSimplePool = class {
|
|
|
791
725
|
};
|
|
792
726
|
const allOpened = Promise.all(
|
|
793
727
|
groupedRequests.map(async ({ url, filters }, i) => {
|
|
728
|
+
if (this.allowConnectingToRelay?.(url, ["read", filters]) === false) {
|
|
729
|
+
handleClose(i, "connection skipped by allowConnectingToRelay");
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
794
732
|
let relay;
|
|
795
733
|
try {
|
|
796
734
|
relay = await this.ensureRelay(url, {
|
|
797
|
-
connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) :
|
|
735
|
+
connectionTimeout: this.maxWaitForConnection < (params.maxWait || 0) ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : this.maxWaitForConnection,
|
|
798
736
|
abort: params.abort
|
|
799
737
|
});
|
|
800
738
|
} catch (err) {
|
|
739
|
+
this.onRelayConnectionFailure?.(url);
|
|
801
740
|
handleClose(i, err?.message || String(err));
|
|
802
741
|
return;
|
|
803
742
|
}
|
|
743
|
+
this.onRelayConnectionSuccess?.(url);
|
|
804
744
|
let subscription = relay.subscribe(filters, {
|
|
805
745
|
...params,
|
|
806
746
|
oneose: () => handleEose(i),
|
|
@@ -850,13 +790,7 @@ var AbstractSimplePool = class {
|
|
|
850
790
|
return subcloser;
|
|
851
791
|
}
|
|
852
792
|
subscribeManyEose(relays, filter, params) {
|
|
853
|
-
|
|
854
|
-
...params,
|
|
855
|
-
oneose() {
|
|
856
|
-
subcloser.close("closed automatically on eose");
|
|
857
|
-
}
|
|
858
|
-
});
|
|
859
|
-
return subcloser;
|
|
793
|
+
return this.subscribeEose(relays, filter, params);
|
|
860
794
|
}
|
|
861
795
|
async querySync(relays, filter, params) {
|
|
862
796
|
return new Promise(async (resolve) => {
|
|
@@ -878,15 +812,27 @@ var AbstractSimplePool = class {
|
|
|
878
812
|
events.sort((a, b) => b.created_at - a.created_at);
|
|
879
813
|
return events[0] || null;
|
|
880
814
|
}
|
|
881
|
-
publish(relays, event,
|
|
815
|
+
publish(relays, event, params) {
|
|
882
816
|
return relays.map(normalizeURL).map(async (url, i, arr) => {
|
|
883
817
|
if (arr.indexOf(url) !== i) {
|
|
884
818
|
return Promise.reject("duplicate url");
|
|
885
819
|
}
|
|
886
|
-
|
|
820
|
+
if (this.allowConnectingToRelay?.(url, ["write", event]) === false) {
|
|
821
|
+
return Promise.reject("connection skipped by allowConnectingToRelay");
|
|
822
|
+
}
|
|
823
|
+
let r;
|
|
824
|
+
try {
|
|
825
|
+
r = await this.ensureRelay(url, {
|
|
826
|
+
connectionTimeout: this.maxWaitForConnection < (params?.maxWait || 0) ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : this.maxWaitForConnection,
|
|
827
|
+
abort: params?.abort
|
|
828
|
+
});
|
|
829
|
+
} catch (err) {
|
|
830
|
+
this.onRelayConnectionFailure?.(url);
|
|
831
|
+
return String("connection failure: " + String(err));
|
|
832
|
+
}
|
|
887
833
|
return r.publish(event).catch(async (err) => {
|
|
888
|
-
if (err instanceof Error && err.message.startsWith("auth-required: ") &&
|
|
889
|
-
await r.auth(
|
|
834
|
+
if (err instanceof Error && err.message.startsWith("auth-required: ") && params?.onauth) {
|
|
835
|
+
await r.auth(params.onauth);
|
|
890
836
|
return r.publish(event);
|
|
891
837
|
}
|
|
892
838
|
throw err;
|
|
@@ -912,4 +858,15 @@ var AbstractSimplePool = class {
|
|
|
912
858
|
this.relays.forEach((conn) => conn.close());
|
|
913
859
|
this.relays = /* @__PURE__ */ new Map();
|
|
914
860
|
}
|
|
861
|
+
pruneIdleRelays(idleThresholdMs = 1e4) {
|
|
862
|
+
const prunedUrls = [];
|
|
863
|
+
for (const [url, relay] of this.relays) {
|
|
864
|
+
if (relay.idleSince && Date.now() - relay.idleSince >= idleThresholdMs) {
|
|
865
|
+
this.relays.delete(url);
|
|
866
|
+
prunedUrls.push(url);
|
|
867
|
+
relay.close();
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
return prunedUrls;
|
|
871
|
+
}
|
|
915
872
|
};
|