diff --git a/android/build.gradle b/android/build.gradle index 812c6841..0dee991a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -98,7 +98,7 @@ repositories { dependencies { implementation project(':expo-modules-core') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}" - implementation "org.xmtp:android:3.0.10" + implementation "org.xmtp:android:3.0.13" 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" diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index a4d2db31..8974d6bd 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -332,14 +332,14 @@ class XMTPModule : Module() { } } - AsyncFunction("build") Coroutine { address: String, dbEncryptionKey: List, authParams: String -> + AsyncFunction("build") Coroutine { address: String, inboxId: String?, dbEncryptionKey: List, authParams: String -> withContext(Dispatchers.IO) { logV("build") val options = clientOptions( dbEncryptionKey, authParams, ) - val client = Client().build(address = address, options = options) + val client = Client().build(address = address, options = options, inboxId = inboxId) ContentJson.Companion clients[client.installationId] = client ClientWrapper.encodeToObj(client) @@ -444,6 +444,17 @@ class XMTPModule : Module() { } } + AsyncFunction("staticCanMessage") Coroutine { environment: String, peerAddresses: List -> + withContext(Dispatchers.IO) { + logV("staticCanMessage") + Client.canMessage( + peerAddresses, + context, + apiEnvironments(environment, null) + ) + } + } + AsyncFunction("getOrCreateInboxId") Coroutine { address: String, environment: String -> withContext(Dispatchers.IO) { try { diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index cf4baccd..9d3bc8eb 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -55,7 +55,7 @@ PODS: - hermes-engine/Pre-built (= 0.71.14) - hermes-engine/Pre-built (0.71.14) - libevent (2.1.12) - - LibXMTP (3.0.7) + - LibXMTP (3.0.10) - MessagePacker (0.4.7) - MMKV (2.0.0): - MMKVCore (~> 2.0.0) @@ -440,17 +440,24 @@ PODS: - React-RCTImage - RNSVG (13.14.0): - React-Core + - SQLCipher (4.5.7): + - SQLCipher/standard (= 4.5.7) + - SQLCipher/common (4.5.7) + - SQLCipher/standard (4.5.7): + - SQLCipher/common - SwiftProtobuf (1.28.2) - - XMTP (3.0.10): + - XMTP (3.0.14): - Connect-Swift (= 1.0.0) - CryptoSwift (= 1.8.3) - CSecp256k1 (~> 0.2) - - LibXMTP (= 3.0.7) + - LibXMTP (= 3.0.10) + - SQLCipher (= 4.5.7) - XMTPReactNative (0.1.0): - CSecp256k1 (~> 0.2) - ExpoModulesCore - MessagePacker - - XMTP (= 3.0.10) + - SQLCipher (= 4.5.7) + - XMTP (= 3.0.14) - Yoga (1.14.0) DEPENDENCIES: @@ -536,6 +543,7 @@ SPEC REPOS: - MMKV - MMKVCore - OpenSSL-Universal + - SQLCipher - SwiftProtobuf - XMTP @@ -698,7 +706,7 @@ SPEC CHECKSUMS: glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - LibXMTP: 1d9b9514c2b6407a82d72b203288cd5af064d787 + LibXMTP: e550ccb4565023eb77f5a2eddd9d5a71cfb9d2b3 MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02 MMKV: f7d1d5945c8765f97f39c3d121f353d46735d801 MMKVCore: c04b296010fcb1d1638f2c69405096aac12f6390 @@ -746,9 +754,10 @@ SPEC CHECKSUMS: RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396 + SQLCipher: 5e6bfb47323635c8b657b1b27d25c5f1baf63bf5 SwiftProtobuf: 4dbaffec76a39a8dc5da23b40af1a5dc01a4c02d - XMTP: 22bd60ccd58801953c1bbc7619b0046b2eef5b97 - XMTPReactNative: 48e8bbbb9c1800cd507121bd9918aa4a571e8237 + XMTP: 3b586fa3703640bb5fec8a64daba9e157d9e5fdc + XMTPReactNative: ab20c0030e2092fb7201c42d6ec17a7055ec6bf8 Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 PODFILE CHECKSUM: 0e6fe50018f34e575d38dc6a1fdf1f99c9596cdd diff --git a/example/ios/xmtpreactnativesdkexample.xcodeproj/project.pbxproj b/example/ios/xmtpreactnativesdkexample.xcodeproj/project.pbxproj index c977d86d..2400bd11 100644 --- a/example/ios/xmtpreactnativesdkexample.xcodeproj/project.pbxproj +++ b/example/ios/xmtpreactnativesdkexample.xcodeproj/project.pbxproj @@ -296,6 +296,7 @@ "${PODS_CONFIGURATION_BUILD_DIR}/CryptoSwift/CryptoSwift.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/SQLCipher/SQLCipher.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/SwiftProtobuf/SwiftProtobuf.bundle", ); name = "[CP] Copy Pods Resources"; @@ -303,6 +304,7 @@ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/CryptoSwift.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SQLCipher.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SwiftProtobuf.bundle", ); runOnlyForDeploymentPostprocessing = 0; diff --git a/example/src/tests/clientTests.ts b/example/src/tests/clientTests.ts index b3ff2496..b05405f9 100644 --- a/example/src/tests/clientTests.ts +++ b/example/src/tests/clientTests.ts @@ -34,6 +34,34 @@ test('can make a client', async () => { return true }) +test('static can message', async () => { + const [alix, bo] = await createClients(2) + + const addressMap = await Client.canMessage('local', [ + alix.address, + '0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67', + bo.address, + ]) + + assert( + addressMap[ + '0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67'.toLocaleLowerCase() + ] === false, + `should not be able to message 0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67` + ) + + assert( + addressMap[alix.address.toLowerCase()] === true, + `should be able to message ${alix.address}` + ) + + assert( + addressMap[bo.address.toLowerCase()] === true, + `should be able to message ${bo.address}` + ) + return true +}) + test('can revoke all other installations', async () => { const keyBytes = new Uint8Array([ 233, 120, 198, 96, 154, 65, 132, 17, 132, 96, 250, 40, 103, 35, 125, 64, diff --git a/example/src/tests/conversationTests.ts b/example/src/tests/conversationTests.ts index a3e58ded..3bba5c17 100644 --- a/example/src/tests/conversationTests.ts +++ b/example/src/tests/conversationTests.ts @@ -603,8 +603,6 @@ test('can sync consent', async () => { // Sync conversations await bo.conversations.sync() if (boDm) await boDm.sync() - await alix.conversations.sync() - await alix2.conversations.sync() await alix2.preferences.syncConsent() await alix.conversations.syncAllConversations() await delayToPropogate(2000) @@ -667,8 +665,6 @@ test('can stream consent', async () => { }) await alixGroup.send('Hello') - await alix.conversations.sync() - await alix2.conversations.sync() await alix.conversations.syncAllConversations() await alix2.conversations.syncAllConversations() diff --git a/example/src/tests/groupPerformanceTests.ts b/example/src/tests/groupPerformanceTests.ts index a18d86df..abada6c0 100644 --- a/example/src/tests/groupPerformanceTests.ts +++ b/example/src/tests/groupPerformanceTests.ts @@ -1,7 +1,16 @@ /* eslint-disable @typescript-eslint/no-extra-non-null-assertion */ -import { Client, Dm, Group } from 'xmtp-react-native-sdk' - -import { Test, assert, createClients } from './test-utils' +import { Wallet } from 'ethers' +import RNFS from 'react-native-fs' +import { + Client, + GroupUpdatedCodec, + ReactionCodec, + RemoteAttachmentCodec, + ReplyCodec, + StaticAttachmentCodec, +} from 'xmtp-react-native-sdk' + +import { Test, assert } from './test-utils' export const groupPerformanceTests: Test[] = [] let counter = 1 @@ -12,389 +21,84 @@ function test(name: string, perform: () => Promise) { }) } -async function createGroups( - client: Client, - peers: Client[], - numGroups: number, - numMessages: number -): Promise { - const groups = [] - const addresses: string[] = peers.map((client) => client.address) - for (let i = 0; i < numGroups; i++) { - const group = await client.conversations.newGroup(addresses, { - name: `group ${i}`, - imageUrlSquare: `www.group${i}.com`, - description: `group ${i}`, - }) - groups.push(group) - for (let i = 0; i < numMessages; i++) { - await group.send({ text: `Alix message ${i}` }) - } - } - return groups -} - -async function createDms( - client: Client, - peers: Client[], - numMessages: number -): Promise { - const dms = [] - for (let i = 0; i < peers.length; i++) { - const dm = await peers[i].conversations.findOrCreateDm(client.address) - dms.push(dm) - for (let i = 0; i < numMessages; i++) { - await dm.send({ text: `Alix message ${i}` }) - } - } - return dms -} - -let alixClient: Client -let boClient: Client -let initialPeers: Client[] -let initialGroups: Group[] -// let initialDms: Dm[] - -async function beforeAll( - groupSize: number = 1, - messages: number = 1, - peersSize: number = 1, - includeDms: boolean = false -) { - ;[alixClient] = await createClients(1) - - initialPeers = await createClients(peersSize) - boClient = initialPeers[0] - - initialGroups = await createGroups( - alixClient, - initialPeers, - groupSize, - messages - ) - - if (includeDms) { - await createDms(alixClient, initialPeers, messages) +test('building and creating', async () => { + 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, + ]) + const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` + const directoryExists = await RNFS.exists(dbDirPath) + if (!directoryExists) { + await RNFS.mkdir(dbDirPath) } -} - -test('test compare V3 dms', async () => { - await beforeAll(0, 0, 50, true) - let start = Date.now() - await alixClient.conversations.sync() - let end = Date.now() - console.log(`Davon synced ${50} Dms in ${end - start}ms`) - - start = Date.now() - let dms = await alixClient.conversations.list() - end = Date.now() - console.log(`Davon loaded ${dms.length} Dms in ${end - start}ms`) - - await createDms(alixClient, await createClients(5), 1) - - start = Date.now() - await alixClient.conversations.sync() - end = Date.now() - console.log(`Davon synced ${dms.length} Dms in ${end - start}ms`) - - start = Date.now() - dms = await alixClient.conversations.list() - end = Date.now() - console.log(`Davon loaded ${dms.length} Dms in ${end - start}ms`) - - return true -}) - -test('testing large group listings with ordering', async () => { - await beforeAll(1000, 10, 10) - - let start = Date.now() - let groups = await alixClient.conversations.listGroups() - let end = Date.now() - console.log(`Alix loaded ${groups.length} groups in ${end - start}ms`) - - await groups[5].send({ text: `Alix message` }) - await groups[50].send({ text: `Alix message` }) - await groups[150].send({ text: `Alix message` }) - await groups[500].send({ text: `Alix message` }) - await groups[700].send({ text: `Alix message` }) - await groups[900].send({ text: `Alix message` }) - - let start2 = Date.now() - let groups2 = await alixClient.conversations.listGroups( - { - consentState: false, - description: false, - addedByInboxId: false, - isActive: false, - lastMessage: true, - }, - 'lastMessage' - ) - let end2 = Date.now() - console.log(`Alix loaded ${groups2.length} groups in ${end2 - start2}ms`) - assert( - end2 - start2 < end - start, - 'listing 1000 groups without certain fields should take less time' - ) - - start = Date.now() - await alixClient.conversations.sync() - end = Date.now() - console.log(`Alix synced ${groups.length} groups in ${end - start}ms`) - assert( - end - start < 100, - 'syncing 1000 cached groups should take less than a .1 second' - ) - - start = Date.now() - await boClient.conversations.sync() - end = Date.now() - console.log(`Bo synced ${groups.length} groups in ${end - start}ms`) - - start = Date.now() - await boClient.conversations.syncAllConversations() - end = Date.now() - console.log(`Bo synced all ${groups.length} groups in ${end - start}ms`) - assert( - end - start < 30000, - 'Syncing all 1000 groups should take less than a 30 second' - ) - - start = Date.now() - groups = await boClient.conversations.listGroups() - end = Date.now() - console.log(`Bo loaded ${groups.length} groups in ${end - start}ms`) + const alixWallet = Wallet.createRandom() + + const start1 = performance.now() + const alix = await Client.create(alixWallet, { + env: 'dev', + appVersion: 'Testing/0.0.0', + dbEncryptionKey: keyBytes, + dbDirectory: dbDirPath, + codecs: [ + new ReactionCodec(), + new ReplyCodec(), + new GroupUpdatedCodec(), + new StaticAttachmentCodec(), + new RemoteAttachmentCodec(), + ], + }) + const end1 = performance.now() + console.log(`Created a new client in ${end1 - start1}ms`) + + const start2 = performance.now() + await Client.build(alixWallet.address, { + env: 'dev', + appVersion: 'Testing/0.0.0', + dbEncryptionKey: keyBytes, + dbDirectory: dbDirPath, + codecs: [ + new ReactionCodec(), + new ReplyCodec(), + new GroupUpdatedCodec(), + new StaticAttachmentCodec(), + new RemoteAttachmentCodec(), + ], + }) + const end2 = performance.now() + console.log(`Built a client in ${end2 - start2}ms`) - start2 = Date.now() - groups2 = await boClient.conversations.listGroups( + const start3 = performance.now() + await Client.build( + alixWallet.address, { - consentState: false, - description: false, - addedByInboxId: false, - isActive: false, - lastMessage: true, + env: 'dev', + appVersion: 'Testing/0.0.0', + dbEncryptionKey: keyBytes, + dbDirectory: dbDirPath, + codecs: [ + new ReactionCodec(), + new ReplyCodec(), + new GroupUpdatedCodec(), + new StaticAttachmentCodec(), + new RemoteAttachmentCodec(), + ], }, - 'lastMessage' - ) - end2 = Date.now() - console.log(`Bo loaded ${groups2.length} groups in ${end2 - start2}ms`) - assert( - end2 - start2 < end - start, - 'listing 1000 groups without certain fields should take less time' - ) - - return true -}) - -test('testing large group listings', async () => { - await beforeAll(1000) - - let start = Date.now() - let groups = await alixClient.conversations.listGroups() - let end = Date.now() - console.log(`Alix loaded ${groups.length} groups in ${end - start}ms`) - assert( - end - start < 3000, - 'listing 1000 groups should take less than a 3 second' - ) - - start = Date.now() - await alixClient.conversations.sync() - end = Date.now() - console.log(`Alix synced ${groups.length} groups in ${end - start}ms`) - assert( - end - start < 100, - 'syncing 1000 cached groups should take less than a .1 second' - ) - - start = Date.now() - await boClient.conversations.sync() - end = Date.now() - console.log(`Bo synced ${groups.length} groups in ${end - start}ms`) - assert( - end - start < 6000, - 'syncing 1000 groups should take less than a 6 second' + alix.inboxId ) + const end3 = performance.now() + console.log(`Built a client with inboxId in ${end3 - start3}ms`) - start = Date.now() - groups = await boClient.conversations.listGroups() - end = Date.now() - console.log(`Bo loaded ${groups.length} groups in ${end - start}ms`) assert( - end - start < 3000, - 'loading 1000 groups should take less than a 3 second' + end2 - start2 < end1 - start1, + 'building a client should be faster than creating one' ) - - return true -}) - -test('testing large message listings', async () => { - await beforeAll(1, 2000) - - const alixGroup = initialGroups[0] - let start = Date.now() - let messages = await alixGroup.messages() - let end = Date.now() - console.log(`Alix loaded ${messages.length} messages in ${end - start}ms`) - assert( - end - start < 1000, - 'listing 2000 self messages should take less than a 1 second' - ) - - start = Date.now() - await alixGroup.sync() - end = Date.now() - console.log(`Alix synced ${messages.length} messages in ${end - start}ms`) - assert( - end - start < 100, - 'syncing 2000 self messages should take less than a .1 second' - ) - - await boClient.conversations.sync() - const boGroup = await boClient.conversations.findGroup(alixGroup.id) - start = Date.now() - await boGroup!.sync() - end = Date.now() - console.log(`Bo synced ${messages.length} messages in ${end - start}ms`) - assert( - end - start < 3000, - 'syncing 2000 messages should take less than a 3 second' - ) - - start = Date.now() - messages = await boGroup!.messages() - end = Date.now() - console.log(`Bo loaded ${messages.length} messages in ${end - start}ms`) assert( - end - start < 1000, - 'loading 2000 messages should take less than a 1 second' + end3 - start3 < end1 - start1, + 'building a client with an inboxId should be faster than creating one' ) - - return true -}) - -test('testing large member listings', async () => { - await beforeAll(1, 1, 50) - - const alixGroup = initialGroups[0] - let start = Date.now() - let members = await alixGroup.members - let end = Date.now() - console.log(`Alix loaded ${members.length} members in ${end - start}ms`) - assert( - end - start < 100, - 'listing 50 members should take less than a .1 second' - ) - - start = Date.now() - await alixGroup.sync() - end = Date.now() - console.log(`Alix synced ${members.length} members in ${end - start}ms`) - assert( - end - start < 100, - 'syncing 50 members should take less than a .1 second' - ) - - await boClient.conversations.sync() - const boGroup = await boClient.conversations.findGroup(alixGroup.id) - start = Date.now() - await boGroup!.sync() - end = Date.now() - console.log(`Bo synced ${members.length} members in ${end - start}ms`) - assert( - end - start < 100, - 'syncing 50 members should take less than a .1 second' - ) - - start = Date.now() - members = await boGroup!.members - end = Date.now() - console.log(`Bo loaded ${members.length} members in ${end - start}ms`) - assert( - end - start < 100, - 'loading 50 members should take less than a .1 second' - ) - - const [davonClient] = await createClients(1) - - start = Date.now() - await alixGroup.addMembers([davonClient.address]) - end = Date.now() - console.log(`Alix added 1 member in ${end - start}ms`) - assert(end - start < 100, 'adding 1 member should take less than a .1 second') - - start = Date.now() - members = await alixGroup.members - end = Date.now() - console.log(`Alix loaded ${members.length} members in ${end - start}ms`) - assert( - end - start < 100, - 'loading 50 member should take less than a .1 second' - ) - - start = Date.now() - await boGroup!.sync() - end = Date.now() - console.log(`Bo synced ${members.length} members in ${end - start}ms`) - assert( - end - start < 100, - 'syncing 50 member should take less than a .1 second' - ) - - start = Date.now() - members = await boGroup!.members - end = Date.now() - console.log(`Bo loaded ${members.length} members in ${end - start}ms`) - assert( - end - start < 100, - 'loading 50 member should take less than a .1 second' - ) - - return true -}) - -test('testing sending message in large group', async () => { - await beforeAll(1, 2000, 100) - - const alixGroup = initialGroups[0] - let start = Date.now() - await alixGroup.send({ text: `Alix message` }) - let end = Date.now() - console.log(`Alix sent a message in ${end - start}ms`) - assert( - end - start < 200, - 'sending a message should take less than a .2 second' - ) - - await boClient.conversations.sync() - const boGroup = await boClient.conversations.findGroup(alixGroup.id) - start = Date.now() - await boGroup!.prepareMessage({ text: `Bo message` }) - end = Date.now() - console.log(`Bo sent a message in ${end - start}ms`) - assert( - end - start < 100, - 'preparing a message should take less than a .1 second' - ) - - start = Date.now() - await boGroup!.sync() - end = Date.now() - console.log(`Bo synced messages in ${end - start}ms`) - assert( - end - start < 9000, - 'syncing 2000 messages should take less than a 9 second' - ) - - start = Date.now() - await boGroup!.send({ text: `Bo message 2` }) - end = Date.now() - console.log(`Bo sent a message in ${end - start}ms`) assert( - end - start < 100, - 'sending a message should take less than a .1 second' + end3 - start3 < end2 - start2, + 'building a client with an inboxId should be faster than building without' ) return true diff --git a/example/src/tests/groupTests.ts b/example/src/tests/groupTests.ts index c97455b6..fa0b2dcb 100644 --- a/example/src/tests/groupTests.ts +++ b/example/src/tests/groupTests.ts @@ -866,12 +866,13 @@ test('canMessage', async () => { const canMessageV3 = await caro.canMessage([ caro.address, alix.address, - '0x0000000000000000000000000000000000000000', + '0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67', ]) assert( - canMessageV3['0x0000000000000000000000000000000000000000'] === false, - `should not be able to message 0x0000000000000000000000000000000000000000` + canMessageV3['0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67'.toLowerCase()] === + false, + `should not be able to message 0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67` ) assert( diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 1807d3a8..5a51e554 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -4,12 +4,15 @@ import OSLog import XMTP extension Conversation { - static func cacheKeyForTopic(installationId: String, topic: String) -> String { + static func cacheKeyForTopic(installationId: String, topic: String) + -> String + { return "\(installationId):\(topic)" } func cacheKey(_ installationId: String) -> String { - return Conversation.cacheKeyForTopic(installationId: installationId, topic: topic) + return Conversation.cacheKeyForTopic( + installationId: installationId, topic: topic) } } @@ -70,13 +73,13 @@ public class XMTPModule: Module { } } } - + enum Error: Swift.Error, LocalizedError { case noClient case conversationNotFound(String) case noMessage case invalidPermissionOption - + var errorDescription: String? { switch self { case .noClient: @@ -105,7 +108,8 @@ public class XMTPModule: Module { ) AsyncFunction("address") { (installationId: String) -> String in - if let client = await clientsManager.getClient(key: installationId) { + if let client = await clientsManager.getClient(key: installationId) + { return client.address } else { return "No Client." @@ -113,7 +117,8 @@ public class XMTPModule: Module { } AsyncFunction("inboxId") { (installationId: String) -> String in - if let client = await clientsManager.getClient(key: installationId) { + if let client = await clientsManager.getClient(key: installationId) + { return client.inboxID } else { return "No Client." @@ -122,7 +127,8 @@ public class XMTPModule: Module { AsyncFunction("findInboxIdFromAddress") { (installationId: String, address: String) -> String? in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -130,15 +136,18 @@ public class XMTPModule: Module { } AsyncFunction("deleteLocalDatabase") { (installationId: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } try client.deleteLocalDatabase() } - AsyncFunction("dropLocalDatabaseConnection") { (installationId: String) in - guard let client = await clientsManager.getClient(key: installationId) + AsyncFunction("dropLocalDatabaseConnection") { + (installationId: String) in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -146,7 +155,8 @@ public class XMTPModule: Module { } AsyncFunction("reconnectLocalDatabase") { (installationId: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -154,7 +164,8 @@ public class XMTPModule: Module { } AsyncFunction("requestMessageHistorySync") { (installationId: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -163,7 +174,8 @@ public class XMTPModule: Module { AsyncFunction("getInboxState") { (installationId: String, refreshFromNetwork: Bool) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -173,9 +185,13 @@ public class XMTPModule: Module { } AsyncFunction("getInboxStates") { - (installationId: String, refreshFromNetwork: Bool, inboxIds: [String]) + ( + installationId: String, refreshFromNetwork: Bool, + inboxIds: [String] + ) -> [String] in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -269,7 +285,10 @@ public class XMTPModule: Module { } AsyncFunction("build") { - (address: String, dbEncryptionKey: [UInt8], authParams: String) + ( + address: String, inboxId: String?, dbEncryptionKey: [UInt8], + authParams: String + ) -> [String: String] in let authOptions = AuthParamsWrapper.authParamsFromJson(authParams) let encryptionKeyData = Data(dbEncryptionKey) @@ -280,7 +299,7 @@ public class XMTPModule: Module { preAuthenticateToInboxCallback: preAuthenticateToInboxCallback ) let client = try await XMTP.Client.build( - address: address, options: options) + address: address, options: options, inboxId: inboxId) await clientsManager.updateClient( key: client.installationID, client: client) return try ClientWrapper.encodeToObj(client) @@ -288,7 +307,8 @@ public class XMTPModule: Module { AsyncFunction("revokeAllOtherInstallations") { (installationId: String, walletParams: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -306,8 +326,10 @@ public class XMTPModule: Module { } AsyncFunction("addAccount") { - (installationId: String, newAddress: String, walletParams: String) in - guard let client = await clientsManager.getClient(key: installationId) + (installationId: String, newAddress: String, walletParams: String) + in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -325,8 +347,12 @@ public class XMTPModule: Module { } AsyncFunction("removeAccount") { - (installationId: String, addressToRemove: String, walletParams: String) in - guard let client = await clientsManager.getClient(key: installationId) + ( + installationId: String, addressToRemove: String, + walletParams: String + ) in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -351,7 +377,8 @@ public class XMTPModule: Module { AsyncFunction("signWithInstallationKey") { (installationId: String, message: String) -> [UInt8] in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -360,8 +387,10 @@ public class XMTPModule: Module { } AsyncFunction("verifySignature") { - (installationId: String, message: String, signature: [UInt8]) -> Bool in - guard let client = await clientsManager.getClient(key: installationId) + (installationId: String, message: String, signature: [UInt8]) + -> Bool in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -370,8 +399,10 @@ public class XMTPModule: Module { } AsyncFunction("canMessage") { - (installationId: String, peerAddresses: [String]) -> [String: Bool] in - guard let client = await clientsManager.getClient(key: installationId) + (installationId: String, peerAddresses: [String]) -> [String: Bool] + in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -379,6 +410,14 @@ public class XMTPModule: Module { return try await client.canMessage(addresses: peerAddresses) } + AsyncFunction("staticCanMessage") { + (environment: String, peerAddresses: [String]) -> [String: Bool] in + return try await XMTP.Client.canMessage( + accountAddresses: peerAddresses, + api: createApiClient(env: environment) + ) + } + AsyncFunction("getOrCreateInboxId") { (address: String, environment: String) -> String in do { @@ -392,7 +431,8 @@ public class XMTPModule: Module { AsyncFunction("encryptAttachment") { (installationId: String, fileJson: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -422,7 +462,8 @@ public class XMTPModule: Module { AsyncFunction("decryptAttachment") { (installationId: String, encryptedFileJson: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -453,10 +494,12 @@ public class XMTPModule: Module { AsyncFunction("listGroups") { ( - installationId: String, groupParams: String?, sortOrder: String?, + installationId: String, groupParams: String?, + sortOrder: String?, limit: Int?, consentState: String? ) -> [String] in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -484,10 +527,12 @@ public class XMTPModule: Module { AsyncFunction("listDms") { ( - installationId: String, groupParams: String?, sortOrder: String?, + installationId: String, groupParams: String?, + sortOrder: String?, limit: Int?, consentState: String? ) -> [String] in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -518,7 +563,8 @@ public class XMTPModule: Module { installationId: String, conversationParams: String?, sortOrder: String?, limit: Int?, consentState: String? ) -> [String] in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -551,7 +597,8 @@ public class XMTPModule: Module { installationId: String, conversationId: String, limit: Int?, beforeNs: Double?, afterNs: Double?, direction: String? ) -> [String] in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -585,7 +632,8 @@ public class XMTPModule: Module { AsyncFunction("findMessage") { (installationId: String, messageId: String) -> String? in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -599,7 +647,8 @@ public class XMTPModule: Module { AsyncFunction("findGroup") { (installationId: String, groupId: String) -> String? in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -612,7 +661,8 @@ public class XMTPModule: Module { AsyncFunction("findConversation") { (installationId: String, conversationId: String) -> String? in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -629,7 +679,8 @@ public class XMTPModule: Module { AsyncFunction("findConversationByTopic") { (installationId: String, topic: String) -> String? in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -645,7 +696,8 @@ public class XMTPModule: Module { AsyncFunction("findDmByInboxId") { (installationId: String, peerInboxId: String) -> String? in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -658,7 +710,8 @@ public class XMTPModule: Module { AsyncFunction("findDmByAddress") { (installationId: String, peerAddress: String) -> String? in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -670,8 +723,10 @@ public class XMTPModule: Module { } AsyncFunction("sendMessage") { - (installationId: String, id: String, contentJson: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + (installationId: String, id: String, contentJson: String) -> String + in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -692,7 +747,8 @@ public class XMTPModule: Module { AsyncFunction("publishPreparedMessages") { (installationId: String, id: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -708,8 +764,10 @@ public class XMTPModule: Module { } AsyncFunction("prepareMessage") { - (installationId: String, id: String, contentJson: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + (installationId: String, id: String, contentJson: String) -> String + in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -730,7 +788,8 @@ public class XMTPModule: Module { AsyncFunction("findOrCreateDm") { (installationId: String, peerAddress: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -747,10 +806,12 @@ public class XMTPModule: Module { AsyncFunction("createGroup") { ( - installationId: String, peerAddresses: [String], permission: String, + installationId: String, peerAddresses: [String], + permission: String, groupOptionsJson: String ) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -786,7 +847,8 @@ public class XMTPModule: Module { installationId: String, peerAddresses: [String], permissionPolicySetJson: String, groupOptionsJson: String ) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -815,7 +877,8 @@ public class XMTPModule: Module { AsyncFunction("listMemberInboxIds") { (installationId: String, groupId: String) -> [String] in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -828,7 +891,8 @@ public class XMTPModule: Module { AsyncFunction("dmPeerInboxId") { (installationId: String, dmId: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -850,12 +914,14 @@ public class XMTPModule: Module { AsyncFunction("listConversationMembers") { (installationId: String, conversationId: String) -> [String] in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -872,23 +938,28 @@ public class XMTPModule: Module { } AsyncFunction("syncConversations") { (installationId: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } try await client.conversations.sync() } - AsyncFunction("syncAllConversations") { (installationId: String) -> UInt32 in - guard let client = await clientsManager.getClient(key: installationId) + AsyncFunction("syncAllConversations") { + (installationId: String) -> UInt32 in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } return try await client.conversations.syncAllConversations() } - AsyncFunction("syncConversation") { (installationId: String, id: String) in - guard let client = await clientsManager.getClient(key: installationId) + AsyncFunction("syncConversation") { + (installationId: String, id: String) in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -904,7 +975,8 @@ public class XMTPModule: Module { AsyncFunction("addGroupMembers") { (installationId: String, id: String, peerAddresses: [String]) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -917,7 +989,8 @@ public class XMTPModule: Module { AsyncFunction("removeGroupMembers") { (installationId: String, id: String, peerAddresses: [String]) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -930,7 +1003,8 @@ public class XMTPModule: Module { AsyncFunction("addGroupMembersByInboxId") { (installationId: String, id: String, inboxIds: [String]) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -943,7 +1017,8 @@ public class XMTPModule: Module { AsyncFunction("removeGroupMembersByInboxId") { (installationId: String, id: String, inboxIds: [String]) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -955,8 +1030,10 @@ public class XMTPModule: Module { try await group.removeMembersByInboxId(inboxIds: inboxIds) } - AsyncFunction("groupName") { (installationId: String, id: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + AsyncFunction("groupName") { + (installationId: String, id: String) -> String in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -970,7 +1047,8 @@ public class XMTPModule: Module { AsyncFunction("updateGroupName") { (installationId: String, id: String, groupName: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -984,7 +1062,8 @@ public class XMTPModule: Module { AsyncFunction("groupImageUrlSquare") { (installationId: String, id: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -998,7 +1077,8 @@ public class XMTPModule: Module { AsyncFunction("updateGroupImageUrlSquare") { (installationId: String, id: String, groupImageUrl: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1013,7 +1093,8 @@ public class XMTPModule: Module { AsyncFunction("groupDescription") { (installationId: String, id: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1027,7 +1108,8 @@ public class XMTPModule: Module { AsyncFunction("updateGroupDescription") { (installationId: String, id: String, description: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1042,7 +1124,8 @@ public class XMTPModule: Module { AsyncFunction("groupPinnedFrameUrl") { (installationId: String, id: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1056,7 +1139,8 @@ public class XMTPModule: Module { AsyncFunction("updateGroupPinnedFrameUrl") { (installationId: String, id: String, pinnedFrameUrl: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1071,7 +1155,8 @@ public class XMTPModule: Module { AsyncFunction("isGroupActive") { (installationId: String, id: String) -> Bool in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1085,7 +1170,8 @@ public class XMTPModule: Module { AsyncFunction("addedByInboxId") { (installationId: String, id: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1099,7 +1185,8 @@ public class XMTPModule: Module { AsyncFunction("creatorInboxId") { (installationId: String, id: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1111,9 +1198,11 @@ public class XMTPModule: Module { } AsyncFunction("isAdmin") { - (clientInstallationId: String, id: String, inboxId: String) -> Bool in + (clientInstallationId: String, id: String, inboxId: String) -> Bool + in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1125,9 +1214,11 @@ public class XMTPModule: Module { } AsyncFunction("isSuperAdmin") { - (clientInstallationId: String, id: String, inboxId: String) -> Bool in + (clientInstallationId: String, id: String, inboxId: String) -> Bool + in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1140,7 +1231,8 @@ public class XMTPModule: Module { AsyncFunction("listAdmins") { (installationId: String, id: String) -> [String] in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1153,7 +1245,8 @@ public class XMTPModule: Module { AsyncFunction("listSuperAdmins") { (installationId: String, id: String) -> [String] in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1167,7 +1260,8 @@ public class XMTPModule: Module { AsyncFunction("addAdmin") { (clientInstallationId: String, id: String, inboxId: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1181,7 +1275,8 @@ public class XMTPModule: Module { AsyncFunction("addSuperAdmin") { (clientInstallationId: String, id: String, inboxId: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1195,7 +1290,8 @@ public class XMTPModule: Module { AsyncFunction("removeAdmin") { (clientInstallationId: String, id: String, inboxId: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1209,7 +1305,8 @@ public class XMTPModule: Module { AsyncFunction("removeSuperAdmin") { (clientInstallationId: String, id: String, inboxId: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1223,7 +1320,8 @@ public class XMTPModule: Module { AsyncFunction("updateAddMemberPermission") { (clientInstallationId: String, id: String, newPermission: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1239,7 +1337,8 @@ public class XMTPModule: Module { AsyncFunction("updateRemoveMemberPermission") { (clientInstallationId: String, id: String, newPermission: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1255,7 +1354,8 @@ public class XMTPModule: Module { AsyncFunction("updateAddAdminPermission") { (clientInstallationId: String, id: String, newPermission: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1271,7 +1371,8 @@ public class XMTPModule: Module { AsyncFunction("updateRemoveAdminPermission") { (clientInstallationId: String, id: String, newPermission: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1287,7 +1388,8 @@ public class XMTPModule: Module { AsyncFunction("updateGroupNamePermission") { (clientInstallationId: String, id: String, newPermission: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1303,7 +1405,8 @@ public class XMTPModule: Module { AsyncFunction("updateGroupImageUrlSquarePermission") { (clientInstallationId: String, id: String, newPermission: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1319,7 +1422,8 @@ public class XMTPModule: Module { AsyncFunction("updateGroupDescriptionPermission") { (clientInstallationId: String, id: String, newPermission: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1335,7 +1439,8 @@ public class XMTPModule: Module { AsyncFunction("updateGroupPinnedFrameUrlPermission") { (clientInstallationId: String, id: String, newPermission: String) in guard - let client = await clientsManager.getClient(key: clientInstallationId) + let client = await clientsManager.getClient( + key: clientInstallationId) else { throw Error.noClient } @@ -1350,7 +1455,8 @@ public class XMTPModule: Module { AsyncFunction("permissionPolicySet") { (installationId: String, id: String) async throws -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1366,8 +1472,10 @@ public class XMTPModule: Module { } AsyncFunction("processMessage") { - (installationId: String, id: String, encryptedMessage: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + (installationId: String, id: String, encryptedMessage: String) + -> String in + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1394,7 +1502,8 @@ public class XMTPModule: Module { AsyncFunction("processWelcomeMessage") { (installationId: String, encryptedMessage: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1416,7 +1525,8 @@ public class XMTPModule: Module { } AsyncFunction("syncConsent") { (installationId: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1429,7 +1539,8 @@ public class XMTPModule: Module { installationId: String, value: String, entryType: String, consentType: String ) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1450,7 +1561,8 @@ public class XMTPModule: Module { AsyncFunction("consentAddressState") { (installationId: String, address: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1461,7 +1573,8 @@ public class XMTPModule: Module { AsyncFunction("consentInboxIdState") { (installationId: String, peerInboxId: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1472,7 +1585,8 @@ public class XMTPModule: Module { AsyncFunction("consentConversationIdState") { (installationId: String, conversationId: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1484,7 +1598,8 @@ public class XMTPModule: Module { AsyncFunction("conversationConsentState") { (installationId: String, conversationId: String) -> String in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1502,7 +1617,8 @@ public class XMTPModule: Module { AsyncFunction("updateConversationConsent") { (installationId: String, conversationId: String, state: String) in - guard let client = await clientsManager.getClient(key: installationId) + guard + let client = await clientsManager.getClient(key: installationId) else { throw Error.noClient } @@ -1530,38 +1646,46 @@ public class XMTPModule: Module { (installationId: String, type: String) in try await subscribeToConversations( - installationId: installationId, type: getConversationType(type: type)) + installationId: installationId, + type: getConversationType(type: type)) } AsyncFunction("subscribeToAllMessages") { (installationId: String, type: String) in try await subscribeToAllMessages( - installationId: installationId, type: getConversationType(type: type)) + installationId: installationId, + type: getConversationType(type: type)) } AsyncFunction("subscribeToMessages") { (installationId: String, id: String) in - try await subscribeToMessages(installationId: installationId, id: id) + try await subscribeToMessages( + installationId: installationId, id: id) } AsyncFunction("unsubscribeFromConsent") { (installationId: String) in - await subscriptionsManager.get(getConsentKey(installationId: installationId))? + await subscriptionsManager.get( + getConsentKey(installationId: installationId))? .cancel() } - AsyncFunction("unsubscribeFromConversations") { (installationId: String) in + AsyncFunction("unsubscribeFromConversations") { + (installationId: String) in await subscriptionsManager.get( getConversationsKey(installationId: installationId))?.cancel() } - AsyncFunction("unsubscribeFromAllMessages") { (installationId: String) in - await subscriptionsManager.get(getMessagesKey(installationId: installationId))? + AsyncFunction("unsubscribeFromAllMessages") { + (installationId: String) in + await subscriptionsManager.get( + getMessagesKey(installationId: installationId))? .cancel() } AsyncFunction("unsubscribeFromMessages") { (installationId: String, id: String) in - try await unsubscribeFromMessages(installationId: installationId, id: id) + try await unsubscribeFromMessages( + installationId: installationId, id: id) } AsyncFunction("registerPushToken") { @@ -1749,15 +1873,17 @@ public class XMTPModule: Module { dbDirectory: authOptions.dbDirectory, historySyncUrl: authOptions.historySyncUrl) } - + func subscribeToConsent(installationId: String) async throws { - guard let client = await clientsManager.getClient(key: installationId) else { + guard let client = await clientsManager.getClient(key: installationId) + else { return } - await subscriptionsManager.get(getConsentKey(installationId: installationId))? + await subscriptionsManager.get( + getConsentKey(installationId: installationId))? .cancel() await subscriptionsManager.set( getConsentKey(installationId: installationId), @@ -1782,14 +1908,18 @@ public class XMTPModule: Module { }) } - func subscribeToConversations(installationId: String, type: ConversationType) + func subscribeToConversations( + installationId: String, type: ConversationType + ) async throws { - guard let client = await clientsManager.getClient(key: installationId) else { + guard let client = await clientsManager.getClient(key: installationId) + else { return } - await subscriptionsManager.get(getConversationsKey(installationId: installationId))? + await subscriptionsManager.get( + getConversationsKey(installationId: installationId))? .cancel() await subscriptionsManager.set( getConversationsKey(installationId: installationId), @@ -1809,7 +1939,8 @@ public class XMTPModule: Module { } catch { print("Error in all conversations subscription: \(error)") await subscriptionsManager.get( - getConversationsKey(installationId: installationId))?.cancel() + getConversationsKey(installationId: installationId))? + .cancel() } }) } @@ -1817,11 +1948,13 @@ public class XMTPModule: Module { func subscribeToAllMessages(installationId: String, type: ConversationType) async throws { - guard let client = await clientsManager.getClient(key: installationId) else { + guard let client = await clientsManager.getClient(key: installationId) + else { return } - await subscriptionsManager.get(getMessagesKey(installationId: installationId))? + await subscriptionsManager.get( + getMessagesKey(installationId: installationId))? .cancel() await subscriptionsManager.set( getMessagesKey(installationId: installationId), @@ -1841,13 +1974,15 @@ public class XMTPModule: Module { } catch { print("Error in all messages subscription: \(error)") await subscriptionsManager.get( - getMessagesKey(installationId: installationId))?.cancel() + getMessagesKey(installationId: installationId))? + .cancel() } }) } func subscribeToMessages(installationId: String, id: String) async throws { - guard let client = await clientsManager.getClient(key: installationId) else { + guard let client = await clientsManager.getClient(key: installationId) + else { throw Error.noClient } @@ -1887,8 +2022,11 @@ public class XMTPModule: Module { }) } - func unsubscribeFromMessages(installationId: String, id: String) async throws { - guard let client = await clientsManager.getClient(key: installationId) else { + func unsubscribeFromMessages(installationId: String, id: String) + async throws + { + guard let client = await clientsManager.getClient(key: installationId) + else { throw Error.noClient } @@ -1900,7 +2038,7 @@ public class XMTPModule: Module { await subscriptionsManager.get(converation.cacheKey(installationId))? .cancel() } - + func getConsentKey(installationId: String) -> String { return "consent:\(installationId)" } diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 26f28970..4756572c 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,6 +26,7 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency "MessagePacker" - s.dependency "XMTP", "= 3.0.10" + s.dependency "XMTP", "= 3.0.14" s.dependency 'CSecp256k1', '~> 0.2' + s.dependency "SQLCipher", "= 4.5.7" end diff --git a/src/index.ts b/src/index.ts index 54bbbb9e..00f467e1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -174,7 +174,8 @@ export async function build( dbEncryptionKey: Uint8Array, appVersion?: string | undefined, dbDirectory?: string | undefined, - historySyncUrl?: string | undefined + historySyncUrl?: string | undefined, + inboxId?: InboxId | undefined ): Promise { const authParams: AuthParams = { environment, @@ -184,6 +185,7 @@ export async function build( } return await XMTPModule.build( address, + inboxId, Array.from(dbEncryptionKey), JSON.stringify(authParams) ) @@ -278,6 +280,13 @@ export async function canMessage( return await XMTPModule.canMessage(installationId, peerAddresses) } +export async function staticCanMessage( + environment: XMTPEnvironment, + peerAddresses: Address[] +): Promise<{ [key: Address]: boolean }> { + return await XMTPModule.staticCanMessage(environment, peerAddresses) +} + export async function getOrCreateInboxId( address: Address, environment: XMTPEnvironment diff --git a/src/lib/Client.ts b/src/lib/Client.ts index 36b065e9..eaf6492d 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -204,7 +204,8 @@ export class Client< ContentCodecs extends DefaultContentTypes = DefaultContentTypes, >( address: Address, - options: ClientOptions & { codecs?: ContentCodecs } + options: ClientOptions & { codecs?: ContentCodecs }, + inboxId?: InboxId | undefined ): Promise> { if (options.dbEncryptionKey.length !== 32) { throw new Error('Must pass an encryption key that is exactly 32 bytes.') @@ -215,7 +216,8 @@ export class Client< options.dbEncryptionKey, options.appVersion, options.dbDirectory, - options.historySyncUrl + options.historySyncUrl, + inboxId ) return new Client( @@ -280,7 +282,7 @@ export class Client< * Static method to determine the inboxId for the address. * * @param {Address} peerAddress - The address of the peer to check for messaging eligibility. - * @param {Partial} opts - Optional configuration options for the Client. + * @param {XMTPEnvironment} env - Environment to get the inboxId from * @returns {Promise} */ static async getOrCreateInboxId( @@ -290,6 +292,22 @@ export class Client< return await XMTPModule.getOrCreateInboxId(address, env) } + /** + * Determines whether the current user can send messages to the specified peers. + * + * This method checks if the specified peers are using clients that are on the network. + * + * @param {Address[]} addresses - The addresses of the peers to check for messaging eligibility. + * @param {XMTPEnvironment} env - Environment to see if the address is on the network for + * @returns {Promise<{ [key: Address]: boolean }>} A Promise resolving to a hash of addresses and booleans if they can message on the network. + */ + static async canMessage( + env: XMTPEnvironment, + addresses: Address[] + ): Promise<{ [key: Address]: boolean }> { + return await XMTPModule.staticCanMessage(env, addresses) + } + constructor( address: Address, inboxId: InboxId, @@ -550,12 +568,12 @@ export class Client< } /** - * Determines whether the current user can send messages to the specified peers over groups. + * Determines whether the current user can send messages to the specified peers. * - * This method checks if the specified peers are using clients that support group messaging. + * This method checks if the specified peers are using clients that are on the network. * * @param {Address[]} addresses - The addresses of the peers to check for messaging eligibility. - * @returns {Promise<{ [key: Address]: boolean }>} A Promise resolving to a hash of addresses and booleans if they can message on the V3 network. + * @returns {Promise<{ [key: Address]: boolean }>} A Promise resolving to a hash of addresses and booleans if they can message on the network. */ async canMessage(addresses: Address[]): Promise<{ [key: Address]: boolean }> { return await XMTPModule.canMessage(this.installationId, addresses)