diff --git a/src/lib/chat/adapters/nip-53-adapter.ts b/src/lib/chat/adapters/nip-53-adapter.ts index a3d6e8e..32f1d12 100644 --- a/src/lib/chat/adapters/nip-53-adapter.ts +++ b/src/lib/chat/adapters/nip-53-adapter.ts @@ -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"]; } /** diff --git a/src/lib/relay-transformer.test.ts b/src/lib/relay-transformer.test.ts index c99feea..0cae894 100644 --- a/src/lib/relay-transformer.test.ts +++ b/src/lib/relay-transformer.test.ts @@ -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", ]; diff --git a/src/services/loaders.test.ts b/src/services/loaders.test.ts index fbd5780..4c5ebb6 100644 --- a/src/services/loaders.test.ts +++ b/src/services/loaders.test.ts @@ -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/"); diff --git a/src/services/loaders.ts b/src/services/loaders.ts index fef398e..706265e 100644 --- a/src/services/loaders.ts +++ b/src/services/loaders.ts @@ -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/", diff --git a/src/services/relay-selection.test.ts b/src/services/relay-selection.test.ts index b923b85..3b694f0 100644 --- a/src/services/relay-selection.test.ts +++ b/src/services/relay-selection.test.ts @@ -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/"); diff --git a/src/services/supporters.ts b/src/services/supporters.ts index e587759..300f482 100644 --- a/src/services/supporters.ts +++ b/src/services/supporters.ts @@ -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)