diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index 9ac1fb62a..c9493a0b9 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -133,6 +133,7 @@ class XMTPModule : Module() { } AsyncFunction("createFromKeyBundle") { keyBundle: String, environment: String -> + try { logV("createFromKeyBundle") val options = ClientOptions(api = apiEnvironments[environment] ?: apiEnvironments["dev"]!!) @@ -141,6 +142,9 @@ class XMTPModule : Module() { val client = Client().buildFromBundle(bundle = bundle, options = options) clients[client.address] = client client.address + } catch (e: Exception) { + throw XMTPException("Failed to create client: $e") + } } AsyncFunction("exportKeyBundle") { clientAddress: String -> diff --git a/example/src/tests.ts b/example/src/tests.ts index 1c01d91c6..fd8d7be01 100644 --- a/example/src/tests.ts +++ b/example/src/tests.ts @@ -5,6 +5,7 @@ import * as XMTP from "../../src/index"; import { DecodedMessage } from "../../src/index"; import { CodecError } from "../../src/lib/CodecError"; import { CodecRegistry } from "../../src/lib/CodecRegistry"; +import { randomBytes } from "crypto"; function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); @@ -178,3 +179,13 @@ test("can send and receive number codec", async () => { return false; } }); + +test("createFromKeyBundle throws error for non string value", async () => { + try { + const bytes = randomBytes(32); + await XMTP.Client.createFromKeyBundle(JSON.stringify(bytes), "local"); + } catch (e) { + return true; + } + return false; +}); diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index b13ff1bd8..166e7e463 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -91,7 +91,8 @@ public class XMTPModule: Module { var subscriptions: [String: Task] = [:] enum Error: Swift.Error { - case noClient, conversationNotFound(String), noMessage + case noClient, conversationNotFound(String), noMessage, invalidKeyBundle + } public func definition() -> ModuleDefinition { @@ -135,11 +136,20 @@ public class XMTPModule: Module { // Create a client using its serialized key bundle. AsyncFunction("createFromKeyBundle") { (keyBundle: String, environment: String) -> String in - let bundle = try PrivateKeyBundle(serializedData: Data(base64Encoded: Data(keyBundle.utf8))!) - let options = XMTP.ClientOptions(api: apiEnvironments[environment] ?? apiEnvironments["dev"]!) - let client = try await Client.from(bundle: bundle, options: options) - self.clients[client.address] = client - return client.address + do { + guard let keyBundleData = Data(base64Encoded: keyBundle), + let bundle = try? PrivateKeyBundle(serializedData: keyBundleData) else { + throw Error.invalidKeyBundle + } + + let options = XMTP.ClientOptions(api: apiEnvironments[environment] ?? apiEnvironments["dev"]!) + let client = try await Client.from(bundle: bundle, options: options) + self.clients[client.address] = client + return client.address + } catch { + print("ERRO! Failed to create client: \(error)") + throw error + } } // Export the client's serialized key bundle.