From 4449843cb4e8ace684add1395bc6e8af3ec0cb8b Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 4 Dec 2024 09:50:25 -0800 Subject: [PATCH] Static Can Message (#344) * add a static can message method to the client * add static can message * fix up linter --- .../org/xmtp/android/library/ClientTest.kt | 29 +++++++++++++ .../java/org/xmtp/android/library/Client.kt | 43 +++++++++++++++++-- 2 files changed, 69 insertions(+), 3 deletions(-) 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 5bb831ff..c30f8cc8 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/ClientTest.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/ClientTest.kt @@ -72,6 +72,35 @@ class ClientTest { assertEquals(inboxId, client.inboxId) } + @Test + fun testStaticCanMessage() { + val context = InstrumentationRegistry.getInstrumentation().targetContext + val fixtures = fixtures() + val notOnNetwork = PrivateKeyBuilder() + + val canMessageList = runBlocking { + Client.canMessage( + listOf( + fixtures.alix.walletAddress, + notOnNetwork.address, + fixtures.bo.walletAddress + ), + context, + ClientOptions.Api(XMTPEnvironment.LOCAL, false) + ) + } + + val expectedResults = mapOf( + fixtures.alix.walletAddress.lowercase() to true, + notOnNetwork.address.lowercase() to false, + fixtures.bo.walletAddress.lowercase() to true + ) + + expectedResults.forEach { (address, expected) -> + assertEquals(expected, canMessageList[address.lowercase()]) + } + } + @Test fun testCanDeleteDatabase() { val key = SecureRandom().generateSeed(32) 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 e771a6f1..5fba3312 100644 --- a/library/src/main/java/org/xmtp/android/library/Client.kt +++ b/library/src/main/java/org/xmtp/android/library/Client.kt @@ -76,6 +76,39 @@ class Client() { fun register(codec: ContentCodec<*>) { codecRegistry.register(codec = codec) } + + suspend fun canMessage( + accountAddresses: List, + appContext: Context, + api: ClientOptions.Api, + ): Map { + val accountAddress = "0x0000000000000000000000000000000000000000" + val inboxId = getOrCreateInboxId(api, accountAddress) + val alias = "xmtp-${api.env}-$inboxId" + + val directoryFile = File(appContext.filesDir.absolutePath, "xmtp_db") + directoryFile.mkdir() + val dbPath = directoryFile.absolutePath + "/$alias.db3" + + val ffiClient = createClient( + logger = XMTPLogger(), + host = api.env.getUrl(), + isSecure = api.isSecure, + db = dbPath, + encryptionKey = null, + accountAddress = accountAddress.lowercase(), + inboxId = inboxId, + nonce = 0.toULong(), + legacySignedPrivateKeyProto = null, + historySyncUrl = null + ) + + val result = ffiClient.canMessage(accountAddresses) + ffiClient.releaseDbConnection() + File(dbPath).delete() + + return result + } } constructor( @@ -101,7 +134,7 @@ class Client() { address: String, clientOptions: ClientOptions, signingKey: SigningKey? = null, - inboxId: String? = null + inboxId: String? = null, ): Client { val accountAddress = address.lowercase() val recoveredInboxId = inboxId ?: getOrCreateInboxId(clientOptions.api, accountAddress) @@ -140,7 +173,7 @@ class Client() { suspend fun build( address: String, options: ClientOptions, - inboxId: String? = null + inboxId: String? = null, ): Client { return try { initializeV3Client(address, options, inboxId = inboxId) @@ -245,7 +278,11 @@ class Client() { } } - fun verifySignatureWithInstallationId(message: String, signature: ByteArray, installationId: String): Boolean { + fun verifySignatureWithInstallationId( + message: String, + signature: ByteArray, + installationId: String, + ): Boolean { return try { ffiClient.verifySignedWithPublicKey(message, signature, installationId.hexToByteArray()) true