@unicitylabs/sphere-sdk 0.6.8-dev.1 → 0.6.8-dev.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.
- package/README.md +30 -0
- package/dist/connect/index.cjs +2 -0
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.js +2 -0
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +140 -6
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +18 -0
- package/dist/core/index.d.ts +18 -0
- package/dist/core/index.js +140 -6
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/connect/index.cjs +2 -0
- package/dist/impl/browser/connect/index.cjs.map +1 -1
- package/dist/impl/browser/connect/index.js +2 -0
- package/dist/impl/browser/connect/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +66 -0
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +66 -0
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/browser/ipfs.cjs +2 -0
- package/dist/impl/browser/ipfs.cjs.map +1 -1
- package/dist/impl/browser/ipfs.js +2 -0
- package/dist/impl/browser/ipfs.js.map +1 -1
- package/dist/impl/nodejs/connect/index.cjs +2 -0
- package/dist/impl/nodejs/connect/index.cjs.map +1 -1
- package/dist/impl/nodejs/connect/index.js +2 -0
- package/dist/impl/nodejs/connect/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +66 -0
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +15 -0
- package/dist/impl/nodejs/index.d.ts +15 -0
- package/dist/impl/nodejs/index.js +66 -0
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +140 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +140 -6
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +2 -0
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.js +2 -0
- package/dist/l1/index.js.map +1 -1
- package/package.json +1 -1
package/dist/core/index.cjs
CHANGED
|
@@ -191,6 +191,8 @@ var init_constants = __esm({
|
|
|
191
191
|
TRACKED_ADDRESSES: "tracked_addresses",
|
|
192
192
|
/** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
|
|
193
193
|
LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
|
|
194
|
+
/** Last processed Nostr DM (gift-wrap) event timestamp (unix seconds), keyed per pubkey */
|
|
195
|
+
LAST_DM_EVENT_TS: "last_dm_event_ts",
|
|
194
196
|
/** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
|
|
195
197
|
GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
|
|
196
198
|
/** Cached token registry JSON (fetched from remote) */
|
|
@@ -1314,8 +1316,12 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
1314
1316
|
storage = null;
|
|
1315
1317
|
/** In-memory max event timestamp to avoid read-before-write races in updateLastEventTimestamp. */
|
|
1316
1318
|
lastEventTs = 0;
|
|
1319
|
+
/** In-memory max DM (gift-wrap) event timestamp. */
|
|
1320
|
+
lastDmEventTs = 0;
|
|
1317
1321
|
/** Fallback 'since' timestamp for first-time address subscriptions (consumed once). */
|
|
1318
1322
|
fallbackSince = null;
|
|
1323
|
+
/** Fallback 'since' timestamp for DM (gift-wrap) subscriptions (consumed once). */
|
|
1324
|
+
fallbackDmSince = null;
|
|
1319
1325
|
identity = null;
|
|
1320
1326
|
keyManager = null;
|
|
1321
1327
|
status = "disconnected";
|
|
@@ -1570,6 +1576,8 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
1570
1576
|
this.identity = identity;
|
|
1571
1577
|
this.processedEventIds.clear();
|
|
1572
1578
|
this.lastEventTs = 0;
|
|
1579
|
+
this.lastDmEventTs = 0;
|
|
1580
|
+
this.fallbackDmSince = null;
|
|
1573
1581
|
const secretKey = import_buffer.Buffer.from(identity.privateKey, "hex");
|
|
1574
1582
|
this.keyManager = import_nostr_js_sdk.NostrKeyManager.fromPrivateKey(secretKey);
|
|
1575
1583
|
const nostrPubkey = this.keyManager.getPublicKeyHex();
|
|
@@ -1615,6 +1623,9 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
1615
1623
|
setFallbackSince(sinceSeconds) {
|
|
1616
1624
|
this.fallbackSince = sinceSeconds;
|
|
1617
1625
|
}
|
|
1626
|
+
setFallbackDmSince(sinceSeconds) {
|
|
1627
|
+
this.fallbackDmSince = sinceSeconds;
|
|
1628
|
+
}
|
|
1618
1629
|
/**
|
|
1619
1630
|
* Get the Nostr-format public key (32 bytes / 64 hex chars)
|
|
1620
1631
|
* This is the x-coordinate only, without the 02/03 prefix.
|
|
@@ -2149,6 +2160,17 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
2149
2160
|
logger.debug("Nostr", "Failed to save last event timestamp:", err);
|
|
2150
2161
|
});
|
|
2151
2162
|
}
|
|
2163
|
+
/** Persist the max DM (gift-wrap) event timestamp for the since filter on next connect. */
|
|
2164
|
+
updateLastDmEventTimestamp(createdAt) {
|
|
2165
|
+
if (!this.storage || !this.keyManager) return;
|
|
2166
|
+
if (createdAt <= this.lastDmEventTs) return;
|
|
2167
|
+
this.lastDmEventTs = createdAt;
|
|
2168
|
+
const pubkey = this.keyManager.getPublicKeyHex();
|
|
2169
|
+
const storageKey = `${STORAGE_KEYS_GLOBAL.LAST_DM_EVENT_TS}_${pubkey.slice(0, 16)}`;
|
|
2170
|
+
this.storage.set(storageKey, createdAt.toString()).catch((err) => {
|
|
2171
|
+
logger.debug("Nostr", "Failed to save last DM event timestamp:", err);
|
|
2172
|
+
});
|
|
2173
|
+
}
|
|
2152
2174
|
async handleDirectMessage(event) {
|
|
2153
2175
|
logger.debug("Nostr", "Ignoring NIP-04 kind 4 event (DMs use NIP-17):", event.id?.slice(0, 12));
|
|
2154
2176
|
}
|
|
@@ -2159,6 +2181,9 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
2159
2181
|
}
|
|
2160
2182
|
try {
|
|
2161
2183
|
const pm = import_nostr_js_sdk.NIP17.unwrap(event, this.keyManager);
|
|
2184
|
+
if (event.created_at) {
|
|
2185
|
+
this.updateLastDmEventTimestamp(event.created_at);
|
|
2186
|
+
}
|
|
2162
2187
|
logger.debug("Nostr", "Gift wrap unwrapped, sender:", pm.senderPubkey?.slice(0, 16), "kind:", pm.kind);
|
|
2163
2188
|
if (pm.senderPubkey === this.keyManager.getPublicKeyHex()) {
|
|
2164
2189
|
try {
|
|
@@ -2605,9 +2630,50 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
2605
2630
|
}
|
|
2606
2631
|
});
|
|
2607
2632
|
logger.debug("Nostr", "Wallet subscription created, subId:", this.walletSubscriptionId);
|
|
2633
|
+
let dmSince;
|
|
2634
|
+
if (this.storage) {
|
|
2635
|
+
const dmStorageKey = `${STORAGE_KEYS_GLOBAL.LAST_DM_EVENT_TS}_${nostrPubkey.slice(0, 16)}`;
|
|
2636
|
+
try {
|
|
2637
|
+
const stored = await this.storage.get(dmStorageKey);
|
|
2638
|
+
const parsed = stored ? parseInt(stored, 10) : NaN;
|
|
2639
|
+
if (Number.isFinite(parsed)) {
|
|
2640
|
+
dmSince = parsed;
|
|
2641
|
+
this.lastDmEventTs = dmSince;
|
|
2642
|
+
this.fallbackDmSince = null;
|
|
2643
|
+
logger.debug("Nostr", "DM resuming from stored timestamp:", dmSince);
|
|
2644
|
+
} else if (this.fallbackDmSince !== null) {
|
|
2645
|
+
dmSince = this.fallbackDmSince;
|
|
2646
|
+
this.lastDmEventTs = dmSince;
|
|
2647
|
+
this.fallbackDmSince = null;
|
|
2648
|
+
logger.debug("Nostr", "DM using fallback since timestamp:", dmSince);
|
|
2649
|
+
} else {
|
|
2650
|
+
dmSince = Math.floor(Date.now() / 1e3);
|
|
2651
|
+
logger.debug("Nostr", "No stored DM timestamp, starting from now:", dmSince);
|
|
2652
|
+
}
|
|
2653
|
+
} catch (err) {
|
|
2654
|
+
if (this.fallbackDmSince !== null) {
|
|
2655
|
+
dmSince = this.fallbackDmSince;
|
|
2656
|
+
this.lastDmEventTs = dmSince;
|
|
2657
|
+
this.fallbackDmSince = null;
|
|
2658
|
+
logger.debug("Nostr", "Storage read failed, using DM fallback since:", dmSince, err);
|
|
2659
|
+
} else {
|
|
2660
|
+
dmSince = Math.floor(Date.now() / 1e3);
|
|
2661
|
+
logger.debug("Nostr", "Failed to read last DM event timestamp, falling back to now:", err);
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
} else if (this.fallbackDmSince !== null) {
|
|
2665
|
+
dmSince = this.fallbackDmSince;
|
|
2666
|
+
this.lastDmEventTs = dmSince;
|
|
2667
|
+
this.fallbackDmSince = null;
|
|
2668
|
+
logger.debug("Nostr", "No storage adapter for DM, using fallback since:", dmSince);
|
|
2669
|
+
} else {
|
|
2670
|
+
dmSince = Math.floor(Date.now() / 1e3);
|
|
2671
|
+
logger.debug("Nostr", "No storage adapter for DM, starting from now:", dmSince);
|
|
2672
|
+
}
|
|
2608
2673
|
const chatFilter = new import_nostr_js_sdk.Filter();
|
|
2609
2674
|
chatFilter.kinds = [import_nostr_js_sdk.EventKinds.GIFT_WRAP];
|
|
2610
2675
|
chatFilter["#p"] = [nostrPubkey];
|
|
2676
|
+
chatFilter.since = dmSince;
|
|
2611
2677
|
this.chatSubscriptionId = this.nostrClient.subscribe(chatFilter, {
|
|
2612
2678
|
onEvent: (event) => {
|
|
2613
2679
|
logger.debug("Nostr", "Received chat event kind:", event.kind, "id:", event.id?.slice(0, 12));
|
|
@@ -2852,7 +2918,9 @@ var MultiAddressTransportMux = class {
|
|
|
2852
2918
|
nostrPubkey,
|
|
2853
2919
|
adapter,
|
|
2854
2920
|
lastEventTs: 0,
|
|
2855
|
-
|
|
2921
|
+
lastDmEventTs: 0,
|
|
2922
|
+
fallbackSince: null,
|
|
2923
|
+
fallbackDmSince: null
|
|
2856
2924
|
};
|
|
2857
2925
|
this.addresses.set(index, entry);
|
|
2858
2926
|
this.pubkeyToIndex.set(nostrPubkey, index);
|
|
@@ -2894,6 +2962,12 @@ var MultiAddressTransportMux = class {
|
|
|
2894
2962
|
entry.fallbackSince = sinceSeconds;
|
|
2895
2963
|
}
|
|
2896
2964
|
}
|
|
2965
|
+
setFallbackDmSince(index, sinceSeconds) {
|
|
2966
|
+
const entry = this.addresses.get(index);
|
|
2967
|
+
if (entry) {
|
|
2968
|
+
entry.fallbackDmSince = sinceSeconds;
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2897
2971
|
// ===========================================================================
|
|
2898
2972
|
// Connection Management (delegated from adapters)
|
|
2899
2973
|
// ===========================================================================
|
|
@@ -3029,11 +3103,20 @@ var MultiAddressTransportMux = class {
|
|
|
3029
3103
|
}
|
|
3030
3104
|
logger.debug("Mux", `Subscribing for ${allPubkeys.length} address(es):`, allPubkeys.map((p) => p.slice(0, 12)).join(", "));
|
|
3031
3105
|
let globalSince = Math.floor(Date.now() / 1e3);
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3106
|
+
let globalDmSince = Math.floor(Date.now() / 1e3);
|
|
3107
|
+
const entries = [...this.addresses.values()];
|
|
3108
|
+
const sinceResults = await Promise.all(
|
|
3109
|
+
entries.map(async (entry) => {
|
|
3110
|
+
const [walletSince, dmSince] = await Promise.all([
|
|
3111
|
+
this.getAddressSince(entry),
|
|
3112
|
+
this.getAddressDmSince(entry)
|
|
3113
|
+
]);
|
|
3114
|
+
return { walletSince, dmSince };
|
|
3115
|
+
})
|
|
3116
|
+
);
|
|
3117
|
+
for (const { walletSince, dmSince } of sinceResults) {
|
|
3118
|
+
if (walletSince < globalSince) globalSince = walletSince;
|
|
3119
|
+
if (dmSince < globalDmSince) globalDmSince = dmSince;
|
|
3037
3120
|
}
|
|
3038
3121
|
const walletFilter = new import_nostr_js_sdk2.Filter();
|
|
3039
3122
|
walletFilter.kinds = [
|
|
@@ -3066,6 +3149,7 @@ var MultiAddressTransportMux = class {
|
|
|
3066
3149
|
const chatFilter = new import_nostr_js_sdk2.Filter();
|
|
3067
3150
|
chatFilter.kinds = [import_nostr_js_sdk2.EventKinds.GIFT_WRAP];
|
|
3068
3151
|
chatFilter["#p"] = allPubkeys;
|
|
3152
|
+
chatFilter.since = globalDmSince;
|
|
3069
3153
|
this.chatSubscriptionId = this.nostrClient.subscribe(chatFilter, {
|
|
3070
3154
|
onEvent: (event) => {
|
|
3071
3155
|
this.handleEvent({
|
|
@@ -3172,6 +3256,9 @@ var MultiAddressTransportMux = class {
|
|
|
3172
3256
|
for (const entry of this.addresses.values()) {
|
|
3173
3257
|
try {
|
|
3174
3258
|
const pm = import_nostr_js_sdk2.NIP17.unwrap(event, entry.keyManager);
|
|
3259
|
+
if (event.created_at) {
|
|
3260
|
+
this.updateLastDmEventTimestamp(entry, event.created_at);
|
|
3261
|
+
}
|
|
3175
3262
|
logger.debug("Mux", `Gift wrap decrypted by address ${entry.index}, sender: ${pm.senderPubkey?.slice(0, 16)}`);
|
|
3176
3263
|
if (pm.senderPubkey === entry.nostrPubkey) {
|
|
3177
3264
|
try {
|
|
@@ -3528,6 +3615,47 @@ var MultiAddressTransportMux = class {
|
|
|
3528
3615
|
logger.debug("Mux", "Failed to save last event timestamp:", err);
|
|
3529
3616
|
});
|
|
3530
3617
|
}
|
|
3618
|
+
updateLastDmEventTimestamp(entry, createdAt) {
|
|
3619
|
+
if (!this.storage) return;
|
|
3620
|
+
if (createdAt <= entry.lastDmEventTs) return;
|
|
3621
|
+
entry.lastDmEventTs = createdAt;
|
|
3622
|
+
const storageKey = `${STORAGE_KEYS_GLOBAL.LAST_DM_EVENT_TS}_${entry.nostrPubkey.slice(0, 16)}`;
|
|
3623
|
+
this.storage.set(storageKey, createdAt.toString()).catch((err) => {
|
|
3624
|
+
logger.debug("Mux", "Failed to save last DM event timestamp:", err);
|
|
3625
|
+
});
|
|
3626
|
+
}
|
|
3627
|
+
async getAddressDmSince(entry) {
|
|
3628
|
+
if (this.storage) {
|
|
3629
|
+
const storageKey = `${STORAGE_KEYS_GLOBAL.LAST_DM_EVENT_TS}_${entry.nostrPubkey.slice(0, 16)}`;
|
|
3630
|
+
try {
|
|
3631
|
+
const stored = await this.storage.get(storageKey);
|
|
3632
|
+
const parsed = stored ? parseInt(stored, 10) : NaN;
|
|
3633
|
+
if (Number.isFinite(parsed)) {
|
|
3634
|
+
entry.lastDmEventTs = parsed;
|
|
3635
|
+
entry.fallbackDmSince = null;
|
|
3636
|
+
return parsed;
|
|
3637
|
+
} else if (entry.fallbackDmSince !== null) {
|
|
3638
|
+
const ts = entry.fallbackDmSince;
|
|
3639
|
+
entry.lastDmEventTs = ts;
|
|
3640
|
+
entry.fallbackDmSince = null;
|
|
3641
|
+
return ts;
|
|
3642
|
+
}
|
|
3643
|
+
} catch {
|
|
3644
|
+
if (entry.fallbackDmSince !== null) {
|
|
3645
|
+
const ts = entry.fallbackDmSince;
|
|
3646
|
+
entry.lastDmEventTs = ts;
|
|
3647
|
+
entry.fallbackDmSince = null;
|
|
3648
|
+
return ts;
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
} else if (entry.fallbackDmSince !== null) {
|
|
3652
|
+
const ts = entry.fallbackDmSince;
|
|
3653
|
+
entry.lastDmEventTs = ts;
|
|
3654
|
+
entry.fallbackDmSince = null;
|
|
3655
|
+
return ts;
|
|
3656
|
+
}
|
|
3657
|
+
return Math.floor(Date.now() / 1e3);
|
|
3658
|
+
}
|
|
3531
3659
|
// ===========================================================================
|
|
3532
3660
|
// Mux-level event system
|
|
3533
3661
|
// ===========================================================================
|
|
@@ -3824,6 +3952,9 @@ var AddressTransportAdapter = class {
|
|
|
3824
3952
|
setFallbackSince(sinceSeconds) {
|
|
3825
3953
|
this.mux.setFallbackSince(this.addressIndex, sinceSeconds);
|
|
3826
3954
|
}
|
|
3955
|
+
setFallbackDmSince(sinceSeconds) {
|
|
3956
|
+
this.mux.setFallbackDmSince(this.addressIndex, sinceSeconds);
|
|
3957
|
+
}
|
|
3827
3958
|
async fetchPendingEvents() {
|
|
3828
3959
|
}
|
|
3829
3960
|
onChatReady(handler) {
|
|
@@ -16569,6 +16700,9 @@ var Sphere = class _Sphere {
|
|
|
16569
16700
|
const groupChat = _Sphere.resolveGroupChatConfig(options.groupChat, options.network);
|
|
16570
16701
|
const market = _Sphere.resolveMarketConfig(options.market);
|
|
16571
16702
|
const walletExists = await _Sphere.exists(options.storage);
|
|
16703
|
+
if (options.dmSince != null && options.transport.setFallbackDmSince) {
|
|
16704
|
+
options.transport.setFallbackDmSince(options.dmSince);
|
|
16705
|
+
}
|
|
16572
16706
|
if (walletExists) {
|
|
16573
16707
|
const sphere2 = await _Sphere.load({
|
|
16574
16708
|
storage: options.storage,
|