Skip to content

Commit

Permalink
Merge pull request #193 from xmtp/cameronvoell/sign-actions-wait-for-…
Browse files Browse the repository at this point in the history
…callbacks

fix: sign actions should wait for preCallback completion before proceeding
  • Loading branch information
nplasterer authored Jan 3, 2024
2 parents 0f6324c + 8560716 commit 66cc38c
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import expo.modules.xmtpreactnativesdk.wrappers.DecodedMessageWrapper
import expo.modules.xmtpreactnativesdk.wrappers.DecryptedLocalAttachment
import expo.modules.xmtpreactnativesdk.wrappers.EncryptedLocalAttachment
import expo.modules.xmtpreactnativesdk.wrappers.PreparedLocalMessage
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
Expand Down Expand Up @@ -126,6 +127,9 @@ class XMTPModule : Module() {
private val isDebugEnabled = BuildConfig.DEBUG // TODO: consider making this configurable
private val conversations: MutableMap<String, Conversation> = mutableMapOf()
private val subscriptions: MutableMap<String, Job> = mutableMapOf()
private var preEnableIdentityCallbackDeferred: CompletableDeferred<Unit>? = null
private var preCreateIdentityCallbackDeferred: CompletableDeferred<Unit>? = null


override fun definition() = ModuleDefinition {
Name("XMTP")
Expand All @@ -151,6 +155,11 @@ class XMTPModule : Module() {
logV("auth")
val reactSigner = ReactNativeSigner(module = this@XMTPModule, address = address)
signer = reactSigner

if (hasCreateIdentityCallback == true)
preCreateIdentityCallbackDeferred = CompletableDeferred()
if (hasEnableIdentityCallback == true)
preEnableIdentityCallbackDeferred = CompletableDeferred()
val preCreateIdentityCallback: PreEventCallback? =
preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true }
val preEnableIdentityCallback: PreEventCallback? =
Expand All @@ -175,6 +184,11 @@ class XMTPModule : Module() {
AsyncFunction("createRandom") { environment: String, appVersion: String?, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean? ->
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? =
Expand Down Expand Up @@ -623,6 +637,16 @@ class XMTPModule : Module() {
val client = clients[clientAddress] ?: throw XMTPException("No client")
client.contacts.consentList.entries.map { ConsentWrapper.encode(it.value) }
}

Function("preCreateIdentityCallbackCompleted") {
logV("preCreateIdentityCallbackCompleted")
preCreateIdentityCallbackDeferred?.complete(Unit)
}

Function("preEnableIdentityCallbackCompleted") {
logV("preEnableIdentityCallbackCompleted")
preEnableIdentityCallbackDeferred?.complete(Unit)
}
}

//
Expand Down Expand Up @@ -748,10 +772,14 @@ class XMTPModule : Module() {

private val preEnableIdentityCallback: suspend () -> Unit = {
sendEvent("preEnableIdentityCallback")
preEnableIdentityCallbackDeferred?.await()
preCreateIdentityCallbackDeferred == null
}

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

Expand Down
30 changes: 30 additions & 0 deletions ios/XMTPModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public class XMTPModule: Module {
let clientsManager = ClientsManager()
let conversationsManager = IsolatedManager<Conversation>()
let subscriptionsManager = IsolatedManager<Task<Void, Never>>()
private var preEnableIdentityCallbackDeferred: DispatchSemaphore?
private var preCreateIdentityCallbackDeferred: DispatchSemaphore?

actor ClientsManager {
private var clients: [String: XMTP.Client] = [:]
Expand Down Expand Up @@ -67,6 +69,12 @@ public class XMTPModule: Module {
AsyncFunction("auth") { (address: String, environment: String, appVersion: String?, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?) in
let signer = ReactNativeSigner(module: self, address: address)
self.signer = signer
if(hasCreateIdentityCallback ?? false) {
preCreateIdentityCallbackDeferred = DispatchSemaphore(value: 0)
}
if(hasEnableIdentityCallback ?? false) {
preEnableIdentityCallbackDeferred = DispatchSemaphore(value: 0)
}
let preCreateIdentityCallback: PreEventCallback? = hasCreateIdentityCallback ?? false ? self.preCreateIdentityCallback : nil
let preEnableIdentityCallback: PreEventCallback? = hasEnableIdentityCallback ?? false ? self.preEnableIdentityCallback : nil
let options = createClientConfig(env: environment, appVersion: appVersion, preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback)
Expand All @@ -82,6 +90,12 @@ public class XMTPModule: Module {
// Generate a random wallet and set the client to that
AsyncFunction("createRandom") { (environment: String, appVersion: String?, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?) -> String in
let privateKey = try PrivateKey.generate()
if(hasCreateIdentityCallback ?? false) {
preCreateIdentityCallbackDeferred = DispatchSemaphore(value: 0)
}
if(hasEnableIdentityCallback ?? false) {
preEnableIdentityCallbackDeferred = DispatchSemaphore(value: 0)
}
let preCreateIdentityCallback: PreEventCallback? = hasCreateIdentityCallback ?? false ? self.preCreateIdentityCallback : nil
let preEnableIdentityCallback: PreEventCallback? = hasEnableIdentityCallback ?? false ? self.preEnableIdentityCallback : nil

Expand Down Expand Up @@ -558,6 +572,18 @@ public class XMTPModule: Module {
try ConsentWrapper.encode(entry.value)
}
}

Function("preEnableIdentityCallbackCompleted") {
DispatchQueue.global().async {
self.preEnableIdentityCallbackDeferred?.signal()
}
}

Function("preCreateIdentityCallbackCompleted") {
DispatchQueue.global().async {
self.preCreateIdentityCallbackDeferred?.signal()
}
}
}

//
Expand Down Expand Up @@ -697,9 +723,13 @@ public class XMTPModule: Module {

func preEnableIdentityCallback() {
sendEvent("preEnableIdentityCallback")
self.preEnableIdentityCallbackDeferred?.wait()
self.preCreateIdentityCallbackDeferred = nil
}

func preCreateIdentityCallback() {
sendEvent("preCreateIdentityCallback")
self.preCreateIdentityCallbackDeferred?.wait()
self.preEnableIdentityCallbackDeferred = nil
}
}
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,14 @@ export async function consentList(
})
}

export function preEnableIdentityCallbackCompleted() {
XMTPModule.preEnableIdentityCallbackCompleted()
}

export function preCreateIdentityCallbackCompleted() {
XMTPModule.preCreateIdentityCallbackCompleted()
}

export const emitter = new EventEmitter(XMTPModule ?? NativeModulesProxy.XMTP)

export * from './lib/ContentCodec'
Expand Down
2 changes: 2 additions & 0 deletions src/lib/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ export class Client<ContentTypes> {
opts,
async () => {
await this.executeCallback(opts?.preEnableIdentityCallback)
XMTPModule.preEnableIdentityCallbackCompleted()
}
)

Expand All @@ -244,6 +245,7 @@ export class Client<ContentTypes> {
opts,
async () => {
await this.executeCallback(opts?.preCreateIdentityCallback)
XMTPModule.preCreateIdentityCallbackCompleted()
}
)

Expand Down

0 comments on commit 66cc38c

Please sign in to comment.