Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move React Native to latest User Preferences #169

Merged
merged 9 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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.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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -546,23 +548,26 @@ 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 ->
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 ->
alexrisch marked this conversation as resolved.
Show resolved Hide resolved
val client = clients[clientAddress] ?: throw XMTPException("No client")
client.contacts.consentList.entries.map { ConsentWrapper.encode(it.value) }
}
}

//
// Helpers
//

private fun findConversation(
clientAddress: String,
topic: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, Any> = 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"
}
}
}
}
14 changes: 7 additions & 7 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -411,16 +411,16 @@ PODS:
- GenericJSON (~> 2.0)
- Logging (~> 1.0.0)
- secp256k1.swift (~> 0.1)
- XMTP (0.6.14-alpha0):
- XMTP (0.7.2-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.2-alpha0)
- XMTPRust (0.3.7-beta0)
- Yoga (1.14.0)

DEPENDENCIES:
Expand Down Expand Up @@ -668,9 +668,9 @@ SPEC CHECKSUMS:
secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634
SwiftProtobuf: b02b5075dcf60c9f5f403000b3b0c202a11b6ae1
web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959
XMTP: 5314a5151dbfad2e24bb5910e679052916a9faff
XMTPReactNative: 5e393ab43d402bae404f675245cfc66a078a33ff
XMTPRust: 3c958736a4f4ee798e425b5644551f1c948da4b0
XMTP: 4930b80dc99a6a8ebcf1f292a162c1f316f78c50
XMTPReactNative: 68c723488857950d10fc8ee969de0baae8f9b2ca
XMTPRust: 8848a2ba761b2c961d666632f2ad27d1082faa93
Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556

PODFILE CHECKSUM: 522d88edc2d5fac4825e60a121c24abc18983367
Expand Down
15 changes: 15 additions & 0 deletions example/src/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,21 @@ test('canManagePreferences', async () => {
)
}

const boConsentList = await bo.contacts.consentList()
await delayToPropogate()

if (boConsentList.length !== 1) {
throw new Error(`consent list for bo should 1 not ${boConsentList.length}`)
}

const boConsentListState = boConsentList[0].permissionType

if (boConsentListState !== 'denied') {
throw new Error(
`conversations denied by bo should be denied in consent list not ${boConsentListState}`
)
}

return true
})

Expand Down
30 changes: 30 additions & 0 deletions ios/Wrappers/ConsentWrapper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Foundation
import XMTP

struct ConsentWrapper {
static func encodeToObj(_ entry: XMTP.ConsentListEntry) throws -> [String: Any] {
return [
"type": entry.entryType.rawValue,
"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"
}
}

}
27 changes: 19 additions & 8 deletions ios/XMTPModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -501,30 +501,41 @@ 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
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 ConsentWrapper.consentStateToString(state: await conversation.consentState())
}

AsyncFunction("consentList") { (clientAddress: String) -> [String] in
alexrisch marked this conversation as resolved.
Show resolved Hide resolved
guard let client = await clientsManager.getClient(key: clientAddress) else {
throw Error.noClient
}
let entries = await client.contacts.consentList.entries

return try entries.compactMap { entry in
try ConsentWrapper.encode(entry.value)
}
}
}

//
// Helpers
//

func createClientConfig(env: String, appVersion: String?) -> XMTP.ClientOptions {
func createClientConfig(env: String, appVersion: String?) -> XMTP.ClientOptions {
// Ensure that all codecs have been registered.
switch env {
case "local":
Expand Down
2 changes: 1 addition & 1 deletion ios/XMTPReactNative.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -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.2-alpha0"
end
24 changes: 21 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, ConsentState } from './lib/ConsentListEntry'
import {
DecryptedLocalAttachment,
EncryptedLocalAttachment,
Expand Down Expand Up @@ -320,7 +321,7 @@ export async function decodeMessage(
export async function conversationConsentState(
clientAddress: string,
conversationTopic: string
): Promise<'allowed' | 'denied' | 'unknown'> {
): Promise<ConsentState> {
return await XMTPModule.conversationConsentState(
clientAddress,
conversationTopic
Expand Down Expand Up @@ -349,8 +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<ConsentListEntry[]> {
const consentList = await XMTPModule.refreshConsentList(clientAddress)

return consentList.map((json: string) => {
return ConsentListEntry.from(json)
})
}

export async function consentList(
clientAddress: string
): Promise<ConsentListEntry[]> {
const consentList = await XMTPModule.consentList(clientAddress)

return consentList.map((json: string) => {
return ConsentListEntry.from(json)
})
}

export const emitter = new EventEmitter(XMTPModule ?? NativeModulesProxy.XMTP)
Expand All @@ -362,3 +379,4 @@ export * from './XMTP.types'
export { Query } from './lib/Query'
export { XMTPPush } from './lib/XMTPPush'
export { DecodedMessage }
export { ConsentListEntry }
24 changes: 24 additions & 0 deletions src/lib/ConsentListEntry.ts
Original file line number Diff line number Diff line change
@@ -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)
}
}
15 changes: 9 additions & 6 deletions src/lib/Contacts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Client } from './Client'
import { ConsentListEntry } from './ConsentListEntry'
import * as XMTPModule from '../index'

export default class Contacts {
Expand All @@ -9,13 +10,11 @@ export default class Contacts {
}

async isAllowed(address: string): Promise<boolean> {
const result = await XMTPModule.isAllowed(this.client.address, address)
return result
return await XMTPModule.isAllowed(this.client.address, address)
}

async isDenied(address: string): Promise<boolean> {
const result = await XMTPModule.isDenied(this.client.address, address)
return result
return await XMTPModule.isDenied(this.client.address, address)
}

deny(addresses: string[]) {
Expand All @@ -26,7 +25,11 @@ export default class Contacts {
XMTPModule.allowContacts(this.client.address, addresses)
}

refreshConsentList() {
XMTPModule.refreshConsentList(this.client.address)
async refreshConsentList(): Promise<ConsentListEntry[]> {
return await XMTPModule.refreshConsentList(this.client.address)
}

async consentList(): Promise<ConsentListEntry[]> {
return await XMTPModule.consentList(this.client.address)
}
}
Loading