Skip to content

Commit

Permalink
Merge pull request #455 from xmtp/cv/pre-auth-inbox-callback
Browse files Browse the repository at this point in the history
  • Loading branch information
nmalzieu authored Aug 1, 2024
2 parents 9c662f0 + ad77903 commit e6aa77b
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 44 deletions.
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ repositories {
dependencies {
implementation project(':expo-modules-core')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
implementation "org.xmtp:android:0.14.14"
implementation "org.xmtp:android:0.14.15"
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"
// 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 files('<PATH_TO_LIBRARY>/xmtp-android/library/build/outputs/aar/library-debug.aar')
// implementation 'com.google.crypto.tink:tink-android:1.8.0'
// implementation 'io.grpc:grpc-kotlin-stub:1.4.1'
// implementation 'io.grpc:grpc-okhttp:1.62.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class XMTPModule : Module() {
private val subscriptions: MutableMap<String, Job> = mutableMapOf()
private var preEnableIdentityCallbackDeferred: CompletableDeferred<Unit>? = null
private var preCreateIdentityCallbackDeferred: CompletableDeferred<Unit>? = null
private var preAuthenticateToInboxCallbackDeferred: CompletableDeferred<Unit>? = null


override fun definition() = ModuleDefinition {
Expand All @@ -165,6 +166,7 @@ class XMTPModule : Module() {
"authed",
"preCreateIdentityCallback",
"preEnableIdentityCallback",
"preAuthenticateToInboxCallback",
// Conversations
"conversation",
"group",
Expand Down Expand Up @@ -227,7 +229,7 @@ class XMTPModule : Module() {
//
// Auth functions
//
AsyncFunction("auth") Coroutine { address: String, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, dbEncryptionKey: List<Int>?, authParams: String ->
AsyncFunction("auth") Coroutine { address: String, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, hasAuthInboxCallback: Boolean?, dbEncryptionKey: List<Int>?, authParams: String ->
withContext(Dispatchers.IO) {

logV("auth")
Expand All @@ -239,10 +241,14 @@ class XMTPModule : Module() {
preCreateIdentityCallbackDeferred = CompletableDeferred()
if (hasEnableIdentityCallback == true)
preEnableIdentityCallbackDeferred = CompletableDeferred()
if (hasAuthInboxCallback == true)
preAuthenticateToInboxCallbackDeferred = CompletableDeferred()
val preCreateIdentityCallback: PreEventCallback? =
preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true }
val preEnableIdentityCallback: PreEventCallback? =
preEnableIdentityCallback.takeIf { hasEnableIdentityCallback == true }
val preAuthenticateToInboxCallback: PreEventCallback? =
preAuthenticateToInboxCallback.takeIf { hasAuthInboxCallback == true }
val context = if (authOptions.enableV3) context else null
val encryptionKeyBytes =
dbEncryptionKey?.foldIndexed(ByteArray(dbEncryptionKey.size)) { i, a, v ->
Expand All @@ -253,6 +259,7 @@ class XMTPModule : Module() {
api = apiEnvironments(authOptions.environment, authOptions.appVersion),
preCreateIdentityCallback = preCreateIdentityCallback,
preEnableIdentityCallback = preEnableIdentityCallback,
preAuthenticateToInboxCallback = preAuthenticateToInboxCallback,
enableV3 = authOptions.enableV3,
appContext = context,
dbEncryptionKey = encryptionKeyBytes,
Expand All @@ -273,7 +280,7 @@ class XMTPModule : Module() {
}

// Generate a random wallet and set the client to that
AsyncFunction("createRandom") Coroutine { hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, dbEncryptionKey: List<Int>?, authParams: String ->
AsyncFunction("createRandom") Coroutine { hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, hasPreAuthenticateToInboxCallback: Boolean?, dbEncryptionKey: List<Int>?, authParams: String ->
withContext(Dispatchers.IO) {
logV("createRandom")
val privateKey = PrivateKeyBuilder()
Expand All @@ -282,10 +289,14 @@ class XMTPModule : Module() {
preCreateIdentityCallbackDeferred = CompletableDeferred()
if (hasEnableIdentityCallback == true)
preEnableIdentityCallbackDeferred = CompletableDeferred()
if (hasPreAuthenticateToInboxCallback == true)
preAuthenticateToInboxCallbackDeferred = CompletableDeferred()
val preCreateIdentityCallback: PreEventCallback? =
preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true }
val preEnableIdentityCallback: PreEventCallback? =
preEnableIdentityCallback.takeIf { hasEnableIdentityCallback == true }
val preAuthenticateToInboxCallback: PreEventCallback? =
preAuthenticateToInboxCallback.takeIf { hasPreAuthenticateToInboxCallback == true }

val authOptions = AuthParamsWrapper.authParamsFromJson(authParams)
val context = if (authOptions.enableV3) context else null
Expand All @@ -298,6 +309,7 @@ class XMTPModule : Module() {
api = apiEnvironments(authOptions.environment, authOptions.appVersion),
preCreateIdentityCallback = preCreateIdentityCallback,
preEnableIdentityCallback = preEnableIdentityCallback,
preAuthenticateToInboxCallback = preAuthenticateToInboxCallback,
enableV3 = authOptions.enableV3,
appContext = context,
dbEncryptionKey = encryptionKeyBytes,
Expand Down Expand Up @@ -1536,6 +1548,11 @@ class XMTPModule : Module() {
preEnableIdentityCallbackDeferred?.complete(Unit)
}

Function("preAuthenticateToInboxCallbackCompleted") {
logV("preAuthenticateToInboxCallbackCompleted")
preAuthenticateToInboxCallbackDeferred?.complete(Unit)
}

AsyncFunction("allowGroups") Coroutine { inboxId: String, groupIds: List<String> ->
withContext(Dispatchers.IO) {
logV("allowGroups")
Expand Down Expand Up @@ -1856,6 +1873,12 @@ class XMTPModule : Module() {
preCreateIdentityCallbackDeferred?.await()
preCreateIdentityCallbackDeferred = null
}

private val preAuthenticateToInboxCallback: suspend () -> Unit = {
sendEvent("preAuthenticateToInboxCallback")
preAuthenticateToInboxCallbackDeferred?.await()
preAuthenticateToInboxCallbackDeferred = null
}
}


8 changes: 4 additions & 4 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ PODS:
- GenericJSON (~> 2.0)
- Logging (~> 1.0.0)
- secp256k1.swift (~> 0.1)
- XMTP (0.13.14):
- XMTP (0.13.15):
- Connect-Swift (= 0.12.0)
- GzipSwift
- LibXMTP (= 0.5.6-beta4)
Expand All @@ -458,7 +458,7 @@ PODS:
- ExpoModulesCore
- MessagePacker
- secp256k1.swift
- XMTP (= 0.13.14)
- XMTP (= 0.13.15)
- Yoga (1.14.0)

DEPENDENCIES:
Expand Down Expand Up @@ -763,8 +763,8 @@ SPEC CHECKSUMS:
secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634
SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1
web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959
XMTP: f590939a897f00a0f957223eba31d5d6bee10a48
XMTPReactNative: ca2cdef4fcadb3e072fec62de63f379c84464250
XMTP: d364bb93ef30523ba8a66a3e57c3a39f32e06f5e
XMTPReactNative: 9ce794973cfe73271557ae504c99be9d81d80cd2
Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9

PODFILE CHECKSUM: 95d6ace79946933ecf80684613842ee553dd76a2
Expand Down
7 changes: 7 additions & 0 deletions example/src/LaunchScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ export default function LaunchScreen(
console.log('Pre Enable Identity Callback')
}

const preAuthenticateToInboxCallback = async () => {
console.log('Pre Authenticate To Inbox Callback')
}

const networkOptions = [
{ key: 0, label: 'dev' },
{ key: 1, label: 'local' },
Expand Down Expand Up @@ -222,8 +226,10 @@ export default function LaunchScreen(
XMTP.Client.create(signer, {
env: selectedNetwork,
appVersion,
codecs: supportedCodecs,
preCreateIdentityCallback,
preEnableIdentityCallback,
preAuthenticateToInboxCallback,
enableV3: enableGroups === 'true',
dbEncryptionKey,
})
Expand Down Expand Up @@ -258,6 +264,7 @@ export default function LaunchScreen(
codecs: supportedCodecs,
preCreateIdentityCallback,
preEnableIdentityCallback,
preAuthenticateToInboxCallback,
enableV3: enableGroups === 'true',
dbEncryptionKey,
})
Expand Down
39 changes: 39 additions & 0 deletions example/src/tests/groupTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,45 @@ test('can make a MLS V3 client', async () => {
return true
})

test('calls preAuthenticateToInboxCallback when supplied', async () => {
let isCallbackCalled = 0
let isPreAuthCalled = false
const preAuthenticateToInboxCallback = () => {
isCallbackCalled++
isPreAuthCalled = true
}
const preEnableIdentityCallback = () => {
isCallbackCalled++
}
const preCreateIdentityCallback = () => {
isCallbackCalled++
}
const keyBytes = new Uint8Array([
233, 120, 198, 96, 154, 65, 132, 17, 132, 96, 250, 40, 103, 35, 125, 64,
166, 83, 208, 224, 254, 44, 205, 227, 175, 49, 234, 129, 74, 252, 135, 145,
])

await Client.createRandom({
env: 'local',
enableV3: true,
preEnableIdentityCallback,
preCreateIdentityCallback,
preAuthenticateToInboxCallback,
dbEncryptionKey: keyBytes,
})

assert(
isCallbackCalled === 3,
`callback should be called 3 times but was ${isCallbackCalled}`
)

if (!isPreAuthCalled) {
throw new Error('preAuthenticateToInboxCallback not called')
}

return true
})

test('can delete a local database', async () => {
let [client, anotherClient] = await createClients(2)

Expand Down
58 changes: 50 additions & 8 deletions ios/XMTPModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class XMTPModule: Module {
let subscriptionsManager = IsolatedManager<Task<Void, Never>>()
private var preEnableIdentityCallbackDeferred: DispatchSemaphore?
private var preCreateIdentityCallbackDeferred: DispatchSemaphore?
private var preAuthenticateToInboxCallbackDeferred: DispatchSemaphore?

actor ClientsManager {
private var clients: [String: XMTP.Client] = [:]
Expand Down Expand Up @@ -71,6 +72,7 @@ public class XMTPModule: Module {
"authed",
"preCreateIdentityCallback",
"preEnableIdentityCallback",
"preAuthenticateToInboxCallback",
// Conversations
"conversation",
"group",
Expand Down Expand Up @@ -137,7 +139,7 @@ public class XMTPModule: Module {
//
// Auth functions
//
AsyncFunction("auth") { (address: String, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?, dbEncryptionKey: [UInt8]?, authParams: String) in
AsyncFunction("auth") { (address: String, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?, hasAuthenticateToInboxCallback: Bool?, dbEncryptionKey: [UInt8]?, authParams: String) in
let signer = ReactNativeSigner(module: self, address: address)
self.signer = signer
if(hasCreateIdentityCallback ?? false) {
Expand All @@ -146,12 +148,26 @@ public class XMTPModule: Module {
if(hasEnableIdentityCallback ?? false) {
self.preEnableIdentityCallbackDeferred = DispatchSemaphore(value: 0)
}
if(hasAuthenticateToInboxCallback ?? false) {
self.preAuthenticateToInboxCallbackDeferred = DispatchSemaphore(value: 0)
}
let preCreateIdentityCallback: PreEventCallback? = hasCreateIdentityCallback ?? false ? self.preCreateIdentityCallback : nil
let preEnableIdentityCallback: PreEventCallback? = hasEnableIdentityCallback ?? false ? self.preEnableIdentityCallback : nil
let preAuthenticateToInboxCallback: PreEventCallback? = hasAuthenticateToInboxCallback ?? false ? self.preAuthenticateToInboxCallback : nil
let encryptionKeyData = dbEncryptionKey == nil ? nil : Data(dbEncryptionKey!)
let authOptions = AuthParamsWrapper.authParamsFromJson(authParams)

let options = self.createClientConfig(env: authOptions.environment, appVersion: authOptions.appVersion, preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback, enableV3: authOptions.enableV3, dbEncryptionKey: encryptionKeyData, dbDirectory: authOptions.dbDirectory, historySyncUrl: authOptions.historySyncUrl)
let options = self.createClientConfig(
env: authOptions.environment,
appVersion: authOptions.appVersion,
preEnableIdentityCallback: preEnableIdentityCallback,
preCreateIdentityCallback: preCreateIdentityCallback,
preAuthenticateToInboxCallback: preAuthenticateToInboxCallback,
enableV3: authOptions.enableV3,
dbEncryptionKey: encryptionKeyData,
dbDirectory: authOptions.dbDirectory,
historySyncUrl: authOptions.historySyncUrl
)
let client = try await XMTP.Client.create(account: signer, options: options)
await self.clientsManager.updateClient(key: client.inboxID, client: client)
self.signer = nil
Expand All @@ -163,7 +179,7 @@ public class XMTPModule: Module {
}

// Generate a random wallet and set the client to that
AsyncFunction("createRandom") { (hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?, dbEncryptionKey: [UInt8]?, authParams: String) -> [String: String] in
AsyncFunction("createRandom") { (hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?, hasAuthenticateToInboxCallback: Bool?, dbEncryptionKey: [UInt8]?, authParams: String) -> [String: String] in

let privateKey = try PrivateKey.generate()
if(hasCreateIdentityCallback ?? false) {
Expand All @@ -172,12 +188,26 @@ public class XMTPModule: Module {
if(hasEnableIdentityCallback ?? false) {
preEnableIdentityCallbackDeferred = DispatchSemaphore(value: 0)
}
if(hasAuthenticateToInboxCallback ?? false) {
preAuthenticateToInboxCallbackDeferred = DispatchSemaphore(value: 0)
}
let preCreateIdentityCallback: PreEventCallback? = hasCreateIdentityCallback ?? false ? self.preCreateIdentityCallback : nil
let preEnableIdentityCallback: PreEventCallback? = hasEnableIdentityCallback ?? false ? self.preEnableIdentityCallback : nil
let preAuthenticateToInboxCallback: PreEventCallback? = hasAuthenticateToInboxCallback ?? false ? self.preAuthenticateToInboxCallback : nil
let encryptionKeyData = dbEncryptionKey == nil ? nil : Data(dbEncryptionKey!)
let authOptions = AuthParamsWrapper.authParamsFromJson(authParams)

let options = createClientConfig(env: authOptions.environment, appVersion: authOptions.appVersion, preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback, enableV3: authOptions.enableV3, dbEncryptionKey: encryptionKeyData, dbDirectory: authOptions.dbDirectory, historySyncUrl: authOptions.historySyncUrl)
let options = createClientConfig(
env: authOptions.environment,
appVersion: authOptions.appVersion,
preEnableIdentityCallback: preEnableIdentityCallback,
preCreateIdentityCallback: preCreateIdentityCallback,
preAuthenticateToInboxCallback: preAuthenticateToInboxCallback,
enableV3: authOptions.enableV3,
dbEncryptionKey: encryptionKeyData,
dbDirectory: authOptions.dbDirectory,
historySyncUrl: authOptions.historySyncUrl
)
let client = try await Client.create(account: privateKey, options: options)

await clientsManager.updateClient(key: client.inboxID, client: client)
Expand Down Expand Up @@ -1414,6 +1444,13 @@ public class XMTPModule: Module {
self.preCreateIdentityCallbackDeferred = nil
}
}

Function("preAuthenticateToInboxCallbackCompleted") {
DispatchQueue.global().async {
self.preAuthenticateToInboxCallbackDeferred?.signal()
self.preAuthenticateToInboxCallbackDeferred = nil
}
}

AsyncFunction("allowGroups") { (inboxId: String, groupIds: [String]) in
guard let client = await clientsManager.getClient(key: inboxId) else {
Expand Down Expand Up @@ -1463,27 +1500,27 @@ public class XMTPModule: Module {
}
}

func createClientConfig(env: String, appVersion: String?, preEnableIdentityCallback: PreEventCallback? = nil, preCreateIdentityCallback: PreEventCallback? = nil, enableV3: Bool = false, dbEncryptionKey: Data? = nil, dbDirectory: String? = nil, historySyncUrl: String? = nil) -> XMTP.ClientOptions {
func createClientConfig(env: String, appVersion: String?, preEnableIdentityCallback: PreEventCallback? = nil, preCreateIdentityCallback: PreEventCallback? = nil, preAuthenticateToInboxCallback: PreEventCallback? = nil, enableV3: Bool = false, dbEncryptionKey: Data? = nil, dbDirectory: String? = nil, historySyncUrl: String? = nil) -> XMTP.ClientOptions {
// Ensure that all codecs have been registered.
switch env {
case "local":
return XMTP.ClientOptions(api: XMTP.ClientOptions.Api(
env: XMTP.XMTPEnvironment.local,
isSecure: false,
appVersion: appVersion
), preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback, enableV3: enableV3, encryptionKey: dbEncryptionKey, dbDirectory: dbDirectory, historySyncUrl: historySyncUrl)
), preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback, preAuthenticateToInboxCallback: preAuthenticateToInboxCallback, enableV3: enableV3, encryptionKey: dbEncryptionKey, dbDirectory: dbDirectory, historySyncUrl: historySyncUrl)
case "production":
return XMTP.ClientOptions(api: XMTP.ClientOptions.Api(
env: XMTP.XMTPEnvironment.production,
isSecure: true,
appVersion: appVersion
), preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback, enableV3: enableV3, encryptionKey: dbEncryptionKey, dbDirectory: dbDirectory, historySyncUrl: historySyncUrl)
), preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback, preAuthenticateToInboxCallback: preAuthenticateToInboxCallback, enableV3: enableV3, encryptionKey: dbEncryptionKey, dbDirectory: dbDirectory, historySyncUrl: historySyncUrl)
default:
return XMTP.ClientOptions(api: XMTP.ClientOptions.Api(
env: XMTP.XMTPEnvironment.dev,
isSecure: true,
appVersion: appVersion
), preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback, enableV3: enableV3, encryptionKey: dbEncryptionKey, dbDirectory: dbDirectory, historySyncUrl: historySyncUrl)
), preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback, preAuthenticateToInboxCallback: preAuthenticateToInboxCallback, enableV3: enableV3, encryptionKey: dbEncryptionKey, dbDirectory: dbDirectory, historySyncUrl: historySyncUrl)
}
}

Expand Down Expand Up @@ -1734,4 +1771,9 @@ public class XMTPModule: Module {
sendEvent("preCreateIdentityCallback")
self.preCreateIdentityCallbackDeferred?.wait()
}

func preAuthenticateToInboxCallback() {
sendEvent("preAuthenticateToInboxCallback")
self.preAuthenticateToInboxCallbackDeferred?.wait()
}
}
2 changes: 1 addition & 1 deletion ios/XMTPReactNative.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ Pod::Spec.new do |s|
s.source_files = "**/*.{h,m,swift}"
s.dependency 'secp256k1.swift'
s.dependency "MessagePacker"
s.dependency "XMTP", "= 0.13.14"
s.dependency "XMTP", "= 0.13.15"
end
Loading

0 comments on commit e6aa77b

Please sign in to comment.