From c6578aa65247deb25b36c437931a125fb10d325e Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 26 Feb 2026 14:32:14 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/di/domain/ManageTokensDomainModule.kt | 43 --- .../tap/di/domain/MarketsDomainModule.kt | 36 --- .../tap/di/domain/TokensDomainModule.kt | 50 ---- .../DefaultCustomTokensRepository.kt | 41 --- .../managetokens/di/ManageTokensDataModule.kt | 5 - .../repository/DefaultCurrenciesRepository.kt | 148 ----------- ...emoveCustomManagedCryptoCurrencyUseCase.kt | 19 -- .../managetokens/SaveManagedTokensUseCase.kt | 174 ------------ .../repository/CustomTokensRepository.kt | 3 - .../domain/markets/SaveMarketTokensUseCase.kt | 145 ---------- .../tokens/AddCryptoCurrenciesUseCase.kt | 251 ------------------ .../tokens/ApplyTokenListSortingUseCase.kt | 115 -------- .../domain/tokens/RemoveCurrencyUseCase.kt | 60 ----- .../tokens/repository/CurrenciesRepository.kt | 64 ----- .../ApplyTokenListSortingUseCaseTest.kt | 207 --------------- .../repository/MockCurrenciesRepository.kt | 152 ----------- .../list/CustomTokenFormUseCasesFacade.kt | 12 +- .../utils/list/ManageTokensUseCasesFacade.kt | 20 +- .../model/OnrampAddToPortfolioModel.kt | 36 +-- .../referral/domain/ReferralInteractor.kt | 4 +- .../referral/domain/ReferralInteractorImpl.kt | 73 ++--- .../domain/di/ReferralDomainModule.kt | 9 - .../feature/referral/model/ReferralModel.kt | 50 ++-- .../v2/send/confirm/model/SendConfirmModel.kt | 24 +- .../tokendetails/model/TokenDetailsModel.kt | 26 +- .../factory/express/ExchangeStatusFactory.kt | 63 ++--- .../TokenDetailsExchangeStatusFactory.kt | 63 ++--- 27 files changed, 111 insertions(+), 1782 deletions(-) delete mode 100644 domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/RemoveCustomManagedCryptoCurrencyUseCase.kt delete mode 100644 domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt delete mode 100644 domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt delete mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt delete mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCase.kt delete mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RemoveCurrencyUseCase.kt delete mode 100644 domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCaseTest.kt delete mode 100644 domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockCurrenciesRepository.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt index b1d7b0a206..b527533fc1 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt @@ -3,20 +3,11 @@ package com.tangem.tap.di.domain import com.tangem.domain.managetokens.* import com.tangem.domain.managetokens.repository.CustomTokensRepository import com.tangem.domain.managetokens.repository.ManageTokensRepository -import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher -import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher -import com.tangem.domain.staking.StakingIdFactory -import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher -import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.domain.wallets.derivations.DerivationsRepository import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -57,40 +48,6 @@ internal object ManageTokensDomainModule { return CheckIsCurrencyNotAddedUseCase(customTokensRepository) } - @Provides - @Singleton - fun provideRemoveCustomManagedCryptoCurrencyUseCase( - customTokensRepository: CustomTokensRepository, - ): RemoveCustomManagedCryptoCurrencyUseCase { - return RemoveCustomManagedCryptoCurrencyUseCase(customTokensRepository) - } - - @Provides - @Singleton - fun provideSaveManagedTokensUseCase( - customTokensRepository: CustomTokensRepository, - walletManagersFacade: WalletManagersFacade, - currenciesRepository: CurrenciesRepository, - derivationsRepository: DerivationsRepository, - multiNetworkStatusFetcher: MultiNetworkStatusFetcher, - multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - multiStakingBalanceFetcher: MultiStakingBalanceFetcher, - stakingIdFactory: StakingIdFactory, - dispatchers: CoroutineDispatcherProvider, - ): SaveManagedTokensUseCase { - return SaveManagedTokensUseCase( - customTokensRepository = customTokensRepository, - walletManagersFacade = walletManagersFacade, - currenciesRepository = currenciesRepository, - derivationsRepository = derivationsRepository, - multiNetworkStatusFetcher = multiNetworkStatusFetcher, - multiQuoteStatusFetcher = multiQuoteStatusFetcher, - multiStakingBalanceFetcher = multiStakingBalanceFetcher, - stakingIdFactory = stakingIdFactory, - parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default), - ) - } - @Provides @Singleton fun provideGetSupportedNetworksUseCase( diff --git a/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt index d96861be6a..3be28c02e2 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt @@ -4,22 +4,12 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.markets.* import com.tangem.domain.markets.repositories.MarketsTokenRepository -import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.promo.PromoRepository -import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier -import com.tangem.domain.staking.StakingIdFactory -import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher -import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.domain.wallets.derivations.DerivationsRepository -import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob import javax.inject.Singleton @Module @@ -66,32 +56,6 @@ object MarketsDomainModule { return GetCurrencyQuotesUseCase(singleQuoteStatusSupplier = singleQuoteStatusSupplier) } - @Provides - @Singleton - fun provideSaveMarketTokensUseCase( - derivationsRepository: DerivationsRepository, - marketsTokenRepository: MarketsTokenRepository, - walletManagersFacade: WalletManagersFacade, - currenciesRepository: CurrenciesRepository, - multiNetworkStatusFetcher: MultiNetworkStatusFetcher, - multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - multiStakingBalanceFetcher: MultiStakingBalanceFetcher, - stakingIdFactory: StakingIdFactory, - dispatchers: CoroutineDispatcherProvider, - ): SaveMarketTokensUseCase { - return SaveMarketTokensUseCase( - derivationsRepository = derivationsRepository, - marketsTokenRepository = marketsTokenRepository, - walletManagersFacade = walletManagersFacade, - currenciesRepository = currenciesRepository, - multiNetworkStatusFetcher = multiNetworkStatusFetcher, - multiQuoteStatusFetcher = multiQuoteStatusFetcher, - multiStakingBalanceFetcher = multiStakingBalanceFetcher, - stakingIdFactory = stakingIdFactory, - parallelUpdatingScope = CoroutineScope(SupervisorJob() + dispatchers.default), - ) - } - @Provides @Singleton fun provideGetTokenMarketCryptoCurrency( diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index ecba7042ef..56bf1c96ba 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -40,28 +40,6 @@ import javax.inject.Singleton @Suppress("TooManyFunctions", "LargeClass") internal object TokensDomainModule { - @Provides - @Singleton - fun provideAddCryptoCurrenciesUseCase( - currenciesRepository: CurrenciesRepository, - walletManagersFacade: WalletManagersFacade, - multiNetworkStatusFetcher: MultiNetworkStatusFetcher, - multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - singleStakingBalanceFetcher: SingleStakingBalanceFetcher, - multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, - stakingIdFactory: StakingIdFactory, - ): AddCryptoCurrenciesUseCase { - return AddCryptoCurrenciesUseCase( - currenciesRepository = currenciesRepository, - walletManagersFacade = walletManagersFacade, - multiNetworkStatusFetcher = multiNetworkStatusFetcher, - multiQuoteStatusFetcher = multiQuoteStatusFetcher, - singleStakingBalanceFetcher = singleStakingBalanceFetcher, - multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier, - stakingIdFactory = stakingIdFactory, - ) - } - @Provides @Singleton fun provideFetchPendingTransactionsUseCase( @@ -88,20 +66,6 @@ internal object TokensDomainModule { ) } - @Provides - @Singleton - fun provideRemoveCurrencyUseCase( - currenciesRepository: CurrenciesRepository, - walletManagersFacade: WalletManagersFacade, - multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, - ): RemoveCurrencyUseCase { - return RemoveCurrencyUseCase( - currenciesRepository = currenciesRepository, - walletManagersFacade = walletManagersFacade, - multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier, - ) - } - @Provides @Singleton fun provideGetCurrencyUseCase( @@ -177,20 +141,6 @@ internal object TokensDomainModule { return GetCryptoCurrencyUseCase(currenciesRepository, multiWalletCryptoCurrenciesSupplier) } - @Provides - @Singleton - fun provideApplyTokenListSortingUseCase( - currenciesRepository: CurrenciesRepository, - multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, - dispatchers: CoroutineDispatcherProvider, - ): ApplyTokenListSortingUseCase { - return ApplyTokenListSortingUseCase( - currenciesRepository = currenciesRepository, - multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier, - dispatchers = dispatchers, - ) - } - @Provides @Singleton fun provideGetCryptoCurrencyActionsUseCase( diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt index 7725874819..492194a851 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultCustomTokensRepository.kt @@ -6,8 +6,6 @@ import com.tangem.blockchainsdk.utils.toBlockchain import com.tangem.blockchainsdk.utils.toNetworkId import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.data.common.currency.CryptoCurrencyFactory -import com.tangem.data.common.currency.UserTokensResponseFactory -import com.tangem.data.common.currency.UserTokensSaver import com.tangem.data.common.network.NetworkFactory import com.tangem.data.managetokens.utils.TokenAddressesConverter import com.tangem.datasource.api.common.response.getOrThrow @@ -26,7 +24,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.withContext @@ -35,10 +32,8 @@ internal class DefaultCustomTokensRepository( private val tangemTechApi: TangemTechApi, private val userWalletsListRepository: UserWalletsListRepository, private val userTokensResponseStore: UserTokensResponseStore, - private val walletManagersFacade: WalletManagersFacade, private val excludedBlockchains: ExcludedBlockchains, private val dispatchers: CoroutineDispatcherProvider, - private val userTokensSaver: UserTokensSaver, private val networkFactory: NetworkFactory, ) : CustomTokensRepository { @@ -48,7 +43,6 @@ internal class DefaultCustomTokensRepository( ) private val cryptoCurrencyFactory = CryptoCurrencyFactory(excludedBlockchains) - private val userTokensResponseFactory = UserTokensResponseFactory() private val tokenAddressConverter = TokenAddressesConverter() override suspend fun validateContractAddress(contractAddress: String, networkId: Network.ID): Boolean = @@ -213,41 +207,6 @@ internal class DefaultCustomTokensRepository( ) } - @Deprecated("Use ManageCryptoCurrenciesUseCase") - override suspend fun removeCurrency(userWalletId: UserWalletId, currency: ManagedCryptoCurrency.Custom) = - withContext(dispatchers.io) { - val cryptoCurrency = when (currency) { - is ManagedCryptoCurrency.Custom.Coin -> createCoin( - userWalletId = userWalletId, - networkId = currency.network.id, - derivationPath = currency.network.derivationPath, - ) - is ManagedCryptoCurrency.Custom.Token -> cryptoCurrencyFactory.createToken( - network = currency.network, - rawId = currency.currencyId.rawCurrencyId, - name = currency.name, - symbol = currency.symbol, - decimals = currency.decimals, - contractAddress = currency.contractAddress, - ) - } - val storedCurrencies = userTokensResponseStore.getSyncOrNull(userWalletId) - - requireNotNull(storedCurrencies) { - "User tokens not found for user wallet [$userWalletId] while removing currency" - } - - val token = userTokensResponseFactory.createResponseToken(currency = cryptoCurrency, accountId = null) - userTokensSaver.storeAndPush( - userWalletId = userWalletId, - response = storedCurrencies.copy(tokens = storedCurrencies.tokens.filterNot { it == token }), - ) - when (cryptoCurrency) { - is CryptoCurrency.Coin -> walletManagersFacade.remove(userWalletId, setOf(cryptoCurrency.network)) - is CryptoCurrency.Token -> walletManagersFacade.removeTokens(userWalletId, setOf(cryptoCurrency)) - } - } - override suspend fun convertToCryptoCurrency( userWalletId: UserWalletId, currency: ManagedCryptoCurrency.Custom, diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt index ea538bf3d2..bd5efcfcc6 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt @@ -15,7 +15,6 @@ import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.managetokens.repository.CustomTokensRepository import com.tangem.domain.managetokens.repository.ManageTokensRepository -import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides @@ -65,20 +64,16 @@ internal object ManageTokensDataModule { tangemTechApi: TangemTechApi, userWalletsListRepository: UserWalletsListRepository, userTokensResponseStore: UserTokensResponseStore, - walletManagersFacade: WalletManagersFacade, dispatchers: CoroutineDispatcherProvider, excludedBlockchains: ExcludedBlockchains, - userTokensSaver: UserTokensSaver, networkFactory: NetworkFactory, ): CustomTokensRepository { return DefaultCustomTokensRepository( tangemTechApi = tangemTechApi, userWalletsListRepository = userWalletsListRepository, userTokensResponseStore = userTokensResponseStore, - walletManagersFacade = walletManagersFacade, excludedBlockchains = excludedBlockchains, dispatchers = dispatchers, - userTokensSaver = userTokensSaver, networkFactory = networkFactory, ) } diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt index b2ec4a4968..3e5eadeda3 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt @@ -34,7 +34,6 @@ import com.tangem.domain.tokens.model.FeePaidCurrency import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import com.tangem.utils.coroutines.runSuspendCatching import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import timber.log.Timber @@ -66,134 +65,6 @@ internal class DefaultCurrenciesRepository( userTokensSaver = userTokensSaver, ) - override suspend fun saveTokens( - userWalletId: UserWalletId, - currencies: List, - isGroupedByNetwork: Boolean, - isSortedByBalance: Boolean, - ) = withContext(dispatchers.io) { - ensureIsCorrectUserWallet(userWalletId, isMultiCurrencyWalletExpected = true) - - val response = userTokensResponseFactory.createUserTokensResponse( - currencies = currencies, - isGroupedByNetwork = isGroupedByNetwork, - isSortedByBalance = isSortedByBalance, - ) - userTokensSaver.storeAndPush(userWalletId, response) - } - - override suspend fun addCurrenciesCache( - userWalletId: UserWalletId, - currencies: List, - ): List = withContext(dispatchers.io) { - val savedCurrencies = requireNotNull( - value = getSavedUserTokensResponseSync(key = userWalletId), - lazyMessage = { "Saved tokens empty. Can not perform add currencies action" }, - ) - - val currenciesToAdd = filterAlreadyAddedCurrencies( - savedCurrencies = savedCurrencies.tokens, - currenciesToAdd = populateCurrenciesWithMissedCoins(currencies = currencies), - ) - - val updatedResponse = savedCurrencies.copy( - tokens = savedCurrencies.tokens + currenciesToAdd.map(userTokensResponseFactory::createResponseToken), - ) - - userTokensSaver.store( - userWalletId = userWalletId, - response = updatedResponse, - ) - - fetchExpressAssetsByNetworkIds( - userWallet = userWalletsListRepository.getSyncStrict(id = userWalletId), - userTokens = updatedResponse, - ) - - currenciesToAdd - } - - private fun filterAlreadyAddedCurrencies( - savedCurrencies: List, - currenciesToAdd: List, - ): List { - return currenciesToAdd.filter { currency -> - val networkId = currency.network.toBlockchain().toNetworkId() - val contractAddress = (currency as? CryptoCurrency.Token)?.contractAddress - - savedCurrencies.none { token -> - token.contractAddress == contractAddress && - token.networkId == networkId && - token.derivationPath == currency.network.derivationPath.value - } - } - } - - private fun populateCurrenciesWithMissedCoins(currencies: List): List { - val currenciesSequence = currencies.asSequence() - - val networksWithTokens = currenciesSequence - .filterIsInstance() - .map { it.network } - .distinct() - - val networksWithCoins = currenciesSequence - .filterIsInstance() - .map { it.network } - .distinct() - - val networksNeedingCoins = (networksWithTokens - networksWithCoins.toSet()).toMutableList() - - if (networksNeedingCoins.isEmpty()) return currencies - - return buildList { - currencies.forEach { currency -> - if (currency is CryptoCurrency.Token && currency.network in networksNeedingCoins) { - val coin = cryptoCurrencyFactory.createCoin(currency.network) - add(coin) - - networksNeedingCoins.remove(currency.network) - } - - add(currency) - } - } - } - - override suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency) = - withContext(dispatchers.io) { - val savedCurrencies = requireNotNull( - value = getSavedUserTokensResponseSync(key = userWalletId), - lazyMessage = { "Saved tokens empty. Can not perform remove currency action" }, - ) - - val token = userTokensResponseFactory.createResponseToken(currency) - val updatedResponse = - savedCurrencies.copy(tokens = savedCurrencies.tokens.filterNot { it == token }) - userTokensSaver.storeAndPush( - userWalletId = userWalletId, - response = updatedResponse, - ) - } - - override suspend fun removeCurrencies(userWalletId: UserWalletId, currencies: List) { - return withContext(dispatchers.io) { - val savedCurrencies = requireNotNull( - value = getSavedUserTokensResponseSync(key = userWalletId), - lazyMessage = { "Saved tokens empty. Can not perform remove currencies action" }, - ) - - val tokens = currencies.map(userTokensResponseFactory::createResponseToken) - val updatedResponse = savedCurrencies.copy( - tokens = savedCurrencies.tokens.filterNot(tokens::contains), - ) - userTokensSaver.storeAndPush( - userWalletId = userWalletId, - response = updatedResponse, - ) - } - } - override fun getWalletCurrenciesUpdates(userWalletId: UserWalletId): Flow> { return channelFlow { val userWallet = userWalletsListRepository.getSyncStrict(userWalletId) @@ -577,19 +448,6 @@ internal class DefaultCurrenciesRepository( return blockchain?.isNetworkFeeZero() == true } - override suspend fun syncTokens(userWalletId: UserWalletId) { - runSuspendCatching { - val savedCurrencies = requireNotNull( - value = getSavedUserTokensResponseSync(key = userWalletId), - lazyMessage = { "Saved tokens empty. Can not perform add currencies action" }, - ) - userTokensSaver.storeAndPush( - userWalletId = userWalletId, - response = savedCurrencies, - ) - } - } - override fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver? { return (userWalletsListRepository.getSyncStrict(userWalletId) as? UserWallet.Cold)?.cardTypesResolver } @@ -712,12 +570,6 @@ internal class DefaultCurrenciesRepository( accountId = null, ) - private fun ensureIsCorrectUserWallet(userWalletId: UserWalletId, isMultiCurrencyWalletExpected: Boolean) { - val userWallet = userWalletsListRepository.getSyncStrict(userWalletId) - - ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected) - } - private fun ensureIsCorrectUserWallet(userWallet: UserWallet, isMultiCurrencyWalletExpected: Boolean) { val userWalletId = userWallet.walletId diff --git a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/RemoveCustomManagedCryptoCurrencyUseCase.kt b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/RemoveCustomManagedCryptoCurrencyUseCase.kt deleted file mode 100644 index b82f1cf58a..0000000000 --- a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/RemoveCustomManagedCryptoCurrencyUseCase.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.tangem.domain.managetokens - -import arrow.core.Either -import com.tangem.domain.managetokens.model.ManagedCryptoCurrency -import com.tangem.domain.managetokens.repository.CustomTokensRepository -import com.tangem.domain.models.wallet.UserWalletId - -@Deprecated("Use ManageCryptoCurrenciesUseCase") -class RemoveCustomManagedCryptoCurrencyUseCase(private val repository: CustomTokensRepository) { - - suspend operator fun invoke( - userWalletId: UserWalletId, - customCurrency: ManagedCryptoCurrency.Custom, - ): Either { - return Either.catch { - repository.removeCurrency(userWalletId, customCurrency) - } - } -} \ No newline at end of file diff --git a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt deleted file mode 100644 index 3fd2900bd7..0000000000 --- a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/SaveManagedTokensUseCase.kt +++ /dev/null @@ -1,174 +0,0 @@ -package com.tangem.domain.managetokens - -import arrow.core.Either -import arrow.core.flatten -import com.tangem.domain.managetokens.model.ManagedCryptoCurrency -import com.tangem.domain.managetokens.repository.CustomTokensRepository -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher -import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher -import com.tangem.domain.staking.StakingIdFactory -import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher -import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.domain.wallets.derivations.DerivationsRepository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.NonCancellable -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -@Deprecated("Use ManageCryptoCurrenciesUseCase") -@Suppress("LongParameterList") -class SaveManagedTokensUseCase( - private val customTokensRepository: CustomTokensRepository, - private val walletManagersFacade: WalletManagersFacade, - private val currenciesRepository: CurrenciesRepository, - private val derivationsRepository: DerivationsRepository, - private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher, - private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher, - private val stakingIdFactory: StakingIdFactory, - private val parallelUpdatingScope: CoroutineScope, -) { - - suspend operator fun invoke( - userWalletId: UserWalletId, - currenciesToAdd: Map>, - currenciesToRemove: Map>, - ): Either = Either.catch { - if (currenciesToRemove.isNotEmpty()) { - val removingCurrencies = currenciesToRemove.mapToCryptoCurrencies(userWalletId) - - currenciesRepository.removeCurrencies(userWalletId = userWalletId, currencies = removingCurrencies) - - removeCurrenciesFromWalletManager(userWalletId = userWalletId, currencies = removingCurrencies) - } - - if (currenciesToAdd.isNotEmpty()) { - derivationsRepository.derivePublicKeysByNetworks( - userWalletId = userWalletId, - networks = currenciesToAdd.values.flatten(), - ) - - val addingCurrencies = currenciesToAdd.mapToCryptoCurrencies(userWalletId) - - val savedCurrencies = currenciesRepository.addCurrenciesCache( - userWalletId = userWalletId, - currencies = addingCurrencies, - ) - - parallelUpdatingScope.launch { - withContext(NonCancellable) { - syncTokens(userWalletId = userWalletId, addedCurrencies = savedCurrencies) - - launch { - refreshUpdatedNetworks( - userWalletId = userWalletId, - addedCurrencies = savedCurrencies, - ) - } - launch { - refreshUpdatedStakingBalances( - userWalletId = userWalletId, - addedCurrencies = savedCurrencies, - ) - } - launch { refreshUpdatedQuotes(addedCurrencies = savedCurrencies) } - } - } - } - } - - private suspend fun removeCurrenciesFromWalletManager( - userWalletId: UserWalletId, - currencies: List, - ) { - walletManagersFacade.remove( - userWalletId = userWalletId, - networks = currencies - .filterIsInstance() - .mapTo(hashSetOf(), CryptoCurrency::network), - ) - - walletManagersFacade.removeTokens( - userWalletId = userWalletId, - tokens = currencies.filterIsInstance().toSet(), - ) - } - - private suspend fun syncTokens(userWalletId: UserWalletId, addedCurrencies: List) { - createWalletManagers(userWalletId = userWalletId, currencies = addedCurrencies) - currenciesRepository.syncTokens(userWalletId) - } - - /** - * Creates wallet managers for the given [currencies] if they do not already exist. - * The method will generate addresses for new networks to ensure the stability of the "Push notifications" feature. - * - * @param userWalletId The ID of the user's wallet. - * @param currencies The list of cryptocurrencies for which to create wallet managers. - */ - private suspend fun createWalletManagers(userWalletId: UserWalletId, currencies: List) { - val networks = currencies.mapTo(hashSetOf(), CryptoCurrency::network) - - for (network in networks) { - walletManagersFacade.getOrCreateWalletManager(userWalletId = userWalletId, network = network) - } - } - - private suspend fun refreshUpdatedNetworks(userWalletId: UserWalletId, addedCurrencies: List) { - multiNetworkStatusFetcher( - MultiNetworkStatusFetcher.Params( - userWalletId = userWalletId, - networks = addedCurrencies.map(CryptoCurrency::network).toSet(), - ), - ) - } - - private suspend fun refreshUpdatedStakingBalances( - userWalletId: UserWalletId, - addedCurrencies: List, - ) { - val stakingIds = addedCurrencies.mapNotNullTo(hashSetOf()) { - stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it).getOrNull() - } - - multiStakingBalanceFetcher( - params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds), - ) - } - - private suspend fun refreshUpdatedQuotes(addedCurrencies: List) { - multiQuoteStatusFetcher( - params = MultiQuoteStatusFetcher.Params( - currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId }, - appCurrencyId = null, - ), - ) - } - - private suspend fun Map>.mapToCryptoCurrencies( - userWalletId: UserWalletId, - ): List { - return flatMap { (token, networks) -> - token.availableNetworks - .filter { sourceNetwork -> networks.contains(sourceNetwork.network) } - .map { sourceNetwork -> - when (sourceNetwork) { - is ManagedCryptoCurrency.SourceNetwork.Default -> customTokensRepository.createToken( - managedCryptoCurrency = token, - sourceNetwork = sourceNetwork, - rawId = CryptoCurrency.RawID(token.id.value), - ) - is ManagedCryptoCurrency.SourceNetwork.Main -> customTokensRepository.createCoin( - userWalletId = userWalletId, - networkId = sourceNetwork.id, - derivationPath = sourceNetwork.network.derivationPath, - ) - } - } - } - } -} \ No newline at end of file diff --git a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/repository/CustomTokensRepository.kt b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/repository/CustomTokensRepository.kt index 2f6cb3035e..219d138628 100644 --- a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/repository/CustomTokensRepository.kt +++ b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/repository/CustomTokensRepository.kt @@ -43,9 +43,6 @@ interface CustomTokensRepository { formValues: AddCustomTokenForm.Validated.All, ): CryptoCurrency.Token - @Deprecated("Use ManageCryptoCurrenciesUseCase") - suspend fun removeCurrency(userWalletId: UserWalletId, currency: ManagedCryptoCurrency.Custom) - suspend fun convertToCryptoCurrency( userWalletId: UserWalletId, currency: ManagedCryptoCurrency.Custom, diff --git a/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt b/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt deleted file mode 100644 index 08b7e83e21..0000000000 --- a/domain/markets/src/main/java/com/tangem/domain/markets/SaveMarketTokensUseCase.kt +++ /dev/null @@ -1,145 +0,0 @@ -package com.tangem.domain.markets - -import arrow.core.Either -import com.tangem.domain.markets.repositories.MarketsTokenRepository -import com.tangem.domain.models.account.DerivationIndex -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher -import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher -import com.tangem.domain.staking.StakingIdFactory -import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher -import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.domain.wallets.derivations.DerivationsRepository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.NonCancellable -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -/** - * Use case for saving tokens from Markets - * - * @property derivationsRepository derivations repository - * @property marketsTokenRepository markets token repository - * @property currenciesRepository currencies repository - * -[REDACTED_AUTHOR] - */ -@Deprecated("Use ManageCryptoCurrenciesUseCase") -@Suppress("LongParameterList") -class SaveMarketTokensUseCase( - private val derivationsRepository: DerivationsRepository, - private val marketsTokenRepository: MarketsTokenRepository, - private val walletManagersFacade: WalletManagersFacade, - private val currenciesRepository: CurrenciesRepository, - private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher, - private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - private val multiStakingBalanceFetcher: MultiStakingBalanceFetcher, - private val stakingIdFactory: StakingIdFactory, - private val parallelUpdatingScope: CoroutineScope, -) { - - suspend operator fun invoke( - userWalletId: UserWalletId, - tokenMarketParams: TokenMarketParams, - addedNetworks: Set, - removedNetworks: Set, - ): Either = Either.catch { - if (removedNetworks.isNotEmpty()) { - val removedCurrencies = removedNetworks.mapNotNull { network -> - marketsTokenRepository.createCryptoCurrency( - userWalletId = userWalletId, - token = tokenMarketParams, - network = network, - ) - } - - currenciesRepository.removeCurrencies(userWalletId = userWalletId, currencies = removedCurrencies) - } - - if (addedNetworks.isNotEmpty()) { - derivationsRepository.derivePublicKeysByNetworkIds( - userWalletId = userWalletId, - networkIds = addedNetworks.map { Network.RawID(it.networkId) }, - accountIndex = DerivationIndex.Main, - ) - - val addedCurrencies = addedNetworks.mapNotNull { network -> - marketsTokenRepository.createCryptoCurrency( - userWalletId = userWalletId, - token = tokenMarketParams, - network = network, - accountIndex = DerivationIndex.Main, - ) - } - - val savedCurrencies = currenciesRepository.addCurrenciesCache( - userWalletId = userWalletId, - currencies = addedCurrencies, - ) - - parallelUpdatingScope.launch { - withContext(NonCancellable) { - syncTokens(userWalletId, savedCurrencies) - - launch { refreshUpdatedNetworks(userWalletId, savedCurrencies) } - launch { refreshUpdatedStakingBalances(userWalletId, savedCurrencies) } - launch { refreshUpdatedQuotes(savedCurrencies) } - } - } - } - } - - private suspend fun syncTokens(userWalletId: UserWalletId, addedCurrencies: List) { - createWalletManagers(userWalletId = userWalletId, currencies = addedCurrencies) - currenciesRepository.syncTokens(userWalletId) - } - - /** - * Creates wallet managers for the given [currencies] if they do not already exist. - * The method will generate addresses for new networks to ensure the stability of the "Push notifications" feature. - * - * @param userWalletId The ID of the user's wallet. - * @param currencies The list of cryptocurrencies for which to create wallet managers. - */ - private suspend fun createWalletManagers(userWalletId: UserWalletId, currencies: List) { - val networks = currencies.mapTo(hashSetOf(), CryptoCurrency::network) - - for (network in networks) { - walletManagersFacade.getOrCreateWalletManager(userWalletId = userWalletId, network = network) - } - } - - private suspend fun refreshUpdatedNetworks(userWalletId: UserWalletId, addedCurrencies: List) { - multiNetworkStatusFetcher( - MultiNetworkStatusFetcher.Params( - userWalletId = userWalletId, - networks = addedCurrencies.map(CryptoCurrency::network).toSet(), - ), - ) - } - - private suspend fun refreshUpdatedStakingBalances( - userWalletId: UserWalletId, - existingCurrencies: List, - ) { - val stakingIds = existingCurrencies.mapNotNullTo(hashSetOf()) { - stakingIdFactory.create(userWalletId = userWalletId, cryptoCurrency = it).getOrNull() - } - - multiStakingBalanceFetcher( - params = MultiStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingIds = stakingIds), - ) - } - - private suspend fun refreshUpdatedQuotes(addedCurrencies: List) { - multiQuoteStatusFetcher( - params = MultiQuoteStatusFetcher.Params( - currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId }, - appCurrencyId = null, - ), - ) - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt deleted file mode 100644 index 7473e2eb33..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/AddCryptoCurrenciesUseCase.kt +++ /dev/null @@ -1,251 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import arrow.core.getOrElse -import arrow.core.raise.Raise -import arrow.core.raise.catch -import arrow.core.raise.either -import arrow.core.right -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher -import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher -import com.tangem.domain.staking.StakingIdFactory -import com.tangem.domain.staking.single.SingleStakingBalanceFetcher -import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.walletmanager.WalletManagersFacade -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope - -/** - * A use case for adding multiple cryptocurrencies to a user's wallet. - * - * This use case interacts with the underlying repositories to both add currencies and refresh - * network statuses, particularly after the addition of new tokens. - */ -@Deprecated("Use ManageCryptoCurrenciesUseCase") -@Suppress("LongParameterList") -class AddCryptoCurrenciesUseCase( - private val currenciesRepository: CurrenciesRepository, - private val walletManagersFacade: WalletManagersFacade, - private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher, - private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher, - private val singleStakingBalanceFetcher: SingleStakingBalanceFetcher, - private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, - private val stakingIdFactory: StakingIdFactory, -) { - - /** - * Adds a [cryptoCurrency] token with specific [network] and derivation to the wallet identified by [userWalletId]. - * - * After successfully adding a currency, it also refreshes the networks for tokens - * that are being added and have corresponding coins in the existing currencies list. - * - * @param userWalletId The ID of the user's wallet. - * @param cryptoCurrency Token to add. - * @param network Network where we add - * @return Either an [Throwable] or [Unit] indicating the success of the operation. - */ - suspend operator fun invoke( - userWalletId: UserWalletId, - cryptoCurrency: CryptoCurrency.Token, - network: Network, - ): Either = either { - val tokenToAdd = currenciesRepository.createTokenCurrency(cryptoCurrency = cryptoCurrency, network = network) - invoke(userWalletId = userWalletId, currency = tokenToAdd) - } - - /** - * Adds a [currency] to the wallet identified by [userWalletId]. - * - * After successfully adding a currency, it also refreshes the networks for tokens - * that are being added and have corresponding coins in the existing currencies list. - * - * @param userWalletId The ID of the user's wallet. - * @param currency Cryptocurrency to add. - * @return Either an [Throwable] or [Unit] indicating the success of the operation. - */ - suspend operator fun invoke(userWalletId: UserWalletId, currency: CryptoCurrency): Either = - either { - val existingCurrencies = catch( - block = { currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId) }, - catch = ::raise, - ) - val currencyToAdd = currency.takeUnless(existingCurrencies::contains) ?: return@either - - val addedCurrencies = addCurrencies(userWalletId, currencyToAdd) - - coroutineScope { - syncTokens(userWalletId, addedCurrencies) - - awaitAll( - async { refreshUpdatedNetworks(userWalletId, currencyToAdd, existingCurrencies) }, - async { refreshUpdatedStakingBalances(userWalletId, currencyToAdd) }, - async { refreshUpdatedQuotes(currencyToAdd) }, - ) - } - } - - suspend operator fun invoke( - userWalletId: UserWalletId, - contractAddress: String, - networkId: String, - ): Either = either { - val existingCurrencies = catch( - block = { - multiWalletCryptoCurrenciesSupplier.getSyncOrNull( - params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId), - ) - .orEmpty() - .toList() - }, - catch = ::raise, - ) - - val foundToken = existingCurrencies - .filterIsInstance() - .firstOrNull { token -> - token.network.backendId == networkId && - !token.isCustom && - token.contractAddress.equals(contractAddress, true) - } - if (foundToken != null) { - return@either foundToken - } - val tokenToAdd = createTokenCurrency(userWalletId, contractAddress, networkId) - val addedCurrencies = addCurrencies(userWalletId, tokenToAdd) - - coroutineScope { - syncTokens(userWalletId = userWalletId, addedCurrencies = addedCurrencies) - - awaitAll( - async { refreshUpdatedNetworks(userWalletId, tokenToAdd, existingCurrencies) }, - async { refreshUpdatedStakingBalances(userWalletId, tokenToAdd) }, - async { refreshUpdatedQuotes(tokenToAdd) }, - ) - } - - tokenToAdd - } - - private suspend fun syncTokens(userWalletId: UserWalletId, addedCurrencies: List) { - createWalletManagers(userWalletId = userWalletId, currencies = addedCurrencies) - currenciesRepository.syncTokens(userWalletId) - } - - /** - * Creates wallet managers for the given [currencies] if they do not already exist. - * The method will generate addresses for new networks to ensure the stability of the "Push notifications" feature. - * - * @param userWalletId The ID of the user's wallet. - * @param currencies The list of cryptocurrencies for which to create wallet managers. - */ - private suspend fun createWalletManagers(userWalletId: UserWalletId, currencies: List) { - val networks = currencies.mapTo(hashSetOf(), CryptoCurrency::network) - - for (network in networks) { - walletManagersFacade.getOrCreateWalletManager(userWalletId = userWalletId, network = network) - } - } - - /** - * Refreshes the network statuses for tokens that have corresponding coins in the - * [existingCurrencies] list. - */ - private suspend fun refreshUpdatedNetworks( - userWalletId: UserWalletId, - currencyToAdd: CryptoCurrency, - existingCurrencies: List, - ) { - val networksToUpdate = currencyToAdd.takeIf { currency -> - currency is CryptoCurrency.Token && hasCoinForToken(existingCurrencies, currency) - } - ?.network - - val networkToUpdate = currencyToAdd.takeIf { - !existingCurrencies.map(CryptoCurrency::network).contains(it.network) - } - ?.network - - multiNetworkStatusFetcher( - MultiNetworkStatusFetcher.Params( - userWalletId = userWalletId, - networks = setOfNotNull(networksToUpdate, networkToUpdate), - ), - ) - } - - private suspend fun refreshUpdatedStakingBalances( - userWalletId: UserWalletId, - addedCurrency: CryptoCurrency, - ): Either = either { - val stakingId = stakingIdFactory.create( - userWalletId = userWalletId, - currencyId = addedCurrency.id, - network = addedCurrency.network, - ) - .getOrElse { error -> - when (error) { - is StakingIdFactory.Error.UnableToGetAddress -> raise(IllegalStateException("$error")) - StakingIdFactory.Error.UnsupportedCurrency -> Unit.right() - } - - return@either - } - - singleStakingBalanceFetcher( - params = SingleStakingBalanceFetcher.Params(userWalletId = userWalletId, stakingId = stakingId), - ) - .bind() - } - - private suspend fun refreshUpdatedQuotes(currencyToAdd: CryptoCurrency) { - multiQuoteStatusFetcher( - params = MultiQuoteStatusFetcher.Params( - currenciesIds = setOfNotNull(currencyToAdd.id.rawCurrencyId), - appCurrencyId = null, - ), - ) - } - - private suspend fun Raise.createTokenCurrency( - userWalletId: UserWalletId, - contractAddress: String, - networkId: String, - ): CryptoCurrency.Token { - return catch( - block = { - currenciesRepository.createTokenCurrency( - userWalletId = userWalletId, - contractAddress = contractAddress, - networkId = networkId, - ) - }, - catch = { - raise(it) - }, - ) - } - - private suspend fun Raise.addCurrencies( - userWalletId: UserWalletId, - currency: CryptoCurrency, - ): List { - return catch( - block = { currenciesRepository.addCurrenciesCache(userWalletId, listOf(currency)) }, - catch = ::raise, - ) - } - - /** - * Determines if the [existingCurrencies] list contains a coin that corresponds - * to the given [token]. - */ - private fun hasCoinForToken(existingCurrencies: List, token: CryptoCurrency.Token): Boolean { - return existingCurrencies.any { currency -> - currency is CryptoCurrency.Coin && currency.network == token.network - } - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCase.kt deleted file mode 100644 index e98428eee2..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCase.kt +++ /dev/null @@ -1,115 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import arrow.core.raise.Raise -import arrow.core.raise.catch -import arrow.core.raise.either -import arrow.core.raise.ensureNotNull -import arrow.core.toNonEmptyListOrNull -import arrow.core.toNonEmptySetOrNull -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.tokens.error.TokenListSortingError -import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.flow.firstOrNull -import kotlinx.coroutines.withContext - -@Deprecated("Use ApplyAccountListSortingUseCase") -class ApplyTokenListSortingUseCase( - private val currenciesRepository: CurrenciesRepository, - private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, - private val dispatchers: CoroutineDispatcherProvider, -) { - - suspend operator fun invoke( - userWalletId: UserWalletId, - sortedTokensIds: List, - isGroupedByNetwork: Boolean, - isSortedByBalance: Boolean, - ): Either { - return either { - val storedCurrencies = getCurrencies(userWalletId) - val isSortingTypeChanged = checkIsCurrenciesSortedByBalance(userWalletId) != isSortedByBalance - val isGroupingTypeChanged = checkIsCurrenciesGroupedByNetwork(userWalletId) != isGroupedByNetwork - - val sortedCurrencies = sortTokens(sortedTokensIds, storedCurrencies) - - if (storedCurrencies != sortedCurrencies || isSortingTypeChanged || isGroupingTypeChanged) { - applySorting( - userWalletId = userWalletId, - currencies = sortedCurrencies, - isGrouped = isGroupedByNetwork, - isSortedByBalance = isSortedByBalance, - ) - } - } - } - - private suspend fun Raise.checkIsCurrenciesSortedByBalance(userWalletId: UserWalletId) = - catch( - block = { currenciesRepository.isTokensSortedByBalance(userWalletId).firstOrNull() == true }, - catch = { raise(TokenListSortingError.DataError(it)) }, - ) - - private suspend fun Raise.checkIsCurrenciesGroupedByNetwork(userWalletId: UserWalletId) = - catch( - block = { currenciesRepository.isTokensGrouped(userWalletId).firstOrNull() == true }, - catch = { raise(TokenListSortingError.DataError(it)) }, - ) - - private suspend fun Raise.sortTokens( - sortedCurrenciesIds: List, - unsortedCurrencies: List, - ): List = withContext(dispatchers.default) { - val nonEmptySortedTokensIds = ensureNotNull(sortedCurrenciesIds.toNonEmptySetOrNull()) { - TokenListSortingError.TokenListIsEmpty - } - - val sortedTokens = sortedMapOf() - - unsortedCurrencies.distinct().forEach { currency -> - val index = nonEmptySortedTokensIds.indexOfFirst { currencyId -> - currencyId == currency.id - } - - if (index >= 0) { - sortedTokens[index] = currency - } else { - raise(TokenListSortingError.UnableToSortTokenList) - } - } - - ensureNotNull(sortedTokens.values.toNonEmptyListOrNull()) { - TokenListSortingError.TokenListIsEmpty - } - } - - private suspend fun Raise.getCurrencies(userWalletId: UserWalletId): List { - val tokens = catch( - block = { - multiWalletCryptoCurrenciesSupplier.getSyncOrNull( - params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId), - ) - .orEmpty() - }, - catch = { raise(TokenListSortingError.DataError(it)) }, - ) - - return ensureNotNull(tokens.toNonEmptyListOrNull()) { - TokenListSortingError.TokenListIsEmpty - } - } - - private suspend fun Raise.applySorting( - userWalletId: UserWalletId, - currencies: List, - isGrouped: Boolean, - isSortedByBalance: Boolean, - ) = withContext(dispatchers.io) { - catch( - block = { currenciesRepository.saveTokens(userWalletId, currencies, isGrouped, isSortedByBalance) }, - catch = { raise(TokenListSortingError.DataError(it)) }, - ) - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RemoveCurrencyUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RemoveCurrencyUseCase.kt deleted file mode 100644 index 1ff28dd2af..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RemoveCurrencyUseCase.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import arrow.core.raise.catch -import arrow.core.raise.either -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.tokens.model.remove.RemoveCurrencyError -import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.walletmanager.WalletManagersFacade - -@Deprecated("Use ManageCryptoCurrenciesUseCase") -class RemoveCurrencyUseCase( - private val currenciesRepository: CurrenciesRepository, - private val walletManagersFacade: WalletManagersFacade, - private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, -) { - - @Deprecated("Use ManageCryptoCurrenciesUseCase") - suspend operator fun invoke( - userWalletId: UserWalletId, - currency: CryptoCurrency, - ): Either { - return either { - if (hasLinkedTokens(userWalletId, currency)) { - raise(RemoveCurrencyError.HasLinkedTokens) - } - - catch( - block = { - currenciesRepository.removeCurrency(userWalletId, currency) - - when (currency) { - is CryptoCurrency.Coin -> { - walletManagersFacade.remove(userWalletId, setOf(currency.network)) - } - is CryptoCurrency.Token -> { - walletManagersFacade.removeTokens(userWalletId, setOf(currency)) - } - } - }, - catch = { raise(RemoveCurrencyError.DataError(it)) }, - ) - } - } - - suspend fun hasLinkedTokens(userWalletId: UserWalletId, currency: CryptoCurrency): Boolean { - return when (currency) { - is CryptoCurrency.Coin -> { - val walletCurrencies = multiWalletCryptoCurrenciesSupplier.getSyncOrNull( - params = MultiWalletCryptoCurrenciesProducer.Params(userWalletId), - ) - .orEmpty() - - walletCurrencies.any { it is CryptoCurrency.Token && it.network == currency.network } - } - is CryptoCurrency.Token -> false - } - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt index 91a762bc11..779e36f447 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt @@ -16,58 +16,6 @@ import kotlinx.coroutines.flow.Flow @Suppress("TooManyFunctions") interface CurrenciesRepository { - /** - * Saves the given list of cryptocurrencies, along with the preferences for grouping and sorting, for a specific - * multi-currency user wallet. - * - * @param userWalletId The unique identifier of the user wallet. - * @param currencies The list of cryptocurrencies to be saved. - * @param isGroupedByNetwork A boolean flag indicating whether the tokens should be grouped by network. - * @param isSortedByBalance A boolean flag indicating whether the tokens should be sorted by balance. - * @throws DataError.UserWalletError.WrongUserWallet If single-currency user wallet - * ID provided. - */ - @Deprecated("Use ManageCryptoCurrenciesUseCase") - suspend fun saveTokens( - userWalletId: UserWalletId, - currencies: List, - isGroupedByNetwork: Boolean, - isSortedByBalance: Boolean, - ) - - /** - * Add currencies to a specific user wallet. - * - * @param userWalletId The unique identifier of the user wallet. - * @param currencies The currencies which must be added. - * @throws DataError.UserWalletError.WrongUserWallet If single-currency user wallet - * ID provided. - */ - @Deprecated("Use ManageCryptoCurrenciesUseCase") - suspend fun addCurrenciesCache(userWalletId: UserWalletId, currencies: List): List - - /** - * Removes currency from a specific user wallet. - * - * @param userWalletId The unique identifier of the user wallet. - * @param currency The currency which must be removed. - * @throws DataError.UserWalletError.WrongUserWallet If multi-currency user wallet - * ID provided. - */ - @Deprecated("Use ManageCryptoCurrenciesUseCase") - suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency) - - /** - * Removes currencies from a specific user wallet. - * - * @param userWalletId The unique identifier of the user wallet. - * @param currencies The currencies which must be removed. - * @throws DataError.UserWalletError.WrongUserWallet If single-currency user wallet - * ID provided. - */ - @Deprecated("Use ManageCryptoCurrenciesUseCase") - suspend fun removeCurrencies(userWalletId: UserWalletId, currencies: List) - /** * Retrieves the list of cryptocurrencies within a user wallet. * @@ -211,18 +159,6 @@ interface CurrenciesRepository { fun isNetworkFeeZero(userWalletId: UserWalletId, network: Network): Boolean - /** - * Synchronizes local tokens with remote data for a specific user wallet. - * This method ensures that the local token list matches the remote state by fetching - * the token data from the local cache and push it to backend. - * - * @param userWalletId The unique identifier of the user wallet to sync tokens for. - * @throws Exception if the sync request to the backend fails - */ - @Deprecated("Use AccountsCRUDRepository instead") - @Throws - suspend fun syncTokens(userWalletId: UserWalletId) - @Throws fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver? } \ No newline at end of file diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCaseTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCaseTest.kt deleted file mode 100644 index be67de0762..0000000000 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCaseTest.kt +++ /dev/null @@ -1,207 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import arrow.core.left -import arrow.core.right -import com.tangem.domain.core.error.DataError -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.tokens.error.TokenListSortingError -import com.tangem.domain.tokens.mock.MockTokens -import com.tangem.domain.tokens.repository.MockCurrenciesRepository -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider -import io.mockk.mockk -import junit.framework.TestCase.assertEquals -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.test.runTest -import org.junit.Test -import kotlin.random.Random - -internal class ApplyTokenListSortingUseCaseTest { - - private val userWalletId = UserWalletId(value = null) - - @Test - fun `when tokens are empty then error should be received`() = runTest { - // Given - val expectedResult = TokenListSortingError.TokenListIsEmpty.left() - - val useCase = getUseCase() - - // When - val result = useCase( - userWalletId = userWalletId, - sortedTokensIds = emptyList(), - isGroupedByNetwork = false, - isSortedByBalance = false, - ) - - // Then - assertEquals(expectedResult, result) - } - - @Test - fun `when tokens saving failed then error should be received`() = runTest { - // Given - val expectedResult = TokenListSortingError.DataError(DataError.NetworkError.NoInternetConnection).left() - - val repository = getTokensRepository( - sortTokensResult = DataError.NetworkError.NoInternetConnection.left(), - ) - val useCase = getUseCase(repository) - - // When - val result = useCase( - userWalletId = userWalletId, - sortedTokensIds = MockTokens.tokens.map { it.id }.sortedByDescending { it.value }, - isGroupedByNetwork = false, - isSortedByBalance = false, - ) - - // Then - assertEquals(expectedResult, result) - } - - @Test - fun `when apply sorting for sorted and grouped list then correct args should be used`() = runTest { - // Given - val expectedTokens = getSortedTokens() - val expectedIsGrouped = true - val expectedIsSorted = true - - val repository = getTokensRepository() - val useCase = getUseCase(repository) - - // When - useCase( - userWalletId = userWalletId, - sortedTokensIds = expectedTokens.map { it.id }, - isGroupedByNetwork = expectedIsGrouped, - isSortedByBalance = expectedIsSorted, - ) - - // Then - assertEquals(expectedTokens, repository.tokensIdsAfterSortingApply) - assertEquals(expectedIsGrouped, repository.isTokensGroupedAfterSortingApply) - assertEquals(expectedIsSorted, repository.isTokensSortedByBalanceAfterSortingApply) - } - - @Test - fun `when apply sorting for unsorted and grouped list then correct args should be used`() = runTest { - // Given - val expectedTokens = getSortedTokens() - val expectedIsGrouped = true - val expectedIsSorted = false - - val repository = getTokensRepository() - val useCase = getUseCase(repository) - - // When - useCase( - userWalletId = userWalletId, - sortedTokensIds = expectedTokens.map { it.id }, - isGroupedByNetwork = expectedIsGrouped, - isSortedByBalance = expectedIsSorted, - ) - - // Then - assertEquals(expectedTokens, repository.tokensIdsAfterSortingApply) - assertEquals(expectedIsGrouped, repository.isTokensGroupedAfterSortingApply) - assertEquals(expectedIsSorted, repository.isTokensSortedByBalanceAfterSortingApply) - } - - @Test - fun `when apply sorting for sorted and ungrouped list then correct args should be used`() = runTest { - // Given - val expectedTokens = getSortedTokens() - val expectedIsGrouped = false - val expectedIsSorted = true - - val repository = getTokensRepository() - val useCase = getUseCase(repository) - - // When - useCase( - userWalletId = userWalletId, - sortedTokensIds = expectedTokens.map { it.id }, - isGroupedByNetwork = expectedIsGrouped, - isSortedByBalance = expectedIsSorted, - ) - - // Then - assertEquals(expectedTokens, repository.tokensIdsAfterSortingApply) - assertEquals(expectedIsGrouped, repository.isTokensGroupedAfterSortingApply) - assertEquals(expectedIsSorted, repository.isTokensSortedByBalanceAfterSortingApply) - } - - @Test - fun `when apply sorting for unsorted and ungrouped list then correct args should be used`() = runTest { - // Given - val expectedTokens = getSortedTokens() - val expectedIsGrouped = false - val expectedIsSorted = false - - val repository = getTokensRepository() - val useCase = getUseCase(repository) - - // When - useCase( - userWalletId = userWalletId, - sortedTokensIds = expectedTokens.map { it.id }, - isGroupedByNetwork = expectedIsGrouped, - isSortedByBalance = expectedIsSorted, - ) - - // Then - assertEquals(expectedTokens, repository.tokensIdsAfterSortingApply) - assertEquals(expectedIsGrouped, repository.isTokensGroupedAfterSortingApply) - assertEquals(expectedIsSorted, repository.isTokensSortedByBalanceAfterSortingApply) - } - - @Test - fun `when sorted tokens IDs do not contain all tokens IDs then error should be received`() = runTest { - // Given - val expectedResult = TokenListSortingError.UnableToSortTokenList.left() - - val repository = getTokensRepository() - val useCase = getUseCase(repository) - - // When - val result = useCase( - userWalletId = userWalletId, - sortedTokensIds = getSortedTokens().drop(n = 3).map { it.id }, - isGroupedByNetwork = false, - isSortedByBalance = false, - ) - - // Then - assertEquals(expectedResult, result) - } - - private fun getSortedTokens() = MockTokens.tokens - .sortedBy { Random.nextInt(0, MockTokens.tokens.size) } - - private fun getUseCase(tokensRepository: MockCurrenciesRepository = getTokensRepository()) = - ApplyTokenListSortingUseCase( - currenciesRepository = tokensRepository, - dispatchers = TestingCoroutineDispatcherProvider(), - multiWalletCryptoCurrenciesSupplier = mockk(), - ) - - private fun getTokensRepository( - sortTokensResult: Either = Unit.right(), - removeCurrencyResult: Either = Unit.right(), - tokens: Flow>> = flowOf(MockTokens.tokens.right()), - ): MockCurrenciesRepository { - return MockCurrenciesRepository( - sortTokensResult = sortTokensResult, - removeCurrencyResult = removeCurrencyResult, - token = MockTokens.token1.right(), - tokens = tokens, - isGrouped = emptyFlow(), - isSortedByBalance = emptyFlow(), - ) - } -} \ No newline at end of file diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockCurrenciesRepository.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockCurrenciesRepository.kt deleted file mode 100644 index befef5c116..0000000000 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockCurrenciesRepository.kt +++ /dev/null @@ -1,152 +0,0 @@ -package com.tangem.domain.tokens.repository - -import arrow.core.Either -import arrow.core.getOrElse -import com.tangem.domain.card.CardTypesResolver -import com.tangem.domain.core.error.DataError -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.currency.CryptoCurrencyStatus -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.tokens.model.FeePaidCurrency -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.map - -internal class MockCurrenciesRepository( - private val sortTokensResult: Either, - private val removeCurrencyResult: Either, - private val token: Either, - private val tokens: Flow>>, - private val isGrouped: Flow>, - private val isSortedByBalance: Flow>, -) : CurrenciesRepository { - - var tokensIdsAfterSortingApply: List? = null - private set - - var isTokensGroupedAfterSortingApply: Boolean? = null - private set - - var isTokensSortedByBalanceAfterSortingApply: Boolean? = null - private set - - override suspend fun saveTokens( - userWalletId: UserWalletId, - currencies: List, - isGroupedByNetwork: Boolean, - isSortedByBalance: Boolean, - ) { - sortTokensResult.onLeft { throw it } - - tokensIdsAfterSortingApply = currencies - isTokensGroupedAfterSortingApply = isGroupedByNetwork - isTokensSortedByBalanceAfterSortingApply = isSortedByBalance - } - - override suspend fun addCurrenciesCache( - userWalletId: UserWalletId, - currencies: List, - ): List = emptyList() - - override suspend fun removeCurrency(userWalletId: UserWalletId, currency: CryptoCurrency) { - removeCurrencyResult.onLeft { throw it } - } - - override suspend fun removeCurrencies(userWalletId: UserWalletId, currencies: List) = Unit - - override fun getWalletCurrenciesUpdates(userWalletId: UserWalletId): Flow> { - return emptyFlow() - } - - override suspend fun getMultiCurrencyWalletCurrenciesSync( - userWalletId: UserWalletId, - refresh: Boolean, - ): List { - return tokens.first().getOrElse { e -> throw e } - } - - override suspend fun getSingleCurrencyWalletPrimaryCurrency( - userWalletId: UserWalletId, - refresh: Boolean, - ): CryptoCurrency { - return token.getOrElse { e -> throw e } - } - - override suspend fun getSingleCurrencyWalletWithCardCurrencies( - userWalletId: UserWalletId, - refresh: Boolean, - ): List { - return tokens.first().getOrElse { e -> throw e } - } - - override suspend fun getSingleCurrencyWalletWithCardCurrency( - userWalletId: UserWalletId, - id: CryptoCurrency.ID, - ): CryptoCurrency { - return token.getOrElse { e -> throw e } - } - - override suspend fun getNetworkCoin( - userWalletId: UserWalletId, - networkId: Network.ID, - derivationPath: Network.DerivationPath, - ): CryptoCurrency.Coin { - TODO("Not yet implemented") - } - - override fun isTokensGrouped(userWalletId: UserWalletId): Flow { - return isGrouped.map { it.getOrElse { e -> throw e } } - } - - override fun isTokensSortedByBalance(userWalletId: UserWalletId): Flow { - return isSortedByBalance.map { it.getOrElse { e -> throw e } } - } - - override suspend fun isSendBlockedByPendingTransactions( - userWalletId: UserWalletId, - cryptoCurrencyStatus: CryptoCurrencyStatus, - ): Boolean { - return false - } - - override suspend fun getFeePaidCurrency(userWalletId: UserWalletId, network: Network): FeePaidCurrency { - return FeePaidCurrency.Coin - } - - override fun createCoinCurrency(network: Network): CryptoCurrency.Coin { - error("not implemented") - } - - override fun createTokenCurrency(cryptoCurrency: CryptoCurrency.Token, network: Network): CryptoCurrency.Token { - return cryptoCurrency - } - - override suspend fun createTokenCurrency( - userWalletId: UserWalletId, - contractAddress: String, - networkId: String, - ): CryptoCurrency.Token { - error("not implemented") - } - - override fun getAllWalletsCryptoCurrencies( - currencyRawId: CryptoCurrency.RawID, - ): Flow>> { - return emptyFlow() - } - - override fun isNetworkFeeZero(userWalletId: UserWalletId, network: Network): Boolean { - return false - } - - override suspend fun syncTokens(userWalletId: UserWalletId) { - return Unit - } - - override fun getCardTypesResolver(userWalletId: UserWalletId): CardTypesResolver { - error("No-op") - } -} \ No newline at end of file diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/CustomTokenFormUseCasesFacade.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/CustomTokenFormUseCasesFacade.kt index 51a46bd0e0..42e7cf42b9 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/CustomTokenFormUseCasesFacade.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/CustomTokenFormUseCasesFacade.kt @@ -19,7 +19,6 @@ import com.tangem.domain.models.account.DerivationIndex import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase import com.tangem.lib.crypto.derivation.AccountNodeRecognizer import dagger.assisted.Assisted @@ -30,7 +29,6 @@ import timber.log.Timber @Suppress("LongParameterList") internal class CustomTokenFormUseCasesFacade @AssistedInject constructor( @Assisted private val userWalletId: UserWalletId, - private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, private val derivePublicKeysUseCase: DerivePublicKeysUseCase, private val checkIsCurrencyNotAddedUseCase: CheckIsCurrencyNotAddedUseCase, private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase, @@ -40,14 +38,10 @@ internal class CustomTokenFormUseCasesFacade @AssistedInject constructor( ) { suspend fun addCryptoCurrenciesUseCase(currency: CryptoCurrency): Either { - return if (accountsFeatureToggles.isFeatureEnabled) { - either { - val accountId = getAccountId(currency) + return either { + val accountId = getAccountId(currency) - manageCryptoCurrenciesUseCase(accountId = accountId, add = currency).bind() - } - } else { - addCryptoCurrenciesUseCase.invoke(userWalletId = userWalletId, currency = currency) + manageCryptoCurrenciesUseCase(accountId = accountId, add = currency).bind() } } diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUseCasesFacade.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUseCasesFacade.kt index e692352aad..e291de38c9 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUseCasesFacade.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensUseCasesFacade.kt @@ -7,7 +7,10 @@ import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.producer.SingleAccountProducer import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase import com.tangem.domain.account.supplier.SingleAccountSupplier -import com.tangem.domain.managetokens.* +import com.tangem.domain.managetokens.CheckCurrencyUnsupportedUseCase +import com.tangem.domain.managetokens.CheckHasLinkedTokensUseCase +import com.tangem.domain.managetokens.GetDistinctManagedCurrenciesUseCase +import com.tangem.domain.managetokens.GetManagedTokensUseCase import com.tangem.domain.managetokens.model.CurrencyUnsupportedState import com.tangem.domain.managetokens.model.ManageTokensListConfig import com.tangem.domain.managetokens.model.ManagedCryptoCurrency @@ -27,10 +30,8 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor( val getManagedTokensUseCase: GetManagedTokensUseCase, val getDistinctManagedTokensUseCase: GetDistinctManagedCurrenciesUseCase, private val checkHasLinkedTokensUseCase: CheckHasLinkedTokensUseCase, - private val removeCustomCurrencyUseCase: RemoveCustomManagedCryptoCurrencyUseCase, private val checkCurrencyUnsupportedUseCase: CheckCurrencyUnsupportedUseCase, private val coldWalletAndHasMissedDerivationsUseCase: ColdWalletAndHasMissedDerivationsUseCase, - private val saveManagedTokensUseCase: SaveManagedTokensUseCase, private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase, private val customTokensRepository: CustomTokensRepository, private val accountsFeatureToggles: AccountsFeatureToggles, @@ -69,10 +70,7 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor( manageCryptoCurrenciesUseCase(accountId = mode.accountId, remove = currency) } - is ManageTokensMode.Wallet -> removeCustomCurrencyUseCase.invoke( - userWalletId = mode.userWalletId, - customCurrency = customCurrency, - ) + is ManageTokensMode.Wallet -> error("Unsupported") ManageTokensMode.None -> nonePortfolioError.left() } } @@ -147,13 +145,7 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor( remove = currenciesToRemove.mapToCryptoCurrencies(userWalletId = mode.accountId.userWalletId), ) } - is ManageTokensMode.Wallet -> { - saveManagedTokensUseCase.invoke( - userWalletId = mode.userWalletId, - currenciesToAdd = currenciesToAdd, - currenciesToRemove = currenciesToRemove, - ) - } + is ManageTokensMode.Wallet -> error("Unsupported") ManageTokensMode.None -> nonePortfolioError.left() } diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/model/OnrampAddToPortfolioModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/model/OnrampAddToPortfolioModel.kt index 66fa4f5693..9863a66e16 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/model/OnrampAddToPortfolioModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/model/OnrampAddToPortfolioModel.kt @@ -1,12 +1,11 @@ package com.tangem.features.onramp.hottokens.portfolio.model -import arrow.core.getOrElse import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase +import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase -import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.onramp.hottokens.portfolio.OnrampAddToPortfolioComponent import com.tangem.features.onramp.hottokens.portfolio.entity.OnrampAddToPortfolioUM @@ -21,11 +20,10 @@ import javax.inject.Inject /** * Model for adding token to portfolio * - * @param paramsContainer params container - * @property dispatchers dispatchers - * @property derivePublicKeysUseCase use case for deriving public key - * @property addCryptoCurrenciesUseCase use case for adding crypto currency - * @property getUserWalletUseCase use case for getting user wallet by id + * @param paramsContainer params container + * @property dispatchers dispatchers + * @property manageCryptoCurrenciesUseCase use case for managing crypto currencies + * @property getUserWalletUseCase use case for getting user wallet by id * [REDACTED_AUTHOR] */ @@ -33,8 +31,7 @@ import javax.inject.Inject internal class OnrampAddToPortfolioModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, - private val derivePublicKeysUseCase: DerivePublicKeysUseCase, - private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, + private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, ) : Model() { @@ -72,21 +69,14 @@ internal class OnrampAddToPortfolioModel @Inject constructor( private fun onAddClick() { modelScope.launch { changeAddButtonProgressStatus(isProgress = true) - derivePublicKeysUseCase( - userWalletId = params.userWalletId, - currencies = listOf(params.cryptoCurrency), - ).getOrElse { throwable -> - Timber.e("Failed to derive public keys: $throwable") - changeAddButtonProgressStatus(isProgress = false) - } - - addCryptoCurrenciesUseCase( - userWalletId = params.userWalletId, - currency = params.cryptoCurrency, - ) + val accountId = AccountId.forMainCryptoPortfolio(params.userWalletId) + manageCryptoCurrenciesUseCase(accountId = accountId, add = params.cryptoCurrency) .onRight { params.onSuccessAdding(params.cryptoCurrency.id) } - .onLeft { changeAddButtonProgressStatus(isProgress = false) } + .onLeft { throwable -> + Timber.e("Failed to add crypto currency: $throwable") + changeAddButtonProgressStatus(isProgress = false) + } } } diff --git a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractor.kt b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractor.kt index 67af26dc2a..49ad108455 100644 --- a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractor.kt +++ b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractor.kt @@ -1,6 +1,6 @@ package com.tangem.feature.referral.domain -import com.tangem.domain.models.PortfolioId +import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.account.DerivationIndex import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWalletId @@ -11,7 +11,7 @@ interface ReferralInteractor { suspend fun getReferralStatus(userWalletId: UserWalletId): ReferralData - suspend fun startReferral(portfolioId: PortfolioId): ReferralData + suspend fun startReferral(accountId: AccountId): ReferralData suspend fun getCryptoCurrency( userWalletId: UserWalletId, diff --git a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt index 930418c920..5e67063fe0 100644 --- a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt +++ b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt @@ -1,30 +1,22 @@ package com.tangem.feature.referral.domain -import arrow.core.getOrElse import com.tangem.common.core.TangemSdkError import com.tangem.domain.account.producer.SingleAccountProducer import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase import com.tangem.domain.account.supplier.SingleAccountSupplier -import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.account.Account +import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.account.DerivationIndex import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase -import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.feature.referral.domain.errors.ReferralError import com.tangem.feature.referral.domain.models.ReferralData import com.tangem.feature.referral.domain.models.TokenData import timber.log.Timber -@Suppress("LongParameterList") internal class ReferralInteractorImpl( private val repository: ReferralRepository, - private val derivePublicKeysUseCase: DerivePublicKeysUseCase, - private val getUserWalletUseCase: GetUserWalletUseCase, - private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase, private val singleAccountSupplier: SingleAccountSupplier, private val walletManagersFacade: WalletManagersFacade, @@ -40,64 +32,41 @@ internal class ReferralInteractorImpl( return referralData } - override suspend fun startReferral(portfolioId: PortfolioId): ReferralData { + override suspend fun startReferral(accountId: AccountId): ReferralData { if (tokensForReferral.isEmpty()) error("Tokens for ref is empty") val tokenData = tokensForReferral.first() - val userWalletId = portfolioId.userWalletId - val userWallet = getUserWalletUseCase(userWalletId).getOrElse { - error("Failed to get user wallet $userWalletId: $it") - } + val userWalletId = accountId.userWalletId - val accountIndex = when (portfolioId) { - is PortfolioId.Account -> { - val account = singleAccountSupplier.getSyncOrNull( - params = SingleAccountProducer.Params(accountId = portfolioId.accountId), - ) - ?: error("Account not found: ${portfolioId.accountId}") + val account = singleAccountSupplier.getSyncOrNull( + params = SingleAccountProducer.Params(accountId = accountId), + ) + ?: error("Account not found: $accountId") - when (account) { - is Account.CryptoPortfolio -> account.derivationIndex - is Account.Payment -> TODO("[REDACTED_JIRA]") - } - } - is PortfolioId.Wallet -> null + val accountIndex = when (account) { + is Account.CryptoPortfolio -> account.derivationIndex + is Account.Payment -> TODO("[REDACTED_JIRA]") } val cryptoCurrency = getCryptoCurrency( - userWalletId = portfolioId.userWalletId, + userWalletId = accountId.userWalletId, tokenData = tokenData, accountIndex = accountIndex, ) ?: error("Failed to create crypto currency") - when (portfolioId) { - is PortfolioId.Account -> { - manageCryptoCurrenciesUseCase( - accountId = portfolioId.accountId, - add = cryptoCurrency, - skipDerivationErrors = false, - ).mapLeft { - it.mapToDomainError() - }.onLeft { error -> - if (error is ReferralError.UserCancelledException) { - throw error - } + manageCryptoCurrenciesUseCase( + accountId = accountId, + add = cryptoCurrency, + skipDerivationErrors = false, + ) + .mapLeft { it.mapToDomainError() } + .onLeft { error -> + Timber.e(error) + if (error is ReferralError.UserCancelledException) { + throw error } } - is PortfolioId.Wallet -> { - derivePublicKeysUseCase(userWallet.walletId, listOf(cryptoCurrency)).getOrElse { throwable -> - Timber.e("Failed to derive public keys: $throwable") - throw throwable.mapToDomainError() - } - - addCryptoCurrenciesUseCase( - userWalletId = userWallet.walletId, - currency = cryptoCurrency, - ) - } - } - .onLeft(Timber::e) val publicAddress = walletManagersFacade.getDefaultAddress( userWalletId = userWalletId, diff --git a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt index c82165bda3..f560ae39b1 100644 --- a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt +++ b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt @@ -4,10 +4,7 @@ import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.di.ModelScoped import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase import com.tangem.domain.account.supplier.SingleAccountSupplier -import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase -import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.feature.referral.domain.ReferralInteractor import com.tangem.feature.referral.domain.ReferralInteractorImpl import com.tangem.feature.referral.domain.ReferralRepository @@ -23,18 +20,12 @@ class ReferralDomainModule { @ModelScoped fun provideReferralInteractor( referralRepository: ReferralRepository, - derivePublicKeysUseCase: DerivePublicKeysUseCase, - getUserWalletUseCase: GetUserWalletUseCase, - addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase, singleAccountSupplier: SingleAccountSupplier, walletManagersFacade: WalletManagersFacade, ): ReferralInteractor { return ReferralInteractorImpl( repository = referralRepository, - derivePublicKeysUseCase = derivePublicKeysUseCase, - getUserWalletUseCase = getUserWalletUseCase, - addCryptoCurrenciesUseCase = addCryptoCurrenciesUseCase, manageCryptoCurrenciesUseCase = manageCryptoCurrenciesUseCase, singleAccountSupplier = singleAccountSupplier, walletManagersFacade = walletManagersFacade, diff --git a/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt index eddb1e949d..f928bf5249 100644 --- a/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt +++ b/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt @@ -15,7 +15,6 @@ import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.share.ShareManager import com.tangem.core.navigation.url.UrlOpener -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.models.AccountStatusList import com.tangem.domain.account.status.model.AccountCryptoCurrency import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer @@ -24,8 +23,6 @@ import com.tangem.domain.account.status.usecase.GetAccountCurrencyByAddressUseCa import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.demo.IsDemoCardUseCase -import com.tangem.domain.models.PortfolioId -import com.tangem.domain.models.account.AccountStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.wallets.usecase.GetUserWalletUseCase @@ -44,10 +41,12 @@ import com.tangem.features.account.PortfolioFetcher import com.tangem.features.account.PortfolioSelectorComponent import com.tangem.features.account.PortfolioSelectorController import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import javax.inject.Inject +@OptIn(ExperimentalCoroutinesApi::class) @Suppress("LongParameterList") @Stable @ModelScoped @@ -60,7 +59,6 @@ internal class ReferralModel @Inject constructor( private val urlOpener: UrlOpener, private val getUserWalletUseCase: GetUserWalletUseCase, private val isDemoCardUseCase: IsDemoCardUseCase, - private val accountsFeatureToggles: AccountsFeatureToggles, private val portfolioFetcherFactory: PortfolioFetcher.Factory, val portfolioSelectorController: PortfolioSelectorController, private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, @@ -92,26 +90,24 @@ internal class ReferralModel @Inject constructor( init { analyticsEventHandler.send(ReferralEvents.ReferralScreenOpened()) - if (accountsFeatureToggles.isFeatureEnabled) { - combine( - flow = referralData.filterNotNull().onEach(::selectAccount), - flow2 = portfolioSelectorController.isAccountMode, - transform = { referralData, isAccountMode -> referralData to isAccountMode }, - ).transformLatest { (referralData, isAccountMode) -> - when (isAccountMode) { - false -> showContent(referralData) - true -> combineAccountUI(referralData) + + combine( + flow = referralData.filterNotNull().onEach(::selectAccount), + flow2 = portfolioSelectorController.isAccountMode, + transform = { referralData, isAccountMode -> referralData to isAccountMode }, + ) + .transformLatest { (referralData, isAccountMode) -> + if (!isAccountMode) { + showContent(referralData) + } else { + combineAccountUI(referralData) .map { referralData to it } .collect(::emit) } } - .onEach { (referralData, accountAward) -> showContent(referralData, accountAward) } - .launchIn(modelScope) - } else { - referralData.filterNotNull() - .onEach(::showContent) - .launchIn(modelScope) - } + .onEach { (referralData, accountAward) -> showContent(referralData, accountAward) } + .launchIn(modelScope) + loadReferralData() } @@ -123,12 +119,7 @@ internal class ReferralModel @Inject constructor( flow3 = getSelectedAppCurrencyUseCase.invokeOrDefault(), flow4 = portfolioFetcher.data, ) { pair, isBalanceHidden, appCurrency, portfolios -> - val selectedAccount = pair?.second ?: return@combine null - - val cryptoPortfolio = when (selectedAccount) { - is AccountStatus.CryptoPortfolio -> selectedAccount - is AccountStatus.Payment -> TODO("[REDACTED_JIRA]") - } + val cryptoPortfolio = pair?.second ?: return@combine null val awardCryptoCurrency = referralInteractor.getCryptoCurrency( userWalletId = params.userWalletId, @@ -185,11 +176,8 @@ internal class ReferralModel @Inject constructor( val lastInfoState = uiState.referralInfoState uiState = uiState.copy(referralInfoState = ReferralInfoState.Loading) modelScope.launch { - val portfolioId = when (accountsFeatureToggles.isFeatureEnabled) { - true -> PortfolioId(requireNotNull(portfolioSelectorController.selectedAccountSync)) - false -> PortfolioId(params.userWalletId) - } - runCatching { referralInteractor.startReferral(portfolioId) } + val accountId = requireNotNull(portfolioSelectorController.selectedAccountSync) + runCatching { referralInteractor.startReferral(accountId) } .onSuccess { referral -> analyticsEventHandler.send(ReferralEvents.ParticipateSuccessful()) referralData.value = referral diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt index 3411103f5c..c4b53d2a7f 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt @@ -23,7 +23,6 @@ import com.tangem.core.ui.HoldToConfirmButtonFeatureToggles import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.feedback.GetWalletMetaInfoUseCase @@ -36,7 +35,6 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.isHotWallet import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase import com.tangem.domain.settings.NeverShowTapHelpUseCase -import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.tokens.IsAmountSubtractAvailableUseCase import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.transaction.usecase.CreateTransferTransactionUseCase @@ -75,10 +73,8 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.orZero import com.tangem.utils.extensions.stripZeroPlainString import com.tangem.utils.transformer.update -import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import timber.log.Timber import java.math.BigDecimal import javax.inject.Inject @@ -100,7 +96,6 @@ internal class SendConfirmModel @Inject constructor( private val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase, private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, - private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, private val isAmountSubtractAvailableUseCase: IsAmountSubtractAvailableUseCase, private val feeSelectorCheckReloadListener: FeeSelectorCheckReloadListener, @@ -114,7 +109,6 @@ internal class SendConfirmModel @Inject constructor( private val feeSelectorReloadTrigger: FeeSelectorReloadTrigger, private val sendAmountReduceTrigger: SendAmountReduceTrigger, private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, - private val accountsFeatureToggles: AccountsFeatureToggles, private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase, private val currenciesRepository: CurrenciesRepository, private val createAndSendGaslessTransactionUseCase: CreateAndSendGaslessTransactionUseCase, @@ -466,24 +460,14 @@ internal class SendConfirmModel @Inject constructor( .firstOrNull { it.address == confirmData.enteredDestination } ?: return - val userWalletId = receivingUserWallet.userWalletId ?: return val network = receivingUserWallet.network ?: return modelScope.launch(dispatchers.default) { - if (accountsFeatureToggles.isFeatureEnabled) { - val accountId = receivingUserWallet.accountId ?: return@launch + val accountId = receivingUserWallet.accountId ?: return@launch - val tokenToAdd = currenciesRepository.createTokenCurrency(cryptoCurrency, network) - manageCryptoCurrenciesUseCase(accountId = accountId, add = tokenToAdd) - } else { - withContext(NonCancellable) { - addCryptoCurrenciesUseCase( - userWalletId = userWalletId, - cryptoCurrency = cryptoCurrency, - network = network, - ) - } - }.onLeft(Timber::e) + val tokenToAdd = currenciesRepository.createTokenCurrency(cryptoCurrency, network) + manageCryptoCurrenciesUseCase(accountId = accountId, add = tokenToAdd) + .onLeft(Timber::e) } } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index a0b3afb86c..17c4f1ad60 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -115,7 +115,7 @@ internal class TokenDetailsModel @Inject constructor( private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, private val getExploreUrlUseCase: GetExploreUrlUseCase, private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase, - private val removeCurrencyUseCase: RemoveCurrencyUseCase, + private val isCryptoCurrencyCoinCouldHideUseCase: IsCryptoCurrencyCoinCouldHideUseCase, private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, private val getCurrencyWarningsUseCase: GetCurrencyWarningsUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, @@ -758,8 +758,12 @@ internal class TokenDetailsModel @Inject constructor( analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonRemoveToken(cryptoCurrency.symbol)) modelScope.launch { - val hasLinkedTokens = removeCurrencyUseCase.hasLinkedTokens(userWalletId, cryptoCurrency) - internalUiState.value = if (hasLinkedTokens) { + val canHide = cryptoCurrency is CryptoCurrency.Coin && isCryptoCurrencyCoinCouldHideUseCase( + userWalletId = userWalletId, + cryptoCurrencyCoin = cryptoCurrency, + ) + + internalUiState.value = if (!canHide) { stateFactory.getStateWithLinkedTokensDialog(cryptoCurrency) } else { stateFactory.getStateWithConfirmHideTokenDialog(cryptoCurrency) @@ -769,18 +773,14 @@ internal class TokenDetailsModel @Inject constructor( override fun onHideConfirmed() { modelScope.launch { - if (accountsFeatureToggles.isFeatureEnabled) { - val accountId = account?.accountId + val accountId = account?.accountId - if (accountId == null) { - Timber.e("Account ID is null, cannot hide currency ${cryptoCurrency.id}") - return@launch - } - - manageCryptoCurrenciesUseCase(accountId = accountId, remove = cryptoCurrency) - } else { - removeCurrencyUseCase(userWalletId, cryptoCurrency) + if (accountId == null) { + Timber.e("Account ID is null, cannot hide currency ${cryptoCurrency.id}") + return@launch } + + manageCryptoCurrenciesUseCase(accountId = accountId, remove = cryptoCurrency) .onLeft { Timber.e(it) } .onRight { router.popBackStack() } } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt index 778b4f2edf..20d13122a3 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt @@ -5,7 +5,6 @@ import com.tangem.common.ui.expressStatus.state.ExpressTransactionsBlockState import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.datasource.local.swap.ExpressAnalyticsStatus import com.tangem.datasource.local.swap.SwapTransactionStatusStore -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase import com.tangem.domain.appcurrency.model.AppCurrency @@ -14,7 +13,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.quote.QuoteStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.quotes.QuotesRepository -import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.tokens.model.analytics.TokenExchangeAnalyticsEvent import com.tangem.feature.swap.domain.SwapTransactionRepository import com.tangem.feature.swap.domain.api.SwapRepository @@ -38,8 +36,6 @@ internal class ExchangeStatusFactory @AssistedInject constructor( private val swapTransactionRepository: SwapTransactionRepository, private val swapRepository: SwapRepository, private val quotesRepository: QuotesRepository, - private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, - private val accountsFeatureToggles: AccountsFeatureToggles, private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase, private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase, private val swapTransactionStatusStore: SwapTransactionStatusStore, @@ -117,30 +113,22 @@ internal class ExchangeStatusFactory @AssistedInject constructor( ifRight = { statusModel -> sendStatusUpdateAnalytics(statusModel, provider) - val accountId = if (accountsFeatureToggles.isFeatureEnabled) { - getAccountCurrencyStatusUseCase.invokeSync( - userWalletId = userWallet.walletId, - currency = cryptoCurrency, - ) - .map { it.account.accountId } - .getOrNull() - } else { - null - } + val accountId = getAccountCurrencyStatusUseCase.invokeSync( + userWalletId = userWallet.walletId, + currency = cryptoCurrency, + ) + .map { it.account.accountId } + .getOrNull() - val refundTokenCurrency = if (accountsFeatureToggles.isFeatureEnabled) { - if (accountId != null) { - addRefundCurrencyIfNeededNew( - accountId = accountId, - status = statusModel, - type = provider.type, - ) - } else { - Timber.e("Account ID is null, cannot add refund currency ${cryptoCurrency.id}") - null - } + val refundTokenCurrency = if (accountId != null) { + addRefundCurrencyIfNeeded( + accountId = accountId, + status = statusModel, + type = provider.type, + ) } else { - addRefundCurrencyIfNeededLegacy(status = statusModel, type = provider.type) + Timber.e("Account ID is null, cannot add refund currency ${cryptoCurrency.id}") + null } swapTransactionRepository.storeTransactionState( @@ -170,28 +158,7 @@ internal class ExchangeStatusFactory @AssistedInject constructor( } } - /** - * For now do it only for dex-bridge provider - */ - private suspend fun addRefundCurrencyIfNeededLegacy( - status: ExchangeStatusModel?, - type: ExchangeProviderType, - ): CryptoCurrency? { - status ?: return null - if (type != ExchangeProviderType.DEX_BRIDGE) return null - val refundNetwork = status.refundNetwork - val refundContractAddress = status.refundContractAddress - if (refundNetwork != null && refundContractAddress != null) { - return addCryptoCurrenciesUseCase( - userWalletId = userWallet.walletId, - contractAddress = refundContractAddress, - networkId = refundNetwork, - ).getOrNull() - } - return null - } - - private suspend fun addRefundCurrencyIfNeededNew( + private suspend fun addRefundCurrencyIfNeeded( accountId: AccountId, status: ExchangeStatusModel?, type: ExchangeProviderType, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/TokenDetailsExchangeStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/TokenDetailsExchangeStatusFactory.kt index 7c10c7d5d6..d145a7ab35 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/TokenDetailsExchangeStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/TokenDetailsExchangeStatusFactory.kt @@ -4,7 +4,6 @@ import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.datasource.local.swap.ExpressAnalyticsStatus import com.tangem.datasource.local.swap.SwapTransactionStatusStore -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase import com.tangem.domain.appcurrency.model.AppCurrency @@ -13,7 +12,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.quote.QuoteStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.quotes.QuotesRepository -import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.tokens.model.analytics.TokenExchangeAnalyticsEvent import com.tangem.feature.swap.domain.SwapTransactionRepository import com.tangem.feature.swap.domain.api.SwapRepository @@ -39,8 +37,6 @@ internal class TokenDetailsExchangeStatusFactory @AssistedInject constructor( private val swapTransactionRepository: SwapTransactionRepository, private val swapRepository: SwapRepository, private val quotesRepository: QuotesRepository, - private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, - private val accountsFeatureToggles: AccountsFeatureToggles, private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase, private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase, private val swapTransactionStatusStore: SwapTransactionStatusStore, @@ -118,30 +114,22 @@ internal class TokenDetailsExchangeStatusFactory @AssistedInject constructor( ifRight = { statusModel -> sendStatusUpdateAnalytics(statusModel, provider) - val accountId = if (accountsFeatureToggles.isFeatureEnabled) { - getAccountCurrencyStatusUseCase.invokeSync( - userWalletId = userWallet.walletId, - currency = cryptoCurrency, - ) - .map { it.account.accountId } - .getOrNull() - } else { - null - } + val accountId = getAccountCurrencyStatusUseCase.invokeSync( + userWalletId = userWallet.walletId, + currency = cryptoCurrency, + ) + .map { it.account.accountId } + .getOrNull() - val refundTokenCurrency = if (accountsFeatureToggles.isFeatureEnabled) { - if (accountId != null) { - addRefundCurrencyIfNeededNew( - accountId = accountId, - status = statusModel, - type = provider.type, - ) - } else { - Timber.e("Account ID is null, cannot add refund currency ${cryptoCurrency.id}") - null - } + val refundTokenCurrency = if (accountId != null) { + addRefundCurrencyIfNeeded( + accountId = accountId, + status = statusModel, + type = provider.type, + ) } else { - addRefundCurrencyIfNeededLegacy(status = statusModel, type = provider.type) + Timber.e("Account ID is null, cannot add refund currency ${cryptoCurrency.id}") + null } swapTransactionRepository.storeTransactionState( @@ -171,28 +159,7 @@ internal class TokenDetailsExchangeStatusFactory @AssistedInject constructor( } } - /** - * For now do it only for dex-bridge provider - */ - private suspend fun addRefundCurrencyIfNeededLegacy( - status: ExchangeStatusModel?, - type: ExchangeProviderType, - ): CryptoCurrency? { - status ?: return null - if (type != ExchangeProviderType.DEX_BRIDGE) return null - val refundNetwork = status.refundNetwork - val refundContractAddress = status.refundContractAddress - if (refundNetwork != null && refundContractAddress != null) { - return addCryptoCurrenciesUseCase( - userWalletId = userWallet.walletId, - contractAddress = refundContractAddress, - networkId = refundNetwork, - ).getOrNull() - } - return null - } - - private suspend fun addRefundCurrencyIfNeededNew( + private suspend fun addRefundCurrencyIfNeeded( accountId: AccountId, status: ExchangeStatusModel?, type: ExchangeProviderType,