@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/index.cjs
CHANGED
|
@@ -195,6 +195,8 @@ var init_constants = __esm({
|
|
|
195
195
|
TRACKED_ADDRESSES: "tracked_addresses",
|
|
196
196
|
/** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
|
|
197
197
|
LAST_WALLET_EVENT_TS: "last_wallet_event_ts",
|
|
198
|
+
/** Last processed Nostr DM (gift-wrap) event timestamp (unix seconds), keyed per pubkey */
|
|
199
|
+
LAST_DM_EVENT_TS: "last_dm_event_ts",
|
|
198
200
|
/** Group chat: last used relay URL (stale data detection) — global, same relay for all addresses */
|
|
199
201
|
GROUP_CHAT_RELAY_URL: "group_chat_relay_url",
|
|
200
202
|
/** Cached token registry JSON (fetched from remote) */
|
|
@@ -1412,8 +1414,12 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
1412
1414
|
storage = null;
|
|
1413
1415
|
/** In-memory max event timestamp to avoid read-before-write races in updateLastEventTimestamp. */
|
|
1414
1416
|
lastEventTs = 0;
|
|
1417
|
+
/** In-memory max DM (gift-wrap) event timestamp. */
|
|
1418
|
+
lastDmEventTs = 0;
|
|
1415
1419
|
/** Fallback 'since' timestamp for first-time address subscriptions (consumed once). */
|
|
1416
1420
|
fallbackSince = null;
|
|
1421
|
+
/** Fallback 'since' timestamp for DM (gift-wrap) subscriptions (consumed once). */
|
|
1422
|
+
fallbackDmSince = null;
|
|
1417
1423
|
identity = null;
|
|
1418
1424
|
keyManager = null;
|
|
1419
1425
|
status = "disconnected";
|
|
@@ -1668,6 +1674,8 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
1668
1674
|
this.identity = identity;
|
|
1669
1675
|
this.processedEventIds.clear();
|
|
1670
1676
|
this.lastEventTs = 0;
|
|
1677
|
+
this.lastDmEventTs = 0;
|
|
1678
|
+
this.fallbackDmSince = null;
|
|
1671
1679
|
const secretKey = import_buffer.Buffer.from(identity.privateKey, "hex");
|
|
1672
1680
|
this.keyManager = import_nostr_js_sdk.NostrKeyManager.fromPrivateKey(secretKey);
|
|
1673
1681
|
const nostrPubkey = this.keyManager.getPublicKeyHex();
|
|
@@ -1713,6 +1721,9 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
1713
1721
|
setFallbackSince(sinceSeconds) {
|
|
1714
1722
|
this.fallbackSince = sinceSeconds;
|
|
1715
1723
|
}
|
|
1724
|
+
setFallbackDmSince(sinceSeconds) {
|
|
1725
|
+
this.fallbackDmSince = sinceSeconds;
|
|
1726
|
+
}
|
|
1716
1727
|
/**
|
|
1717
1728
|
* Get the Nostr-format public key (32 bytes / 64 hex chars)
|
|
1718
1729
|
* This is the x-coordinate only, without the 02/03 prefix.
|
|
@@ -2247,6 +2258,17 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
2247
2258
|
logger.debug("Nostr", "Failed to save last event timestamp:", err);
|
|
2248
2259
|
});
|
|
2249
2260
|
}
|
|
2261
|
+
/** Persist the max DM (gift-wrap) event timestamp for the since filter on next connect. */
|
|
2262
|
+
updateLastDmEventTimestamp(createdAt) {
|
|
2263
|
+
if (!this.storage || !this.keyManager) return;
|
|
2264
|
+
if (createdAt <= this.lastDmEventTs) return;
|
|
2265
|
+
this.lastDmEventTs = createdAt;
|
|
2266
|
+
const pubkey = this.keyManager.getPublicKeyHex();
|
|
2267
|
+
const storageKey = `${STORAGE_KEYS_GLOBAL.LAST_DM_EVENT_TS}_${pubkey.slice(0, 16)}`;
|
|
2268
|
+
this.storage.set(storageKey, createdAt.toString()).catch((err) => {
|
|
2269
|
+
logger.debug("Nostr", "Failed to save last DM event timestamp:", err);
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2250
2272
|
async handleDirectMessage(event) {
|
|
2251
2273
|
logger.debug("Nostr", "Ignoring NIP-04 kind 4 event (DMs use NIP-17):", event.id?.slice(0, 12));
|
|
2252
2274
|
}
|
|
@@ -2257,6 +2279,9 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
2257
2279
|
}
|
|
2258
2280
|
try {
|
|
2259
2281
|
const pm = import_nostr_js_sdk.NIP17.unwrap(event, this.keyManager);
|
|
2282
|
+
if (event.created_at) {
|
|
2283
|
+
this.updateLastDmEventTimestamp(event.created_at);
|
|
2284
|
+
}
|
|
2260
2285
|
logger.debug("Nostr", "Gift wrap unwrapped, sender:", pm.senderPubkey?.slice(0, 16), "kind:", pm.kind);
|
|
2261
2286
|
if (pm.senderPubkey === this.keyManager.getPublicKeyHex()) {
|
|
2262
2287
|
try {
|
|
@@ -2703,9 +2728,50 @@ var NostrTransportProvider = class _NostrTransportProvider {
|
|
|
2703
2728
|
}
|
|
2704
2729
|
});
|
|
2705
2730
|
logger.debug("Nostr", "Wallet subscription created, subId:", this.walletSubscriptionId);
|
|
2731
|
+
let dmSince;
|
|
2732
|
+
if (this.storage) {
|
|
2733
|
+
const dmStorageKey = `${STORAGE_KEYS_GLOBAL.LAST_DM_EVENT_TS}_${nostrPubkey.slice(0, 16)}`;
|
|
2734
|
+
try {
|
|
2735
|
+
const stored = await this.storage.get(dmStorageKey);
|
|
2736
|
+
const parsed = stored ? parseInt(stored, 10) : NaN;
|
|
2737
|
+
if (Number.isFinite(parsed)) {
|
|
2738
|
+
dmSince = parsed;
|
|
2739
|
+
this.lastDmEventTs = dmSince;
|
|
2740
|
+
this.fallbackDmSince = null;
|
|
2741
|
+
logger.debug("Nostr", "DM resuming from stored timestamp:", dmSince);
|
|
2742
|
+
} else if (this.fallbackDmSince !== null) {
|
|
2743
|
+
dmSince = this.fallbackDmSince;
|
|
2744
|
+
this.lastDmEventTs = dmSince;
|
|
2745
|
+
this.fallbackDmSince = null;
|
|
2746
|
+
logger.debug("Nostr", "DM using fallback since timestamp:", dmSince);
|
|
2747
|
+
} else {
|
|
2748
|
+
dmSince = Math.floor(Date.now() / 1e3);
|
|
2749
|
+
logger.debug("Nostr", "No stored DM timestamp, starting from now:", dmSince);
|
|
2750
|
+
}
|
|
2751
|
+
} catch (err) {
|
|
2752
|
+
if (this.fallbackDmSince !== null) {
|
|
2753
|
+
dmSince = this.fallbackDmSince;
|
|
2754
|
+
this.lastDmEventTs = dmSince;
|
|
2755
|
+
this.fallbackDmSince = null;
|
|
2756
|
+
logger.debug("Nostr", "Storage read failed, using DM fallback since:", dmSince, err);
|
|
2757
|
+
} else {
|
|
2758
|
+
dmSince = Math.floor(Date.now() / 1e3);
|
|
2759
|
+
logger.debug("Nostr", "Failed to read last DM event timestamp, falling back to now:", err);
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
} else if (this.fallbackDmSince !== null) {
|
|
2763
|
+
dmSince = this.fallbackDmSince;
|
|
2764
|
+
this.lastDmEventTs = dmSince;
|
|
2765
|
+
this.fallbackDmSince = null;
|
|
2766
|
+
logger.debug("Nostr", "No storage adapter for DM, using fallback since:", dmSince);
|
|
2767
|
+
} else {
|
|
2768
|
+
dmSince = Math.floor(Date.now() / 1e3);
|
|
2769
|
+
logger.debug("Nostr", "No storage adapter for DM, starting from now:", dmSince);
|
|
2770
|
+
}
|
|
2706
2771
|
const chatFilter = new import_nostr_js_sdk.Filter();
|
|
2707
2772
|
chatFilter.kinds = [import_nostr_js_sdk.EventKinds.GIFT_WRAP];
|
|
2708
2773
|
chatFilter["#p"] = [nostrPubkey];
|
|
2774
|
+
chatFilter.since = dmSince;
|
|
2709
2775
|
this.chatSubscriptionId = this.nostrClient.subscribe(chatFilter, {
|
|
2710
2776
|
onEvent: (event) => {
|
|
2711
2777
|
logger.debug("Nostr", "Received chat event kind:", event.kind, "id:", event.id?.slice(0, 12));
|
|
@@ -2950,7 +3016,9 @@ var MultiAddressTransportMux = class {
|
|
|
2950
3016
|
nostrPubkey,
|
|
2951
3017
|
adapter,
|
|
2952
3018
|
lastEventTs: 0,
|
|
2953
|
-
|
|
3019
|
+
lastDmEventTs: 0,
|
|
3020
|
+
fallbackSince: null,
|
|
3021
|
+
fallbackDmSince: null
|
|
2954
3022
|
};
|
|
2955
3023
|
this.addresses.set(index, entry);
|
|
2956
3024
|
this.pubkeyToIndex.set(nostrPubkey, index);
|
|
@@ -2992,6 +3060,12 @@ var MultiAddressTransportMux = class {
|
|
|
2992
3060
|
entry.fallbackSince = sinceSeconds;
|
|
2993
3061
|
}
|
|
2994
3062
|
}
|
|
3063
|
+
setFallbackDmSince(index, sinceSeconds) {
|
|
3064
|
+
const entry = this.addresses.get(index);
|
|
3065
|
+
if (entry) {
|
|
3066
|
+
entry.fallbackDmSince = sinceSeconds;
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
2995
3069
|
// ===========================================================================
|
|
2996
3070
|
// Connection Management (delegated from adapters)
|
|
2997
3071
|
// ===========================================================================
|
|
@@ -3127,11 +3201,20 @@ var MultiAddressTransportMux = class {
|
|
|
3127
3201
|
}
|
|
3128
3202
|
logger.debug("Mux", `Subscribing for ${allPubkeys.length} address(es):`, allPubkeys.map((p) => p.slice(0, 12)).join(", "));
|
|
3129
3203
|
let globalSince = Math.floor(Date.now() / 1e3);
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3204
|
+
let globalDmSince = Math.floor(Date.now() / 1e3);
|
|
3205
|
+
const entries = [...this.addresses.values()];
|
|
3206
|
+
const sinceResults = await Promise.all(
|
|
3207
|
+
entries.map(async (entry) => {
|
|
3208
|
+
const [walletSince, dmSince] = await Promise.all([
|
|
3209
|
+
this.getAddressSince(entry),
|
|
3210
|
+
this.getAddressDmSince(entry)
|
|
3211
|
+
]);
|
|
3212
|
+
return { walletSince, dmSince };
|
|
3213
|
+
})
|
|
3214
|
+
);
|
|
3215
|
+
for (const { walletSince, dmSince } of sinceResults) {
|
|
3216
|
+
if (walletSince < globalSince) globalSince = walletSince;
|
|
3217
|
+
if (dmSince < globalDmSince) globalDmSince = dmSince;
|
|
3135
3218
|
}
|
|
3136
3219
|
const walletFilter = new import_nostr_js_sdk2.Filter();
|
|
3137
3220
|
walletFilter.kinds = [
|
|
@@ -3164,6 +3247,7 @@ var MultiAddressTransportMux = class {
|
|
|
3164
3247
|
const chatFilter = new import_nostr_js_sdk2.Filter();
|
|
3165
3248
|
chatFilter.kinds = [import_nostr_js_sdk2.EventKinds.GIFT_WRAP];
|
|
3166
3249
|
chatFilter["#p"] = allPubkeys;
|
|
3250
|
+
chatFilter.since = globalDmSince;
|
|
3167
3251
|
this.chatSubscriptionId = this.nostrClient.subscribe(chatFilter, {
|
|
3168
3252
|
onEvent: (event) => {
|
|
3169
3253
|
this.handleEvent({
|
|
@@ -3270,6 +3354,9 @@ var MultiAddressTransportMux = class {
|
|
|
3270
3354
|
for (const entry of this.addresses.values()) {
|
|
3271
3355
|
try {
|
|
3272
3356
|
const pm = import_nostr_js_sdk2.NIP17.unwrap(event, entry.keyManager);
|
|
3357
|
+
if (event.created_at) {
|
|
3358
|
+
this.updateLastDmEventTimestamp(entry, event.created_at);
|
|
3359
|
+
}
|
|
3273
3360
|
logger.debug("Mux", `Gift wrap decrypted by address ${entry.index}, sender: ${pm.senderPubkey?.slice(0, 16)}`);
|
|
3274
3361
|
if (pm.senderPubkey === entry.nostrPubkey) {
|
|
3275
3362
|
try {
|
|
@@ -3626,6 +3713,47 @@ var MultiAddressTransportMux = class {
|
|
|
3626
3713
|
logger.debug("Mux", "Failed to save last event timestamp:", err);
|
|
3627
3714
|
});
|
|
3628
3715
|
}
|
|
3716
|
+
updateLastDmEventTimestamp(entry, createdAt) {
|
|
3717
|
+
if (!this.storage) return;
|
|
3718
|
+
if (createdAt <= entry.lastDmEventTs) return;
|
|
3719
|
+
entry.lastDmEventTs = createdAt;
|
|
3720
|
+
const storageKey = `${STORAGE_KEYS_GLOBAL.LAST_DM_EVENT_TS}_${entry.nostrPubkey.slice(0, 16)}`;
|
|
3721
|
+
this.storage.set(storageKey, createdAt.toString()).catch((err) => {
|
|
3722
|
+
logger.debug("Mux", "Failed to save last DM event timestamp:", err);
|
|
3723
|
+
});
|
|
3724
|
+
}
|
|
3725
|
+
async getAddressDmSince(entry) {
|
|
3726
|
+
if (this.storage) {
|
|
3727
|
+
const storageKey = `${STORAGE_KEYS_GLOBAL.LAST_DM_EVENT_TS}_${entry.nostrPubkey.slice(0, 16)}`;
|
|
3728
|
+
try {
|
|
3729
|
+
const stored = await this.storage.get(storageKey);
|
|
3730
|
+
const parsed = stored ? parseInt(stored, 10) : NaN;
|
|
3731
|
+
if (Number.isFinite(parsed)) {
|
|
3732
|
+
entry.lastDmEventTs = parsed;
|
|
3733
|
+
entry.fallbackDmSince = null;
|
|
3734
|
+
return parsed;
|
|
3735
|
+
} else if (entry.fallbackDmSince !== null) {
|
|
3736
|
+
const ts = entry.fallbackDmSince;
|
|
3737
|
+
entry.lastDmEventTs = ts;
|
|
3738
|
+
entry.fallbackDmSince = null;
|
|
3739
|
+
return ts;
|
|
3740
|
+
}
|
|
3741
|
+
} catch {
|
|
3742
|
+
if (entry.fallbackDmSince !== null) {
|
|
3743
|
+
const ts = entry.fallbackDmSince;
|
|
3744
|
+
entry.lastDmEventTs = ts;
|
|
3745
|
+
entry.fallbackDmSince = null;
|
|
3746
|
+
return ts;
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
} else if (entry.fallbackDmSince !== null) {
|
|
3750
|
+
const ts = entry.fallbackDmSince;
|
|
3751
|
+
entry.lastDmEventTs = ts;
|
|
3752
|
+
entry.fallbackDmSince = null;
|
|
3753
|
+
return ts;
|
|
3754
|
+
}
|
|
3755
|
+
return Math.floor(Date.now() / 1e3);
|
|
3756
|
+
}
|
|
3629
3757
|
// ===========================================================================
|
|
3630
3758
|
// Mux-level event system
|
|
3631
3759
|
// ===========================================================================
|
|
@@ -3922,6 +4050,9 @@ var AddressTransportAdapter = class {
|
|
|
3922
4050
|
setFallbackSince(sinceSeconds) {
|
|
3923
4051
|
this.mux.setFallbackSince(this.addressIndex, sinceSeconds);
|
|
3924
4052
|
}
|
|
4053
|
+
setFallbackDmSince(sinceSeconds) {
|
|
4054
|
+
this.mux.setFallbackDmSince(this.addressIndex, sinceSeconds);
|
|
4055
|
+
}
|
|
3925
4056
|
async fetchPendingEvents() {
|
|
3926
4057
|
}
|
|
3927
4058
|
onChatReady(handler) {
|
|
@@ -16824,6 +16955,9 @@ var Sphere = class _Sphere {
|
|
|
16824
16955
|
const groupChat = _Sphere.resolveGroupChatConfig(options.groupChat, options.network);
|
|
16825
16956
|
const market = _Sphere.resolveMarketConfig(options.market);
|
|
16826
16957
|
const walletExists = await _Sphere.exists(options.storage);
|
|
16958
|
+
if (options.dmSince != null && options.transport.setFallbackDmSince) {
|
|
16959
|
+
options.transport.setFallbackDmSince(options.dmSince);
|
|
16960
|
+
}
|
|
16827
16961
|
if (walletExists) {
|
|
16828
16962
|
const sphere2 = await _Sphere.load({
|
|
16829
16963
|
storage: options.storage,
|