NIP05.swift (1543B)
1 // 2 // NIP05.swift 3 // damus 4 // 5 // Created by William Casarin on 2023-01-04. 6 // 7 8 import Foundation 9 10 struct NIP05: Equatable { 11 let username: String 12 let host: String 13 14 var url: URL? { 15 URL(string: "https://\(host)/.well-known/nostr.json?name=\(username)") 16 } 17 18 var siteUrl: URL? { 19 URL(string: "https://\(host)") 20 } 21 22 static func parse(_ nip05: String) -> NIP05? { 23 let parts = nip05.split(separator: "@") 24 guard parts.count == 2 else { 25 return nil 26 } 27 return NIP05(username: String(parts[0]), host: String(parts[1])) 28 } 29 } 30 31 32 struct NIP05Response: Decodable { 33 let names: [String: Pubkey] 34 } 35 36 func fetch_nip05(nip05: NIP05) async -> NIP05Response? { 37 guard let url = nip05.url else { 38 return nil 39 } 40 41 print("fetching nip05 \(url.absoluteString)") 42 guard let ret = try? await URLSession.shared.data(from: url) else { 43 return nil 44 } 45 let dat = ret.0 46 47 guard let decoded = try? JSONDecoder().decode(NIP05Response.self, from: dat) else { 48 return nil 49 } 50 51 return decoded 52 } 53 54 func validate_nip05(pubkey: Pubkey, nip05_str: String) async -> NIP05? { 55 guard let nip05 = NIP05.parse(nip05_str) else { 56 return nil 57 } 58 59 guard let decoded = await fetch_nip05(nip05: nip05) else { 60 return nil 61 } 62 63 guard let stored_pk = decoded.names[nip05.username] else { 64 return nil 65 } 66 67 guard stored_pk == pubkey else { 68 return nil 69 } 70 71 return nip05 72 }