diff --git a/library/src/androidTest/java/org/xmtp/android/library/ClientTest.kt b/library/src/androidTest/java/org/xmtp/android/library/ClientTest.kt index e6e4ee2ea..702451e68 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/ClientTest.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/ClientTest.kt @@ -345,4 +345,33 @@ class ClientTest { assertEquals(boClient.conversations.listGroups().size, 1) } } + + @Test + fun testCanGetAnInboxIdFromAddress() { + val context = InstrumentationRegistry.getInstrumentation().targetContext + val alixWallet = PrivateKeyBuilder() + val boWallet = PrivateKeyBuilder() + val alixClient = + Client().create( + account = alixWallet, + options = ClientOptions( + ClientOptions.Api(XMTPEnvironment.LOCAL, false), + enableV3 = true, + appContext = context + ) + ) + val boClient = + Client().create( + account = boWallet, + options = ClientOptions( + ClientOptions.Api(XMTPEnvironment.LOCAL, false), + enableV3 = true, + appContext = context + ) + ) + val boInboxId = runBlocking { + alixClient.inboxIdFromAddress(boClient.address) + } + assertEquals(boClient.inboxId, boInboxId) + } } 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 748de0e5f..a242008be 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt @@ -17,6 +17,7 @@ import org.junit.Before import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith +import org.web3j.utils.Numeric import org.xmtp.android.library.codecs.ContentTypeGroupUpdated import org.xmtp.android.library.codecs.ContentTypeReaction import org.xmtp.android.library.codecs.GroupUpdatedCodec @@ -24,7 +25,6 @@ import org.xmtp.android.library.codecs.Reaction import org.xmtp.android.library.codecs.ReactionAction import org.xmtp.android.library.codecs.ReactionCodec import org.xmtp.android.library.codecs.ReactionSchema -import org.xmtp.android.library.codecs.id import org.xmtp.android.library.messages.MessageDeliveryStatus import org.xmtp.android.library.messages.PrivateKey import org.xmtp.android.library.messages.PrivateKeyBuilder @@ -789,4 +789,39 @@ class GroupTest { assert(!boClient.contacts.isInboxAllowed(alixClient.inboxId)) assert(boClient.contacts.isInboxDenied(alixClient.inboxId)) } + + @Test + fun testCanFetchGroupById() { + val boGroup = runBlocking { + boClient.conversations.newGroup( + listOf( + alix.walletAddress, + caro.walletAddress + ) + ) + } + runBlocking { alixClient.conversations.syncGroups() } + val alixGroup = alixClient.findGroup(boGroup.id) + + assertEquals(alixGroup?.id?.toHex(), boGroup.id.toHex()) + } + + @Test + fun testCanFetchMessageById() { + val boGroup = runBlocking { + boClient.conversations.newGroup( + listOf( + alix.walletAddress, + caro.walletAddress + ) + ) + } + val boMessageId = runBlocking { boGroup.send("Hello") } + runBlocking { alixClient.conversations.syncGroups() } + val alixGroup = alixClient.findGroup(boGroup.id) + runBlocking { alixGroup?.sync() } + val alixMessage = alixClient.findMessage(Numeric.hexStringToByteArray(boMessageId)) + + assertEquals(alixMessage?.id?.toHex(), boMessageId) + } } diff --git a/library/src/main/java/libxmtp-version.txt b/library/src/main/java/libxmtp-version.txt index e86d4e686..e8e461bea 100644 --- a/library/src/main/java/libxmtp-version.txt +++ b/library/src/main/java/libxmtp-version.txt @@ -1,3 +1,3 @@ -Version: 43e21e0d +Version: 1e096906 Branch: main -Date: 2024-06-20 20:35:11 +0000 +Date: 2024-06-24 17:58:00 +0000 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 5563a3be8..099603023 100644 --- a/library/src/main/java/org/xmtp/android/library/Client.kt +++ b/library/src/main/java/org/xmtp/android/library/Client.kt @@ -17,6 +17,7 @@ import org.web3j.crypto.Keys.toChecksumAddress import org.xmtp.android.library.GRPCApiClient.Companion.makeSubscribeRequest import org.xmtp.android.library.codecs.ContentCodec import org.xmtp.android.library.codecs.TextCodec +import org.xmtp.android.library.libxmtp.MessageV3 import org.xmtp.android.library.libxmtp.XMTPLogger import org.xmtp.android.library.messages.ContactBundle import org.xmtp.android.library.messages.EncryptedPrivateKeyBundle @@ -71,6 +72,7 @@ data class ClientOptions( val enableV3: Boolean = false, val dbDirectory: String? = null, val dbEncryptionKey: ByteArray? = null, + val historySyncUrl: String? = null, ) { data class Api( val env: XMTPEnvironment = XMTPEnvironment.DEV, @@ -368,7 +370,8 @@ class Client() { accountAddress = accountAddress, inboxId = inboxId, nonce = 0.toULong(), - legacySignedPrivateKeyProto = privateKeyBundleV1.toV2().identityKey.toByteArray() + legacySignedPrivateKeyProto = privateKeyBundleV1.toV2().identityKey.toByteArray(), + historySyncUrl = options.historySyncUrl ) } else { null @@ -515,6 +518,28 @@ class Client() { } } + fun findGroup(groupId: ByteArray): Group? { + v3Client?.let { + try { + return Group(this, it.group(groupId)) + } catch (e: Exception) { + return null + } + } + throw XMTPException("Error no V3 client initialized") + } + + fun findMessage(messageId: ByteArray): MessageV3? { + v3Client?.let { + try { + return MessageV3(this, it.message(messageId)) + } catch (e: Exception) { + return null + } + } + throw XMTPException("Error no V3 client initialized") + } + suspend fun publish(envelopes: List): PublishResponse { val authorized = AuthorizedIdentity( address = address, @@ -609,6 +634,13 @@ class Client() { throw XMTPException("Error no V3 client initialized") } + suspend fun inboxIdFromAddress(address: String): String? { + v3Client?.let { + return it.findInboxId(address.lowercase()) + } + throw XMTPException("Error no V3 client initialized") + } + fun deleteLocalDatabase() { File(dbPath).delete() } @@ -624,6 +656,10 @@ class Client() { v3Client?.dbReconnect() ?: throw XMTPException("Error no V3 client initialized") } + suspend fun requestMessageHistorySync() { + v3Client?.requestHistorySync() ?: throw XMTPException("Error no V3 client initialized") + } + val privateKeyBundle: PrivateKeyBundle get() = PrivateKeyBundleBuilder.buildFromV1Key(privateKeyBundleV1) diff --git a/library/src/main/java/xmtpv3.kt b/library/src/main/java/xmtpv3.kt index 812403992..87fc4cefc 100644 --- a/library/src/main/java/xmtpv3.kt +++ b/library/src/main/java/xmtpv3.kt @@ -1127,6 +1127,14 @@ internal interface UniffiLib : Library { `ptr`: Pointer, ): Long + fun uniffi_xmtpv3_fn_method_ffixmtpclient_find_inbox_id( + `ptr`: Pointer, `address`: RustBuffer.ByValue, + ): Long + + fun uniffi_xmtpv3_fn_method_ffixmtpclient_group( + `ptr`: Pointer, `groupId`: RustBuffer.ByValue, uniffi_out_err: UniffiRustCallStatus, + ): Pointer + fun uniffi_xmtpv3_fn_method_ffixmtpclient_inbox_id( `ptr`: Pointer, uniffi_out_err: UniffiRustCallStatus, ): RustBuffer.ByValue @@ -1135,6 +1143,10 @@ internal interface UniffiLib : Library { `ptr`: Pointer, uniffi_out_err: UniffiRustCallStatus, ): RustBuffer.ByValue + fun uniffi_xmtpv3_fn_method_ffixmtpclient_message( + `ptr`: Pointer, `messageId`: RustBuffer.ByValue, uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + fun uniffi_xmtpv3_fn_method_ffixmtpclient_register_identity( `ptr`: Pointer, `signatureRequest`: Pointer, ): Long @@ -1143,6 +1155,10 @@ internal interface UniffiLib : Library { `ptr`: Pointer, uniffi_out_err: UniffiRustCallStatus, ): Unit + fun uniffi_xmtpv3_fn_method_ffixmtpclient_request_history_sync( + `ptr`: Pointer, + ): Long + fun uniffi_xmtpv3_fn_method_ffixmtpclient_signature_request( `ptr`: Pointer, uniffi_out_err: UniffiRustCallStatus, ): RustBuffer.ByValue @@ -1173,6 +1189,7 @@ internal interface UniffiLib : Library { `accountAddress`: RustBuffer.ByValue, `nonce`: Long, `legacySignedPrivateKeyProto`: RustBuffer.ByValue, + `historySyncUrl`: RustBuffer.ByValue, ): Long fun uniffi_xmtpv3_fn_func_create_v2_client( @@ -1693,18 +1710,30 @@ internal interface UniffiLib : Library { fun uniffi_xmtpv3_checksum_method_ffixmtpclient_db_reconnect( ): Short + fun uniffi_xmtpv3_checksum_method_ffixmtpclient_find_inbox_id( + ): Short + + fun uniffi_xmtpv3_checksum_method_ffixmtpclient_group( + ): Short + fun uniffi_xmtpv3_checksum_method_ffixmtpclient_inbox_id( ): Short fun uniffi_xmtpv3_checksum_method_ffixmtpclient_installation_id( ): Short + fun uniffi_xmtpv3_checksum_method_ffixmtpclient_message( + ): Short + fun uniffi_xmtpv3_checksum_method_ffixmtpclient_register_identity( ): Short fun uniffi_xmtpv3_checksum_method_ffixmtpclient_release_db_connection( ): Short + fun uniffi_xmtpv3_checksum_method_ffixmtpclient_request_history_sync( + ): Short + fun uniffi_xmtpv3_checksum_method_ffixmtpclient_signature_request( ): Short @@ -1740,7 +1769,7 @@ private fun uniffiCheckContractApiVersion(lib: UniffiLib) { @Suppress("UNUSED_PARAMETER") private fun uniffiCheckApiChecksums(lib: UniffiLib) { - if (lib.uniffi_xmtpv3_checksum_func_create_client() != 51078.toShort()) { + if (lib.uniffi_xmtpv3_checksum_func_create_client() != 6255.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } if (lib.uniffi_xmtpv3_checksum_func_create_v2_client() != 48060.toShort()) { @@ -1953,18 +1982,30 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) { if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_db_reconnect() != 6707.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_find_inbox_id() != 59020.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_group() != 64533.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_inbox_id() != 25128.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_installation_id() != 37173.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_message() != 26932.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_register_identity() != 42003.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_release_db_connection() != 11067.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_request_history_sync() != 22295.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_signature_request() != 18270.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -5554,14 +5595,22 @@ public interface FfiXmtpClientInterface { suspend fun `dbReconnect`() + suspend fun `findInboxId`(`address`: kotlin.String): kotlin.String? + + fun `group`(`groupId`: kotlin.ByteArray): FfiGroup + fun `inboxId`(): kotlin.String fun `installationId`(): kotlin.ByteArray + fun `message`(`messageId`: kotlin.ByteArray): FfiMessage + suspend fun `registerIdentity`(`signatureRequest`: FfiSignatureRequest) fun `releaseDbConnection`() + suspend fun `requestHistorySync`() + fun `signatureRequest`(): FfiSignatureRequest? companion object @@ -5725,6 +5774,53 @@ open class FfiXmtpClient : Disposable, AutoCloseable, FfiXmtpClientInterface { ) } + + @Throws(GenericException::class) + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + override suspend fun `findInboxId`(`address`: kotlin.String): kotlin.String? { + return uniffiRustCallAsync( + callWithPointer { thisPtr -> + UniffiLib.INSTANCE.uniffi_xmtpv3_fn_method_ffixmtpclient_find_inbox_id( + thisPtr, + FfiConverterString.lower(`address`), + ) + }, + { future, callback, continuation -> + UniffiLib.INSTANCE.ffi_xmtpv3_rust_future_poll_rust_buffer( + future, + callback, + continuation + ) + }, + { future, continuation -> + UniffiLib.INSTANCE.ffi_xmtpv3_rust_future_complete_rust_buffer( + future, + continuation + ) + }, + { future -> UniffiLib.INSTANCE.ffi_xmtpv3_rust_future_free_rust_buffer(future) }, + // lift function + { FfiConverterOptionalString.lift(it) }, + // Error FFI converter + GenericException.ErrorHandler, + ) + } + + + @Throws(GenericException::class) + override fun `group`(`groupId`: kotlin.ByteArray): FfiGroup { + return FfiConverterTypeFfiGroup.lift( + callWithPointer { + uniffiRustCallWithError(GenericException) { _status -> + UniffiLib.INSTANCE.uniffi_xmtpv3_fn_method_ffixmtpclient_group( + it, FfiConverterByteArray.lower(`groupId`), _status + ) + } + } + ) + } + + override fun `inboxId`(): kotlin.String { return FfiConverterString.lift( callWithPointer { @@ -5751,6 +5847,20 @@ open class FfiXmtpClient : Disposable, AutoCloseable, FfiXmtpClientInterface { } + @Throws(GenericException::class) + override fun `message`(`messageId`: kotlin.ByteArray): FfiMessage { + return FfiConverterTypeFfiMessage.lift( + callWithPointer { + uniffiRustCallWithError(GenericException) { _status -> + UniffiLib.INSTANCE.uniffi_xmtpv3_fn_method_ffixmtpclient_message( + it, FfiConverterByteArray.lower(`messageId`), _status + ) + } + } + ) + } + + @Throws(GenericException::class) @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") override suspend fun `registerIdentity`(`signatureRequest`: FfiSignatureRequest) { @@ -5795,6 +5905,38 @@ open class FfiXmtpClient : Disposable, AutoCloseable, FfiXmtpClientInterface { } + @Throws(GenericException::class) + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + override suspend fun `requestHistorySync`() { + return uniffiRustCallAsync( + callWithPointer { thisPtr -> + UniffiLib.INSTANCE.uniffi_xmtpv3_fn_method_ffixmtpclient_request_history_sync( + thisPtr, + + ) + }, + { future, callback, continuation -> + UniffiLib.INSTANCE.ffi_xmtpv3_rust_future_poll_void( + future, + callback, + continuation + ) + }, + { future, continuation -> + UniffiLib.INSTANCE.ffi_xmtpv3_rust_future_complete_void( + future, + continuation + ) + }, + { future -> UniffiLib.INSTANCE.ffi_xmtpv3_rust_future_free_void(future) }, + // lift function + { Unit }, + + // Error FFI converter + GenericException.ErrorHandler, + ) + } + override fun `signatureRequest`(): FfiSignatureRequest? { return FfiConverterOptionalTypeFfiSignatureRequest.lift( callWithPointer { @@ -7296,6 +7438,7 @@ suspend fun `createClient`( `accountAddress`: kotlin.String, `nonce`: kotlin.ULong, `legacySignedPrivateKeyProto`: kotlin.ByteArray?, + `historySyncUrl`: kotlin.String?, ): FfiXmtpClient { return uniffiRustCallAsync( UniffiLib.INSTANCE.uniffi_xmtpv3_fn_func_create_client( @@ -7310,6 +7453,7 @@ suspend fun `createClient`( FfiConverterString.lower(`accountAddress`), FfiConverterULong.lower(`nonce`), FfiConverterOptionalByteArray.lower(`legacySignedPrivateKeyProto`), + FfiConverterOptionalString.lower(`historySyncUrl`), ), { future, callback, continuation -> UniffiLib.INSTANCE.ffi_xmtpv3_rust_future_poll_pointer( diff --git a/library/src/main/jniLibs/arm64-v8a/libuniffi_xmtpv3.so b/library/src/main/jniLibs/arm64-v8a/libuniffi_xmtpv3.so index 126be7b77..f30b4a249 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 67ec8e429..cffbc2bd4 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 40abde7d7..f02eb564c 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 2f49b509b..f4ba92696 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