From 6c63e3a1df74ff92564c220c0f7cd3f9c1a864ab Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 7 Nov 2024 11:33:56 -0800 Subject: [PATCH] a few more v2 client clean ups --- Sources/XMTPiOS/Conversations.swift | 67 +------- Sources/XMTPiOS/Frames/FramesConstants.swift | 12 -- Sources/XMTPiOS/Frames/FramesTypes.swift | 166 ------------------- Sources/XMTPiOS/Frames/OpenFramesProxy.swift | 38 ----- Sources/XMTPiOS/Frames/ProxyClient.swift | 97 ----------- 5 files changed, 9 insertions(+), 371 deletions(-) delete mode 100644 Sources/XMTPiOS/Frames/FramesConstants.swift delete mode 100644 Sources/XMTPiOS/Frames/FramesTypes.swift delete mode 100644 Sources/XMTPiOS/Frames/OpenFramesProxy.swift delete mode 100644 Sources/XMTPiOS/Frames/ProxyClient.swift diff --git a/Sources/XMTPiOS/Conversations.swift b/Sources/XMTPiOS/Conversations.swift index 6a0dcb75..bf0ffe65 100644 --- a/Sources/XMTPiOS/Conversations.swift +++ b/Sources/XMTPiOS/Conversations.swift @@ -50,38 +50,6 @@ final class ConversationStreamCallback: FfiConversationCallback { } } -final class V2SubscriptionCallback: FfiV2SubscriptionCallback { - func onError(error: LibXMTP.GenericError) { - print("Error V2SubscriptionCallback \(error)") - } - - let callback: (Envelope) -> Void - - init(callback: @escaping (Envelope) -> Void) { - self.callback = callback - } - - func onMessage(message: LibXMTP.FfiEnvelope) { - self.callback(message.fromFFI) - } -} - -class StreamManager { - var stream: FfiV2Subscription? - - func updateStream(with request: FfiV2SubscribeRequest) async throws { - try await stream?.update(req: request) - } - - func endStream() async throws { - try await stream?.end() - } - - func setStream(_ newStream: FfiV2Subscription?) { - self.stream = newStream - } -} - actor FfiStreamActor { private var ffiStream: FfiStreamCloser? @@ -135,9 +103,6 @@ public actor Conversations { public func listDms( createdAfter: Date? = nil, createdBefore: Date? = nil, limit: Int? = nil ) async throws -> [Dm] { - guard let v3Client = client.v3Client else { - return [] - } var options = FfiListConversationsOptions( createdAfterNs: nil, createdBeforeNs: nil, limit: nil, consentState: nil) @@ -269,7 +234,7 @@ public actor Conversations { if peerAddress.lowercased() == client.address.lowercased() { throw ConversationError.memberCannotBeSelf } - let canMessage = try await self.client.canMessageV3( + let canMessage = try await self.client.canMessage( address: peerAddress) if !canMessage { throw ConversationError.memberNotRegistered([peerAddress]) @@ -340,29 +305,15 @@ public actor Conversations { }) != nil { throw ConversationError.memberCannotBeSelf } - let erroredAddresses = try await withThrowingTaskGroup( - of: (String?).self - ) { group in - for address in addresses { - group.addTask { - if try await self.client.canMessageV3(address: address) { - return nil - } else { - return address - } - } - } - var results: [String] = [] - for try await result in group { - if let result { - results.append(result) - } - } - return results - } - if !erroredAddresses.isEmpty { - throw ConversationError.memberNotRegistered(erroredAddresses) + let addressMap = try await self.client.canMessage(addresses: addresses) + let unregisteredAddresses = addressMap + .filter { !$0.value } + .map { $0.key } + + if !unregisteredAddresses.isEmpty { + throw ConversationError.memberNotRegistered(unregisteredAddresses) } + let group = try await ffiConversations.createGroup( accountAddresses: addresses, opts: FfiCreateGroupOptions( diff --git a/Sources/XMTPiOS/Frames/FramesConstants.swift b/Sources/XMTPiOS/Frames/FramesConstants.swift deleted file mode 100644 index 976b8746..00000000 --- a/Sources/XMTPiOS/Frames/FramesConstants.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// File.swift -// -// -// Created by Alex Risch on 3/28/24. -// - -import Foundation - -let OPEN_FRAMES_PROXY_URL = "https://frames.xmtp.chat/" - -let PROTOCOL_VERSION = "2024-02-09" diff --git a/Sources/XMTPiOS/Frames/FramesTypes.swift b/Sources/XMTPiOS/Frames/FramesTypes.swift deleted file mode 100644 index 1f0819dc..00000000 --- a/Sources/XMTPiOS/Frames/FramesTypes.swift +++ /dev/null @@ -1,166 +0,0 @@ -// -// File.swift -// -// -// Created by Alex Risch on 3/28/24. -// - -import Foundation - -typealias AcceptedFrameClients = [String: String] - -enum OpenFrameButton: Codable { - case link(target: String, label: String) - case mint(target: String, label: String) - case post(target: String?, label: String) - case postRedirect(target: String?, label: String) - - enum CodingKeys: CodingKey { - case action, target, label - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let action = try container.decode(String.self, forKey: .action) - guard let target = try container.decodeIfPresent(String.self, forKey: .target) else { - throw FramesClientError.missingTarget - } - let label = try container.decode(String.self, forKey: .label) - - switch action { - case "link": - self = .link(target: target, label: label) - case "mint": - self = .mint(target: target, label: label) - case "post": - self = .post(target: target, label: label) - case "post_redirect": - self = .postRedirect(target: target, label: label) - default: - throw DecodingError.dataCorruptedError(forKey: .action, in: container, debugDescription: "Invalid action value") - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - switch self { - case .link(let target, let label): - try container.encode("link", forKey: .action) - try container.encode(target, forKey: .target) - try container.encode(label, forKey: .label) - case .mint(let target, let label): - try container.encode("mint", forKey: .action) - try container.encode(target, forKey: .target) - try container.encode(label, forKey: .label) - case .post(let target, let label): - try container.encode("post", forKey: .action) - try container.encode(target, forKey: .target) - try container.encode(label, forKey: .label) - case .postRedirect(let target, let label): - try container.encode("post_redirect", forKey: .action) - try container.encode(target, forKey: .target) - try container.encode(label, forKey: .label) - } - } -} - -public struct OpenFrameImage: Codable { - let content: String - let aspectRatio: AspectRatio? - let alt: String? -} - -public enum AspectRatio: String, Codable { - case ratio_1_91_1 = "1.91.1" - case ratio_1_1 = "1:1" -} - -public struct TextInput: Codable { - let content: String -} - -struct OpenFrameResult: Codable { - let acceptedClients: AcceptedFrameClients - let image: OpenFrameImage - let postUrl: String? - let textInput: TextInput? - let buttons: [String: OpenFrameButton]? - let ogImage: String - let state: String? -}; - -public struct GetMetadataResponse: Codable { - let url: String - public let extractedTags: [String: String] -} - -public struct PostRedirectResponse: Codable { - let originalUrl: String - let redirectedTo: String -}; - -public struct OpenFramesUntrustedData: Codable { - let url: String - let timestamp: Int - let buttonIndex: Int - let inputText: String? - let state: String? -} - -public typealias FramesApiRedirectResponse = PostRedirectResponse; - -public struct FramePostUntrustedData: Codable { - let url: String - let timestamp: UInt64 - let buttonIndex: Int32 - let inputText: String? - let state: String? - let walletAddress: String - let opaqueConversationIdentifier: String - let unixTimestamp: UInt32 -} - -public struct FramePostTrustedData: Codable { - let messageBytes: String -} - -public struct FramePostPayload: Codable { - let clientProtocol: String - let untrustedData: FramePostUntrustedData - let trustedData: FramePostTrustedData -} - -public struct DmActionInputs: Codable { - public let conversationTopic: String? - public let participantAccountAddresses: [String] - public init(conversationTopic: String? = nil, participantAccountAddresses: [String]) { - self.conversationTopic = conversationTopic - self.participantAccountAddresses = participantAccountAddresses - } -} - -public struct GroupActionInputs: Codable { - let groupId: Data - let groupSecret: Data -} - -public enum ConversationActionInputs: Codable { - case dm(DmActionInputs) - case group(GroupActionInputs) -} - -public struct FrameActionInputs: Codable { - let frameUrl: String - let buttonIndex: Int32 - let inputText: String? - let state: String? - let conversationInputs: ConversationActionInputs - public init(frameUrl: String, buttonIndex: Int32, inputText: String?, state: String?, conversationInputs: ConversationActionInputs) { - self.frameUrl = frameUrl - self.buttonIndex = buttonIndex - self.inputText = inputText - self.state = state - self.conversationInputs = conversationInputs - } -} - diff --git a/Sources/XMTPiOS/Frames/OpenFramesProxy.swift b/Sources/XMTPiOS/Frames/OpenFramesProxy.swift deleted file mode 100644 index 7f00c07b..00000000 --- a/Sources/XMTPiOS/Frames/OpenFramesProxy.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// File.swift -// -// -// Created by Alex Risch on 3/28/24. -// - -import Foundation - -public class OpenFramesProxy { - let inner: ProxyClient - - init(baseUrl: String = OPEN_FRAMES_PROXY_URL) { - self.inner = ProxyClient(baseUrl: baseUrl); - } - - public func readMetadata(url: String) async throws -> GetMetadataResponse { - return try await self.inner.readMetadata(url: url); - } - - public func post(url: String, payload: FramePostPayload) async throws -> GetMetadataResponse { - return try await self.inner.post(url: url, payload: payload); - } - - public func postRedirect( - url: String, - payload: FramePostPayload - ) async throws -> FramesApiRedirectResponse { - return try await self.inner.postRedirect(url: url, payload: payload); - } - - public func mediaUrl(url: String) async throws -> String { - if url.hasPrefix("data:") { - return url - } - return self.inner.mediaUrl(url: url); - } -} diff --git a/Sources/XMTPiOS/Frames/ProxyClient.swift b/Sources/XMTPiOS/Frames/ProxyClient.swift deleted file mode 100644 index 6a7330b1..00000000 --- a/Sources/XMTPiOS/Frames/ProxyClient.swift +++ /dev/null @@ -1,97 +0,0 @@ -// -// File.swift -// -// -// Created by Alex Risch on 3/28/24. -// - -import Foundation - -struct Metadata: Codable { - let title: String - let description: String - let imageUrl: String -} - -class ProxyClient { - var baseUrl: String - - init(baseUrl: String) { - self.baseUrl = baseUrl - } - - func readMetadata(url: String) async throws -> GetMetadataResponse { - let encodedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" - let fullUrl = "\(self.baseUrl)?url=\(encodedUrl)" - guard let url = URL(string: fullUrl) else { - throw URLError(.badURL) - } - - let (data, response) = try await URLSession.shared.data(from: url) - guard let httpResponse = response as? HTTPURLResponse else { - throw URLError(.badServerResponse) - } - - guard httpResponse.statusCode == 200 else { - throw FramesClientError.readMetadataFailed(message: "Failed to read metadata for \(url)", code: httpResponse.statusCode) - } - - let decoder = JSONDecoder() - let metadataResponse: GetMetadataResponse = try decoder.decode(GetMetadataResponse.self, from: data) - return metadataResponse - } - - func post(url: String, payload: Codable) async throws -> GetMetadataResponse { - let encodedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" - let fullUrl = "\(self.baseUrl)?url=\(encodedUrl)" - guard let url = URL(string: fullUrl) else { - throw URLError(.badURL) - } - let encoder = JSONEncoder() - var request = URLRequest(url: url) - request.httpMethod = "POST" - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - request.httpBody = try encoder.encode(payload) - - let (data, response) = try await URLSession.shared.data(for: request) - guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { - throw URLError(.badServerResponse) - } - - let decoder = JSONDecoder() - let metadataResponse = try decoder.decode(GetMetadataResponse.self, from: data) - return metadataResponse - } - - func postRedirect(url: String, payload: Codable) async throws -> PostRedirectResponse { - let encodedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" - let fullUrl = "\(self.baseUrl)redirect?url=\(encodedUrl)" - guard let url = URL(string: fullUrl) else { - throw URLError(.badURL) - } - - var request = URLRequest(url: url) - request.httpMethod = "POST" - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - request.httpBody = try JSONSerialization.data(withJSONObject: payload) - - let (data, response) = try await URLSession.shared.data(for: request) - guard let httpResponse = response as? HTTPURLResponse else { - throw URLError(.badServerResponse) - } - - guard httpResponse.statusCode == 200 else { - throw FramesClientError.postFrameFailed(message: "Failed to post to frame \(url)", code: httpResponse.statusCode) - } - - let decoder = JSONDecoder() - let postRedirectResponse = try decoder.decode(PostRedirectResponse.self, from: data) - return postRedirectResponse - } - - func mediaUrl(url: String) -> String { - let encodedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" - let result = "\(self.baseUrl)media?url=\(encodedUrl)" - return result - } -}