Handle watch history snapshot publish without NIP-07 signer

This commit is contained in:
thePR0M3TH3AN committed 2025-10-01 20:37:47 -04:00
1 parent 297fbb2450
commit a1505b7538
2 files changed
+124 -3

No files matched your search

+34 -3
View File
@@ -2315,6 +2315,22 @@ class NostrClient {
return key && !skippedKeys.has(key);
});
const baselineEntry =
existingEntry || this.watchHistoryCache.get(normalizedActor) || null;
const persistSnapshotToCache = () => {
const pointerForCache = baselineEntry?.pointerEvent || null;
const entry = this.createWatchHistoryEntry(
pointerForCache,
persistedItems,
Date.now(),
baselineEntry
);
this.watchHistoryCache.set(normalizedActor, entry);
this.persistWatchHistoryEntry(normalizedActor, entry);
return entry;
};
if (chunkInfo.skipped?.length && isDevMode) {
console.warn(
`[nostr] Skipped ${chunkInfo.skipped.length} oversized watch history entries while chunking.`
@@ -2333,6 +2349,24 @@ class NostrClient {
typeof window.nostr.signEvent === "function";
if (!useExtension) {
if (
normalizedActorLower === normalizedLogged &&
(!window?.nostr || typeof window.nostr.signEvent !== "function")
) {
const cachedEntry = persistSnapshotToCache();
if (allowRetry && persistedItems.length) {
this.scheduleWatchHistoryRepublish(normalizedActor, persistedItems);
}
return {
ok: false,
error: "signing-unavailable",
snapshot: snapshotId,
items: cachedEntry.items
.map((item) => clonePointerItem(item))
.filter(Boolean),
};
}
try {
if (!this.sessionActor || this.sessionActor.pubkey !== normalizedActor) {
await this.ensureSessionActor(true);
@@ -2549,9 +2583,6 @@ class NostrClient {
this.scheduleWatchHistoryRepublish(normalizedActor, persistedItems);
}
const baselineEntry =
existingEntry || this.watchHistoryCache.get(normalizedActor) || null;
const pointerEvent =
signedIndexEvent ||
chunkResults.find((chunk) => chunk.success)?.event ||
+90
View File
@@ -507,6 +507,96 @@ assert.deepEqual(
"republish scheduler should receive the remaining items"
);
const LOGGED_ACTOR = `${ACTOR}-logged`;
const {
client: noSignerClient,
publishedEvents: noSignerPublishedEvents,
scheduledRepublishes: noSignerRepublishes,
persistedEntries: noSignerPersistedEntries,
} = createPublishingClient(LOGGED_ACTOR);
noSignerClient.pubkey = LOGGED_ACTOR;
const noSignerItems = [
{
type: "e",
value: `${LOGGED_ACTOR}-event`,
watchedAt: baseWatchedAt + 123,
},
{
type: "a",
value: `30078:${LOGGED_ACTOR}:history`,
watchedAt: baseWatchedAt + 456,
},
];
const noSignerResult = await noSignerClient.publishWatchHistorySnapshot(
LOGGED_ACTOR,
noSignerItems
);
assert.equal(
noSignerResult.ok,
false,
"logged actor without signer should report failure"
);
assert.equal(
noSignerResult.error,
"signing-unavailable",
"missing signer failure should flag availability"
);
assert.equal(
noSignerPublishedEvents.length,
0,
"no events should publish when signer unavailable"
);
assert.equal(
noSignerRepublishes.length,
1,
"missing signer should schedule a retry"
);
assert.equal(
noSignerRepublishes[0].actor,
LOGGED_ACTOR,
"retry should target the logged actor"
);
const cachedLoggedEntry = noSignerClient.watchHistoryCache.get(LOGGED_ACTOR);
assert(cachedLoggedEntry, "missing signer should keep snapshot cached");
assert.equal(
cachedLoggedEntry.items.length,
noSignerItems.length,
"cached entry should retain merged items"
);
assert.equal(
noSignerPersistedEntries.length,
1,
"missing signer should persist cached payload"
);
assert.deepEqual(
cachedLoggedEntry.items.map((item) => ({
type: item.type,
value: item.value,
})),
noSignerResult.items.map((item) => ({
type: item.type,
value: item.value,
})),
"returned items should mirror cached payload"
);
const scheduledLoggedKeys = new Set(
noSignerRepublishes[0].items.map((item) => `${item.type}:${item.value}`)
);
const cachedLoggedKeys = new Set(
cachedLoggedEntry.items.map((item) => `${item.type}:${item.value}`)
);
assert.deepEqual(
scheduledLoggedKeys,
cachedLoggedKeys,
"scheduled retry should include cached items"
);
const NO_SEEN_ACTOR = `${ACTOR}-no-seen`;
const {
client: noSeenClient,