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
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ repositories {
dependencies {
implementation project(':expo-modules-core')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
implementation "org.xmtp:android:0.6.20"
implementation "org.xmtp:android:0.7.0"
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
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)
ContentJson.Companion
signer = null
Expand All @@ -156,10 +172,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)
ContentJson.Companion
clients[randomClient.address] = randomClient
Expand Down Expand Up @@ -687,6 +712,14 @@ class XMTPModule : Module() {
Log.v("XMTPModule", msg)
}
}

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

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


10 changes: 5 additions & 5 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -411,15 +411,15 @@ PODS:
- GenericJSON (~> 2.0)
- Logging (~> 1.0.0)
- secp256k1.swift (~> 0.1)
- XMTP (0.7.2-alpha0):
- XMTP (0.7.3-alpha0):
- Connect-Swift (= 0.3.0)
- GzipSwift
- web3.swift
- XMTPRust (= 0.3.7-beta0)
- XMTPReactNative (0.1.0):
- ExpoModulesCore
- MessagePacker
- XMTP (= 0.7.2-alpha0)
- XMTP (= 0.7.3-alpha0)
- XMTPRust (0.3.7-beta0)
- Yoga (1.14.0)

Expand Down Expand Up @@ -668,11 +668,11 @@ SPEC CHECKSUMS:
secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634
SwiftProtobuf: b02b5075dcf60c9f5f403000b3b0c202a11b6ae1
web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959
XMTP: 4930b80dc99a6a8ebcf1f292a162c1f316f78c50
XMTPReactNative: 68c723488857950d10fc8ee969de0baae8f9b2ca
XMTP: dc02c96b475e326a4a7b3d3912cc45cf3527bd0b
XMTPReactNative: 5c1111c5bd3456e75b3fa67d1ddccabb7a01df11
XMTPRust: 8848a2ba761b2c961d666632f2ad27d1082faa93
Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9

PODFILE CHECKSUM: 522d88edc2d5fac4825e60a121c24abc18983367

COCOAPODS: 1.14.3
COCOAPODS: 1.13.0
34 changes: 34 additions & 0 deletions example/src/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -751,3 +751,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")
}
}
2 changes: 1 addition & 1 deletion ios/XMTPReactNative.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ Pod::Spec.new do |s|

s.source_files = "**/*.{h,m,swift}"
s.dependency "MessagePacker"
s.dependency "XMTP", "= 0.7.2-alpha0"
s.dependency "XMTP", "= 0.7.3-alpha0"
end
23 changes: 19 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,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 @@ -44,9 +52,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