From bb0708d5620433ede569e52051639a80a335db43 Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Fri, 21 Jun 2024 14:19:07 +0200 Subject: [PATCH 01/12] update mobile connect flow and UI --- .../babylon/wallet/android/MainActivity.kt | 10 +- .../com/babylon/wallet/android/WalletApp.kt | 14 +- .../data/dapp/IncomingRequestRepository.kt | 82 +- .../android/data/dapp/PeerdroidClient.kt | 2 +- .../android/domain/model/IncomingMessage.kt | 7 +- .../domain/model/deeplink/DeepLinkEvent.kt | 10 - .../deeplink/ProcessDeepLinkUseCase.kt | 25 +- .../login/DAppAuthorizedLoginViewModel.kt | 10 +- .../login/DAppUnauthorizedLoginNav.kt | 2 +- .../login/DAppUnauthorizedLoginViewModel.kt | 14 +- .../presentation/main/MainViewModel.kt | 34 +- .../mobileconnect/MobileConnectLinkNav.kt | 36 +- .../mobileconnect/MobileConnectLinkScreen.kt | 46 +- .../MobileConnectLinkViewModel.kt | 47 +- .../presentation/navigation/NavigationHost.kt | 23 +- .../presentation/navigation/PriorityRoutes.kt | 3 +- .../status/dapp/DappInteractionDialog.kt | 19 +- .../transaction/TransactionStatusDialog.kt | 4 +- .../TransactionStatusDialogViewModel.kt | 2 +- .../transaction/TransactionReviewViewModel.kt | 13 +- .../presentation/ui/composables/Dialogs.kt | 4 +- .../wallet/android/utils/AppEventBusImpl.kt | 1 + app/src/main/res/values-en/strings.xml | 2400 ++++++++--------- .../dapp/IncomingRequestRepositoryTest.kt | 64 +- .../ChooseAccountsViewModelTest.kt | 4 +- .../login/DAppAuthorizedLoginViewModelTest.kt | 10 +- .../ApprovedDappsViewModelTest.kt | 3 +- .../dappdetail/DappDetailViewModelTest.kt | 3 +- .../TransactionReviewViewModelTest.kt | 6 +- ...nsactionReviewViewModelTestExperimental.kt | 9 +- ...ransactionReviewViewModelTestExtensions.kt | 10 +- gradle/libraries.versions.toml | 2 +- 32 files changed, 1512 insertions(+), 1407 deletions(-) delete mode 100644 app/src/main/java/com/babylon/wallet/android/domain/model/deeplink/DeepLinkEvent.kt diff --git a/app/src/main/java/com/babylon/wallet/android/MainActivity.kt b/app/src/main/java/com/babylon/wallet/android/MainActivity.kt index e71ffb876c..452d60976b 100644 --- a/app/src/main/java/com/babylon/wallet/android/MainActivity.kt +++ b/app/src/main/java/com/babylon/wallet/android/MainActivity.kt @@ -61,7 +61,10 @@ class MainActivity : FragmentActivity() { super.onCreate(savedInstanceState) cloudBackupSyncExecutor.startPeriodicChecks(lifecycleOwner = this) - intent.data?.let { viewModel.handleDeepLink(it) } + intent.data?.let { + intent.replaceExtras(Bundle()) + viewModel.handleDeepLink(it) + } setContent { RadixWalletTheme { val isVisible by balanceVisibilityObserver.isBalanceVisible.collectAsState(initial = true) @@ -100,7 +103,10 @@ class MainActivity : FragmentActivity() { override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) - intent?.data?.let { viewModel.handleDeepLink(it) } + intent?.data?.let { + this.intent.replaceExtras(Bundle()) + viewModel.handleDeepLink(it) + } } private fun setSplashExitAnimation(splashScreen: SplashScreen) { diff --git a/app/src/main/java/com/babylon/wallet/android/WalletApp.kt b/app/src/main/java/com/babylon/wallet/android/WalletApp.kt index 7e33cdc39d..52ebdbfc7b 100644 --- a/app/src/main/java/com/babylon/wallet/android/WalletApp.kt +++ b/app/src/main/java/com/babylon/wallet/android/WalletApp.kt @@ -68,26 +68,26 @@ fun WalletApp( mainViewModel.oneOffEvent.collect { event -> when (event) { is MainEvent.IncomingRequestEvent -> { + if (event.request.needVerification) { + navController.mobileConnect(event.request.interactionId) + return@collect + } when (val incomingRequest = event.request) { is IncomingMessage.IncomingRequest.TransactionRequest -> { navController.transactionReview( - requestId = incomingRequest.interactionId.toString() + requestId = incomingRequest.interactionId ) } is IncomingMessage.IncomingRequest.AuthorizedRequest -> { - navController.dAppLoginAuthorized(incomingRequest.interactionId.toString()) + navController.dAppLoginAuthorized(incomingRequest.interactionId) } is IncomingMessage.IncomingRequest.UnauthorizedRequest -> { - navController.dAppLoginUnauthorized(incomingRequest.interactionId.toString()) + navController.dAppLoginUnauthorized(incomingRequest.interactionId) } } } - - is MainEvent.MobileConnectLink -> { - navController.mobileConnect(event.request) - } } } } diff --git a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt index f325548c2f..32caf6a862 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt @@ -1,6 +1,8 @@ package com.babylon.wallet.android.data.dapp import com.babylon.wallet.android.domain.model.IncomingMessage.IncomingRequest +import com.babylon.wallet.android.utils.AppEvent +import com.babylon.wallet.android.utils.AppEventBus import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asSharedFlow @@ -17,24 +19,24 @@ interface IncomingRequestRepository { suspend fun add(incomingRequest: IncomingRequest) + suspend fun addFirst(incomingRequest: IncomingRequest) + suspend fun requestHandled(requestId: String) suspend fun pauseIncomingRequests() suspend fun resumeIncomingRequests() - fun getUnauthorizedRequest(requestId: String): IncomingRequest.UnauthorizedRequest? - - fun getTransactionWriteRequest(requestId: String): IncomingRequest.TransactionRequest? - - fun getAuthorizedRequest(requestId: String): IncomingRequest.AuthorizedRequest? + fun getRequest(requestId: String): IncomingRequest? fun removeAll() fun getAmountOfRequests(): Int } -class IncomingRequestRepositoryImpl @Inject constructor() : IncomingRequestRepository { +class IncomingRequestRepositoryImpl @Inject constructor( + private val appEventBus: AppEventBus +) : IncomingRequestRepository { private val requestQueue = LinkedList() @@ -68,9 +70,36 @@ class IncomingRequestRepositoryImpl @Inject constructor() : IncomingRequestRepos } } + /** + * There are two path of execution when using this method: + * - there is high priority screen in the queue, so the incoming request is added below it, + * taking priority over requests currently in the queue + * - there is no high priority screen: request is added at the top of queue and if there other request currently handled, + * we send a dismiss event for it so that UI can react and dismiss handling, without removing it from the queue. + * Dismissed request will be handled again when top priority one handling completes + */ + override suspend fun addFirst(incomingRequest: IncomingRequest) { + mutex.withLock { + if (requestQueue.firstOrNull() is QueueItem.HighPriorityScreen) { + requestQueue.add(1, QueueItem.RequestItem(incomingRequest)) + } else { + requestQueue.addFirst(QueueItem.RequestItem(incomingRequest)) + _currentRequestToHandle.value?.let { + Timber.d("🗂 Dismissing request with id ${it.interactionId}") + appEventBus.sendEvent(AppEvent.DismissRequestHandling(it.interactionId)) + } + handleNextRequest() + Timber.d( + "🗂 new incoming request with id ${incomingRequest.interactionId} " + + "added in list, so size now is ${getAmountOfRequests()}" + ) + } + } + } + override suspend fun requestHandled(requestId: String) { mutex.withLock { - requestQueue.removeIf { it is QueueItem.RequestItem && it.incomingRequest.interactionId.toString() == requestId } + requestQueue.removeIf { it is QueueItem.RequestItem && it.incomingRequest.interactionId == requestId } handleNextRequest() Timber.d("🗂 request $requestId handled so size of list is now: ${getAmountOfRequests()}") } @@ -83,9 +112,11 @@ class IncomingRequestRepositoryImpl @Inject constructor() : IncomingRequestRepos return } - // Put high priority item below any internal request + // Put high priority item below any internal request and mobile connect requests val topQueueItem = requestQueue.peekFirst() - if (topQueueItem is QueueItem.RequestItem && topQueueItem.incomingRequest.isInternal) { + if (topQueueItem is QueueItem.RequestItem && + (topQueueItem.incomingRequest.isInternal || topQueueItem.incomingRequest.isMobileConnectRequest) + ) { requestQueue.add(1, QueueItem.HighPriorityScreen) } else { requestQueue.addFirst(QueueItem.HighPriorityScreen) @@ -104,37 +135,14 @@ class IncomingRequestRepositoryImpl @Inject constructor() : IncomingRequestRepos } } - override fun getUnauthorizedRequest(requestId: String): IncomingRequest.UnauthorizedRequest? { + override fun getRequest(requestId: String): IncomingRequest? { val queueItem = requestQueue.find { - it is QueueItem.RequestItem && it.incomingRequest.interactionId.toString() == requestId && - it.incomingRequest is IncomingRequest.UnauthorizedRequest + it is QueueItem.RequestItem && it.incomingRequest.interactionId == requestId } if (queueItem == null) { - Timber.w("Unauthorized request with id $requestId is null") + Timber.w("Request with id $requestId is null") } - return (queueItem as? QueueItem.RequestItem)?.incomingRequest as? IncomingRequest.UnauthorizedRequest - } - - override fun getTransactionWriteRequest(requestId: String): IncomingRequest.TransactionRequest? { - val queueItem = requestQueue.find { - it is QueueItem.RequestItem && it.incomingRequest.interactionId.toString() == requestId && - it.incomingRequest is IncomingRequest.TransactionRequest - } - if (queueItem == null) { - Timber.w("Transaction request with id $requestId is null") - } - return (queueItem as? QueueItem.RequestItem)?.incomingRequest as? IncomingRequest.TransactionRequest - } - - override fun getAuthorizedRequest(requestId: String): IncomingRequest.AuthorizedRequest? { - val queueItem = requestQueue.find { - it is QueueItem.RequestItem && it.incomingRequest.interactionId.toString() == requestId && - it.incomingRequest is IncomingRequest.AuthorizedRequest - } - if (queueItem == null) { - Timber.w("Authorized request with id $requestId is null") - } - return (queueItem as? QueueItem.RequestItem)?.incomingRequest as? IncomingRequest.AuthorizedRequest + return (queueItem as? QueueItem.RequestItem)?.incomingRequest } override fun removeAll() { @@ -156,7 +164,7 @@ class IncomingRequestRepositoryImpl @Inject constructor() : IncomingRequestRepos private sealed interface QueueItem { data object HighPriorityScreen : QueueItem - data class RequestItem(val incomingRequest: IncomingRequest) : QueueItem + data class MobileConnectItem(val incomingRequest: IncomingRequest) : QueueItem } } diff --git a/app/src/main/java/com/babylon/wallet/android/data/dapp/PeerdroidClient.kt b/app/src/main/java/com/babylon/wallet/android/data/dapp/PeerdroidClient.kt index d38c4d6767..2a7c612446 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/dapp/PeerdroidClient.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/dapp/PeerdroidClient.kt @@ -146,7 +146,7 @@ class PeerdroidClientImpl @Inject constructor( if (interactionVersion != Constants.WALLET_INTERACTION_VERSION) { throw IncompatibleRequestVersionException( requestVersion = interactionVersion, - requestId = dappInteraction.interactionId.toString() + requestId = dappInteraction.interactionId ) } dappInteraction.toDomainModel(remoteEntityId = IncomingMessage.RemoteEntityID.ConnectorId(remoteConnectorId)).getOrThrow() diff --git a/app/src/main/java/com/babylon/wallet/android/domain/model/IncomingMessage.kt b/app/src/main/java/com/babylon/wallet/android/domain/model/IncomingMessage.kt index 7c42c4ccfa..c7ec002a3a 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/model/IncomingMessage.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/model/IncomingMessage.kt @@ -25,9 +25,11 @@ sealed interface IncomingMessage { val value: String - data class RadixMobileConnectRemoteSession(val id: String) : RemoteEntityID { + data class RadixMobileConnectRemoteSession(val id: String, val originVerificationUrl: String? = null) : RemoteEntityID { override val value: String get() = id + + val needOriginVerification: Boolean = originVerificationUrl != null } data class ConnectorId(val id: String) : RemoteEntityID { @@ -50,6 +52,9 @@ sealed interface IncomingMessage { val isMobileConnectRequest: Boolean get() = remoteEntityId is RemoteEntityID.RadixMobileConnectRemoteSession + val needVerification: Boolean + get() = (remoteEntityId as? RemoteEntityID.RadixMobileConnectRemoteSession)?.needOriginVerification == true + val blockUntilComplete: Boolean get() { return metadata.blockUntilCompleted diff --git a/app/src/main/java/com/babylon/wallet/android/domain/model/deeplink/DeepLinkEvent.kt b/app/src/main/java/com/babylon/wallet/android/domain/model/deeplink/DeepLinkEvent.kt deleted file mode 100644 index 74a45a9ad1..0000000000 --- a/app/src/main/java/com/babylon/wallet/android/domain/model/deeplink/DeepLinkEvent.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.babylon.wallet.android.domain.model.deeplink - -import com.radixdlt.sargon.RadixConnectMobileSessionRequest - -sealed interface DeepLinkEvent { - - data class MobileConnectVerifyRequest( - val request: RadixConnectMobileSessionRequest - ) : DeepLinkEvent -} diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt index 069246d26c..e02694f3e5 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt @@ -3,7 +3,6 @@ package com.babylon.wallet.android.domain.usecases.deeplink import com.babylon.wallet.android.data.dapp.IncomingRequestRepository import com.babylon.wallet.android.data.dapp.model.toDomainModel import com.babylon.wallet.android.domain.model.IncomingMessage -import com.babylon.wallet.android.domain.model.deeplink.DeepLinkEvent import com.radixdlt.sargon.RadixConnectMobile import timber.log.Timber import javax.inject.Inject @@ -13,23 +12,19 @@ class ProcessDeepLinkUseCase @Inject constructor( private val incomingRequestRepository: IncomingRequestRepository ) { - suspend operator fun invoke(deepLink: String): DeepLinkEvent? { + suspend operator fun invoke(deepLink: String) { val sessionRequest = runCatching { radixConnectMobile.handleDeepLink(deepLink) }.onFailure { Timber.d("Failed to parse deep link: $deepLink. Error: ${it.message}") - return null + return }.getOrThrow() - return if (sessionRequest.originRequiresValidation) { - DeepLinkEvent.MobileConnectVerifyRequest( - request = sessionRequest - ) - } else { - incomingRequestRepository.add( - sessionRequest.interaction.toDomainModel( - remoteEntityId = IncomingMessage.RemoteEntityID.RadixMobileConnectRemoteSession(sessionRequest.sessionId.toString()) - ).getOrThrow() - ) - null - } + incomingRequestRepository.addFirst( + sessionRequest.interaction.toDomainModel( + remoteEntityId = IncomingMessage.RemoteEntityID.RadixMobileConnectRemoteSession( + id = sessionRequest.sessionId.toString(), + originVerificationUrl = if (sessionRequest.originRequiresValidation) sessionRequest.origin else null + ) + ).getOrThrow() + ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt index 0ab6b9ffe4..af849bff6d 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt @@ -45,6 +45,7 @@ import com.radixdlt.sargon.SharedToDappWithPersonaAccountAddresses import com.radixdlt.sargon.extensions.ReferencesToAuthorizedPersonas import com.radixdlt.sargon.extensions.init import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex @@ -92,9 +93,16 @@ class DAppAuthorizedLoginViewModel @Inject constructor( override fun initialState(): DAppLoginUiState = DAppLoginUiState() init { + viewModelScope.launch { + appEventBus.events.filterIsInstance().collect { + if (it.interactionId == args.interactionId) { + sendEvent(Event.CloseLoginFlow) + } + } + } observeSigningState() viewModelScope.launch { - val requestToHandle = incomingRequestRepository.getAuthorizedRequest(args.interactionId) + val requestToHandle = incomingRequestRepository.getRequest(args.interactionId) as? AuthorizedRequest if (requestToHandle == null) { sendEvent(Event.CloseLoginFlow) return@launch diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginNav.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginNav.kt index c53acf44e7..869fc3c0ba 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginNav.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginNav.kt @@ -17,7 +17,7 @@ internal const val ARG_REQUEST_ID = "request_id" const val ROUTE_DAPP_LOGIN_UNAUTHORIZED_GRAPH = "dapp_login_unauthorized/{$ARG_REQUEST_ID}" const val ROUTE_DAPP_LOGIN_UNAUTHORIZED_SCREEN = "dapp_login_unauthorized_screen/{$ARG_REQUEST_ID}" -internal class DAppUnauthorizedLoginArgs(val requestId: String) { +internal class DAppUnauthorizedLoginArgs(val interactionId: String) { constructor(savedStateHandle: SavedStateHandle) : this(checkNotNull(savedStateHandle[ARG_REQUEST_ID]) as String) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt index cf6d3edfe3..e6f0ae81eb 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt @@ -35,6 +35,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import rdx.works.core.domain.DApp @@ -69,7 +70,14 @@ class DAppUnauthorizedLoginViewModel @Inject constructor( init { observeSigningState() viewModelScope.launch { - val requestToHandle = incomingRequestRepository.getUnauthorizedRequest(args.requestId) + appEventBus.events.filterIsInstance().collect { + if (it.interactionId == args.interactionId) { + sendEvent(Event.CloseLoginFlow) + } + } + } + viewModelScope.launch { + val requestToHandle = incomingRequestRepository.getRequest(args.interactionId) as? IncomingMessage.IncomingRequest.UnauthorizedRequest if (requestToHandle == null) { sendEvent(Event.CloseLoginFlow) return@launch @@ -187,7 +195,7 @@ class DAppUnauthorizedLoginViewModel @Inject constructor( respondToIncomingRequestUseCase.respondWithFailure(request, exception.ceError, exception.getDappMessage()) _state.update { it.copy(failureDialogState = FailureDialogState.Closed) } sendEvent(Event.CloseLoginFlow) - incomingRequestRepository.requestHandled(requestId = args.requestId) + incomingRequestRepository.requestHandled(requestId = args.interactionId) } fun onMessageShown() { @@ -218,7 +226,7 @@ class DAppUnauthorizedLoginViewModel @Inject constructor( fun onRejectRequest() { viewModelScope.launch { - incomingRequestRepository.requestHandled(requestId = args.requestId) + incomingRequestRepository.requestHandled(requestId = args.interactionId) respondToIncomingRequestUseCase.respondWithFailure(request, DappWalletInteractionErrorType.REJECTED_BY_USER) sendEvent(Event.CloseLoginFlow) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt index 777f2cee5a..d671825b5d 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt @@ -7,7 +7,6 @@ import com.babylon.wallet.android.data.dapp.PeerdroidClient import com.babylon.wallet.android.data.repository.p2plink.P2PLinksRepository import com.babylon.wallet.android.domain.RadixWalletException import com.babylon.wallet.android.domain.model.IncomingMessage.IncomingRequest -import com.babylon.wallet.android.domain.model.deeplink.DeepLinkEvent import com.babylon.wallet.android.domain.usecases.AuthorizeSpecifiedPersonaUseCase import com.babylon.wallet.android.domain.usecases.VerifyDAppUseCase import com.babylon.wallet.android.domain.usecases.deeplink.ProcessDeepLinkUseCase @@ -23,7 +22,6 @@ import com.babylon.wallet.android.utils.DeviceCapabilityHelper import com.radixdlt.sargon.Account import com.radixdlt.sargon.NetworkId import com.radixdlt.sargon.Persona -import com.radixdlt.sargon.RadixConnectMobileSessionRequest import com.radixdlt.sargon.RadixConnectPassword import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -214,14 +212,14 @@ class MainViewModel @Inject constructor( private fun handleAllIncomingRequests() { viewModelScope.launch { incomingRequestRepository.currentRequestToHandle.collect { request -> - if (request.metadata.isInternal) { + if (request.metadata.isInternal || request.isMobileConnectRequest) { sendEvent(MainEvent.IncomingRequestEvent(request)) } else { delay(REQUEST_HANDLING_DELAY) authorizeSpecifiedPersonaUseCase.invoke(request).onSuccess { dAppData -> appEventBus.sendEvent( AppEvent.Status.DappInteraction( - requestId = dAppData.interactionId.toString(), + requestId = dAppData.interactionId, dAppName = dAppData.name ) ) @@ -230,7 +228,7 @@ class MainViewModel @Inject constructor( when (dappRequestFailure) { RadixWalletException.DappRequestException.InvalidPersona, RadixWalletException.DappRequestException.InvalidRequest -> { - incomingRequestRepository.requestHandled(request.interactionId.toString()) + incomingRequestRepository.requestHandled(request.interactionId) _state.update { state -> state.copy(dappRequestFailure = dappRequestFailure) } @@ -248,9 +246,8 @@ class MainViewModel @Inject constructor( } fun handleDeepLink(deepLink: Uri) { - Timber.d("dApp deep link: $deepLink") - viewModelScope.launch { + delay(REQUEST_HANDLING_DELAY) val profileInitialized = getProfileUseCase.isInitialized() if (!profileInitialized) { _state.update { @@ -261,10 +258,6 @@ class MainViewModel @Inject constructor( runCatching { processDeepLinkUseCase(deepLink.toString()) - }.onSuccess { event -> - if (event is DeepLinkEvent.MobileConnectVerifyRequest) { - sendEvent(MainEvent.MobileConnectLink(event.request)) - } }.onFailure { Timber.d(it) } @@ -273,13 +266,17 @@ class MainViewModel @Inject constructor( private fun verifyIncomingRequest(request: IncomingRequest) { verifyingDappRequestJob = viewModelScope.launch { - verifyDappUseCase(request).onSuccess { verified -> - if (verified) { - incomingRequestRepository.add(request) - } - }.onFailure { - _state.update { state -> - state.copy(dappRequestFailure = RadixWalletException.DappRequestException.InvalidRequest) + if (request.isMobileConnectRequest) { + incomingRequestRepository.add(request) + } else { + verifyDappUseCase(request).onSuccess { verified -> + if (verified) { + incomingRequestRepository.add(request) + } + }.onFailure { + _state.update { state -> + state.copy(dappRequestFailure = RadixWalletException.DappRequestException.InvalidRequest) + } } } } @@ -354,7 +351,6 @@ class MainViewModel @Inject constructor( sealed class MainEvent : OneOffEvent { data class IncomingRequestEvent(val request: IncomingRequest) : MainEvent() - data class MobileConnectLink(val request: RadixConnectMobileSessionRequest) : MainEvent() } data class MainUiState( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkNav.kt b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkNav.kt index 68f47a3e93..8d98b51c95 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkNav.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkNav.kt @@ -7,35 +7,36 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavType import androidx.navigation.compose.composable import androidx.navigation.navArgument -import com.radixdlt.sargon.RadixConnectMobileSessionRequest -import com.radixdlt.sargon.extensions.fromJson -import com.radixdlt.sargon.extensions.toJson +import com.babylon.wallet.android.presentation.navigation.markAsHighPriority -private const val ARG_REQUEST = "request" -private const val ROUTE_ARGS = "$ARG_REQUEST={$ARG_REQUEST}" -private const val ROUTE = "mobileConnect?$ROUTE_ARGS" +private const val ARG_INTERACTION_ID = "interactionId" +private const val ROUTE = "mobileConnect/{$ARG_INTERACTION_ID}" fun NavController.mobileConnect( - request: RadixConnectMobileSessionRequest + interactionId: String ) { - navigate(route = "mobileConnect?$ARG_REQUEST=${request.toJson()}") + navigate(route = "mobileConnect/$interactionId") } internal class MobileConnectArgs( - val request: RadixConnectMobileSessionRequest + val interactionId: String ) { constructor(savedStateHandle: SavedStateHandle) : this( - request = checkNotNull(savedStateHandle.get(ARG_REQUEST)).let { - RadixConnectMobileSessionRequest.fromJson(it) - } + interactionId = checkNotNull(savedStateHandle.get(ARG_INTERACTION_ID)) ) } -fun NavGraphBuilder.mobileConnect(onBackClick: () -> Unit) { +fun NavGraphBuilder.mobileConnect( + onBackClick: () -> Unit, + onHandleRequestAuthorizedRequest: (String) -> Unit, + onHandleUnauthorizedRequest: (String) -> Unit, + onHandleTransactionRequest: (String) -> Unit +) { + markAsHighPriority(route = ROUTE) composable( route = ROUTE, arguments = listOf( - navArgument(ARG_REQUEST) { + navArgument(ARG_INTERACTION_ID) { type = NavType.StringType } ), @@ -46,6 +47,11 @@ fun NavGraphBuilder.mobileConnect(onBackClick: () -> Unit) { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Down) } ) { - MobileConnectLinkScreen(onClose = onBackClick) + MobileConnectLinkScreen( + onClose = onBackClick, + onHandleRequestAuthorizedRequest = onHandleRequestAuthorizedRequest, + onHandleUnauthorizedRequest = onHandleUnauthorizedRequest, + onHandleTransactionRequest = onHandleTransactionRequest + ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkScreen.kt index 5ade22f073..3cb9a7cf0a 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkScreen.kt @@ -1,6 +1,7 @@ package com.babylon.wallet.android.presentation.mobileconnect import androidx.activity.compose.BackHandler +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets @@ -25,10 +26,12 @@ import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme +import com.babylon.wallet.android.domain.model.IncomingMessage import com.babylon.wallet.android.presentation.ui.RadixWalletPreviewTheme import com.babylon.wallet.android.presentation.ui.composables.BackIconType import com.babylon.wallet.android.presentation.ui.composables.BottomPrimaryButton @@ -43,13 +46,31 @@ import com.radixdlt.sargon.annotation.UsesSampleValues fun MobileConnectLinkScreen( modifier: Modifier = Modifier, viewModel: MobileConnectLinkViewModel = hiltViewModel(), - onClose: () -> Unit + onClose: () -> Unit, + onHandleRequestAuthorizedRequest: (String) -> Unit, + onHandleUnauthorizedRequest: (String) -> Unit, + onHandleTransactionRequest: (String) -> Unit ) { val state by viewModel.state.collectAsStateWithLifecycle() LaunchedEffect(Unit) { viewModel.oneOffEvent.collect { event -> when (event) { MobileConnectLinkViewModel.Event.Close -> onClose() + is MobileConnectLinkViewModel.Event.HandleRequest -> { + when (event.request) { + is IncomingMessage.IncomingRequest.AuthorizedRequest -> { + onHandleRequestAuthorizedRequest(event.request.interactionId) + } + + is IncomingMessage.IncomingRequest.TransactionRequest -> { + onHandleTransactionRequest(event.request.interactionId) + } + + is IncomingMessage.IncomingRequest.UnauthorizedRequest -> { + onHandleUnauthorizedRequest(event.request.interactionId) + } + } + } } } } @@ -126,9 +147,9 @@ fun MobileConnectLinkContent( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXXLarge), - text = stringResource(id = R.string.mobileConnect_verifyingDApp_title, dAppDisplayName), + text = stringResource(id = R.string.mobileConnect_title), color = RadixTheme.colors.gray1, - style = RadixTheme.typography.title, // TODO Mobile Connect (UI) + style = RadixTheme.typography.title, textAlign = TextAlign.Center ) @@ -139,7 +160,7 @@ fun MobileConnectLinkContent( .padding(horizontal = RadixTheme.dimensions.paddingXXXLarge), text = buildAnnotatedString { val valueToDisplay = stringResource( - id = R.string.mobileConnect_verifyingDApp_subtitle, + id = R.string.mobileConnect_subtitle, dAppDisplayName ) @@ -147,25 +168,26 @@ fun MobileConnectLinkContent( val startOfSpan = valueToDisplay.indexOf(dAppDisplayName) addStyle( - style = RadixTheme.typography.body1StandaloneLink.toSpanStyle(), // TODO Mobile Connect (UI) + style = RadixTheme.typography.body2Header.copy(fontSize = 16.sp).toSpanStyle(), start = startOfSpan, end = startOfSpan + dAppDisplayName.length, ) }, - color = RadixTheme.colors.gray2, - style = RadixTheme.typography.body1HighImportance, // TODO Mobile Connect (UI) + color = RadixTheme.colors.gray1, + style = RadixTheme.typography.body1HighImportance, textAlign = TextAlign.Center ) - - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingXXXLarge)) Text( modifier = Modifier .fillMaxWidth() - .padding(horizontal = RadixTheme.dimensions.paddingXXXLarge), - text = stringResource(id = R.string.mobileConnect_verifyingDApp_body), + .padding(horizontal = RadixTheme.dimensions.paddingXXXLarge) + .background(color = RadixTheme.colors.gray5, shape = RadixTheme.shapes.roundedRectSmall) + .padding(RadixTheme.dimensions.paddingSmall), + text = stringResource(id = R.string.mobileConnect_body), color = RadixTheme.colors.gray1, style = RadixTheme.typography.body1Regular, // TODO Mobile Connect (UI) - textAlign = TextAlign.Center + textAlign = TextAlign.Start ) Spacer(modifier = Modifier.weight(1f)) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkViewModel.kt index e45d36482d..785e9e44bb 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkViewModel.kt @@ -3,8 +3,8 @@ package com.babylon.wallet.android.presentation.mobileconnect import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import com.babylon.wallet.android.data.dapp.IncomingRequestRepository -import com.babylon.wallet.android.data.dapp.model.toDomainModel import com.babylon.wallet.android.data.repository.dapps.WellKnownDAppDefinitionRepository +import com.babylon.wallet.android.domain.model.IncomingMessage import com.babylon.wallet.android.domain.model.IncomingMessage.RemoteEntityID.RadixMobileConnectRemoteSession import com.babylon.wallet.android.domain.usecases.GetDAppsUseCase import com.babylon.wallet.android.presentation.common.OneOffEvent @@ -13,14 +13,12 @@ import com.babylon.wallet.android.presentation.common.OneOffEventHandlerImpl import com.babylon.wallet.android.presentation.common.StateViewModel import com.babylon.wallet.android.presentation.common.UiMessage import com.babylon.wallet.android.presentation.common.UiState -import com.radixdlt.sargon.RadixConnectMobile import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import rdx.works.core.domain.DApp import rdx.works.core.then import rdx.works.profile.domain.GetProfileUseCase -import timber.log.Timber import javax.inject.Inject @Suppress("LongParameterList") @@ -30,17 +28,26 @@ class MobileConnectLinkViewModel @Inject constructor( private val wellKnownDAppDefinitionRepository: WellKnownDAppDefinitionRepository, private val getProfileUseCase: GetProfileUseCase, private val getDAppsUseCase: GetDAppsUseCase, - private val radixConnectMobile: RadixConnectMobile, private val incomingRequestRepository: IncomingRequestRepository ) : StateViewModel(), OneOffEventHandler by OneOffEventHandlerImpl() { private val args = MobileConnectArgs(savedStateHandle) + + private lateinit var request: IncomingMessage.IncomingRequest + override fun initialState(): State { return State() } init { viewModelScope.launch { + val requestToHandle = incomingRequestRepository.getRequest(args.interactionId) + if (requestToHandle == null) { + sendEvent(Event.Close) + return@launch + } else { + request = requestToHandle + } val developerMode = getProfileUseCase().appPreferences.security.isDeveloperModeEnabled _state.update { it.copy( @@ -48,9 +55,9 @@ class MobileConnectLinkViewModel @Inject constructor( isInDevMode = developerMode ) } - + val remoteId = request.remoteEntityId as? RadixMobileConnectRemoteSession ?: return@launch wellKnownDAppDefinitionRepository.getWellKnownDappDefinitions( - origin = args.request.origin.toString() + origin = remoteId.originVerificationUrl.toString() ).then { dAppDefinitions -> val dAppDefinition = dAppDefinitions.dAppDefinitions.firstOrNull() if (dAppDefinition != null) { @@ -76,20 +83,8 @@ class MobileConnectLinkViewModel @Inject constructor( _state.update { it.copy(isVerifying = true) } - - runCatching { - radixConnectMobile.requestOriginVerified(sessionId = args.request.sessionId) - args.request.interaction.toDomainModel( - remoteEntityId = RadixMobileConnectRemoteSession(id = args.request.sessionId.toString()) - ).getOrThrow() - }.onSuccess { request -> - incomingRequestRepository.add(request) - sendEvent(Event.Close) - }.onFailure { error -> - Timber.w(error) - _state.update { - it.copy(uiMessage = UiMessage.ErrorMessage(error), isVerifying = false) - } + viewModelScope.launch { + sendEvent(Event.HandleRequest(request)) } } @@ -97,21 +92,15 @@ class MobileConnectLinkViewModel @Inject constructor( _state.update { it.copy(isVerifying = true) } - - runCatching { - radixConnectMobile.requestOriginDenied(sessionId = args.request.sessionId) - }.onSuccess { + viewModelScope.launch { + incomingRequestRepository.requestHandled(args.interactionId) sendEvent(Event.Close) - }.onFailure { error -> - Timber.w(error) - _state.update { - it.copy(uiMessage = UiMessage.ErrorMessage(error), isVerifying = false) - } } } sealed class Event : OneOffEvent { data object Close : Event() + data class HandleRequest(val request: IncomingMessage.IncomingRequest) : Event() } data class State( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt b/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt index 24dd0a99fb..70bd339c59 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt @@ -27,8 +27,10 @@ import com.babylon.wallet.android.presentation.account.settings.specificassets.s import com.babylon.wallet.android.presentation.account.settings.specificdepositor.specificDepositor import com.babylon.wallet.android.presentation.account.settings.thirdpartydeposits.accountThirdPartyDeposits import com.babylon.wallet.android.presentation.dapp.authorized.dappLoginAuthorizedNavGraph +import com.babylon.wallet.android.presentation.dapp.authorized.login.dAppLoginAuthorized import com.babylon.wallet.android.presentation.dapp.completion.ChooseAccountsCompletionScreen import com.babylon.wallet.android.presentation.dapp.unauthorized.dappLoginUnauthorizedNavGraph +import com.babylon.wallet.android.presentation.dapp.unauthorized.login.dAppLoginUnauthorized import com.babylon.wallet.android.presentation.incompatibleprofile.IncompatibleProfileContent import com.babylon.wallet.android.presentation.incompatibleprofile.ROUTE_INCOMPATIBLE_PROFILE import com.babylon.wallet.android.presentation.main.MAIN_ROUTE @@ -71,6 +73,7 @@ import com.babylon.wallet.android.presentation.status.dapp.dAppDetailsDialog import com.babylon.wallet.android.presentation.status.dapp.dappInteractionDialog import com.babylon.wallet.android.presentation.status.transaction.transactionStatusDialog import com.babylon.wallet.android.presentation.survey.npsSurveyDialog +import com.babylon.wallet.android.presentation.transaction.transactionReview import com.babylon.wallet.android.presentation.transaction.transactionReviewScreen import com.babylon.wallet.android.presentation.transfer.transfer import com.babylon.wallet.android.presentation.transfer.transferScreen @@ -527,8 +530,22 @@ fun NavigationHost( navController.popBackStack() } ) - mobileConnect(onBackClick = { - navController.popBackStack() - }) + mobileConnect( + onBackClick = { + navController.popBackStack() + }, + onHandleRequestAuthorizedRequest = { + navController.popBackStack() + navController.dAppLoginAuthorized(it) + }, + onHandleUnauthorizedRequest = { + navController.popBackStack() + navController.dAppLoginUnauthorized(it) + }, + onHandleTransactionRequest = { + navController.popBackStack() + navController.transactionReview(it) + } + ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/navigation/PriorityRoutes.kt b/app/src/main/java/com/babylon/wallet/android/presentation/navigation/PriorityRoutes.kt index 6cc7db055d..930792b8d7 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/navigation/PriorityRoutes.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/navigation/PriorityRoutes.kt @@ -1,7 +1,6 @@ package com.babylon.wallet.android.presentation.navigation import androidx.navigation.NavBackStackEntry -import androidx.navigation.NavGraphBuilder object PriorityRoutes { @@ -14,6 +13,6 @@ object PriorityRoutes { } } -fun NavGraphBuilder.markAsHighPriority(route: String) { +fun markAsHighPriority(route: String) { PriorityRoutes.add(route = route) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/dapp/DappInteractionDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/dapp/DappInteractionDialog.kt index 602b3fc464..3a1a12ee54 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/dapp/DappInteractionDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/dapp/DappInteractionDialog.kt @@ -73,20 +73,21 @@ private fun DappInteractionDialogContent( contentDescription = null ) Text( - text = stringResource(id = R.string.transactionStatus_success_title), + text = stringResource(id = R.string.dAppRequest_completion_title), style = RadixTheme.typography.title, color = RadixTheme.colors.gray1 ) - Text( - text = stringResource(id = R.string.dAppRequest_completion_subtitle, state.dAppName), - style = RadixTheme.typography.body1Regular, - color = RadixTheme.colors.gray1, - textAlign = TextAlign.Center - ) if (state.isMobileConnect) { Text( - text = "You can return back to the dApp!", - style = RadixTheme.typography.body1HighImportance, + text = "Switch back to your browser to continue", // TODO crowdin + style = RadixTheme.typography.body1Regular, + color = RadixTheme.colors.gray1, + textAlign = TextAlign.Center + ) + } else { + Text( + text = stringResource(id = R.string.dAppRequest_completion_subtitle, state.dAppName), + style = RadixTheme.typography.body1Regular, color = RadixTheme.colors.gray1, textAlign = TextAlign.Center ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/transaction/TransactionStatusDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/transaction/TransactionStatusDialog.kt index 66acf6d946..7bcb84887d 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/transaction/TransactionStatusDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/transaction/TransactionStatusDialog.kt @@ -193,8 +193,8 @@ private fun SuccessContent( } if (isMobileConnect) { Text( - text = "You can return back to the dApp!", - style = RadixTheme.typography.body1HighImportance, + text = "Switch back to your browser to continue", + style = RadixTheme.typography.body1Regular, color = RadixTheme.colors.gray1, textAlign = TextAlign.Center ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/transaction/TransactionStatusDialogViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/transaction/TransactionStatusDialogViewModel.kt index 4e735bca50..bda6a771cb 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/transaction/TransactionStatusDialogViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/transaction/TransactionStatusDialogViewModel.kt @@ -94,7 +94,7 @@ class TransactionStatusDialogViewModel @Inject constructor( }.onFailure { error -> if (!status.isInternal) { (error as? RadixWalletException.TransactionSubmitException)?.let { exception -> - incomingRequestRepository.getTransactionWriteRequest(status.requestId)?.let { transactionRequest -> + incomingRequestRepository.getRequest(status.requestId)?.let { transactionRequest -> respondToIncomingRequestUseCase.respondWithFailure( request = transactionRequest, error = exception.ceError, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt index 4143e9f7ee..54a818109e 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt @@ -24,6 +24,8 @@ import com.babylon.wallet.android.presentation.transaction.fees.TransactionFees import com.babylon.wallet.android.presentation.transaction.fees.TransactionFeesDelegate import com.babylon.wallet.android.presentation.transaction.guarantees.TransactionGuaranteesDelegate import com.babylon.wallet.android.presentation.transaction.submit.TransactionSubmitDelegate +import com.babylon.wallet.android.utils.AppEvent +import com.babylon.wallet.android.utils.AppEventBus import com.radixdlt.sargon.Account import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.Address @@ -45,6 +47,7 @@ import com.radixdlt.sargon.extensions.times import com.radixdlt.sargon.extensions.toDecimal192 import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.ImmutableList +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import rdx.works.core.domain.DApp @@ -60,6 +63,7 @@ import javax.inject.Inject @Suppress("LongParameterList", "TooManyFunctions") @HiltViewModel class TransactionReviewViewModel @Inject constructor( + private val appEventBus: AppEventBus, private val signTransactionUseCase: SignTransactionUseCase, private val analysis: TransactionAnalysisDelegate, private val guarantees: TransactionGuaranteesDelegate, @@ -84,7 +88,7 @@ class TransactionReviewViewModel @Inject constructor( fees(scope = viewModelScope, state = _state) submit(scope = viewModelScope, state = _state) - val request = incomingRequestRepository.getTransactionWriteRequest(args.requestId) + val request = incomingRequestRepository.getRequest(args.requestId) as? IncomingMessage.IncomingRequest.TransactionRequest if (request == null) { viewModelScope.launch { _state.update { state -> @@ -112,6 +116,13 @@ class TransactionReviewViewModel @Inject constructor( } } } + viewModelScope.launch { + appEventBus.events.filterIsInstance().collect { + _state.update { state -> + state.copy(isTransactionDismissed = true) + } + } + } } fun onBackClick() { diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/Dialogs.kt b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/Dialogs.kt index 5e9cb8068e..5ed02734af 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/Dialogs.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/Dialogs.kt @@ -484,8 +484,8 @@ fun FailureDialogContent( } if (isMobileConnect) { Text( - text = "You can return back to the dApp!", - style = RadixTheme.typography.body1HighImportance, + text = "Switch back to your browser to continue", // TODO crowdin + style = RadixTheme.typography.body1Regular, color = RadixTheme.colors.gray1, textAlign = TextAlign.Center ) diff --git a/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt b/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt index a7ac91bb20..748014f235 100644 --- a/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt +++ b/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt @@ -33,6 +33,7 @@ sealed interface AppEvent { data object NPSSurveySubmitted : AppEvent data object SecureFolderWarning : AppEvent + data class DismissRequestHandling(val interactionId: String) : AppEvent sealed interface AccessFactorSources : AppEvent { data class SelectedLedgerDevice(val ledgerFactorSource: FactorSource.Ledger) : AccessFactorSources diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 585446b7af..23f49d2a23 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -1,1207 +1,1205 @@ - Please write down seed phrase to ensure Account control - Seed phrase required - begin entry - I have written down this seed phrase - Create a New Account - Legacy - Welcome. Here are all your Accounts on the Radix Network. - Radix Wallet - Total value - dApp Definition - Legacy - Legacy (Ledger) - Ledger - Visit the Radix Dashboard - Ready to get started using the Radix Network and your Wallet? - SERIOUS ERROR - PLEASE READ - Your wallet is in a rare condition that must be resolved manually. Please email support at hello@radixdlt.com with subject line BDFS ERROR. Somebody will respond and help you resolve the issue safely. - Affected Accounts - Affected Personas - OK (%d) - Start Using Radix - Complete setting up your wallet and start staking, using dApps and more! - Get Started Now - Your wallet has encountered a problem that should be resolved before you continue use. If you have a Samsung phone, this may be caused by putting the Radix Wallet in the \"Secure Folder\". Please contact support at hello@radixdlt.com for assistance. - Transfer - Tokens - NFTs - Staking - Radix Network XRD Stake Summary - STAKED VALIDATORS (%d) - Unstaking - Ready to Claim - Ready to be claimed - Staked - Current Stake: %s - Liquid Stake Units - Stake Claim NFTs - WORTH - Claim - Pool Units - Unknown - Unknown - Unknown - Current Redeemable Value - Missing Total supply - could not calculate redemption value - Badges - Address - Validator - Name - Current Supply - Unknown - Behavior - Ready to claim in about %d minutes or less. - Tags - Official Radix - Associated dApps - You have no Tokens - What are Tokens? - You have no NFTs - What are NFTs? - ID - Name - Description - complex data - Name - %d NFTs - %d NFTs of total supply %d - You have no Stakes - What is Staking? - You have no Pool units - What are Pool units? - You have no badges - What are badges? - Hide Asset - Hide this asset in your Radix Wallet? You can always unhide it in your account settings. - Hide Asset - This is a simple asset - The supply of this asset can be increased. - The supply of this asset can be decreased. - The supply of this asset can be increased or decreased. - Only the Radix Network may increase or decrease the supply of XRD. - Anyone can increase the supply of this asset. - Anyone can decrease the supply of this asset. - Anyone can increase or decrease the supply of this asset. - Movement of this asset is restricted. - Movement of this asset can be restricted in the future. - Anyone can restrict movement of this token in the future. - Naming and information about this asset can be changed. - Anyone can change naming and information about this asset. - A third party can remove this asset from accounts and dApps. - Anyone can remove this asset from accounts and dApps. - A third party can freeze this asset in place. - Anyone can freeze this asset in place. - Data that is set on these NFTs can be changed. - Anyone can change data that is set on these NFTs. - Account Settings - Personalize this Account - Account Label - Account Color - Select from a list of unique colors - Show Assets with Tags - Show Account QR Code - Updated - Select which tags to show for assets in this Account - Set how you want this Account to work - Third-party Deposits - Hide Account - Account Hidden - Get XRD Test Tokens - This may take several seconds, please wait for completion - Rename Account - Enter a new label for this Account - Update - Select the color for this Account - Selected - Hide This Account - Hide this Account in your wallet? You can always unhide it from the main application settings. - Hide Account - Choose if you want to allow third parties to directly deposit assets into your Account. Deposits that you approve yourself in your Radix Wallet are always accepted. - Accept all deposits - Allow third-parties to deposit any asset - Only accept known - Allow third-parties to deposit only assets this Account already holds - Deny all - Deny all third-party deposits - This account will not be able to receive \"air drops\" or be used by a trusted contact to assist with account recovery. - Discard Changes - Keep Editing - Are you sure you want to discard changes? - Allow/Deny specific assets - Deny or allow third-party deposits of specific assets, ignoring the setting above - Add a Depositor Badge - Enter the badge’s resource address (starting with “reso”) - Allow specific depositors - Allow certain third party depositors to deposit assets freely - Add Depositor Badge - Remove Asset - The asset will be removed from the deny list - The asset will be removed from the allow list - The badge will be removed from the list - Remove Depositor - The depositor will be removed from the allow list - Allow/Deny Specific Assets - Update - Allow - Deny - Add a specific asset by its resource address to allow all third-party deposits - Add a specific asset by its resource address to deny all third-party deposits - Add an Asset - Enter the asset’s resource address (starting with “reso”) - Resource Address - Allow Deposits - Deny Deposits - Add Asset - The following resource addresses may always be deposited to this account by third parties. - The following resource addresses may never be deposited to this account by third parties. - Add a specific badge by its resource address to allow all deposits from its holder. - The holder of the following badges may always deposit accounts to this account. - Select exception list - Sorry, this Account\'s third-party exceptions and depositor lists are in an unknown state and cannot be viewed or edited because it was imported using only a seed phrase or Ledger. A forthcoming wallet update will enable viewing and editing of these lists. - Asset creators can add tags to them. You can choose which tags you want to see in this Account. - Select the ones you’d like shown on all your assets. - Recommended - Set development preferences - Dev Preferences - Hide This Account - Are you sure you want to hide this account? - Settings - Authorized dApps - Personas - Account Security & Settings - App Settings - Please write down the seed phrase for your Personas - Link your Wallet to a Desktop Browser - Scan the QR code in the Radix Wallet Connector extension - Link to Connector - Radix Olympia Desktop Wallet user? - Get started importing your Olympia accounts into your new Radix Wallet - Import Legacy Accounts - Version: %s build #%s - Linked Connectors - Connect your Radix Wallet to desktop web browsers by linking to the Radix Connector browser extension. Here are your linked Connectors. - Last connected %s - Link New Connector - Link New Connector - Open your Radix Connector extension\'s menu by clicking its icon in your list of browser extensions, and scan the QR code shown. - Linking… - Name New Connector - What would you like to call this Radix Connector installation? - e.g. Chrome on Personal Laptop - Name this connector e.g. ‘Chrome on MacBook Pro’ - Continue - Remove Connection - You will no longer be able to connect your wallet to this device and browser combination. - Remove - Access Required - Camera access is required to link to a Connector. - Access Required - Local network access is required to link to a Connector. - Incorrect QR code scanned. - Please scan the QR code provided by your Radix Wallet Connector browser extension. - Link Connector - Update Link - This Connector will be trusted to verify the dApp origin of requests to this wallet.\n\nOnly continue if you are linking to the **official Radix Connector browser extension** - or a Connector you control and trust. - This appears to be a Radix Connector you previously linked to. Link will be updated. - Link Failed - This type of Connector link is not supported. - Changing a Connector’s type is not supported. - This is an old version of the Radix Connector browser extension. Please update to the latest Connector and try linking again. - Re-link Connector - Radix Connector now supports linking multiple phones with one browser.\n\nTo support this feature, we\'ve had to disconnect your existing links – **please re-link your Connector(s).** - Any Connectors you had linked to this wallet using a different phone have been disconnected\n\n**Please re-link your Connector(s) to use with this phone.** - Later - Gateways - Choose the gateway your wallet will use to connect to the Radix Network or test networks. Only change this if you know what you’re doing. - What is a Gateway? - RCnet Gateway - Add New Gateway - Add New Gateway - Enter a gateway URL - Enter full URL - Add Gateway - This gateway is already added - No gateway found at specified URL - There was an error establishing a connection - Remove Gateway - You will no longer be able to connect to this gateway. - Authorized dApps - These are the dApps that you have logged into using the Radix Wallet. - What is a dApp? - dApp Definition - Missing description - Website - Associated Tokens - Unknown name - Associated NFTs - Here are the Personas that you have used to login to this dApp. - No Personas have been used to login to this dApp. - Forget this dApp - Persona Hidden - Edit Avatar - Persona Label - Here is the personal data that you are sharing with %s. - You are not sharing any personal data with %s. - First Name - Last Name - Email Address - Phone Number - Edit Persona - Here are the dApps you have logged into with this Persona. - Here are the Account names and addresses that you are currently sharing with %s. - Edit Account Sharing - Disconnect Persona from this dApp - Forget This dApp - Do you really want to forget this dApp and remove its permissions for all Personas? - Forget dApp? - Remove Authorization - This dApp will no longer have authorization to see data associated with this Persona, unless you choose to login with it again in the future. - Continue - Full Name - Name Order - Given Name(s) - Family Name - Nickname - Eastern style (family name first) - Western style (given name(s) first) - Hide This Persona - Are you sure you want to hide this persona? - Required by dApp - The following information can be seen if requested by the dApp - Label cannot be blank - Invalid email address - Required field for this dApp - Add a Field - Add a Field - Choose one or more data fields to add to this Persona. - Add Data Fields - Discard Changes - Keep Editing - Are you sure you want to discard changes to this Persona? - Personas - Here are all of your current Personas in your Radix Wallet. - What is a Persona? - Create a New Persona - Write down main seed phrase - Your Account lives on the Radix Network and you can access it any time in your Radix Wallet. - You’ve created your first Account! - Your Account has been created. - e.g. My Main Account - What would you like to call your Account? - This can be changed any time. - Continue - Create an Account - Create First Account - Create New Account - Choose Accounts - Persona Selection - Gateways - Account List - Persona List - Continue to %s - Congratulations - Create Ledger Account - Create Ledger Persona - Your Account lives on the Radix Network and you can access it any time in your Wallet. - Create with Ledger Hardware Wallet - You will be asked to sign transactions with the Ledger device you select. - Empty display name - You’ve created your first Persona! - Your Persona has been created. - Personal data that you add to your Persona will only be shared with dApps with your permission. - Some dApps may request personal information, like name or email address, that can be added to your Persona. Add some data now if you like. - This will be shared with dApps you login to - Create a Persona - A Persona is an identity that you own and control. You can have as many as you like. - Personas are used to login to dApps on Radix. dApps may request access to personal information associated with your Persona, like your name or email address. - Learn about Personas - Continue - What would you like to call your Persona? - e.g. My Main Persona - Continue - Required field - Save and Continue - Login Request - %s is requesting that you login with a Persona. - New Login Request - %s is requesting that you login for the **first time** with a Persona. - Choose a Persona - Your last login was on %s - Continue - Account Permission - %d or more accounts - Any number of accounts - %d accounts - 1 account - Continue - **%s** is requesting permission to *always* be able to view Account information when you login with this Persona. - You can update this permission in wallet settings for this dApp at any time. - Create a New Account - You are now connected to %s. You can change your preferences for this dApp in wallet settings at any time. - dApp Connection Successful - DApp error - Continue - Account Request - **%s** is making a one-time request for at least %d accounts. - **%s** is making a one-time request for any number of accounts. - **%s** is making a one-time request for at least 1 account. - **%s** is making a one-time request for %d accounts. - **%s** is making a one-time request for 1 account. - Account Permission - Choose at least %d accounts you wish to use with **%s**. - Choose any accounts you wish to use with **%s**. - Choose at least 1 account you wish to use with **%s**. - Choose %d accounts you wish to use with **%s**. - Choose 1 account you wish to use with **%s**. - One-Time Data Request - Choose the data to provide - **%s** is requesting that you provide some pieces of personal data **just one time** - Continue - Personal Data Permission - **%s** is requesting permission to **always** be able to view the following personal data when you login with this Persona. - You can update this permission in your Settings at any time. - Continue - Invalid content - Incompatible connector extension - Network mismatch - Invalid value of `numberOfAccountsInvalid`: must not be `exactly(0)` nor can `quantity` be negative - %s (CE: %s, wallet: %s) - \'%s\' is not valid origin. - \'%s\' is not valid account address. - Invalid data in request - Please update Radix Wallet - Please update Radix Connector browser extension - Invalid origin - Invalid dApp Definition Address - Radix Connect connection error - Invalid Request. - Could not validate the dApp. - Request received from dApp is invalid. - dApp specified an invalid Persona. - dApp made a request intended for network %s, but you are currently connected to %s. - Failed to send request response to dApp. - Success - Request from %s complete - Danger! Bad dApp configuration, or you\'re being spoofed! - Loading… - Unknown dApp - Radix Wallet - Edit - Required information: - Review Your Transaction - Proposed by %s - Review Your Transfer - Approve - Customize Guarantees - Estimated - Account - Guaranteed - Raw Transaction - Unknown - Unnamed dApp - Worth - To be claimed - Unknown pool - %d Unknown Components - %d Pool Components - Pool Units - Slide to Sign - %s XRD - Not enough XRD for transaction fee - Fee payer account required - Withdrawing From - Depositing To - Sending to - Message - Presenting - Using dApps - Third-party deposit setting - Third-party deposit exceptions - Staking to Validators - Requesting unstake from validators - Claim from validators - Contributing to pools - Redeeming from pools - Transaction Fee - The network is currently congested. Add a tip to speed up your transfer. - Customize - Customize Guarantees - Protect yourself by setting guaranteed minimums for estimated deposits - Apply - How do guarantees work? - Set guaranteed minimum %% - Preparing Transaction - Preparing transaction for signing - Submitting - Submitted but not confirmed - Rejected - Failed - Successfully committed - Transaction ID - Status - Submitting Transaction - Review New Deposit Settings - Third-party deposit setting - Allow third parties to deposit **any asset** to this account. - Allow third parties to deposit **only assets this account has already held**. - **Disallow** all deposits from third parties without your consent. - Allow - Disallow - Remove Exception - Add Depositor - Remove Depositor - A proposed transaction was rejected because it contains one or more reserved instructions. - Could Not Complete - The required seed phrase is missing. Please return to the account and begin the recovery process. - Warning - This is a complex transaction that cannot be summarized - the raw transaction manifest will be shown. Do not submit unless you understand the contents. - Completing Transaction… - Transaction ID: - Transaction Success - Transaction Failed - Transaction Rejected - Transaction Error - Your transaction was successful - Your transaction was processed, but had a problem that caused it to fail permanently - This transaction was rejected and is unlikely to be processed, but could potentially be processed within the next %s minutes. It is likely that the dApp you are using proposed a transaction that includes an action that is not currently valid. - Your transaction was improperly constructed and cannot be processed - Something Went Wrong - Transaction was rejected as invalid by the Radix Network. - Stop waiting for transaction result? The transaction will not be canceled. - Dismiss - This transaction requires to be completed - A guarantee on transaction results was not met. Consider reducing your preferred guarantee %% - Copy Address - Copied to Clipboard - Copy NFT ID - Copy Transaction ID - There is no web browser installed in this device - View on Radix Dashboard - Show Address QR Code - Verify Address with Ledger - Address verified - Verify address request failed - QR code for an account - Could not create QR code - Authenticate to continue - Authenticate to create new %s with this phone. - Authenticate to sign proof with this phone. - Authenticate to sign transaction with this phone. - Display seed phrase. - Create Auth signing key. - Check if seed phrase already exists. - Checking accounts. - Update account metadata. - Unsecured Device - Your device currently has no device access security set, such as biometrics or a PIN. The Radix Wallet requires this to be set for your security. - Open Settings - Quit - Account - Cancel - Continue - Connected to a test network, not Radix main network. - An Error Occurred - None - OK - Done - Copy - Persona - History - Pool - Retry - Remove - Something Went Wrong - Settings - Confirm - Save - Invalid - Public - Choose - Max - Optional - Show More - Show Less - Component - Unauthorized - Gateway access blocked due to exceeding rate limit. Please wait a few minutes to retry. - Bad HTTP response status code %d - Dismiss - Invalid Persona specified by dApp - Invalid request - Failed to import Radix Wallet backup: %s - Failed to import Radix Wallet backup, error: %s, version: %s - Failed to commit transaction - Failed to convert transaction manifest - Failed to get epoch - Failed to build transaction header - Failed to convert transaction manifest - You don\'t have access to some accounts or personas required to authorise this transaction - Wrong network - No funds to approve transaction - Failed to poll transaction status - Failed to prepare transaction - Transaction rejected - Unknown error - Failed to find ledger - Failed to add Transaction Fee, try a different amount of fee payer. - Failed to add Guarantee, try a different percentage, or try skip adding a guarantee. - A proposed transaction could not be processed. - Your current Ledger settings only allow signing of simple token transfers. Please either enable \"verbose mode\" (to see full transaction manifests) or \"blind signing mode\" (to enable signing of complex transaction manifest hashes) on your Ledger app device. - Failed to convert transaction manifest - Failed to submit transaction - Persona label too long - Account label too long - Account label required - One of the receiving accounts does not allow Third-Party deposits - Import Legacy Olympia Accounts - Scan the QR code shown in the Export section of the Radix Desktop Wallet for Olympia. - Scanned: %d/%d - Import Accounts - The following accounts will be imported into this Radix Wallet. - Legacy Account - Ledger (Legacy) - Unnamed - Olympia Address (Obsolete) - New Address - Import %d accounts - Import 1 account - Verify With Your Seed Phrase - To complete importing your accounts, please view your seed phrase in the Radix Desktop Wallet and enter the words here. - This will give this Radix Wallet control of your accounts. Never give your seed phrase to anyone for any reason. - Warning - Do not throw away this seed phrase! You will still need it if you need to recover access to your Olympia accounts in the future. - I Understand - Congratulations - You\'ve now imported these Accounts: - You\'ve now imported this Account: - Your Accounts live on the Radix Network and you can access them anytime in your Wallet. - Continue to Account List - Already imported - BIP39 passphrase - Import - Invalid Mnemonic - Invalid QR code - No mnemonic found for accounts - No new accounts were found on this Ledger device - Passphrase - Seed phrase - I\'m a New Radix Wallet User - Restore Wallet from Backup - Welcome to the Radix Wallet - Your direct connection to the Radix Network - A World of Possibilities - Let\'s get started - Your phone is your login - Connect and transact securely with a world of web3 dApps, tokens, NFTs, and much more - User Terms - To proceed, you must accept the user terms below. - Accept - Back up your Wallet Settings - Connect to Google Drive to automatically backup your Radix wallet settings. - Skip - Back up to Google Drive - Restore Wallet from Backup - Log in to Google Drive to restore your Radix wallet from Backup. - Skip - Log in to Google Drive - Tap to unlock - Passcode not set up - This app requires your phone to have a passcode set up - Delete Wallet Data - For this Preview wallet version, you must delete your wallet data to continue. - Wallet Data is Incompatible - Warning - Passcode is not set up. Please update settings. - Claim This Wallet? - Claim Existing Wallet - Clear Wallet on This Phone - Ask Later (no changes) - This wallet is currently configured with a set of Accounts and Personas in use by a different phone.\n\nTo make changes to this wallet, you must claim it for use on this phone instead, removing access by the other phone.\n\nOr you can clear this wallet from this phone and start fresh. - It appears that your device might be rooted. To ensure the security of your Accounts and assets, using the Radix Wallet on rooted devices is not recommended. Please confirm if you wish to continue anyway at your own risk. - Possible jailbreak detected - It appears that your device might be jailbroken. To ensure the security of your Accounts and assets, using the Radix Wallet on jailbroken devices is not recommended. Please confirm if you wish to continue anyway at your own risk. - I Understand the Risk - Approve Transaction - Incoming Transaction - Approve Transaction - Submitting transaction… - Import Seed Phrase - Backup Seed Phrase - Word %d - Passphrase - Passphrase - Optional BIP39 Passphrase. This is not your wallet password, and the Radix Desktop Wallet did not use a BIP39 passphrase. This is only to support import from other wallets that may have used one. - Number of Seed Phrase Words - Incorrect seed phrase - Success - Advanced Mode - Regular Mode - Import - Imported Seed Phrase - Confirm Seed Phrase Saved - Are you sure you have securely written down this seed phrase? You will need it to recover access if you lose your phone. - Yes, I have written it down - No, not yet - Failed to validate all accounts against mnemonic - Wrong mnemmonic - Tell a story - Hitchcock\'s The Birds mixed with Office space - Without revealing the words, what comes to mind when reading this seed phrase? - Backup location? - In that book my mother used to read to me at my best childhoods summer vacation place - Without revealing location, vague hint on where this mnemonic is backed up, if anywhere. - Save with description - Save without description - Enter this Account\'s seed phrase - Please write down seed phrase to ensure Account control - Change seed phrase length - %d word seed phrase - Recover Mnemonic - Can\'t displays image of vector type - Can\'t load image - Message - Add a message - Scan a QR code of a Radix Account address from another wallet or an exchange. - Continue - Account - From - To - Add Transfer - Transfer - Add Message - Invalid address - Account already added - Choose Receiving Account - Enter or scan an Account address - Or: Choose one of your own Accounts - Scan Account QR Code - Enter Radix Account address - Choose Asset(s) to Send - Select Assets - Choose 1 Asset - Choose %d Assets - Total exceeds your current balance - Balance: %s - Choose Account - Add Assets - Address is not valid on current network - Resource already added - Total amount exceeds your current balance - Sending All XRD - Sending the full amount of XRD in this account will require you to pay the transaction fee from a different account. Or, the wallet can reduce the amount transferred so the fee can be paid from this account. Choose the amount to transfer: - %s (send all XRD) - %s (save 1 XRD for fee) - You will be asked for an extra signature - Verify With Ledger Device - You are attempting to import one or more Olympia accounts that must be verified with a Ledger hardware wallet device. - Already verified Ledger devices: - Continue - Accounts remaining to verify: %d - Connect your next Ledger device, launch the Radix Babylon app on it, and tap Continue here. - Link a Connector - To use a Ledger hardware wallet device, it must be connected to a computer running the Radix Connector browser extension. - Continue - Choose Ledger - Choose Ledger Device - Ledger Devices - What is a Ledger Factor Source - Add Ledger Device - Added - Last Used - Continue - No Ledger devices currently added to your Radix Wallet - Choose a Ledger device to use - Choose an existing Ledger or add a new one - Here are all the Ledger devices you have added. - Could not find Ledger devices - Transaction could not be signed. To sign complex transactions, please enable either \"blind signing\" or \"verbose mode\" in the Radix app on your Ledger device. - Could Not Sign - Address verified - Verify address: Mismatched addresses - Verify address: Returned bad response - Verify address: Request failed - Use Caution - Reveal Seed Phrase - A seed phrase provides full control of its Accounts. Do not view in a public area. Write down the seed phrase words securely. Screenshots are disabled. - Seed Phrases - Connected to Personas and %d Account - Connected to Personas and to %d Accounts - Connected to %d Account - Connected to %d Accounts - You are responsible for the security of your Seed Phrase - Write Down this Seed Phrase - Begin seed phrase entry - Confirm Your Seed Phrase - Confirm you have written down the seed phrase by entering the missing words below. - Reveal Seed Phrase - For your safety, make sure no one is looking at your screen. Taking a screen shot has been disabled. - Word %d - Passphrase - Use Caution - Are you sure you have written down your seed phrase? - I have written down this seed phrase - Seed Phrases - A Seed Phrase provides full access to your accounts and funds. When viewing, ensure you’re in a safe environment and no one is looking at your screen. - You are responsible for the security of your Seed Phrase - Please write down your Seed Phrase - Hidden Accounts only - Seed Phrase Entry Required - Reveal Seed Phrase - Not connected to any Accounts - Connected to 1 Account - Connected to %d Accounts - Seed Phrase - Not yet connected to any Accounts - Currently connected to 1 Account - Currently connected to %d Accounts - App Settings - Customize your Radix Wallet - Linked Connectors - Network Gateways - Account & Persona Hiding - Manage hiding - Accounts and Personas you have created can be hidden in your Radix Wallet, acting as if “deleted”. - %d Persona currently hidden - %d Personas currently hidden - %d Account currently hidden - %d Accounts currently hidden - Unhide Accounts & Personas - Unhide All - Are you sure you wish to unhide all Accounts and Personas? This cannot be undone. - Developer Mode - Warning: Disables website validity checks - Crash Reporting - I\'m aware Radix Wallet will send crash reports together with device state from the moment of crash. - Ledger Already Added - You have already added this Ledger as: %s - Add Ledger Device - Let’s set up a Ledger hardware wallet device. You will be able to use it to create new Ledger-secured Accounts, or import Ledger-secured Accounts from the Radix Olympia Desktop Wallet. - Connect your Ledger to a computer running a linked Radix Connector browser extension, and make sure the Radix Babylon app is running on the Ledger device. - Continue - Name Your Ledger - What would you like to call this Ledger device? - This will be displayed when you’re prompted to sign with this Ledger device. - Detected type: %s - Green Ledger Nano S+ - Save and Continue - Backing up your wallet ensures that you can restore access to your Accounts, Personas, and wallet settings on a new phone by re-entering your seed phrase(s).\n\n**For security, backups do not contain any seed phrases or private keys. You must write them down separately.** - Automatic Backups (recommended) - Manual Backups - A manually exported wallet backup file may also be used for recovery, along with your seed phrase(s).\n\nOnly the **current configuration** of your wallet is backed up with each manual export. - Export Wallet Backup File - Encrypt this backup with a password? - Exported wallet backup file - Yes - No - Encrypt Wallet Backup File - Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. - Decrypt Wallet Backup File - Enter the password you chose when you originally encrypted this Wallet Backup file. - Enter password - Confirm password - Passwords do not match - Encryption password - Decryption password - Incorrect password - OK - Failed to encrypt using provided password. - Failed to decrypt using provided password. - Delete Wallet - WARNING. This will clear all contents of your Wallet. If you have no backup, you will lose access to your Accounts and Personas permanently. - Delete Wallet - Reset Wallet? - Reset Wallet - Reset and Delete iCloud Backup - WARNING. This will clear all contents of your Wallet. If you have no backup, you will lose access to your Accounts and Personas permanently. - Back up is turned off - Last Backed up: %s - Not backed up yet - Open System Backup Settings - Backup Wallet Data to Cloud - Warning: If disabled you might lose access to your Accounts and Personas. - You may delete your wallet. This will clear the Radix Wallet app, clears its contents, and delete any cloud backup.\n\n**Access to any Accounts or Personas will be permanently lost unless you have a manual backup file.** - Delete Wallet - Enabling iCloud sync - iCloud sync is now enabled, but it might take up to an hour before your wallet data is uploaded to iCloud. - Disabling iCloud sync will delete the iCloud backup data, are you sure you want to disable iCloud sync? - Enable Backup to iCloud - Disable Backup to iCloud - Automatic continuous backups - Sync Wallet Data to iCloud - Warning: If disabled you might lose access to your Accounts and Personas. - Wallet Data Backup - Import From Backup - Available backups: - Use iCloud Backup Data - This Device - Backup created by: %s - Creation date: %s - Last used on device: %s - Last modified date: %s - Number of networks: %d - Number of Accounts: %d - Number of Personas: %d - Incompatible Wallet data - You may delete your wallet. This will clear the Radix Wallet app, clears its contents, and delete any iCloud backup.\n\n**Access to any Accounts or Personas will be permanently lost unless you have a manual backup file.** - Delete Wallet and iCloud Backup - Unable to find wallet backup in iCloud. - Encrypt Wallet Backup File - Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. - Enter password - Confirm password - Passwords do not match - Restore Wallet From Backup - Select a backup to restore your Radix Wallet. You will be asked to enter your seed phrase(s) to recover control of your Accounts and Personas. - Choose a backup - Choose a backup on iCloud - No wallet backups available on current iCloud account - No wallet backups available - **Backup from:** %s - **Last modified:** %s - **Number of accounts:** %d - **Number of personas:** %d - Import from Backup File Instead - Incompatible Wallet data - The password is wrong - Backup not available? - Other Restore Options - Main Seed Phrase Required - No Main Seed Phrase? - Seed Phrase Required - Your **Personas** and the following **Accounts** are controlled by your main seed phrase. To recover control, you must re-enter it. - The following **Accounts** are controlled by a seed phrase. To recover control, you must re-enter it. - The Radix Wallet always uses a single main “Babylon” seed phrase to generate new Personas and new Accounts (when not using a Ledger device).\n\nIf you do not have access to your previous main seed phrase, you can skip entering it for now. **The Radix Wallet will create a new one, which will be used for new Personas and Accounts.**\n\nYour old Accounts and Personas will still be listed, but you will have to enter their original seed phrase to use them. Alternatively, you can hide them if you no longer are interested in using them. - Skip This Seed Phrase For Now - I Don’t Have the Main Seed Phrase - Enter This Seed Phrase - Skip Main Seed Phrase Entry - Hidden accounts only. - Phone - Ledger - Seed phrase - Third-party - Security Questions - Customize Fees - Estimated Transaction Fees - Transaction Fee - (maximum to lock) - Advanced Customize Fees - Choose what account to pay the transaction fee from, or add a \"tip\" to speed up your transaction if necessary. - Fully customize fee payment for this transaction. Not recomended unless you are a developer or advanced user. - Pay fee from - Change - None required - None due - No account selected - Select Fee Payer - Select an account to pay %s XRD transaction fee - Select Account - View Normal Mode - View Advanced Mode - Network Fee - Network Execution - Network Finalization - Effective Tip - Network Storage - Padding - Royalties - Royalty fee - Paid by dApps - Adjust Fee Padding Amount (XRD) - Adjust Tip to Lock - (%% of Execution + Finalization Fees) - Please select a fee payer for the transaction fee - Not enough XRD for transaction fee - Scanning in progress - Scanning for Accounts that have been included in at least one transaction, using: - **Babylon Seed Phrase** - **Olympia Seed Phrase** - **Ledger hardware wallet device** - Signing Factor - Unnamed - Scanning network - Scan Complete - The first **%d** potential Accounts from this signing factor were scanned. The following Accounts had at least one transaction: - No new accounts found - Tap here to scan the next %d - Continue - Add Inactive Accounts? - These Accounts were never used, but you **may** have created them. Select any addresses that you wish to keep: - Continue - Account Recovery Scan - The Radix Wallet can scan for previously used accounts using a bare seed phrase or Ledger hardware wallet device - Babylon Accounts - Scan for Accounts originally created on the **Babylon** network. - Olympia Accounts - Scan for Accounts originally created on the **Olympia** network.\n\n(If you have Olympia Accounts in the Radix Olympia Desktop Wallet, consider using **Import from a Legacy Wallet** instead. - Note: You will still use the new **Radix Babylon** app on your Ledger device, not the old Radix Ledger app. - Use Seed Phrase - Use Ledger Hardware Wallet - Choose Seed Phrase - Choose the \"Legacy\" Olympia seed phrase for use for derivation: - Choose the Babylon seed phrase for use for derivation: - Add Babylon Seed Phrase - Add Olympia Seed Phrase - Enter Legacy Seed Phrase - Enter Seed Phrase - Continue - Note: You must still use the new *Radix Babylon* app on your Ledger device, not the old Radix Ledger app. - Seed Phrases - Ledger Hardware Wallets - Default Deposit Guarantees - Set your default guaranteed minimum for estimated deposits - Set the guaranteed minimum deposit to be applied whenever a deposit in a transaction can only be estimated.\n\nYou can always change the guarantee from this default in each transaction. - Account Recovery Scan - Using seed phrase or Ledger device - Backups - Import from a Legacy Wallet - Enter Seed Phrase - Enter Main Seed Phrase - For your safety, make sure no one is looking at your screen. Never give your seed phrase to anyone for any reason. - Enter Main Seed Phrase - Enter Babylon Seed Phrase - Enter Olympia Seed Phrase - Recover Control Without Backup - If you have no wallet backup in the cloud, or as an exported backup file, you still have other restore options. - I have my main “Babylon” 24-word seed phrase. - Recover with Main Seed Phrase - I only want to restore Ledger hardware wallet Accounts. - Ledger-only Restore - I only have Accounts created on the Radix Olympia network. - Olympia-only Restore - No Main Seed Phrase? - Tap “I\'m a New Wallet User”. After completing wallet creation, in Settings you can perform an “account recovery scan” using your Ledger device. - Tap “I\'m a New Wallet User”. After completing wallet creation, in Settings you can perform an “account recovery scan” using your Olympia seed phrase. - Cancel - Continue - Recover Control Without Backup - **If you have no wallet backup in the cloud or as an exported backup file**, you can still restore Account access only using your main “Babylon” seed phrase. You cannot recover your Account names or other wallet settings this way.\n\nYou will be asked to enter your main seed phrase. This is a set of **24 words** that the Radix Wallet mobile app showed you to write down and save securely. - Continue - Recovery Complete - Accounts discovered in the scan have been added to your wallet.\n\nIf you have any “Legacy” Accounts (created on the Olympia network) to import - or any Accounts using a Ledger hardware wallet device - please continue and then use the **Account Recovery Scan** option in your Radix Wallet settings under **Account Security**. - Continue - History - Settings - Withdrawn - Deposited - Updated Account Deposit Settings - No deposits or withdrawals from this account in this transaction. - This transaction cannot be summarized. Only the raw transaction manifest may be viewed. - Failed Transaction - You have no Transactions. - General - Transfer - Stake - Request Unstake - Claim Stake - Contribute - Redeem - Deposit Settings - Other - Filter - Clear All - Show Results - Type of Asset - Show All Tokens - Show Less Tokens - Show All NFTs - Show Less NFTs - Tokens - Deposits - Withdrawals - NFTs - Type of Transaction - Today - Yesterday - How\'s it Going? - How likely are you to recommend Radix and the Radix Wallet to your friends or colleagues? - 0 - Not likely - 10 - Very likely - What’s the main reason for your score? - Let us know... - Submit Feedback - Thanks! - Signature Request - Creating Account - Creating Persona - Deriving Accounts - Proving Ownership - Encrypting Message - Creating Key - Authenticate to your phone to sign. - Authenticate to your phone to complete using your phone\'s signing key. - Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. + Please write down seed phrase to ensure Account control + Seed phrase required - begin entry + I have written down this seed phrase + Create a New Account + Legacy + Welcome. Here are all your Accounts on the Radix Network. + Radix Wallet + Total value + dApp Definition + Legacy + Legacy (Ledger) + Ledger + Visit the Radix Dashboard + Ready to get started using the Radix Network and your Wallet? + SERIOUS ERROR - PLEASE READ + Your wallet is in a rare condition that must be resolved manually. Please email support at hello@radixdlt.com with subject line BDFS ERROR. Somebody will respond and help you resolve the issue safely. + Affected Accounts + Affected Personas + OK (%d) + Start Using Radix + Complete setting up your wallet and start staking, using dApps and more! + Get Started Now + Your wallet has encountered a problem that should be resolved before you continue use. If you have a Samsung phone, this may be caused by putting the Radix Wallet in the \"Secure Folder\". Please contact support at hello@radixdlt.com for assistance. + Transfer + Tokens + NFTs + Staking + Radix Network XRD Stake Summary + STAKED VALIDATORS (%d) + Unstaking + Ready to Claim + Ready to be claimed + Staked + Current Stake: %s + Liquid Stake Units + Stake Claim NFTs + WORTH + Claim + Pool Units + Unknown + Unknown + Unknown + Current Redeemable Value + Missing Total supply - could not calculate redemption value + Badges + Address + Validator + Name + Current Supply + Unknown + Behavior + Ready to claim in about %d minutes or less. + Tags + Official Radix + Associated dApps + You have no Tokens + What are Tokens? + You have no NFTs + What are NFTs? + ID + Name + Description + complex data + Name + %d NFTs + %d NFTs of total supply %d + You have no Stakes + What is Staking? + You have no Pool units + What are Pool units? + You have no badges + What are badges? + Hide Asset + Hide this asset in your Radix Wallet? You can always unhide it in your account settings. + Hide Asset + This is a simple asset + The supply of this asset can be increased. + The supply of this asset can be decreased. + The supply of this asset can be increased or decreased. + Only the Radix Network may increase or decrease the supply of XRD. + Anyone can increase the supply of this asset. + Anyone can decrease the supply of this asset. + Anyone can increase or decrease the supply of this asset. + Movement of this asset is restricted. + Movement of this asset can be restricted in the future. + Anyone can restrict movement of this token in the future. + Naming and information about this asset can be changed. + Anyone can change naming and information about this asset. + A third party can remove this asset from accounts and dApps. + Anyone can remove this asset from accounts and dApps. + A third party can freeze this asset in place. + Anyone can freeze this asset in place. + Data that is set on these NFTs can be changed. + Anyone can change data that is set on these NFTs. + Account Settings + Personalize this Account + Account Label + Account Color + Select from a list of unique colors + Show Assets with Tags + Show Account QR Code + Updated + Select which tags to show for assets in this Account + Set how you want this Account to work + Third-party Deposits + Hide Account + Account Hidden + Get XRD Test Tokens + This may take several seconds, please wait for completion + Rename Account + Enter a new label for this Account + Update + Select the color for this Account + Selected + Hide This Account + Hide this Account in your wallet? You can always unhide it from the main application settings. + Hide Account + Choose if you want to allow third parties to directly deposit assets into your Account. Deposits that you approve yourself in your Radix Wallet are always accepted. + Accept all deposits + Allow third-parties to deposit any asset + Only accept known + Allow third-parties to deposit only assets this Account already holds + Deny all + Deny all third-party deposits + This account will not be able to receive \"air drops\" or be used by a trusted contact to assist with account recovery. + Discard Changes + Keep Editing + Are you sure you want to discard changes? + Allow/Deny specific assets + Deny or allow third-party deposits of specific assets, ignoring the setting above + Add a Depositor Badge + Enter the badge’s resource address (starting with “reso”) + Allow specific depositors + Allow certain third party depositors to deposit assets freely + Add Depositor Badge + Remove Asset + The asset will be removed from the deny list + The asset will be removed from the allow list + The badge will be removed from the list + Remove Depositor + The depositor will be removed from the allow list + Allow/Deny Specific Assets + Update + Allow + Deny + Add a specific asset by its resource address to allow all third-party deposits + Add a specific asset by its resource address to deny all third-party deposits + Add an Asset + Enter the asset’s resource address (starting with “reso”) + Resource Address + Allow Deposits + Deny Deposits + Add Asset + The following resource addresses may always be deposited to this account by third parties. + The following resource addresses may never be deposited to this account by third parties. + Add a specific badge by its resource address to allow all deposits from its holder. + The holder of the following badges may always deposit accounts to this account. + Select exception list + Sorry, this Account\'s third-party exceptions and depositor lists are in an unknown state and cannot be viewed or edited because it was imported using only a seed phrase or Ledger. A forthcoming wallet update will enable viewing and editing of these lists. + Asset creators can add tags to them. You can choose which tags you want to see in this Account. + Select the ones you’d like shown on all your assets. + Recommended + Set development preferences + Dev Preferences + Hide This Account + Are you sure you want to hide this account? + Settings + Authorized dApps + Personas + Account Security & Settings + App Settings + Please write down the seed phrase for your Personas + Link your Wallet to a Desktop Browser + Scan the QR code in the Radix Wallet Connector extension + Link to Connector + Radix Olympia Desktop Wallet user? + Get started importing your Olympia accounts into your new Radix Wallet + Import Legacy Accounts + Version: %s build #%s + Linked Connectors + Connect your Radix Wallet to desktop web browsers by linking to the Radix Connector browser extension. Here are your linked Connectors. + Last connected %s + Link New Connector + Link New Connector + Open your Radix Connector extension\'s menu by clicking its icon in your list of browser extensions, and scan the QR code shown. + Linking… + Name New Connector + What would you like to call this Radix Connector installation? + e.g. Chrome on Personal Laptop + Name this connector e.g. ‘Chrome on MacBook Pro’ + Continue + Remove Connection + You will no longer be able to connect your wallet to this device and browser combination. + Remove + Access Required + Camera access is required to link to a Connector. + Access Required + Local network access is required to link to a Connector. + Incorrect QR code scanned. + Please scan the QR code provided by your Radix Wallet Connector browser extension. + Link Connector + Update Link + This Connector will be trusted to verify the dApp origin of requests to this wallet.\n\nOnly continue if you are linking to the **official Radix Connector browser extension** - or a Connector you control and trust. + This appears to be a Radix Connector you previously linked to. Link will be updated. + Link Failed + This type of Connector link is not supported. + Changing a Connector’s type is not supported. + This is an old version of the Radix Connector browser extension. Please update to the latest Connector and try linking again. + Re-link Connector + Radix Connector now supports linking multiple phones with one browser.\n\nTo support this feature, we\'ve had to disconnect your existing links – **please re-link your Connector(s).** + Any Connectors you had linked to this wallet using a different phone have been disconnected\n\n**Please re-link your Connector(s) to use with this phone.** + Later + Gateways + Choose the gateway your wallet will use to connect to the Radix Network or test networks. Only change this if you know what you’re doing. + What is a Gateway? + RCnet Gateway + Add New Gateway + Add New Gateway + Enter a gateway URL + Enter full URL + Add Gateway + This gateway is already added + No gateway found at specified URL + There was an error establishing a connection + Remove Gateway + You will no longer be able to connect to this gateway. + Authorized dApps + These are the dApps that you have logged into using the Radix Wallet. + What is a dApp? + dApp Definition + Missing description + Website + Associated Tokens + Unknown name + Associated NFTs + Here are the Personas that you have used to login to this dApp. + No Personas have been used to login to this dApp. + Forget this dApp + Persona Hidden + Edit Avatar + Persona Label + Here is the personal data that you are sharing with %s. + You are not sharing any personal data with %s. + First Name + Last Name + Email Address + Phone Number + Edit Persona + Here are the dApps you have logged into with this Persona. + Here are the Account names and addresses that you are currently sharing with %s. + Edit Account Sharing + Disconnect Persona from this dApp + Forget This dApp + Do you really want to forget this dApp and remove its permissions for all Personas? + Forget dApp? + Remove Authorization + This dApp will no longer have authorization to see data associated with this Persona, unless you choose to login with it again in the future. + Continue + Full Name + Name Order + Given Name(s) + Family Name + Nickname + Eastern style (family name first) + Western style (given name(s) first) + Hide This Persona + Are you sure you want to hide this persona? + Required by dApp + The following information can be seen if requested by the dApp + Label cannot be blank + Invalid email address + Required field for this dApp + Add a Field + Add a Field + Choose one or more data fields to add to this Persona. + Add Data Fields + Discard Changes + Keep Editing + Are you sure you want to discard changes to this Persona? + Personas + Here are all of your current Personas in your Radix Wallet. + What is a Persona? + Create a New Persona + Write down main seed phrase + Your Account lives on the Radix Network and you can access it any time in your Radix Wallet. + You’ve created your first Account! + Your Account has been created. + e.g. My Main Account + What would you like to call your Account? + This can be changed any time. + Continue + Create an Account + Create First Account + Create New Account + Choose Accounts + Persona Selection + Gateways + Account List + Persona List + Continue to %s + Congratulations + Create Ledger Account + Create Ledger Persona + Your Account lives on the Radix Network and you can access it any time in your Wallet. + Create with Ledger Hardware Wallet + You will be asked to sign transactions with the Ledger device you select. + Empty display name + You’ve created your first Persona! + Your Persona has been created. + Personal data that you add to your Persona will only be shared with dApps with your permission. + Some dApps may request personal information, like name or email address, that can be added to your Persona. Add some data now if you like. + This will be shared with dApps you login to + Create a Persona + A Persona is an identity that you own and control. You can have as many as you like. + Personas are used to login to dApps on Radix. dApps may request access to personal information associated with your Persona, like your name or email address. + Learn about Personas + Continue + What would you like to call your Persona? + e.g. My Main Persona + Continue + Required field + Save and Continue + Login Request + %s is requesting that you login with a Persona. + New Login Request + %s is requesting that you login for the **first time** with a Persona. + Choose a Persona + Your last login was on %s + Continue + Account Permission + %d or more accounts + Any number of accounts + %d accounts + 1 account + Continue + **%s** is requesting permission to *always* be able to view Account information when you login with this Persona. + You can update this permission in wallet settings for this dApp at any time. + Create a New Account + You are now connected to %s. You can change your preferences for this dApp in wallet settings at any time. + dApp Connection Successful + DApp error + Continue + Account Request + **%s** is making a one-time request for at least %d accounts. + **%s** is making a one-time request for any number of accounts. + **%s** is making a one-time request for at least 1 account. + **%s** is making a one-time request for %d accounts. + **%s** is making a one-time request for 1 account. + Account Permission + Choose at least %d accounts you wish to use with **%s**. + Choose any accounts you wish to use with **%s**. + Choose at least 1 account you wish to use with **%s**. + Choose %d accounts you wish to use with **%s**. + Choose 1 account you wish to use with **%s**. + One-Time Data Request + Choose the data to provide + **%s** is requesting that you provide some pieces of personal data **just one time** + Continue + Personal Data Permission + **%s** is requesting permission to **always** be able to view the following personal data when you login with this Persona. + You can update this permission in your Settings at any time. + Continue + Invalid content + Incompatible connector extension + Network mismatch + Invalid value of `numberOfAccountsInvalid`: must not be `exactly(0)` nor can `quantity` be negative + %s (CE: %s, wallet: %s) + \'%s\' is not valid origin. + \'%s\' is not valid account address. + Invalid data in request + Please update Radix Wallet + Please update Radix Connector browser extension + Invalid origin + Invalid dApp Definition Address + Radix Connect connection error + Invalid Request. + Could not validate the dApp. + Request received from dApp is invalid. + dApp specified an invalid Persona. + dApp made a request intended for network %s, but you are currently connected to %s. + Failed to send request response to dApp. + Success + Request from %s complete + Danger! Bad dApp configuration, or you\'re being spoofed! + Loading… + Unknown dApp + Radix Wallet + Edit + Required information: + Review Your Transaction + Proposed by %s + Review Your Transfer + Approve + Customize Guarantees + Estimated + Account + Guaranteed + Raw Transaction + Unknown + Unnamed dApp + Worth + To be claimed + Unknown pool + %d Unknown Components + %d Pool Components + Pool Units + Slide to Sign + %s XRD + Not enough XRD for transaction fee + Fee payer account required + Withdrawing From + Depositing To + Sending to + Message + Presenting + Using dApps + Third-party deposit setting + Third-party deposit exceptions + Staking to Validators + Requesting unstake from validators + Claim from validators + Contributing to pools + Redeeming from pools + Transaction Fee + The network is currently congested. Add a tip to speed up your transfer. + Customize + Customize Guarantees + Protect yourself by setting guaranteed minimums for estimated deposits + Apply + How do guarantees work? + Set guaranteed minimum %% + Preparing Transaction + Preparing transaction for signing + Submitting + Submitted but not confirmed + Rejected + Failed + Successfully committed + Transaction ID + Status + Submitting Transaction + Review New Deposit Settings + Third-party deposit setting + Allow third parties to deposit **any asset** to this account. + Allow third parties to deposit **only assets this account has already held**. + **Disallow** all deposits from third parties without your consent. + Allow + Disallow + Remove Exception + Add Depositor + Remove Depositor + A proposed transaction was rejected because it contains one or more reserved instructions. + Could Not Complete + The required seed phrase is missing. Please return to the account and begin the recovery process. + Warning + This is a complex transaction that cannot be summarized - the raw transaction manifest will be shown. Do not submit unless you understand the contents. + Completing Transaction… + Transaction ID: + Transaction Success + Transaction Failed + Transaction Rejected + Transaction Error + Your transaction was successful + Your transaction was processed, but had a problem that caused it to fail permanently + This transaction was rejected and is unlikely to be processed, but could potentially be processed within the next %s minutes. It is likely that the dApp you are using proposed a transaction that includes an action that is not currently valid. + Your transaction was improperly constructed and cannot be processed + Something Went Wrong + Transaction was rejected as invalid by the Radix Network. + Stop waiting for transaction result? The transaction will not be canceled. + Dismiss + This transaction requires to be completed + A guarantee on transaction results was not met. Consider reducing your preferred guarantee %% + Copy Address + Copied to Clipboard + Copy NFT ID + Copy Transaction ID + There is no web browser installed in this device + View on Radix Dashboard + Show Address QR Code + Verify Address with Ledger + Address verified + Verify address request failed + QR code for an account + Could not create QR code + Authenticate to continue + Authenticate to create new %s with this phone. + Authenticate to sign proof with this phone. + Authenticate to sign transaction with this phone. + Display seed phrase. + Create Auth signing key. + Check if seed phrase already exists. + Checking accounts. + Update account metadata. + Unsecured Device + Your device currently has no device access security set, such as biometrics or a PIN. The Radix Wallet requires this to be set for your security. + Open Settings + Quit + Account + Cancel + Continue + Connected to a test network, not Radix main network. + An Error Occurred + None + OK + Done + Copy + Persona + History + Pool + Retry + Remove + Something Went Wrong + Settings + Confirm + Save + Invalid + Public + Choose + Max + Optional + Show More + Show Less + Component + Unauthorized + Gateway access blocked due to exceeding rate limit. Please wait a few minutes to retry. + Bad HTTP response status code %d + Dismiss + Invalid Persona specified by dApp + Invalid request + Failed to import Radix Wallet backup: %s + Failed to import Radix Wallet backup, error: %s, version: %s + Failed to commit transaction + Failed to convert transaction manifest + Failed to get epoch + Failed to build transaction header + Failed to convert transaction manifest + You don\'t have access to some accounts or personas required to authorise this transaction + Wrong network + No funds to approve transaction + Failed to poll transaction status + Failed to prepare transaction + Transaction rejected + Unknown error + Failed to find ledger + Failed to add Transaction Fee, try a different amount of fee payer. + Failed to add Guarantee, try a different percentage, or try skip adding a guarantee. + A proposed transaction could not be processed. + Your current Ledger settings only allow signing of simple token transfers. Please either enable \"verbose mode\" (to see full transaction manifests) or \"blind signing mode\" (to enable signing of complex transaction manifest hashes) on your Ledger app device. + Failed to convert transaction manifest + Failed to submit transaction + Persona label too long + Account label too long + Account label required + One of the receiving accounts does not allow Third-Party deposits + Import Legacy Olympia Accounts + Scan the QR code shown in the Export section of the Radix Desktop Wallet for Olympia. + Scanned: %d/%d + Import Accounts + The following accounts will be imported into this Radix Wallet. + Legacy Account + Ledger (Legacy) + Unnamed + Olympia Address (Obsolete) + New Address + Import %d accounts + Import 1 account + Verify With Your Seed Phrase + To complete importing your accounts, please view your seed phrase in the Radix Desktop Wallet and enter the words here. + This will give this Radix Wallet control of your accounts. Never give your seed phrase to anyone for any reason. + Warning + Do not throw away this seed phrase! You will still need it if you need to recover access to your Olympia accounts in the future. + I Understand + Congratulations + You\'ve now imported these Accounts: + You\'ve now imported this Account: + Your Accounts live on the Radix Network and you can access them anytime in your Wallet. + Continue to Account List + Already imported + BIP39 passphrase + Import + Invalid Mnemonic + Invalid QR code + No mnemonic found for accounts + No new accounts were found on this Ledger device + Passphrase + Seed phrase + I\'m a New Radix Wallet User + Restore Wallet from Backup + Welcome to the Radix Wallet + Your direct connection to the Radix Network + A World of Possibilities + Let\'s get started + Your phone is your login + Connect and transact securely with a world of web3 dApps, tokens, NFTs, and much more + User Terms + To proceed, you must accept the user terms below. + Accept + Back up your Wallet Settings + Connect to Google Drive to automatically backup your Radix wallet settings. + Skip + Back up to Google Drive + Restore Wallet from Backup + Log in to Google Drive to restore your Radix wallet from Backup. + Skip + Log in to Google Drive + Tap to unlock + Passcode not set up + This app requires your phone to have a passcode set up + Delete Wallet Data + For this Preview wallet version, you must delete your wallet data to continue. + Wallet Data is Incompatible + Warning + Passcode is not set up. Please update settings. + Claim This Wallet? + Claim Existing Wallet + Clear Wallet on This Phone + Ask Later (no changes) + This wallet is currently configured with a set of Accounts and Personas in use by a different phone.\n\nTo make changes to this wallet, you must claim it for use on this phone instead, removing access by the other phone.\n\nOr you can clear this wallet from this phone and start fresh. + It appears that your device might be rooted. To ensure the security of your Accounts and assets, using the Radix Wallet on rooted devices is not recommended. Please confirm if you wish to continue anyway at your own risk. + Possible jailbreak detected + It appears that your device might be jailbroken. To ensure the security of your Accounts and assets, using the Radix Wallet on jailbroken devices is not recommended. Please confirm if you wish to continue anyway at your own risk. + I Understand the Risk + Approve Transaction + Incoming Transaction + Approve Transaction + Submitting transaction… + Import Seed Phrase + Backup Seed Phrase + Word %d + Passphrase + Passphrase + Optional BIP39 Passphrase. This is not your wallet password, and the Radix Desktop Wallet did not use a BIP39 passphrase. This is only to support import from other wallets that may have used one. + Number of Seed Phrase Words + Incorrect seed phrase + Success + Advanced Mode + Regular Mode + Import + Imported Seed Phrase + Confirm Seed Phrase Saved + Are you sure you have securely written down this seed phrase? You will need it to recover access if you lose your phone. + Yes, I have written it down + No, not yet + Failed to validate all accounts against mnemonic + Wrong mnemmonic + Tell a story + Hitchcock\'s The Birds mixed with Office space + Without revealing the words, what comes to mind when reading this seed phrase? + Backup location? + In that book my mother used to read to me at my best childhoods summer vacation place + Without revealing location, vague hint on where this mnemonic is backed up, if anywhere. + Save with description + Save without description + Enter this Account\'s seed phrase + Please write down seed phrase to ensure Account control + Change seed phrase length + %d word seed phrase + Recover Mnemonic + Can\'t displays image of vector type + Can\'t load image + Message + Add a message + Scan a QR code of a Radix Account address from another wallet or an exchange. + Continue + Account + From + To + Add Transfer + Transfer + Add Message + Invalid address + Account already added + Choose Receiving Account + Enter or scan an Account address + Or: Choose one of your own Accounts + Scan Account QR Code + Enter Radix Account address + Choose Asset(s) to Send + Select Assets + Choose 1 Asset + Choose %d Assets + Total exceeds your current balance + Balance: %s + Choose Account + Add Assets + Address is not valid on current network + Resource already added + Total amount exceeds your current balance + Sending All XRD + Sending the full amount of XRD in this account will require you to pay the transaction fee from a different account. Or, the wallet can reduce the amount transferred so the fee can be paid from this account. Choose the amount to transfer: + %s (send all XRD) + %s (save 1 XRD for fee) + You will be asked for an extra signature + Verify With Ledger Device + You are attempting to import one or more Olympia accounts that must be verified with a Ledger hardware wallet device. + Already verified Ledger devices: + Continue + Accounts remaining to verify: %d + Connect your next Ledger device, launch the Radix Babylon app on it, and tap Continue here. + Link a Connector + To use a Ledger hardware wallet device, it must be connected to a computer running the Radix Connector browser extension. + Continue + Choose Ledger + Choose Ledger Device + Ledger Devices + What is a Ledger Factor Source + Add Ledger Device + Added + Last Used + Continue + No Ledger devices currently added to your Radix Wallet + Choose a Ledger device to use + Choose an existing Ledger or add a new one + Here are all the Ledger devices you have added. + Could not find Ledger devices + Transaction could not be signed. To sign complex transactions, please enable either \"blind signing\" or \"verbose mode\" in the Radix app on your Ledger device. + Could Not Sign + Address verified + Verify address: Mismatched addresses + Verify address: Returned bad response + Verify address: Request failed + Use Caution + Reveal Seed Phrase + A seed phrase provides full control of its Accounts. Do not view in a public area. Write down the seed phrase words securely. Screenshots are disabled. + Seed Phrases + Connected to Personas and %d Account + Connected to Personas and to %d Accounts + Connected to %d Account + Connected to %d Accounts + You are responsible for the security of your Seed Phrase + Write Down this Seed Phrase + Begin seed phrase entry + Confirm Your Seed Phrase + Confirm you have written down the seed phrase by entering the missing words below. + Reveal Seed Phrase + For your safety, make sure no one is looking at your screen. Taking a screen shot has been disabled. + Word %d + Passphrase + Use Caution + Are you sure you have written down your seed phrase? + I have written down this seed phrase + Seed Phrases + A Seed Phrase provides full access to your accounts and funds. When viewing, ensure you’re in a safe environment and no one is looking at your screen. + You are responsible for the security of your Seed Phrase + Please write down your Seed Phrase + Hidden Accounts only + Seed Phrase Entry Required + Reveal Seed Phrase + Not connected to any Accounts + Connected to 1 Account + Connected to %d Accounts + Seed Phrase + Not yet connected to any Accounts + Currently connected to 1 Account + Currently connected to %d Accounts + App Settings + Customize your Radix Wallet + Linked Connectors + Network Gateways + Account & Persona Hiding + Manage hiding + Accounts and Personas you have created can be hidden in your Radix Wallet, acting as if “deleted”. + %d Persona currently hidden + %d Personas currently hidden + %d Account currently hidden + %d Accounts currently hidden + Unhide Accounts & Personas + Unhide All + Are you sure you wish to unhide all Accounts and Personas? This cannot be undone. + Developer Mode + Warning: Disables website validity checks + Crash Reporting + I\'m aware Radix Wallet will send crash reports together with device state from the moment of crash. + Ledger Already Added + You have already added this Ledger as: %s + Add Ledger Device + Let’s set up a Ledger hardware wallet device. You will be able to use it to create new Ledger-secured Accounts, or import Ledger-secured Accounts from the Radix Olympia Desktop Wallet. + Connect your Ledger to a computer running a linked Radix Connector browser extension, and make sure the Radix Babylon app is running on the Ledger device. + Continue + Name Your Ledger + What would you like to call this Ledger device? + This will be displayed when you’re prompted to sign with this Ledger device. + Detected type: %s + Green Ledger Nano S+ + Save and Continue + Backing up your wallet ensures that you can restore access to your Accounts, Personas, and wallet settings on a new phone by re-entering your seed phrase(s).\n\n**For security, backups do not contain any seed phrases or private keys. You must write them down separately.** + Automatic Backups (recommended) + Manual Backups + A manually exported wallet backup file may also be used for recovery, along with your seed phrase(s).\n\nOnly the **current configuration** of your wallet is backed up with each manual export. + Export Wallet Backup File + Encrypt this backup with a password? + Exported wallet backup file + Yes + No + Encrypt Wallet Backup File + Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. + Decrypt Wallet Backup File + Enter the password you chose when you originally encrypted this Wallet Backup file. + Enter password + Confirm password + Passwords do not match + Encryption password + Decryption password + Incorrect password + OK + Failed to encrypt using provided password. + Failed to decrypt using provided password. + Delete Wallet + WARNING. This will clear all contents of your Wallet. If you have no backup, you will lose access to your Accounts and Personas permanently. + Delete Wallet + Reset Wallet? + Reset Wallet + Reset and Delete iCloud Backup + WARNING. This will clear all contents of your Wallet. If you have no backup, you will lose access to your Accounts and Personas permanently. + Back up is turned off + Last Backed up: %s + Not backed up yet + Open System Backup Settings + Backup Wallet Data to Cloud + Warning: If disabled you might lose access to your Accounts and Personas. + You may delete your wallet. This will clear the Radix Wallet app, clears its contents, and delete any cloud backup.\n\n**Access to any Accounts or Personas will be permanently lost unless you have a manual backup file.** + Delete Wallet + Enabling iCloud sync + iCloud sync is now enabled, but it might take up to an hour before your wallet data is uploaded to iCloud. + Disabling iCloud sync will delete the iCloud backup data, are you sure you want to disable iCloud sync? + Enable Backup to iCloud + Disable Backup to iCloud + Automatic continuous backups + Sync Wallet Data to iCloud + Warning: If disabled you might lose access to your Accounts and Personas. + Wallet Data Backup + Import From Backup + Available backups: + Use iCloud Backup Data + This Device + Backup created by: %s + Creation date: %s + Last used on device: %s + Last modified date: %s + Number of networks: %d + Number of Accounts: %d + Number of Personas: %d + Incompatible Wallet data + You may delete your wallet. This will clear the Radix Wallet app, clears its contents, and delete any iCloud backup.\n\n**Access to any Accounts or Personas will be permanently lost unless you have a manual backup file.** + Delete Wallet and iCloud Backup + Unable to find wallet backup in iCloud. + Encrypt Wallet Backup File + Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. + Enter password + Confirm password + Passwords do not match + Restore Wallet From Backup + Select a backup to restore your Radix Wallet. You will be asked to enter your seed phrase(s) to recover control of your Accounts and Personas. + Choose a backup + Choose a backup on iCloud + No wallet backups available on current iCloud account + No wallet backups available + **Backup from:** %s + **Last modified:** %s + **Number of accounts:** %d + **Number of personas:** %d + Import from Backup File Instead + Incompatible Wallet data + The password is wrong + Backup not available? + Other Restore Options + Main Seed Phrase Required + No Main Seed Phrase? + Seed Phrase Required + Your **Personas** and the following **Accounts** are controlled by your main seed phrase. To recover control, you must re-enter it. + The following **Accounts** are controlled by a seed phrase. To recover control, you must re-enter it. + The Radix Wallet always uses a single main “Babylon” seed phrase to generate new Personas and new Accounts (when not using a Ledger device).\n\nIf you do not have access to your previous main seed phrase, you can skip entering it for now. **The Radix Wallet will create a new one, which will be used for new Personas and Accounts.**\n\nYour old Accounts and Personas will still be listed, but you will have to enter their original seed phrase to use them. Alternatively, you can hide them if you no longer are interested in using them. + Skip This Seed Phrase For Now + I Don’t Have the Main Seed Phrase + Enter This Seed Phrase + Skip Main Seed Phrase Entry + Hidden accounts only. + Phone + Ledger + Seed phrase + Third-party + Security Questions + Customize Fees + Estimated Transaction Fees + Transaction Fee + (maximum to lock) + Advanced Customize Fees + Choose what account to pay the transaction fee from, or add a \"tip\" to speed up your transaction if necessary. + Fully customize fee payment for this transaction. Not recomended unless you are a developer or advanced user. + Pay fee from + Change + None required + None due + No account selected + Select Fee Payer + Select an account to pay %s XRD transaction fee + Select Account + View Normal Mode + View Advanced Mode + Network Fee + Network Execution + Network Finalization + Effective Tip + Network Storage + Padding + Royalties + Royalty fee + Paid by dApps + Adjust Fee Padding Amount (XRD) + Adjust Tip to Lock + (%% of Execution + Finalization Fees) + Please select a fee payer for the transaction fee + Not enough XRD for transaction fee + Scanning in progress + Scanning for Accounts that have been included in at least one transaction, using: + **Babylon Seed Phrase** + **Olympia Seed Phrase** + **Ledger hardware wallet device** + Signing Factor + Unnamed + Scanning network + Scan Complete + The first **%d** potential Accounts from this signing factor were scanned. The following Accounts had at least one transaction: + No new accounts found + Tap here to scan the next %d + Continue + Add Inactive Accounts? + These Accounts were never used, but you **may** have created them. Select any addresses that you wish to keep: + Continue + Account Recovery Scan + The Radix Wallet can scan for previously used accounts using a bare seed phrase or Ledger hardware wallet device + Babylon Accounts + Scan for Accounts originally created on the **Babylon** network. + Olympia Accounts + Scan for Accounts originally created on the **Olympia** network.\n\n(If you have Olympia Accounts in the Radix Olympia Desktop Wallet, consider using **Import from a Legacy Wallet** instead. + Note: You will still use the new **Radix Babylon** app on your Ledger device, not the old Radix Ledger app. + Use Seed Phrase + Use Ledger Hardware Wallet + Choose Seed Phrase + Choose the \"Legacy\" Olympia seed phrase for use for derivation: + Choose the Babylon seed phrase for use for derivation: + Add Babylon Seed Phrase + Add Olympia Seed Phrase + Enter Legacy Seed Phrase + Enter Seed Phrase + Continue + Note: You must still use the new *Radix Babylon* app on your Ledger device, not the old Radix Ledger app. + Seed Phrases + Ledger Hardware Wallets + Default Deposit Guarantees + Set your default guaranteed minimum for estimated deposits + Set the guaranteed minimum deposit to be applied whenever a deposit in a transaction can only be estimated.\n\nYou can always change the guarantee from this default in each transaction. + Account Recovery Scan + Using seed phrase or Ledger device + Backups + Import from a Legacy Wallet + Enter Seed Phrase + Enter Main Seed Phrase + For your safety, make sure no one is looking at your screen. Never give your seed phrase to anyone for any reason. + Enter Main Seed Phrase + Enter Babylon Seed Phrase + Enter Olympia Seed Phrase + Recover Control Without Backup + If you have no wallet backup in the cloud, or as an exported backup file, you still have other restore options. + I have my main “Babylon” 24-word seed phrase. + Recover with Main Seed Phrase + I only want to restore Ledger hardware wallet Accounts. + Ledger-only Restore + I only have Accounts created on the Radix Olympia network. + Olympia-only Restore + No Main Seed Phrase? + Tap “I\'m a New Wallet User”. After completing wallet creation, in Settings you can perform an “account recovery scan” using your Ledger device. + Tap “I\'m a New Wallet User”. After completing wallet creation, in Settings you can perform an “account recovery scan” using your Olympia seed phrase. + Cancel + Continue + Recover Control Without Backup + **If you have no wallet backup in the cloud or as an exported backup file**, you can still restore Account access only using your main “Babylon” seed phrase. You cannot recover your Account names or other wallet settings this way.\n\nYou will be asked to enter your main seed phrase. This is a set of **24 words** that the Radix Wallet mobile app showed you to write down and save securely. + Continue + Recovery Complete + Accounts discovered in the scan have been added to your wallet.\n\nIf you have any “Legacy” Accounts (created on the Olympia network) to import - or any Accounts using a Ledger hardware wallet device - please continue and then use the **Account Recovery Scan** option in your Radix Wallet settings under **Account Security**. + Continue + History + Settings + Withdrawn + Deposited + Updated Account Deposit Settings + No deposits or withdrawals from this account in this transaction. + This transaction cannot be summarized. Only the raw transaction manifest may be viewed. + Failed Transaction + You have no Transactions. + General + Transfer + Stake + Request Unstake + Claim Stake + Contribute + Redeem + Deposit Settings + Other + Filter + Clear All + Show Results + Type of Asset + Show All Tokens + Show Less Tokens + Show All NFTs + Show Less NFTs + Tokens + Deposits + Withdrawals + NFTs + Type of Transaction + Today + Yesterday + How\'s it Going? + How likely are you to recommend Radix and the Radix Wallet to your friends or colleagues? + 0 - Not likely + 10 - Very likely + What’s the main reason for your score? + Let us know... + Submit Feedback - Thanks! + Signature Request + Creating Account + Creating Persona + Deriving Accounts + Proving Ownership + Encrypting Message + Creating Key + Authenticate to your phone to sign. + Authenticate to your phone to complete using your phone\'s signing key. + Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. **Complete signing on the device.** - Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. + Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. **Derivation may take up to a minute.** - Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. - Security Center - Decentralized security settings that give you total control over your wallet’s protection. - Your wallet is recoverable - Security Factors - The keys you use to control your Accounts and Personas - Active - Configuration Backup - A backup of your Account, Personas and wallet settings - Backed up - Action required - Encrypt Wallet Backup File - Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. - Enter Password - Confirm Password - Passwords do not match - Continue - Security Factors - View and manage your security factors - Seed Phrases - Your seedphrases connected to your account - 1 Seed phrase - %d Seed phrases - Enter your seed phrase to recover Accounts - Ledger Hardware Wallets - Hardware wallet designed for holding crypto - 1 set - %d set - Configuration Backup - You need an up-to-date Configuration Backup to recover your Accounts and Personas if you lose access to them.\n\nYour Backup does not contain your keys or seed phrase. - Configuration Backup status - Without an updated Configuration Backup, you cannot recover your Accounts and Personas. - Automated iCloud Backups - Automated Google Drive Backups - Last backup: %s - Log in to Google Drive - Logged in as: - Disconnect - Out-of-date backup still present on iCloud - Delete - Accounts - Your list of Accounts and the Factors required to recover them - Personas - Your list of Personas and the Factors required to recover them. Also your Persona data. - Security Factors - The list of Security Factors you need to recover your Accounts and Personas. - Wallet settings - Your general settings, such as trusted dApps, linked Connectors and wallet display settings. - Wallet Control Has Been Transferred - The current wallet configuration is now controlled by another phone. - If this was done in error, you can reclaim control to this phone. You won’t be able to access it from your old phone after the transfer. - Or, you can clear the wallet configuration from this phone and start fresh. - Clear Wallet on This Phone - Transfer Control Back to This Phone - Backups on Google Drive Have Updated - The Radix Wallet has an all new and improved backup system.\n\nTo continue, log in with the Google Drive account you want to use for backups. - Login to Google Drive for Backups - Skip for Now - Manual backup - You can export your own Configuration Backup file and save it locally - You’ll need to export a new Backup file each time you make a change in your wallet. - Export Backup File - Last backup: %s - Wallet Settings - Security Center - Manage your wallet security settings - Personas - Manage Radix dApp login details - Please write down the seed phrase for your Personas - Approved dApps - Manage the Radix dApps you\'re connected to - Linked Connectors - Connect to desktop through the Radix Connector browser extension - Preferences - Deposits, hidden Accounts and Personas, and advanced preferences - Troubleshooting - Add your existing Accounts and contact support - App version: %s - Link your Wallet to a desktop browser - Scan the QR code in the Radix Wallet Connector extension - Link to Connector - Preferences - Default Deposit Guarantees - Set your guaranteed minimum for estimated deposits - Hidden Accounts and Personas - Manage hidden Accounts and Personas - Advanced Preferences - Network Gateways - Developer Mode - Warning: disables website validity checks - Troubleshooting - Account Recovery - Account Recovery Scan - Recover Accounts with a seed phrase or Ledger device - Import from a Legacy Wallet - Import Accounts from an Olympia wallet - Support and Community - Contact Support - Connect directly with the Radix support team - Discord - Connect to the official Radix Discord channel to join the community and ask for help. - Reset Account - Factory Reset - Restore your Radix wallet to its original state - Address QR Code - Full address - Copy - Enlarge - Share - View on Radix Dashboard - Verify Address on Ledger Device - Could not create QR code - Today - Yesterday - Tomorrow - %s ago - Just now - Factory Reset - A factory reset will restore your Radix wallet to its original settings. All of your data and preferences will be erased. - Security Center status - Your wallet is recoverable - Your wallet is not recoverable - Your wallet is currently unrecoverable. If you do a factory reset now, you will never be able to access your Accounts and Personas again. - Once you’ve completed a factory reset, you will not be able to access your Accounts and Personas unless you do a full recovery. - Reset Wallet - Confirm factory reset - Return wallet to factory settings? You cannot undo this. - You need to write down a seed phrase - %s and %s are not recoverable. - %s and %s (plus some hidden) are not recoverable. - View and write down your seed phrase so Accounts and Personas are recoverable. - View and write down seed phrase - View and write down seed phrase - Personas are not recoverable - You need to write down a seed phrase - Problem with Configuration Backup - Your wallet is not recoverable - Automated Configuration Backup has stopped working. Check internet and cloud settings. - Automated Configuration Backup not working. Check internet connection and cloud settings. - Personas are not recoverable - Problem with Configuration Backup - Your wallet is not recoverable - Your wallet is not recoverable - Configuration Backup is not up to date. Create backup now. - To secure your wallet, turn on automated backups or manually export backup file. - Personas are not recoverable - Your wallet is not recoverable - Configuration Backup not up to date - Your wallet is not recoverable - Accounts and Personas not recoverable. Create Configuration Backup now. - Configuration Backup not up to date. Turn on automated backups or manually export backup file. - Personas are not recoverable - Configuration Backup not up to date - Recovery required - Recovery required - Enter seed phrase to recover control. - Enter seed phrase to recover control - Enter seed phrase to recover control - Recovery required - Recovery required - 1 account - %d accounts - 1 persona - %d personas + Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. + Security Center + Decentralized security settings that give you total control over your wallet’s protection. + Your wallet is recoverable + Security Factors + The keys you use to control your Accounts and Personas + Active + Configuration Backup + A backup of your Account, Personas and wallet settings + Backed up + Action required + Encrypt Wallet Backup File + Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. + Enter Password + Confirm Password + Passwords do not match + Continue + Security Factors + View and manage your security factors + Seed Phrases + Your seedphrases connected to your account + 1 Seed phrase + %d Seed phrases + Enter your seed phrase to recover Accounts + Ledger Hardware Wallets + Hardware wallet designed for holding crypto + 1 set + %d set + Configuration Backup + You need an up-to-date Configuration Backup to recover your Accounts and Personas if you lose access to them.\n\nYour Backup does not contain your keys or seed phrase. + Configuration Backup status + Without an updated Configuration Backup, you cannot recover your Accounts and Personas. + Automated iCloud Backups + Automated Google Drive Backups + Last backup: %s + Log in to Google Drive + Logged in as: + Disconnect + Out-of-date backup still present on iCloud + Delete + Accounts + Your list of Accounts and the Factors required to recover them + Personas + Your list of Personas and the Factors required to recover them. Also your Persona data. + Security Factors + The list of Security Factors you need to recover your Accounts and Personas. + Wallet settings + Your general settings, such as trusted dApps, linked Connectors and wallet display settings. + Wallet Control Has Been Transferred + The current wallet configuration is now controlled by another phone. + If this was done in error, you can reclaim control to this phone. You won’t be able to access it from your old phone after the transfer. + Or, you can clear the wallet configuration from this phone and start fresh. + Clear Wallet on This Phone + Transfer Control Back to This Phone + Backups on Google Drive Have Updated + The Radix Wallet has an all new and improved backup system.\n\nTo continue, log in with the Google Drive account you want to use for backups. + Login to Google Drive for Backups + Skip for Now + Manual backup + You can export your own Configuration Backup file and save it locally + You’ll need to export a new Backup file each time you make a change in your wallet. + Export Backup File + Last backup: %s + Wallet Settings + Security Center + Manage your wallet security settings + Personas + Manage Radix dApp login details + Please write down the seed phrase for your Personas + Approved dApps + Manage the Radix dApps you\'re connected to + Linked Connectors + Connect to desktop through the Radix Connector browser extension + Preferences + Deposits, hidden Accounts and Personas, and advanced preferences + Troubleshooting + Add your existing Accounts and contact support + App version: %s + Link your Wallet to a desktop browser + Scan the QR code in the Radix Wallet Connector extension + Link to Connector + Preferences + Default Deposit Guarantees + Set your guaranteed minimum for estimated deposits + Hidden Accounts and Personas + Manage hidden Accounts and Personas + Advanced Preferences + Network Gateways + Developer Mode + Warning: disables website validity checks + Troubleshooting + Account Recovery + Account Recovery Scan + Recover Accounts with a seed phrase or Ledger device + Import from a Legacy Wallet + Import Accounts from an Olympia wallet + Support and Community + Contact Support + Connect directly with the Radix support team + Discord + Connect to the official Radix Discord channel to join the community and ask for help. + Reset Account + Factory Reset + Restore your Radix wallet to its original state + Address QR Code + Full address + Copy + Enlarge + Share + View on Radix Dashboard + Verify Address on Ledger Device + Could not create QR code + Today + Yesterday + Tomorrow + %s ago + Just now + Factory Reset + A factory reset will restore your Radix wallet to its original settings. All of your data and preferences will be erased. + Security Center status + Your wallet is recoverable + Your wallet is not recoverable + Your wallet is currently unrecoverable. If you do a factory reset now, you will never be able to access your Accounts and Personas again. + Once you’ve completed a factory reset, you will not be able to access your Accounts and Personas unless you do a full recovery. + Reset Wallet + Confirm factory reset + Return wallet to factory settings? You cannot undo this. + You need to write down a seed phrase + %s and %s are not recoverable. + %s and %s (plus some hidden) are not recoverable. + View and write down your seed phrase so Accounts and Personas are recoverable. + View and write down seed phrase + View and write down seed phrase + Personas are not recoverable + You need to write down a seed phrase + Problem with Configuration Backup + Your wallet is not recoverable + Automated Configuration Backup has stopped working. Check internet and cloud settings. + Automated Configuration Backup not working. Check internet connection and cloud settings. + Personas are not recoverable + Problem with Configuration Backup + Your wallet is not recoverable + Your wallet is not recoverable + Configuration Backup is not up to date. Create backup now. + To secure your wallet, turn on automated backups or manually export backup file. + Personas are not recoverable + Your wallet is not recoverable + Configuration Backup not up to date + Your wallet is not recoverable + Accounts and Personas not recoverable. Create Configuration Backup now. + Configuration Backup not up to date. Turn on automated backups or manually export backup file. + Personas are not recoverable + Configuration Backup not up to date + Recovery required + Recovery required + Enter seed phrase to recover control. + Enter seed phrase to recover control + Enter seed phrase to recover control + Recovery required + Recovery required + 1 account + %d accounts + 1 persona + %d personas - Connecting to %s - You’re connecting to %s for the first time - For this first connection, we’re going to run some quick automatic checks to verify the dApp. - Never show this screen again - Run all future verification checks automatically + Have you come from a genuine website? + Before you connect to %s, you should be confident the site is safe. + \u2022 Check the website address to see if it matches what you\'re expecting.\n\u2022 If you came from a social media ad, make sure it\'s legitimate diff --git a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt index c98448248d..95bbe2c936 100644 --- a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt @@ -1,8 +1,11 @@ package com.babylon.wallet.android.data.dapp import com.babylon.wallet.android.domain.model.IncomingMessage +import com.babylon.wallet.android.utils.AppEvent +import com.babylon.wallet.android.utils.AppEventBusImpl import com.radixdlt.sargon.NetworkId -import com.radixdlt.sargon.WalletInteractionId +import io.mockk.coVerify +import io.mockk.spyk import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -20,7 +23,8 @@ import java.util.UUID @OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class) class IncomingRequestRepositoryTest { - private val incomingRequestRepository = IncomingRequestRepositoryImpl() + private val eventBus = spyk() + private val incomingRequestRepository = IncomingRequestRepositoryImpl(eventBus) private val amountOfIncomingRequests = 100 private val sampleIncomingRequest = IncomingMessage.IncomingRequest.AuthorizedRequest( remoteEntityId = IncomingMessage.RemoteEntityID.ConnectorId("remoteConnectorId"), @@ -78,18 +82,58 @@ class IncomingRequestRepositoryTest { } advanceUntilIdle() assertTrue(incomingRequestRepository.getAmountOfRequests() == 5) - assert(currentRequest?.interactionId.toString() == interactionIds[0].toString()) - incomingRequestRepository.requestHandled(interactionIds[0].toString()) - incomingRequestRepository.requestHandled(interactionIds[1].toString()) + assert(currentRequest?.interactionId.toString() == interactionIds[0]) + incomingRequestRepository.requestHandled(interactionIds[0]) + incomingRequestRepository.requestHandled(interactionIds[1]) advanceUntilIdle() - assert(currentRequest?.interactionId.toString() == interactionIds[2].toString()) + assert(currentRequest?.interactionId.toString() == interactionIds[2]) assertTrue(incomingRequestRepository.getAmountOfRequests() == 3) - incomingRequestRepository.requestHandled(interactionIds[2].toString()) - incomingRequestRepository.requestHandled(interactionIds[3].toString()) + incomingRequestRepository.requestHandled(interactionIds[2]) + incomingRequestRepository.requestHandled(interactionIds[3]) advanceUntilIdle() - assert(currentRequest?.interactionId.toString() == interactionIds[4].toString()) + assert(currentRequest?.interactionId.toString() == interactionIds[4]) assertTrue(incomingRequestRepository.getAmountOfRequests() == 1) - incomingRequestRepository.requestHandled(interactionIds[4].toString()) + incomingRequestRepository.requestHandled(interactionIds[4]) assertTrue(incomingRequestRepository.getAmountOfRequests() == 0) } + + @Test + fun `addFirst takes priority over current and sends dismiss event for previous current`() = runTest { + var currentRequest: IncomingMessage.IncomingRequest? = null + val interactionId1 = UUID.randomUUID().toString() + val interactionId2 = UUID.randomUUID().toString() + incomingRequestRepository.currentRequestToHandle + .onEach { currentRequest = it } + .launchIn(CoroutineScope(UnconfinedTestDispatcher(testScheduler))) + incomingRequestRepository.add(incomingRequest = sampleIncomingRequest.copy(interactionId = interactionId1)) + advanceUntilIdle() + assertTrue(incomingRequestRepository.getAmountOfRequests() == 1) + assert(currentRequest?.interactionId == interactionId1) + incomingRequestRepository.addFirst(sampleIncomingRequest.copy(interactionId = interactionId2)) + advanceUntilIdle() + assert(currentRequest?.interactionId == interactionId2) + assertTrue(incomingRequestRepository.getAmountOfRequests() == 2) + coVerify(exactly = 1) { eventBus.sendEvent(AppEvent.DismissRequestHandling(interactionId1)) } + } + + @Test + fun `addFirst inserts item at 2nd position when there is high priority screen`() = runTest { + var currentRequest: IncomingMessage.IncomingRequest? = null + val interactionId1 = UUID.randomUUID().toString() + val interactionId2 = UUID.randomUUID().toString() + incomingRequestRepository.currentRequestToHandle + .onEach { currentRequest = it } + .launchIn(CoroutineScope(UnconfinedTestDispatcher(testScheduler))) + incomingRequestRepository.pauseIncomingRequests() + incomingRequestRepository.add(incomingRequest = sampleIncomingRequest.copy(interactionId = interactionId1)) + advanceUntilIdle() + assertTrue(incomingRequestRepository.getAmountOfRequests() == 1) + assert(currentRequest?.interactionId == null) + incomingRequestRepository.addFirst(sampleIncomingRequest.copy(interactionId = interactionId2)) + advanceUntilIdle() + incomingRequestRepository.resumeIncomingRequests() + advanceUntilIdle() + assert(currentRequest?.interactionId == interactionId2) + assertTrue(incomingRequestRepository.getAmountOfRequests() == 2) + } } diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/ChooseAccountsViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/ChooseAccountsViewModelTest.kt index 88b8a64f3a..fdf6b11b98 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/ChooseAccountsViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/ChooseAccountsViewModelTest.kt @@ -7,10 +7,10 @@ import com.babylon.wallet.android.fakes.FakeProfileRepository import com.babylon.wallet.android.presentation.dapp.unauthorized.accountonetime.ARG_EXACT_ACCOUNT_COUNT import com.babylon.wallet.android.presentation.dapp.unauthorized.accountonetime.ARG_NUMBER_OF_ACCOUNTS import com.babylon.wallet.android.presentation.dapp.unauthorized.accountonetime.OneTimeChooseAccountsViewModel +import com.babylon.wallet.android.utils.AppEventBusImpl import com.radixdlt.sargon.Gateway import com.radixdlt.sargon.NetworkId import com.radixdlt.sargon.Profile -import com.radixdlt.sargon.WalletInteractionId import com.radixdlt.sargon.extensions.forNetwork import com.radixdlt.sargon.samples.sample import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -41,7 +41,7 @@ class ChooseAccountsViewModelTest { ) private val getProfileUseCase = GetProfileUseCase(profileRepository) - private val incomingRequestRepository = IncomingRequestRepositoryImpl() + private val incomingRequestRepository = IncomingRequestRepositoryImpl(AppEventBusImpl()) private lateinit var viewModel: OneTimeChooseAccountsViewModel diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt index e6a71caa51..ce54a4bb52 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt @@ -32,7 +32,6 @@ import com.radixdlt.sargon.PoolAddress import com.radixdlt.sargon.Profile import com.radixdlt.sargon.ResourceAddress import com.radixdlt.sargon.ValidatorAddress -import com.radixdlt.sargon.WalletInteractionId import com.radixdlt.sargon.extensions.AuthorizedDapps import com.radixdlt.sargon.extensions.Personas import com.radixdlt.sargon.extensions.ProfileEntity @@ -203,12 +202,13 @@ class DAppAuthorizedLoginViewModelTest : StateViewModelTest(ARG_INTERACTION_ID) } returns "1" coEvery { getCurrentGatewayUseCase() } returns Gateway.forNetwork(NetworkId.MAINNET) every { buildAuthorizedDappResponseUseCase.signingState } returns emptyFlow() coEvery { buildAuthorizedDappResponseUseCase.invoke(any(), any(), any(), any(), any(), any()) } returns Result.success(any()) coEvery { getProfileUseCase() } returns sampleProfile - coEvery { incomingRequestRepository.getAuthorizedRequest(any()) } returns requestWithNonExistingDappAddress + coEvery { incomingRequestRepository.getRequest(any()) } returns requestWithNonExistingDappAddress } @Test @@ -243,7 +243,7 @@ class DAppAuthorizedLoginViewModelTest : StateViewModelTest() { - private val incomingRequestRepository = IncomingRequestRepositoryImpl() + private val incomingRequestRepository = IncomingRequestRepositoryImpl(AppEventBusImpl()) private val getProfileUseCase = mockk() private val savedStateHandle = mockk() private val getDAppWithAssociatedResourcesUseCase = mockk() diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/settings/dappdetail/DappDetailViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/settings/dappdetail/DappDetailViewModelTest.kt index b8b88b0b6e..39bb021d7b 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/settings/dappdetail/DappDetailViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/settings/dappdetail/DappDetailViewModelTest.kt @@ -13,6 +13,7 @@ import com.babylon.wallet.android.presentation.settings.approveddapps.dappdetail import com.babylon.wallet.android.presentation.settings.approveddapps.dappdetail.DappDetailEvent import com.babylon.wallet.android.presentation.settings.approveddapps.dappdetail.DappDetailViewModel import com.babylon.wallet.android.presentation.settings.approveddapps.dappdetail.SelectedSheetState +import com.babylon.wallet.android.utils.AppEventBusImpl import com.radixdlt.sargon.AuthorizedDapp import com.radixdlt.sargon.AuthorizedPersonaSimple import com.radixdlt.sargon.Gateway @@ -50,7 +51,7 @@ import rdx.works.profile.domain.GetProfileUseCase @OptIn(ExperimentalCoroutinesApi::class) internal class DappDetailViewModelTest : StateViewModelTest() { - private val incomingRequestRepository = IncomingRequestRepositoryImpl() + private val incomingRequestRepository = IncomingRequestRepositoryImpl(AppEventBusImpl()) private val getProfileUseCase = mockk() private val savedStateHandle = mockk() private val getDAppWithAssociatedResourcesUseCase = mockk() diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt index e3e8292376..adfc01c134 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt @@ -53,7 +53,6 @@ import com.radixdlt.sargon.NetworkId import com.radixdlt.sargon.NewEntities import com.radixdlt.sargon.Profile import com.radixdlt.sargon.ResourceAddress -import com.radixdlt.sargon.WalletInteractionId import com.radixdlt.sargon.extensions.Curve25519SecretKey import com.radixdlt.sargon.extensions.forNetwork import com.radixdlt.sargon.extensions.rounded @@ -114,9 +113,9 @@ internal class TransactionReviewViewModelTest : StateViewModelTest() private val resolveNotaryAndSignersUseCase = mockk() private val transactionRepository = mockk() - private val incomingRequestRepository = IncomingRequestRepositoryImpl() private val respondToIncomingRequestUseCase = mockk() private val appEventBus = mockk() + private val incomingRequestRepository = IncomingRequestRepositoryImpl(appEventBus) private val deviceCapabilityHelper = mockk() private val savedStateHandle = mockk() private val exceptionMessageProvider = mockk() @@ -295,7 +294,8 @@ internal class TransactionReviewViewModelTest : StateViewModelTest() private val respondToIncomingRequestUseCase = mockk() - private val appEventBus = mockk() + private val appEventBus = AppEventBusImpl() private val exceptionMessageProvider = mockk() private val signTransactionUseCase = mockk().apply { every { signingState } returns flowOf() @@ -106,7 +105,7 @@ internal class TransactionReviewViewModelTestExperimental : StateViewModelTest Date: Mon, 24 Jun 2024 12:13:15 +0200 Subject: [PATCH 02/12] update mobile connect requests handling --- .../data/dapp/IncomingRequestRepository.kt | 32 ++++++------- .../deeplink/ProcessDeepLinkUseCase.kt | 2 +- .../login/DAppAuthorizedLoginViewModel.kt | 1 + .../login/DAppUnauthorizedLoginViewModel.kt | 5 +- .../transaction/TransactionReviewNav.kt | 2 +- .../transaction/TransactionReviewScreen.kt | 10 ++-- .../transaction/TransactionReviewViewModel.kt | 26 ++++++---- .../submit/TransactionSubmitDelegate.kt | 48 ++++++++++--------- .../dapp/IncomingRequestRepositoryTest.kt | 7 +-- .../TransactionReviewViewModelTest.kt | 7 ++- ...nsactionReviewViewModelTestExperimental.kt | 5 +- 11 files changed, 80 insertions(+), 65 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt index 32caf6a862..b3c4b05f0a 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt @@ -19,7 +19,7 @@ interface IncomingRequestRepository { suspend fun add(incomingRequest: IncomingRequest) - suspend fun addFirst(incomingRequest: IncomingRequest) + suspend fun addMobileConnectRequest(incomingRequest: IncomingRequest) suspend fun requestHandled(requestId: String) @@ -32,6 +32,7 @@ interface IncomingRequestRepository { fun removeAll() fun getAmountOfRequests(): Int + suspend fun requestDismissed(requestId: String) } class IncomingRequestRepositoryImpl @Inject constructor( @@ -78,21 +79,12 @@ class IncomingRequestRepositoryImpl @Inject constructor( * we send a dismiss event for it so that UI can react and dismiss handling, without removing it from the queue. * Dismissed request will be handled again when top priority one handling completes */ - override suspend fun addFirst(incomingRequest: IncomingRequest) { + override suspend fun addMobileConnectRequest(incomingRequest: IncomingRequest) { mutex.withLock { - if (requestQueue.firstOrNull() is QueueItem.HighPriorityScreen) { - requestQueue.add(1, QueueItem.RequestItem(incomingRequest)) - } else { - requestQueue.addFirst(QueueItem.RequestItem(incomingRequest)) - _currentRequestToHandle.value?.let { - Timber.d("🗂 Dismissing request with id ${it.interactionId}") - appEventBus.sendEvent(AppEvent.DismissRequestHandling(it.interactionId)) - } - handleNextRequest() - Timber.d( - "🗂 new incoming request with id ${incomingRequest.interactionId} " + - "added in list, so size now is ${getAmountOfRequests()}" - ) + requestQueue.addFirst(QueueItem.RequestItem(incomingRequest)) + _currentRequestToHandle.value?.let { + Timber.d("🗂 Dismissing request with id ${it.interactionId}") + appEventBus.sendEvent(AppEvent.DismissRequestHandling(it.interactionId)) } } } @@ -105,6 +97,13 @@ class IncomingRequestRepositoryImpl @Inject constructor( } } + override suspend fun requestDismissed(requestId: String) { + mutex.withLock { + handleNextRequest() + Timber.d("🗂 request $requestId handled so size of list is now: ${getAmountOfRequests()}") + } + } + override suspend fun pauseIncomingRequests() { mutex.withLock { // If the queue knows about any high priority item, no need to add it again @@ -157,7 +156,7 @@ class IncomingRequestRepositoryImpl @Inject constructor( // In order to emit an incoming request, the topmost item should be // a. An incoming request // b. It should not be the same as the one being handled already - if (nextRequest is QueueItem.RequestItem && _currentRequestToHandle.value != nextRequest) { + if (nextRequest is QueueItem.RequestItem && _currentRequestToHandle.value != nextRequest.incomingRequest) { _currentRequestToHandle.emit(nextRequest.incomingRequest) } } @@ -165,6 +164,5 @@ class IncomingRequestRepositoryImpl @Inject constructor( private sealed interface QueueItem { data object HighPriorityScreen : QueueItem data class RequestItem(val incomingRequest: IncomingRequest) : QueueItem - data class MobileConnectItem(val incomingRequest: IncomingRequest) : QueueItem } } diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt index e02694f3e5..76f6d8882c 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt @@ -18,7 +18,7 @@ class ProcessDeepLinkUseCase @Inject constructor( return }.getOrThrow() - incomingRequestRepository.addFirst( + incomingRequestRepository.addMobileConnectRequest( sessionRequest.interaction.toDomainModel( remoteEntityId = IncomingMessage.RemoteEntityID.RadixMobileConnectRemoteSession( id = sessionRequest.sessionId.toString(), diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt index af849bff6d..26f3631d42 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt @@ -97,6 +97,7 @@ class DAppAuthorizedLoginViewModel @Inject constructor( appEventBus.events.filterIsInstance().collect { if (it.interactionId == args.interactionId) { sendEvent(Event.CloseLoginFlow) + incomingRequestRepository.requestDismissed(args.interactionId) } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt index e6f0ae81eb..f6630fae20 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt @@ -73,11 +73,14 @@ class DAppUnauthorizedLoginViewModel @Inject constructor( appEventBus.events.filterIsInstance().collect { if (it.interactionId == args.interactionId) { sendEvent(Event.CloseLoginFlow) + incomingRequestRepository.requestDismissed(args.interactionId) } } } viewModelScope.launch { - val requestToHandle = incomingRequestRepository.getRequest(args.interactionId) as? IncomingMessage.IncomingRequest.UnauthorizedRequest + val requestToHandle = incomingRequestRepository.getRequest( + args.interactionId + ) as? IncomingMessage.IncomingRequest.UnauthorizedRequest if (requestToHandle == null) { sendEvent(Event.CloseLoginFlow) return@launch diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewNav.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewNav.kt index 8cbab7e998..85875bb977 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewNav.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewNav.kt @@ -18,7 +18,7 @@ internal const val ARG_TRANSACTION_REQUEST_ID = "arg_transaction_request_id" const val ROUTE_TRANSACTION_REVIEW = "transaction_review_route/{$ARG_TRANSACTION_REQUEST_ID}" -internal class TransactionReviewArgs(val requestId: String) { +internal class TransactionReviewArgs(val interactionId: String) { constructor(savedStateHandle: SavedStateHandle) : this( checkNotNull(savedStateHandle[ARG_TRANSACTION_REQUEST_ID]) as String ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt index 46b1853130..f3ba21f45c 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt @@ -85,7 +85,6 @@ fun TransactionReviewScreen( ) { val state by viewModel.state.collectAsStateWithLifecycle() val context = LocalContext.current - TransactionPreviewContent( onBackClick = viewModel::onBackClick, state = state, @@ -139,10 +138,11 @@ fun TransactionReviewScreen( ) } } - - LaunchedEffect(state.isTransactionDismissed) { - if (state.isTransactionDismissed) { - onDismiss() + LaunchedEffect(Unit) { + viewModel.oneOffEvent.collect { event -> + when (event) { + Event.Dismiss -> onDismiss() + } } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt index 54a818109e..2ae3000699 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt @@ -15,6 +15,9 @@ import com.babylon.wallet.android.domain.model.Transferable import com.babylon.wallet.android.domain.model.TransferableAsset import com.babylon.wallet.android.domain.usecases.GetDAppsUseCase import com.babylon.wallet.android.domain.usecases.SignTransactionUseCase +import com.babylon.wallet.android.presentation.common.OneOffEvent +import com.babylon.wallet.android.presentation.common.OneOffEventHandler +import com.babylon.wallet.android.presentation.common.OneOffEventHandlerImpl import com.babylon.wallet.android.presentation.common.StateViewModel import com.babylon.wallet.android.presentation.common.UiMessage import com.babylon.wallet.android.presentation.common.UiState @@ -70,9 +73,9 @@ class TransactionReviewViewModel @Inject constructor( private val fees: TransactionFeesDelegate, private val submit: TransactionSubmitDelegate, private val getDAppsUseCase: GetDAppsUseCase, - incomingRequestRepository: IncomingRequestRepository, + private val incomingRequestRepository: IncomingRequestRepository, savedStateHandle: SavedStateHandle, -) : StateViewModel() { +) : StateViewModel(), OneOffEventHandler by OneOffEventHandlerImpl() { private val args = TransactionReviewArgs(savedStateHandle) @@ -87,13 +90,12 @@ class TransactionReviewViewModel @Inject constructor( guarantees(scope = viewModelScope, state = _state) fees(scope = viewModelScope, state = _state) submit(scope = viewModelScope, state = _state) + submit.oneOffEventHandler = this - val request = incomingRequestRepository.getRequest(args.requestId) as? IncomingMessage.IncomingRequest.TransactionRequest + val request = incomingRequestRepository.getRequest(args.interactionId) as? IncomingMessage.IncomingRequest.TransactionRequest if (request == null) { viewModelScope.launch { - _state.update { state -> - state.copy(isTransactionDismissed = true) - } + sendEvent(Event.Dismiss) } } else { _state.update { it.copy(request = request) } @@ -118,8 +120,9 @@ class TransactionReviewViewModel @Inject constructor( } viewModelScope.launch { appEventBus.events.filterIsInstance().collect { - _state.update { state -> - state.copy(isTransactionDismissed = true) + if (it.interactionId == args.interactionId) { + sendEvent(Event.Dismiss) + incomingRequestRepository.requestDismissed(args.interactionId) } } } @@ -261,8 +264,7 @@ class TransactionReviewViewModel @Inject constructor( private val latestFeesMode: Sheet.CustomizeFees.FeesMode = Sheet.CustomizeFees.FeesMode.Default, val error: TransactionErrorMessage? = null, val ephemeralNotaryPrivateKey: Curve25519SecretKey = Curve25519SecretKey.secureRandom(), - val interactionState: InteractionState? = null, - val isTransactionDismissed: Boolean = false + val interactionState: InteractionState? = null ) : UiState { val requestNonNull: IncomingMessage.IncomingRequest.TransactionRequest @@ -432,6 +434,10 @@ class TransactionReviewViewModel @Inject constructor( } } +sealed interface Event : OneOffEvent { + data object Dismiss : Event +} + data class TransactionErrorMessage( private val error: Throwable? ) { diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/submit/TransactionSubmitDelegate.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/submit/TransactionSubmitDelegate.kt index 86e08df470..a00cc5d20d 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/submit/TransactionSubmitDelegate.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/submit/TransactionSubmitDelegate.kt @@ -13,7 +13,9 @@ import com.babylon.wallet.android.domain.toConnectorExtensionError import com.babylon.wallet.android.domain.usecases.RespondToIncomingRequestUseCase import com.babylon.wallet.android.domain.usecases.SignTransactionUseCase import com.babylon.wallet.android.domain.usecases.transaction.SubmitTransactionUseCase +import com.babylon.wallet.android.presentation.common.OneOffEventHandler import com.babylon.wallet.android.presentation.common.ViewModelDelegate +import com.babylon.wallet.android.presentation.transaction.Event import com.babylon.wallet.android.presentation.transaction.PreviewType import com.babylon.wallet.android.presentation.transaction.TransactionErrorMessage import com.babylon.wallet.android.presentation.transaction.TransactionReviewViewModel @@ -52,6 +54,8 @@ class TransactionSubmitDelegate @Inject constructor( private var approvalJob: Job? = null + var oneOffEventHandler: OneOffEventHandler? = null + @Suppress("SwallowedException") fun onSubmit( signTransactionUseCase: SignTransactionUseCase, @@ -97,29 +101,29 @@ class TransactionSubmitDelegate @Inject constructor( suspend fun onDismiss( signTransactionUseCase: SignTransactionUseCase, exception: RadixWalletException.DappRequestException - ) { - if (approvalJob == null) { - val request = _state.value.requestNonNull - if (!request.isInternal) { - respondToIncomingRequestUseCase.respondWithFailure( - request = request, - error = exception.ceError, - message = exception.getDappMessage() - ) - } - _state.update { - it.copy(isTransactionDismissed = true) - } - incomingRequestRepository.requestHandled(request.interactionId.toString()) - } else if (_state.value.interactionState != null) { - approvalJob?.cancel() - approvalJob = null - signTransactionUseCase.cancelSigning() - _state.update { - it.copy(isSubmitting = false) + ): Result { + return runCatching { + if (approvalJob == null) { + val request = _state.value.requestNonNull + if (!request.isInternal) { + respondToIncomingRequestUseCase.respondWithFailure( + request = request, + error = exception.ceError, + message = exception.getDappMessage() + ) + } + oneOffEventHandler?.sendEvent(Event.Dismiss) + incomingRequestRepository.requestHandled(request.interactionId) + } else if (_state.value.interactionState != null) { + approvalJob?.cancel() + approvalJob = null + signTransactionUseCase.cancelSigning() + _state.update { + it.copy(isSubmitting = false) + } + } else { + logger.d("Cannot dismiss transaction while is in progress") } - } else { - logger.d("Cannot dismiss transaction while is in progress") } } diff --git a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt index 95bbe2c936..58922a28f2 100644 --- a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt @@ -98,7 +98,7 @@ class IncomingRequestRepositoryTest { } @Test - fun `addFirst takes priority over current and sends dismiss event for previous current`() = runTest { + fun `adding mobile connect request and dismissing current makes mobile request new current, while dismissed event stays in queue`() = runTest { var currentRequest: IncomingMessage.IncomingRequest? = null val interactionId1 = UUID.randomUUID().toString() val interactionId2 = UUID.randomUUID().toString() @@ -109,7 +109,8 @@ class IncomingRequestRepositoryTest { advanceUntilIdle() assertTrue(incomingRequestRepository.getAmountOfRequests() == 1) assert(currentRequest?.interactionId == interactionId1) - incomingRequestRepository.addFirst(sampleIncomingRequest.copy(interactionId = interactionId2)) + incomingRequestRepository.addMobileConnectRequest(sampleIncomingRequest.copy(interactionId = interactionId2)) + incomingRequestRepository.requestDismissed(interactionId1) advanceUntilIdle() assert(currentRequest?.interactionId == interactionId2) assertTrue(incomingRequestRepository.getAmountOfRequests() == 2) @@ -129,7 +130,7 @@ class IncomingRequestRepositoryTest { advanceUntilIdle() assertTrue(incomingRequestRepository.getAmountOfRequests() == 1) assert(currentRequest?.interactionId == null) - incomingRequestRepository.addFirst(sampleIncomingRequest.copy(interactionId = interactionId2)) + incomingRequestRepository.addMobileConnectRequest(sampleIncomingRequest.copy(interactionId = interactionId2)) advanceUntilIdle() incomingRequestRepository.resumeIncomingRequests() advanceUntilIdle() diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt index adfc01c134..d687acecbb 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt @@ -1,6 +1,7 @@ package com.babylon.wallet.android.presentation.transaction import androidx.lifecycle.SavedStateHandle +import app.cash.turbine.test import com.babylon.wallet.android.DefaultLocaleRule import com.babylon.wallet.android.data.dapp.IncomingRequestRepositoryImpl import com.babylon.wallet.android.data.gateway.coreapi.CoreApiTransactionReceipt @@ -68,6 +69,7 @@ import io.mockk.just import io.mockk.mockk import io.mockk.mockkStatic import io.mockk.slot +import junit.framework.TestCase import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.first @@ -77,7 +79,6 @@ import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull -import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Ignore import org.junit.Rule @@ -329,7 +330,9 @@ internal class TransactionReviewViewModelTest : StateViewModelTest Date: Mon, 24 Jun 2024 14:21:40 +0200 Subject: [PATCH 03/12] buffer deep link when wallet is not set up --- .../com/babylon/wallet/android/WalletApp.kt | 4 +-- .../data/dapp/IncomingRequestRepository.kt | 35 ++++++++++++++----- .../repository/BufferedDeepLinkRepository.kt | 25 +++++++++++++ .../deeplink/ProcessDeepLinkUseCase.kt | 35 +++++++++++++------ .../login/DAppAuthorizedLoginNav.kt | 5 +-- .../login/DAppAuthorizedLoginViewModel.kt | 2 +- .../login/DAppUnauthorizedLoginNav.kt | 5 +-- .../presentation/main/MainViewModel.kt | 24 +++++++------ .../mobileconnect/MobileConnectLinkNav.kt | 6 ++-- .../MobileConnectLinkViewModel.kt | 11 +++++- .../presentation/navigation/NavigationHost.kt | 16 +++++---- .../presentation/navigation/PriorityRoutes.kt | 3 +- .../transaction/TransactionReviewNav.kt | 5 +-- .../presentation/wallet/WalletViewModel.kt | 9 +++++ .../BufferedDeepLinkRepositoryTest.kt | 31 ++++++++++++++++ .../presentation/WalletViewModelTest.kt | 8 ++++- 16 files changed, 174 insertions(+), 50 deletions(-) create mode 100644 app/src/main/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepository.kt create mode 100644 app/src/test/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepositoryTest.kt diff --git a/app/src/main/java/com/babylon/wallet/android/WalletApp.kt b/app/src/main/java/com/babylon/wallet/android/WalletApp.kt index 52ebdbfc7b..cb9b021abe 100644 --- a/app/src/main/java/com/babylon/wallet/android/WalletApp.kt +++ b/app/src/main/java/com/babylon/wallet/android/WalletApp.kt @@ -177,10 +177,10 @@ fun WalletApp( dismissText = null ) } - if (!state.isProfileInitialized) { + if (state.showMobileConnectWarning) { BasicPromptAlertDialog( finish = { - onCloseApp() + mainViewModel.onMobileConnectWarningShown() }, titleText = "No profile found", messageText = "You need to create a profile to respond to dApp requests", diff --git a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt index b3c4b05f0a..347578555a 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt @@ -82,9 +82,19 @@ class IncomingRequestRepositoryImpl @Inject constructor( override suspend fun addMobileConnectRequest(incomingRequest: IncomingRequest) { mutex.withLock { requestQueue.addFirst(QueueItem.RequestItem(incomingRequest)) - _currentRequestToHandle.value?.let { - Timber.d("🗂 Dismissing request with id ${it.interactionId}") - appEventBus.sendEvent(AppEvent.DismissRequestHandling(it.interactionId)) + val currentRequest = _currentRequestToHandle.value + val handlingPaused = requestQueue.contains(QueueItem.HighPriorityScreen) + when { + currentRequest != null -> { + Timber.d("🗂 Dismissing request with id ${currentRequest.interactionId}") + appEventBus.sendEvent(AppEvent.DismissRequestHandling(currentRequest.interactionId)) + } + + else -> { + if (!handlingPaused) { + handleNextRequest() + } + } } } } @@ -92,6 +102,7 @@ class IncomingRequestRepositoryImpl @Inject constructor( override suspend fun requestHandled(requestId: String) { mutex.withLock { requestQueue.removeIf { it is QueueItem.RequestItem && it.incomingRequest.interactionId == requestId } + clearCurrent(requestId) handleNextRequest() Timber.d("🗂 request $requestId handled so size of list is now: ${getAmountOfRequests()}") } @@ -99,11 +110,18 @@ class IncomingRequestRepositoryImpl @Inject constructor( override suspend fun requestDismissed(requestId: String) { mutex.withLock { + clearCurrent(requestId) handleNextRequest() Timber.d("🗂 request $requestId handled so size of list is now: ${getAmountOfRequests()}") } } + private suspend fun clearCurrent(requestId: String) { + if (_currentRequestToHandle.value?.interactionId == requestId) { + _currentRequestToHandle.emit(null) + } + } + override suspend fun pauseIncomingRequests() { mutex.withLock { // If the queue knows about any high priority item, no need to add it again @@ -112,11 +130,12 @@ class IncomingRequestRepositoryImpl @Inject constructor( } // Put high priority item below any internal request and mobile connect requests - val topQueueItem = requestQueue.peekFirst() - if (topQueueItem is QueueItem.RequestItem && - (topQueueItem.incomingRequest.isInternal || topQueueItem.incomingRequest.isMobileConnectRequest) - ) { - requestQueue.add(1, QueueItem.HighPriorityScreen) + val index = requestQueue.indexOfFirst { + val item = it as? QueueItem.RequestItem + item != null && !item.incomingRequest.isInternal && !item.incomingRequest.isMobileConnectRequest + } + if (index != -1) { + requestQueue.add(index, QueueItem.HighPriorityScreen) } else { requestQueue.addFirst(QueueItem.HighPriorityScreen) } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepository.kt new file mode 100644 index 0000000000..21c4ba1fcb --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepository.kt @@ -0,0 +1,25 @@ +package com.babylon.wallet.android.data.repository + +import com.babylon.wallet.android.data.dapp.IncomingRequestRepository +import com.babylon.wallet.android.domain.model.IncomingMessage +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class BufferedDeepLinkRepository @Inject constructor( + private val incomingRequestRepository: IncomingRequestRepository, +) { + + private var bufferedRequest: IncomingMessage.IncomingRequest? = null + + fun setBufferedRequest(request: IncomingMessage.IncomingRequest) { + bufferedRequest = request + } + + suspend fun processBufferedRequest() { + bufferedRequest?.let { + incomingRequestRepository.addMobileConnectRequest(it) + bufferedRequest = null + } + } +} diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt index 76f6d8882c..51e2588e10 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt @@ -2,29 +2,44 @@ package com.babylon.wallet.android.domain.usecases.deeplink import com.babylon.wallet.android.data.dapp.IncomingRequestRepository import com.babylon.wallet.android.data.dapp.model.toDomainModel +import com.babylon.wallet.android.data.repository.BufferedDeepLinkRepository import com.babylon.wallet.android.domain.model.IncomingMessage import com.radixdlt.sargon.RadixConnectMobile +import rdx.works.profile.domain.GetProfileUseCase import timber.log.Timber import javax.inject.Inject class ProcessDeepLinkUseCase @Inject constructor( private val radixConnectMobile: RadixConnectMobile, - private val incomingRequestRepository: IncomingRequestRepository + private val incomingRequestRepository: IncomingRequestRepository, + private val getProfileUseCase: GetProfileUseCase, + private val bufferedDeepLinkRepository: BufferedDeepLinkRepository ) { - suspend operator fun invoke(deepLink: String) { - val sessionRequest = runCatching { radixConnectMobile.handleDeepLink(deepLink) }.onFailure { - Timber.d("Failed to parse deep link: $deepLink. Error: ${it.message}") - return - }.getOrThrow() - - incomingRequestRepository.addMobileConnectRequest( - sessionRequest.interaction.toDomainModel( + suspend operator fun invoke(deepLink: String): Result { + return runCatching { + val profileInitialized = getProfileUseCase.isInitialized() + val sessionRequest = radixConnectMobile.handleDeepLink(deepLink) + val request = sessionRequest.interaction.toDomainModel( remoteEntityId = IncomingMessage.RemoteEntityID.RadixMobileConnectRemoteSession( id = sessionRequest.sessionId.toString(), originVerificationUrl = if (sessionRequest.originRequiresValidation) sessionRequest.origin else null ) ).getOrThrow() - ) + if (profileInitialized) { + incomingRequestRepository.addMobileConnectRequest(request) + DeepLinkProcessingResult.PROCESSED + } else { + bufferedDeepLinkRepository.setBufferedRequest(request) + DeepLinkProcessingResult.BUFFERED + } + }.onFailure { + Timber.d("Failed to parse deep link: $deepLink. Error: ${it.message}") + } } } + +enum class DeepLinkProcessingResult { + PROCESSED, + BUFFERED +} diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginNav.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginNav.kt index 2645df5426..f980f49380 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginNav.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginNav.kt @@ -6,6 +6,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.SavedStateHandle import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptionsBuilder import androidx.navigation.NavType import androidx.navigation.compose.composable import androidx.navigation.navArgument @@ -23,8 +24,8 @@ internal class DAppAuthorizedLoginArgs(val interactionId: String) { constructor(savedStateHandle: SavedStateHandle) : this(checkNotNull(savedStateHandle[ARG_INTERACTION_ID]) as String) } -fun NavController.dAppLoginAuthorized(requestId: String) { - navigate("dapp_login_authorized/$requestId") +fun NavController.dAppLoginAuthorized(requestId: String, navOptionsBuilder: NavOptionsBuilder.() -> Unit = {}) { + navigate("dapp_login_authorized/$requestId", navOptionsBuilder) } @Suppress("LongParameterList") diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt index 26f3631d42..f032d9e524 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt @@ -596,7 +596,7 @@ class DAppAuthorizedLoginViewModel @Inject constructor( fun onAbortDappLogin(walletWalletErrorType: DappWalletInteractionErrorType = DappWalletInteractionErrorType.REJECTED_BY_USER) { viewModelScope.launch { - incomingRequestRepository.requestHandled(request.interactionId.toString()) + incomingRequestRepository.requestHandled(request.interactionId) if (!request.isInternal) { respondToIncomingRequestUseCase.respondWithFailure(request, walletWalletErrorType) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginNav.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginNav.kt index 869fc3c0ba..67ba307d65 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginNav.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginNav.kt @@ -6,6 +6,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.SavedStateHandle import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptionsBuilder import androidx.navigation.NavType import androidx.navigation.compose.composable import androidx.navigation.navArgument @@ -21,8 +22,8 @@ internal class DAppUnauthorizedLoginArgs(val interactionId: String) { constructor(savedStateHandle: SavedStateHandle) : this(checkNotNull(savedStateHandle[ARG_REQUEST_ID]) as String) } -fun NavController.dAppLoginUnauthorized(requestId: String) { - navigate("dapp_login_unauthorized/$requestId") +fun NavController.dAppLoginUnauthorized(requestId: String, navOptionsBuilder: NavOptionsBuilder.() -> Unit = {}) { + navigate("dapp_login_unauthorized/$requestId", navOptionsBuilder) } @Suppress("LongParameterList") diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt index d671825b5d..6b6b4280ae 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt @@ -9,6 +9,7 @@ import com.babylon.wallet.android.domain.RadixWalletException import com.babylon.wallet.android.domain.model.IncomingMessage.IncomingRequest import com.babylon.wallet.android.domain.usecases.AuthorizeSpecifiedPersonaUseCase import com.babylon.wallet.android.domain.usecases.VerifyDAppUseCase +import com.babylon.wallet.android.domain.usecases.deeplink.DeepLinkProcessingResult import com.babylon.wallet.android.domain.usecases.deeplink.ProcessDeepLinkUseCase import com.babylon.wallet.android.domain.usecases.p2plink.ObserveAccountsAndSyncWithConnectorExtensionUseCase import com.babylon.wallet.android.presentation.common.OneOffEvent @@ -247,23 +248,24 @@ class MainViewModel @Inject constructor( fun handleDeepLink(deepLink: Uri) { viewModelScope.launch { - delay(REQUEST_HANDLING_DELAY) - val profileInitialized = getProfileUseCase.isInitialized() - if (!profileInitialized) { - _state.update { - it.copy(isProfileInitialized = false) + processDeepLinkUseCase(deepLink.toString()).onSuccess { result -> + if (result == DeepLinkProcessingResult.BUFFERED) { + _state.update { + it.copy(showMobileConnectWarning = true) + } } - return@launch - } - - runCatching { - processDeepLinkUseCase(deepLink.toString()) }.onFailure { Timber.d(it) } } } + fun onMobileConnectWarningShown() { + _state.update { + it.copy(showMobileConnectWarning = false) + } + } + private fun verifyIncomingRequest(request: IncomingRequest) { verifyingDappRequestJob = viewModelScope.launch { if (request.isMobileConnectRequest) { @@ -359,7 +361,7 @@ data class MainUiState( val dappRequestFailure: RadixWalletException.DappRequestException? = null, val olympiaErrorState: OlympiaErrorState? = null, val claimedByAnotherDeviceError: ClaimedByAnotherDevice? = null, - val isProfileInitialized: Boolean = true + val showMobileConnectWarning: Boolean = false ) : UiState data class OlympiaErrorState( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkNav.kt b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkNav.kt index 8d98b51c95..728215688b 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkNav.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkNav.kt @@ -10,7 +10,7 @@ import androidx.navigation.navArgument import com.babylon.wallet.android.presentation.navigation.markAsHighPriority private const val ARG_INTERACTION_ID = "interactionId" -private const val ROUTE = "mobileConnect/{$ARG_INTERACTION_ID}" +const val ROUTE_MOBILE_CONNECT = "mobileConnect/{$ARG_INTERACTION_ID}" fun NavController.mobileConnect( interactionId: String @@ -32,9 +32,9 @@ fun NavGraphBuilder.mobileConnect( onHandleUnauthorizedRequest: (String) -> Unit, onHandleTransactionRequest: (String) -> Unit ) { - markAsHighPriority(route = ROUTE) + markAsHighPriority(route = ROUTE_MOBILE_CONNECT) composable( - route = ROUTE, + route = ROUTE_MOBILE_CONNECT, arguments = listOf( navArgument(ARG_INTERACTION_ID) { type = NavType.StringType diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkViewModel.kt index 785e9e44bb..94a6ffb6bd 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkViewModel.kt @@ -4,16 +4,20 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import com.babylon.wallet.android.data.dapp.IncomingRequestRepository import com.babylon.wallet.android.data.repository.dapps.WellKnownDAppDefinitionRepository +import com.babylon.wallet.android.di.coroutines.ApplicationScope import com.babylon.wallet.android.domain.model.IncomingMessage import com.babylon.wallet.android.domain.model.IncomingMessage.RemoteEntityID.RadixMobileConnectRemoteSession import com.babylon.wallet.android.domain.usecases.GetDAppsUseCase +import com.babylon.wallet.android.domain.usecases.RespondToIncomingRequestUseCase import com.babylon.wallet.android.presentation.common.OneOffEvent import com.babylon.wallet.android.presentation.common.OneOffEventHandler import com.babylon.wallet.android.presentation.common.OneOffEventHandlerImpl import com.babylon.wallet.android.presentation.common.StateViewModel import com.babylon.wallet.android.presentation.common.UiMessage import com.babylon.wallet.android.presentation.common.UiState +import com.radixdlt.sargon.DappWalletInteractionErrorType import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import rdx.works.core.domain.DApp @@ -28,7 +32,9 @@ class MobileConnectLinkViewModel @Inject constructor( private val wellKnownDAppDefinitionRepository: WellKnownDAppDefinitionRepository, private val getProfileUseCase: GetProfileUseCase, private val getDAppsUseCase: GetDAppsUseCase, - private val incomingRequestRepository: IncomingRequestRepository + private val incomingRequestRepository: IncomingRequestRepository, + private val respondToIncomingRequestUseCase: RespondToIncomingRequestUseCase, + @ApplicationScope private val appScope: CoroutineScope ) : StateViewModel(), OneOffEventHandler by OneOffEventHandlerImpl() { private val args = MobileConnectArgs(savedStateHandle) @@ -92,6 +98,9 @@ class MobileConnectLinkViewModel @Inject constructor( _state.update { it.copy(isVerifying = true) } + appScope.launch { + respondToIncomingRequestUseCase.respondWithFailure(request, DappWalletInteractionErrorType.REJECTED_BY_USER) + } viewModelScope.launch { incomingRequestRepository.requestHandled(args.interactionId) sendEvent(Event.Close) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt b/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt index 70bd339c59..b670ad4e56 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt @@ -36,6 +36,7 @@ import com.babylon.wallet.android.presentation.incompatibleprofile.ROUTE_INCOMPA import com.babylon.wallet.android.presentation.main.MAIN_ROUTE import com.babylon.wallet.android.presentation.main.MainUiState import com.babylon.wallet.android.presentation.main.main +import com.babylon.wallet.android.presentation.mobileconnect.ROUTE_MOBILE_CONNECT import com.babylon.wallet.android.presentation.mobileconnect.mobileConnect import com.babylon.wallet.android.presentation.onboarding.OnboardingScreen import com.babylon.wallet.android.presentation.onboarding.cloudbackup.ConnectCloudBackupViewModel.ConnectMode @@ -535,16 +536,19 @@ fun NavigationHost( navController.popBackStack() }, onHandleRequestAuthorizedRequest = { - navController.popBackStack() - navController.dAppLoginAuthorized(it) + navController.dAppLoginAuthorized(it) { + popUpTo(ROUTE_MOBILE_CONNECT) { inclusive = true } + } }, onHandleUnauthorizedRequest = { - navController.popBackStack() - navController.dAppLoginUnauthorized(it) + navController.dAppLoginUnauthorized(it) { + popUpTo(ROUTE_MOBILE_CONNECT) { inclusive = true } + } }, onHandleTransactionRequest = { - navController.popBackStack() - navController.transactionReview(it) + navController.transactionReview(it) { + popUpTo(ROUTE_MOBILE_CONNECT) { inclusive = true } + } } ) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/navigation/PriorityRoutes.kt b/app/src/main/java/com/babylon/wallet/android/presentation/navigation/PriorityRoutes.kt index 930792b8d7..6cc7db055d 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/navigation/PriorityRoutes.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/navigation/PriorityRoutes.kt @@ -1,6 +1,7 @@ package com.babylon.wallet.android.presentation.navigation import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavGraphBuilder object PriorityRoutes { @@ -13,6 +14,6 @@ object PriorityRoutes { } } -fun markAsHighPriority(route: String) { +fun NavGraphBuilder.markAsHighPriority(route: String) { PriorityRoutes.add(route = route) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewNav.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewNav.kt index 85875bb977..63d034ad80 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewNav.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewNav.kt @@ -5,6 +5,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.SavedStateHandle import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptionsBuilder import androidx.navigation.NavType import androidx.navigation.compose.composable import androidx.navigation.navArgument @@ -24,8 +25,8 @@ internal class TransactionReviewArgs(val interactionId: String) { ) } -fun NavController.transactionReview(requestId: String) { - navigate("transaction_review_route/$requestId") +fun NavController.transactionReview(requestId: String, navOptionsBuilder: NavOptionsBuilder.() -> Unit = {}) { + navigate("transaction_review_route/$requestId", navOptionsBuilder) } fun NavGraphBuilder.transactionReviewScreen( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletViewModel.kt index 20db65c0e9..be7170d9d2 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletViewModel.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import androidx.lifecycle.viewModelScope import com.babylon.wallet.android.NPSSurveyState import com.babylon.wallet.android.NPSSurveyStateObserver +import com.babylon.wallet.android.data.repository.BufferedDeepLinkRepository import com.babylon.wallet.android.data.repository.p2plink.P2PLinksRepository import com.babylon.wallet.android.data.repository.tokenprice.FiatPriceRepository import com.babylon.wallet.android.di.coroutines.DefaultDispatcher @@ -83,6 +84,7 @@ class WalletViewModel @Inject constructor( private val npsSurveyStateObserver: NPSSurveyStateObserver, private val p2PLinksRepository: P2PLinksRepository, private val checkMigrationToNewBackupSystemUseCase: CheckMigrationToNewBackupSystemUseCase, + private val bufferedDeepLinkRepository: BufferedDeepLinkRepository, @DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher ) : StateViewModel(), OneOffEventHandler by OneOffEventHandlerImpl() { @@ -111,6 +113,7 @@ class WalletViewModel @Inject constructor( return@launch } } + processBufferedDeepLinkRequest() observePrompts() observeAccounts() observeGlobalAppEvents() @@ -119,6 +122,12 @@ class WalletViewModel @Inject constructor( checkForOldBackupSystemToMigrate() } + private fun processBufferedDeepLinkRequest() { + viewModelScope.launch { + bufferedDeepLinkRepository.processBufferedRequest() + } + } + override fun initialState() = WalletUiState() fun popUpScreen(): StateFlow = popUpScreen diff --git a/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepositoryTest.kt new file mode 100644 index 0000000000..e09cc313bd --- /dev/null +++ b/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepositoryTest.kt @@ -0,0 +1,31 @@ +package com.babylon.wallet.android.data.repository + +import com.babylon.wallet.android.data.dapp.IncomingRequestRepository +import com.babylon.wallet.android.domain.model.IncomingMessage +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.mockk +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test + +class BufferedDeepLinkRepositoryTest { + + private lateinit var bufferedDeepLinkRepository: BufferedDeepLinkRepository + private val incomingRequestRepository = mockk() + + @Before + fun setup() { + bufferedDeepLinkRepository = BufferedDeepLinkRepository(incomingRequestRepository) + coEvery { incomingRequestRepository.addMobileConnectRequest(any()) } returns Unit + } + + @Test + fun `add buffered request to incoming request repository`() = runTest { + val request = mockk() + bufferedDeepLinkRepository.setBufferedRequest(request) + bufferedDeepLinkRepository.processBufferedRequest() + coVerify(exactly = 1) { incomingRequestRepository.addMobileConnectRequest(request) } + } + +} \ No newline at end of file diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt index 2a429eb9e1..e64634ef0b 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt @@ -3,6 +3,7 @@ package com.babylon.wallet.android.presentation import app.cash.turbine.test import com.babylon.wallet.android.NPSSurveyState import com.babylon.wallet.android.NPSSurveyStateObserver +import com.babylon.wallet.android.data.repository.BufferedDeepLinkRepository import com.babylon.wallet.android.data.repository.p2plink.P2PLinksRepository import com.babylon.wallet.android.domain.model.assets.AccountWithAssets import com.babylon.wallet.android.domain.usecases.GetEntitiesWithSecurityPromptUseCase @@ -16,8 +17,10 @@ import com.radixdlt.sargon.Profile import com.radixdlt.sargon.extensions.asIdentifiable import com.radixdlt.sargon.extensions.toDecimal192 import com.radixdlt.sargon.samples.sample +import io.mockk.Runs import io.mockk.coEvery import io.mockk.every +import io.mockk.just import io.mockk.mockk import junit.framework.TestCase.assertEquals import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -30,9 +33,9 @@ import kotlinx.coroutines.test.runTest import org.junit.Test import rdx.works.core.InstantGenerator import rdx.works.core.TimestampGenerator -import rdx.works.core.domain.cloudbackup.BackupState import rdx.works.core.domain.assets.Assets import rdx.works.core.domain.assets.Token +import rdx.works.core.domain.cloudbackup.BackupState import rdx.works.core.domain.resources.ExplicitMetadataKey import rdx.works.core.domain.resources.Resource import rdx.works.core.domain.resources.XrdResource @@ -60,6 +63,7 @@ class WalletViewModelTest : StateViewModelTest() { private val preferencesManager = mockk() private val appEventBus = mockk() private val testDispatcher = StandardTestDispatcher() + private val bufferedDeepLinkRepository = mockk() private val p2PLinksRepository = mockk() private val sampleProfile = Profile.sample() @@ -83,11 +87,13 @@ class WalletViewModelTest : StateViewModelTest() { npsSurveyStateObserver, p2PLinksRepository, checkMigrationToNewBackupSystemUseCase, + bufferedDeepLinkRepository, testDispatcher, ) override fun setUp() { super.setUp() + coEvery { bufferedDeepLinkRepository.processBufferedRequest() } just Runs coEvery { ensureBabylonFactorSourceExistUseCase.babylonFactorSourceExist() } returns true every { getAccountsForSecurityPromptUseCase() } returns flow { emit(emptyList()) } every { getBackupStateUseCase() } returns flowOf( From dfa36038866b2f55aeef0fa77a4b94091f932853 Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Mon, 24 Jun 2024 15:16:20 +0200 Subject: [PATCH 04/12] remove app link scheme --- app/src/main/AndroidManifest.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9b45aec587..a5bcf592aa 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,15 +41,6 @@ - - - - - - - - - From 2e0da3b4901ab70a639f1b208dd872b737767ff8 Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Tue, 25 Jun 2024 12:45:34 +0200 Subject: [PATCH 05/12] changes after merge with main --- .../babylon/wallet/android/MainActivity.kt | 2 +- .../com/babylon/wallet/android/WalletApp.kt | 4 +- .../data/dapp/IncomingRequestRepository.kt | 5 +- .../login/DAppAuthorizedLoginViewModel.kt | 2 +- .../login/DAppUnauthorizedLoginViewModel.kt | 2 +- .../mobileconnect/MobileConnectLinkScreen.kt | 58 +- .../presentation/navigation/NavigationHost.kt | 3 +- .../status/dapp/DappInteractionDialog.kt | 15 +- .../transaction/TransactionReviewViewModel.kt | 2 +- .../presentation/ui/composables/Dialogs.kt | 2 +- .../wallet/android/utils/ContextExtensions.kt | 2 +- app/src/main/res/values-en/strings.xml | 2414 +++++++++-------- app/src/main/res/values/constants.xml | 1 + .../dapp/IncomingRequestRepositoryTest.kt | 2 +- 14 files changed, 1277 insertions(+), 1237 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/MainActivity.kt b/app/src/main/java/com/babylon/wallet/android/MainActivity.kt index c1d760e8a3..f42fed7406 100644 --- a/app/src/main/java/com/babylon/wallet/android/MainActivity.kt +++ b/app/src/main/java/com/babylon/wallet/android/MainActivity.kt @@ -103,7 +103,7 @@ class MainActivity : FragmentActivity() { override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) - intent?.data?.let { + intent.data?.let { this.intent.replaceExtras(Bundle()) viewModel.handleDeepLink(it) } diff --git a/app/src/main/java/com/babylon/wallet/android/WalletApp.kt b/app/src/main/java/com/babylon/wallet/android/WalletApp.kt index cb9b021abe..5bf956c653 100644 --- a/app/src/main/java/com/babylon/wallet/android/WalletApp.kt +++ b/app/src/main/java/com/babylon/wallet/android/WalletApp.kt @@ -182,8 +182,8 @@ fun WalletApp( finish = { mainViewModel.onMobileConnectWarningShown() }, - titleText = "No profile found", - messageText = "You need to create a profile to respond to dApp requests", + titleText = stringResource(id = R.string.mobileConnect_noProfileDialog_title), + messageText = stringResource(id = R.string.mobileConnect_noProfileDialog_subtitle), confirmText = stringResource(id = R.string.common_ok), dismissText = null ) diff --git a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt index 347578555a..b9919b51ef 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt @@ -32,7 +32,8 @@ interface IncomingRequestRepository { fun removeAll() fun getAmountOfRequests(): Int - suspend fun requestDismissed(requestId: String) + + suspend fun requestDeferred(requestId: String) } class IncomingRequestRepositoryImpl @Inject constructor( @@ -108,7 +109,7 @@ class IncomingRequestRepositoryImpl @Inject constructor( } } - override suspend fun requestDismissed(requestId: String) { + override suspend fun requestDeferred(requestId: String) { mutex.withLock { clearCurrent(requestId) handleNextRequest() diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt index f032d9e524..450f2538e9 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt @@ -97,7 +97,7 @@ class DAppAuthorizedLoginViewModel @Inject constructor( appEventBus.events.filterIsInstance().collect { if (it.interactionId == args.interactionId) { sendEvent(Event.CloseLoginFlow) - incomingRequestRepository.requestDismissed(args.interactionId) + incomingRequestRepository.requestDeferred(args.interactionId) } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt index f6630fae20..d39137bc0e 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt @@ -73,7 +73,7 @@ class DAppUnauthorizedLoginViewModel @Inject constructor( appEventBus.events.filterIsInstance().collect { if (it.interactionId == args.interactionId) { sendEvent(Event.CloseLoginFlow) - incomingRequestRepository.requestDismissed(args.interactionId) + incomingRequestRepository.requestDeferred(args.interactionId) } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkScreen.kt index 3cb9a7cf0a..8b73648f50 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/mobileconnect/MobileConnectLinkScreen.kt @@ -2,7 +2,11 @@ package com.babylon.wallet.android.presentation.mobileconnect import androidx.activity.compose.BackHandler import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize @@ -12,6 +16,9 @@ import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text @@ -132,7 +139,8 @@ fun MobileConnectLinkContent( Column( modifier = Modifier .fillMaxSize() - .padding(padding), + .padding(padding) + .verticalScroll(state = rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally ) { Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingXXXXLarge)) @@ -147,20 +155,20 @@ fun MobileConnectLinkContent( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXXLarge), - text = stringResource(id = R.string.mobileConnect_title), + text = stringResource(id = R.string.mobileConnect_linkTitle), color = RadixTheme.colors.gray1, style = RadixTheme.typography.title, textAlign = TextAlign.Center ) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingXXXXLarge)) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingXXXLarge)) Text( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXXLarge), text = buildAnnotatedString { val valueToDisplay = stringResource( - id = R.string.mobileConnect_subtitle, + id = R.string.mobileConnect_linkSubtitle, dAppDisplayName ) @@ -174,23 +182,53 @@ fun MobileConnectLinkContent( ) }, color = RadixTheme.colors.gray1, - style = RadixTheme.typography.body1HighImportance, + style = RadixTheme.typography.body1Link, textAlign = TextAlign.Center ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingXXXLarge)) - Text( + Column( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXXLarge) .background(color = RadixTheme.colors.gray5, shape = RadixTheme.shapes.roundedRectSmall) - .padding(RadixTheme.dimensions.paddingSmall), - text = stringResource(id = R.string.mobileConnect_body), + .padding(vertical = RadixTheme.dimensions.paddingLarge, horizontal = RadixTheme.dimensions.paddingDefault), + verticalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingDefault) + ) { + NumberedListItem(number = 1, text = stringResource(id = R.string.mobileConnect_linkBody1)) + HorizontalDivider(color = RadixTheme.colors.gray4) + NumberedListItem(number = 2, text = stringResource(id = R.string.mobileConnect_linkBody2)) + } + Spacer(modifier = Modifier.weight(1f)) + } + } +} + +@Composable +private fun NumberedListItem(modifier: Modifier = Modifier, number: Int, text: String) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingDefault) + ) { + Box( + modifier = Modifier + .size(28.dp) + .border(1.dp, RadixTheme.colors.gray1, RadixTheme.shapes.circle) + ) { + Text( + modifier = Modifier.align(Alignment.Center), + text = number.toString(), color = RadixTheme.colors.gray1, - style = RadixTheme.typography.body1Regular, // TODO Mobile Connect (UI) + style = RadixTheme.typography.body1Header.copy(fontSize = 20.sp), textAlign = TextAlign.Start ) - Spacer(modifier = Modifier.weight(1f)) } + Text( + text = text, + color = RadixTheme.colors.gray1, + style = RadixTheme.typography.body1Regular, + textAlign = TextAlign.Start + ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt b/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt index 7a5d8d5cb9..8b9a4ff544 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt @@ -30,9 +30,8 @@ import com.babylon.wallet.android.presentation.dapp.authorized.dappLoginAuthoriz import com.babylon.wallet.android.presentation.dapp.authorized.login.dAppLoginAuthorized import com.babylon.wallet.android.presentation.dapp.completion.ChooseAccountsCompletionScreen import com.babylon.wallet.android.presentation.dapp.unauthorized.dappLoginUnauthorizedNavGraph -import com.babylon.wallet.android.presentation.incompatibleprofile.IncompatibleProfileScreen import com.babylon.wallet.android.presentation.dapp.unauthorized.login.dAppLoginUnauthorized -import com.babylon.wallet.android.presentation.incompatibleprofile.IncompatibleProfileContent +import com.babylon.wallet.android.presentation.incompatibleprofile.IncompatibleProfileScreen import com.babylon.wallet.android.presentation.incompatibleprofile.ROUTE_INCOMPATIBLE_PROFILE import com.babylon.wallet.android.presentation.main.MAIN_ROUTE import com.babylon.wallet.android.presentation.main.MainUiState diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/dapp/DappInteractionDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/dapp/DappInteractionDialog.kt index 3a1a12ee54..5a8be664c0 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/dapp/DappInteractionDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/dapp/DappInteractionDialog.kt @@ -77,16 +77,15 @@ private fun DappInteractionDialogContent( style = RadixTheme.typography.title, color = RadixTheme.colors.gray1 ) + Text( + text = stringResource(id = R.string.dAppRequest_completion_subtitle, state.dAppName), + style = RadixTheme.typography.body1Regular, + color = RadixTheme.colors.gray1, + textAlign = TextAlign.Center + ) if (state.isMobileConnect) { Text( - text = "Switch back to your browser to continue", // TODO crowdin - style = RadixTheme.typography.body1Regular, - color = RadixTheme.colors.gray1, - textAlign = TextAlign.Center - ) - } else { - Text( - text = stringResource(id = R.string.dAppRequest_completion_subtitle, state.dAppName), + text = stringResource(id = R.string.mobileConnect_interactionSuccess), style = RadixTheme.typography.body1Regular, color = RadixTheme.colors.gray1, textAlign = TextAlign.Center diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt index 2ae3000699..829a6fcd10 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt @@ -122,7 +122,7 @@ class TransactionReviewViewModel @Inject constructor( appEventBus.events.filterIsInstance().collect { if (it.interactionId == args.interactionId) { sendEvent(Event.Dismiss) - incomingRequestRepository.requestDismissed(args.interactionId) + incomingRequestRepository.requestDeferred(args.interactionId) } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/Dialogs.kt b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/Dialogs.kt index 5ed02734af..2dbe527aa4 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/Dialogs.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/Dialogs.kt @@ -484,7 +484,7 @@ fun FailureDialogContent( } if (isMobileConnect) { Text( - text = "Switch back to your browser to continue", // TODO crowdin + text = stringResource(id = R.string.mobileConnect_interactionSuccess), style = RadixTheme.typography.body1Regular, color = RadixTheme.colors.gray1, textAlign = TextAlign.Center diff --git a/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt b/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt index 4b92a0abe5..92676dbc0d 100644 --- a/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt @@ -80,7 +80,7 @@ fun Context.openEmail(recipientAddress: String? = null, subject: String? = null, } catch (activityNotFound: ActivityNotFoundException) { Toast.makeText( this, - "No email client installed", // TODO crowdin + getString(R.string.no_email_client_installed), Toast.LENGTH_SHORT ).show() } diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index d0a802110b..64dba9d6ec 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -1,1213 +1,1215 @@ - Please write down seed phrase to ensure Account control - Seed phrase required - begin entry - I have written down this seed phrase - Create a New Account - Legacy - Welcome. Here are all your Accounts on the Radix Network. - Radix Wallet - Total value - dApp Definition - Legacy - Legacy (Ledger) - Ledger - Visit the Radix Dashboard - Ready to get started using the Radix Network and your Wallet? - SERIOUS ERROR - PLEASE READ - Your wallet is in a rare condition that must be resolved manually. Please email support at hello@radixdlt.com with subject line BDFS ERROR. Somebody will respond and help you resolve the issue safely. - Affected Accounts - Affected Personas - OK (%d) - Start Using Radix - Complete setting up your wallet and start staking, using dApps and more! - Get Started Now - Your wallet has encountered a problem that should be resolved before you continue use. If you have a Samsung phone, this may be caused by putting the Radix Wallet in the \"Secure Folder\". Please contact support at hello@radixdlt.com for assistance. - Transfer - Tokens - NFTs - Staking - Radix Network XRD Stake Summary - STAKED VALIDATORS (%d) - Unstaking - Ready to Claim - Ready to be claimed - Staked - Current Stake: %s - Liquid Stake Units - Stake Claim NFTs - WORTH - Claim - Pool Units - Unknown - Unknown - Unknown - Current Redeemable Value - Missing Total supply - could not calculate redemption value - Badges - Address - Validator - Name - Current Supply - Unknown - Behavior - Ready to claim in about %d minutes or less. - Tags - Official Radix - Associated dApps - You have no Tokens - What are Tokens? - You have no NFTs - What are NFTs? - ID - Name - Description - complex data - Name - %d NFTs - %d NFTs of total supply %d - You have no Stakes - What is Staking? - You have no Pool units - What are Pool units? - You have no badges - What are badges? - Hide Asset - Hide this asset in your Radix Wallet? You can always unhide it in your account settings. - Hide Asset - This is a simple asset - The supply of this asset can be increased. - The supply of this asset can be decreased. - The supply of this asset can be increased or decreased. - Only the Radix Network may increase or decrease the supply of XRD. - Anyone can increase the supply of this asset. - Anyone can decrease the supply of this asset. - Anyone can increase or decrease the supply of this asset. - Movement of this asset is restricted. - Movement of this asset can be restricted in the future. - Anyone can restrict movement of this token in the future. - Naming and information about this asset can be changed. - Anyone can change naming and information about this asset. - A third party can remove this asset from accounts and dApps. - Anyone can remove this asset from accounts and dApps. - A third party can freeze this asset in place. - Anyone can freeze this asset in place. - Data that is set on these NFTs can be changed. - Anyone can change data that is set on these NFTs. - Account Settings - Personalize this Account - Account Label - Account Color - Select from a list of unique colors - Show Assets with Tags - Show Account QR Code - Updated - Select which tags to show for assets in this Account - Set how you want this Account to work - Third-party Deposits - Hide Account - Account Hidden - Get XRD Test Tokens - This may take several seconds, please wait for completion - Rename Account - Enter a new label for this Account - Update - Select the color for this Account - Selected - Hide This Account - Hide this Account in your wallet? You can always unhide it from the main application settings. - Hide Account - Choose if you want to allow third parties to directly deposit assets into your Account. Deposits that you approve yourself in your Radix Wallet are always accepted. - Accept all deposits - Allow third-parties to deposit any asset - Only accept known - Allow third-parties to deposit only assets this Account already holds - Deny all - Deny all third-party deposits - This account will not be able to receive \"air drops\" or be used by a trusted contact to assist with account recovery. - Discard Changes - Keep Editing - Are you sure you want to discard changes? - Allow/Deny specific assets - Deny or allow third-party deposits of specific assets, ignoring the setting above - Add a Depositor Badge - Enter the badge’s resource address (starting with “reso”) - Allow specific depositors - Allow certain third party depositors to deposit assets freely - Add Depositor Badge - Remove Asset - The asset will be removed from the deny list - The asset will be removed from the allow list - The badge will be removed from the list - Remove Depositor - The depositor will be removed from the allow list - Allow/Deny Specific Assets - Update - Allow - Deny - Add a specific asset by its resource address to allow all third-party deposits - Add a specific asset by its resource address to deny all third-party deposits - Add an Asset - Enter the asset’s resource address (starting with “reso”) - Resource Address - Allow Deposits - Deny Deposits - Add Asset - The following resource addresses may always be deposited to this account by third parties. - The following resource addresses may never be deposited to this account by third parties. - Add a specific badge by its resource address to allow all deposits from its holder. - The holder of the following badges may always deposit accounts to this account. - Select exception list - Sorry, this Account\'s third-party exceptions and depositor lists are in an unknown state and cannot be viewed or edited because it was imported using only a seed phrase or Ledger. A forthcoming wallet update will enable viewing and editing of these lists. - Asset creators can add tags to them. You can choose which tags you want to see in this Account. - Select the ones you’d like shown on all your assets. - Recommended - Set development preferences - Dev Preferences - Hide This Account - Are you sure you want to hide this account? - Settings - Authorized dApps - Personas - Account Security & Settings - App Settings - Please write down the seed phrase for your Personas - Link your Wallet to a Desktop Browser - Scan the QR code in the Radix Wallet Connector extension - Link to Connector - Radix Olympia Desktop Wallet user? - Get started importing your Olympia accounts into your new Radix Wallet - Import Legacy Accounts - Version: %s build #%s - Linked Connectors - Connect your Radix Wallet to desktop web browsers by linking to the Radix Connector browser extension. Here are your linked Connectors. - Last connected %s - Link New Connector - Link New Connector - Open your Radix Connector extension\'s menu by clicking its icon in your list of browser extensions, and scan the QR code shown. - Linking… - Name New Connector - What would you like to call this Radix Connector installation? - e.g. Chrome on Personal Laptop - Name this connector e.g. ‘Chrome on MacBook Pro’ - Continue - Remove Connection - You will no longer be able to connect your wallet to this device and browser combination. - Remove - Access Required - Camera access is required to link to a Connector. - Access Required - Local network access is required to link to a Connector. - Incorrect QR code scanned. - Please scan the QR code provided by your Radix Wallet Connector browser extension. - Link Connector - Update Link - This Connector will be trusted to verify the dApp origin of requests to this wallet.\n\nOnly continue if you are linking to the **official Radix Connector browser extension** - or a Connector you control and trust. - This appears to be a Radix Connector you previously linked to. Link will be updated. - Link Failed - This type of Connector link is not supported. - Changing a Connector’s type is not supported. - This is an old version of the Radix Connector browser extension. Please update to the latest Connector and try linking again. - Re-link Connector - Radix Connector now supports linking multiple phones with one browser.\n\nTo support this feature, we\'ve had to disconnect your existing links – **please re-link your Connector(s).** - Any Connectors you had linked to this wallet using a different phone have been disconnected\n\n**Please re-link your Connector(s) to use with this phone.** - Later - Gateways - Choose the gateway your wallet will use to connect to the Radix Network or test networks. Only change this if you know what you’re doing. - What is a Gateway? - RCnet Gateway - Add New Gateway - Add New Gateway - Enter a gateway URL - Enter full URL - Add Gateway - This gateway is already added - No gateway found at specified URL - There was an error establishing a connection - Remove Gateway - You will no longer be able to connect to this gateway. - Authorized dApps - These are the dApps that you have logged into using the Radix Wallet. - What is a dApp? - dApp Definition - Missing description - Website - Associated Tokens - Unknown name - Associated NFTs - Here are the Personas that you have used to login to this dApp. - No Personas have been used to login to this dApp. - Forget this dApp - Persona Hidden - Edit Avatar - Persona Label - Here is the personal data that you are sharing with %s. - You are not sharing any personal data with %s. - First Name - Last Name - Email Address - Phone Number - Edit Persona - Here are the dApps you have logged into with this Persona. - Here are the Account names and addresses that you are currently sharing with %s. - Edit Account Sharing - Disconnect Persona from this dApp - Forget This dApp - Do you really want to forget this dApp and remove its permissions for all Personas? - Forget dApp? - Remove Authorization - This dApp will no longer have authorization to see data associated with this Persona, unless you choose to login with it again in the future. - Continue - Full Name - Name Order - Given Name(s) - Family Name - Nickname - Eastern style (family name first) - Western style (given name(s) first) - Hide This Persona - Are you sure you want to hide this persona? - Required by dApp - The following information can be seen if requested by the dApp - Label cannot be blank - Invalid email address - Required field for this dApp - Add a Field - Add a Field - Choose one or more data fields to add to this Persona. - Add Data Fields - Discard Changes - Keep Editing - Are you sure you want to discard changes to this Persona? - Personas - Here are all of your current Personas in your Radix Wallet. - What is a Persona? - Create a New Persona - Write down main seed phrase - Your Account lives on the Radix Network and you can access it any time in your Radix Wallet. - You’ve created your first Account! - Your Account has been created. - e.g. My Main Account - What would you like to call your Account? - This can be changed any time. - Continue - Create an Account - Create First Account - Create New Account - Choose Accounts - Persona Selection - Gateways - Account List - Persona List - Continue to %s - Congratulations - Create Ledger Account - Create Ledger Persona - Your Account lives on the Radix Network and you can access it any time in your Wallet. - Create with Ledger Hardware Wallet - You will be asked to sign transactions with the Ledger device you select. - Empty display name - You’ve created your first Persona! - Your Persona has been created. - Personal data that you add to your Persona will only be shared with dApps with your permission. - Some dApps may request personal information, like name or email address, that can be added to your Persona. Add some data now if you like. - This will be shared with dApps you login to - Create a Persona - A Persona is an identity that you own and control. You can have as many as you like. - Personas are used to login to dApps on Radix. dApps may request access to personal information associated with your Persona, like your name or email address. - Learn about Personas - Continue - What would you like to call your Persona? - e.g. My Main Persona - Continue - Required field - Save and Continue - Login Request - %s is requesting that you login with a Persona. - New Login Request - %s is requesting that you login for the **first time** with a Persona. - Choose a Persona - Your last login was on %s - Continue - Account Permission - %d or more accounts - Any number of accounts - %d accounts - 1 account - Continue - **%s** is requesting permission to *always* be able to view Account information when you login with this Persona. - You can update this permission in wallet settings for this dApp at any time. - Create a New Account - You are now connected to %s. You can change your preferences for this dApp in wallet settings at any time. - dApp Connection Successful - DApp error - Continue - Account Request - **%s** is making a one-time request for at least %d accounts. - **%s** is making a one-time request for any number of accounts. - **%s** is making a one-time request for at least 1 account. - **%s** is making a one-time request for %d accounts. - **%s** is making a one-time request for 1 account. - Account Permission - Choose at least %d accounts you wish to use with **%s**. - Choose any accounts you wish to use with **%s**. - Choose at least 1 account you wish to use with **%s**. - Choose %d accounts you wish to use with **%s**. - Choose 1 account you wish to use with **%s**. - One-Time Data Request - Choose the data to provide - **%s** is requesting that you provide some pieces of personal data **just one time** - Continue - Personal Data Permission - **%s** is requesting permission to **always** be able to view the following personal data when you login with this Persona. - You can update this permission in your Settings at any time. - Continue - Invalid content - Incompatible connector extension - Network mismatch - Invalid value of `numberOfAccountsInvalid`: must not be `exactly(0)` nor can `quantity` be negative - %s (CE: %s, wallet: %s) - \'%s\' is not valid origin. - \'%s\' is not valid account address. - Invalid data in request - Please update Radix Wallet - Please update Radix Connector browser extension - Invalid origin - Invalid dApp Definition Address - Radix Connect connection error - Invalid Request. - Could not validate the dApp. - Request received from dApp is invalid. - dApp specified an invalid Persona. - dApp made a request intended for network %s, but you are currently connected to %s. - Failed to send request response to dApp. - Success - Request from %s complete - Danger! Bad dApp configuration, or you\'re being spoofed! - Loading… - Unknown dApp - Radix Wallet - Edit - Required information: - Review Your Transaction - Proposed by %s - Review Your Transfer - Approve - Customize Guarantees - Estimated - Account - Guaranteed - Raw Transaction - Unknown - Unnamed dApp - Worth - To be claimed - Unknown pool - %d Unknown Components - %d Pool Components - Pool Units - Slide to Sign - %s XRD - Not enough XRD for transaction fee - Fee payer account required - Withdrawing From - Depositing To - Sending to - Message - Presenting - Using dApps - Third-party deposit setting - Third-party deposit exceptions - Staking to Validators - Requesting unstake from validators - Claim from validators - Contributing to pools - Redeeming from pools - Transaction Fee - The network is currently congested. Add a tip to speed up your transfer. - Customize - Customize Guarantees - Protect yourself by setting guaranteed minimums for estimated deposits - Apply - How do guarantees work? - Set guaranteed minimum %% - Preparing Transaction - Preparing transaction for signing - Submitting - Submitted but not confirmed - Rejected - Failed - Successfully committed - Transaction ID - Status - Submitting Transaction - Review New Deposit Settings - Third-party deposit setting - Allow third parties to deposit **any asset** to this account. - Allow third parties to deposit **only assets this account has already held**. - **Disallow** all deposits from third parties without your consent. - Allow - Disallow - Remove Exception - Add Depositor - Remove Depositor - A proposed transaction was rejected because it contains one or more reserved instructions. - Could Not Complete - The required seed phrase is missing. Please return to the account and begin the recovery process. - Warning - This is a complex transaction that cannot be summarized - the raw transaction manifest will be shown. Do not submit unless you understand the contents. - Completing Transaction… - Transaction ID: - Transaction Success - Transaction Failed - Transaction Rejected - Transaction Error - Your transaction was successful - Your transaction was processed, but had a problem that caused it to fail permanently - This transaction was rejected and is unlikely to be processed, but could potentially be processed within the next %s minutes. It is likely that the dApp you are using proposed a transaction that includes an action that is not currently valid. - Your transaction was improperly constructed and cannot be processed - Something Went Wrong - Transaction was rejected as invalid by the Radix Network. - Stop waiting for transaction result? The transaction will not be canceled. - Dismiss - This transaction requires to be completed - A guarantee on transaction results was not met. Consider reducing your preferred guarantee %% - Copy Address - Copied to Clipboard - Copy NFT ID - Copy Transaction ID - There is no web browser installed in this device - View on Radix Dashboard - Show Address QR Code - Verify Address with Ledger - Address verified - Verify address request failed - QR code for an account - Could not create QR code - Authenticate to continue - Authenticate to create new %s with this phone. - Authenticate to sign proof with this phone. - Authenticate to sign transaction with this phone. - Display seed phrase. - Create Auth signing key. - Check if seed phrase already exists. - Checking accounts. - Update account metadata. - Unsecured Device - Your device currently has no device access security set, such as biometrics or a PIN. The Radix Wallet requires this to be set for your security. - Open Settings - Quit - Account - Cancel - Continue - Connected to a test network, not Radix main network. - An Error Occurred - None - OK - Done - Copy - Persona - History - Pool - Retry - Remove - Something Went Wrong - Settings - Confirm - Save - Invalid - Public - Choose - Max - Optional - Show More - Show Less - Component - Unauthorized - Gateway access blocked due to exceeding rate limit. Please wait a few minutes to retry. - Bad HTTP response status code %d - Dismiss - Invalid Persona specified by dApp - Invalid request - Failed to import Radix Wallet backup: %s - Failed to import Radix Wallet backup, error: %s, version: %s - Failed to commit transaction - Failed to convert transaction manifest - Failed to get epoch - Failed to build transaction header - Failed to convert transaction manifest - You don\'t have access to some accounts or personas required to authorise this transaction - Wrong network - No funds to approve transaction - Failed to poll transaction status - Failed to prepare transaction - Transaction rejected - Unknown error - Failed to find ledger - Failed to add Transaction Fee, try a different amount of fee payer. - Failed to add Guarantee, try a different percentage, or try skip adding a guarantee. - A proposed transaction could not be processed. - Your current Ledger settings only allow signing of simple token transfers. Please either enable \"verbose mode\" (to see full transaction manifests) or \"blind signing mode\" (to enable signing of complex transaction manifest hashes) on your Ledger app device. - Failed to convert transaction manifest - Failed to submit transaction - Persona label too long - Account label too long - Account label required - One of the receiving accounts does not allow Third-Party deposits - Email Support - Please email support to automatically provide debugging info, and get assistance. + Please write down seed phrase to ensure Account control + Seed phrase required - begin entry + I have written down this seed phrase + Create a New Account + Legacy + Welcome. Here are all your Accounts on the Radix Network. + Radix Wallet + Total value + dApp Definition + Legacy + Legacy (Ledger) + Ledger + Visit the Radix Dashboard + Ready to get started using the Radix Network and your Wallet? + SERIOUS ERROR - PLEASE READ + Your wallet is in a rare condition that must be resolved manually. Please email support at hello@radixdlt.com with subject line BDFS ERROR. Somebody will respond and help you resolve the issue safely. + Affected Accounts + Affected Personas + OK (%d) + Start Using Radix + Complete setting up your wallet and start staking, using dApps and more! + Get Started Now + Your wallet has encountered a problem that should be resolved before you continue use. If you have a Samsung phone, this may be caused by putting the Radix Wallet in the \"Secure Folder\". Please contact support at hello@radixdlt.com for assistance. + Transfer + Tokens + NFTs + Staking + Radix Network XRD Stake Summary + STAKED VALIDATORS (%d) + Unstaking + Ready to Claim + Ready to be claimed + Staked + Current Stake: %s + Liquid Stake Units + Stake Claim NFTs + WORTH + Claim + Pool Units + Unknown + Unknown + Unknown + Current Redeemable Value + Missing Total supply - could not calculate redemption value + Badges + Address + Validator + Name + Current Supply + Unknown + Behavior + Ready to claim in about %d minutes or less. + Tags + Official Radix + Associated dApps + You have no Tokens + What are Tokens? + You have no NFTs + What are NFTs? + ID + Name + Description + complex data + Name + %d NFTs + %d NFTs of total supply %d + You have no Stakes + What is Staking? + You have no Pool units + What are Pool units? + You have no badges + What are badges? + Hide Asset + Hide this asset in your Radix Wallet? You can always unhide it in your account settings. + Hide Asset + This is a simple asset + The supply of this asset can be increased. + The supply of this asset can be decreased. + The supply of this asset can be increased or decreased. + Only the Radix Network may increase or decrease the supply of XRD. + Anyone can increase the supply of this asset. + Anyone can decrease the supply of this asset. + Anyone can increase or decrease the supply of this asset. + Movement of this asset is restricted. + Movement of this asset can be restricted in the future. + Anyone can restrict movement of this token in the future. + Naming and information about this asset can be changed. + Anyone can change naming and information about this asset. + A third party can remove this asset from accounts and dApps. + Anyone can remove this asset from accounts and dApps. + A third party can freeze this asset in place. + Anyone can freeze this asset in place. + Data that is set on these NFTs can be changed. + Anyone can change data that is set on these NFTs. + Account Settings + Personalize this Account + Account Label + Account Color + Select from a list of unique colors + Show Assets with Tags + Show Account QR Code + Updated + Select which tags to show for assets in this Account + Set how you want this Account to work + Third-party Deposits + Hide Account + Account Hidden + Get XRD Test Tokens + This may take several seconds, please wait for completion + Rename Account + Enter a new label for this Account + Update + Select the color for this Account + Selected + Hide This Account + Hide this Account in your wallet? You can always unhide it from the main application settings. + Hide Account + Choose if you want to allow third parties to directly deposit assets into your Account. Deposits that you approve yourself in your Radix Wallet are always accepted. + Accept all deposits + Allow third-parties to deposit any asset + Only accept known + Allow third-parties to deposit only assets this Account already holds + Deny all + Deny all third-party deposits + This account will not be able to receive \"air drops\" or be used by a trusted contact to assist with account recovery. + Discard Changes + Keep Editing + Are you sure you want to discard changes? + Allow/Deny specific assets + Deny or allow third-party deposits of specific assets, ignoring the setting above + Add a Depositor Badge + Enter the badge’s resource address (starting with “reso”) + Allow specific depositors + Allow certain third party depositors to deposit assets freely + Add Depositor Badge + Remove Asset + The asset will be removed from the deny list + The asset will be removed from the allow list + The badge will be removed from the list + Remove Depositor + The depositor will be removed from the allow list + Allow/Deny Specific Assets + Update + Allow + Deny + Add a specific asset by its resource address to allow all third-party deposits + Add a specific asset by its resource address to deny all third-party deposits + Add an Asset + Enter the asset’s resource address (starting with “reso”) + Resource Address + Allow Deposits + Deny Deposits + Add Asset + The following resource addresses may always be deposited to this account by third parties. + The following resource addresses may never be deposited to this account by third parties. + Add a specific badge by its resource address to allow all deposits from its holder. + The holder of the following badges may always deposit accounts to this account. + Select exception list + Sorry, this Account\'s third-party exceptions and depositor lists are in an unknown state and cannot be viewed or edited because it was imported using only a seed phrase or Ledger. A forthcoming wallet update will enable viewing and editing of these lists. + Asset creators can add tags to them. You can choose which tags you want to see in this Account. + Select the ones you’d like shown on all your assets. + Recommended + Set development preferences + Dev Preferences + Hide This Account + Are you sure you want to hide this account? + Settings + Authorized dApps + Personas + Account Security & Settings + App Settings + Please write down the seed phrase for your Personas + Link your Wallet to a Desktop Browser + Scan the QR code in the Radix Wallet Connector extension + Link to Connector + Radix Olympia Desktop Wallet user? + Get started importing your Olympia accounts into your new Radix Wallet + Import Legacy Accounts + Version: %s build #%s + Linked Connectors + Connect your Radix Wallet to desktop web browsers by linking to the Radix Connector browser extension. Here are your linked Connectors. + Last connected %s + Link New Connector + Link New Connector + Open your Radix Connector extension\'s menu by clicking its icon in your list of browser extensions, and scan the QR code shown. + Linking… + Name New Connector + What would you like to call this Radix Connector installation? + e.g. Chrome on Personal Laptop + Name this connector e.g. ‘Chrome on MacBook Pro’ + Continue + Remove Connection + You will no longer be able to connect your wallet to this device and browser combination. + Remove + Access Required + Camera access is required to link to a Connector. + Access Required + Local network access is required to link to a Connector. + Incorrect QR code scanned. + Please scan the QR code provided by your Radix Wallet Connector browser extension. + Link Connector + Update Link + This Connector will be trusted to verify the dApp origin of requests to this wallet.\n\nOnly continue if you are linking to the **official Radix Connector browser extension** - or a Connector you control and trust. + This appears to be a Radix Connector you previously linked to. Link will be updated. + Link Failed + This type of Connector link is not supported. + Changing a Connector’s type is not supported. + This is an old version of the Radix Connector browser extension. Please update to the latest Connector and try linking again. + Re-link Connector + Radix Connector now supports linking multiple phones with one browser.\n\nTo support this feature, we\'ve had to disconnect your existing links – **please re-link your Connector(s).** + Any Connectors you had linked to this wallet using a different phone have been disconnected\n\n**Please re-link your Connector(s) to use with this phone.** + Later + Gateways + Choose the gateway your wallet will use to connect to the Radix Network or test networks. Only change this if you know what you’re doing. + What is a Gateway? + RCnet Gateway + Add New Gateway + Add New Gateway + Enter a gateway URL + Enter full URL + Add Gateway + This gateway is already added + No gateway found at specified URL + There was an error establishing a connection + Remove Gateway + You will no longer be able to connect to this gateway. + Authorized dApps + These are the dApps that you have logged into using the Radix Wallet. + What is a dApp? + dApp Definition + Missing description + Website + Associated Tokens + Unknown name + Associated NFTs + Here are the Personas that you have used to login to this dApp. + No Personas have been used to login to this dApp. + Forget this dApp + Persona Hidden + Edit Avatar + Persona Label + Here is the personal data that you are sharing with %s. + You are not sharing any personal data with %s. + First Name + Last Name + Email Address + Phone Number + Edit Persona + Here are the dApps you have logged into with this Persona. + Here are the Account names and addresses that you are currently sharing with %s. + Edit Account Sharing + Disconnect Persona from this dApp + Forget This dApp + Do you really want to forget this dApp and remove its permissions for all Personas? + Forget dApp? + Remove Authorization + This dApp will no longer have authorization to see data associated with this Persona, unless you choose to login with it again in the future. + Continue + Full Name + Name Order + Given Name(s) + Family Name + Nickname + Eastern style (family name first) + Western style (given name(s) first) + Hide This Persona + Are you sure you want to hide this persona? + Required by dApp + The following information can be seen if requested by the dApp + Label cannot be blank + Invalid email address + Required field for this dApp + Add a Field + Add a Field + Choose one or more data fields to add to this Persona. + Add Data Fields + Discard Changes + Keep Editing + Are you sure you want to discard changes to this Persona? + Personas + Here are all of your current Personas in your Radix Wallet. + What is a Persona? + Create a New Persona + Write down main seed phrase + Your Account lives on the Radix Network and you can access it any time in your Radix Wallet. + You’ve created your first Account! + Your Account has been created. + e.g. My Main Account + What would you like to call your Account? + This can be changed any time. + Continue + Create an Account + Create First Account + Create New Account + Choose Accounts + Persona Selection + Gateways + Account List + Persona List + Continue to %s + Congratulations + Create Ledger Account + Create Ledger Persona + Your Account lives on the Radix Network and you can access it any time in your Wallet. + Create with Ledger Hardware Wallet + You will be asked to sign transactions with the Ledger device you select. + Empty display name + You’ve created your first Persona! + Your Persona has been created. + Personal data that you add to your Persona will only be shared with dApps with your permission. + Some dApps may request personal information, like name or email address, that can be added to your Persona. Add some data now if you like. + This will be shared with dApps you login to + Create a Persona + A Persona is an identity that you own and control. You can have as many as you like. + Personas are used to login to dApps on Radix. dApps may request access to personal information associated with your Persona, like your name or email address. + Learn about Personas + Continue + What would you like to call your Persona? + e.g. My Main Persona + Continue + Required field + Save and Continue + Login Request + %s is requesting that you login with a Persona. + New Login Request + %s is requesting that you login for the **first time** with a Persona. + Choose a Persona + Your last login was on %s + Continue + Account Permission + %d or more accounts + Any number of accounts + %d accounts + 1 account + Continue + **%s** is requesting permission to *always* be able to view Account information when you login with this Persona. + You can update this permission in wallet settings for this dApp at any time. + Create a New Account + You are now connected to %s. You can change your preferences for this dApp in wallet settings at any time. + dApp Connection Successful + DApp error + Continue + Account Request + **%s** is making a one-time request for at least %d accounts. + **%s** is making a one-time request for any number of accounts. + **%s** is making a one-time request for at least 1 account. + **%s** is making a one-time request for %d accounts. + **%s** is making a one-time request for 1 account. + Account Permission + Choose at least %d accounts you wish to use with **%s**. + Choose any accounts you wish to use with **%s**. + Choose at least 1 account you wish to use with **%s**. + Choose %d accounts you wish to use with **%s**. + Choose 1 account you wish to use with **%s**. + One-Time Data Request + Choose the data to provide + **%s** is requesting that you provide some pieces of personal data **just one time** + Continue + Personal Data Permission + **%s** is requesting permission to **always** be able to view the following personal data when you login with this Persona. + You can update this permission in your Settings at any time. + Continue + Invalid content + Incompatible connector extension + Network mismatch + Invalid value of `numberOfAccountsInvalid`: must not be `exactly(0)` nor can `quantity` be negative + %s (CE: %s, wallet: %s) + \'%s\' is not valid origin. + \'%s\' is not valid account address. + Invalid data in request + Please update Radix Wallet + Please update Radix Connector browser extension + Invalid origin + Invalid dApp Definition Address + Radix Connect connection error + Invalid Request. + Could not validate the dApp. + Request received from dApp is invalid. + dApp specified an invalid Persona. + dApp made a request intended for network %s, but you are currently connected to %s. + Failed to send request response to dApp. + Success + Request from %s complete + Danger! Bad dApp configuration, or you\'re being spoofed! + Loading… + Unknown dApp + Radix Wallet + Edit + Required information: + Review Your Transaction + Proposed by %s + Review Your Transfer + Approve + Customize Guarantees + Estimated + Account + Guaranteed + Raw Transaction + Unknown + Unnamed dApp + Worth + To be claimed + Unknown pool + %d Unknown Components + %d Pool Components + Pool Units + Slide to Sign + %s XRD + Not enough XRD for transaction fee + Fee payer account required + Withdrawing From + Depositing To + Sending to + Message + Presenting + Using dApps + Third-party deposit setting + Third-party deposit exceptions + Staking to Validators + Requesting unstake from validators + Claim from validators + Contributing to pools + Redeeming from pools + Transaction Fee + The network is currently congested. Add a tip to speed up your transfer. + Customize + Customize Guarantees + Protect yourself by setting guaranteed minimums for estimated deposits + Apply + How do guarantees work? + Set guaranteed minimum %% + Preparing Transaction + Preparing transaction for signing + Submitting + Submitted but not confirmed + Rejected + Failed + Successfully committed + Transaction ID + Status + Submitting Transaction + Review New Deposit Settings + Third-party deposit setting + Allow third parties to deposit **any asset** to this account. + Allow third parties to deposit **only assets this account has already held**. + **Disallow** all deposits from third parties without your consent. + Allow + Disallow + Remove Exception + Add Depositor + Remove Depositor + A proposed transaction was rejected because it contains one or more reserved instructions. + Could Not Complete + The required seed phrase is missing. Please return to the account and begin the recovery process. + Warning + This is a complex transaction that cannot be summarized - the raw transaction manifest will be shown. Do not submit unless you understand the contents. + Completing Transaction… + Transaction ID: + Transaction Success + Transaction Failed + Transaction Rejected + Transaction Error + Your transaction was successful + Your transaction was processed, but had a problem that caused it to fail permanently + This transaction was rejected and is unlikely to be processed, but could potentially be processed within the next %s minutes. It is likely that the dApp you are using proposed a transaction that includes an action that is not currently valid. + Your transaction was improperly constructed and cannot be processed + Something Went Wrong + Transaction was rejected as invalid by the Radix Network. + Stop waiting for transaction result? The transaction will not be canceled. + Dismiss + This transaction requires to be completed + A guarantee on transaction results was not met. Consider reducing your preferred guarantee %% + Copy Address + Copied to Clipboard + Copy NFT ID + Copy Transaction ID + There is no web browser installed in this device + View on Radix Dashboard + Show Address QR Code + Verify Address with Ledger + Address verified + Verify address request failed + QR code for an account + Could not create QR code + Authenticate to continue + Authenticate to create new %s with this phone. + Authenticate to sign proof with this phone. + Authenticate to sign transaction with this phone. + Display seed phrase. + Create Auth signing key. + Check if seed phrase already exists. + Checking accounts. + Update account metadata. + Unsecured Device + Your device currently has no device access security set, such as biometrics or a PIN. The Radix Wallet requires this to be set for your security. + Open Settings + Quit + Account + Cancel + Continue + Connected to a test network, not Radix main network. + An Error Occurred + None + OK + Done + Copy + Persona + History + Pool + Retry + Remove + Something Went Wrong + Settings + Confirm + Save + Invalid + Public + Choose + Max + Optional + Show More + Show Less + Component + Unauthorized + Gateway access blocked due to exceeding rate limit. Please wait a few minutes to retry. + Bad HTTP response status code %d + Dismiss + Invalid Persona specified by dApp + Invalid request + Failed to import Radix Wallet backup: %s + Failed to import Radix Wallet backup, error: %s, version: %s + Failed to commit transaction + Failed to convert transaction manifest + Failed to get epoch + Failed to build transaction header + Failed to convert transaction manifest + You don\'t have access to some accounts or personas required to authorise this transaction + Wrong network + No funds to approve transaction + Failed to poll transaction status + Failed to prepare transaction + Transaction rejected + Unknown error + Failed to find ledger + Failed to add Transaction Fee, try a different amount of fee payer. + Failed to add Guarantee, try a different percentage, or try skip adding a guarantee. + A proposed transaction could not be processed. + Your current Ledger settings only allow signing of simple token transfers. Please either enable \"verbose mode\" (to see full transaction manifests) or \"blind signing mode\" (to enable signing of complex transaction manifest hashes) on your Ledger app device. + Failed to convert transaction manifest + Failed to submit transaction + Persona label too long + Account label too long + Account label required + One of the receiving accounts does not allow Third-Party deposits + Email Support + Please email support to automatically provide debugging info, and get assistance. Code: %s - Import Legacy Olympia Accounts - Scan the QR code shown in the Export section of the Radix Desktop Wallet for Olympia. - Scanned: %d/%d - Import Accounts - The following accounts will be imported into this Radix Wallet. - Legacy Account - Ledger (Legacy) - Unnamed - Olympia Address (Obsolete) - New Address - Import %d accounts - Import 1 account - Verify With Your Seed Phrase - To complete importing your accounts, please view your seed phrase in the Radix Desktop Wallet and enter the words here. - This will give this Radix Wallet control of your accounts. Never give your seed phrase to anyone for any reason. - Warning - Do not throw away this seed phrase! You will still need it if you need to recover access to your Olympia accounts in the future. - I Understand - Congratulations - You\'ve now imported these Accounts: - You\'ve now imported this Account: - Your Accounts live on the Radix Network and you can access them anytime in your Wallet. - Continue to Account List - Already imported - BIP39 passphrase - Import - Invalid Mnemonic - Invalid QR code - No mnemonic found for accounts - No new accounts were found on this Ledger device - Passphrase - Seed phrase - I\'m a New Radix Wallet User - Restore Wallet from Backup - Welcome to the Radix Wallet - Your direct connection to the Radix Network - A World of Possibilities - Let\'s get started - Your phone is your login - Connect and transact securely with a world of web3 dApps, tokens, NFTs, and much more - User Terms - To proceed, you must accept the user terms below. - Accept - Back up your Wallet Settings - Connect to Google Drive to automatically backup your Radix wallet settings. - Skip - Back up to Google Drive - Restore Wallet from Backup - Log in to Google Drive to restore your Radix wallet from Backup. - Skip - Log in to Google Drive - Tap to unlock - Passcode not set up - This app requires your phone to have a passcode set up - Delete Wallet Data - For this Preview wallet version, you must delete your wallet data to continue. - Wallet Data is Incompatible - Warning - Passcode is not set up. Please update settings. - Claim This Wallet? - Claim Existing Wallet - Clear Wallet on This Phone - Ask Later (no changes) - This wallet is currently configured with a set of Accounts and Personas in use by a different phone.\n\nTo make changes to this wallet, you must claim it for use on this phone instead, removing access by the other phone.\n\nOr you can clear this wallet from this phone and start fresh. - It appears that your device might be rooted. To ensure the security of your Accounts and assets, using the Radix Wallet on rooted devices is not recommended. Please confirm if you wish to continue anyway at your own risk. - Possible jailbreak detected - It appears that your device might be jailbroken. To ensure the security of your Accounts and assets, using the Radix Wallet on jailbroken devices is not recommended. Please confirm if you wish to continue anyway at your own risk. - I Understand the Risk - Approve Transaction - Incoming Transaction - Approve Transaction - Submitting transaction… - Import Seed Phrase - Backup Seed Phrase - Word %d - Passphrase - Passphrase - Optional BIP39 Passphrase. This is not your wallet password, and the Radix Desktop Wallet did not use a BIP39 passphrase. This is only to support import from other wallets that may have used one. - Number of Seed Phrase Words - Incorrect seed phrase - Success - Advanced Mode - Regular Mode - Import - Imported Seed Phrase - Confirm Seed Phrase Saved - Are you sure you have securely written down this seed phrase? You will need it to recover access if you lose your phone. - Yes, I have written it down - No, not yet - Failed to validate all accounts against mnemonic - Wrong mnemmonic - Tell a story - Hitchcock\'s The Birds mixed with Office space - Without revealing the words, what comes to mind when reading this seed phrase? - Backup location? - In that book my mother used to read to me at my best childhoods summer vacation place - Without revealing location, vague hint on where this mnemonic is backed up, if anywhere. - Save with description - Save without description - Enter this Account\'s seed phrase - Please write down seed phrase to ensure Account control - Change seed phrase length - %d word seed phrase - Recover Mnemonic - Can\'t displays image of vector type - Can\'t load image - Message - Add a message - Scan a QR code of a Radix Account address from another wallet or an exchange. - Continue - Account - From - To - Add Transfer - Transfer - Add Message - Invalid address - Account already added - Choose Receiving Account - Enter or scan an Account address - Or: Choose one of your own Accounts - Scan Account QR Code - Enter Radix Account address - Choose Asset(s) to Send - Select Assets - Choose 1 Asset - Choose %d Assets - Total exceeds your current balance - Balance: %s - Choose Account - Add Assets - Address is not valid on current network - Resource already added - Total amount exceeds your current balance - Sending All XRD - Sending the full amount of XRD in this account will require you to pay the transaction fee from a different account. Or, the wallet can reduce the amount transferred so the fee can be paid from this account. Choose the amount to transfer: - %s (send all XRD) - %s (save 1 XRD for fee) - You will be asked for an extra signature - Verify With Ledger Device - You are attempting to import one or more Olympia accounts that must be verified with a Ledger hardware wallet device. - Already verified Ledger devices: - Continue - Accounts remaining to verify: %d - Connect your next Ledger device, launch the Radix Babylon app on it, and tap Continue here. - Link a Connector - To use a Ledger hardware wallet device, it must be connected to a computer running the Radix Connector browser extension. - Continue - Choose Ledger - Choose Ledger Device - Ledger Devices - What is a Ledger Factor Source - Add Ledger Device - Added - Last Used - Continue - No Ledger devices currently added to your Radix Wallet - Choose a Ledger device to use - Choose an existing Ledger or add a new one - Here are all the Ledger devices you have added. - Could not find Ledger devices - Transaction could not be signed. To sign complex transactions, please enable either \"blind signing\" or \"verbose mode\" in the Radix app on your Ledger device. - Could Not Sign - Address verified - Verify address: Mismatched addresses - Verify address: Returned bad response - Verify address: Request failed - Use Caution - Reveal Seed Phrase - A seed phrase provides full control of its Accounts. Do not view in a public area. Write down the seed phrase words securely. Screenshots are disabled. - Seed Phrases - Connected to Personas and %d Account - Connected to Personas and to %d Accounts - Connected to %d Account - Connected to %d Accounts - You are responsible for the security of your Seed Phrase - Write Down this Seed Phrase - Begin seed phrase entry - Confirm Your Seed Phrase - Confirm you have written down the seed phrase by entering the missing words below. - Reveal Seed Phrase - For your safety, make sure no one is looking at your screen. Taking a screen shot has been disabled. - Word %d - Passphrase - Use Caution - Are you sure you have written down your seed phrase? - I have written down this seed phrase - Seed Phrases - A Seed Phrase provides full access to your accounts and funds. When viewing, ensure you’re in a safe environment and no one is looking at your screen. - You are responsible for the security of your Seed Phrase - Please write down your Seed Phrase - Hidden Accounts only - Seed Phrase Entry Required - Reveal Seed Phrase - Not connected to any Accounts - Connected to 1 Account - Connected to %d Accounts - Seed Phrase - Not yet connected to any Accounts - Currently connected to 1 Account - Currently connected to %d Accounts - App Settings - Customize your Radix Wallet - Linked Connectors - Network Gateways - Account & Persona Hiding - Manage hiding - Accounts and Personas you have created can be hidden in your Radix Wallet, acting as if “deleted”. - %d Persona currently hidden - %d Personas currently hidden - %d Account currently hidden - %d Accounts currently hidden - Unhide Accounts & Personas - Unhide All - Are you sure you wish to unhide all Accounts and Personas? This cannot be undone. - Developer Mode - Warning: Disables website validity checks - Crash Reporting - I\'m aware Radix Wallet will send crash reports together with device state from the moment of crash. - Ledger Already Added - You have already added this Ledger as: %s - Add Ledger Device - Let’s set up a Ledger hardware wallet device. You will be able to use it to create new Ledger-secured Accounts, or import Ledger-secured Accounts from the Radix Olympia Desktop Wallet. - Connect your Ledger to a computer running a linked Radix Connector browser extension, and make sure the Radix Babylon app is running on the Ledger device. - Continue - Name Your Ledger - What would you like to call this Ledger device? - This will be displayed when you’re prompted to sign with this Ledger device. - Detected type: %s - Green Ledger Nano S+ - Save and Continue - Backing up your wallet ensures that you can restore access to your Accounts, Personas, and wallet settings on a new phone by re-entering your seed phrase(s).\n\n**For security, backups do not contain any seed phrases or private keys. You must write them down separately.** - Automatic Backups (recommended) - Manual Backups - A manually exported wallet backup file may also be used for recovery, along with your seed phrase(s).\n\nOnly the **current configuration** of your wallet is backed up with each manual export. - Export Wallet Backup File - Encrypt this backup with a password? - Exported wallet backup file - Yes - No - Encrypt Wallet Backup File - Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. - Decrypt Wallet Backup File - Enter the password you chose when you originally encrypted this Wallet Backup file. - Enter password - Confirm password - Passwords do not match - Encryption password - Decryption password - Incorrect password - OK - Failed to encrypt using provided password. - Failed to decrypt using provided password. - Delete Wallet - WARNING. This will clear all contents of your Wallet. If you have no backup, you will lose access to your Accounts and Personas permanently. - Delete Wallet - Reset Wallet? - Reset Wallet - Reset and Delete iCloud Backup - WARNING. This will clear all contents of your Wallet. If you have no backup, you will lose access to your Accounts and Personas permanently. - Back up is turned off - Last Backed up: %s - Not backed up yet - Open System Backup Settings - Backup Wallet Data to Cloud - Warning: If disabled you might lose access to your Accounts and Personas. - You may delete your wallet. This will clear the Radix Wallet app, clears its contents, and delete any cloud backup.\n\n**Access to any Accounts or Personas will be permanently lost unless you have a manual backup file.** - Delete Wallet - Enabling iCloud sync - iCloud sync is now enabled, but it might take up to an hour before your wallet data is uploaded to iCloud. - Disabling iCloud sync will delete the iCloud backup data, are you sure you want to disable iCloud sync? - Enable Backup to iCloud - Disable Backup to iCloud - Automatic continuous backups - Sync Wallet Data to iCloud - Warning: If disabled you might lose access to your Accounts and Personas. - Wallet Data Backup - Import From Backup - Available backups: - Use iCloud Backup Data - This Device - Backup created by: %s - Creation date: %s - Last used on device: %s - Last modified date: %s - Number of networks: %d - Number of Accounts: %d - Number of Personas: %d - Incompatible Wallet data - You may delete your wallet. This will clear the Radix Wallet app, clears its contents, and delete any iCloud backup.\n\n**Access to any Accounts or Personas will be permanently lost unless you have a manual backup file.** - Delete Wallet and iCloud Backup - Unable to find wallet backup in iCloud. - Encrypt Wallet Backup File - Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. - Enter password - Confirm password - Passwords do not match - Restore Wallet From Backup - Select a backup to restore your Radix Wallet. You will be asked to enter your seed phrase(s) to recover control of your Accounts and Personas. - Choose a backup - Choose a backup on iCloud - No wallet backups available on current iCloud account - Not logged in to iCloud - Network unavailable - Could not load backups - No wallet backups available - **Backup from:** %s - **Last modified:** %s - **Number of accounts:** %d - **Number of personas:** %d - Import from Backup File Instead - Incompatible Wallet data - The password is wrong - Backup not available? - Other Restore Options - Main Seed Phrase Required - No Main Seed Phrase? - Seed Phrase Required - Your **Personas** and the following **Accounts** are controlled by your main seed phrase. To recover control, you must re-enter it. - The following **Accounts** are controlled by a seed phrase. To recover control, you must re-enter it. - The Radix Wallet always uses a single main “Babylon” seed phrase to generate new Personas and new Accounts (when not using a Ledger device).\n\nIf you do not have access to your previous main seed phrase, you can skip entering it for now. **The Radix Wallet will create a new one, which will be used for new Personas and Accounts.**\n\nYour old Accounts and Personas will still be listed, but you will have to enter their original seed phrase to use them. Alternatively, you can hide them if you no longer are interested in using them. - Skip This Seed Phrase For Now - I Don’t Have the Main Seed Phrase - Enter This Seed Phrase - Skip Main Seed Phrase Entry - Hidden accounts only. - Phone - Ledger - Seed phrase - Third-party - Security Questions - Customize Fees - Estimated Transaction Fees - Transaction Fee - (maximum to lock) - Advanced Customize Fees - Choose what account to pay the transaction fee from, or add a \"tip\" to speed up your transaction if necessary. - Fully customize fee payment for this transaction. Not recomended unless you are a developer or advanced user. - Pay fee from - Change - None required - None due - No account selected - Select Fee Payer - Select an account to pay %s XRD transaction fee - Select Account - View Normal Mode - View Advanced Mode - Network Fee - Network Execution - Network Finalization - Effective Tip - Network Storage - Padding - Royalties - Royalty fee - Paid by dApps - Adjust Fee Padding Amount (XRD) - Adjust Tip to Lock - (%% of Execution + Finalization Fees) - Please select a fee payer for the transaction fee - Not enough XRD for transaction fee - Scanning in progress - Scanning for Accounts that have been included in at least one transaction, using: - **Babylon Seed Phrase** - **Olympia Seed Phrase** - **Ledger hardware wallet device** - Signing Factor - Unnamed - Scanning network - Scan Complete - The first **%d** potential Accounts from this signing factor were scanned. The following Accounts had at least one transaction: - No new accounts found - Tap here to scan the next %d - Continue - Add Inactive Accounts? - These Accounts were never used, but you **may** have created them. Select any addresses that you wish to keep: - Continue - Account Recovery Scan - The Radix Wallet can scan for previously used accounts using a bare seed phrase or Ledger hardware wallet device - Babylon Accounts - Scan for Accounts originally created on the **Babylon** network. - Olympia Accounts - Scan for Accounts originally created on the **Olympia** network.\n\n(If you have Olympia Accounts in the Radix Olympia Desktop Wallet, consider using **Import from a Legacy Wallet** instead. - Note: You will still use the new **Radix Babylon** app on your Ledger device, not the old Radix Ledger app. - Use Seed Phrase - Use Ledger Hardware Wallet - Choose Seed Phrase - Choose the \"Legacy\" Olympia seed phrase for use for derivation: - Choose the Babylon seed phrase for use for derivation: - Add Babylon Seed Phrase - Add Olympia Seed Phrase - Enter Legacy Seed Phrase - Enter Seed Phrase - Continue - Note: You must still use the new *Radix Babylon* app on your Ledger device, not the old Radix Ledger app. - Seed Phrases - Ledger Hardware Wallets - Default Deposit Guarantees - Set your default guaranteed minimum for estimated deposits - Set the guaranteed minimum deposit to be applied whenever a deposit in a transaction can only be estimated.\n\nYou can always change the guarantee from this default in each transaction. - Account Recovery Scan - Using seed phrase or Ledger device - Backups - Import from a Legacy Wallet - Enter Seed Phrase - Enter Main Seed Phrase - For your safety, make sure no one is looking at your screen. Never give your seed phrase to anyone for any reason. - Enter Main Seed Phrase - Enter Babylon Seed Phrase - Enter Olympia Seed Phrase - Recover Control Without Backup - If you have no wallet backup in the cloud, or as an exported backup file, you still have other restore options. - I have my main “Babylon” 24-word seed phrase. - Recover with Main Seed Phrase - I only want to restore Ledger hardware wallet Accounts. - Ledger-only Restore - I only have Accounts created on the Radix Olympia network. - Olympia-only Restore - No Main Seed Phrase? - Tap “I\'m a New Wallet User”. After completing wallet creation, in Settings you can perform an “account recovery scan” using your Ledger device. - Tap “I\'m a New Wallet User”. After completing wallet creation, in Settings you can perform an “account recovery scan” using your Olympia seed phrase. - Cancel - Continue - Recover Control Without Backup - **If you have no wallet backup in the cloud or as an exported backup file**, you can still restore Account access only using your main “Babylon” seed phrase. You cannot recover your Account names or other wallet settings this way.\n\nYou will be asked to enter your main seed phrase. This is a set of **24 words** that the Radix Wallet mobile app showed you to write down and save securely. - Continue - Recovery Complete - Accounts discovered in the scan have been added to your wallet.\n\nIf you have any “Legacy” Accounts (created on the Olympia network) to import - or any Accounts using a Ledger hardware wallet device - please continue and then use the **Account Recovery Scan** option in your Radix Wallet settings under **Account Security**. - Continue - History - Settings - Withdrawn - Deposited - Updated Account Deposit Settings - No deposits or withdrawals from this account in this transaction. - This transaction cannot be summarized. Only the raw transaction manifest may be viewed. - Failed Transaction - You have no Transactions. - General - Transfer - Stake - Request Unstake - Claim Stake - Contribute - Redeem - Deposit Settings - Other - Filter - Clear All - Show Results - Type of Asset - Show All Tokens - Show Less Tokens - Show All NFTs - Show Less NFTs - Tokens - Deposits - Withdrawals - NFTs - Type of Transaction - Today - Yesterday - How\'s it Going? - How likely are you to recommend Radix and the Radix Wallet to your friends or colleagues? - 0 - Not likely - 10 - Very likely - What’s the main reason for your score? - Let us know... - Submit Feedback - Thanks! - Signature Request - Creating Account - Creating Persona - Deriving Accounts - Proving Ownership - Encrypting Message - Creating Key - Authenticate to your phone to sign. - Authenticate to your phone to complete using your phone\'s signing key. - Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. + Import Legacy Olympia Accounts + Scan the QR code shown in the Export section of the Radix Desktop Wallet for Olympia. + Scanned: %d/%d + Import Accounts + The following accounts will be imported into this Radix Wallet. + Legacy Account + Ledger (Legacy) + Unnamed + Olympia Address (Obsolete) + New Address + Import %d accounts + Import 1 account + Verify With Your Seed Phrase + To complete importing your accounts, please view your seed phrase in the Radix Desktop Wallet and enter the words here. + This will give this Radix Wallet control of your accounts. Never give your seed phrase to anyone for any reason. + Warning + Do not throw away this seed phrase! You will still need it if you need to recover access to your Olympia accounts in the future. + I Understand + Congratulations + You\'ve now imported these Accounts: + You\'ve now imported this Account: + Your Accounts live on the Radix Network and you can access them anytime in your Wallet. + Continue to Account List + Already imported + BIP39 passphrase + Import + Invalid Mnemonic + Invalid QR code + No mnemonic found for accounts + No new accounts were found on this Ledger device + Passphrase + Seed phrase + I\'m a New Radix Wallet User + Restore Wallet from Backup + Welcome to the Radix Wallet + Your direct connection to the Radix Network + A World of Possibilities + Let\'s get started + Your phone is your login + Connect and transact securely with a world of web3 dApps, tokens, NFTs, and much more + User Terms + To proceed, you must accept the user terms below. + Accept + Back up your Wallet Settings + Connect to Google Drive to automatically backup your Radix wallet settings. + Skip + Back up to Google Drive + Restore Wallet from Backup + Log in to Google Drive to restore your Radix wallet from Backup. + Skip + Log in to Google Drive + Tap to unlock + Passcode not set up + This app requires your phone to have a passcode set up + Delete Wallet Data + For this Preview wallet version, you must delete your wallet data to continue. + Wallet Data is Incompatible + Warning + Passcode is not set up. Please update settings. + Claim This Wallet? + Claim Existing Wallet + Clear Wallet on This Phone + Ask Later (no changes) + This wallet is currently configured with a set of Accounts and Personas in use by a different phone.\n\nTo make changes to this wallet, you must claim it for use on this phone instead, removing access by the other phone.\n\nOr you can clear this wallet from this phone and start fresh. + It appears that your device might be rooted. To ensure the security of your Accounts and assets, using the Radix Wallet on rooted devices is not recommended. Please confirm if you wish to continue anyway at your own risk. + Possible jailbreak detected + It appears that your device might be jailbroken. To ensure the security of your Accounts and assets, using the Radix Wallet on jailbroken devices is not recommended. Please confirm if you wish to continue anyway at your own risk. + I Understand the Risk + Approve Transaction + Incoming Transaction + Approve Transaction + Submitting transaction… + Import Seed Phrase + Backup Seed Phrase + Word %d + Passphrase + Passphrase + Optional BIP39 Passphrase. This is not your wallet password, and the Radix Desktop Wallet did not use a BIP39 passphrase. This is only to support import from other wallets that may have used one. + Number of Seed Phrase Words + Incorrect seed phrase + Success + Advanced Mode + Regular Mode + Import + Imported Seed Phrase + Confirm Seed Phrase Saved + Are you sure you have securely written down this seed phrase? You will need it to recover access if you lose your phone. + Yes, I have written it down + No, not yet + Failed to validate all accounts against mnemonic + Wrong mnemmonic + Tell a story + Hitchcock\'s The Birds mixed with Office space + Without revealing the words, what comes to mind when reading this seed phrase? + Backup location? + In that book my mother used to read to me at my best childhoods summer vacation place + Without revealing location, vague hint on where this mnemonic is backed up, if anywhere. + Save with description + Save without description + Enter this Account\'s seed phrase + Please write down seed phrase to ensure Account control + Change seed phrase length + %d word seed phrase + Recover Mnemonic + Can\'t displays image of vector type + Can\'t load image + Message + Add a message + Scan a QR code of a Radix Account address from another wallet or an exchange. + Continue + Account + From + To + Add Transfer + Transfer + Add Message + Invalid address + Account already added + Choose Receiving Account + Enter or scan an Account address + Or: Choose one of your own Accounts + Scan Account QR Code + Enter Radix Account address + Choose Asset(s) to Send + Select Assets + Choose 1 Asset + Choose %d Assets + Total exceeds your current balance + Balance: %s + Choose Account + Add Assets + Address is not valid on current network + Resource already added + Total amount exceeds your current balance + Sending All XRD + Sending the full amount of XRD in this account will require you to pay the transaction fee from a different account. Or, the wallet can reduce the amount transferred so the fee can be paid from this account. Choose the amount to transfer: + %s (send all XRD) + %s (save 1 XRD for fee) + You will be asked for an extra signature + Verify With Ledger Device + You are attempting to import one or more Olympia accounts that must be verified with a Ledger hardware wallet device. + Already verified Ledger devices: + Continue + Accounts remaining to verify: %d + Connect your next Ledger device, launch the Radix Babylon app on it, and tap Continue here. + Link a Connector + To use a Ledger hardware wallet device, it must be connected to a computer running the Radix Connector browser extension. + Continue + Choose Ledger + Choose Ledger Device + Ledger Devices + What is a Ledger Factor Source + Add Ledger Device + Added + Last Used + Continue + No Ledger devices currently added to your Radix Wallet + Choose a Ledger device to use + Choose an existing Ledger or add a new one + Here are all the Ledger devices you have added. + Could not find Ledger devices + Transaction could not be signed. To sign complex transactions, please enable either \"blind signing\" or \"verbose mode\" in the Radix app on your Ledger device. + Could Not Sign + Address verified + Verify address: Mismatched addresses + Verify address: Returned bad response + Verify address: Request failed + Use Caution + Reveal Seed Phrase + A seed phrase provides full control of its Accounts. Do not view in a public area. Write down the seed phrase words securely. Screenshots are disabled. + Seed Phrases + Connected to Personas and %d Account + Connected to Personas and to %d Accounts + Connected to %d Account + Connected to %d Accounts + You are responsible for the security of your Seed Phrase + Write Down this Seed Phrase + Begin seed phrase entry + Confirm Your Seed Phrase + Confirm you have written down the seed phrase by entering the missing words below. + Reveal Seed Phrase + For your safety, make sure no one is looking at your screen. Taking a screen shot has been disabled. + Word %d + Passphrase + Use Caution + Are you sure you have written down your seed phrase? + I have written down this seed phrase + Seed Phrases + A Seed Phrase provides full access to your accounts and funds. When viewing, ensure you’re in a safe environment and no one is looking at your screen. + You are responsible for the security of your Seed Phrase + Please write down your Seed Phrase + Hidden Accounts only + Seed Phrase Entry Required + Reveal Seed Phrase + Not connected to any Accounts + Connected to 1 Account + Connected to %d Accounts + Seed Phrase + Not yet connected to any Accounts + Currently connected to 1 Account + Currently connected to %d Accounts + App Settings + Customize your Radix Wallet + Linked Connectors + Network Gateways + Account & Persona Hiding + Manage hiding + Accounts and Personas you have created can be hidden in your Radix Wallet, acting as if “deleted”. + %d Persona currently hidden + %d Personas currently hidden + %d Account currently hidden + %d Accounts currently hidden + Unhide Accounts & Personas + Unhide All + Are you sure you wish to unhide all Accounts and Personas? This cannot be undone. + Developer Mode + Warning: Disables website validity checks + Crash Reporting + I\'m aware Radix Wallet will send crash reports together with device state from the moment of crash. + Ledger Already Added + You have already added this Ledger as: %s + Add Ledger Device + Let’s set up a Ledger hardware wallet device. You will be able to use it to create new Ledger-secured Accounts, or import Ledger-secured Accounts from the Radix Olympia Desktop Wallet. + Connect your Ledger to a computer running a linked Radix Connector browser extension, and make sure the Radix Babylon app is running on the Ledger device. + Continue + Name Your Ledger + What would you like to call this Ledger device? + This will be displayed when you’re prompted to sign with this Ledger device. + Detected type: %s + Green Ledger Nano S+ + Save and Continue + Backing up your wallet ensures that you can restore access to your Accounts, Personas, and wallet settings on a new phone by re-entering your seed phrase(s).\n\n**For security, backups do not contain any seed phrases or private keys. You must write them down separately.** + Automatic Backups (recommended) + Manual Backups + A manually exported wallet backup file may also be used for recovery, along with your seed phrase(s).\n\nOnly the **current configuration** of your wallet is backed up with each manual export. + Export Wallet Backup File + Encrypt this backup with a password? + Exported wallet backup file + Yes + No + Encrypt Wallet Backup File + Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. + Decrypt Wallet Backup File + Enter the password you chose when you originally encrypted this Wallet Backup file. + Enter password + Confirm password + Passwords do not match + Encryption password + Decryption password + Incorrect password + OK + Failed to encrypt using provided password. + Failed to decrypt using provided password. + Delete Wallet + WARNING. This will clear all contents of your Wallet. If you have no backup, you will lose access to your Accounts and Personas permanently. + Delete Wallet + Reset Wallet? + Reset Wallet + Reset and Delete iCloud Backup + WARNING. This will clear all contents of your Wallet. If you have no backup, you will lose access to your Accounts and Personas permanently. + Back up is turned off + Last Backed up: %s + Not backed up yet + Open System Backup Settings + Backup Wallet Data to Cloud + Warning: If disabled you might lose access to your Accounts and Personas. + You may delete your wallet. This will clear the Radix Wallet app, clears its contents, and delete any cloud backup.\n\n**Access to any Accounts or Personas will be permanently lost unless you have a manual backup file.** + Delete Wallet + Enabling iCloud sync + iCloud sync is now enabled, but it might take up to an hour before your wallet data is uploaded to iCloud. + Disabling iCloud sync will delete the iCloud backup data, are you sure you want to disable iCloud sync? + Enable Backup to iCloud + Disable Backup to iCloud + Automatic continuous backups + Sync Wallet Data to iCloud + Warning: If disabled you might lose access to your Accounts and Personas. + Wallet Data Backup + Import From Backup + Available backups: + Use iCloud Backup Data + This Device + Backup created by: %s + Creation date: %s + Last used on device: %s + Last modified date: %s + Number of networks: %d + Number of Accounts: %d + Number of Personas: %d + Incompatible Wallet data + You may delete your wallet. This will clear the Radix Wallet app, clears its contents, and delete any iCloud backup.\n\n**Access to any Accounts or Personas will be permanently lost unless you have a manual backup file.** + Delete Wallet and iCloud Backup + Unable to find wallet backup in iCloud. + Encrypt Wallet Backup File + Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. + Enter password + Confirm password + Passwords do not match + Restore Wallet From Backup + Select a backup to restore your Radix Wallet. You will be asked to enter your seed phrase(s) to recover control of your Accounts and Personas. + Choose a backup + Choose a backup on iCloud + No wallet backups available on current iCloud account + Not logged in to iCloud + Network unavailable + Could not load backups + No wallet backups available + **Backup from:** %s + **Last modified:** %s + **Number of accounts:** %d + **Number of personas:** %d + Import from Backup File Instead + Incompatible Wallet data + The password is wrong + Backup not available? + Other Restore Options + Main Seed Phrase Required + No Main Seed Phrase? + Seed Phrase Required + Your **Personas** and the following **Accounts** are controlled by your main seed phrase. To recover control, you must re-enter it. + The following **Accounts** are controlled by a seed phrase. To recover control, you must re-enter it. + The Radix Wallet always uses a single main “Babylon” seed phrase to generate new Personas and new Accounts (when not using a Ledger device).\n\nIf you do not have access to your previous main seed phrase, you can skip entering it for now. **The Radix Wallet will create a new one, which will be used for new Personas and Accounts.**\n\nYour old Accounts and Personas will still be listed, but you will have to enter their original seed phrase to use them. Alternatively, you can hide them if you no longer are interested in using them. + Skip This Seed Phrase For Now + I Don’t Have the Main Seed Phrase + Enter This Seed Phrase + Skip Main Seed Phrase Entry + Hidden accounts only. + Phone + Ledger + Seed phrase + Third-party + Security Questions + Customize Fees + Estimated Transaction Fees + Transaction Fee + (maximum to lock) + Advanced Customize Fees + Choose what account to pay the transaction fee from, or add a \"tip\" to speed up your transaction if necessary. + Fully customize fee payment for this transaction. Not recomended unless you are a developer or advanced user. + Pay fee from + Change + None required + None due + No account selected + Select Fee Payer + Select an account to pay %s XRD transaction fee + Select Account + View Normal Mode + View Advanced Mode + Network Fee + Network Execution + Network Finalization + Effective Tip + Network Storage + Padding + Royalties + Royalty fee + Paid by dApps + Adjust Fee Padding Amount (XRD) + Adjust Tip to Lock + (%% of Execution + Finalization Fees) + Please select a fee payer for the transaction fee + Not enough XRD for transaction fee + Scanning in progress + Scanning for Accounts that have been included in at least one transaction, using: + **Babylon Seed Phrase** + **Olympia Seed Phrase** + **Ledger hardware wallet device** + Signing Factor + Unnamed + Scanning network + Scan Complete + The first **%d** potential Accounts from this signing factor were scanned. The following Accounts had at least one transaction: + No new accounts found + Tap here to scan the next %d + Continue + Add Inactive Accounts? + These Accounts were never used, but you **may** have created them. Select any addresses that you wish to keep: + Continue + Account Recovery Scan + The Radix Wallet can scan for previously used accounts using a bare seed phrase or Ledger hardware wallet device + Babylon Accounts + Scan for Accounts originally created on the **Babylon** network. + Olympia Accounts + Scan for Accounts originally created on the **Olympia** network.\n\n(If you have Olympia Accounts in the Radix Olympia Desktop Wallet, consider using **Import from a Legacy Wallet** instead. + Note: You will still use the new **Radix Babylon** app on your Ledger device, not the old Radix Ledger app. + Use Seed Phrase + Use Ledger Hardware Wallet + Choose Seed Phrase + Choose the \"Legacy\" Olympia seed phrase for use for derivation: + Choose the Babylon seed phrase for use for derivation: + Add Babylon Seed Phrase + Add Olympia Seed Phrase + Enter Legacy Seed Phrase + Enter Seed Phrase + Continue + Note: You must still use the new *Radix Babylon* app on your Ledger device, not the old Radix Ledger app. + Seed Phrases + Ledger Hardware Wallets + Default Deposit Guarantees + Set your default guaranteed minimum for estimated deposits + Set the guaranteed minimum deposit to be applied whenever a deposit in a transaction can only be estimated.\n\nYou can always change the guarantee from this default in each transaction. + Account Recovery Scan + Using seed phrase or Ledger device + Backups + Import from a Legacy Wallet + Enter Seed Phrase + Enter Main Seed Phrase + For your safety, make sure no one is looking at your screen. Never give your seed phrase to anyone for any reason. + Enter Main Seed Phrase + Enter Babylon Seed Phrase + Enter Olympia Seed Phrase + Recover Control Without Backup + If you have no wallet backup in the cloud, or as an exported backup file, you still have other restore options. + I have my main “Babylon” 24-word seed phrase. + Recover with Main Seed Phrase + I only want to restore Ledger hardware wallet Accounts. + Ledger-only Restore + I only have Accounts created on the Radix Olympia network. + Olympia-only Restore + No Main Seed Phrase? + Tap “I\'m a New Wallet User”. After completing wallet creation, in Settings you can perform an “account recovery scan” using your Ledger device. + Tap “I\'m a New Wallet User”. After completing wallet creation, in Settings you can perform an “account recovery scan” using your Olympia seed phrase. + Cancel + Continue + Recover Control Without Backup + **If you have no wallet backup in the cloud or as an exported backup file**, you can still restore Account access only using your main “Babylon” seed phrase. You cannot recover your Account names or other wallet settings this way.\n\nYou will be asked to enter your main seed phrase. This is a set of **24 words** that the Radix Wallet mobile app showed you to write down and save securely. + Continue + Recovery Complete + Accounts discovered in the scan have been added to your wallet.\n\nIf you have any “Legacy” Accounts (created on the Olympia network) to import - or any Accounts using a Ledger hardware wallet device - please continue and then use the **Account Recovery Scan** option in your Radix Wallet settings under **Account Security**. + Continue + History + Settings + Withdrawn + Deposited + Updated Account Deposit Settings + No deposits or withdrawals from this account in this transaction. + This transaction cannot be summarized. Only the raw transaction manifest may be viewed. + Failed Transaction + You have no Transactions. + General + Transfer + Stake + Request Unstake + Claim Stake + Contribute + Redeem + Deposit Settings + Other + Filter + Clear All + Show Results + Type of Asset + Show All Tokens + Show Less Tokens + Show All NFTs + Show Less NFTs + Tokens + Deposits + Withdrawals + NFTs + Type of Transaction + Today + Yesterday + How\'s it Going? + How likely are you to recommend Radix and the Radix Wallet to your friends or colleagues? + 0 - Not likely + 10 - Very likely + What’s the main reason for your score? + Let us know... + Submit Feedback - Thanks! + Signature Request + Creating Account + Creating Persona + Deriving Accounts + Proving Ownership + Encrypting Message + Creating Key + Authenticate to your phone to sign. + Authenticate to your phone to complete using your phone\'s signing key. + Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. **Complete signing on the device.** - Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. + Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. **Derivation may take up to a minute.** - Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. - Security Center - Decentralized security settings that give you total control over your wallet’s protection. - Your wallet is recoverable - Security Factors - The keys you use to control your Accounts and Personas - Active - Configuration Backup - A backup of your Account, Personas and wallet settings - Backed up - Action required - Encrypt Wallet Backup File - Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. - Enter Password - Confirm Password - Passwords do not match - Continue - Security Factors - View and manage your security factors - Seed Phrases - Your seedphrases connected to your account - 1 Seed phrase - %d Seed phrases - Enter your seed phrase to recover Accounts - Ledger Hardware Wallets - Hardware wallet designed for holding crypto - 1 set - %d set - Configuration Backup - You need an up-to-date Configuration Backup to recover your Accounts and Personas if you lose access to them.\n\nYour Backup does not contain your keys or seed phrase. - Configuration Backup status - Without an updated Configuration Backup, you cannot recover your Accounts and Personas. - Automated iCloud Backups - Automated Google Drive Backups - Last backup: %s - Log in to Google Drive - Logged in as: - Disconnect - Out-of-date backup still present on iCloud - Delete - Accounts - Your list of Accounts and the Factors required to recover them - Personas - Your list of Personas and the Factors required to recover them. Also your Persona data. - Security Factors - The list of Security Factors you need to recover your Accounts and Personas. - Wallet settings - Your general settings, such as trusted dApps, linked Connectors and wallet display settings. - Wallet Control Has Been Transferred - The current wallet configuration is now controlled by another phone. - If this was done in error, you can reclaim control to this phone. You won’t be able to access it from your old phone after the transfer. - Or, you can clear the wallet configuration from this phone and start fresh. - Clear Wallet on This Phone - Transfer Control Back to This Phone - Backups on Google Drive Have Updated - The Radix Wallet has an all new and improved backup system.\n\nTo continue, log in with the Google Drive account you want to use for backups. - Login to Google Drive for Backups - Skip for Now - Manual backup - You can export your own Configuration Backup file and save it locally - You’ll need to export a new Backup file each time you make a change in your wallet. - Export Backup File - Last backup: %s - Wallet Settings - Security Center - Manage your wallet security settings - Personas - Manage Radix dApp login details - Please write down the seed phrase for your Personas - Approved dApps - Manage the Radix dApps you\'re connected to - Linked Connectors - Connect to desktop through the Radix Connector browser extension - Preferences - Deposits, hidden Accounts and Personas, and advanced preferences - Troubleshooting - Add your existing Accounts and contact support - App version: %s - Link your Wallet to a desktop browser - Scan the QR code in the Radix Wallet Connector extension - Link to Connector - Preferences - Default Deposit Guarantees - Set your guaranteed minimum for estimated deposits - Hidden Accounts and Personas - Manage hidden Accounts and Personas - Advanced Preferences - Network Gateways - Developer Mode - Warning: disables website validity checks - Troubleshooting - Account Recovery - Account Recovery Scan - Recover Accounts with a seed phrase or Ledger device - Import from a Legacy Wallet - Import Accounts from an Olympia wallet - Support and Community - Contact Support - Connect directly with the Radix support team - Discord - Connect to the official Radix Discord channel to join the community and ask for help. - Reset Account - Factory Reset - Restore your Radix wallet to its original state - Address QR Code - Full address - Copy - Enlarge - Share - View on Radix Dashboard - Verify Address on Ledger Device - Could not create QR code - Today - Yesterday - Tomorrow - %s ago - Just now - Factory Reset - A factory reset will restore your Radix wallet to its original settings. All of your data and preferences will be erased. - Security Center status - Your wallet is recoverable - Your wallet is not recoverable - Your wallet is currently unrecoverable. If you do a factory reset now, you will never be able to access your Accounts and Personas again. - Once you’ve completed a factory reset, you will not be able to access your Accounts and Personas unless you do a full recovery. - Reset Wallet - Confirm factory reset - Return wallet to factory settings? You cannot undo this. - You need to write down a seed phrase - %s and %s are not recoverable. - %s and %s (plus some hidden) are not recoverable. - View and write down your seed phrase so Accounts and Personas are recoverable. - View and write down seed phrase - View and write down seed phrase - Personas are not recoverable - You need to write down a seed phrase - Problem with Configuration Backup - Your wallet is not recoverable - Automated Configuration Backup has stopped working. Check internet and cloud settings. - Automated Configuration Backup not working. Check internet connection and cloud settings. - Personas are not recoverable - Problem with Configuration Backup - Your wallet is not recoverable - Your wallet is not recoverable - Configuration Backup is not up to date. Create backup now. - To secure your wallet, turn on automated backups or manually export backup file. - Personas are not recoverable - Your wallet is not recoverable - Configuration Backup not up to date - Your wallet is not recoverable - Accounts and Personas not recoverable. Create Configuration Backup now. - Configuration Backup not up to date. Turn on automated backups or manually export backup file. - Personas are not recoverable - Configuration Backup not up to date - Recovery required - Recovery required - Enter seed phrase to recover control. - Enter seed phrase to recover control - Enter seed phrase to recover control - Recovery required - Recovery required - 1 account - %d accounts - 1 persona - %d personas + Make sure the following **Ledger hardware wallet** is connected to a computer with a linked Radix Connector browser extension. + Security Center + Decentralized security settings that give you total control over your wallet’s protection. + Your wallet is recoverable + Security Factors + The keys you use to control your Accounts and Personas + Active + Configuration Backup + A backup of your Account, Personas and wallet settings + Backed up + Action required + Encrypt Wallet Backup File + Enter a password to encrypt this wallet backup file. You will be required to enter this password when recovering your Wallet from this file. + Enter Password + Confirm Password + Passwords do not match + Continue + Security Factors + View and manage your security factors + Seed Phrases + Your seedphrases connected to your account + 1 Seed phrase + %d Seed phrases + Enter your seed phrase to recover Accounts + Ledger Hardware Wallets + Hardware wallet designed for holding crypto + 1 set + %d set + Configuration Backup + You need an up-to-date Configuration Backup to recover your Accounts and Personas if you lose access to them.\n\nYour Backup does not contain your keys or seed phrase. + Configuration Backup status + Without an updated Configuration Backup, you cannot recover your Accounts and Personas. + Automated iCloud Backups + Automated Google Drive Backups + Last backup: %s + Log in to Google Drive + Logged in as: + Disconnect + Out-of-date backup still present on iCloud + Delete + Accounts + Your list of Accounts and the Factors required to recover them + Personas + Your list of Personas and the Factors required to recover them. Also your Persona data. + Security Factors + The list of Security Factors you need to recover your Accounts and Personas. + Wallet settings + Your general settings, such as trusted dApps, linked Connectors and wallet display settings. + Wallet Control Has Been Transferred + The current wallet configuration is now controlled by another phone. + If this was done in error, you can reclaim control to this phone. You won’t be able to access it from your old phone after the transfer. + Or, you can clear the wallet configuration from this phone and start fresh. + Clear Wallet on This Phone + Transfer Control Back to This Phone + Backups on Google Drive Have Updated + The Radix Wallet has an all new and improved backup system.\n\nTo continue, log in with the Google Drive account you want to use for backups. + Login to Google Drive for Backups + Skip for Now + Manual backup + You can export your own Configuration Backup file and save it locally + You’ll need to export a new Backup file each time you make a change in your wallet. + Export Backup File + Last backup: %s + Wallet Settings + Security Center + Manage your wallet security settings + Personas + Manage Radix dApp login details + Please write down the seed phrase for your Personas + Approved dApps + Manage the Radix dApps you\'re connected to + Linked Connectors + Connect to desktop through the Radix Connector browser extension + Preferences + Deposits, hidden Accounts and Personas, and advanced preferences + Troubleshooting + Add your existing Accounts and contact support + App version: %s + Link your Wallet to a desktop browser + Scan the QR code in the Radix Wallet Connector extension + Link to Connector + Preferences + Default Deposit Guarantees + Set your guaranteed minimum for estimated deposits + Hidden Accounts and Personas + Manage hidden Accounts and Personas + Advanced Preferences + Network Gateways + Developer Mode + Warning: disables website validity checks + Troubleshooting + Account Recovery + Account Recovery Scan + Recover Accounts with a seed phrase or Ledger device + Import from a Legacy Wallet + Import Accounts from an Olympia wallet + Support and Community + Contact Support + Connect directly with the Radix support team + Discord + Connect to the official Radix Discord channel to join the community and ask for help. + Reset Account + Factory Reset + Restore your Radix wallet to its original state + Address QR Code + Full address + Copy + Enlarge + Share + View on Radix Dashboard + Verify Address on Ledger Device + Could not create QR code + Today + Yesterday + Tomorrow + %s ago + Just now + Factory Reset + A factory reset will restore your Radix wallet to its original settings. All of your data and preferences will be erased. + Security Center status + Your wallet is recoverable + Your wallet is not recoverable + Your wallet is currently unrecoverable. If you do a factory reset now, you will never be able to access your Accounts and Personas again. + Once you’ve completed a factory reset, you will not be able to access your Accounts and Personas unless you do a full recovery. + Reset Wallet + Confirm factory reset + Return wallet to factory settings? You cannot undo this. + You need to write down a seed phrase + %s and %s are not recoverable. + %s and %s (plus some hidden) are not recoverable. + View and write down your seed phrase so Accounts and Personas are recoverable. + View and write down seed phrase + View and write down seed phrase + Personas are not recoverable + You need to write down a seed phrase + Problem with Configuration Backup + Your wallet is not recoverable + Automated Configuration Backup has stopped working. Check internet and cloud settings. + Automated Configuration Backup not working. Check internet connection and cloud settings. + Personas are not recoverable + Problem with Configuration Backup + Your wallet is not recoverable + Your wallet is not recoverable + Configuration Backup is not up to date. Create backup now. + To secure your wallet, turn on automated backups or manually export backup file. + Personas are not recoverable + Your wallet is not recoverable + Configuration Backup not up to date + Your wallet is not recoverable + Accounts and Personas not recoverable. Create Configuration Backup now. + Configuration Backup not up to date. Turn on automated backups or manually export backup file. + Personas are not recoverable + Configuration Backup not up to date + Recovery required + Recovery required + Enter seed phrase to recover control. + Enter seed phrase to recover control + Enter seed phrase to recover control + Recovery required + Recovery required + 1 account + %d accounts + 1 persona + %d personas - Connecting to %s - You’re connecting to %s for the first time - For this first connection, we’re going to run some quick automatic checks to verify the dApp. - Never show this screen again - Run all future verification checks automatically + dApp Request + You can proceed with this request after you create or restore your Radix Wallet. + Have you come from a genuine website? + Before you connect to %s, you might want to check: + Does the website address match what you\’re expecting? + If you came from a social media ad, is the website legitimate? + Switch back to your browser to continue diff --git a/app/src/main/res/values/constants.xml b/app/src/main/res/values/constants.xml index 1cbe003cbd..f7cdb4b534 100644 --- a/app/src/main/res/values/constants.xml +++ b/app/src/main/res/values/constants.xml @@ -7,4 +7,5 @@ Inspect Profile Mobile Connect Delay Seconds Inspect Cloud Backups + No email client installed diff --git a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt index 58922a28f2..5e37d44566 100644 --- a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt @@ -110,7 +110,7 @@ class IncomingRequestRepositoryTest { assertTrue(incomingRequestRepository.getAmountOfRequests() == 1) assert(currentRequest?.interactionId == interactionId1) incomingRequestRepository.addMobileConnectRequest(sampleIncomingRequest.copy(interactionId = interactionId2)) - incomingRequestRepository.requestDismissed(interactionId1) + incomingRequestRepository.requestDeferred(interactionId1) advanceUntilIdle() assert(currentRequest?.interactionId == interactionId2) assertTrue(incomingRequestRepository.getAmountOfRequests() == 2) From 67b9c8ad9d99c9cbdbd4aed837ba22551a08b168 Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Tue, 25 Jun 2024 13:12:39 +0200 Subject: [PATCH 06/12] downgrade okhttp to match the one in sargon --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 309f8afe27..f492ceed64 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ biometricKtx = "1.2.0-alpha05" coilCompose = "2.6.0" kotlinxSerialization = "1.7.0" sargon = "1.0.15-b7ddec52" -okhttpBom = "5.0.0-alpha.14" +okhttpBom = "5.0.0-alpha.12" retrofit = "2.11.0" retrofitKoltinxConverter = "1.0.0" timber = "5.0.1" From e6a77e132d0a0ab7a82aa5c6ec1d89d6e742eea0 Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Tue, 25 Jun 2024 14:12:12 +0200 Subject: [PATCH 07/12] update 'dismiss' request wording with defer --- .../wallet/android/data/dapp/IncomingRequestRepository.kt | 8 ++++---- .../dapp/authorized/login/DAppAuthorizedLoginViewModel.kt | 2 +- .../unauthorized/login/DAppUnauthorizedLoginViewModel.kt | 2 +- .../transaction/TransactionReviewViewModel.kt | 2 +- .../com/babylon/wallet/android/utils/AppEventBusImpl.kt | 2 +- .../android/data/dapp/IncomingRequestRepositoryTest.kt | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt index b9919b51ef..5f91983402 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt @@ -77,8 +77,8 @@ class IncomingRequestRepositoryImpl @Inject constructor( * - there is high priority screen in the queue, so the incoming request is added below it, * taking priority over requests currently in the queue * - there is no high priority screen: request is added at the top of queue and if there other request currently handled, - * we send a dismiss event for it so that UI can react and dismiss handling, without removing it from the queue. - * Dismissed request will be handled again when top priority one handling completes + * we send a defer event for it so that UI can react and defer handling, without removing it from the queue. + * Deferred request will be handled again when top priority one handling completes */ override suspend fun addMobileConnectRequest(incomingRequest: IncomingRequest) { mutex.withLock { @@ -87,8 +87,8 @@ class IncomingRequestRepositoryImpl @Inject constructor( val handlingPaused = requestQueue.contains(QueueItem.HighPriorityScreen) when { currentRequest != null -> { - Timber.d("🗂 Dismissing request with id ${currentRequest.interactionId}") - appEventBus.sendEvent(AppEvent.DismissRequestHandling(currentRequest.interactionId)) + Timber.d("🗂 Deferring request with id ${currentRequest.interactionId}") + appEventBus.sendEvent(AppEvent.DeferRequestHandling(currentRequest.interactionId)) } else -> { diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt index 450f2538e9..8b4d754dfb 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt @@ -94,7 +94,7 @@ class DAppAuthorizedLoginViewModel @Inject constructor( init { viewModelScope.launch { - appEventBus.events.filterIsInstance().collect { + appEventBus.events.filterIsInstance().collect { if (it.interactionId == args.interactionId) { sendEvent(Event.CloseLoginFlow) incomingRequestRepository.requestDeferred(args.interactionId) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt index d39137bc0e..cdaf8682bd 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt @@ -70,7 +70,7 @@ class DAppUnauthorizedLoginViewModel @Inject constructor( init { observeSigningState() viewModelScope.launch { - appEventBus.events.filterIsInstance().collect { + appEventBus.events.filterIsInstance().collect { if (it.interactionId == args.interactionId) { sendEvent(Event.CloseLoginFlow) incomingRequestRepository.requestDeferred(args.interactionId) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt index 829a6fcd10..cb286e0b5b 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt @@ -119,7 +119,7 @@ class TransactionReviewViewModel @Inject constructor( } } viewModelScope.launch { - appEventBus.events.filterIsInstance().collect { + appEventBus.events.filterIsInstance().collect { if (it.interactionId == args.interactionId) { sendEvent(Event.Dismiss) incomingRequestRepository.requestDeferred(args.interactionId) diff --git a/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt b/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt index 748014f235..1a0d64f164 100644 --- a/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt +++ b/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt @@ -33,7 +33,7 @@ sealed interface AppEvent { data object NPSSurveySubmitted : AppEvent data object SecureFolderWarning : AppEvent - data class DismissRequestHandling(val interactionId: String) : AppEvent + data class DeferRequestHandling(val interactionId: String) : AppEvent sealed interface AccessFactorSources : AppEvent { data class SelectedLedgerDevice(val ledgerFactorSource: FactorSource.Ledger) : AccessFactorSources diff --git a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt index 5e37d44566..e016096e76 100644 --- a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt @@ -114,7 +114,7 @@ class IncomingRequestRepositoryTest { advanceUntilIdle() assert(currentRequest?.interactionId == interactionId2) assertTrue(incomingRequestRepository.getAmountOfRequests() == 2) - coVerify(exactly = 1) { eventBus.sendEvent(AppEvent.DismissRequestHandling(interactionId1)) } + coVerify(exactly = 1) { eventBus.sendEvent(AppEvent.DeferRequestHandling(interactionId1)) } } @Test From d5536e94e654ac7c4f0a3a61cf62c18532994062 Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Tue, 25 Jun 2024 14:13:21 +0200 Subject: [PATCH 08/12] dismiss -> defer wording in tests --- .../wallet/android/data/dapp/IncomingRequestRepositoryTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt index e016096e76..e88a81f884 100644 --- a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt @@ -98,7 +98,7 @@ class IncomingRequestRepositoryTest { } @Test - fun `adding mobile connect request and dismissing current makes mobile request new current, while dismissed event stays in queue`() = runTest { + fun `adding mobile connect request and deferring current makes mobile request new current, while deferred event stays in queue`() = runTest { var currentRequest: IncomingMessage.IncomingRequest? = null val interactionId1 = UUID.randomUUID().toString() val interactionId2 = UUID.randomUUID().toString() From e0aa5481e33579b5942f17f8de3a8919215faeca Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Wed, 26 Jun 2024 11:18:54 +0200 Subject: [PATCH 09/12] update mobile connect request buffering and requests verification logic --- .../repository/BufferedDeepLinkRepository.kt | 25 --------- .../BufferedMobileConnectRequestRepository.kt | 19 +++++++ .../domain/usecases/VerifyDAppUseCase.kt | 10 +++- .../deeplink/ProcessDeepLinkUseCase.kt | 22 ++++---- .../deriveaccounts/DeriveAccountsNavGraph.kt | 2 + .../DerivePublicKeyNavGraph.kt | 2 + .../login/DAppAuthorizedLoginViewModel.kt | 14 +---- .../login/DAppUnauthorizedLoginViewModel.kt | 14 +---- .../presentation/main/MainViewModel.kt | 54 +++++++++++++------ .../presentation/wallet/WalletViewModel.kt | 7 +-- .../wallet/android/utils/AppEventBusImpl.kt | 1 + .../BufferedDeepLinkRepositoryTest.kt | 31 ----------- ...feredMobileConnectRequestRepositoryTest.kt | 26 +++++++++ .../presentation/WalletViewModelTest.kt | 9 ++-- .../login/DAppAuthorizedLoginViewModelTest.kt | 1 - 15 files changed, 114 insertions(+), 123 deletions(-) delete mode 100644 app/src/main/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepository.kt create mode 100644 app/src/main/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepository.kt delete mode 100644 app/src/test/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepositoryTest.kt create mode 100644 app/src/test/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepositoryTest.kt diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepository.kt deleted file mode 100644 index 21c4ba1fcb..0000000000 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepository.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.babylon.wallet.android.data.repository - -import com.babylon.wallet.android.data.dapp.IncomingRequestRepository -import com.babylon.wallet.android.domain.model.IncomingMessage -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class BufferedDeepLinkRepository @Inject constructor( - private val incomingRequestRepository: IncomingRequestRepository, -) { - - private var bufferedRequest: IncomingMessage.IncomingRequest? = null - - fun setBufferedRequest(request: IncomingMessage.IncomingRequest) { - bufferedRequest = request - } - - suspend fun processBufferedRequest() { - bufferedRequest?.let { - incomingRequestRepository.addMobileConnectRequest(it) - bufferedRequest = null - } - } -} diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepository.kt new file mode 100644 index 0000000000..72d66ea79e --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepository.kt @@ -0,0 +1,19 @@ +package com.babylon.wallet.android.data.repository + +import com.babylon.wallet.android.domain.model.IncomingMessage +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class BufferedMobileConnectRequestRepository @Inject constructor() { + + private var bufferedRequest: IncomingMessage.IncomingRequest? = null + + fun setBufferedRequest(request: IncomingMessage.IncomingRequest) { + bufferedRequest = request + } + + fun getBufferedRequest(): IncomingMessage.IncomingRequest? { + return bufferedRequest?.also { bufferedRequest = null } + } +} diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/VerifyDAppUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/VerifyDAppUseCase.kt index bdb2b9b108..745fbbba78 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/VerifyDAppUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/VerifyDAppUseCase.kt @@ -12,6 +12,7 @@ import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.DappWalletInteractionErrorType import com.radixdlt.sargon.extensions.init import rdx.works.core.domain.DApp +import rdx.works.core.sargon.currentGateway import rdx.works.core.then import rdx.works.profile.domain.GetProfileUseCase import javax.inject.Inject @@ -24,6 +25,14 @@ class VerifyDAppUseCase @Inject constructor( ) { suspend operator fun invoke(request: IncomingRequest): Result { + val networkId = getProfileUseCase().currentGateway.network.id + if (networkId != request.metadata.networkId) { + respondToIncomingRequestUseCase.respondWithFailure( + request = request, + error = DappWalletInteractionErrorType.INVALID_REQUEST + ) + return Result.failure(RadixWalletException.DappRequestException.WrongNetwork(networkId, request.metadata.networkId)) + } val dAppDefinitionAddress = runCatching { AccountAddress.init(request.metadata.dAppDefinitionAddress) }.getOrElse { respondToIncomingRequestUseCase.respondWithFailure( request = request, @@ -31,7 +40,6 @@ class VerifyDAppUseCase @Inject constructor( ) return Result.failure(RadixWalletException.DappRequestException.InvalidRequest) } - val developerMode = getProfileUseCase().appPreferences.security.isDeveloperModeEnabled return if (developerMode) { Result.success(true) diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt index 51e2588e10..3ddddf96a7 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt @@ -1,8 +1,7 @@ package com.babylon.wallet.android.domain.usecases.deeplink -import com.babylon.wallet.android.data.dapp.IncomingRequestRepository import com.babylon.wallet.android.data.dapp.model.toDomainModel -import com.babylon.wallet.android.data.repository.BufferedDeepLinkRepository +import com.babylon.wallet.android.data.repository.BufferedMobileConnectRequestRepository import com.babylon.wallet.android.domain.model.IncomingMessage import com.radixdlt.sargon.RadixConnectMobile import rdx.works.profile.domain.GetProfileUseCase @@ -11,9 +10,8 @@ import javax.inject.Inject class ProcessDeepLinkUseCase @Inject constructor( private val radixConnectMobile: RadixConnectMobile, - private val incomingRequestRepository: IncomingRequestRepository, private val getProfileUseCase: GetProfileUseCase, - private val bufferedDeepLinkRepository: BufferedDeepLinkRepository + private val bufferedMobileConnectRequestRepository: BufferedMobileConnectRequestRepository ) { suspend operator fun invoke(deepLink: String): Result { @@ -26,20 +24,18 @@ class ProcessDeepLinkUseCase @Inject constructor( originVerificationUrl = if (sessionRequest.originRequiresValidation) sessionRequest.origin else null ) ).getOrThrow() - if (profileInitialized) { - incomingRequestRepository.addMobileConnectRequest(request) - DeepLinkProcessingResult.PROCESSED - } else { - bufferedDeepLinkRepository.setBufferedRequest(request) - DeepLinkProcessingResult.BUFFERED + if (!profileInitialized) { + bufferedMobileConnectRequestRepository.setBufferedRequest(request) + return Result.success(DeepLinkProcessingResult.Buffered) } + DeepLinkProcessingResult.Processed(request) }.onFailure { Timber.d("Failed to parse deep link: $deepLink. Error: ${it.message}") } } } -enum class DeepLinkProcessingResult { - PROCESSED, - BUFFERED +sealed interface DeepLinkProcessingResult { + data object Buffered : DeepLinkProcessingResult + data class Processed(val request: IncomingMessage.IncomingRequest) : DeepLinkProcessingResult } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/accessfactorsources/deriveaccounts/DeriveAccountsNavGraph.kt b/app/src/main/java/com/babylon/wallet/android/presentation/accessfactorsources/deriveaccounts/DeriveAccountsNavGraph.kt index 3870c077cb..84a7e819fb 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/accessfactorsources/deriveaccounts/DeriveAccountsNavGraph.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/accessfactorsources/deriveaccounts/DeriveAccountsNavGraph.kt @@ -5,6 +5,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.dialog +import com.babylon.wallet.android.presentation.navigation.markAsHighPriority fun NavController.deriveAccounts() { navigate("derive_accounts_bottom_sheet") @@ -13,6 +14,7 @@ fun NavController.deriveAccounts() { fun NavGraphBuilder.deriveAccounts( onDismiss: () -> Unit ) { + markAsHighPriority("derive_accounts_bottom_sheet") dialog( route = "derive_accounts_bottom_sheet", dialogProperties = DialogProperties(usePlatformDefaultWidth = false) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/accessfactorsources/derivepublickey/DerivePublicKeyNavGraph.kt b/app/src/main/java/com/babylon/wallet/android/presentation/accessfactorsources/derivepublickey/DerivePublicKeyNavGraph.kt index b6c87a90b6..f3ba812476 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/accessfactorsources/derivepublickey/DerivePublicKeyNavGraph.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/accessfactorsources/derivepublickey/DerivePublicKeyNavGraph.kt @@ -5,6 +5,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.dialog +import com.babylon.wallet.android.presentation.navigation.markAsHighPriority fun NavController.derivePublicKey() { navigate("derive_public_key_bottom_sheet") @@ -13,6 +14,7 @@ fun NavController.derivePublicKey() { fun NavGraphBuilder.derivePublicKey( onDismiss: () -> Unit ) { + markAsHighPriority("derive_public_key_bottom_sheet") dialog( route = "derive_public_key_bottom_sheet", dialogProperties = DialogProperties(usePlatformDefaultWidth = false) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt index 8b4d754dfb..88c935d864 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/authorized/login/DAppAuthorizedLoginViewModel.kt @@ -63,7 +63,6 @@ import rdx.works.core.sargon.updateDAppAuthorizedPersonaSharedAccounts import rdx.works.profile.data.repository.DAppConnectionRepository import rdx.works.profile.domain.GetProfileUseCase import rdx.works.profile.domain.ProfileException -import rdx.works.profile.domain.gateway.GetCurrentGatewayUseCase import javax.inject.Inject @HiltViewModel @@ -74,7 +73,6 @@ class DAppAuthorizedLoginViewModel @Inject constructor( private val respondToIncomingRequestUseCase: RespondToIncomingRequestUseCase, private val dAppConnectionRepository: DAppConnectionRepository, private val getProfileUseCase: GetProfileUseCase, - private val getCurrentGatewayUseCase: GetCurrentGatewayUseCase, private val stateRepository: StateRepository, private val incomingRequestRepository: IncomingRequestRepository, private val buildAuthorizedDappResponseUseCase: BuildAuthorizedDappResponseUseCase @@ -110,16 +108,6 @@ class DAppAuthorizedLoginViewModel @Inject constructor( } else { request = requestToHandle } - val currentNetworkId = getCurrentGatewayUseCase().network.id - if (currentNetworkId != request.requestMetadata.networkId) { - handleRequestError( - RadixWalletException.DappRequestException.WrongNetwork( - currentNetworkId, - request.requestMetadata.networkId - ) - ) - return@launch - } val dAppDefinitionAddress = runCatching { AccountAddress.init(request.requestMetadata.dAppDefinitionAddress) }.getOrNull() if (!request.isValidRequest() || dAppDefinitionAddress == null) { handleRequestError(RadixWalletException.DappRequestException.InvalidRequest) @@ -701,7 +689,7 @@ class DAppAuthorizedLoginViewModel @Inject constructor( mutex.withLock { editedDapp?.let { dAppConnectionRepository.updateOrCreateAuthorizedDApp(it) } } - incomingRequestRepository.requestHandled(request.interactionId.toString()) + incomingRequestRepository.requestHandled(request.interactionId) sendEvent(Event.LoginFlowCompleted) } else { buildAuthorizedDappResponseUseCase( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt index cdaf8682bd..7dbadf6552 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/dapp/unauthorized/login/DAppUnauthorizedLoginViewModel.kt @@ -46,7 +46,6 @@ import rdx.works.core.sargon.fields import rdx.works.core.sargon.toPersonaData import rdx.works.profile.domain.GetProfileUseCase import rdx.works.profile.domain.ProfileException -import rdx.works.profile.domain.gateway.GetCurrentGatewayUseCase import javax.inject.Inject @HiltViewModel @@ -56,7 +55,6 @@ class DAppUnauthorizedLoginViewModel @Inject constructor( private val respondToIncomingRequestUseCase: RespondToIncomingRequestUseCase, private val appEventBus: AppEventBus, private val getProfileUseCase: GetProfileUseCase, - private val getCurrentGatewayUseCase: GetCurrentGatewayUseCase, private val stateRepository: StateRepository, private val incomingRequestRepository: IncomingRequestRepository, private val buildUnauthorizedDappResponseUseCase: BuildUnauthorizedDappResponseUseCase @@ -87,16 +85,6 @@ class DAppUnauthorizedLoginViewModel @Inject constructor( } else { request = requestToHandle } - val currentNetworkId = getCurrentGatewayUseCase().network.id - if (currentNetworkId != request.requestMetadata.networkId) { - handleRequestError( - RadixWalletException.DappRequestException.WrongNetwork( - currentNetworkId, - request.requestMetadata.networkId - ) - ) - return@launch - } val dAppDefinitionAddress = runCatching { AccountAddress.init(request.metadata.dAppDefinitionAddress) }.getOrNull() if (!request.isValidRequest() || dAppDefinitionAddress == null) { handleRequestError(RadixWalletException.DappRequestException.InvalidRequest) @@ -271,7 +259,7 @@ class DAppUnauthorizedLoginViewModel @Inject constructor( if (!request.isInternal) { appEventBus.sendEvent( AppEvent.Status.DappInteraction( - requestId = request.interactionId.toString(), + requestId = request.interactionId, dAppName = state.value.dapp?.name, isMobileConnect = result is IncomingRequestResponse.SuccessRadixMobileConnect ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt index 493fc6273d..d4c009ba7a 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt @@ -4,6 +4,7 @@ import android.net.Uri import androidx.lifecycle.viewModelScope import com.babylon.wallet.android.data.dapp.IncomingRequestRepository import com.babylon.wallet.android.data.dapp.PeerdroidClient +import com.babylon.wallet.android.data.repository.BufferedMobileConnectRequestRepository import com.babylon.wallet.android.data.repository.p2plink.P2PLinksRepository import com.babylon.wallet.android.domain.RadixWalletException import com.babylon.wallet.android.domain.model.IncomingMessage.IncomingRequest @@ -71,7 +72,8 @@ class MainViewModel @Inject constructor( private val checkEntitiesCreatedWithOlympiaUseCase: CheckEntitiesCreatedWithOlympiaUseCase, private val observeAccountsAndSyncWithConnectorExtensionUseCase: ObserveAccountsAndSyncWithConnectorExtensionUseCase, private val cloudBackupErrorStream: CloudBackupErrorStream, - private val processDeepLinkUseCase: ProcessDeepLinkUseCase + private val processDeepLinkUseCase: ProcessDeepLinkUseCase, + private val bufferedMobileConnectRequestRepository: BufferedMobileConnectRequestRepository ) : StateViewModel(), OneOffEventHandler by OneOffEventHandlerImpl() { private var verifyingDappRequestJob: Job? = null @@ -149,10 +151,20 @@ class MainViewModel @Inject constructor( }.collect() } handleAllIncomingRequests() - viewModelScope.launch { observeAccountsAndSyncWithConnectorExtensionUseCase() } + processBufferedDeepLinkRequest() + } + + private fun processBufferedDeepLinkRequest() { + viewModelScope.launch { + appEventBus.events.filterIsInstance().collect { + bufferedMobileConnectRequestRepository.getBufferedRequest()?.let { request -> + verifyIncomingRequest(request) + } + } + } } override fun initialState(): MainUiState { @@ -249,13 +261,19 @@ class MainViewModel @Inject constructor( fun handleDeepLink(deepLink: Uri) { viewModelScope.launch { processDeepLinkUseCase(deepLink.toString()).onSuccess { result -> - if (result == DeepLinkProcessingResult.BUFFERED) { - _state.update { - it.copy(showMobileConnectWarning = true) + when (result) { + is DeepLinkProcessingResult.Processed -> { + verifyIncomingRequest(result.request) + } + + DeepLinkProcessingResult.Buffered -> { + _state.update { + it.copy(showMobileConnectWarning = true) + } } } - }.onFailure { - Timber.d(it) + }.onFailure { error -> + Timber.d(error) } } } @@ -268,16 +286,22 @@ class MainViewModel @Inject constructor( private fun verifyIncomingRequest(request: IncomingRequest) { verifyingDappRequestJob = viewModelScope.launch { - if (request.isMobileConnectRequest) { - incomingRequestRepository.add(request) - } else { - verifyDappUseCase(request).onSuccess { verified -> - if (verified) { + verifyDappUseCase(request).onSuccess { verified -> + if (verified) { + if (request.isMobileConnectRequest) { + incomingRequestRepository.addMobileConnectRequest(request) + } else { incomingRequestRepository.add(request) } - }.onFailure { - _state.update { state -> - state.copy(dappRequestFailure = RadixWalletException.DappRequestException.InvalidRequest) + } + }.onFailure { error -> + if (error is RadixWalletException.DappRequestException) { + _state.update { + it.copy(dappRequestFailure = error) + } + } else { + _state.update { + it.copy(dappRequestFailure = RadixWalletException.DappRequestException.InvalidRequest) } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletViewModel.kt index be7170d9d2..5309e2a9db 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletViewModel.kt @@ -4,7 +4,6 @@ import android.annotation.SuppressLint import androidx.lifecycle.viewModelScope import com.babylon.wallet.android.NPSSurveyState import com.babylon.wallet.android.NPSSurveyStateObserver -import com.babylon.wallet.android.data.repository.BufferedDeepLinkRepository import com.babylon.wallet.android.data.repository.p2plink.P2PLinksRepository import com.babylon.wallet.android.data.repository.tokenprice.FiatPriceRepository import com.babylon.wallet.android.di.coroutines.DefaultDispatcher @@ -84,7 +83,6 @@ class WalletViewModel @Inject constructor( private val npsSurveyStateObserver: NPSSurveyStateObserver, private val p2PLinksRepository: P2PLinksRepository, private val checkMigrationToNewBackupSystemUseCase: CheckMigrationToNewBackupSystemUseCase, - private val bufferedDeepLinkRepository: BufferedDeepLinkRepository, @DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher ) : StateViewModel(), OneOffEventHandler by OneOffEventHandlerImpl() { @@ -113,7 +111,6 @@ class WalletViewModel @Inject constructor( return@launch } } - processBufferedDeepLinkRequest() observePrompts() observeAccounts() observeGlobalAppEvents() @@ -122,9 +119,9 @@ class WalletViewModel @Inject constructor( checkForOldBackupSystemToMigrate() } - private fun processBufferedDeepLinkRequest() { + fun processBufferedDeepLinkRequest() { viewModelScope.launch { - bufferedDeepLinkRepository.processBufferedRequest() + appEventBus.sendEvent(AppEvent.ProcessBufferedDeepLinkRequest) } } diff --git a/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt b/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt index 1a0d64f164..e3fe5b093c 100644 --- a/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt +++ b/app/src/main/java/com/babylon/wallet/android/utils/AppEventBusImpl.kt @@ -34,6 +34,7 @@ sealed interface AppEvent { data object SecureFolderWarning : AppEvent data class DeferRequestHandling(val interactionId: String) : AppEvent + data object ProcessBufferedDeepLinkRequest : AppEvent sealed interface AccessFactorSources : AppEvent { data class SelectedLedgerDevice(val ledgerFactorSource: FactorSource.Ledger) : AccessFactorSources diff --git a/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepositoryTest.kt deleted file mode 100644 index e09cc313bd..0000000000 --- a/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedDeepLinkRepositoryTest.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.babylon.wallet.android.data.repository - -import com.babylon.wallet.android.data.dapp.IncomingRequestRepository -import com.babylon.wallet.android.domain.model.IncomingMessage -import io.mockk.coEvery -import io.mockk.coVerify -import io.mockk.mockk -import kotlinx.coroutines.test.runTest -import org.junit.Before -import org.junit.Test - -class BufferedDeepLinkRepositoryTest { - - private lateinit var bufferedDeepLinkRepository: BufferedDeepLinkRepository - private val incomingRequestRepository = mockk() - - @Before - fun setup() { - bufferedDeepLinkRepository = BufferedDeepLinkRepository(incomingRequestRepository) - coEvery { incomingRequestRepository.addMobileConnectRequest(any()) } returns Unit - } - - @Test - fun `add buffered request to incoming request repository`() = runTest { - val request = mockk() - bufferedDeepLinkRepository.setBufferedRequest(request) - bufferedDeepLinkRepository.processBufferedRequest() - coVerify(exactly = 1) { incomingRequestRepository.addMobileConnectRequest(request) } - } - -} \ No newline at end of file diff --git a/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepositoryTest.kt new file mode 100644 index 0000000000..3ea2513b76 --- /dev/null +++ b/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepositoryTest.kt @@ -0,0 +1,26 @@ +package com.babylon.wallet.android.data.repository + +import com.babylon.wallet.android.domain.model.IncomingMessage +import io.mockk.mockk +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test + +class BufferedMobileConnectRequestRepositoryTest { + + private lateinit var bufferedMobileConnectRequestRepository: BufferedMobileConnectRequestRepository + + @Before + fun setup() { + bufferedMobileConnectRequestRepository = BufferedMobileConnectRequestRepository() + } + + @Test + fun `reading buffered request clears it`() = runTest { + val request = mockk() + bufferedMobileConnectRequestRepository.setBufferedRequest(request) + bufferedMobileConnectRequestRepository.getBufferedRequest() + assert(bufferedMobileConnectRequestRepository.getBufferedRequest() == null) + } + +} \ No newline at end of file diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt index e64634ef0b..e3cdd2de2b 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt @@ -3,7 +3,7 @@ package com.babylon.wallet.android.presentation import app.cash.turbine.test import com.babylon.wallet.android.NPSSurveyState import com.babylon.wallet.android.NPSSurveyStateObserver -import com.babylon.wallet.android.data.repository.BufferedDeepLinkRepository +import com.babylon.wallet.android.data.repository.BufferedMobileConnectRequestRepository import com.babylon.wallet.android.data.repository.p2plink.P2PLinksRepository import com.babylon.wallet.android.domain.model.assets.AccountWithAssets import com.babylon.wallet.android.domain.usecases.GetEntitiesWithSecurityPromptUseCase @@ -17,10 +17,8 @@ import com.radixdlt.sargon.Profile import com.radixdlt.sargon.extensions.asIdentifiable import com.radixdlt.sargon.extensions.toDecimal192 import com.radixdlt.sargon.samples.sample -import io.mockk.Runs import io.mockk.coEvery import io.mockk.every -import io.mockk.just import io.mockk.mockk import junit.framework.TestCase.assertEquals import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -63,7 +61,7 @@ class WalletViewModelTest : StateViewModelTest() { private val preferencesManager = mockk() private val appEventBus = mockk() private val testDispatcher = StandardTestDispatcher() - private val bufferedDeepLinkRepository = mockk() + private val bufferedMobileConnectRequestRepository = mockk() private val p2PLinksRepository = mockk() private val sampleProfile = Profile.sample() @@ -87,13 +85,12 @@ class WalletViewModelTest : StateViewModelTest() { npsSurveyStateObserver, p2PLinksRepository, checkMigrationToNewBackupSystemUseCase, - bufferedDeepLinkRepository, testDispatcher, ) override fun setUp() { super.setUp() - coEvery { bufferedDeepLinkRepository.processBufferedRequest() } just Runs + coEvery { bufferedMobileConnectRequestRepository.getBufferedRequest() } returns null coEvery { ensureBabylonFactorSourceExistUseCase.babylonFactorSourceExist() } returns true every { getAccountsForSecurityPromptUseCase() } returns flow { emit(emptyList()) } every { getBackupStateUseCase() } returns flowOf( diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt index ce54a4bb52..c53a311008 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt @@ -192,7 +192,6 @@ class DAppAuthorizedLoginViewModelTest : StateViewModelTest Date: Wed, 26 Jun 2024 11:22:05 +0200 Subject: [PATCH 10/12] push missing code --- .../wallet/android/presentation/wallet/WalletScreen.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletScreen.kt index 420cef4886..36129b451b 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/wallet/WalletScreen.kt @@ -29,6 +29,7 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -104,6 +105,13 @@ fun WalletScreen( onRadixBannerDismiss = viewModel::onRadixBannerDismiss ) + val lifecycleState by LocalLifecycleOwner.current.lifecycle.currentStateFlow.collectAsState() + LaunchedEffect(lifecycleState) { + if (lifecycleState == Lifecycle.State.RESUMED) { + viewModel.processBufferedDeepLinkRequest() + } + } + LaunchedEffect(Unit) { viewModel.babylonFactorSourceDoesNotExistEvent.collect { viewModel.createBabylonFactorSource { context.biometricAuthenticateSuspend() } From b0c2275cb92a9d21359874d9f23f4d1b58de745c Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Thu, 27 Jun 2024 10:33:01 +0200 Subject: [PATCH 11/12] pr review changes --- .../data/dapp/IncomingRequestRepository.kt | 4 +- .../domain/usecases/VerifyDAppUseCase.kt | 7 +++- .../presentation/main/MainViewModel.kt | 2 +- .../submit/TransactionSubmitDelegate.kt | 42 +++++++++---------- .../dapp/IncomingRequestRepositoryTest.kt | 4 +- 5 files changed, 31 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt index 5f91983402..44504b032e 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt @@ -19,7 +19,7 @@ interface IncomingRequestRepository { suspend fun add(incomingRequest: IncomingRequest) - suspend fun addMobileConnectRequest(incomingRequest: IncomingRequest) + suspend fun addPriorityRequest(incomingRequest: IncomingRequest) suspend fun requestHandled(requestId: String) @@ -80,7 +80,7 @@ class IncomingRequestRepositoryImpl @Inject constructor( * we send a defer event for it so that UI can react and defer handling, without removing it from the queue. * Deferred request will be handled again when top priority one handling completes */ - override suspend fun addMobileConnectRequest(incomingRequest: IncomingRequest) { + override suspend fun addPriorityRequest(incomingRequest: IncomingRequest) { mutex.withLock { requestQueue.addFirst(QueueItem.RequestItem(incomingRequest)) val currentRequest = _currentRequestToHandle.value diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/VerifyDAppUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/VerifyDAppUseCase.kt index 745fbbba78..71d33202a2 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/VerifyDAppUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/VerifyDAppUseCase.kt @@ -31,7 +31,12 @@ class VerifyDAppUseCase @Inject constructor( request = request, error = DappWalletInteractionErrorType.INVALID_REQUEST ) - return Result.failure(RadixWalletException.DappRequestException.WrongNetwork(networkId, request.metadata.networkId)) + return Result.failure( + RadixWalletException.DappRequestException.WrongNetwork( + currentNetworkId = networkId, + requestNetworkId = request.metadata.networkId + ) + ) } val dAppDefinitionAddress = runCatching { AccountAddress.init(request.metadata.dAppDefinitionAddress) }.getOrElse { respondToIncomingRequestUseCase.respondWithFailure( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt index d4c009ba7a..b239c9a245 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt @@ -289,7 +289,7 @@ class MainViewModel @Inject constructor( verifyDappUseCase(request).onSuccess { verified -> if (verified) { if (request.isMobileConnectRequest) { - incomingRequestRepository.addMobileConnectRequest(request) + incomingRequestRepository.addPriorityRequest(request) } else { incomingRequestRepository.add(request) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/submit/TransactionSubmitDelegate.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/submit/TransactionSubmitDelegate.kt index a00cc5d20d..45932d5374 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/submit/TransactionSubmitDelegate.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/submit/TransactionSubmitDelegate.kt @@ -101,29 +101,27 @@ class TransactionSubmitDelegate @Inject constructor( suspend fun onDismiss( signTransactionUseCase: SignTransactionUseCase, exception: RadixWalletException.DappRequestException - ): Result { - return runCatching { - if (approvalJob == null) { - val request = _state.value.requestNonNull - if (!request.isInternal) { - respondToIncomingRequestUseCase.respondWithFailure( - request = request, - error = exception.ceError, - message = exception.getDappMessage() - ) - } - oneOffEventHandler?.sendEvent(Event.Dismiss) - incomingRequestRepository.requestHandled(request.interactionId) - } else if (_state.value.interactionState != null) { - approvalJob?.cancel() - approvalJob = null - signTransactionUseCase.cancelSigning() - _state.update { - it.copy(isSubmitting = false) - } - } else { - logger.d("Cannot dismiss transaction while is in progress") + ): Result = runCatching { + if (approvalJob == null) { + val request = _state.value.requestNonNull + if (!request.isInternal) { + respondToIncomingRequestUseCase.respondWithFailure( + request = request, + error = exception.ceError, + message = exception.getDappMessage() + ) + } + oneOffEventHandler?.sendEvent(Event.Dismiss) + incomingRequestRepository.requestHandled(request.interactionId) + } else if (_state.value.interactionState != null) { + approvalJob?.cancel() + approvalJob = null + signTransactionUseCase.cancelSigning() + _state.update { + it.copy(isSubmitting = false) } + } else { + logger.d("Cannot dismiss transaction while is in progress") } } diff --git a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt index e88a81f884..8da46ca29d 100644 --- a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt @@ -109,7 +109,7 @@ class IncomingRequestRepositoryTest { advanceUntilIdle() assertTrue(incomingRequestRepository.getAmountOfRequests() == 1) assert(currentRequest?.interactionId == interactionId1) - incomingRequestRepository.addMobileConnectRequest(sampleIncomingRequest.copy(interactionId = interactionId2)) + incomingRequestRepository.addPriorityRequest(sampleIncomingRequest.copy(interactionId = interactionId2)) incomingRequestRepository.requestDeferred(interactionId1) advanceUntilIdle() assert(currentRequest?.interactionId == interactionId2) @@ -130,7 +130,7 @@ class IncomingRequestRepositoryTest { advanceUntilIdle() assertTrue(incomingRequestRepository.getAmountOfRequests() == 1) assert(currentRequest?.interactionId == null) - incomingRequestRepository.addMobileConnectRequest(sampleIncomingRequest.copy(interactionId = interactionId2)) + incomingRequestRepository.addPriorityRequest(sampleIncomingRequest.copy(interactionId = interactionId2)) advanceUntilIdle() incomingRequestRepository.resumeIncomingRequests() advanceUntilIdle() From 6b03334de52e7d76c58e5f0de806e24e6029945b Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Thu, 27 Jun 2024 11:10:04 +0200 Subject: [PATCH 12/12] buffer request in incoming request repository --- .../data/dapp/IncomingRequestRepository.kt | 18 ++++++++ .../BufferedMobileConnectRequestRepository.kt | 19 -------- .../deeplink/ProcessDeepLinkUseCase.kt | 6 +-- .../presentation/main/MainViewModel.kt | 6 +-- .../dapp/IncomingRequestRepositoryTest.kt | 46 +++++++++++-------- ...feredMobileConnectRequestRepositoryTest.kt | 26 ----------- .../presentation/WalletViewModelTest.kt | 6 +-- 7 files changed, 54 insertions(+), 73 deletions(-) delete mode 100644 app/src/main/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepository.kt delete mode 100644 app/src/test/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepositoryTest.kt diff --git a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt index 44504b032e..112c9f7968 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepository.kt @@ -34,8 +34,13 @@ interface IncomingRequestRepository { fun getAmountOfRequests(): Int suspend fun requestDeferred(requestId: String) + + fun consumeBufferedRequest(): IncomingRequest? + + fun setBufferedRequest(request: IncomingRequest) } +@Suppress("TooManyFunctions") class IncomingRequestRepositoryImpl @Inject constructor( private val appEventBus: AppEventBus ) : IncomingRequestRepository { @@ -56,6 +61,19 @@ class IncomingRequestRepositoryImpl @Inject constructor( private val mutex = Mutex() + /** + * Request that can come in via deep link before wallet is setup. + */ + private var bufferedRequest: IncomingRequest? = null + + override fun setBufferedRequest(request: IncomingRequest) { + bufferedRequest = request + } + + override fun consumeBufferedRequest(): IncomingRequest? { + return bufferedRequest?.also { bufferedRequest = null } + } + override suspend fun add(incomingRequest: IncomingRequest) { mutex.withLock { val requestItem = QueueItem.RequestItem(incomingRequest) diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepository.kt deleted file mode 100644 index 72d66ea79e..0000000000 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepository.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.babylon.wallet.android.data.repository - -import com.babylon.wallet.android.domain.model.IncomingMessage -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class BufferedMobileConnectRequestRepository @Inject constructor() { - - private var bufferedRequest: IncomingMessage.IncomingRequest? = null - - fun setBufferedRequest(request: IncomingMessage.IncomingRequest) { - bufferedRequest = request - } - - fun getBufferedRequest(): IncomingMessage.IncomingRequest? { - return bufferedRequest?.also { bufferedRequest = null } - } -} diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt index 3ddddf96a7..af601bb1fd 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/deeplink/ProcessDeepLinkUseCase.kt @@ -1,7 +1,7 @@ package com.babylon.wallet.android.domain.usecases.deeplink +import com.babylon.wallet.android.data.dapp.IncomingRequestRepository import com.babylon.wallet.android.data.dapp.model.toDomainModel -import com.babylon.wallet.android.data.repository.BufferedMobileConnectRequestRepository import com.babylon.wallet.android.domain.model.IncomingMessage import com.radixdlt.sargon.RadixConnectMobile import rdx.works.profile.domain.GetProfileUseCase @@ -11,7 +11,7 @@ import javax.inject.Inject class ProcessDeepLinkUseCase @Inject constructor( private val radixConnectMobile: RadixConnectMobile, private val getProfileUseCase: GetProfileUseCase, - private val bufferedMobileConnectRequestRepository: BufferedMobileConnectRequestRepository + private val incomingRequestRepository: IncomingRequestRepository ) { suspend operator fun invoke(deepLink: String): Result { @@ -25,7 +25,7 @@ class ProcessDeepLinkUseCase @Inject constructor( ) ).getOrThrow() if (!profileInitialized) { - bufferedMobileConnectRequestRepository.setBufferedRequest(request) + incomingRequestRepository.setBufferedRequest(request) return Result.success(DeepLinkProcessingResult.Buffered) } DeepLinkProcessingResult.Processed(request) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt index b239c9a245..1ef3083078 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/main/MainViewModel.kt @@ -4,7 +4,6 @@ import android.net.Uri import androidx.lifecycle.viewModelScope import com.babylon.wallet.android.data.dapp.IncomingRequestRepository import com.babylon.wallet.android.data.dapp.PeerdroidClient -import com.babylon.wallet.android.data.repository.BufferedMobileConnectRequestRepository import com.babylon.wallet.android.data.repository.p2plink.P2PLinksRepository import com.babylon.wallet.android.domain.RadixWalletException import com.babylon.wallet.android.domain.model.IncomingMessage.IncomingRequest @@ -72,8 +71,7 @@ class MainViewModel @Inject constructor( private val checkEntitiesCreatedWithOlympiaUseCase: CheckEntitiesCreatedWithOlympiaUseCase, private val observeAccountsAndSyncWithConnectorExtensionUseCase: ObserveAccountsAndSyncWithConnectorExtensionUseCase, private val cloudBackupErrorStream: CloudBackupErrorStream, - private val processDeepLinkUseCase: ProcessDeepLinkUseCase, - private val bufferedMobileConnectRequestRepository: BufferedMobileConnectRequestRepository + private val processDeepLinkUseCase: ProcessDeepLinkUseCase ) : StateViewModel(), OneOffEventHandler by OneOffEventHandlerImpl() { private var verifyingDappRequestJob: Job? = null @@ -160,7 +158,7 @@ class MainViewModel @Inject constructor( private fun processBufferedDeepLinkRequest() { viewModelScope.launch { appEventBus.events.filterIsInstance().collect { - bufferedMobileConnectRequestRepository.getBufferedRequest()?.let { request -> + incomingRequestRepository.consumeBufferedRequest()?.let { request -> verifyIncomingRequest(request) } } diff --git a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt index 8da46ca29d..264c2b61ee 100644 --- a/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/data/dapp/IncomingRequestRepositoryTest.kt @@ -5,6 +5,7 @@ import com.babylon.wallet.android.utils.AppEvent import com.babylon.wallet.android.utils.AppEventBusImpl import com.radixdlt.sargon.NetworkId import io.mockk.coVerify +import io.mockk.mockk import io.mockk.spyk import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DelicateCoroutinesApi @@ -98,24 +99,25 @@ class IncomingRequestRepositoryTest { } @Test - fun `adding mobile connect request and deferring current makes mobile request new current, while deferred event stays in queue`() = runTest { - var currentRequest: IncomingMessage.IncomingRequest? = null - val interactionId1 = UUID.randomUUID().toString() - val interactionId2 = UUID.randomUUID().toString() - incomingRequestRepository.currentRequestToHandle - .onEach { currentRequest = it } - .launchIn(CoroutineScope(UnconfinedTestDispatcher(testScheduler))) - incomingRequestRepository.add(incomingRequest = sampleIncomingRequest.copy(interactionId = interactionId1)) - advanceUntilIdle() - assertTrue(incomingRequestRepository.getAmountOfRequests() == 1) - assert(currentRequest?.interactionId == interactionId1) - incomingRequestRepository.addPriorityRequest(sampleIncomingRequest.copy(interactionId = interactionId2)) - incomingRequestRepository.requestDeferred(interactionId1) - advanceUntilIdle() - assert(currentRequest?.interactionId == interactionId2) - assertTrue(incomingRequestRepository.getAmountOfRequests() == 2) - coVerify(exactly = 1) { eventBus.sendEvent(AppEvent.DeferRequestHandling(interactionId1)) } - } + fun `adding mobile connect request and deferring current makes mobile request new current, while deferred event stays in queue`() = + runTest { + var currentRequest: IncomingMessage.IncomingRequest? = null + val interactionId1 = UUID.randomUUID().toString() + val interactionId2 = UUID.randomUUID().toString() + incomingRequestRepository.currentRequestToHandle + .onEach { currentRequest = it } + .launchIn(CoroutineScope(UnconfinedTestDispatcher(testScheduler))) + incomingRequestRepository.add(incomingRequest = sampleIncomingRequest.copy(interactionId = interactionId1)) + advanceUntilIdle() + assertTrue(incomingRequestRepository.getAmountOfRequests() == 1) + assert(currentRequest?.interactionId == interactionId1) + incomingRequestRepository.addPriorityRequest(sampleIncomingRequest.copy(interactionId = interactionId2)) + incomingRequestRepository.requestDeferred(interactionId1) + advanceUntilIdle() + assert(currentRequest?.interactionId == interactionId2) + assertTrue(incomingRequestRepository.getAmountOfRequests() == 2) + coVerify(exactly = 1) { eventBus.sendEvent(AppEvent.DeferRequestHandling(interactionId1)) } + } @Test fun `addFirst inserts item at 2nd position when there is high priority screen`() = runTest { @@ -137,4 +139,12 @@ class IncomingRequestRepositoryTest { assert(currentRequest?.interactionId == interactionId2) assertTrue(incomingRequestRepository.getAmountOfRequests() == 2) } + + @Test + fun `reading buffered request clears it`() = runTest { + val request = mockk() + incomingRequestRepository.setBufferedRequest(request) + assert(incomingRequestRepository.consumeBufferedRequest() != null) + assert(incomingRequestRepository.consumeBufferedRequest() == null) + } } diff --git a/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepositoryTest.kt b/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepositoryTest.kt deleted file mode 100644 index 3ea2513b76..0000000000 --- a/app/src/test/java/com/babylon/wallet/android/data/repository/BufferedMobileConnectRequestRepositoryTest.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.babylon.wallet.android.data.repository - -import com.babylon.wallet.android.domain.model.IncomingMessage -import io.mockk.mockk -import kotlinx.coroutines.test.runTest -import org.junit.Before -import org.junit.Test - -class BufferedMobileConnectRequestRepositoryTest { - - private lateinit var bufferedMobileConnectRequestRepository: BufferedMobileConnectRequestRepository - - @Before - fun setup() { - bufferedMobileConnectRequestRepository = BufferedMobileConnectRequestRepository() - } - - @Test - fun `reading buffered request clears it`() = runTest { - val request = mockk() - bufferedMobileConnectRequestRepository.setBufferedRequest(request) - bufferedMobileConnectRequestRepository.getBufferedRequest() - assert(bufferedMobileConnectRequestRepository.getBufferedRequest() == null) - } - -} \ No newline at end of file diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt index e3cdd2de2b..a8b684fad5 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/WalletViewModelTest.kt @@ -3,7 +3,7 @@ package com.babylon.wallet.android.presentation import app.cash.turbine.test import com.babylon.wallet.android.NPSSurveyState import com.babylon.wallet.android.NPSSurveyStateObserver -import com.babylon.wallet.android.data.repository.BufferedMobileConnectRequestRepository +import com.babylon.wallet.android.data.dapp.IncomingRequestRepository import com.babylon.wallet.android.data.repository.p2plink.P2PLinksRepository import com.babylon.wallet.android.domain.model.assets.AccountWithAssets import com.babylon.wallet.android.domain.usecases.GetEntitiesWithSecurityPromptUseCase @@ -61,7 +61,7 @@ class WalletViewModelTest : StateViewModelTest() { private val preferencesManager = mockk() private val appEventBus = mockk() private val testDispatcher = StandardTestDispatcher() - private val bufferedMobileConnectRequestRepository = mockk() + private val incomingRequestRepository = mockk() private val p2PLinksRepository = mockk() private val sampleProfile = Profile.sample() @@ -90,7 +90,7 @@ class WalletViewModelTest : StateViewModelTest() { override fun setUp() { super.setUp() - coEvery { bufferedMobileConnectRequestRepository.getBufferedRequest() } returns null + coEvery { incomingRequestRepository.consumeBufferedRequest() } returns null coEvery { ensureBabylonFactorSourceExistUseCase.babylonFactorSourceExist() } returns true every { getAccountsForSecurityPromptUseCase() } returns flow { emit(emptyList()) } every { getBackupStateUseCase() } returns flowOf(