From 1d5ce994a6ebff8cd83b13912a18d3485553c852 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 16 May 2026 19:56:22 +0000 Subject: [PATCH] fix(onchain-zaps): UserProfileZapsViewModel crashed casting kind 8333 as LnZapEvent observeEvents(filterAcceptingBothKinds) is generic-erased at runtime, so an OnchainZapEvent landing in the cache (e.g. right after sending an onchain zap from the wallet) flowed through and crashed in sumAmountsByUser's forEach checkcast. Observe as and dispatch on type: LnZapEvent keeps its private-zap decryption path; OnchainZapEvent attributes the claimedAmountInSats to event.pubKey (no zap-request envelope). --- .../zaps/dal/UserProfileZapsViewModel.kt | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/zaps/dal/UserProfileZapsViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/zaps/dal/UserProfileZapsViewModel.kt index 703f3d7a9..6ec8803b4 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/zaps/dal/UserProfileZapsViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/zaps/dal/UserProfileZapsViewModel.kt @@ -28,6 +28,7 @@ import androidx.lifecycle.viewModelScope import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.User +import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent import com.vitorpamplona.quartz.nipBCOnchainZaps.zap.OnchainZapEvent @@ -96,11 +97,24 @@ class UserProfileZapsViewModel( } } - suspend fun List.sumAmountsByUser(): List { + private fun mapOnchainZap(event: OnchainZapEvent): ZapAmount { + val amountSats = event.claimedAmountInSats() ?: 0L + return ZapAmount( + LocalCache.getOrCreateUser(event.pubKey), + BigDecimal(amountSats), + ) + } + + suspend fun List.sumAmountsByUser(): List { val results = mutableMapOf() this.forEach { zapEvent -> - val zapAmount = mapRequest(zapEvent) + val zapAmount = + when (zapEvent) { + is LnZapEvent -> mapRequest(zapEvent) + is OnchainZapEvent -> mapOnchainZap(zapEvent) + else -> null + } if (zapAmount != null) { val existingAmount = results[zapAmount.user] ?: BigDecimal.ZERO results[zapAmount.user] = existingAmount + zapAmount.amount @@ -113,7 +127,7 @@ class UserProfileZapsViewModel( @OptIn(kotlinx.coroutines.FlowPreview::class) val receivedZapAmountsByUser: StateFlow> = account.cache - .observeEvents(zapsToUser) + .observeEvents(zapsToUser) .sample(500) .map { zapEvents -> zapEvents.sumAmountsByUser()