diff --git a/android/build.gradle b/android/build.gradle index 7fcbe5e5..6ebd92fa 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.4" + implementation "org.xmtp:android:3.0.5" 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 35ed22f0..6d980b01 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -175,7 +175,7 @@ class XMTPModule : Module() { val historySyncUrl = authOptions.historySyncUrl ?: when (authOptions.environment) { "production" -> "https://message-history.production.ephemera.network/" - "local" -> "http://0.0.0.0:5558" + "local" -> "http://10.0.2.2:5558" else -> "https://message-history.dev.ephemera.network/" } return ClientOptions( @@ -438,41 +438,43 @@ class XMTPModule : Module() { ).toJson() } - AsyncFunction("listGroups") Coroutine { inboxId: String, groupParams: String?, sortOrder: String?, limit: Int? -> + AsyncFunction("listGroups") Coroutine { inboxId: String, groupParams: String?, sortOrder: String?, limit: Int?, consentState: String? -> withContext(Dispatchers.IO) { logV("listGroups") val client = clients[inboxId] ?: throw XMTPException("No client") val params = ConversationParamsWrapper.conversationParamsFromJson(groupParams ?: "") val order = getConversationSortOrder(sortOrder ?: "") - val groups = client.conversations.listGroups(order = order, limit = limit) + val consent = consentState?.let { getConsentState(it) } + val groups = client.conversations.listGroups(order = order, limit = limit, consentState = consent) groups.map { group -> GroupWrapper.encode(client, group, params) } } } - AsyncFunction("listDms") Coroutine { inboxId: String, groupParams: String?, sortOrder: String?, limit: Int? -> + AsyncFunction("listDms") Coroutine { inboxId: String, groupParams: String?, sortOrder: String?, limit: Int?, consentState: String? -> withContext(Dispatchers.IO) { logV("listDms") val client = clients[inboxId] ?: throw XMTPException("No client") val params = ConversationParamsWrapper.conversationParamsFromJson(groupParams ?: "") val order = getConversationSortOrder(sortOrder ?: "") - val dms = client.conversations.listDms(order = order, limit = limit) + val consent = consentState?.let { getConsentState(it) } + val dms = client.conversations.listDms(order = order, limit = limit, consentState = consent) dms.map { dm -> DmWrapper.encode(client, dm, params) } } } - AsyncFunction("listConversations") Coroutine { inboxId: String, conversationParams: String?, sortOrder: String?, limit: Int? -> + AsyncFunction("listConversations") Coroutine { inboxId: String, conversationParams: String?, sortOrder: String?, limit: Int?, consentState: String? -> withContext(Dispatchers.IO) { logV("listConversations") val client = clients[inboxId] ?: throw XMTPException("No client") val params = ConversationParamsWrapper.conversationParamsFromJson(conversationParams ?: "") val order = getConversationSortOrder(sortOrder ?: "") - val conversations = - client.conversations.list(order = order, limit = limit) + val consent = consentState?.let { getConsentState(it) } + val conversations = client.conversations.list(order = order, limit = limit, consentState = consent) conversations.map { conversation -> ConversationWrapper.encode(client, conversation, params) } @@ -1060,6 +1062,13 @@ class XMTPModule : Module() { } } + AsyncFunction("syncConsent") Coroutine { inboxId: String -> + withContext(Dispatchers.IO) { + val client = clients[inboxId] ?: throw XMTPException("No client") + client.syncConsent() + } + } + AsyncFunction("setConsentState") Coroutine { inboxId: String, value: String, entryType: String, consentType: String -> withContext(Dispatchers.IO) { val client = clients[inboxId] ?: throw XMTPException("No client") diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index a2405114..533c7ead 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -56,7 +56,7 @@ PODS: - hermes-engine/Pre-built (= 0.71.14) - hermes-engine/Pre-built (0.71.14) - libevent (2.1.12) - - LibXMTP (3.0.0) + - LibXMTP (3.0.1) - Logging (1.0.0) - MessagePacker (0.4.7) - MMKV (2.0.0): @@ -449,16 +449,16 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (3.0.4): + - XMTP (3.0.5): - Connect-Swift (= 0.12.0) - GzipSwift - - LibXMTP (= 3.0.0) + - LibXMTP (= 3.0.1) - web3.swift - XMTPReactNative (0.1.0): - ExpoModulesCore - MessagePacker - secp256k1.swift - - XMTP (= 3.0.4) + - XMTP (= 3.0.5) - Yoga (1.14.0) DEPENDENCIES: @@ -711,7 +711,7 @@ SPEC CHECKSUMS: GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - LibXMTP: 4ef99026c3b353bd27195b48580e1bd34d083c3a + LibXMTP: b23a18d05d458fee72f0a96a114b1eb1e6d77d3b Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26 MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02 MMKV: f7d1d5945c8765f97f39c3d121f353d46735d801 @@ -763,8 +763,8 @@ SPEC CHECKSUMS: secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: dba23b4f3bcee464ca2f7569e1dc05fd9f4c0148 - XMTPReactNative: 117d8a00b063044029c11f50320a6b9c8abcdea7 + XMTP: 7b9105a3549427a294fb991c5892ebec73d2388d + XMTPReactNative: 0862a746eaddb7d643ad4cbdc2727d02863d9a18 Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 PODFILE CHECKSUM: 0e6fe50018f34e575d38dc6a1fdf1f99c9596cdd diff --git a/example/src/tests/conversationTests.ts b/example/src/tests/conversationTests.ts index 6c2c5cf6..5012c14c 100644 --- a/example/src/tests/conversationTests.ts +++ b/example/src/tests/conversationTests.ts @@ -97,6 +97,63 @@ test('can find a dm by address', async () => { return true }) +test('can filter conversations by consent', async () => { + const [alixClient, boClient, caroClient] = await createClients(3) + + const boGroup1 = await boClient.conversations.newGroup([alixClient.address]) + const otherGroup = await alixClient.conversations.newGroup([boClient.address]) + const boDm1 = await boClient.conversations.findOrCreateDm(alixClient.address) + await caroClient.conversations.findOrCreateDm(boClient.address) + await boClient.conversations.sync() + const boDm2 = await boClient.conversations.findDmByInboxId(caroClient.inboxId) + const boGroup2 = await boClient.conversations.findGroup(otherGroup.id) + + const boConvos = await boClient.conversations.list() + const boConvosFilteredAllowed = await boClient.conversations.list( + {}, + undefined, + undefined, + 'allowed' + ) + const boConvosFilteredUnknown = await boClient.conversations.list( + {}, + undefined, + undefined, + 'unknown' + ) + + assert( + boConvos.length === 4, + `Conversation length should be 4 but was ${boConvos.length}` + ) + + assert( + boConvosFilteredAllowed + .map((conversation: any) => conversation.id) + .toString() === [boGroup1.id, boDm1.id].toString(), + `Conversation allowed should be ${[ + boGroup1.id, + boDm1.id, + ].toString()} but was ${boConvosFilteredAllowed + .map((convo: any) => convo.id) + .toString()}` + ) + + assert( + boConvosFilteredUnknown + .map((conversation: any) => conversation.id) + .toString() === [boGroup2?.id, boDm2?.id].toString(), + `Conversation unknown filter should be ${[ + boGroup2?.id, + boDm2?.id, + ].toString()} but was ${boConvosFilteredUnknown + .map((convo: any) => convo.id) + .toString()}` + ) + + return true +}) + test('can list conversations with params', async () => { const [alixClient, boClient, caroClient] = await createClients(3) @@ -124,13 +181,27 @@ test('can list conversations with params', async () => { assert( boConvosOrderCreated.map((group: any) => group.id).toString() === [boGroup1.id, boGroup2.id, boDm1.id, boDm2.id].toString(), - `Conversation created at order should be ${[boGroup1.id, boGroup2.id, boDm1.id, boDm2.id].toString()} but was ${boConvosOrderCreated.map((group: any) => group.id).toString()}` + `Conversation created at order should be ${[ + boGroup1.id, + boGroup2.id, + boDm1.id, + boDm2.id, + ].toString()} but was ${boConvosOrderCreated + .map((group: any) => group.id) + .toString()}` ) assert( boConvosOrderLastMessage.map((group: any) => group.id).toString() === [boDm1.id, boGroup2.id, boDm2.id, boGroup1.id].toString(), - `Conversation last message order should be ${[boDm1.id, boGroup2.id, boDm2.id, boGroup1.id].toString()} but was ${boConvosOrderLastMessage.map((group: any) => group.id).toString()}` + `Conversation last message order should be ${[ + boDm1.id, + boGroup2.id, + boDm2.id, + boGroup1.id, + ].toString()} but was ${boConvosOrderLastMessage + .map((group: any) => group.id) + .toString()}` ) const messages = await boConvosOrderLastMessage[0].messages() @@ -213,12 +284,12 @@ test('can list conversation messages', async () => { assert( boGroupMessages?.length === 3, - `bo conversation lengths should be 4 but was ${boGroupMessages?.length}` + `bo conversation lengths should be 3 but was ${boGroupMessages?.length}` ) assert( - boDmMessages?.length === 3, - `alix conversation lengths should be 3 but was ${boDmMessages?.length}` + boDmMessages?.length === 2, + `alix conversation lengths should be 2 but was ${boDmMessages?.length}` ) return true diff --git a/example/src/tests/dmTests.ts b/example/src/tests/dmTests.ts index 0c10ca24..51fd0c36 100644 --- a/example/src/tests/dmTests.ts +++ b/example/src/tests/dmTests.ts @@ -10,6 +10,61 @@ function test(name: string, perform: () => Promise) { }) } +test('can filter dms by consent', async () => { + const [alixClient, boClient, caroClient] = await createClients(3) + + await boClient.conversations.newGroup([alixClient.address]) + const otherGroup = await alixClient.conversations.newGroup([boClient.address]) + const boDm1 = await boClient.conversations.findOrCreateDm(alixClient.address) + await caroClient.conversations.findOrCreateDm(boClient.address) + await boClient.conversations.sync() + const boDm2 = await boClient.conversations.findDmByInboxId(caroClient.inboxId) + await boClient.conversations.findGroup(otherGroup.id) + + const boConvos = await boClient.conversations.listDms() + const boConvosFilteredAllowed = await boClient.conversations.listDms( + {}, + undefined, + undefined, + 'allowed' + ) + const boConvosFilteredUnknown = await boClient.conversations.listDms( + {}, + undefined, + undefined, + 'unknown' + ) + + assert( + boConvos.length === 2, + `Conversation length should be 2 but was ${boConvos.length}` + ) + + assert( + boConvosFilteredAllowed + .map((conversation: any) => conversation.id) + .toString() === [boDm1.id].toString(), + `Conversation allowed should be ${[ + boDm1.id, + ].toString()} but was ${boConvosFilteredAllowed + .map((convo: any) => convo.id) + .toString()}` + ) + + assert( + boConvosFilteredUnknown + .map((conversation: any) => conversation.id) + .toString() === [boDm2?.id].toString(), + `Conversation unknown filter should be ${[ + boDm2?.id, + ].toString()} but was ${boConvosFilteredUnknown + .map((convo: any) => convo.id) + .toString()}` + ) + + return true +}) + test('can list dms with params', async () => { const [alixClient, boClient, caroClient] = await createClients(3) @@ -37,14 +92,24 @@ test('can list dms with params', async () => { boConvosOrderCreated .map((conversation: any) => conversation.id) .toString() === [boDm1.id, boDm2.id].toString(), - `Conversation created at order should be ${[boDm1.id, boDm2.id].toString()} but was ${boConvosOrderCreated.map((convo: any) => convo.id).toString()}` + `Conversation created at order should be ${[ + boDm1.id, + boDm2.id, + ].toString()} but was ${boConvosOrderCreated + .map((convo: any) => convo.id) + .toString()}` ) assert( boConvosOrderLastMessage .map((conversation: any) => conversation.id) .toString() === [boDm1.id, boDm2.id].toString(), - `Conversation last message order should be ${[boDm1.id, boDm2.id].toString()} but was ${boConvosOrderLastMessage.map((convo: any) => convo.id).toString()}` + `Conversation last message order should be ${[ + boDm1.id, + boDm2.id, + ].toString()} but was ${boConvosOrderLastMessage + .map((convo: any) => convo.id) + .toString()}` ) const messages = await boConvosOrderLastMessage[0].messages() diff --git a/example/src/tests/groupTests.ts b/example/src/tests/groupTests.ts index 267a96f7..e8b04e71 100644 --- a/example/src/tests/groupTests.ts +++ b/example/src/tests/groupTests.ts @@ -1,5 +1,4 @@ import { Wallet } from 'ethers' -import { DecodedMessage } from 'xmtp-react-native-sdk/lib/DecodedMessage' import { Test, @@ -15,6 +14,7 @@ import { GroupUpdatedContent, GroupUpdatedCodec, ConsentListEntry, + DecodedMessage, } from '../../../src/index' export const groupTests: Test[] = [] @@ -671,6 +671,61 @@ test('can stream groups', async () => { return true }) +test('can filter groups by consent', async () => { + const [alixClient, boClient, caroClient] = await createClients(3) + + const boGroup1 = await boClient.conversations.newGroup([alixClient.address]) + const otherGroup = await alixClient.conversations.newGroup([boClient.address]) + await boClient.conversations.findOrCreateDm(alixClient.address) + await caroClient.conversations.findOrCreateDm(boClient.address) + await boClient.conversations.sync() + await boClient.conversations.findDmByInboxId(caroClient.inboxId) + const boGroup2 = await boClient.conversations.findGroup(otherGroup.id) + + const boConvos = await boClient.conversations.listGroups() + const boConvosFilteredAllowed = await boClient.conversations.listGroups( + {}, + undefined, + undefined, + 'allowed' + ) + const boConvosFilteredUnknown = await boClient.conversations.listGroups( + {}, + undefined, + undefined, + 'unknown' + ) + + assert( + boConvos.length === 2, + `Conversation length should be 2 but was ${boConvos.length}` + ) + + assert( + boConvosFilteredAllowed + .map((conversation: any) => conversation.id) + .toString() === [boGroup1.id].toString(), + `Conversation allowed should be ${[ + boGroup1.id, + ].toString()} but was ${boConvosFilteredAllowed + .map((convo: any) => convo.id) + .toString()}` + ) + + assert( + boConvosFilteredUnknown + .map((conversation: any) => conversation.id) + .toString() === [boGroup2?.id].toString(), + `Conversation unknown filter should be ${[ + boGroup2?.id, + ].toString()} but was ${boConvosFilteredUnknown + .map((convo: any) => convo.id) + .toString()}` + ) + + return true +}) + test('can list groups with params', async () => { const [alixClient, boClient] = await createClients(2) @@ -696,13 +751,17 @@ test('can list groups with params', async () => { assert( boGroupsOrderCreated.map((group: any) => group.id).toString() === [boGroup1.id, boGroup2.id].toString(), - `Group order should be group1 then group2 but was ${boGroupsOrderCreated.map((group: any) => group.id).toString()}` + `Group order should be group1 then group2 but was ${boGroupsOrderCreated + .map((group: any) => group.id) + .toString()}` ) assert( boGroupsOrderLastMessage.map((group: any) => group.id).toString() === [boGroup2.id, boGroup1.id].toString(), - `Group order should be group2 then group1 but was ${boGroupsOrderLastMessage.map((group: any) => group.id).toString()}` + `Group order should be group2 then group1 but was ${boGroupsOrderLastMessage + .map((group: any) => group.id) + .toString()}` ) const messages = await boGroupsOrderLastMessage[0].messages() @@ -1447,8 +1506,8 @@ test('can sync all groups', async () => { `messages should be 4 after sync but was ${boGroup?.messages?.length}` ) assert( - numGroupsSynced === 50, - `should have synced 50 groups but synced ${numGroupsSynced}` + numGroupsSynced === 51, + `should have synced 51 groups but synced ${numGroupsSynced}` ) for (const group of groups) { @@ -1458,15 +1517,15 @@ test('can sync all groups', async () => { // First syncAllConversations after removal will still sync each group to set group inactive const numGroupsSynced2 = await bo.conversations.syncAllConversations() assert( - numGroupsSynced2 === 50, - `should have synced 50 groups but synced ${numGroupsSynced2}` + numGroupsSynced2 === 51, + `should have synced 51 groups but synced ${numGroupsSynced2}` ) // Next syncAllConversations will not sync inactive groups const numGroupsSynced3 = await bo.conversations.syncAllConversations() assert( - numGroupsSynced3 === 0, - `should have synced 0 groups but synced ${numGroupsSynced3}` + numGroupsSynced3 === 1, + `should have synced 1 groups but synced ${numGroupsSynced3}` ) return true }) diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 94f6910a..fdcfa1f9 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -385,7 +385,7 @@ public class XMTPModule: Module { AsyncFunction("listGroups") { ( inboxId: String, groupParams: String?, sortOrder: String?, - limit: Int? + limit: Int?, consentState: String? ) -> [String] in guard let client = await clientsManager.getClient(key: inboxId) else { @@ -395,9 +395,14 @@ public class XMTPModule: Module { let params = ConversationParamsWrapper.conversationParamsFromJson( groupParams ?? "") let order = getConversationSortOrder(order: sortOrder ?? "") - + let consent: ConsentState? + if let state = consentState { + consent = try getConsentState(state: state) + } else { + consent = nil + } var groupList: [Group] = try await client.conversations.listGroups( - limit: limit, order: order) + limit: limit, order: order, consentState: consent) var results: [String] = [] for group in groupList { @@ -411,7 +416,7 @@ public class XMTPModule: Module { AsyncFunction("listDms") { ( inboxId: String, groupParams: String?, sortOrder: String?, - limit: Int? + limit: Int?, consentState: String? ) -> [String] in guard let client = await clientsManager.getClient(key: inboxId) else { @@ -421,9 +426,14 @@ public class XMTPModule: Module { let params = ConversationParamsWrapper.conversationParamsFromJson( groupParams ?? "") let order = getConversationSortOrder(order: sortOrder ?? "") - + let consent: ConsentState? + if let state = consentState { + consent = try getConsentState(state: state) + } else { + consent = nil + } var dmList: [Dm] = try await client.conversations.listDms( - limit: limit, order: order) + limit: limit, order: order, consentState: consent) var results: [String] = [] for dm in dmList { @@ -437,7 +447,7 @@ public class XMTPModule: Module { AsyncFunction("listConversations") { ( inboxId: String, conversationParams: String?, - sortOrder: String?, limit: Int? + sortOrder: String?, limit: Int?, consentState: String? ) -> [String] in guard let client = await clientsManager.getClient(key: inboxId) else { @@ -447,8 +457,14 @@ public class XMTPModule: Module { let params = ConversationParamsWrapper.conversationParamsFromJson( conversationParams ?? "") let order = getConversationSortOrder(order: sortOrder ?? "") + let consent: ConsentState? + if let state = consentState { + consent = try getConsentState(state: state) + } else { + consent = nil + } let conversations = try await client.conversations.list( - limit: limit, order: order) + limit: limit, order: order, consentState: consent) var results: [String] = [] for conversation in conversations { @@ -1329,6 +1345,15 @@ public class XMTPModule: Module { conversation, client: client) } + AsyncFunction("syncConsent") { (inboxId: String) in + guard let client = await clientsManager.getClient(key: inboxId) + else { + throw Error.noClient + } + + try await client.syncConsent() + } + AsyncFunction("setConsentState") { ( inboxId: String, value: String, entryType: String, diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 9bf755fc..d0b93865 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,5 +26,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency 'secp256k1.swift' s.dependency "MessagePacker" - s.dependency "XMTP", "= 3.0.4" + s.dependency "XMTP", "= 3.0.5" end diff --git a/src/index.ts b/src/index.ts index 1fae6317..25e48c9f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -88,9 +88,13 @@ export async function getInboxState( export async function getInboxStates( inboxId: InboxId, refreshFromNetwork: boolean, - inboxIds: InboxId[], + inboxIds: InboxId[] ): Promise { - const inboxStates = await XMTPModule.getInboxStates(inboxId, refreshFromNetwork, inboxIds) + const inboxStates = await XMTPModule.getInboxStates( + inboxId, + refreshFromNetwork, + inboxIds + ) return inboxStates.map((json: string) => { return InboxState.from(json) }) @@ -230,14 +234,16 @@ export async function listGroups< client: Client, opts?: ConversationOptions | undefined, order?: ConversationOrder | undefined, - limit?: number | undefined + limit?: number | undefined, + consentState?: ConsentState | undefined ): Promise[]> { return ( await XMTPModule.listGroups( client.inboxId, JSON.stringify(opts), order, - limit + limit, + consentState ) ).map((json: string) => { const group = JSON.parse(json) @@ -255,10 +261,17 @@ export async function listDms< client: Client, opts?: ConversationOptions | undefined, order?: ConversationOrder | undefined, - limit?: number | undefined + limit?: number | undefined, + consentState?: ConsentState | undefined ): Promise[]> { return ( - await XMTPModule.listDms(client.inboxId, JSON.stringify(opts), order, limit) + await XMTPModule.listDms( + client.inboxId, + JSON.stringify(opts), + order, + limit, + consentState + ) ).map((json: string) => { const group = JSON.parse(json) @@ -275,14 +288,16 @@ export async function listConversations< client: Client, opts?: ConversationOptions | undefined, order?: ConversationOrder | undefined, - limit?: number | undefined + limit?: number | undefined, + consentState?: ConsentState | undefined ): Promise[]> { return ( await XMTPModule.listConversations( client.inboxId, JSON.stringify(opts), order, - limit + limit, + consentState ) ).map((json: string) => { const jsonObj = JSON.parse(json) @@ -854,6 +869,10 @@ export async function processWelcomeMessage< } } +export async function syncConsent(inboxId: InboxId): Promise { + return await XMTPModule.syncConsent(inboxId) +} + export async function setConsentState( inboxId: InboxId, value: string, diff --git a/src/lib/Conversations.ts b/src/lib/Conversations.ts index e585c124..d6e51924 100644 --- a/src/lib/Conversations.ts +++ b/src/lib/Conversations.ts @@ -13,6 +13,7 @@ import { PermissionPolicySet } from './types/PermissionPolicySet' import * as XMTPModule from '../index' import { Address, + ConsentState, ContentCodec, Conversation, ConversationId, @@ -32,67 +33,6 @@ export default class Conversations< this.client = client } - /** - * Creates a new conversation. - * - * This method creates a new conversation with the specified peer address and context. - * - * @param {Address} peerAddress - The address of the peer to create a conversation with. - * @returns {Promise} A Promise that resolves to a Conversation object. - */ - async newConversation( - peerAddress: Address - ): Promise> { - const checksumAddress = getAddress(peerAddress) - return await XMTPModule.findOrCreateDm(this.client, checksumAddress) - } - - /** - * Creates a new conversation. - * - * This method creates a new conversation with the specified peer address. - * - * @param {Address} peerAddress - The address of the peer to create a conversation with. - * @returns {Promise} A Promise that resolves to a Dm object. - */ - async findOrCreateDm(peerAddress: Address): Promise> { - return await XMTPModule.findOrCreateDm(this.client, peerAddress) - } - - /** - * This method returns a list of all groups that the client is a member of. - * To get the latest list of groups from the network, call syncGroups() first. - * @param {ConversationOptions} opts - The options to specify what fields you want returned for the groups in the list. - * @param {ConversationOrder} order - The order to specify if you want groups listed by last message or by created at. - * @param {number} limit - Limit the number of groups returned in the list. - * - * @returns {Promise} A Promise that resolves to an array of Group objects. - */ - async listGroups( - opts?: ConversationOptions | undefined, - order?: ConversationOrder | undefined, - limit?: number | undefined - ): Promise[]> { - return await XMTPModule.listGroups(this.client, opts, order, limit) - } - - /** - * This method returns a list of all dms that the client is a member of. - * To get the latest list of dms from the network, call sync() first. - * @param {ConversationOptions} opts - The options to specify what fields you want returned for the dms in the list. - * @param {ConversationOrder} order - The order to specify if you want dms listed by last message or by created at. - * @param {number} limit - Limit the number of dms returned in the list. - * - * @returns {Promise} A Promise that resolves to an array of Dms objects. - */ - async listDms( - opts?: ConversationOptions | undefined, - order?: ConversationOrder | undefined, - limit?: number | undefined - ): Promise[]> { - return await XMTPModule.listDms(this.client, opts, order, limit) - } - /** * This method returns a group by the group id if that group exists in the local database. * To get the latest list of groups from the network, call sync() first. @@ -165,54 +105,45 @@ export default class Conversations< return await XMTPModule.findMessage(this.client, messageId) } + async fromWelcome( + encryptedMessage: string + ): Promise> { + try { + return await XMTPModule.processWelcomeMessage( + this.client, + encryptedMessage + ) + } catch (e) { + console.info('ERROR in processWelcomeMessage()', e) + throw e + } + } + /** - * This method returns a list of all V3 conversations that the client is a member of. - * To include the latest conversations from the network in the returned list, call sync() first. + * Creates a new conversation. * - * @returns {Promise} A Promise that resolves to an array of Conversation objects. + * This method creates a new conversation with the specified peer address and context. + * + * @param {Address} peerAddress - The address of the peer to create a conversation with. + * @returns {Promise} A Promise that resolves to a Conversation object. */ - async list( - opts?: ConversationOptions | undefined, - order?: ConversationOrder | undefined, - limit?: number | undefined - ): Promise[]> { - return await XMTPModule.listConversations(this.client, opts, order, limit) + async newConversation( + peerAddress: Address + ): Promise> { + const checksumAddress = getAddress(peerAddress) + return await XMTPModule.findOrCreateDm(this.client, checksumAddress) } /** - * This method streams conversations that the client is a member of. - * @param {type} ConversationType - Whether to stream groups, dms, or both - * @returns {Promise} A Promise that resolves to an array of Conversation objects. + * Creates a new conversation. + * + * This method creates a new conversation with the specified peer address. + * + * @param {Address} peerAddress - The address of the peer to create a conversation with. + * @returns {Promise} A Promise that resolves to a Dm object. */ - async stream( - callback: (conversation: Conversation) => Promise, - type: ConversationType = 'all' - ): Promise { - XMTPModule.subscribeToConversations(this.client.inboxId, type) - const subscription = XMTPModule.emitter.addListener( - EventTypes.Conversation, - async ({ - inboxId, - conversation, - }: { - inboxId: string - conversation: Conversation - }) => { - if (inboxId !== this.client.inboxId) { - return - } - if (conversation.version === ConversationVersion.GROUP) { - return await callback( - new Group(this.client, conversation as unknown as GroupParams) - ) - } else if (conversation.version === ConversationVersion.DM) { - return await callback( - new Dm(this.client, conversation as unknown as DmParams) - ) - } - } - ) - this.subscriptions[EventTypes.Conversation] = subscription + async findOrCreateDm(peerAddress: Address): Promise> { + return await XMTPModule.findOrCreateDm(this.client, peerAddress) } /** @@ -265,6 +196,75 @@ export default class Conversations< ) } + /** + * This method returns a list of all groups that the client is a member of. + * To get the latest list of groups from the network, call syncGroups() first. + * @param {ConversationOptions} opts - The options to specify what fields you want returned for the groups in the list. + * @param {ConversationOrder} order - The order to specify if you want groups listed by last message or by created at. + * @param {number} limit - Limit the number of groups returned in the list. + * + * @returns {Promise} A Promise that resolves to an array of Group objects. + */ + async listGroups( + opts?: ConversationOptions | undefined, + order?: ConversationOrder | undefined, + limit?: number | undefined, + consentState?: ConsentState | undefined + ): Promise[]> { + return await XMTPModule.listGroups( + this.client, + opts, + order, + limit, + consentState + ) + } + + /** + * This method returns a list of all dms that the client is a member of. + * To get the latest list of dms from the network, call sync() first. + * @param {ConversationOptions} opts - The options to specify what fields you want returned for the dms in the list. + * @param {ConversationOrder} order - The order to specify if you want dms listed by last message or by created at. + * @param {number} limit - Limit the number of dms returned in the list. + * + * @returns {Promise} A Promise that resolves to an array of Dms objects. + */ + async listDms( + opts?: ConversationOptions | undefined, + order?: ConversationOrder | undefined, + limit?: number | undefined, + consentState?: ConsentState | undefined + ): Promise[]> { + return await XMTPModule.listDms( + this.client, + opts, + order, + limit, + consentState + ) + } + + /** + * This method returns a list of all V3 conversations that the client is a member of. + * To include the latest conversations from the network in the returned list, call sync() first. + * + * @returns {Promise} A Promise that resolves to an array of Conversation objects. + */ + async list( + opts?: ConversationOptions | undefined, + order?: ConversationOrder | undefined, + limit?: number | undefined, + consentState?: ConsentState | undefined + ): Promise[]> { + return await XMTPModule.listConversations( + this.client, + opts, + order, + limit, + consentState + ) + } + /** * Executes a network request to fetch the latest list of conversations associated with the client * and save them to the local state. @@ -282,6 +282,42 @@ export default class Conversations< return await XMTPModule.syncAllConversations(this.client.inboxId) } + /** + * This method streams conversations that the client is a member of. + * @param {type} ConversationType - Whether to stream groups, dms, or both + * @returns {Promise} A Promise that resolves to an array of Conversation objects. + */ + async stream( + callback: (conversation: Conversation) => Promise, + type: ConversationType = 'all' + ): Promise { + XMTPModule.subscribeToConversations(this.client.inboxId, type) + const subscription = XMTPModule.emitter.addListener( + EventTypes.Conversation, + async ({ + inboxId, + conversation, + }: { + inboxId: string + conversation: Conversation + }) => { + if (inboxId !== this.client.inboxId) { + return + } + if (conversation.version === ConversationVersion.GROUP) { + return await callback( + new Group(this.client, conversation as unknown as GroupParams) + ) + } else if (conversation.version === ConversationVersion.DM) { + return await callback( + new Dm(this.client, conversation as unknown as DmParams) + ) + } + } + ) + this.subscriptions[EventTypes.Conversation] = subscription + } + /** * Listen for new messages in all conversations. * @@ -313,20 +349,6 @@ export default class Conversations< this.subscriptions[EventTypes.Message] = subscription } - async fromWelcome( - encryptedMessage: string - ): Promise> { - try { - return await XMTPModule.processWelcomeMessage( - this.client, - encryptedMessage - ) - } catch (e) { - console.info('ERROR in processWelcomeMessage()', e) - throw e - } - } - /** * Cancels the stream for new conversations. */ diff --git a/src/lib/PrivatePreferences.ts b/src/lib/PrivatePreferences.ts index 04c8e782..f78baca7 100644 --- a/src/lib/PrivatePreferences.ts +++ b/src/lib/PrivatePreferences.ts @@ -39,4 +39,8 @@ export default class PrivatePreferences { consentEntry.permissionType ) } + + async syncConsent(): Promise { + return await XMTPModule.syncConsent(this.client.inboxId) + } }