From 461f4af08580aff9e311183aa9f90f02627146c6 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 5 Dec 2023 21:08:55 -0800 Subject: [PATCH 1/9] bump to latest native versions --- android/build.gradle | 2 +- ios/XMTPReactNative.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 893fb66d0..4ab0b7f5d 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -95,7 +95,7 @@ repositories { dependencies { implementation project(':expo-modules-core') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}" - implementation "org.xmtp:android:0.6.17" + implementation "org.xmtp:android:0.6.18" 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/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index f37f2a985..56007fb4e 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -25,5 +25,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.6.14-alpha0" + s.dependency "XMTP", "= 0.7.0-alpha0" end From 1f0be17ace3eb09d5e9a0ea17c2fcb9fc1404086 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 6 Dec 2023 06:35:11 -0800 Subject: [PATCH 2/9] update the lock file --- example/ios/Podfile.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 13838025c..cd71435dd 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -411,16 +411,16 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (0.6.14-alpha0): + - XMTP (0.7.0-alpha0): - Connect-Swift (= 0.3.0) - GzipSwift - web3.swift - - XMTPRust (= 0.3.6-beta0) + - XMTPRust (= 0.3.7-beta0) - XMTPReactNative (0.1.0): - ExpoModulesCore - MessagePacker - - XMTP (= 0.6.14-alpha0) - - XMTPRust (0.3.6-beta0) + - XMTP (= 0.7.0-alpha0) + - XMTPRust (0.3.7-beta0) - Yoga (1.14.0) DEPENDENCIES: @@ -668,9 +668,9 @@ SPEC CHECKSUMS: secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: b02b5075dcf60c9f5f403000b3b0c202a11b6ae1 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: 5314a5151dbfad2e24bb5910e679052916a9faff - XMTPReactNative: 5e393ab43d402bae404f675245cfc66a078a33ff - XMTPRust: 3c958736a4f4ee798e425b5644551f1c948da4b0 + XMTP: bf9244684e659096f6a3351e8e942ad45eeed842 + XMTPReactNative: 2b0e4a9532081c6f84f54a9377b1cda633a7b47d + XMTPRust: 8848a2ba761b2c961d666632f2ad27d1082faa93 Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556 PODFILE CHECKSUM: 522d88edc2d5fac4825e60a121c24abc18983367 From 134e468306f7d9139da6e9a1e87b940caa84300c Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 6 Dec 2023 12:41:39 -0800 Subject: [PATCH 3/9] add consentList functions to the native modules --- android/build.gradle | 2 +- .../modules/xmtpreactnativesdk/XMTPModule.kt | 19 +++++++++++---- example/ios/Podfile.lock | 8 +++---- ios/XMTPModule.swift | 24 ++++++++++++++----- ios/XMTPReactNative.podspec | 2 +- 5 files changed, 38 insertions(+), 17 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 4ab0b7f5d..88caf0565 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -95,7 +95,7 @@ repositories { dependencies { implementation project(':expo-modules-core') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}" - implementation "org.xmtp:android:0.6.18" + implementation "org.xmtp:android:0.6.19" 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 9d4e4e6fd..fd743fd29 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -552,17 +552,26 @@ class XMTPModule : Module() { AsyncFunction("conversationConsentState") { clientAddress: String, conversationTopic: String -> val conversation = findConversation(clientAddress, conversationTopic) ?: throw XMTPException("no conversation found for $conversationTopic") - when (conversation.consentState()) { - ConsentState.ALLOWED -> "allowed" - ConsentState.DENIED -> "denied" - ConsentState.UNKNOWN -> "unknown" - } + consentStateToString(conversation.consentState()) + } + + AsyncFunction("consentList") { clientAddress: String -> + val client = clients[clientAddress] ?: throw XMTPException("No client") + client.contacts.consentList.entries.map { "${it.key}: ${consentStateToString(it.value)}" } } } // // Helpers // + private fun consentStateToString(state: ConsentState): String { + return when (state) { + ConsentState.ALLOWED -> "allowed" + ConsentState.DENIED -> "denied" + ConsentState.UNKNOWN -> "unknown" + } + } + private fun findConversation( clientAddress: String, topic: String, diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index cd71435dd..428a983b3 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -411,7 +411,7 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (0.7.0-alpha0): + - XMTP (0.7.1-alpha0): - Connect-Swift (= 0.3.0) - GzipSwift - web3.swift @@ -419,7 +419,7 @@ PODS: - XMTPReactNative (0.1.0): - ExpoModulesCore - MessagePacker - - XMTP (= 0.7.0-alpha0) + - XMTP (= 0.7.1-alpha0) - XMTPRust (0.3.7-beta0) - Yoga (1.14.0) @@ -668,8 +668,8 @@ SPEC CHECKSUMS: secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: b02b5075dcf60c9f5f403000b3b0c202a11b6ae1 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: bf9244684e659096f6a3351e8e942ad45eeed842 - XMTPReactNative: 2b0e4a9532081c6f84f54a9377b1cda633a7b47d + XMTP: 36069f94fc0485a0e6fe7a9fd5debc7ba816002c + XMTPReactNative: 40f71f1405e0ba3fcd4311382a236e7748ce1301 XMTPRust: 8848a2ba761b2c961d666632f2ad27d1082faa93 Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556 diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 39dd3c1ab..5a37197a2 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -512,19 +512,31 @@ public class XMTPModule: Module { guard let conversation = try await findConversation(clientAddress: clientAddress, topic: conversationTopic) else { throw Error.conversationNotFound(conversationTopic) } - switch await conversation.consentState() { - case .allowed: return "allowed" - case .denied: return "denied" - case .unknown: return "unknown" - } + return consentStateToString(state: await conversation.consentState()) } + + AsyncFunction("consentList") { (clientAddress: String) -> [String] in + guard let client = await clientsManager.getClient(key: clientAddress) else { + throw Error.noClient + } + let entries = await client.contacts.consentList.entries + return entries.map { "\($0.key): \(consentStateToString(state: $0.value))" } + } } // // Helpers // - func createClientConfig(env: String, appVersion: String?) -> XMTP.ClientOptions { + func consentStateToString(state: ConsentState) -> String { + switch state { + case .allowed: return "allowed" + case .denied: return "denied" + case .unknown: return "unknown" + } + } + + func createClientConfig(env: String, appVersion: String?) -> XMTP.ClientOptions { // Ensure that all codecs have been registered. switch env { case "local": diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 56007fb4e..ea844efb4 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -25,5 +25,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.7.0-alpha0" + s.dependency "XMTP", "= 0.7.1-alpha0" end From 0a7d80b6908cee5fd5809624c1246f2d698c72ad Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 6 Dec 2023 12:55:07 -0800 Subject: [PATCH 4/9] write the typescript RN side --- src/index.ts | 21 +++++++++++++++++++++ src/lib/Contacts.ts | 10 ++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index 72f0b1940..349210ca7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -353,6 +353,27 @@ export function refreshConsentList(clientAddress: string) { XMTPModule.refreshConsentList(clientAddress) } +export async function consentList( + clientAddress: string +): Promise> { + return jsonArrayToMap(await XMTPModule.consentList(clientAddress)) +} + +function jsonArrayToMap(jsonArray: string[]): Map { + const result = new Map() + + jsonArray.forEach((jsonString) => { + const parsedObject = JSON.parse(jsonString) + if (parsedObject && parsedObject.key) { + result.set(parsedObject.key, parsedObject) + } else { + console.error('Invalid JSON structure:', jsonString) + } + }) + + return result +} + export const emitter = new EventEmitter(XMTPModule ?? NativeModulesProxy.XMTP) export * from './lib/ContentCodec' diff --git a/src/lib/Contacts.ts b/src/lib/Contacts.ts index 77480048c..c4e809849 100644 --- a/src/lib/Contacts.ts +++ b/src/lib/Contacts.ts @@ -9,13 +9,11 @@ export default class Contacts { } async isAllowed(address: string): Promise { - const result = await XMTPModule.isAllowed(this.client.address, address) - return result + return await XMTPModule.isAllowed(this.client.address, address) } async isDenied(address: string): Promise { - const result = await XMTPModule.isDenied(this.client.address, address) - return result + return await XMTPModule.isDenied(this.client.address, address) } deny(addresses: string[]) { @@ -29,4 +27,8 @@ export default class Contacts { refreshConsentList() { XMTPModule.refreshConsentList(this.client.address) } + + async consentList(): Promise> { + return await XMTPModule.consentList(this.client.address) + } } From ada1c446a61e2086111b1154f0c72c6ddc44f90a Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 6 Dec 2023 13:39:49 -0800 Subject: [PATCH 5/9] fix up the tests and the way the map was parsing --- example/src/tests.ts | 17 +++++++++++++++++ src/index.ts | 17 +++++------------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/example/src/tests.ts b/example/src/tests.ts index 50e188eea..5995bf5f5 100644 --- a/example/src/tests.ts +++ b/example/src/tests.ts @@ -672,6 +672,23 @@ test('canManagePreferences', async () => { ) } + const boConsentList = await bo.contacts.consentList() + await delayToPropogate() + + if (boConsentList.size !== 1) { + throw new Error(`consent list for bo should 1 not ${boConsentList.size}`) + } + + const boConsentListState = boConsentList.get( + `address-${alixConversation.peerAddress.toLowerCase()}` + ) + + if (boConsentListState !== 'denied') { + throw new Error( + `conversations denied by bo should be denied in consent list not ${boConsentListState}` + ) + } + return true }) diff --git a/src/index.ts b/src/index.ts index 349210ca7..a98507fa4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -356,19 +356,12 @@ export function refreshConsentList(clientAddress: string) { export async function consentList( clientAddress: string ): Promise> { - return jsonArrayToMap(await XMTPModule.consentList(clientAddress)) -} - -function jsonArrayToMap(jsonArray: string[]): Map { - const result = new Map() + const consentList = await XMTPModule.consentList(clientAddress) + const result = new Map() - jsonArray.forEach((jsonString) => { - const parsedObject = JSON.parse(jsonString) - if (parsedObject && parsedObject.key) { - result.set(parsedObject.key, parsedObject) - } else { - console.error('Invalid JSON structure:', jsonString) - } + consentList.forEach((item) => { + const [key, value] = item.split(':').map((str: string) => str.trim()) + result.set(key.toLowerCase(), value) }) return result From ed1d7915fcad93bb82856f920731f37d780f25cd Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 7 Dec 2023 14:26:05 -0800 Subject: [PATCH 6/9] update the swift and kotlin side to support types --- android/build.gradle | 2 +- .../modules/xmtpreactnativesdk/XMTPModule.kt | 11 ++----- .../wrappers/ConsentWrapper.kt | 32 +++++++++++++++++++ example/ios/Podfile.lock | 8 ++--- ios/Wrappers/ConsentWrapper.swift | 31 ++++++++++++++++++ ios/XMTPModule.swift | 15 +++------ ios/XMTPReactNative.podspec | 2 +- 7 files changed, 77 insertions(+), 24 deletions(-) create mode 100644 android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/ConsentWrapper.kt create mode 100644 ios/Wrappers/ConsentWrapper.swift diff --git a/android/build.gradle b/android/build.gradle index 88caf0565..015f1b152 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -95,7 +95,7 @@ repositories { dependencies { implementation project(':expo-modules-core') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}" - implementation "org.xmtp:android:0.6.19" + implementation "org.xmtp:android:0.6.20" 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 fd743fd29..fe01b654f 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -9,6 +9,8 @@ import com.google.gson.JsonParser import com.google.protobuf.kotlin.toByteString import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition +import expo.modules.xmtpreactnativesdk.wrappers.ConsentWrapper +import expo.modules.xmtpreactnativesdk.wrappers.ConsentWrapper.Companion.consentStateToString import expo.modules.xmtpreactnativesdk.wrappers.ContentJson import expo.modules.xmtpreactnativesdk.wrappers.ConversationWrapper import expo.modules.xmtpreactnativesdk.wrappers.DecodedMessageWrapper @@ -557,20 +559,13 @@ class XMTPModule : Module() { AsyncFunction("consentList") { clientAddress: String -> val client = clients[clientAddress] ?: throw XMTPException("No client") - client.contacts.consentList.entries.map { "${it.key}: ${consentStateToString(it.value)}" } + client.contacts.consentList.entries.map { ConsentWrapper.encode(it.value) } } } // // Helpers // - private fun consentStateToString(state: ConsentState): String { - return when (state) { - ConsentState.ALLOWED -> "allowed" - ConsentState.DENIED -> "denied" - ConsentState.UNKNOWN -> "unknown" - } - } private fun findConversation( clientAddress: String, diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/ConsentWrapper.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/ConsentWrapper.kt new file mode 100644 index 000000000..c80eef381 --- /dev/null +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/ConsentWrapper.kt @@ -0,0 +1,32 @@ +package expo.modules.xmtpreactnativesdk.wrappers + +import com.google.gson.GsonBuilder +import org.xmtp.android.library.ConsentListEntry +import org.xmtp.android.library.ConsentState +import org.xmtp.android.library.codecs.description +import org.xmtp.android.library.messages.DecryptedMessage + +class ConsentWrapper { + + companion object { + fun encode(model: ConsentListEntry): String { + val gson = GsonBuilder().create() + val message = encodeMap(model) + return gson.toJson(message) + } + + fun encodeMap(model: ConsentListEntry): Map = mapOf( + "type" to model.entryType.name.lowercase(), + "value" to model.value.lowercase(), + "state" to consentStateToString(model.consentType), + ) + + fun consentStateToString(state: ConsentState): String { + return when (state) { + ConsentState.ALLOWED -> "allowed" + ConsentState.DENIED -> "denied" + ConsentState.UNKNOWN -> "unknown" + } + } + } +} diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 428a983b3..784ff3564 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -411,7 +411,7 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (0.7.1-alpha0): + - XMTP (0.7.2-alpha0): - Connect-Swift (= 0.3.0) - GzipSwift - web3.swift @@ -419,7 +419,7 @@ PODS: - XMTPReactNative (0.1.0): - ExpoModulesCore - MessagePacker - - XMTP (= 0.7.1-alpha0) + - XMTP (= 0.7.2-alpha0) - XMTPRust (0.3.7-beta0) - Yoga (1.14.0) @@ -668,8 +668,8 @@ SPEC CHECKSUMS: secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: b02b5075dcf60c9f5f403000b3b0c202a11b6ae1 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: 36069f94fc0485a0e6fe7a9fd5debc7ba816002c - XMTPReactNative: 40f71f1405e0ba3fcd4311382a236e7748ce1301 + XMTP: 4930b80dc99a6a8ebcf1f292a162c1f316f78c50 + XMTPReactNative: 68c723488857950d10fc8ee969de0baae8f9b2ca XMTPRust: 8848a2ba761b2c961d666632f2ad27d1082faa93 Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556 diff --git a/ios/Wrappers/ConsentWrapper.swift b/ios/Wrappers/ConsentWrapper.swift new file mode 100644 index 000000000..b1b273c14 --- /dev/null +++ b/ios/Wrappers/ConsentWrapper.swift @@ -0,0 +1,31 @@ +import Foundation +import XMTP + +// Wrapper around XMTP.Conversation to allow passing these objects back into react native. +struct ConsentWrapper { + static func encodeToObj(_ entry: XMTP.ConsentListEntry) throws -> [String: Any] { + return [ + "type": entry.entryType, + "value": entry.value, + "state": consentStateToString(state: entry.consentType), + ] + } + + static func encode(_ entry: XMTP.ConsentListEntry) throws -> String { + let obj = try encodeToObj(entry) + let data = try JSONSerialization.data(withJSONObject: obj) + guard let result = String(data: data, encoding: .utf8) else { + throw WrapperError.encodeError("could not encode consent") + } + return result + } + + static func consentStateToString(state: ConsentState) -> String { + switch state { + case .allowed: return "allowed" + case .denied: return "denied" + case .unknown: return "unknown" + } + } + +} diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 5a37197a2..280e1201f 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -512,7 +512,7 @@ public class XMTPModule: Module { guard let conversation = try await findConversation(clientAddress: clientAddress, topic: conversationTopic) else { throw Error.conversationNotFound(conversationTopic) } - return consentStateToString(state: await conversation.consentState()) + return ConsentWrapper.consentStateToString(state: await conversation.consentState()) } AsyncFunction("consentList") { (clientAddress: String) -> [String] in @@ -520,7 +520,10 @@ public class XMTPModule: Module { throw Error.noClient } let entries = await client.contacts.consentList.entries - return entries.map { "\($0.key): \(consentStateToString(state: $0.value))" } + + return try entries.compactMap { entry in + try ConsentWrapper.encode(entry.value) + } } } @@ -528,14 +531,6 @@ public class XMTPModule: Module { // Helpers // - func consentStateToString(state: ConsentState) -> String { - switch state { - case .allowed: return "allowed" - case .denied: return "denied" - case .unknown: return "unknown" - } - } - func createClientConfig(env: String, appVersion: String?) -> XMTP.ClientOptions { // Ensure that all codecs have been registered. switch env { diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index ea844efb4..24024418e 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -25,5 +25,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.7.1-alpha0" + s.dependency "XMTP", "= 0.7.2-alpha0" end From c25bd2360e7c093c601e2b7ab181a1d5ef350698 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 7 Dec 2023 16:58:39 -0800 Subject: [PATCH 7/9] feat: update all consent entries to be returned --- .../modules/xmtpreactnativesdk/XMTPModule.kt | 3 ++- example/src/tests.ts | 8 +++---- ios/XMTPModule.swift | 8 +++++-- src/index.ts | 22 ++++++++++------- src/lib/ConsentListEntry.ts | 24 +++++++++++++++++++ src/lib/Contacts.ts | 7 +++--- 6 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 src/lib/ConsentListEntry.ts diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index fe01b654f..b9bf5da58 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -548,7 +548,8 @@ class XMTPModule : Module() { AsyncFunction("refreshConsentList") { clientAddress: String -> val client = clients[clientAddress] ?: throw XMTPException("No client") - client.contacts.refreshConsentList() + val consentList = client.contacts.refreshConsentList() + consentList.entries.map { ConsentWrapper.encode(it.value) } } AsyncFunction("conversationConsentState") { clientAddress: String, conversationTopic: String -> diff --git a/example/src/tests.ts b/example/src/tests.ts index 5995bf5f5..4d2c97122 100644 --- a/example/src/tests.ts +++ b/example/src/tests.ts @@ -675,13 +675,11 @@ test('canManagePreferences', async () => { const boConsentList = await bo.contacts.consentList() await delayToPropogate() - if (boConsentList.size !== 1) { - throw new Error(`consent list for bo should 1 not ${boConsentList.size}`) + if (boConsentList.length !== 1) { + throw new Error(`consent list for bo should 1 not ${boConsentList.length}`) } - const boConsentListState = boConsentList.get( - `address-${alixConversation.peerAddress.toLowerCase()}` - ) + const boConsentListState = boConsentList[0].permissionType if (boConsentListState !== 'denied') { throw new Error( diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 280e1201f..7a086f37d 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -501,11 +501,15 @@ public class XMTPModule: Module { try await client.contacts.allow(addresses: addresses) } - AsyncFunction("refreshConsentList") { (clientAddress: String) in + AsyncFunction("refreshConsentList") { (clientAddress: String) -> [String] in guard let client = await clientsManager.getClient(key: clientAddress) else { throw Error.noClient } - try await client.contacts.refreshConsentList() + let consentList = try await client.contacts.refreshConsentList() + + return try consentList.entries.compactMap { entry in + try ConsentWrapper.encode(entry.value) + } } AsyncFunction("conversationConsentState") { (clientAddress: String, conversationTopic: String) -> String in diff --git a/src/index.ts b/src/index.ts index a98507fa4..477126086 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import { EventEmitter, NativeModulesProxy } from 'expo-modules-core' import { Client } from '.' import { ConversationContext } from './XMTP.types' import XMTPModule from './XMTPModule' +import { ConsentListEntry } from './lib/ConsentListEntry' import { DecryptedLocalAttachment, EncryptedLocalAttachment, @@ -349,22 +350,24 @@ export function allowContacts(clientAddress: string, addresses: string[]) { XMTPModule.allowContacts(clientAddress, addresses) } -export function refreshConsentList(clientAddress: string) { - XMTPModule.refreshConsentList(clientAddress) +export async function refreshConsentList( + clientAddress: string +): Promise { + const consentList = await XMTPModule.refreshConsentList(clientAddress) + + return consentList.map((json: string) => { + return ConsentListEntry.from(json) + }) } export async function consentList( clientAddress: string -): Promise> { +): Promise { const consentList = await XMTPModule.consentList(clientAddress) - const result = new Map() - consentList.forEach((item) => { - const [key, value] = item.split(':').map((str: string) => str.trim()) - result.set(key.toLowerCase(), value) + return consentList.map((json: string) => { + return ConsentListEntry.from(json) }) - - return result } export const emitter = new EventEmitter(XMTPModule ?? NativeModulesProxy.XMTP) @@ -376,3 +379,4 @@ export * from './XMTP.types' export { Query } from './lib/Query' export { XMTPPush } from './lib/XMTPPush' export { DecodedMessage } +export { ConsentListEntry } diff --git a/src/lib/ConsentListEntry.ts b/src/lib/ConsentListEntry.ts new file mode 100644 index 000000000..9adb1392c --- /dev/null +++ b/src/lib/ConsentListEntry.ts @@ -0,0 +1,24 @@ +export type ConsentState = 'allowed' | 'denied' | 'unknown' + +export type ConsentListEntryType = 'address' + +export class ConsentListEntry { + value: string + entryType: ConsentListEntryType + permissionType: ConsentState + + constructor( + value: string, + entryType: ConsentListEntryType, + permissionType: ConsentState + ) { + this.value = value + this.entryType = entryType + this.permissionType = permissionType + } + + static from(json: string): ConsentListEntry { + const entry = JSON.parse(json) + return new ConsentListEntry(entry.value, entry.type, entry.state) + } +} diff --git a/src/lib/Contacts.ts b/src/lib/Contacts.ts index c4e809849..19c4c302f 100644 --- a/src/lib/Contacts.ts +++ b/src/lib/Contacts.ts @@ -1,5 +1,6 @@ import { Client } from './Client' import * as XMTPModule from '../index' +import { ConsentListEntry } from './ConsentListEntry' export default class Contacts { client: Client @@ -24,11 +25,11 @@ export default class Contacts { XMTPModule.allowContacts(this.client.address, addresses) } - refreshConsentList() { - XMTPModule.refreshConsentList(this.client.address) + async refreshConsentList(): Promise { + return await XMTPModule.refreshConsentList(this.client.address) } - async consentList(): Promise> { + async consentList(): Promise { return await XMTPModule.consentList(this.client.address) } } From 8242b1b8d49f69d84feefedc924d3addb838efbf Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 7 Dec 2023 17:51:05 -0800 Subject: [PATCH 8/9] fix up the tests and make sure they all pass --- ios/Wrappers/ConsentWrapper.swift | 2 +- src/index.ts | 4 ++-- src/lib/Contacts.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/Wrappers/ConsentWrapper.swift b/ios/Wrappers/ConsentWrapper.swift index b1b273c14..8f083a14f 100644 --- a/ios/Wrappers/ConsentWrapper.swift +++ b/ios/Wrappers/ConsentWrapper.swift @@ -5,7 +5,7 @@ import XMTP struct ConsentWrapper { static func encodeToObj(_ entry: XMTP.ConsentListEntry) throws -> [String: Any] { return [ - "type": entry.entryType, + "type": entry.entryType.rawValue, "value": entry.value, "state": consentStateToString(state: entry.consentType), ] diff --git a/src/index.ts b/src/index.ts index 477126086..d924bf230 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,7 @@ import { EventEmitter, NativeModulesProxy } from 'expo-modules-core' import { Client } from '.' import { ConversationContext } from './XMTP.types' import XMTPModule from './XMTPModule' -import { ConsentListEntry } from './lib/ConsentListEntry' +import { ConsentListEntry, ConsentState } from './lib/ConsentListEntry' import { DecryptedLocalAttachment, EncryptedLocalAttachment, @@ -321,7 +321,7 @@ export async function decodeMessage( export async function conversationConsentState( clientAddress: string, conversationTopic: string -): Promise<'allowed' | 'denied' | 'unknown'> { +): Promise { return await XMTPModule.conversationConsentState( clientAddress, conversationTopic diff --git a/src/lib/Contacts.ts b/src/lib/Contacts.ts index 19c4c302f..4738fc6d7 100644 --- a/src/lib/Contacts.ts +++ b/src/lib/Contacts.ts @@ -1,6 +1,6 @@ import { Client } from './Client' -import * as XMTPModule from '../index' import { ConsentListEntry } from './ConsentListEntry' +import * as XMTPModule from '../index' export default class Contacts { client: Client From 731699882ab83151fa9a763b35d1f942fad09510 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 7 Dec 2023 17:57:02 -0800 Subject: [PATCH 9/9] remove incorrect comment --- ios/Wrappers/ConsentWrapper.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/ios/Wrappers/ConsentWrapper.swift b/ios/Wrappers/ConsentWrapper.swift index 8f083a14f..c683925a4 100644 --- a/ios/Wrappers/ConsentWrapper.swift +++ b/ios/Wrappers/ConsentWrapper.swift @@ -1,7 +1,6 @@ import Foundation import XMTP -// Wrapper around XMTP.Conversation to allow passing these objects back into react native. struct ConsentWrapper { static func encodeToObj(_ entry: XMTP.ConsentListEntry) throws -> [String: Any] { return [