commit b1fee253b4faa691c8b4eb0c445df74c721bc829
parent e472e559a5653de6487d8c5df98bc77b7811e873
Author: William Casarin <jb55@jb55.com>
Date: Sun, 14 May 2023 10:48:44 -0700
nwc: fix bug where private nwc zaps weren't getting tracked properly
It was using the wrapper zap request id instead of the inner id. Fix
this type error by creating a ZapRequestId wrapper that makes sure it
uses the proper request id.
Diffstat:
6 files changed, 80 insertions(+), 21 deletions(-)
diff --git a/damus/Components/ZapButton.swift b/damus/Components/ZapButton.swift
@@ -174,7 +174,7 @@ struct ZapButton: View {
struct ZapButton_Previews: PreviewProvider {
static var previews: some View {
- let pending_zap = PendingZap(amount_msat: 1000, target: ZapTarget.note(id: "noteid", author: "author"), request: test_zap_request, type: .pub, state: .external(.init(state: .fetching_invoice)))
+ let pending_zap = PendingZap(amount_msat: 1000, target: ZapTarget.note(id: "noteid", author: "author"), request: .normal(test_zap_request), type: .pub, state: .external(.init(state: .fetching_invoice)))
let zaps = ZapsDataModel([.pending(pending_zap)])
ZapButton(damus_state: test_damus_state(), event: test_event, lnurl: "lnurl", zaps: zaps)
@@ -203,7 +203,7 @@ func send_zap(damus_state: DamusState, event: NostrEvent, lnurl: String, is_cust
let target = ZapTarget.note(id: event.id, author: event.pubkey)
let content = comment ?? ""
- guard let zapreq = make_zap_request_event(keypair: keypair, content: content, relays: relays, target: target, zap_type: zap_type) else {
+ guard let mzapreq = make_zap_request_event(keypair: keypair, content: content, relays: relays, target: target, zap_type: zap_type) else {
// this should never happen
return
}
@@ -211,7 +211,9 @@ func send_zap(damus_state: DamusState, event: NostrEvent, lnurl: String, is_cust
let zap_amount = amount_sats ?? damus_state.settings.default_zap_amount
let amount_msat = Int64(zap_amount) * 1000
let pending_zap_state = initial_pending_zap_state(settings: damus_state.settings)
- let pending_zap = PendingZap(amount_msat: amount_msat, target: target, request: ZapRequest(ev: zapreq), type: zap_type, state: pending_zap_state)
+ let pending_zap = PendingZap(amount_msat: amount_msat, target: target, request: mzapreq, type: zap_type, state: pending_zap_state)
+ let zapreq = mzapreq.potentially_anon_outer_request.ev
+ let reqid = ZapRequestId(from_makezap: mzapreq)
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
damus_state.add_zap(zap: .pending(pending_zap))
@@ -225,7 +227,7 @@ func send_zap(damus_state: DamusState, event: NostrEvent, lnurl: String, is_cust
guard let payreq = mpayreq else {
// TODO: show error
DispatchQueue.main.async {
- remove_zap(reqid: zapreq.id, zapcache: damus_state.zaps, evcache: damus_state.events)
+ remove_zap(reqid: reqid, zapcache: damus_state.zaps, evcache: damus_state.events)
let typ = ZappingEventType.failed(.bad_lnurl)
let ev = ZappingEvent(is_custom: is_custom, type: typ, event: event)
notify(.zapping, ev)
@@ -239,7 +241,7 @@ func send_zap(damus_state: DamusState, event: NostrEvent, lnurl: String, is_cust
guard let inv = await fetch_zap_invoice(payreq, zapreq: zapreq, sats: zap_amount, zap_type: zap_type, comment: comment) else {
DispatchQueue.main.async {
- remove_zap(reqid: zapreq.id, zapcache: damus_state.zaps, evcache: damus_state.events)
+ remove_zap(reqid: reqid, zapcache: damus_state.zaps, evcache: damus_state.events)
let typ = ZappingEventType.failed(.fetching_invoice)
let ev = ZappingEvent(is_custom: is_custom, type: typ, event: event)
notify(.zapping, ev)
@@ -253,7 +255,7 @@ func send_zap(damus_state: DamusState, event: NostrEvent, lnurl: String, is_cust
case .nwc(let nwc_state):
// don't both continuing, user has canceled
if case .cancel_fetching_invoice = nwc_state.state {
- remove_zap(reqid: zapreq.id, zapcache: damus_state.zaps, evcache: damus_state.events)
+ remove_zap(reqid: reqid, zapcache: damus_state.zaps, evcache: damus_state.events)
return
}
@@ -308,10 +310,12 @@ func cancel_zap(zap: PendingZap, box: PostBox, zapcache: Zaps, evcache: EventCac
if let err = box.cancel_send(evid: nwc_req.id) {
return .send_err(err)
}
- remove_zap(reqid: zap.request.ev.id, zapcache: zapcache, evcache: evcache)
+ let reqid = ZapRequestId(from_pending: zap)
+ remove_zap(reqid: reqid, zapcache: zapcache, evcache: evcache)
case .failed:
- remove_zap(reqid: zap.request.ev.id, zapcache: zapcache, evcache: evcache)
+ let reqid = ZapRequestId(from_pending: zap)
+ remove_zap(reqid: reqid, zapcache: zapcache, evcache: evcache)
}
return nil
diff --git a/damus/Nostr/NostrEvent.swift b/damus/Nostr/NostrEvent.swift
@@ -512,7 +512,12 @@ func zap_target_to_tags(_ target: ZapTarget) -> [[String]] {
}
}
-func make_private_zap_request_event(identity: FullKeypair, enc_key: FullKeypair, target: ZapTarget, message: String) -> String? {
+struct PrivateZapRequest {
+ let req: ZapRequest
+ let enc: String
+}
+
+func make_private_zap_request_event(identity: FullKeypair, enc_key: FullKeypair, target: ZapTarget, message: String) -> PrivateZapRequest? {
// target tags must be the same as zap request target tags
let tags = zap_target_to_tags(target)
@@ -520,10 +525,13 @@ func make_private_zap_request_event(identity: FullKeypair, enc_key: FullKeypair,
note.id = calculate_event_id(ev: note)
note.sig = sign_event(privkey: identity.privkey, ev: note)
- guard let note_json = encode_json(note) else {
+ guard let note_json = encode_json(note),
+ let enc = encrypt_message(message: note_json, privkey: enc_key.privkey, to_pk: target.pubkey, encoding: .bech32)
+ else {
return nil
}
- return encrypt_message(message: note_json, privkey: enc_key.privkey, to_pk: target.pubkey, encoding: .bech32)
+
+ return PrivateZapRequest(req: ZapRequest(ev: note), enc: enc)
}
func decrypt_private_zap(our_privkey: String, zapreq: NostrEvent, target: ZapTarget) -> NostrEvent? {
@@ -587,7 +595,30 @@ func generate_private_keypair(our_privkey: String, id: String, created_at: Int64
return FullKeypair(pubkey: pubkey, privkey: privkey)
}
-func make_zap_request_event(keypair: FullKeypair, content: String, relays: [RelayDescriptor], target: ZapTarget, zap_type: ZapType) -> NostrEvent? {
+enum MakeZapRequest {
+ case priv(ZapRequest, PrivateZapRequest)
+ case normal(ZapRequest)
+
+ var private_inner_request: ZapRequest {
+ switch self {
+ case .priv(let _, let pzr):
+ return pzr.req
+ case .normal(let zr):
+ return zr
+ }
+ }
+
+ var potentially_anon_outer_request: ZapRequest {
+ switch self {
+ case .priv(let zr, _):
+ return zr
+ case .normal(let zr):
+ return zr
+ }
+ }
+}
+
+func make_zap_request_event(keypair: FullKeypair, content: String, relays: [RelayDescriptor], target: ZapTarget, zap_type: ZapType) -> MakeZapRequest? {
var tags = zap_target_to_tags(target)
var relay_tag = ["relays"]
relay_tag.append(contentsOf: relays.map { $0.url.id })
@@ -597,6 +628,8 @@ func make_zap_request_event(keypair: FullKeypair, content: String, relays: [Rela
let now = Int64(Date().timeIntervalSince1970)
+ var privzap_req: PrivateZapRequest?
+
var message = content
switch zap_type {
case .pub:
@@ -614,14 +647,20 @@ func make_zap_request_event(keypair: FullKeypair, content: String, relays: [Rela
guard let privreq = make_private_zap_request_event(identity: keypair, enc_key: kp, target: target, message: message) else {
return nil
}
- tags.append(["anon", privreq])
+ tags.append(["anon", privreq.enc])
message = ""
+ privzap_req = privreq
}
let ev = NostrEvent(content: message, pubkey: kp.pubkey, kind: 9734, tags: tags, createdAt: now)
ev.id = calculate_event_id(ev: ev)
ev.sig = sign_event(privkey: kp.privkey, ev: ev)
- return ev
+ let zapreq = ZapRequest(ev: ev)
+ if let privzap_req {
+ return .priv(zapreq, privzap_req)
+ } else {
+ return .normal(zapreq)
+ }
}
func uniq<T: Hashable>(_ xs: [T]) -> [T] {
diff --git a/damus/Util/WalletConnect.swift b/damus/Util/WalletConnect.swift
@@ -234,7 +234,8 @@ func nwc_error(zapcache: Zaps, evcache: EventCache, resp: FullWalletResponse) {
}
// remove the pending zap if there was an error
- remove_zap(reqid: pzap.request.ev.id, zapcache: zapcache, evcache: evcache)
+ let reqid = ZapRequestId(from_pending: pzap)
+ remove_zap(reqid: reqid, zapcache: zapcache, evcache: evcache)
return
}
}
diff --git a/damus/Util/Zap.swift b/damus/Util/Zap.swift
@@ -105,10 +105,10 @@ class PendingZap {
let type: ZapType
private(set) var state: PendingZapState
- init(amount_msat: Int64, target: ZapTarget, request: ZapRequest, type: ZapType, state: PendingZapState) {
+ init(amount_msat: Int64, target: ZapTarget, request: MakeZapRequest, type: ZapType, state: PendingZapState) {
self.amount_msat = amount_msat
self.target = target
- self.request = request
+ self.request = request.private_inner_request
self.type = type
self.state = state
}
@@ -125,6 +125,21 @@ class PendingZap {
}
}
+struct ZapRequestId: Equatable {
+ let reqid: String
+
+ init(from_zap: Zapping) {
+ self.reqid = from_zap.request.id
+ }
+
+ init(from_makezap: MakeZapRequest) {
+ self.reqid = from_makezap.private_inner_request.ev.id
+ }
+
+ init(from_pending: PendingZap) {
+ self.reqid = from_pending.request.ev.id
+ }
+}
enum Zapping {
case zap(Zap)
diff --git a/damus/Util/Zaps.swift b/damus/Util/Zaps.swift
@@ -91,9 +91,9 @@ class Zaps {
}
}
-func remove_zap(reqid: String, zapcache: Zaps, evcache: EventCache) {
- guard let zap = zapcache.remove_zap(reqid: reqid) else {
+func remove_zap(reqid: ZapRequestId, zapcache: Zaps, evcache: EventCache) {
+ guard let zap = zapcache.remove_zap(reqid: reqid.reqid) else {
return
}
- evcache.get_cache_data(zap.target.id).zaps_model.remove(reqid: reqid)
+ evcache.get_cache_data(zap.target.id).zaps_model.remove(reqid: reqid.reqid)
}
diff --git a/damus/Views/Events/ZapEvent.swift b/damus/Views/Events/ZapEvent.swift
@@ -45,7 +45,7 @@ let test_zap = Zap(event: test_event, invoice: test_zap_invoice, zapper: "zapper
let test_private_zap = Zap(event: test_event, invoice: test_zap_invoice, zapper: "zapper", target: .profile("pk"), request: test_zap_request, is_anon: false, private_request: test_event)
-let test_pending_zap = PendingZap(amount_msat: 10000, target: .note(id: "id", author: "pk"), request: test_zap_request, type: .pub, state: .external(.init(state: .fetching_invoice)))
+let test_pending_zap = PendingZap(amount_msat: 10000, target: .note(id: "id", author: "pk"), request: .normal(test_zap_request), type: .pub, state: .external(.init(state: .fetching_invoice)))
struct ZapEvent_Previews: PreviewProvider {
static var previews: some View {