diff --git a/library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt b/library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt index e8bd7cced..7c5167363 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt @@ -3,7 +3,6 @@ package org.xmtp.android.library import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import app.cash.turbine.test -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking import org.junit.Assert.assertEquals import org.junit.Assert.assertThrows @@ -113,6 +112,25 @@ class GroupTest { ) } + @Test + fun testIsActiveReturnsCorrectly() { + val group = boClient.conversations.newGroup( + listOf( + alix.walletAddress, + caro.walletAddress + ) + ) + runBlocking { caroClient.conversations.syncGroups() } + val caroGroup = caroClient.conversations.listGroups().first() + runBlocking { caroGroup.sync() } + assert(caroGroup.isActive()) + assert(group.isActive()) + group.removeMembers(listOf(caro.walletAddress)) + runBlocking { caroGroup.sync() } + assert(group.isActive()) + assert(!caroGroup.isActive()) + } + @Test fun testCanListGroups() { boClient.conversations.newGroup(listOf(alix.walletAddress)) @@ -200,11 +218,9 @@ class GroupTest { assertEquals(ReactionSchema.Unicode, content?.schema) } - @OptIn(ExperimentalCoroutinesApi::class) @Test fun testCanStreamGroupMessages() = kotlinx.coroutines.test.runTest { val group = boClient.conversations.newGroup(listOf(alix.walletAddress.lowercase())) - group.streamMessages().test { group.send("hi") assertEquals("hi", awaitItem().body) @@ -213,7 +229,6 @@ class GroupTest { } } - @OptIn(ExperimentalCoroutinesApi::class) @Test fun testCanStreamDecryptedGroupMessages() = kotlinx.coroutines.test.runTest { val group = boClient.conversations.newGroup(listOf(alix.walletAddress)) @@ -226,7 +241,6 @@ class GroupTest { } } - @OptIn(ExperimentalCoroutinesApi::class) @Test fun testCanStreamGroups() = kotlinx.coroutines.test.runTest { boClient.conversations.streamGroups().test { @@ -239,7 +253,6 @@ class GroupTest { } } - @OptIn(ExperimentalCoroutinesApi::class) @Test fun testCanStreamGroupsAndConversations() = kotlinx.coroutines.test.runTest { boClient.conversations.streamAll().test { diff --git a/library/src/main/java/org/xmtp/android/library/Client.kt b/library/src/main/java/org/xmtp/android/library/Client.kt index 8b0ef064b..b6b5925d7 100644 --- a/library/src/main/java/org/xmtp/android/library/Client.kt +++ b/library/src/main/java/org/xmtp/android/library/Client.kt @@ -44,6 +44,7 @@ import org.xmtp.proto.message.api.v1.MessageApiOuterClass.QueryRequest import uniffi.xmtpv3.FfiXmtpClient import uniffi.xmtpv3.LegacyIdentitySource import uniffi.xmtpv3.createClient +import uniffi.xmtpv3.getVersionInfo import java.io.File import java.nio.charset.StandardCharsets import java.security.KeyStore @@ -81,6 +82,7 @@ class Client() { lateinit var conversations: Conversations var logger: XMTPLogger = XMTPLogger() var libXMTPClient: FfiXmtpClient? = null + val libXMTPVersion: String = getVersionInfo() companion object { private const val TAG = "Client" @@ -347,7 +349,7 @@ class Client() { throw XMTPException("No signer passed but signer was required.") } } - + Log.i(TAG, "LibXMTP $libXMTPVersion") return v3Client } diff --git a/library/src/main/java/org/xmtp/android/library/Group.kt b/library/src/main/java/org/xmtp/android/library/Group.kt index 1dce2bba1..a425da20d 100644 --- a/library/src/main/java/org/xmtp/android/library/Group.kt +++ b/library/src/main/java/org/xmtp/android/library/Group.kt @@ -128,6 +128,10 @@ class Group(val client: Client, private val libXMTPGroup: FfiGroup) { ) } + fun isActive(): Boolean { + return libXMTPGroup.isActive() + } + fun addMembers(addresses: List) { runBlocking { libXMTPGroup.addMembers(addresses) } } diff --git a/library/src/main/java/xmtpv3.kt b/library/src/main/java/xmtpv3.kt index 67a1e3937..29bc1a528 100644 --- a/library/src/main/java/xmtpv3.kt +++ b/library/src/main/java/xmtpv3.kt @@ -413,6 +413,8 @@ internal interface _UniFFILib : Library { ): RustBuffer.ByValue fun uniffi_xmtpv3_fn_method_ffigroup_id(`ptr`: Pointer,_uniffi_out_err: RustCallStatus, ): RustBuffer.ByValue + fun uniffi_xmtpv3_fn_method_ffigroup_is_active(`ptr`: Pointer,_uniffi_out_err: RustCallStatus, + ): Byte fun uniffi_xmtpv3_fn_method_ffigroup_list_members(`ptr`: Pointer,_uniffi_out_err: RustCallStatus, ): RustBuffer.ByValue fun uniffi_xmtpv3_fn_method_ffigroup_remove_members(`ptr`: Pointer,`accountAddresses`: RustBuffer.ByValue, @@ -427,6 +429,8 @@ internal interface _UniFFILib : Library { ): Unit fun uniffi_xmtpv3_fn_method_ffistreamcloser_end(`ptr`: Pointer,_uniffi_out_err: RustCallStatus, ): Unit + fun uniffi_xmtpv3_fn_method_ffistreamcloser_is_closed(`ptr`: Pointer,_uniffi_out_err: RustCallStatus, + ): Byte fun uniffi_xmtpv3_fn_free_ffiv2apiclient(`ptr`: Pointer,_uniffi_out_err: RustCallStatus, ): Unit fun uniffi_xmtpv3_fn_method_ffiv2apiclient_batch_query(`ptr`: Pointer,`req`: RustBuffer.ByValue, @@ -475,6 +479,8 @@ internal interface _UniFFILib : Library { ): RustBuffer.ByValue fun uniffi_xmtpv3_fn_func_generate_private_preferences_topic_identifier(`privateKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus, ): RustBuffer.ByValue + fun uniffi_xmtpv3_fn_func_get_version_info(_uniffi_out_err: RustCallStatus, + ): RustBuffer.ByValue fun uniffi_xmtpv3_fn_func_keccak256(`input`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus, ): RustBuffer.ByValue fun uniffi_xmtpv3_fn_func_public_key_from_private_key_k256(`privateKeyBytes`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus, @@ -615,6 +621,8 @@ internal interface _UniFFILib : Library { ): Short fun uniffi_xmtpv3_checksum_func_generate_private_preferences_topic_identifier( ): Short + fun uniffi_xmtpv3_checksum_func_get_version_info( + ): Short fun uniffi_xmtpv3_checksum_func_keccak256( ): Short fun uniffi_xmtpv3_checksum_func_public_key_from_private_key_k256( @@ -649,6 +657,8 @@ internal interface _UniFFILib : Library { ): Short fun uniffi_xmtpv3_checksum_method_ffigroup_id( ): Short + fun uniffi_xmtpv3_checksum_method_ffigroup_is_active( + ): Short fun uniffi_xmtpv3_checksum_method_ffigroup_list_members( ): Short fun uniffi_xmtpv3_checksum_method_ffigroup_remove_members( @@ -661,6 +671,8 @@ internal interface _UniFFILib : Library { ): Short fun uniffi_xmtpv3_checksum_method_ffistreamcloser_end( ): Short + fun uniffi_xmtpv3_checksum_method_ffistreamcloser_is_closed( + ): Short fun uniffi_xmtpv3_checksum_method_ffiv2apiclient_batch_query( ): Short fun uniffi_xmtpv3_checksum_method_ffiv2apiclient_publish( @@ -726,6 +738,9 @@ private fun uniffiCheckApiChecksums(lib: _UniFFILib) { if (lib.uniffi_xmtpv3_checksum_func_generate_private_preferences_topic_identifier() != 5952.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_xmtpv3_checksum_func_get_version_info() != 3533.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_xmtpv3_checksum_func_keccak256() != 17749.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -777,6 +792,9 @@ private fun uniffiCheckApiChecksums(lib: _UniFFILib) { if (lib.uniffi_xmtpv3_checksum_method_ffigroup_id() != 35243.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_xmtpv3_checksum_method_ffigroup_is_active() != 27808.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_xmtpv3_checksum_method_ffigroup_list_members() != 15786.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -795,6 +813,9 @@ private fun uniffiCheckApiChecksums(lib: _UniFFILib) { if (lib.uniffi_xmtpv3_checksum_method_ffistreamcloser_end() != 47211.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_xmtpv3_checksum_method_ffistreamcloser_is_closed() != 37884.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_xmtpv3_checksum_method_ffiv2apiclient_batch_query() != 10812.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -1379,6 +1400,7 @@ public interface FfiGroupInterface { fun `createdAtNs`(): Long@Throws(GenericException::class) fun `findMessages`(`opts`: FfiListMessagesOptions): List fun `id`(): ByteArray@Throws(GenericException::class) + fun `isActive`(): Boolean@Throws(GenericException::class) fun `listMembers`(): List@Throws(GenericException::class) suspend fun `removeMembers`(`accountAddresses`: List)@Throws(GenericException::class) suspend fun `send`(`contentBytes`: ByteArray)@Throws(GenericException::class) @@ -1461,6 +1483,18 @@ class FfiGroup( } + @Throws(GenericException::class)override fun `isActive`(): Boolean = + callWithPointer { + rustCallWithError(GenericException) { _status -> + _UniFFILib.INSTANCE.uniffi_xmtpv3_fn_method_ffigroup_is_active(it, + + _status) + } + }.let { + FfiConverterBoolean.lift(it) + } + + @Throws(GenericException::class)override fun `listMembers`(): List = callWithPointer { rustCallWithError(GenericException) { _status -> @@ -1590,6 +1624,7 @@ public object FfiConverterTypeFfiGroup: FfiConverter { public interface FfiStreamCloserInterface { fun `end`() + fun `isClosed`(): Boolean companion object } @@ -1621,6 +1656,17 @@ class FfiStreamCloser( } + override fun `isClosed`(): Boolean = + callWithPointer { + rustCall() { _status -> + _UniFFILib.INSTANCE.uniffi_xmtpv3_fn_method_ffistreamcloser_is_closed(it, + + _status) + } + }.let { + FfiConverterBoolean.lift(it) + } + @@ -3511,6 +3557,14 @@ fun `generatePrivatePreferencesTopicIdentifier`(`privateKey`: ByteArray): String } +fun `getVersionInfo`(): String { + return FfiConverterString.lift( + rustCall() { _status -> + _UniFFILib.INSTANCE.uniffi_xmtpv3_fn_func_get_version_info(_status) + }) +} + + fun `keccak256`(`input`: ByteArray): ByteArray { return FfiConverterByteArray.lift( rustCall() { _status -> diff --git a/library/src/main/jniLibs/arm64-v8a/libuniffi_xmtpv3.so b/library/src/main/jniLibs/arm64-v8a/libuniffi_xmtpv3.so index b9dd08d6a..f5f056218 100755 Binary files a/library/src/main/jniLibs/arm64-v8a/libuniffi_xmtpv3.so and b/library/src/main/jniLibs/arm64-v8a/libuniffi_xmtpv3.so differ diff --git a/library/src/main/jniLibs/armeabi-v7a/libuniffi_xmtpv3.so b/library/src/main/jniLibs/armeabi-v7a/libuniffi_xmtpv3.so index d1fa2e0b3..487df6ced 100755 Binary files a/library/src/main/jniLibs/armeabi-v7a/libuniffi_xmtpv3.so and b/library/src/main/jniLibs/armeabi-v7a/libuniffi_xmtpv3.so differ diff --git a/library/src/main/jniLibs/x86/libuniffi_xmtpv3.so b/library/src/main/jniLibs/x86/libuniffi_xmtpv3.so index 10aeb510a..dfb169dd9 100755 Binary files a/library/src/main/jniLibs/x86/libuniffi_xmtpv3.so and b/library/src/main/jniLibs/x86/libuniffi_xmtpv3.so differ diff --git a/library/src/main/jniLibs/x86_64/libuniffi_xmtpv3.so b/library/src/main/jniLibs/x86_64/libuniffi_xmtpv3.so index 2f4b88dd5..48eb26c70 100755 Binary files a/library/src/main/jniLibs/x86_64/libuniffi_xmtpv3.so and b/library/src/main/jniLibs/x86_64/libuniffi_xmtpv3.so differ