Updated on 2026-08-14
This commit is contained in:
commit
e4754fed3b
483 changed files with 9315 additions and 4084 deletions
|
|
@ -28,6 +28,7 @@ import com.tangem.domain.apptheme.repository.AppThemeModeRepository
|
|||
import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
|
||||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
|
|
@ -38,7 +39,9 @@ import com.tangem.domain.walletmanager.WalletManagersFacade
|
|||
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
|
||||
import com.tangem.hot.sdk.TangemHotSdk
|
||||
import com.tangem.tap.common.analytics.handlers.BlockchainExceptionHandler
|
||||
import com.tangem.tap.common.log.TangemAppLoggerInitializer
|
||||
import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles
|
||||
|
|
@ -142,4 +145,10 @@ interface ApplicationEntryPoint {
|
|||
fun getApiConfigsManager(): ApiConfigsManager
|
||||
|
||||
fun getUserTokensResponseStore(): UserTokensResponseStore
|
||||
|
||||
fun getUserWalletsListRepository(): UserWalletsListRepository
|
||||
|
||||
fun getTangemHotSdk(): TangemHotSdk
|
||||
|
||||
fun getHotWalletFeatureToggles(): HotWalletFeatureToggles
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@ import androidx.work.WorkerParameters
|
|||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.legacy.asLockable
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import timber.log.Timber
|
||||
|
|
@ -17,13 +19,22 @@ class LockTimerWorker @AssistedInject constructor(
|
|||
@Assisted params: WorkerParameters,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) : CoroutineWorker(context, params) {
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
Timber.i("onStart job")
|
||||
val userWalletsListManagerLockable = userWalletsListManager.asLockable() ?: return Result.failure()
|
||||
userWalletsListManagerLockable.lock()
|
||||
settingsRepository.setShouldOpenWelcomeScreenOnResume(value = true)
|
||||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
userWalletsListRepository.lockAllWallets()
|
||||
.onRight {
|
||||
settingsRepository.setShouldOpenWelcomeScreenOnResume(value = true)
|
||||
}
|
||||
} else {
|
||||
val userWalletsListManagerLockable = userWalletsListManager.asLockable() ?: return Result.failure()
|
||||
userWalletsListManagerLockable.lock()
|
||||
settingsRepository.setShouldOpenWelcomeScreenOnResume(value = true)
|
||||
}
|
||||
Timber.i("onStart job complete")
|
||||
return Result.success()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import com.tangem.common.routing.AppRoute
|
|||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.legacy.asLockable
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.tap.LockTimerWorker.Companion.TAG
|
||||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -25,6 +27,8 @@ internal class LockUserWalletsTimer(
|
|||
private val settingsRepository: SettingsRepository,
|
||||
private val duration: Duration = with(Duration) { 5.minutes },
|
||||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
) : LifecycleOwner by context as LifecycleOwner,
|
||||
DefaultLifecycleObserver {
|
||||
|
|
@ -108,20 +112,33 @@ internal class LockUserWalletsTimer(
|
|||
|
||||
delay(duration)
|
||||
|
||||
val userWalletsListManager = userWalletsListManager.asLockable() ?: return@launch
|
||||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
val userWallets = userWalletsListRepository.userWalletsSync()
|
||||
if (userWallets.isNotEmpty()) {
|
||||
userWalletsListRepository.lockAllWallets()
|
||||
.onLeft {
|
||||
start()
|
||||
}
|
||||
.onRight {
|
||||
store.dispatchNavigationAction { replaceAll(AppRoute.Welcome()) }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val userWalletsListManager = userWalletsListManager.asLockable() ?: return@launch
|
||||
|
||||
if (userWalletsListManager.hasUserWallets) {
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (userWalletsListManager.hasUserWallets) {
|
||||
val currentTime = System.currentTimeMillis()
|
||||
|
||||
Timber.i(
|
||||
"""
|
||||
Timber.i(
|
||||
"""
|
||||
Finished
|
||||
|- Millis passed: ${currentTime - startTime}
|
||||
""".trimIndent(),
|
||||
)
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
userWalletsListManager.lock()
|
||||
store.dispatchNavigationAction { replaceAll(AppRoute.Welcome()) }
|
||||
userWalletsListManager.lock()
|
||||
store.dispatchNavigationAction { replaceAll(AppRoute.Welcome()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +40,7 @@ import com.tangem.domain.apptheme.model.AppThemeMode
|
|||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
import com.tangem.domain.settings.SetGooglePayAvailabilityUseCase
|
||||
import com.tangem.domain.settings.SetGoogleServicesAvailabilityUseCase
|
||||
import com.tangem.domain.settings.ShouldInitiallyAskPermissionUseCase
|
||||
|
|
@ -48,7 +49,10 @@ import com.tangem.domain.staking.SendUnsubmittedHashesUseCase
|
|||
import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase
|
||||
import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import com.tangem.features.tester.api.TesterMenuLauncher
|
||||
import com.tangem.features.walletconnect.components.WalletConnectFeatureToggles
|
||||
import com.tangem.google.GoogleServicesHelper
|
||||
|
|
@ -188,6 +192,15 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
|||
@Inject
|
||||
internal lateinit var backgroundScanIntentHandler: BackgroundScanIntentHandler
|
||||
|
||||
@Inject
|
||||
internal lateinit var userWalletsListRepository: UserWalletsListRepository
|
||||
|
||||
@Inject
|
||||
internal lateinit var hotWalletFeatureToggles: HotWalletFeatureToggles
|
||||
|
||||
@Inject
|
||||
internal lateinit var tangemPayFeatureToggles: TangemPayFeatureToggles
|
||||
|
||||
internal val viewModel: MainViewModel by viewModels()
|
||||
|
||||
private lateinit var appThemeModeFlow: SharedFlow<AppThemeMode>
|
||||
|
|
@ -271,6 +284,8 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
|||
settingsRepository = settingsRepository,
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
coroutineScope = mainScope,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
hotWalletFeatureToggles = hotWalletFeatureToggles,
|
||||
)
|
||||
|
||||
initIntentHandlers()
|
||||
|
|
@ -429,6 +444,12 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
|||
}
|
||||
|
||||
private fun navigateToInitialScreenIfNeeded(intentWhichStartedActivity: Intent?) {
|
||||
// TODO refactor this method to return a route instead of navigating directly
|
||||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
navigateToInitialScreenIfNeededNew(intentWhichStartedActivity)
|
||||
return
|
||||
}
|
||||
|
||||
val backStack = appRouterConfig.stack ?: emptyList()
|
||||
// TODO move inital navigation to navigation component ([REDACTED_JIRA])
|
||||
val isOnlyInitialRoute = backStack.all { it is AppRoute.Initial }
|
||||
|
|
@ -448,9 +469,66 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("Refactor this method to return a route instead of navigating directly")
|
||||
private fun navigateToInitialScreenIfNeededNew(intentWhichStartedActivity: Intent?) {
|
||||
lifecycleScope.launch {
|
||||
val userWallets = userWalletsListRepository.userWalletsSync()
|
||||
val launchMode = backgroundScanIntentHandler.getInitScreenLaunchMode(intentWhichStartedActivity)
|
||||
if (userWallets.isEmpty()) {
|
||||
val shouldShowTos = !cardRepository.isTangemTOSAccepted()
|
||||
|
||||
val route = if (shouldShowTos) {
|
||||
AppRoute.Disclaimer(isTosAccepted = false)
|
||||
} else {
|
||||
AppRoute.Home(launchMode = launchMode)
|
||||
}
|
||||
|
||||
store.dispatchNavigationAction { replaceAll(route) }
|
||||
intentProcessor.handleIntent(
|
||||
intent = intentWhichStartedActivity,
|
||||
isFromForeground = false,
|
||||
skipNavigationHandlers = false,
|
||||
)
|
||||
} else {
|
||||
if (userWallets.any { it.isLocked }) {
|
||||
store.dispatchNavigationAction {
|
||||
replaceAll(
|
||||
AppRoute.Welcome(
|
||||
launchMode = launchMode,
|
||||
intent = intentWhichStartedActivity?.let(::SerializableIntent),
|
||||
),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
store.dispatchNavigationAction {
|
||||
replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
}
|
||||
|
||||
intentProcessor.handleIntent(
|
||||
intent = intentWhichStartedActivity,
|
||||
isFromForeground = false,
|
||||
skipNavigationHandlers = true,
|
||||
)
|
||||
}
|
||||
|
||||
if (intent != null) {
|
||||
handleDeepLink(intent = intent, isFromOnNewIntent = false)
|
||||
}
|
||||
|
||||
viewModel.checkForUnfinishedBackup()
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToInitialScreen(intentWhichStartedActivity: Intent?) {
|
||||
val launchMode = backgroundScanIntentHandler.getInitScreenLaunchMode(intentWhichStartedActivity)
|
||||
if (userWalletsListManager.isLockable && userWalletsListManager.hasUserWallets) {
|
||||
|
||||
// Workaround to navigate to TangemPayDetails screen. Will be deleted in next PRs
|
||||
if (tangemPayFeatureToggles.isTangemPayEnabled) {
|
||||
store.dispatchNavigationAction {
|
||||
replaceAll(AppRoute.TangemPayDetails)
|
||||
}
|
||||
} else if (userWalletsListManager.isLockable && userWalletsListManager.hasUserWallets) {
|
||||
store.dispatchNavigationAction {
|
||||
replaceAll(
|
||||
AppRoute.Welcome(
|
||||
|
|
|
|||
|
|
@ -227,6 +227,15 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat
|
|||
private val userTokensResponseStore: UserTokensResponseStore
|
||||
get() = entryPoint.getUserTokensResponseStore()
|
||||
|
||||
private val userWalletsListRepository
|
||||
get() = entryPoint.getUserWalletsListRepository()
|
||||
|
||||
private val tangemHotSdk
|
||||
get() = entryPoint.getTangemHotSdk()
|
||||
|
||||
private val hotWalletFeatureToggles
|
||||
get() = entryPoint.getHotWalletFeatureToggles()
|
||||
|
||||
// endregion
|
||||
|
||||
private val appScope = MainScope()
|
||||
|
|
@ -364,6 +373,9 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat
|
|||
uiMessageSender = uiMessageSender,
|
||||
coldUserWalletBuilderFactory = coldUserWalletBuilderFactory,
|
||||
userTokensResponseStore = userTokensResponseStore,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
tangemHotSdk = tangemHotSdk,
|
||||
hotWalletFeatureToggles = hotWalletFeatureToggles,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
package com.tangem.tap.common.analytics.converters
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.domain.card.CardTypesResolver
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.core.analytics.models.AnalyticsParam as CoreAnalyticsParam
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class ParamCardCurrencyConverter : Converter<CardTypesResolver, CoreAnalyticsParam.WalletType?> {
|
||||
|
||||
override fun convert(value: CardTypesResolver): CoreAnalyticsParam.WalletType? {
|
||||
if (value.isMultiwalletAllowed()) return CoreAnalyticsParam.WalletType.MultiCurrency
|
||||
|
||||
val type = when {
|
||||
value.isTangemNote() -> AnalyticsParam.CurrencyType.Blockchain(value.getBlockchain())
|
||||
value.isTangemTwins() -> AnalyticsParam.CurrencyType.Blockchain(Blockchain.Bitcoin)
|
||||
value.getBlockchain() != Blockchain.Unknown -> AnalyticsParam.CurrencyType.Blockchain(value.getBlockchain())
|
||||
value.getPrimaryToken() != null -> AnalyticsParam.CurrencyType.Token(value.getPrimaryToken()!!)
|
||||
else -> null
|
||||
} ?: return null
|
||||
|
||||
return CoreAnalyticsParam.WalletType.SingleCurrency(type.value)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,12 +2,12 @@ package com.tangem.tap.common.analytics.paramsInterceptor
|
|||
|
||||
import com.tangem.core.analytics.api.ParamsInterceptor
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.domain.card.analytics.IntroductionProcess
|
||||
import com.tangem.domain.card.analytics.ParamCardCurrencyConverter
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.builder.UserWalletIdBuilder
|
||||
import com.tangem.features.home.impl.analytics.IntroductionProcess
|
||||
import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.features.demo.DemoHelper
|
||||
|
|
|
|||
|
|
@ -26,10 +26,9 @@ internal object LegacyMiddleware {
|
|||
{ action ->
|
||||
when (action) {
|
||||
is LegacyAction.PrepareDetailsScreen -> {
|
||||
val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
|
||||
val walletsRepository = store.inject(DaggerGraphState::walletsRepository)
|
||||
|
||||
userWalletsListManager.selectedUserWallet
|
||||
selectedUserWallet()
|
||||
.distinctUntilChanged()
|
||||
.onEach { selectedUserWallet ->
|
||||
val initializedAppSettingsStateContent = initializeAppSettingsState(
|
||||
|
|
@ -52,6 +51,16 @@ internal object LegacyMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun selectedUserWallet(): Flow<UserWallet> {
|
||||
val hotWalletFeatureToggles = store.inject(DaggerGraphState::hotWalletFeatureToggles)
|
||||
return if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
store.inject(DaggerGraphState::userWalletsListRepository).selectedUserWallet.filterNotNull()
|
||||
} else {
|
||||
val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
|
||||
userWalletsListManager.selectedUserWallet
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LEGACY: We need to initialize [AppSettingsState] async to avoid drawing blocking
|
||||
* previously it was initialized in runBlocking and blocked details screen
|
||||
|
|
@ -64,6 +73,8 @@ internal object LegacyMiddleware {
|
|||
selectedAppCurrency = store.state.globalState.appCurrency,
|
||||
selectedThemeMode = store.inject(DaggerGraphState::appThemeModeRepository).getAppThemeMode().firstOrNull()
|
||||
?: AppThemeMode.DEFAULT,
|
||||
requireAccessCode = store.inject(DaggerGraphState::walletsRepository).requireAccessCode(),
|
||||
useBiometricAuthentication = store.inject(DaggerGraphState::walletsRepository).useBiometricAuthentication(),
|
||||
isHidingEnabled = store.inject(DaggerGraphState::balanceHidingRepository)
|
||||
.getBalanceHidingSettings().isHidingEnabledInSettings,
|
||||
needEnrollBiometrics = runCatching(tangemSdkManager::needEnrollBiometrics).getOrNull() == true,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.domain.models.wallet.UserWallet
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
|
||||
// FIXME: Workaround, remove it once the normal UserWalletsStore has been implemented
|
||||
// [REDACTED_JIRA]
|
||||
|
|
@ -28,10 +27,6 @@ internal class RuntimeUserWalletsStore(
|
|||
return requireNotNull(getSyncOrNull(key)) { "Unable to find user wallet with provided ID: $key" }
|
||||
}
|
||||
|
||||
override suspend fun getAllSyncOrNull(): List<UserWallet>? {
|
||||
return userWalletsListManager.userWallets.firstOrNull()
|
||||
}
|
||||
|
||||
override suspend fun update(
|
||||
userWalletId: UserWalletId,
|
||||
update: suspend (UserWallet) -> UserWallet,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
package com.tangem.tap.data
|
||||
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.catching
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
class UserWalletsStoreRepositoryProxy(
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
) : UserWalletsStore {
|
||||
|
||||
override val selectedUserWalletOrNull: UserWallet?
|
||||
get() = userWalletsListRepository.selectedUserWallet.value
|
||||
|
||||
override val userWallets: Flow<List<UserWallet>>
|
||||
get() = flow {
|
||||
userWalletsListRepository.load()
|
||||
userWalletsListRepository.userWallets.collect {
|
||||
emit(requireNotNull(it))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyncOrNull(key: UserWalletId): UserWallet? {
|
||||
return userWalletsListRepository.userWallets.value?.find { it.walletId == key }
|
||||
}
|
||||
|
||||
override fun getSyncStrict(key: UserWalletId): UserWallet {
|
||||
return requireNotNull(getSyncOrNull(key)) { "Unable to find user wallet with provided ID: $key" }
|
||||
}
|
||||
|
||||
override suspend fun update(
|
||||
userWalletId: UserWalletId,
|
||||
update: suspend (UserWallet) -> UserWallet,
|
||||
): CompletionResult<UserWallet> {
|
||||
return catching {
|
||||
val userWallet = userWalletsListRepository.userWallets.value?.find { it.walletId == userWalletId }
|
||||
requireNotNull(userWallet) { "Unable to find user wallet with provided ID: $userWalletId" }
|
||||
val updatedUserWallet = update(userWallet)
|
||||
userWalletsListRepository.saveWithoutLock(
|
||||
userWallet = updatedUserWallet,
|
||||
canOverride = true,
|
||||
)
|
||||
updatedUserWallet
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,10 @@ package com.tangem.tap.di.data
|
|||
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.tap.data.RuntimeUserWalletsStore
|
||||
import com.tangem.tap.data.UserWalletsStoreRepositoryProxy
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -15,7 +18,15 @@ internal object UserWalletsStoreModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideUserWalletsStore(userWalletsListManager: UserWalletsListManager): UserWalletsStore {
|
||||
return RuntimeUserWalletsStore(userWalletsListManager = userWalletsListManager)
|
||||
fun provideUserWalletsStore(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): UserWalletsStore {
|
||||
return if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
UserWalletsStoreRepositoryProxy(userWalletsListRepository)
|
||||
} else {
|
||||
RuntimeUserWalletsStore(userWalletsListManager = userWalletsListManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,7 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.domain.account.repository.AccountsCRUDRepository
|
||||
import com.tangem.domain.account.usecase.AddCryptoPortfolioUseCase
|
||||
import com.tangem.domain.account.usecase.ArchiveCryptoPortfolioUseCase
|
||||
import com.tangem.domain.account.usecase.RecoverCryptoPortfolioUseCase
|
||||
import com.tangem.domain.account.usecase.UpdateCryptoPortfolioUseCase
|
||||
import com.tangem.domain.account.usecase.*
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -44,4 +41,12 @@ internal object AccountDomainModule {
|
|||
): RecoverCryptoPortfolioUseCase {
|
||||
return RecoverCryptoPortfolioUseCase(crudRepository = accountsCRUDRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetUnoccupiedAccountIndexUseCase(
|
||||
accountsCRUDRepository: AccountsCRUDRepository,
|
||||
): GetUnoccupiedAccountIndexUseCase {
|
||||
return GetUnoccupiedAccountIndexUseCase(crudRepository = accountsCRUDRepository)
|
||||
}
|
||||
}
|
||||
|
|
@ -7,11 +7,13 @@ import com.tangem.domain.demo.models.DemoConfig
|
|||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetExtendedPublicKeyForCurrencyUseCase
|
||||
import com.tangem.domain.wallets.usecase.HasMissedDerivationsUseCase
|
||||
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
|
||||
import com.tangem.domain.wallets.usecase.NetworkHasDerivationUseCase
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.card.DefaultDeleteSavedAccessCodesUseCase
|
||||
import com.tangem.tap.domain.card.DefaultResetCardUseCase
|
||||
|
|
@ -42,9 +44,16 @@ internal object CardDomainModule {
|
|||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideIsNeedToBackupUseCase(userWalletsListManager: UserWalletsListManager): IsNeedToBackupUseCase {
|
||||
return IsNeedToBackupUseCase(userWalletsListManager = userWalletsListManager)
|
||||
fun provideIsNeedToBackupUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): IsNeedToBackupUseCase {
|
||||
return IsNeedToBackupUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ package com.tangem.tap.di.domain
|
|||
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
|
||||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles
|
||||
import com.tangem.tap.domain.scanCard.DefaultScanCardProcessor
|
||||
import com.tangem.tap.domain.scanCard.LegacyScanProcessor
|
||||
|
|
@ -31,7 +33,15 @@ internal object CardLegacyDomainModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesWalletNameGenerateUseCase(userWalletsListManager: UserWalletsListManager): GenerateWalletNameUseCase {
|
||||
return GenerateWalletNameUseCase(userWalletsListManager)
|
||||
fun providesWalletNameGenerateUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): GenerateWalletNameUseCase {
|
||||
return GenerateWalletNameUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,8 @@ import com.tangem.domain.staking.StakingIdFactory
|
|||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -81,10 +83,14 @@ object MarketsDomainModule {
|
|||
@Singleton
|
||||
fun provideFilterNetworksUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
): FilterAvailableNetworksForWalletUseCase {
|
||||
return FilterAvailableNetworksForWalletUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import com.tangem.domain.staking.repositories.StakingRepository
|
|||
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
|
||||
import com.tangem.domain.staking.single.SingleYieldBalanceSupplier
|
||||
import com.tangem.domain.tokens.*
|
||||
import com.tangem.domain.tokens.operations.BaseCurrenciesStatusesOperations
|
||||
import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations
|
||||
import com.tangem.domain.tokens.operations.CachedCurrenciesStatusesOperations
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
|
|
@ -98,11 +97,11 @@ internal object TokensDomainModule {
|
|||
@Singleton
|
||||
fun provideGetTokenListUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
baseCurrenciesStatusesOperations: BaseCurrenciesStatusesOperations,
|
||||
currenciesStatusesOperations: BaseCurrencyStatusOperations,
|
||||
): GetTokenListUseCase {
|
||||
return GetTokenListUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
currenciesStatusesOperations = baseCurrenciesStatusesOperations,
|
||||
currenciesStatusesOperations = currenciesStatusesOperations,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -370,9 +369,9 @@ internal object TokensDomainModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideGetWalletTotalBalanceUseCase(
|
||||
baseCurrenciesStatusesOperations: BaseCurrenciesStatusesOperations,
|
||||
currenciesStatusesOperations: BaseCurrencyStatusOperations,
|
||||
): GetWalletTotalBalanceUseCase {
|
||||
return GetWalletTotalBalanceUseCase(baseCurrenciesStatusesOperations)
|
||||
return GetWalletTotalBalanceUseCase(currenciesStatusesOperations)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
@ -400,42 +399,6 @@ internal object TokensDomainModule {
|
|||
return GetCurrencyCheckUseCase(currencyChecksRepository, dispatchers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideBaseCurrenciesStatusesOperations(
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
|
||||
singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
|
||||
multiYieldBalanceSupplier: MultiYieldBalanceSupplier,
|
||||
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
): BaseCurrenciesStatusesOperations {
|
||||
return CachedCurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
singleQuoteStatusSupplier = singleQuoteStatusSupplier,
|
||||
singleYieldBalanceSupplier = singleYieldBalanceSupplier,
|
||||
multiYieldBalanceSupplier = multiYieldBalanceSupplier,
|
||||
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideBaseCurrencyStatusOperations(
|
||||
|
|
|
|||
|
|
@ -191,6 +191,15 @@ internal object TransactionDomainModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providePrepareAndSignUseCase(
|
||||
transactionRepository: TransactionRepository,
|
||||
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
): PrepareAndSignUseCase {
|
||||
return PrepareAndSignUseCase(transactionRepository, cardSdkConfigRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSignUseCase(
|
||||
|
|
|
|||
|
|
@ -10,11 +10,13 @@ import com.tangem.domain.walletmanager.WalletManagersFacade
|
|||
import com.tangem.domain.wallets.delegate.DefaultUserWalletsSyncDelegate
|
||||
import com.tangem.domain.wallets.delegate.UserWalletsSyncDelegate
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.wallets.repository.WalletNamesMigrationRepository
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.domain.wallets.usecase.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.IsWalletNFTEnabledSyncUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletNameMigrationUseCase
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.operations.attestation.CardArtworksProvider
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
|
|
@ -31,18 +33,30 @@ internal object WalletsDomainModule {
|
|||
@Provides
|
||||
fun providesUserWalletsSyncDelegate(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): UserWalletsSyncDelegate {
|
||||
return DefaultUserWalletsSyncDelegate(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesGetWalletsUseCase(userWalletsListManager: UserWalletsListManager): GetWalletsUseCase {
|
||||
return GetWalletsUseCase(userWalletsListManager = userWalletsListManager)
|
||||
fun providesGetWalletsUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): GetWalletsUseCase {
|
||||
return GetWalletsUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewListRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
@ -50,37 +64,79 @@ internal object WalletsDomainModule {
|
|||
fun providesWalletNameMigrationUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
walletNamesMigrationRepository: WalletNamesMigrationRepository,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): WalletNameMigrationUseCase {
|
||||
return WalletNameMigrationUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
walletNamesMigrationRepository = walletNamesMigrationRepository,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewListRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesGetUserWalletUseCase(userWalletsListManager: UserWalletsListManager): GetUserWalletUseCase {
|
||||
return GetUserWalletUseCase(userWalletsListManager = userWalletsListManager)
|
||||
fun providesGetUserWalletUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): GetUserWalletUseCase {
|
||||
return GetUserWalletUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewListRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesGetSelectedWalletSyncUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): GetSelectedWalletSyncUseCase {
|
||||
return GetSelectedWalletSyncUseCase(userWalletsListManager = userWalletsListManager)
|
||||
return GetSelectedWalletSyncUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesGetSelectedWalletUseCase(userWalletsListManager: UserWalletsListManager): GetSelectedWalletUseCase {
|
||||
return GetSelectedWalletUseCase(userWalletsListManager = userWalletsListManager)
|
||||
fun providesGetSelectedWalletUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): GetSelectedWalletUseCase {
|
||||
return GetSelectedWalletUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesSaveWalletUseCase(userWalletsListManager: UserWalletsListManager): SaveWalletUseCase {
|
||||
return SaveWalletUseCase(userWalletsListManager = userWalletsListManager)
|
||||
fun providesSaveWalletUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
walletsRepository: WalletsRepository,
|
||||
): SaveWalletUseCase {
|
||||
return SaveWalletUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
walletsRepository = walletsRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesOpenBuyTangemCardUseCase(): GenerateBuyTangemCardLinkUseCase {
|
||||
return GenerateBuyTangemCardLinkUseCase()
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
@ -99,15 +155,30 @@ internal object WalletsDomainModule {
|
|||
@Singleton
|
||||
fun providesSelectWalletUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
reduxStateHolder: ReduxStateHolder,
|
||||
): SelectWalletUseCase {
|
||||
return SelectWalletUseCase(userWalletsListManager = userWalletsListManager, reduxStateHolder = reduxStateHolder)
|
||||
return SelectWalletUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
reduxStateHolder = reduxStateHolder,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesUpdateWalletUseCase(userWalletsListManager: UserWalletsListManager): UpdateWalletUseCase {
|
||||
return UpdateWalletUseCase(userWalletsListManager = userWalletsListManager)
|
||||
fun providesUpdateWalletUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): UpdateWalletUseCase {
|
||||
return UpdateWalletUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
@ -124,14 +195,30 @@ internal object WalletsDomainModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesGetWalletsSyncUseCase(userWalletsListManager: UserWalletsListManager): GetWalletNamesUseCase {
|
||||
return GetWalletNamesUseCase(userWalletsListManager = userWalletsListManager)
|
||||
fun providesGetWalletsSyncUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): GetWalletNamesUseCase {
|
||||
return GetWalletNamesUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesDeleteWalletUseCase(userWalletsListManager: UserWalletsListManager): DeleteWalletUseCase {
|
||||
return DeleteWalletUseCase(userWalletsListManager = userWalletsListManager)
|
||||
fun providesDeleteWalletUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): DeleteWalletUseCase {
|
||||
return DeleteWalletUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
@ -214,9 +301,13 @@ internal object WalletsDomainModule {
|
|||
@Singleton
|
||||
fun providesGetSavedWalletChangesIdUseCase(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): GetSavedWalletsCountUseCase {
|
||||
return GetSavedWalletsCountUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,9 +24,7 @@ import com.tangem.domain.wallets.derivations.derivationStyleProvider
|
|||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.visa.model.VisaActivationInput
|
||||
import com.tangem.domain.visa.model.VisaDataForApprove
|
||||
import com.tangem.domain.visa.model.VisaSignedDataByCustomerWallet
|
||||
import com.tangem.domain.visa.model.*
|
||||
import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
|
||||
import com.tangem.operations.ScanTask
|
||||
import com.tangem.operations.derivation.DerivationTaskResponse
|
||||
|
|
@ -501,7 +499,12 @@ internal class DefaultTangemSdkManager(
|
|||
): CompletionResult<VisaSignedDataByCustomerWallet> {
|
||||
return runTaskAsyncReturnOnMain(
|
||||
runnable = VisaCustomerWalletApproveTask(
|
||||
visaDataForApprove = visaDataForApprove,
|
||||
VisaCustomerWalletApproveTask.Input(
|
||||
cardId = visaDataForApprove.customerWalletCardId,
|
||||
targetAddress = visaDataForApprove.targetAddress,
|
||||
hashToSign = visaDataForApprove.dataToSign.hashToSign,
|
||||
sign = visaDataForApprove.dataToSign::sign,
|
||||
),
|
||||
),
|
||||
cardId = visaDataForApprove.customerWalletCardId,
|
||||
initialMessage = Message(resources.getStringSafe(R.string.initial_message_tap_header)),
|
||||
|
|
|
|||
|
|
@ -18,9 +18,7 @@ import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
|
|||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.visa.model.VisaActivationInput
|
||||
import com.tangem.domain.visa.model.VisaDataForApprove
|
||||
import com.tangem.domain.visa.model.VisaSignedDataByCustomerWallet
|
||||
import com.tangem.domain.visa.model.*
|
||||
import com.tangem.operations.derivation.DerivationTaskResponse
|
||||
import com.tangem.operations.preflightread.PreflightReadFilter
|
||||
import com.tangem.operations.wallet.CreateWalletResponse
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.domain.tasks.visa
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumUtils.toKeccak
|
||||
import com.tangem.blockchain.common.UnmarshalHelper
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.card.Card
|
||||
|
|
@ -10,7 +11,6 @@ import com.tangem.common.core.CardSession
|
|||
import com.tangem.common.core.CardSessionRunnable
|
||||
import com.tangem.common.core.CompletionCallback
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.common.extensions.toDecompressedPublicKey
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.core.error.ext.tangemError
|
||||
|
|
@ -22,15 +22,13 @@ import com.tangem.domain.card.common.visa.VisaWalletPublicKeyUtility
|
|||
import com.tangem.domain.card.common.visa.VisaWalletPublicKeyUtility.findKeyWithoutDerivation
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.visa.error.VisaActivationError
|
||||
import com.tangem.domain.visa.model.VisaDataForApprove
|
||||
import com.tangem.domain.visa.model.VisaSignedDataByCustomerWallet
|
||||
import com.tangem.domain.visa.model.sign
|
||||
import com.tangem.operations.ScanTask
|
||||
import com.tangem.operations.derivation.DeriveWalletPublicKeyTask
|
||||
import com.tangem.operations.sign.SignHashCommand
|
||||
|
||||
class VisaCustomerWalletApproveTask(
|
||||
private val visaDataForApprove: VisaDataForApprove,
|
||||
private val visaDataForApprove: Input,
|
||||
) : CardSessionRunnable<VisaSignedDataByCustomerWallet> {
|
||||
|
||||
override fun run(session: CardSession, callback: CompletionCallback<VisaSignedDataByCustomerWallet>) {
|
||||
|
|
@ -44,7 +42,7 @@ class VisaCustomerWalletApproveTask(
|
|||
return
|
||||
}
|
||||
|
||||
if (visaDataForApprove.customerWalletCardId != null && card.cardId != visaDataForApprove.customerWalletCardId) {
|
||||
if (visaDataForApprove.cardId != null && card.cardId != visaDataForApprove.cardId) {
|
||||
callback(CompletionResult.Failure(VisaActivationError.CardIdNotMatched.tangemError))
|
||||
return
|
||||
}
|
||||
|
|
@ -153,6 +151,12 @@ class VisaCustomerWalletApproveTask(
|
|||
)
|
||||
}
|
||||
|
||||
// TODO: [REDACTED_TASK_KEY] - Get this public function from Blockchain SDK
|
||||
private fun hashPersonalMessage(message: ByteArray): ByteArray {
|
||||
val prefix = "\u0019Ethereum Signed Message:\n${message.size}".toByteArray()
|
||||
return (prefix + message).toKeccak()
|
||||
}
|
||||
|
||||
private fun signApproveData(
|
||||
targetWalletPublicKey: ByteArray,
|
||||
derivationPath: DerivationPath?,
|
||||
|
|
@ -160,10 +164,11 @@ class VisaCustomerWalletApproveTask(
|
|||
session: CardSession,
|
||||
callback: CompletionCallback<VisaSignedDataByCustomerWallet>,
|
||||
) {
|
||||
val hashToSign = visaDataForApprove.dataToSign.hashToSign.hexToBytes()
|
||||
val content = "Tangem Pay wants to sign in with your account. Nonce: ${visaDataForApprove.hashToSign}"
|
||||
val hash = hashPersonalMessage(content.toByteArray(Charsets.UTF_8))
|
||||
|
||||
val signTask = SignHashCommand(
|
||||
hash = hashToSign,
|
||||
hash = hash,
|
||||
walletPublicKey = targetWalletPublicKey,
|
||||
derivationPath = derivationPath,
|
||||
)
|
||||
|
|
@ -173,7 +178,7 @@ class VisaCustomerWalletApproveTask(
|
|||
is CompletionResult.Success -> {
|
||||
val rsvSignature = UnmarshalHelper.unmarshalSignatureExtended(
|
||||
signature = result.data.signature,
|
||||
hash = hashToSign,
|
||||
hash = hash,
|
||||
publicKey = extendedPublicKey?.publicKey?.toDecompressedPublicKey()
|
||||
?: targetWalletPublicKey.toDecompressedPublicKey(),
|
||||
).asRSVLegacyEVM().toHexString().lowercase()
|
||||
|
|
@ -181,10 +186,7 @@ class VisaCustomerWalletApproveTask(
|
|||
scanCard(
|
||||
session = session,
|
||||
callback = callback,
|
||||
signedData = visaDataForApprove.dataToSign.sign(
|
||||
signature = rsvSignature,
|
||||
customerWalletAddress = visaDataForApprove.targetAddress,
|
||||
),
|
||||
signedData = visaDataForApprove.sign(rsvSignature, visaDataForApprove.targetAddress),
|
||||
)
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
|
|
@ -211,4 +213,11 @@ class VisaCustomerWalletApproveTask(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class Input(
|
||||
val cardId: String? = null,
|
||||
val targetAddress: String,
|
||||
val hashToSign: String,
|
||||
val sign: (signature: String, customerWalletAddress: String) -> VisaSignedDataByCustomerWallet,
|
||||
)
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import com.tangem.domain.visa.model.VisaCardActivationStatus
|
|||
import com.tangem.domain.wallets.hot.HotWalletPasswordRequester
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.wallets.hot.HotWalletAccessCodeAttemptsRepository
|
||||
import com.tangem.sdk.storage.AndroidSecureStorage
|
||||
import com.tangem.sdk.storage.AndroidSecureStorageV2
|
||||
import com.tangem.sdk.storage.createEncryptedSharedPreferences
|
||||
|
|
@ -119,6 +120,8 @@ internal object UserWalletsListManagerModule {
|
|||
@ApplicationContext applicationContext: Context,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
passwordRequester: HotWalletPasswordRequester,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
hotWalletAccessCodeAttemptsRepository: HotWalletAccessCodeAttemptsRepository,
|
||||
): UserWalletsListRepository {
|
||||
val moshi = buildMoshi()
|
||||
val secureStorage = buildSecureStorage(applicationContext = applicationContext)
|
||||
|
|
@ -162,8 +165,9 @@ internal object UserWalletsListManagerModule {
|
|||
passwordRequester = passwordRequester,
|
||||
userWalletEncryptionKeysRepository = userWalletEncryptionKeysRepository,
|
||||
tangemSdkManagerProvider = Provider { tangemSdkManager },
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
savePersistentInformation = ProviderSuspend { true }, // Always save persistent information for now
|
||||
// TODO add a settings toggle to disable saving persistent information
|
||||
hotWalletAccessCodeAttemptsRepository = hotWalletAccessCodeAttemptsRepository,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import com.tangem.common.doOnFailure
|
|||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.common.flatMap
|
||||
import com.tangem.common.map
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.datasource.local.preferences.utils.getSyncOrDefault
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
|
|
@ -22,6 +25,8 @@ import com.tangem.domain.core.wallets.error.SetLockError
|
|||
import com.tangem.domain.core.wallets.error.UnlockWalletError
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository.LockMethod
|
||||
import com.tangem.domain.wallets.hot.HotWalletAccessCodeAttemptsRepository
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.userWalletList.model.UserWalletEncryptionKey
|
||||
import com.tangem.tap.domain.userWalletList.utils.encryptionKey
|
||||
|
|
@ -30,10 +35,11 @@ import com.tangem.tap.domain.userWalletList.utils.toUserWallets
|
|||
import com.tangem.tap.domain.userWalletList.utils.updateWith
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.ProviderSuspend
|
||||
import com.tangem.utils.extensions.indexOfFirstOrNull
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Suppress("LongParameterList", "LargeClass")
|
||||
internal class DefaultUserWalletsListRepository(
|
||||
private val publicInformationRepository: UserWalletsPublicInformationRepository,
|
||||
private val sensitiveInformationRepository: UserWalletsSensitiveInformationRepository,
|
||||
|
|
@ -42,6 +48,8 @@ internal class DefaultUserWalletsListRepository(
|
|||
private val userWalletEncryptionKeysRepository: UserWalletEncryptionKeysRepository,
|
||||
private val tangemSdkManagerProvider: Provider<TangemSdkManager>,
|
||||
private val savePersistentInformation: ProviderSuspend<Boolean>,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val hotWalletAccessCodeAttemptsRepository: HotWalletAccessCodeAttemptsRepository,
|
||||
) : UserWalletsListRepository {
|
||||
|
||||
override val userWallets = MutableStateFlow<List<UserWallet>?>(null)
|
||||
|
|
@ -76,7 +84,9 @@ internal class DefaultUserWalletsListRepository(
|
|||
|
||||
override suspend fun userWalletsSync(): List<UserWallet> {
|
||||
load()
|
||||
return userWallets.value!!
|
||||
return requireNotNull(userWallets.value) {
|
||||
"This should never happen"
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun selectedUserWalletSync(): UserWallet? {
|
||||
|
|
@ -126,38 +136,46 @@ internal class DefaultUserWalletsListRepository(
|
|||
userWallet
|
||||
}
|
||||
|
||||
override suspend fun setLock(userWalletId: UserWalletId, lockMethod: LockMethod): Either<SetLockError, Unit> =
|
||||
either {
|
||||
val userWallet = userWallets.value?.find { it.walletId == userWalletId }
|
||||
?: raise(SetLockError.UserWalletNotFound)
|
||||
override suspend fun setLock(
|
||||
userWalletId: UserWalletId,
|
||||
lockMethod: LockMethod,
|
||||
changeUnsecured: Boolean,
|
||||
): Either<SetLockError, Unit> = either {
|
||||
val userWallet = userWallets.value?.find { it.walletId == userWalletId }
|
||||
?: raise(SetLockError.UserWalletNotFound)
|
||||
|
||||
val encryptionKey = userWallet.encryptionKey
|
||||
?: raise(SetLockError.UserWalletLocked)
|
||||
val encryptionKey = userWallet.encryptionKey
|
||||
?: raise(SetLockError.UserWalletLocked)
|
||||
|
||||
runCatching {
|
||||
userWalletEncryptionKeysRepository.save(
|
||||
encryptionKey = UserWalletEncryptionKey(
|
||||
walletId = userWalletId,
|
||||
encryptionKey = encryptionKey,
|
||||
),
|
||||
method = when (lockMethod) {
|
||||
is LockMethod.AccessCode -> {
|
||||
UserWalletEncryptionKeysRepository.EncryptionMethod.Password(lockMethod.accessCode)
|
||||
runCatching {
|
||||
userWalletEncryptionKeysRepository.save(
|
||||
encryptionKey = UserWalletEncryptionKey(
|
||||
walletId = userWalletId,
|
||||
encryptionKey = encryptionKey,
|
||||
),
|
||||
removeUnsecured = changeUnsecured,
|
||||
method = when (lockMethod) {
|
||||
is LockMethod.AccessCode -> {
|
||||
UserWalletEncryptionKeysRepository.EncryptionMethod.Password(lockMethod.accessCode)
|
||||
}
|
||||
LockMethod.Biometric -> {
|
||||
UserWalletEncryptionKeysRepository.EncryptionMethod.Biometric
|
||||
}
|
||||
LockMethod.NoLock -> {
|
||||
if (userWallet is UserWallet.Cold) {
|
||||
raise(SetLockError.UserWalletNotFound)
|
||||
}
|
||||
LockMethod.Biometric -> {
|
||||
UserWalletEncryptionKeysRepository.EncryptionMethod.Biometric
|
||||
}
|
||||
LockMethod.NoLock -> {
|
||||
if (userWallet is UserWallet.Cold) {
|
||||
raise(SetLockError.UserWalletNotFound)
|
||||
}
|
||||
|
||||
UserWalletEncryptionKeysRepository.EncryptionMethod.Unsecured
|
||||
}
|
||||
},
|
||||
)
|
||||
}.onFailure { raise(SetLockError.UnableToSetLock(it)) }
|
||||
}
|
||||
UserWalletEncryptionKeysRepository.EncryptionMethod.Unsecured
|
||||
}
|
||||
},
|
||||
)
|
||||
}.onFailure { raise(SetLockError.UnableToSetLock(it)) }
|
||||
}
|
||||
|
||||
override suspend fun removeBiometricLock(userWalletId: UserWalletId) {
|
||||
userWalletEncryptionKeysRepository.removeBiometricKey(userWalletId)
|
||||
}
|
||||
|
||||
override suspend fun delete(userWalletIds: List<UserWalletId>): Either<DeleteWalletError, Unit> = either {
|
||||
if (userWalletIds.isEmpty()) return Unit.right()
|
||||
|
|
@ -173,6 +191,8 @@ internal class DefaultUserWalletsListRepository(
|
|||
|
||||
userWalletEncryptionKeysRepository.delete(userWalletIds)
|
||||
|
||||
val userWalletsBeforeDelete = userWallets.value ?: return@either
|
||||
|
||||
userWallets.update { currentWallets ->
|
||||
currentWallets?.filterNot { it.walletId in userWalletIds }
|
||||
}
|
||||
|
|
@ -181,7 +201,7 @@ internal class DefaultUserWalletsListRepository(
|
|||
if (currentSelected == null) return@update null
|
||||
|
||||
userWallets.value?.findAvailableUserWallet(
|
||||
userWallets.value?.indexOfFirst { it.walletId == currentSelected.walletId } ?: 0,
|
||||
userWalletsBeforeDelete.indexOfFirstOrNull { it.walletId == currentSelected.walletId } ?: 0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -199,7 +219,7 @@ internal class DefaultUserWalletsListRepository(
|
|||
|
||||
when (unlockMethod) {
|
||||
UserWalletsListRepository.UnlockMethod.Biometric -> {
|
||||
unlockAllWallets()
|
||||
unlockAllWallets().bind()
|
||||
select(userWalletId)
|
||||
}
|
||||
UserWalletsListRepository.UnlockMethod.AccessCode -> {
|
||||
|
|
@ -208,6 +228,7 @@ internal class DefaultUserWalletsListRepository(
|
|||
}
|
||||
|
||||
val encryptionKey = requestPasswordRecursive(
|
||||
hotWalletId = userWallet.hotWalletId,
|
||||
block = { password ->
|
||||
runCatching {
|
||||
userWalletEncryptionKeysRepository.getEncryptedWithPassword(userWalletId, password)
|
||||
|
|
@ -224,8 +245,10 @@ internal class DefaultUserWalletsListRepository(
|
|||
return@either
|
||||
}
|
||||
|
||||
removePasswordAttempts(userWallet)
|
||||
|
||||
sensitiveInformationRepository.getAll(listOf(encryptionKey))
|
||||
.doOnSuccess { userWallets.value?.updateWith(it) }
|
||||
.doOnSuccess { sensitiveInfo -> userWallets.update { it?.updateWith(sensitiveInfo) } }
|
||||
.doOnFailure { error ->
|
||||
raise(UnlockWalletError.UnableToUnlock)
|
||||
}
|
||||
|
|
@ -255,6 +278,7 @@ internal class DefaultUserWalletsListRepository(
|
|||
}
|
||||
|
||||
override suspend fun unlockAllWallets(): Either<UnlockWalletError, Unit> = either {
|
||||
val userWalletIds = userWalletsSync().map { it.walletId }.toSet()
|
||||
val biometricKeys = runCatching {
|
||||
userWalletEncryptionKeysRepository.getAllBiometric()
|
||||
}.getOrElse {
|
||||
|
|
@ -263,9 +287,28 @@ internal class DefaultUserWalletsListRepository(
|
|||
}
|
||||
|
||||
val unsecuredKeys = userWalletEncryptionKeysRepository.getAllUnsecured()
|
||||
val allKeys = biometricKeys + unsecuredKeys
|
||||
val allKeys = (biometricKeys + unsecuredKeys).distinct()
|
||||
val unlockedWalletsIds = allKeys.map { it.walletId }
|
||||
|
||||
val unlockedWallets = unlockedWalletsIds.mapNotNull { id ->
|
||||
userWalletsSync().firstOrNull { it.walletId == id }
|
||||
}
|
||||
|
||||
// Remove all password attempts for unlocked hot wallets
|
||||
unlockedWallets.forEach {
|
||||
removePasswordAttempts(it)
|
||||
}
|
||||
|
||||
// if we cant unlock all wallets
|
||||
if (userWalletIds.all { it in unlockedWalletsIds }.not()) {
|
||||
raise(UnlockWalletError.UnableToUnlock)
|
||||
}
|
||||
|
||||
sensitiveInformationRepository.getAll(allKeys)
|
||||
.doOnSuccess { userWallets.value?.updateWith(it) }
|
||||
.doOnSuccess { sensitiveInfo ->
|
||||
userWallets.update { it?.updateWith(sensitiveInfo) }
|
||||
}
|
||||
.doOnFailure { raise(UnlockWalletError.UnableToUnlock) }
|
||||
}
|
||||
|
||||
override suspend fun lockAllWallets(): Either<LockWalletsError, Unit> = either {
|
||||
|
|
@ -293,12 +336,16 @@ internal class DefaultUserWalletsListRepository(
|
|||
}
|
||||
|
||||
private suspend fun requestPasswordRecursive(
|
||||
hotWalletId: HotWalletId,
|
||||
block: suspend (CharArray) -> UserWalletEncryptionKey?,
|
||||
biometryFallback: suspend () -> Either<UnlockWalletError, Unit>,
|
||||
): Either<UnlockWalletError, UserWalletEncryptionKey?> {
|
||||
val result = passwordRequester.requestPassword(
|
||||
hasBiometry = tangemSdkManagerProvider.invoke().needEnrollBiometrics,
|
||||
val attemptRequest = HotWalletPasswordRequester.AttemptRequest(
|
||||
hotWalletId = hotWalletId,
|
||||
authMode = true, // In auth mode user wallet can be deleted after 30 failed attempts
|
||||
hasBiometry = hasBiometry(),
|
||||
)
|
||||
val result = passwordRequester.requestPassword(attemptRequest)
|
||||
|
||||
return when (result) {
|
||||
HotWalletPasswordRequester.Result.Dismiss -> {
|
||||
|
|
@ -309,9 +356,10 @@ internal class DefaultUserWalletsListRepository(
|
|||
val decrypted = block(result.password.value)
|
||||
if (decrypted == null) {
|
||||
passwordRequester.wrongPassword()
|
||||
requestPasswordRecursive(block, biometryFallback)
|
||||
requestPasswordRecursive(hotWalletId, block, biometryFallback)
|
||||
} else {
|
||||
passwordRequester.successfulAuthentication()
|
||||
passwordRequester.dismiss()
|
||||
decrypted.right()
|
||||
}
|
||||
}
|
||||
|
|
@ -319,13 +367,28 @@ internal class DefaultUserWalletsListRepository(
|
|||
biometryFallback()
|
||||
.onRight {
|
||||
passwordRequester.successfulAuthentication()
|
||||
passwordRequester.dismiss()
|
||||
}
|
||||
passwordRequester.dismiss()
|
||||
null.right()
|
||||
.map { null }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun removePasswordAttempts(userWallet: UserWallet) {
|
||||
if (userWallet is UserWallet.Hot) {
|
||||
hotWalletAccessCodeAttemptsRepository.resetAttempts(userWallet.hotWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun hasBiometry(): Boolean {
|
||||
val useBiometricAuthentication = appPreferencesStore.getSyncOrDefault(
|
||||
key = PreferencesKeys.USE_BIOMETRIC_AUTHENTICATION_KEY,
|
||||
default = false,
|
||||
)
|
||||
|
||||
return tangemSdkManagerProvider.invoke().canUseBiometry && useBiometricAuthentication
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the nearest available wallet that can be selected
|
||||
*
|
||||
|
|
|
|||
|
|
@ -25,8 +25,14 @@ internal class UserWalletEncryptionKeysRepository(
|
|||
Types.newParameterizedType(List::class.java, UserWalletId::class.java),
|
||||
)
|
||||
|
||||
suspend fun save(encryptionKey: UserWalletEncryptionKey, method: EncryptionMethod) = withContext(dispatchers.io) {
|
||||
secureStorage.delete(StorageKey.UserWalletEncryptionKeyUnsecured(encryptionKey.walletId).name)
|
||||
suspend fun save(
|
||||
encryptionKey: UserWalletEncryptionKey,
|
||||
removeUnsecured: Boolean = true,
|
||||
method: EncryptionMethod,
|
||||
) = withContext(dispatchers.io) {
|
||||
if (removeUnsecured) {
|
||||
secureStorage.delete(StorageKey.UserWalletEncryptionKeyUnsecured(encryptionKey.walletId).name)
|
||||
}
|
||||
|
||||
when (method) {
|
||||
EncryptionMethod.Unsecured -> {
|
||||
|
|
@ -35,12 +41,6 @@ internal class UserWalletEncryptionKeysRepository(
|
|||
data = encryptionKey.encode(),
|
||||
)
|
||||
}
|
||||
EncryptionMethod.Biometric -> {
|
||||
authenticatedStorage.store(
|
||||
keyAlias = StorageKey.UserWalletEncryptionKey(encryptionKey.walletId).name,
|
||||
data = encryptionKey.encode(),
|
||||
)
|
||||
}
|
||||
is EncryptionMethod.Password -> {
|
||||
val encodedWithPass = AESEncryptionProtocol.encryptWithPassword(
|
||||
password = method.password,
|
||||
|
|
@ -51,26 +51,37 @@ internal class UserWalletEncryptionKeysRepository(
|
|||
data = encodedWithPass,
|
||||
)
|
||||
}
|
||||
EncryptionMethod.Biometric -> {
|
||||
authenticatedStorage.store(
|
||||
keyAlias = StorageKey.UserWalletEncryptionKey(encryptionKey.walletId).name,
|
||||
data = encryptionKey.encode(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
storeUserWalletId(userWalletId = encryptionKey.walletId)
|
||||
}
|
||||
|
||||
fun removeBiometricKey(userWalletId: UserWalletId) {
|
||||
authenticatedStorage.delete(StorageKey.UserWalletEncryptionKey(userWalletId).name)
|
||||
}
|
||||
|
||||
suspend fun getAllUnsecured(): List<UserWalletEncryptionKey> = withContext(dispatchers.io) {
|
||||
getUserWalletsIds().mapNotNull { userWalletId ->
|
||||
secureStorage.get(account = StorageKey.UserWalletEncryptionKeyUnsecured(userWalletId).name).decodeToKey()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getEncryptedWithPassword(userWalletId: UserWalletId, password: CharArray): UserWalletEncryptionKey? {
|
||||
val encrypted = secureStorage.get(
|
||||
account = StorageKey.UserWalletEncryptionKeyEncrypted(userWalletId).name,
|
||||
) ?: return null
|
||||
suspend fun getEncryptedWithPassword(userWalletId: UserWalletId, password: CharArray): UserWalletEncryptionKey? =
|
||||
withContext(dispatchers.io) {
|
||||
val encrypted = secureStorage.get(
|
||||
account = StorageKey.UserWalletEncryptionKeyEncrypted(userWalletId).name,
|
||||
) ?: return@withContext null
|
||||
|
||||
val decrypted = AESEncryptionProtocol.decryptWithPassword(password, encrypted)
|
||||
|
||||
return decrypted.decodeToKey()
|
||||
}
|
||||
withContext(dispatchers.default) {
|
||||
AESEncryptionProtocol.decryptWithPassword(password, encrypted).decodeToKey()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getAllBiometric(): List<UserWalletEncryptionKey> = withContext(dispatchers.io) {
|
||||
val keys = getUserWalletsIds().map { userWalletId ->
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ import com.tangem.common.CompletionResult
|
|||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.common.extensions.toDecompressedPublicKey
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.core.analytics.models.Basic.TransactionSent.MemoType
|
||||
import com.tangem.data.walletconnect.network.ethereum.LegacySdkHelper
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.operations.sign.SignHashCommand
|
||||
|
|
@ -42,7 +39,6 @@ import org.json.JSONArray
|
|||
import org.json.JSONObject
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
import com.tangem.core.analytics.models.AnalyticsParam as CoreAnalyticsParam
|
||||
|
||||
@Suppress("LargeClass")
|
||||
class WalletConnectSdkHelper {
|
||||
|
|
@ -227,8 +223,6 @@ class WalletConnectSdkHelper {
|
|||
)
|
||||
return when (result) {
|
||||
is Result.Success -> {
|
||||
val sentFrom = CoreAnalyticsParam.TxSentFrom.WalletConnect
|
||||
Analytics.send(Basic.TransactionSent(sentFrom = sentFrom, memoType = MemoType.Null))
|
||||
val hash = result.data.hash
|
||||
if (hash.startsWith(HEX_PREFIX)) {
|
||||
hash
|
||||
|
|
@ -394,7 +388,8 @@ class WalletConnectSdkHelper {
|
|||
signature = signedHash,
|
||||
hash = hashToSign,
|
||||
publicKey = wallet.publicKey.blockchainKey.toDecompressedPublicKey(),
|
||||
).asRSVLegacyEVM().toHexString().formatHex().lowercase() // use lowercase because some dapps cant handle UPPERCASE
|
||||
).asRSVLegacyEVM().toHexString().formatHex()
|
||||
.lowercase() // use lowercase because some dapps cant handle UPPERCASE
|
||||
}
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import com.tangem.domain.walletconnect.WcPairService
|
|||
import com.tangem.domain.walletconnect.model.legacy.WalletConnectSessionsRepository
|
||||
import com.tangem.domain.walletconnect.usecase.initialize.WcInitializeUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.features.walletconnect.components.WalletConnectFeatureToggles
|
||||
import com.tangem.tap.domain.walletconnect.WalletConnectSdkHelper
|
||||
import com.tangem.tap.domain.walletconnect2.app.TangemWcBlockchainHelper
|
||||
|
|
@ -42,9 +42,9 @@ internal object WalletConnectInteractorModule {
|
|||
wcSessionsRepository: WalletConnectSessionsRepository,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
walletConnectFeatureToggles: WalletConnectFeatureToggles,
|
||||
coroutineDispatcherProvider: CoroutineDispatcherProvider,
|
||||
getSelectedWalletUseCase: GetSelectedWalletUseCase,
|
||||
): WalletConnectInteractor {
|
||||
return WalletConnectInteractor(
|
||||
handler = WalletConnectEventsHandlerImpl(),
|
||||
|
|
@ -54,7 +54,7 @@ internal object WalletConnectInteractorModule {
|
|||
blockchainHelper = TangemWcBlockchainHelper(),
|
||||
currenciesRepository = currenciesRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
getSelectedWalletUseCase = getSelectedWalletUseCase,
|
||||
dispatchers = coroutineDispatcherProvider,
|
||||
walletConnectFeatureToggles = walletConnectFeatureToggles,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.domain.walletconnect.model.legacy.Account
|
|||
import com.tangem.domain.walletconnect.model.legacy.Session
|
||||
import com.tangem.domain.walletconnect.model.legacy.WalletConnectSessionsRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.features.walletconnect.components.WalletConnectFeatureToggles
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
@ -38,18 +37,14 @@ class WalletConnectInteractor(
|
|||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val walletConnectFeatureToggles: WalletConnectFeatureToggles,
|
||||
private val getSelectedWalletUseCase: GetSelectedWalletUseCase,
|
||||
val blockchainHelper: WcBlockchainHelper,
|
||||
) {
|
||||
private val isNewWc by lazy { walletConnectFeatureToggles.isRedesignedWalletConnectEnabled }
|
||||
|
||||
private var isWalletConnectReadyForDeepLinks = false
|
||||
|
||||
private val getSelectedWalletUseCase by lazy(LazyThreadSafetyMode.NONE) {
|
||||
GetSelectedWalletUseCase(userWalletsListManager)
|
||||
}
|
||||
|
||||
private val wcScope = CoroutineScope(
|
||||
SupervisorJob() + dispatchers.io + CoroutineExceptionHandler { _, throwable ->
|
||||
Timber.e("CoroutineException: from: LISTENER SCOPE, exception: $throwable")
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ import com.tangem.common.doOnSuccess
|
|||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository.LockMethod
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
|
|
@ -64,6 +66,14 @@ class DetailsMiddleware {
|
|||
when (action.setting) {
|
||||
AppSetting.SaveWallets -> toggleSaveWallets(state, enable = action.enable)
|
||||
AppSetting.SaveAccessCode -> toggleSaveAccessCodes(state, enable = action.enable)
|
||||
AppSetting.RequireAccessCode -> toggleRequireAccessCode(
|
||||
state = state,
|
||||
enable = action.enable,
|
||||
)
|
||||
AppSetting.BiometricAuthentication -> toggleBiometricsAuthentication(
|
||||
state = state,
|
||||
enable = action.enable,
|
||||
)
|
||||
}
|
||||
}
|
||||
is DetailsAction.AppSettings.CheckBiometricsStatus -> {
|
||||
|
|
@ -90,6 +100,91 @@ class DetailsMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun toggleBiometricsAuthentication(state: DetailsState, enable: Boolean) {
|
||||
scope.launch {
|
||||
val walletsRepository = store.inject(DaggerGraphState::walletsRepository)
|
||||
|
||||
// Nothing to change
|
||||
if (walletsRepository.useBiometricAuthentication() == enable) {
|
||||
store.dispatchWithMain(DetailsAction.AppSettings.SwitchPrivacySetting.Success)
|
||||
return@launch
|
||||
}
|
||||
|
||||
toggleRequireAccessCode(
|
||||
state = state,
|
||||
enable = true,
|
||||
)
|
||||
|
||||
if (enable) {
|
||||
setBiometricLockForAllWallets()
|
||||
} else {
|
||||
// Remove all biometric-related data
|
||||
removeAllBiometricData()
|
||||
}
|
||||
|
||||
walletsRepository.setUseBiometricAuthentication(value = enable)
|
||||
store.dispatchWithMain(DetailsAction.AppSettings.SwitchPrivacySetting.Success)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleRequireAccessCode(state: DetailsState, enable: Boolean) {
|
||||
scope.launch {
|
||||
val walletsRepository = store.inject(DaggerGraphState::walletsRepository)
|
||||
|
||||
// Nothing to change
|
||||
if (walletsRepository.requireAccessCode() == enable) {
|
||||
store.dispatchWithMain(DetailsAction.AppSettings.SwitchPrivacySetting.Success)
|
||||
return@launch
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
// Remove all biometric sign data
|
||||
removeAllBiometricSingData()
|
||||
toggleSaveAccessCodes(state, enable = false)
|
||||
} else {
|
||||
toggleSaveAccessCodes(state, enable = true)
|
||||
}
|
||||
|
||||
walletsRepository.setRequireAccessCode(value = enable)
|
||||
store.dispatchWithMain(DetailsAction.AppSettings.SwitchPrivacySetting.Success)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun setBiometricLockForAllWallets() {
|
||||
val userWalletsListRepository = store.inject(DaggerGraphState::userWalletsListRepository)
|
||||
val userWallets = userWalletsListRepository.userWalletsSync()
|
||||
userWallets.forEach {
|
||||
userWalletsListRepository.setLock(
|
||||
userWalletId = it.walletId,
|
||||
lockMethod = LockMethod.Biometric,
|
||||
changeUnsecured = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun removeAllBiometricData() {
|
||||
val userWalletsListRepository = store.inject(DaggerGraphState::userWalletsListRepository)
|
||||
userWalletsListRepository.userWalletsSync().forEach {
|
||||
userWalletsListRepository.removeBiometricLock(it.walletId)
|
||||
}
|
||||
removeAllBiometricSingData()
|
||||
}
|
||||
|
||||
private suspend fun removeAllBiometricSingData() {
|
||||
deleteSavedAccessCodes()
|
||||
val userWalletsListRepository = store.inject(DaggerGraphState::userWalletsListRepository)
|
||||
val tangemHotSdk = store.inject(DaggerGraphState::tangemHotSdk)
|
||||
userWalletsListRepository.userWalletsSync().forEach {
|
||||
if (it is UserWallet.Hot) {
|
||||
userWalletsListRepository.saveWithoutLock(
|
||||
userWallet = it.copy(
|
||||
hotWalletId = tangemHotSdk.removeBiometryAuthIfPresented(it.hotWalletId),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeBiometricsStatusChanges(scope: CoroutineScope) {
|
||||
val needEnrollBiometricsFlow = flow {
|
||||
do {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ private fun handlePrepareScreen(action: DetailsAction.PrepareScreen): DetailsSta
|
|||
)
|
||||
}
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: DetailsState): DetailsState {
|
||||
return when (action) {
|
||||
is DetailsAction.AppSettings.SwitchPrivacySetting -> state.copy(
|
||||
|
|
@ -46,6 +47,14 @@ private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: Detail
|
|||
saveWallets = true, // User can't enable access codes saving without wallets saving
|
||||
saveAccessCodes = action.enable,
|
||||
)
|
||||
AppSetting.RequireAccessCode -> state.appSettingsState.copy(
|
||||
isInProgress = true,
|
||||
requireAccessCode = action.enable,
|
||||
)
|
||||
AppSetting.BiometricAuthentication -> state.appSettingsState.copy(
|
||||
isInProgress = true,
|
||||
useBiometricAuthentication = action.enable,
|
||||
)
|
||||
},
|
||||
)
|
||||
is DetailsAction.AppSettings.SwitchPrivacySetting.Success -> state.copy(
|
||||
|
|
@ -63,6 +72,14 @@ private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: Detail
|
|||
isInProgress = false,
|
||||
saveAccessCodes = action.prevState,
|
||||
)
|
||||
AppSetting.RequireAccessCode -> state.appSettingsState.copy(
|
||||
isInProgress = false,
|
||||
requireAccessCode = action.prevState,
|
||||
)
|
||||
AppSetting.BiometricAuthentication -> state.appSettingsState.copy(
|
||||
isInProgress = false,
|
||||
needEnrollBiometrics = action.prevState,
|
||||
)
|
||||
},
|
||||
)
|
||||
is DetailsAction.AppSettings.BiometricsStatusChanged -> state.copy(
|
||||
|
|
|
|||
|
|
@ -12,9 +12,14 @@ data class DetailsState(
|
|||
) : StateType
|
||||
|
||||
data class AppSettingsState(
|
||||
@Deprecated("Delete after hot wallet release")
|
||||
val saveWallets: Boolean = false,
|
||||
@Deprecated("Delete after hot wallet release")
|
||||
val saveAccessCodes: Boolean = false,
|
||||
@Deprecated("Delete after hot wallet release")
|
||||
val isBiometricsAvailable: Boolean = false,
|
||||
val requireAccessCode: Boolean = false,
|
||||
val useBiometricAuthentication: Boolean = false,
|
||||
val needEnrollBiometrics: Boolean = false,
|
||||
val isHidingEnabled: Boolean = false,
|
||||
val isInProgress: Boolean = false,
|
||||
|
|
@ -25,5 +30,5 @@ data class AppSettingsState(
|
|||
enum class SecurityOption { LongTap, PassCode, AccessCode }
|
||||
|
||||
enum class AppSetting {
|
||||
SaveWallets, SaveAccessCode
|
||||
SaveWallets, SaveAccessCode, RequireAccessCode, BiometricAuthentication,
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.features.details.ui.appsettings
|
||||
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Dialog
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -55,4 +56,37 @@ internal class AppSettingsDialogsFactory {
|
|||
onDismiss = onDismiss,
|
||||
)
|
||||
}
|
||||
|
||||
fun createDisableBiometricAuthenticationAlert(onDisable: () -> Unit, onDismiss: () -> Unit): Dialog.Alert {
|
||||
return Dialog.Alert(
|
||||
title = resourceReference(R.string.common_attention),
|
||||
description = resourceReference(
|
||||
R.string.app_settings_off_biometrics_alert_message,
|
||||
wrappedList(resourceReference(R.string.common_biometrics)),
|
||||
),
|
||||
confirmText = resourceReference(R.string.common_disable),
|
||||
onConfirm = onDisable,
|
||||
onDismiss = onDismiss,
|
||||
)
|
||||
}
|
||||
|
||||
fun createEnableRequireAccessCodeAlert(onEnable: () -> Unit, onDismiss: () -> Unit): Dialog.Alert {
|
||||
return Dialog.Alert(
|
||||
title = resourceReference(R.string.common_attention),
|
||||
description = resourceReference(R.string.app_settings_on_require_access_code_alert_message),
|
||||
confirmText = resourceReference(R.string.common_enable),
|
||||
onConfirm = { onEnable() },
|
||||
onDismiss = onDismiss,
|
||||
)
|
||||
}
|
||||
|
||||
fun createDisableRequireAccessCodeAlert(onDisable: () -> Unit, onDismiss: () -> Unit): Dialog.Alert {
|
||||
return Dialog.Alert(
|
||||
title = resourceReference(R.string.common_attention),
|
||||
description = resourceReference(R.string.app_settings_off_require_access_code_alert_message),
|
||||
confirmText = resourceReference(R.string.common_disable),
|
||||
onConfirm = { onDisable() },
|
||||
onDismiss = onDismiss,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.features.details.ui.appsettings
|
|||
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Item
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -33,6 +34,39 @@ internal class AppSettingsItemsFactory {
|
|||
)
|
||||
}
|
||||
|
||||
fun createUseBiometricsSwitch(
|
||||
isChecked: Boolean,
|
||||
isEnabled: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
): Item.Switch {
|
||||
return Item.Switch(
|
||||
id = ID_USE_BIOMETRICS_SWITCH,
|
||||
title = resourceReference(R.string.app_settings_enable_biometrics_title),
|
||||
description = resourceReference(
|
||||
R.string.app_settings_biometrics_footer,
|
||||
wrappedList(resourceReference(R.string.common_biometrics)),
|
||||
),
|
||||
isEnabled = isEnabled,
|
||||
isChecked = isChecked,
|
||||
onCheckedChange = onCheckedChange,
|
||||
)
|
||||
}
|
||||
|
||||
fun createRequireAccessCodeSwitch(
|
||||
isChecked: Boolean,
|
||||
isEnabled: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
): Item.Switch {
|
||||
return Item.Switch(
|
||||
id = ID_REQUIRE_ACCESS_CODE_SWITCH,
|
||||
title = resourceReference(R.string.app_settings_require_access_code),
|
||||
description = resourceReference(R.string.app_settings_require_access_code_footer),
|
||||
isEnabled = isEnabled,
|
||||
isChecked = isChecked,
|
||||
onCheckedChange = onCheckedChange,
|
||||
)
|
||||
}
|
||||
|
||||
fun createSaveAccessCodeSwitch(
|
||||
isChecked: Boolean,
|
||||
isEnabled: Boolean,
|
||||
|
|
@ -96,5 +130,7 @@ internal class AppSettingsItemsFactory {
|
|||
const val ID_FLIP_TO_HIDE_BALANCE_SWITCH = "flip_to_hide_balance_switch"
|
||||
const val ID_SELECT_APP_CURRENCY_BUTTON = "select_app_currency_button"
|
||||
const val ID_SELECT_THEME_MODE_BUTTON = "select_theme_mode_button"
|
||||
const val ID_USE_BIOMETRICS_SWITCH = "use_biometrics_switch"
|
||||
const val ID_REQUIRE_ACCESS_CODE_SWITCH = "require_access_code_switch"
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
|
|||
import com.tangem.domain.settings.CanUseBiometryUseCase
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
|
|
@ -51,6 +52,7 @@ internal class AppSettingsModel @Inject constructor(
|
|||
private val appThemeModeRepository: AppThemeModeRepository,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
private val appSettingsItemsAnalyticsSender: AppSettingsItemsAnalyticsSender,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) : Model(), StoreSubscriber<DetailsState> {
|
||||
|
||||
private val itemsFactory = AppSettingsItemsFactory()
|
||||
|
|
@ -109,20 +111,36 @@ internal class AppSettingsModel @Inject constructor(
|
|||
onClick = ::showAppCurrencySelector,
|
||||
).let(::add)
|
||||
|
||||
if (state.isBiometricsAvailable) {
|
||||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
val canUseBiometrics = !state.needEnrollBiometrics && !state.isInProgress
|
||||
|
||||
itemsFactory.createSaveWalletsSwitch(
|
||||
isChecked = state.saveWallets,
|
||||
itemsFactory.createUseBiometricsSwitch(
|
||||
isChecked = state.useBiometricAuthentication,
|
||||
isEnabled = canUseBiometrics,
|
||||
onCheckedChange = ::onSaveWalletsToggled,
|
||||
onCheckedChange = ::onBiometricAuthenticationToggled,
|
||||
).let(::add)
|
||||
|
||||
itemsFactory.createSaveAccessCodeSwitch(
|
||||
isChecked = state.saveAccessCodes,
|
||||
isEnabled = canUseBiometrics,
|
||||
onCheckedChange = ::onSaveAccessCodesToggled,
|
||||
itemsFactory.createRequireAccessCodeSwitch(
|
||||
isChecked = state.requireAccessCode,
|
||||
isEnabled = canUseBiometrics && state.useBiometricAuthentication,
|
||||
onCheckedChange = ::onRequireAccessCodeToggled,
|
||||
).let(::add)
|
||||
} else {
|
||||
if (state.isBiometricsAvailable) {
|
||||
val canUseBiometrics = !state.needEnrollBiometrics && !state.isInProgress
|
||||
|
||||
itemsFactory.createSaveWalletsSwitch(
|
||||
isChecked = state.saveWallets,
|
||||
isEnabled = canUseBiometrics,
|
||||
onCheckedChange = ::onSaveWalletsToggled,
|
||||
).let(::add)
|
||||
|
||||
itemsFactory.createSaveAccessCodeSwitch(
|
||||
isChecked = state.saveAccessCodes,
|
||||
isEnabled = canUseBiometrics,
|
||||
onCheckedChange = ::onSaveAccessCodesToggled,
|
||||
).let(::add)
|
||||
}
|
||||
}
|
||||
|
||||
itemsFactory.createFlipToHideBalanceSwitch(
|
||||
|
|
@ -168,6 +186,56 @@ internal class AppSettingsModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun onBiometricAuthenticationToggled(isChecked: Boolean) {
|
||||
// TODO : Uncomment and implement analytics event when ready
|
||||
// val param = AnalyticsParam.OnOffState(isChecked)
|
||||
// analyticsEventHandler.send(Settings.AppSettings.BiometricAuthenticationChanged(param))
|
||||
if (isChecked) {
|
||||
onSettingsToggled(AppSetting.BiometricAuthentication, enable = true)
|
||||
onSettingsToggled(AppSetting.RequireAccessCode, enable = true)
|
||||
} else {
|
||||
updateContentState {
|
||||
copy(
|
||||
dialog = dialogsFactory.createDisableBiometricAuthenticationAlert(
|
||||
onDisable = {
|
||||
onSettingsToggled(AppSetting.BiometricAuthentication, enable = false)
|
||||
onSettingsToggled(AppSetting.RequireAccessCode, enable = true)
|
||||
dismissDialog()
|
||||
},
|
||||
onDismiss = ::dismissDialog,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onRequireAccessCodeToggled(isChecked: Boolean) {
|
||||
// TODO : Uncomment and implement analytics event when ready
|
||||
// val param = AnalyticsParam.OnOffState(isChecked)
|
||||
// analyticsEventHandler.send(Settings.AppSettings.RequireAccessCodeChanged(param))
|
||||
updateContentState {
|
||||
copy(
|
||||
dialog = if (isChecked) {
|
||||
dialogsFactory.createEnableRequireAccessCodeAlert(
|
||||
onEnable = {
|
||||
onSettingsToggled(AppSetting.RequireAccessCode, enable = true)
|
||||
dismissDialog()
|
||||
},
|
||||
onDismiss = ::dismissDialog,
|
||||
)
|
||||
} else {
|
||||
dialogsFactory.createDisableRequireAccessCodeAlert(
|
||||
onDisable = {
|
||||
onSettingsToggled(AppSetting.RequireAccessCode, enable = false)
|
||||
dismissDialog()
|
||||
},
|
||||
onDismiss = ::dismissDialog,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSaveWalletsToggled(isChecked: Boolean) {
|
||||
if (isChecked) {
|
||||
onSettingsToggled(AppSetting.SaveWallets, enable = true)
|
||||
|
|
@ -236,6 +304,8 @@ internal class AppSettingsModel @Inject constructor(
|
|||
saveWallets = walletsRepository.shouldSaveUserWalletsSync(),
|
||||
saveAccessCodes = settingsRepository.shouldSaveAccessCodes(),
|
||||
isBiometricsAvailable = canUseBiometryUseCase(),
|
||||
useBiometricAuthentication = walletsRepository.useBiometricAuthentication(),
|
||||
requireAccessCode = walletsRepository.requireAccessCode(),
|
||||
isHidingEnabled = balanceHidingRepository.getBalanceHidingSettings().isHidingEnabledInSettings,
|
||||
selectedAppCurrency = appCurrencyRepository.getSelectedAppCurrency().firstOrNull() ?: AppCurrency.Default,
|
||||
selectedThemeMode = appThemeModeRepository.getAppThemeMode().firstOrNull() ?: AppThemeMode.DEFAULT,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ class TangemHotSDKProxy @Inject constructor() : TangemHotSdk {
|
|||
override suspend fun changeAuth(unlockHotWallet: UnlockHotWallet, auth: HotAuth): HotWalletId =
|
||||
callSdk { changeAuth(unlockHotWallet, auth) }
|
||||
|
||||
override suspend fun removeBiometryAuthIfPresented(id: HotWalletId): HotWalletId =
|
||||
callSdk { removeBiometryAuthIfPresented(id) }
|
||||
|
||||
override suspend fun derivePublicKey(
|
||||
unlockHotWallet: UnlockHotWallet,
|
||||
request: DeriveWalletRequest,
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ import com.tangem.common.routing.utils.popTo
|
|||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.domain.card.analytics.ParamCardCurrencyConverter
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
|
||||
import com.tangem.domain.wallets.legacy.unlockIfLockable
|
||||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.features.intentHandler.handlers.WalletConnectLinkIntentHandler
|
||||
|
|
|
|||
|
|
@ -4,11 +4,16 @@ import com.tangem.common.extensions.toHexString
|
|||
import com.tangem.datasource.api.common.AuthProvider
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
|
||||
internal class DefaultAuthProvider(private val userWalletsListManager: UserWalletsListManager) : AuthProvider {
|
||||
internal class DefaultAuthProvider(
|
||||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val useNewListRepository: Boolean = false,
|
||||
) : AuthProvider {
|
||||
|
||||
override fun getCardPublicKey(): String {
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync
|
||||
override suspend fun getCardPublicKey(): String {
|
||||
val userWallet = getSelectedWallet()
|
||||
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return ""
|
||||
|
|
@ -17,8 +22,8 @@ internal class DefaultAuthProvider(private val userWalletsListManager: UserWalle
|
|||
return userWallet.scanResponse.card.cardPublicKey.toHexString()
|
||||
}
|
||||
|
||||
override fun getCardId(): String {
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync
|
||||
override suspend fun getCardId(): String {
|
||||
val userWallet = getSelectedWallet()
|
||||
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return ""
|
||||
|
|
@ -27,9 +32,25 @@ internal class DefaultAuthProvider(private val userWalletsListManager: UserWalle
|
|||
return userWallet.scanResponse.card.cardId
|
||||
}
|
||||
|
||||
override fun getCardsPublicKeys(): Map<String, String> {
|
||||
return userWalletsListManager.userWalletsSync.filterIsInstance<UserWallet.Cold>().associate {
|
||||
override suspend fun getCardsPublicKeys(): Map<String, String> {
|
||||
return getWallets().filterIsInstance<UserWallet.Cold>().associate {
|
||||
it.scanResponse.card.cardId to it.scanResponse.card.cardPublicKey.toHexString()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getWallets(): List<UserWallet> {
|
||||
return if (useNewListRepository) {
|
||||
userWalletsListRepository.userWalletsSync()
|
||||
} else {
|
||||
userWalletsListManager.userWalletsSync
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getSelectedWallet(): UserWallet? {
|
||||
return if (useNewListRepository) {
|
||||
userWalletsListRepository.selectedUserWalletSync()
|
||||
} else {
|
||||
userWalletsListManager.selectedUserWalletSync
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,8 @@ package com.tangem.tap.network.auth.di
|
|||
import com.tangem.datasource.api.common.AuthProvider
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.lib.auth.ExpressAuthProvider
|
||||
import com.tangem.lib.auth.StakeKitAuthProvider
|
||||
import com.tangem.tap.network.auth.DefaultAppVersionProvider
|
||||
|
|
@ -22,8 +24,16 @@ internal class AuthModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAuthProvider(userWalletsListManager: UserWalletsListManager): AuthProvider {
|
||||
return DefaultAuthProvider(userWalletsListManager)
|
||||
fun provideAuthProvider(
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
): AuthProvider {
|
||||
return DefaultAuthProvider(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
useNewListRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.tangem.domain.models.wallet.UserWallet
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.transaction.models.AssetRequirementsCondition
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.runCatching
|
||||
|
|
@ -130,6 +131,18 @@ internal class DefaultRampManager(
|
|||
}
|
||||
}
|
||||
|
||||
override fun checkAssetRequirements(requirements: AssetRequirementsCondition?): Boolean {
|
||||
return when (requirements) {
|
||||
AssetRequirementsCondition.PaidTransaction,
|
||||
is AssetRequirementsCondition.PaidTransactionWithFee,
|
||||
is AssetRequirementsCondition.RequiredTrustline,
|
||||
-> false
|
||||
is AssetRequirementsCondition.IncompleteTransaction,
|
||||
null,
|
||||
-> true
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getExchangeableState(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.tangem.domain.card.ScanCardProcessor
|
|||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
|
|
@ -31,7 +32,9 @@ import com.tangem.domain.walletmanager.WalletManagersFacade
|
|||
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
|
||||
import com.tangem.hot.sdk.TangemHotSdk
|
||||
import com.tangem.operations.attestation.CardArtworksProvider
|
||||
import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles
|
||||
import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository
|
||||
|
|
@ -77,4 +80,7 @@ data class DaggerGraphState(
|
|||
val cardArworksProvider: CardArtworksProvider? = null,
|
||||
val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory? = null,
|
||||
val userTokensResponseStore: UserTokensResponseStore? = null,
|
||||
val userWalletsListRepository: UserWalletsListRepository? = null,
|
||||
val hotWalletFeatureToggles: HotWalletFeatureToggles? = null,
|
||||
val tangemHotSdk: TangemHotSdk? = null,
|
||||
) : StateType
|
||||
|
|
@ -8,6 +8,7 @@ import com.tangem.feature.referral.api.ReferralComponent
|
|||
import com.tangem.feature.stories.api.StoriesComponent
|
||||
import com.tangem.feature.usedesk.api.UsedeskComponent
|
||||
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
|
||||
import com.tangem.features.account.ArchivedAccountListComponent
|
||||
import com.tangem.features.account.AccountCreateEditComponent
|
||||
import com.tangem.features.account.AccountDetailsComponent
|
||||
import com.tangem.features.createwalletselection.CreateWalletSelectionComponent
|
||||
|
|
@ -17,8 +18,10 @@ import com.tangem.features.home.api.HomeComponent
|
|||
import com.tangem.features.hotwallet.AddExistingWalletComponent
|
||||
import com.tangem.features.hotwallet.CreateMobileWalletComponent
|
||||
import com.tangem.features.hotwallet.WalletActivationComponent
|
||||
import com.tangem.features.hotwallet.WalletBackupComponent
|
||||
import com.tangem.features.hotwallet.CreateWalletBackupComponent
|
||||
import com.tangem.features.hotwallet.UpdateAccessCodeComponent
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.features.hotwallet.WalletBackupComponent
|
||||
import com.tangem.features.managetokens.component.ChooseManagedTokensComponent
|
||||
import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||
import com.tangem.features.managetokens.component.ManageTokensSource
|
||||
|
|
@ -36,6 +39,7 @@ import com.tangem.features.send.v2.api.SendEntryPointComponent
|
|||
import com.tangem.features.staking.api.StakingComponent
|
||||
import com.tangem.features.swap.SwapComponent
|
||||
import com.tangem.features.swap.v2.api.SendWithSwapComponent
|
||||
import com.tangem.features.tangempay.components.TangemPayDetailsComponent
|
||||
import com.tangem.features.tokendetails.TokenDetailsComponent
|
||||
import com.tangem.features.wallet.WalletEntryComponent
|
||||
import com.tangem.features.walletconnect.components.WalletConnectEntryComponent
|
||||
|
|
@ -52,6 +56,7 @@ import com.tangem.tap.routing.component.RoutingComponent.Child
|
|||
import dagger.hilt.android.scopes.ActivityScoped
|
||||
import javax.inject.Inject
|
||||
import com.tangem.features.walletconnect.components.WalletConnectEntryComponent as RedesignedWalletConnectComponent
|
||||
import com.tangem.features.welcome.WelcomeComponent as NewWelcomeComponent
|
||||
|
||||
@ActivityScoped
|
||||
@Suppress("LongParameterList", "LargeClass")
|
||||
|
|
@ -70,6 +75,7 @@ internal class ChildFactory @Inject constructor(
|
|||
private val swapSelectTokensComponentFactory: SwapSelectTokensComponent.Factory,
|
||||
private val onboardingEntryComponentFactory: OnboardingEntryComponent.Factory,
|
||||
private val welcomeComponentFactory: WelcomeComponent.Factory,
|
||||
private val newWelcomeComponentFactory: NewWelcomeComponent.Factory,
|
||||
private val storiesComponentFactory: StoriesComponent.Factory,
|
||||
private val stakingComponentFactory: StakingComponent.Factory,
|
||||
private val swapComponentFactory: SwapComponent.Factory,
|
||||
|
|
@ -90,6 +96,7 @@ internal class ChildFactory @Inject constructor(
|
|||
private val redesignedWalletConnectComponentFactory: WalletConnectEntryComponent.Factory,
|
||||
private val accountCreateEditComponentFactory: AccountCreateEditComponent.Factory,
|
||||
private val accountDetailsComponentFactory: AccountDetailsComponent.Factory,
|
||||
private val archivedAccountListComponentFactory: ArchivedAccountListComponent.Factory,
|
||||
private val nftComponentFactory: NFTComponent.Factory,
|
||||
private val nftSendComponentFactory: NFTSendComponent.Factory,
|
||||
private val usedeskComponentFactory: UsedeskComponent.Factory,
|
||||
|
|
@ -98,10 +105,13 @@ internal class ChildFactory @Inject constructor(
|
|||
private val createMobileWalletComponentFactory: CreateMobileWalletComponent.Factory,
|
||||
private val addExistingWalletComponentFactory: AddExistingWalletComponent.Factory,
|
||||
private val walletActivationComponentFactory: WalletActivationComponent.Factory,
|
||||
private val createWalletBackupComponentFactory: CreateWalletBackupComponent.Factory,
|
||||
private val updateAccessCodeComponentFactory: UpdateAccessCodeComponent.Factory,
|
||||
private val sendWithSwapComponentFactory: SendWithSwapComponent.Factory,
|
||||
private val sendEntryPointComponentFactory: SendEntryPointComponent.Factory,
|
||||
private val tangemPayDetailsComponentFactory: TangemPayDetailsComponent.Factory,
|
||||
private val walletConnectFeatureToggles: WalletConnectFeatureToggles,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) {
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
|
|
@ -138,14 +148,22 @@ internal class ChildFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
is AppRoute.Welcome -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = WelcomeComponent.Params(
|
||||
launchMode = route.launchMode,
|
||||
intent = route.intent,
|
||||
),
|
||||
componentFactory = welcomeComponentFactory,
|
||||
)
|
||||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = Unit,
|
||||
componentFactory = newWelcomeComponentFactory,
|
||||
)
|
||||
} else {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = WelcomeComponent.Params(
|
||||
launchMode = route.launchMode,
|
||||
intent = route.intent,
|
||||
),
|
||||
componentFactory = welcomeComponentFactory,
|
||||
)
|
||||
}
|
||||
}
|
||||
is AppRoute.WalletSettings -> {
|
||||
createComponentChild(
|
||||
|
|
@ -393,6 +411,7 @@ internal class ChildFactory @Inject constructor(
|
|||
context = context,
|
||||
params = PushNotificationsParams(
|
||||
modelCallbacks = PushNotificationsModelCallbacksStub(),
|
||||
source = route.source,
|
||||
nextRoute = AppRoute.Home(),
|
||||
),
|
||||
componentFactory = pushNotificationsComponentFactory,
|
||||
|
|
@ -483,6 +502,15 @@ internal class ChildFactory @Inject constructor(
|
|||
componentFactory = walletActivationComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.CreateWalletBackup -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = CreateWalletBackupComponent.Params(
|
||||
userWalletId = route.userWalletId,
|
||||
),
|
||||
componentFactory = createWalletBackupComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.UpdateAccessCode -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
|
|
@ -539,6 +567,22 @@ internal class ChildFactory @Inject constructor(
|
|||
componentFactory = accountDetailsComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.ArchivedAccountList -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = ArchivedAccountListComponent.Params(
|
||||
userWalletId = route.userWalletId,
|
||||
),
|
||||
componentFactory = archivedAccountListComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.TangemPayDetails -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = TangemPayDetailsComponent.Params(),
|
||||
componentFactory = tangemPayDetailsComponentFactory,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue