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

feat: Notifications History with changed ids #1288

Merged
merged 13 commits into from
Jan 29, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ object Core {
data class Notify(
val title: String,
val body: String,
val icon: String?,
val url: String?,
val type: String,
val topic: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
moshi.adapter(CoreNotifyParams.UpdateParams::class.java, emptySet(), "result")
private val chatNotifyResponseAuthParamsAdapter: JsonAdapter<ChatNotifyResponseAuthParams.ResponseAuth> =
moshi.adapter(ChatNotifyResponseAuthParams.ResponseAuth::class.java, emptySet(), "result")
private val chatNotifyAuthParamsAdapter: JsonAdapter<ChatNotifyResponseAuthParams.Auth> =
moshi.adapter(ChatNotifyResponseAuthParams.Auth::class.java, emptySet(), "result")

@Volatile
private var constructorRef: Constructor<JsonRpcResponse.JsonRpcResult>? = null
Expand Down Expand Up @@ -71,6 +73,10 @@
chatNotifyResponseAuthParamsAdapter.fromJson(reader)
}

runCatching { chatNotifyAuthParamsAdapter.fromJson(reader.peekJson()) }.isSuccess -> {
chatNotifyAuthParamsAdapter.fromJson(reader)
}

else -> anyAdapter.fromJson(reader)
}
}
Expand Down Expand Up @@ -102,7 +108,7 @@
).also { [email protected] = it }
return localConstructor.newInstance(
id ?: throw Util.missingProperty("id", "id", reader),
jsonrpc,

Check notice on line 111 in core/android/src/main/kotlin/com/walletconnect/android/internal/common/adapter/JsonRpcResultAdapter.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for Android

Constant conditions

Value of 'jsonrpc' is always null
result ?: throw Util.missingProperty("result", "result", reader),
mask0,
/* DefaultConstructorMarker */ null
Expand Down Expand Up @@ -146,6 +152,13 @@
}
}

(value_.result as? ChatNotifyResponseAuthParams.Auth) != null -> {
val notifyResponseParamsString = chatNotifyAuthParamsAdapter.toJson(value_.result)
writer.valueSink().use {
it.writeUtf8(notifyResponseParamsString)
}
}

(value_.result as? CoreNotifyParams.UpdateParams) != null -> {
val notifySubscribeUpdateParamsString = notifySubscribeUpdateParamsAdapter.toJson(value_.result)
writer.valueSink().use {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ class ExplorerRepository(
name = name,
description = description,
imageUrl = imageUrl?.toImageUrl(),
homepage = homepage,
homepage = homepage ?: "",
dappUrl = dappUrl,
isVerified = isVerified,
)
}
}

private fun NotificationTypeDTO.toNotificationType(): NotificationType = NotificationType(name = name, id = id, description = description)
private fun NotificationTypeDTO.toNotificationType(): NotificationType = NotificationType(name = name, id = id, description = description, imageUrl = imageUrl?.toImageUrl())


