mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-10 00:16:59 +00:00
fix(nwc): drop authors and #p from response subscription filter
Some wallet services and relays don't produce or index the `p` tag on NIP-47 response events the way the spec implies for ephemeral kinds, which made Amethyst's strict relay-side filter (kinds + authors + #e + #p) match nothing while looser clients (Primal uses just kinds + #e) work against the same connection string. Reduce the relay filter to the same shape Primal uses. The request event id in #e is a unique 32-byte identifier, so the false-positive rate is effectively zero, and the wallet's identity is still authenticated end-to-end by NIP-04 decryption against the per-connection shared secret — the relay filter was never the security boundary. NWCPaymentQueryState no longer needs `fromServiceHex` or `toUserHex`; remove them and propagate the simpler ctor through callers.
This commit is contained in:
-4
@@ -144,8 +144,6 @@ class NwcSignerState(
|
||||
|
||||
val filter =
|
||||
NWCPaymentQueryState(
|
||||
fromServiceHex = walletService.pubKeyHex,
|
||||
toUserHex = event.pubKey,
|
||||
replyingToHex = event.id,
|
||||
relay = walletService.relayUri,
|
||||
)
|
||||
@@ -185,8 +183,6 @@ class NwcSignerState(
|
||||
|
||||
val filter =
|
||||
NWCPaymentQueryState(
|
||||
fromServiceHex = walletService.pubKeyHex,
|
||||
toUserHex = event.pubKey,
|
||||
replyingToHex = event.id,
|
||||
relay = walletService.relayUri,
|
||||
)
|
||||
|
||||
+10
-11
@@ -24,17 +24,16 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.events.LnZapPaymentResponseEvent
|
||||
|
||||
fun filterNWCPaymentsFromRequests(
|
||||
serviceKeys: Set<HexKey>,
|
||||
paymentRequests: Set<HexKey>,
|
||||
fromUsers: Set<HexKey>,
|
||||
): Filter =
|
||||
// The request event id (#e) is a unique 32-byte identifier — sufficient on
|
||||
// its own to match the response. Adding `authors` or `#p` makes the filter
|
||||
// strictly stricter at the relay, which causes silent timeouts on services
|
||||
// or relays that don't set / index those fields the way NIP-47 expects
|
||||
// (e.g. wallets that omit the `p` tag, relays that don't index single-letter
|
||||
// tags on ephemeral kinds). Primal's client uses the same minimal filter
|
||||
// (kinds + #e), and the wallet's identity is still authenticated end-to-end
|
||||
// by NIP-04 decryption against the per-connection shared secret.
|
||||
fun filterNWCPaymentsFromRequests(paymentRequests: Set<HexKey>): Filter =
|
||||
Filter(
|
||||
kinds = listOf(LnZapPaymentResponseEvent.KIND),
|
||||
authors = serviceKeys.sorted(),
|
||||
tags =
|
||||
mapOf(
|
||||
"e" to paymentRequests.sorted(),
|
||||
"p" to fromUsers.sorted(),
|
||||
),
|
||||
tags = mapOf("e" to paymentRequests.sorted()),
|
||||
)
|
||||
|
||||
+1
-3
@@ -49,11 +49,9 @@ fun NWCFinderFilterAssemblerSubscription(
|
||||
remember(note) {
|
||||
val zapPaymentRequestNote = note
|
||||
(zapPaymentRequestNote.event as? LnZapPaymentRequestEvent)?.let { noteEvent ->
|
||||
noteEvent.walletServicePubKey()?.let { serviceId ->
|
||||
noteEvent.walletServicePubKey()?.let {
|
||||
zapPaymentRequestNote.relays.map {
|
||||
NWCPaymentQueryState(
|
||||
fromServiceHex = serviceId,
|
||||
toUserHex = noteEvent.pubKey,
|
||||
replyingToHex = noteEvent.id,
|
||||
relay = it,
|
||||
)
|
||||
|
||||
+4
-3
@@ -26,11 +26,12 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
|
||||
// This allows multiple screen to be listening to tags, even the same tag
|
||||
// This allows multiple screen to be listening to tags, even the same tag.
|
||||
// The subscription filter only needs the request event id (#e) — the wallet
|
||||
// service's identity is authenticated by NIP-04 decryption against the
|
||||
// per-connection shared secret, not by relay-side `authors`/`#p` filtering.
|
||||
@Stable
|
||||
class NWCPaymentQueryState(
|
||||
val fromServiceHex: HexKey,
|
||||
val toUserHex: HexKey,
|
||||
val replyingToHex: HexKey,
|
||||
val relay: NormalizedRelayUrl,
|
||||
)
|
||||
|
||||
+2
-4
@@ -32,15 +32,13 @@ class NWCPaymentWatcherSubAssembler(
|
||||
if (keys.isEmpty()) return null
|
||||
|
||||
return keys.groupBy { it.relay }.map { relayGroup ->
|
||||
val fromAuthors = relayGroup.value.mapTo(mutableSetOf()) { it.fromServiceHex }
|
||||
val replyingToPayments = relayGroup.value.mapTo(mutableSetOf()) { it.replyingToHex }
|
||||
val aboutUsers = relayGroup.value.mapTo(mutableSetOf()) { it.toUserHex }
|
||||
|
||||
if (fromAuthors.isEmpty() || replyingToPayments.isEmpty()) return null
|
||||
if (replyingToPayments.isEmpty()) return null
|
||||
|
||||
RelayBasedFilter(
|
||||
relay = relayGroup.key,
|
||||
filter = filterNWCPaymentsFromRequests(fromAuthors, replyingToPayments, aboutUsers),
|
||||
filter = filterNWCPaymentsFromRequests(replyingToPayments),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user