Pending Zaps

A fairly large change that replaces Zaps in the codebase with "Zapping"
which is a tagged union consisting of a resolved Zap and a Pending Zap.
These are both counted as Zaps everywhere in Damus, except pending zaps
can be cancelled (most of the time).
This commit is contained in:
William Casarin
2023-05-13 21:33:34 -07:00
parent 1518a0a16c
commit 03691d0369
24 changed files with 738 additions and 179 deletions

View File

@@ -7,12 +7,17 @@
import Foundation
enum Zapped {
case not_zapped
case pending
case zapped
}
class ActionBarModel: ObservableObject {
@Published var our_like: NostrEvent?
@Published var our_boost: NostrEvent?
@Published var our_reply: NostrEvent?
@Published var our_zap: Zap?
@Published var our_zap: Zapping?
@Published var likes: Int
@Published var boosts: Int
@Published var zaps: Int
@@ -35,7 +40,7 @@ class ActionBarModel: ObservableObject {
self.replies = 0
}
init(likes: Int, boosts: Int, zaps: Int, zap_total: Int64, replies: Int, our_like: NostrEvent?, our_boost: NostrEvent?, our_zap: Zap?, our_reply: NostrEvent?) {
init(likes: Int, boosts: Int, zaps: Int, zap_total: Int64, replies: Int, our_like: NostrEvent?, our_boost: NostrEvent?, our_zap: Zapping?, our_reply: NostrEvent?) {
self.likes = likes
self.boosts = boosts
self.zaps = zaps
@@ -64,10 +69,6 @@ class ActionBarModel: ObservableObject {
return likes == 0 && boosts == 0 && zaps == 0
}
var zapped: Bool {
return our_zap != nil
}
var liked: Bool {
return our_like != nil
}

View File

@@ -32,7 +32,7 @@ struct DamusState {
let wallet: WalletModel
@discardableResult
func add_zap(zap: Zap) -> Bool {
func add_zap(zap: Zapping) -> Bool {
// store generic zap mapping
self.zaps.add_zap(zap: zap)
// associate with events as well

View File

@@ -129,6 +129,25 @@ class HomeModel: ObservableObject {
handle_zap_event(ev)
case .zap_request:
break
case .nwc_request:
break
case .nwc_response:
handle_nwc_response(ev)
}
}
func handle_nwc_response(_ ev: NostrEvent) {
Task { @MainActor in
guard let resp = await FullWalletResponse(from: ev) else {
return
}
if resp.response.error == nil {
nwc_success(zapcache: self.damus_state.zaps, resp: resp)
return
}
nwc_error(zapcache: self.damus_state.zaps, evcache: self.damus_state.events, resp: resp)
}
}
@@ -137,13 +156,13 @@ class HomeModel: ObservableObject {
return
}
damus_state.add_zap(zap: zap)
damus_state.add_zap(zap: .zap(zap))
guard zap.target.pubkey == our_keypair.pubkey else {
return
}
if !notifications.insert_zap(zap) {
if !notifications.insert_zap(.zap(zap)) {
return
}
@@ -301,6 +320,16 @@ class HomeModel: ObservableObject {
//remove_bootstrap_nodes(damus_state)
send_home_filters(relay_id: relay_id)
}
// connect to nwc relays when connected
if let nwc_str = damus_state.settings.nostr_wallet_connect,
let r = pool.get_relay(relay_id),
r.descriptor.variant == .nwc,
let nwc = WalletConnectURL(str: nwc_str),
nwc.relay.id == relay_id
{
subscribe_to_nwc(url: nwc, pool: pool)
}
case .error(let merr):
let desc = String(describing: merr)
if desc.contains("Software caused connection abort") {
@@ -431,7 +460,7 @@ class HomeModel: ObservableObject {
print_filters(relay_id: relay_id, filters: [home_filters, contacts_filters, notifications_filters, dms_filters])
if let relay_id = relay_id {
if let relay_id {
pool.send(.subscribe(.init(filters: home_filters, sub_id: home_subid)), to: [relay_id])
pool.send(.subscribe(.init(filters: contacts_filters, sub_id: contacts_subid)), to: [relay_id])
pool.send(.subscribe(.init(filters: notifications_filters, sub_id: notifications_subid)), to: [relay_id])
@@ -836,7 +865,8 @@ func load_our_relays(state: DamusState, m_old_ev: NostrEvent?, ev: NostrEvent) {
changed = true
if new.contains(d) {
if let url = RelayURL(d) {
add_new_relay(relay_filters: state.relay_filters, metadatas: state.relay_metadata, pool: state.pool, url: url, info: decoded[d] ?? .rw, new_relay_filters: new_relay_filters)
let descriptor = RelayDescriptor(url: url, info: decoded[d] ?? .rw)
add_new_relay(relay_filters: state.relay_filters, metadatas: state.relay_metadata, pool: state.pool, descriptor: descriptor, new_relay_filters: new_relay_filters)
}
} else {
state.pool.remove_relay(d)
@@ -849,8 +879,9 @@ func load_our_relays(state: DamusState, m_old_ev: NostrEvent?, ev: NostrEvent) {
}
}
func add_new_relay(relay_filters: RelayFilters, metadatas: RelayMetadatas, pool: RelayPool, url: RelayURL, info: RelayInfo, new_relay_filters: Bool) {
try? pool.add_relay(url, info: info)
func add_new_relay(relay_filters: RelayFilters, metadatas: RelayMetadatas, pool: RelayPool, descriptor: RelayDescriptor, new_relay_filters: Bool) {
try? pool.add_relay(descriptor)
let url = descriptor.url
let relay_id = url.id
guard metadatas.lookup(relay_id: relay_id) == nil else {

View File

@@ -8,7 +8,7 @@
import Foundation
class ZapGroup {
var zaps: [Zap]
var zaps: [Zapping]
var msat_total: Int64
var zappers: Set<String>
@@ -17,22 +17,16 @@ class ZapGroup {
return 0
}
return first.event.created_at
return first.created_at
}
func zap_requests() -> [NostrEvent] {
zaps.map { z in
if let priv = z.private_request {
return priv
} else {
return z.request.ev
}
}
zaps.map { z in z.request }
}
func would_filter(_ isIncluded: (NostrEvent) -> Bool) -> Bool {
for zap in zaps {
if !isIncluded(zap.request_ev) {
if !isIncluded(zap.request) {
return true
}
}
@@ -41,7 +35,7 @@ class ZapGroup {
}
func filter(_ isIncluded: (NostrEvent) -> Bool) -> ZapGroup? {
let new_zaps = zaps.filter { isIncluded($0.request_ev) }
let new_zaps = zaps.filter { isIncluded($0.request) }
guard new_zaps.count > 0 else {
return nil
}
@@ -59,15 +53,15 @@ class ZapGroup {
}
@discardableResult
func insert(_ zap: Zap) -> Bool {
func insert(_ zap: Zapping) -> Bool {
if !insert_uniq_sorted_zap_by_created(zaps: &zaps, new_zap: zap) {
return false
}
msat_total += zap.invoice.amount
msat_total += zap.amount
if !zappers.contains(zap.request.ev.pubkey) {
zappers.insert(zap.request.ev.pubkey)
if !zappers.contains(zap.request.pubkey) {
zappers.insert(zap.request.pubkey)
}
return true

View File

@@ -99,7 +99,7 @@ enum NotificationItem {
}
class NotificationsModel: ObservableObject, ScrollQueue {
var incoming_zaps: [Zap]
var incoming_zaps: [Zapping]
var incoming_events: [NostrEvent]
var should_queue: Bool
@@ -150,7 +150,7 @@ class NotificationsModel: ObservableObject, ScrollQueue {
}
for zap in incoming_zaps {
pks.insert(zap.request.ev.pubkey)
pks.insert(zap.request.pubkey)
}
return Array(pks)
@@ -249,7 +249,7 @@ class NotificationsModel: ObservableObject, ScrollQueue {
return false
}
private func insert_zap_immediate(_ zap: Zap) -> Bool {
private func insert_zap_immediate(_ zap: Zapping) -> Bool {
switch zap.target {
case .note(let notezt):
let id = notezt.note_id
@@ -285,7 +285,7 @@ class NotificationsModel: ObservableObject, ScrollQueue {
return false
}
func insert_zap(_ zap: Zap) -> Bool {
func insert_zap(_ zap: Zapping) -> Bool {
if should_queue {
return insert_uniq_sorted_zap_by_created(zaps: &incoming_zaps, new_zap: zap)
}
@@ -307,7 +307,7 @@ class NotificationsModel: ObservableObject, ScrollQueue {
changed = changed || incoming_events.count != count
count = profile_zaps.zaps.count
profile_zaps.zaps = profile_zaps.zaps.filter { zap in isIncluded(zap.request.ev) }
profile_zaps.zaps = profile_zaps.zaps.filter { zap in isIncluded(zap.request) }
changed = changed || profile_zaps.zaps.count != count
for el in reactions {
@@ -325,7 +325,7 @@ class NotificationsModel: ObservableObject, ScrollQueue {
for el in zaps {
count = el.value.zaps.count
el.value.zaps = el.value.zaps.filter {
isIncluded($0.request.ev)
isIncluded($0.request)
}
changed = changed || el.value.zaps.count != count
}

View File

@@ -19,7 +19,7 @@ class ZapsModel: ObservableObject {
self.target = target
}
var zaps: [Zap] {
var zaps: [Zapping] {
return state.events.lookup_zaps(target: target)
}
@@ -53,7 +53,7 @@ class ZapsModel: ObservableObject {
case .notice:
break
case .eose:
let events = state.events.lookup_zaps(target: target).map { $0.request_ev }
let events = state.events.lookup_zaps(target: target).map { $0.request }
load_profiles(profiles_subid: profiles_subid, relay_id: relay_id, load: .from_events(events), damus_state: state)
case .event(_, let ev):
guard ev.kind == 9735 else {
@@ -61,22 +61,19 @@ class ZapsModel: ObservableObject {
}
if let zap = state.zaps.zaps[ev.id] {
if state.events.store_zap(zap: zap) {
objectWillChange.send()
}
} else {
guard let zapper = state.profiles.lookup_zapper(pubkey: target.pubkey) else {
return
}
guard let zap = Zap.from_zap_event(zap_ev: ev, zapper: zapper, our_privkey: state.keypair.privkey) else {
return
}
if self.state.add_zap(zap: zap) {
objectWillChange.send()
}
state.events.store_zap(zap: zap)
return
}
guard let zapper = state.profiles.lookup_zapper(pubkey: target.pubkey) else {
return
}
guard let zap = Zap.from_zap_event(zap_ev: ev, zapper: zapper, our_privkey: state.keypair.privkey) else {
return
}
self.state.add_zap(zap: .zap(zap))
}