From 5bbbd9e945cd2cbfc1f445c1252330b987a64a7c Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 5 Oct 2023 17:41:54 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../viewmodels/AddCustomTokenViewModel.kt | 116 +++++++++++------- .../impl/data/DefaultTokensListRepository.kt | 39 +++--- .../impl/data/TangemApiTokensPagingSource.kt | 19 +-- .../impl/di/TokensListInteractorModule.kt | 6 +- .../impl/di/TokensListRepositoryModule.kt | 6 +- 5 files changed, 109 insertions(+), 77 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt index dffe1709dd..660be89b17 100644 --- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt @@ -22,6 +22,7 @@ import com.tangem.domain.common.extensions.* import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.features.addCustomToken.CustomCurrency +import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase import com.tangem.tap.domain.model.WalletDataModel import com.tangem.tap.features.customtoken.impl.domain.CustomTokenInteractor import com.tangem.tap.features.customtoken.impl.domain.models.FoundToken @@ -35,7 +36,6 @@ import com.tangem.tap.features.customtoken.impl.presentation.validators.ContactA import com.tangem.tap.features.customtoken.impl.presentation.validators.ContractAddressValidatorResult import com.tangem.tap.features.details.ui.cardsettings.TextReference import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.proxy.AppStateHolder import com.tangem.tap.store import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider import com.tangem.utils.coroutines.runCatching @@ -51,11 +51,11 @@ import javax.inject.Inject /** * ViewModel for add custom token screen * - * @param analyticsEventHandler analytics event handler - * @param featureRouter feature router - * @property featureInteractor feature interactor - * @property dispatchers coroutine dispatchers provider - * @property reduxStateHolder redux state holder + * @param analyticsEventHandler analytics event handler + * @param featureRouter feature router + * @property featureInteractor feature interactor + * @property getSelectedWalletUseCase use case that returns selected wallet + * @property dispatchers coroutine dispatchers provider * [REDACTED_AUTHOR] */ @@ -66,7 +66,7 @@ internal class AddCustomTokenViewModel @Inject constructor( featureRouter: CustomTokenRouter, private val featureInteractor: CustomTokenInteractor, private val dispatchers: AppCoroutineDispatcherProvider, - private val reduxStateHolder: AppStateHolder, + private val getSelectedWalletUseCase: GetSelectedWalletUseCase, ) : ViewModel(), DefaultLifecycleObserver { private val analyticsSender = AddCustomTokenAnalyticsSender(analyticsEventHandler) @@ -208,7 +208,10 @@ internal class AddCustomTokenViewModel @Inject constructor( private fun getNetworkSelectorItems(): List { val defaultNetwork = createNetworkSelectorItem(blockchain = Blockchain.Unknown) - val scanResponse = reduxStateHolder.scanResponse + val scanResponse = getSelectedWalletUseCase().fold( + ifLeft = { null }, + ifRight = { it.scanResponse }, + ) val derivationStyle = scanResponse?.derivationStyleProvider?.getDerivationStyle() return listOf(defaultNetwork) + Blockchain.values() .filter { blockchain -> @@ -262,17 +265,20 @@ internal class AddCustomTokenViewModel @Inject constructor( } private fun createDerivationPathsSelectorField(): AddCustomTokenSelectorField.DerivationPath? { - val scanResponse = reduxStateHolder.scanResponse - if (scanResponse?.card?.settings?.isHDWalletAllowed == false) return null + return getSelectedWalletUseCase().fold( + ifLeft = { null }, + ifRight = { + if (!it.scanResponse.card.settings.isHDWalletAllowed) return null - val selectorItems = - getDerivationPathsSelectorItems(scanResponse?.derivationStyleProvider) - return AddCustomTokenSelectorField.DerivationPath( - label = TextReference.Res(R.string.custom_token_derivation_path_input_title), - selectedItem = requireNotNull(selectorItems.firstOrNull()), - items = selectorItems, - onMenuItemClick = actionsHandler::onDerivationPathSelectorItemClick, - isEnabled = true, + val selectorItems = getDerivationPathsSelectorItems(it.scanResponse.derivationStyleProvider) + AddCustomTokenSelectorField.DerivationPath( + label = TextReference.Res(R.string.custom_token_derivation_path_input_title), + selectedItem = requireNotNull(selectorItems.firstOrNull()), + items = selectorItems, + onMenuItemClick = actionsHandler::onDerivationPathSelectorItemClick, + isEnabled = true, + ) + }, ) } @@ -315,14 +321,19 @@ internal class AddCustomTokenViewModel @Inject constructor( } private fun createDerivationPathInputField(): AddCustomTokenInputField.DerivationPath? { - if (reduxStateHolder.scanResponse?.card?.settings?.isHDWalletAllowed == false) return null + return getSelectedWalletUseCase().fold( + ifLeft = { null }, + ifRight = { + if (!it.scanResponse.card.settings.isHDWalletAllowed) return null - return AddCustomTokenInputField.DerivationPath( - value = "", - onValueChange = actionsHandler::onDerivationPathValueChange, - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - label = TextReference.Res(R.string.custom_token_custom_derivation), - placeholder = TextReference.Str(value = DERIVATION_PATH_PLACEHOLDER), + AddCustomTokenInputField.DerivationPath( + value = "", + onValueChange = actionsHandler::onDerivationPathValueChange, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + label = TextReference.Res(R.string.custom_token_custom_derivation), + placeholder = TextReference.Str(value = DERIVATION_PATH_PLACEHOLDER), + ) + }, ) } } @@ -440,11 +451,15 @@ internal class AddCustomTokenViewModel @Inject constructor( val isSupportedToken = if (!isNetworkSelected()) { true } else { - val scanResponse = reduxStateHolder.scanResponse - scanResponse?.card?.canHandleToken( - blockchain = networkSelectorValue, - cardTypesResolver = scanResponse.cardTypesResolver, - ) ?: false + getSelectedWalletUseCase().fold( + ifLeft = { false }, + ifRight = { + it.scanResponse.card.canHandleToken( + blockchain = networkSelectorValue, + cardTypesResolver = it.scanResponse.cardTypesResolver, + ) + }, + ) } return buildSet { @@ -478,13 +493,16 @@ internal class AddCustomTokenViewModel @Inject constructor( address = uiState.form.contractAddressInputField.value, blockchain = networkSelectorValue, ) - val scanResponse = reduxStateHolder.scanResponse - val isSupportedToken = scanResponse?.card - ?.canHandleToken( - blockchain = networkSelectorValue, - cardTypesResolver = scanResponse.cardTypesResolver, - ) - ?: false + + val isSupportedToken = getSelectedWalletUseCase().fold( + ifLeft = { false }, + ifRight = { + it.scanResponse.card.canHandleToken( + blockchain = networkSelectorValue, + cardTypesResolver = it.scanResponse.cardTypesResolver, + ) + }, + ) uiState.copySealed( floatingButton = uiState.floatingButton.copy( @@ -641,8 +659,12 @@ internal class AddCustomTokenViewModel @Inject constructor( private fun getDerivationPathForBlockchain(blockchain: Blockchain?): DerivationPath? { if (blockchain == null) return null - val derivationStyle = reduxStateHolder.scanResponse?.derivationStyleProvider?.getDerivationStyle() - ?: DerivationStyle.V1 + val derivationStyle = getSelectedWalletUseCase().fold( + ifLeft = { null }, + ifRight = { + it.scanResponse.derivationStyleProvider.getDerivationStyle() + }, + ) val derivationNetwork = if (blockchain == Blockchain.Unknown) { uiState.form.networkSelectorField.selectedItem.blockchain @@ -653,12 +675,15 @@ internal class AddCustomTokenViewModel @Inject constructor( } private fun isUnsupportedBlockchain(blockchain: Blockchain): Boolean { - val scanResponse = reduxStateHolder.scanResponse - val canHandleToken = scanResponse?.card?.canHandleBlockchain( - blockchain = blockchain, - cardTypesResolver = scanResponse.cardTypesResolver, - ) ?: false - return !canHandleToken + return getSelectedWalletUseCase().fold( + ifLeft = { false }, + ifRight = { + !it.scanResponse.card.canHandleBlockchain( + blockchain = blockchain, + cardTypesResolver = it.scanResponse.cardTypesResolver, + ) + }, + ) } private inner class ActionsHandler(private val featureRouter: CustomTokenRouter) { @@ -827,7 +852,6 @@ internal class AddCustomTokenViewModel @Inject constructor( } fun onResetButtonClick() { - val scanResponse = reduxStateHolder.scanResponse with(uiState.form) { uiState = uiState.copySealed( form = uiState.form.copy( diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/data/DefaultTokensListRepository.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/data/DefaultTokensListRepository.kt index 7ff7b78228..7f6ecf5aec 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/data/DefaultTokensListRepository.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/data/DefaultTokensListRepository.kt @@ -6,26 +6,26 @@ import androidx.paging.PagingData import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.local.testnet.TestnetTokensStorage import com.tangem.domain.common.TapWorkarounds.isTestCard +import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase import com.tangem.tap.features.tokens.impl.domain.TokensListRepository import com.tangem.tap.features.tokens.impl.domain.models.Token -import com.tangem.tap.proxy.AppStateHolder import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.Flow /** * Default repository implementation of tokens list feature * - * @property tangemTechApi Tangem Tech API - * @property dispatchers coroutine dispatchers provider - * @property reduxStateHolder redux state holder - * @property testnetTokensStorage storage for getting testnet tokens data + * @property tangemTechApi Tangem Tech API + * @property dispatchers coroutine dispatchers provider + * @property getSelectedWalletUseCase use case that returns selected wallet + * @property testnetTokensStorage storage for getting testnet tokens data * [REDACTED_AUTHOR] */ internal class DefaultTokensListRepository( private val tangemTechApi: TangemTechApi, private val dispatchers: CoroutineDispatcherProvider, - private val reduxStateHolder: AppStateHolder, + private val getSelectedWalletUseCase: GetSelectedWalletUseCase, private val testnetTokensStorage: TestnetTokensStorage, ) : TokensListRepository { @@ -37,16 +37,23 @@ internal class DefaultTokensListRepository( enablePlaceholders = false, ), pagingSourceFactory = { - if (reduxStateHolder.scanResponse?.card?.isTestCard == true) { - TestnetTokensPagingSource(testnetTokensStorage, searchText) - } else { - TangemApiTokensPagingSource( - api = tangemTechApi, - dispatchers = dispatchers, - reduxStateHolder = reduxStateHolder, - searchText = searchText, - ) - } + val defaultSource = TangemApiTokensPagingSource( + api = tangemTechApi, + dispatchers = dispatchers, + getSelectedWalletUseCase = getSelectedWalletUseCase, + searchText = searchText, + ) + + getSelectedWalletUseCase().fold( + ifLeft = { defaultSource }, + ifRight = { + if (it.scanResponse.card.isTestCard) { + TestnetTokensPagingSource(testnetTokensStorage, searchText) + } else { + defaultSource + } + }, + ) }, ).flow } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/data/TangemApiTokensPagingSource.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/data/TangemApiTokensPagingSource.kt index fb04538ee2..e36aaa66d5 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/data/TangemApiTokensPagingSource.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/data/TangemApiTokensPagingSource.kt @@ -7,24 +7,24 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.domain.common.extensions.supportedBlockchains import com.tangem.domain.common.extensions.toNetworkId import com.tangem.domain.common.util.cardTypesResolver +import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase import com.tangem.tap.features.tokens.impl.data.converters.CoinsResponseConverter import com.tangem.tap.features.tokens.impl.domain.models.Token -import com.tangem.tap.proxy.AppStateHolder import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.runCatching /** * Paging source that get tokens by Tangem Tech API * - * @property api Tangem Tech API - * @property dispatchers coroutine dispatchers provider - * @property reduxStateHolder redux state holder - * @property searchText search text + * @property api Tangem Tech API + * @property dispatchers coroutine dispatchers provider + * @property getSelectedWalletUseCase use case that returns selected wallet + * @property searchText search text */ internal class TangemApiTokensPagingSource( private val api: TangemTechApi, private val dispatchers: CoroutineDispatcherProvider, - private val reduxStateHolder: AppStateHolder, + private val getSelectedWalletUseCase: GetSelectedWalletUseCase, private val searchText: String?, ) : PagingSource() { @@ -39,9 +39,10 @@ internal class TangemApiTokensPagingSource( val page = params.key ?: 0 return runCatching(dispatchers.io) { - val scanResponse = reduxStateHolder.scanResponse - val supportedBlockchains = scanResponse?.card?.supportedBlockchains(scanResponse.cardTypesResolver) - ?: Blockchain.values().toList() + val supportedBlockchains = getSelectedWalletUseCase().fold( + ifLeft = { Blockchain.values().toList() }, + ifRight = { it.scanResponse.card.supportedBlockchains(it.scanResponse.cardTypesResolver) }, + ) api.getCoins( networkIds = supportedBlockchains.joinToString(separator = ",", transform = Blockchain::toNetworkId), diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/di/TokensListInteractorModule.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/di/TokensListInteractorModule.kt index 85fd22ab71..f588d3fc76 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/di/TokensListInteractorModule.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/di/TokensListInteractorModule.kt @@ -2,10 +2,10 @@ package com.tangem.tap.features.tokens.impl.di import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.local.testnet.TestnetTokensStorage +import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase import com.tangem.tap.features.tokens.impl.data.DefaultTokensListRepository import com.tangem.tap.features.tokens.impl.domain.DefaultTokensListInteractor import com.tangem.tap.features.tokens.impl.domain.TokensListInteractor -import com.tangem.tap.proxy.AppStateHolder import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides @@ -25,14 +25,14 @@ internal object TokensListInteractorModule { fun provideTokensListInteractor( tangemTechApi: TangemTechApi, dispatchers: CoroutineDispatcherProvider, - reduxStateHolder: AppStateHolder, + getSelectedWalletUseCase: GetSelectedWalletUseCase, testnetTokensStorage: TestnetTokensStorage, ): TokensListInteractor { return DefaultTokensListInteractor( repository = DefaultTokensListRepository( tangemTechApi = tangemTechApi, dispatchers = dispatchers, - reduxStateHolder = reduxStateHolder, + getSelectedWalletUseCase = getSelectedWalletUseCase, testnetTokensStorage = testnetTokensStorage, ), ) diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/di/TokensListRepositoryModule.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/di/TokensListRepositoryModule.kt index dbba8fe0dd..88443e8601 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/di/TokensListRepositoryModule.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/di/TokensListRepositoryModule.kt @@ -2,9 +2,9 @@ package com.tangem.tap.features.tokens.impl.di import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.local.testnet.TestnetTokensStorage +import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase import com.tangem.tap.features.tokens.impl.data.DefaultTokensListRepository import com.tangem.tap.features.tokens.impl.domain.TokensListRepository -import com.tangem.tap.proxy.AppStateHolder import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides @@ -24,13 +24,13 @@ internal object TokensListRepositoryModule { fun providesTokensListRepository( tangemTechApi: TangemTechApi, dispatchers: CoroutineDispatcherProvider, - reduxStateHolder: AppStateHolder, + getSelectedWalletUseCase: GetSelectedWalletUseCase, testnetTokensStorage: TestnetTokensStorage, ): TokensListRepository { return DefaultTokensListRepository( tangemTechApi = tangemTechApi, dispatchers = dispatchers, - reduxStateHolder = reduxStateHolder, + getSelectedWalletUseCase = getSelectedWalletUseCase, testnetTokensStorage = testnetTokensStorage, ) }