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

feat: add preCreateIdentityCallback & preEnableIdentityCallback #177

Merged
merged 10 commits into from
Dec 16, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.xmtp.android.library.Client
import org.xmtp.android.library.ClientOptions
import org.xmtp.android.library.ConsentState
import org.xmtp.android.library.Conversation
import org.xmtp.android.library.PreEventCallback
import org.xmtp.android.library.PreparedMessage
import org.xmtp.android.library.SendOptions
import org.xmtp.android.library.SigningKey
Expand Down Expand Up @@ -128,7 +129,14 @@ class XMTPModule : Module() {

override fun definition() = ModuleDefinition {
Name("XMTP")
Events("sign", "authed", "conversation", "message")
Events(
"sign",
"authed",
"conversation",
"message",
"preEnableIdentityCallback",
"preCreateIdentityCallback"
)

Function("address") { clientAddress: String ->
logV("address")
Expand All @@ -139,11 +147,19 @@ class XMTPModule : Module() {
//
// Auth functions
//
AsyncFunction("auth") { address: String, environment: String, appVersion: String? ->
AsyncFunction("auth") { address: String, environment: String, appVersion: String?, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean? ->
logV("auth")
val reactSigner = ReactNativeSigner(module = this@XMTPModule, address = address)
signer = reactSigner
val options = ClientOptions(api = apiEnvironments(environment, appVersion))
val preCreateIdentityCallback: PreEventCallback? =
preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true }
val preEnableIdentityCallback: PreEventCallback? =
preEnableIdentityCallback.takeIf { hasEnableIdentityCallback == true }
val options = ClientOptions(
api = apiEnvironments(environment, appVersion),
preCreateIdentityCallback = preCreateIdentityCallback,
preEnableIdentityCallback = preEnableIdentityCallback
)
clients[address] = Client().create(account = reactSigner, options = options)
signer = null
sendEvent("authed")
Expand All @@ -155,10 +171,19 @@ class XMTPModule : Module() {
}

// Generate a random wallet and set the client to that
AsyncFunction("createRandom") { environment: String, appVersion: String? ->
AsyncFunction("createRandom") { environment: String, appVersion: String?, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean? ->
logV("createRandom")
val privateKey = PrivateKeyBuilder()
val options = ClientOptions(api = apiEnvironments(environment, appVersion))
val preCreateIdentityCallback: PreEventCallback? =
preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true }
val preEnableIdentityCallback: PreEventCallback? =
preEnableIdentityCallback.takeIf { hasEnableIdentityCallback == true }

val options = ClientOptions(
api = apiEnvironments(environment, appVersion),
preCreateIdentityCallback = preCreateIdentityCallback,
preEnableIdentityCallback = preEnableIdentityCallback
)
val randomClient = Client().create(account = privateKey, options = options)
clients[randomClient.address] = randomClient
randomClient.address
Expand Down Expand Up @@ -684,6 +709,14 @@ class XMTPModule : Module() {
Log.v("XMTPModule", msg)
}
}

private val preEnableIdentityCallback: suspend () -> Unit = {
sendEvent("preEnableIdentityCallback")
}

private val preCreateIdentityCallback: suspend () -> Unit = {
sendEvent("preCreateIdentityCallback")
}
}


34 changes: 34 additions & 0 deletions example/src/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -743,3 +743,37 @@ test('register and use custom content types', async () => {

return true
})

test('calls preCreateIdentityCallback when supplied', async () => {
let isCallbackCalled = false
const preCreateIdentityCallback = () => {
isCallbackCalled = true
}
await Client.createRandom({
env: 'local',
preCreateIdentityCallback,
})

if (!isCallbackCalled) {
throw new Error('preCreateIdentityCallback not called')
}

return isCallbackCalled
})

test('calls preEnableIdentityCallback when supplied', async () => {
let isCallbackCalled = false
const preEnableIdentityCallback = () => {
isCallbackCalled = true
}
await Client.createRandom({
env: 'local',
preEnableIdentityCallback,
})

if (!isCallbackCalled) {
throw new Error('preEnableIdentityCallback not called')
}

return isCallbackCalled
})
77 changes: 45 additions & 32 deletions ios/XMTPModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public class XMTPModule: Module {
public func definition() -> ModuleDefinition {
Name("XMTP")

Events("sign", "authed", "conversation", "message")
Events("sign", "authed", "conversation", "message", "preEnableIdentityCallback", "preCreateIdentityCallback")

AsyncFunction("address") { (clientAddress: String) -> String in
if let client = await clientsManager.getClient(key: clientAddress) {
Expand All @@ -64,10 +64,12 @@ public class XMTPModule: Module {
//
// Auth functions
//
AsyncFunction("auth") { (address: String, environment: String, appVersion: String?) in
AsyncFunction("auth") { (address: String, environment: String, appVersion: String?, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?) in
let signer = ReactNativeSigner(module: self, address: address)
self.signer = signer
let options = createClientConfig(env: environment, appVersion: appVersion)
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)
try await clientsManager.updateClient(key: address, client: await XMTP.Client.create(account: signer, options: options))
self.signer = nil
sendEvent("authed")
Expand All @@ -78,9 +80,12 @@ public class XMTPModule: Module {
}

// Generate a random wallet and set the client to that
AsyncFunction("createRandom") { (environment: String, appVersion: String?) -> String in
AsyncFunction("createRandom") { (environment: String, appVersion: String?, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?) -> String in
let privateKey = try PrivateKey.generate()
let options = createClientConfig(env: environment, appVersion: appVersion)
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)
let client = try await Client.create(account: privateKey, options: options)

await clientsManager.updateClient(key: client.address, client: client)
Expand Down Expand Up @@ -146,14 +151,14 @@ public class XMTPModule: Module {
return try await client.canMessage(peerAddress)
}

AsyncFunction("staticCanMessage") { (peerAddress: String, environment: String, appVersion: String?) -> Bool in
do {
let options = createClientConfig(env: environment, appVersion: appVersion)
return try await XMTP.Client.canMessage(peerAddress, options: options)
} catch {
throw Error.noClient
}
}
AsyncFunction("staticCanMessage") { (peerAddress: String, environment: String, appVersion: String?) -> Bool in
do {
let options = createClientConfig(env: environment, appVersion: appVersion)
return try await XMTP.Client.canMessage(peerAddress, options: options)
} catch {
throw Error.noClient
}
}

AsyncFunction("encryptAttachment") { (clientAddress: String, fileJson: String) -> String in
guard let client = await clientsManager.getClient(key: clientAddress) else {
Expand Down Expand Up @@ -506,56 +511,56 @@ public class XMTPModule: Module {
throw Error.noClient
}
let consentList = try await client.contacts.refreshConsentList()
return try consentList.entries.compactMap { entry in
try ConsentWrapper.encode(entry.value)
}

return try consentList.entries.compactMap { entry in
try ConsentWrapper.encode(entry.value)
}
}

AsyncFunction("conversationConsentState") { (clientAddress: String, conversationTopic: String) -> String in
guard let conversation = try await findConversation(clientAddress: clientAddress, topic: conversationTopic) else {
throw Error.conversationNotFound(conversationTopic)
}
return ConsentWrapper.consentStateToString(state: await conversation.consentState())
return ConsentWrapper.consentStateToString(state: await conversation.consentState())
}

AsyncFunction("consentList") { (clientAddress: String) -> [String] in
guard let client = await clientsManager.getClient(key: clientAddress) else {
throw Error.noClient
}
let entries = await client.contacts.consentList.entries
return try entries.compactMap { entry in
try ConsentWrapper.encode(entry.value)
}
}
AsyncFunction("consentList") { (clientAddress: String) -> [String] in
guard let client = await clientsManager.getClient(key: clientAddress) else {
throw Error.noClient
}
let entries = await client.contacts.consentList.entries

return try entries.compactMap { entry in
try ConsentWrapper.encode(entry.value)
}
}
}

//
// Helpers
//

func createClientConfig(env: String, appVersion: String?) -> XMTP.ClientOptions {
func createClientConfig(env: String, appVersion: String?, preEnableIdentityCallback: PreEventCallback? = nil, preCreateIdentityCallback: PreEventCallback? = 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)
case "production":
return XMTP.ClientOptions(api: XMTP.ClientOptions.Api(
env: XMTP.XMTPEnvironment.production,
isSecure: true,
appVersion: appVersion
))
), preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback)
default:
return XMTP.ClientOptions(api: XMTP.ClientOptions.Api(
env: XMTP.XMTPEnvironment.dev,
isSecure: true,
appVersion: appVersion
))
), preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback)
}
}

Expand Down Expand Up @@ -665,4 +670,12 @@ public class XMTPModule: Module {
func getConversationsKey(clientAddress: String) -> String {
return "conversations:\(clientAddress)"
}

func preEnableIdentityCallback() {
sendEvent("preEnableIdentityCallback")
}

func preCreateIdentityCallback() {
sendEvent("preCreateIdentityCallback")
}
}
23 changes: 19 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,17 @@ export function address(): string {
export async function auth(
address: string,
environment: 'local' | 'dev' | 'production',
appVersion?: string | undefined
appVersion?: string | undefined,
hasCreateIdentityCallback?: boolean | undefined,
hasEnableIdentityCallback?: boolean | undefined
) {
return await XMTPModule.auth(address, environment, appVersion)
return await XMTPModule.auth(
address,
environment,
appVersion,
hasCreateIdentityCallback,
hasEnableIdentityCallback
)
}

export async function receiveSignature(requestID: string, signature: string) {
Expand All @@ -42,9 +50,16 @@ export async function receiveSignature(requestID: string, signature: string) {

export async function createRandom(
environment: 'local' | 'dev' | 'production',
appVersion?: string | undefined
appVersion?: string | undefined,
hasCreateIdentityCallback?: boolean | undefined,
hasEnableIdentityCallback?: boolean | undefined
): Promise<string> {
return await XMTPModule.createRandom(environment, appVersion)
return await XMTPModule.createRandom(
environment,
appVersion,
hasCreateIdentityCallback,
hasEnableIdentityCallback
)
}

export async function createFromKeyBundle(
Expand Down
Loading
Loading