diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt index 4e0d85cd0b..90151c26be 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt @@ -373,6 +373,7 @@ fun RenderNutzapGallery( user = note.author, comment = event?.content?.ifBlank { null }, amount = showAmount(java.math.BigDecimal(sats)), + zapNote = note, ) }.toImmutableList() } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NutzapUserSetCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NutzapUserSetCompose.kt index 393c8e86ae..c40ef4da95 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NutzapUserSetCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NutzapUserSetCompose.kt @@ -84,6 +84,7 @@ fun NutzapUserSetCompose( user = note.author, comment = event?.content?.ifBlank { null }, amount = showAmount(java.math.BigDecimal(sats)), + zapNote = note, ) }.toImmutableList() } diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt index 4af0b077ca..b334dd73ab 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt @@ -176,7 +176,10 @@ class LnZapRequestEvent( } LnZapEvent.ZapType.ANONYMOUS -> { - tags += arrayOf(arrayOf("anon", "")) + // Valueless `anon` tag: a blank-valued one (`["anon", ""]`) is the + // marker for an *unsigned private* zap and would make the throwaway + // signer encrypt the message instead of keeping it public. + tags += arrayOf(arrayOf("anon")) NostrSignerInternal(KeyPair()).sign(createdAt, KIND, tags, message) } diff --git a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestAnonTagTest.kt b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestAnonTagTest.kt index 2d0dc8a575..3de89a1d2d 100644 --- a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestAnonTagTest.kt +++ b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestAnonTagTest.kt @@ -88,6 +88,30 @@ class LnZapRequestAnonTagTest { assertFalse(zapRequest.pubKey == signer.pubKey, "anonymous zaps must be signed by a throwaway key") } + /** + * Regression test for the user-only (profile zap) overload: its ANONYMOUS + * branch used a blank-valued `anon` tag, which [NostrSignerInternal] treats + * as an unsigned *private* zap and encrypts — silently turning a public + * anonymous comment into an encrypted one nobody but the recipient can read. + */ + @Test + fun `anonymous profile zap request keeps the message public`() = + runTest { + val zapRequest = + LnZapRequestEvent.create( + userHex = receiverPubKey, + relays = relays, + signer = signer, + message = "great work", + zapType = LnZapEvent.ZapType.ANONYMOUS, + ) + + assertTrue(zapRequest.hasAnonTag()) + assertFalse(zapRequest.isPrivateZap(), "anonymous zaps must not be encrypted as private zaps") + assertEquals("great work", zapRequest.content) + assertFalse(zapRequest.pubKey == signer.pubKey, "anonymous zaps must be signed by a throwaway key") + } + @Test fun `private zap request has anon tag, is private, and hides the sender key`() = runTest {