Skip to content

Commit

Permalink
Merge pull request #275 from xmtp/np/update-sdk-functionality
Browse files Browse the repository at this point in the history
Group Admin & Message Pagination
  • Loading branch information
nplasterer authored Feb 21, 2024
2 parents 40acfc1 + 7e37791 commit 295487d
Show file tree
Hide file tree
Showing 11 changed files with 268 additions and 92 deletions.
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ dependencies {
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.facebook.react:react-native:0.71.3'
implementation "com.daveanthonythomas.moshipack:moshipack:1.0.1"
implementation "org.xmtp:android:0.7.13"
implementation "org.xmtp:android:0.7.15"
// xmtp-android local testing setup below (comment org.xmtp:android above)
// implementation files('<PATH TO XMTP-ANDROID>/xmtp-android/library/build/outputs/aar/library-debug.aar')
// implementation 'com.google.crypto.tink:tink-android:1.7.0'
Expand Down
136 changes: 67 additions & 69 deletions android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import org.xmtp.android.library.toHex
import org.xmtp.proto.keystore.api.v1.Keystore.TopicMap.TopicData
import org.xmtp.proto.message.api.v1.MessageApiOuterClass
import org.xmtp.proto.message.contents.PrivateKeyOuterClass
import uniffi.xmtpv3.GroupPermissions
import java.io.File
import java.util.Date
import java.util.UUID
Expand Down Expand Up @@ -184,7 +185,7 @@ class XMTPModule : Module() {
val preEnableIdentityCallback: PreEventCallback? =
preEnableIdentityCallback.takeIf { hasEnableIdentityCallback == true }
val context = if (enableAlphaMls == true) context else null

val options = ClientOptions(
api = apiEnvironments(environment, appVersion),
preCreateIdentityCallback = preCreateIdentityCallback,
Expand Down Expand Up @@ -325,10 +326,7 @@ class XMTPModule : Module() {
AsyncFunction("canGroupMessage") { clientAddress: String, peerAddresses: List<String> ->
logV("canGroupMessage")
val client = clients[clientAddress] ?: throw XMTPException("No client")
if (client.libXMTPClient == null) {
throw XMTPException("Create client with enableAlphaMLS true in order to call canGroupMessage")
}
client.canMessage(peerAddresses)
client.canMessageV3(peerAddresses)
}

AsyncFunction("staticCanMessage") { peerAddress: String, environment: String, appVersion: String? ->
Expand Down Expand Up @@ -466,14 +464,20 @@ class XMTPModule : Module() {
.map { DecodedMessageWrapper.encode(it) }
}

AsyncFunction("groupMessages") { clientAddress: String, id: String ->
AsyncFunction("groupMessages") { clientAddress: String, id: String, limit: Int?, before: Long?, after: Long?, direction: String? ->
logV("groupMessages")
val client = clients[clientAddress] ?: throw XMTPException("No client")
if (client.libXMTPClient == null) {
throw XMTPException("Create client with enableAlphaMLS true in order to synch groups")
}
val beforeDate = if (before != null) Date(before) else null
val afterDate = if (after != null) Date(after) else null
val group = findGroup(clientAddress, id)
group?.decryptedMessages()?.map { DecodedMessageWrapper.encode(it) }
group?.decryptedMessages(
limit = limit,
before = beforeDate,
after = afterDate,
direction = MessageApiOuterClass.SortDirection.valueOf(
direction ?: "SORT_DIRECTION_DESCENDING"
)
)?.map { DecodedMessageWrapper.encode(it) }
}

AsyncFunction("loadBatchMessages") { clientAddress: String, topics: List<String> ->
Expand Down Expand Up @@ -536,20 +540,20 @@ class XMTPModule : Module() {
)
}

AsyncFunction("sendMessageToGroup") { clientAddress: String, id: String, contentJson: String ->
logV("sendMessageToGroup")
val group =
findGroup(
clientAddress = clientAddress,
id = id
)
?: throw XMTPException("no group found for $id")
val sending = ContentJson.fromJson(contentJson)
group.send(
content = sending.content,
options = SendOptions(contentType = sending.type)
)
}
AsyncFunction("sendMessageToGroup") { clientAddress: String, id: String, contentJson: String ->
logV("sendMessageToGroup")
val group =
findGroup(
clientAddress = clientAddress,
id = id
)
?: throw XMTPException("no group found for $id")
val sending = ContentJson.fromJson(contentJson)
group.send(
content = sending.content,
options = SendOptions(contentType = sending.type)
)
}

AsyncFunction("prepareMessage") { clientAddress: String, conversationTopic: String, contentJson: String ->
logV("prepareMessage")
Expand Down Expand Up @@ -649,51 +653,40 @@ class XMTPModule : Module() {
ConversationWrapper.encode(client, conversation)
}

AsyncFunction("createGroup") { clientAddress: String, peerAddresses: List<String> ->
AsyncFunction("createGroup") { clientAddress: String, peerAddresses: List<String>, permission: String ->
logV("createGroup")
val client = clients[clientAddress] ?: throw XMTPException("No client")
if (client.libXMTPClient == null) {
throw XMTPException("Create client with enableAlphaMLS true in order to create a group")
val permissionLevel = when (permission) {
"creator_admin" -> GroupPermissions.GROUP_CREATOR_IS_ADMIN
else -> GroupPermissions.EVERYONE_IS_ADMIN
}
val group = client.conversations.newGroup(peerAddresses)
val group = client.conversations.newGroup(peerAddresses, permissionLevel)
GroupWrapper.encode(client, group)
}

AsyncFunction("listMemberAddresses") { clientAddress: String, groupId: String ->
logV("listMembers")
val client = clients[clientAddress] ?: throw XMTPException("No client")
if (client.libXMTPClient == null) {
throw XMTPException("Create client with enableAlphaMLS true in order to create a group")
}
val group = findGroup(clientAddress, groupId)
group?.memberAddresses()
}

AsyncFunction("syncGroups") { clientAddress: String ->
logV("syncGroups")
val client = clients[clientAddress] ?: throw XMTPException("No client")
if (client.libXMTPClient == null) {
throw XMTPException("Create client with enableAlphaMLS true in order to synch groups")
}
runBlocking { client.conversations.syncGroups() }
}

AsyncFunction("syncGroup") { clientAddress: String, id: String ->
logV("syncGroup")
val client = clients[clientAddress] ?: throw XMTPException("No client")
if (client.libXMTPClient == null) {
throw XMTPException("Create client with enableAlphaMLS true in order to synch groups")
}
val group = findGroup(clientAddress, id)
runBlocking { group?.sync() }
}

AsyncFunction("addGroupMembers") { clientAddress: String, id: String, peerAddresses: List<String> ->
logV("addGroupMembers")
val client = clients[clientAddress] ?: throw XMTPException("No client")
if (client.libXMTPClient == null) {
throw XMTPException("Create client with enableAlphaMLS true in order to create a group")
}
val group = findGroup(clientAddress, id)

runBlocking { group?.addMembers(peerAddresses) }
Expand All @@ -702,9 +695,6 @@ class XMTPModule : Module() {
AsyncFunction("removeGroupMembers") { clientAddress: String, id: String, peerAddresses: List<String> ->
logV("removeGroupMembers")
val client = clients[clientAddress] ?: throw XMTPException("No client")
if (client.libXMTPClient == null) {
throw XMTPException("Create client with enableAlphaMLS true in order to create a group")
}
val group = findGroup(clientAddress, id)

runBlocking { group?.removeMembers(peerAddresses) }
Expand All @@ -713,14 +703,19 @@ class XMTPModule : Module() {
Function("isGroupActive") { clientAddress: String, id: String ->
logV("isGroupActive")
val client = clients[clientAddress] ?: throw XMTPException("No client")
if (client.libXMTPClient == null) {
throw XMTPException("Create client with enableAlphaMLS true in order to create a group")
}
val group = findGroup(clientAddress, id)

group?.isActive()
}

Function("isGroupAdmin") { clientAddress: String, id: String ->
logV("isGroupAdmin")
val client = clients[clientAddress] ?: throw XMTPException("No client")
val group = findGroup(clientAddress, id)

group?.isAdmin()
}

Function("subscribeToConversations") { clientAddress: String ->
logV("subscribeToConversations")
subscribeToConversations(clientAddress = clientAddress)
Expand Down Expand Up @@ -762,7 +757,7 @@ class XMTPModule : Module() {
subscriptions[getConversationsKey(clientAddress)]?.cancel()
}

Function("unsubscribeFromGroups") { clientAddress: String ->
Function("unsubscribeFromGroups") { clientAddress: String ->
logV("unsubscribeFromGroups")
subscriptions[getGroupsKey(clientAddress)]?.cancel()
}
Expand Down Expand Up @@ -894,26 +889,26 @@ class XMTPModule : Module() {
return null
}

private fun findGroup(
clientAddress: String,
id: String,
): Group? {
val client = clients[clientAddress] ?: throw XMTPException("No client")

val cacheKey = "${clientAddress}:${id}"
val cacheGroup = groups[cacheKey]
if (cacheGroup != null) {
return cacheGroup
} else {
val group = client.conversations.listGroups()
.firstOrNull {it.id.toHex() == id }
if (group != null) {
groups[group.cacheKey(clientAddress)] = group
return group
}
}
return null
}
private fun findGroup(
clientAddress: String,
id: String,
): Group? {
val client = clients[clientAddress] ?: throw XMTPException("No client")

val cacheKey = "${clientAddress}:${id}"
val cacheGroup = groups[cacheKey]
if (cacheGroup != null) {
return cacheGroup
} else {
val group = client.conversations.listGroups()
.firstOrNull { it.id.toHex() == id }
if (group != null) {
groups[group.cacheKey(clientAddress)] = group
return group
}
}
return null
}

private fun subscribeToConversations(clientAddress: String) {
val client = clients[clientAddress] ?: throw XMTPException("No client")
Expand Down Expand Up @@ -970,7 +965,10 @@ class XMTPModule : Module() {
"conversationContainer",
mapOf(
"clientAddress" to clientAddress,
"conversationContainer" to ConversationContainerWrapper.encodeToObj(client, conversation)
"conversationContainer" to ConversationContainerWrapper.encodeToObj(
client,
conversation
)
)
)
}
Expand Down Expand Up @@ -1110,7 +1108,7 @@ class XMTPModule : Module() {
}

private fun requireNotProductionEnvForAlphaMLS(enableAlphaMls: Boolean?, environment: String) {
if (enableAlphaMls == true && (environment == "production" )) {
if (enableAlphaMls == true && (environment == "production")) {
throw XMTPException("Environment must be \"local\" or \"dev\" to enable alpha MLS")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,25 @@ import com.google.gson.GsonBuilder
import org.xmtp.android.library.Client
import org.xmtp.android.library.Group
import org.xmtp.android.library.toHex
import uniffi.xmtpv3.GroupPermissions

class GroupWrapper {

companion object {
fun encodeToObj(client: Client, group: Group): Map<String, Any> {
val permissionString = when (group.permissionLevel()) {
GroupPermissions.EVERYONE_IS_ADMIN -> "everyone_admin"
GroupPermissions.GROUP_CREATOR_IS_ADMIN -> "creator_admin"
}
return mapOf(
"clientAddress" to client.address,
"id" to group.id.toHex(),
"createdAt" to group.createdAt.time,
"peerAddresses" to group.memberAddresses(),
"version" to "GROUP",
"topic" to group.id.toHex()
"topic" to group.id.toHex(),
"permissionLevel" to permissionString,
"adminAddress" to group.adminAddress()
)
}

Expand Down
14 changes: 7 additions & 7 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ PODS:
- hermes-engine/Pre-built (= 0.71.14)
- hermes-engine/Pre-built (0.71.14)
- libevent (2.1.12)
- LibXMTP (0.4.2-beta1)
- LibXMTP (0.4.2-beta3)
- Logging (1.0.0)
- MessagePacker (0.4.7)
- MMKV (1.3.3):
Expand Down Expand Up @@ -442,16 +442,16 @@ PODS:
- GenericJSON (~> 2.0)
- Logging (~> 1.0.0)
- secp256k1.swift (~> 0.1)
- XMTP (0.8.7):
- XMTP (0.8.9):
- Connect-Swift (= 0.3.0)
- GzipSwift
- LibXMTP (= 0.4.2-beta1)
- LibXMTP (= 0.4.2-beta3)
- web3.swift
- XMTPReactNative (0.1.0):
- ExpoModulesCore
- MessagePacker
- secp256k1.swift
- XMTP (= 0.8.7)
- XMTP (= 0.8.9)
- Yoga (1.14.0)

DEPENDENCIES:
Expand Down Expand Up @@ -695,7 +695,7 @@ SPEC CHECKSUMS:
GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa
hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
LibXMTP: 026f2fec3c88b24e92f21895b29a12817fa54779
LibXMTP: d6e1d416c7138b3593dfd7a6f07c8e88537c00eb
Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26
MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02
MMKV: f902fb6719da13c2ab0965233d8963a59416f911
Expand Down Expand Up @@ -744,8 +744,8 @@ SPEC CHECKSUMS:
secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634
SwiftProtobuf: b02b5075dcf60c9f5f403000b3b0c202a11b6ae1
web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959
XMTP: 35a0ca7e90bbabf4c49a862ae7750626324f55bf
XMTPReactNative: 3fc471163e34f82b44dbf29f2d0ae366cc07f502
XMTP: 4bc651602abefdb119a7ac2e8a12e9bf67aa3447
XMTPReactNative: 4c0ae41719aa36ca90c3f65ff998977c3011bca8
Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9

PODFILE CHECKSUM: 95d6ace79946933ecf80684613842ee553dd76a2
Expand Down
Loading

0 comments on commit 295487d

Please sign in to comment.