From 6d9f4e7adbcd7580e3a88b45d38f15eede0268c2 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 16 Oct 2024 10:44:15 -0700 Subject: [PATCH] add involved tests --- .../org/xmtp/android/library/V3ClientTest.kt | 71 +++++++++++++++++-- .../java/org/xmtp/android/library/Client.kt | 8 +++ .../org/xmtp/android/library/Conversation.kt | 9 +++ .../org/xmtp/android/library/Conversations.kt | 20 ++++-- 4 files changed, 99 insertions(+), 9 deletions(-) diff --git a/library/src/androidTest/java/org/xmtp/android/library/V3ClientTest.kt b/library/src/androidTest/java/org/xmtp/android/library/V3ClientTest.kt index e57552c49..6cae62bc2 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/V3ClientTest.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/V3ClientTest.kt @@ -81,7 +81,8 @@ class V3ClientTest { @Test fun testsCanCreateGroup() { - val group = runBlocking { boV3Client.conversations.newGroup(listOf(caroV2V3.walletAddress)) } + val group = + runBlocking { boV3Client.conversations.newGroup(listOf(caroV2V3.walletAddress)) } assertEquals( runBlocking { group.members().map { it.inboxId }.sorted() }, listOf(caroV2V3Client.inboxId, boV3Client.inboxId).sorted() @@ -93,8 +94,29 @@ class V3ClientTest { } @Test - fun testsCanSendMessages() { - val group = runBlocking { boV3Client.conversations.newGroup(listOf(caroV2V3.walletAddress)) } + fun testsCanCreateDm() { + val dm = runBlocking { boV3Client.conversations.findOrCreateDm(caroV2V3.walletAddress) } + assertEquals( + runBlocking { dm.members().map { it.inboxId }.sorted() }, + listOf(caroV2V3Client.inboxId, boV3Client.inboxId).sorted() + ) + + val sameDm = runBlocking { boV3Client.findDm(caroV2V3.walletAddress) } + assertEquals(sameDm?.id, dm.id) + + runBlocking { caroV2V3Client.conversations.syncConversations() } + val caroDm = runBlocking { caroV2V3Client.findDm(boV3Client.address) } + assertEquals(caroDm?.id, dm.id) + + Assert.assertThrows("Recipient not on network", XMTPException::class.java) { + runBlocking { boV3Client.conversations.findOrCreateDm(alixV2.walletAddress) } + } + } + + @Test + fun testsCanSendMessagesToGroup() { + val group = + runBlocking { boV3Client.conversations.newGroup(listOf(caroV2V3.walletAddress)) } runBlocking { group.send("howdy") } val messageId = runBlocking { group.send("gm") } runBlocking { group.sync() } @@ -103,13 +125,51 @@ class V3ClientTest { assertEquals(group.messages().first().deliveryStatus, MessageDeliveryStatus.PUBLISHED) assertEquals(group.messages().size, 3) - runBlocking { caroV2V3Client.conversations.syncGroups() } + runBlocking { caroV2V3Client.conversations.syncConversations() } val sameGroup = runBlocking { caroV2V3Client.conversations.listGroups().last() } runBlocking { sameGroup.sync() } assertEquals(sameGroup.messages().size, 2) assertEquals(sameGroup.messages().first().body, "gm") } + @Test + fun testsCanSendMessagesToDm() { + val boDm = + runBlocking { boV3Client.conversations.newConversation(caroV2V3.walletAddress) } + runBlocking { boDm.send("howdy") } + var messageId = runBlocking { boDm.send("gm") } + var boDmMessage = runBlocking { boDm.messages() } + assertEquals(boDmMessage.first().body, "gm") + assertEquals(boDmMessage.first().id, messageId) + assertEquals(boDmMessage.first().deliveryStatus, MessageDeliveryStatus.PUBLISHED) + assertEquals(boDmMessage.size, 3) + + runBlocking { caroV2V3Client.conversations.syncConversations() } + var sameDm = runBlocking { caroV2V3Client.conversations.list().last() } + runBlocking { sameDm.sync() } + var caroDmMessage = runBlocking { sameDm.messages() } + assertEquals(caroDmMessage.size, 2) + assertEquals(caroDmMessage.first().body, "gm") + + // Do the inverse + val caroDm = + runBlocking { caroV2V3Client.conversations.newConversation(boV3.walletAddress) } + runBlocking { caroDm.send("howdy") } + messageId = runBlocking { caroDm.send("gm") } + caroDmMessage = runBlocking { caroDm.messages() } + assertEquals(caroDmMessage.first().body, "gm") + assertEquals(caroDmMessage.first().id, messageId) + assertEquals(caroDmMessage.first().deliveryStatus, MessageDeliveryStatus.PUBLISHED) + assertEquals(caroDmMessage.size, 4) + + runBlocking { boV3Client.conversations.syncConversations() } + sameDm = runBlocking { boV3Client.conversations.list().last() } + runBlocking { sameDm.sync() } + boDmMessage = runBlocking { sameDm.messages() } + assertEquals(boDmMessage.size, 5) + assertEquals(boDmMessage.first().body, "gm") + } + @Test fun testGroupConsent() { runBlocking { @@ -159,7 +219,8 @@ class V3ClientTest { @Test fun testCanStreamAllMessagesFromV2andV3Users() { - val group = runBlocking { boV3Client.conversations.newGroup(listOf(caroV2V3.walletAddress)) } + val group = + runBlocking { boV3Client.conversations.newGroup(listOf(caroV2V3.walletAddress)) } val conversation = runBlocking { alixV2Client.conversations.newConversation(caroV2V3.walletAddress) } runBlocking { caroV2V3Client.conversations.syncGroups() } 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 7af850c47..673fe2e68 100644 --- a/library/src/main/java/org/xmtp/android/library/Client.kt +++ b/library/src/main/java/org/xmtp/android/library/Client.kt @@ -741,6 +741,14 @@ class Client() { } } + suspend fun addressesFromInboxIds( + refreshFromNetwork: Boolean, + inboxIds: List, + ): List { + val client = v3Client ?: throw XMTPException("Error no V3 client initialized") + return client.addressesFromInboxId(refreshFromNetwork, inboxIds).map { InboxState(it) } + } + suspend fun inboxState(refreshFromNetwork: Boolean): InboxState { val client = v3Client ?: throw XMTPException("Error no V3 client initialized") return InboxState(client.inboxState(refreshFromNetwork)) diff --git a/library/src/main/java/org/xmtp/android/library/Conversation.kt b/library/src/main/java/org/xmtp/android/library/Conversation.kt index ac37d78a7..1479e1a6c 100644 --- a/library/src/main/java/org/xmtp/android/library/Conversation.kt +++ b/library/src/main/java/org/xmtp/android/library/Conversation.kt @@ -183,6 +183,15 @@ sealed class Conversation { } } + suspend fun sync() { + return when (this) { + is V1 -> throw XMTPException("Only supported for V3") + is V2 -> throw XMTPException("Only supported for V3") + is Group -> group.sync() + is Dm -> dm.sync() + } + } + /** * This lists messages sent to the [Conversation]. * @param before initial date to filter diff --git a/library/src/main/java/org/xmtp/android/library/Conversations.kt b/library/src/main/java/org/xmtp/android/library/Conversations.kt index 1be26235d..551adbcd4 100644 --- a/library/src/main/java/org/xmtp/android/library/Conversations.kt +++ b/library/src/main/java/org/xmtp/android/library/Conversations.kt @@ -222,7 +222,7 @@ data class Conversations( val dm = findOrCreateDm(peerAddress) val conversation = Conversation.Dm(dm) conversationsByTopic[conversation.topic] = conversation - if (!client.hasV2Client) { + if (!client.hasV2Client || !client.canMessage(peerAddress)) { return conversation } } @@ -330,7 +330,6 @@ data class Conversations( limit: Int? = null, order: ConversationOrder = ConversationOrder.CREATED_AT, ): List { - if (client.hasV2Client) throw XMTPException("Only supported for V3 only clients.") val ffiDms = libXMTPConversations?.listDms( opts = FfiListConversationsOptions( after?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), @@ -428,10 +427,23 @@ data class Conversations( conversationsByTopic += newConversations.filter { it.peerAddress != client.address && Topic.isValidTopic(it.topic) }.map { Pair(it.topic, it) } - } else if (client.v3Client != null) { + } + if (client.v3Client != null) { syncConversations() val dms = listDms() - conversationsByTopic += dms.map { Pair(it.topic, Conversation.Dm(it)) } + if (!client.hasV2Client) { + conversationsByTopic += dms.map { it.topic to Conversation.Dm(it) } + } else { + conversationsByTopic.putAll( + dms.filter { dm -> + conversationsByTopic.values.none { existing -> + client.inboxIdFromAddress(existing.peerAddress)?.lowercase() == dm.peerInboxId().lowercase() + } + }.associate { dm -> + dm.topic to Conversation.Dm(dm) + } + ) + } } if (includeGroups) {