Skip to content

Commit

Permalink
Revoke installations (#362)
Browse files Browse the repository at this point in the history
* add static inbox state and revoke installation and clean up run blocking

* add tests for it
  • Loading branch information
nplasterer authored Jan 13, 2025
1 parent 9c2ec6c commit b34ebb9
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,27 @@ class ClientTest {
}
}

@Test
fun testStaticInboxIds() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val fixtures = fixtures()
val states = runBlocking {
Client.inboxStatesForInboxIds(
listOf(fixtures.boClient.inboxId, fixtures.caroClient.inboxId),
context,
ClientOptions.Api(XMTPEnvironment.LOCAL, false)
)
}
assertEquals(
states.first().recoveryAddress.lowercase(),
fixtures.bo.walletAddress.lowercase()
)
assertEquals(
states.last().recoveryAddress.lowercase(),
fixtures.caro.walletAddress.lowercase()
)
}

@Test
fun testCanDeleteDatabase() {
val key = SecureRandom().generateSeed(32)
Expand Down Expand Up @@ -302,6 +323,59 @@ class ClientTest {
assertEquals(boClient.inboxId, boInboxId)
}

@Test
fun testRevokesInstallations() {
val key = SecureRandom().generateSeed(32)
val context = InstrumentationRegistry.getInstrumentation().targetContext
val alixWallet = PrivateKeyBuilder()

val alixClient = runBlocking {
Client().create(
account = alixWallet,
options = ClientOptions(
ClientOptions.Api(XMTPEnvironment.LOCAL, false),
appContext = context,
dbEncryptionKey = key
)
)
}

val alixClient2 = runBlocking {
Client().create(
account = alixWallet,
options = ClientOptions(
ClientOptions.Api(XMTPEnvironment.LOCAL, false),
appContext = context,
dbEncryptionKey = key,
dbDirectory = context.filesDir.absolutePath.toString()
)
)
}

val alixClient3 = runBlocking {
Client().create(
account = alixWallet,
options = ClientOptions(
ClientOptions.Api(XMTPEnvironment.LOCAL, false),
appContext = context,
dbEncryptionKey = key,
dbDirectory = File(context.filesDir.absolutePath, "xmtp_db3").toPath()
.toString()
)
)
}

var state = runBlocking { alixClient3.inboxState(true) }
assertEquals(state.installations.size, 3)

runBlocking {
alixClient3.revokeInstallations(alixWallet, listOf(alixClient2.installationId))
}

state = runBlocking { alixClient3.inboxState(true) }
assertEquals(state.installations.size, 2)
}

@Test
fun testRevokesAllOtherInstallations() {
val key = SecureRandom().generateSeed(32)
Expand Down Expand Up @@ -335,7 +409,8 @@ class ClientTest {
ClientOptions.Api(XMTPEnvironment.LOCAL, false),
appContext = context,
dbEncryptionKey = key,
dbDirectory = File(context.filesDir.absolutePath, "xmtp_db3").toPath().toString()
dbDirectory = File(context.filesDir.absolutePath, "xmtp_db3").toPath()
.toString()
)
)
}
Expand Down
52 changes: 40 additions & 12 deletions library/src/main/java/org/xmtp/android/library/Client.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package org.xmtp.android.library

import android.content.Context
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.xmtp.android.library.codecs.ContentCodec
import org.xmtp.android.library.codecs.TextCodec
import org.xmtp.android.library.libxmtp.InboxState
Expand Down Expand Up @@ -60,15 +62,13 @@ class Client() {
}

private val apiClientCache = mutableMapOf<String, XmtpApiClient>()
private val cacheLock = Any()
private val cacheLock = Mutex()

suspend fun connectToApiBackend(api: ClientOptions.Api): XmtpApiClient {
val cacheKey = api.env.getUrl()
return synchronized(cacheLock) {
return cacheLock.withLock {
apiClientCache.getOrPut(cacheKey) {
runBlocking {
connectToBackend(api.env.getUrl(), api.isSecure)
}
connectToBackend(api.env.getUrl(), api.isSecure)
}
}
}
Expand All @@ -91,11 +91,11 @@ class Client() {
codecRegistry.register(codec = codec)
}

suspend fun canMessage(
accountAddresses: List<String>,
suspend fun <T> withFfiClient(
appContext: Context,
api: ClientOptions.Api,
): Map<String, Boolean> {
useClient: suspend (ffiClient: FfiXmtpClient) -> T,
): T {
val accountAddress = "0x0000000000000000000000000000000000000000"
val inboxId = getOrCreateInboxId(api, accountAddress)
val alias = "xmtp-${api.env}-$inboxId"
Expand All @@ -115,11 +115,32 @@ class Client() {
historySyncUrl = null
)

val result = ffiClient.canMessage(accountAddresses)
ffiClient.releaseDbConnection()
File(dbPath).delete()
return try {
useClient(ffiClient)
} finally {
ffiClient.releaseDbConnection()
File(dbPath).delete()
}
}

suspend fun inboxStatesForInboxIds(
inboxIds: List<String>,
appContext: Context,
api: ClientOptions.Api,
): List<InboxState> {
return withFfiClient(appContext, api) { ffiClient ->
ffiClient.addressesFromInboxId(true, inboxIds).map { InboxState(it) }
}
}

return result
suspend fun canMessage(
accountAddresses: List<String>,
appContext: Context,
api: ClientOptions.Api,
): Map<String, Boolean> {
return withFfiClient(appContext, api) { ffiClient ->
ffiClient.canMessage(accountAddresses)
}
}
}

Expand Down Expand Up @@ -237,6 +258,13 @@ class Client() {
return Pair(ffiClient, dbPath)
}

suspend fun revokeInstallations(signingKey: SigningKey, installationIds: List<String>) {
val ids = installationIds.map { it.hexToByteArray() }
val signatureRequest = ffiClient.revokeInstallations(ids)
handleSignature(signatureRequest, signingKey)
ffiClient.applySignatureRequest(signatureRequest)
}

suspend fun revokeAllOtherInstallations(signingKey: SigningKey) {
val signatureRequest = ffiClient.revokeAllOtherInstallations()
handleSignature(signatureRequest, signingKey)
Expand Down

0 comments on commit b34ebb9

Please sign in to comment.