diff --git a/android/build.gradle b/android/build.gradle index d62d2555e..df5fa58bd 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -88,6 +88,6 @@ repositories { dependencies { implementation project(':expo-modules-core') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}" - implementation "org.xmtp:android:0.2.0" + implementation "org.xmtp:android:0.3.0" implementation 'com.google.code.gson:gson:2.10.1' } diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index 841e9a856..c5dcf90e8 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -25,6 +25,7 @@ import org.xmtp.android.library.messages.InvitationV1ContextBuilder import org.xmtp.android.library.messages.PrivateKeyBuilder import org.xmtp.android.library.messages.Signature import org.xmtp.android.library.push.XMTPPush +import org.xmtp.proto.keystore.api.v1.Keystore.TopicMap.TopicData import org.xmtp.proto.message.contents.SignatureOuterClass import org.xmtp.proto.message.contents.PrivateKeyOuterClass import java.util.Date @@ -72,11 +73,7 @@ data class SignatureRequest( ) fun Conversation.cacheKey(clientAddress: String): String { - return if (conversationId != "") { - "${clientAddress}:${topic}:${conversationId}" - } else { - "${clientAddress}:${topic}" - } + return "${clientAddress}:${topic}" } class XMTPModule : Module() { @@ -150,6 +147,25 @@ class XMTPModule : Module() { Base64.encodeToString(client.privateKeyBundle.toByteArray(), NO_WRAP) } + // Export the conversation's serialized topic data. + AsyncFunction("exportConversationTopicData") { clientAddress: String, topic: String -> + logV("exportConversationTopicData") + val client = clients[clientAddress] ?: throw XMTPException("No client") + val conversation = findConversation(clientAddress, topic) + ?: throw XMTPException("no conversation found for $topic") + Base64.encodeToString(conversation.toTopicData().toByteArray(), NO_WRAP) + } + + // Import a conversation from its serialized topic data. + AsyncFunction("importConversationTopicData") { clientAddress: String, topicData: String -> + logV("importConversationTopicData") + val client = clients[clientAddress] ?: throw XMTPException("No client") + val data = TopicData.parseFrom(Base64.decode(topicData, NO_WRAP)) + val conversation = client.conversations.importTopicData(data) + conversations[conversation.cacheKey(clientAddress)] = conversation + ConversationWrapper.encode(ConversationWithClientAddress(client, conversation)) + } + // // Client API AsyncFunction("canMessage") { clientAddress: String, peerAddress: String -> @@ -186,8 +202,7 @@ class XMTPModule : Module() { val conversation = findConversation( clientAddress = clientAddress, - topic = conversationTopic, - conversationId = conversationID + topic = conversationTopic ) ?: throw XMTPException("no conversation found for $conversationTopic") val preparedMessage = conversation.prepareMessage(content = content) @@ -260,8 +275,7 @@ class XMTPModule : Module() { val conversation = findConversation( clientAddress = clientAddress, - topic = topic, - conversationId = conversationID + topic = topic ) ?: throw XMTPException("no conversation found for $topic") val decodedMessage = conversation.decode(envelope) @@ -275,22 +289,16 @@ class XMTPModule : Module() { private fun findConversation( clientAddress: String, topic: String, - conversationId: String?, ): Conversation? { val client = clients[clientAddress] ?: throw XMTPException("No client") - val cacheKey: String = if (!conversationId.isNullOrBlank()) { - "${clientAddress}:${topic}:${conversationId}" - } else { - "${clientAddress}:${topic}" - } - + val cacheKey = "${clientAddress}:${topic}" val cacheConversation = conversations[cacheKey] if (cacheConversation != null) { return cacheConversation } else { val conversation = client.conversations.list() - .firstOrNull { it.topic == topic && it.conversationId == conversationId } + .firstOrNull { it.topic == topic } if (conversation != null) { conversations[conversation.cacheKey(clientAddress)] = conversation return conversation @@ -349,8 +357,7 @@ class XMTPModule : Module() { val conversation = findConversation( clientAddress = clientAddress, - topic = topic, - conversationId = conversationId + topic = topic ) ?: return subscriptions[conversation.cacheKey(clientAddress)] = CoroutineScope(Dispatchers.IO).launch { @@ -380,8 +387,7 @@ class XMTPModule : Module() { val conversation = findConversation( clientAddress = clientAddress, - topic = topic, - conversationId = conversationId + topic = topic ) ?: return subscriptions[conversation.cacheKey(clientAddress)]?.cancel() } diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index f5710113f..1cde23f59 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -18,31 +18,31 @@ PODS: - ExpoModulesCore - EXFont (11.1.1): - ExpoModulesCore - - Expo (48.0.11): + - Expo (48.0.17): - ExpoModulesCore - ExpoKeepAwake (12.0.1): - ExpoModulesCore - - ExpoModulesCore (1.2.6): + - ExpoModulesCore (1.2.7): - React-Core - React-RCTAppDelegate - ReactCommon/turbomodule/core - EXSecureStore (12.1.1): - ExpoModulesCore - - FBLazyVector (0.71.6) - - FBReactNativeSpec (0.71.6): + - FBLazyVector (0.71.8) + - FBReactNativeSpec (0.71.8): - RCT-Folly (= 2021.07.22.00) - - RCTRequired (= 0.71.6) - - RCTTypeSafety (= 0.71.6) - - React-Core (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) + - RCTRequired (= 0.71.8) + - RCTTypeSafety (= 0.71.8) + - React-Core (= 0.71.8) + - React-jsi (= 0.71.8) + - ReactCommon/turbomodule/core (= 0.71.8) - fmt (6.2.1) - GenericJSON (2.0.2) - glog (0.3.5) - GzipSwift (5.1.1) - - hermes-engine (0.71.6): - - hermes-engine/Pre-built (= 0.71.6) - - hermes-engine/Pre-built (0.71.6) + - hermes-engine (0.71.8): + - hermes-engine/Pre-built (= 0.71.8) + - hermes-engine/Pre-built (0.71.8) - libevent (2.1.12) - Logging (1.0.0) - MMKV (1.3.0): @@ -65,26 +65,26 @@ PODS: - fmt (~> 6.2.1) - glog - libevent - - RCTRequired (0.71.6) - - RCTTypeSafety (0.71.6): - - FBLazyVector (= 0.71.6) - - RCTRequired (= 0.71.6) - - React-Core (= 0.71.6) - - React (0.71.6): - - React-Core (= 0.71.6) - - React-Core/DevSupport (= 0.71.6) - - React-Core/RCTWebSocket (= 0.71.6) - - React-RCTActionSheet (= 0.71.6) - - React-RCTAnimation (= 0.71.6) - - React-RCTBlob (= 0.71.6) - - React-RCTImage (= 0.71.6) - - React-RCTLinking (= 0.71.6) - - React-RCTNetwork (= 0.71.6) - - React-RCTSettings (= 0.71.6) - - React-RCTText (= 0.71.6) - - React-RCTVibration (= 0.71.6) - - React-callinvoker (0.71.6) - - React-Codegen (0.71.6): + - RCTRequired (0.71.8) + - RCTTypeSafety (0.71.8): + - FBLazyVector (= 0.71.8) + - RCTRequired (= 0.71.8) + - React-Core (= 0.71.8) + - React (0.71.8): + - React-Core (= 0.71.8) + - React-Core/DevSupport (= 0.71.8) + - React-Core/RCTWebSocket (= 0.71.8) + - React-RCTActionSheet (= 0.71.8) + - React-RCTAnimation (= 0.71.8) + - React-RCTBlob (= 0.71.8) + - React-RCTImage (= 0.71.8) + - React-RCTLinking (= 0.71.8) + - React-RCTNetwork (= 0.71.8) + - React-RCTSettings (= 0.71.8) + - React-RCTText (= 0.71.8) + - React-RCTVibration (= 0.71.8) + - React-callinvoker (0.71.8) + - React-Codegen (0.71.8): - FBReactNativeSpec - hermes-engine - RCT-Folly @@ -95,209 +95,209 @@ PODS: - React-jsiexecutor - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - React-Core (0.71.6): + - React-Core (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.6) - - React-cxxreact (= 0.71.6) + - React-Core/Default (= 0.71.8) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/CoreModulesHeaders (0.71.6): + - React-Core/CoreModulesHeaders (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/Default (0.71.6): + - React-Core/Default (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/DevSupport (0.71.6): + - React-Core/DevSupport (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.6) - - React-Core/RCTWebSocket (= 0.71.6) - - React-cxxreact (= 0.71.6) + - React-Core/Default (= 0.71.8) + - React-Core/RCTWebSocket (= 0.71.8) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-jsinspector (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-jsinspector (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/RCTActionSheetHeaders (0.71.6): + - React-Core/RCTActionSheetHeaders (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/RCTAnimationHeaders (0.71.6): + - React-Core/RCTAnimationHeaders (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/RCTBlobHeaders (0.71.6): + - React-Core/RCTBlobHeaders (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/RCTImageHeaders (0.71.6): + - React-Core/RCTImageHeaders (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/RCTLinkingHeaders (0.71.6): + - React-Core/RCTLinkingHeaders (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/RCTNetworkHeaders (0.71.6): + - React-Core/RCTNetworkHeaders (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/RCTSettingsHeaders (0.71.6): + - React-Core/RCTSettingsHeaders (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/RCTTextHeaders (0.71.6): + - React-Core/RCTTextHeaders (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/RCTVibrationHeaders (0.71.6): + - React-Core/RCTVibrationHeaders (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-Core/RCTWebSocket (0.71.6): + - React-Core/RCTWebSocket (0.71.8): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.6) - - React-cxxreact (= 0.71.6) + - React-Core/Default (= 0.71.8) + - React-cxxreact (= 0.71.8) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.8) + - React-jsiexecutor (= 0.71.8) + - React-perflogger (= 0.71.8) - Yoga - - React-CoreModules (0.71.6): + - React-CoreModules (0.71.8): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.6) - - React-Codegen (= 0.71.6) - - React-Core/CoreModulesHeaders (= 0.71.6) - - React-jsi (= 0.71.6) + - RCTTypeSafety (= 0.71.8) + - React-Codegen (= 0.71.8) + - React-Core/CoreModulesHeaders (= 0.71.8) + - React-jsi (= 0.71.8) - React-RCTBlob - - React-RCTImage (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-cxxreact (0.71.6): + - React-RCTImage (= 0.71.8) + - ReactCommon/turbomodule/core (= 0.71.8) + - React-cxxreact (0.71.8): - boost (= 1.76.0) - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.6) - - React-jsi (= 0.71.6) - - React-jsinspector (= 0.71.6) - - React-logger (= 0.71.6) - - React-perflogger (= 0.71.6) - - React-runtimeexecutor (= 0.71.6) - - React-hermes (0.71.6): + - React-callinvoker (= 0.71.8) + - React-jsi (= 0.71.8) + - React-jsinspector (= 0.71.8) + - React-logger (= 0.71.8) + - React-perflogger (= 0.71.8) + - React-runtimeexecutor (= 0.71.8) + - React-hermes (0.71.8): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - RCT-Folly/Futures (= 2021.07.22.00) - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.8) - React-jsi - - React-jsiexecutor (= 0.71.6) - - React-jsinspector (= 0.71.6) - - React-perflogger (= 0.71.6) - - React-jsi (0.71.6): + - React-jsiexecutor (= 0.71.8) + - React-jsinspector (= 0.71.8) + - React-perflogger (= 0.71.8) + - React-jsi (0.71.8): - boost (= 1.76.0) - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-jsiexecutor (0.71.6): + - React-jsiexecutor (0.71.8): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-cxxreact (= 0.71.6) - - React-jsi (= 0.71.6) - - React-perflogger (= 0.71.6) - - React-jsinspector (0.71.6) - - React-logger (0.71.6): + - React-cxxreact (= 0.71.8) + - React-jsi (= 0.71.8) + - React-perflogger (= 0.71.8) + - React-jsinspector (0.71.8) + - React-logger (0.71.8): - glog - react-native-get-random-values (1.8.0): - React-Core @@ -312,90 +312,90 @@ PODS: - RCTTypeSafety - React-Core - ReactCommon/turbomodule/core - - React-perflogger (0.71.6) - - React-RCTActionSheet (0.71.6): - - React-Core/RCTActionSheetHeaders (= 0.71.6) - - React-RCTAnimation (0.71.6): + - React-perflogger (0.71.8) + - React-RCTActionSheet (0.71.8): + - React-Core/RCTActionSheetHeaders (= 0.71.8) + - React-RCTAnimation (0.71.8): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.6) - - React-Codegen (= 0.71.6) - - React-Core/RCTAnimationHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTAppDelegate (0.71.6): + - RCTTypeSafety (= 0.71.8) + - React-Codegen (= 0.71.8) + - React-Core/RCTAnimationHeaders (= 0.71.8) + - React-jsi (= 0.71.8) + - ReactCommon/turbomodule/core (= 0.71.8) + - React-RCTAppDelegate (0.71.8): - RCT-Folly - RCTRequired - RCTTypeSafety - React-Core - ReactCommon/turbomodule/core - - React-RCTBlob (0.71.6): + - React-RCTBlob (0.71.8): - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Codegen (= 0.71.6) - - React-Core/RCTBlobHeaders (= 0.71.6) - - React-Core/RCTWebSocket (= 0.71.6) - - React-jsi (= 0.71.6) - - React-RCTNetwork (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTImage (0.71.6): + - React-Codegen (= 0.71.8) + - React-Core/RCTBlobHeaders (= 0.71.8) + - React-Core/RCTWebSocket (= 0.71.8) + - React-jsi (= 0.71.8) + - React-RCTNetwork (= 0.71.8) + - ReactCommon/turbomodule/core (= 0.71.8) + - React-RCTImage (0.71.8): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.6) - - React-Codegen (= 0.71.6) - - React-Core/RCTImageHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - React-RCTNetwork (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTLinking (0.71.6): - - React-Codegen (= 0.71.6) - - React-Core/RCTLinkingHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTNetwork (0.71.6): + - RCTTypeSafety (= 0.71.8) + - React-Codegen (= 0.71.8) + - React-Core/RCTImageHeaders (= 0.71.8) + - React-jsi (= 0.71.8) + - React-RCTNetwork (= 0.71.8) + - ReactCommon/turbomodule/core (= 0.71.8) + - React-RCTLinking (0.71.8): + - React-Codegen (= 0.71.8) + - React-Core/RCTLinkingHeaders (= 0.71.8) + - React-jsi (= 0.71.8) + - ReactCommon/turbomodule/core (= 0.71.8) + - React-RCTNetwork (0.71.8): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.6) - - React-Codegen (= 0.71.6) - - React-Core/RCTNetworkHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTSettings (0.71.6): + - RCTTypeSafety (= 0.71.8) + - React-Codegen (= 0.71.8) + - React-Core/RCTNetworkHeaders (= 0.71.8) + - React-jsi (= 0.71.8) + - ReactCommon/turbomodule/core (= 0.71.8) + - React-RCTSettings (0.71.8): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.6) - - React-Codegen (= 0.71.6) - - React-Core/RCTSettingsHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTText (0.71.6): - - React-Core/RCTTextHeaders (= 0.71.6) - - React-RCTVibration (0.71.6): + - RCTTypeSafety (= 0.71.8) + - React-Codegen (= 0.71.8) + - React-Core/RCTSettingsHeaders (= 0.71.8) + - React-jsi (= 0.71.8) + - ReactCommon/turbomodule/core (= 0.71.8) + - React-RCTText (0.71.8): + - React-Core/RCTTextHeaders (= 0.71.8) + - React-RCTVibration (0.71.8): - RCT-Folly (= 2021.07.22.00) - - React-Codegen (= 0.71.6) - - React-Core/RCTVibrationHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-runtimeexecutor (0.71.6): - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/bridging (0.71.6): + - React-Codegen (= 0.71.8) + - React-Core/RCTVibrationHeaders (= 0.71.8) + - React-jsi (= 0.71.8) + - ReactCommon/turbomodule/core (= 0.71.8) + - React-runtimeexecutor (0.71.8): + - React-jsi (= 0.71.8) + - ReactCommon/turbomodule/bridging (0.71.8): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.6) - - React-Core (= 0.71.6) - - React-cxxreact (= 0.71.6) - - React-jsi (= 0.71.6) - - React-logger (= 0.71.6) - - React-perflogger (= 0.71.6) - - ReactCommon/turbomodule/core (0.71.6): + - React-callinvoker (= 0.71.8) + - React-Core (= 0.71.8) + - React-cxxreact (= 0.71.8) + - React-jsi (= 0.71.8) + - React-logger (= 0.71.8) + - React-perflogger (= 0.71.8) + - ReactCommon/turbomodule/core (0.71.8): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.6) - - React-Core (= 0.71.6) - - React-cxxreact (= 0.71.6) - - React-jsi (= 0.71.6) - - React-logger (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-callinvoker (= 0.71.8) + - React-Core (= 0.71.8) + - React-cxxreact (= 0.71.8) + - React-jsi (= 0.71.8) + - React-logger (= 0.71.8) + - React-perflogger (= 0.71.8) - RNScreens (3.20.0): - React-Core - React-RCTImage @@ -408,14 +408,14 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (0.3.2-alpha0): + - XMTP (0.3.4-alpha0): - Connect-Swift - GzipSwift - web3.swift - XMTPRust (= 0.3.0-beta0) - XMTPReactNative (0.1.0): - ExpoModulesCore - - XMTP (= 0.3.2-alpha0) + - XMTP (= 0.3.4-alpha0) - XMTPRust (0.3.0-beta0) - Yoga (1.14.0) @@ -605,62 +605,62 @@ SPEC CHECKSUMS: EXConstants: f348da07e21b23d2b085e270d7b74f282df1a7d9 EXFileSystem: 844e86ca9b5375486ecc4ef06d3838d5597d895d EXFont: 6ea3800df746be7233208d80fe379b8ed74f4272 - Expo: 81418098ffb16914b2e190f54e06db923248e4a1 + Expo: d351b4546895fb99ae4e5a1bc39df770ab9dc7d1 ExpoKeepAwake: 69f5f627670d62318410392d03e0b5db0f85759a - ExpoModulesCore: 6e0259511f4c4341b6b8357db393624df2280828 + ExpoModulesCore: 653958063a301098b541ae4dfed1ac0b98db607b EXSecureStore: e8923258361cc406d0401af380f12bd05b2b720f - FBLazyVector: a83ceaa8a8581003a623facdb3c44f6d4f342ac5 - FBReactNativeSpec: 85eee79837cb797ab6176f0243a2b40511c09158 + FBLazyVector: f637f31eacba90d4fdeff3fa41608b8f361c173b + FBReactNativeSpec: 0d9a4f4de7ab614c49e98c00aedfd3bfbda33d59 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 GenericJSON: 79a840eeb77030962e8cf02a62d36bd413b67626 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa - hermes-engine: b434cea529ad0152c56c7cb6486b0c4c0b23b5de + hermes-engine: 47986d26692ae75ee7a17ab049caee8864f855de libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26 MMKV: 9c6c3fa4ddd849f28c7b9a5c9d23aab84f14ee35 MMKVCore: 9bb7440b170181ac5b81f542ac258103542e693d RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 - RCTRequired: 5c6fd63b03abb06947d348dadac51c93e3485bd8 - RCTTypeSafety: 1c66daedd66f674e39ce9f40782f0d490c78b175 - React: e11ca7cdc7aa4ddd7e6a59278b808cfe17ebbd9f - React-callinvoker: 77a82869505c96945c074b80bbdc8df919646d51 - React-Codegen: 9ee33090c38ab3da3c4dc029924d50fb649f0dfc - React-Core: 44903e47b428a491f48fd0eae54caddb2ea05ebf - React-CoreModules: 83d989defdfc82be1f7386f84a56b6509f54ac74 - React-cxxreact: 058e7e6349649eae9cfcdec5854e702b26298932 - React-hermes: ba19a405804b833c9b832c1f2061ad5038bb97f2 - React-jsi: 3fe6f589c9cafbef85ed5a4be7c6dc8edfb4ab54 - React-jsiexecutor: 7894956638ff3e00819dd3f9f6f4a84da38f2409 - React-jsinspector: d5ce2ef3eb8fd30c28389d0bc577918c70821bd6 - React-logger: 9332c3e7b4ef007a0211c0a9868253aac3e1da82 + RCTRequired: 8af6a32dfc2b65ec82193c2dee6e1011ff22ac2a + RCTTypeSafety: bee9dd161c175896c680d47ef1d9eaacf2b587f4 + React: d850475db9ba8006a8b875d79e1e0d6ac8a0f8b6 + React-callinvoker: 6a0c75475ddc17c9ed54e4ff0478074a18fd7ab5 + React-Codegen: 786571642e87add634e7f4d299c85314ec6cc158 + React-Core: 1adfab153f59e4f56e09b97a153089f466d7b8aa + React-CoreModules: 958d236715415d4ccdd5fa35c516cf0356637393 + React-cxxreact: 2e7a6283807ce8755c3d501735acd400bec3b5cd + React-hermes: 8102c3112ba32207c3052619be8cfae14bf99d84 + React-jsi: dd29264f041a587e91f994e4be97e86c127742b2 + React-jsiexecutor: 747911ab5921641b4ed7e4900065896597142125 + React-jsinspector: c712f9e3bb9ba4122d6b82b4f906448b8a281580 + React-logger: 342f358b8decfbf8f272367f4eacf4b6154061be react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a react-native-mmkv: 7da5e18e55c04a9af9a7e0ab9792a1e8d33765a1 react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846 react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc - React-perflogger: 43392072a5b867a504e2b4857606f8fc5a403d7f - React-RCTActionSheet: c7b67c125bebeda9fb19fc7b200d85cb9d6899c4 - React-RCTAnimation: c2de79906f607986633a7114bee44854e4c7e2f5 - React-RCTAppDelegate: 96bc933c3228a549718a6475c4d3f9dd4bbae98d - React-RCTBlob: cf72446957310e7da6627a4bdaadf970d3a8f232 - React-RCTImage: c6093f1bf3d67c0428d779b00390617d5bd90699 - React-RCTLinking: 5de47e37937889d22599af4b99d0552bad1b1c3c - React-RCTNetwork: e7d7077e073b08e5dd486fba3fe87ccad90a9bc4 - React-RCTSettings: 72a04921b2e8fb832da7201a60ffffff2a7c62f7 - React-RCTText: 7123c70fef5367e2121fea37e65b9ad6d3747e54 - React-RCTVibration: 73d201599a64ea14b4e0b8f91b64970979fd92e6 - React-runtimeexecutor: 8692ac548bec648fa121980ccb4304afd136d584 - ReactCommon: 0c43eaeaaee231d7d8dc24fc5a6e4cf2b75bf196 + React-perflogger: d21f182895de9d1b077f8a3cd00011095c8c9100 + React-RCTActionSheet: 0151f83ef92d2a7139bba7dfdbc8066632a6d47b + React-RCTAnimation: 5ec9c0705bb2297549c120fe6473aa3e4a01e215 + React-RCTAppDelegate: 9895fd1b6d1176d88c4b10ddc169b2e1300c91f0 + React-RCTBlob: f3634eb45b6e7480037655e1ca93d1136ac984dd + React-RCTImage: 3c12cb32dec49549ae62ed6cba4018db43841ffc + React-RCTLinking: 310e930ee335ef25481b4a173d9edb64b77895f9 + React-RCTNetwork: b6837841fe88303b0c04c1e3c01992b30f1f5498 + React-RCTSettings: 600d91fe25fa7c16b0ff891304082440f2904b89 + React-RCTText: a0a19f749088280c6def5397ed6211b811e7eef3 + React-RCTVibration: 43ffd976a25f6057a7cf95ea3648ba4e00287f89 + React-runtimeexecutor: 7c51ae9d4b3e9608a2366e39ccaa606aa551b9ed + ReactCommon: 85c98ab0a509e70bf5ee5d9715cf68dbf495b84c RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f RNSVG: 53c661b76829783cdaf9b7a57258f3d3b4c28315 secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: afced68785854575756db965e9da52bbf3dc45e7 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: bbdd2c59b57104d7713a31be2fa011fc07f81314 - XMTPReactNative: 48408071eeb51d1593d49c548c6002e948cd6b43 + XMTP: 0678e0b6c2e66f197db098106bec2fe35f7295fb + XMTPReactNative: 7f86c6cde3d3123d5f25adb0c9cdaedb7ca5b6aa XMTPRust: 233518ed46fbe3ea9e3bc3035de9a620dba09ce5 - Yoga: ba09b6b11e6139e3df8229238aa794205ca6a02a + Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556 PODFILE CHECKSUM: 522d88edc2d5fac4825e60a121c24abc18983367 -COCOAPODS: 1.11.3 +COCOAPODS: 1.12.1 diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 67f0af132..7914a114c 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -59,12 +59,13 @@ struct SignatureRequest: Codable { } extension Conversation { - func cacheKey(_ clientAddress: String) -> String { - if let conversationID, conversationID != "" { - return "\(clientAddress):\(topic):\(conversationID)" - } else { + + static func cacheKeyForTopic(clientAddress: String, topic: String) -> String { return "\(clientAddress):\(topic)" } + + func cacheKey(_ clientAddress: String) -> String { + return Conversation.cacheKeyForTopic(clientAddress: clientAddress, topic: topic) } } @@ -150,6 +151,30 @@ public class XMTPModule: Module { return bundle } + // Export the conversation's serialized topic data. + AsyncFunction("exportConversationTopicData") { (clientAddress: String, topic: String) -> String in + guard let client = clients[clientAddress] else { + throw Error.noClient + } + guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { + throw Error.conversationNotFound(topic) + } + return try conversation.toTopicData().serializedData().base64EncodedString() + } + + // Import a conversation from its serialized topic data. + AsyncFunction("importConversationTopicData") { (clientAddress: String, topicData: String) -> String in + guard let client = clients[clientAddress] else { + throw Error.noClient + } + let data = try Xmtp_KeystoreApi_V1_TopicMap.TopicData( + serializedData: Data(base64Encoded: Data(topicData.utf8))! + ) + let conversation = client.conversations.importTopicData(data: data) + conversations[conversation.cacheKey(clientAddress)] = conversation + return try ConversationWrapper.encode(ConversationWithClientAddress(client: client, conversation: conversation)) + } + // // Client API AsyncFunction("canMessage") { (clientAddress: String, peerAddress: String) -> Bool in @@ -190,7 +215,7 @@ public class XMTPModule: Module { // TODO: Support content types AsyncFunction("sendMessage") { (clientAddress: String, conversationTopic: String, conversationID: String?, content: String) -> String in - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: conversationTopic, conversationID: conversationID) else { + guard let conversation = try await findConversation(clientAddress: clientAddress, topic: conversationTopic) else { throw Error.conversationNotFound("no conversation found for \(conversationTopic)") } @@ -262,7 +287,7 @@ public class XMTPModule: Module { envelope.contentTopic = topic } - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic, conversationID: conversationID) else { + guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { throw Error.conversationNotFound("no conversation found for \(topic)") } let decodedMessage = try conversation.decode(envelope) @@ -274,23 +299,16 @@ public class XMTPModule: Module { // Helpers // - func findConversation(clientAddress: String, topic: String, conversationID: String?) async throws -> Conversation? { + func findConversation(clientAddress: String, topic: String) async throws -> Conversation? { guard let client = clients[clientAddress] else { throw Error.noClient } - let cacheKey: String - - if let conversationID, conversationID != "" { - cacheKey = "\(clientAddress):\(topic):\(conversationID)" - } else { - cacheKey = "\(clientAddress):\(topic)" - } - + let cacheKey = Conversation.cacheKeyForTopic(clientAddress: clientAddress, topic: topic) if let conversation = conversations[cacheKey] { return conversation - } else if let conversation = try await client.conversations.list().first(where: { $0.topic == topic && $0.conversationID == conversationID }) { - conversations[conversation.cacheKey(clientAddress)] = conversation + } else if let conversation = try await client.conversations.list().first(where: { $0.topic == topic }) { + conversations[cacheKey] = conversation return conversation } @@ -342,7 +360,7 @@ public class XMTPModule: Module { } func subscribeToMessages(clientAddress: String, topic: String, conversationID: String?) async throws { - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic, conversationID: conversationID) else { + guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { return } @@ -363,7 +381,7 @@ public class XMTPModule: Module { } func unsubscribeFromMessages(clientAddress: String, topic: String, conversationID: String?) async throws { - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic, conversationID: conversationID) else { + guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { return } diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index aa51a9e20..6ee5f4728 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -24,5 +24,5 @@ Pod::Spec.new do |s| } s.source_files = "**/*.{h,m,swift}" - s.dependency "XMTP", "= 0.3.2-alpha0" + s.dependency "XMTP", "= 0.3.4-alpha0" end diff --git a/src/index.ts b/src/index.ts index e0fef76ee..0e6b34dde 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,6 +36,21 @@ export async function exportKeyBundle(clientAddress: string): Promise { return await XMTPModule.exportKeyBundle(clientAddress); } +export async function exportConversationTopicData( + clientAddress: string, + conversationTopic: string +): Promise { + return await XMTPModule.exportConversationTopicData(clientAddress, conversationTopic); +} + +export async function importConversationTopicData( + clientAddress: string, + topicData: string +): Promise { + let json = await XMTPModule.importConversationTopicData(clientAddress, topicData); + return new Conversation(JSON.parse(json)); +} + export async function canMessage(clientAddress: string, peerAddress: string): Promise { return await XMTPModule.canMessage(clientAddress, peerAddress); } diff --git a/src/lib/Conversation.ts b/src/lib/Conversation.ts index 76715acf5..285d1561d 100644 --- a/src/lib/Conversation.ts +++ b/src/lib/Conversation.ts @@ -22,6 +22,10 @@ export class Conversation { this.conversationID = params.conversationID; } + async exportTopicData(): Promise { + return await XMTP.exportConversationTopicData(this.clientAddress, this.topic); + } + // TODO: Support pagination and conversation ID here async messages( limit?: number | undefined, diff --git a/src/lib/Conversations.ts b/src/lib/Conversations.ts index 9f0fbcbe4..069bac1bf 100644 --- a/src/lib/Conversations.ts +++ b/src/lib/Conversations.ts @@ -25,6 +25,15 @@ export default class Conversations { return result; } + async importTopicData(topicData: string): Promise { + const conversation = await XMTPModule.importConversationTopicData( + this.client.address, + topicData + ); + this.known[conversation.topic] = true; + return conversation; + } + // TODO: support conversation ID async newConversation( peerAddress: string,