diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index 97f982a50..82495fd94 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -111,8 +111,8 @@ data class SignatureRequest( var message: String, ) -fun Conversation.cacheKey(clientAddress: String): String { - return "${clientAddress}:${topic}" +fun Conversation.cacheKey(inboxId: String): String { + return "${inboxId}:${topic}" } fun Group.cacheKey(inboxId: String): String { @@ -178,31 +178,34 @@ class XMTPModule : Module() { ) - Function("address") { clientAddress: String -> + Function("address") { inboxId: String -> logV("address") - val client = clients[clientAddress] + val client = clients[inboxId] client?.address ?: "No Client." } - Function("inboxId") { clientAddress: String -> + Function("inboxId") { inboxId: String -> logV("inboxId") - val client = clients[clientAddress] + val client = clients[inboxId] client?.inboxId ?: "No Client." } - AsyncFunction("deleteLocalDatabase") { clientAddress: String -> - val client = clients[clientAddress] ?: throw XMTPException("No client") + AsyncFunction("deleteLocalDatabase") { inboxId: String -> + logV("LOPI") + logV(inboxId) + logV(clients.toString()) + val client = clients[inboxId] ?: throw XMTPException("No client") client.deleteLocalDatabase() } - Function("dropLocalDatabaseConnection") { clientAddress: String -> - val client = clients[clientAddress] ?: throw XMTPException("No client") + Function("dropLocalDatabaseConnection") { inboxId: String -> + val client = clients[inboxId] ?: throw XMTPException("No client") client.dropLocalDatabaseConnection() } - AsyncFunction("reconnectLocalDatabase") Coroutine { clientAddress: String -> + AsyncFunction("reconnectLocalDatabase") Coroutine { inboxId: String -> withContext(Dispatchers.IO) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.reconnectLocalDatabase() } } @@ -240,7 +243,7 @@ class XMTPModule : Module() { dbDirectory = dbDirectory ) val client = Client().create(account = reactSigner, options = options) - clients[address] = client + clients[client.inboxId] = client ContentJson.Companion signer = null sendEvent("authed", ClientWrapper.encodeToObj(client)) @@ -282,7 +285,7 @@ class XMTPModule : Module() { ) val randomClient = Client().create(account = privateKey, options = options) ContentJson.Companion - clients[randomClient.address] = randomClient + clients[randomClient.inboxId] = randomClient ClientWrapper.encodeToObj(randomClient) } @@ -312,16 +315,16 @@ class XMTPModule : Module() { ) val client = Client().buildFromBundle(bundle = bundle, options = options) ContentJson.Companion - clients[client.address] = client + clients[client.inboxId] = client ClientWrapper.encodeToObj(client) } catch (e: Exception) { throw XMTPException("Failed to create client: $e") } } - AsyncFunction("sign") { clientAddress: String, digest: List, keyType: String, preKeyIndex: Int -> + AsyncFunction("sign") { inboxId: String, digest: List, keyType: String, preKeyIndex: Int -> logV("sign") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val digestBytes = digest.foldIndexed(ByteArray(digest.size)) { i, a, v -> a.apply { @@ -344,43 +347,43 @@ class XMTPModule : Module() { signature.toByteArray().map { it.toInt() and 0xFF } } - AsyncFunction("exportPublicKeyBundle") { clientAddress: String -> + AsyncFunction("exportPublicKeyBundle") { inboxId: String -> logV("exportPublicKeyBundle") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.keys.getPublicKeyBundle().toByteArray().map { it.toInt() and 0xFF } } - AsyncFunction("exportKeyBundle") { clientAddress: String -> + AsyncFunction("exportKeyBundle") { inboxId: String -> logV("exportKeyBundle") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") Base64.encodeToString(client.privateKeyBundle.toByteArray(), NO_WRAP) } // Export the conversation's serialized topic data. - AsyncFunction("exportConversationTopicData") Coroutine { clientAddress: String, topic: String -> + AsyncFunction("exportConversationTopicData") Coroutine { inboxId: String, topic: String -> withContext(Dispatchers.IO) { logV("exportConversationTopicData") - val conversation = findConversation(clientAddress, topic) + val conversation = findConversation(inboxId, topic) ?: throw XMTPException("no conversation found for $topic") Base64.encodeToString(conversation.toTopicData().toByteArray(), NO_WRAP) } } - AsyncFunction("getHmacKeys") { clientAddress: String -> + AsyncFunction("getHmacKeys") { inboxId: String -> logV("getHmacKeys") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val hmacKeys = client.conversations.getHmacKeys() logV("$hmacKeys") hmacKeys.toByteArray().map { it.toInt() and 0xFF } } // Import a conversation from its serialized topic data. - AsyncFunction("importConversationTopicData") { clientAddress: String, topicData: String -> + AsyncFunction("importConversationTopicData") { inboxId: String, topicData: String -> logV("importConversationTopicData") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val data = TopicData.parseFrom(Base64.decode(topicData, NO_WRAP)) val conversation = client.conversations.importTopicData(data) - conversations[conversation.cacheKey(clientAddress)] = conversation + conversations[conversation.cacheKey(inboxId)] = conversation if (conversation.keyMaterial == null) { logV("Null key material before encode conversation") } @@ -389,17 +392,17 @@ class XMTPModule : Module() { // // Client API - AsyncFunction("canMessage") { clientAddress: String, peerAddress: String -> + AsyncFunction("canMessage") { inboxId: String, peerAddress: String -> logV("canMessage") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.canMessage(peerAddress) } - AsyncFunction("canGroupMessage") Coroutine { clientAddress: String, peerAddresses: List -> + AsyncFunction("canGroupMessage") Coroutine { inboxId: String, peerAddresses: List -> withContext(Dispatchers.IO) { logV("canGroupMessage") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.canMessageV3(peerAddresses) } } @@ -414,9 +417,9 @@ class XMTPModule : Module() { } } - AsyncFunction("encryptAttachment") { clientAddress: String, fileJson: String -> + AsyncFunction("encryptAttachment") { inboxId: String, fileJson: String -> logV("encryptAttachment") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val file = DecryptedLocalAttachment.fromJson(fileJson) val uri = Uri.parse(file.fileUri) val data = appContext.reactContext?.contentResolver @@ -441,9 +444,9 @@ class XMTPModule : Module() { ).toJson() } - AsyncFunction("decryptAttachment") { clientAddress: String, encryptedFileJson: String -> + AsyncFunction("decryptAttachment") { inboxId: String, encryptedFileJson: String -> logV("decryptAttachment") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val encryptedFile = EncryptedLocalAttachment.fromJson(encryptedFileJson) val encryptedData = appContext.reactContext?.contentResolver ?.openInputStream(Uri.parse(encryptedFile.encryptedLocalFileUri)) @@ -468,11 +471,11 @@ class XMTPModule : Module() { ).toJson() } - AsyncFunction("sendEncodedContent") Coroutine { clientAddress: String, topic: String, encodedContentData: List -> + AsyncFunction("sendEncodedContent") Coroutine { inboxId: String, topic: String, encodedContentData: List -> withContext(Dispatchers.IO) { val conversation = findConversation( - clientAddress = clientAddress, + inboxId = inboxId, topic = topic ) ?: throw XMTPException("no conversation found for $topic") @@ -491,13 +494,13 @@ class XMTPModule : Module() { } } - AsyncFunction("listConversations") Coroutine { clientAddress: String -> + AsyncFunction("listConversations") Coroutine { inboxId: String -> withContext(Dispatchers.IO) { logV("listConversations") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val conversationList = client.conversations.list() conversationList.map { conversation -> - conversations[conversation.cacheKey(clientAddress)] = conversation + conversations[conversation.cacheKey(inboxId)] = conversation if (conversation.keyMaterial == null) { logV("Null key material before encode conversation") } @@ -506,35 +509,35 @@ class XMTPModule : Module() { } } - AsyncFunction("listGroups") Coroutine { clientAddress: String -> + AsyncFunction("listGroups") Coroutine { inboxId: String -> withContext(Dispatchers.IO) { logV("listGroups") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val groupList = client.conversations.listGroups() groupList.map { group -> - groups[group.cacheKey(clientAddress)] = group + groups[group.cacheKey(inboxId)] = group GroupWrapper.encode(client, group) } } } - AsyncFunction("listAll") Coroutine { clientAddress: String -> + AsyncFunction("listAll") Coroutine { inboxId: String -> withContext(Dispatchers.IO) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val conversationContainerList = client.conversations.list(includeGroups = true) conversationContainerList.map { conversation -> - conversations[conversation.cacheKey(clientAddress)] = conversation + conversations[conversation.cacheKey(inboxId)] = conversation ConversationContainerWrapper.encode(client, conversation) } } } - AsyncFunction("loadMessages") Coroutine { clientAddress: String, topic: String, limit: Int?, before: Long?, after: Long?, direction: String? -> + AsyncFunction("loadMessages") Coroutine { inboxId: String, topic: String, limit: Int?, before: Long?, after: Long?, direction: String? -> withContext(Dispatchers.IO) { logV("loadMessages") val conversation = findConversation( - clientAddress = clientAddress, + inboxId = inboxId, topic = topic, ) ?: throw XMTPException("no conversation found for $topic") val beforeDate = if (before != null) Date(before) else null @@ -552,13 +555,13 @@ class XMTPModule : Module() { } } - AsyncFunction("groupMessages") Coroutine { clientAddress: String, id: String, limit: Int?, before: Long?, after: Long?, direction: String?, deliveryStatus: String? -> + AsyncFunction("groupMessages") Coroutine { inboxId: String, id: String, limit: Int?, before: Long?, after: Long?, direction: String?, deliveryStatus: String? -> withContext(Dispatchers.IO) { logV("groupMessages") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val beforeDate = if (before != null) Date(before) else null val afterDate = if (after != null) Date(after) else null - val group = findGroup(clientAddress, id) + val group = findGroup(inboxId, id) group?.decryptedMessages( limit = limit, before = beforeDate, @@ -573,10 +576,10 @@ class XMTPModule : Module() { } } - AsyncFunction("loadBatchMessages") Coroutine { clientAddress: String, topics: List -> + AsyncFunction("loadBatchMessages") Coroutine { inboxId: String, topics: List -> withContext(Dispatchers.IO) { logV("loadBatchMessages") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val topicsList = mutableListOf>() topics.forEach { val jsonObj = JSONObject(it) @@ -620,12 +623,12 @@ class XMTPModule : Module() { } } - AsyncFunction("sendMessage") Coroutine { clientAddress: String, conversationTopic: String, contentJson: String -> + AsyncFunction("sendMessage") Coroutine { inboxId: String, conversationTopic: String, contentJson: String -> withContext(Dispatchers.IO) { logV("sendMessage") val conversation = findConversation( - clientAddress = clientAddress, + inboxId = inboxId, topic = conversationTopic ) ?: throw XMTPException("no conversation found for $conversationTopic") @@ -637,12 +640,12 @@ class XMTPModule : Module() { } } - AsyncFunction("sendMessageToGroup") Coroutine { clientAddress: String, id: String, contentJson: String -> + AsyncFunction("sendMessageToGroup") Coroutine { inboxId: String, id: String, contentJson: String -> withContext(Dispatchers.IO) { logV("sendMessageToGroup") val group = findGroup( - clientAddress = clientAddress, + inboxId = inboxId, id = id ) ?: throw XMTPException("no group found for $id") @@ -654,12 +657,12 @@ class XMTPModule : Module() { } } - AsyncFunction("prepareMessage") Coroutine { clientAddress: String, conversationTopic: String, contentJson: String -> + AsyncFunction("prepareMessage") Coroutine { inboxId: String, conversationTopic: String, contentJson: String -> withContext(Dispatchers.IO) { logV("prepareMessage") val conversation = findConversation( - clientAddress = clientAddress, + inboxId = inboxId, topic = conversationTopic ) ?: throw XMTPException("no conversation found for $conversationTopic") @@ -679,12 +682,12 @@ class XMTPModule : Module() { } } - AsyncFunction("prepareEncodedMessage") Coroutine { clientAddress: String, conversationTopic: String, encodedContentData: List -> + AsyncFunction("prepareEncodedMessage") Coroutine { inboxId: String, conversationTopic: String, encodedContentData: List -> withContext(Dispatchers.IO) { logV("prepareEncodedMessage") val conversation = findConversation( - clientAddress = clientAddress, + inboxId = inboxId, topic = conversationTopic ) ?: throw XMTPException("no conversation found for $conversationTopic") @@ -714,10 +717,10 @@ class XMTPModule : Module() { } } - AsyncFunction("sendPreparedMessage") Coroutine { clientAddress: String, preparedLocalMessageJson: String -> + AsyncFunction("sendPreparedMessage") Coroutine { inboxId: String, preparedLocalMessageJson: String -> withContext(Dispatchers.IO) { logV("sendPreparedMessage") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val local = PreparedLocalMessage.fromJson(preparedLocalMessageJson) val preparedFileUrl = Uri.parse(local.preparedFileUri) val contentResolver = appContext.reactContext?.contentResolver!! @@ -734,10 +737,10 @@ class XMTPModule : Module() { } } - AsyncFunction("createConversation") Coroutine { clientAddress: String, peerAddress: String, contextJson: String, consentProofPayload: List -> + AsyncFunction("createConversation") Coroutine { inboxId: String, peerAddress: String, contextJson: String, consentProofPayload: List -> withContext(Dispatchers.IO) { logV("createConversation: $contextJson") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val context = JsonParser.parseString(contextJson).asJsonObject var consentProof: ConsentProofPayload? = null @@ -782,10 +785,10 @@ class XMTPModule : Module() { ConversationWrapper.encode(client, conversation) } } - AsyncFunction("createGroup") Coroutine { clientAddress: String, peerAddresses: List, permission: String -> + AsyncFunction("createGroup") Coroutine { inboxId: String, peerAddresses: List, permission: String -> withContext(Dispatchers.IO) { logV("createGroup") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val permissionLevel = when (permission) { "admin_only" -> GroupPermissions.ADMIN_ONLY else -> GroupPermissions.ALL_MEMBERS @@ -795,215 +798,215 @@ class XMTPModule : Module() { } } - AsyncFunction("listMemberInboxIds") Coroutine { clientAddress: String, groupId: String -> + AsyncFunction("listMemberInboxIds") Coroutine { inboxId: String, groupId: String -> withContext(Dispatchers.IO) { logV("listMembers") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, groupId) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, groupId) group?.members()?.map { it.inboxId } } } - AsyncFunction("listGroupMembers") Coroutine { clientAddress: String, groupId: String -> + AsyncFunction("listGroupMembers") Coroutine { inboxId: String, groupId: String -> withContext(Dispatchers.IO) { logV("listGroupMembers") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, groupId) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, groupId) group?.members()?.map { MemberWrapper.encode(it) } } } - AsyncFunction("syncGroups") Coroutine { clientAddress: String -> + AsyncFunction("syncGroups") Coroutine { inboxId: String -> withContext(Dispatchers.IO) { logV("syncGroups") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.conversations.syncGroups() } } - AsyncFunction("syncGroup") Coroutine { clientAddress: String, id: String -> + AsyncFunction("syncGroup") Coroutine { inboxId: String, id: String -> withContext(Dispatchers.IO) { logV("syncGroup") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.sync() } } - AsyncFunction("addGroupMembers") Coroutine { clientAddress: String, id: String, peerAddresses: List -> + AsyncFunction("addGroupMembers") Coroutine { inboxId: String, id: String, peerAddresses: List -> withContext(Dispatchers.IO) { logV("addGroupMembers") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.addMembers(peerAddresses) } } - AsyncFunction("removeGroupMembers") Coroutine { clientAddress: String, id: String, peerAddresses: List -> + AsyncFunction("removeGroupMembers") Coroutine { inboxId: String, id: String, peerAddresses: List -> withContext(Dispatchers.IO) { logV("removeGroupMembers") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.removeMembers(peerAddresses) } } - AsyncFunction("addGroupMembersByInboxId") Coroutine { clientAddress: String, id: String, peerInboxIds: List -> + AsyncFunction("addGroupMembersByInboxId") Coroutine { inboxId: String, id: String, peerInboxIds: List -> withContext(Dispatchers.IO) { logV("addGroupMembersByInboxId") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.addMembersByInboxId(peerInboxIds) } } - AsyncFunction("removeGroupMembersByInboxId") Coroutine { clientAddress: String, id: String, peerInboxIds: List -> + AsyncFunction("removeGroupMembersByInboxId") Coroutine { inboxId: String, id: String, peerInboxIds: List -> withContext(Dispatchers.IO) { logV("removeGroupMembersByInboxId") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.removeMembersByInboxId(peerInboxIds) } } - AsyncFunction("groupName") Coroutine { clientAddress: String, id: String -> + AsyncFunction("groupName") Coroutine { inboxId: String, id: String -> withContext(Dispatchers.IO) { logV("groupName") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.name } } - AsyncFunction("updateGroupName") Coroutine { clientAddress: String, id: String, groupName: String -> + AsyncFunction("updateGroupName") Coroutine { inboxId: String, id: String, groupName: String -> withContext(Dispatchers.IO) { logV("updateGroupName") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.updateGroupName(groupName) } } - AsyncFunction("isGroupActive") Coroutine { clientAddress: String, id: String -> + AsyncFunction("isGroupActive") Coroutine { inboxId: String, id: String -> withContext(Dispatchers.IO) { logV("isGroupActive") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.isActive() } } - AsyncFunction("addedByInboxId") Coroutine { clientAddress: String, id: String -> + AsyncFunction("addedByInboxId") Coroutine { inboxId: String, id: String -> withContext(Dispatchers.IO) { logV("addedByInboxId") - val group = findGroup(clientAddress, id) ?: throw XMTPException("No group found") + val group = findGroup(inboxId, id) ?: throw XMTPException("No group found") group.addedByInboxId() } } - AsyncFunction("creatorInboxId") Coroutine { clientAddress: String, id: String -> + AsyncFunction("creatorInboxId") Coroutine { inboxId: String, id: String -> withContext(Dispatchers.IO) { logV("creatorInboxId") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.creatorInboxId() } } - AsyncFunction("isAdmin") Coroutine { clientAddress: String, id: String, inboxId: String -> + AsyncFunction("isAdmin") Coroutine { id: String, inboxId: String -> withContext(Dispatchers.IO) { logV("isGroupAdmin") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.isAdmin(inboxId) } } - AsyncFunction("isSuperAdmin") Coroutine { clientAddress: String, id: String, inboxId: String -> + AsyncFunction("isSuperAdmin") Coroutine { id: String, inboxId: String -> withContext(Dispatchers.IO) { logV("isSuperAdmin") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.isSuperAdmin(inboxId) } } - AsyncFunction("listAdmins") Coroutine { clientAddress: String, id: String -> + AsyncFunction("listAdmins") Coroutine { inboxId: String, id: String -> withContext(Dispatchers.IO) { logV("listAdmins") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.listAdmins() } } - AsyncFunction("listSuperAdmins") Coroutine { clientAddress: String, id: String -> + AsyncFunction("listSuperAdmins") Coroutine { inboxId: String, id: String -> withContext(Dispatchers.IO) { logV("listSuperAdmins") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.listSuperAdmins() } } - AsyncFunction("addAdmin") Coroutine { clientAddress: String, id: String, inboxId: String -> + AsyncFunction("addAdmin") Coroutine { id: String, inboxId: String -> withContext(Dispatchers.IO) { logV("addAdmin") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.addAdmin(inboxId) } } - AsyncFunction("addSuperAdmin") Coroutine { clientAddress: String, id: String, inboxId: String -> + AsyncFunction("addSuperAdmin") Coroutine { id: String, inboxId: String -> withContext(Dispatchers.IO) { logV("addSuperAdmin") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.addSuperAdmin(inboxId) } } - AsyncFunction("removeAdmin") Coroutine { clientAddress: String, id: String, inboxId: String -> + AsyncFunction("removeAdmin") Coroutine { id: String, inboxId: String -> withContext(Dispatchers.IO) { logV("removeAdmin") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.removeAdmin(inboxId) } } - AsyncFunction("removeSuperAdmin") Coroutine { clientAddress: String, id: String, inboxId: String -> + AsyncFunction("removeSuperAdmin") Coroutine { id: String, inboxId: String -> withContext(Dispatchers.IO) { logV("removeSuperAdmin") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) group?.removeSuperAdmin(inboxId) } } - AsyncFunction("processGroupMessage") Coroutine { clientAddress: String, id: String, encryptedMessage: String -> + AsyncFunction("processGroupMessage") Coroutine { inboxId: String, id: String, encryptedMessage: String -> withContext(Dispatchers.IO) { logV("processGroupMessage") - val client = clients[clientAddress] ?: throw XMTPException("No client") - val group = findGroup(clientAddress, id) + val client = clients[inboxId] ?: throw XMTPException("No client") + val group = findGroup(inboxId, id) val message = group?.processMessage(Base64.decode(encryptedMessage, NO_WRAP)) ?: throw XMTPException("could not decrypt message for $id") @@ -1011,10 +1014,10 @@ class XMTPModule : Module() { } } - AsyncFunction("processWelcomeMessage") Coroutine { clientAddress: String, encryptedMessage: String -> + AsyncFunction("processWelcomeMessage") Coroutine { inboxId: String, encryptedMessage: String -> withContext(Dispatchers.IO) { logV("processWelcomeMessage") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val group = client.conversations.fromWelcome(Base64.decode(encryptedMessage, NO_WRAP)) @@ -1022,54 +1025,54 @@ class XMTPModule : Module() { } } - Function("subscribeToConversations") { clientAddress: String -> + Function("subscribeToConversations") { inboxId: String -> logV("subscribeToConversations") - subscribeToConversations(clientAddress = clientAddress) + subscribeToConversations(inboxId = inboxId) } - Function("subscribeToGroups") { clientAddress: String -> + Function("subscribeToGroups") { inboxId: String -> logV("subscribeToGroups") - subscribeToGroups(clientAddress = clientAddress) + subscribeToGroups(inboxId = inboxId) } - Function("subscribeToAll") { clientAddress: String -> + Function("subscribeToAll") { inboxId: String -> logV("subscribeToAll") - subscribeToAll(clientAddress = clientAddress) + subscribeToAll(inboxId = inboxId) } - Function("subscribeToAllMessages") { clientAddress: String, includeGroups: Boolean -> + Function("subscribeToAllMessages") { inboxId: String, includeGroups: Boolean -> logV("subscribeToAllMessages") - subscribeToAllMessages(clientAddress = clientAddress, includeGroups = includeGroups) + subscribeToAllMessages(inboxId = inboxId, includeGroups = includeGroups) } - Function("subscribeToAllGroupMessages") { clientAddress: String -> + Function("subscribeToAllGroupMessages") { inboxId: String -> logV("subscribeToAllGroupMessages") - subscribeToAllGroupMessages(clientAddress = clientAddress) + subscribeToAllGroupMessages(inboxId = inboxId) } - AsyncFunction("subscribeToMessages") Coroutine { clientAddress: String, topic: String -> + AsyncFunction("subscribeToMessages") Coroutine { inboxId: String, topic: String -> withContext(Dispatchers.IO) { logV("subscribeToMessages") subscribeToMessages( - clientAddress = clientAddress, + inboxId = inboxId, topic = topic ) } } - AsyncFunction("subscribeToGroupMessages") Coroutine { clientAddress: String, id: String -> + AsyncFunction("subscribeToGroupMessages") Coroutine { inboxId: String, id: String -> withContext(Dispatchers.IO) { logV("subscribeToGroupMessages") subscribeToGroupMessages( - clientAddress = clientAddress, + inboxId = inboxId, id = id ) } } - Function("unsubscribeFromConversations") { clientAddress: String -> + Function("unsubscribeFromConversations") { inboxId: String -> logV("unsubscribeFromConversations") - subscriptions[getConversationsKey(clientAddress)]?.cancel() + subscriptions[getConversationsKey(inboxId)]?.cancel() } Function("unsubscribeFromGroups") { inboxId: String -> @@ -1077,9 +1080,9 @@ class XMTPModule : Module() { subscriptions[getGroupsKey(inboxId)]?.cancel() } - Function("unsubscribeFromAllMessages") { clientAddress: String -> + Function("unsubscribeFromAllMessages") { inboxId: String -> logV("unsubscribeFromAllMessages") - subscriptions[getMessagesKey(clientAddress)]?.cancel() + subscriptions[getMessagesKey(inboxId)]?.cancel() } Function("unsubscribeFromAllGroupMessages") { inboxId: String -> @@ -1087,21 +1090,21 @@ class XMTPModule : Module() { subscriptions[getGroupMessagesKey(inboxId)]?.cancel() } - AsyncFunction("unsubscribeFromMessages") Coroutine { clientAddress: String, topic: String -> + AsyncFunction("unsubscribeFromMessages") Coroutine { inboxId: String, topic: String -> withContext(Dispatchers.IO) { logV("unsubscribeFromMessages") unsubscribeFromMessages( - clientAddress = clientAddress, + inboxId = inboxId, topic = topic ) } } - AsyncFunction("unsubscribeFromGroupMessages") Coroutine { clientAddress: String, id: String -> + AsyncFunction("unsubscribeFromGroupMessages") Coroutine { inboxId: String, id: String -> withContext(Dispatchers.IO) { logV("unsubscribeFromGroupMessages") unsubscribeFromGroupMessages( - clientAddress = clientAddress, + inboxId = inboxId, id = id ) } @@ -1113,13 +1116,13 @@ class XMTPModule : Module() { xmtpPush?.register(token) } - Function("subscribePushTopics") { clientAddress: String, topics: List -> + Function("subscribePushTopics") { inboxId: String, topics: List -> logV("subscribePushTopics") if (topics.isNotEmpty()) { if (xmtpPush == null) { throw XMTPException("Push server not registered") } - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val hmacKeysResult = client.conversations.getHmacKeys() val subscriptions = topics.map { @@ -1144,14 +1147,14 @@ class XMTPModule : Module() { } } - AsyncFunction("decodeMessage") Coroutine { clientAddress: String, topic: String, encryptedMessage: String -> + AsyncFunction("decodeMessage") Coroutine { inboxId: String, topic: String, encryptedMessage: String -> withContext(Dispatchers.IO) { logV("decodeMessage") val encryptedMessageData = Base64.decode(encryptedMessage, NO_WRAP) val envelope = EnvelopeBuilder.buildFromString(topic, Date(), encryptedMessageData) val conversation = findConversation( - clientAddress = clientAddress, + inboxId = inboxId, topic = topic ) ?: throw XMTPException("no conversation found for $topic") @@ -1160,87 +1163,87 @@ class XMTPModule : Module() { } } - AsyncFunction("isAllowed") { clientAddress: String, address: String -> + AsyncFunction("isAllowed") { inboxId: String, address: String -> logV("isAllowed") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.contacts.isAllowed(address) } - Function("isDenied") { clientAddress: String, address: String -> + Function("isDenied") { inboxId: String, address: String -> logV("isDenied") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.contacts.isDenied(address) } - AsyncFunction("denyContacts") Coroutine { clientAddress: String, addresses: List -> + AsyncFunction("denyContacts") Coroutine { inboxId: String, addresses: List -> withContext(Dispatchers.IO) { logV("denyContacts") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.contacts.deny(addresses) } } - AsyncFunction("allowContacts") Coroutine { clientAddress: String, addresses: List -> + AsyncFunction("allowContacts") Coroutine { inboxId: String, addresses: List -> withContext(Dispatchers.IO) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.contacts.allow(addresses) } } - AsyncFunction("isInboxAllowed") { clientAddress: String, inboxId: String -> + AsyncFunction("isInboxAllowed") { clientInboxId: String, inboxId: String -> logV("isInboxIdAllowed") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[clientInboxId] ?: throw XMTPException("No client") client.contacts.isInboxAllowed(inboxId) } - AsyncFunction("isInboxDenied") { clientAddress: String, inboxId: String -> + AsyncFunction("isInboxDenied") { clientInboxId: String, inboxId: String -> logV("isInboxIdDenied") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[clientInboxId] ?: throw XMTPException("No client") client.contacts.isInboxDenied(inboxId) } - AsyncFunction("denyInboxes") Coroutine { clientAddress: String, inboxIds: List -> + AsyncFunction("denyInboxes") Coroutine { inboxId: String, inboxIds: List -> withContext(Dispatchers.IO) { logV("denyInboxIds") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.contacts.denyInboxes(inboxIds) } } - AsyncFunction("allowInboxes") Coroutine { clientAddress: String, inboxIds: List -> + AsyncFunction("allowInboxes") Coroutine { inboxId: String, inboxIds: List -> withContext(Dispatchers.IO) { logV("allowInboxIds") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.contacts.allowInboxes(inboxIds) } } - AsyncFunction("refreshConsentList") Coroutine { clientAddress: String -> + AsyncFunction("refreshConsentList") Coroutine { inboxId: String -> withContext(Dispatchers.IO) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val consentList = client.contacts.refreshConsentList() consentList.entries.map { ConsentWrapper.encode(it.value) } } } - AsyncFunction("conversationConsentState") Coroutine { clientAddress: String, conversationTopic: String -> + AsyncFunction("conversationConsentState") Coroutine { inboxId: String, conversationTopic: String -> withContext(Dispatchers.IO) { - val conversation = findConversation(clientAddress, conversationTopic) + val conversation = findConversation(inboxId, conversationTopic) ?: throw XMTPException("no conversation found for $conversationTopic") consentStateToString(conversation.consentState()) } } - AsyncFunction("groupConsentState") Coroutine { clientAddress: String, groupId: String -> + AsyncFunction("groupConsentState") Coroutine { inboxId: String, groupId: String -> withContext(Dispatchers.IO) { - val group = findGroup(clientAddress, groupId) + val group = findGroup(inboxId, groupId) ?: throw XMTPException("no group found for $groupId") consentStateToString(Conversation.Group(group).consentState()) } } - AsyncFunction("consentList") { clientAddress: String -> - val client = clients[clientAddress] ?: throw XMTPException("No client") + AsyncFunction("consentList") { inboxId: String -> + val client = clients[inboxId] ?: throw XMTPException("No client") client.contacts.consentList.entries.map { ConsentWrapper.encode(it.value) } } @@ -1254,29 +1257,29 @@ class XMTPModule : Module() { preEnableIdentityCallbackDeferred?.complete(Unit) } - AsyncFunction("allowGroups") Coroutine { clientAddress: String, groupIds: List -> + AsyncFunction("allowGroups") Coroutine { inboxId: String, groupIds: List -> logV("allowGroups") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val groupDataIds = groupIds.mapNotNull { Hex.hexStringToByteArray(it) } client.contacts.allowGroups(groupDataIds) } - AsyncFunction("denyGroups") Coroutine { clientAddress: String, groupIds: List -> + AsyncFunction("denyGroups") Coroutine { inboxId: String, groupIds: List -> logV("denyGroups") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val groupDataIds = groupIds.mapNotNull { Hex.hexStringToByteArray(it) } client.contacts.denyGroups(groupDataIds) } - AsyncFunction("isGroupAllowed") { clientAddress: String, groupId: String -> + AsyncFunction("isGroupAllowed") { inboxId: String, groupId: String -> logV("isGroupAllowed") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.contacts.isGroupAllowed(Hex.hexStringToByteArray(groupId)) } - AsyncFunction("isGroupDenied") { clientAddress: String, groupId: String -> + AsyncFunction("isGroupDenied") { inboxId: String, groupId: String -> logV("isGroupDenied") - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") client.contacts.isGroupDenied(Hex.hexStringToByteArray(groupId)) } } @@ -1286,12 +1289,12 @@ class XMTPModule : Module() { // private suspend fun findConversation( - clientAddress: String, + inboxId: String, topic: String, ): Conversation? { - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") - val cacheKey = "${clientAddress}:${topic}" + val cacheKey = "${inboxId}:${topic}" val cacheConversation = conversations[cacheKey] if (cacheConversation != null) { return cacheConversation @@ -1299,7 +1302,7 @@ class XMTPModule : Module() { val conversation = client.conversations.list() .firstOrNull { it.topic == topic } if (conversation != null) { - conversations[conversation.cacheKey(clientAddress)] = conversation + conversations[conversation.cacheKey(inboxId)] = conversation return conversation } } @@ -1307,12 +1310,12 @@ class XMTPModule : Module() { } private suspend fun findGroup( - clientAddress: String, + inboxId: String, id: String, ): Group? { - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") - val cacheKey = "${client.inboxId}:${id}" + val cacheKey = "${inboxId}:${id}" val cacheGroup = groups[cacheKey] if (cacheGroup != null) { return cacheGroup @@ -1320,18 +1323,18 @@ class XMTPModule : Module() { val group = client.conversations.listGroups() .firstOrNull { it.id.toHex() == id } if (group != null) { - groups[group.cacheKey(client.inboxId)] = group + groups[group.cacheKey(inboxId)] = group return group } } return null } - private fun subscribeToConversations(clientAddress: String) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + private fun subscribeToConversations(inboxId: String) { + val client = clients[inboxId] ?: throw XMTPException("No client") - subscriptions[getConversationsKey(clientAddress)]?.cancel() - subscriptions[getConversationsKey(clientAddress)] = CoroutineScope(Dispatchers.IO).launch { + subscriptions[getConversationsKey(inboxId)]?.cancel() + subscriptions[getConversationsKey(inboxId)] = CoroutineScope(Dispatchers.IO).launch { try { client.conversations.stream().collect { conversation -> run { @@ -1341,7 +1344,7 @@ class XMTPModule : Module() { sendEvent( "conversation", mapOf( - "clientAddress" to clientAddress, + "inboxId" to inboxId, "conversation" to ConversationWrapper.encodeToObj( client, conversation @@ -1352,13 +1355,13 @@ class XMTPModule : Module() { } } catch (e: Exception) { Log.e("XMTPModule", "Error in conversations subscription: $e") - subscriptions[getConversationsKey(clientAddress)]?.cancel() + subscriptions[getConversationsKey(inboxId)]?.cancel() } } } - private fun subscribeToGroups(clientAddress: String) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + private fun subscribeToGroups(inboxId: String) { + val client = clients[inboxId] ?: throw XMTPException("No client") subscriptions[getGroupsKey(client.inboxId)]?.cancel() subscriptions[getGroupsKey(client.inboxId)] = CoroutineScope(Dispatchers.IO).launch { @@ -1367,7 +1370,7 @@ class XMTPModule : Module() { sendEvent( "group", mapOf( - "clientAddress" to clientAddress, + "inboxId" to inboxId, "group" to GroupWrapper.encodeToObj(client, group) ) ) @@ -1379,17 +1382,17 @@ class XMTPModule : Module() { } } - private fun subscribeToAll(clientAddress: String) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + private fun subscribeToAll(inboxId: String) { + val client = clients[inboxId] ?: throw XMTPException("No client") - subscriptions[getConversationsKey(clientAddress)]?.cancel() - subscriptions[getConversationsKey(clientAddress)] = CoroutineScope(Dispatchers.IO).launch { + subscriptions[getConversationsKey(inboxId)]?.cancel() + subscriptions[getConversationsKey(inboxId)] = CoroutineScope(Dispatchers.IO).launch { try { client.conversations.streamAll().collect { conversation -> sendEvent( "conversationContainer", mapOf( - "clientAddress" to clientAddress, + "inboxId" to inboxId, "conversationContainer" to ConversationContainerWrapper.encodeToObj( client, conversation @@ -1399,71 +1402,71 @@ class XMTPModule : Module() { } } catch (e: Exception) { Log.e("XMTPModule", "Error in subscription to groups + conversations: $e") - subscriptions[getConversationsKey(clientAddress)]?.cancel() + subscriptions[getConversationsKey(inboxId)]?.cancel() } } } - private fun subscribeToAllMessages(clientAddress: String, includeGroups: Boolean = false) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + private fun subscribeToAllMessages(inboxId: String, includeGroups: Boolean = false) { + val client = clients[inboxId] ?: throw XMTPException("No client") - subscriptions[getMessagesKey(clientAddress)]?.cancel() - subscriptions[getMessagesKey(clientAddress)] = CoroutineScope(Dispatchers.IO).launch { + subscriptions[getMessagesKey(inboxId)]?.cancel() + subscriptions[getMessagesKey(inboxId)] = CoroutineScope(Dispatchers.IO).launch { try { client.conversations.streamAllDecryptedMessages(includeGroups = includeGroups) .collect { message -> sendEvent( "message", mapOf( - "clientAddress" to clientAddress, + "inboxId" to inboxId, "message" to DecodedMessageWrapper.encodeMap(message), ) ) } } catch (e: Exception) { Log.e("XMTPModule", "Error in all messages subscription: $e") - subscriptions[getMessagesKey(clientAddress)]?.cancel() + subscriptions[getMessagesKey(inboxId)]?.cancel() } } } - private fun subscribeToAllGroupMessages(clientAddress: String) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + private fun subscribeToAllGroupMessages(inboxId: String) { + val client = clients[inboxId] ?: throw XMTPException("No client") - subscriptions[getGroupMessagesKey(client.inboxId)]?.cancel() - subscriptions[getGroupMessagesKey(client.inboxId)] = CoroutineScope(Dispatchers.IO).launch { + subscriptions[getGroupMessagesKey(inboxId)]?.cancel() + subscriptions[getGroupMessagesKey(inboxId)] = CoroutineScope(Dispatchers.IO).launch { try { client.conversations.streamAllGroupDecryptedMessages().collect { message -> sendEvent( "allGroupMessage", mapOf( - "clientAddress" to clientAddress, + "inboxId" to inboxId, "message" to DecodedMessageWrapper.encodeMap(message), ) ) } } catch (e: Exception) { Log.e("XMTPModule", "Error in all group messages subscription: $e") - subscriptions[getGroupMessagesKey(client.inboxId)]?.cancel() + subscriptions[getGroupMessagesKey(inboxId)]?.cancel() } } } - private suspend fun subscribeToMessages(clientAddress: String, topic: String) { + private suspend fun subscribeToMessages(inboxId: String, topic: String) { val conversation = findConversation( - clientAddress = clientAddress, + inboxId = inboxId, topic = topic ) ?: return - subscriptions[conversation.cacheKey(clientAddress)]?.cancel() - subscriptions[conversation.cacheKey(clientAddress)] = + subscriptions[conversation.cacheKey(inboxId)]?.cancel() + subscriptions[conversation.cacheKey(inboxId)] = CoroutineScope(Dispatchers.IO).launch { try { conversation.streamDecryptedMessages().collect { message -> sendEvent( "conversationMessage", mapOf( - "clientAddress" to clientAddress, + "inboxId" to inboxId, "message" to DecodedMessageWrapper.encodeMap(message), "topic" to topic, ) @@ -1471,27 +1474,27 @@ class XMTPModule : Module() { } } catch (e: Exception) { Log.e("XMTPModule", "Error in messages subscription: $e") - subscriptions[conversation.cacheKey(clientAddress)]?.cancel() + subscriptions[conversation.cacheKey(inboxId)]?.cancel() } } } - private suspend fun subscribeToGroupMessages(clientAddress: String, id: String) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + private suspend fun subscribeToGroupMessages(inboxId: String, id: String) { + val client = clients[inboxId] ?: throw XMTPException("No client") val group = findGroup( - clientAddress = clientAddress, + inboxId = inboxId, id = id ) ?: return - subscriptions[group.cacheKey(client.inboxId)]?.cancel() - subscriptions[group.cacheKey(client.inboxId)] = + subscriptions[group.cacheKey(inboxId)]?.cancel() + subscriptions[group.cacheKey(inboxId)] = CoroutineScope(Dispatchers.IO).launch { try { group.streamDecryptedMessages().collect { message -> sendEvent( "groupMessage", mapOf( - "clientAddress" to clientAddress, + "inboxId" to inboxId, "message" to DecodedMessageWrapper.encodeMap(message), "groupId" to id, ) @@ -1499,21 +1502,21 @@ class XMTPModule : Module() { } } catch (e: Exception) { Log.e("XMTPModule", "Error in messages subscription: $e") - subscriptions[group.cacheKey(client.inboxId)]?.cancel() + subscriptions[group.cacheKey(inboxId)]?.cancel() } } } - private fun getMessagesKey(clientAddress: String): String { - return "messages:$clientAddress" + private fun getMessagesKey(inboxId: String): String { + return "messages:$inboxId" } private fun getGroupMessagesKey(inboxId: String): String { return "groupMessages:$inboxId" } - private fun getConversationsKey(clientAddress: String): String { - return "conversations:$clientAddress" + private fun getConversationsKey(inboxId: String): String { + return "conversations:$inboxId" } private fun getGroupsKey(inboxId: String): String { @@ -1521,29 +1524,29 @@ class XMTPModule : Module() { } private suspend fun unsubscribeFromMessages( - clientAddress: String, + inboxId: String, topic: String, ) { val conversation = findConversation( - clientAddress = clientAddress, + inboxId = inboxId, topic = topic ) ?: return - subscriptions[conversation.cacheKey(clientAddress)]?.cancel() + subscriptions[conversation.cacheKey(inboxId)]?.cancel() } private suspend fun unsubscribeFromGroupMessages( - clientAddress: String, + inboxId: String, id: String, ) { - val client = clients[clientAddress] ?: throw XMTPException("No client") + val client = clients[inboxId] ?: throw XMTPException("No client") val group = findGroup( - clientAddress = clientAddress, + inboxId = inboxId, id = id ) ?: return - subscriptions[group.cacheKey(client.inboxId)]?.cancel() + subscriptions[group.cacheKey(inboxId)]?.cancel() } private fun logV(msg: String) { diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/GroupWrapper.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/GroupWrapper.kt index 8240a444a..6214afbd6 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/GroupWrapper.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/GroupWrapper.kt @@ -17,6 +17,7 @@ class GroupWrapper { GroupPermissions.ADMIN_ONLY -> "admin_only" } return mapOf( + "clientAddress" to client.address, "id" to group.id.toHex(), "createdAt" to group.createdAt.time, "peerInboxIds" to group.peerInboxIds(), diff --git a/example/src/tests/groupTests.ts b/example/src/tests/groupTests.ts index b326e38e9..e6cf877b8 100644 --- a/example/src/tests/groupTests.ts +++ b/example/src/tests/groupTests.ts @@ -174,8 +174,8 @@ test('can make a MLS V3 client from bundle', async () => { const group1 = await client.conversations.newGroup([anotherClient.address]) assert( - group1.clientAddress === client.address, - `clients dont match ${client.address} and ${group1.clientAddress}` + group1.client.address === client.address, + `clients dont match ${client.address} and ${group1.client.address}` ) const bundle = await client.exportKeyBundle() @@ -211,8 +211,8 @@ test('can make a MLS V3 client from bundle', async () => { const group = await client2.conversations.newGroup([randomClient.address]) assert( - group.clientAddress === client2.address, - `clients dont match ${client2.address} and ${group.clientAddress}` + group.client.address === client2.address, + `clients dont match ${client2.address} and ${group.client.address}` ) return true diff --git a/example/src/tests/tests.ts b/example/src/tests/tests.ts index 388edd8fd..c76afc0b0 100644 --- a/example/src/tests/tests.ts +++ b/example/src/tests/tests.ts @@ -602,8 +602,8 @@ test('can stream messages', async () => { }) await delayToPropogate() - if (bobConvo.clientAddress !== bob.address) { - throw Error('Unexpected client address ' + bobConvo.clientAddress) + if (bobConvo.client.address !== bob.address) { + throw Error('Unexpected client address ' + bobConvo.client.address) } if (!bobConvo.topic) { throw Error('Missing topic ' + bobConvo.topic) diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 3dd958a4e..509277ada 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -3,12 +3,12 @@ import XMTP import LibXMTP extension Conversation { - static func cacheKeyForTopic(clientAddress: String, topic: String) -> String { - return "\(clientAddress):\(topic)" + static func cacheKeyForTopic(inboxId: String, topic: String) -> String { + return "\(inboxId):\(topic)" } - func cacheKey(_ clientAddress: String) -> String { - return Conversation.cacheKeyForTopic(clientAddress: clientAddress, topic: topic) + func cacheKey(_ inboxId: String) -> String { + return Conversation.cacheKeyForTopic(inboxId: inboxId, topic: topic) } } @@ -83,38 +83,38 @@ public class XMTPModule: Module { "groupMessage" ) - AsyncFunction("address") { (clientAddress: String) -> String in - if let client = await clientsManager.getClient(key: clientAddress) { + AsyncFunction("address") { (inboxId: String) -> String in + if let client = await clientsManager.getClient(key: inboxId) { return client.address } else { return "No Client." } } - AsyncFunction("inboxId") { (clientAddress: String) -> String in - if let client = await clientsManager.getClient(key: clientAddress) { + AsyncFunction("inboxId") { (inboxId: String) -> String in + if let client = await clientsManager.getClient(key: inboxId) { return client.inboxID } else { return "No Client." } } - AsyncFunction("deleteLocalDatabase") { (clientAddress: String) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("deleteLocalDatabase") { (inboxId: String) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } try client.deleteLocalDatabase() } - AsyncFunction("dropLocalDatabaseConnection") { (clientAddress: String) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("dropLocalDatabaseConnection") { (inboxId: String) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } try client.dropLocalDatabaseConnection() } - AsyncFunction("reconnectLocalDatabase") { (clientAddress: String) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("reconnectLocalDatabase") { (inboxId: String) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } try await client.reconnectLocalDatabase() @@ -140,7 +140,7 @@ public class XMTPModule: Module { let options = createClientConfig(env: environment, appVersion: appVersion, preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback, mlsAlpha: enableAlphaMls == true, encryptionKey: encryptionKeyData, dbDirectory: dbDirectory) let client = try await XMTP.Client.create(account: signer, options: options) - await clientsManager.updateClient(key: address, client: client) + await clientsManager.updateClient(key: client.inboxID, client: client) self.signer = nil sendEvent("authed", try ClientWrapper.encodeToObj(client)) } @@ -167,7 +167,7 @@ public class XMTPModule: Module { let options = createClientConfig(env: environment, appVersion: appVersion, preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback, mlsAlpha: enableAlphaMls == true, encryptionKey: encryptionKeyData, dbDirectory: dbDirectory) let client = try await Client.create(account: privateKey, options: options) - await clientsManager.updateClient(key: client.address, client: client) + await clientsManager.updateClient(key: client.inboxID, client: client) return try ClientWrapper.encodeToObj(client) } @@ -184,7 +184,7 @@ public class XMTPModule: Module { let encryptionKeyData = dbEncryptionKey == nil ? nil : Data(dbEncryptionKey!) let options = createClientConfig(env: environment, appVersion: appVersion, mlsAlpha: enableAlphaMls == true, encryptionKey: encryptionKeyData, dbDirectory: dbDirectory) let client = try await Client.from(bundle: bundle, options: options) - await clientsManager.updateClient(key: client.address, client: client) + await clientsManager.updateClient(key: client.inboxID, client: client) return try ClientWrapper.encodeToObj(client) } catch { print("ERRO! Failed to create client: \(error)") @@ -192,8 +192,8 @@ public class XMTPModule: Module { } } - AsyncFunction("sign") { (clientAddress: String, digest: [UInt8], keyType: String, preKeyIndex: Int) -> [UInt8] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("sign") { (inboxId: String, digest: [UInt8], keyType: String, preKeyIndex: Int) -> [UInt8] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let privateKeyBundle = client.keys @@ -205,8 +205,8 @@ public class XMTPModule: Module { return uint } - AsyncFunction("exportPublicKeyBundle") { (clientAddress: String) -> [UInt8] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("exportPublicKeyBundle") { (inboxId: String) -> [UInt8] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let bundle = try client.publicKeyBundle.serializedData() @@ -214,8 +214,8 @@ public class XMTPModule: Module { } // Export the client's serialized key bundle. - AsyncFunction("exportKeyBundle") { (clientAddress: String) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("exportKeyBundle") { (inboxId: String) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let bundle = try client.privateKeyBundle.serializedData().base64EncodedString() @@ -223,15 +223,15 @@ public class XMTPModule: Module { } // Export the conversation's serialized topic data. - AsyncFunction("exportConversationTopicData") { (clientAddress: String, topic: String) -> String in - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { + AsyncFunction("exportConversationTopicData") { (inboxId: String, topic: String) -> String in + guard let conversation = try await findConversation(inboxId: inboxId, topic: topic) else { throw Error.conversationNotFound(topic) } return try conversation.toTopicData().serializedData().base64EncodedString() } - AsyncFunction("getHmacKeys") { (clientAddress: String) -> [UInt8] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("getHmacKeys") { (inboxId: String) -> [UInt8] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let hmacKeys = await client.conversations.getHmacKeys() @@ -240,30 +240,30 @@ public class XMTPModule: Module { } // Import a conversation from its serialized topic data. - AsyncFunction("importConversationTopicData") { (clientAddress: String, topicData: String) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("importConversationTopicData") { (inboxId: String, topicData: String) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let data = try Xmtp_KeystoreApi_V1_TopicMap.TopicData( serializedData: Data(base64Encoded: Data(topicData.utf8))! ) let conversation = await client.conversations.importTopicData(data: data) - await conversationsManager.set(conversation.cacheKey(clientAddress), conversation) + await conversationsManager.set(conversation.cacheKey(inboxId), conversation) return try ConversationWrapper.encode(conversation, client: client) } // // Client API - AsyncFunction("canMessage") { (clientAddress: String, peerAddress: String) -> Bool in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("canMessage") { (inboxId: String, peerAddress: String) -> Bool in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } return try await client.canMessage(peerAddress) } - AsyncFunction("canGroupMessage") { (clientAddress: String, peerAddresses: [String]) -> [String: Bool] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("canGroupMessage") { (inboxId: String, peerAddresses: [String]) -> [String: Bool] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } @@ -279,8 +279,8 @@ public class XMTPModule: Module { } } - AsyncFunction("encryptAttachment") { (clientAddress: String, fileJson: String) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("encryptAttachment") { (inboxId: String, fileJson: String) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let file = try DecryptedLocalAttachment.fromJson(fileJson) @@ -306,8 +306,8 @@ public class XMTPModule: Module { ).toJson() } - AsyncFunction("decryptAttachment") { (clientAddress: String, encryptedFileJson: String) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("decryptAttachment") { (inboxId: String, encryptedFileJson: String) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let encryptedFile = try EncryptedLocalAttachment.fromJson(encryptedFileJson) @@ -331,8 +331,8 @@ public class XMTPModule: Module { ).toJson() } - AsyncFunction("sendEncodedContent") { (clientAddress: String, topic: String, encodedContentData: [UInt8]) -> String in - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { + AsyncFunction("sendEncodedContent") { (inboxId: String, topic: String, encodedContentData: [UInt8]) -> String in + guard let conversation = try await findConversation(inboxId: inboxId, topic: topic) else { throw Error.conversationNotFound("no conversation found for \(topic)") } @@ -341,8 +341,8 @@ public class XMTPModule: Module { return try await conversation.send(encodedContent: encodedContent) } - AsyncFunction("listConversations") { (clientAddress: String) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("listConversations") { (inboxId: String) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } @@ -351,7 +351,7 @@ public class XMTPModule: Module { return try await withThrowingTaskGroup(of: String.self) { group in for conversation in conversations { group.addTask { - await self.conversationsManager.set(conversation.cacheKey(clientAddress), conversation) + await self.conversationsManager.set(conversation.cacheKey(inboxId), conversation) return try ConversationWrapper.encode(conversation, client: client) } } @@ -365,15 +365,15 @@ public class XMTPModule: Module { } } - AsyncFunction("listGroups") { (clientAddress: String) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("listGroups") { (inboxId: String) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let groupList = try await client.conversations.groups() return try await withThrowingTaskGroup(of: String.self) { taskGroup in for group in groupList { taskGroup.addTask { - await self.groupsManager.set(group.cacheKey(clientAddress), group) + await self.groupsManager.set(group.cacheKey(inboxId), group) return try GroupWrapper.encode(group, client: client) } } @@ -387,8 +387,8 @@ public class XMTPModule: Module { } } - AsyncFunction("listAll") { (clientAddress: String) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("listAll") { (inboxId: String) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let conversationContainerList = try await client.conversations.list(includeGroups: true) @@ -396,7 +396,7 @@ public class XMTPModule: Module { return try await withThrowingTaskGroup(of: String.self) { taskGroup in for conversation in conversationContainerList { taskGroup.addTask { - await self.conversationsManager.set(conversation.cacheKey(clientAddress), conversation) + await self.conversationsManager.set(conversation.cacheKey(inboxId), conversation) return try ConversationContainerWrapper.encode(conversation, client: client) } } @@ -410,15 +410,15 @@ public class XMTPModule: Module { } } - AsyncFunction("loadMessages") { (clientAddress: String, topic: String, limit: Int?, before: Double?, after: Double?, direction: String?) -> [String] in + AsyncFunction("loadMessages") { (inboxId: String, topic: String, limit: Int?, before: Double?, after: Double?, direction: String?) -> [String] in let beforeDate = before != nil ? Date(timeIntervalSince1970: TimeInterval(before!) / 1000) : nil let afterDate = after != nil ? Date(timeIntervalSince1970: TimeInterval(after!) / 1000) : nil - guard let client = await clientsManager.getClient(key: clientAddress) else { + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { + guard let conversation = try await findConversation(inboxId: inboxId, topic: topic) else { throw Error.conversationNotFound("no conversation found for \(topic)") } @@ -441,8 +441,8 @@ public class XMTPModule: Module { } } - AsyncFunction("groupMessages") { (clientAddress: String, id: String, limit: Int?, before: Double?, after: Double?, direction: String?, deliveryStatus: String?) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("groupMessages") { (inboxId: String, id: String, limit: Int?, before: Double?, after: Double?, direction: String?, deliveryStatus: String?) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } @@ -453,7 +453,7 @@ public class XMTPModule: Module { let status: String = (deliveryStatus != nil) ? deliveryStatus!.lowercased() : "all" - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } let decryptedMessages = try await group.decryptedMessages( @@ -474,8 +474,8 @@ public class XMTPModule: Module { } } - AsyncFunction("loadBatchMessages") { (clientAddress: String, topics: [String]) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("loadBatchMessages") { (inboxId: String, topics: [String]) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } @@ -532,8 +532,8 @@ public class XMTPModule: Module { } } - AsyncFunction("sendMessage") { (clientAddress: String, conversationTopic: String, contentJson: String) -> String in - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: conversationTopic) else { + AsyncFunction("sendMessage") { (inboxId: String, conversationTopic: String, contentJson: String) -> String in + guard let conversation = try await findConversation(inboxId: inboxId, topic: conversationTopic) else { throw Error.conversationNotFound("no conversation found for \(conversationTopic)") } @@ -544,8 +544,8 @@ public class XMTPModule: Module { ) } - AsyncFunction("sendMessageToGroup") { (clientAddress: String, id: String, contentJson: String) -> String in - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + AsyncFunction("sendMessageToGroup") { (inboxId: String, id: String, contentJson: String) -> String in + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } @@ -557,11 +557,11 @@ public class XMTPModule: Module { } AsyncFunction("prepareMessage") { ( - clientAddress: String, + inboxId: String, conversationTopic: String, contentJson: String ) -> String in - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: conversationTopic) else { + guard let conversation = try await findConversation(inboxId: inboxId, topic: conversationTopic) else { throw Error.conversationNotFound("no conversation found for \(conversationTopic)") } let sending = try ContentJson.fromJson(contentJson) @@ -581,11 +581,11 @@ public class XMTPModule: Module { } AsyncFunction("prepareEncodedMessage") { ( - clientAddress: String, + inboxId: String, conversationTopic: String, encodedContentData: [UInt8] ) -> String in - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: conversationTopic) else { + guard let conversation = try await findConversation(inboxId: inboxId, topic: conversationTopic) else { throw Error.conversationNotFound("no conversation found for \(conversationTopic)") } let encodedContent = try EncodedContent(serializedData: Data(encodedContentData)) @@ -604,8 +604,8 @@ public class XMTPModule: Module { ).toJson() } - AsyncFunction("sendPreparedMessage") { (clientAddress: String, preparedLocalMessageJson: String) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("sendPreparedMessage") { (inboxId: String, preparedLocalMessageJson: String) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } guard let local = try? PreparedLocalMessage.fromJson(preparedLocalMessageJson) else { @@ -627,8 +627,8 @@ public class XMTPModule: Module { return prepared.messageID } - AsyncFunction("createConversation") { (clientAddress: String, peerAddress: String, contextJson: String, consentProofBytes: [UInt8]) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("createConversation") { (inboxId: String, peerAddress: String, contextJson: String, consentProofBytes: [UInt8]) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } @@ -659,8 +659,8 @@ public class XMTPModule: Module { } } - AsyncFunction("createGroup") { (clientAddress: String, peerAddresses: [String], permission: String) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("createGroup") { (inboxId: String, peerAddresses: [String], permission: String) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let permissionLevel: GroupPermissions = { @@ -680,23 +680,23 @@ public class XMTPModule: Module { } } - AsyncFunction("listMemberInboxIds") { (clientAddress: String, groupId: String) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("listMemberInboxIds") { (inboxId: String, groupId: String) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: groupId) else { + guard let group = try await findGroup(inboxId: inboxId, id: groupId) else { throw Error.conversationNotFound("no group found for \(groupId)") } return try group.members.map(\.inboxId) } - AsyncFunction("listGroupMembers") { (clientAddress: String, groupId: String) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("listGroupMembers") { (inboxId: String, groupId: String) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: groupId) else { + guard let group = try await findGroup(inboxId: inboxId, id: groupId) else { throw Error.conversationNotFound("no group found for \(groupId)") } return try group.members.compactMap { member in @@ -705,64 +705,64 @@ public class XMTPModule: Module { } - AsyncFunction("syncGroups") { (clientAddress: String) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("syncGroups") { (inboxId: String) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } try await client.conversations.sync() } - AsyncFunction("syncGroup") { (clientAddress: String, id: String) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("syncGroup") { (inboxId: String, id: String) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } try await group.sync() } - AsyncFunction("addGroupMembers") { (clientAddress: String, id: String, peerAddresses: [String]) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("addGroupMembers") { (inboxId: String, id: String, peerAddresses: [String]) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } try await group.addMembers(addresses: peerAddresses) } - AsyncFunction("removeGroupMembers") { (clientAddress: String, id: String, peerAddresses: [String]) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("removeGroupMembers") { (inboxId: String, id: String, peerAddresses: [String]) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } try await group.removeMembers(addresses: peerAddresses) } - AsyncFunction("addGroupMembersByInboxId") { (clientAddress: String, id: String, inboxIds: [String]) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("addGroupMembersByInboxId") { (inboxId: String, id: String, inboxIds: [String]) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } try await group.addMembersByInboxId(inboxIds: inboxIds) } - AsyncFunction("removeGroupMembersByInboxId") { (clientAddress: String, id: String, inboxIds: [String]) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("removeGroupMembersByInboxId") { (inboxId: String, id: String, inboxIds: [String]) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } @@ -770,146 +770,146 @@ public class XMTPModule: Module { } - AsyncFunction("groupName") { (clientAddress: String, id: String) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("groupName") { (inboxId: String, id: String) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } return try group.groupName() } - AsyncFunction("updateGroupName") { (clientAddress: String, id: String, groupName: String) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("updateGroupName") { (inboxId: String, id: String, groupName: String) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } try await group.updateGroupName(groupName: groupName) } - AsyncFunction("isGroupActive") { (clientAddress: String, id: String) -> Bool in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("isGroupActive") { (inboxId: String, id: String) -> Bool in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } return try group.isActive() } - AsyncFunction("addedByInboxId") { (clientAddress: String, id: String) -> String in - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + AsyncFunction("addedByInboxId") { (inboxId: String, id: String) -> String in + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } return try group.addedByInboxId() } - AsyncFunction("creatorInboxId") { (clientAddress: String, id: String) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("creatorInboxId") { (inboxId: String, id: String) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } return try group.creatorInboxId() } - AsyncFunction("isAdmin") { (clientAddress: String, id: String, inboxId: String) -> Bool in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("isAdmin") { (id: String, inboxId: String) -> Bool in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } return try group.isAdmin(inboxId: inboxId) } - AsyncFunction("isSuperAdmin") { (clientAddress: String, id: String, inboxId: String) -> Bool in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("isSuperAdmin") { (id: String, inboxId: String) -> Bool in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } return try group.isSuperAdmin(inboxId: inboxId) } - AsyncFunction("listAdmins") { (clientAddress: String, id: String) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("listAdmins") { (inboxId: String, id: String) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } return try group.listAdmins() } - AsyncFunction("listSuperAdmins") { (clientAddress: String, id: String) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("listSuperAdmins") { (inboxId: String, id: String) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } return try group.listSuperAdmins() } - AsyncFunction("addAdmin") { (clientAddress: String, id: String, inboxId: String) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("addAdmin") { (id: String, inboxId: String) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } try await group.addAdmin(inboxId: inboxId) } - AsyncFunction("addSuperAdmin") { (clientAddress: String, id: String, inboxId: String) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("addSuperAdmin") { (id: String, inboxId: String) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } try await group.addSuperAdmin(inboxId: inboxId) } - AsyncFunction("removeAdmin") { (clientAddress: String, id: String, inboxId: String) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("removeAdmin") { (id: String, inboxId: String) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } try await group.removeAdmin(inboxId: inboxId) } - AsyncFunction("removeSuperAdmin") { (clientAddress: String, id: String, inboxId: String) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("removeSuperAdmin") { (id: String, inboxId: String) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } try await group.removeSuperAdmin(inboxId: inboxId) } - AsyncFunction("processGroupMessage") { (clientAddress: String, id: String, encryptedMessage: String) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("processGroupMessage") { (inboxId: String, id: String, encryptedMessage: String) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { throw Error.conversationNotFound("no group found for \(id)") } @@ -920,8 +920,8 @@ public class XMTPModule: Module { return try DecodedMessageWrapper.encode(decodedMessage, client: client) } - AsyncFunction("processWelcomeMessage") { (clientAddress: String, encryptedMessage: String) -> String in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("processWelcomeMessage") { (inboxId: String, encryptedMessage: String) -> String in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } guard let encryptedMessageData = Data(base64Encoded: Data(encryptedMessage.utf8)) else { @@ -934,40 +934,40 @@ public class XMTPModule: Module { return try GroupWrapper.encode(group, client: client) } - AsyncFunction("subscribeToConversations") { (clientAddress: String) in - try await subscribeToConversations(clientAddress: clientAddress) + AsyncFunction("subscribeToConversations") { (inboxId: String) in + try await subscribeToConversations(inboxId: inboxId) } - AsyncFunction("subscribeToAllMessages") { (clientAddress: String, includeGroups: Bool) in - try await subscribeToAllMessages(clientAddress: clientAddress, includeGroups: includeGroups) + AsyncFunction("subscribeToAllMessages") { (inboxId: String, includeGroups: Bool) in + try await subscribeToAllMessages(inboxId: inboxId, includeGroups: includeGroups) } - AsyncFunction("subscribeToAllGroupMessages") { (clientAddress: String) in - try await subscribeToAllGroupMessages(clientAddress: clientAddress) + AsyncFunction("subscribeToAllGroupMessages") { (inboxId: String) in + try await subscribeToAllGroupMessages(inboxId: inboxId) } - AsyncFunction("subscribeToMessages") { (clientAddress: String, topic: String) in - try await subscribeToMessages(clientAddress: clientAddress, topic: topic) + AsyncFunction("subscribeToMessages") { (inboxId: String, topic: String) in + try await subscribeToMessages(inboxId: inboxId, topic: topic) } - AsyncFunction("subscribeToGroups") { (clientAddress: String) in - try await subscribeToGroups(clientAddress: clientAddress) + AsyncFunction("subscribeToGroups") { (inboxId: String) in + try await subscribeToGroups(inboxId: inboxId) } - AsyncFunction("subscribeToAll") { (clientAddress: String) in - try await subscribeToAll(clientAddress: clientAddress) + AsyncFunction("subscribeToAll") { (inboxId: String) in + try await subscribeToAll(inboxId: inboxId) } - AsyncFunction("subscribeToGroupMessages") { (clientAddress: String, id: String) in - try await subscribeToGroupMessages(clientAddress: clientAddress, id: id) + AsyncFunction("subscribeToGroupMessages") { (inboxId: String, id: String) in + try await subscribeToGroupMessages(inboxId: inboxId, id: id) } - AsyncFunction("unsubscribeFromConversations") { (clientAddress: String) in - await subscriptionsManager.get(getConversationsKey(clientAddress: clientAddress))?.cancel() + AsyncFunction("unsubscribeFromConversations") { (inboxId: String) in + await subscriptionsManager.get(getConversationsKey(inboxId: inboxId))?.cancel() } - AsyncFunction("unsubscribeFromAllMessages") { (clientAddress: String) in - await subscriptionsManager.get(getMessagesKey(clientAddress: clientAddress))?.cancel() + AsyncFunction("unsubscribeFromAllMessages") { (inboxId: String) in + await subscriptionsManager.get(getMessagesKey(inboxId: inboxId))?.cancel() } AsyncFunction("unsubscribeFromAllGroupMessages") { (inboxId: String) in @@ -975,12 +975,12 @@ public class XMTPModule: Module { } - AsyncFunction("unsubscribeFromMessages") { (clientAddress: String, topic: String) in - try await unsubscribeFromMessages(clientAddress: clientAddress, topic: topic) + AsyncFunction("unsubscribeFromMessages") { (inboxId: String, topic: String) in + try await unsubscribeFromMessages(inboxId: inboxId, topic: topic) } - AsyncFunction("unsubscribeFromGroupMessages") { (clientAddress: String, id: String) in - try await unsubscribeFromGroupMessages(clientAddress: clientAddress, id: id) + AsyncFunction("unsubscribeFromGroupMessages") { (inboxId: String, id: String) in + try await unsubscribeFromGroupMessages(inboxId: inboxId, id: id) } AsyncFunction("unsubscribeFromGroups") { (inboxId: String) in @@ -996,9 +996,9 @@ public class XMTPModule: Module { } } - AsyncFunction("subscribePushTopics") { (clientAddress: String, topics: [String]) in + AsyncFunction("subscribePushTopics") { (inboxId: String, topics: [String]) in do { - guard let client = await clientsManager.getClient(key: clientAddress) else { + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let hmacKeysResult = await client.conversations.getHmacKeys() @@ -1024,7 +1024,7 @@ public class XMTPModule: Module { } } - AsyncFunction("decodeMessage") { (clientAddress: String, topic: String, encryptedMessage: String) -> String in + AsyncFunction("decodeMessage") { (inboxId: String, topic: String, encryptedMessage: String) -> String in guard let encryptedMessageData = Data(base64Encoded: Data(encryptedMessage.utf8)) else { throw Error.noMessage } @@ -1034,75 +1034,75 @@ public class XMTPModule: Module { envelope.contentTopic = topic } - guard let client = await clientsManager.getClient(key: clientAddress) else { + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { + guard let conversation = try await findConversation(inboxId: inboxId, topic: topic) else { throw Error.conversationNotFound("no conversation found for \(topic)") } let decodedMessage = try conversation.decrypt(envelope) return try DecodedMessageWrapper.encode(decodedMessage, client: client) } - AsyncFunction("isAllowed") { (clientAddress: String, address: String) -> Bool in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("isAllowed") { (inboxId: String, address: String) -> Bool in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } return await client.contacts.isAllowed(address) } - AsyncFunction("isDenied") { (clientAddress: String, address: String) -> Bool in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("isDenied") { (inboxId: String, address: String) -> Bool in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } return await client.contacts.isDenied(address) } - AsyncFunction("denyContacts") { (clientAddress: String, addresses: [String]) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("denyContacts") { (inboxId: String, addresses: [String]) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } try await client.contacts.deny(addresses: addresses) } - AsyncFunction("allowContacts") { (clientAddress: String, addresses: [String]) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("allowContacts") { (inboxId: String, addresses: [String]) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } try await client.contacts.allow(addresses: addresses) } - AsyncFunction("isInboxAllowed") { (clientAddress: String, inboxId: String) -> Bool in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("isInboxAllowed") { (clientInboxId: String, inboxId: String) -> Bool in + guard let client = await clientsManager.getClient(key: clientInboxId) else { throw Error.noClient } return await client.contacts.isInboxAllowed(inboxId: inboxId) } - AsyncFunction("isInboxDenied") { (clientAddress: String, inboxId: String) -> Bool in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("isInboxDenied") { (clientInboxId: String,inboxId: String) -> Bool in + guard let client = await clientsManager.getClient(key: clientInboxId) else { throw Error.noClient } return await client.contacts.isInboxDenied(inboxId: inboxId) } - AsyncFunction("denyInboxes") { (clientAddress: String, inboxIds: [String]) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("denyInboxes") { (inboxId: String, inboxIds: [String]) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } try await client.contacts.denyInboxes(inboxIds: inboxIds) } - AsyncFunction("allowInboxes") { (clientAddress: String, inboxIds: [String]) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("allowInboxes") { (inboxId: String, inboxIds: [String]) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } try await client.contacts.allowInboxes(inboxIds: inboxIds) } - AsyncFunction("refreshConsentList") { (clientAddress: String) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("refreshConsentList") { (inboxId: String) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let consentList = try await client.contacts.refreshConsentList() @@ -1112,22 +1112,22 @@ public class XMTPModule: Module { } } - AsyncFunction("conversationConsentState") { (clientAddress: String, conversationTopic: String) -> String in - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: conversationTopic) else { + AsyncFunction("conversationConsentState") { (inboxId: String, conversationTopic: String) -> String in + guard let conversation = try await findConversation(inboxId: inboxId, topic: conversationTopic) else { throw Error.conversationNotFound(conversationTopic) } return try ConsentWrapper.consentStateToString(state: await conversation.consentState()) } - AsyncFunction("groupConsentState") { (clientAddress: String, groupId: String) -> String in - guard let group = try await findGroup(clientAddress: clientAddress, id: groupId) else { + AsyncFunction("groupConsentState") { (inboxId: String, groupId: String) -> String in + guard let group = try await findGroup(inboxId: inboxId, id: groupId) else { throw Error.conversationNotFound("no group found for \(groupId)") } return try ConsentWrapper.consentStateToString(state: await XMTP.Conversation.group(group).consentState()) } - AsyncFunction("consentList") { (clientAddress: String) -> [String] in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("consentList") { (inboxId: String) -> [String] in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let entries = await client.contacts.consentList.entriesManager.map @@ -1151,24 +1151,24 @@ public class XMTPModule: Module { } } - AsyncFunction("allowGroups") { (clientAddress: String, groupIds: [String]) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("allowGroups") { (inboxId: String, groupIds: [String]) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let groupDataIds = groupIds.compactMap { Data(hex: $0) } try await client.contacts.allowGroups(groupIds: groupDataIds) } - AsyncFunction("denyGroups") { (clientAddress: String, groupIds: [String]) in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("denyGroups") { (inboxId: String, groupIds: [String]) in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } let groupDataIds = groupIds.compactMap { Data(hex: $0) } try await client.contacts.denyGroups(groupIds: groupDataIds) } - AsyncFunction("isGroupAllowed") { (clientAddress: String, groupId: String) -> Bool in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("isGroupAllowed") { (inboxId: String, groupId: String) -> Bool in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } guard let groupDataId = Data(hex: groupId) else { @@ -1177,8 +1177,8 @@ public class XMTPModule: Module { return await client.contacts.isGroupAllowed(groupId: groupDataId) } - AsyncFunction("isGroupDenied") { (clientAddress: String, groupId: String) -> Bool in - guard let client = await clientsManager.getClient(key: clientAddress) else { + AsyncFunction("isGroupDenied") { (inboxId: String, groupId: String) -> Bool in + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.invalidString } guard let groupDataId = Data(hex: groupId) else { @@ -1216,12 +1216,12 @@ public class XMTPModule: Module { } } - func findConversation(clientAddress: String, topic: String) async throws -> Conversation? { - guard let client = await clientsManager.getClient(key: clientAddress) else { + func findConversation(inboxId: String, topic: String) async throws -> Conversation? { + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - let cacheKey = Conversation.cacheKeyForTopic(clientAddress: clientAddress, topic: topic) + let cacheKey = Conversation.cacheKeyForTopic(inboxId: inboxId, topic: topic) if let conversation = await conversationsManager.get(cacheKey) { return conversation } else if let conversation = try await client.conversations.list().first(where: { $0.topic == topic }) { @@ -1232,8 +1232,8 @@ public class XMTPModule: Module { return nil } - func findGroup(clientAddress: String, id: String) async throws -> XMTP.Group? { - guard let client = await clientsManager.getClient(key: clientAddress) else { + func findGroup(inboxId: String, id: String) async throws -> XMTP.Group? { + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } @@ -1249,39 +1249,39 @@ public class XMTPModule: Module { } - func subscribeToConversations(clientAddress: String) async throws { - guard let client = await clientsManager.getClient(key: clientAddress) else { + func subscribeToConversations(inboxId: String) async throws { + guard let client = await clientsManager.getClient(key: inboxId) else { return } - await subscriptionsManager.get(getConversationsKey(clientAddress: clientAddress))?.cancel() - await subscriptionsManager.set(getConversationsKey(clientAddress: clientAddress), Task { + await subscriptionsManager.get(getConversationsKey(inboxId: inboxId))?.cancel() + await subscriptionsManager.set(getConversationsKey(inboxId: inboxId), Task { do { for try await conversation in await client.conversations.stream() { try sendEvent("conversation", [ - "clientAddress": clientAddress, + "inboxId": inboxId, "conversation": ConversationWrapper.encodeToObj(conversation, client: client), ]) } } catch { print("Error in conversations subscription: \(error)") - await subscriptionsManager.get(getConversationsKey(clientAddress: clientAddress))?.cancel() + await subscriptionsManager.get(getConversationsKey(inboxId: inboxId))?.cancel() } }) } - func subscribeToAllMessages(clientAddress: String, includeGroups: Bool = false) async throws { - guard let client = await clientsManager.getClient(key: clientAddress) else { + func subscribeToAllMessages(inboxId: String, includeGroups: Bool = false) async throws { + guard let client = await clientsManager.getClient(key: inboxId) else { return } - await subscriptionsManager.get(getMessagesKey(clientAddress: clientAddress))?.cancel() - await subscriptionsManager.set(getMessagesKey(clientAddress: clientAddress), Task { + await subscriptionsManager.get(getMessagesKey(inboxId: inboxId))?.cancel() + await subscriptionsManager.set(getMessagesKey(inboxId: inboxId), Task { do { for try await message in await client.conversations.streamAllDecryptedMessages(includeGroups: includeGroups) { do { try sendEvent("message", [ - "clientAddress": clientAddress, + "inboxId": inboxId, "message": DecodedMessageWrapper.encodeToObj(message, client: client), ]) } catch { @@ -1290,13 +1290,13 @@ public class XMTPModule: Module { } } catch { print("Error in all messages subscription: \(error)") - await subscriptionsManager.get(getMessagesKey(clientAddress: clientAddress))?.cancel() + await subscriptionsManager.get(getMessagesKey(inboxId: inboxId))?.cancel() } }) } - func subscribeToAllGroupMessages(clientAddress: String) async throws { - guard let client = await clientsManager.getClient(key: clientAddress) else { + func subscribeToAllGroupMessages(inboxId: String) async throws { + guard let client = await clientsManager.getClient(key: inboxId) else { return } @@ -1306,7 +1306,7 @@ public class XMTPModule: Module { for try await message in await client.conversations.streamAllGroupDecryptedMessages() { do { try sendEvent("allGroupMessage", [ - "clientAddress": clientAddress, + "inboxId": inboxId, "message": DecodedMessageWrapper.encodeToObj(message, client: client), ]) } catch { @@ -1315,27 +1315,27 @@ public class XMTPModule: Module { } } catch { print("Error in all messages subscription: \(error)") - await subscriptionsManager.get(getMessagesKey(clientAddress: clientAddress))?.cancel() + await subscriptionsManager.get(getMessagesKey(inboxId: inboxId))?.cancel() } }) } - func subscribeToMessages(clientAddress: String, topic: String) async throws { - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { + func subscribeToMessages(inboxId: String, topic: String) async throws { + guard let conversation = try await findConversation(inboxId: inboxId, topic: topic) else { return } - guard let client = await clientsManager.getClient(key: clientAddress) else { + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } - await subscriptionsManager.get(conversation.cacheKey(clientAddress))?.cancel() - await subscriptionsManager.set(conversation.cacheKey(clientAddress), Task { + await subscriptionsManager.get(conversation.cacheKey(inboxId))?.cancel() + await subscriptionsManager.set(conversation.cacheKey(inboxId), Task { do { for try await message in conversation.streamDecryptedMessages() { do { try sendEvent("conversationMessage", [ - "clientAddress": clientAddress, + "inboxId": inboxId, "message": DecodedMessageWrapper.encodeToObj(message, client: client), "topic": topic ]) @@ -1345,13 +1345,13 @@ public class XMTPModule: Module { } } catch { print("Error in messages subscription: \(error)") - await subscriptionsManager.get(conversation.cacheKey(clientAddress))?.cancel() + await subscriptionsManager.get(conversation.cacheKey(inboxId))?.cancel() } }) } - func subscribeToGroups(clientAddress: String) async throws { - guard let client = await clientsManager.getClient(key: clientAddress) else { + func subscribeToGroups(inboxId: String) async throws { + guard let client = await clientsManager.getClient(key: inboxId) else { return } await subscriptionsManager.get(getGroupsKey(inboxId: client.inboxID))?.cancel() @@ -1359,7 +1359,7 @@ public class XMTPModule: Module { do { for try await group in try await client.conversations.streamGroups() { try sendEvent("group", [ - "clientAddress": clientAddress, + "inboxId": inboxId, "group": GroupWrapper.encodeToObj(group, client: client), ]) } @@ -1370,33 +1370,33 @@ public class XMTPModule: Module { }) } - func subscribeToAll(clientAddress: String) async throws { - guard let client = await clientsManager.getClient(key: clientAddress) else { + func subscribeToAll(inboxId: String) async throws { + guard let client = await clientsManager.getClient(key: inboxId) else { return } - await subscriptionsManager.get(getConversationsKey(clientAddress: clientAddress))?.cancel() - await subscriptionsManager.set(getConversationsKey(clientAddress: clientAddress), Task { + await subscriptionsManager.get(getConversationsKey(inboxId: inboxId))?.cancel() + await subscriptionsManager.set(getConversationsKey(inboxId: inboxId), Task { do { for try await conversation in await client.conversations.streamAll() { try sendEvent("conversationContainer", [ - "clientAddress": clientAddress, + "inboxId": inboxId, "conversationContainer": ConversationContainerWrapper.encodeToObj(conversation, client: client), ]) } } catch { print("Error in all conversations subscription: \(error)") - await subscriptionsManager.get(getConversationsKey(clientAddress: clientAddress))?.cancel() + await subscriptionsManager.get(getConversationsKey(inboxId: inboxId))?.cancel() } }) } - func subscribeToGroupMessages(clientAddress: String, id: String) async throws { - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + func subscribeToGroupMessages(inboxId: String, id: String) async throws { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { return } - guard let client = await clientsManager.getClient(key: clientAddress) else { + guard let client = await clientsManager.getClient(key: inboxId) else { throw Error.noClient } @@ -1406,7 +1406,7 @@ public class XMTPModule: Module { for try await message in group.streamDecryptedMessages() { do { try sendEvent("groupMessage", [ - "clientAddress": clientAddress, + "inboxId": inboxId, "message": DecodedMessageWrapper.encodeToObj(message, client: client), "groupId": id, ]) @@ -1416,38 +1416,38 @@ public class XMTPModule: Module { } } catch { print("Error in group messages subscription: \(error)") - await subscriptionsManager.get(group.cacheKey(clientAddress))?.cancel() + await subscriptionsManager.get(group.cacheKey(inboxId))?.cancel() } }) } - func unsubscribeFromMessages(clientAddress: String, topic: String) async throws { - guard let conversation = try await findConversation(clientAddress: clientAddress, topic: topic) else { + func unsubscribeFromMessages(inboxId: String, topic: String) async throws { + guard let conversation = try await findConversation(inboxId: inboxId, topic: topic) else { return } - await subscriptionsManager.get(conversation.cacheKey(clientAddress))?.cancel() + await subscriptionsManager.get(conversation.cacheKey(inboxId))?.cancel() } - func unsubscribeFromGroupMessages(clientAddress: String, id: String) async throws { - guard let group = try await findGroup(clientAddress: clientAddress, id: id) else { + func unsubscribeFromGroupMessages(inboxId: String, id: String) async throws { + guard let group = try await findGroup(inboxId: inboxId, id: id) else { return } - await subscriptionsManager.get(group.cacheKey(clientAddress))?.cancel() + await subscriptionsManager.get(group.cacheKey(inboxId))?.cancel() } - func getMessagesKey(clientAddress: String) -> String { - return "messages:\(clientAddress)" + func getMessagesKey(inboxId: String) -> String { + return "messages:\(inboxId)" } func getGroupMessagesKey(inboxId: String) -> String { return "groupMessages:\(inboxId)" } - func getConversationsKey(clientAddress: String) -> String { - return "conversations:\(clientAddress)" + func getConversationsKey(inboxId: String) -> String { + return "conversations:\(inboxId)" } func getGroupsKey(inboxId: String) -> String { diff --git a/src/index.ts b/src/index.ts index 734909119..f5ef980b3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,7 @@ import type { Query } from './lib/Query' import { ConversationSendPayload } from './lib/types' import { DefaultContentTypes } from './lib/types/DefaultContentType' import { getAddress } from './utils/address' +import { InboxId } from './lib/Client' export * from './context' export * from './hooks' @@ -45,20 +46,20 @@ export function inboxId(): string { return XMTPModule.inboxId() } -export async function deleteLocalDatabase(address: string) { - return XMTPModule.deleteLocalDatabase(address) +export async function deleteLocalDatabase(inboxId: string) { + return XMTPModule.deleteLocalDatabase(inboxId) } -export async function dropLocalDatabaseConnection(address: string) { - return XMTPModule.dropLocalDatabaseConnection(address) +export async function dropLocalDatabaseConnection(inboxId: string) { + return XMTPModule.dropLocalDatabaseConnection(inboxId) } -export async function reconnectLocalDatabase(address: string) { - return XMTPModule.reconnectLocalDatabase(address) +export async function reconnectLocalDatabase(inboxId: string) { + return XMTPModule.reconnectLocalDatabase(inboxId) } export async function auth( - address: string, + inboxId: string, environment: 'local' | 'dev' | 'production', appVersion?: string | undefined, hasCreateIdentityCallback?: boolean | undefined, @@ -68,7 +69,7 @@ export async function auth( dbDirectory?: string | undefined ) { return await XMTPModule.auth( - address, + inboxId, environment, appVersion, hasCreateIdentityCallback, @@ -132,7 +133,7 @@ export async function createGroup< client, JSON.parse( await XMTPModule.createGroup( - client.address, + client.inboxId, peerAddresses, permissionLevel ) @@ -143,22 +144,22 @@ export async function createGroup< export async function listGroups< ContentTypes extends DefaultContentTypes = DefaultContentTypes, >(client: Client): Promise[]> { - return (await XMTPModule.listGroups(client.address)).map((json: string) => { + return (await XMTPModule.listGroups(client.inboxId)).map((json: string) => { return new Group(client, JSON.parse(json)) }) } export async function listMemberInboxIds< ContentTypes extends DefaultContentTypes = DefaultContentTypes, ->(client: Client, id: string): Promise { - return XMTPModule.listMemberInboxIds(client.address, id) +>(client: Client, id: string): Promise { + return XMTPModule.listMemberInboxIds(client.inboxId, id) } export async function listGroupMembers( - clientAddress: string, + inboxId: string, id: string ): Promise { - const members = await XMTPModule.listGroupMembers(clientAddress, id) + const members = await XMTPModule.listGroupMembers(inboxId, id) return members.map((json: string) => { return Member.from(json) @@ -166,16 +167,12 @@ export async function listGroupMembers( } export async function sendMessageToGroup( - clientAddress: string, + inboxId: string, groupId: string, content: any ): Promise { const contentJson = JSON.stringify(content) - return await XMTPModule.sendMessageToGroup( - clientAddress, - groupId, - contentJson - ) + return await XMTPModule.sendMessageToGroup(inboxId, groupId, contentJson) } export async function groupMessages< @@ -193,7 +190,7 @@ export async function groupMessages< deliveryStatus?: MessageDeliveryStatus | undefined ): Promise[]> { const messages = await XMTPModule.groupMessages( - client.address, + client.inboxId, id, limit, before, @@ -206,83 +203,80 @@ export async function groupMessages< }) } -export async function syncGroups(clientAddress: string) { - await XMTPModule.syncGroups(clientAddress) +export async function syncGroups(inboxId: string) { + await XMTPModule.syncGroups(inboxId) } -export async function syncGroup(clientAddress: string, id: string) { - await XMTPModule.syncGroup(clientAddress, id) +export async function syncGroup(inboxId: string, id: string) { + await XMTPModule.syncGroup(inboxId, id) } -export async function subscribeToGroupMessages( - clientAddress: string, - id: string -) { - return await XMTPModule.subscribeToGroupMessages(clientAddress, id) +export async function subscribeToGroupMessages(inboxId: string, id: string) { + return await XMTPModule.subscribeToGroupMessages(inboxId, id) } export async function unsubscribeFromGroupMessages( - clientAddress: string, + inboxId: string, id: string ) { - return await XMTPModule.unsubscribeFromGroupMessages(clientAddress, id) + return await XMTPModule.unsubscribeFromGroupMessages(inboxId, id) } export async function addGroupMembers( - clientAddress: string, + inboxId: string, id: string, addresses: string[] ): Promise { - return XMTPModule.addGroupMembers(clientAddress, id, addresses) + return XMTPModule.addGroupMembers(inboxId, id, addresses) } export async function removeGroupMembers( - clientAddress: string, + inboxId: string, id: string, addresses: string[] ): Promise { - return XMTPModule.removeGroupMembers(clientAddress, id, addresses) + return XMTPModule.removeGroupMembers(inboxId, id, addresses) } export async function addGroupMembersByInboxId( - clientAddress: string, + inboxId: string, id: string, inboxIds: string[] ): Promise { - return XMTPModule.addGroupMembersByInboxId(clientAddress, id, inboxIds) + return XMTPModule.addGroupMembersByInboxId(inboxId, id, inboxIds) } export async function removeGroupMembersByInboxId( - clientAddress: string, + inboxId: string, id: string, inboxIds: string[] ): Promise { - return XMTPModule.removeGroupMembersByInboxId(clientAddress, id, inboxIds) + return XMTPModule.removeGroupMembersByInboxId(inboxId, id, inboxIds) } export function groupName( - address: string, + inboxId: string, id: string ): string | PromiseLike { - return XMTPModule.groupName(address, id) + return XMTPModule.groupName(inboxId, id) } export function updateGroupName( - address: string, + inboxId: string, id: string, groupName: string ): Promise { - return XMTPModule.updateGroupName(address, id, groupName) + return XMTPModule.updateGroupName(inboxId, id, groupName) } export async function sign( - clientAddress: string, + inboxId: string, digest: Uint8Array, keyType: string, preKeyIndex: number = 0 ): Promise { const signatureArray = await XMTPModule.sign( - clientAddress, + inboxId, Array.from(digest), keyType, preKeyIndex @@ -291,31 +285,30 @@ export async function sign( } export async function exportPublicKeyBundle( - clientAddress: string + inboxId: string ): Promise { - const publicBundleArray = - await XMTPModule.exportPublicKeyBundle(clientAddress) + const publicBundleArray = await XMTPModule.exportPublicKeyBundle(inboxId) return new Uint8Array(publicBundleArray) } -export async function exportKeyBundle(clientAddress: string): Promise { - return await XMTPModule.exportKeyBundle(clientAddress) +export async function exportKeyBundle(inboxId: string): Promise { + return await XMTPModule.exportKeyBundle(inboxId) } export async function exportConversationTopicData( - clientAddress: string, + inboxId: string, conversationTopic: string ): Promise { return await XMTPModule.exportConversationTopicData( - clientAddress, + inboxId, conversationTopic ) } export async function getHmacKeys( - clientAddress: string + inboxId: string ): Promise { - const hmacKeysArray = await XMTPModule.getHmacKeys(clientAddress) + const hmacKeysArray = await XMTPModule.getHmacKeys(inboxId) const array = new Uint8Array(hmacKeysArray) return keystore.GetConversationHmacKeysResponse.decode(array) } @@ -327,24 +320,24 @@ export async function importConversationTopicData< topicData: string ): Promise> { const json = await XMTPModule.importConversationTopicData( - client.address, + client.inboxId, topicData ) return new Conversation(client, JSON.parse(json)) } export async function canMessage( - clientAddress: string, + inboxId: string, peerAddress: string ): Promise { - return await XMTPModule.canMessage(clientAddress, getAddress(peerAddress)) + return await XMTPModule.canMessage(inboxId, getAddress(peerAddress)) } export async function canGroupMessage( - clientAddress: string, + inboxId: string, peerAddresses: string[] ): Promise<{ [key: string]: boolean }> { - return await XMTPModule.canGroupMessage(clientAddress, peerAddresses) + return await XMTPModule.canGroupMessage(inboxId, peerAddresses) } export async function staticCanMessage( @@ -360,24 +353,24 @@ export async function staticCanMessage( } export async function encryptAttachment( - clientAddress: string, + inboxId: string, file: DecryptedLocalAttachment ): Promise { const fileJson = JSON.stringify(file) const encryptedFileJson = await XMTPModule.encryptAttachment( - clientAddress, + inboxId, fileJson ) return JSON.parse(encryptedFileJson) } export async function decryptAttachment( - clientAddress: string, + inboxId: string, encryptedFile: EncryptedLocalAttachment ): Promise { const encryptedFileJson = JSON.stringify(encryptedFile) const fileJson = await XMTPModule.decryptAttachment( - clientAddress, + inboxId, encryptedFileJson ) return JSON.parse(fileJson) @@ -386,7 +379,7 @@ export async function decryptAttachment( export async function listConversations< ContentTypes extends DefaultContentTypes = DefaultContentTypes, >(client: Client): Promise[]> { - return (await XMTPModule.listConversations(client.address)).map( + return (await XMTPModule.listConversations(client.inboxId)).map( (json: string) => { return new Conversation(client, JSON.parse(json)) } @@ -398,7 +391,7 @@ export async function listAll< >( client: Client ): Promise[]> { - const list = await XMTPModule.listAll(client.address) + const list = await XMTPModule.listAll(client.inboxId) return list.map((json: string) => { const jsonObj = JSON.parse(json) if (jsonObj.version === ConversationVersion.GROUP) { @@ -423,7 +416,7 @@ export async function listMessages< | undefined ): Promise[]> { const messages = await XMTPModule.loadMessages( - client.address, + client.inboxId, conversationTopic, limit, typeof before === 'number' ? before : before?.getTime(), @@ -457,7 +450,7 @@ export async function listBatchMessages< direction: item.direction || 'SORT_DIRECTION_DESCENDING', }) }) - const messages = await XMTPModule.loadBatchMessages(client.address, topics) + const messages = await XMTPModule.loadBatchMessages(client.inboxId, topics) return messages.map((json: string) => { return DecodedMessage.from(json, client) @@ -482,7 +475,7 @@ export async function createConversation< client, JSON.parse( await XMTPModule.createConversation( - client.address, + client.inboxId, getAddress(peerAddress), JSON.stringify(context || {}), consentProofData @@ -492,25 +485,21 @@ export async function createConversation< } export async function sendWithContentType( - clientAddress: string, + inboxId: string, conversationTopic: string, content: T, codec: ContentCodec ): Promise { if ('contentKey' in codec) { const contentJson = JSON.stringify(content) - return await XMTPModule.sendMessage( - clientAddress, - conversationTopic, - contentJson - ) + return await XMTPModule.sendMessage(inboxId, conversationTopic, contentJson) } else { const encodedContent = codec.encode(content) encodedContent.fallback = codec.fallback(content) const encodedContentData = EncodedContent.encode(encodedContent).finish() return await XMTPModule.sendEncodedContent( - clientAddress, + inboxId, conversationTopic, Array.from(encodedContentData) ) @@ -520,24 +509,20 @@ export async function sendWithContentType( export async function sendMessage< SendContentTypes extends DefaultContentTypes = DefaultContentTypes, >( - clientAddress: string, + inboxId: string, conversationTopic: string, content: ConversationSendPayload ): Promise { // TODO: consider eager validating of `MessageContent` here // instead of waiting for native code to validate const contentJson = JSON.stringify(content) - return await XMTPModule.sendMessage( - clientAddress, - conversationTopic, - contentJson - ) + return await XMTPModule.sendMessage(inboxId, conversationTopic, contentJson) } export async function prepareMessage< PrepareContentTypes extends DefaultContentTypes = DefaultContentTypes, >( - clientAddress: string, + inboxId: string, conversationTopic: string, content: ConversationSendPayload ): Promise { @@ -545,7 +530,7 @@ export async function prepareMessage< // instead of waiting for native code to validate const contentJson = JSON.stringify(content) const preparedJson = await XMTPModule.prepareMessage( - clientAddress, + inboxId, conversationTopic, contentJson ) @@ -553,19 +538,19 @@ export async function prepareMessage< } export async function prepareMessageWithContentType( - clientAddress: string, + inboxId: string, conversationTopic: string, content: any, codec: ContentCodec ): Promise { if ('contentKey' in codec) { - return prepareMessage(clientAddress, conversationTopic, content) + return prepareMessage(inboxId, conversationTopic, content) } const encodedContent = codec.encode(content) encodedContent.fallback = codec.fallback(content) const encodedContentData = EncodedContent.encode(encodedContent).finish() const preparedJson = await XMTPModule.prepareEncodedMessage( - clientAddress, + inboxId, conversationTopic, Array.from(encodedContentData) ) @@ -573,138 +558,126 @@ export async function prepareMessageWithContentType( } export async function sendPreparedMessage( - clientAddress: string, + inboxId: string, preparedLocalMessage: PreparedLocalMessage ): Promise { const preparedLocalMessageJson = JSON.stringify(preparedLocalMessage) - return await XMTPModule.sendPreparedMessage( - clientAddress, - preparedLocalMessageJson - ) + return await XMTPModule.sendPreparedMessage(inboxId, preparedLocalMessageJson) } -export function subscribeToConversations(clientAddress: string) { - return XMTPModule.subscribeToConversations(clientAddress) +export function subscribeToConversations(inboxId: string) { + return XMTPModule.subscribeToConversations(inboxId) } -export function subscribeToAll(clientAddress: string) { - return XMTPModule.subscribeToAll(clientAddress) +export function subscribeToAll(inboxId: string) { + return XMTPModule.subscribeToAll(inboxId) } -export function subscribeToGroups(clientAddress: string) { - return XMTPModule.subscribeToGroups(clientAddress) +export function subscribeToGroups(inboxId: string) { + return XMTPModule.subscribeToGroups(inboxId) } export function subscribeToAllMessages( - clientAddress: string, + inboxId: string, includeGroups: boolean ) { - return XMTPModule.subscribeToAllMessages(clientAddress, includeGroups) + return XMTPModule.subscribeToAllMessages(inboxId, includeGroups) } -export function subscribeToAllGroupMessages(clientAddress: string) { - return XMTPModule.subscribeToAllGroupMessages(clientAddress) +export function subscribeToAllGroupMessages(inboxId: string) { + return XMTPModule.subscribeToAllGroupMessages(inboxId) } -export async function subscribeToMessages( - clientAddress: string, - topic: string -) { - return await XMTPModule.subscribeToMessages(clientAddress, topic) +export async function subscribeToMessages(inboxId: string, topic: string) { + return await XMTPModule.subscribeToMessages(inboxId, topic) } -export function unsubscribeFromConversations(clientAddress: string) { - return XMTPModule.unsubscribeFromConversations(clientAddress) +export function unsubscribeFromConversations(inboxId: string) { + return XMTPModule.unsubscribeFromConversations(inboxId) } export function unsubscribeFromGroups(inboxId: string) { return XMTPModule.unsubscribeFromGroups(inboxId) } -export function unsubscribeFromAllMessages(clientAddress: string) { - return XMTPModule.unsubscribeFromAllMessages(clientAddress) +export function unsubscribeFromAllMessages(inboxId: string) { + return XMTPModule.unsubscribeFromAllMessages(inboxId) } export function unsubscribeFromAllGroupMessages(inboxId: string) { return XMTPModule.unsubscribeFromAllGroupMessages(inboxId) } -export async function unsubscribeFromMessages( - clientAddress: string, - topic: string -) { - return await XMTPModule.unsubscribeFromMessages(clientAddress, topic) +export async function unsubscribeFromMessages(inboxId: string, topic: string) { + return await XMTPModule.unsubscribeFromMessages(inboxId, topic) } export function registerPushToken(pushServer: string, token: string) { return XMTPModule.registerPushToken(pushServer, token) } -export function subscribePushTopics(clientAddress: string, topics: string[]) { - return XMTPModule.subscribePushTopics(clientAddress, topics) +export function subscribePushTopics(inboxId: string, topics: string[]) { + return XMTPModule.subscribePushTopics(inboxId, topics) } export async function decodeMessage< ContentTypes extends DefaultContentTypes = DefaultContentTypes, >( - clientAddress: string, + inboxId: string, topic: string, encryptedMessage: string ): Promise> { return JSON.parse( - await XMTPModule.decodeMessage(clientAddress, topic, encryptedMessage) + await XMTPModule.decodeMessage(inboxId, topic, encryptedMessage) ) } export async function conversationConsentState( - clientAddress: string, + inboxId: string, conversationTopic: string ): Promise { - return await XMTPModule.conversationConsentState( - clientAddress, - conversationTopic - ) + return await XMTPModule.conversationConsentState(inboxId, conversationTopic) } export async function groupConsentState( - clientAddress: string, + inboxId: string, groupId: string ): Promise { - return await XMTPModule.groupConsentState(clientAddress, groupId) + return await XMTPModule.groupConsentState(inboxId, groupId) } export async function isAllowed( - clientAddress: string, + inboxId: string, address: string ): Promise { - return await XMTPModule.isAllowed(clientAddress, address) + return await XMTPModule.isAllowed(inboxId, address) } export async function isDenied( - clientAddress: string, + inboxId: string, address: string ): Promise { - return await XMTPModule.isDenied(clientAddress, address) + return await XMTPModule.isDenied(inboxId, address) } export async function denyContacts( - clientAddress: string, + inboxId: string, addresses: string[] ): Promise { - return await XMTPModule.denyContacts(clientAddress, addresses) + return await XMTPModule.denyContacts(inboxId, addresses) } export async function allowContacts( - clientAddress: string, + inboxId: string, addresses: string[] ): Promise { - return await XMTPModule.allowContacts(clientAddress, addresses) + return await XMTPModule.allowContacts(inboxId, addresses) } export async function refreshConsentList( - clientAddress: string + inboxId: string ): Promise { - const consentList = await XMTPModule.refreshConsentList(clientAddress) + const consentList = await XMTPModule.refreshConsentList(inboxId) return consentList.map((json: string) => { return ConsentListEntry.from(json) @@ -712,9 +685,9 @@ export async function refreshConsentList( } export async function consentList( - clientAddress: string + inboxId: string ): Promise { - const consentList = await XMTPModule.consentList(clientAddress) + const consentList = await XMTPModule.consentList(inboxId) return consentList.map((json: string) => { return ConsentListEntry.from(json) @@ -730,142 +703,127 @@ export function preCreateIdentityCallbackCompleted() { } export async function isGroupActive( - clientAddress: string, + inboxId: string, id: string ): Promise { - return XMTPModule.isGroupActive(clientAddress, id) + return XMTPModule.isGroupActive(inboxId, id) } export async function addedByInboxId( - clientAddress: string, + inboxId: string, id: string -): Promise { - return XMTPModule.addedByInboxId(clientAddress, id) +): Promise { + return XMTPModule.addedByInboxId(inboxId, id) as InboxId } export async function creatorInboxId( - clientAddress: string, + inboxId: string, id: string -): Promise { - return XMTPModule.creatorInboxId(clientAddress, id) +): Promise { + return XMTPModule.creatorInboxId(inboxId, id) as InboxId } -export async function isAdmin( - clientAddress: string, - id: string, - inboxId: string -): Promise { - return XMTPModule.isAdmin(clientAddress, id, inboxId) +export async function isAdmin(id: string, inboxId: string): Promise { + return XMTPModule.isAdmin(id, inboxId) } export async function isSuperAdmin( - clientAddress: string, id: string, inboxId: string ): Promise { - return XMTPModule.isSuperAdmin(clientAddress, id, inboxId) + return XMTPModule.isSuperAdmin(id, inboxId) } export async function listAdmins( - clientAddress: string, + inboxId: string, id: string -): Promise { - return XMTPModule.listAdmins(clientAddress, id) +): Promise { + return XMTPModule.listAdmins(inboxId, id) } export async function listSuperAdmins( - clientAddress: string, + inboxId: string, id: string -): Promise { - return XMTPModule.listSuperAdmins(clientAddress, id) +): Promise { + return XMTPModule.listSuperAdmins(inboxId, id) } -export async function addAdmin( - clientAddress: string, - id: string, - inboxId: string -): Promise { - return XMTPModule.addAdmin(clientAddress, id, inboxId) +export async function addAdmin(id: string, inboxId: string): Promise { + return XMTPModule.addAdmin(id, inboxId) } export async function addSuperAdmin( - clientAddress: string, id: string, inboxId: string ): Promise { - return XMTPModule.addSuperAdmin(clientAddress, id, inboxId) + return XMTPModule.addSuperAdmin(id, inboxId) } -export async function removeAdmin( - clientAddress: string, - id: string, - inboxId: string -): Promise { - return XMTPModule.removeAdmin(clientAddress, id, inboxId) +export async function removeAdmin(id: string, inboxId: string): Promise { + return XMTPModule.removeAdmin(id, inboxId) } export async function removeSuperAdmin( - clientAddress: string, id: string, inboxId: string ): Promise { - return XMTPModule.removeSuperAdmin(clientAddress, id, inboxId) + return XMTPModule.removeSuperAdmin(id, inboxId) } export async function allowGroups( - clientAddress: string, + inboxId: string, groupIds: string[] ): Promise { - return XMTPModule.allowGroups(clientAddress, groupIds) + return XMTPModule.allowGroups(inboxId, groupIds) } export async function denyGroups( - clientAddress: string, + inboxId: string, groupIds: string[] ): Promise { - return XMTPModule.denyGroups(clientAddress, groupIds) + return XMTPModule.denyGroups(inboxId, groupIds) } export async function isGroupAllowed( - clientAddress: string, + inboxId: string, groupId: string ): Promise { - return XMTPModule.isGroupAllowed(clientAddress, groupId) + return XMTPModule.isGroupAllowed(inboxId, groupId) } export async function isGroupDenied( - clientAddress: string, + inboxId: string, groupId: string ): Promise { - return XMTPModule.isGroupDenied(clientAddress, groupId) + return XMTPModule.isGroupDenied(inboxId, groupId) } export async function allowInboxes( - clientAddress: string, + inboxId: string, inboxIds: string[] ): Promise { - return XMTPModule.allowInboxes(clientAddress, inboxIds) + return XMTPModule.allowInboxes(inboxId, inboxIds) } export async function denyInboxes( - clientAddress: string, + inboxId: string, inboxIds: string[] ): Promise { - return XMTPModule.denyInboxes(clientAddress, inboxIds) + return XMTPModule.denyInboxes(inboxId, inboxIds) } export async function isInboxAllowed( - clientAddress: string, + clientInboxId: string, inboxId: string ): Promise { - return XMTPModule.isInboxAllowed(clientAddress, inboxId) + return XMTPModule.isInboxAllowed(clientInboxId, inboxId) } export async function isInboxDenied( - clientAddress: string, + clientInboxId: string, inboxId: string ): Promise { - return XMTPModule.isInboxDenied(clientAddress, inboxId) + return XMTPModule.isInboxDenied(clientInboxId, inboxId) } export async function processGroupMessage< @@ -876,7 +834,7 @@ export async function processGroupMessage< encryptedMessage: string ): Promise> { const json = XMTPModule.processGroupMessage( - client.address, + client.inboxId, id, encryptedMessage ) @@ -890,7 +848,7 @@ export async function processWelcomeMessage< encryptedMessage: string ): Promise> { const json = await XMTPModule.processWelcomeMessage( - client.address, + client.inboxId, encryptedMessage ) return new Group(client, JSON.parse(json)) diff --git a/src/lib/Client.ts b/src/lib/Client.ts index 51321e448..f259a1575 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -25,11 +25,13 @@ export type GetMessageContentTypeFromClient = export type ExtractDecodedType = C extends XMTPModule.ContentCodec ? T : never +export type InboxId = string & { readonly brand: unique symbol } + export class Client< ContentTypes extends DefaultContentTypes = DefaultContentTypes, > { address: string - inboxId: string + inboxId: InboxId installationId: string conversations: Conversations contacts: Contacts @@ -105,7 +107,7 @@ export class Client< resolve( new Client( message.address, - message.inboxId, + message.inboxId as InboxId, message.installationId, opts?.codecs || [] ) @@ -283,7 +285,7 @@ export class Client< constructor( address: string, - inboxId: string, + inboxId: InboxId, installationId: string, codecs: XMTPModule.ContentCodec[] = [] ) { @@ -308,7 +310,7 @@ export class Client< async sign(digest: Uint8Array, keyType: KeyType): Promise { return XMTPModule.sign( - this.address, + this.inboxId, digest, keyType.kind, keyType.prekeyIndex @@ -316,7 +318,7 @@ export class Client< } async exportPublicKeyBundle(): Promise { - return XMTPModule.exportPublicKeyBundle(this.address) + return XMTPModule.exportPublicKeyBundle(this.inboxId) } /** @@ -328,7 +330,7 @@ export class Client< * @returns {Promise} A Promise that resolves to the unencrypted key bundle for the current XMTP address. */ async exportKeyBundle(): Promise { - return XMTPModule.exportKeyBundle(this.address) + return XMTPModule.exportKeyBundle(this.inboxId) } /** @@ -341,28 +343,28 @@ export class Client< * @returns {Promise} A Promise resolving to true if messaging is allowed, and false otherwise. */ async canMessage(peerAddress: string): Promise { - return await XMTPModule.canMessage(this.address, peerAddress) + return await XMTPModule.canMessage(this.inboxId, peerAddress) } /** * Deletes the local database. This cannot be undone and these stored messages will not be refetched from the network. */ async deleteLocalDatabase() { - return await XMTPModule.deleteLocalDatabase(this.address) + return await XMTPModule.deleteLocalDatabase(this.inboxId) } /** * Drop the local database connection. This function is delicate and should be used with caution. App will error if database not properly reconnected. See: reconnectLocalDatabase() */ async dropLocalDatabaseConnection() { - return await XMTPModule.dropLocalDatabaseConnection(this.address) + return await XMTPModule.dropLocalDatabaseConnection(this.inboxId) } /** * Reconnects the local database after being dropped. */ async reconnectLocalDatabase() { - return await XMTPModule.reconnectLocalDatabase(this.address) + return await XMTPModule.reconnectLocalDatabase(this.inboxId) } /** @@ -376,7 +378,7 @@ export class Client< async canGroupMessage( addresses: string[] ): Promise<{ [key: string]: boolean }> { - return await XMTPModule.canGroupMessage(this.address, addresses) + return await XMTPModule.canGroupMessage(this.inboxId, addresses) } // TODO: support persisting conversations for quick lookup @@ -419,7 +421,7 @@ export class Client< if (!file.fileUri?.startsWith('file://')) { throw new Error('the attachment must be a local file:// uri') } - return await XMTPModule.encryptAttachment(this.address, file) + return await XMTPModule.encryptAttachment(this.inboxId, file) } /** @@ -436,7 +438,7 @@ export class Client< if (!encryptedFile.encryptedLocalFileUri?.startsWith('file://')) { throw new Error('the attachment must be a local file:// uri') } - return await XMTPModule.decryptAttachment(this.address, encryptedFile) + return await XMTPModule.decryptAttachment(this.inboxId, encryptedFile) } /** @@ -448,7 +450,7 @@ export class Client< */ async sendPreparedMessage(prepared: PreparedLocalMessage): Promise { try { - return await XMTPModule.sendPreparedMessage(this.address, prepared) + return await XMTPModule.sendPreparedMessage(this.inboxId, prepared) } catch (e) { console.info('ERROR in sendPreparedMessage()', e) throw e diff --git a/src/lib/Contacts.ts b/src/lib/Contacts.ts index 9dc9ee202..97d8b9a12 100644 --- a/src/lib/Contacts.ts +++ b/src/lib/Contacts.ts @@ -1,4 +1,4 @@ -import { Client } from './Client' +import { Client, InboxId } from './Client' import { ConsentListEntry } from './ConsentListEntry' import * as XMTPModule from '../index' import { getAddress } from '../utils/address' @@ -11,17 +11,17 @@ export default class Contacts { } async isAllowed(address: string): Promise { - return await XMTPModule.isAllowed(this.client.address, getAddress(address)) + return await XMTPModule.isAllowed(this.client.inboxId, getAddress(address)) } async isDenied(address: string): Promise { - return await XMTPModule.isDenied(this.client.address, getAddress(address)) + return await XMTPModule.isDenied(this.client.inboxId, getAddress(address)) } async deny(addresses: string[]): Promise { const checkSummedAddresses = addresses.map((address) => getAddress(address)) return await XMTPModule.denyContacts( - this.client.address, + this.client.inboxId, checkSummedAddresses ) } @@ -29,48 +29,48 @@ export default class Contacts { async allow(addresses: string[]): Promise { const checkSummedAddresses = addresses.map((address) => getAddress(address)) return await XMTPModule.allowContacts( - this.client.address, + this.client.inboxId, checkSummedAddresses ) } async refreshConsentList(): Promise { - return await XMTPModule.refreshConsentList(this.client.address) + return await XMTPModule.refreshConsentList(this.client.inboxId) } async consentList(): Promise { - return await XMTPModule.consentList(this.client.address) + return await XMTPModule.consentList(this.client.inboxId) } async allowGroups(groupIds: string[]): Promise { - return await XMTPModule.allowGroups(this.client.address, groupIds) + return await XMTPModule.allowGroups(this.client.inboxId, groupIds) } async denyGroups(groupIds: string[]): Promise { - return await XMTPModule.denyGroups(this.client.address, groupIds) + return await XMTPModule.denyGroups(this.client.inboxId, groupIds) } async isGroupAllowed(groupId: string): Promise { - return await XMTPModule.isGroupAllowed(this.client.address, groupId) + return await XMTPModule.isGroupAllowed(this.client.inboxId, groupId) } async isGroupDenied(groupId: string): Promise { - return await XMTPModule.isGroupDenied(this.client.address, groupId) + return await XMTPModule.isGroupDenied(this.client.inboxId, groupId) } - async allowInboxes(inboxIds: string[]): Promise { - return await XMTPModule.allowInboxes(this.client.address, inboxIds) + async allowInboxes(inboxIds: InboxId[]): Promise { + return await XMTPModule.allowInboxes(this.client.inboxId, inboxIds) } - async denyInboxes(inboxIds: string[]): Promise { - return await XMTPModule.denyInboxes(this.client.address, inboxIds) + async denyInboxes(inboxIds: InboxId[]): Promise { + return await XMTPModule.denyInboxes(this.client.inboxId, inboxIds) } - async isInboxAllowed(inboxId: string): Promise { - return await XMTPModule.isInboxAllowed(this.client.address, inboxId) + async isInboxAllowed(inboxId: InboxId): Promise { + return await XMTPModule.isInboxAllowed(this.client.inboxId, inboxId) } - async isInboxDenied(inboxId: string): Promise { - return await XMTPModule.isInboxDenied(this.client.address, inboxId) + async isInboxDenied(inboxId: InboxId): Promise { + return await XMTPModule.isInboxDenied(this.client.inboxId, inboxId) } } diff --git a/src/lib/Conversation.ts b/src/lib/Conversation.ts index 16b6a3c15..d5eff4724 100644 --- a/src/lib/Conversation.ts +++ b/src/lib/Conversation.ts @@ -60,13 +60,9 @@ export class Conversation } catch {} } - get clientAddress(): string { - return this.client.address - } - async exportTopicData(): Promise { return await XMTP.exportConversationTopicData( - this.client.address, + this.client.inboxId, this.topic ) } @@ -123,7 +119,7 @@ export class Conversation } return await XMTP.sendWithContentType( - this.client.address, + this.client.inboxId, this.topic, content, codec @@ -152,7 +148,7 @@ export class Conversation content = { text: content } } - return await XMTP.sendMessage(this.client.address, this.topic, content) + return await XMTP.sendMessage(this.client.inboxId, this.topic, content) } catch (e) { console.info('ERROR in send()', e) throw e @@ -173,7 +169,7 @@ export class Conversation } return await XMTP.prepareMessageWithContentType( - this.client.address, + this.client.inboxId, this.topic, content, codec @@ -208,7 +204,7 @@ export class Conversation if (typeof content === 'string') { content = { text: content } } - return await XMTP.prepareMessage(this.client.address, this.topic, content) + return await XMTP.prepareMessage(this.client.inboxId, this.topic, content) } catch (e) { console.info('ERROR in prepareMessage()', e) throw e @@ -227,7 +223,7 @@ export class Conversation */ async sendPreparedMessage(prepared: PreparedLocalMessage): Promise { try { - return await XMTP.sendPreparedMessage(this.client.address, prepared) + return await XMTP.sendPreparedMessage(this.client.inboxId, prepared) } catch (e) { console.info('ERROR in sendPreparedMessage()', e) throw e @@ -249,7 +245,7 @@ export class Conversation ): Promise> { try { return await XMTP.decodeMessage( - this.client.address, + this.client.inboxId, this.topic, encryptedMessage ) @@ -269,7 +265,7 @@ export class Conversation * @returns {Promise<"allowed" | "denied" | "unknown">} A Promise that resolves to the consent state, which can be "allowed," "denied," or "unknown." */ async consentState(): Promise<'allowed' | 'denied' | 'unknown'> { - return await XMTP.conversationConsentState(this.clientAddress, this.topic) + return await XMTP.conversationConsentState(this.client.inboxId, this.topic) } /** * Sets up a real-time message stream for the current conversation. @@ -284,21 +280,21 @@ export class Conversation async streamMessages( callback: (message: DecodedMessage) => Promise ): Promise<() => void> { - await XMTP.subscribeToMessages(this.client.address, this.topic) + await XMTP.subscribeToMessages(this.client.inboxId, this.topic) const hasSeen = {} const messageSubscription = XMTP.emitter.addListener( EventTypes.ConversationMessage, async ({ - clientAddress, + inboxId, message, topic, }: { - clientAddress: string + inboxId: string message: DecodedMessage topic: string }) => { // Long term these checks should be able to be done on the native layer as well, but additional checks in JS for safety - if (clientAddress !== this.client.address) { + if (inboxId !== this.client.inboxId) { return } if (topic !== this.topic) { @@ -317,7 +313,7 @@ export class Conversation return async () => { messageSubscription.remove() - await XMTP.unsubscribeFromMessages(this.client.address, this.topic) + await XMTP.unsubscribeFromMessages(this.client.inboxId, this.topic) } } } diff --git a/src/lib/Conversations.ts b/src/lib/Conversations.ts index b86daa905..63cc14c15 100644 --- a/src/lib/Conversations.ts +++ b/src/lib/Conversations.ts @@ -41,7 +41,7 @@ export default class Conversations< } async getHmacKeys(): Promise { - return await XMTPModule.getHmacKeys(this.client.address) + return await XMTPModule.getHmacKeys(this.client.inboxId) } async importTopicData( @@ -117,14 +117,14 @@ export default class Conversations< async streamGroups( callback: (group: Group) => Promise ): Promise<() => void> { - XMTPModule.subscribeToGroups(this.client.address) + XMTPModule.subscribeToGroups(this.client.inboxId) const groupsSubscription = XMTPModule.emitter.addListener( EventTypes.Group, async ({ - clientAddress, + inboxId, group, }: { - clientAddress: string + inboxId: string group: Group }) => { if (this.known[group.id]) { @@ -137,7 +137,7 @@ export default class Conversations< this.subscriptions[EventTypes.Group] = groupsSubscription return () => { groupsSubscription.remove() - XMTPModule.unsubscribeFromGroups(this.client.address) + XMTPModule.unsubscribeFromGroups(this.client.inboxId) } } @@ -165,7 +165,7 @@ export default class Conversations< * and save them to the local state. */ async syncGroups() { - await XMTPModule.syncGroups(this.client.address) + await XMTPModule.syncGroups(this.client.inboxId) } /** @@ -180,17 +180,17 @@ export default class Conversations< async stream( callback: (conversation: Conversation) => Promise ) { - XMTPModule.subscribeToConversations(this.client.address) + XMTPModule.subscribeToConversations(this.client.inboxId) const subscription = XMTPModule.emitter.addListener( EventTypes.Conversation, async ({ - clientAddress, + inboxId, conversation, }: { - clientAddress: string + inboxId: string conversation: ConversationParams }) => { - if (clientAddress !== this.client.address) { + if (inboxId !== this.client.inboxId) { return } if (this.known[conversation.topic]) { @@ -218,17 +218,17 @@ export default class Conversations< conversation: ConversationContainer ) => Promise ) { - XMTPModule.subscribeToAll(this.client.address) + XMTPModule.subscribeToAll(this.client.inboxId) const subscription = XMTPModule.emitter.addListener( EventTypes.ConversationContainer, async ({ - clientAddress, + inboxId, conversationContainer, }: { - clientAddress: string + inboxId: string conversationContainer: ConversationContainer }) => { - if (clientAddress !== this.client.address) { + if (inboxId !== this.client.inboxId) { return } if (this.known[conversationContainer.topic]) { @@ -268,17 +268,17 @@ export default class Conversations< callback: (message: DecodedMessage) => Promise, includeGroups: boolean = false ): Promise { - XMTPModule.subscribeToAllMessages(this.client.address, includeGroups) + XMTPModule.subscribeToAllMessages(this.client.inboxId, includeGroups) const subscription = XMTPModule.emitter.addListener( EventTypes.Message, async ({ - clientAddress, + inboxId, message, }: { - clientAddress: string + inboxId: string message: DecodedMessage }) => { - if (clientAddress !== this.client.address) { + if (inboxId !== this.client.inboxId) { return } if (this.known[message.id]) { @@ -302,17 +302,17 @@ export default class Conversations< async streamAllGroupMessages( callback: (message: DecodedMessage) => Promise ): Promise { - XMTPModule.subscribeToAllGroupMessages(this.client.address) + XMTPModule.subscribeToAllGroupMessages(this.client.inboxId) const subscription = XMTPModule.emitter.addListener( EventTypes.AllGroupMessage, async ({ - clientAddress, + inboxId, message, }: { - clientAddress: string + inboxId: string message: DecodedMessage }) => { - if (clientAddress !== this.client.address) { + if (inboxId !== this.client.inboxId) { return } if (this.known[message.id]) { @@ -346,7 +346,7 @@ export default class Conversations< this.subscriptions[EventTypes.Conversation].remove() delete this.subscriptions[EventTypes.Conversation] } - XMTPModule.unsubscribeFromConversations(this.client.address) + XMTPModule.unsubscribeFromConversations(this.client.inboxId) } /** @@ -368,7 +368,7 @@ export default class Conversations< this.subscriptions[EventTypes.Message].remove() delete this.subscriptions[EventTypes.Message] } - XMTPModule.unsubscribeFromAllMessages(this.client.address) + XMTPModule.unsubscribeFromAllMessages(this.client.inboxId) } /** diff --git a/src/lib/Group.ts b/src/lib/Group.ts index 754615b84..372c13ce3 100644 --- a/src/lib/Group.ts +++ b/src/lib/Group.ts @@ -1,3 +1,4 @@ +import { InboxId } from './Client' import { ConversationVersion, ConversationContainer, @@ -18,10 +19,10 @@ export class Group< client: XMTP.Client id: string createdAt: number - peerInboxIds: string[] + peerInboxIds: InboxId[] version = ConversationVersion.GROUP topic: string - creatorInboxId: string + creatorInboxId: InboxId permissionLevel: 'all_members' | 'admin_only' name: string isGroupActive: boolean @@ -31,8 +32,8 @@ export class Group< params: { id: string createdAt: number - peerInboxIds: string[] - creatorInboxId: string + peerInboxIds: InboxId[] + creatorInboxId: InboxId permissionLevel: 'all_members' | 'admin_only' topic: string name: string @@ -50,16 +51,12 @@ export class Group< this.isGroupActive = params.isGroupActive } - get clientAddress(): string { - return this.client.address - } - /** * This method returns an array of inbox ids associated with the group. * To get the latest member inbox ids from the network, call sync() first. * @returns {Promise[]>} A Promise that resolves to an array of DecodedMessage objects. */ - async memberInboxIds(): Promise { + async memberInboxIds(): Promise { return XMTP.listMemberInboxIds(this.client, this.id) } @@ -87,7 +84,7 @@ export class Group< } return await XMTP.sendMessageToGroup( - this.client.address, + this.client.inboxId, this.id, content ) @@ -126,7 +123,7 @@ export class Group< * associated with the group and saves them to the local state. */ async sync() { - await XMTP.syncGroup(this.client.address, this.id) + await XMTP.syncGroup(this.client.inboxId, this.id) } /** @@ -142,21 +139,21 @@ export class Group< async streamGroupMessages( callback: (message: DecodedMessage) => Promise ): Promise<() => void> { - await XMTP.subscribeToGroupMessages(this.client.address, this.id) + await XMTP.subscribeToGroupMessages(this.client.inboxId, this.id) const hasSeen = {} const messageSubscription = XMTP.emitter.addListener( EventTypes.GroupMessage, async ({ - clientAddress, + inboxId, message, groupId, }: { - clientAddress: string + inboxId: string message: DecodedMessage groupId: string }) => { // Long term these checks should be able to be done on the native layer as well, but additional checks in JS for safety - if (clientAddress !== this.client.address) { + if (inboxId !== this.client.inboxId) { return } if (groupId !== this.id) { @@ -174,7 +171,7 @@ export class Group< ) return async () => { messageSubscription.remove() - await XMTP.unsubscribeFromGroupMessages(this.client.address, this.id) + await XMTP.unsubscribeFromGroupMessages(this.client.inboxId, this.id) } } @@ -184,7 +181,7 @@ export class Group< * @returns */ async addMembers(addresses: string[]): Promise { - return XMTP.addGroupMembers(this.client.address, this.id, addresses) + return XMTP.addGroupMembers(this.client.inboxId, this.id, addresses) } /** @@ -193,7 +190,7 @@ export class Group< * @returns */ async removeMembers(addresses: string[]): Promise { - return XMTP.removeGroupMembers(this.client.address, this.id, addresses) + return XMTP.removeGroupMembers(this.client.inboxId, this.id, addresses) } /** @@ -201,8 +198,8 @@ export class Group< * @param inboxIds inboxIds to add to the group * @returns */ - async addMembersByInboxId(inboxIds: string[]): Promise { - return XMTP.addGroupMembersByInboxId(this.client.address, this.id, inboxIds) + async addMembersByInboxId(inboxIds: InboxId[]): Promise { + return XMTP.addGroupMembersByInboxId(this.client.inboxId, this.id, inboxIds) } /** @@ -210,9 +207,9 @@ export class Group< * @param inboxIds inboxIds to remove from the group * @returns */ - async removeMembersByInboxId(inboxIds: string[]): Promise { + async removeMembersByInboxId(inboxIds: InboxId[]): Promise { return XMTP.removeGroupMembersByInboxId( - this.client.address, + this.client.inboxId, this.id, inboxIds ) @@ -224,7 +221,7 @@ export class Group< * @returns {string} A Promise that resolves to the group name. */ async groupName(): Promise { - return XMTP.groupName(this.client.address, this.id) + return XMTP.groupName(this.client.inboxId, this.id) } /** @@ -235,7 +232,7 @@ export class Group< */ async updateGroupName(groupName: string): Promise { - return XMTP.updateGroupName(this.client.address, this.id, groupName) + return XMTP.updateGroupName(this.client.inboxId, this.id, groupName) } /** @@ -245,7 +242,7 @@ export class Group< */ async isActive(): Promise { - return XMTP.isGroupActive(this.client.address, this.id) + return XMTP.isGroupActive(this.client.inboxId, this.id) } /** @@ -253,8 +250,8 @@ export class Group< * To get the latest added by inbox id from the network, call sync() first. * @returns {Promise} A Promise that resolves to the inbox id that added you to the group. */ - async addedByInboxId(): Promise { - return XMTP.addedByInboxId(this.client.address, this.id) + async addedByInboxId(): Promise { + return XMTP.addedByInboxId(this.client.inboxId, this.id) } /** @@ -263,8 +260,8 @@ export class Group< * @returns {Promise} whether a given inboxId is an admin of the group. * To get the latest admin status from the network, call sync() first. */ - async isAdmin(inboxId: string): Promise { - return XMTP.isAdmin(this.client.address, this.id, inboxId) + async isAdmin(inboxId: InboxId): Promise { + return XMTP.isAdmin(this.id, inboxId) } /** @@ -273,8 +270,8 @@ export class Group< * @returns {Promise} whether a given inboxId is a super admin of the group. * To get the latest super admin status from the network, call sync() first. */ - async isSuperAdmin(inboxId: string): Promise { - return XMTP.isSuperAdmin(this.client.address, this.id, inboxId) + async isSuperAdmin(inboxId: InboxId): Promise { + return XMTP.isSuperAdmin(this.id, inboxId) } /** @@ -282,8 +279,8 @@ export class Group< * @returns {Promise} A Promise that resolves to an array of inboxIds that are admins of the group. * To get the latest admin list from the network, call sync() first. */ - async listAdmins(): Promise { - return XMTP.listAdmins(this.client.address, this.id) + async listAdmins(): Promise { + return XMTP.listAdmins(this.client.inboxId, this.id) } /** @@ -291,48 +288,48 @@ export class Group< * @returns {Promise} A Promise that resolves to an array of inboxIds that are super admins of the group. * To get the latest super admin list from the network, call sync() first. */ - async listSuperAdmins(): Promise { - return XMTP.listSuperAdmins(this.client.address, this.id) + async listSuperAdmins(): Promise { + return XMTP.listSuperAdmins(this.client.inboxId, this.id) } /** * - * @param {string} inboxId + * @param {InboxId} inboxId * @returns {Promise} A Promise that resolves when the inboxId is added to the group admins. * Will throw if the user does not have the required permissions. */ - async addAdmin(inboxId: string): Promise { - return XMTP.addAdmin(this.client.address, this.id, inboxId) + async addAdmin(inboxId: InboxId): Promise { + return XMTP.addAdmin(this.id, inboxId) } /** * - * @param {string} inboxId + * @param {InboxId} inboxId * @returns {Promise} A Promise that resolves when the inboxId is added to the group super admins. * Will throw if the user does not have the required permissions. */ - async addSuperAdmin(inboxId: string): Promise { - return XMTP.addSuperAdmin(this.client.address, this.id, inboxId) + async addSuperAdmin(inboxId: InboxId): Promise { + return XMTP.addSuperAdmin(this.id, inboxId) } /** * - * @param {string} inboxId + * @param {InboxId} inboxId * @returns {Promise} A Promise that resolves when the inboxId is removed from the group admins. * Will throw if the user does not have the required permissions. */ - async removeAdmin(inboxId: string): Promise { - return XMTP.removeAdmin(this.client.address, this.id, inboxId) + async removeAdmin(inboxId: InboxId): Promise { + return XMTP.removeAdmin(this.id, inboxId) } /** * - * @param {string} inboxId + * @param {InboxId} inboxId * @returns {Promise} A Promise that resolves when the inboxId is removed from the group super admins. * Will throw if the user does not have the required permissions. */ - async removeSuperAdmin(inboxId: string): Promise { - return XMTP.removeSuperAdmin(this.client.address, this.id, inboxId) + async removeSuperAdmin(inboxId: InboxId): Promise { + return XMTP.removeSuperAdmin(this.id, inboxId) } async processMessage( @@ -351,21 +348,21 @@ export class Group< } async consentState(): Promise<'allowed' | 'denied' | 'unknown'> { - return await XMTP.groupConsentState(this.clientAddress, this.id) + return await XMTP.groupConsentState(this.client.inboxId, this.id) } /** * @returns {Promise} a boolean indicating whether the group is allowed by the user. */ async isAllowed(): Promise { - return await XMTP.isGroupAllowed(this.client.address, this.id) + return await XMTP.isGroupAllowed(this.client.inboxId, this.id) } /** * @returns {Promise} a boolean indicating whether the group is denied by the user. */ async isDenied(): Promise { - return await XMTP.isGroupDenied(this.client.address, this.id) + return await XMTP.isGroupDenied(this.client.inboxId, this.id) } /** @@ -374,6 +371,6 @@ export class Group< * To get the latest member list from the network, call sync() first. */ async members(): Promise { - return await XMTP.listGroupMembers(this.client.address, this.id) + return await XMTP.listGroupMembers(this.client.inboxId, this.id) } } diff --git a/src/lib/Member.ts b/src/lib/Member.ts index 10aa2db1a..932800a45 100644 --- a/src/lib/Member.ts +++ b/src/lib/Member.ts @@ -1,10 +1,12 @@ +import { InboxId } from './Client' + export class Member { - inboxId: string + inboxId: InboxId addresses: string[] permissionLevel: 'member' | 'admin' | 'super_admin' constructor( - inboxId: string, + inboxId: InboxId, addresses: string[], permissionLevel: 'member' | 'admin' | 'super_admin' ) {