refactor(commons): share NIP-59 gift-wrap+seal unwrap helper

Three call sites did the same two-layer peel —
  kind:1059 → (nip44 decrypt) → kind:13 sealed rumor → (nip44 decrypt) → rumor

Extracted as `GiftWrapEvent.unwrapAndUnsealOrNull(signer)` in
commons/relayClient/nip17Dm/, and collapsed:

- commons/marmot/MarmotIngest.kt — was an inline `when` switch; now a
  one-liner. Behaviour unchanged (still passes through if the inner
  isn't a seal, matching the previous defensive `else -> inner` branch).
- desktopApp/Main.kt — dropped the nested unwrap/unseal block in the
  kind:1059 case of the LocalCache dispatcher.
- cli/DmCommands.kt — replaced the manual chain in `decryptChatMessages`.

Android's DecryptAndIndexProcessor keeps its two separate handlers
(processNewGiftWrap / processNewSealedRumor) because the LocalCache
pipeline re-enters on each peel — that's a different shape and not
touched.

No behaviour change on any platform.
This commit is contained in:
Claude
2026-04-23 18:40:35 +00:00
parent 15205c24b5
commit 1e5b5d6276
4 changed files with 58 additions and 23 deletions
@@ -71,6 +71,7 @@ import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowPosition
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState
import com.vitorpamplona.amethyst.commons.relayClient.nip17Dm.unwrapAndUnsealOrNull
import com.vitorpamplona.amethyst.desktop.account.AccountManager
import com.vitorpamplona.amethyst.desktop.account.AccountState
import com.vitorpamplona.amethyst.desktop.cache.DesktopLocalCache
@@ -1022,13 +1023,9 @@ fun MainContent(
}
is com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent -> {
// NIP-17: unwrap gift wrap seal → inner event
// NIP-17: peel both the gift-wrap and sealed-rumor layers.
scope.launch {
val seal =
event.unwrapOrNull(iAccount.signer)
as? com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
?: return@launch
val innerEvent = seal.unsealOrNull(iAccount.signer) ?: return@launch
val innerEvent = event.unwrapAndUnsealOrNull(iAccount.signer) ?: return@launch
when (innerEvent) {
is com.vitorpamplona.quartz.nip17Dm.messages.ChatMessageEvent -> {
val innerNote = localCache.getOrCreateNote(innerEvent.id)