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 a06fb50bc..6af15b7b5 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.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.messages.MessageDeliveryStatus import org.xmtp.android.library.messages.PrivateKey import org.xmtp.android.library.messages.PrivateKeyBuilder import org.xmtp.android.library.messages.walletAddress @@ -330,9 +331,11 @@ class GroupTest { fun testCanSendMessageToGroup() { val group = runBlocking { boClient.conversations.newGroup(listOf(alix.walletAddress)) } runBlocking { group.send("howdy") } - runBlocking { group.send("gm") } + val messageId = runBlocking { group.send("gm") } runBlocking { group.sync() } assertEquals(group.messages().first().body, "gm") + assertEquals(group.messages().first().id, messageId) + assertEquals(group.messages().first().deliveryStatus, MessageDeliveryStatus.PUBLISHED) assertEquals(group.messages().size, 3) runBlocking { alixClient.conversations.syncGroups() } @@ -342,6 +345,28 @@ class GroupTest { assertEquals(sameGroup.messages().first().body, "gm") } + @Test + fun testCanListGroupMessages() { + val group = runBlocking { boClient.conversations.newGroup(listOf(alix.walletAddress)) } + runBlocking { + group.send("howdy") + group.send("gm") + } + + assertEquals(group.messages().size, 3) + assertEquals(group.messages(deliveryStatus = MessageDeliveryStatus.UNPUBLISHED).size, 2) + assertEquals(group.messages(deliveryStatus = MessageDeliveryStatus.PUBLISHED).size, 1) + runBlocking { group.sync() } + assertEquals(group.messages().size, 3) + assertEquals(group.messages(deliveryStatus = MessageDeliveryStatus.UNPUBLISHED).size, 0) + assertEquals(group.messages(deliveryStatus = MessageDeliveryStatus.PUBLISHED).size, 3) + + runBlocking { alixClient.conversations.syncGroups() } + val sameGroup = runBlocking { alixClient.conversations.listGroups().last() } + runBlocking { sameGroup.sync() } + assertEquals(sameGroup.messages(deliveryStatus = MessageDeliveryStatus.PUBLISHED).size, 2) + } + @Test fun testCanSendContentTypesToGroup() { Client.register(codec = ReactionCodec()) diff --git a/library/src/main/java/libxmtp-version.txt b/library/src/main/java/libxmtp-version.txt index c066b7057..d02f9aa56 100644 --- a/library/src/main/java/libxmtp-version.txt +++ b/library/src/main/java/libxmtp-version.txt @@ -1,3 +1,3 @@ -Version: 4068715 +Version: 5b62701 Branch: main -Date: 2024-04-06 04:27:39 +0000 +Date: 2024-04-18 03:59:02 +0000 diff --git a/library/src/main/java/org/xmtp/android/library/DecodedMessage.kt b/library/src/main/java/org/xmtp/android/library/DecodedMessage.kt index 8657e2ad5..eab903b1a 100644 --- a/library/src/main/java/org/xmtp/android/library/DecodedMessage.kt +++ b/library/src/main/java/org/xmtp/android/library/DecodedMessage.kt @@ -2,6 +2,7 @@ package org.xmtp.android.library import org.xmtp.android.library.codecs.TextCodec import org.xmtp.android.library.codecs.decoded +import org.xmtp.android.library.messages.MessageDeliveryStatus import org.xmtp.proto.message.contents.Content import java.util.Date @@ -12,6 +13,7 @@ data class DecodedMessage( var encodedContent: Content.EncodedContent, var senderAddress: String, var sent: Date, + var deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.PUBLISHED ) { companion object { fun preview(client: Client, topic: String, body: String, senderAddress: String, sent: Date): DecodedMessage { 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 876df77ff..ad4aa554f 100644 --- a/library/src/main/java/org/xmtp/android/library/Group.kt +++ b/library/src/main/java/org/xmtp/android/library/Group.kt @@ -8,9 +8,11 @@ import org.xmtp.android.library.codecs.EncodedContent import org.xmtp.android.library.codecs.compress import org.xmtp.android.library.libxmtp.MessageV3 import org.xmtp.android.library.messages.DecryptedMessage +import org.xmtp.android.library.messages.MessageDeliveryStatus import org.xmtp.android.library.messages.PagingInfoSortDirection import org.xmtp.android.library.messages.Topic import org.xmtp.proto.message.api.v1.MessageApiOuterClass +import uniffi.xmtpv3.FfiDeliveryStatus import uniffi.xmtpv3.FfiGroup import uniffi.xmtpv3.FfiGroupMetadata import uniffi.xmtpv3.FfiListMessagesOptions @@ -47,8 +49,8 @@ class Group(val client: Client, private val libXMTPGroup: FfiGroup) { if (client.contacts.consentList.groupState(groupId = id) == ConsentState.UNKNOWN) { client.contacts.allowGroup(groupIds = listOf(id)) } - libXMTPGroup.send(contentBytes = encodedContent.toByteArray()) - return id.toHex() + val messageId = libXMTPGroup.send(contentBytes = encodedContent.toByteArray()) + return messageId.toHex() } fun prepareMessage(content: T, options: SendOptions?): EncodedContent { @@ -86,12 +88,19 @@ class Group(val client: Client, private val libXMTPGroup: FfiGroup) { before: Date? = null, after: Date? = null, direction: PagingInfoSortDirection = MessageApiOuterClass.SortDirection.SORT_DIRECTION_DESCENDING, + deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.ALL, ): List { val messages = libXMTPGroup.findMessages( opts = FfiListMessagesOptions( sentBeforeNs = before?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), sentAfterNs = after?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), - limit = limit?.toLong() + limit = limit?.toLong(), + deliveryStatus = when (deliveryStatus) { + MessageDeliveryStatus.PUBLISHED -> FfiDeliveryStatus.PUBLISHED + MessageDeliveryStatus.UNPUBLISHED -> FfiDeliveryStatus.UNPUBLISHED + MessageDeliveryStatus.FAILED -> FfiDeliveryStatus.FAILED + else -> null + } ) ).mapNotNull { MessageV3(client, it).decodeOrNull() @@ -108,12 +117,19 @@ class Group(val client: Client, private val libXMTPGroup: FfiGroup) { before: Date? = null, after: Date? = null, direction: PagingInfoSortDirection = MessageApiOuterClass.SortDirection.SORT_DIRECTION_DESCENDING, + deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.ALL, ): List { val messages = libXMTPGroup.findMessages( opts = FfiListMessagesOptions( sentBeforeNs = before?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), sentAfterNs = after?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), - limit = limit?.toLong() + limit = limit?.toLong(), + deliveryStatus = when (deliveryStatus) { + MessageDeliveryStatus.PUBLISHED -> FfiDeliveryStatus.PUBLISHED + MessageDeliveryStatus.UNPUBLISHED -> FfiDeliveryStatus.UNPUBLISHED + MessageDeliveryStatus.FAILED -> FfiDeliveryStatus.FAILED + else -> null + } ) ).mapNotNull { MessageV3(client, it).decryptOrNull() diff --git a/library/src/main/java/org/xmtp/android/library/libxmtp/MessageV3.kt b/library/src/main/java/org/xmtp/android/library/libxmtp/MessageV3.kt index 8bc57409a..953c14cc6 100644 --- a/library/src/main/java/org/xmtp/android/library/libxmtp/MessageV3.kt +++ b/library/src/main/java/org/xmtp/android/library/libxmtp/MessageV3.kt @@ -6,8 +6,10 @@ import org.xmtp.android.library.DecodedMessage import org.xmtp.android.library.XMTPException import org.xmtp.android.library.codecs.EncodedContent import org.xmtp.android.library.messages.DecryptedMessage +import org.xmtp.android.library.messages.MessageDeliveryStatus import org.xmtp.android.library.messages.Topic import org.xmtp.android.library.toHex +import uniffi.xmtpv3.FfiDeliveryStatus import uniffi.xmtpv3.FfiGroupMessageKind import uniffi.xmtpv3.FfiMessage import uniffi.xmtpv3.org.xmtp.android.library.codecs.ContentTypeGroupMembershipChange @@ -27,6 +29,13 @@ data class MessageV3(val client: Client, private val libXMTPMessage: FfiMessage) val sentAt: Date get() = Date(libXMTPMessage.sentAtNs / 1_000_000) + val deliveryStatus: MessageDeliveryStatus + get() = when (libXMTPMessage.deliveryStatus) { + FfiDeliveryStatus.UNPUBLISHED -> MessageDeliveryStatus.UNPUBLISHED + FfiDeliveryStatus.PUBLISHED -> MessageDeliveryStatus.PUBLISHED + FfiDeliveryStatus.FAILED -> MessageDeliveryStatus.FAILED + } + fun decode(): DecodedMessage { try { val decodedMessage = DecodedMessage( @@ -36,6 +45,7 @@ data class MessageV3(val client: Client, private val libXMTPMessage: FfiMessage) encodedContent = EncodedContent.parseFrom(libXMTPMessage.content), senderAddress = senderAddress, sent = sentAt, + deliveryStatus = deliveryStatus ) if (decodedMessage.encodedContent.type == ContentTypeGroupMembershipChange && libXMTPMessage.kind != FfiGroupMessageKind.MEMBERSHIP_CHANGE) { throw XMTPException("Error decoding group membership change") @@ -71,6 +81,7 @@ data class MessageV3(val client: Client, private val libXMTPMessage: FfiMessage) encodedContent = decode().encodedContent, senderAddress = senderAddress, sentAt = Date(), + deliveryStatus = deliveryStatus ) } } diff --git a/library/src/main/java/org/xmtp/android/library/messages/DecryptedMessage.kt b/library/src/main/java/org/xmtp/android/library/messages/DecryptedMessage.kt index 2b3980073..accd89459 100644 --- a/library/src/main/java/org/xmtp/android/library/messages/DecryptedMessage.kt +++ b/library/src/main/java/org/xmtp/android/library/messages/DecryptedMessage.kt @@ -9,4 +9,5 @@ data class DecryptedMessage( var senderAddress: String, var sentAt: Date, var topic: String = "", + var deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.PUBLISHED ) diff --git a/library/src/main/java/org/xmtp/android/library/messages/Message.kt b/library/src/main/java/org/xmtp/android/library/messages/Message.kt index 09657929d..2beb7c8ac 100644 --- a/library/src/main/java/org/xmtp/android/library/messages/Message.kt +++ b/library/src/main/java/org/xmtp/android/library/messages/Message.kt @@ -2,6 +2,10 @@ package org.xmtp.android.library.messages typealias Message = org.xmtp.proto.message.contents.MessageOuterClass.Message +enum class MessageDeliveryStatus { + ALL, PUBLISHED, UNPUBLISHED, FAILED +} + enum class MessageVersion(val rawValue: String) { V1("v1"), V2("v2"); diff --git a/library/src/main/java/xmtpv3.kt b/library/src/main/java/xmtpv3.kt index b0e2902a3..3d45c7843 100644 --- a/library/src/main/java/xmtpv3.kt +++ b/library/src/main/java/xmtpv3.kt @@ -854,7 +854,7 @@ private fun uniffiCheckApiChecksums(lib: _UniFFILib) { if (lib.uniffi_xmtpv3_checksum_method_ffigroup_remove_members() != 1645.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } - if (lib.uniffi_xmtpv3_checksum_method_ffigroup_send() != 55957.toShort()) { + if (lib.uniffi_xmtpv3_checksum_method_ffigroup_send() != 2523.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } if (lib.uniffi_xmtpv3_checksum_method_ffigroup_stream() != 7482.toShort()) { @@ -1505,7 +1505,7 @@ public interface FfiGroupInterface { fun `listMembers`(): List@Throws(GenericException::class) suspend fun `processStreamedGroupMessage`(`envelopeBytes`: ByteArray): FfiMessage@Throws(GenericException::class) suspend fun `removeMembers`(`accountAddresses`: List)@Throws(GenericException::class) - suspend fun `send`(`contentBytes`: ByteArray)@Throws(GenericException::class) + suspend fun `send`(`contentBytes`: ByteArray): ByteArray@Throws(GenericException::class) suspend fun `stream`(`messageCallback`: FfiMessageCallback): FfiStreamCloser@Throws(GenericException::class) suspend fun `sync`() companion object @@ -1676,7 +1676,7 @@ class FfiGroup( @Throws(GenericException::class) @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") - override suspend fun `send`(`contentBytes`: ByteArray) { + override suspend fun `send`(`contentBytes`: ByteArray) : ByteArray { return uniffiRustCallAsync( callWithPointer { thisPtr -> _UniFFILib.INSTANCE.uniffi_xmtpv3_fn_method_ffigroup_send( @@ -1684,12 +1684,11 @@ class FfiGroup( FfiConverterByteArray.lower(`contentBytes`), ) }, - { future, continuation -> _UniFFILib.INSTANCE.ffi_xmtpv3_rust_future_poll_void(future, continuation) }, - { future, continuation -> _UniFFILib.INSTANCE.ffi_xmtpv3_rust_future_complete_void(future, continuation) }, - { future -> _UniFFILib.INSTANCE.ffi_xmtpv3_rust_future_free_void(future) }, + { future, continuation -> _UniFFILib.INSTANCE.ffi_xmtpv3_rust_future_poll_rust_buffer(future, 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 - { Unit }, - + { FfiConverterByteArray.lift(it) }, // Error FFI converter GenericException.ErrorHandler, ) @@ -2484,7 +2483,8 @@ public object FfiConverterTypeFfiListConversationsOptions: FfiConverterRustBuffe data class FfiListMessagesOptions ( var `sentBeforeNs`: Long?, var `sentAfterNs`: Long?, - var `limit`: Long? + var `limit`: Long?, + var `deliveryStatus`: FfiDeliveryStatus? ) { companion object @@ -2496,19 +2496,22 @@ public object FfiConverterTypeFfiListMessagesOptions: FfiConverterRustBuffer { FfiConverterString.read(buf), FfiConverterByteArray.read(buf), FfiConverterTypeFfiGroupMessageKind.read(buf), + FfiConverterTypeFfiDeliveryStatus.read(buf), ) } @@ -2545,7 +2550,8 @@ public object FfiConverterTypeFfiMessage: FfiConverterRustBuffer { FfiConverterByteArray.allocationSize(value.`convoId`) + FfiConverterString.allocationSize(value.`addrFrom`) + FfiConverterByteArray.allocationSize(value.`content`) + - FfiConverterTypeFfiGroupMessageKind.allocationSize(value.`kind`) + FfiConverterTypeFfiGroupMessageKind.allocationSize(value.`kind`) + + FfiConverterTypeFfiDeliveryStatus.allocationSize(value.`deliveryStatus`) ) override fun write(value: FfiMessage, buf: ByteBuffer) { @@ -2555,6 +2561,7 @@ public object FfiConverterTypeFfiMessage: FfiConverterRustBuffer { FfiConverterString.write(value.`addrFrom`, buf) FfiConverterByteArray.write(value.`content`, buf) FfiConverterTypeFfiGroupMessageKind.write(value.`kind`, buf) + FfiConverterTypeFfiDeliveryStatus.write(value.`deliveryStatus`, buf) } } @@ -2767,6 +2774,30 @@ public object FfiConverterTypeFfiV2SubscribeRequest: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = try { + FfiDeliveryStatus.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: FfiDeliveryStatus) = 4 + + override fun write(value: FfiDeliveryStatus, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + + + + + + enum class FfiGroupMessageKind { APPLICATION,MEMBERSHIP_CHANGE; companion object @@ -3591,6 +3622,35 @@ public object FfiConverterOptionalTypeFfiPagingInfo: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): FfiDeliveryStatus? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeFfiDeliveryStatus.read(buf) + } + + override fun allocationSize(value: FfiDeliveryStatus?): Int { + if (value == null) { + return 1 + } else { + return 1 + FfiConverterTypeFfiDeliveryStatus.allocationSize(value) + } + } + + override fun write(value: FfiDeliveryStatus?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeFfiDeliveryStatus.write(value, buf) + } + } +} + + + + public object FfiConverterOptionalTypeGroupPermissions: FfiConverterRustBuffer { override fun read(buf: ByteBuffer): GroupPermissions? { if (buf.get().toInt() == 0) { diff --git a/library/src/main/jniLibs/arm64-v8a/libuniffi_xmtpv3.so b/library/src/main/jniLibs/arm64-v8a/libuniffi_xmtpv3.so index 48dcc1b13..e4ba548c4 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 1a8a40ac5..0323ae2b3 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 d32916daf..8aa403508 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 c790a1687..f8416b836 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