Skip to content

Commit

Permalink
Merge pull request #1440 from WalletConnect/close_dialog_fix
Browse files Browse the repository at this point in the history
Improve navigation on connection refresh
  • Loading branch information
jakubuid authored Jul 11, 2024
2 parents 1bd55da + 998a80e commit 75fee10
Show file tree
Hide file tree
Showing 15 changed files with 147 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,10 @@ class SendEventUseCaseTest : KoinTest {
private lateinit var useCase: SendEventUseCase
private val testDispatcher = StandardTestDispatcher()

private val testModule: Module = module {
single(named(AndroidCommonDITags.ENABLE_WEB_3_MODAL_ANALYTICS)) { true }
}

@OptIn(ExperimentalCoroutinesApi::class)
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
val app = startKoin { modules(testModule) }
useCase = SendEventUseCase(pulseService, logger, bundleId)
wcKoinApp = app
}

@OptIn(ExperimentalCoroutinesApi::class)
Expand All @@ -64,6 +57,14 @@ class SendEventUseCaseTest : KoinTest {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `send should log and send event when analytics is enabled and response is successful`() = runTest(testDispatcher) {
stopKoin()
val module: Module = module {
single(named(AndroidCommonDITags.ENABLE_WEB_3_MODAL_ANALYTICS)) { true }
}
val app = startKoin { modules(module) }
useCase = SendEventUseCase(pulseService, logger, bundleId)
wcKoinApp = app

val props = Props(type = "testEvent")
val sdkType = SDKType.WEB3MODAL
val event = Event(props = props, bundleId = bundleId)
Expand All @@ -82,6 +83,14 @@ class SendEventUseCaseTest : KoinTest {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `send should log error when analytics is enabled and response is unsuccessful`() = runTest(testDispatcher) {
stopKoin()
val module: Module = module {
single(named(AndroidCommonDITags.ENABLE_WEB_3_MODAL_ANALYTICS)) { true }
}
val app = startKoin { modules(module) }
useCase = SendEventUseCase(pulseService, logger, bundleId)
wcKoinApp = app

val props = Props(type = "testEvent")
val sdkType = SDKType.WEB3MODAL
val event = Event(props = props, bundleId = bundleId)
Expand All @@ -100,6 +109,14 @@ class SendEventUseCaseTest : KoinTest {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `send should log exception when analytics is enabled and an exception occurs`() = runTest(testDispatcher) {
stopKoin()
val module: Module = module {
single(named(AndroidCommonDITags.ENABLE_WEB_3_MODAL_ANALYTICS)) { true }
}
val app = startKoin { modules(module) }
useCase = SendEventUseCase(pulseService, logger, bundleId)
wcKoinApp = app

val props = Props(type = "testEvent")
val sdkType = SDKType.WEB3MODAL
val event = Event(props = props, bundleId = bundleId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal class ClientIdJwtRepositoryAndroidTest {

// Expected JWT for given nonce
private val expectedJWT =
"eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaWQ6a2V5Ono2TWtvZEhad25lVlJTaHRhTGY4SktZa3hwREdwMXZHWm5wR21kQnBYOE0yZXh4SCIsInN1YiI6ImM0NzlmZTVkYzQ2NGU3NzFlNzhiMTkzZDIzOWE2NWI1OGQyNzhjYWQxYzM0YmZiMGI1NzE2ZTViYjUxNDkyOGUiLCJhdWQiOiJ3c3M6Ly9yZWxheS53YWxsZXRjb25uZWN0LmNvbSIsImlhdCI6MTY1NjkxMDA5NywiZXhwIjoxNjU2OTk2NDk3fQ.bAKl1swvwqqV_FgwvD4Bx3Yp987B9gTpZctyBviA-EkAuWc8iI8SyokOjkv9GJESgid4U8Tf2foCgrQp2qrxBA"
"eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaWQ6a2V5Ono2TWtvZEhad25lVlJTaHRhTGY4SktZa3hwREdwMXZHWm5wR21kQnBYOE0yZXh4SCIsInN1YiI6ImM0NzlmZTVkYzQ2NGU3NzFlNzhiMTkzZDIzOWE2NWI1OGQyNzhjYWQxYzM0YmZiMGI1NzE2ZTViYjUxNDkyOGUiLCJhdWQiOiJ3c3M6Ly9yZWxheS53YWxsZXRjb25uZWN0Lm9yZyIsImlhdCI6MTY1NjkxMDA5NywiZXhwIjoxNjU2OTk2NDk3fQ.lV9WBz1j3uQvDlv8NFnzymGczKQMWFsSqaZdXs4cUwFepP5LVC2eYIHdGsYkiJfwJxNia3LghX20GBW09SuwBA"

@Before
fun setUp() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import java.util.concurrent.TimeUnit

fun networkModule(serverUrl: String, sdkVersion: String, jwt: String): Module = module {
val DEFAULT_BACKOFF_SECONDS = 5L
val TIMEOUT_TIME = 5000L
val TIMEOUT_TIME = 10000L

// TODO: Setup env variable for tag instead of relayTest. Use env variable here instead of hard coded version
single(named(FoundationDITags.INTERCEPTOR)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ sealed class TestState {
@ExperimentalCoroutinesApi
class RelayTest {
private val testProjectId: String = requireNotNull(System.getProperty("TEST_PROJECT_ID"))
private val testRelayUrl: String = requireNotNull(System.getProperty("TEST_RELAY_URL"))
private val testRelayUrl: String = "https://staging.relay.walletconnect.org"
private val serverUrl = "$testRelayUrl?projectId=$testProjectId"
private val sdkVersion: String = System.getProperty("SDK_VERSION") + "-relayTest"
private val testJob: CompletableJob = SupervisorJob()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ internal class ClientIdJwtRepositoryTest {

// Expected JWT for given nonce
private val expectedJWT =
"eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaWQ6a2V5Ono2TWtvZEhad25lVlJTaHRhTGY4SktZa3hwREdwMXZHWm5wR21kQnBYOE0yZXh4SCIsInN1YiI6ImM0NzlmZTVkYzQ2NGU3NzFlNzhiMTkzZDIzOWE2NWI1OGQyNzhjYWQxYzM0YmZiMGI1NzE2ZTViYjUxNDkyOGUiLCJhdWQiOiJ3c3M6Ly9yZWxheS53YWxsZXRjb25uZWN0LmNvbSIsImlhdCI6MTY1NjkxMDA5NywiZXhwIjoxNjU2OTk2NDk3fQ.bAKl1swvwqqV_FgwvD4Bx3Yp987B9gTpZctyBviA-EkAuWc8iI8SyokOjkv9GJESgid4U8Tf2foCgrQp2qrxBA"
"eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaWQ6a2V5Ono2TWtvZEhad25lVlJTaHRhTGY4SktZa3hwREdwMXZHWm5wR21kQnBYOE0yZXh4SCIsInN1YiI6ImM0NzlmZTVkYzQ2NGU3NzFlNzhiMTkzZDIzOWE2NWI1OGQyNzhjYWQxYzM0YmZiMGI1NzE2ZTViYjUxNDkyOGUiLCJhdWQiOiJ3c3M6Ly9yZWxheS53YWxsZXRjb25uZWN0Lm9yZyIsImlhdCI6MTY1NjkxMDA5NywiZXhwIjoxNjU2OTk2NDk3fQ.lV9WBz1j3uQvDlv8NFnzymGczKQMWFsSqaZdXs4cUwFepP5LVC2eYIHdGsYkiJfwJxNia3LghX20GBW09SuwBA"

@Before
fun setUp() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class ClientInstrumentedActivityScenario : TestRule, ActivityScenario() {
}
}
}.fold(
onSuccess = { Timber.d("Connection established and peers initialized with: ${TestClient.RELAY_URL}") },
onSuccess = { Timber.d("Connection established and peers initialized successfully") },
onFailure = { fail("Unable to establish connection OR initialize peers within $timeoutDuration") }
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Web3WalletActivity : AppCompatActivity() {
private val connectionsViewModel = ConnectionsViewModel()

private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
// FCM SDK (and your app) can post notifications.
Expand Down Expand Up @@ -93,7 +93,10 @@ class Web3WalletActivity : AppCompatActivity() {
when (event) {
is CoreEvent.Disconnect -> {
connectionsViewModel.refreshConnections()
navController.navigate(Route.Connections.path)

if (navController.currentDestination?.route != Route.Connections.path) {
navController.navigate(Route.Connections.path)
}
}

else -> Unit
Expand All @@ -115,39 +118,41 @@ class Web3WalletActivity : AppCompatActivity() {
connectionsViewModel: ConnectionsViewModel,
) {
web3walletViewModel.sessionRequestStateFlow
.onEach {
if (it.arrayOfArgs.isNotEmpty()) {
web3walletViewModel.showRequestLoader(false)
navController.navigate(Route.SessionRequest.path)
}
.onEach {
if (it.arrayOfArgs.isNotEmpty()) {
web3walletViewModel.showRequestLoader(false)
navController.navigate(Route.SessionRequest.path)
}
.launchIn(lifecycleScope)
}
.launchIn(lifecycleScope)

web3walletViewModel.walletEvents
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.onEach { event ->
when (event) {
is SignEvent.SessionProposal -> navController.navigate(Route.SessionProposal.path)
is SignEvent.ExpiredRequest -> {
navController.popBackStack(
route = Route.Connections.path,
inclusive = false
)
if (navController.currentDestination?.route != Route.Connections.path) {
navController.popBackStack(route = Route.Connections.path, inclusive = false)
}
Toast.makeText(baseContext, "Request expired", Toast.LENGTH_SHORT).show()
}

is SignEvent.Disconnect -> {
connectionsViewModel.refreshConnections()
is SignEvent.Disconnect -> {
connectionsViewModel.refreshConnections()

if (navController.currentDestination?.route != Route.Connections.path) {
navController.navigate(Route.Connections.path)
}
}

is AuthEvent.OnRequest -> navController.navigate(Route.AuthRequest.path)
is SignEvent.SessionAuthenticate -> navController.navigate(Route.SessionAuthenticate.path)
is AuthEvent.OnRequest -> navController.navigate(Route.AuthRequest.path)
is SignEvent.SessionAuthenticate -> navController.navigate(Route.SessionAuthenticate.path)

else -> Unit
}
else -> Unit
}
.launchIn(lifecycleScope)
}
.launchIn(lifecycleScope)
}

override fun onNewIntent(intent: Intent?) {
Expand All @@ -170,7 +175,7 @@ class Web3WalletActivity : AppCompatActivity() {
}

if (intent?.dataString?.startsWith("kotlin-web3wallet://request") == false
&& intent.dataString?.contains("requestId") == false
&& intent.dataString?.contains("requestId") == false
) {
navController.handleDeepLink(intent)
}
Expand All @@ -180,9 +185,9 @@ class Web3WalletActivity : AppCompatActivity() {
// This is only necessary for API level >= 33 (TIRAMISU)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.POST_NOTIFICATIONS
) == PackageManager.PERMISSION_GRANTED
this,
android.Manifest.permission.POST_NOTIFICATIONS
) == PackageManager.PERMISSION_GRANTED
) {
// FCM SDK (and your app) can post notifications.
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import com.google.accompanist.navigation.material.BottomSheetNavigator
import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
import com.google.accompanist.navigation.material.ModalBottomSheetLayout
import com.google.accompanist.navigation.material.bottomSheet
import com.walletconnect.sample.wallet.domain.WCDelegate
import com.walletconnect.sample.wallet.ui.routes.Route
import com.walletconnect.sample.wallet.ui.routes.bottomsheet_routes.scan_uri.ScanUriRoute
import com.walletconnect.sample.wallet.ui.routes.bottomsheet_routes.update_subscription.UpdateSubscriptionRoute
Expand Down Expand Up @@ -60,6 +61,14 @@ fun Web3WalletNavGraph(
var scrimColor by remember { mutableStateOf(Color.Unspecified) }
val inboxViewModel: InboxViewModel = viewModel()

navController.addOnDestinationChangedListener(
listener = { _, destination, _ ->
if (destination.route == Route.Connections.path) {
WCDelegate.sessionRequestEvent = null
WCDelegate.currentId = null
}
})

ModalBottomSheetLayout(
modifier = modifier,
bottomSheetNavigator = bottomSheetNavigator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import androidx.compose.ui.unit.sp
import androidx.core.net.toUri
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import com.walletconnect.android.internal.common.exception.NoConnectivityException
import com.walletconnect.sample.common.sendResponseDeepLink
import com.walletconnect.sample.common.ui.theme.mismatch_color
import com.walletconnect.sample.common.ui.themedColor
Expand Down Expand Up @@ -156,10 +157,10 @@ private fun SessionAuthenticateDialog(
},
onError = { error ->
isCancelLoading = false
showError(error, composableScope, context)
showError(navController, error, composableScope, context)
})
} catch (e: Throwable) {
showError(e.message, composableScope, context)
showError(navController, e, composableScope, context)
}
}, onConfirm = {
isConfirmLoading = true
Expand All @@ -183,10 +184,10 @@ private fun SessionAuthenticateDialog(
},
onError = { error ->
isConfirmLoading = false
showError(error, composableScope, context)
showError(navController, error, composableScope, context)
})
} catch (e: Exception) {
showError(e.message, composableScope, context)
showError(navController, e, composableScope, context)
}
},
isLoadingConfirm = isConfirmLoading,
Expand All @@ -196,9 +197,13 @@ private fun SessionAuthenticateDialog(
}
}

private fun showError(message: String?, coroutineScope: CoroutineScope, context: Context) {
private fun showError(navController: NavHostController, throwable: Throwable?, coroutineScope: CoroutineScope, context: Context) {
coroutineScope.launch(Dispatchers.Main) {
Toast.makeText(context, message ?: "Session authenticate error, please check your Internet connection", Toast.LENGTH_SHORT).show()
if (throwable !is NoConnectivityException) {
navController.popBackStack()
}

Toast.makeText(context, throwable?.message ?: "Session authenticate error, please check your Internet connection", Toast.LENGTH_SHORT).show()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import com.walletconnect.android.cacao.signature.SignatureType
import com.walletconnect.android.internal.common.exception.NoConnectivityException
import com.walletconnect.android.utils.cacao.sign
import com.walletconnect.sample.wallet.domain.ACCOUNTS_1_EIP155_ADDRESS
import com.walletconnect.sample.wallet.domain.EthAccountDelegate
Expand All @@ -18,7 +19,7 @@ import com.walletconnect.web3.wallet.utils.CacaoSigner
class SessionAuthenticateViewModel : ViewModel() {
val sessionAuthenticateUI: SessionAuthenticateUI? get() = generateAuthRequestUI()

fun approve(onSuccess: (String) -> Unit = {}, onError: (String) -> Unit = {}) {
fun approve(onSuccess: (String) -> Unit = {}, onError: (Throwable) -> Unit = {}) {
if (WCDelegate.sessionAuthenticateEvent != null) {
try {
val sessionAuthenticate = WCDelegate.sessionAuthenticateEvent!!.first
Expand All @@ -42,25 +43,29 @@ class SessionAuthenticateViewModel : ViewModel() {

val approveProposal = Wallet.Params.ApproveSessionAuthenticate(id = sessionAuthenticate.id, auths = auths)
Web3Wallet.approveSessionAuthenticate(approveProposal,
onError = { error ->
Firebase.crashlytics.recordException(error.throwable)
onError(error.throwable.message ?: "Undefined error, please check your Internet connection")
},
onSuccess = {
WCDelegate.sessionAuthenticateEvent = null
onSuccess(sessionAuthenticate.participant.metadata?.redirect ?: "")
})
},
onError = { error ->
if (error.throwable !is NoConnectivityException) {
WCDelegate.sessionAuthenticateEvent = null
}
Firebase.crashlytics.recordException(error.throwable)
onError(error.throwable)
}
)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
WCDelegate.sessionAuthenticateEvent = null
onError(e.message ?: "Undefined error, please check your Internet connection")
onError(e)
}
} else {
onError("Authenticate request expired")
onError(Throwable("Authenticate request expired"))
}
}

fun reject(onSuccess: (String) -> Unit = {}, onError: (String) -> Unit = {}) {
fun reject(onSuccess: (String) -> Unit = {}, onError: (Throwable) -> Unit = {}) {
if (WCDelegate.sessionAuthenticateEvent != null) {
try {
val sessionAuthenticate = WCDelegate.sessionAuthenticateEvent!!.first
Expand All @@ -76,16 +81,19 @@ class SessionAuthenticateViewModel : ViewModel() {
onSuccess(sessionAuthenticate.participant.metadata?.redirect ?: "")
},
onError = { error ->
if (error.throwable !is NoConnectivityException) {
WCDelegate.sessionAuthenticateEvent = null
}
Firebase.crashlytics.recordException(error.throwable)
onError(error.throwable.message ?: "Undefined error, please check your Internet connection")
onError(error.throwable)
})
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
WCDelegate.sessionAuthenticateEvent = null
onError(e.message ?: "Undefined error, please check your Internet connection")
onError(e)
}
} else {
onError("Authenticate request expired")
onError(Throwable("Authenticate request expired"))
}
}

Expand Down
Loading

0 comments on commit 75fee10

Please sign in to comment.