From 940825efdb258d8e441d2c07bc57c61671ad8606 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 18 Dec 2024 11:52:59 -0800 Subject: [PATCH] add the ability to cache the api client in android --- .../modules/xmtpreactnativesdk/XMTPModule.kt | 20 +++++++++++++--- example/src/tests/groupPerformanceTests.ts | 24 +++++++++++++++++++ src/index.ts | 6 +++++ src/lib/Client.ts | 10 ++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index 854d8a32..1436c7ff 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -59,6 +59,7 @@ import org.xmtp.android.library.messages.PrivateKeyBuilder import org.xmtp.android.library.messages.Signature import org.xmtp.android.library.push.Service import org.xmtp.android.library.push.XMTPPush +import uniffi.xmtpv3.XmtpApiClient import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.GroupPermissionPreconfiguration import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.PermissionOption import java.io.BufferedReader @@ -191,6 +192,7 @@ class XMTPModule : Module() { } private var clients: MutableMap = mutableMapOf() + private var apiClient: XmtpApiClient? = null private var xmtpPush: XMTPPush? = null private var signer: ReactNativeSigner? = null private val isDebugEnabled = BuildConfig.DEBUG // TODO: consider making this configurable @@ -290,6 +292,15 @@ class XMTPModule : Module() { signer?.handleSCW(id = requestID, signature = signature) } + AsyncFunction("connectToApiBackend") Coroutine { environment: String -> + withContext(Dispatchers.IO) { + logV("connectToApiBackend") + val api = apiEnvironments(environment, null) + val xmtpApiClient = Client().connectToApiBackend(api) + apiClient = xmtpApiClient + } + } + AsyncFunction("createRandom") Coroutine { hasPreAuthenticateToInboxCallback: Boolean?, dbEncryptionKey: List, authParams: String -> withContext(Dispatchers.IO) { logV("createRandom") @@ -299,10 +310,11 @@ class XMTPModule : Module() { authParams, hasPreAuthenticateToInboxCallback, ) - val randomClient = Client().create(account = privateKey, options = options) + val randomClient = Client().create(account = privateKey, options = options, apiClient = apiClient) ContentJson.Companion clients[randomClient.installationId] = randomClient + apiClient = randomClient.apiClient ClientWrapper.encodeToObj(randomClient) } } @@ -324,8 +336,9 @@ class XMTPModule : Module() { authParams, hasAuthInboxCallback, ) - val client = Client().create(account = reactSigner, options = options) + val client = Client().create(account = reactSigner, options = options, apiClient = apiClient) clients[client.installationId] = client + apiClient = client.apiClient ContentJson.Companion signer = null sendEvent("authed", ClientWrapper.encodeToObj(client)) @@ -339,9 +352,10 @@ class XMTPModule : Module() { dbEncryptionKey, authParams, ) - val client = Client().build(address = address, options = options, inboxId = inboxId) + val client = Client().build(address = address, options = options, inboxId = inboxId, apiClient = apiClient) ContentJson.Companion clients[client.installationId] = client + apiClient = client.apiClient ClientWrapper.encodeToObj(client) } } diff --git a/example/src/tests/groupPerformanceTests.ts b/example/src/tests/groupPerformanceTests.ts index abada6c0..df43994f 100644 --- a/example/src/tests/groupPerformanceTests.ts +++ b/example/src/tests/groupPerformanceTests.ts @@ -88,6 +88,26 @@ test('building and creating', async () => { const end3 = performance.now() console.log(`Built a client with inboxId in ${end3 - start3}ms`) + await Client.connectToApiBackend('dev') + const start4 = performance.now() + await Client.createRandom({ + env: 'dev', + appVersion: 'Testing/0.0.0', + dbEncryptionKey: keyBytes, + dbDirectory: dbDirPath, + codecs: [ + new ReactionCodec(), + new ReplyCodec(), + new GroupUpdatedCodec(), + new StaticAttachmentCodec(), + new RemoteAttachmentCodec(), + ], + }) + const end4 = performance.now() + console.log( + `Created a client after connecting to backend in ${end4 - start4}ms` + ) + assert( end2 - start2 < end1 - start1, 'building a client should be faster than creating one' @@ -100,6 +120,10 @@ test('building and creating', async () => { end3 - start3 < end2 - start2, 'building a client with an inboxId should be faster than building without' ) + assert( + end4 - start4 < end1 - start1, + 'creating a client with an apiClient cached should be faster than creating one without' + ) return true }) diff --git a/src/index.ts b/src/index.ts index a48bb7c9..be4acc4b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -119,6 +119,12 @@ export async function receiveSCWSignature( return await XMTPModule.receiveSCWSignature(requestID, signature) } +export async function connectToApiBackend( + environment: XMTPEnvironment +): Promise { + return await XMTPModule.connectToApiBackend(environment) +} + export async function createRandom( environment: 'local' | 'dev' | 'production', dbEncryptionKey: Uint8Array, diff --git a/src/lib/Client.ts b/src/lib/Client.ts index eaf6492d..0689d659 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -79,6 +79,16 @@ export class Client< } } + /** + * Connects to the XMTP api backend to speed up creating and building future clients. + * + * @param {XMTPEnvironment} env - Environment to connect to + * @returns {Promise} A Promise to let you know the api has been connected + */ + static async connectToApiBackend(env: XMTPEnvironment): Promise { + return await XMTPModule.connectToApiBackend(env) + } + /** * Creates a new instance of the XMTP Client with a randomly generated address. *