fix: remove dead relay.nostr.band and add detailed zap processing logs

Remove relay.nostr.band from all relay lists as it's dead.

Changes:
- Remove from AGGREGATOR_RELAYS in loaders.ts
- Remove from NIP-53 fallback relays
- Update all test files to use alternative relays

Add detailed logging to debug progress bar showing 0:
- Log each zap processing step (validation, recipient check, sender check)
- Log duplicate zaps, invalid zaps, and 0-sat zaps
- Log existing zap count in DB on init
- Add timestamps to successful zap recordings

This will help diagnose why the progress bar shows 0 even though
zaps are being fetched.
This commit is contained in:
Claude
2026-01-19 10:42:24 +00:00
parent 8fbd0a36af
commit 29dd29b979
6 changed files with 42 additions and 23 deletions

View File

@@ -655,7 +655,7 @@ export class Nip53Adapter extends ChatProtocolAdapter {
}
// Default fallback relays for live activities
return ["wss://relay.damus.io", "wss://nos.lol", "wss://relay.nostr.band"];
return ["wss://relay.damus.io", "wss://nos.lol", "wss://purplepag.es"];
}
/**

View File

@@ -296,7 +296,7 @@ describe("relayReferences transformer", () => {
"wss://relay.damus.io",
"wss://nos.lol",
"wss://relay.snort.social",
"wss://relay.nostr.band",
"wss://purplepag.es",
"wss://nostr.wine",
];

View File

@@ -76,9 +76,7 @@ describe("eventLoader", () => {
expect(result).toBeDefined();
expect((result as any)._testPointer.id).toBe("test123");
// mergeRelaySets normalizes URLs with trailing slash
expect((result as any)._testPointer.relays).toContain(
"wss://relay.nostr.band/",
);
expect((result as any)._testPointer.relays).toContain("wss://nos.lol/");
});
it("should handle EventPointer with relay hints", () => {
@@ -100,9 +98,7 @@ describe("eventLoader", () => {
expect(result).toBeDefined();
// mergeRelaySets normalizes URLs with trailing slash
expect((result as any)._testPointer.relays).toContain(
"wss://relay.nostr.band/",
);
expect((result as any)._testPointer.relays).toContain("wss://nos.lol/");
});
});
@@ -249,7 +245,7 @@ describe("eventLoader", () => {
expect(relays).toContain("wss://r-tag.com/");
expect(relays).toContain("wss://e-tag.com/");
// mergeRelaySets normalizes aggregator relays with trailing slash
expect(relays).toContain("wss://relay.nostr.band/");
expect(relays).toContain("wss://nos.lol/");
});
});
@@ -328,9 +324,7 @@ describe("eventLoader", () => {
expect(result).toBeDefined();
// mergeRelaySets normalizes aggregator relays with trailing slash
expect((result as any)._testPointer.relays).toContain(
"wss://relay.nostr.band/",
);
expect((result as any)._testPointer.relays).toContain("wss://nos.lol/");
});
it("should handle invalid e tags gracefully", () => {
@@ -390,7 +384,7 @@ describe("eventLoader", () => {
const relays = (result as any)._testPointer.relays;
// Should only have aggregator relays (normalized with trailing slash)
expect(relays).toContain("wss://relay.nostr.band/");
expect(relays).toContain("wss://nos.lol/");
expect(relays).toContain("wss://nos.lol/");
expect(relays).toContain("wss://purplepag.es/");
expect(relays).toContain("wss://relay.primal.net/");

View File

@@ -52,7 +52,6 @@ function extractRelayContext(event: NostrEvent): {
// Aggregator relays for better event discovery
// IMPORTANT: URLs must be normalized (trailing slash, lowercase) to match RelayStateManager keys
export const AGGREGATOR_RELAYS = [
"wss://relay.nostr.band/",
"wss://nos.lol/",
"wss://purplepag.es/",
"wss://relay.primal.net/",

View File

@@ -76,7 +76,7 @@ describe("selectRelaysForFilter", () => {
const relayListEvent = createRelayListEvent(testSecretKeys[0], [
["r", "wss://relay.damus.io"],
["r", "wss://nos.lol"],
["r", "wss://relay.nostr.band", "read"],
["r", "wss://purplepag.es", "read"],
]);
// Add to event store
@@ -99,7 +99,7 @@ describe("selectRelaysForFilter", () => {
result.relays.includes("wss://nos.lol/");
expect(hasWriteRelay).toBe(true);
// Should NOT include read-only relay
expect(result.relays).not.toContain("wss://relay.nostr.band/");
expect(result.relays).not.toContain("wss://purplepag.es/");
});
it("should handle multiple authors", async () => {
@@ -141,7 +141,7 @@ describe("selectRelaysForFilter", () => {
const relayListEvent = createRelayListEvent(testSecretKeys[2], [
["r", "wss://relay.damus.io", "write"],
["r", "wss://nos.lol", "read"],
["r", "wss://relay.nostr.band", "read"],
["r", "wss://purplepag.es", "read"],
]);
eventStore.add(relayListEvent);
@@ -160,7 +160,7 @@ describe("selectRelaysForFilter", () => {
// Should include at least one read relay - selectOptimalRelays may pick subset
const hasReadRelay =
result.relays.includes("wss://nos.lol/") ||
result.relays.includes("wss://relay.nostr.band/");
result.relays.includes("wss://purplepag.es/");
expect(hasReadRelay).toBe(true);
// Should NOT include write-only relay
expect(result.relays).not.toContain("wss://relay.damus.io/");

View File

@@ -58,6 +58,10 @@ class SupportersService {
async init() {
console.log("[Supporters] Initializing...");
// Log existing zaps in DB
const existingCount = await db.grimoireZaps.count();
console.log(`[Supporters] Found ${existingCount} existing zaps in DB`);
// Clean up existing subscription if any
if (this.subscription) {
this.subscription.unsubscribe();
@@ -191,24 +195,46 @@ class SupportersService {
private async processZapReceipt(event: NostrEvent) {
try {
// Only process valid zaps
if (!isValidZap(event)) return;
if (!isValidZap(event)) {
console.log(`[Supporters] Invalid zap event ${event.id.slice(0, 8)}`);
return;
}
// Double-check recipient is Grimoire
const recipient = getZapRecipient(event);
if (recipient !== GRIMOIRE_DONATE_PUBKEY) return;
if (recipient !== GRIMOIRE_DONATE_PUBKEY) {
console.log(
`[Supporters] Zap not for Grimoire: ${recipient?.slice(0, 8)}`,
);
return;
}
// Get sender
const sender = getZapSender(event);
if (!sender) return;
if (!sender) {
console.log(
`[Supporters] No sender found for zap ${event.id.slice(0, 8)}`,
);
return;
}
// Check if already recorded (deduplication)
const existing = await db.grimoireZaps.get(event.id);
if (existing) return;
if (existing) {
console.log(`[Supporters] Duplicate zap ${event.id.slice(0, 8)}`);
return;
}
// Get amount (millisats -> sats)
const amountMsats = getZapAmount(event);
const amountSats = amountMsats ? Math.floor(amountMsats / 1000) : 0;
if (amountSats === 0) {
console.log(
`[Supporters] Zap with 0 sats: ${event.id.slice(0, 8)} (${amountMsats} msats)`,
);
}
// Get comment from zap request
const zapRequest = getZapRequest(event);
const comment = zapRequest?.content;
@@ -225,7 +251,7 @@ class SupportersService {
await db.grimoireZaps.add(zapRecord);
console.log(
`[Supporters] Recorded zap: ${amountSats} sats from ${sender.slice(0, 8)}`,
`[Supporters] Recorded zap: ${amountSats} sats from ${sender.slice(0, 8)} at ${new Date(event.created_at * 1000).toISOString()}`,
);
} catch (error) {
// Silently ignore duplicate key errors (race condition protection)