nostr-tools 2.23.8 → 2.23.11
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 +163 -7
- package/lib/cjs/abstract-pool.js.map +4 -4
- package/lib/cjs/abstract-relay.js +59 -6
- package/lib/cjs/abstract-relay.js.map +2 -2
- package/lib/cjs/filter.js.map +1 -1
- package/lib/cjs/index.js +412 -64
- package/lib/cjs/index.js.map +4 -4
- package/lib/cjs/kinds.js +196 -4
- package/lib/cjs/kinds.js.map +2 -2
- package/lib/cjs/nip17.js.map +2 -2
- package/lib/cjs/nip18.js.map +2 -2
- package/lib/cjs/nip25.js.map +1 -1
- package/lib/cjs/nip28.js.map +2 -2
- package/lib/cjs/nip42.js.map +2 -2
- package/lib/cjs/nip45.js +183 -0
- package/lib/cjs/nip45.js.map +7 -0
- package/lib/cjs/nip46.js +163 -7
- package/lib/cjs/nip46.js.map +4 -4
- package/lib/cjs/nip47.js.map +2 -2
- package/lib/cjs/nip57.js.map +1 -1
- package/lib/cjs/nip58.js.map +2 -2
- package/lib/cjs/nip59.js.map +2 -2
- package/lib/cjs/nip75.js.map +2 -2
- package/lib/cjs/nip94.js.map +2 -2
- package/lib/cjs/nip98.js.map +2 -2
- package/lib/cjs/nip99.js.map +2 -2
- package/lib/cjs/nipb0.js +1064 -0
- package/lib/cjs/nipb0.js.map +7 -0
- package/lib/cjs/pool.js +163 -7
- package/lib/cjs/pool.js.map +4 -4
- package/lib/cjs/relay.js +59 -6
- package/lib/cjs/relay.js.map +2 -2
- package/lib/esm/abstract-pool.js +163 -7
- package/lib/esm/abstract-pool.js.map +4 -4
- package/lib/esm/abstract-relay.js +59 -6
- package/lib/esm/abstract-relay.js.map +2 -2
- package/lib/esm/filter.js.map +1 -1
- package/lib/esm/index.js +388 -40
- package/lib/esm/index.js.map +4 -4
- package/lib/esm/kinds.js +196 -4
- package/lib/esm/kinds.js.map +2 -2
- package/lib/esm/nip17.js.map +2 -2
- package/lib/esm/nip18.js.map +2 -2
- package/lib/esm/nip25.js.map +1 -1
- package/lib/esm/nip28.js.map +2 -2
- package/lib/esm/nip42.js.map +2 -2
- package/lib/esm/nip45.js +162 -0
- package/lib/esm/nip45.js.map +7 -0
- package/lib/esm/nip46.js +163 -7
- package/lib/esm/nip46.js.map +4 -4
- package/lib/esm/nip47.js.map +2 -2
- package/lib/esm/nip57.js.map +1 -1
- package/lib/esm/nip58.js.map +2 -2
- package/lib/esm/nip59.js.map +2 -2
- package/lib/esm/nip75.js.map +2 -2
- package/lib/esm/nip94.js.map +2 -2
- package/lib/esm/nip98.js.map +2 -2
- package/lib/esm/nip99.js.map +2 -2
- package/lib/esm/nipb0.js +1049 -0
- package/lib/esm/nipb0.js.map +7 -0
- package/lib/esm/pool.js +163 -7
- package/lib/esm/pool.js.map +4 -4
- package/lib/esm/relay.js +59 -6
- package/lib/esm/relay.js.map +2 -2
- package/lib/nostr.bundle.js +361 -15
- package/lib/nostr.bundle.js.map +4 -4
- package/lib/types/abstract-pool.d.ts +10 -0
- package/lib/types/abstract-relay.d.ts +15 -1
- package/lib/types/kinds.d.ts +200 -8
- package/lib/types/nip45.d.ts +13 -0
- package/lib/types/nip45.test.d.ts +1 -0
- package/lib/types/nipb0.d.ts +129 -0
- package/lib/types/relay.d.ts +2 -2
- package/package.json +13 -1
package/lib/cjs/abstract-pool.js
CHANGED
|
@@ -146,12 +146,14 @@ var AbstractRelay = class {
|
|
|
146
146
|
openSubs = /* @__PURE__ */ new Map();
|
|
147
147
|
enablePing;
|
|
148
148
|
enableReconnect;
|
|
149
|
+
idleTimeout = 0;
|
|
149
150
|
idleSince = Date.now();
|
|
150
151
|
ongoingOperations = 0;
|
|
151
152
|
reconnectTimeoutHandle;
|
|
152
153
|
pingIntervalHandle;
|
|
153
154
|
reconnectAttempts = 0;
|
|
154
155
|
skipReconnection = false;
|
|
156
|
+
idleTimeoutHandle;
|
|
155
157
|
connectionPromise;
|
|
156
158
|
openCountRequests = /* @__PURE__ */ new Map();
|
|
157
159
|
openEventPublishes = /* @__PURE__ */ new Map();
|
|
@@ -167,6 +169,8 @@ var AbstractRelay = class {
|
|
|
167
169
|
this._WebSocket = opts.websocketImplementation || WebSocket;
|
|
168
170
|
this.enablePing = opts.enablePing;
|
|
169
171
|
this.enableReconnect = opts.enableReconnect || false;
|
|
172
|
+
if (opts.idleTimeout)
|
|
173
|
+
this.idleTimeout = opts.idleTimeout;
|
|
170
174
|
}
|
|
171
175
|
static async connect(url, opts) {
|
|
172
176
|
const relay = new AbstractRelay(url, opts);
|
|
@@ -190,6 +194,22 @@ var AbstractRelay = class {
|
|
|
190
194
|
get connected() {
|
|
191
195
|
return this._connected;
|
|
192
196
|
}
|
|
197
|
+
clearIdleTimeout() {
|
|
198
|
+
if (this.idleTimeoutHandle) {
|
|
199
|
+
clearTimeout(this.idleTimeoutHandle);
|
|
200
|
+
this.idleTimeoutHandle = void 0;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
scheduleIdleClose() {
|
|
204
|
+
this.clearIdleTimeout();
|
|
205
|
+
if (this.idleTimeout > 0) {
|
|
206
|
+
this.idleTimeoutHandle = setTimeout(() => {
|
|
207
|
+
if (this.ongoingOperations === 0 && this.idleSince) {
|
|
208
|
+
this.close();
|
|
209
|
+
}
|
|
210
|
+
}, this.idleTimeout);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
193
213
|
async reconnect() {
|
|
194
214
|
const backoff = this.resubscribeBackoff[Math.min(this.reconnectAttempts, this.resubscribeBackoff.length - 1)];
|
|
195
215
|
this.reconnectAttempts++;
|
|
@@ -208,6 +228,7 @@ var AbstractRelay = class {
|
|
|
208
228
|
this._connected = false;
|
|
209
229
|
this.connectionPromise = void 0;
|
|
210
230
|
this.idleSince = void 0;
|
|
231
|
+
this.clearIdleTimeout();
|
|
211
232
|
if (this.enableReconnect && !this.skipReconnection) {
|
|
212
233
|
this.reconnect();
|
|
213
234
|
} else {
|
|
@@ -365,6 +386,7 @@ var AbstractRelay = class {
|
|
|
365
386
|
}
|
|
366
387
|
async publish(event) {
|
|
367
388
|
this.idleSince = void 0;
|
|
389
|
+
this.clearIdleTimeout();
|
|
368
390
|
this.ongoingOperations++;
|
|
369
391
|
const ret = new Promise((resolve, reject) => {
|
|
370
392
|
const timeout = setTimeout(() => {
|
|
@@ -376,24 +398,46 @@ var AbstractRelay = class {
|
|
|
376
398
|
}, this.publishTimeout);
|
|
377
399
|
this.openEventPublishes.set(event.id, { resolve, reject, timeout });
|
|
378
400
|
});
|
|
379
|
-
|
|
401
|
+
try {
|
|
402
|
+
await this.send('["EVENT",' + JSON.stringify(event) + "]");
|
|
403
|
+
} catch (err) {
|
|
404
|
+
const ep = this.openEventPublishes.get(event.id);
|
|
405
|
+
if (ep) {
|
|
406
|
+
ep.reject(err);
|
|
407
|
+
this.openEventPublishes.delete(event.id);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
380
410
|
this.ongoingOperations--;
|
|
381
|
-
if (this.ongoingOperations === 0)
|
|
411
|
+
if (this.ongoingOperations === 0) {
|
|
382
412
|
this.idleSince = Date.now();
|
|
413
|
+
this.scheduleIdleClose();
|
|
414
|
+
}
|
|
383
415
|
return ret;
|
|
384
416
|
}
|
|
385
417
|
async count(filters, params) {
|
|
418
|
+
return (await this.countWithHLL(filters, params)).count;
|
|
419
|
+
}
|
|
420
|
+
async countWithHLL(filters, params) {
|
|
386
421
|
this.serial++;
|
|
387
422
|
const id = params?.id || "count:" + this.serial;
|
|
388
423
|
const ret = new Promise((resolve, reject) => {
|
|
389
424
|
this.openCountRequests.set(id, { resolve, reject });
|
|
390
425
|
});
|
|
391
|
-
|
|
426
|
+
try {
|
|
427
|
+
await this.send('["COUNT","' + id + '",' + JSON.stringify(filters).substring(1));
|
|
428
|
+
} catch (err) {
|
|
429
|
+
const cr = this.openCountRequests.get(id);
|
|
430
|
+
if (cr) {
|
|
431
|
+
cr.reject(err);
|
|
432
|
+
this.openCountRequests.delete(id);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
392
435
|
return ret;
|
|
393
436
|
}
|
|
394
437
|
subscribe(filters, params) {
|
|
395
438
|
if (params.label !== "<forced-ping>") {
|
|
396
439
|
this.idleSince = void 0;
|
|
440
|
+
this.clearIdleTimeout();
|
|
397
441
|
this.ongoingOperations++;
|
|
398
442
|
}
|
|
399
443
|
const sub = this.prepareSubscription(filters, params);
|
|
@@ -423,6 +467,7 @@ var AbstractRelay = class {
|
|
|
423
467
|
this.closeAllSubscriptions("relay connection closed by us");
|
|
424
468
|
this._connected = false;
|
|
425
469
|
this.idleSince = void 0;
|
|
470
|
+
this.clearIdleTimeout();
|
|
426
471
|
this.onclose?.();
|
|
427
472
|
if (this.ws?.readyState === this._WebSocket.OPEN) {
|
|
428
473
|
this.ws?.close();
|
|
@@ -466,7 +511,7 @@ var AbstractRelay = class {
|
|
|
466
511
|
const payload = data[2];
|
|
467
512
|
const cr = this.openCountRequests.get(id);
|
|
468
513
|
if (cr) {
|
|
469
|
-
cr.resolve(payload
|
|
514
|
+
cr.resolve(payload);
|
|
470
515
|
this.openCountRequests.delete(id);
|
|
471
516
|
}
|
|
472
517
|
return;
|
|
@@ -496,8 +541,14 @@ var AbstractRelay = class {
|
|
|
496
541
|
case "CLOSED": {
|
|
497
542
|
const id = data[1];
|
|
498
543
|
const so = this.openSubs.get(id);
|
|
499
|
-
if (!so)
|
|
544
|
+
if (!so) {
|
|
545
|
+
const cr = this.openCountRequests.get(id);
|
|
546
|
+
if (cr) {
|
|
547
|
+
cr.reject(new Error(data[2]));
|
|
548
|
+
this.openCountRequests.delete(id);
|
|
549
|
+
}
|
|
500
550
|
return;
|
|
551
|
+
}
|
|
501
552
|
so.closed = true;
|
|
502
553
|
so.close(data[2]);
|
|
503
554
|
return;
|
|
@@ -594,8 +645,10 @@ var Subscription = class {
|
|
|
594
645
|
}
|
|
595
646
|
this.relay.openSubs.delete(this.id);
|
|
596
647
|
this.relay.ongoingOperations--;
|
|
597
|
-
if (this.relay.ongoingOperations === 0)
|
|
648
|
+
if (this.relay.ongoingOperations === 0) {
|
|
598
649
|
this.relay.idleSince = Date.now();
|
|
650
|
+
this.relay.scheduleIdleClose();
|
|
651
|
+
}
|
|
599
652
|
this.onclose?.(reason);
|
|
600
653
|
}
|
|
601
654
|
};
|
|
@@ -606,6 +659,63 @@ var alwaysTrue = (t) => {
|
|
|
606
659
|
return true;
|
|
607
660
|
};
|
|
608
661
|
|
|
662
|
+
// nip45.ts
|
|
663
|
+
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
664
|
+
var import_utils3 = require("@noble/hashes/utils.js");
|
|
665
|
+
var M = 256;
|
|
666
|
+
var HLL_HEX_LENGTH = M * 2;
|
|
667
|
+
var utf8Encoder2 = new TextEncoder();
|
|
668
|
+
function getCountManyFilter(target, directive) {
|
|
669
|
+
switch (directive) {
|
|
670
|
+
case "reactions":
|
|
671
|
+
return { "#e": [target], kinds: [7] };
|
|
672
|
+
case "reposts":
|
|
673
|
+
return { "#e": [target], kinds: [6] };
|
|
674
|
+
case "quotes":
|
|
675
|
+
return { "#q": [target], kinds: [1, 1111] };
|
|
676
|
+
case "replies":
|
|
677
|
+
return { "#e": [target], kinds: [1] };
|
|
678
|
+
case "comments":
|
|
679
|
+
return { "#E": [target], kinds: [1111] };
|
|
680
|
+
case "followers":
|
|
681
|
+
return { "#p": [target], kinds: [3] };
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
function newHll() {
|
|
685
|
+
return new Uint8Array(M);
|
|
686
|
+
}
|
|
687
|
+
function hllDecode(hex) {
|
|
688
|
+
if (hex.length !== HLL_HEX_LENGTH || !/^[0-9a-fA-F]+$/.test(hex))
|
|
689
|
+
return void 0;
|
|
690
|
+
const registers = new Uint8Array(M);
|
|
691
|
+
for (let i = 0; i < M; i++) {
|
|
692
|
+
registers[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
693
|
+
}
|
|
694
|
+
return registers;
|
|
695
|
+
}
|
|
696
|
+
function hllEncode(registers) {
|
|
697
|
+
if (registers.length !== M)
|
|
698
|
+
throw new Error(`invalid number of registers ${registers.length}`);
|
|
699
|
+
let hex = "";
|
|
700
|
+
for (let i = 0; i < M; i++) {
|
|
701
|
+
hex += registers[i].toString(16).padStart(2, "0");
|
|
702
|
+
}
|
|
703
|
+
return hex;
|
|
704
|
+
}
|
|
705
|
+
function mergeHll(target, source) {
|
|
706
|
+
if (target.length === 0)
|
|
707
|
+
target = newHll();
|
|
708
|
+
if (target.length !== M)
|
|
709
|
+
throw new Error(`invalid number of registers ${target.length}`);
|
|
710
|
+
if (source.length !== M)
|
|
711
|
+
throw new Error(`invalid number of registers ${source.length}`);
|
|
712
|
+
for (let i = 0; i < M; i++) {
|
|
713
|
+
if (source[i] > target[i])
|
|
714
|
+
target[i] = source[i];
|
|
715
|
+
}
|
|
716
|
+
return target;
|
|
717
|
+
}
|
|
718
|
+
|
|
609
719
|
// abstract-pool.ts
|
|
610
720
|
var AbstractSimplePool = class {
|
|
611
721
|
relays = /* @__PURE__ */ new Map();
|
|
@@ -614,6 +724,7 @@ var AbstractSimplePool = class {
|
|
|
614
724
|
verifyEvent;
|
|
615
725
|
enablePing;
|
|
616
726
|
enableReconnect;
|
|
727
|
+
idleTimeout = 2e4;
|
|
617
728
|
automaticallyAuth;
|
|
618
729
|
trustedRelayURLs = /* @__PURE__ */ new Set();
|
|
619
730
|
onRelayConnectionFailure;
|
|
@@ -626,6 +737,8 @@ var AbstractSimplePool = class {
|
|
|
626
737
|
this._WebSocket = opts.websocketImplementation;
|
|
627
738
|
this.enablePing = opts.enablePing;
|
|
628
739
|
this.enableReconnect = opts.enableReconnect || false;
|
|
740
|
+
if (opts.idleTimeout)
|
|
741
|
+
this.idleTimeout = opts.idleTimeout;
|
|
629
742
|
this.automaticallyAuth = opts.automaticallyAuth;
|
|
630
743
|
this.onRelayConnectionFailure = opts.onRelayConnectionFailure;
|
|
631
744
|
this.onRelayConnectionSuccess = opts.onRelayConnectionSuccess;
|
|
@@ -640,7 +753,8 @@ var AbstractSimplePool = class {
|
|
|
640
753
|
verifyEvent: this.trustedRelayURLs.has(url) ? alwaysTrue : this.verifyEvent,
|
|
641
754
|
websocketImplementation: this._WebSocket,
|
|
642
755
|
enablePing: this.enablePing,
|
|
643
|
-
enableReconnect: this.enableReconnect
|
|
756
|
+
enableReconnect: this.enableReconnect,
|
|
757
|
+
idleTimeout: this.idleTimeout
|
|
644
758
|
});
|
|
645
759
|
relay.onclose = () => {
|
|
646
760
|
this.relays.delete(url);
|
|
@@ -833,6 +947,48 @@ var AbstractSimplePool = class {
|
|
|
833
947
|
events.sort((a, b) => b.created_at - a.created_at);
|
|
834
948
|
return events[0] || null;
|
|
835
949
|
}
|
|
950
|
+
async countMany(relays, target, directive, params) {
|
|
951
|
+
const filter = getCountManyFilter(target, directive);
|
|
952
|
+
const urls = [];
|
|
953
|
+
for (let i = 0; i < relays.length; i++) {
|
|
954
|
+
const url = normalizeURL(relays[i]);
|
|
955
|
+
if (urls.indexOf(url) === -1)
|
|
956
|
+
urls.push(url);
|
|
957
|
+
}
|
|
958
|
+
const responses = await Promise.all(
|
|
959
|
+
urls.map(async (url) => {
|
|
960
|
+
if (this.allowConnectingToRelay?.(url, ["read", [filter]]) === false)
|
|
961
|
+
return null;
|
|
962
|
+
let relay;
|
|
963
|
+
try {
|
|
964
|
+
relay = await this.ensureRelay(url, {
|
|
965
|
+
connectionTimeout: this.maxWaitForConnection < (params?.maxWait || 0) ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : this.maxWaitForConnection,
|
|
966
|
+
abort: params?.abort
|
|
967
|
+
});
|
|
968
|
+
} catch (err) {
|
|
969
|
+
this.onRelayConnectionFailure?.(url);
|
|
970
|
+
return null;
|
|
971
|
+
}
|
|
972
|
+
this.onRelayConnectionSuccess?.(url);
|
|
973
|
+
return relay.countWithHLL([filter], { id: params?.id }).catch(() => null);
|
|
974
|
+
})
|
|
975
|
+
);
|
|
976
|
+
let count = 0;
|
|
977
|
+
let hll;
|
|
978
|
+
for (const response of responses) {
|
|
979
|
+
if (!response)
|
|
980
|
+
continue;
|
|
981
|
+
if (response.count > count)
|
|
982
|
+
count = response.count;
|
|
983
|
+
if (!response.hll || response.hll.length !== 512)
|
|
984
|
+
continue;
|
|
985
|
+
const registers = hllDecode(response.hll);
|
|
986
|
+
if (!registers)
|
|
987
|
+
continue;
|
|
988
|
+
hll = mergeHll(hll || new Uint8Array(0), registers);
|
|
989
|
+
}
|
|
990
|
+
return hll ? { count, hll: hllEncode(hll) } : { count };
|
|
991
|
+
}
|
|
836
992
|
publish(relays, event, params) {
|
|
837
993
|
return relays.map(normalizeURL).map(async (url, i, arr) => {
|
|
838
994
|
if (arr.indexOf(url) !== i) {
|