diff --git a/damus/Components/ImageCarousel.swift b/damus/Components/ImageCarousel.swift index 48f6cdd9..f99b6729 100644 --- a/damus/Components/ImageCarousel.swift +++ b/damus/Components/ImageCarousel.swift @@ -57,7 +57,7 @@ enum ImageShape { struct ImageCarousel: View { var urls: [MediaUrl] - let evid: String + let evid: NoteId let state: DamusState @@ -72,7 +72,7 @@ struct ImageCarousel: View { @State private var selectedIndex = 0 @State private var video_size: CGSize? = nil - init(state: DamusState, evid: String, urls: [MediaUrl]) { + init(state: DamusState, evid: NoteId, urls: [MediaUrl]) { _open_sheet = State(initialValue: false) _current_url = State(initialValue: nil) let media_model = state.events.get_cache_data(evid).media_metadata_model diff --git a/damus/Components/InvoiceView.swift b/damus/Components/InvoiceView.swift index 6ca5ccb1..ad370030 100644 --- a/damus/Components/InvoiceView.swift +++ b/damus/Components/InvoiceView.swift @@ -9,7 +9,7 @@ import SwiftUI struct InvoiceView: View { @Environment(\.colorScheme) var colorScheme - let our_pubkey: String + let our_pubkey: Pubkey let invoice: Invoice @State var showing_select_wallet: Bool = false @State var copied = false @@ -108,7 +108,7 @@ let test_invoice = Invoice(description: .description("this is a description"), a struct InvoiceView_Previews: PreviewProvider { static var previews: some View { - InvoiceView(our_pubkey: "", invoice: test_invoice, settings: test_damus_state().settings) + InvoiceView(our_pubkey: .empty, invoice: test_invoice, settings: test_damus_state().settings) .frame(width: 300, height: 200) } } diff --git a/damus/Components/InvoicesView.swift b/damus/Components/InvoicesView.swift index 86f851d0..9c587abb 100644 --- a/damus/Components/InvoicesView.swift +++ b/damus/Components/InvoicesView.swift @@ -8,7 +8,7 @@ import SwiftUI struct InvoicesView: View { - let our_pubkey: String + let our_pubkey: Pubkey var invoices: [Invoice] let settings: UserSettingsStore @@ -29,7 +29,7 @@ struct InvoicesView: View { struct InvoicesView_Previews: PreviewProvider { static var previews: some View { - InvoicesView(our_pubkey: "", invoices: [Invoice.init(description: .description("description"), amount: .specific(10000), string: "invstr", expiry: 100000, payment_hash: Data(), created_at: 1000000)], settings: test_damus_state().settings) + InvoicesView(our_pubkey: test_note.pubkey, invoices: [Invoice.init(description: .description("description"), amount: .specific(10000), string: "invstr", expiry: 100000, payment_hash: Data(), created_at: 1000000)], settings: test_damus_state().settings) .frame(width: 300) } } diff --git a/damus/Components/NIP05Badge.swift b/damus/Components/NIP05Badge.swift index 759b733e..0c2552db 100644 --- a/damus/Components/NIP05Badge.swift +++ b/damus/Components/NIP05Badge.swift @@ -9,14 +9,14 @@ import SwiftUI struct NIP05Badge: View { let nip05: NIP05 - let pubkey: String + let pubkey: Pubkey let contacts: Contacts let show_domain: Bool let profiles: Profiles @Environment(\.openURL) var openURL - init(nip05: NIP05, pubkey: String, contacts: Contacts, show_domain: Bool, profiles: Profiles) { + init(nip05: NIP05, pubkey: Pubkey, contacts: Contacts, show_domain: Bool, profiles: Profiles) { self.nip05 = nip05 self.pubkey = pubkey self.contacts = contacts @@ -91,7 +91,7 @@ extension View { } } -func use_nip05_color(pubkey: String, contacts: Contacts) -> Bool { +func use_nip05_color(pubkey: Pubkey, contacts: Contacts) -> Bool { return contacts.is_friend_or_self(pubkey) ? true : false } @@ -105,7 +105,7 @@ struct NIP05Badge_Previews: PreviewProvider { NIP05Badge(nip05: NIP05(username: "jb55", host: "jb55.com"), pubkey: test_state.pubkey, contacts: test_state.contacts, show_domain: true, profiles: test_state.profiles) - NIP05Badge(nip05: NIP05(username: "jb55", host: "jb55.com"), pubkey: test_state.pubkey, contacts: Contacts(our_pubkey: "sdkfjsdf"), show_domain: true, profiles: test_state.profiles) + NIP05Badge(nip05: NIP05(username: "jb55", host: "jb55.com"), pubkey: test_state.pubkey, contacts: Contacts(our_pubkey: test_pubkey), show_domain: true, profiles: test_state.profiles) } } } diff --git a/damus/Components/Reposted.swift b/damus/Components/Reposted.swift index 4808e870..f4e5e80f 100644 --- a/damus/Components/Reposted.swift +++ b/damus/Components/Reposted.swift @@ -9,7 +9,7 @@ import SwiftUI struct Reposted: View { let damus: DamusState - let pubkey: String + let pubkey: Pubkey let profile: Profile? var body: some View { diff --git a/damus/Components/TranslateView.swift b/damus/Components/TranslateView.swift index ccab2d7c..47830f9a 100644 --- a/damus/Components/TranslateView.swift +++ b/damus/Components/TranslateView.swift @@ -125,7 +125,7 @@ struct TranslateView_Previews: PreviewProvider { } } -func translate_note(profiles: Profiles, privkey: String?, event: NostrEvent, settings: UserSettingsStore, note_lang: String) async -> TranslateStatus { +func translate_note(profiles: Profiles, privkey: Privkey?, event: NostrEvent, settings: UserSettingsStore, note_lang: String) async -> TranslateStatus { // If the note language is different from our preferred languages, send a translation request. let translator = Translator(settings) diff --git a/damus/Components/UserView.swift b/damus/Components/UserView.swift index 9cf08867..e59fe24b 100644 --- a/damus/Components/UserView.swift +++ b/damus/Components/UserView.swift @@ -9,8 +9,8 @@ import SwiftUI struct UserViewRow: View { let damus_state: DamusState - let pubkey: String - + let pubkey: Pubkey + var body: some View { UserView(damus_state: damus_state, pubkey: pubkey) .contentShape(Rectangle()) @@ -20,12 +20,12 @@ struct UserViewRow: View { struct UserView: View { let damus_state: DamusState - let pubkey: String + let pubkey: Pubkey let spacer: Bool @State var about_text: Text? = nil - init(damus_state: DamusState, pubkey: String, spacer: Bool = true) { + init(damus_state: DamusState, pubkey: Pubkey, spacer: Bool = true) { self.damus_state = damus_state self.pubkey = pubkey self.spacer = spacer diff --git a/damus/ContentView.swift b/damus/ContentView.swift index 2c0f5c0c..32d8b58c 100644 --- a/damus/ContentView.swift +++ b/damus/ContentView.swift @@ -70,11 +70,11 @@ enum FilterState : Int { struct ContentView: View { let keypair: Keypair - var pubkey: String { + var pubkey: Pubkey { return keypair.pubkey } - var privkey: String? { + var privkey: Privkey? { return keypair.privkey } @@ -83,7 +83,7 @@ struct ContentView: View { @State var active_sheet: Sheets? = nil @State var damus_state: DamusState? = nil @SceneStorage("ContentView.selected_timeline") var selected_timeline: Timeline = .home - @State var muting: String? = nil + @State var muting: Pubkey? = nil @State var confirm_mute: Bool = false @State var user_muted_confirm: Bool = false @State var confirm_overwrite_mutelist: Bool = false @@ -231,9 +231,9 @@ struct ContentView: View { navigationCoordinator.push(route: Route.Script(script: model)) } - func open_profile(id: String) { - let profile_model = ProfileModel(pubkey: id, damus: damus_state!) - let followers = FollowersModel(damus_state: damus_state!, target: id) + func open_profile(pubkey: Pubkey) { + let profile_model = ProfileModel(pubkey: pubkey, damus: damus_state!) + let followers = FollowersModel(damus_state: damus_state!, target: pubkey) navigationCoordinator.push(route: Route.Profile(profile: profile_model, followers: followers)) } @@ -342,7 +342,7 @@ struct ContentView: View { switch res { case .filter(let filt): self.open_search(filt: filt) - case .profile(let id): self.open_profile(id: id) + case .profile(let pk): self.open_profile(pubkey: pk) case .event(let ev): self.open_event(ev: ev) case .wallet_connect(let nwc): self.open_wallet(nwc: nwc) case .script(let data): self.open_script(data) @@ -470,7 +470,7 @@ struct ContentView: View { guard let damus_state else { return } if local.type == .profile_zap { - open_profile(id: local.event_id) + open_profile(pubkey: local.event_id) return } @@ -656,7 +656,7 @@ struct ContentView: View { struct ContentView_Previews: PreviewProvider { static var previews: some View { - ContentView(keypair: Keypair(pubkey: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681", privkey: nil)) + ContentView(keypair: Keypair(pubkey: test_pubkey, privkey: nil)) } } @@ -680,7 +680,7 @@ extension UINavigationController: UIGestureRecognizerDelegate { } struct LastNotification { - let id: String + let id: NoteId let created_at: Int64 } @@ -689,17 +689,20 @@ func get_last_event(_ timeline: Timeline) -> LastNotification? { let last = UserDefaults.standard.string(forKey: "last_\(str)") let last_created = UserDefaults.standard.string(forKey: "last_\(str)_time") .flatMap { Int64($0) } - - return last.flatMap { id in - last_created.map { created in - return LastNotification(id: id, created_at: created) - } + + guard let last, + let note_id = NoteId(hex: last), + let last_created + else { + return nil } + + return LastNotification(id: note_id, created_at: last_created) } func save_last_event(_ ev: NostrEvent, timeline: Timeline) { let str = timeline.rawValue - UserDefaults.standard.set(ev.id, forKey: "last_\(str)") + UserDefaults.standard.set(ev.id.hex(), forKey: "last_\(str)") UserDefaults.standard.set(String(ev.created_at), forKey: "last_\(str)_time") } @@ -757,18 +760,18 @@ struct FindEvent { let type: FindEventType let find_from: [String]? - static func profile(pubkey: String, find_from: [String]? = nil) -> FindEvent { + static func profile(pubkey: Pubkey, find_from: [String]? = nil) -> FindEvent { return FindEvent(type: .profile(pubkey), find_from: find_from) } - static func event(evid: String, find_from: [String]? = nil) -> FindEvent { + static func event(evid: NoteId, find_from: [String]? = nil) -> FindEvent { return FindEvent(type: .event(evid), find_from: find_from) } } enum FindEventType { - case profile(String) - case event(String) + case profile(Pubkey) + case event(NoteId) } enum FoundEvent { @@ -961,7 +964,7 @@ func handle_post_notification(keypair: FullKeypair, postbox: PostBox, events: Ev enum OpenResult { - case profile(String) + case profile(Pubkey) case filter(NostrFilter) case event(NostrEvent) case wallet_connect(WalletConnectURL) diff --git a/damus/Models/ActionBarModel.swift b/damus/Models/ActionBarModel.swift index bf51d574..d0109757 100644 --- a/damus/Models/ActionBarModel.swift +++ b/damus/Models/ActionBarModel.swift @@ -40,7 +40,7 @@ class ActionBarModel: ObservableObject { self.our_reply = our_reply } - func update(damus: DamusState, evid: String) { + func update(damus: DamusState, evid: NoteId) { self.likes = damus.likes.counts[evid] ?? 0 self.boosts = damus.boosts.counts[evid] ?? 0 self.zaps = damus.zaps.event_counts[evid] ?? 0 diff --git a/damus/Models/BookmarksManager.swift b/damus/Models/BookmarksManager.swift index 43a9c919..2f694d54 100644 --- a/damus/Models/BookmarksManager.swift +++ b/damus/Models/BookmarksManager.swift @@ -7,18 +7,18 @@ import Foundation -fileprivate func get_bookmarks_key(pubkey: String) -> String { +fileprivate func get_bookmarks_key(pubkey: Pubkey) -> String { pk_setting_key(pubkey, key: "bookmarks") } -func load_bookmarks(pubkey: String) -> [NostrEvent] { +func load_bookmarks(pubkey: Pubkey) -> [NostrEvent] { let key = get_bookmarks_key(pubkey: pubkey) return (UserDefaults.standard.stringArray(forKey: key) ?? []).compactMap { event_from_json(dat: $0) } } -func save_bookmarks(pubkey: String, current_value: [NostrEvent], value: [NostrEvent]) -> Bool { +func save_bookmarks(pubkey: Pubkey, current_value: [NostrEvent], value: [NostrEvent]) -> Bool { let uniq_bookmarks = uniq(value) if uniq_bookmarks != current_value { @@ -32,8 +32,8 @@ func save_bookmarks(pubkey: String, current_value: [NostrEvent], value: [NostrEv class BookmarksManager: ObservableObject { - private let pubkey: String - + private let pubkey: Pubkey + private var _bookmarks: [NostrEvent] var bookmarks: [NostrEvent] { get { @@ -47,7 +47,7 @@ class BookmarksManager: ObservableObject { } } - init(pubkey: String) { + init(pubkey: Pubkey) { self._bookmarks = load_bookmarks(pubkey: pubkey) self.pubkey = pubkey } diff --git a/damus/Models/Contacts.swift b/damus/Models/Contacts.swift index 0f781f7d..1e8eeef1 100644 --- a/damus/Models/Contacts.swift +++ b/damus/Models/Contacts.swift @@ -9,21 +9,21 @@ import Foundation class Contacts { - private var friends: Set = Set() - private var friend_of_friends: Set = Set() + private var friends: Set = Set() + private var friend_of_friends: Set = Set() /// Tracks which friends are friends of a given pubkey. - private var pubkey_to_our_friends = [String : Set]() - private var muted: Set = Set() - - let our_pubkey: String + private var pubkey_to_our_friends = [Pubkey : Set]() + private var muted: Set = Set() + + let our_pubkey: Pubkey var event: NostrEvent? var mutelist: NostrEvent? - init(our_pubkey: String) { + init(our_pubkey: Pubkey) { self.our_pubkey = our_pubkey } - func is_muted(_ pk: String) -> Bool { + func is_muted(_ pk: Pubkey) -> Bool { return muted.contains(pk) } @@ -58,7 +58,7 @@ class Contacts { } } - func remove_friend(_ pubkey: String) { + func remove_friend(_ pubkey: Pubkey) { friends.remove(pubkey) pubkey_to_our_friends.forEach { @@ -66,7 +66,7 @@ class Contacts { } } - func get_friend_list() -> Set { + func get_friend_list() -> Set { return friends } @@ -75,7 +75,7 @@ class Contacts { return Set(ev.referenced_hashtags.map({ $0.ref_id.string() })) } - func add_friend_pubkey(_ pubkey: String) { + func add_friend_pubkey(_ pubkey: Pubkey) { friends.insert(pubkey) } @@ -88,7 +88,7 @@ class Contacts { // Exclude themself and us. if contact.pubkey != our_pubkey && contact.pubkey != pk { if pubkey_to_our_friends[pk] == nil { - pubkey_to_our_friends[pk] = Set() + pubkey_to_our_friends[pk] = Set() } pubkey_to_our_friends[pk]?.insert(contact.pubkey) @@ -96,28 +96,28 @@ class Contacts { } } - func is_friend_of_friend(_ pubkey: String) -> Bool { + func is_friend_of_friend(_ pubkey: Pubkey) -> Bool { return friend_of_friends.contains(pubkey) } - func is_in_friendosphere(_ pubkey: String) -> Bool { + func is_in_friendosphere(_ pubkey: Pubkey) -> Bool { return friends.contains(pubkey) || friend_of_friends.contains(pubkey) } - func is_friend(_ pubkey: String) -> Bool { + func is_friend(_ pubkey: Pubkey) -> Bool { return friends.contains(pubkey) } - func is_friend_or_self(_ pubkey: String) -> Bool { + func is_friend_or_self(_ pubkey: Pubkey) -> Bool { return pubkey == our_pubkey || is_friend(pubkey) } - func follow_state(_ pubkey: String) -> FollowState { + func follow_state(_ pubkey: Pubkey) -> FollowState { return is_friend(pubkey) ? .follows : .unfollows } /// Gets the list of pubkeys of our friends who follow the given pubkey. - func get_friended_followers(_ pubkey: String) -> [String] { + func get_friended_followers(_ pubkey: Pubkey) -> [Pubkey] { return Array((pubkey_to_our_friends[pubkey] ?? Set())) } } diff --git a/damus/Models/CreateAccountModel.swift b/damus/Models/CreateAccountModel.swift index 45561ddf..1534caa2 100644 --- a/damus/Models/CreateAccountModel.swift +++ b/damus/Models/CreateAccountModel.swift @@ -12,8 +12,8 @@ class CreateAccountModel: ObservableObject { @Published var real_name: String = "" @Published var nick_name: String = "" @Published var about: String = "" - @Published var pubkey: String = "" - @Published var privkey: String = "" + @Published var pubkey: Pubkey = .empty + @Published var privkey: Privkey = .empty @Published var profile_image: URL? = nil var pubkey_bech32: String { diff --git a/damus/Models/DamusState.swift b/damus/Models/DamusState.swift index c4a6cd02..c455ab96 100644 --- a/damus/Models/DamusState.swift +++ b/damus/Models/DamusState.swift @@ -50,7 +50,7 @@ struct DamusState { return stored } - var pubkey: String { + var pubkey: Pubkey { return keypair.pubkey } diff --git a/damus/Models/DirectMessageModel.swift b/damus/Models/DirectMessageModel.swift index f5b1a1b4..3d6e0470 100644 --- a/damus/Models/DirectMessageModel.swift +++ b/damus/Models/DirectMessageModel.swift @@ -16,11 +16,11 @@ class DirectMessageModel: ObservableObject { @Published var draft: String = "" - let pubkey: String - + let pubkey: Pubkey + var is_request = false - var our_pubkey: String - + var our_pubkey: Pubkey + func determine_is_request() -> Bool { for event in events { if event.pubkey == our_pubkey { @@ -31,7 +31,7 @@ class DirectMessageModel: ObservableObject { return true } - init(events: [NostrEvent] = [], our_pubkey: String, pubkey: String) { + init(events: [NostrEvent] = [], our_pubkey: Pubkey, pubkey: Pubkey) { self.events = events self.our_pubkey = our_pubkey self.pubkey = pubkey diff --git a/damus/Models/DirectMessagesModel.swift b/damus/Models/DirectMessagesModel.swift index 7402de67..ba75ef55 100644 --- a/damus/Models/DirectMessagesModel.swift +++ b/damus/Models/DirectMessagesModel.swift @@ -11,10 +11,10 @@ class DirectMessagesModel: ObservableObject { @Published var dms: [DirectMessageModel] = [] @Published var loading: Bool = false @Published var open_dm: Bool = false - @Published private(set) var active_model: DirectMessageModel = DirectMessageModel(our_pubkey: "", pubkey: "") - let our_pubkey: String - - init(our_pubkey: String) { + @Published private(set) var active_model: DirectMessageModel = DirectMessageModel(our_pubkey: .empty, pubkey: .empty) + let our_pubkey: Pubkey + + init(our_pubkey: Pubkey) { self.our_pubkey = our_pubkey } @@ -30,14 +30,14 @@ class DirectMessagesModel: ObservableObject { self.active_model = model } - func set_active_dm(_ pubkey: String) { + func set_active_dm(_ pubkey: Pubkey) { for model in self.dms where model.pubkey == pubkey { self.set_active_dm_model(model) break } } - func lookup_or_create(_ pubkey: String) -> DirectMessageModel { + func lookup_or_create(_ pubkey: Pubkey) -> DirectMessageModel { if let dm = lookup(pubkey) { return dm } @@ -47,7 +47,7 @@ class DirectMessagesModel: ObservableObject { return new } - func lookup(_ pubkey: String) -> DirectMessageModel? { + func lookup(_ pubkey: Pubkey) -> DirectMessageModel? { for dm in dms { if pubkey == dm.pubkey { return dm diff --git a/damus/Models/EventsModel.swift b/damus/Models/EventsModel.swift index aa9130ba..2a32da84 100644 --- a/damus/Models/EventsModel.swift +++ b/damus/Models/EventsModel.swift @@ -10,14 +10,14 @@ import Foundation class EventsModel: ObservableObject { let state: DamusState - let target: String + let target: NoteId let kind: NostrKind let sub_id = UUID().uuidString let profiles_id = UUID().uuidString @Published var events: [NostrEvent] = [] - init(state: DamusState, target: String, kind: NostrKind) { + init(state: DamusState, target: NoteId, kind: NostrKind) { self.state = state self.target = target self.kind = kind diff --git a/damus/Models/FollowersModel.swift b/damus/Models/FollowersModel.swift index 1f90df29..b3cec471 100644 --- a/damus/Models/FollowersModel.swift +++ b/damus/Models/FollowersModel.swift @@ -9,11 +9,11 @@ import Foundation class FollowersModel: ObservableObject { let damus_state: DamusState - let target: String - - @Published var contacts: [String]? = nil - var has_contact: Set = Set() - + let target: Pubkey + + @Published var contacts: [Pubkey]? = nil + var has_contact: Set = Set() + let sub_id: String = UUID().description let profiles_id: String = UUID().description @@ -24,14 +24,13 @@ class FollowersModel: ObservableObject { return contacts.count } - init(damus_state: DamusState, target: String) { + init(damus_state: DamusState, target: Pubkey) { self.damus_state = damus_state self.target = target } func get_filter() -> NostrFilter { - NostrFilter(kinds: [.contacts], - pubkeys: [target]) + NostrFilter(kinds: [.contacts], pubkeys: [target]) } func subscribe() { diff --git a/damus/Models/FollowingModel.swift b/damus/Models/FollowingModel.swift index 08fe905f..64c90566 100644 --- a/damus/Models/FollowingModel.swift +++ b/damus/Models/FollowingModel.swift @@ -11,18 +11,18 @@ class FollowingModel { let damus_state: DamusState var needs_sub: Bool = true - let contacts: [String] - + let contacts: [Pubkey] + let sub_id: String = UUID().description - init(damus_state: DamusState, contacts: [String]) { + init(damus_state: DamusState, contacts: [Pubkey]) { self.damus_state = damus_state self.contacts = contacts } func get_filter() -> NostrFilter { var f = NostrFilter(kinds: [.metadata]) - f.authors = self.contacts.reduce(into: Array()) { acc, pk in + f.authors = self.contacts.reduce(into: Array()) { acc, pk in // don't fetch profiles we already have if damus_state.profiles.has_fresh_profile(id: pk) { return diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift index 8ca93ea2..e2235727 100644 --- a/damus/Models/HomeModel.swift +++ b/damus/Models/HomeModel.swift @@ -29,7 +29,7 @@ enum Resubscribe { } enum HomeResubFilter { - case pubkey(String) + case pubkey(Pubkey) case hashtag(String) init?(from: ReferencedId) { @@ -63,9 +63,10 @@ class HomeModel { var damus_state: DamusState - var has_event: [String: Set] = [:] - var deleted_events: Set = Set() var channels: [String: NostrEvent] = [:] + // NDBTODO: let's get rid of this entirely, let nostrdb handle it + var has_event: [String: Set] = [:] + var deleted_events: Set = Set() var last_event_of_kind: [String: [UInt32: NostrEvent]] = [:] var done_init: Bool = false var incoming_dms: [NostrEvent] = [] @@ -109,7 +110,7 @@ class HomeModel { return damus_state.dms } - func has_sub_id_event(sub_id: String, ev_id: String) -> Bool { + func has_sub_id_event(sub_id: String, ev_id: NoteId) -> Bool { if !has_event.keys.contains(sub_id) { has_event[sub_id] = Set() return false @@ -502,13 +503,13 @@ class HomeModel { pool.send(.unsubscribe(home_subid)) } - func get_friends() -> [String] { + func get_friends() -> [Pubkey] { var friends = damus_state.contacts.get_friend_list() friends.insert(damus_state.pubkey) return Array(friends) } - func subscribe_to_home_filters(friends fs: [String]? = nil, relay_id: String? = nil) { + func subscribe_to_home_filters(friends fs: [Pubkey]? = nil, relay_id: String? = nil) { // TODO: separate likes? var home_filter_kinds: [NostrKind] = [ .text, .longform, .boost @@ -782,7 +783,7 @@ func print_filters(relay_id: String?, filters groups: [[NostrFilter]]) { print("-----") } -func process_metadata_profile(our_pubkey: String, profiles: Profiles, profile: Profile, ev: NostrEvent) { +func process_metadata_profile(our_pubkey: Pubkey, profiles: Profiles, profile: Profile, ev: NostrEvent) { var old_nip05: String? = nil let mprof = profiles.lookup_with_timestamp(id: ev.pubkey) @@ -847,7 +848,7 @@ func guard_valid_event(events: EventCache, ev: NostrEvent, callback: @escaping ( } } -func process_metadata_event(events: EventCache, our_pubkey: String, profiles: Profiles, ev: NostrEvent, completion: ((Profile?) -> Void)? = nil) { +func process_metadata_event(events: EventCache, our_pubkey: Pubkey, profiles: Profiles, ev: NostrEvent, completion: ((Profile?) -> Void)? = nil) { guard_valid_event(events: events, ev: ev) { DispatchQueue.global(qos: .background).async { guard let profile: Profile = decode_data(Data(ev.content.utf8)) else { @@ -865,8 +866,8 @@ func process_metadata_event(events: EventCache, our_pubkey: String, profiles: Pr } } -func robohash(_ pk: String) -> String { - return "https://robohash.org/" + pk +func robohash(_ pk: Pubkey) -> String { + return "https://robohash.org/" + pk.hex() } func load_our_stuff(state: DamusState, ev: NostrEvent) { @@ -1171,7 +1172,7 @@ func zap_notification_body(profiles: Profiles, zap: Zap, locale: Locale = Locale } } -func create_in_app_profile_zap_notification(profiles: Profiles, zap: Zap, locale: Locale = Locale.current, profile_id: String) { +func create_in_app_profile_zap_notification(profiles: Profiles, zap: Zap, locale: Locale = Locale.current, profile_id: Pubkey) { let content = UNMutableNotificationContent() content.title = zap_notification_title(zap) @@ -1192,7 +1193,7 @@ func create_in_app_profile_zap_notification(profiles: Profiles, zap: Zap, locale } } -func create_in_app_event_zap_notification(profiles: Profiles, zap: Zap, locale: Locale = Locale.current, evId: String) { +func create_in_app_event_zap_notification(profiles: Profiles, zap: Zap, locale: Locale = Locale.current, evId: NoteId) { let content = UNMutableNotificationContent() content.title = zap_notification_title(zap) @@ -1213,7 +1214,7 @@ func create_in_app_event_zap_notification(profiles: Profiles, zap: Zap, locale: } } -func render_notification_content_preview(cache: EventCache, ev: NostrEvent, profiles: Profiles, privkey: String?) -> String { +func render_notification_content_preview(cache: EventCache, ev: NostrEvent, profiles: Profiles, privkey: Privkey?) -> String { let prefix_len = 50 let artifacts = cache.get_cache_data(ev.id).artifacts.artifacts ?? render_note_content(ev: ev, profiles: profiles, privkey: privkey) @@ -1329,7 +1330,7 @@ enum ProcessZapResult { // securely get the zap target's pubkey. this can be faked so we need to be // careful -func get_zap_target_pubkey(ev: NostrEvent, events: EventCache) -> String? { +func get_zap_target_pubkey(ev: NostrEvent, events: EventCache) -> Pubkey? { let etags = ev.referenced_ids guard let etag = etags.first else { @@ -1409,7 +1410,7 @@ func process_zap_event(damus_state: DamusState, ev: NostrEvent, completion: @esc } -fileprivate func process_zap_event_with_zapper(damus_state: DamusState, ev: NostrEvent, zapper: String) -> Zap? { +fileprivate func process_zap_event_with_zapper(damus_state: DamusState, ev: NostrEvent, zapper: Pubkey) -> Zap? { let our_keypair = damus_state.keypair guard let zap = Zap.from_zap_event(zap_ev: ev, zapper: zapper, our_privkey: our_keypair.privkey) else { diff --git a/damus/Models/LikeCounter.swift b/damus/Models/LikeCounter.swift index d8dbe42e..4cbca085 100644 --- a/damus/Models/LikeCounter.swift +++ b/damus/Models/LikeCounter.swift @@ -13,16 +13,16 @@ enum CountResult { } class EventCounter { - var counts: [String: Int] = [:] - var user_events: [String: Set] = [:] - var our_events: [String: NostrEvent] = [:] - var our_pubkey: String - - init(our_pubkey: String) { + var counts: [NoteId: Int] = [:] + var user_events: [Pubkey: Set] = [:] + var our_events: [NoteId: NostrEvent] = [:] + var our_pubkey: Pubkey + + init(our_pubkey: Pubkey) { self.our_pubkey = our_pubkey } - func add_event(_ ev: NostrEvent, target: String) -> CountResult { + func add_event(_ ev: NostrEvent, target: NoteId) -> CountResult { let pubkey = ev.pubkey if self.user_events[pubkey] == nil { diff --git a/damus/Models/Liked.swift b/damus/Models/Liked.swift index 5d7eb35a..59b9263b 100644 --- a/damus/Models/Liked.swift +++ b/damus/Models/Liked.swift @@ -9,6 +9,6 @@ import Foundation struct Counted { let event: NostrEvent - let id: String + let id: NoteId let total: Int } diff --git a/damus/Models/MutedThreadsManager.swift b/damus/Models/MutedThreadsManager.swift index e788ac23..a76b6108 100644 --- a/damus/Models/MutedThreadsManager.swift +++ b/damus/Models/MutedThreadsManager.swift @@ -7,16 +7,16 @@ import Foundation -fileprivate func getMutedThreadsKey(pubkey: String) -> String { +fileprivate func getMutedThreadsKey(pubkey: Pubkey) -> String { pk_setting_key(pubkey, key: "muted_threads") } -func loadMutedThreads(pubkey: String) -> [String] { +func loadMutedThreads(pubkey: Pubkey) -> [NoteId] { let key = getMutedThreadsKey(pubkey: pubkey) return UserDefaults.standard.stringArray(forKey: key) ?? [] } -func saveMutedThreads(pubkey: String, currentValue: [String], value: [String]) -> Bool { +func saveMutedThreads(pubkey: Pubkey, currentValue: [NoteId], value: [NoteId]) -> Bool { let uniqueMutedThreads = Array(Set(value)) if uniqueMutedThreads != currentValue { @@ -31,9 +31,9 @@ class MutedThreadsManager: ObservableObject { private let keypair: Keypair - private var _mutedThreadsSet: Set - private var _mutedThreads: [String] - var mutedThreads: [String] { + private var _mutedThreadsSet: Set + private var _mutedThreads: [NoteId] + var mutedThreads: [NoteId] { get { return _mutedThreads } @@ -51,7 +51,7 @@ class MutedThreadsManager: ObservableObject { self.keypair = keypair } - func isMutedThread(_ ev: NostrEvent, privkey: String?) -> Bool { + func isMutedThread(_ ev: NostrEvent, privkey: Privkey?) -> Bool { return _mutedThreadsSet.contains(ev.thread_id(privkey: privkey)) } diff --git a/damus/Models/Notifications/ZapGroup.swift b/damus/Models/Notifications/ZapGroup.swift index 7cd4cb4c..3f55a95e 100644 --- a/damus/Models/Notifications/ZapGroup.swift +++ b/damus/Models/Notifications/ZapGroup.swift @@ -10,8 +10,8 @@ import Foundation class ZapGroup { var zaps: [Zapping] = [] var msat_total: Int64 = 0 - var zappers = Set() - + var zappers = Set() + var last_event_at: UInt32 { guard let first = zaps.first else { return 0 diff --git a/damus/Models/NotificationsModel.swift b/damus/Models/NotificationsModel.swift index dad0d129..c28afb1a 100644 --- a/damus/Models/NotificationsModel.swift +++ b/damus/Models/NotificationsModel.swift @@ -8,10 +8,10 @@ import Foundation enum NotificationItem { - case repost(String, EventGroup) - case reaction(String, EventGroup) + case repost(NoteId, EventGroup) + case reaction(NoteId, EventGroup) case profile_zap(ZapGroup) - case event_zap(String, ZapGroup) + case event_zap(NoteId, ZapGroup) case reply(NostrEvent) var is_reply: NostrEvent? { @@ -104,23 +104,23 @@ class NotificationsModel: ObservableObject, ScrollQueue { var should_queue: Bool = true // mappings from events to - var zaps: [String: ZapGroup] = [:] + var zaps: [NoteId: ZapGroup] = [:] var profile_zaps = ZapGroup() - var reactions: [String: EventGroup] = [:] - var reposts: [String: EventGroup] = [:] + var reactions: [NoteId: EventGroup] = [:] + var reposts: [NoteId: EventGroup] = [:] var replies: [NostrEvent] = [] - var has_reply = Set() - var has_ev = Set() - + var has_reply = Set() + var has_ev = Set() + @Published var notifications: [NotificationItem] = [] func set_should_queue(_ val: Bool) { self.should_queue = val } - func uniq_pubkeys() -> [String] { - var pks = Set() - + func uniq_pubkeys() -> [Pubkey] { + var pks = Set() + for ev in incoming_events { pks.insert(ev.pubkey) } diff --git a/damus/Models/ProfileModel.swift b/damus/Models/ProfileModel.swift index fbca1fc2..87010792 100644 --- a/damus/Models/ProfileModel.swift +++ b/damus/Models/ProfileModel.swift @@ -14,14 +14,14 @@ class ProfileModel: ObservableObject, Equatable { @Published var progress: Int = 0 var events: EventHolder - let pubkey: String + let pubkey: Pubkey let damus: DamusState - var seen_event: Set = Set() + var seen_event: Set = Set() var sub_id = UUID().description var prof_subid = UUID().description - init(pubkey: String, damus: DamusState) { + init(pubkey: Pubkey, damus: DamusState) { self.pubkey = pubkey self.damus = damus self.events = EventHolder(on_queue: { ev in @@ -29,7 +29,7 @@ class ProfileModel: ObservableObject, Equatable { }) } - func follows(pubkey: String) -> Bool { + func follows(pubkey: Pubkey) -> Bool { guard let contacts = self.contacts else { return false } diff --git a/damus/Models/ProfileUpdate.swift b/damus/Models/ProfileUpdate.swift index bcbb165b..7e302fba 100644 --- a/damus/Models/ProfileUpdate.swift +++ b/damus/Models/ProfileUpdate.swift @@ -9,6 +9,6 @@ import Foundation struct ProfileUpdate { - let pubkey: String + let pubkey: Pubkey let profile: Profile } diff --git a/damus/Models/ReactionsModel.swift b/damus/Models/ReactionsModel.swift index 7d25441f..3f3bf723 100644 --- a/damus/Models/ReactionsModel.swift +++ b/damus/Models/ReactionsModel.swift @@ -10,7 +10,7 @@ import Foundation final class ReactionsModel: EventsModel { - init(state: DamusState, target: String) { + init(state: DamusState, target: NoteId) { super.init(state: state, target: target, kind: .like) } } diff --git a/damus/Models/Reply.swift b/damus/Models/Reply.swift index 518006c8..89359e73 100644 --- a/damus/Models/Reply.swift +++ b/damus/Models/Reply.swift @@ -8,13 +8,13 @@ import Foundation struct ReplyDesc { - let pubkeys: [String] + let pubkeys: [Pubkey] let others: Int } func make_reply_description(_ tags: [[String]]) -> ReplyDesc { var c = 0 - var ns: [String] = [] + var ns: [Pubkey] = [] var i = tags.count - 1 while i >= 0 { diff --git a/damus/Models/ReplyMap.swift b/damus/Models/ReplyMap.swift index 3064fa05..c3da10dc 100644 --- a/damus/Models/ReplyMap.swift +++ b/damus/Models/ReplyMap.swift @@ -8,20 +8,20 @@ import Foundation class ReplyMap { - var replies: [String: Set] = [:] - - func lookup(_ id: String) -> Set? { + var replies: [NoteId: Set] = [:] + + func lookup(_ id: NoteId) -> Set? { return replies[id] } - private func ensure_set(id: String) { + private func ensure_set(id: NoteId) { if replies[id] == nil { replies[id] = Set() } } @discardableResult - func add(id: String, reply_id: String) -> Bool { + func add(id: NoteId, reply_id: NoteId) -> Bool { ensure_set(id: id) if (replies[id]!).contains(reply_id) { return false diff --git a/damus/Models/Report.swift b/damus/Models/Report.swift index fe59a3e9..3414125a 100644 --- a/damus/Models/Report.swift +++ b/damus/Models/Report.swift @@ -31,12 +31,12 @@ enum ReportType: String, CustomStringConvertible, CaseIterable { } struct ReportNoteTarget { - let pubkey: String - let note_id: String + let pubkey: Pubkey + let note_id: NoteId } enum ReportTarget { - case user(String) + case user(Pubkey) case note(ReportNoteTarget) static func note(pubkey: Pubkey, note_id: NoteId) -> ReportTarget { @@ -54,9 +54,10 @@ struct Report { func create_report_tags(target: ReportTarget, type: ReportType) -> [[String]] { switch target { case .user(let pubkey): - return [["p", pubkey, type.rawValue]] + return [["p", pubkey.hex(), type.rawValue]] case .note(let notet): - return [["e", notet.note_id, type.rawValue], ["p", notet.pubkey]] + return [["e", notet.note_id.hex(), type.rawValue], + ["p", notet.pubkey.hex()]] } } diff --git a/damus/Models/RepostsModel.swift b/damus/Models/RepostsModel.swift index 4b0fccce..2369b900 100644 --- a/damus/Models/RepostsModel.swift +++ b/damus/Models/RepostsModel.swift @@ -9,7 +9,7 @@ import Foundation final class RepostsModel: EventsModel { - init(state: DamusState, target: String) { + init(state: DamusState, target: NoteId) { super.init(state: state, target: target, kind: .boost) } } diff --git a/damus/Models/SearchHomeModel.swift b/damus/Models/SearchHomeModel.swift index e4f3a223..6931f395 100644 --- a/damus/Models/SearchHomeModel.swift +++ b/damus/Models/SearchHomeModel.swift @@ -13,7 +13,7 @@ class SearchHomeModel: ObservableObject { var events: EventHolder @Published var loading: Bool = false - var seen_pubkey: Set = Set() + var seen_pubkey: Set = Set() let damus_state: DamusState let base_subid = UUID().description let profiles_subid = UUID().description @@ -91,7 +91,7 @@ class SearchHomeModel: ObservableObject { } } -func find_profiles_to_fetch(profiles: Profiles, load: PubkeysToLoad, cache: EventCache) -> [String] { +func find_profiles_to_fetch(profiles: Profiles, load: PubkeysToLoad, cache: EventCache) -> [Pubkey] { switch load { case .from_events(let events): return find_profiles_to_fetch_from_events(profiles: profiles, events: events, cache: cache) @@ -100,13 +100,13 @@ func find_profiles_to_fetch(profiles: Profiles, load: PubkeysToLoad, cache: Even } } -func find_profiles_to_fetch_from_keys(profiles: Profiles, pks: [String]) -> [String] { +func find_profiles_to_fetch_from_keys(profiles: Profiles, pks: [Pubkey]) -> [Pubkey] { Array(Set(pks.filter { pk in !profiles.has_fresh_profile(id: pk) })) } -func find_profiles_to_fetch_from_events(profiles: Profiles, events: [NostrEvent], cache: EventCache) -> [String] { - var pubkeys = Set() - +func find_profiles_to_fetch_from_events(profiles: Profiles, events: [NostrEvent], cache: EventCache) -> [Pubkey] { + var pubkeys = Set() + for ev in events { // lookup profiles from boosted events if ev.known_kind == .boost, let bev = ev.get_inner_event(cache: cache), !profiles.has_fresh_profile(id: bev.pubkey) { @@ -123,7 +123,7 @@ func find_profiles_to_fetch_from_events(profiles: Profiles, events: [NostrEvent] enum PubkeysToLoad { case from_events([NostrEvent]) - case from_keys([String]) + case from_keys([Pubkey]) } func load_profiles(profiles_subid: String, relay_id: String, load: PubkeysToLoad, damus_state: DamusState) { diff --git a/damus/Models/ThreadModel.swift b/damus/Models/ThreadModel.swift index d84f549c..18bd7ebb 100644 --- a/damus/Models/ThreadModel.swift +++ b/damus/Models/ThreadModel.swift @@ -128,7 +128,7 @@ class ThreadModel: ObservableObject { } -func get_top_zap(events: EventCache, evid: String) -> Zapping? { +func get_top_zap(events: EventCache, evid: NoteId) -> Zapping? { return events.get_cache_data(evid).zaps_model.zaps.first(where: { zap in !zap.request.marked_hidden }) diff --git a/damus/Models/UserSearchCache.swift b/damus/Models/UserSearchCache.swift index 8e62729c..e83ce7b1 100644 --- a/damus/Models/UserSearchCache.swift +++ b/damus/Models/UserSearchCache.swift @@ -11,15 +11,15 @@ import Foundation /// Optimized for fast searches of substrings by using a Trie. /// Optimal for performing user searches that could be initiated by typing quickly on a keyboard into a text input field. class UserSearchCache { - private let trie = Trie() + private let trie = Trie() - func search(key: String) -> [String] { + func search(key: String) -> [Pubkey] { let results = trie.find(key: key) return results } /// Computes the differences between an old profile, if it exists, and a new profile, and updates the user search cache accordingly. - func updateProfile(id: String, profiles: Profiles, oldProfile: Profile?, newProfile: Profile) { + func updateProfile(id: Pubkey, profiles: Profiles, oldProfile: Profile?, newProfile: Profile) { // Remove searchable keys tied to the old profile if they differ from the new profile // to keep the trie clean without empty nodes while avoiding excessive graph searching. if let oldProfile { @@ -38,7 +38,7 @@ class UserSearchCache { } /// Adds a profile to the user search cache. - private func addProfile(id: String, profiles: Profiles, profile: Profile) { + private func addProfile(id: Pubkey, profiles: Profiles, profile: Profile) { // Searchable by name. if let name = profile.name { trie.insert(key: name.lowercased(), value: id) @@ -56,7 +56,7 @@ class UserSearchCache { } /// Computes the diffences between an old contacts event and a new contacts event for our own user, and updates the search cache accordingly. - func updateOwnContactsPetnames(id: String, oldEvent: NostrEvent?, newEvent: NostrEvent) { + func updateOwnContactsPetnames(id: Pubkey, oldEvent: NostrEvent?, newEvent: NostrEvent) { guard newEvent.known_kind == .contacts && newEvent.pubkey == id else { return } diff --git a/damus/Models/UserSettingsStore.swift b/damus/Models/UserSettingsStore.swift index ac509e96..7f00a2dd 100644 --- a/damus/Models/UserSettingsStore.swift +++ b/damus/Models/UserSettingsStore.swift @@ -11,7 +11,7 @@ import UIKit let fallback_zap_amount = 1000 func setting_property_key(key: String) -> String { - return pk_setting_key(UserSettingsStore.pubkey ?? "", key: key) + return pk_setting_key(UserSettingsStore.pubkey ?? .empty, key: key) } func setting_get_property_value(key: String, scoped_key: String, default_value: T) -> T { @@ -63,7 +63,7 @@ func setting_set_property_value(scoped_key: String, old_value: T, private var value: T init(key: String, default_value: T) { - self.key = pk_setting_key(UserSettingsStore.pubkey ?? "", key: key) + self.key = pk_setting_key(UserSettingsStore.pubkey ?? .empty, key: key) if let loaded = UserDefaults.standard.string(forKey: self.key), let val = T.init(from: loaded) { self.value = val } else if let loaded = UserDefaults.standard.string(forKey: key), let val = T.init(from: loaded) { @@ -91,7 +91,7 @@ func setting_set_property_value(scoped_key: String, old_value: T, } class UserSettingsStore: ObservableObject { - static var pubkey: String? = nil + static var pubkey: Pubkey? = nil static var shared: UserSettingsStore? = nil static var bool_options = Set() @@ -261,6 +261,6 @@ class UserSettingsStore: ObservableObject { } } -func pk_setting_key(_ pubkey: String, key: String) -> String { - return "\(pubkey)_\(key)" +func pk_setting_key(_ pubkey: Pubkey, key: String) -> String { + return "\(pubkey.hex())_\(key)" } diff --git a/damus/Nostr/Nostr.swift b/damus/Nostr/Nostr.swift index 4ff8afb7..1e439f25 100644 --- a/damus/Nostr/Nostr.swift +++ b/damus/Nostr/Nostr.swift @@ -201,7 +201,7 @@ class Profile: Codable { try container.encode(value) } - static func displayName(profile: Profile?, pubkey: String) -> DisplayName { + static func displayName(profile: Profile?, pubkey: Pubkey) -> DisplayName { return parse_display_name(profile: profile, pubkey: pubkey) } } diff --git a/damus/Nostr/NostrEvent.swift b/damus/Nostr/NostrEvent.swift index f1c0d231..d4fa988a 100644 --- a/damus/Nostr/NostrEvent.swift +++ b/damus/Nostr/NostrEvent.swift @@ -379,7 +379,7 @@ func decode_data(_ data: Data) -> T? { return nil } -func event_commitment(pubkey: String, created_at: UInt32, kind: UInt32, tags: [[String]], content: String) -> String { +func event_commitment(pubkey: Pubkey, created_at: UInt32, kind: UInt32, tags: [[String]], content: String) -> String { let encoder = JSONEncoder() encoder.outputFormatting = .withoutEscapingSlashes let str_data = try! encoder.encode(content) @@ -393,12 +393,12 @@ func event_commitment(pubkey: String, created_at: UInt32, kind: UInt32, tags: [[ return "[0,\"\(pubkey)\",\(created_at),\(kind),\(tags),\(content)]" } -func calculate_event_commitment(pubkey: String, created_at: UInt32, kind: UInt32, tags: [[String]], content: String) -> Data { +func calculate_event_commitment(pubkey: Pubkey, created_at: UInt32, kind: UInt32, tags: [[String]], content: String) -> Data { let target = event_commitment(pubkey: pubkey, created_at: created_at, kind: kind, tags: tags, content: content) return target.data(using: .utf8)! } -func calculate_event_id(pubkey: String, created_at: UInt32, kind: UInt32, tags: [[String]], content: String) -> Data { +func calculate_event_id(pubkey: Pubkey, created_at: UInt32, kind: UInt32, tags: [[String]], content: String) -> Data { let commitment = calculate_event_commitment(pubkey: pubkey, created_at: created_at, kind: kind, tags: tags, content: content) return sha256(commitment) } @@ -497,7 +497,7 @@ func make_first_contact_event(keypair: Keypair) -> NostrEvent? { let damus_pubkey = "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681" let tags = [ ["p", damus_pubkey], - ["p", keypair.pubkey] // you're a friend of yourself! + ["p", keypair.pubkey.hex()] // you're a friend of yourself! ] return NostrEvent(content: relay_json, keypair: keypair, kind: NostrKind.contacts.rawValue, tags: tags) } @@ -514,24 +514,25 @@ func make_boost_event(keypair: FullKeypair, boosted: NostrEvent) -> NostrEvent? var tags: [[String]] = boosted.tags.filter { tag in tag.count >= 2 && (tag[0] == "e" || tag[0] == "p") } tags.append(["e", boosted.id, "", "root"]) - tags.append(["p", boosted.pubkey]) + tags.append(["p", boosted.pubkey.hex()]) return NostrEvent(content: event_to_json(ev: boosted), keypair: keypair.to_keypair(), kind: 6, tags: tags) } func make_like_event(keypair: FullKeypair, liked: NostrEvent, content: String = "🤙") -> NostrEvent? { var tags: [[String]] = liked.tags.filter { tag in tag.count >= 2 && (tag[0] == "e" || tag[0] == "p") } - tags.append(["e", liked.id]) - tags.append(["p", liked.pubkey]) + tags.append(["e", liked.id.hex()]) + tags.append(["p", liked.pubkey.hex()]) return NostrEvent(content: content, keypair: keypair.to_keypair(), kind: 7, tags: tags) } func zap_target_to_tags(_ target: ZapTarget) -> [[String]] { switch target { case .profile(let pk): - return [["p", pk]] + return [["p", pk.hex()]] case .note(let note_target): - return [["e", note_target.note_id], ["p", note_target.author]] + return [["e", note_target.note_id.hex()], + ["p", note_target.author.hex()]] } } @@ -554,7 +555,7 @@ func make_private_zap_request_event(identity: FullKeypair, enc_key: FullKeypair, return PrivateZapRequest(req: ZapRequest(ev: note), enc: enc) } -func decrypt_private_zap(our_privkey: String, zapreq: NostrEvent, target: ZapTarget) -> NostrEvent? { +func decrypt_private_zap(our_privkey: Privkey, zapreq: NostrEvent, target: ZapTarget) -> NostrEvent? { guard let anon_tag = zapreq.tags.first(where: { t in t.count >= 2 && t[0] == "anon" }) else { return nil } @@ -732,7 +733,7 @@ func event_to_json(ev: NostrEvent) -> String { return str } -func decrypt_dm(_ privkey: String?, pubkey: String, content: String, encoding: EncEncoding) -> String? { +func decrypt_dm(_ privkey: Privkey?, pubkey: Pubkey, content: String, encoding: EncEncoding) -> String? { guard let privkey = privkey else { return nil } @@ -748,7 +749,7 @@ func decrypt_dm(_ privkey: String?, pubkey: String, content: String, encoding: E return String(data: dat, encoding: .utf8) } -func decrypt_note(our_privkey: String, their_pubkey: String, enc_note: String, encoding: EncEncoding) -> NostrEvent? { +func decrypt_note(our_privkey: Privkey, their_pubkey: Pubkey, enc_note: String, encoding: EncEncoding) -> NostrEvent? { guard let dec = decrypt_dm(our_privkey, pubkey: their_pubkey, content: enc_note, encoding: encoding) else { return nil } diff --git a/damus/Nostr/NostrFilter.swift b/damus/Nostr/NostrFilter.swift index 70013c2c..cd6472bf 100644 --- a/damus/Nostr/NostrFilter.swift +++ b/damus/Nostr/NostrFilter.swift @@ -8,14 +8,14 @@ import Foundation struct NostrFilter: Codable, Equatable { - var ids: [String]? + var ids: [NoteId]? var kinds: [NostrKind]? - var referenced_ids: [String]? - var pubkeys: [String]? + var referenced_ids: [NoteId]? + var pubkeys: [Pubkey]? var since: UInt32? var until: UInt32? var limit: UInt32? - var authors: [String]? + var authors: [Pubkey]? var hashtag: [String]? var parameter: [String]? @@ -32,7 +32,7 @@ struct NostrFilter: Codable, Equatable { case limit } - init(ids: [String]? = nil, kinds: [NostrKind]? = nil, referenced_ids: [String]? = nil, pubkeys: [String]? = nil, since: UInt32? = nil, until: UInt32? = nil, limit: UInt32? = nil, authors: [String]? = nil, hashtag: [String]? = nil) { + init(ids: [NoteId]? = nil, kinds: [NostrKind]? = nil, referenced_ids: [NoteId]? = nil, pubkeys: [Pubkey]? = nil, since: UInt32? = nil, until: UInt32? = nil, limit: UInt32? = nil, authors: [Pubkey]? = nil, hashtag: [String]? = nil) { self.ids = ids self.kinds = kinds self.referenced_ids = referenced_ids diff --git a/damus/Nostr/NostrResponse.swift b/damus/Nostr/NostrResponse.swift index 3e7c1c59..8393ec0d 100644 --- a/damus/Nostr/NostrResponse.swift +++ b/damus/Nostr/NostrResponse.swift @@ -8,7 +8,7 @@ import Foundation struct CommandResult { - let event_id: String + let event_id: NoteId let ok: Bool let msg: String } diff --git a/damus/Nostr/ProfileDatabase.swift b/damus/Nostr/ProfileDatabase.swift index 0e5ec17d..6d4385f0 100644 --- a/damus/Nostr/ProfileDatabase.swift +++ b/damus/Nostr/ProfileDatabase.swift @@ -25,8 +25,8 @@ final class ProfileDatabase { private var queue = DispatchQueue(label: "io.damus.profile_db", qos: .userInteractive, attributes: .concurrent) - private var network_pull_date_cache = [String: Date]() - + private var network_pull_date_cache = [Pubkey: Date]() + init(cache_url: URL = ProfileDatabase.profile_cache_url) { self.cache_url = cache_url set_up() @@ -73,14 +73,14 @@ final class ProfileDatabase { background_context?.mergePolicy = NSMergePolicy(merge: .mergeByPropertyObjectTrumpMergePolicyType) } - private func get_persisted(id: String, context: NSManagedObjectContext) -> PersistedProfile? { + private func get_persisted(id: Pubkey, context: NSManagedObjectContext) -> PersistedProfile? { let request = NSFetchRequest(entityName: entity_name) - request.predicate = NSPredicate(format: "id == %@", id) + request.predicate = NSPredicate(format: "id == %@", id.hex()) request.fetchLimit = 1 return try? context.fetch(request).first } - func get_network_pull_date(id: String) -> Date? { + func get_network_pull_date(id: Pubkey) -> Date? { var pull_date: Date? queue.sync { pull_date = network_pull_date_cache[id] @@ -90,7 +90,7 @@ final class ProfileDatabase { } let request = NSFetchRequest(entityName: entity_name) - request.predicate = NSPredicate(format: "id == %@", id) + request.predicate = NSPredicate(format: "id == %@", id.hex()) request.fetchLimit = 1 request.propertiesToFetch = ["network_pull_date"] guard let profile = try? persistent_container?.viewContext.fetch(request).first else { @@ -111,7 +111,7 @@ final class ProfileDatabase { /// - id: Profile id (pubkey) /// - profile: Profile object to be stored /// - last_update: Date that the Profile was updated - func upsert(id: String, profile: Profile, last_update: Date) async throws { + func upsert(id: Pubkey, profile: Profile, last_update: Date) async throws { guard let context = background_context else { throw ProfileDatabaseError.missing_context } @@ -126,7 +126,7 @@ final class ProfileDatabase { } } else { persisted_profile = NSEntityDescription.insertNewObject(forEntityName: self.entity_name, into: context) as? PersistedProfile - persisted_profile?.id = id + persisted_profile?.id = id.hex() } persisted_profile?.copyValues(from: profile) persisted_profile?.last_update = last_update @@ -141,7 +141,7 @@ final class ProfileDatabase { } } - func get(id: String) -> Profile? { + func get(id: Pubkey) -> Profile? { guard let container = persistent_container, let profile = get_persisted(id: id, context: container.viewContext) else { return nil diff --git a/damus/Nostr/Profiles.swift b/damus/Nostr/Profiles.swift index a75d1a5e..cbce11d5 100644 --- a/damus/Nostr/Profiles.swift +++ b/damus/Nostr/Profiles.swift @@ -21,11 +21,11 @@ class Profiles { qos: .userInteractive, attributes: .concurrent) - private var profiles: [String: TimestampedProfile] = [:] - private var validated: [String: NIP05] = [:] - var nip05_pubkey: [String: String] = [:] - var zappers: [String: String] = [:] - + private var profiles: [Pubkey: TimestampedProfile] = [:] + private var validated: [Pubkey: NIP05] = [:] + var nip05_pubkey: [String: Pubkey] = [:] + var zappers: [Pubkey: Pubkey] = [:] + private let database = ProfileDatabase() let user_search_cache: UserSearchCache @@ -34,35 +34,35 @@ class Profiles { self.user_search_cache = user_search_cache } - func is_validated(_ pk: String) -> NIP05? { + func is_validated(_ pk: Pubkey) -> NIP05? { validated_queue.sync { validated[pk] } } - func invalidate_nip05(_ pk: String) { + func invalidate_nip05(_ pk: Pubkey) { validated_queue.async(flags: .barrier) { self.validated.removeValue(forKey: pk) } } - func set_validated(_ pk: String, nip05: NIP05?) { + func set_validated(_ pk: Pubkey, nip05: NIP05?) { validated_queue.async(flags: .barrier) { self.validated[pk] = nip05 } } - func enumerated() -> EnumeratedSequence<[String: TimestampedProfile]> { + func enumerated() -> EnumeratedSequence<[Pubkey: TimestampedProfile]> { return profiles_queue.sync { return profiles.enumerated() } } - func lookup_zapper(pubkey: String) -> String? { + func lookup_zapper(pubkey: Pubkey) -> Pubkey? { zappers[pubkey] } - func add(id: String, profile: TimestampedProfile) { + func add(id: Pubkey, profile: TimestampedProfile) { profiles_queue.async(flags: .barrier) { let old_timestamped_profile = self.profiles[id] self.profiles[id] = profile @@ -78,7 +78,7 @@ class Profiles { } } - func lookup(id: String) -> Profile? { + func lookup(id: Pubkey) -> Profile? { var profile: Profile? profiles_queue.sync { profile = profiles[id]?.profile @@ -86,14 +86,13 @@ class Profiles { return profile ?? database.get(id: id) } - func lookup_with_timestamp(id: String) -> TimestampedProfile? { + func lookup_with_timestamp(id: Pubkey) -> TimestampedProfile? { profiles_queue.sync { return profiles[id] } } - func has_fresh_profile(id: String) -> Bool { - // check memory first + func has_fresh_profile(id: Pubkey) -> Bool { var profile: Profile? profiles_queue.sync { profile = profiles[id]?.profile @@ -111,7 +110,7 @@ class Profiles { } -func invalidate_zapper_cache(pubkey: String, profiles: Profiles, lnurl: LNUrls) { +func invalidate_zapper_cache(pubkey: Pubkey, profiles: Profiles, lnurl: LNUrls) { profiles.zappers.removeValue(forKey: pubkey) lnurl.endpoints.removeValue(forKey: pubkey) } diff --git a/damus/Nostr/Relay.swift b/damus/Nostr/Relay.swift index 110922bf..92bfb588 100644 --- a/damus/Nostr/Relay.swift +++ b/damus/Nostr/Relay.swift @@ -68,7 +68,7 @@ struct Limitations: Codable { struct RelayMetadata: Codable { let name: String? let description: String? - let pubkey: String? + let pubkey: Pubkey? let contact: String? let supported_nips: [Int]? let software: String? diff --git a/damus/Nostr/RelayPool.swift b/damus/Nostr/RelayPool.swift index 59d98439..293e016c 100644 --- a/damus/Nostr/RelayPool.swift +++ b/damus/Nostr/RelayPool.swift @@ -21,7 +21,7 @@ struct QueuedRequest { struct SeenEvent: Hashable { let relay_id: String - let evid: String + let evid: NoteId } class RelayPool { diff --git a/damus/Util/Bech32Object.swift b/damus/Util/Bech32Object.swift index c9ce1f0c..beb1e328 100644 --- a/damus/Util/Bech32Object.swift +++ b/damus/Util/Bech32Object.swift @@ -9,9 +9,9 @@ import Foundation enum Bech32Object { - case nsec(String) - case npub(String) - case note(String) + case nsec(Privkey) + case npub(Pubkey) + case note(NoteId) case nscript([UInt8]) static func parse(_ str: String) -> Bech32Object? { diff --git a/damus/Util/DisplayName.swift b/damus/Util/DisplayName.swift index 1671e816..52468065 100644 --- a/damus/Util/DisplayName.swift +++ b/damus/Util/DisplayName.swift @@ -37,7 +37,7 @@ enum DisplayName { } -func parse_display_name(profile: Profile?, pubkey: String) -> DisplayName { +func parse_display_name(profile: Profile?, pubkey: Pubkey) -> DisplayName { if pubkey == ANON_PUBKEY { return .one(NSLocalizedString("Anonymous", comment: "Placeholder display name of anonymous user.")) } diff --git a/damus/Util/EventCache.swift b/damus/Util/EventCache.swift index f97d8a92..ff063e6d 100644 --- a/damus/Util/EventCache.swift +++ b/damus/Util/EventCache.swift @@ -61,7 +61,7 @@ class ZapsDataModel: ObservableObject { self.zaps = zaps } - func confirm_nwc(reqid: String) { + func confirm_nwc(reqid: NoteId) { guard let zap = zaps.first(where: { z in z.request.ev.id == reqid }), case .pending(let pzap) = zap else { @@ -82,7 +82,7 @@ class ZapsDataModel: ObservableObject { zaps.reduce(0) { total, zap in total + zap.amount } } - func from(_ pubkey: String) -> [Zapping] { + func from(_ pubkey: Pubkey) -> [Zapping] { return self.zaps.filter { z in z.request.ev.pubkey == pubkey } } @@ -137,7 +137,7 @@ class EventData { } class EventCache { - private var events: [String: NostrEvent] = [:] + private var events: [NoteId: NostrEvent] = [:] private var replies = ReplyMap() private var cancellable: AnyCancellable? private var image_metadata: [String: ImageMetadataState] = [:] @@ -154,7 +154,7 @@ class EventCache { } } - func get_cache_data(_ evid: String) -> EventData { + func get_cache_data(_ evid: NoteId) -> EventData { guard let data = event_data[evid] else { let data = EventData() event_data[evid] = data @@ -164,11 +164,11 @@ class EventCache { return data } - func is_event_valid(_ evid: String) -> ValidationResult { + func is_event_valid(_ evid: NoteId) -> ValidationResult { return get_cache_data(evid).validated } - func store_event_validation(evid: String, validated: ValidationResult) { + func store_event_validation(evid: NoteId, validated: ValidationResult) { get_cache_data(evid).validated = validated } @@ -278,7 +278,7 @@ class EventCache { return ev } - func lookup(_ evid: String) -> NostrEvent? { + func lookup(_ evid: NoteId) -> NostrEvent? { return events[evid] } diff --git a/damus/Util/Keys.swift b/damus/Util/Keys.swift index 704c2168..55606fd2 100644 --- a/damus/Util/Keys.swift +++ b/damus/Util/Keys.swift @@ -12,8 +12,8 @@ let PUBKEY_HRP = "npub" let ANON_PUBKEY = "anon" struct FullKeypair: Equatable { - let pubkey: String - let privkey: String + let pubkey: Pubkey + let privkey: Privkey func to_keypair() -> Keypair { return Keypair(pubkey: pubkey, privkey: privkey) @@ -21,11 +21,11 @@ struct FullKeypair: Equatable { } struct Keypair { - let pubkey: String - let privkey: String? + let pubkey: Pubkey + let privkey: Privkey? let pubkey_bech32: String let privkey_bech32: String? - + func to_full() -> FullKeypair? { guard let privkey = self.privkey else { return nil @@ -33,8 +33,12 @@ struct Keypair { return FullKeypair(pubkey: pubkey, privkey: privkey) } - - init(pubkey: String, privkey: String?) { + + static func just_pubkey(_ pk: Pubkey) -> Keypair { + return .init(pubkey: pk, privkey: nil) + } + + init(pubkey: Pubkey, privkey: Privkey?) { self.pubkey = pubkey self.privkey = privkey self.pubkey_bech32 = bech32_pubkey(pubkey) ?? pubkey @@ -43,8 +47,8 @@ struct Keypair { } enum Bech32Key { - case pub(String) - case sec(String) + case pub(Pubkey) + case sec(Privkey) } func decode_bech32_key(_ key: String) -> Bech32Key? { @@ -105,7 +109,7 @@ func generate_new_keypair() -> Keypair { return Keypair(pubkey: pubkey, privkey: privkey) } -func privkey_to_pubkey_raw(sec: [UInt8]) -> String? { +func privkey_to_pubkey_raw(sec: [UInt8]) -> Pubkey? { guard let key = try? secp256k1.Signing.PrivateKey(rawRepresentation: sec) else { return nil } @@ -117,8 +121,8 @@ func privkey_to_pubkey(privkey: String) -> String? { return privkey_to_pubkey_raw(sec: sec) } -func save_pubkey(pubkey: String) { - UserDefaults.standard.set(pubkey, forKey: "pubkey") +func save_pubkey(pubkey: Pubkey) { + UserDefaults.standard.set(pubkey.hex(), forKey: "pubkey") } enum Keys { @@ -126,8 +130,8 @@ enum Keys { static var privkey: String? } -func save_privkey(privkey: String) throws { - Keys.privkey = privkey +func save_privkey(privkey: Privkey) throws { + Keys.privkey = privkey.hex() } func clear_saved_privkey() throws { @@ -138,7 +142,7 @@ func clear_saved_pubkey() { UserDefaults.standard.removeObject(forKey: "pubkey") } -func save_keypair(pubkey: String, privkey: String) throws { +func save_keypair(pubkey: Pubkey, privkey: Privkey) throws { save_pubkey(pubkey: pubkey) try save_privkey(privkey: privkey) } diff --git a/damus/Util/LNUrls.swift b/damus/Util/LNUrls.swift index a5c45c6a..c4614c33 100644 --- a/damus/Util/LNUrls.swift +++ b/damus/Util/LNUrls.swift @@ -15,14 +15,14 @@ enum LNUrlState { } class LNUrls { - var endpoints: [String: LNUrlState] + var endpoints: [Pubkey: LNUrlState] init() { self.endpoints = [:] } @MainActor - func lookup_or_fetch(pubkey: String, lnurl: String) async -> LNUrlPayRequest? { + func lookup_or_fetch(pubkey: Pubkey, lnurl: String) async -> LNUrlPayRequest? { switch lookup(pubkey: pubkey) { case .failed(let tries): print("lnurls.lookup_or_fetch failed \(tries) \(lnurl)") @@ -57,7 +57,7 @@ class LNUrls { return v } - func lookup(pubkey: String) -> LNUrlState { + func lookup(pubkey: Pubkey) -> LNUrlState { return self.endpoints[pubkey] ?? .not_fetched } } diff --git a/damus/Util/NIP05.swift b/damus/Util/NIP05.swift index 455732c8..9432a2bb 100644 --- a/damus/Util/NIP05.swift +++ b/damus/Util/NIP05.swift @@ -30,7 +30,7 @@ struct NIP05 { struct NIP05Response: Decodable { - let names: [String: String] + let names: [String: Pubkey] } func fetch_nip05(nip05: NIP05) async -> NIP05Response? { @@ -51,7 +51,7 @@ func fetch_nip05(nip05: NIP05) async -> NIP05Response? { return decoded } -func validate_nip05(pubkey: String, nip05_str: String) async -> NIP05? { +func validate_nip05(pubkey: Pubkey, nip05_str: String) async -> NIP05? { guard let nip05 = NIP05.parse(nip05_str) else { return nil } diff --git a/damus/Util/PostBox.swift b/damus/Util/PostBox.swift index 3616d88d..e45a05af 100644 --- a/damus/Util/PostBox.swift +++ b/damus/Util/PostBox.swift @@ -55,8 +55,8 @@ enum CancelSendErr { class PostBox { let pool: RelayPool - var events: [String: PostedEvent] - + var events: [NoteId: PostedEvent] + init(pool: RelayPool) { self.pool = pool self.events = [:] @@ -64,7 +64,7 @@ class PostBox { } // only works reliably on delay-sent events - func cancel_send(evid: String) -> CancelSendErr? { + func cancel_send(evid: NoteId) -> CancelSendErr? { guard let ev = events[evid] else { return .nothing_to_cancel } @@ -114,7 +114,7 @@ class PostBox { } @discardableResult - func remove_relayer(relay_id: String, event_id: String) -> Bool { + func remove_relayer(relay_id: String, event_id: NoteId) -> Bool { guard let ev = self.events[event_id] else { return false } diff --git a/damus/Util/PreviewCache.swift b/damus/Util/PreviewCache.swift index 33b51c87..e48061b5 100644 --- a/damus/Util/PreviewCache.swift +++ b/damus/Util/PreviewCache.swift @@ -65,9 +65,9 @@ enum PreviewState { } class PreviewCache { - private var previews: [String: Preview] = [:] + private var previews: [NoteId: Preview] = [:] - func lookup(_ evid: String) -> Preview? { + func lookup(_ evid: NoteId) -> Preview? { return previews[evid] } } diff --git a/damus/Util/Relays/RelayBootstrap.swift b/damus/Util/Relays/RelayBootstrap.swift index d2792859..344f3679 100644 --- a/damus/Util/Relays/RelayBootstrap.swift +++ b/damus/Util/Relays/RelayBootstrap.swift @@ -14,17 +14,17 @@ let BOOTSTRAP_RELAYS = [ "wss://nos.lol", ] -func bootstrap_relays_setting_key(pubkey: String) -> String { +func bootstrap_relays_setting_key(pubkey: Pubkey) -> String { return pk_setting_key(pubkey, key: "bootstrap_relays") } -func save_bootstrap_relays(pubkey: String, relays: [String]) { +func save_bootstrap_relays(pubkey: Pubkey, relays: [String]) { let key = bootstrap_relays_setting_key(pubkey: pubkey) UserDefaults.standard.set(relays, forKey: key) } -func load_bootstrap_relays(pubkey: String) -> [String] { +func load_bootstrap_relays(pubkey: Pubkey) -> [String] { let key = bootstrap_relays_setting_key(pubkey: pubkey) guard let relays = UserDefaults.standard.stringArray(forKey: key) else { diff --git a/damus/Util/Relays/RelayFilters.swift b/damus/Util/Relays/RelayFilters.swift index 08ff8528..dabd4f94 100644 --- a/damus/Util/Relays/RelayFilters.swift +++ b/damus/Util/Relays/RelayFilters.swift @@ -18,7 +18,7 @@ struct RelayFilter: Hashable { } class RelayFilters { - private let our_pubkey: String + private let our_pubkey: Pubkey private var disabled: Set func is_filtered(timeline: Timeline, relay_id: String) -> Bool { @@ -47,23 +47,23 @@ class RelayFilters { save_relay_filters(our_pubkey, filters: disabled) } - init(our_pubkey: String) { + init(our_pubkey: Pubkey) { self.our_pubkey = our_pubkey disabled = load_relay_filters(our_pubkey) ?? Set() } } -func save_relay_filters(_ pubkey: String, filters: Set) { +func save_relay_filters(_ pubkey: Pubkey, filters: Set) { let key = pk_setting_key(pubkey, key: "relay_filters") let arr = Array(filters.map { filter in "\(filter.timeline)\t\(filter.relay_id)" }) UserDefaults.standard.set(arr, forKey: key) } -func relay_filter_setting_key(_ pubkey: String) -> String { +func relay_filter_setting_key(_ pubkey: Pubkey) -> String { return pk_setting_key(pubkey, key: "relay_filters") } -func load_relay_filters(_ pubkey: String) -> Set? { +func load_relay_filters(_ pubkey: Pubkey) -> Set? { let key = relay_filter_setting_key(pubkey) guard let filters = UserDefaults.standard.stringArray(forKey: key) else { return nil diff --git a/damus/Util/ReplyCounter.swift b/damus/Util/ReplyCounter.swift index 89b56765..39cf8c83 100644 --- a/damus/Util/ReplyCounter.swift +++ b/damus/Util/ReplyCounter.swift @@ -8,23 +8,23 @@ import Foundation class ReplyCounter { - private var replies: [String: Int] - private var counted: Set - private var our_replies: [String: NostrEvent] - private let our_pubkey: String - - init(our_pubkey: String) { + private var replies: [NoteId: Int] + private var counted: Set + private var our_replies: [NoteId: NostrEvent] + private let our_pubkey: Pubkey + + init(our_pubkey: Pubkey) { self.our_pubkey = our_pubkey replies = [:] counted = Set() our_replies = [:] } - func our_reply(_ evid: String) -> NostrEvent? { + func our_reply(_ evid: NoteId) -> NostrEvent? { return our_replies[evid] } - func get_replies(_ evid: String) -> Int { + func get_replies(_ evid: NoteId) -> Int { return replies[evid] ?? 0 } diff --git a/damus/Util/Router.swift b/damus/Util/Router.swift index 4ad66ada..1ea0b21f 100644 --- a/damus/Util/Router.swift +++ b/damus/Util/Router.swift @@ -8,13 +8,13 @@ import SwiftUI enum Route: Hashable { - case ProfileByKey(pubkey: String) + case ProfileByKey(pubkey: Pubkey) case Profile(profile: ProfileModel, followers: FollowersModel) case Followers(followers: FollowersModel) case Relay(relay: String, showActionButtons: Binding) case RelayDetail(relay: String, metadata: RelayMetadata?) case Following(following: FollowingModel) - case MuteList(users: [String]) + case MuteList(users: [Pubkey]) case RelayConfig case Script(script: ScriptModel) case Bookmarks @@ -41,7 +41,7 @@ enum Route: Hashable { case SaveKeys(account: CreateAccountModel) case Wallet(wallet: WalletModel) case WalletScanner(result: Binding) - case FollowersYouKnow(friendedFollowers: [String], followers: FollowersModel) + case FollowersYouKnow(friendedFollowers: [Pubkey], followers: FollowersModel) @ViewBuilder func view(navigationCoordinator: NavigationCoordinator, damusState: DamusState) -> some View { diff --git a/damus/Util/WalletConnect.swift b/damus/Util/WalletConnect.swift index 2faa3a39..c122a240 100644 --- a/damus/Util/WalletConnect.swift +++ b/damus/Util/WalletConnect.swift @@ -16,16 +16,16 @@ struct WalletConnectURL: Equatable { let relay: RelayURL let keypair: FullKeypair - let pubkey: String + let pubkey: Pubkey let lud16: String? func to_url() -> URL { var urlComponents = URLComponents() urlComponents.scheme = "nostrwalletconnect" - urlComponents.host = pubkey + urlComponents.host = pubkey.hex() urlComponents.queryItems = [ URLQueryItem(name: "relay", value: relay.id), - URLQueryItem(name: "secret", value: keypair.privkey) + URLQueryItem(name: "secret", value: keypair.privkey.hex()) ] if let lud16 { @@ -55,7 +55,7 @@ struct WalletConnectURL: Equatable { self = WalletConnectURL(pubkey: pk, relay: relay_url, keypair: keypair, lud16: lud16) } - init(pubkey: String, relay: RelayURL, keypair: FullKeypair, lud16: String?) { + init(pubkey: Pubkey, relay: RelayURL, keypair: FullKeypair, lud16: String?) { self.pubkey = pubkey self.relay = relay self.keypair = keypair @@ -86,7 +86,7 @@ enum WalletResponseResult { } struct FullWalletResponse { - let req_id: String + let req_id: NoteId let response: WalletResponse init?(from: NostrEvent, nwc: WalletConnectURL) async { @@ -165,7 +165,7 @@ struct PayInvoiceRequest: Codable { let invoice: String } -func make_wallet_connect_request(req: WalletRequest, to_pk: String, keypair: FullKeypair) -> NostrEvent? { +func make_wallet_connect_request(req: WalletRequest, to_pk: Pubkey, keypair: FullKeypair) -> NostrEvent? { let tags = [["p", to_pk]] let created_at = UInt32(Date().timeIntervalSince1970) guard let content = encode_json(req) else { diff --git a/damus/Util/Zap.swift b/damus/Util/Zap.swift index 53e0ec74..fa21ee92 100644 --- a/damus/Util/Zap.swift +++ b/damus/Util/Zap.swift @@ -7,20 +7,20 @@ import Foundation -public struct NoteZapTarget: Equatable, Hashable { - public let note_id: String - public let author: String +struct NoteZapTarget: Equatable, Hashable { + public let note_id: NoteId + public let author: Pubkey } -public enum ZapTarget: Equatable { - case profile(String) +enum ZapTarget: Equatable, Hashable { + case profile(Pubkey) case note(NoteZapTarget) - public static func note(id: String, author: String) -> ZapTarget { + static func note(id: NoteId, author: Pubkey) -> ZapTarget { return .note(NoteZapTarget(note_id: id, author: author)) } - - var pubkey: String { + + var pubkey: Pubkey { switch self { case .profile(let pk): return pk @@ -258,7 +258,7 @@ enum Zapping { struct Zap { public let event: NostrEvent public let invoice: ZapInvoice - public let zapper: String /// zap authorizer + public let zapper: Pubkey /// zap authorizer public let target: ZapTarget public let raw_request: ZapRequest public let is_anon: Bool @@ -268,7 +268,7 @@ struct Zap { return private_request ?? self.raw_request } - public static func from_zap_event(zap_ev: NostrEvent, zapper: String, our_privkey: String?) -> Zap? { + public static func from_zap_event(zap_ev: NostrEvent, zapper: Pubkey, our_privkey: Privkey?) -> Zap? { /// Make sure that we only create a zap event if it is authorized by the profile or event guard zapper == zap_ev.pubkey else { return nil diff --git a/damus/Util/Zaps.swift b/damus/Util/Zaps.swift index 81366182..747c39e7 100644 --- a/damus/Util/Zaps.swift +++ b/damus/Util/Zaps.swift @@ -8,14 +8,14 @@ import Foundation class Zaps { - private(set) var zaps: [String: Zapping] - let our_pubkey: String - var our_zaps: [String: [Zapping]] + private(set) var zaps: [NoteId: Zapping] + let our_pubkey: Pubkey + var our_zaps: [NoteId: [Zapping]] - private(set) var event_counts: [String: Int] - private(set) var event_totals: [String: Int64] - - init(our_pubkey: String) { + private(set) var event_counts: [NoteId: Int] + private(set) var event_totals: [NoteId: Int64] + + init(our_pubkey: Pubkey) { self.zaps = [:] self.our_pubkey = our_pubkey self.our_zaps = [:] @@ -23,7 +23,7 @@ class Zaps { self.event_totals = [:] } - func remove_zap(reqid: String) -> Zapping? { + func remove_zap(reqid: NoteId) -> Zapping? { var res: Zapping? = nil for kv in our_zaps { let ours = kv.value diff --git a/damus/Views/ActionBar/EventDetailBar.swift b/damus/Views/ActionBar/EventDetailBar.swift index 3b4e7af4..ef22210a 100644 --- a/damus/Views/ActionBar/EventDetailBar.swift +++ b/damus/Views/ActionBar/EventDetailBar.swift @@ -9,12 +9,12 @@ import SwiftUI struct EventDetailBar: View { let state: DamusState - let target: String - let target_pk: String - + let target: NoteId + let target_pk: Pubkey + @ObservedObject var bar: ActionBarModel - init(state: DamusState, target: String, target_pk: String) { + init(state: DamusState, target: NoteId, target_pk: Pubkey) { self.state = state self.target = target self.target_pk = target_pk @@ -56,6 +56,6 @@ struct EventDetailBar: View { struct EventDetailBar_Previews: PreviewProvider { static var previews: some View { - EventDetailBar(state: test_damus_state(), target: "", target_pk: "") + EventDetailBar(state: test_damus_state(), target: .empty, target_pk: .empty) } } diff --git a/damus/Views/BannerImageView.swift b/damus/Views/BannerImageView.swift index c6c6904e..5c1d2e8e 100644 --- a/damus/Views/BannerImageView.swift +++ b/damus/Views/BannerImageView.swift @@ -63,12 +63,12 @@ struct InnerBannerImageView: View { struct BannerImageView: View { let disable_animation: Bool - let pubkey: String + let pubkey: Pubkey let profiles: Profiles @State var banner: String? - init(pubkey: String, profiles: Profiles, disable_animation: Bool, banner: String? = nil) { + init(pubkey: Pubkey, profiles: Profiles, disable_animation: Bool, banner: String? = nil) { self.pubkey = pubkey self.profiles = profiles self._banner = State(initialValue: banner) @@ -89,7 +89,7 @@ struct BannerImageView: View { } } -func get_banner_url(banner: String?, pubkey: String, profiles: Profiles) -> URL? { +func get_banner_url(banner: String?, pubkey: Pubkey, profiles: Profiles) -> URL? { let bannerUrlString = banner ?? profiles.lookup(id: pubkey)?.banner ?? "" if let url = URL(string: bannerUrlString) { return url @@ -98,12 +98,10 @@ func get_banner_url(banner: String?, pubkey: String, profiles: Profiles) -> URL? } struct BannerImageView_Previews: PreviewProvider { - static let pubkey = "ca48854ac6555fed8e439ebb4fa2d928410e0eef13fa41164ec45aaaa132d846" - static var previews: some View { BannerImageView( - pubkey: pubkey, - profiles: make_preview_profiles(pubkey), + pubkey: test_pubkey, + profiles: make_preview_profiles(test_pubkey), disable_animation: false ) } diff --git a/damus/Views/CreateAccountView.swift b/damus/Views/CreateAccountView.swift index b8371bad..cf0b79d6 100644 --- a/damus/Views/CreateAccountView.swift +++ b/damus/Views/CreateAccountView.swift @@ -134,8 +134,8 @@ struct CreateAccountView_Previews: PreviewProvider { } } -func KeyText(_ text: Binding) -> some View { - let decoded = hex_decode(text.wrappedValue)! +func KeyText(_ pubkey: Binding) -> some View { + let decoded = hex_decode(pubkey.wrappedValue)! let bechkey = bech32_encode(hrp: PUBKEY_HRP, decoded) return Text(bechkey) .textSelection(.enabled) diff --git a/damus/Views/DMChatView.swift b/damus/Views/DMChatView.swift index 02354686..a905c68a 100644 --- a/damus/Views/DMChatView.swift +++ b/damus/Views/DMChatView.swift @@ -13,7 +13,7 @@ struct DMChatView: View, KeyboardReadable { @ObservedObject var dms: DirectMessageModel @State var showPrivateKeyWarning: Bool = false - var pubkey: String { + var pubkey: Pubkey { dms.pubkey } @@ -128,7 +128,7 @@ struct DMChatView: View, KeyboardReadable { } func send_message() { - let tags = [["p", pubkey]] + let tags = [["p", pubkey.hex()]] let post_blocks = parse_post_blocks(content: dms.draft) let content = render_blocks(blocks: post_blocks) @@ -190,7 +190,7 @@ enum EncEncoding { case bech32 } -func encrypt_message(message: String, privkey: String, to_pk: String, encoding: EncEncoding = .base64) -> String? { +func encrypt_message(message: String, privkey: Privkey, to_pk: Pubkey, encoding: EncEncoding = .base64) -> String? { let iv = random_bytes(count: 16).bytes guard let shared_sec = get_shared_secret(privkey: privkey, pubkey: to_pk) else { return nil @@ -209,7 +209,7 @@ func encrypt_message(message: String, privkey: String, to_pk: String, encoding: } -func create_encrypted_event(_ message: String, to_pk: String, tags: [[String]], keypair: FullKeypair, created_at: UInt32, kind: UInt32) -> NostrEvent? { +func create_encrypted_event(_ message: String, to_pk: Pubkey, tags: [[String]], keypair: FullKeypair, created_at: UInt32, kind: UInt32) -> NostrEvent? { let privkey = keypair.privkey guard let enc_content = encrypt_message(message: message, privkey: privkey, to_pk: to_pk) else { @@ -219,7 +219,7 @@ func create_encrypted_event(_ message: String, to_pk: String, tags: [[String]], return NostrEvent(content: enc_content, keypair: keypair.to_keypair(), kind: kind, tags: tags, createdAt: created_at) } -func create_dm(_ message: String, to_pk: String, tags: [[String]], keypair: Keypair, created_at: UInt32? = nil) -> NostrEvent? +func create_dm(_ message: String, to_pk: Pubkey, tags: [[String]], keypair: Keypair, created_at: UInt32? = nil) -> NostrEvent? { let created = created_at ?? UInt32(Date().timeIntervalSince1970) diff --git a/damus/Views/EventView.swift b/damus/Views/EventView.swift index d573def7..8f296ec2 100644 --- a/damus/Views/EventView.swift +++ b/damus/Views/EventView.swift @@ -20,9 +20,9 @@ struct EventView: View { let event: NostrEvent let options: EventViewOptions let damus: DamusState - let pubkey: String + let pubkey: Pubkey - init(damus: DamusState, event: NostrEvent, pubkey: String? = nil, options: EventViewOptions = []) { + init(damus: DamusState, event: NostrEvent, pubkey: Pubkey? = nil, options: EventViewOptions = []) { self.event = event self.options = options self.damus = damus @@ -54,7 +54,7 @@ struct EventView: View { } // blame the porn bots for this code -func should_show_images(settings: UserSettingsStore, contacts: Contacts, ev: NostrEvent, our_pubkey: String, booster_pubkey: String? = nil) -> Bool { +func should_show_images(settings: UserSettingsStore, contacts: Contacts, ev: NostrEvent, our_pubkey: Pubkey, booster_pubkey: Pubkey? = nil) -> Bool { if settings.always_show_images { return true } @@ -72,7 +72,7 @@ func should_show_images(settings: UserSettingsStore, contacts: Contacts, ev: Nos } extension View { - func pubkey_context_menu(bech32_pubkey: String) -> some View { + func pubkey_context_menu(bech32_pubkey: Pubkey) -> some View { return self.contextMenu { Button { UIPasteboard.general.string = bech32_pubkey @@ -96,7 +96,7 @@ func format_date(_ created_at: UInt32) -> String { return dateFormatter.string(from: date) } -func make_actionbar_model(ev: String, damus: DamusState) -> ActionBarModel { +func make_actionbar_model(ev: NoteId, damus: DamusState) -> ActionBarModel { let model = ActionBarModel.empty() model.update(damus: damus, evid: ev) return model diff --git a/damus/Views/Events/BuilderEventView.swift b/damus/Views/Events/BuilderEventView.swift index 0bacc90d..4e53efc7 100644 --- a/damus/Views/Events/BuilderEventView.swift +++ b/damus/Views/Events/BuilderEventView.swift @@ -9,7 +9,7 @@ import SwiftUI struct BuilderEventView: View { let damus: DamusState - let event_id: String + let event_id: NoteId @State var event: NostrEvent? @State var subscription_uuid: String = UUID().description @@ -19,7 +19,7 @@ struct BuilderEventView: View { self.event_id = event.id } - init(damus: DamusState, event_id: String) { + init(damus: DamusState, event_id: NoteId) { let event = damus.events.lookup(event_id) self.event_id = event_id self.damus = damus diff --git a/damus/Views/Events/Components/EventTop.swift b/damus/Views/Events/Components/EventTop.swift index bd841dcd..53113759 100644 --- a/damus/Views/Events/Components/EventTop.swift +++ b/damus/Views/Events/Components/EventTop.swift @@ -10,10 +10,10 @@ import SwiftUI struct EventTop: View { let state: DamusState let event: NostrEvent - let pubkey: String + let pubkey: Pubkey let is_anon: Bool - init(state: DamusState, event: NostrEvent, pubkey: String, is_anon: Bool) { + init(state: DamusState, event: NostrEvent, pubkey: Pubkey, is_anon: Bool) { self.state = state self.event = event self.pubkey = pubkey diff --git a/damus/Views/Events/Components/ReplyPart.swift b/damus/Views/Events/Components/ReplyPart.swift index e320e234..506b3754 100644 --- a/damus/Views/Events/Components/ReplyPart.swift +++ b/damus/Views/Events/Components/ReplyPart.swift @@ -9,7 +9,7 @@ import SwiftUI struct ReplyPart: View { let event: NostrEvent - let privkey: String? + let privkey: Privkey? let profiles: Profiles var body: some View { diff --git a/damus/Views/Events/EventMenu.swift b/damus/Views/Events/EventMenu.swift index 23496620..8553f6ec 100644 --- a/damus/Views/Events/EventMenu.swift +++ b/damus/Views/Events/EventMenu.swift @@ -10,7 +10,7 @@ import SwiftUI struct EventMenuContext: View { let event: NostrEvent let keypair: Keypair - let target_pubkey: String + let target_pubkey: Pubkey let bookmarks: BookmarksManager let muted_threads: MutedThreadsManager @ObservedObject var settings: UserSettingsStore @@ -44,7 +44,7 @@ struct EventMenuContext: View { struct MenuItems: View { let event: NostrEvent let keypair: Keypair - let target_pubkey: String + let target_pubkey: Pubkey let bookmarks: BookmarksManager let muted_threads: MutedThreadsManager @ObservedObject var settings: UserSettingsStore @@ -52,7 +52,7 @@ struct MenuItems: View { @State private var isBookmarked: Bool = false @State private var isMutedThread: Bool = false - init(event: NostrEvent, keypair: Keypair, target_pubkey: String, bookmarks: BookmarksManager, muted_threads: MutedThreadsManager, settings: UserSettingsStore) { + init(event: NostrEvent, keypair: Keypair, target_pubkey: Pubkey, bookmarks: BookmarksManager, muted_threads: MutedThreadsManager, settings: UserSettingsStore) { let bookmarked = bookmarks.isBookmarked(event) self._isBookmarked = State(initialValue: bookmarked) diff --git a/damus/Views/Events/EventProfile.swift b/damus/Views/Events/EventProfile.swift index bdd0a7f3..89d72737 100644 --- a/damus/Views/Events/EventProfile.swift +++ b/damus/Views/Events/EventProfile.swift @@ -24,7 +24,7 @@ func eventview_pfp_size(_ size: EventViewKind) -> CGFloat { struct EventProfile: View { let damus_state: DamusState - let pubkey: String + let pubkey: Pubkey let profile: Profile? let size: EventViewKind diff --git a/damus/Views/Events/EventShell.swift b/damus/Views/Events/EventShell.swift index 219461f2..a1671249 100644 --- a/damus/Views/Events/EventShell.swift +++ b/damus/Views/Events/EventShell.swift @@ -10,11 +10,11 @@ import SwiftUI struct EventShell: View { let state: DamusState let event: NostrEvent - let pubkey: String + let pubkey: Pubkey let options: EventViewOptions let content: Content - init(state: DamusState, event: NostrEvent, pubkey: String, options: EventViewOptions, @ViewBuilder content: () -> Content) { + init(state: DamusState, event: NostrEvent, pubkey: Pubkey, options: EventViewOptions, @ViewBuilder content: () -> Content) { self.state = state self.event = event self.options = options diff --git a/damus/Views/Events/SelectedEventView.swift b/damus/Views/Events/SelectedEventView.swift index ae3e624d..15cf3d2c 100644 --- a/damus/Views/Events/SelectedEventView.swift +++ b/damus/Views/Events/SelectedEventView.swift @@ -12,7 +12,7 @@ struct SelectedEventView: View { let event: NostrEvent let size: EventViewKind - var pubkey: String { + var pubkey: Pubkey { event.pubkey } diff --git a/damus/Views/Events/TextEvent.swift b/damus/Views/Events/TextEvent.swift index 5d082234..41b72c2f 100644 --- a/damus/Views/Events/TextEvent.swift +++ b/damus/Views/Events/TextEvent.swift @@ -26,11 +26,11 @@ struct EventViewOptions: OptionSet { struct TextEvent: View { let damus: DamusState let event: NostrEvent - let pubkey: String + let pubkey: Pubkey let options: EventViewOptions let evdata: EventData - init(damus: DamusState, event: NostrEvent, pubkey: String, options: EventViewOptions) { + init(damus: DamusState, event: NostrEvent, pubkey: Pubkey, options: EventViewOptions) { self.damus = damus self.event = event self.pubkey = pubkey diff --git a/damus/Views/FollowingView.swift b/damus/Views/FollowingView.swift index e1aeff81..bdb5724e 100644 --- a/damus/Views/FollowingView.swift +++ b/damus/Views/FollowingView.swift @@ -26,7 +26,7 @@ struct FollowUserView: View { struct FollowersYouKnowView: View { let damus_state: DamusState - let friended_followers: [String] + let friended_followers: [Pubkey] @ObservedObject var followers: FollowersModel var body: some View { diff --git a/damus/Views/ImagePicker.swift b/damus/Views/ImagePicker.swift index 366d8966..d4c7b450 100644 --- a/damus/Views/ImagePicker.swift +++ b/damus/Views/ImagePicker.swift @@ -15,7 +15,7 @@ struct ImagePicker: UIViewControllerRepresentable { let uploader: MediaUploader let sourceType: UIImagePickerController.SourceType - let pubkey: String + let pubkey: Pubkey @Binding var image_upload_confirm: Bool var imagesOnly: Bool = false let onImagePicked: (URL) -> Void diff --git a/damus/Views/Images/ProfilePicImageView.swift b/damus/Views/Images/ProfilePicImageView.swift index 97f9b63d..d36c181e 100644 --- a/damus/Views/Images/ProfilePicImageView.swift +++ b/damus/Views/Images/ProfilePicImageView.swift @@ -62,7 +62,7 @@ struct NavDismissBarView: View { } struct ProfilePicImageView: View { - let pubkey: String + let pubkey: Pubkey let profiles: Profiles let disable_animation: Bool @@ -90,12 +90,10 @@ struct ProfilePicImageView: View { } struct ProfileZoomView_Previews: PreviewProvider { - static let pubkey = "ca48854ac6555fed8e439ebb4fa2d928410e0eef13fa41164ec45aaaa132d846" - static var previews: some View { ProfilePicImageView( - pubkey: pubkey, - profiles: make_preview_profiles(pubkey), + pubkey: test_pubkey, + profiles: make_preview_profiles(test_pubkey), disable_animation: false ) } diff --git a/damus/Views/LoginView.swift b/damus/Views/LoginView.swift index eb084436..bbd7b824 100644 --- a/damus/Views/LoginView.swift +++ b/damus/Views/LoginView.swift @@ -8,8 +8,8 @@ import SwiftUI enum ParsedKey { - case pub(String) - case priv(String) + case pub(Pubkey) + case priv(Privkey) case hex(String) case nip05(String) @@ -203,7 +203,7 @@ func process_login(_ key: ParsedKey, is_pubkey: Bool) async throws { } } - func handle_privkey(_ privkey: String) throws { + func handle_privkey(_ privkey: Privkey) throws { try save_privkey(privkey: privkey) guard let pk = privkey_to_pubkey(privkey: privkey) else { @@ -231,7 +231,7 @@ struct NIP05Result: Decodable { } struct NIP05User { - let pubkey: String + let pubkey: Pubkey let relays: [String] } diff --git a/damus/Views/Muting/MutelistView.swift b/damus/Views/Muting/MutelistView.swift index 539d7fda..64e8a021 100644 --- a/damus/Views/Muting/MutelistView.swift +++ b/damus/Views/Muting/MutelistView.swift @@ -9,9 +9,9 @@ import SwiftUI struct MutelistView: View { let damus_state: DamusState - @State var users: [String] + @State var users: [Pubkey] - func RemoveAction(pubkey: String) -> some View { + func RemoveAction(pubkey: Pubkey) -> some View { Button { guard let mutelist = damus_state.contacts.mutelist else { return diff --git a/damus/Views/NoteContentView.swift b/damus/Views/NoteContentView.swift index 9aecd2c2..eacb160a 100644 --- a/damus/Views/NoteContentView.swift +++ b/damus/Views/NoteContentView.swift @@ -392,7 +392,7 @@ func note_artifact_is_separated(kind: NostrKind?) -> Bool { return kind != .longform } -func render_note_content(ev: NostrEvent, profiles: Profiles, privkey: String?) -> NoteArtifacts { +func render_note_content(ev: NostrEvent, profiles: Profiles, privkey: Privkey?) -> NoteArtifacts { let blocks = ev.blocks(privkey) if ev.known_kind == .longform { @@ -574,7 +574,7 @@ func classify_url(_ url: URL) -> UrlType { return .link(url) } -func lookup_cached_preview_size(previews: PreviewCache, evid: String) -> CGFloat? { +func lookup_cached_preview_size(previews: PreviewCache, evid: NoteId) -> CGFloat? { guard case .value(let cached) = previews.lookup(evid) else { return nil } diff --git a/damus/Views/Notifications/EventGroupView.swift b/damus/Views/Notifications/EventGroupView.swift index 6e6eb8c6..91f4d7a9 100644 --- a/damus/Views/Notifications/EventGroupView.swift +++ b/damus/Views/Notifications/EventGroupView.swift @@ -56,7 +56,7 @@ enum ReactingTo { case your_profile } -func determine_reacting_to(our_pubkey: String, ev: NostrEvent?) -> ReactingTo { +func determine_reacting_to(our_pubkey: Pubkey, ev: NostrEvent?) -> ReactingTo { guard let ev else { return .your_profile } @@ -68,21 +68,21 @@ func determine_reacting_to(our_pubkey: String, ev: NostrEvent?) -> ReactingTo { return .tagged_in } -func event_author_name(profiles: Profiles, pubkey: String) -> String { +func event_author_name(profiles: Profiles, pubkey: Pubkey) -> String { let alice_prof = profiles.lookup(id: pubkey) return Profile.displayName(profile: alice_prof, pubkey: pubkey).username.truncate(maxLength: 50) } -func event_group_unique_pubkeys(profiles: Profiles, group: EventGroupType) -> [String] { - var seen = Set() - var sorted = [String]() +func event_group_unique_pubkeys(profiles: Profiles, group: EventGroupType) -> [Pubkey] { + var seen = Set() + var sorted = [Pubkey]() if let zapgrp = group.zap_group { let zaps = zapgrp.zaps for i in 0.. [S "zapped_your_profile_2" - returned when 2 zaps occurred to the current user's profile "zapped_your_profile_3" - returned when 3 or more zaps occurred to the current user's profile */ -func reacting_to_text(profiles: Profiles, our_pubkey: String, group: EventGroupType, ev: NostrEvent?, pubkeys: [String], locale: Locale? = nil) -> String { +func reacting_to_text(profiles: Profiles, our_pubkey: Pubkey, group: EventGroupType, ev: NostrEvent?, pubkeys: [Pubkey], locale: Locale? = nil) -> String { if group.events.count == 0 { return "??" } @@ -192,7 +192,7 @@ struct EventGroupView: View { let event: NostrEvent? let group: EventGroupType - func GroupDescription(_ pubkeys: [String]) -> some View { + func GroupDescription(_ pubkeys: [Pubkey]) -> some View { Text(verbatim: "\(reacting_to_text(profiles: state.profiles, our_pubkey: state.pubkey, group: group, ev: event, pubkeys: pubkeys))") } diff --git a/damus/Views/Notifications/NotificationsView.swift b/damus/Views/Notifications/NotificationsView.swift index 4580be1f..101a5f3e 100644 --- a/damus/Views/Notifications/NotificationsView.swift +++ b/damus/Views/Notifications/NotificationsView.swift @@ -23,7 +23,7 @@ enum FriendFilter: String, StringCodable { self.rawValue } - func filter(contacts: Contacts, pubkey: String) -> Bool { + func filter(contacts: Contacts, pubkey: Pubkey) -> Bool { switch self { case .all: return true diff --git a/damus/Views/Notifications/ProfilePicturesView.swift b/damus/Views/Notifications/ProfilePicturesView.swift index a247d59c..5a760bcb 100644 --- a/damus/Views/Notifications/ProfilePicturesView.swift +++ b/damus/Views/Notifications/ProfilePicturesView.swift @@ -9,8 +9,8 @@ import SwiftUI struct ProfilePicturesView: View { let state: DamusState - let pubkeys: [String] - + let pubkeys: [Pubkey] + var body: some View { HStack { ForEach(pubkeys.prefix(8), id: \.self) { pubkey in diff --git a/damus/Views/Onboarding/SuggestedUserView.swift b/damus/Views/Onboarding/SuggestedUserView.swift index cd48f808..43dbafe8 100644 --- a/damus/Views/Onboarding/SuggestedUserView.swift +++ b/damus/Views/Onboarding/SuggestedUserView.swift @@ -8,13 +8,13 @@ import SwiftUI struct SuggestedUser: Codable { - let pubkey: String + let pubkey: Pubkey let name: String let about: String let pfp: URL let profile: Profile - init?(profile: Profile, pubkey: String) { + init?(profile: Profile, pubkey: Pubkey) { guard let name = profile.name, let about = profile.about, @@ -64,7 +64,7 @@ struct SuggestedUserView_Previews: PreviewProvider { static var previews: some View { let profile = Profile(name: "klabo", about: "A person who likes nostr a lot and I like to tell people about myself in very long-winded ways that push the limits of UI and almost break things", picture: "https://primal.b-cdn.net/media-cache?s=m&a=1&u=https%3A%2F%2Fpbs.twimg.com%2Fprofile_images%2F1599994711430742017%2F33zLk9Wi_400x400.jpg") - let user = SuggestedUser(profile: profile, pubkey: "abcd")! + let user = SuggestedUser(profile: profile, pubkey: test_pubkey)! List { SuggestedUserView(user: user, damus_state: test_damus_state()) } diff --git a/damus/Views/Onboarding/SuggestedUsersViewModel.swift b/damus/Views/Onboarding/SuggestedUsersViewModel.swift index 3cf9f226..7eae7fb7 100644 --- a/damus/Views/Onboarding/SuggestedUsersViewModel.swift +++ b/damus/Views/Onboarding/SuggestedUsersViewModel.swift @@ -11,7 +11,7 @@ import Combine struct SuggestedUserGroup: Identifiable, Codable { let id = UUID() let title: String - let users: [String] + let users: [Pubkey] enum CodingKeys: String, CodingKey { case title, users @@ -34,7 +34,7 @@ class SuggestedUsersViewModel: ObservableObject { subscribeToSuggestedProfiles(pubkeys: pubkeys) } - func suggestedUser(pubkey: String) -> SuggestedUser? { + func suggestedUser(pubkey: Pubkey) -> SuggestedUser? { if let profile = damus_state.profiles.lookup(id: pubkey), let user = SuggestedUser(profile: profile, pubkey: pubkey) { return user @@ -42,7 +42,7 @@ class SuggestedUsersViewModel: ObservableObject { return nil } - func follow(pubkeys: [String]) { + func follow(pubkeys: [Pubkey]) { for pubkey in pubkeys { notify(.follow(.pubkey(pubkey))) } @@ -66,17 +66,16 @@ class SuggestedUsersViewModel: ObservableObject { } } - private func getPubkeys(groups: [SuggestedUserGroup]) -> [String] { - var pubkeys: [String] = [] + private func getPubkeys(groups: [SuggestedUserGroup]) -> [Pubkey] { + var pubkeys: [Pubkey] = [] for group in groups { pubkeys.append(contentsOf: group.users) } return pubkeys } - private func subscribeToSuggestedProfiles(pubkeys: [String]) { - let filter = NostrFilter(kinds: [.metadata], - authors: pubkeys) + private func subscribeToSuggestedProfiles(pubkeys: [Pubkey]) { + let filter = NostrFilter(kinds: [.metadata], authors: pubkeys) damus_state.pool.subscribe(sub_id: sub_id, filters: [filter], handler: handle_event) } diff --git a/damus/Views/PostView.swift b/damus/Views/PostView.swift index 7729cd80..647b55f8 100644 --- a/damus/Views/PostView.swift +++ b/damus/Views/PostView.swift @@ -21,7 +21,7 @@ class TagModel: ObservableObject { enum PostTarget { case none - case user(String) + case user(Pubkey) } enum PostAction { diff --git a/damus/Views/Posting/UserSearch.swift b/damus/Views/Posting/UserSearch.swift index 570001b7..6cdea437 100644 --- a/damus/Views/Posting/UserSearch.swift +++ b/damus/Views/Posting/UserSearch.swift @@ -9,9 +9,9 @@ import SwiftUI struct SearchedUser: Identifiable { let profile: Profile? - let pubkey: String - - var id: String { + let pubkey: Pubkey + + var id: Pubkey { return pubkey } } @@ -151,7 +151,7 @@ func append_user_tag(tag: NSAttributedString, post: NSMutableAttributedString, w } /// Generate a mention attributed string, including the internal damus:nostr: link -func user_tag_attr_string(profile: Profile?, pubkey: String) -> NSMutableAttributedString { +func user_tag_attr_string(profile: Profile?, pubkey: Pubkey) -> NSMutableAttributedString { let display_name = Profile.displayName(profile: profile, pubkey: pubkey) let name = display_name.username.truncate(maxLength: 50) let tagString = "@\(name)" diff --git a/damus/Views/Profile/CondensedProfilePicturesView.swift b/damus/Views/Profile/CondensedProfilePicturesView.swift index 0cdce14a..982e2173 100644 --- a/damus/Views/Profile/CondensedProfilePicturesView.swift +++ b/damus/Views/Profile/CondensedProfilePicturesView.swift @@ -9,10 +9,10 @@ import SwiftUI struct CondensedProfilePicturesView: View { let state: DamusState - let pubkeys: [String] + let pubkeys: [Pubkey] let maxPictures: Int - init(state: DamusState, pubkeys: [String], maxPictures: Int) { + init(state: DamusState, pubkeys: [Pubkey], maxPictures: Int) { self.state = state self.pubkeys = pubkeys self.maxPictures = min(maxPictures, pubkeys.count) @@ -33,6 +33,6 @@ struct CondensedProfilePicturesView: View { struct CondensedProfilePicturesView_Previews: PreviewProvider { static var previews: some View { - CondensedProfilePicturesView(state: test_damus_state(), pubkeys: ["a", "b", "c", "d"], maxPictures: 3) + CondensedProfilePicturesView(state: test_damus_state(), pubkeys: [test_pubkey, test_pubkey, test_pubkey, test_pubkey], maxPictures: 3) } } diff --git a/damus/Views/Profile/EditPictureControl.swift b/damus/Views/Profile/EditPictureControl.swift index 632635aa..7abdc5fa 100644 --- a/damus/Views/Profile/EditPictureControl.swift +++ b/damus/Views/Profile/EditPictureControl.swift @@ -13,7 +13,7 @@ class ImageUploadingObserver: ObservableObject { struct EditPictureControl: View { let uploader: MediaUploader - let pubkey: String + let pubkey: Pubkey @Binding var image_url: URL? @ObservedObject var uploadObserver: ImageUploadingObserver let callback: (URL?) -> Void @@ -120,12 +120,11 @@ struct EditPictureControl: View { struct EditPictureControl_Previews: PreviewProvider { static var previews: some View { - let pubkey = "123" let url = Binding.constant(URL(string: "https://damus.io")!) let observer = ImageUploadingObserver() ZStack { Color.gray - EditPictureControl(uploader: .nostrBuild, pubkey: pubkey, image_url: url, uploadObserver: observer) { _ in + EditPictureControl(uploader: .nostrBuild, pubkey: test_pubkey, image_url: url, uploadObserver: observer) { _ in // } } diff --git a/damus/Views/Profile/EventProfileName.swift b/damus/Views/Profile/EventProfileName.swift index 2e3cad29..3631e4b5 100644 --- a/damus/Views/Profile/EventProfileName.swift +++ b/damus/Views/Profile/EventProfileName.swift @@ -10,7 +10,7 @@ import SwiftUI /// Profile Name used when displaying an event in the timeline struct EventProfileName: View { let damus_state: DamusState - let pubkey: String + let pubkey: Pubkey let profile: Profile? @State var display_name: DisplayName? @@ -19,7 +19,7 @@ struct EventProfileName: View { let size: EventViewKind - init(pubkey: String, profile: Profile?, damus: DamusState, size: EventViewKind = .normal) { + init(pubkey: Pubkey, profile: Profile?, damus: DamusState, size: EventViewKind = .normal) { self.damus_state = damus self.pubkey = pubkey self.profile = profile diff --git a/damus/Views/Profile/MaybeAnonPfpView.swift b/damus/Views/Profile/MaybeAnonPfpView.swift index 8bc45e06..5a2400a7 100644 --- a/damus/Views/Profile/MaybeAnonPfpView.swift +++ b/damus/Views/Profile/MaybeAnonPfpView.swift @@ -10,10 +10,10 @@ import SwiftUI struct MaybeAnonPfpView: View { let state: DamusState let is_anon: Bool - let pubkey: String + let pubkey: Pubkey let size: CGFloat - init(state: DamusState, is_anon: Bool, pubkey: String, size: CGFloat) { + init(state: DamusState, is_anon: Bool, pubkey: Pubkey, size: CGFloat) { self.state = state self.is_anon = is_anon self.pubkey = pubkey diff --git a/damus/Views/Profile/ProfileName.swift b/damus/Views/Profile/ProfileName.swift index 3a7e7050..5ac2ccbe 100644 --- a/damus/Views/Profile/ProfileName.swift +++ b/damus/Views/Profile/ProfileName.swift @@ -12,7 +12,7 @@ enum FriendType { case fof } -func get_friend_type(contacts: Contacts, pubkey: String) -> FriendType? { +func get_friend_type(contacts: Contacts, pubkey: Pubkey) -> FriendType? { if contacts.is_friend_or_self(pubkey) { return .friend } @@ -26,7 +26,7 @@ func get_friend_type(contacts: Contacts, pubkey: String) -> FriendType? { struct ProfileName: View { let damus_state: DamusState - let pubkey: String + let pubkey: Pubkey let profile: Profile? let prefix: String @@ -36,7 +36,7 @@ struct ProfileName: View { @State var nip05: NIP05? @State var donation: Int? - init(pubkey: String, profile: Profile?, prefix: String = "", damus: DamusState, show_nip5_domain: Bool = true) { + init(pubkey: Pubkey, profile: Profile?, prefix: String = "", damus: DamusState, show_nip5_domain: Bool = true) { self.pubkey = pubkey self.profile = profile self.prefix = prefix diff --git a/damus/Views/Profile/ProfileNameView.swift b/damus/Views/Profile/ProfileNameView.swift index b056170a..72a5076f 100644 --- a/damus/Views/Profile/ProfileNameView.swift +++ b/damus/Views/Profile/ProfileNameView.swift @@ -8,7 +8,7 @@ import SwiftUI struct ProfileNameView: View { - let pubkey: String + let pubkey: Pubkey let profile: Profile? let follows_you: Bool let damus: DamusState diff --git a/damus/Views/Profile/ProfilePicView.swift b/damus/Views/Profile/ProfilePicView.swift index 3c8dd64e..a22f136f 100644 --- a/damus/Views/Profile/ProfilePicView.swift +++ b/damus/Views/Profile/ProfilePicView.swift @@ -31,7 +31,7 @@ func pfp_line_width(_ h: Highlight) -> CGFloat { struct InnerProfilePicView: View { let url: URL? let fallbackUrl: URL? - let pubkey: String + let pubkey: Pubkey let size: CGFloat let highlight: Highlight let disable_animation: Bool @@ -67,7 +67,7 @@ struct InnerProfilePicView: View { } struct ProfilePicView: View { - let pubkey: String + let pubkey: Pubkey let size: CGFloat let highlight: Highlight let profiles: Profiles @@ -75,7 +75,7 @@ struct ProfilePicView: View { @State var picture: String? - init(pubkey: String, size: CGFloat, highlight: Highlight, profiles: Profiles, disable_animation: Bool, picture: String? = nil) { + init(pubkey: Pubkey, size: CGFloat, highlight: Highlight, profiles: Profiles, disable_animation: Bool, picture: String? = nil) { self.pubkey = pubkey self.profiles = profiles self.size = size @@ -98,7 +98,7 @@ struct ProfilePicView: View { } } -func get_profile_url(picture: String?, pubkey: String, profiles: Profiles) -> URL { +func get_profile_url(picture: String?, pubkey: Pubkey, profiles: Profiles) -> URL { let pic = picture ?? profiles.lookup(id: pubkey)?.picture ?? robohash(pubkey) if let url = URL(string: pic) { return url diff --git a/damus/Views/Profile/ProfilePictureSelector.swift b/damus/Views/Profile/ProfilePictureSelector.swift index d3f114a9..9a04b3ff 100644 --- a/damus/Views/Profile/ProfilePictureSelector.swift +++ b/damus/Views/Profile/ProfilePictureSelector.swift @@ -13,7 +13,7 @@ struct EditProfilePictureView: View { @State var profile_url: URL? - let pubkey: String + let pubkey: Pubkey var damus_state: DamusState? var size: CGFloat = 80.0 let highlight: Highlight = .custom(Color.white, 2.0) @@ -52,7 +52,6 @@ struct EditProfilePictureView: View { struct ProfilePictureSelector_Previews: PreviewProvider { static var previews: some View { - let test_pubkey = "ff48854ac6555fed8e439ebb4fa2d928410e0eef13fa41164ec45aaaa132d846" EditProfilePictureView(pubkey: test_pubkey, uploadObserver: ImageUploadingObserver()) { _ in // } diff --git a/damus/Views/Profile/ProfileView.swift b/damus/Views/Profile/ProfileView.swift index 9fe88280..0524e4cb 100644 --- a/damus/Views/Profile/ProfileView.swift +++ b/damus/Views/Profile/ProfileView.swift @@ -31,7 +31,7 @@ func follow_btn_txt(_ fs: FollowState, follows_you: Bool) -> String { } } -func followedByString(_ friend_intersection: [String], profiles: Profiles, locale: Locale = Locale.current) -> String { +func followedByString(_ friend_intersection: [Pubkey], profiles: Profiles, locale: Locale = Locale.current) -> String { let bundle = bundleForLocale(locale: locale) let names: [String] = friend_intersection.prefix(3).map { let profile = profiles.lookup(id: $0) @@ -90,7 +90,7 @@ struct ProfileView: View { self._followers = StateObject(wrappedValue: followers) } - init(damus_state: DamusState, pubkey: String) { + init(damus_state: DamusState, pubkey: Pubkey) { self.damus_state = damus_state self._profile = StateObject(wrappedValue: ProfileModel(pubkey: pubkey, damus: damus_state)) self._followers = StateObject(wrappedValue: FollowersModel(damus_state: damus_state, target: pubkey)) @@ -493,7 +493,7 @@ struct ProfileView_Previews: PreviewProvider { } struct KeyView: View { - let pubkey: String + let pubkey: Pubkey @Environment(\.colorScheme) var colorScheme @@ -566,7 +566,7 @@ extension View { } } -func check_nip05_validity(pubkey: String, profiles: Profiles) { +func check_nip05_validity(pubkey: Pubkey, profiles: Profiles) { guard let profile = profiles.lookup(id: pubkey), let nip05 = profile.nip05, profiles.is_validated(pubkey) == nil diff --git a/damus/Views/QRCodeView.swift b/damus/Views/QRCodeView.swift index 6acc01cf..bfa62565 100644 --- a/damus/Views/QRCodeView.swift +++ b/damus/Views/QRCodeView.swift @@ -9,7 +9,7 @@ import SwiftUI import CoreImage.CIFilterBuiltins struct ProfileScanResult: Equatable { - let pubkey: String + let pubkey: Pubkey init(hex: String) { self.pubkey = hex @@ -42,7 +42,7 @@ struct ProfileScanResult: Equatable { struct QRCodeView: View { let damus_state: DamusState - @State var pubkey: String + @State var pubkey: Pubkey @Environment(\.presentationMode) var presentationMode diff --git a/damus/Views/Search/SearchingEventView.swift b/damus/Views/Search/SearchingEventView.swift index bcb0c4d3..ff18933f 100644 --- a/damus/Views/Search/SearchingEventView.swift +++ b/damus/Views/Search/SearchingEventView.swift @@ -10,7 +10,7 @@ import SwiftUI enum SearchState { case searching case found(NostrEvent) - case found_profile(String) + case found_profile(Pubkey) case not_found } diff --git a/damus/Views/SearchResultsView.swift b/damus/Views/SearchResultsView.swift index 6ece7b62..43615f42 100644 --- a/damus/Views/SearchResultsView.swift +++ b/damus/Views/SearchResultsView.swift @@ -15,8 +15,8 @@ struct MultiSearch { enum Search: Identifiable { case profiles([SearchedUser]) case hashtag(String) - case profile(String) - case note(String) + case profile(Pubkey) + case note(NoteId) case nip05(String) case hex(String) case multi(MultiSearch) @@ -38,7 +38,7 @@ struct InnerSearchResults: View { let damus_state: DamusState let search: Search? - func ProfileSearchResult(pk: String) -> some View { + func ProfileSearchResult(pk: Pubkey) -> some View { FollowUserView(target: .pubkey(pk), damus_state: damus_state) } diff --git a/damus/Views/SelectWalletView.swift b/damus/Views/SelectWalletView.swift index 846c9a3a..62433904 100644 --- a/damus/Views/SelectWalletView.swift +++ b/damus/Views/SelectWalletView.swift @@ -10,7 +10,7 @@ import SwiftUI struct SelectWalletView: View { let default_wallet: Wallet @Binding var active_sheet: Sheets? - let our_pubkey: String + let our_pubkey: Pubkey let invoice: String @State var invoice_copied: Bool = false @@ -71,6 +71,6 @@ struct SelectWalletView_Previews: PreviewProvider { @State static var active_sheet: Sheets? = nil static var previews: some View { - SelectWalletView(default_wallet: .lnlink, active_sheet: $active_sheet, our_pubkey: "", invoice: "") + SelectWalletView(default_wallet: .lnlink, active_sheet: $active_sheet, our_pubkey: test_pubkey, invoice: "") } } diff --git a/damus/Views/Zaps/ZapTypePicker.swift b/damus/Views/Zaps/ZapTypePicker.swift index 4bcef8f7..a85b7e91 100644 --- a/damus/Views/Zaps/ZapTypePicker.swift +++ b/damus/Views/Zaps/ZapTypePicker.swift @@ -31,7 +31,7 @@ struct ZapTypePicker: View { @Binding var zap_type: ZapType @ObservedObject var settings: UserSettingsStore let profiles: Profiles - let pubkey: String + let pubkey: Pubkey @Environment(\.colorScheme) var colorScheme @@ -106,11 +106,11 @@ struct ZapTypePicker_Previews: PreviewProvider { @State static var zap_type: ZapType = .pub static var previews: some View { let ds = test_damus_state() - ZapTypePicker(zap_type: $zap_type, settings: ds.settings, profiles: ds.profiles, pubkey: "bob") + ZapTypePicker(zap_type: $zap_type, settings: ds.settings, profiles: ds.profiles, pubkey: test_pubkey) } } -func zap_type_desc(type: ZapType, profiles: Profiles, pubkey: String) -> String { +func zap_type_desc(type: ZapType, profiles: Profiles, pubkey: Pubkey) -> String { switch type { case .pub: return NSLocalizedString("Everyone will see that you zapped", comment: "Description of public zap type where the zap is sent publicly and identifies the user who sent it.") diff --git a/damus/Views/Zaps/ZapUserView.swift b/damus/Views/Zaps/ZapUserView.swift index 80aa5f6d..465e95b9 100644 --- a/damus/Views/Zaps/ZapUserView.swift +++ b/damus/Views/Zaps/ZapUserView.swift @@ -9,8 +9,8 @@ import SwiftUI struct ZapUserView: View { let state: DamusState - let pubkey: String - + let pubkey: Pubkey + var body: some View { HStack(alignment: .center) { Text("Zap") diff --git a/damusTests/UserSearchCacheTests.swift b/damusTests/UserSearchCacheTests.swift index ecda42dc..f1bc5d15 100644 --- a/damusTests/UserSearchCacheTests.swift +++ b/damusTests/UserSearchCacheTests.swift @@ -86,7 +86,7 @@ final class UserSearchCacheTests: XCTestCase { let damus = "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681" let jb55 = "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" - var pubkeysToPetnames = [String: String]() + var pubkeysToPetnames = [Pubkey: String]() pubkeysToPetnames[damus] = "damus" pubkeysToPetnames[jb55] = "jb55" @@ -114,7 +114,7 @@ final class UserSearchCacheTests: XCTestCase { XCTAssertEqual(damusState.user_search_cache.search(key: "l"), [jb55]) } - private func createContactsEventWithPetnames(pubkeysToPetnames: [String: String]) throws -> NostrEvent { + private func createContactsEventWithPetnames(pubkeysToPetnames: [Pubkey: String]) throws -> NostrEvent { let keypair = try XCTUnwrap(keypair) let bootstrapRelays = load_bootstrap_relays(pubkey: keypair.pubkey) diff --git a/nostrdb/NdbNote.swift b/nostrdb/NdbNote.swift index 0419840c..653ba038 100644 --- a/nostrdb/NdbNote.swift +++ b/nostrdb/NdbNote.swift @@ -242,7 +242,7 @@ extension NdbNote { References.hashtags(tags: self.tags) } - func event_refs(_ privkey: String?) -> [EventRef] { + func event_refs(_ privkey: Privkey?) -> [EventRef] { if let rs = _event_refs { return rs } @@ -251,7 +251,7 @@ extension NdbNote { return refs } - func get_content(_ privkey: String?) -> String { + func get_content(_ privkey: Privkey?) -> String { if known_kind == .dm { return decrypted(privkey: privkey) ?? "*failed to decrypt content*" } @@ -259,7 +259,7 @@ extension NdbNote { return content } - func blocks(_ privkey: String?) -> Blocks { + func blocks(_ privkey: Privkey?) -> Blocks { if let bs = _blocks { return bs } let blocks = get_blocks(content: self.get_content(privkey)) @@ -268,8 +268,8 @@ extension NdbNote { } // NDBTODO: switch this to operating on bytes not strings - func decrypted(privkey: String?) -> String? { - if let decrypted_content = decrypted_content { + func decrypted(privkey: Privkey?) -> String? { + if let decrypted_content { return decrypted_content } @@ -312,7 +312,7 @@ extension NdbNote { } */ - public func direct_replies(_ privkey: String?) -> [ReferencedId] { + public func direct_replies(_ privkey: Privkey?) -> [ReferencedId] { return event_refs(privkey).reduce(into: []) { acc, evref in if let direct_reply = evref.is_direct_reply { acc.append(direct_reply) @@ -321,7 +321,7 @@ extension NdbNote { } // NDBTODO: just use Id - public func thread_id(privkey: String?) -> String { + public func thread_id(privkey: Privkey?) -> NoteId { for ref in event_refs(privkey) { if let thread_id = ref.is_thread_id { return thread_id.ref_id @@ -346,11 +346,11 @@ extension NdbNote { return false } - func is_reply(_ privkey: String?) -> Bool { + func is_reply(_ privkey: Privkey?) -> Bool { return event_is_reply(self.event_refs(privkey)) } - func note_language(_ privkey: String?) async -> String? { + func note_language(_ privkey: Privkey?) async -> String? { let t = Task.detached { // Rely on Apple's NLLanguageRecognizer to tell us which language it thinks the note is in // and filter on only the text portions of the content as URLs and hashtags confuse the language recognizer.