diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index ed97b9513..d019e26a1 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -415,7 +415,7 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (0.5.8-alpha0): + - XMTP (0.5.10-alpha0): - Connect-Swift - GzipSwift - web3.swift @@ -423,7 +423,7 @@ PODS: - XMTPReactNative (0.1.0): - ExpoModulesCore - MessagePacker - - XMTP (= 0.5.8-alpha0) + - XMTP (= 0.5.10-alpha0) - XMTPRust (0.3.1-beta0) - Yoga (1.14.0) @@ -680,11 +680,11 @@ SPEC CHECKSUMS: secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: b70d65f419fbfe61a2d58003456ca5da58e337d6 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: 381e951a5f74ba9751504b50da3bad8c2ab89a20 - XMTPReactNative: 2c4fa8f24957002cfef22b73ff58fb8f08c47cd2 + XMTP: 12d883817894219f263e07cfb768418d8d0eb616 + XMTPReactNative: 5aa3b4be4ed1c501bd1a30ab6ac4297665e836d5 XMTPRust: 78f65f77b1454392980da244961777aee955652f Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556 PODFILE CHECKSUM: 522d88edc2d5fac4825e60a121c24abc18983367 -COCOAPODS: 1.11.3 +COCOAPODS: 1.12.1 diff --git a/ios/Wrappers/DecodedMessageWrapper.swift b/ios/Wrappers/DecodedMessageWrapper.swift index d694df559..41e26429c 100644 --- a/ios/Wrappers/DecodedMessageWrapper.swift +++ b/ios/Wrappers/DecodedMessageWrapper.swift @@ -5,13 +5,13 @@ import XMTP // into react native. struct DecodedMessageWrapper { static func encodeToObj(_ model: XMTP.DecodedMessage) throws -> [String: Any] { - return [ + return try [ "id": model.id, "topic": model.topic, "contentTypeId": model.encodedContent.type.description, - "content": try ContentJson.fromEncoded(model.encodedContent).toJsonMap() as Any, + "content": ContentJson.fromEncoded(model.encodedContent, client: model.client).toJsonMap() as Any, "senderAddress": model.senderAddress, - "sent": UInt64(model.sent.timeIntervalSince1970 * 1000) + "sent": UInt64(model.sent.timeIntervalSince1970 * 1000), ] } @@ -38,21 +38,21 @@ struct ContentJson { AttachmentCodec(), ReplyCodec(), RemoteAttachmentCodec(), - ReadReceiptCodec() + ReadReceiptCodec(), // TODO: - //CompositeCodec(), + // CompositeCodec(), ] - static func initCodecs() -> Void { - codecs.forEach { codec in Client.register(codec: codec) } + static func initCodecs(client: Client) { + codecs.forEach { codec in client.register(codec: codec) } } enum Error: Swift.Error { case unknownContentType, badAttachmentData, badReplyContent, badRemoteAttachmentMetadata } - static func fromEncoded(_ encoded: XMTP.EncodedContent) throws -> ContentJson { - return ContentJson(type: encoded.type, content: try encoded.decoded()) + static func fromEncoded(_ encoded: XMTP.EncodedContent, client: Client) throws -> ContentJson { + return try ContentJson(type: encoded.type, content: encoded.decoded(with: client)) } static func fromJsonObj(_ obj: [String: Any]) throws -> ContentJson { @@ -60,10 +60,10 @@ struct ContentJson { return ContentJson(type: ContentTypeText, content: text) } else if let reaction = obj["reaction"] as? [String: Any] { return ContentJson(type: ContentTypeReaction, content: Reaction( - reference: reaction["reference"] as? String ?? "", - action: ReactionAction(rawValue: reaction["action"] as? String ?? "") , - content: reaction["content"] as? String ?? "", - schema: ReactionSchema(rawValue: reaction["schema"] as? String ?? "") + reference: reaction["reference"] as? String ?? "", + action: ReactionAction(rawValue: reaction["action"] as? String ?? ""), + content: reaction["content"] as? String ?? "", + schema: ReactionSchema(rawValue: reaction["schema"] as? String ?? "") )) } else if let reply = obj["reply"] as? [String: Any] { guard let nestedContent = reply["content"] as? [String: Any] else { @@ -73,32 +73,32 @@ struct ContentJson { throw Error.badReplyContent } return ContentJson(type: ContentTypeReply, content: Reply( - reference: reply["reference"] as? String ?? "", - content: nested.content, - contentType: nested.type + reference: reply["reference"] as? String ?? "", + content: nested.content, + contentType: nested.type )) } else if let attachment = obj["attachment"] as? [String: Any] { guard let data = Data(base64Encoded: (attachment["data"] as? String) ?? "") else { throw Error.badAttachmentData } return ContentJson(type: ContentTypeAttachment, content: Attachment( - filename: attachment["filename"] as? String ?? "", - mimeType: attachment["mimeType"] as? String ?? "", - data: data + filename: attachment["filename"] as? String ?? "", + mimeType: attachment["mimeType"] as? String ?? "", + data: data )) } else if let remoteAttachment = obj["remoteAttachment"] as? [String: Any] { guard let metadata = try? EncryptedAttachmentMetadata.fromJsonObj(remoteAttachment) else { throw Error.badRemoteAttachmentMetadata } guard var content = try? RemoteAttachment( - url: remoteAttachment["url"] as? String ?? "", - contentDigest: metadata.contentDigest, - secret: metadata.secret, - salt: metadata.salt, - nonce: metadata.nonce, - scheme: RemoteAttachment.Scheme.https + url: remoteAttachment["url"] as? String ?? "", + contentDigest: metadata.contentDigest, + secret: metadata.secret, + salt: metadata.salt, + nonce: metadata.nonce, + scheme: RemoteAttachment.Scheme.https ) else { - throw Error.badRemoteAttachmentMetadata + throw Error.badRemoteAttachmentMetadata } content.filename = metadata.filename content.contentLength = metadata.contentLength @@ -126,21 +126,21 @@ struct ContentJson { "reference": reaction.reference, "action": reaction.action.rawValue, "schema": reaction.schema.rawValue, - "content": reaction.content - ]] + "content": reaction.content, + ]] case ContentTypeReply.id where content is XMTP.Reply: let reply = content as! XMTP.Reply let nested = ContentJson(type: reply.contentType, content: reply.content) return ["reply": [ "reference": reply.reference, - "content": nested.toJsonMap() - ] as [String : Any]] + "content": nested.toJsonMap(), + ] as [String: Any]] case ContentTypeAttachment.id where content is XMTP.Attachment: let attachment = content as! XMTP.Attachment return ["attachment": [ "filename": attachment.filename, "mimeType": attachment.mimeType, - "data": attachment.data.base64EncodedString() + "data": attachment.data.base64EncodedString(), ]] case ContentTypeRemoteAttachment.id where content is XMTP.RemoteAttachment: let remoteAttachment = content as! XMTP.RemoteAttachment @@ -152,7 +152,7 @@ struct ContentJson { "contentDigest": remoteAttachment.contentDigest, "contentLength": String(remoteAttachment.contentLength ?? 0), "scheme": "https://", - "url": remoteAttachment.url + "url": remoteAttachment.url, ]] case ContentTypeReadReceipt.id where content is XMTP.ReadReceipt: return ["readReceipt": ""] @@ -175,14 +175,15 @@ struct EncryptedAttachmentMetadata { } static func fromAttachment(attachment: XMTP.Attachment, - encrypted: XMTP.EncryptedEncodedContent) throws -> EncryptedAttachmentMetadata { + encrypted: XMTP.EncryptedEncodedContent) throws -> EncryptedAttachmentMetadata + { return EncryptedAttachmentMetadata( - filename: attachment.filename, - secret: encrypted.secret, - salt: encrypted.salt, - nonce: encrypted.nonce, - contentDigest: encrypted.digest, - contentLength: attachment.data.count + filename: attachment.filename, + secret: encrypted.secret, + salt: encrypted.salt, + nonce: encrypted.nonce, + contentDigest: encrypted.digest, + contentLength: attachment.data.count ) } @@ -197,12 +198,12 @@ struct EncryptedAttachmentMetadata { throw Error.badRemoteAttachmentMetadata } return EncryptedAttachmentMetadata( - filename: obj["filename"] as? String ?? "", - secret: secret, - salt: salt, - nonce: nonce, - contentDigest: obj["contentDigest"] as? String ?? "", - contentLength: Int(obj["contentLength"] as? String ?? "") ?? 0 + filename: obj["filename"] as? String ?? "", + secret: secret, + salt: salt, + nonce: nonce, + contentDigest: obj["contentDigest"] as? String ?? "", + contentLength: Int(obj["contentLength"] as? String ?? "") ?? 0 ) } @@ -213,10 +214,9 @@ struct EncryptedAttachmentMetadata { "salt": salt.toHex, "nonce": nonce.toHex, "contentDigest": contentDigest, - "contentLength": String(contentLength) + "contentLength": String(contentLength), ] } - } struct EncryptedLocalAttachment { @@ -226,56 +226,58 @@ struct EncryptedLocalAttachment { static func from(attachment: XMTP.Attachment, encrypted: XMTP.EncryptedEncodedContent, encryptedFile: URL) - throws -> EncryptedLocalAttachment { - return EncryptedLocalAttachment( - encryptedLocalFileUri: encryptedFile.absoluteString, - metadata: try EncryptedAttachmentMetadata.fromAttachment( - attachment: attachment, - encrypted: encrypted - )) + throws -> EncryptedLocalAttachment + { + return try EncryptedLocalAttachment( + encryptedLocalFileUri: encryptedFile.absoluteString, + metadata: EncryptedAttachmentMetadata.fromAttachment( + attachment: attachment, + encrypted: encrypted + ) + ) } static func fromJson(_ json: String) throws -> EncryptedLocalAttachment { let data = json.data(using: .utf8)! let obj = (try? JSONSerialization.jsonObject(with: data) as? [String: Any]) ?? [:] - return EncryptedLocalAttachment( + return try EncryptedLocalAttachment( encryptedLocalFileUri: obj["encryptedLocalFileUri"] as? String ?? "", - metadata: try EncryptedAttachmentMetadata.fromJsonObj(obj["metadata"] as? [String: Any] ?? [:]) + metadata: EncryptedAttachmentMetadata.fromJsonObj(obj["metadata"] as? [String: Any] ?? [:]) ) } func toJson() throws -> String { let obj: [String: Any] = [ "encryptedLocalFileUri": encryptedLocalFileUri, - "metadata": metadata.toJsonMap() + "metadata": metadata.toJsonMap(), ] return try obj.toJson() } } struct DecryptedLocalAttachment { - var fileUri: String - var mimeType: String - var filename: String + var fileUri: String + var mimeType: String + var filename: String - static func fromJson(_ json: String) throws -> DecryptedLocalAttachment { - let data = json.data(using: .utf8)! - let obj = (try? JSONSerialization.jsonObject(with: data) as? [String: Any]) ?? [:] - return DecryptedLocalAttachment( - fileUri: obj["fileUri"] as? String ?? "", - mimeType: obj["mimeType"] as? String ?? "", - filename: obj["filename"] as? String ?? "" - ) - } + static func fromJson(_ json: String) throws -> DecryptedLocalAttachment { + let data = json.data(using: .utf8)! + let obj = (try? JSONSerialization.jsonObject(with: data) as? [String: Any]) ?? [:] + return DecryptedLocalAttachment( + fileUri: obj["fileUri"] as? String ?? "", + mimeType: obj["mimeType"] as? String ?? "", + filename: obj["filename"] as? String ?? "" + ) + } - func toJson() throws -> String { - let obj: [String: Any] = [ - "fileUri": fileUri, - "mimeType": mimeType, - "filename": filename - ] - return try obj.toJson() - } + func toJson() throws -> String { + let obj: [String: Any] = [ + "fileUri": fileUri, + "mimeType": mimeType, + "filename": filename, + ] + return try obj.toJson() + } } struct PreparedLocalMessage { @@ -287,19 +289,19 @@ struct PreparedLocalMessage { let data = json.data(using: .utf8)! let obj = (try? JSONSerialization.jsonObject(with: data) as? [String: Any]) ?? [:] return PreparedLocalMessage( - messageId: obj["messageId"] as? String ?? "", - preparedFileUri: obj["preparedFileUri"] as? String ?? "", - preparedAt: UInt64(truncating: obj["preparedAt"] as? NSNumber ?? 0) + messageId: obj["messageId"] as? String ?? "", + preparedFileUri: obj["preparedFileUri"] as? String ?? "", + preparedAt: UInt64(truncating: obj["preparedAt"] as? NSNumber ?? 0) ) } func toJson() throws -> String { - let obj: [String: Any] = [ - "messageId": messageId, - "preparedFileUri": preparedFileUri, - "preparedAt": preparedAt - ] - return try obj.toJson() + let obj: [String: Any] = [ + "messageId": messageId, + "preparedFileUri": preparedFileUri, + "preparedAt": preparedAt, + ] + return try obj.toJson() } } diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 17234acc5..30df006fe 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -40,7 +40,7 @@ class ReactNativeSigner: NSObject, XMTP.SigningKey { module.sendEvent("sign", [ "id": request.id, - "message": request.message + "message": request.message, ]) return try await withCheckedThrowingContinuation { continuation in @@ -59,10 +59,9 @@ struct SignatureRequest: Codable { } extension Conversation { - static func cacheKeyForTopic(clientAddress: String, topic: String) -> String { - return "\(clientAddress):\(topic)" - } + return "\(clientAddress):\(topic)" + } func cacheKey(_ clientAddress: String) -> String { return Conversation.cacheKeyForTopic(clientAddress: clientAddress, topic: topic) @@ -74,12 +73,16 @@ public class XMTPModule: Module { let clientsManager = ClientsManager() let conversationsManager = ConversationsManager() let subscriptionsManager = SubscriptionsManager() - + actor ClientsManager { private var clients: [String: XMTP.Client] = [:] // A method to update the conversations func updateClient(key: String, client: XMTP.Client?) { + if clients[key] == nil, let client { + ContentJson.initCodecs(client: client) + } + clients[key] = client } @@ -88,7 +91,7 @@ public class XMTPModule: Module { return clients[key] } } - + actor ConversationsManager { private var conversations: [String: Conversation] = [:] @@ -102,7 +105,7 @@ public class XMTPModule: Module { return conversations[key] } } - + actor SubscriptionsManager { private var subscriptions: [String: Task] = [:] @@ -119,32 +122,31 @@ public class XMTPModule: Module { enum Error: Swift.Error { case noClient, conversationNotFound(String), noMessage, invalidKeyBundle, invalidDigest, badPreparation(String) - } public func definition() -> ModuleDefinition { - Name("XMTP") + Name("XMTP") - Events("sign", "authed", "conversation", "message") + Events("sign", "authed", "conversation", "message") AsyncFunction("address") { (clientAddress: String) -> String in if let client = await clientsManager.getClient(key: clientAddress) { - return client.address - } else { - return "No Client." - } + return client.address + } else { + return "No Client." + } } // // Auth functions // AsyncFunction("auth") { (address: String, environment: String, appVersion: String?) in - let signer = ReactNativeSigner(module: self, address: address) - self.signer = signer - let options = createClientConfig(env: environment, appVersion: appVersion) - await clientsManager.updateClient(key: address, client: try await XMTP.Client.create(account: signer, options: options)) - self.signer = nil - sendEvent("authed") + let signer = ReactNativeSigner(module: self, address: address) + self.signer = signer + let options = createClientConfig(env: environment, appVersion: appVersion) + try await clientsManager.updateClient(key: address, client: await XMTP.Client.create(account: signer, options: options)) + self.signer = nil + sendEvent("authed") } Function("receiveSignature") { (requestID: String, signature: String) in @@ -157,7 +159,7 @@ public class XMTPModule: Module { let options = createClientConfig(env: environment, appVersion: appVersion) let client = try await Client.create(account: privateKey, options: options) - await clientsManager.updateClient(key: client.address, client: client) + await clientsManager.updateClient(key: client.address, client: client) return client.address } @@ -165,13 +167,14 @@ public class XMTPModule: Module { AsyncFunction("createFromKeyBundle") { (keyBundle: String, environment: String, appVersion: String?) -> String in do { guard let keyBundleData = Data(base64Encoded: keyBundle), - let bundle = try? PrivateKeyBundle(serializedData: keyBundleData) else { + let bundle = try? PrivateKeyBundle(serializedData: keyBundleData) + else { throw Error.invalidKeyBundle } let options = createClientConfig(env: environment, appVersion: appVersion) let client = try await Client.from(bundle: bundle, options: options) - await clientsManager.updateClient(key: client.address, client: client) + await clientsManager.updateClient(key: client.address, client: client) return client.address } catch { print("ERRO! Failed to create client: \(error)") @@ -220,7 +223,7 @@ public class XMTPModule: Module { } AsyncFunction("encryptAttachment") { (clientAddress: String, fileJson: String) -> String in - if await clientsManager.getClient(key: clientAddress) == nil { + guard let client = await clientsManager.getClient(key: clientAddress) else { throw Error.noClient } let file = try DecryptedLocalAttachment.fromJson(fileJson) @@ -233,7 +236,8 @@ public class XMTPModule: Module { ) let encrypted = try RemoteAttachment.encodeEncrypted( content: attachment, - codec: AttachmentCodec() + codec: AttachmentCodec(), + with: client ) let encryptedFile = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString) try encrypted.payload.write(to: encryptedFile) @@ -246,7 +250,7 @@ public class XMTPModule: Module { } AsyncFunction("decryptAttachment") { (clientAddress: String, encryptedFileJson: String) -> String in - if await clientsManager.getClient(key: clientAddress) == nil { + guard let client = await clientsManager.getClient(key: clientAddress) else { throw Error.noClient } let encryptedFile = try EncryptedLocalAttachment.fromJson(encryptedFileJson) @@ -260,13 +264,13 @@ public class XMTPModule: Module { payload: encryptedData ) let encoded = try RemoteAttachment.decryptEncoded(encrypted: encrypted) - let attachment: Attachment = try encoded.decoded() + let attachment: Attachment = try encoded.decoded(with: client) let file = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString) try attachment.data.write(to: file) return try DecryptedLocalAttachment( - fileUri: file.absoluteString, - mimeType: attachment.mimeType, - filename: attachment.filename + fileUri: file.absoluteString, + mimeType: attachment.mimeType, + filename: attachment.filename ).toJson() } @@ -276,7 +280,7 @@ public class XMTPModule: Module { } let conversations = try await client.conversations.list() - + return try await withThrowingTaskGroup(of: String.self) { group in for conversation in conversations { group.addTask { @@ -284,19 +288,19 @@ public class XMTPModule: Module { return try await ConversationWrapper.encode(conversation, client: client) } } - + var results: [String] = [] for try await result in group { results.append(result) } - + return results } } AsyncFunction("loadMessages") { (clientAddress: String, topic: String, limit: Int?, before: Double?, after: Double?, direction: String?) -> [String] in - let beforeDate = before != nil ? Date(timeIntervalSince1970: TimeInterval(before!)/1000) : nil - let afterDate = after != nil ? Date(timeIntervalSince1970: TimeInterval(after!)/1000) : nil + let beforeDate = before != nil ? Date(timeIntervalSince1970: TimeInterval(before!) / 1000) : nil + let afterDate = after != nil ? Date(timeIntervalSince1970: TimeInterval(after!) / 1000) : nil guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { throw Error.conversationNotFound("no conversation found for \(topic)") @@ -311,7 +315,7 @@ public class XMTPModule: Module { direction: PagingInfoSortDirection(rawValue: sortDirection) ) - return decodedMessages.compactMap { (msg) in + return decodedMessages.compactMap { msg in do { return try DecodedMessageWrapper.encode(msg) } catch { @@ -321,7 +325,7 @@ public class XMTPModule: Module { } } - AsyncFunction("loadBatchMessages") { (clientAddress: String, topics: [String]) -> [String] in + AsyncFunction("loadBatchMessages") { (clientAddress: String, topics: [String]) -> [String] in guard let client = await clientsManager.getClient(key: clientAddress) else { throw Error.noClient } @@ -330,7 +334,8 @@ public class XMTPModule: Module { topics.forEach { topicJSON in let jsonData = topicJSON.data(using: .utf8)! guard let jsonObj = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any], - let topic = jsonObj["topic"] as? String else { + let topic = jsonObj["topic"] as? String + else { return // Skip this topic if it doesn't have valid JSON data or missing "topic" field } @@ -344,13 +349,13 @@ public class XMTPModule: Module { } if let beforeInt = jsonObj["before"] as? Double { - before = TimeInterval(beforeInt/1000) + before = TimeInterval(beforeInt / 1000) } if let afterInt = jsonObj["after"] as? Double { - after = TimeInterval(afterInt/1000) + after = TimeInterval(afterInt / 1000) } - + if let directionStr = jsonObj["direction"] as? String { let sortDirection: Int = (directionStr == "SORT_DIRECTION_ASCENDING") ? 1 : 2 direction = PagingInfoSortDirection(rawValue: sortDirection) ?? .descending @@ -368,7 +373,7 @@ public class XMTPModule: Module { let decodedMessages = try await client.conversations.listBatchMessages(topics: topicsList) - return decodedMessages.compactMap { (msg) in + return decodedMessages.compactMap { msg in do { return try DecodedMessageWrapper.encode(msg) } catch { @@ -499,7 +504,7 @@ public class XMTPModule: Module { } AsyncFunction("decodeMessage") { (clientAddress: String, topic: String, encryptedMessage: String) -> String in - guard let encryptedMessageData = Data(base64Encoded: Data(encryptedMessage.utf8))else { + guard let encryptedMessageData = Data(base64Encoded: Data(encryptedMessage.utf8)) else { throw Error.noMessage } @@ -514,7 +519,7 @@ public class XMTPModule: Module { let decodedMessage = try conversation.decode(envelope) return try DecodedMessageWrapper.encode(decodedMessage) } - } + } // // Helpers @@ -522,26 +527,25 @@ public class XMTPModule: Module { func createClientConfig(env: String, appVersion: String?) -> XMTP.ClientOptions { // Ensure that all codecs have been registered. - ContentJson.initCodecs(); switch env { - case "local": - return XMTP.ClientOptions(api: XMTP.ClientOptions.Api( - env: XMTP.XMTPEnvironment.local, - isSecure: false, - appVersion: appVersion - )) - case "production": - return XMTP.ClientOptions(api: XMTP.ClientOptions.Api( - env: XMTP.XMTPEnvironment.production, - isSecure: true, - appVersion: appVersion - )) - default: - return XMTP.ClientOptions(api: XMTP.ClientOptions.Api( - env: XMTP.XMTPEnvironment.dev, - isSecure: true, - appVersion: appVersion - )) + case "local": + return XMTP.ClientOptions(api: XMTP.ClientOptions.Api( + env: XMTP.XMTPEnvironment.local, + isSecure: false, + appVersion: appVersion + )) + case "production": + return XMTP.ClientOptions(api: XMTP.ClientOptions.Api( + env: XMTP.XMTPEnvironment.production, + isSecure: true, + appVersion: appVersion + )) + default: + return XMTP.ClientOptions(api: XMTP.ClientOptions.Api( + env: XMTP.XMTPEnvironment.dev, + isSecure: true, + appVersion: appVersion + )) } } @@ -570,9 +574,9 @@ public class XMTPModule: Module { await subscriptionsManager.updateSubscription(key: "conversations", task: Task { do { for try await conversation in try await client.conversations.stream() { - sendEvent("conversation", [ + try sendEvent("conversation", [ "clientAddress": clientAddress, - "conversation": try ConversationWrapper.encodeToObj(conversation, client: client) + "conversation": ConversationWrapper.encodeToObj(conversation, client: client), ]) } } catch { @@ -592,9 +596,9 @@ public class XMTPModule: Module { do { for try await message in try await client.conversations.streamAllMessages() { do { - sendEvent("message", [ + try sendEvent("message", [ "clientAddress": clientAddress, - "message": try DecodedMessageWrapper.encodeToObj(message) + "message": DecodedMessageWrapper.encodeToObj(message), ]) } catch { print("discarding message, unable to encode wrapper \(message.id)") @@ -617,9 +621,9 @@ public class XMTPModule: Module { do { for try await message in conversation.streamMessages() { do { - sendEvent("message", [ + try sendEvent("message", [ "clientAddress": clientAddress, - "message": try DecodedMessageWrapper.encodeToObj(message) + "message": DecodedMessageWrapper.encodeToObj(message), ]) } catch { print("discarding message, unable to encode wrapper \(message.id)") diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 50e5f6745..760613c9d 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -25,5 +25,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.5.9-alpha0" + s.dependency "XMTP", "= 0.5.10-alpha0" end