From f1ba267c653bfefa812a26e5657318f090b2650e Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 27 Nov 2024 08:41:39 -0800 Subject: [PATCH 01/10] update preformance tests --- android/build.gradle | 2 +- example/ios/Podfile.lock | 23 +- .../project.pbxproj | 2 + example/src/tests/groupPerformanceTests.ts | 709 ++++++++++-------- ios/XMTPReactNative.podspec | 3 +- 5 files changed, 406 insertions(+), 333 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 812c68417..6fc236be2 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.11" 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/example/ios/Podfile.lock b/example/ios/Podfile.lock index cf4baccd2..f9441f4c3 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.8) - 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.12): - Connect-Swift (= 1.0.0) - CryptoSwift (= 1.8.3) - CSecp256k1 (~> 0.2) - - LibXMTP (= 3.0.7) + - LibXMTP (= 3.0.8) + - SQLCipher (= 4.5.7) - XMTPReactNative (0.1.0): - CSecp256k1 (~> 0.2) - ExpoModulesCore - MessagePacker - - XMTP (= 3.0.10) + - SQLCipher (= 4.5.7) + - XMTP (= 3.0.12) - 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: bcddd95871e7e3636f395691d73ec8ecbc3c78c9 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: f3a4dec90eadfcf98d4d619238f50d051ac254f9 + XMTPReactNative: 04766f2ca3e776ed5214fc85546c81bf438b5e14 Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 PODFILE CHECKSUM: 0e6fe50018f34e575d38dc6a1fdf1f99c9596cdd diff --git a/example/ios/xmtpreactnativesdkexample.xcodeproj/project.pbxproj b/example/ios/xmtpreactnativesdkexample.xcodeproj/project.pbxproj index c977d86d6..2400bd110 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/groupPerformanceTests.ts b/example/src/tests/groupPerformanceTests.ts index a18d86df8..8be7fee18 100644 --- a/example/src/tests/groupPerformanceTests.ts +++ b/example/src/tests/groupPerformanceTests.ts @@ -1,5 +1,7 @@ /* eslint-disable @typescript-eslint/no-extra-non-null-assertion */ -import { Client, Dm, Group } from 'xmtp-react-native-sdk' +import Config from 'react-native-config' +import { PrivateKeyAccount, privateKeyToAccount } from 'viem/accounts' +import { Client, Dm, Group, Signer } from 'xmtp-react-native-sdk' import { Test, assert, createClients } from './test-utils' @@ -50,352 +52,411 @@ async function createDms( 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) +export function convertPrivateKeyAccountToSigner( + privateKeyAccount: PrivateKeyAccount +): Signer { + if (!privateKeyAccount.address) { + throw new Error('WalletClient is not configured') } -} - -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`) - - start2 = Date.now() - groups2 = await boClient.conversations.listGroups( - { - consentState: false, - description: false, - addedByInboxId: false, - isActive: false, - lastMessage: true, - }, - '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' - ) - 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' - ) + return { + getAddress: async () => privateKeyAccount.address, + signMessage: async (message: string | Uint8Array) => + privateKeyAccount.signMessage({ + message: typeof message === 'string' ? message : { raw: message }, + }), + getChainId: () => undefined, + getBlockNumber: () => undefined, + walletType: () => undefined, + } +} - return true +if (!Config.TEST_PRIVATE_KEY) { + throw new Error('Add private key to .env file') +} +const privateKeyHex: `0x${string}` = `0x${Config.TEST_PRIVATE_KEY}` + +const signer = convertPrivateKeyAccountToSigner( + privateKeyToAccount(privateKeyHex) +) +const alixClient = await Client.create(signer, { + env: 'local', + dbEncryptionKey: 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, + ]), }) -test('testing large message listings', async () => { - await beforeAll(1, 2000) +const initialPeers = await createClients(30) +const boClient = initialPeers[0] +const initialGroups = await createGroups(alixClient, initialPeers, 200, 5) +const initialDms: Dm[] = await createDms(alixClient, initialPeers, 25) - 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' - ) +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 alixWallet = Wallet.createRandom() - 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' - ) - - 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 + const alix = await Client.create(alixWallet, { + env: 'local', + appVersion: 'Testing/0.0.0', + dbEncryptionKey: keyBytes, + }) 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' - ) + console.log(`Created a new client in ${end - start}ms`) 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() + await Client.build(alixWallet.address, { + env: 'local', + appVersion: 'Testing/0.0.0', + dbEncryptionKey: keyBytes, + }) 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' - ) + console.log(`Built a client in ${end - start}ms`) start = Date.now() - members = await boGroup!.members + await alix.deleteLocalDatabase() 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) + console.log(`Deleted a local database in ${end - start}ms`) start = Date.now() - await alixGroup.addMembers([davonClient.address]) + await Client.dropClient(alix.installationId) 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') + console.log(`Droped a client in ${end - start}ms`) - 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 + await Client.create(alixWallet, { + env: 'local', + appVersion: 'Testing/0.0.0', + dbEncryptionKey: keyBytes, + }) 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' - ) + console.log(`Created the same client in ${end - start}ms`) 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' - ) - - return true -}) +// 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`) + +// start2 = Date.now() +// groups2 = await boClient.conversations.listGroups( +// { +// consentState: false, +// description: false, +// addedByInboxId: false, +// isActive: false, +// lastMessage: true, +// }, +// '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' +// ) + +// 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' +// ) + +// 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' +// ) + +// 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' +// ) + +// return true +// }) diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 26f28970d..3e4b04f4a 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.12" s.dependency 'CSecp256k1', '~> 0.2' + s.dependency "SQLCipher", "= 4.5.7" end From 48e197e64bccf06bcb5ef525c7e16ab0ff523afc Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 27 Nov 2024 10:24:07 -0800 Subject: [PATCH 02/10] update performance tests --- example/src/tests/conversationTests.ts | 4 - example/src/tests/groupPerformanceTests.ts | 105 +++++++++++++++------ 2 files changed, 74 insertions(+), 35 deletions(-) diff --git a/example/src/tests/conversationTests.ts b/example/src/tests/conversationTests.ts index a3e58ded4..3bba5c17f 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 8be7fee18..1be81446e 100644 --- a/example/src/tests/groupPerformanceTests.ts +++ b/example/src/tests/groupPerformanceTests.ts @@ -1,9 +1,11 @@ /* eslint-disable @typescript-eslint/no-extra-non-null-assertion */ import Config from 'react-native-config' +import RNFS from 'react-native-fs' import { PrivateKeyAccount, privateKeyToAccount } from 'viem/accounts' -import { Client, Dm, Group, Signer } from 'xmtp-react-native-sdk' +import { Client, Dm, Group, GroupUpdatedCodec, ReactionCodec, RemoteAttachmentCodec, ReplyCodec, Signer, StaticAttachmentCodec } from 'xmtp-react-native-sdk' import { Test, assert, createClients } from './test-utils' +import { Wallet } from 'ethers' export const groupPerformanceTests: Test[] = [] let counter = 1 @@ -71,70 +73,111 @@ export function convertPrivateKeyAccountToSigner( } } -if (!Config.TEST_PRIVATE_KEY) { - throw new Error('Add private key to .env file') -} -const privateKeyHex: `0x${string}` = `0x${Config.TEST_PRIVATE_KEY}` - -const signer = convertPrivateKeyAccountToSigner( - privateKeyToAccount(privateKeyHex) -) -const alixClient = await Client.create(signer, { - env: 'local', - dbEncryptionKey: 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, - ]), -}) +// if (!Config.TEST_PRIVATE_KEY) { +// throw new Error('Add private key to .env file') +// } +// const privateKeyHex: `0x${string}` = `0x${Config.TEST_PRIVATE_KEY}` + +// const signer = convertPrivateKeyAccountToSigner( +// privateKeyToAccount(privateKeyHex) +// ) +// const alixClient = await Client.create(signer, { +// env: 'local', +// dbEncryptionKey: 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 initialPeers = await createClients(30) -const boClient = initialPeers[0] -const initialGroups = await createGroups(alixClient, initialPeers, 200, 5) -const initialDms: Dm[] = await createDms(alixClient, initialPeers, 25) +// const initialPeers = await createClients(30) +// const boClient = initialPeers[0] +// const initialGroups = await createGroups(alixClient, initialPeers, 200, 5) +// const initialDms: Dm[] = await createDms(alixClient, initialPeers, 25) 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) + } const alixWallet = Wallet.createRandom() - let start = Date.now() + let start = performance.now() const alix = await Client.create(alixWallet, { env: 'local', appVersion: 'Testing/0.0.0', dbEncryptionKey: keyBytes, + dbDirectory: dbDirPath, + codecs: [ + new ReactionCodec(), + new ReplyCodec(), + new GroupUpdatedCodec(), + new StaticAttachmentCodec(), + new RemoteAttachmentCodec(), + ], }) - let end = Date.now() + await alix.register(new GroupUpdatedCodec()) + let end = performance.now() console.log(`Created a new client in ${end - start}ms`) - start = Date.now() - await Client.build(alixWallet.address, { + start = performance.now() + await alix.register(new GroupUpdatedCodec()) + end = performance.now() + console.log(`Alix registered group updated codec in ${end - start}ms`) + + start = performance.now() + const alixBuild = await Client.build(alixWallet.address, { env: 'local', appVersion: 'Testing/0.0.0', dbEncryptionKey: keyBytes, + dbDirectory: dbDirPath, + codecs: [ + new ReactionCodec(), + new ReplyCodec(), + new GroupUpdatedCodec(), + new StaticAttachmentCodec(), + new RemoteAttachmentCodec(), + ], }) - end = Date.now() + await alixBuild.register(new GroupUpdatedCodec()) + end = performance.now() console.log(`Built a client in ${end - start}ms`) - start = Date.now() + start = performance.now() + await alixBuild.register(new GroupUpdatedCodec()) + end = performance.now() + console.log(`Alix build registered group updated codec in ${end - start}ms`) + + start = performance.now() await alix.deleteLocalDatabase() - end = Date.now() + end = performance.now() console.log(`Deleted a local database in ${end - start}ms`) - start = Date.now() + start = performance.now() await Client.dropClient(alix.installationId) - end = Date.now() + end = performance.now() console.log(`Droped a client in ${end - start}ms`) - start = Date.now() + start = performance.now() await Client.create(alixWallet, { env: 'local', appVersion: 'Testing/0.0.0', dbEncryptionKey: keyBytes, + dbDirectory: dbDirPath, + codecs: [ + new ReactionCodec(), + new ReplyCodec(), + new GroupUpdatedCodec(), + new StaticAttachmentCodec(), + new RemoteAttachmentCodec(), + ], }) - end = Date.now() + end = performance.now() console.log(`Created the same client in ${end - start}ms`) return true From 759793d6f23d1f99719f2a014640c5f217456ddd Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 3 Dec 2024 19:25:47 -0800 Subject: [PATCH 03/10] add ability to pass inbox id to build to speed up building a client --- android/build.gradle | 2 +- .../modules/xmtpreactnativesdk/XMTPModule.kt | 4 +- example/src/tests/groupPerformanceTests.ts | 41 ++++++++++++++++--- ios/XMTPReactNative.podspec | 2 +- src/index.ts | 4 +- src/lib/Client.ts | 6 ++- 6 files changed, 47 insertions(+), 12 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 6fc236be2..c6be409e7 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.11" + implementation "org.xmtp:android:3.0.12" 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 a4d2db315..4dbead252 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) diff --git a/example/src/tests/groupPerformanceTests.ts b/example/src/tests/groupPerformanceTests.ts index 1be81446e..958eef8aa 100644 --- a/example/src/tests/groupPerformanceTests.ts +++ b/example/src/tests/groupPerformanceTests.ts @@ -2,7 +2,17 @@ import Config from 'react-native-config' import RNFS from 'react-native-fs' import { PrivateKeyAccount, privateKeyToAccount } from 'viem/accounts' -import { Client, Dm, Group, GroupUpdatedCodec, ReactionCodec, RemoteAttachmentCodec, ReplyCodec, Signer, StaticAttachmentCodec } from 'xmtp-react-native-sdk' +import { + Client, + Dm, + Group, + GroupUpdatedCodec, + ReactionCodec, + RemoteAttachmentCodec, + ReplyCodec, + Signer, + StaticAttachmentCodec, +} from 'xmtp-react-native-sdk' import { Test, assert, createClients } from './test-utils' import { Wallet } from 'ethers' @@ -108,7 +118,7 @@ test('building and creating', async () => { let start = performance.now() const alix = await Client.create(alixWallet, { - env: 'local', + env: 'dev', appVersion: 'Testing/0.0.0', dbEncryptionKey: keyBytes, dbDirectory: dbDirPath, @@ -131,7 +141,7 @@ test('building and creating', async () => { start = performance.now() const alixBuild = await Client.build(alixWallet.address, { - env: 'local', + env: 'dev', appVersion: 'Testing/0.0.0', dbEncryptionKey: keyBytes, dbDirectory: dbDirPath, @@ -152,6 +162,28 @@ test('building and creating', async () => { end = performance.now() console.log(`Alix build registered group updated codec in ${end - start}ms`) + start = performance.now() + const alixBuild2 = 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(), + ], + }, + alix.inboxId + ) + await alixBuild2.register(new GroupUpdatedCodec()) + end = performance.now() + console.log(`Built a client with inboxId in ${end - start}ms`) + start = performance.now() await alix.deleteLocalDatabase() end = performance.now() @@ -162,10 +194,9 @@ test('building and creating', async () => { end = performance.now() console.log(`Droped a client in ${end - start}ms`) - start = performance.now() await Client.create(alixWallet, { - env: 'local', + env: 'dev', appVersion: 'Testing/0.0.0', dbEncryptionKey: keyBytes, dbDirectory: dbDirPath, diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 3e4b04f4a..939babfa3 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,7 +26,7 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency "MessagePacker" - s.dependency "XMTP", "= 3.0.12" + s.dependency "XMTP", "= 3.0.13" s.dependency 'CSecp256k1', '~> 0.2' s.dependency "SQLCipher", "= 4.5.7" end diff --git a/src/index.ts b/src/index.ts index 7ed81248c..01219a2f0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -173,7 +173,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, @@ -183,6 +184,7 @@ export async function build( } return await XMTPModule.build( address, + inboxId, Array.from(dbEncryptionKey), JSON.stringify(authParams) ) diff --git a/src/lib/Client.ts b/src/lib/Client.ts index 36b065e90..93a14f989 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( From dedd2fe611cdc793dd4b7674cfde9386f1cc566f Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 3 Dec 2024 19:30:18 -0800 Subject: [PATCH 04/10] fix: up the performance test --- example/src/tests/groupPerformanceTests.ts | 481 ++------------------- 1 file changed, 25 insertions(+), 456 deletions(-) diff --git a/example/src/tests/groupPerformanceTests.ts b/example/src/tests/groupPerformanceTests.ts index 958eef8aa..abada6c0b 100644 --- a/example/src/tests/groupPerformanceTests.ts +++ b/example/src/tests/groupPerformanceTests.ts @@ -1,21 +1,16 @@ /* eslint-disable @typescript-eslint/no-extra-non-null-assertion */ -import Config from 'react-native-config' +import { Wallet } from 'ethers' import RNFS from 'react-native-fs' -import { PrivateKeyAccount, privateKeyToAccount } from 'viem/accounts' import { Client, - Dm, - Group, GroupUpdatedCodec, ReactionCodec, RemoteAttachmentCodec, ReplyCodec, - Signer, StaticAttachmentCodec, } from 'xmtp-react-native-sdk' -import { Test, assert, createClients } from './test-utils' -import { Wallet } from 'ethers' +import { Test, assert } from './test-utils' export const groupPerformanceTests: Test[] = [] let counter = 1 @@ -26,84 +21,6 @@ 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 -} - -export function convertPrivateKeyAccountToSigner( - privateKeyAccount: PrivateKeyAccount -): Signer { - if (!privateKeyAccount.address) { - throw new Error('WalletClient is not configured') - } - - return { - getAddress: async () => privateKeyAccount.address, - signMessage: async (message: string | Uint8Array) => - privateKeyAccount.signMessage({ - message: typeof message === 'string' ? message : { raw: message }, - }), - getChainId: () => undefined, - getBlockNumber: () => undefined, - walletType: () => undefined, - } -} - -// if (!Config.TEST_PRIVATE_KEY) { -// throw new Error('Add private key to .env file') -// } -// const privateKeyHex: `0x${string}` = `0x${Config.TEST_PRIVATE_KEY}` - -// const signer = convertPrivateKeyAccountToSigner( -// privateKeyToAccount(privateKeyHex) -// ) -// const alixClient = await Client.create(signer, { -// env: 'local', -// dbEncryptionKey: 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 initialPeers = await createClients(30) -// const boClient = initialPeers[0] -// const initialGroups = await createGroups(alixClient, initialPeers, 200, 5) -// const initialDms: Dm[] = await createDms(alixClient, initialPeers, 25) - 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, @@ -116,7 +33,7 @@ test('building and creating', async () => { } const alixWallet = Wallet.createRandom() - let start = performance.now() + const start1 = performance.now() const alix = await Client.create(alixWallet, { env: 'dev', appVersion: 'Testing/0.0.0', @@ -130,17 +47,11 @@ test('building and creating', async () => { new RemoteAttachmentCodec(), ], }) - await alix.register(new GroupUpdatedCodec()) - let end = performance.now() - console.log(`Created a new client in ${end - start}ms`) - - start = performance.now() - await alix.register(new GroupUpdatedCodec()) - end = performance.now() - console.log(`Alix registered group updated codec in ${end - start}ms`) + const end1 = performance.now() + console.log(`Created a new client in ${end1 - start1}ms`) - start = performance.now() - const alixBuild = await Client.build(alixWallet.address, { + const start2 = performance.now() + await Client.build(alixWallet.address, { env: 'dev', appVersion: 'Testing/0.0.0', dbEncryptionKey: keyBytes, @@ -153,17 +64,11 @@ test('building and creating', async () => { new RemoteAttachmentCodec(), ], }) - await alixBuild.register(new GroupUpdatedCodec()) - end = performance.now() - console.log(`Built a client in ${end - start}ms`) - - start = performance.now() - await alixBuild.register(new GroupUpdatedCodec()) - end = performance.now() - console.log(`Alix build registered group updated codec in ${end - start}ms`) + const end2 = performance.now() + console.log(`Built a client in ${end2 - start2}ms`) - start = performance.now() - const alixBuild2 = await Client.build( + const start3 = performance.now() + await Client.build( alixWallet.address, { env: 'dev', @@ -180,357 +85,21 @@ test('building and creating', async () => { }, alix.inboxId ) - await alixBuild2.register(new GroupUpdatedCodec()) - end = performance.now() - console.log(`Built a client with inboxId in ${end - start}ms`) - - start = performance.now() - await alix.deleteLocalDatabase() - end = performance.now() - console.log(`Deleted a local database in ${end - start}ms`) - - start = performance.now() - await Client.dropClient(alix.installationId) - end = performance.now() - console.log(`Droped a client in ${end - start}ms`) + const end3 = performance.now() + console.log(`Built a client with inboxId in ${end3 - start3}ms`) - start = performance.now() - 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(), - ], - }) - end = performance.now() - console.log(`Created the same client in ${end - start}ms`) + assert( + end2 - start2 < end1 - start1, + 'building a client should be faster than creating one' + ) + assert( + end3 - start3 < end1 - start1, + 'building a client with an inboxId should be faster than creating one' + ) + assert( + end3 - start3 < end2 - start2, + 'building a client with an inboxId should be faster than building without' + ) return true }) - -// 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`) - -// start2 = Date.now() -// groups2 = await boClient.conversations.listGroups( -// { -// consentState: false, -// description: false, -// addedByInboxId: false, -// isActive: false, -// lastMessage: true, -// }, -// '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' -// ) - -// 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' -// ) - -// 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' -// ) - -// 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' -// ) - -// return true -// }) From 5866f63959093d430c60e7fcdbc2ab35bb38df8d Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 3 Dec 2024 19:38:03 -0800 Subject: [PATCH 05/10] do the iOS side --- example/ios/Podfile.lock | 14 +++++++------- ios/XMTPModule.swift | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index f9441f4c3..cbff39dbd 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.8) + - LibXMTP (3.0.9) - MessagePacker (0.4.7) - MMKV (2.0.0): - MMKVCore (~> 2.0.0) @@ -446,18 +446,18 @@ PODS: - SQLCipher/standard (4.5.7): - SQLCipher/common - SwiftProtobuf (1.28.2) - - XMTP (3.0.12): + - XMTP (3.0.13): - Connect-Swift (= 1.0.0) - CryptoSwift (= 1.8.3) - CSecp256k1 (~> 0.2) - - LibXMTP (= 3.0.8) + - LibXMTP (= 3.0.9) - SQLCipher (= 4.5.7) - XMTPReactNative (0.1.0): - CSecp256k1 (~> 0.2) - ExpoModulesCore - MessagePacker - SQLCipher (= 4.5.7) - - XMTP (= 3.0.12) + - XMTP (= 3.0.13) - Yoga (1.14.0) DEPENDENCIES: @@ -706,7 +706,7 @@ SPEC CHECKSUMS: glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - LibXMTP: bcddd95871e7e3636f395691d73ec8ecbc3c78c9 + LibXMTP: c1bdf81e52b0e995b3aabf962a2b068e4ea184d0 MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02 MMKV: f7d1d5945c8765f97f39c3d121f353d46735d801 MMKVCore: c04b296010fcb1d1638f2c69405096aac12f6390 @@ -756,8 +756,8 @@ SPEC CHECKSUMS: RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396 SQLCipher: 5e6bfb47323635c8b657b1b27d25c5f1baf63bf5 SwiftProtobuf: 4dbaffec76a39a8dc5da23b40af1a5dc01a4c02d - XMTP: f3a4dec90eadfcf98d4d619238f50d051ac254f9 - XMTPReactNative: 04766f2ca3e776ed5214fc85546c81bf438b5e14 + XMTP: 0c1529391b3ed63136498fdf4a95515c296050a3 + XMTPReactNative: 9f22be223ee1bac2f0cfbbddc9cf0d5ac4b68e86 Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 PODFILE CHECKSUM: 0e6fe50018f34e575d38dc6a1fdf1f99c9596cdd diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 1807d3a89..0deb57c94 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -269,7 +269,7 @@ 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 +280,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) From f28a59e333948acf7913d65e0051914e9f9d857d Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 4 Dec 2024 16:29:58 -0800 Subject: [PATCH 06/10] do all the static can message work --- .../modules/xmtpreactnativesdk/XMTPModule.kt | 11 + example/src/tests/clientTests.ts | 23 ++ example/src/tests/groupTests.ts | 6 +- ios/XMTPModule.swift | 388 ++++++++++++------ src/index.ts | 7 + src/lib/Client.ts | 22 +- 6 files changed, 325 insertions(+), 132 deletions(-) diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index 4dbead252..8974d6bdc 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -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/src/tests/clientTests.ts b/example/src/tests/clientTests.ts index b3ff24964..3c16c80b5 100644 --- a/example/src/tests/clientTests.ts +++ b/example/src/tests/clientTests.ts @@ -34,6 +34,29 @@ 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, + 'RANDOM', + bo.address, + ]) + + assert(addressMap['RANDOM'] === false, `should not be able to message RANDOM`) + + 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/groupTests.ts b/example/src/tests/groupTests.ts index c97455b67..d1da8aa04 100644 --- a/example/src/tests/groupTests.ts +++ b/example/src/tests/groupTests.ts @@ -866,12 +866,12 @@ test('canMessage', async () => { const canMessageV3 = await caro.canMessage([ caro.address, alix.address, - '0x0000000000000000000000000000000000000000', + 'RANDOM', ]) assert( - canMessageV3['0x0000000000000000000000000000000000000000'] === false, - `should not be able to message 0x0000000000000000000000000000000000000000` + canMessageV3['RANDOM'] === false, + `should not be able to message RANDOM` ) assert( diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 0deb57c94..6c6ccc66f 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, inboxId: 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) @@ -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 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/src/index.ts b/src/index.ts index 2d1b70381..8d410b897 100644 --- a/src/index.ts +++ b/src/index.ts @@ -280,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.canMessage(environment, peerAddresses) +} + export async function getOrCreateInboxId( address: Address, environment: XMTPEnvironment diff --git a/src/lib/Client.ts b/src/lib/Client.ts index 93a14f989..fbbaafb9f 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -282,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( @@ -292,6 +292,20 @@ 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, @@ -552,12 +566,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) From 99206ea5e8881e2fe0126d9fd65db8b8ac7a1167 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 4 Dec 2024 18:01:03 -0800 Subject: [PATCH 07/10] bump android --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index c6be409e7..0dee991a1 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.12" + 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" From 4d4a4858aba927ecf6f83c21146c8dcbeedb5d9f Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 4 Dec 2024 18:10:11 -0800 Subject: [PATCH 08/10] fix up the can message tests --- example/src/tests/clientTests.ts | 9 +++++++-- example/src/tests/groupTests.ts | 6 +++--- ios/XMTPReactNative.podspec | 2 +- src/index.ts | 2 +- src/lib/Client.ts | 6 ++++-- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/example/src/tests/clientTests.ts b/example/src/tests/clientTests.ts index 3c16c80b5..b05405f94 100644 --- a/example/src/tests/clientTests.ts +++ b/example/src/tests/clientTests.ts @@ -39,11 +39,16 @@ test('static can message', async () => { const addressMap = await Client.canMessage('local', [ alix.address, - 'RANDOM', + '0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67', bo.address, ]) - assert(addressMap['RANDOM'] === false, `should not be able to message RANDOM`) + assert( + addressMap[ + '0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67'.toLocaleLowerCase() + ] === false, + `should not be able to message 0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67` + ) assert( addressMap[alix.address.toLowerCase()] === true, diff --git a/example/src/tests/groupTests.ts b/example/src/tests/groupTests.ts index d1da8aa04..6b24e1d47 100644 --- a/example/src/tests/groupTests.ts +++ b/example/src/tests/groupTests.ts @@ -866,12 +866,12 @@ test('canMessage', async () => { const canMessageV3 = await caro.canMessage([ caro.address, alix.address, - 'RANDOM', + '0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67', ]) assert( - canMessageV3['RANDOM'] === false, - `should not be able to message RANDOM` + canMessageV3['0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67'] === false, + `should not be able to message 0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67` ) assert( diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 939babfa3..4756572ce 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,7 +26,7 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency "MessagePacker" - s.dependency "XMTP", "= 3.0.13" + 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 8d410b897..00f467e11 100644 --- a/src/index.ts +++ b/src/index.ts @@ -284,7 +284,7 @@ export async function staticCanMessage( environment: XMTPEnvironment, peerAddresses: Address[] ): Promise<{ [key: Address]: boolean }> { - return await XMTPModule.canMessage(environment, peerAddresses) + return await XMTPModule.staticCanMessage(environment, peerAddresses) } export async function getOrCreateInboxId( diff --git a/src/lib/Client.ts b/src/lib/Client.ts index fbbaafb9f..eaf6492de 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -292,7 +292,6 @@ export class Client< return await XMTPModule.getOrCreateInboxId(address, env) } - /** * Determines whether the current user can send messages to the specified peers. * @@ -302,7 +301,10 @@ export class Client< * @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 }> { + static async canMessage( + env: XMTPEnvironment, + addresses: Address[] + ): Promise<{ [key: Address]: boolean }> { return await XMTPModule.staticCanMessage(env, addresses) } From 1691f5c17c7bbe86a645d5e96b1a5b92b8ce5419 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 4 Dec 2024 18:32:01 -0800 Subject: [PATCH 09/10] bump the pod --- example/ios/Podfile.lock | 14 +++++++------- ios/XMTPModule.swift | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index cbff39dbd..9d3bc8eb2 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.9) + - LibXMTP (3.0.10) - MessagePacker (0.4.7) - MMKV (2.0.0): - MMKVCore (~> 2.0.0) @@ -446,18 +446,18 @@ PODS: - SQLCipher/standard (4.5.7): - SQLCipher/common - SwiftProtobuf (1.28.2) - - XMTP (3.0.13): + - XMTP (3.0.14): - Connect-Swift (= 1.0.0) - CryptoSwift (= 1.8.3) - CSecp256k1 (~> 0.2) - - LibXMTP (= 3.0.9) + - LibXMTP (= 3.0.10) - SQLCipher (= 4.5.7) - XMTPReactNative (0.1.0): - CSecp256k1 (~> 0.2) - ExpoModulesCore - MessagePacker - SQLCipher (= 4.5.7) - - XMTP (= 3.0.13) + - XMTP (= 3.0.14) - Yoga (1.14.0) DEPENDENCIES: @@ -706,7 +706,7 @@ SPEC CHECKSUMS: glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - LibXMTP: c1bdf81e52b0e995b3aabf962a2b068e4ea184d0 + LibXMTP: e550ccb4565023eb77f5a2eddd9d5a71cfb9d2b3 MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02 MMKV: f7d1d5945c8765f97f39c3d121f353d46735d801 MMKVCore: c04b296010fcb1d1638f2c69405096aac12f6390 @@ -756,8 +756,8 @@ SPEC CHECKSUMS: RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396 SQLCipher: 5e6bfb47323635c8b657b1b27d25c5f1baf63bf5 SwiftProtobuf: 4dbaffec76a39a8dc5da23b40af1a5dc01a4c02d - XMTP: 0c1529391b3ed63136498fdf4a95515c296050a3 - XMTPReactNative: 9f22be223ee1bac2f0cfbbddc9cf0d5ac4b68e86 + XMTP: 3b586fa3703640bb5fec8a64daba9e157d9e5fdc + XMTPReactNative: ab20c0030e2092fb7201c42d6ec17a7055ec6bf8 Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 PODFILE CHECKSUM: 0e6fe50018f34e575d38dc6a1fdf1f99c9596cdd diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 6c6ccc66f..5a51e5546 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -412,7 +412,7 @@ public class XMTPModule: Module { AsyncFunction("staticCanMessage") { (environment: String, peerAddresses: [String]) -> [String: Bool] in - return try await Client.canMessage( + return try await XMTP.Client.canMessage( accountAddresses: peerAddresses, api: createApiClient(env: environment) ) From 91c0382ab018f6728283ca7b9d574a6079ea7884 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 4 Dec 2024 18:44:24 -0800 Subject: [PATCH 10/10] fix can message test --- example/src/tests/groupTests.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/example/src/tests/groupTests.ts b/example/src/tests/groupTests.ts index 6b24e1d47..fa0b2dcbb 100644 --- a/example/src/tests/groupTests.ts +++ b/example/src/tests/groupTests.ts @@ -870,7 +870,8 @@ test('canMessage', async () => { ]) assert( - canMessageV3['0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67'] === false, + canMessageV3['0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67'.toLowerCase()] === + false, `should not be able to message 0x4E9ce36E442e55EcD9025B9a6E0D88485d628A67` )