@unicitylabs/sphere-sdk 0.6.10-dev.4 → 0.6.10-dev.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.cjs +82 -41
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +82 -41
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +2 -2
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +2 -2
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +2 -2
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.js +2 -2
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +82 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +82 -41
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +32 -0
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.js +32 -0
- package/dist/l1/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -559,6 +559,33 @@ function waitForConnection() {
|
|
|
559
559
|
connectionCallbacks.push(callback);
|
|
560
560
|
});
|
|
561
561
|
}
|
|
562
|
+
function startPingTimer() {
|
|
563
|
+
stopPingTimer();
|
|
564
|
+
pingTimer = setInterval(() => {
|
|
565
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
566
|
+
try {
|
|
567
|
+
const id = ++requestId;
|
|
568
|
+
ws.send(JSON.stringify({ jsonrpc: "2.0", id, method: "server.ping", params: [] }));
|
|
569
|
+
pending[id] = {
|
|
570
|
+
resolve: () => {
|
|
571
|
+
},
|
|
572
|
+
reject: () => {
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
const timeoutId = setTimeout(() => {
|
|
576
|
+
delete pending[id];
|
|
577
|
+
}, 1e4);
|
|
578
|
+
pending[id].timeoutId = timeoutId;
|
|
579
|
+
} catch {
|
|
580
|
+
}
|
|
581
|
+
}, PING_INTERVAL);
|
|
582
|
+
}
|
|
583
|
+
function stopPingTimer() {
|
|
584
|
+
if (pingTimer) {
|
|
585
|
+
clearInterval(pingTimer);
|
|
586
|
+
pingTimer = null;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
562
589
|
function connect(endpoint = DEFAULT_ENDPOINT) {
|
|
563
590
|
if (isConnected) {
|
|
564
591
|
return Promise.resolve();
|
|
@@ -581,6 +608,7 @@ function connect(endpoint = DEFAULT_ENDPOINT) {
|
|
|
581
608
|
isConnected = true;
|
|
582
609
|
isConnecting = false;
|
|
583
610
|
reconnectAttempts = 0;
|
|
611
|
+
startPingTimer();
|
|
584
612
|
hasResolved = true;
|
|
585
613
|
resolve();
|
|
586
614
|
connectionCallbacks.forEach((cb) => {
|
|
@@ -592,6 +620,7 @@ function connect(endpoint = DEFAULT_ENDPOINT) {
|
|
|
592
620
|
ws.onclose = () => {
|
|
593
621
|
isConnected = false;
|
|
594
622
|
isBlockSubscribed = false;
|
|
623
|
+
stopPingTimer();
|
|
595
624
|
Object.values(pending).forEach((req) => {
|
|
596
625
|
if (req.timeoutId) clearTimeout(req.timeoutId);
|
|
597
626
|
req.reject(new Error("WebSocket connection closed"));
|
|
@@ -774,6 +803,7 @@ async function getCurrentBlockHeight() {
|
|
|
774
803
|
}
|
|
775
804
|
}
|
|
776
805
|
function disconnect() {
|
|
806
|
+
stopPingTimer();
|
|
777
807
|
if (ws) {
|
|
778
808
|
intentionalClose = true;
|
|
779
809
|
ws.close();
|
|
@@ -794,7 +824,7 @@ function disconnect() {
|
|
|
794
824
|
blockSubscribers.length = 0;
|
|
795
825
|
lastBlockHeader = null;
|
|
796
826
|
}
|
|
797
|
-
var DEFAULT_ENDPOINT, ws, isConnected, isConnecting, requestId, intentionalClose, reconnectAttempts, isBlockSubscribed, lastBlockHeader, pending, blockSubscribers, connectionCallbacks, MAX_RECONNECT_ATTEMPTS, BASE_DELAY, MAX_DELAY, RPC_TIMEOUT, CONNECTION_TIMEOUT;
|
|
827
|
+
var DEFAULT_ENDPOINT, ws, isConnected, isConnecting, requestId, intentionalClose, reconnectAttempts, isBlockSubscribed, lastBlockHeader, pingTimer, pending, blockSubscribers, connectionCallbacks, MAX_RECONNECT_ATTEMPTS, BASE_DELAY, MAX_DELAY, RPC_TIMEOUT, CONNECTION_TIMEOUT, PING_INTERVAL;
|
|
798
828
|
var init_network = __esm({
|
|
799
829
|
"l1/network.ts"() {
|
|
800
830
|
"use strict";
|
|
@@ -810,6 +840,7 @@ var init_network = __esm({
|
|
|
810
840
|
reconnectAttempts = 0;
|
|
811
841
|
isBlockSubscribed = false;
|
|
812
842
|
lastBlockHeader = null;
|
|
843
|
+
pingTimer = null;
|
|
813
844
|
pending = {};
|
|
814
845
|
blockSubscribers = [];
|
|
815
846
|
connectionCallbacks = [];
|
|
@@ -818,6 +849,7 @@ var init_network = __esm({
|
|
|
818
849
|
MAX_DELAY = 6e4;
|
|
819
850
|
RPC_TIMEOUT = 3e4;
|
|
820
851
|
CONNECTION_TIMEOUT = 3e4;
|
|
852
|
+
PING_INTERVAL = 3e4;
|
|
821
853
|
}
|
|
822
854
|
});
|
|
823
855
|
|
|
@@ -2612,9 +2644,9 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
2612
2644
|
if (subId) {
|
|
2613
2645
|
this.nostrClient?.unsubscribe(subId);
|
|
2614
2646
|
}
|
|
2615
|
-
logger.warn("Nostr", `queryEvents timed out after
|
|
2647
|
+
logger.warn("Nostr", `queryEvents timed out after 15s, returning ${events.length} event(s)`, { kinds: filterObj.kinds, limit: filterObj.limit });
|
|
2616
2648
|
resolve(events);
|
|
2617
|
-
},
|
|
2649
|
+
}, 15e3);
|
|
2618
2650
|
const subId = this.nostrClient.subscribe(filter, {
|
|
2619
2651
|
onEvent: (event) => {
|
|
2620
2652
|
events.push({
|
|
@@ -12530,6 +12562,15 @@ var GroupChatModule = class {
|
|
|
12530
12562
|
}
|
|
12531
12563
|
destroy() {
|
|
12532
12564
|
this.destroyConnection();
|
|
12565
|
+
if (this.persistTimer) {
|
|
12566
|
+
clearTimeout(this.persistTimer);
|
|
12567
|
+
this.persistTimer = null;
|
|
12568
|
+
if (this.deps) {
|
|
12569
|
+
this.doPersistAll().catch(
|
|
12570
|
+
(err) => logger.debug("GroupChat", "Persist on destroy failed", err)
|
|
12571
|
+
);
|
|
12572
|
+
}
|
|
12573
|
+
}
|
|
12533
12574
|
this.groups.clear();
|
|
12534
12575
|
this.messages.clear();
|
|
12535
12576
|
this.members.clear();
|
|
@@ -12538,10 +12579,7 @@ var GroupChatModule = class {
|
|
|
12538
12579
|
this.messageHandlers.clear();
|
|
12539
12580
|
this.relayAdminPubkeys = null;
|
|
12540
12581
|
this.relayAdminFetchPromise = null;
|
|
12541
|
-
|
|
12542
|
-
clearTimeout(this.persistTimer);
|
|
12543
|
-
this.persistTimer = null;
|
|
12544
|
-
}
|
|
12582
|
+
this.persistPromise = null;
|
|
12545
12583
|
this.deps = null;
|
|
12546
12584
|
}
|
|
12547
12585
|
destroyConnection() {
|
|
@@ -12666,12 +12704,12 @@ var GroupChatModule = class {
|
|
|
12666
12704
|
if (!this.client) return;
|
|
12667
12705
|
const groupIds = Array.from(this.groups.keys());
|
|
12668
12706
|
if (groupIds.length === 0) return;
|
|
12669
|
-
const
|
|
12707
|
+
const sinceTimestamp = this.getLatestKnownTimestamp(groupIds);
|
|
12670
12708
|
this.trackSubscription(
|
|
12671
12709
|
createNip29Filter({
|
|
12672
12710
|
kinds: [NIP29_KINDS.CHAT_MESSAGE, NIP29_KINDS.THREAD_ROOT, NIP29_KINDS.THREAD_REPLY],
|
|
12673
12711
|
"#h": groupIds,
|
|
12674
|
-
...
|
|
12712
|
+
...sinceTimestamp ? { since: sinceTimestamp } : {}
|
|
12675
12713
|
}),
|
|
12676
12714
|
{ onEvent: (event) => this.handleGroupEvent(event) }
|
|
12677
12715
|
);
|
|
@@ -12692,12 +12730,12 @@ var GroupChatModule = class {
|
|
|
12692
12730
|
}
|
|
12693
12731
|
subscribeToGroup(groupId) {
|
|
12694
12732
|
if (!this.client) return;
|
|
12695
|
-
const
|
|
12733
|
+
const sinceTimestamp = this.getLatestKnownTimestamp([groupId]);
|
|
12696
12734
|
this.trackSubscription(
|
|
12697
12735
|
createNip29Filter({
|
|
12698
12736
|
kinds: [NIP29_KINDS.CHAT_MESSAGE, NIP29_KINDS.THREAD_ROOT, NIP29_KINDS.THREAD_REPLY],
|
|
12699
12737
|
"#h": [groupId],
|
|
12700
|
-
...
|
|
12738
|
+
...sinceTimestamp ? { since: sinceTimestamp } : {}
|
|
12701
12739
|
}),
|
|
12702
12740
|
{ onEvent: (event) => this.handleGroupEvent(event) }
|
|
12703
12741
|
);
|
|
@@ -12771,7 +12809,7 @@ var GroupChatModule = class {
|
|
|
12771
12809
|
}
|
|
12772
12810
|
group.updatedAt = event.created_at * 1e3;
|
|
12773
12811
|
this.groups.set(groupId, group);
|
|
12774
|
-
this.
|
|
12812
|
+
this.schedulePersist();
|
|
12775
12813
|
} else if (event.kind === NIP29_KINDS.GROUP_MEMBERS) {
|
|
12776
12814
|
this.updateMembersFromEvent(groupId, event);
|
|
12777
12815
|
} else if (event.kind === NIP29_KINDS.GROUP_ADMINS) {
|
|
@@ -12792,7 +12830,7 @@ var GroupChatModule = class {
|
|
|
12792
12830
|
}
|
|
12793
12831
|
}
|
|
12794
12832
|
this.deps.emitEvent("groupchat:updated", {});
|
|
12795
|
-
this.
|
|
12833
|
+
this.schedulePersist();
|
|
12796
12834
|
} else if (event.kind === NIP29_KINDS.REMOVE_USER) {
|
|
12797
12835
|
if (this.processedEventIds.has(event.id)) return;
|
|
12798
12836
|
const eventTimestampMs = event.created_at * 1e3;
|
|
@@ -12853,7 +12891,7 @@ var GroupChatModule = class {
|
|
|
12853
12891
|
};
|
|
12854
12892
|
this.saveMemberToMemory(member);
|
|
12855
12893
|
}
|
|
12856
|
-
this.
|
|
12894
|
+
this.schedulePersist();
|
|
12857
12895
|
}
|
|
12858
12896
|
updateAdminsFromEvent(groupId, event) {
|
|
12859
12897
|
const pTags = event.tags.filter((t) => t[0] === "p");
|
|
@@ -12873,7 +12911,7 @@ var GroupChatModule = class {
|
|
|
12873
12911
|
});
|
|
12874
12912
|
}
|
|
12875
12913
|
}
|
|
12876
|
-
this.
|
|
12914
|
+
this.schedulePersist();
|
|
12877
12915
|
}
|
|
12878
12916
|
// ===========================================================================
|
|
12879
12917
|
// Group Membership Restoration
|
|
@@ -12884,13 +12922,11 @@ var GroupChatModule = class {
|
|
|
12884
12922
|
if (!myPubkey) return [];
|
|
12885
12923
|
const groupIdsWithMembership = /* @__PURE__ */ new Set();
|
|
12886
12924
|
await this.oneshotSubscription(
|
|
12887
|
-
|
|
12925
|
+
createNip29Filter({ kinds: [NIP29_KINDS.GROUP_MEMBERS], "#p": [myPubkey] }),
|
|
12888
12926
|
{
|
|
12889
12927
|
onEvent: (event) => {
|
|
12890
12928
|
const groupId = this.getGroupIdFromMetadataEvent(event);
|
|
12891
|
-
if (
|
|
12892
|
-
const pTags = event.tags.filter((t) => t[0] === "p");
|
|
12893
|
-
if (pTags.some((tag) => tag[1] === myPubkey)) {
|
|
12929
|
+
if (groupId) {
|
|
12894
12930
|
groupIdsWithMembership.add(groupId);
|
|
12895
12931
|
}
|
|
12896
12932
|
},
|
|
@@ -12902,22 +12938,24 @@ var GroupChatModule = class {
|
|
|
12902
12938
|
);
|
|
12903
12939
|
if (groupIdsWithMembership.size === 0) return [];
|
|
12904
12940
|
const restoredGroups = [];
|
|
12905
|
-
|
|
12906
|
-
|
|
12907
|
-
|
|
12908
|
-
|
|
12909
|
-
|
|
12910
|
-
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
|
|
12914
|
-
|
|
12915
|
-
|
|
12941
|
+
await Promise.all(
|
|
12942
|
+
Array.from(groupIdsWithMembership).map(async (groupId) => {
|
|
12943
|
+
if (this.groups.has(groupId)) return;
|
|
12944
|
+
try {
|
|
12945
|
+
const group = await this.fetchGroupMetadataInternal(groupId);
|
|
12946
|
+
if (group) {
|
|
12947
|
+
this.groups.set(groupId, group);
|
|
12948
|
+
restoredGroups.push(group);
|
|
12949
|
+
await Promise.all([
|
|
12950
|
+
this.fetchAndSaveMembers(groupId),
|
|
12951
|
+
this.fetchMessages(groupId)
|
|
12952
|
+
]);
|
|
12953
|
+
}
|
|
12954
|
+
} catch (error) {
|
|
12955
|
+
logger.warn("GroupChat", "Failed to restore group", groupId, error);
|
|
12916
12956
|
}
|
|
12917
|
-
}
|
|
12918
|
-
|
|
12919
|
-
}
|
|
12920
|
-
}
|
|
12957
|
+
})
|
|
12958
|
+
);
|
|
12921
12959
|
if (restoredGroups.length > 0) {
|
|
12922
12960
|
await this.subscribeToJoinedGroups();
|
|
12923
12961
|
this.deps.emitEvent("groupchat:updated", {});
|
|
@@ -13303,7 +13341,7 @@ var GroupChatModule = class {
|
|
|
13303
13341
|
if (group && (group.unreadCount || 0) > 0) {
|
|
13304
13342
|
group.unreadCount = 0;
|
|
13305
13343
|
this.groups.set(groupId, group);
|
|
13306
|
-
this.
|
|
13344
|
+
this.schedulePersist();
|
|
13307
13345
|
}
|
|
13308
13346
|
}
|
|
13309
13347
|
// ===========================================================================
|
|
@@ -13325,7 +13363,7 @@ var GroupChatModule = class {
|
|
|
13325
13363
|
if (eventId) {
|
|
13326
13364
|
this.removeMemberFromMemory(groupId, userPubkey);
|
|
13327
13365
|
this.deps.emitEvent("groupchat:updated", {});
|
|
13328
|
-
this.
|
|
13366
|
+
this.schedulePersist();
|
|
13329
13367
|
return true;
|
|
13330
13368
|
}
|
|
13331
13369
|
return false;
|
|
@@ -13348,7 +13386,7 @@ var GroupChatModule = class {
|
|
|
13348
13386
|
if (eventId) {
|
|
13349
13387
|
this.deleteMessageFromMemory(groupId, messageId);
|
|
13350
13388
|
this.deps.emitEvent("groupchat:updated", {});
|
|
13351
|
-
this.
|
|
13389
|
+
this.schedulePersist();
|
|
13352
13390
|
return true;
|
|
13353
13391
|
}
|
|
13354
13392
|
return false;
|
|
@@ -13428,7 +13466,7 @@ var GroupChatModule = class {
|
|
|
13428
13466
|
* or 0 if no messages exist. Used to set `since` on subscriptions so the relay
|
|
13429
13467
|
* only sends events we don't already have.
|
|
13430
13468
|
*/
|
|
13431
|
-
|
|
13469
|
+
getLatestKnownTimestamp(groupIds) {
|
|
13432
13470
|
let latest = 0;
|
|
13433
13471
|
for (const gid of groupIds) {
|
|
13434
13472
|
const msgs = this.messages.get(gid);
|
|
@@ -13509,7 +13547,7 @@ var GroupChatModule = class {
|
|
|
13509
13547
|
});
|
|
13510
13548
|
}
|
|
13511
13549
|
}
|
|
13512
|
-
this.
|
|
13550
|
+
this.schedulePersist();
|
|
13513
13551
|
}
|
|
13514
13552
|
async fetchGroupMembersInternal(groupId) {
|
|
13515
13553
|
if (!this.client) return [];
|
|
@@ -13636,8 +13674,11 @@ var GroupChatModule = class {
|
|
|
13636
13674
|
addProcessedEventId(eventId) {
|
|
13637
13675
|
this.processedEventIds.add(eventId);
|
|
13638
13676
|
if (this.processedEventIds.size > 1e4) {
|
|
13639
|
-
|
|
13640
|
-
|
|
13677
|
+
let toDelete = 5e3;
|
|
13678
|
+
for (const id of this.processedEventIds) {
|
|
13679
|
+
if (toDelete-- <= 0) break;
|
|
13680
|
+
this.processedEventIds.delete(id);
|
|
13681
|
+
}
|
|
13641
13682
|
}
|
|
13642
13683
|
}
|
|
13643
13684
|
// ===========================================================================
|