From aa99cc0b9a9317883729ad73aabcbd107fed927d Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 22 Feb 2024 12:31:23 +0100 Subject: [PATCH 1/5] Fix handling errors while sending session approve --- .../json_rpc/domain/JsonRpcInteractor.kt | 40 +++++++++++-------- .../pairing/engine/domain/PairingEngine.kt | 2 +- .../use_case/calls/ApproveSessionUseCase.kt | 6 +-- .../scan_uri/ScanUriRoute.kt | 19 +++++++-- .../UpdateSubscriptionRoute.kt | 3 +- .../ConnectionDetailsRoute.kt | 22 +++++----- .../composable_routes/inbox/InboxRoute.kt | 4 +- .../NotificiationsScreenRoute.kt | 18 ++++++++- .../session_proposal/SessionProposalRoute.kt | 20 +++++----- .../session_request/SessionRequestRoute.kt | 19 ++++----- .../wallet/ui/routes/host/WalletSampleHost.kt | 8 ++-- 11 files changed, 98 insertions(+), 63 deletions(-) diff --git a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/json_rpc/domain/JsonRpcInteractor.kt b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/json_rpc/domain/JsonRpcInteractor.kt index e74f706ee8..d4c46bc643 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/json_rpc/domain/JsonRpcInteractor.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/json_rpc/domain/JsonRpcInteractor.kt @@ -94,15 +94,23 @@ internal class JsonRpcInteractor( return onFailure(e) } - if (jsonRpcHistory.setRequest(payload.id, topic, payload.method, requestJson)) { - val encryptedRequest = chaChaPolyCodec.encrypt(topic, requestJson, envelopeType, participants) - - relay.publish(topic.value, encryptedRequest, params.toRelay()) { result -> - result.fold( - onSuccess = { onSuccess() }, - onFailure = { error -> onFailure(error) } - ) + try { + if (jsonRpcHistory.setRequest(payload.id, topic, payload.method, requestJson)) { + val encryptedRequest = chaChaPolyCodec.encrypt(topic, requestJson, envelopeType, participants) + + relay.publish(topic.value, encryptedRequest, params.toRelay()) { result -> + result.fold( + onSuccess = { onSuccess() }, + onFailure = { error -> + logger.error("JsonRpcInteractor: Cannot send the request, error: $error") + onFailure(error) + } + ) + } } + } catch (e: Exception) { + logger.error("JsonRpcInteractor: Cannot send the request, exception: $e") + return onFailure(e) } } @@ -131,10 +139,14 @@ internal class JsonRpcInteractor( jsonRpcHistory.updateRequestWithResponse(response.id, responseJson) onSuccess() }, - onFailure = { error -> onFailure(error) } + onFailure = { error -> + logger.error("JsonRpcInteractor: Cannot send the response, error: $error") + onFailure(error) + } ) } } catch (e: Exception) { + logger.error("JsonRpcInteractor: Cannot send the response, exception: $e") return onFailure(e) } } @@ -151,10 +163,7 @@ internal class JsonRpcInteractor( val result = JsonRpcResponse.JsonRpcResult(id = request.id, result = clientParams) publishJsonRpcResponse(request.topic, irnParams, result, envelopeType = envelopeType, participants = participants, - onFailure = { error -> - logger.error("Cannot send the response, error: $error") - onFailure(error) - }, + onFailure = { error -> onFailure(error) }, onSuccess = { onSuccess() } ) } @@ -172,10 +181,7 @@ internal class JsonRpcInteractor( val result = JsonRpcResponse.JsonRpcResult(id = requestId, result = clientParams) publishJsonRpcResponse(topic, irnParams, result, envelopeType = envelopeType, participants = participants, - onFailure = { error -> - logger.error("Cannot send the response, error: $error") - onFailure(error) - }, + onFailure = { error -> onFailure(error) }, onSuccess = { onSuccess() } ) } diff --git a/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt b/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt index 7ec061b64e..77195b82b3 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt @@ -120,7 +120,7 @@ internal class PairingEngine( val inactivePairing = Pairing(pairingTopic, relay, symmetricKey, registeredMethods, Expiry(inactivePairing)) return inactivePairing.runCatching { - logger.log("Pairing created successfully") + logger.log("Creating Pairing") pairingRepository.insertPairing(this) metadataRepository.upsertPeerMetadata(this.topic, selfMetaData, AppMetaDataType.SELF) jsonRpcInteractor.subscribe(this.topic, diff --git a/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/use_case/calls/ApproveSessionUseCase.kt b/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/use_case/calls/ApproveSessionUseCase.kt index 1883d82b8e..e97026b3a5 100644 --- a/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/use_case/calls/ApproveSessionUseCase.kt +++ b/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/use_case/calls/ApproveSessionUseCase.kt @@ -121,7 +121,7 @@ internal class ApproveSessionUseCase( }, onFailure = { error -> logger.error("Subscribe to session topic failure: $error") - throw error + onFailure(error) }) logger.log("Sending session approve, topic: $sessionTopic") jsonRpcInteractor.respondWithParams(request, approvalParams, irnParams, @@ -129,8 +129,8 @@ internal class ApproveSessionUseCase( logger.log("Session approve sent successfully, topic: $sessionTopic") }, onFailure = { error -> - logger.log("Session approve failure, topic: $sessionTopic") - throw error + logger.error("Session approve failure, topic: $sessionTopic: $error") + onFailure(error) }) sessionSettle(request.id, proposal, sessionTopic, request.topic) diff --git a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/bottomsheet_routes/scan_uri/ScanUriRoute.kt b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/bottomsheet_routes/scan_uri/ScanUriRoute.kt index e5067ce4f7..c324c2bdf1 100644 --- a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/bottomsheet_routes/scan_uri/ScanUriRoute.kt +++ b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/bottomsheet_routes/scan_uri/ScanUriRoute.kt @@ -6,6 +6,7 @@ import android.Manifest import android.content.pm.PackageManager import android.util.Size import android.view.Surface.ROTATION_90 +import android.widget.Toast import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.camera.core.CameraSelector @@ -17,12 +18,23 @@ import androidx.camera.view.PreviewView import androidx.camera.view.PreviewView.StreamState import androidx.compose.foundation.Image import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.Text -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -44,7 +56,6 @@ import com.google.accompanist.navigation.material.BottomSheetNavigatorSheetState import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi import com.walletconnect.sample.wallet.R import com.walletconnect.sample.wallet.ui.common.generated.CloseButton -import com.walletconnect.sample.wallet.ui.routes.showSnackbar import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -101,7 +112,7 @@ fun ScanUriRoute(navController: NavController, sheetState: BottomSheetNavigatorS }, onQrCodeScanFailure = { //todo Add Snackbar with error as a route parameter callback: https://stackoverflow.com/questions/68909340/how-to-show-snackbar-with-a-button-onclick-in-jetpack-compose navController.popBackStack() - navController.showSnackbar("QR Scan failed") + Toast.makeText(context, "QR Scan failed", Toast.LENGTH_SHORT).show() }) ) try { diff --git a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/bottomsheet_routes/update_subscription/UpdateSubscriptionRoute.kt b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/bottomsheet_routes/update_subscription/UpdateSubscriptionRoute.kt index c1565ae523..1b66d9ef05 100644 --- a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/bottomsheet_routes/update_subscription/UpdateSubscriptionRoute.kt +++ b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/bottomsheet_routes/update_subscription/UpdateSubscriptionRoute.kt @@ -2,6 +2,7 @@ package com.walletconnect.sample.wallet.ui.routes.bottomsheet_routes.update_subscription +import android.widget.Toast import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -92,7 +93,7 @@ fun UpdateSubscriptionRoute(navController: NavController, sheetState: BottomShee } }, onFailure = { scope.launch { - navController.showSnackbar("Unable to update. Reason: ${it.message}") + Toast.makeText(navController.context, "Unable to update. Reason: ${it.message}", Toast.LENGTH_SHORT).show() } }) } diff --git a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/connection_details/ConnectionDetailsRoute.kt b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/connection_details/ConnectionDetailsRoute.kt index 39ad595eb7..b50c00e924 100644 --- a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/connection_details/ConnectionDetailsRoute.kt +++ b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/connection_details/ConnectionDetailsRoute.kt @@ -2,6 +2,7 @@ package com.walletconnect.sample.wallet.ui.routes.composable_routes.connection_details +import android.widget.Toast import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -35,6 +36,7 @@ import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight @@ -58,7 +60,6 @@ import com.walletconnect.sample.wallet.ui.common.getAllMethodsByChainId import com.walletconnect.sample.wallet.ui.routes.composable_routes.connections.ConnectionType import com.walletconnect.sample.wallet.ui.routes.composable_routes.connections.ConnectionUI import com.walletconnect.sample.wallet.ui.routes.composable_routes.connections.ConnectionsViewModel -import com.walletconnect.sample.wallet.ui.routes.showSnackbar import com.walletconnect.web3.wallet.client.Wallet import com.walletconnect.web3.wallet.client.Web3Wallet import kotlinx.coroutines.Dispatchers @@ -72,6 +73,7 @@ fun ConnectionDetailsRoute(navController: NavController, connectionId: Int?, con var isDeleteLoading by remember { mutableStateOf(false) } var isUpdateLoading by remember { mutableStateOf(false) } val composableScope = rememberCoroutineScope() + val context = LocalContext.current connectionUI?.let { uiConnection -> Column(modifier = Modifier.fillMaxWidth()) { @@ -94,14 +96,14 @@ fun ConnectionDetailsRoute(navController: NavController, connectionId: Int?, con onSuccess = { isEmitLoading = false composableScope.launch(Dispatchers.Main) { - navController.showSnackbar("Event emitted: ${it.event.name}") + Toast.makeText(context, "Event emitted: ${it.event.name}", Toast.LENGTH_SHORT).show() } }, onError = { error -> isEmitLoading = false Firebase.crashlytics.recordException(error.throwable) composableScope.launch(Dispatchers.Main) { - navController.showSnackbar("Event emit error. Error: ${error.throwable.message}") + Toast.makeText(context, "Event emit error. Error: ${error.throwable.message}", Toast.LENGTH_SHORT).show() } } ) @@ -109,7 +111,7 @@ fun ConnectionDetailsRoute(navController: NavController, connectionId: Int?, con isEmitLoading = false Firebase.crashlytics.recordException(e) composableScope.launch(Dispatchers.Main) { - navController.showSnackbar("Event emit error. Error: ${e.message}") + Toast.makeText(context, "Event emit error. Error: ${e.message}", Toast.LENGTH_SHORT).show() } } } @@ -136,14 +138,14 @@ fun ConnectionDetailsRoute(navController: NavController, connectionId: Int?, con isUpdateLoading = false connectionsViewModel.refreshConnections() composableScope.launch(Dispatchers.Main) { - navController.showSnackbar("Session updated") + Toast.makeText(context, "Session updated", Toast.LENGTH_SHORT).show() } }, onError = { error -> isUpdateLoading = false Firebase.crashlytics.recordException(error.throwable) composableScope.launch(Dispatchers.Main) { - navController.showSnackbar("Session update error. Error: ${error.throwable.message}") + Toast.makeText(context, "Session update error. Error: ${error.throwable.message}", Toast.LENGTH_SHORT).show() } } ) @@ -151,7 +153,7 @@ fun ConnectionDetailsRoute(navController: NavController, connectionId: Int?, con isUpdateLoading = false Firebase.crashlytics.recordException(e) composableScope.launch(Dispatchers.Main) { - navController.showSnackbar("Session update error. Error: ${e.message}") + Toast.makeText(context, "Session update error. Error: ${e.message}", Toast.LENGTH_SHORT).show() } } } @@ -173,7 +175,7 @@ fun ConnectionDetailsRoute(navController: NavController, connectionId: Int?, con connectionsViewModel.refreshConnections() composableScope.launch(Dispatchers.Main) { navController.popBackStack() - navController.showSnackbar("Session disconnected") + Toast.makeText(context, "Session disconnected", Toast.LENGTH_SHORT).show() } }, onError = { error -> @@ -181,7 +183,7 @@ fun ConnectionDetailsRoute(navController: NavController, connectionId: Int?, con isDeleteLoading = false connectionsViewModel.refreshConnections() composableScope.launch(Dispatchers.Main) { - navController.showSnackbar("Session disconnection error: ${error.throwable.message ?: "Unknown error please contact support"}") + Toast.makeText(context, "Session disconnection error: ${error.throwable.message ?: "Unknown error please contact support"}", Toast.LENGTH_SHORT).show() } }) } catch (e: Exception) { @@ -189,7 +191,7 @@ fun ConnectionDetailsRoute(navController: NavController, connectionId: Int?, con isDeleteLoading = false connectionsViewModel.refreshConnections() composableScope.launch(Dispatchers.Main) { - navController.showSnackbar("Session disconnection error: ${e.message ?: "Unknown error please contact support"}") + Toast.makeText(context, "Session disconnection error: ${e.message ?: "Unknown error please contact support"}", Toast.LENGTH_SHORT).show() } } } diff --git a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/inbox/InboxRoute.kt b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/inbox/InboxRoute.kt index db30c36bf7..444d5c4714 100644 --- a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/inbox/InboxRoute.kt +++ b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/inbox/InboxRoute.kt @@ -2,6 +2,7 @@ package com.walletconnect.sample.wallet.ui.routes.composable_routes.inbox +import android.widget.Toast import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight @@ -44,7 +45,6 @@ import com.walletconnect.sample.wallet.ui.common.subscriptions.ActiveSubscriptio import com.walletconnect.sample.wallet.ui.routes.composable_routes.inbox.discover.DiscoverTab import com.walletconnect.sample.wallet.ui.routes.composable_routes.inbox.discover.ExplorerApp import com.walletconnect.sample.wallet.ui.routes.composable_routes.inbox.subscriptions.SubscriptionsTab -import com.walletconnect.sample.wallet.ui.routes.showSnackbar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -163,7 +163,7 @@ fun TabViewWithPager( else -> error.localizedMessage } coroutineScope.launch { - navController.showSnackbar(message) + Toast.makeText(navController.context, message, Toast.LENGTH_SHORT).show() } } diff --git a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/notifications/NotificiationsScreenRoute.kt b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/notifications/NotificiationsScreenRoute.kt index a5617ae165..3297669ae7 100644 --- a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/notifications/NotificiationsScreenRoute.kt +++ b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/composable_routes/notifications/NotificiationsScreenRoute.kt @@ -2,11 +2,25 @@ package com.walletconnect.sample.wallet.ui.routes.composable_routes.notification import android.content.Intent import android.net.Uri +import android.widget.Toast import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape @@ -96,7 +110,7 @@ fun NotificationsScreenRoute(navController: NavHostController, subscriptionTopic scope.launch { val message = "Unable to unsubscribe. Reason: ${it.message}" Timber.e(message) - navController.showSnackbar(message) + Toast.makeText(navController.context, message, Toast.LENGTH_SHORT).show() } }) }, onRetry = viewModel::retryFetchingAllNotifications, onFetchMore = viewModel::fetchMore, hasMore = hasMore, scrollToTopCounter = scrollToTopCounter diff --git a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_proposal/SessionProposalRoute.kt b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_proposal/SessionProposalRoute.kt index 99e506d10e..6678484721 100644 --- a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_proposal/SessionProposalRoute.kt +++ b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_proposal/SessionProposalRoute.kt @@ -2,6 +2,7 @@ package com.walletconnect.sample.wallet.ui.routes.dialog_routes.session_proposal import android.content.Context import android.net.Uri +import android.widget.Toast import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -58,7 +59,6 @@ import com.walletconnect.sample.wallet.ui.common.peer.getDescriptionContent import com.walletconnect.sample.wallet.ui.common.peer.getDescriptionTitle import com.walletconnect.sample.wallet.ui.common.peer.getValidationIcon import com.walletconnect.sample.wallet.ui.routes.Route -import com.walletconnect.sample.wallet.ui.routes.showSnackbar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -151,7 +151,7 @@ private fun SessionProposalDialog( AccountAndNetwork(sessionProposalUI) { error -> coroutineScope.launch(Dispatchers.Main) { navController.popBackStack(route = Route.Connections.path, inclusive = false) - navController.showSnackbar(error) + Toast.makeText(context, error, Toast.LENGTH_SHORT).show() } } Spacer(modifier = Modifier.height(18.dp)) @@ -172,17 +172,17 @@ private fun SessionProposalDialog( context.sendResponseDeepLink(redirect.toUri()) } else { coroutineScope.launch(Dispatchers.Main) { - navController.showSnackbar("Go back to your browser") + Toast.makeText(context, "Go back to your browser", Toast.LENGTH_SHORT).show() } } }, onError = { error -> isCancelLoading = false - closeAndShowError(navController, error, coroutineScope) + closeAndShowError(navController, error, coroutineScope, context) }) } catch (e: Throwable) { - closeAndShowError(navController, e.message, coroutineScope) + closeAndShowError(navController, e.message, coroutineScope, context) } }, onConfirm = { @@ -200,16 +200,16 @@ private fun SessionProposalDialog( context.sendResponseDeepLink(redirect.toUri()) } else { coroutineScope.launch(Dispatchers.Main) { - navController.showSnackbar("Go back to your browser") + Toast.makeText(context, "Go back to your browser", Toast.LENGTH_SHORT).show() } } }, onError = { error -> isConfirmLoading = false - closeAndShowError(navController, error, coroutineScope) + closeAndShowError(navController, error, coroutineScope, context) }) } catch (e: Throwable) { - closeAndShowError(navController, e.message, coroutineScope) + closeAndShowError(navController, e.message, coroutineScope, context) } }, isLoadingConfirm = isConfirmLoading, @@ -219,10 +219,10 @@ private fun SessionProposalDialog( } } -private fun closeAndShowError(navController: NavHostController, mesage: String?, coroutineScope: CoroutineScope) { +private fun closeAndShowError(navController: NavHostController, mesage: String?, coroutineScope: CoroutineScope, context: Context) { coroutineScope.launch(Dispatchers.Main) { navController.popBackStack(route = Route.Connections.path, inclusive = false) - navController.showSnackbar(mesage ?: "Session proposal error, please check your Internet connection") + Toast.makeText(context, mesage ?: "Session proposal error, please check your Internet connection", Toast.LENGTH_SHORT).show() } } diff --git a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_request/SessionRequestRoute.kt b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_request/SessionRequestRoute.kt index 0a229f2d9a..334b751039 100644 --- a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_request/SessionRequestRoute.kt +++ b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_request/SessionRequestRoute.kt @@ -1,6 +1,8 @@ package com.walletconnect.sample.wallet.ui.routes.dialog_routes.session_request import android.annotation.SuppressLint +import android.content.Context +import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -45,7 +47,6 @@ import com.walletconnect.sample.wallet.ui.common.peer.Peer import com.walletconnect.sample.wallet.ui.common.peer.PeerUI import com.walletconnect.sample.wallet.ui.common.peer.getColor import com.walletconnect.sample.wallet.ui.routes.Route -import com.walletconnect.sample.wallet.ui.routes.showSnackbar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -93,17 +94,17 @@ fun SessionRequestRoute(navController: NavHostController, sessionRequestViewMode context.sendResponseDeepLink(uri) } else { composableScope.launch(Dispatchers.Main) { - navController.showSnackbar("Go back to your browser") + Toast.makeText(context, "Go back to your browser", Toast.LENGTH_SHORT).show() } } }, onError = { error -> isConfirmLoading = false - closeAndShowError(navController, error, composableScope) + closeAndShowError(navController, error, composableScope, context) }) } catch (e: Throwable) { - closeAndShowError(navController, e.message, composableScope) + closeAndShowError(navController, e.message, composableScope, context) } }, onCancel = { @@ -119,16 +120,16 @@ fun SessionRequestRoute(navController: NavHostController, sessionRequestViewMode context.sendResponseDeepLink(uri) } else { composableScope.launch(Dispatchers.Main) { - navController.showSnackbar("Go back to your browser") + Toast.makeText(context, "Go back to your browser", Toast.LENGTH_SHORT).show() } } }, onError = { error -> isCancelLoading = false - closeAndShowError(navController, error, composableScope) + closeAndShowError(navController, error, composableScope, context) }) } catch (e: Throwable) { - closeAndShowError(navController, e.message, composableScope) + closeAndShowError(navController, e.message, composableScope, context) } }, isLoadingConfirm = isConfirmLoading, @@ -162,10 +163,10 @@ fun SessionRequestRoute(navController: NavHostController, sessionRequestViewMode } } -private fun closeAndShowError(navController: NavHostController, message: String?, coroutineScope: CoroutineScope) { +private fun closeAndShowError(navController: NavHostController, message: String?, coroutineScope: CoroutineScope, context: Context) { coroutineScope.launch(Dispatchers.Main) { navController.popBackStack() - navController.showSnackbar(message ?: "Session request error, please check your Internet connection") + Toast.makeText(context, message ?: "Session request error, please check your Internet connection", Toast.LENGTH_SHORT).show() } } diff --git a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/host/WalletSampleHost.kt b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/host/WalletSampleHost.kt index a80fd4f81d..20c4836ff6 100644 --- a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/host/WalletSampleHost.kt +++ b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/host/WalletSampleHost.kt @@ -2,6 +2,7 @@ package com.walletconnect.sample.wallet.ui.routes.host +import android.widget.Toast import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -54,7 +55,6 @@ import com.walletconnect.sample.wallet.ui.Web3WalletNavGraph import com.walletconnect.sample.wallet.ui.Web3WalletViewModel import com.walletconnect.sample.wallet.ui.routes.Route import com.walletconnect.sample.wallet.ui.routes.composable_routes.connections.ConnectionsViewModel -import com.walletconnect.sample.wallet.ui.routes.showSnackbar import com.walletconnect.sample.wallet.ui.state.ConnectionState import com.walletconnect.sample.wallet.ui.state.PairingEvent import kotlinx.coroutines.delay @@ -79,15 +79,15 @@ fun WalletSampleHost( when (it) { is PairingEvent.Error -> { navController.popBackStack(route = Route.Connections.path, inclusive = false) - navController.showSnackbar(it.message) + Toast.makeText(navController.context, it.message, Toast.LENGTH_SHORT).show() } is PairingEvent.Expired -> { - navController.showSnackbar(it.message) + Toast.makeText(navController.context, it.message, Toast.LENGTH_SHORT).show() } is PairingEvent.ProposalExpired -> { - navController.showSnackbar(it.message) + Toast.makeText(navController.context, it.message, Toast.LENGTH_SHORT).show() } } } From a9495ea9e7de9b5201df2687e511fbdd081f872a Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 22 Feb 2024 12:57:17 +0100 Subject: [PATCH 2/5] Handle remove exception keys in unsubscribe onSuccess callback --- .../use_case/requests/OnSessionDeleteUseCase.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/use_case/requests/OnSessionDeleteUseCase.kt b/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/use_case/requests/OnSessionDeleteUseCase.kt index 8a9eae9f7f..9a93e90b95 100644 --- a/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/use_case/requests/OnSessionDeleteUseCase.kt +++ b/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/use_case/requests/OnSessionDeleteUseCase.kt @@ -38,10 +38,16 @@ internal class OnSessionDeleteUseCase( jsonRpcInteractor.respondWithError(request, Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) return@supervisorScope } - jsonRpcInteractor.unsubscribe(request.topic, onSuccess = { - logger.log("Session delete received on topic: ${request.topic} - unsubscribe success") - crypto.removeKeys(request.topic.value) - }, onFailure = { error -> logger.error("Session delete received on topic: ${request.topic} - unsubscribe error $error") }) + jsonRpcInteractor.unsubscribe(request.topic, + onSuccess = { + logger.log("Session delete received on topic: ${request.topic} - unsubscribe success") + try { + crypto.removeKeys(request.topic.value) + } catch (e: Exception) { + logger.error("Remove keys exception:$e") + } + }, + onFailure = { error -> logger.error("Session delete received on topic: ${request.topic} - unsubscribe error $error") }) sessionStorageRepository.deleteSession(request.topic) logger.log("Session delete received on topic: ${request.topic} - emitting") _events.emit(params.toEngineDO(request.topic)) From ed0112ce9f97643a5d18e9e81494c07bbe961f5e Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 22 Feb 2024 13:46:16 +0100 Subject: [PATCH 3/5] Improve handling errors on responding to session proposal --- .../SessionProposalViewModel.kt | 24 ++++++++++--------- .../SessionRequestViewModel.kt | 4 ++++ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_proposal/SessionProposalViewModel.kt b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_proposal/SessionProposalViewModel.kt index 024df10a39..ee8c1971a2 100644 --- a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_proposal/SessionProposalViewModel.kt +++ b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_proposal/SessionProposalViewModel.kt @@ -8,15 +8,17 @@ import com.walletconnect.sample.wallet.ui.common.peer.PeerUI import com.walletconnect.sample.wallet.ui.common.peer.toPeerUI import com.walletconnect.web3.wallet.client.Wallet import com.walletconnect.web3.wallet.client.Web3Wallet +import timber.log.Timber class SessionProposalViewModel : ViewModel() { val sessionProposal: SessionProposalUI? = generateSessionProposalUI() fun approve(proposalPublicKey: String, onSuccess: (String) -> Unit = {}, onError: (String) -> Unit = {}) { - if (Web3Wallet.getSessionProposals().isNotEmpty()) { + val proposal = Web3Wallet.getSessionProposals().find { it.proposerPublicKey == proposalPublicKey } + if (proposal != null) { try { - val sessionProposal: Wallet.Model.SessionProposal = requireNotNull(Web3Wallet.getSessionProposals().find { it.proposerPublicKey == proposalPublicKey }) - val sessionNamespaces = Web3Wallet.generateApprovedNamespaces(sessionProposal = sessionProposal, supportedNamespaces = walletMetaData.namespaces) - val approveProposal = Wallet.Params.SessionApprove(proposerPublicKey = sessionProposal.proposerPublicKey, namespaces = sessionNamespaces) + Timber.d("Approving session proposal: $proposalPublicKey") + val sessionNamespaces = Web3Wallet.generateApprovedNamespaces(sessionProposal = proposal, supportedNamespaces = walletMetaData.namespaces) + val approveProposal = Wallet.Params.SessionApprove(proposerPublicKey = proposal.proposerPublicKey, namespaces = sessionNamespaces) Web3Wallet.approveSession(approveProposal, onError = { error -> @@ -26,7 +28,7 @@ class SessionProposalViewModel : ViewModel() { }, onSuccess = { WCDelegate.sessionProposalEvent = null - onSuccess(sessionProposal.redirect) + onSuccess(proposal.redirect) }) } catch (e: Exception) { Firebase.crashlytics.recordException(e) @@ -34,24 +36,24 @@ class SessionProposalViewModel : ViewModel() { onError(e.message ?: "Undefined error, please check your Internet connection") } } else { - onError("Proposal expired") + onError("Cannot approve session proposal, it has expired. Please try again.") } } fun reject(proposalPublicKey: String, onSuccess: (String) -> Unit = {}, onError: (String) -> Unit = {}) { - if (Web3Wallet.getSessionProposals().isNotEmpty()) { + val proposal = Web3Wallet.getSessionProposals().find { it.proposerPublicKey == proposalPublicKey } + if (proposal != null) { try { - val sessionProposal: Wallet.Model.SessionProposal = requireNotNull(Web3Wallet.getSessionProposals().find { it.proposerPublicKey == proposalPublicKey }) val rejectionReason = "Reject Session" val reject = Wallet.Params.SessionReject( - proposerPublicKey = sessionProposal.proposerPublicKey, + proposerPublicKey = proposal.proposerPublicKey, reason = rejectionReason ) Web3Wallet.rejectSession(reject, onSuccess = { WCDelegate.sessionProposalEvent = null - onSuccess(sessionProposal.redirect) + onSuccess(proposal.redirect) }, onError = { error -> Firebase.crashlytics.recordException(error.throwable) @@ -64,7 +66,7 @@ class SessionProposalViewModel : ViewModel() { onError(e.message ?: "Undefined error, please check your Internet connection") } } else { - onError("Proposal expired") + onError("Cannot reject session proposal, it has expired. Please try again.") } } diff --git a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_request/SessionRequestViewModel.kt b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_request/SessionRequestViewModel.kt index 0ff7983518..b907fce2c6 100644 --- a/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_request/SessionRequestViewModel.kt +++ b/sample/wallet/src/main/kotlin/com/walletconnect/sample/wallet/ui/routes/dialog_routes/session_request/SessionRequestViewModel.kt @@ -51,6 +51,8 @@ class SessionRequestViewModel : ViewModel() { clearSessionRequest() onError(error.throwable.message ?: "Undefined error, please check your Internet connection") }) + } else { + onError("Reject - Cannot find session request") } } catch (e: Exception) { Firebase.crashlytics.recordException(e) @@ -108,6 +110,8 @@ class SessionRequestViewModel : ViewModel() { clearSessionRequest() onError(error.throwable.message ?: "Undefined error, please check your Internet connection") }) + } else { + onError("Approve - Cannot find session request") } } catch (e: Exception) { Firebase.crashlytics.recordException(e) From aee27592a1bdabc98e11601291fea9669dd06295 Mon Sep 17 00:00:00 2001 From: kubel Date: Tue, 27 Feb 2024 10:18:37 +0100 Subject: [PATCH 4/5] Add robust error handling and fix reported crashes --- buildSrc/src/main/kotlin/Dependencies.kt | 1 + .../internal/common/di/CorePairingModule.kt | 11 ++- .../pairing/PairingStorageRepository.kt | 12 ++- .../PairingStorageRepositoryInterface.kt | 8 +- .../pairing/engine/domain/PairingEngine.kt | 91 ++++++++++++------- .../android/sdk/storage/data/dao/Pairing.sq | 18 ++++ .../com/walletconnect/sign/di/EngineModule.kt | 3 +- .../sign/engine/domain/SignEngine.kt | 44 +++++---- .../proposal/ProposalStorageRepository.kt | 5 +- 9 files changed, 137 insertions(+), 56 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 60594f19df..4f33048b15 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -61,6 +61,7 @@ fun DependencyHandlerScope.bouncyCastle() { fun DependencyHandlerScope.sqlCipher() { "api"("net.zetetic:android-database-sqlcipher:$sqlCipherVersion") + "api"("app.cash.sqldelight:async-extensions:2.0.0") } fun DependencyHandlerScope.reLinker() { diff --git a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/di/CorePairingModule.kt b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/di/CorePairingModule.kt index 7a38c4569a..2900246271 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/di/CorePairingModule.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/di/CorePairingModule.kt @@ -6,7 +6,16 @@ import com.walletconnect.android.pairing.handler.PairingControllerInterface import org.koin.dsl.module fun corePairingModule(pairing: PairingInterface, pairingController: PairingControllerInterface) = module { - single { PairingEngine(get(), get(), get(), get(), get(), get()) } + single { + PairingEngine( + selfMetaData = get(), + crypto = get(), + metadataRepository = get(), + pairingRepository = get(), + jsonRpcInteractor = get(), + logger = get() + ) + } single { pairing } single { pairingController } } \ No newline at end of file diff --git a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/storage/pairing/PairingStorageRepository.kt b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/storage/pairing/PairingStorageRepository.kt index f1a5510b1d..314e60e599 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/storage/pairing/PairingStorageRepository.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/storage/pairing/PairingStorageRepository.kt @@ -1,6 +1,7 @@ package com.walletconnect.android.internal.common.storage.pairing import android.database.sqlite.SQLiteException +import app.cash.sqldelight.async.coroutines.awaitAsList import com.walletconnect.android.internal.common.model.AppMetaData import com.walletconnect.android.internal.common.model.Expiry import com.walletconnect.android.internal.common.model.Pairing @@ -35,7 +36,16 @@ class PairingStorageRepository(private val pairingQueries: PairingQueries) : Pai override fun hasTopic(topic: Topic): Boolean = pairingQueries.hasTopic(topic = topic.value).executeAsOneOrNull() != null @Throws(SQLiteException::class) - override fun getListOfPairings(): List = pairingQueries.getListOfPairing(mapper = this::toPairing).executeAsList() + override suspend fun getListOfPairings(): List = pairingQueries.getListOfPairing(mapper = this::toPairing).awaitAsList() + + @Throws(SQLiteException::class) + override suspend fun getListOfInactivePairings(): List = pairingQueries.getListOfInactivePairings(mapper = this::toPairing).awaitAsList() + + @Throws(SQLiteException::class) + override suspend fun getListOfActivePairings(): List = pairingQueries.getListOfActivePairings(mapper = this::toPairing).awaitAsList() + + @Throws(SQLiteException::class) + override suspend fun getListOfInactivePairingsWithoutRequestReceived(): List = pairingQueries.getListOfInactivePairingsWithoutRequestReceived(mapper = this::toPairing).awaitAsList() @Throws(SQLiteException::class) override fun activatePairing(topic: Topic) = pairingQueries.activatePairing(expiry = activePairing, is_active = true, topic = topic.value) diff --git a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/storage/pairing/PairingStorageRepositoryInterface.kt b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/storage/pairing/PairingStorageRepositoryInterface.kt index 0b7c433d00..0ed119a1a7 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/storage/pairing/PairingStorageRepositoryInterface.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/storage/pairing/PairingStorageRepositoryInterface.kt @@ -12,7 +12,13 @@ interface PairingStorageRepositoryInterface { fun hasTopic(topic: Topic): Boolean - fun getListOfPairings(): List + suspend fun getListOfPairings(): List + + suspend fun getListOfInactivePairings(): List + + suspend fun getListOfActivePairings(): List + + suspend fun getListOfInactivePairingsWithoutRequestReceived(): List fun activatePairing(topic: Topic) diff --git a/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt b/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt index 77195b82b3..19f67a28ae 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt @@ -62,6 +62,7 @@ import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.withTimeout import java.util.concurrent.TimeUnit @@ -97,7 +98,8 @@ internal class PairingEngine( init { setOfRegisteredMethods.addAll(listOf(PairingJsonRpcMethod.WC_PAIRING_DELETE, PairingJsonRpcMethod.WC_PAIRING_PING)) resubscribeToPairingTopics() - pairingExpiryWatcher() + inactivePairingsExpiryWatcher() + activePairingsExpiryWatcher() isPairingStateWatcher() } @@ -200,11 +202,12 @@ internal class PairingEngine( val deleteParams = PairingParams.DeleteParams(6000, "User disconnected") val pairingDelete = PairingRpc.PairingDelete(params = deleteParams) val irnParams = IrnParams(Tags.PAIRING_DELETE, Ttl(dayInSeconds)) + logger.log("Sending Pairing disconnect") jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, pairingDelete, onSuccess = { scope.launch { supervisorScope { - logger.log("Disconnect sent successfully") + logger.log("Pairing disconnect sent successfully") pairingRepository.deletePairing(Topic(topic)) metadataRepository.deleteMetaData(Topic(topic)) jsonRpcInteractor.unsubscribe(Topic(topic)) @@ -232,7 +235,7 @@ internal class PairingEngine( } } - fun getPairings(): List = pairingRepository.getListOfPairings().filter { pairing -> pairing.isNotExpired() } + fun getPairings(): List = runBlocking { pairingRepository.getListOfPairings().filter { pairing -> pairing.isNotExpired() } } fun register(vararg method: String) { setOfRegisteredMethods.addAll(method) @@ -266,7 +269,7 @@ internal class PairingEngine( .onEach { supervisorScope { launch(Dispatchers.IO) { - resubscribeToPairingFlow() + resubscribeToPairing() } } @@ -276,35 +279,56 @@ internal class PairingEngine( }.launchIn(scope) } - private fun pairingExpiryWatcher() { - flow { - while (true) { - emit(Unit) - delay(WATCHER_INTERVAL) - } - }.onEach { - pairingRepository - .getListOfPairings() - .onEach { pairing -> pairing.isNotExpired() } - }.launchIn(scope) + private fun inactivePairingsExpiryWatcher() { + repeatableFlow(WATCHER_INTERVAL) + .onEach { + try { + pairingRepository.getListOfInactivePairings() + .onEach { pairing -> + pairing.isNotExpired() + } + } catch (e: Exception) { + logger.error(e) + } + }.launchIn(scope) + } + + private fun activePairingsExpiryWatcher() { + repeatableFlow(ACTIVE_PAIRINGS_WATCHER_INTERVAL) + .onEach { + try { + pairingRepository.getListOfActivePairings() + .onEach { pairing -> + pairing.isNotExpired() + } + } catch (e: Exception) { + logger.error(e) + } + }.launchIn(scope) } + private fun isPairingStateWatcher() { - flow { - while (true) { - emit(Unit) - delay(WATCHER_INTERVAL) - } - }.onEach { - val inactivePairings = pairingRepository - .getListOfPairings() - .filter { pairing -> !pairing.isActive && !pairing.isProposalReceived } - if (inactivePairings.isNotEmpty()) { - _isPairingStateFlow.compareAndSet(expect = false, update = true) - } else { - _isPairingStateFlow.compareAndSet(expect = true, update = false) - } - }.launchIn(scope) + repeatableFlow(WATCHER_INTERVAL) + .onEach { + try { + val inactivePairings = pairingRepository.getListOfInactivePairingsWithoutRequestReceived() + if (inactivePairings.isNotEmpty()) { + _isPairingStateFlow.compareAndSet(expect = false, update = true) + } else { + _isPairingStateFlow.compareAndSet(expect = true, update = false) + } + } catch (e: Exception) { + logger.error(e) + } + }.launchIn(scope) + } + + private fun repeatableFlow(interval: Long) = flow { + while (true) { + emit(Unit) + delay(interval) + } } private fun collectJsonRpcRequestsFlow(): Job = @@ -317,9 +341,9 @@ internal class PairingEngine( } }.launchIn(scope) - private fun resubscribeToPairingFlow() { + private fun resubscribeToPairing() { try { - val pairingTopics = pairingRepository.getListOfPairings().filter { pairing -> pairing.isNotExpired() }.map { pairing -> pairing.topic.value } + val pairingTopics = runBlocking { pairingRepository.getListOfPairings().filter { pairing -> pairing.isNotExpired() }.map { pairing -> pairing.topic.value } } jsonRpcInteractor.batchSubscribe(pairingTopics) { error -> scope.launch { internalErrorFlow.emit(SDKError(error)) } } } catch (e: Exception) { scope.launch { internalErrorFlow.emit(SDKError(e)) } @@ -416,6 +440,7 @@ internal class PairingEngine( pairingRepository.getPairingOrNullByTopic(Topic(topic))?.let { pairing -> return@let pairing.isNotExpired() } ?: false companion object { - private const val WATCHER_INTERVAL = 3000L + private const val WATCHER_INTERVAL = 5000L + private const val ACTIVE_PAIRINGS_WATCHER_INTERVAL = 600000L //10mins } } \ No newline at end of file diff --git a/core/android/src/main/sqldelight/com/walletconnect/android/sdk/storage/data/dao/Pairing.sq b/core/android/src/main/sqldelight/com/walletconnect/android/sdk/storage/data/dao/Pairing.sq index f0de8887cd..cd7f0031f9 100644 --- a/core/android/src/main/sqldelight/com/walletconnect/android/sdk/storage/data/dao/Pairing.sq +++ b/core/android/src/main/sqldelight/com/walletconnect/android/sdk/storage/data/dao/Pairing.sq @@ -21,6 +21,24 @@ SELECT pd.topic, pd.expiry, pd.relay_protocol, pd.relay_data, pd.uri, pd.methods FROM Pairing pd LEFT JOIN MetaData mdd_peer ON pd.topic = mdd_peer.sequence_topic AND mdd_peer.type = "PEER"; +getListOfInactivePairingsWithoutRequestReceived: +SELECT pd.topic, pd.expiry, pd.relay_protocol, pd.relay_data, pd.uri, pd.methods, pd.is_active, pd.is_proposal_received, mdd_peer.name, mdd_peer.description, mdd_peer.url, mdd_peer.icons, mdd_peer.native +FROM Pairing pd + LEFT JOIN MetaData mdd_peer ON pd.topic = mdd_peer.sequence_topic AND mdd_peer.type = "PEER" +WHERE pd.is_active = 0 AND pd.is_proposal_received = 0; + +getListOfInactivePairings: +SELECT pd.topic, pd.expiry, pd.relay_protocol, pd.relay_data, pd.uri, pd.methods, pd.is_active, pd.is_proposal_received, mdd_peer.name, mdd_peer.description, mdd_peer.url, mdd_peer.icons, mdd_peer.native +FROM Pairing pd + LEFT JOIN MetaData mdd_peer ON pd.topic = mdd_peer.sequence_topic AND mdd_peer.type = "PEER" +WHERE pd.is_active = 0; + +getListOfActivePairings: +SELECT pd.topic, pd.expiry, pd.relay_protocol, pd.relay_data, pd.uri, pd.methods, pd.is_active, pd.is_proposal_received, mdd_peer.name, mdd_peer.description, mdd_peer.url, mdd_peer.icons, mdd_peer.native +FROM Pairing pd + LEFT JOIN MetaData mdd_peer ON pd.topic = mdd_peer.sequence_topic AND mdd_peer.type = "PEER" +WHERE pd.is_active = 1; + getPairingByTopic: SELECT pd.topic, pd.expiry, pd.relay_protocol, pd.relay_data, pd.uri, pd.methods, pd.is_active, pd.is_proposal_received, mdd_peer.name, mdd_peer.description, mdd_peer.url, mdd_peer.icons, mdd_peer.native FROM Pairing pd diff --git a/protocol/sign/src/main/kotlin/com/walletconnect/sign/di/EngineModule.kt b/protocol/sign/src/main/kotlin/com/walletconnect/sign/di/EngineModule.kt index e0c0adbe61..92b329ea85 100644 --- a/protocol/sign/src/main/kotlin/com/walletconnect/sign/di/EngineModule.kt +++ b/protocol/sign/src/main/kotlin/com/walletconnect/sign/di/EngineModule.kt @@ -62,7 +62,8 @@ internal fun engineModule() = module { respondSessionRequestUseCase = get(), sessionRequestUseCase = get(), sessionUpdateUseCase = get(), - deleteRequestByIdUseCase = get() + deleteRequestByIdUseCase = get(), + logger = get(named(AndroidCommonDITags.LOGGER)) ) } } \ No newline at end of file diff --git a/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt b/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt index 461f12a86d..b7ffc5f34a 100644 --- a/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt +++ b/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt @@ -17,6 +17,7 @@ import com.walletconnect.android.pairing.handler.PairingControllerInterface import com.walletconnect.android.push.notifications.DecryptMessageUseCaseInterface import com.walletconnect.android.verify.data.model.VerifyContext import com.walletconnect.foundation.common.model.Topic +import com.walletconnect.foundation.util.Logger import com.walletconnect.sign.common.model.vo.clientsync.session.params.SignParams import com.walletconnect.sign.engine.model.EngineDO import com.walletconnect.sign.engine.model.mapper.toEngineDO @@ -116,6 +117,7 @@ internal class SignEngine( private val onSessionSettleResponseUseCase: OnSessionSettleResponseUseCase, private val onSessionUpdateResponseUseCase: OnSessionUpdateResponseUseCase, private val onSessionRequestResponseUseCase: OnSessionRequestResponseUseCase, + private val logger: Logger ) : ProposeSessionUseCaseInterface by proposeSessionUseCase, PairUseCaseInterface by pairUseCase, RejectSessionUseCaseInterface by rejectSessionUseCase, @@ -302,32 +304,40 @@ internal class SignEngine( private fun sessionProposalExpiryWatcher() { repeatableFlow() .onEach { - proposalStorageRepository - .getProposals() - .onEach { proposal -> - proposal.expiry?.let { - if (it.isExpired()) { - proposalStorageRepository.deleteProposal(proposal.proposerPublicKey) - deleteRequestByIdUseCase(proposal.requestId) - _engineEvent.emit(proposal.toExpiredProposal()) + try { + proposalStorageRepository + .getProposals() + .onEach { proposal -> + proposal.expiry?.let { + if (it.isExpired()) { + proposalStorageRepository.deleteProposal(proposal.proposerPublicKey) + deleteRequestByIdUseCase(proposal.requestId) + _engineEvent.emit(proposal.toExpiredProposal()) + } } } - } + } catch (e: Exception) { + logger.error(e) + } }.launchIn(scope) } private fun sessionRequestsExpiryWatcher() { repeatableFlow() .onEach { - getPendingSessionRequests() - .onEach { pendingRequest -> - pendingRequest.expiry?.let { - if (it.isExpired()) { - deleteRequestByIdUseCase(pendingRequest.id) - _engineEvent.emit(pendingRequest.toExpiredSessionRequest()) + try { + getPendingSessionRequests() + .onEach { pendingRequest -> + pendingRequest.expiry?.let { + if (it.isExpired()) { + deleteRequestByIdUseCase(pendingRequest.id) + _engineEvent.emit(pendingRequest.toExpiredSessionRequest()) + } } } - } + } catch (e: Exception) { + logger.error(e) + } }.launchIn(scope) } @@ -358,6 +368,6 @@ internal class SignEngine( } companion object { - private const val WATCHER_INTERVAL = 3000L + private const val WATCHER_INTERVAL = 5000L } } \ No newline at end of file diff --git a/protocol/sign/src/main/kotlin/com/walletconnect/sign/storage/proposal/ProposalStorageRepository.kt b/protocol/sign/src/main/kotlin/com/walletconnect/sign/storage/proposal/ProposalStorageRepository.kt index 789d4b9a92..326b8435de 100644 --- a/protocol/sign/src/main/kotlin/com/walletconnect/sign/storage/proposal/ProposalStorageRepository.kt +++ b/protocol/sign/src/main/kotlin/com/walletconnect/sign/storage/proposal/ProposalStorageRepository.kt @@ -3,6 +3,7 @@ package com.walletconnect.sign.storage.proposal import android.database.sqlite.SQLiteException +import app.cash.sqldelight.async.coroutines.awaitAsList import com.walletconnect.android.internal.common.model.Expiry import com.walletconnect.android.internal.common.model.Namespace import com.walletconnect.android.internal.common.scope @@ -57,8 +58,8 @@ class ProposalStorageRepository( @JvmSynthetic @Throws(SQLiteException::class) - internal fun getProposals(): List { - return proposalDaoQueries.getListOfProposalDaos(this::mapProposalDaoToProposalVO).executeAsList() + internal suspend fun getProposals(): List { + return proposalDaoQueries.getListOfProposalDaos(this::mapProposalDaoToProposalVO).awaitAsList() } @JvmSynthetic From 570f163900d13d55f6b5117c33b15ab0bbe6f612 Mon Sep 17 00:00:00 2001 From: kubel Date: Wed, 28 Feb 2024 12:15:20 +0100 Subject: [PATCH 5/5] Increase watchers intervals --- .../pairing/engine/domain/PairingEngine.kt | 26 +++++++++---------- .../sign/engine/domain/SignEngine.kt | 2 +- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt b/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt index 19f67a28ae..6d64fea4c3 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt @@ -269,7 +269,7 @@ internal class PairingEngine( .onEach { supervisorScope { launch(Dispatchers.IO) { - resubscribeToPairing() + sendBatchSubcrbeForPairings() } } @@ -279,6 +279,15 @@ internal class PairingEngine( }.launchIn(scope) } + private suspend fun sendBatchSubcrbeForPairings() { + try { + val pairingTopics = pairingRepository.getListOfPairings().filter { pairing -> pairing.isNotExpired() }.map { pairing -> pairing.topic.value } + jsonRpcInteractor.batchSubscribe(pairingTopics) { error -> scope.launch { internalErrorFlow.emit(SDKError(error)) } } + } catch (e: Exception) { + scope.launch { internalErrorFlow.emit(SDKError(e)) } + } + } + private fun inactivePairingsExpiryWatcher() { repeatableFlow(WATCHER_INTERVAL) .onEach { @@ -298,9 +307,7 @@ internal class PairingEngine( .onEach { try { pairingRepository.getListOfActivePairings() - .onEach { pairing -> - pairing.isNotExpired() - } + .onEach { pairing -> pairing.isNotExpired() } } catch (e: Exception) { logger.error(e) } @@ -341,15 +348,6 @@ internal class PairingEngine( } }.launchIn(scope) - private fun resubscribeToPairing() { - try { - val pairingTopics = runBlocking { pairingRepository.getListOfPairings().filter { pairing -> pairing.isNotExpired() }.map { pairing -> pairing.topic.value } } - jsonRpcInteractor.batchSubscribe(pairingTopics) { error -> scope.launch { internalErrorFlow.emit(SDKError(error)) } } - } catch (e: Exception) { - scope.launch { internalErrorFlow.emit(SDKError(e)) } - } - } - private suspend fun onPairingDelete(request: WCRequest, params: PairingParams.DeleteParams) { val irnParams = IrnParams(Tags.PAIRING_DELETE_RESPONSE, Ttl(dayInSeconds)) try { @@ -440,7 +438,7 @@ internal class PairingEngine( pairingRepository.getPairingOrNullByTopic(Topic(topic))?.let { pairing -> return@let pairing.isNotExpired() } ?: false companion object { - private const val WATCHER_INTERVAL = 5000L + private const val WATCHER_INTERVAL = 30000L //30s private const val ACTIVE_PAIRINGS_WATCHER_INTERVAL = 600000L //10mins } } \ No newline at end of file diff --git a/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt b/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt index b7ffc5f34a..9c26651989 100644 --- a/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt +++ b/protocol/sign/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt @@ -368,6 +368,6 @@ internal class SignEngine( } companion object { - private const val WATCHER_INTERVAL = 5000L + private const val WATCHER_INTERVAL = 30000L //30s } } \ No newline at end of file