Updated on 2026-08-14
This commit is contained in:
parent
410253dc5a
commit
3c3f35aeb6
26 changed files with 589 additions and 63 deletions
|
|
@ -193,7 +193,7 @@ internal class LegacyScanProcessor @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod", "MagicNumber")
|
||||
@Suppress("LongMethod", "LongParameterList", "MagicNumber")
|
||||
private suspend inline fun onScanSuccess(
|
||||
scanResponse: ScanResponse,
|
||||
crossinline onProgressStateChange: suspend (showProgress: Boolean) -> Unit,
|
||||
|
|
|
|||
|
|
@ -237,14 +237,19 @@ internal class ChildFactory @Inject constructor(
|
|||
context = context,
|
||||
params = OnboardingEntryComponent.Params(
|
||||
scanResponse = route.scanResponse,
|
||||
mode = when (route.mode) {
|
||||
AppRoute.Onboarding.Mode.Onboarding -> OnboardingEntryComponent.Mode.Onboarding
|
||||
AppRoute.Onboarding.Mode.AddBackupWallet1 -> OnboardingEntryComponent.Mode.AddBackupWallet1
|
||||
AppRoute.Onboarding.Mode.WelcomeOnlyTwin -> OnboardingEntryComponent.Mode.WelcomeOnlyTwin
|
||||
AppRoute.Onboarding.Mode.RecreateWalletTwin ->
|
||||
mode = when (val mode = route.mode) {
|
||||
is AppRoute.Onboarding.Mode.Onboarding ->
|
||||
OnboardingEntryComponent.Mode.Onboarding
|
||||
is AppRoute.Onboarding.Mode.AddBackupWallet1 ->
|
||||
OnboardingEntryComponent.Mode.AddBackupWallet1
|
||||
is AppRoute.Onboarding.Mode.WelcomeOnlyTwin ->
|
||||
OnboardingEntryComponent.Mode.WelcomeOnlyTwin
|
||||
is AppRoute.Onboarding.Mode.RecreateWalletTwin ->
|
||||
OnboardingEntryComponent.Mode.RecreateWalletTwin
|
||||
AppRoute.Onboarding.Mode.ContinueFinalize ->
|
||||
is AppRoute.Onboarding.Mode.ContinueFinalize ->
|
||||
OnboardingEntryComponent.Mode.ContinueFinalize
|
||||
is AppRoute.Onboarding.Mode.UpgradeHotWallet ->
|
||||
OnboardingEntryComponent.Mode.UpgradeHotWallet(mode.userWalletId)
|
||||
},
|
||||
),
|
||||
componentFactory = onboardingEntryComponentFactory,
|
||||
|
|
|
|||
|
|
@ -274,14 +274,16 @@ sealed class AppRoute(val path: String) : Route {
|
|||
data class Onboarding(
|
||||
val scanResponse: ScanResponse,
|
||||
val mode: Mode = Mode.Onboarding,
|
||||
) : AppRoute(path = "/onboarding_v2/${mode.name}") {
|
||||
) : AppRoute(path = "/onboarding_v2/$mode") {
|
||||
|
||||
enum class Mode {
|
||||
Onboarding, // general Mode
|
||||
AddBackupWallet1, // continue backup process for existing wallet 1
|
||||
WelcomeOnlyTwin, // show welcome screen and then navigate to wallet for twins
|
||||
RecreateWalletTwin, // reset twins
|
||||
ContinueFinalize, // continue finalize process (unfinished backup dialog)
|
||||
@Serializable
|
||||
sealed class Mode {
|
||||
data object Onboarding : Mode() // general Mode
|
||||
data object AddBackupWallet1 : Mode() // continue backup process for existing wallet 1
|
||||
data object WelcomeOnlyTwin : Mode() // show welcome screen and then navigate to wallet for twins
|
||||
data object RecreateWalletTwin : Mode() // reset twins
|
||||
data object ContinueFinalize : Mode() // continue finalize process (unfinished backup dialog)
|
||||
data class UpgradeHotWallet(val userWalletId: UserWalletId) : Mode() // upgrade hot wallet
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.data.wallets.hot
|
|||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.hot.HotWalletAccessor
|
||||
import com.tangem.domain.wallets.hot.HotWalletPasswordRequester
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
|
|
@ -56,12 +57,22 @@ class DefaultHotWalletAccessor @Inject constructor(
|
|||
contextualUnlockHotWallet[hotWalletId]
|
||||
|
||||
override fun clearContextualUnlock(hotWalletId: HotWalletId) {
|
||||
contextualUnlockHotWallet[hotWalletId] = null
|
||||
contextualUnlockHotWallet.remove(hotWalletId)
|
||||
scope.launch {
|
||||
tangemHotSdk.clearUnlockContext(hotWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearContextualUnlock(userWalletId: UserWalletId) {
|
||||
scope.launch {
|
||||
val userWallet = userWalletsListRepository.userWalletsSync()
|
||||
.find { it is UserWallet.Hot && it.walletId == userWalletId }
|
||||
as? UserWallet.Hot
|
||||
?: return@launch
|
||||
clearContextualUnlock(userWallet.hotWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearAllContextualUnlock() {
|
||||
val hotWalletsIds = contextualUnlockHotWallet.keys.toList()
|
||||
contextualUnlockHotWallet.clear()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.domain.wallets.hot
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.hot.sdk.model.*
|
||||
|
||||
interface HotWalletAccessor {
|
||||
|
|
@ -16,5 +17,7 @@ interface HotWalletAccessor {
|
|||
|
||||
fun clearContextualUnlock(hotWalletId: HotWalletId)
|
||||
|
||||
fun clearContextualUnlock(userWalletId: UserWalletId)
|
||||
|
||||
fun clearAllContextualUnlock()
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
package com.tangem.domain.wallets.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.hot.HotWalletAccessor
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
|
||||
|
|
@ -14,4 +15,10 @@ class ClearHotWalletContextualUnlockUseCase(
|
|||
hotWalletAccessor.clearContextualUnlock(hotWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
operator fun invoke(userWalletId: UserWalletId): Either<Throwable, Unit> {
|
||||
return Either.catch {
|
||||
hotWalletAccessor.clearContextualUnlock(userWalletId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,8 @@ dependencies {
|
|||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.settings)
|
||||
implementation(projects.domain.feedback)
|
||||
implementation(projects.domain.feedback.models)
|
||||
|
||||
/** Common */
|
||||
implementation(projects.common.ui)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import com.tangem.features.hotwallet.accesscode.entity.AccessCodeUM
|
|||
import com.tangem.features.hotwallet.impl.R
|
||||
import com.tangem.hot.sdk.TangemHotSdk
|
||||
import com.tangem.hot.sdk.model.HotAuth
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.hot.sdk.model.UnlockHotWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -54,8 +53,6 @@ internal class AccessCodeModel @Inject constructor(
|
|||
|
||||
private val params = paramsContainer.require<AccessCodeComponent.Params>()
|
||||
|
||||
private var hotWalletId: HotWalletId? = null
|
||||
|
||||
internal val uiState: StateFlow<AccessCodeUM>
|
||||
field = MutableStateFlow(getInitialState())
|
||||
|
||||
|
|
@ -197,7 +194,7 @@ internal class AccessCodeModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
hotWalletId?.let { clearHotWalletContextualUnlockUseCase.invoke(it) }
|
||||
clearHotWalletContextualUnlockUseCase.invoke(params.userWalletId)
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +1,71 @@
|
|||
package com.tangem.features.hotwallet.upgradewallet
|
||||
|
||||
import com.tangem.common.core.TangemError
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.doOnFailure
|
||||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.toWrappedList
|
||||
import com.tangem.core.ui.message.DialogMessage
|
||||
import com.tangem.core.ui.message.EventMessageAction
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.wallets.usecase.ClearHotWalletContextualUnlockUseCase
|
||||
import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase
|
||||
import com.tangem.features.hotwallet.UpgradeWalletComponent
|
||||
import com.tangem.features.hotwallet.upgradewallet.entity.UpgradeWalletUM
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.sdk.extensions.localizedDescriptionRes
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class UpgradeWalletModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val router: Router,
|
||||
private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val clearHotWalletContextualUnlockUseCase: ClearHotWalletContextualUnlockUseCase,
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||
) : Model() {
|
||||
private val params = paramsContainer.require<UpgradeWalletComponent.Params>()
|
||||
|
||||
internal val uiState: StateFlow<UpgradeWalletUM>
|
||||
field = MutableStateFlow(
|
||||
private val _uiState = MutableStateFlow(
|
||||
UpgradeWalletUM(
|
||||
onBackClick = { router.pop() },
|
||||
onBuyTangemWalletClick = ::onBuyTangemWalletClick,
|
||||
onScanDeviceClick = ::onScanDeviceClick,
|
||||
),
|
||||
)
|
||||
internal val uiState: StateFlow<UpgradeWalletUM> = _uiState
|
||||
|
||||
override fun onDestroy() {
|
||||
clearHotWalletContextualUnlockUseCase.invoke(params.userWalletId)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun onBuyTangemWalletClick() {
|
||||
modelScope.launch {
|
||||
|
|
@ -36,6 +74,73 @@ internal class UpgradeWalletModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onScanDeviceClick() {
|
||||
// TODO [REDACTED_TASK_KEY]
|
||||
scanCard()
|
||||
}
|
||||
|
||||
private fun scanCard() {
|
||||
modelScope.launch {
|
||||
setLoading(true)
|
||||
|
||||
val shouldSaveAccessCodes = settingsRepository.shouldSaveAccessCodes()
|
||||
cardSdkConfigRepository.setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = shouldSaveAccessCodes,
|
||||
)
|
||||
|
||||
tangemSdkManager
|
||||
.scanProduct()
|
||||
.doOnSuccess {
|
||||
delay(DELAY_SDK_DIALOG_CLOSE)
|
||||
tangemSdkManager.changeDisplayedCardIdNumbersCount(it)
|
||||
navigateToUpgradeFlow(it)
|
||||
}
|
||||
.doOnFailure {
|
||||
showCardVerificationFailedDialog(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setLoading(isLoading: Boolean) {
|
||||
_uiState.update { it.copy(isLoading = isLoading) }
|
||||
}
|
||||
|
||||
private fun showCardVerificationFailedDialog(error: TangemError) {
|
||||
if (error !is TangemSdkError.CardVerificationFailed) return
|
||||
|
||||
// TODO [REDACTED_TASK_KEY] track error
|
||||
|
||||
val resource = error.localizedDescriptionRes()
|
||||
val resId = resource.resId ?: R.string.common_unknown_error
|
||||
val resArgs = resource.args.map { it.value }
|
||||
|
||||
uiMessageSender.send(
|
||||
DialogMessage(
|
||||
message = resourceReference(id = resId, resArgs.toWrappedList()),
|
||||
title = resourceReference(id = R.string.security_alert_title),
|
||||
isDismissable = false,
|
||||
firstActionBuilder = {
|
||||
EventMessageAction(
|
||||
title = resourceReference(id = R.string.alert_button_request_support),
|
||||
onClick = {
|
||||
modelScope.launch {
|
||||
sendFeedbackEmailUseCase(type = FeedbackEmailType.CardAttestationFailed)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
secondActionBuilder = { cancelAction(onClick = {}) },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun navigateToUpgradeFlow(scanResponse: ScanResponse) {
|
||||
setLoading(false)
|
||||
router.push(
|
||||
AppRoute.Onboarding(
|
||||
scanResponse = scanResponse,
|
||||
mode = AppRoute.Onboarding.Mode.UpgradeHotWallet(
|
||||
userWalletId = params.userWalletId,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,4 +4,5 @@ internal data class UpgradeWalletUM(
|
|||
val onBackClick: () -> Unit,
|
||||
val onBuyTangemWalletClick: () -> Unit,
|
||||
val onScanDeviceClick: () -> Unit,
|
||||
val isLoading: Boolean = false,
|
||||
)
|
||||
|
|
@ -13,7 +13,6 @@ import com.tangem.domain.wallets.usecase.ExportSeedPhraseUseCase
|
|||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.hotwallet.ViewPhraseComponent
|
||||
import com.tangem.features.hotwallet.viewphrase.entity.ViewPhraseUM
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -35,8 +34,6 @@ internal class ViewPhraseModel @Inject constructor(
|
|||
|
||||
private val params = paramsContainer.require<ViewPhraseComponent.Params>()
|
||||
|
||||
private var hotWalletId: HotWalletId? = null
|
||||
|
||||
internal val uiState: StateFlow<ViewPhraseUM>
|
||||
field = MutableStateFlow(
|
||||
ViewPhraseUM(
|
||||
|
|
@ -52,7 +49,6 @@ internal class ViewPhraseModel @Inject constructor(
|
|||
val userWallet = getUserWalletUseCase(params.userWalletId)
|
||||
.getOrElse { error("User wallet with id ${params.userWalletId} not found") }
|
||||
if (userWallet is UserWallet.Hot) {
|
||||
hotWalletId = userWallet.hotWalletId
|
||||
modelScope.launch {
|
||||
val words = exportSeedPhraseUseCase.invoke(userWallet.hotWalletId)
|
||||
.getOrElse { error("Unable to export seed phrase for wallet with id ${params.userWalletId}") }
|
||||
|
|
@ -70,7 +66,7 @@ internal class ViewPhraseModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
hotWalletId?.let { clearHotWalletContextualUnlockUseCase.invoke(it) }
|
||||
clearHotWalletContextualUnlockUseCase.invoke(params.userWalletId)
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.onboarding.v2.entry
|
|||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
interface OnboardingEntryComponent : ComposableContentComponent {
|
||||
|
||||
|
|
@ -11,12 +12,13 @@ interface OnboardingEntryComponent : ComposableContentComponent {
|
|||
val mode: Mode,
|
||||
)
|
||||
|
||||
enum class Mode {
|
||||
Onboarding,
|
||||
AddBackupWallet1,
|
||||
WelcomeOnlyTwin,
|
||||
RecreateWalletTwin,
|
||||
ContinueFinalize,
|
||||
sealed class Mode {
|
||||
data object Onboarding : Mode()
|
||||
data object AddBackupWallet1 : Mode()
|
||||
data object WelcomeOnlyTwin : Mode()
|
||||
data object RecreateWalletTwin : Mode()
|
||||
data object ContinueFinalize : Mode()
|
||||
data class UpgradeHotWallet(val userWalletId: UserWalletId) : Mode()
|
||||
}
|
||||
|
||||
interface Factory : ComponentFactory<Params, OnboardingEntryComponent>
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ dependencies {
|
|||
implementation(projects.domain.transaction)
|
||||
|
||||
/** Tangem libraries */
|
||||
implementation(tangemDeps.hot.core)
|
||||
implementation(projects.libs.tangemSdkApi)
|
||||
implementation(tangemDeps.card.core)
|
||||
implementation(tangemDeps.card.android) {
|
||||
|
|
|
|||
|
|
@ -73,16 +73,20 @@ internal class OnboardingEntryModel @Inject constructor(
|
|||
uiMessageSender.send(CantLeaveBackupDialog)
|
||||
}
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private fun routeByProductType(scanResponse: ScanResponse): OnboardingRoute {
|
||||
return when (scanResponse.productType) {
|
||||
ProductType.Wallet,
|
||||
ProductType.Wallet2,
|
||||
ProductType.Ring,
|
||||
-> {
|
||||
val multiWalletNavigationMode = when (params.mode) {
|
||||
Mode.Onboarding -> OnboardingMultiWalletComponent.Mode.Onboarding
|
||||
Mode.AddBackupWallet1 -> OnboardingMultiWalletComponent.Mode.AddBackup
|
||||
Mode.ContinueFinalize -> OnboardingMultiWalletComponent.Mode.ContinueFinalize
|
||||
val multiWalletNavigationMode = when (val mode = params.mode) {
|
||||
is Mode.Onboarding -> OnboardingMultiWalletComponent.Mode.Onboarding
|
||||
is Mode.AddBackupWallet1 -> OnboardingMultiWalletComponent.Mode.AddBackup
|
||||
is Mode.ContinueFinalize -> OnboardingMultiWalletComponent.Mode.ContinueFinalize
|
||||
is Mode.UpgradeHotWallet -> OnboardingMultiWalletComponent.Mode.UpgradeHotWallet(
|
||||
userWalletId = mode.userWalletId,
|
||||
)
|
||||
else -> error("Incorrect onboarding type")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.core.decompose.navigation.inner.InnerNavigationHolder
|
|||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.features.onboarding.v2.TitleProvider
|
||||
|
||||
interface OnboardingMultiWalletComponent : ComposableContentComponent, InnerNavigationHolder {
|
||||
|
|
@ -17,10 +18,11 @@ interface OnboardingMultiWalletComponent : ComposableContentComponent, InnerNavi
|
|||
val onDone: (UserWallet.Cold) -> Unit,
|
||||
)
|
||||
|
||||
enum class Mode {
|
||||
Onboarding,
|
||||
AddBackup,
|
||||
ContinueFinalize,
|
||||
sealed class Mode {
|
||||
data object Onboarding : Mode()
|
||||
data object AddBackup : Mode()
|
||||
data object ContinueFinalize : Mode()
|
||||
data class UpgradeHotWallet(val userWalletId: UserWalletId) : Mode()
|
||||
}
|
||||
|
||||
interface Factory : ComponentFactory<Params, OnboardingMultiWalletComponent>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.Mul
|
|||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.MultiWalletFinalizeComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.scanprimary.MultiWalletScanPrimaryComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.MultiWalletSeedPhraseComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.upgradewallet.MultiWalletUpgradeWalletComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletModel
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState.Step.*
|
||||
|
|
@ -57,6 +58,7 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor
|
|||
private val artworksState = instanceKeeper.getOrCreateSimple(key = "artworksState") {
|
||||
MutableStateFlow(
|
||||
when (model.state.value.currentStep) {
|
||||
UpgradeWallet -> WalletArtworksState.Folded
|
||||
CreateWallet -> WalletArtworksState.Folded
|
||||
ChooseBackupOption -> WalletArtworksState.Fan
|
||||
SeedPhrase -> WalletArtworksState.Folded
|
||||
|
|
@ -142,6 +144,11 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor
|
|||
childContext: AppComponentContext,
|
||||
): ComposableContentComponent {
|
||||
return when (step) {
|
||||
UpgradeWallet -> MultiWalletUpgradeWalletComponent(
|
||||
context = childContext,
|
||||
params = childParams,
|
||||
onNextStep = ::handleNavigationEvent,
|
||||
)
|
||||
CreateWallet -> MultiWalletCreateWalletComponent(
|
||||
context = childContext,
|
||||
params = childParams,
|
||||
|
|
|
|||
|
|
@ -265,6 +265,16 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
|
||||
userWallet
|
||||
}
|
||||
is OnboardingMultiWalletComponent.Mode.UpgradeHotWallet -> {
|
||||
saveWalletUseCase(
|
||||
userWallet = userWalletCreated.copy(
|
||||
scanResponse = scanResponse.updateScanResponseAfterBackup(),
|
||||
),
|
||||
canOverride = true,
|
||||
)
|
||||
// TODO [REDACTED_TASK_KEY] remove hot wallet after upgrade
|
||||
userWalletCreated
|
||||
}
|
||||
}.requireColdWallet()
|
||||
|
||||
if (hasRing) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
package com.tangem.features.onboarding.v2.multiwallet.impl.child.upgradewallet
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.arkivanov.essenty.lifecycle.doOnStart
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.features.onboarding.v2.impl.R
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.upgradewallet.model.MultiWalletUpgradeWalletModel
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.upgradewallet.ui.MultiWalletUpgradeWallet
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal class MultiWalletUpgradeWalletComponent(
|
||||
context: AppComponentContext,
|
||||
params: MultiWalletChildParams,
|
||||
onNextStep: (OnboardingMultiWalletState.Step) -> Unit,
|
||||
) : AppComponentContext by context, MultiWalletChildComponent {
|
||||
|
||||
private val model: MultiWalletUpgradeWalletModel = getOrCreateModel(params)
|
||||
|
||||
init {
|
||||
lifecycle.doOnStart {
|
||||
params.innerNavigation.update {
|
||||
it.copy(
|
||||
stackSize = 2,
|
||||
stackMaxSize = 9,
|
||||
)
|
||||
}
|
||||
|
||||
params.parentParams.titleProvider.changeTitle(
|
||||
text = resourceReference(R.string.common_tangem),
|
||||
)
|
||||
}
|
||||
|
||||
componentScope.launch {
|
||||
model.onDone.collect(onNextStep)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
MultiWalletUpgradeWallet(
|
||||
modifier = modifier,
|
||||
state = state,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
package com.tangem.features.onboarding.v2.multiwallet.impl.child.upgradewallet.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.ExportSeedPhraseUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
|
||||
import com.tangem.features.onboarding.v2.impl.R
|
||||
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.upgradewallet.ui.state.MultiWalletUpgradeWalletUM
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.resetCardDialog
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState.Step
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class MultiWalletUpgradeWalletModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||
private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase,
|
||||
private val cardRepository: CardRepository,
|
||||
private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory,
|
||||
private val saveWalletUseCase: SaveWalletUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val exportSeedPhraseUseCase: ExportSeedPhraseUseCase,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<MultiWalletChildParams>()
|
||||
private val multiWalletState
|
||||
get() = params.multiWalletState
|
||||
|
||||
private val _uiState = MutableStateFlow(
|
||||
MultiWalletUpgradeWalletUM(
|
||||
title = resourceReference(R.string.hw_upgrade_start_title),
|
||||
bodyText = resourceReference(R.string.hw_upgrade_start_description),
|
||||
onStartUpgradeClick = {
|
||||
// TODO [REDACTED_TASK_KEY] track button click
|
||||
upgradeWallet(false)
|
||||
},
|
||||
dialog = null,
|
||||
),
|
||||
)
|
||||
|
||||
val uiState: StateFlow<MultiWalletUpgradeWalletUM> = _uiState
|
||||
val onDone = MutableSharedFlow<Step>()
|
||||
|
||||
init {
|
||||
// TODO [REDACTED_TASK_KEY] track screen opened
|
||||
}
|
||||
|
||||
private fun upgradeWallet(shouldReset: Boolean) {
|
||||
modelScope.launch {
|
||||
val mode = params.parentParams.mode
|
||||
require(mode is OnboardingMultiWalletComponent.Mode.UpgradeHotWallet)
|
||||
|
||||
val userWallet = getUserWalletUseCase(mode.userWalletId)
|
||||
.getOrElse { error("User wallet with id ${mode.userWalletId} not found") }
|
||||
if (userWallet is UserWallet.Hot) {
|
||||
val privateInfo = exportSeedPhraseUseCase
|
||||
.invoke(userWallet.hotWalletId)
|
||||
.getOrElse { error("Unable to export seed phrase for wallet with id ${mode.userWalletId}") }
|
||||
|
||||
modelScope.launch {
|
||||
val result = tangemSdkManager.importWallet(
|
||||
scanResponse = multiWalletState.value.currentScanResponse,
|
||||
shouldReset = shouldReset,
|
||||
mnemonic = privateInfo.mnemonic.mnemonicComponents.joinToString(" "),
|
||||
passphrase = privateInfo.passphrase?.concatToString(),
|
||||
)
|
||||
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
multiWalletState.update {
|
||||
it.copy(
|
||||
currentScanResponse = it.currentScanResponse.copy(
|
||||
card = result.data.card,
|
||||
derivedKeys = result.data.derivedKeys,
|
||||
primaryCard = result.data.primaryCard,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
cardRepository.startCardActivation(cardId = result.data.card.cardId)
|
||||
|
||||
// TODO [REDACTED_TASK_KEY] track wallet created
|
||||
val cardDoesNotSupportBackup = result.data.card.settings.isBackupAllowed.not()
|
||||
when {
|
||||
cardDoesNotSupportBackup -> createWalletAndNavigateBackWithDone()
|
||||
params.parentParams.withSeedPhraseFlow -> onDone.emit(Step.AddBackupDevice)
|
||||
else -> {
|
||||
onDone.emit(Step.ChooseBackupOption)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is CompletionResult.Failure -> {
|
||||
if (result.error is TangemSdkError.WalletAlreadyCreated) {
|
||||
// show should reset dialog
|
||||
handleActivationError()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createWalletAndNavigateBackWithDone() {
|
||||
modelScope.launch {
|
||||
val scanResponse = params.multiWalletState.value.currentScanResponse
|
||||
|
||||
val userWallet = createUserWallet(scanResponse)
|
||||
saveWalletUseCase(userWallet, canOverride = true)
|
||||
.onRight {
|
||||
cardRepository.finishCardActivation(scanResponse.card.cardId)
|
||||
|
||||
// save user wallet for manage tokens screen
|
||||
params.multiWalletState.update {
|
||||
it.copy(resultUserWallet = userWallet)
|
||||
}
|
||||
|
||||
onDone.emit(Step.Done)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createUserWallet(scanResponse: ScanResponse): UserWallet.Cold {
|
||||
return requireNotNull(
|
||||
value = coldUserWalletBuilderFactory.create(scanResponse = scanResponse).build(),
|
||||
lazyMessage = { "User wallet not created" },
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleActivationError() {
|
||||
_uiState.update { state ->
|
||||
state.copy(
|
||||
dialog = resetCardDialog(
|
||||
onConfirm = ::navigateToSupportScreen,
|
||||
dismiss = { _uiState.update { it.copy(dialog = null) } },
|
||||
onDismissButtonClick = ::resetCard,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetCard() {
|
||||
upgradeWallet(true)
|
||||
}
|
||||
|
||||
fun navigateToSupportScreen() {
|
||||
modelScope.launch {
|
||||
val cardInfo =
|
||||
getWalletMetaInfoUseCase(multiWalletState.value.currentScanResponse).getOrNull() ?: return@launch
|
||||
sendFeedbackEmailUseCase(FeedbackEmailType.DirectUserRequest(cardInfo))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
package com.tangem.features.onboarding.v2.multiwallet.impl.child.upgradewallet.ui
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.BasicDialog
|
||||
import com.tangem.core.ui.components.DialogButtonUM
|
||||
import com.tangem.core.ui.components.PrimaryButtonIconEnd
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.onboarding.v2.impl.R
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.upgradewallet.ui.state.MultiWalletUpgradeWalletUM
|
||||
|
||||
@Composable
|
||||
internal fun MultiWalletUpgradeWallet(state: MultiWalletUpgradeWalletUM, modifier: Modifier = Modifier) {
|
||||
if (state.dialog != null) {
|
||||
BasicDialog(
|
||||
title = state.dialog.title.resolveReference(),
|
||||
message = state.dialog.message.resolveReference(),
|
||||
confirmButton = DialogButtonUM(
|
||||
title = state.dialog.confirmButtonText.resolveReference(),
|
||||
onClick = state.dialog.onConfirmClick,
|
||||
),
|
||||
dismissButton = DialogButtonUM(
|
||||
title = state.dialog.dismissButtonText.resolveReference(),
|
||||
warning = state.dialog.dismissWarningColor,
|
||||
onClick = state.dialog.onDismissButtonClick,
|
||||
),
|
||||
onDismissDialog = state.dialog.onDismiss,
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.navigationBarsPadding(),
|
||||
verticalArrangement = Arrangement.Bottom,
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(start = 32.dp, end = 32.dp, bottom = 16.dp)
|
||||
.weight(1f),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
text = state.title.resolveReference(),
|
||||
style = TangemTheme.typography.h2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.padding(top = 16.dp),
|
||||
)
|
||||
|
||||
Text(
|
||||
text = state.bodyText.resolveReference(),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.padding(top = 12.dp),
|
||||
)
|
||||
}
|
||||
|
||||
PrimaryButtonIconEnd(
|
||||
modifier = Modifier
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
text = stringResourceSafe(R.string.hw_upgrade_start_action),
|
||||
onClick = state.onStartUpgradeClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
TangemThemePreview {
|
||||
MultiWalletUpgradeWallet(
|
||||
state = MultiWalletUpgradeWalletUM(
|
||||
title = stringReference("Title"),
|
||||
bodyText = stringReference("Body body body"),
|
||||
onStartUpgradeClick = {},
|
||||
dialog = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.features.onboarding.v2.multiwallet.impl.child.upgradewallet.ui.state
|
||||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.features.onboarding.v2.common.ui.OnboardingDialogUM
|
||||
|
||||
internal data class MultiWalletUpgradeWalletUM(
|
||||
val title: TextReference,
|
||||
val bodyText: TextReference,
|
||||
val onStartUpgradeClick: () -> Unit,
|
||||
val dialog: OnboardingDialogUM?,
|
||||
)
|
||||
|
|
@ -11,6 +11,7 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.mod
|
|||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.model.MultiWalletFinalizeModel
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.scanprimary.model.MultiWalletScanPrimaryModel
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.MultiWalletSeedPhraseModel
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.upgradewallet.model.MultiWalletUpgradeWalletModel
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletModel
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
|
@ -72,4 +73,9 @@ internal interface ModelModule {
|
|||
@IntoMap
|
||||
@ClassKey(MultiWalletScanPrimaryModel::class)
|
||||
fun provideModel8(model: MultiWalletScanPrimaryModel): Model
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(MultiWalletUpgradeWalletModel::class)
|
||||
fun provideModel9(model: MultiWalletUpgradeWalletModel): Model
|
||||
}
|
||||
|
|
@ -117,6 +117,9 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
val card = scanResponse.card
|
||||
|
||||
return when {
|
||||
params.mode is OnboardingMultiWalletComponent.Mode.UpgradeHotWallet -> {
|
||||
OnboardingMultiWalletState.Step.UpgradeWallet
|
||||
}
|
||||
params.mode == OnboardingMultiWalletComponent.Mode.ContinueFinalize ->
|
||||
OnboardingMultiWalletState.Step.Finalize
|
||||
// Add backup button
|
||||
|
|
|
|||
|
|
@ -32,7 +32,14 @@ data class OnboardingMultiWalletState(
|
|||
* -> AddBackupDevice -> Finalize -> [Done]
|
||||
*/
|
||||
enum class Step {
|
||||
CreateWallet, ChooseBackupOption, SeedPhrase, ScanPrimary, AddBackupDevice, Finalize, Done
|
||||
UpgradeWallet,
|
||||
CreateWallet,
|
||||
ChooseBackupOption,
|
||||
SeedPhrase,
|
||||
ScanPrimary,
|
||||
AddBackupDevice,
|
||||
Finalize,
|
||||
Done,
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
|
|
|
|||
|
|
@ -14,4 +14,5 @@ fun screenTitleByStep(step: OnboardingMultiWalletState.Step): TextReference = wh
|
|||
OnboardingMultiWalletState.Step.ChooseBackupOption -> resourceReference(R.string.onboarding_getting_started)
|
||||
OnboardingMultiWalletState.Step.Finalize -> resourceReference(R.string.onboarding_button_finalize_backup)
|
||||
OnboardingMultiWalletState.Step.Done -> resourceReference(R.string.common_done)
|
||||
OnboardingMultiWalletState.Step.UpgradeWallet -> resourceReference(R.string.common_tangem)
|
||||
}
|
||||
|
|
@ -363,32 +363,16 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
if (!state.value.isWalletBackedUp) {
|
||||
messageSender.send(makeBackupAtFirstAlertBS)
|
||||
} else {
|
||||
val userWallet = getUserWalletUseCase(params.userWalletId)
|
||||
.getOrElse { error("User wallet with id ${params.userWalletId} not found") }
|
||||
if (userWallet is UserWallet.Hot) {
|
||||
val hotWalletId = userWallet.hotWalletId
|
||||
when (hotWalletId.authType) {
|
||||
HotWalletId.AuthType.NoPassword -> {
|
||||
router.push(AppRoute.UpdateAccessCode(params.userWalletId))
|
||||
}
|
||||
HotWalletId.AuthType.Password,
|
||||
HotWalletId.AuthType.Biometry,
|
||||
-> modelScope.launch {
|
||||
unlockHotWalletContextualUseCase.invoke(hotWalletId)
|
||||
.onLeft {
|
||||
Timber.e("Unable to unlock wallet with id ${params.userWalletId}")
|
||||
}
|
||||
.onRight {
|
||||
router.push(AppRoute.UpdateAccessCode(params.userWalletId))
|
||||
}
|
||||
}
|
||||
}
|
||||
unlockWalletIfNeedAndProceed {
|
||||
router.push(AppRoute.UpdateAccessCode(params.userWalletId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onUpgradeWalletClick() {
|
||||
router.push(AppRoute.UpgradeWallet(params.userWalletId))
|
||||
unlockWalletIfNeedAndProceed {
|
||||
router.push(AppRoute.UpgradeWallet(params.userWalletId))
|
||||
}
|
||||
}
|
||||
|
||||
private fun onDismissUpgradeWalletClick() {
|
||||
|
|
@ -396,4 +380,28 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
dismissUpgradeWalletNotificationUseCase.invoke(params.userWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun unlockWalletIfNeedAndProceed(action: () -> Unit) {
|
||||
val userWallet = getUserWalletUseCase(params.userWalletId)
|
||||
.getOrElse { error("User wallet with id ${params.userWalletId} not found") }
|
||||
if (userWallet is UserWallet.Hot) {
|
||||
val hotWalletId = userWallet.hotWalletId
|
||||
when (hotWalletId.authType) {
|
||||
HotWalletId.AuthType.NoPassword -> {
|
||||
action()
|
||||
}
|
||||
HotWalletId.AuthType.Password,
|
||||
HotWalletId.AuthType.Biometry,
|
||||
-> modelScope.launch {
|
||||
unlockHotWalletContextualUseCase.invoke(hotWalletId)
|
||||
.onLeft {
|
||||
Timber.e("Unable to unlock wallet with id ${params.userWalletId}")
|
||||
}
|
||||
.onRight {
|
||||
action()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue