Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

main => beta #437

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ repositories {
dependencies {
implementation project(':expo-modules-core')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
implementation "org.xmtp:android:0.14.8"
implementation "org.xmtp:android:0.14.10"
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"
Expand Down
198 changes: 112 additions & 86 deletions android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -228,41 +228,44 @@ class XMTPModule : Module() {
//
// Auth functions
//
AsyncFunction("auth") { address: String, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, dbEncryptionKey: List<Int>?, authParams: String ->
logV("auth")
val reactSigner = ReactNativeSigner(module = this@XMTPModule, address = address)
signer = reactSigner
val authOptions = AuthParamsWrapper.authParamsFromJson(authParams)

if (hasCreateIdentityCallback == true)
preCreateIdentityCallbackDeferred = CompletableDeferred()
if (hasEnableIdentityCallback == true)
preEnableIdentityCallbackDeferred = CompletableDeferred()
val preCreateIdentityCallback: PreEventCallback? =
preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true }
val preEnableIdentityCallback: PreEventCallback? =
preEnableIdentityCallback.takeIf { hasEnableIdentityCallback == true }
val context = if (authOptions.enableV3) context else null
val encryptionKeyBytes =
dbEncryptionKey?.foldIndexed(ByteArray(dbEncryptionKey.size)) { i, a, v ->
a.apply { set(i, v.toByte()) }
}
AsyncFunction("auth") Coroutine { address: String, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, dbEncryptionKey: List<Int>?, authParams: String ->
withContext(Dispatchers.IO) {

logV("auth")
val reactSigner = ReactNativeSigner(module = this@XMTPModule, address = address)
signer = reactSigner
val authOptions = AuthParamsWrapper.authParamsFromJson(authParams)

if (hasCreateIdentityCallback == true)
preCreateIdentityCallbackDeferred = CompletableDeferred()
if (hasEnableIdentityCallback == true)
preEnableIdentityCallbackDeferred = CompletableDeferred()
val preCreateIdentityCallback: PreEventCallback? =
preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true }
val preEnableIdentityCallback: PreEventCallback? =
preEnableIdentityCallback.takeIf { hasEnableIdentityCallback == true }
val context = if (authOptions.enableV3) context else null
val encryptionKeyBytes =
dbEncryptionKey?.foldIndexed(ByteArray(dbEncryptionKey.size)) { i, a, v ->
a.apply { set(i, v.toByte()) }
}

val options = ClientOptions(
api = apiEnvironments(authOptions.environment, authOptions.appVersion),
preCreateIdentityCallback = preCreateIdentityCallback,
preEnableIdentityCallback = preEnableIdentityCallback,
enableV3 = authOptions.enableV3,
appContext = context,
dbEncryptionKey = encryptionKeyBytes,
dbDirectory = authOptions.dbDirectory,
historySyncUrl = authOptions.historySyncUrl
)
val client = Client().create(account = reactSigner, options = options)
clients[client.inboxId] = client
ContentJson.Companion
signer = null
sendEvent("authed", ClientWrapper.encodeToObj(client))
val options = ClientOptions(
api = apiEnvironments(authOptions.environment, authOptions.appVersion),
preCreateIdentityCallback = preCreateIdentityCallback,
preEnableIdentityCallback = preEnableIdentityCallback,
enableV3 = authOptions.enableV3,
appContext = context,
dbEncryptionKey = encryptionKeyBytes,
dbDirectory = authOptions.dbDirectory,
historySyncUrl = authOptions.historySyncUrl
)
val client = Client().create(account = reactSigner, options = options)
clients[client.inboxId] = client
ContentJson.Companion
signer = null
sendEvent("authed", ClientWrapper.encodeToObj(client))
}
}

Function("receiveSignature") { requestID: String, signature: String ->
Expand All @@ -271,74 +274,78 @@ class XMTPModule : Module() {
}

// Generate a random wallet and set the client to that
AsyncFunction("createRandom") { hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, dbEncryptionKey: List<Int>?, authParams: String ->
logV("createRandom")
val privateKey = PrivateKeyBuilder()

if (hasCreateIdentityCallback == true)
preCreateIdentityCallbackDeferred = CompletableDeferred()
if (hasEnableIdentityCallback == true)
preEnableIdentityCallbackDeferred = CompletableDeferred()
val preCreateIdentityCallback: PreEventCallback? =
preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true }
val preEnableIdentityCallback: PreEventCallback? =
preEnableIdentityCallback.takeIf { hasEnableIdentityCallback == true }

val authOptions = AuthParamsWrapper.authParamsFromJson(authParams)
val context = if (authOptions.enableV3) context else null
val encryptionKeyBytes =
dbEncryptionKey?.foldIndexed(ByteArray(dbEncryptionKey.size)) { i, a, v ->
a.apply { set(i, v.toByte()) }
}

val options = ClientOptions(
api = apiEnvironments(authOptions.environment, authOptions.appVersion),
preCreateIdentityCallback = preCreateIdentityCallback,
preEnableIdentityCallback = preEnableIdentityCallback,
enableV3 = authOptions.enableV3,
appContext = context,
dbEncryptionKey = encryptionKeyBytes,
dbDirectory = authOptions.dbDirectory,
historySyncUrl = authOptions.historySyncUrl

)
val randomClient = Client().create(account = privateKey, options = options)
AsyncFunction("createRandom") Coroutine { hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, dbEncryptionKey: List<Int>?, authParams: String ->
withContext(Dispatchers.IO) {
logV("createRandom")
val privateKey = PrivateKeyBuilder()

ContentJson.Companion
clients[randomClient.inboxId] = randomClient
ClientWrapper.encodeToObj(randomClient)
}
if (hasCreateIdentityCallback == true)
preCreateIdentityCallbackDeferred = CompletableDeferred()
if (hasEnableIdentityCallback == true)
preEnableIdentityCallbackDeferred = CompletableDeferred()
val preCreateIdentityCallback: PreEventCallback? =
preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true }
val preEnableIdentityCallback: PreEventCallback? =
preEnableIdentityCallback.takeIf { hasEnableIdentityCallback == true }

AsyncFunction("createFromKeyBundle") { keyBundle: String, dbEncryptionKey: List<Int>?, authParams: String ->
logV("createFromKeyBundle")
val authOptions = AuthParamsWrapper.authParamsFromJson(authParams)
try {
val authOptions = AuthParamsWrapper.authParamsFromJson(authParams)
val context = if (authOptions.enableV3) context else null
val encryptionKeyBytes =
dbEncryptionKey?.foldIndexed(ByteArray(dbEncryptionKey.size)) { i, a, v ->
a.apply { set(i, v.toByte()) }
}

val options = ClientOptions(
api = apiEnvironments(authOptions.environment, authOptions.appVersion),
preCreateIdentityCallback = preCreateIdentityCallback,
preEnableIdentityCallback = preEnableIdentityCallback,
enableV3 = authOptions.enableV3,
appContext = context,
dbEncryptionKey = encryptionKeyBytes,
dbDirectory = authOptions.dbDirectory,
historySyncUrl = authOptions.historySyncUrl

)
val bundle =
PrivateKeyOuterClass.PrivateKeyBundle.parseFrom(
Base64.decode(
keyBundle,
NO_WRAP
)
)
val client = Client().buildFromBundle(bundle = bundle, options = options)
val randomClient = Client().create(account = privateKey, options = options)

ContentJson.Companion
clients[client.inboxId] = client
ClientWrapper.encodeToObj(client)
} catch (e: Exception) {
throw XMTPException("Failed to create client: $e")
clients[randomClient.inboxId] = randomClient
ClientWrapper.encodeToObj(randomClient)
}
}

AsyncFunction("createFromKeyBundle") Coroutine { keyBundle: String, dbEncryptionKey: List<Int>?, authParams: String ->
withContext(Dispatchers.IO) {
logV("createFromKeyBundle")
val authOptions = AuthParamsWrapper.authParamsFromJson(authParams)
try {
val context = if (authOptions.enableV3) context else null
val encryptionKeyBytes =
dbEncryptionKey?.foldIndexed(ByteArray(dbEncryptionKey.size)) { i, a, v ->
a.apply { set(i, v.toByte()) }
}
val options = ClientOptions(
api = apiEnvironments(authOptions.environment, authOptions.appVersion),
enableV3 = authOptions.enableV3,
appContext = context,
dbEncryptionKey = encryptionKeyBytes,
dbDirectory = authOptions.dbDirectory,
historySyncUrl = authOptions.historySyncUrl
)
val bundle =
PrivateKeyOuterClass.PrivateKeyBundle.parseFrom(
Base64.decode(
keyBundle,
NO_WRAP
)
)
val client = Client().buildFromBundle(bundle = bundle, options = options)
ContentJson.Companion
clients[client.inboxId] = client
ClientWrapper.encodeToObj(client)
} catch (e: Exception) {
throw XMTPException("Failed to create client: $e")
}
}
}

Expand Down Expand Up @@ -885,6 +892,25 @@ class XMTPModule : Module() {
}
}

AsyncFunction("createGroupCustomPermissions") Coroutine { inboxId: String, peerAddresses: List<String>, permissionPolicySetJson: String, groupOptionsJson: String ->
withContext(Dispatchers.IO) {
logV("createGroup")
val client = clients[inboxId] ?: throw XMTPException("No client")
val createGroupParams =
CreateGroupParamsWrapper.createGroupParamsFromJson(groupOptionsJson)
val permissionPolicySet = PermissionPolicySetWrapper.createPermissionPolicySetFromJson(permissionPolicySetJson)
val group = client.conversations.newGroupCustomPermissions(
peerAddresses,
permissionPolicySet,
createGroupParams.groupName,
createGroupParams.groupImageUrlSquare,
createGroupParams.groupDescription,
createGroupParams.groupPinnedFrameUrl
)
GroupWrapper.encode(client, group)
}
}


AsyncFunction("listMemberInboxIds") Coroutine { inboxId: String, groupId: String ->
withContext(Dispatchers.IO) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package expo.modules.xmtpreactnativesdk.wrappers

import com.google.gson.GsonBuilder
import com.google.gson.JsonParser
import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.PermissionOption
import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.PermissionPolicySet

Expand All @@ -16,6 +17,16 @@ class PermissionPolicySetWrapper {
PermissionOption.Unknown -> "unknown"
}
}

fun createPermissionOptionFromString(permissionOptionString: String): PermissionOption {
return when (permissionOptionString) {
"allow" -> PermissionOption.Allow
"deny" -> PermissionOption.Deny
"admin" -> PermissionOption.Admin
"superAdmin" -> PermissionOption.SuperAdmin
else -> PermissionOption.Unknown
}
}
fun encodeToObj(policySet: PermissionPolicySet): Map<String, Any> {
return mapOf(
"addMemberPolicy" to fromPermissionOption(policySet.addMemberPolicy),
Expand All @@ -29,6 +40,20 @@ class PermissionPolicySetWrapper {
)
}

fun createPermissionPolicySetFromJson(permissionPolicySetJson: String): PermissionPolicySet {
val jsonObj = JsonParser.parseString(permissionPolicySetJson).asJsonObject
return PermissionPolicySet(
addMemberPolicy = createPermissionOptionFromString(jsonObj.get("addMemberPolicy").asString),
removeMemberPolicy = createPermissionOptionFromString(jsonObj.get("removeMemberPolicy").asString),
addAdminPolicy = createPermissionOptionFromString(jsonObj.get("addAdminPolicy").asString),
removeAdminPolicy = createPermissionOptionFromString(jsonObj.get("removeAdminPolicy").asString),
updateGroupNamePolicy = createPermissionOptionFromString(jsonObj.get("updateGroupNamePolicy").asString),
updateGroupDescriptionPolicy = createPermissionOptionFromString(jsonObj.get("updateGroupDescriptionPolicy").asString),
updateGroupImagePolicy = createPermissionOptionFromString(jsonObj.get("updateGroupImagePolicy").asString),
updateGroupPinnedFrameUrlPolicy = createPermissionOptionFromString(jsonObj.get("updateGroupPinnedFrameUrlPolicy").asString)
)
}

fun encodeToJsonString(policySet: PermissionPolicySet): String {
val gson = GsonBuilder().create()
val obj = encodeToObj(policySet)
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.5.6-beta0)
- LibXMTP (0.5.6-beta1)
- Logging (1.0.0)
- MessagePacker (0.4.7)
- MMKV (1.3.7):
Expand Down Expand Up @@ -449,16 +449,16 @@ PODS:
- GenericJSON (~> 2.0)
- Logging (~> 1.0.0)
- secp256k1.swift (~> 0.1)
- XMTP (0.13.7):
- XMTP (0.13.10):
- Connect-Swift (= 0.12.0)
- GzipSwift
- LibXMTP (= 0.5.6-beta0)
- LibXMTP (= 0.5.6-beta1)
- web3.swift
- XMTPReactNative (0.1.0):
- ExpoModulesCore
- MessagePacker
- secp256k1.swift
- XMTP (= 0.13.7)
- XMTP (= 0.13.10)
- Yoga (1.14.0)

DEPENDENCIES:
Expand Down Expand Up @@ -711,7 +711,7 @@ SPEC CHECKSUMS:
GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa
hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
LibXMTP: e7682dedb10e18343c011280d494a8e4a43d9eb7
LibXMTP: 2205108c6c3a2bcdc405e42d4c718ad87c31a7c2
Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26
MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02
MMKV: 36a22a9ec84c9bb960613a089ddf6f48be9312b0
Expand Down Expand Up @@ -763,8 +763,8 @@ SPEC CHECKSUMS:
secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634
SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1
web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959
XMTP: 16bd630ff61081d3a325619a26ea176ed256d419
XMTPReactNative: 4716836807cb33c72bde0846ac46b3fe923a3625
XMTP: 19f9c073262c44fbe98489208cda7a44d079064d
XMTPReactNative: 296aaa356ea5c67c98779665bcb5e1cad140d135
Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9

PODFILE CHECKSUM: 95d6ace79946933ecf80684613842ee553dd76a2
Expand Down
Loading
Loading