Updated on 2026-08-14

This commit is contained in:
Tangem 2025-05-29 18:56:04 +04:00
parent b98b0f659c
commit 8b0a7f01cf
18 changed files with 83 additions and 281 deletions

View file

@ -10,7 +10,6 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
@ -71,7 +70,6 @@ internal object ManageTokensDomainModule {
currenciesRepository: CurrenciesRepository,
derivationsRepository: DerivationsRepository,
stakingRepository: StakingRepository,
quotesRepository: QuotesRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
@ -83,7 +81,6 @@ internal object ManageTokensDomainModule {
currenciesRepository = currenciesRepository,
derivationsRepository = derivationsRepository,
stakingRepository = stakingRepository,
quotesRepository = quotesRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
multiYieldBalanceFetcher = multiYieldBalanceFetcher,

View file

@ -13,7 +13,6 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import dagger.Module
import dagger.Provides
@ -53,16 +52,8 @@ object MarketsDomainModule {
@Provides
@Singleton
fun provideGetTokenQuotesUseCase(
quotesRepository: QuotesRepository,
singleQuoteSupplier: SingleQuoteSupplier,
tokensFeatureToggles: TokensFeatureToggles,
): GetCurrencyQuotesUseCase {
return GetCurrencyQuotesUseCase(
quotesRepository = quotesRepository,
singleQuoteSupplier = singleQuoteSupplier,
tokensFeatureToggles = tokensFeatureToggles,
)
fun provideGetTokenQuotesUseCase(singleQuoteSupplier: SingleQuoteSupplier): GetCurrencyQuotesUseCase {
return GetCurrencyQuotesUseCase(singleQuoteSupplier = singleQuoteSupplier)
}
@Provides
@ -72,7 +63,6 @@ object MarketsDomainModule {
marketsTokenRepository: MarketsTokenRepository,
currenciesRepository: CurrenciesRepository,
stakingRepository: StakingRepository,
quotesRepository: QuotesRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
@ -83,7 +73,6 @@ object MarketsDomainModule {
marketsTokenRepository = marketsTokenRepository,
currenciesRepository = currenciesRepository,
stakingRepository = stakingRepository,
quotesRepository = quotesRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
multiYieldBalanceFetcher = multiYieldBalanceFetcher,

View file

@ -22,7 +22,6 @@ import com.tangem.domain.tokens.operations.CachedCurrenciesStatusesOperations
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.CurrencyChecksRepository
import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.tap.domain.tokens.DefaultTokensFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -42,7 +41,6 @@ internal object TokensDomainModule {
fun provideAddCryptoCurrenciesUseCase(
currenciesRepository: CurrenciesRepository,
stakingRepository: StakingRepository,
quotesRepository: QuotesRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
@ -51,7 +49,6 @@ internal object TokensDomainModule {
return AddCryptoCurrenciesUseCase(
currenciesRepository = currenciesRepository,
stakingRepository = stakingRepository,
quotesRepository = quotesRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
singleYieldBalanceFetcher = singleYieldBalanceFetcher,
@ -63,7 +60,6 @@ internal object TokensDomainModule {
@Singleton
fun provideFetchTokenListUseCase(
currenciesRepository: CurrenciesRepository,
quotesRepository: QuotesRepository,
stakingRepository: StakingRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
@ -72,7 +68,6 @@ internal object TokensDomainModule {
): FetchTokenListUseCase {
return FetchTokenListUseCase(
currenciesRepository = currenciesRepository,
quotesRepository = quotesRepository,
stakingRepository = stakingRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
@ -164,7 +159,6 @@ internal object TokensDomainModule {
@Singleton
fun provideFetchCurrencyStatusUseCase(
currenciesRepository: CurrenciesRepository,
quotesRepository: QuotesRepository,
stakingRepository: StakingRepository,
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
@ -173,7 +167,6 @@ internal object TokensDomainModule {
): FetchCurrencyStatusUseCase {
return FetchCurrencyStatusUseCase(
currenciesRepository = currenciesRepository,
quotesRepository = quotesRepository,
stakingRepository = stakingRepository,
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
@ -186,7 +179,6 @@ internal object TokensDomainModule {
@Singleton
fun provideFetchCardTokenListUseCase(
currenciesRepository: CurrenciesRepository,
quotesRepository: QuotesRepository,
stakingRepository: StakingRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
@ -195,7 +187,6 @@ internal object TokensDomainModule {
): FetchCardTokenListUseCase {
return FetchCardTokenListUseCase(
currenciesRepository = currenciesRepository,
quotesRepository = quotesRepository,
stakingRepository = stakingRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
@ -355,15 +346,11 @@ internal object TokensDomainModule {
@Singleton
fun provideRefreshMultiCurrencyWalletQuotesUseCase(
currenciesRepository: CurrenciesRepository,
quotesRepository: QuotesRepository,
multiQuoteFetcher: MultiQuoteFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): RefreshMultiCurrencyWalletQuotesUseCase {
return RefreshMultiCurrencyWalletQuotesUseCase(
currenciesRepository = currenciesRepository,
quotesRepository = quotesRepository,
multiQuoteFetcher = multiQuoteFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
}
@ -381,7 +368,6 @@ internal object TokensDomainModule {
fun provideBaseCurrenciesStatusesOperations(
tokensFeatureToggles: TokensFeatureToggles,
currenciesRepository: CurrenciesRepository,
quotesRepository: QuotesRepository,
quotesRepositoryV2: QuotesRepositoryV2,
stakingRepository: StakingRepository,
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
@ -394,7 +380,6 @@ internal object TokensDomainModule {
): BaseCurrenciesStatusesOperations {
return CachedCurrenciesStatusesOperations(
currenciesRepository = currenciesRepository,
quotesRepository = quotesRepository,
quotesRepositoryV2 = quotesRepositoryV2,
stakingRepository = stakingRepository,
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
@ -413,7 +398,6 @@ internal object TokensDomainModule {
fun provideBaseCurrencyStatusOperations(
tokensFeatureToggles: TokensFeatureToggles,
currenciesRepository: CurrenciesRepository,
quotesRepository: QuotesRepository,
quotesRepositoryV2: QuotesRepositoryV2,
stakingRepository: StakingRepository,
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
@ -426,7 +410,6 @@ internal object TokensDomainModule {
): BaseCurrencyStatusOperations {
return CachedCurrenciesStatusesOperations(
currenciesRepository = currenciesRepository,
quotesRepository = quotesRepository,
quotesRepositoryV2 = quotesRepositoryV2,
stakingRepository = stakingRepository,
singleNetworkStatusSupplier = singleNetworkStatusSupplier,

View file

@ -7,9 +7,6 @@ internal class DefaultTokensFeatureToggles(
private val featureTogglesManager: FeatureTogglesManager,
) : TokensFeatureToggles {
override val isQuotesLoadingRefactoringEnabled: Boolean
get() = featureTogglesManager.isFeatureEnabled(name = "QUOTES_LOADING_REFACTORING_ENABLED")
override val isStakingLoadingRefactoringEnabled: Boolean
get() = featureTogglesManager.isFeatureEnabled(name = "STAKING_LOADING_REFACTORING_ENABLED")
}

View file

@ -55,10 +55,6 @@
"name": "WALLET_CONNECT_REDESIGN_ENABLED",
"version": "undefined"
},
{
"name": "QUOTES_LOADING_REFACTORING_ENABLED",
"version": "5.24.0"
},
{
"name": "STAKING_LOADING_REFACTORING_ENABLED",
"version": "5.25.0"

View file

@ -14,7 +14,6 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWalletId
@ -25,7 +24,6 @@ class SaveManagedTokensUseCase(
private val currenciesRepository: CurrenciesRepository,
private val derivationsRepository: DerivationsRepository,
private val stakingRepository: StakingRepository,
private val quotesRepository: QuotesRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
@ -129,19 +127,12 @@ class SaveManagedTokensUseCase(
}
private suspend fun refreshUpdatedQuotes(addedCurrencies: List<CryptoCurrency>) {
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
appCurrencyId = null,
),
)
} else {
quotesRepository.fetchQuotes(
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
refresh = true,
)
}
appCurrencyId = null,
),
)
}
/**

View file

@ -6,18 +6,14 @@ import arrow.core.toOption
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.quotes.single.SingleQuoteProducer
import com.tangem.domain.quotes.single.SingleQuoteSupplier
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.repository.QuotesRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
class GetCurrencyQuotesUseCase(
private val quotesRepository: QuotesRepository,
private val singleQuoteSupplier: SingleQuoteSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
// TODO apply interval parameter [REDACTED_TASK_KEY]
operator fun invoke(
@ -27,18 +23,10 @@ class GetCurrencyQuotesUseCase(
): Flow<Option<Quote.Value>> {
val rawId = currencyID.rawCurrencyId ?: return flowOf(None)
return if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
singleQuoteSupplier(
params = SingleQuoteProducer.Params(rawCurrencyId = rawId),
)
.map { (it as? Quote.Value).toOption() }
} else {
quotesRepository.getQuotesUpdatesLegacy(
currenciesIds = setOf(rawId),
refresh = refresh,
)
.map { it.filterIsInstance<Quote.Value>().firstOrNull().toOption() }
}
return singleQuoteSupplier(
params = SingleQuoteProducer.Params(rawCurrencyId = rawId),
)
.map { (it as? Quote.Value).toOption() }
.catch { emit(None) }
}
}

View file

@ -12,7 +12,6 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.wallets.models.UserWalletId
/**
@ -30,7 +29,6 @@ class SaveMarketTokensUseCase(
private val marketsTokenRepository: MarketsTokenRepository,
private val currenciesRepository: CurrenciesRepository,
private val stakingRepository: StakingRepository,
private val quotesRepository: QuotesRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
@ -110,18 +108,11 @@ class SaveMarketTokensUseCase(
}
private suspend fun refreshUpdatedQuotes(addedCurrencies: List<CryptoCurrency>) {
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
appCurrencyId = null,
),
)
} else {
quotesRepository.fetchQuotes(
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
refresh = true,
)
}
appCurrencyId = null,
),
)
}
}

View file

@ -12,7 +12,6 @@ import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@ -29,7 +28,6 @@ import kotlinx.coroutines.coroutineScope
class AddCryptoCurrenciesUseCase(
private val currenciesRepository: CurrenciesRepository,
private val stakingRepository: StakingRepository,
private val quotesRepository: QuotesRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
@ -165,19 +163,12 @@ class AddCryptoCurrenciesUseCase(
}
private suspend fun refreshUpdatedQuotes(currencyToAdd: CryptoCurrency) {
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = setOfNotNull(currencyToAdd.id.rawCurrencyId),
appCurrencyId = null,
),
)
} else {
quotesRepository.fetchQuotes(
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = setOfNotNull(currencyToAdd.id.rawCurrencyId),
refresh = true,
)
}
appCurrencyId = null,
),
)
}
private suspend fun Raise<Throwable>.createTokenCurrency(

View file

@ -13,7 +13,6 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@ -22,7 +21,6 @@ import kotlinx.coroutines.coroutineScope
@Suppress("LongParameterList")
class FetchCardTokenListUseCase(
private val currenciesRepository: CurrenciesRepository,
private val quotesRepository: QuotesRepository,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
@ -44,7 +42,6 @@ class FetchCardTokenListUseCase(
val fetchQuotes = async {
fetchQuotes(
currenciesIds = currencies.mapNotNullTo(destination = hashSetOf()) { it.id.rawCurrencyId },
refresh = refresh,
)
}
val yieldBalances = async {
@ -85,17 +82,10 @@ class FetchCardTokenListUseCase(
.bind()
}
private suspend fun fetchQuotes(currenciesIds: Set<CryptoCurrency.RawID>, refresh: Boolean) {
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null),
)
} else {
catch(
block = { quotesRepository.getQuotesSync(currenciesIds, refresh) },
catch = { /* Ignore error */ },
)
}
private suspend fun fetchQuotes(currenciesIds: Set<CryptoCurrency.RawID>) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null),
)
}
private suspend fun fetchYieldBalances(

View file

@ -13,7 +13,6 @@ import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@ -25,13 +24,11 @@ import kotlinx.coroutines.coroutineScope
* by providing a specific currency ID or fetching the status of the primary currency.
*
* @param currenciesRepository The repository for retrieving currency-related data.
* @param quotesRepository The repository for retrieving cryptocurrency quotes.
*/
// TODO: Add tests
@Suppress("LongParameterList")
class FetchCurrencyStatusUseCase(
private val currenciesRepository: CurrenciesRepository,
private val quotesRepository: QuotesRepository,
private val stakingRepository: StakingRepository,
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
@ -86,7 +83,7 @@ class FetchCurrencyStatusUseCase(
fetchNetworkStatus(userWalletId, currency.network)
}
val fetchQuote = async {
fetchQuote(currency.id, refresh)
fetchQuote(currency.id)
}
val fetchStakingBalance = async {
fetchStakingBalance(userWalletId, currency, refresh)
@ -125,21 +122,15 @@ class FetchCurrencyStatusUseCase(
.bind()
}
private suspend fun Raise<CurrencyStatusError>.fetchQuote(currencyId: CryptoCurrency.ID, refresh: Boolean) {
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = setOfNotNull(currencyId.rawCurrencyId),
appCurrencyId = null,
),
)
} else {
catch(
block = { quotesRepository.getQuotesSync(setOfNotNull(currencyId.rawCurrencyId), refresh) },
) {
raise(CurrencyStatusError.DataError(it))
}
}
private suspend fun Raise<CurrencyStatusError>.fetchQuote(currencyId: CryptoCurrency.ID) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = setOfNotNull(currencyId.rawCurrencyId),
appCurrencyId = null,
),
)
.mapLeft { CurrencyStatusError.DataError(it) }
.bind()
}
private suspend fun Raise<CurrencyStatusError>.fetchStakingBalance(

View file

@ -15,7 +15,6 @@ import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@ -26,14 +25,12 @@ import kotlinx.coroutines.coroutineScope
* network statuses, and quotes for tokens associated with a user's wallet.
*
* @param currenciesRepository The repository for retrieving currency-related data.
* @param quotesRepository The repository for retrieving cryptocurrency quotes.
* @param stakingRepository The repository for retrieving staking-related data.
*/
// TODO: Add tests
@Suppress("LongParameterList")
class FetchTokenListUseCase(
private val currenciesRepository: CurrenciesRepository,
private val quotesRepository: QuotesRepository,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
@ -73,7 +70,6 @@ class FetchTokenListUseCase(
val fetchQuotes = async {
fetchQuotes(
currenciesIds = currencies.mapTo(hashSetOf()) { it.id },
refresh = mode.refreshQuotes,
)
}
@ -115,24 +111,15 @@ class FetchTokenListUseCase(
.bind()
}
private suspend fun fetchQuotes(currenciesIds: Set<CryptoCurrency.ID>, refresh: Boolean) {
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = currenciesIds.mapNotNull { it.rawCurrencyId }.toSet(),
appCurrencyId = null,
),
)
} else {
catch(
block = {
val rawIds = currenciesIds.mapNotNull { it.rawCurrencyId }.toSet()
quotesRepository.getQuotesSync(rawIds, refresh)
},
) {
/* Ignore error */
}
}
private suspend fun Raise<TokenListError>.fetchQuotes(currenciesIds: Set<CryptoCurrency.ID>) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = currenciesIds.mapNotNull { it.rawCurrencyId }.toSet(),
appCurrencyId = null,
),
)
.mapLeft(TokenListError::DataError)
.bind()
}
private suspend fun fetchYieldBalances(

View file

@ -8,17 +8,14 @@ import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.tokens.error.QuotesError
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
class RefreshMultiCurrencyWalletQuotesUseCase(
private val quotesRepository: QuotesRepository,
private val currenciesRepository: CurrenciesRepository,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
suspend operator fun invoke(userWalletId: UserWalletId): Either<QuotesError, Unit> {
@ -48,23 +45,11 @@ class RefreshMultiCurrencyWalletQuotesUseCase(
}
private suspend fun fetchQuotes(currenciesIds: Set<CryptoCurrency.ID>) {
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = currenciesIds.mapNotNullTo(hashSetOf(), CryptoCurrency.ID::rawCurrencyId),
appCurrencyId = null,
),
)
} else {
catch(
block = {
quotesRepository.fetchQuotes(
currenciesIds = currenciesIds.mapNotNullTo(hashSetOf(), CryptoCurrency.ID::rawCurrencyId),
refresh = true,
)
},
catch = { /* Ignore error */ },
)
}
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
currenciesIds = currenciesIds.mapNotNullTo(hashSetOf(), CryptoCurrency.ID::rawCurrencyId),
appCurrencyId = null,
),
)
}
}

View file

@ -7,7 +7,5 @@ package com.tangem.domain.tokens
*/
interface TokensFeatureToggles {
val isQuotesLoadingRefactoringEnabled: Boolean
val isStakingLoadingRefactoringEnabled: Boolean
}

View file

@ -26,7 +26,6 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.tokens.utils.CurrencyStatusProxyCreator
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.*
@ -35,7 +34,6 @@ import kotlinx.coroutines.flow.*
* Base operations for working with currency status
*
* @property currenciesRepository repository for currencies
* @property quotesRepository repository for quotes
* @property stakingRepository repository for staking
*
[REDACTED_AUTHOR]
@ -43,7 +41,6 @@ import kotlinx.coroutines.flow.*
@Suppress("LargeClass", "LongParameterList")
abstract class BaseCurrencyStatusOperations(
private val currenciesRepository: CurrenciesRepository,
private val quotesRepository: QuotesRepository,
private val quotesRepositoryV2: QuotesRepositoryV2,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
@ -194,12 +191,8 @@ abstract class BaseCurrencyStatusOperations(
}
val quote = cryptoCurrencyId.rawCurrencyId?.let { rawId ->
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
singleQuoteSupplier(params = SingleQuoteProducer.Params(rawCurrencyId = rawId))
.firstOrNull()
} else {
quotesRepository.getQuoteSync(rawId)
}
singleQuoteSupplier(params = SingleQuoteProducer.Params(rawCurrencyId = rawId))
.firstOrNull()
}
?.right()
?: Error.EmptyQuotes.left()
@ -264,11 +257,7 @@ abstract class BaseCurrencyStatusOperations(
val (_, currenciesIds) = getIds(nonEmptyCurrencies)
val rawIds = currenciesIds.mapNotNull { it.rawCurrencyId }.toSet()
val quotes = if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
quotesRepositoryV2.getMultiQuoteSyncOrNull(currenciesIds = rawIds)?.right()
} else {
quotesRepository.getQuotesSync(rawIds, false).right()
}
val quotes = quotesRepositoryV2.getMultiQuoteSyncOrNull(currenciesIds = rawIds)?.right()
val networkStatuses = multiNetworkStatusSupplier(
params = MultiNetworkStatusProducer.Params(userWalletId = userWalletId),
@ -297,22 +286,12 @@ abstract class BaseCurrencyStatusOperations(
catch = { raise(Error.DataError(it)) },
)
val quotes = if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
currency.id.rawCurrencyId?.let {
singleQuoteSupplier(params = SingleQuoteProducer.Params(rawCurrencyId = it))
.firstOrNull()
}
?.right()
?: Error.EmptyQuotes.left()
} else {
catch(
block = {
currency.id.rawCurrencyId?.let { quotesRepository.getQuoteSync(it) }
?.right() ?: Error.EmptyQuotes.left()
},
catch = { Error.DataError(it).left() },
)
val quotes = currency.id.rawCurrencyId?.let {
singleQuoteSupplier(params = SingleQuoteProducer.Params(rawCurrencyId = it))
.firstOrNull()
}
?.right()
?: Error.EmptyQuotes.left()
val networkStatus = singleNetworkStatusSupplier(
params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = currency.network),

View file

@ -34,7 +34,6 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.tokens.utils.extractAddress
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.extensions.addOrReplace
@ -44,7 +43,6 @@ import kotlinx.coroutines.flow.*
@Suppress("LongParameterList", "LargeClass")
class CachedCurrenciesStatusesOperations(
private val currenciesRepository: CurrenciesRepository,
private val quotesRepository: QuotesRepository,
quotesRepositoryV2: QuotesRepositoryV2,
private val stakingRepository: StakingRepository,
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
@ -58,7 +56,6 @@ class CachedCurrenciesStatusesOperations(
) : BaseCurrenciesStatusesOperations,
BaseCurrencyStatusOperations(
currenciesRepository = currenciesRepository,
quotesRepository = quotesRepository,
quotesRepositoryV2 = quotesRepositoryV2,
stakingRepository = stakingRepository,
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
@ -192,13 +189,9 @@ class CachedCurrenciesStatusesOperations(
async {
val rawCurrenciesIds = currenciesIds.mapNotNullTo(mutableSetOf()) { it.rawCurrencyId }
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(currenciesIds = rawCurrenciesIds, appCurrencyId = null),
)
} else {
quotesRepository.fetchQuotes(rawCurrenciesIds)
}
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(currenciesIds = rawCurrenciesIds, appCurrencyId = null),
)
},
async {
if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) {
@ -280,44 +273,20 @@ class CachedCurrenciesStatusesOperations(
}
private fun getQuotes(tokensIds: NonEmptySet<CryptoCurrency.ID>): Flow<Either<TokenListError, Set<Quote>>> {
return if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
getQuotesUpdates(
rawCurrencyIds = tokensIds.mapNotNullTo(
destination = hashSetOf(),
transform = CryptoCurrency.ID::rawCurrencyId,
),
)
} else {
quotesRepository.getQuotesUpdates(tokensIds.mapNotNull { it.rawCurrencyId }.toSet())
.map<Set<Quote>, Either<TokenListError, Set<Quote>>> { it.right() }
.retryWhen { cause, _ ->
emit(TokenListError.DataError(cause).left())
// adding delay before retry to avoid spam when flow restarted
delay(RETRY_DELAY)
true
}
.distinctUntilChanged()
}
return getQuotesUpdates(
rawCurrencyIds = tokensIds.mapNotNullTo(
destination = hashSetOf(),
transform = CryptoCurrency.ID::rawCurrencyId,
),
)
}
override fun getQuotes(id: CryptoCurrency.RawID): Flow<Either<Error, Set<Quote>>> {
return if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
singleQuoteSupplier(
params = SingleQuoteProducer.Params(rawCurrencyId = id),
)
.map<Quote, Either<Error, Set<Quote>>> { setOf(it).right() }
.distinctUntilChanged()
} else {
quotesRepository.getQuotesUpdates(setOf(id))
.map<Set<Quote>, Either<Error, Set<Quote>>> { it.right() }
.retryWhen { cause, _ ->
emit(Error.DataError(cause).left())
// adding delay before retry to avoid spam when flow restarted
delay(RETRY_DELAY)
true
}
.distinctUntilChanged()
}
return singleQuoteSupplier(
params = SingleQuoteProducer.Params(rawCurrencyId = id),
)
.map<Quote, Either<Error, Set<Quote>>> { setOf(it).right() }
.distinctUntilChanged()
}
override fun getNetworksStatuses(

View file

@ -23,14 +23,12 @@ import com.tangem.domain.quotes.QuotesRepositoryV2
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.GetCurrencyCheckUseCase
import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.FeePaidCurrency
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyCheck
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.CurrencyChecksRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.transaction.error.GetFeeError
import com.tangem.domain.transaction.usecase.*
import com.tangem.domain.utils.convertToSdkAmount
@ -67,9 +65,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
private val createTransactionExtrasUseCase: CreateTransactionDataExtrasUseCase,
private val createApprovalTransactionUseCase: CreateApprovalTransactionUseCase,
private val isDemoCardUseCase: IsDemoCardUseCase,
private val quotesRepository: QuotesRepository,
private val quotesRepositoryV2: QuotesRepositoryV2,
private val tokensFeatureToggles: TokensFeatureToggles,
private val swapTransactionRepository: SwapTransactionRepository,
private val currencyChecksRepository: CurrencyChecksRepository,
private val appCurrencyRepository: AppCurrencyRepository,
@ -1802,7 +1798,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
private suspend fun getQuotes(vararg ids: CryptoCurrency.ID): Map<CryptoCurrency.ID, Quote.Value> {
val set = ids.mapNotNull { it.rawCurrencyId }
.toSet()
.getQuotesOrEmpty(false)
.getQuotesOrEmpty()
.filterIsInstance<Quote.Value>()
return ids
@ -1810,16 +1806,10 @@ internal class SwapInteractorImpl @AssistedInject constructor(
.toMap()
}
private suspend fun Set<CryptoCurrency.RawID>.getQuotesOrEmpty(refresh: Boolean): Set<Quote> {
return try {
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
quotesRepositoryV2.getMultiQuoteSyncOrNull(currenciesIds = this).orEmpty()
} else {
quotesRepository.getQuotesSync(this, refresh)
}
} catch (t: Throwable) {
emptySet()
}
private suspend fun Set<CryptoCurrency.RawID>.getQuotesOrEmpty(): Set<Quote> {
return runCatching { quotesRepositoryV2.getMultiQuoteSyncOrNull(currenciesIds = this) }
.getOrNull()
.orEmpty()
}
companion object {

View file

@ -8,10 +8,8 @@ import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.quotes.QuotesRepositoryV2
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
import com.tangem.domain.tokens.TokensFeatureToggles
import com.tangem.domain.tokens.model.Quote
import com.tangem.domain.tokens.model.analytics.TokenExchangeAnalyticsEvent
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.feature.swap.domain.SwapTransactionRepository
import com.tangem.feature.swap.domain.api.SwapRepository
@ -34,9 +32,7 @@ import kotlinx.coroutines.flow.map
internal class ExchangeStatusFactory @AssistedInject constructor(
private val swapTransactionRepository: SwapTransactionRepository,
private val swapRepository: SwapRepository,
private val quotesRepository: QuotesRepository,
private val quotesRepositoryV2: QuotesRepositoryV2,
private val tokensFeatureToggles: TokensFeatureToggles,
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
private val swapTransactionStatusStore: SwapTransactionStatusStore,
private val analyticsEventsHandler: AnalyticsEventHandler,
@ -65,7 +61,7 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
val quotes = savedTransactions
?.flatMap { setOf(it.fromCryptoCurrency.id, it.toCryptoCurrency.id) }
?.toSet()
?.getQuotesOrEmpty(true)
?.getQuotesOrEmpty()
?: emptySet()
getExchangeStatusState(
@ -191,18 +187,12 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
}
}
private suspend fun Set<CryptoCurrency.ID>.getQuotesOrEmpty(refresh: Boolean): Set<Quote> {
return try {
val rawIds = mapNotNull { it.rawCurrencyId }.toSet()
private suspend fun Set<CryptoCurrency.ID>.getQuotesOrEmpty(): Set<Quote> {
val rawIds = mapNotNull { it.rawCurrencyId }.toSet()
if (tokensFeatureToggles.isQuotesLoadingRefactoringEnabled) {
quotesRepositoryV2.getMultiQuoteSyncOrNull(currenciesIds = rawIds).orEmpty()
} else {
quotesRepository.getQuotesSync(rawIds, refresh)
}
} catch (t: Throwable) {
emptySet()
}
return runCatching { quotesRepositoryV2.getMultiQuoteSyncOrNull(currenciesIds = rawIds) }
.getOrNull()
.orEmpty()
}
@AssistedFactory