private fun ProjectListingDTO.toProjectListing(): ProjectListing {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ data class NotificationType(
val name: String,
val id: String,
val description: String,
val imageUrl: ImageUrl?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ data class NotifyConfigDTO(
@JsonClass(generateAdapter = true)
data class NotifyConfigDataDTO(
@Json(name = "name") val name: String,
@Json(name = "homepage") val homepage: String,
@Json(name = "homepage") val homepage: String?,
@Json(name = "description") val description: String,
@Json(name = "dapp_url") val dappUrl: String,
@Json(name = "image_url") val imageUrl: ImageUrlDTO?,
Expand All @@ -31,4 +31,8 @@ data class NotificationTypeDTO(
val id: String,
@Json(name = "description")
val description: String,
)
@Json(name = "imageUrls")
val imageUrl: ImageUrlDTO?,


)
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package com.walletconnect.android.internal.common.explorer.domain.usecase
import com.walletconnect.android.internal.common.explorer.ExplorerRepository
import com.walletconnect.android.internal.common.explorer.data.model.NotifyConfig

class GetNotifyConfigUseCase(
private val explorerRepository: ExplorerRepository,
) {
class GetNotifyConfigUseCase(private val explorerRepository: ExplorerRepository) {
suspend operator fun invoke(appDomain: String): Result<NotifyConfig> = runCatching { explorerRepository.getNotifyConfig(appDomain) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,8 @@ enum class Tags(val id: Int) {
NOTIFY_SUBSCRIPTIONS_CHANGED(4012),
NOTIFY_SUBSCRIPTIONS_CHANGED_RESPONSE(4013),

NOTIFY_GET_NOTIFICATIONS(4014),
NOTIFY_GET_NOTIFICATIONS_RESPONSE(4015),

//todo: Discuss: Should Tags be in specific SDKs?
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ interface ChatNotifyResponseAuthParams {
@Json(name = "responseAuth")
val responseAuth: String,
) : ClientParams

@JsonClass(generateAdapter = true)
data class Auth(
@Json(name = "auth")
val auth: String,
) : ClientParams
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,10 @@ sealed interface CoreNotifyParams : ClientParams {
@Json(name = "subscriptionsChangedAuth")
val subscriptionsChangedAuth: String,
) : CoreNotifyParams

@JsonClass(generateAdapter = true)
data class GetNotificationsParams(
@Json(name = "auth")
val auth: String,
) : CoreNotifyParams
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.walletconnect.android.Core
import com.walletconnect.android.CoreInterface
import com.walletconnect.android.cacao.SignatureInterface
import com.walletconnect.foundation.common.model.PrivateKey
import kotlin.time.Duration

object Notify {

Expand All @@ -22,14 +23,13 @@ object Notify {
data class Decrypted(
override val title: String,
override val body: String,
val icon: String?,
val url: String?,
val type: String,
val topic: String,
) : Notification()
}

data class NotificationRecord(val id: String, val topic: String, val publishedAt: Long, val message: Notification, val metadata: Core.Model.AppMetaData) : Model()
data class NotificationRecord(val id: String, val topic: String, val sentAt: Long, val notification: Notification, val metadata: Core.Model.AppMetaData) : Model()

data class Subscription(
val topic: String,
Expand Down Expand Up @@ -58,20 +58,19 @@ object Notify {
) : Model()
}

data class NotificationType(val id: String, val name: String, val description: String) : Model()
data class NotificationType(val id: String, val name: String, val description: String, val iconUrl: String?) : Model()

data class Error(val throwable: Throwable) : Model()

data class CacaoPayloadWithIdentityPrivateKey(val payload: Cacao.Payload, val key: PrivateKey) : Model()
}

sealed class Event {
data class Notification (val notification: Model.NotificationRecord) : Event()
data class Notification(val notification: Model.NotificationRecord) : Event()

data class SubscriptionsChanged(val subscriptions: List<Model.Subscription>) : Event()
}

// todo: move to model
sealed interface Result {
sealed interface Subscribe {
data class Success(val subscription: Model.Subscription) : Subscribe
Expand All @@ -87,21 +86,28 @@ object Notify {
data class Success(val topic: String) : DeleteSubscription
data class Error(val error: Model.Error) : DeleteSubscription
}

sealed interface GetNotificationHistory {
data class Success(val notifications: List<Model.NotificationRecord>, val hasMore: Boolean) : GetNotificationHistory
data class Error(val error: Model.Error) : GetNotificationHistory
}
}

sealed class Params {

class Init(val core: CoreInterface) : Params()

data class Subscribe(val appDomain: Uri, val account: String) : Params()
data class Subscribe(val appDomain: Uri, val account: String, val timeout: Duration? = null) : Params()

data class UpdateSubscription(val topic: String, val scope: List<String>, val timeout: Duration? = null) : Params()

data class UpdateSubscription(val topic: String, val scope: List<String>) : Params()
data class GetNotificationTypes(val appDomain: String, val timeout: Duration? = null) : Params()

data class GetNotificationTypes(val appDomain: String) : Params()
data class GetNotificationHistory(val topic: String, val limit: Int? = null, val startingAfter: String? = null, val timeout: Duration? = null) : Params()

data class GetNotificationHistory(val topic: String) : Params()
data class DeleteSubscription(val topic: String, val timeout: Duration? = null) : Params()

data class DeleteSubscription(val topic: String) : Params()
data class GetActiveSubscriptions(val account: String, val timeout: Duration? = null) : Params()

data class DecryptNotification(val topic: String, val encryptedMessage: String) : Params()

Expand All @@ -111,6 +117,6 @@ object Notify {

data class IsRegistered(val account: String, val domain: String, val allApps: Boolean = true) : Params()

data class Unregister (val account: String) : Params()
data class Unregister(val account: String) : Params()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.walletconnect.notify.client

interface NotifyInterface {
interface Delegate {
//todo: migration guide and remove all deprecations
fun onNotifyNotification(notifyNotification: Notify.Event.Notification)

fun onError(error: Notify.Model.Error)
Expand Down Expand Up @@ -42,13 +41,13 @@ interface NotifyInterface {
* Caution: This function is blocking and runs on the current thread.
* It is advised that this function be called from background operation
*/
fun getActiveSubscriptions(): Map<String, Notify.Model.Subscription>
fun getActiveSubscriptions(params: Notify.Params.GetActiveSubscriptions): Map<String, Notify.Model.Subscription>

/**
* Caution: This function is blocking and runs on the current thread.
* It is advised that this function be called from background operation
*/
fun getNotificationHistory(params: Notify.Params.GetNotificationHistory): Map<Long, Notify.Model.NotificationRecord>
fun getNotificationHistory(params: Notify.Params.GetNotificationHistory): Notify.Result.GetNotificationHistory


fun decryptNotification(params: Notify.Params.DecryptNotification, onSuccess: (Notify.Model.Notification.Decrypted) -> Unit, onError: (Notify.Model.Error) -> Unit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.walletconnect.android.internal.common.di.DatabaseConfig
import com.walletconnect.android.internal.common.model.SDKError
import com.walletconnect.android.internal.common.scope
import com.walletconnect.android.internal.common.wcKoinApp
import com.walletconnect.notify.common.model.NotifyRecord
import com.walletconnect.notify.common.model.Notification
import com.walletconnect.notify.common.model.SubscriptionChanged
import com.walletconnect.notify.common.model.toClient
import com.walletconnect.notify.common.model.toCommon
Expand Down Expand Up @@ -46,7 +46,7 @@ class NotifyProtocol(private val koinApp: KoinApplication = wcKoinApp) : NotifyI

notifyEngine.engineEvent.onEach { event ->
when (event) {
is NotifyRecord -> delegate.onNotifyNotification(Notify.Event.Notification(event.toClient()))
is Notification -> delegate.onNotifyNotification(Notify.Event.Notification(event.toClient()))
is SubscriptionChanged -> delegate.onSubscriptionsChanged(event.toClient())
is SDKError -> delegate.onError(event.toClient())
}
Expand All @@ -58,7 +58,7 @@ class NotifyProtocol(private val koinApp: KoinApplication = wcKoinApp) : NotifyI

return runBlocking {
try {
notifyEngine.subscribeToDapp(params.appDomain, params.account).toClient()
notifyEngine.subscribeToDapp(params.appDomain, params.account, params.timeout).toClient()
} catch (e: Exception) {
Notify.Result.Subscribe.Error(Notify.Model.Error(e))
}
Expand All @@ -70,7 +70,7 @@ class NotifyProtocol(private val koinApp: KoinApplication = wcKoinApp) : NotifyI

return runBlocking {
try {
notifyEngine.update(params.topic, params.scope).toClient()
notifyEngine.update(params.topic, params.scope, params.timeout).toClient()
} catch (e: Exception) {
Notify.Result.UpdateSubscription.Error(Notify.Model.Error(e))
}
Expand All @@ -81,35 +81,37 @@ class NotifyProtocol(private val koinApp: KoinApplication = wcKoinApp) : NotifyI
checkEngineInitialization()

return runBlocking {
notifyEngine.getNotificationTypes(params.appDomain).mapValues { (_, notificationType) ->
notificationType.toClient()
}
notifyEngine.getNotificationTypes(params.appDomain, params.timeout).mapValues { (_, notificationType) -> notificationType.toClient() }
}
}


override fun getActiveSubscriptions(): Map<String, Notify.Model.Subscription> {
override fun getActiveSubscriptions(params: Notify.Params.GetActiveSubscriptions): Map<String, Notify.Model.Subscription> {
checkEngineInitialization()

return runBlocking {
notifyEngine.getListOfActiveSubscriptions().mapValues { (_, subscriptionWMetadata) ->
subscriptionWMetadata.toClient()
}
notifyEngine.getActiveSubscriptions(params.account, params.timeout).mapValues { (_, subscriptionWMetadata) -> subscriptionWMetadata.toClient() }
}
}

override fun getNotificationHistory(params: Notify.Params.GetNotificationHistory): Map<Long, Notify.Model.NotificationRecord> {
override fun getNotificationHistory(params: Notify.Params.GetNotificationHistory): Notify.Result.GetNotificationHistory {
checkEngineInitialization()

return runBlocking { notifyEngine.getListOfNotifications(params.topic).mapValues { (_, notifyRecord) -> notifyRecord.toClient() } }
return runBlocking {
try {
notifyEngine.getNotificationHistory(params.topic, params.limit, params.startingAfter, params.timeout).toClient()
} catch (e: Exception) {
Notify.Result.GetNotificationHistory.Error(Notify.Model.Error(e))
}
}
}

override fun deleteSubscription(params: Notify.Params.DeleteSubscription): Notify.Result.DeleteSubscription {
checkEngineInitialization()

return runBlocking {
try {
notifyEngine.deleteSubscription(params.topic).toClient()
notifyEngine.deleteSubscription(params.topic, params.timeout).toClient()
} catch (e: Exception) {
Notify.Result.DeleteSubscription.Error(Notify.Model.Error(e))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ internal object JsonRpcMethod {

@get:JvmSynthetic
const val WC_NOTIFY_SUBSCRIPTIONS_CHANGED: String = "wc_notifySubscriptionsChanged"

@get:JvmSynthetic
const val WC_NOTIFY_GET_NOTIFICATIONS: String = "wc_notifyGetNotifications"
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package com.walletconnect.notify.common

import com.walletconnect.android.internal.common.model.Expiry
import com.walletconnect.android.internal.utils.monthInSeconds
import java.nio.charset.Charset
import java.util.concurrent.TimeUnit

@JvmSynthetic
Expand All @@ -13,4 +14,11 @@ internal fun calcExpiry(): Expiry {
val expiryTimeSeconds = currentTimeSeconds + monthInSeconds

return Expiry(expiryTimeSeconds)
}
}


@JvmSynthetic
internal fun convertToUTF8(input: String): String {
val bytes = input.toByteArray(Charset.forName("ISO-8859-1"))
return String(bytes, Charset.forName("UTF-8"))
}
Loading
Loading