Relay.swift (3519B)
1 // 2 // Relay.swift 3 // damus 4 // 5 // Created by William Casarin on 2022-04-11. 6 // 7 8 import Foundation 9 10 public struct RelayInfo: Codable { 11 let read: Bool? 12 let write: Bool? 13 14 init(read: Bool, write: Bool) { 15 self.read = read 16 self.write = write 17 } 18 19 static let rw = RelayInfo(read: true, write: true) 20 } 21 22 enum RelayVariant { 23 case regular 24 case ephemeral 25 case nwc 26 } 27 28 public struct RelayDescriptor { 29 let url: RelayURL 30 let info: RelayInfo 31 let variant: RelayVariant 32 33 init(url: RelayURL, info: RelayInfo, variant: RelayVariant = .regular) { 34 self.url = url 35 self.info = info 36 self.variant = variant 37 } 38 39 var ephemeral: Bool { 40 switch variant { 41 case .regular: 42 return false 43 case .ephemeral: 44 return true 45 case .nwc: 46 return true 47 } 48 } 49 50 static func nwc(url: RelayURL) -> RelayDescriptor { 51 return RelayDescriptor(url: url, info: .rw, variant: .nwc) 52 } 53 } 54 55 enum RelayFlags: Int { 56 case none = 0 57 case broken = 1 58 } 59 60 enum RelayAuthenticationError { 61 /// Only a public key was provided in keypair to sign challenge. 62 /// 63 /// A private key is required to sign `auth` challenge. 64 case no_private_key 65 /// No keypair was provided to sign challenge. 66 case no_key 67 } 68 enum RelayAuthenticationState: Equatable { 69 /// No `auth` request has been made from this relay 70 case none 71 /// We have received an `auth` challenge, but have not yet replied to the challenge 72 case pending 73 /// We have received an `auth` challenge and replied with an `auth` event 74 case verified 75 /// We received an `auth` challenge but failed to reply to the challenge 76 case error(RelayAuthenticationError) 77 } 78 79 struct Limitations: Codable { 80 let payment_required: Bool? 81 82 static var empty: Limitations { 83 Limitations(payment_required: nil) 84 } 85 } 86 87 struct Admission: Codable { 88 let amount: Int64 89 let unit: String 90 } 91 92 struct Subscription: Codable { 93 let amount: Int64 94 let unit: String 95 let period: Int 96 } 97 98 struct Publication: Codable { 99 let kinds: [Int] 100 let amount: Int64 101 let unit: String 102 } 103 104 struct Fees: Codable { 105 let admission: [Admission]? 106 let subscription: [Subscription]? 107 let publication: [Publication]? 108 109 static var empty: Fees { 110 Fees(admission: nil, subscription: nil, publication: nil) 111 } 112 } 113 114 struct RelayMetadata: Codable { 115 let name: String? 116 let description: String? 117 let pubkey: Pubkey? 118 let contact: String? 119 let supported_nips: [Int]? 120 let software: String? 121 let version: String? 122 let limitation: Limitations? 123 let payments_url: String? 124 let icon: String? 125 let fees: Fees? 126 127 var is_paid: Bool { 128 return limitation?.payment_required ?? false 129 } 130 } 131 132 class Relay: Identifiable { 133 let descriptor: RelayDescriptor 134 let connection: RelayConnection 135 var authentication_state: RelayAuthenticationState 136 137 var flags: Int 138 139 init(descriptor: RelayDescriptor, connection: RelayConnection) { 140 self.flags = 0 141 self.descriptor = descriptor 142 self.connection = connection 143 self.authentication_state = RelayAuthenticationState.none 144 } 145 146 var is_broken: Bool { 147 return (flags & RelayFlags.broken.rawValue) == RelayFlags.broken.rawValue 148 } 149 150 var id: RelayURL { 151 return descriptor.url 152 } 153 154 } 155 156 enum RelayError: Error { 157 case RelayAlreadyExists 158 }