Updated on 2026-08-14

This commit is contained in:
Tangem 2025-06-10 19:16:32 +04:00
parent 9b281427a1
commit c38b5836ff
37 changed files with 285 additions and 262 deletions

View file

@ -5,7 +5,7 @@ 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.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.TokensFeatureToggles
@ -71,7 +71,7 @@ internal object ManageTokensDomainModule {
derivationsRepository: DerivationsRepository,
stakingRepository: StakingRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): SaveManagedTokensUseCase {
@ -82,7 +82,7 @@ internal object ManageTokensDomainModule {
derivationsRepository = derivationsRepository,
stakingRepository = stakingRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)

View file

@ -6,8 +6,8 @@ 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.MultiQuoteFetcher
import com.tangem.domain.quotes.single.SingleQuoteSupplier
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
@ -52,8 +52,8 @@ object MarketsDomainModule {
@Provides
@Singleton
fun provideGetTokenQuotesUseCase(singleQuoteSupplier: SingleQuoteSupplier): GetCurrencyQuotesUseCase {
return GetCurrencyQuotesUseCase(singleQuoteSupplier = singleQuoteSupplier)
fun provideGetTokenQuotesUseCase(singleQuoteStatusSupplier: SingleQuoteStatusSupplier): GetCurrencyQuotesUseCase {
return GetCurrencyQuotesUseCase(singleQuoteStatusSupplier = singleQuoteStatusSupplier)
}
@Provides
@ -64,7 +64,7 @@ object MarketsDomainModule {
currenciesRepository: CurrenciesRepository,
stakingRepository: StakingRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): SaveMarketTokensUseCase {
@ -74,7 +74,7 @@ object MarketsDomainModule {
currenciesRepository = currenciesRepository,
stakingRepository = stakingRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)

View file

@ -3,8 +3,8 @@ package com.tangem.tap.di.domain
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.nft.*
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.quotes.single.SingleQuoteFetcher
import com.tangem.domain.quotes.single.SingleQuoteSupplier
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -92,18 +92,18 @@ internal object NFTDomainModule {
@Singleton
fun provideGetNFTPriceUseCase(
nftRepository: NFTRepository,
singleQuoteSupplier: SingleQuoteSupplier,
singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
): GetNFTPriceUseCase {
return GetNFTPriceUseCase(nftRepository, singleQuoteSupplier)
return GetNFTPriceUseCase(nftRepository, singleQuoteStatusSupplier)
}
@Provides
@Singleton
fun provideFetchNFTPriceUseCase(
nftRepository: NFTRepository,
singleQuoteFetcher: SingleQuoteFetcher,
singleQuoteStatusFetcher: SingleQuoteStatusFetcher,
): FetchNFTPriceUseCase {
return FetchNFTPriceUseCase(nftRepository, singleQuoteFetcher)
return FetchNFTPriceUseCase(nftRepository, singleQuoteStatusFetcher)
}
@Provides

View file

@ -9,8 +9,8 @@ import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.promo.PromoRepository
import com.tangem.domain.quotes.QuotesRepository
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.single.SingleQuoteSupplier
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
@ -42,7 +42,7 @@ internal object TokensDomainModule {
currenciesRepository: CurrenciesRepository,
stakingRepository: StakingRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): AddCryptoCurrenciesUseCase {
@ -50,7 +50,7 @@ internal object TokensDomainModule {
currenciesRepository = currenciesRepository,
stakingRepository = stakingRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
singleYieldBalanceFetcher = singleYieldBalanceFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
@ -62,7 +62,7 @@ internal object TokensDomainModule {
currenciesRepository: CurrenciesRepository,
stakingRepository: StakingRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): FetchTokenListUseCase {
@ -70,7 +70,7 @@ internal object TokensDomainModule {
currenciesRepository = currenciesRepository,
stakingRepository = stakingRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
@ -161,7 +161,7 @@ internal object TokensDomainModule {
currenciesRepository: CurrenciesRepository,
stakingRepository: StakingRepository,
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): FetchCurrencyStatusUseCase {
@ -169,7 +169,7 @@ internal object TokensDomainModule {
currenciesRepository = currenciesRepository,
stakingRepository = stakingRepository,
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
singleYieldBalanceFetcher = singleYieldBalanceFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
@ -181,7 +181,7 @@ internal object TokensDomainModule {
currenciesRepository: CurrenciesRepository,
stakingRepository: StakingRepository,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
tokensFeatureToggles: TokensFeatureToggles,
): FetchCardTokenListUseCase {
@ -189,7 +189,7 @@ internal object TokensDomainModule {
currenciesRepository = currenciesRepository,
stakingRepository = stakingRepository,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
tokensFeatureToggles = tokensFeatureToggles,
)
@ -346,11 +346,11 @@ internal object TokensDomainModule {
@Singleton
fun provideRefreshMultiCurrencyWalletQuotesUseCase(
currenciesRepository: CurrenciesRepository,
multiQuoteFetcher: MultiQuoteFetcher,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
): RefreshMultiCurrencyWalletQuotesUseCase {
return RefreshMultiCurrencyWalletQuotesUseCase(
currenciesRepository = currenciesRepository,
multiQuoteFetcher = multiQuoteFetcher,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
)
}
@ -373,8 +373,8 @@ internal object TokensDomainModule {
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
singleQuoteSupplier: SingleQuoteSupplier,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
): BaseCurrenciesStatusesOperations {
@ -385,8 +385,8 @@ internal object TokensDomainModule {
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
singleQuoteSupplier = singleQuoteSupplier,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
singleQuoteStatusSupplier = singleQuoteStatusSupplier,
singleYieldBalanceSupplier = singleYieldBalanceSupplier,
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
tokensFeatureToggles = tokensFeatureToggles,
@ -403,8 +403,8 @@ internal object TokensDomainModule {
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
multiQuoteFetcher: MultiQuoteFetcher,
singleQuoteSupplier: SingleQuoteSupplier,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
): BaseCurrencyStatusOperations {
@ -415,8 +415,8 @@ internal object TokensDomainModule {
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
multiQuoteFetcher = multiQuoteFetcher,
singleQuoteSupplier = singleQuoteSupplier,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
singleQuoteStatusSupplier = singleQuoteStatusSupplier,
singleYieldBalanceSupplier = singleYieldBalanceSupplier,
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
tokensFeatureToggles = tokensFeatureToggles,

View file

@ -1,30 +0,0 @@
package com.tangem.data.quotes.di
import com.tangem.data.quotes.multi.DefaultMultiQuoteFetcher
import com.tangem.data.quotes.multi.DefaultMultiQuoteUpdater
import com.tangem.data.quotes.single.DefaultSingleQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteUpdater
import com.tangem.domain.quotes.single.SingleQuoteFetcher
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal interface QuoteFetcherModule {
@Binds
@Singleton
fun bindMultiQuoteFetcher(impl: DefaultMultiQuoteFetcher): MultiQuoteFetcher
@Binds
@Singleton
fun bindMultiQuoteUpdater(impl: DefaultMultiQuoteUpdater): MultiQuoteUpdater
@Binds
@Singleton
fun bindSingleQuoteFetcher(impl: DefaultSingleQuoteFetcher): SingleQuoteFetcher
}

View file

@ -1,18 +0,0 @@
package com.tangem.data.quotes.di
import com.tangem.data.quotes.single.DefaultSingleQuoteProducer
import com.tangem.domain.quotes.single.SingleQuoteProducer
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal interface QuoteProducerFactoryModule {
@Binds
@Singleton
fun bindSingleQuoteProducerFactory(impl: DefaultSingleQuoteProducer.Factory): SingleQuoteProducer.Factory
}

View file

@ -0,0 +1,24 @@
package com.tangem.data.quotes.di
import com.tangem.data.quotes.multi.DefaultMultiQuoteStatusFetcher
import com.tangem.data.quotes.single.DefaultSingleQuoteStatusFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal interface QuoteStatusFetcherModule {
@Binds
@Singleton
fun bindMultiQuoteStatusFetcher(impl: DefaultMultiQuoteStatusFetcher): MultiQuoteStatusFetcher
@Binds
@Singleton
fun bindSingleQuoteStatusFetcher(impl: DefaultSingleQuoteStatusFetcher): SingleQuoteStatusFetcher
}

View file

@ -0,0 +1,20 @@
package com.tangem.data.quotes.di
import com.tangem.data.quotes.single.DefaultSingleQuoteStatusProducer
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal interface QuoteStatusProducerFactoryModule {
@Binds
@Singleton
fun bindSingleQuoteStatusProducerFactory(
impl: DefaultSingleQuoteStatusProducer.Factory,
): SingleQuoteStatusProducer.Factory
}

View file

@ -1,7 +1,7 @@
package com.tangem.data.quotes.di
import com.tangem.domain.quotes.single.SingleQuoteProducer
import com.tangem.domain.quotes.single.SingleQuoteSupplier
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -10,12 +10,12 @@ import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object QuoteSupplierModule {
internal object QuoteStatusSupplierModule {
@Provides
@Singleton
fun provideSingleQuoteSupplier(factory: SingleQuoteProducer.Factory): SingleQuoteSupplier {
return object : SingleQuoteSupplier(
fun provideSingleQuoteStatusSupplier(factory: SingleQuoteStatusProducer.Factory): SingleQuoteStatusSupplier {
return object : SingleQuoteStatusSupplier(
factory = factory,
keyCreator = { "single_quote_${it.rawCurrencyId.value}" },
) {}

View file

@ -4,15 +4,19 @@ import android.content.Context
import androidx.datastore.core.DataStoreFactory
import androidx.datastore.dataStoreFile
import com.squareup.moshi.Moshi
import com.tangem.data.quotes.multi.DefaultMultiQuoteUpdater
import com.tangem.data.quotes.repository.DefaultQuotesRepository
import com.tangem.data.quotes.store.DefaultQuotesStatusesStore
import com.tangem.data.quotes.store.QuotesStatusesStore
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.local.datastore.RuntimeSharedStore
import com.tangem.datasource.utils.MoshiDataStoreSerializer
import com.tangem.datasource.utils.mapWithStringKeyTypes
import com.tangem.domain.quotes.QuotesRepository
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.quotes.multi.MultiQuoteUpdater
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
import dagger.Provides
@ -51,5 +55,23 @@ internal object QuotesDataModule {
@Singleton
@Provides
fun providesQuotesRepository(impl: DefaultQuotesRepository): QuotesRepository = impl
fun providesQuotesRepository(quotesStatusesStore: QuotesStatusesStore): QuotesRepository {
return DefaultQuotesRepository(quotesStatusesStore = quotesStatusesStore)
}
@Singleton
@Provides
fun bindMultiQuoteUpdater(
appCurrencyResponseStore: AppCurrencyResponseStore,
quotesStatusesStore: QuotesStatusesStore,
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
dispatchers: CoroutineDispatcherProvider,
): MultiQuoteUpdater {
return DefaultMultiQuoteUpdater(
appCurrencyResponseStore = appCurrencyResponseStore,
quotesStatusesStore = quotesStatusesStore,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
dispatchers = dispatchers,
)
}
}

View file

@ -10,7 +10,7 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
import com.tangem.domain.core.utils.catchOn
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
import timber.log.Timber
@ -18,30 +18,30 @@ import javax.inject.Inject
import javax.inject.Singleton
/**
* Default implementation of [MultiQuoteFetcher]
* Default implementation of [MultiQuoteStatusFetcher]
*
* @property tangemTechApi tangemTech api
* @property appCurrencyResponseStore app currency response store
* @property quotesStore quotes store
* @property quotesStatusesStore quotes store
* @property dispatchers dispatchers
*
[REDACTED_AUTHOR]
*/
@Singleton
internal class DefaultMultiQuoteFetcher @Inject constructor(
internal class DefaultMultiQuoteStatusFetcher @Inject constructor(
private val tangemTechApi: TangemTechApi,
private val appCurrencyResponseStore: AppCurrencyResponseStore,
private val quotesStore: QuotesStatusesStore,
private val quotesStatusesStore: QuotesStatusesStore,
private val dispatchers: CoroutineDispatcherProvider,
) : MultiQuoteFetcher {
) : MultiQuoteStatusFetcher {
override suspend fun invoke(params: MultiQuoteFetcher.Params) = Either.catchOn(dispatchers.default) {
override suspend fun invoke(params: MultiQuoteStatusFetcher.Params) = Either.catchOn(dispatchers.default) {
if (params.currenciesIds.isEmpty()) {
Timber.d("No currencies to fetch quotes for")
return@catchOn
}
quotesStore.setSourceAsCache(currenciesIds = params.currenciesIds)
quotesStatusesStore.setSourceAsCache(currenciesIds = params.currenciesIds)
val replacementIdsResult = QuotesUnsupportedCurrenciesIdAdapter.replaceUnsupportedCurrencies(
currenciesIds = params.currenciesIds.mapTo(
@ -67,14 +67,14 @@ internal class DefaultMultiQuoteFetcher @Inject constructor(
filteredIds = replacementIdsResult.idsFiltered,
)
quotesStore.store(values = updatedResponse.quotes)
quotesStatusesStore.store(values = updatedResponse.quotes)
}
.onLeft {
Timber.e(it)
quotesStore.setSourceAsOnlyCache(currenciesIds = params.currenciesIds)
quotesStatusesStore.setSourceAsOnlyCache(currenciesIds = params.currenciesIds)
}
private suspend fun getAppCurrencyId(params: MultiQuoteFetcher.Params): String {
private suspend fun getAppCurrencyId(params: MultiQuoteStatusFetcher.Params): String {
val appCurrencyId = params.appCurrencyId
?: appCurrencyResponseStore.getSyncOrNull()?.id

View file

@ -6,7 +6,7 @@ import com.tangem.data.quotes.store.QuotesStatusesStore
import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
import com.tangem.domain.core.utils.EitherFlow
import com.tangem.domain.models.quote.QuoteStatus
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.quotes.multi.MultiQuoteUpdater
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.JobHolder
@ -17,24 +17,21 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton
/**
* Default implementation of [MultiQuoteUpdater] which updates quotes when the app currency changes
*
* @property appCurrencyResponseStore app currency response store
* @property quotesStore quotes store
* @property multiQuoteFetcher multi quote fetcher
* @property quotesStatusesStore quotes store
* @property multiQuoteStatusFetcher multi quote status fetcher
* @param dispatchers dispatchers
*
[REDACTED_AUTHOR]
*/
@Singleton
internal class DefaultMultiQuoteUpdater @Inject constructor(
internal class DefaultMultiQuoteUpdater(
private val appCurrencyResponseStore: AppCurrencyResponseStore,
private val quotesStore: QuotesStatusesStore,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val quotesStatusesStore: QuotesStatusesStore,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
dispatchers: CoroutineDispatcherProvider,
) : MultiQuoteUpdater {
@ -60,11 +57,14 @@ internal class DefaultMultiQuoteUpdater @Inject constructor(
.distinctUntilChanged()
.filterNotNull()
.mapLatest { appCurrency ->
val currenciesIds = quotesStore.getAllSyncOrNull().orEmpty()
val currenciesIds = quotesStatusesStore.getAllSyncOrNull().orEmpty()
.mapTo(destination = hashSetOf(), transform = QuoteStatus::rawCurrencyId)
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = appCurrency.id),
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(
currenciesIds = currenciesIds,
appCurrencyId = appCurrency.id,
),
)
.onLeft(Timber::e)
}

View file

@ -5,7 +5,6 @@ import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.quote.QuoteStatus
import com.tangem.domain.quotes.QuotesRepository
import timber.log.Timber
import javax.inject.Inject
/**
* Default implementation of [QuotesRepository]
@ -14,7 +13,7 @@ import javax.inject.Inject
*
[REDACTED_AUTHOR]
*/
internal class DefaultQuotesRepository @Inject constructor(
internal class DefaultQuotesRepository(
private val quotesStatusesStore: QuotesStatusesStore,
) : QuotesRepository {

View file

@ -1,17 +0,0 @@
package com.tangem.data.quotes.single
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.single.SingleQuoteFetcher
import javax.inject.Inject
internal class DefaultSingleQuoteFetcher @Inject constructor(
private val multiQuoteFetcher: MultiQuoteFetcher,
) : SingleQuoteFetcher {
override suspend fun invoke(params: SingleQuoteFetcher.Params) = multiQuoteFetcher.invoke(
MultiQuoteFetcher.Params(
currenciesIds = setOf(params.rawCurrencyId),
appCurrencyId = params.appCurrencyId,
),
)
}

View file

@ -0,0 +1,22 @@
package com.tangem.data.quotes.single
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
import javax.inject.Inject
/**
* Default implementation of [SingleQuoteStatusFetcher]
*
* @property multiQuoteStatusFetcher fetcher of quotes statuses
*/
internal class DefaultSingleQuoteStatusFetcher @Inject constructor(
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
) : SingleQuoteStatusFetcher {
override suspend fun invoke(params: SingleQuoteStatusFetcher.Params) = multiQuoteStatusFetcher.invoke(
MultiQuoteStatusFetcher.Params(
currenciesIds = setOf(params.rawCurrencyId),
appCurrencyId = params.appCurrencyId,
),
)
}

View file

@ -2,7 +2,7 @@ package com.tangem.data.quotes.single
import com.tangem.data.quotes.store.QuotesStatusesStore
import com.tangem.domain.models.quote.QuoteStatus
import com.tangem.domain.quotes.single.SingleQuoteProducer
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -13,28 +13,28 @@ import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.mapNotNull
/**
* Default implementation of [SingleQuoteProducer]
* Default implementation of [SingleQuoteStatusProducer]
*
* @property params params
* @property quotesStore quotes store
* @property params params
* @property quotesStatusesStore quotes store
*/
internal class DefaultSingleQuoteProducer @AssistedInject constructor(
@Assisted val params: SingleQuoteProducer.Params,
private val quotesStore: QuotesStatusesStore,
internal class DefaultSingleQuoteStatusProducer @AssistedInject constructor(
@Assisted val params: SingleQuoteStatusProducer.Params,
private val quotesStatusesStore: QuotesStatusesStore,
private val dispatchers: CoroutineDispatcherProvider,
) : SingleQuoteProducer {
) : SingleQuoteStatusProducer {
override val fallback: QuoteStatus = QuoteStatus(rawCurrencyId = params.rawCurrencyId)
override fun produce(): Flow<QuoteStatus> {
return quotesStore.get()
return quotesStatusesStore.get()
.mapNotNull { quotes -> quotes.firstOrNull { it.rawCurrencyId == params.rawCurrencyId } }
.distinctUntilChanged()
.flowOn(dispatchers.default)
}
@AssistedFactory
interface Factory : SingleQuoteProducer.Factory {
override fun create(params: SingleQuoteProducer.Params): DefaultSingleQuoteProducer
interface Factory : SingleQuoteStatusProducer.Factory {
override fun create(params: SingleQuoteStatusProducer.Params): DefaultSingleQuoteStatusProducer
}
}

View file

@ -12,7 +12,7 @@ import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.coEvery
import io.mockk.coVerify
@ -31,16 +31,16 @@ internal class DefaultMultiQuoteStatusFetcherTest {
private val appCurrencyResponseStore = mockk<AppCurrencyResponseStore>(relaxed = true)
private val quotesStore = mockk<QuotesStatusesStore>(relaxed = true)
private val fetcher = DefaultMultiQuoteFetcher(
private val fetcher = DefaultMultiQuoteStatusFetcher(
tangemTechApi = tangemTechApi,
appCurrencyResponseStore = appCurrencyResponseStore,
quotesStore = quotesStore,
quotesStatusesStore = quotesStore,
dispatchers = TestingCoroutineDispatcherProvider(),
)
@Test
fun `fetch quotes successfully`() = runTest {
val params = MultiQuoteFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null)
val params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null)
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns usdAppCurrency
@ -70,7 +70,7 @@ internal class DefaultMultiQuoteStatusFetcherTest {
@Test
fun `fetch quotes successfully if currenciesIds from params is empty`() = runTest {
val params = MultiQuoteFetcher.Params(currenciesIds = emptySet(), appCurrencyId = null)
val params = MultiQuoteStatusFetcher.Params(currenciesIds = emptySet(), appCurrencyId = null)
val actual = fetcher(params)
@ -88,7 +88,7 @@ internal class DefaultMultiQuoteStatusFetcherTest {
@Test
fun `fetch quotes successfully if appCurrencyId from params is not null`() = runTest {
val appCurrencyId = "usd"
val params = MultiQuoteFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = appCurrencyId)
val params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = appCurrencyId)
val coinIds = "BTC,ETH"
coEvery {
@ -116,7 +116,7 @@ internal class DefaultMultiQuoteStatusFetcherTest {
@Test
fun `fetch quotes failure because appCurrencyId from params is blank`() = runTest {
val appCurrencyId = ""
val params = MultiQuoteFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = appCurrencyId)
val params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = appCurrencyId)
val actual = fetcher(params)
@ -139,7 +139,7 @@ internal class DefaultMultiQuoteStatusFetcherTest {
@Test
fun `fetch quotes failure because api request failed`() = runTest {
val params = MultiQuoteFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null)
val params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null)
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns usdAppCurrency
@ -170,7 +170,7 @@ internal class DefaultMultiQuoteStatusFetcherTest {
@Test
fun `fetch quotes failure because app currency not found`() = runTest {
val params = MultiQuoteFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null)
val params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null)
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns null

View file

@ -6,7 +6,7 @@ import com.tangem.common.test.utils.getEmittedValues
import com.tangem.data.quotes.store.QuotesStatusesStore
import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.*
import kotlinx.coroutines.flow.*
@ -20,12 +20,12 @@ internal class DefaultMultiQuoteStatusUpdaterTest {
private val appCurrencyResponseStore: AppCurrencyResponseStore = mockk()
private val quotesStore: QuotesStatusesStore = mockk()
private val multiQuoteFetcher: MultiQuoteFetcher = mockk()
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher = mockk()
private val multiQuoteUpdater = DefaultMultiQuoteUpdater(
appCurrencyResponseStore = appCurrencyResponseStore,
quotesStore = quotesStore,
multiQuoteFetcher = multiQuoteFetcher,
quotesStatusesStore = quotesStore,
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
dispatchers = TestingCoroutineDispatcherProvider(),
)
@ -36,8 +36,8 @@ internal class DefaultMultiQuoteStatusUpdaterTest {
every { appCurrencyResponseStore.get() } returns appCurrencyFlow
coEvery { quotesStore.getAllSyncOrNull() } returns emptySet()
val params = MultiQuoteFetcher.Params(currenciesIds = emptySet(), appCurrencyId = usdAppCurrency.id)
coEvery { multiQuoteFetcher(params) } returns Unit.right()
val params = MultiQuoteStatusFetcher.Params(currenciesIds = emptySet(), appCurrencyId = usdAppCurrency.id)
coEvery { multiQuoteStatusFetcher(params) } returns Unit.right()
val actual = multiQuoteUpdater.getMultiQuoteUpdatesFlow()
@ -48,7 +48,7 @@ internal class DefaultMultiQuoteStatusUpdaterTest {
coVerifyOrder {
quotesStore.getAllSyncOrNull()
multiQuoteFetcher(params)
multiQuoteStatusFetcher(params)
}
}
@ -59,8 +59,8 @@ internal class DefaultMultiQuoteStatusUpdaterTest {
every { appCurrencyResponseStore.get() } returns appCurrencyFlow
coEvery { quotesStore.getAllSyncOrNull() } returns emptySet()
val params = MultiQuoteFetcher.Params(currenciesIds = emptySet(), appCurrencyId = usdAppCurrency.id)
coEvery { multiQuoteFetcher(params) } returns Unit.right()
val params = MultiQuoteStatusFetcher.Params(currenciesIds = emptySet(), appCurrencyId = usdAppCurrency.id)
coEvery { multiQuoteStatusFetcher(params) } returns Unit.right()
val actual = multiQuoteUpdater.getMultiQuoteUpdatesFlow()
@ -71,7 +71,7 @@ internal class DefaultMultiQuoteStatusUpdaterTest {
coVerifyOrder {
quotesStore.getAllSyncOrNull()
multiQuoteFetcher(params)
multiQuoteStatusFetcher(params)
}
}
@ -90,7 +90,7 @@ internal class DefaultMultiQuoteStatusUpdaterTest {
coVerify(inverse = true) {
quotesStore.getAllSyncOrNull()
multiQuoteFetcher(any())
multiQuoteStatusFetcher(any())
}
}
@ -111,8 +111,8 @@ internal class DefaultMultiQuoteStatusUpdaterTest {
every { appCurrencyResponseStore.get() } returns appCurrencyFlow
coEvery { quotesStore.getAllSyncOrNull() } returns emptySet()
val params = MultiQuoteFetcher.Params(currenciesIds = emptySet(), appCurrencyId = usdAppCurrency.id)
coEvery { multiQuoteFetcher(params) } returns Unit.right()
val params = MultiQuoteStatusFetcher.Params(currenciesIds = emptySet(), appCurrencyId = usdAppCurrency.id)
coEvery { multiQuoteStatusFetcher(params) } returns Unit.right()
val actual = multiQuoteUpdater.getMultiQuoteUpdatesFlow()
@ -126,7 +126,7 @@ internal class DefaultMultiQuoteStatusUpdaterTest {
coVerify(inverse = true) {
quotesStore.getAllSyncOrNull()
multiQuoteFetcher(any())
multiQuoteStatusFetcher(any())
}
innerFlow.emit(value = true)
@ -136,7 +136,7 @@ internal class DefaultMultiQuoteStatusUpdaterTest {
coVerifyOrder {
quotesStore.getAllSyncOrNull()
multiQuoteFetcher(params)
multiQuoteStatusFetcher(params)
}
}

View file

@ -2,7 +2,7 @@ package com.tangem.data.quotes.single
import com.google.common.truth.Truth
import com.tangem.common.test.data.quote.MockQuoteResponseFactory
import com.tangem.data.quotes.multi.DefaultMultiQuoteFetcher
import com.tangem.data.quotes.multi.DefaultMultiQuoteStatusFetcher
import com.tangem.data.quotes.store.QuotesStatusesStore
import com.tangem.data.quotes.store.setSourceAsCache
import com.tangem.data.quotes.store.setSourceAsOnlyCache
@ -13,7 +13,7 @@ import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.quotes.single.SingleQuoteFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.coEvery
import io.mockk.coVerify
@ -29,18 +29,18 @@ internal class DefaultSingleQuoteStatusFetcherTest {
private val appCurrencyResponseStore = mockk<AppCurrencyResponseStore>(relaxed = true)
private val quotesStore = mockk<QuotesStatusesStore>(relaxed = true)
private val multiFetcher = DefaultMultiQuoteFetcher(
private val multiFetcher = DefaultMultiQuoteStatusFetcher(
tangemTechApi = tangemTechApi,
appCurrencyResponseStore = appCurrencyResponseStore,
quotesStore = quotesStore,
quotesStatusesStore = quotesStore,
dispatchers = TestingCoroutineDispatcherProvider(),
)
private val singleFetcher = DefaultSingleQuoteFetcher(multiFetcher)
private val singleFetcher = DefaultSingleQuoteStatusFetcher(multiFetcher)
@Test
fun `fetch single quote successfully`() = runTest {
val params = SingleQuoteFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = null)
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = null)
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns usdAppCurrency
@ -68,7 +68,7 @@ internal class DefaultSingleQuoteStatusFetcherTest {
@Test
fun `fetch single quote successfully if appCurrencyId from params is not null`() = runTest {
val appCurrencyId = "usd"
val params = SingleQuoteFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = appCurrencyId)
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = appCurrencyId)
val coinIds = "BTC"
coEvery {
@ -89,7 +89,7 @@ internal class DefaultSingleQuoteStatusFetcherTest {
@Test
fun `fetch single quote failure because appCurrencyId from params is blank`() = runTest {
val appCurrencyId = ""
val params = SingleQuoteFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = appCurrencyId)
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = appCurrencyId)
val actual = singleFetcher(params)
@ -106,7 +106,7 @@ internal class DefaultSingleQuoteStatusFetcherTest {
@Test
fun `fetch single quote failure because api request failed`() = runTest {
val params = SingleQuoteFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = null)
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = null)
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns usdAppCurrency
@ -134,7 +134,7 @@ internal class DefaultSingleQuoteStatusFetcherTest {
@Test
fun `fetch single quote failure because app currency not found`() = runTest {
val params = SingleQuoteFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = null)
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = null)
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns null

View file

@ -6,7 +6,7 @@ import com.tangem.data.quotes.store.QuotesStatusesStore
import com.tangem.domain.models.StatusSource
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.quote.QuoteStatus
import com.tangem.domain.quotes.single.SingleQuoteProducer
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.every
import io.mockk.mockk
@ -21,15 +21,15 @@ import java.math.BigDecimal
*/
internal class DefaultSingleQuoteStatusProducerTest {
private val params = SingleQuoteProducer.Params(
private val params = SingleQuoteStatusProducer.Params(
rawCurrencyId = CryptoCurrency.RawID(value = "BTC"),
)
private val quotesStore = mockk<QuotesStatusesStore>()
private val producer = DefaultSingleQuoteProducer(
private val producer = DefaultSingleQuoteStatusProducer(
params = params,
quotesStore = quotesStore,
quotesStatusesStore = quotesStore,
dispatchers = TestingCoroutineDispatcherProvider(),
)

View file

@ -8,7 +8,7 @@ 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.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
@ -25,7 +25,7 @@ class SaveManagedTokensUseCase(
private val derivationsRepository: DerivationsRepository,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
@ -127,8 +127,8 @@ class SaveManagedTokensUseCase(
}
private suspend fun refreshUpdatedQuotes(addedCurrencies: List<CryptoCurrency>) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
appCurrencyId = null,
),

View file

@ -5,15 +5,15 @@ import arrow.core.Option
import arrow.core.toOption
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.quote.QuoteStatus
import com.tangem.domain.quotes.single.SingleQuoteProducer
import com.tangem.domain.quotes.single.SingleQuoteSupplier
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
class GetCurrencyQuotesUseCase(
private val singleQuoteSupplier: SingleQuoteSupplier,
private val singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
) {
// TODO apply interval parameter [REDACTED_TASK_KEY]
operator fun invoke(
@ -23,8 +23,8 @@ class GetCurrencyQuotesUseCase(
): Flow<Option<QuoteStatus.Data>> {
val rawId = currencyID.rawCurrencyId ?: return flowOf(None)
return singleQuoteSupplier(
params = SingleQuoteProducer.Params(rawCurrencyId = rawId),
return singleQuoteStatusSupplier(
params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawId),
)
.map { (it.value as? QuoteStatus.Data).toOption() }
.catch { emit(None) }

View file

@ -6,7 +6,7 @@ import com.tangem.domain.markets.repositories.MarketsTokenRepository
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
@ -30,7 +30,7 @@ class SaveMarketTokensUseCase(
private val currenciesRepository: CurrenciesRepository,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
@ -108,8 +108,8 @@ class SaveMarketTokensUseCase(
}
private suspend fun refreshUpdatedQuotes(addedCurrencies: List<CryptoCurrency>) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
appCurrencyId = null,
),

View file

@ -3,11 +3,11 @@ package com.tangem.domain.nft
import arrow.core.Either
import com.tangem.domain.models.network.Network
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.quotes.single.SingleQuoteFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
class FetchNFTPriceUseCase(
private val nftRepository: NFTRepository,
private val singleQuoteFetcher: SingleQuoteFetcher,
private val singleQuoteStatusFetcher: SingleQuoteStatusFetcher,
) {
suspend operator fun invoke(network: Network, appCurrencyId: String?): Either<Throwable, Unit> {
@ -15,8 +15,8 @@ class FetchNFTPriceUseCase(
val nftCurrency = nftRepository.getNFTCurrency(network)
val rawId = nftCurrency.id.rawCurrencyId ?: error("Invalid nft currency id")
singleQuoteFetcher(
params = SingleQuoteFetcher.Params(
singleQuoteStatusFetcher(
params = SingleQuoteStatusFetcher.Params(
rawCurrencyId = rawId,
appCurrencyId = appCurrencyId,
),

View file

@ -5,15 +5,15 @@ import com.tangem.domain.models.quote.fold
import com.tangem.domain.nft.models.NFTAsset
import com.tangem.domain.nft.models.NFTSalePrice
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.quotes.single.SingleQuoteProducer
import com.tangem.domain.quotes.single.SingleQuoteSupplier
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class GetNFTPriceUseCase(
private val nftRepository: NFTRepository,
private val singleQuoteSupplier: SingleQuoteSupplier,
private val singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
) {
suspend operator fun invoke(userWalletId: UserWalletId, nftAsset: NFTAsset): Either<Throwable, Flow<NFTSalePrice>> {
@ -21,8 +21,8 @@ class GetNFTPriceUseCase(
val nftCurrency = nftRepository.getNFTCurrency(nftAsset.network)
val rawId = nftCurrency.id.rawCurrencyId ?: error("Invalid nft currency id")
singleQuoteSupplier(
params = SingleQuoteProducer.Params(rawCurrencyId = rawId),
singleQuoteStatusSupplier(
params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawId),
).map { quote ->
val nftPrice = nftRepository.getNFTSalePrice(
userWalletId = userWalletId,

View file

@ -4,11 +4,11 @@ import com.tangem.domain.core.flow.FlowFetcher
import com.tangem.domain.models.currency.CryptoCurrency
/**
* Fetcher of quotes
* Fetcher of quotes statuses for specified list of [CryptoCurrency.RawID]
*
[REDACTED_AUTHOR]
*/
interface MultiQuoteFetcher : FlowFetcher<MultiQuoteFetcher.Params> {
interface MultiQuoteStatusFetcher : FlowFetcher<MultiQuoteStatusFetcher.Params> {
/**
* Params

View file

@ -4,16 +4,17 @@ import com.tangem.domain.core.flow.FlowFetcher
import com.tangem.domain.models.currency.CryptoCurrency
/**
* Fetcher of quote for [CryptoCurrency.RawID]
* Fetcher of quote for specified [CryptoCurrency.RawID]
*
[REDACTED_AUTHOR]
*/
interface SingleQuoteFetcher : FlowFetcher<SingleQuoteFetcher.Params> {
interface SingleQuoteStatusFetcher : FlowFetcher<SingleQuoteStatusFetcher.Params> {
/**
* Params
*
* @property rawCurrencyId crypto currency id
* @property appCurrencyId app currency id, if null then selected app currency will be used
*/
data class Params(
val rawCurrencyId: CryptoCurrency.RawID,

View file

@ -9,9 +9,9 @@ import com.tangem.domain.models.quote.QuoteStatus
*
[REDACTED_AUTHOR]
*/
interface SingleQuoteProducer : FlowProducer<QuoteStatus> {
interface SingleQuoteStatusProducer : FlowProducer<QuoteStatus> {
data class Params(val rawCurrencyId: CryptoCurrency.RawID)
interface Factory : FlowProducer.Factory<Params, SingleQuoteProducer>
interface Factory : FlowProducer.Factory<Params, SingleQuoteStatusProducer>
}

View file

@ -0,0 +1,17 @@
package com.tangem.domain.quotes.single
import com.tangem.domain.core.flow.FlowCachingSupplier
import com.tangem.domain.models.quote.QuoteStatus
/**
* Supplier of quote [SingleQuoteStatusProducer.Params]
*
* @property factory factory for creating [SingleQuoteStatusProducer]
* @property keyCreator key creator
*
[REDACTED_AUTHOR]
*/
abstract class SingleQuoteStatusSupplier(
override val factory: SingleQuoteStatusProducer.Factory,
override val keyCreator: (SingleQuoteStatusProducer.Params) -> String,
) : FlowCachingSupplier<SingleQuoteStatusProducer, SingleQuoteStatusProducer.Params, QuoteStatus>()

View file

@ -1,17 +0,0 @@
package com.tangem.domain.quotes.single
import com.tangem.domain.core.flow.FlowCachingSupplier
import com.tangem.domain.models.quote.QuoteStatus
/**
* Supplier of quote [SingleQuoteProducer.Params]
*
* @property factory factory for creating [SingleQuoteProducer]
* @property keyCreator key creator
*
[REDACTED_AUTHOR]
*/
abstract class SingleQuoteSupplier(
override val factory: SingleQuoteProducer.Factory,
override val keyCreator: (SingleQuoteProducer.Params) -> String,
) : FlowCachingSupplier<SingleQuoteProducer, SingleQuoteProducer.Params, QuoteStatus>()

View file

@ -7,7 +7,7 @@ import arrow.core.raise.either
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
@ -29,7 +29,7 @@ class AddCryptoCurrenciesUseCase(
private val currenciesRepository: CurrenciesRepository,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
private val singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
@ -163,8 +163,8 @@ class AddCryptoCurrenciesUseCase(
}
private suspend fun refreshUpdatedQuotes(currencyToAdd: CryptoCurrency) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(
currenciesIds = setOfNotNull(currencyToAdd.id.rawCurrencyId),
appCurrencyId = null,
),

View file

@ -7,7 +7,7 @@ import arrow.core.raise.either
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
@ -23,7 +23,7 @@ class FetchCardTokenListUseCase(
private val currenciesRepository: CurrenciesRepository,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
@ -83,8 +83,8 @@ class FetchCardTokenListUseCase(
}
private suspend fun fetchQuotes(currenciesIds: Set<CryptoCurrency.RawID>) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null),
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null),
)
}

View file

@ -7,7 +7,7 @@ import arrow.core.raise.either
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
@ -31,7 +31,7 @@ class FetchCurrencyStatusUseCase(
private val currenciesRepository: CurrenciesRepository,
private val stakingRepository: StakingRepository,
private val singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
private val singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
@ -123,8 +123,8 @@ class FetchCurrencyStatusUseCase(
}
private suspend fun Raise<CurrencyStatusError>.fetchQuote(currencyId: CryptoCurrency.ID) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(
currenciesIds = setOfNotNull(currencyId.rawCurrencyId),
appCurrencyId = null,
),

View file

@ -9,7 +9,7 @@ import arrow.core.toNonEmptyListOrNull
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.network.Network
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
import com.tangem.domain.staking.repositories.StakingRepository
@ -33,7 +33,7 @@ class FetchTokenListUseCase(
private val currenciesRepository: CurrenciesRepository,
private val stakingRepository: StakingRepository,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
@ -112,8 +112,8 @@ class FetchTokenListUseCase(
}
private suspend fun Raise<TokenListError>.fetchQuotes(currenciesIds: Set<CryptoCurrency.ID>) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(
currenciesIds = currenciesIds.mapNotNull { it.rawCurrencyId }.toSet(),
appCurrencyId = null,
),

View file

@ -5,7 +5,7 @@ import arrow.core.getOrElse
import arrow.core.raise.catch
import arrow.core.raise.either
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.tokens.error.QuotesError
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.wallets.models.UserWalletId
@ -15,7 +15,7 @@ import kotlinx.coroutines.coroutineScope
class RefreshMultiCurrencyWalletQuotesUseCase(
private val currenciesRepository: CurrenciesRepository,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
) {
suspend operator fun invoke(userWalletId: UserWalletId): Either<QuotesError, Unit> {
@ -45,8 +45,8 @@ class RefreshMultiCurrencyWalletQuotesUseCase(
}
private suspend fun fetchQuotes(currenciesIds: Set<CryptoCurrency.ID>) {
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(
currenciesIds = currenciesIds.mapNotNullTo(hashSetOf(), CryptoCurrency.ID::rawCurrencyId),
appCurrencyId = null,
),

View file

@ -15,8 +15,8 @@ import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
import com.tangem.domain.networks.single.SingleNetworkStatusProducer
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.quotes.QuotesRepository
import com.tangem.domain.quotes.single.SingleQuoteProducer
import com.tangem.domain.quotes.single.SingleQuoteSupplier
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
import com.tangem.domain.staking.model.stakekit.YieldBalance
import com.tangem.domain.staking.model.stakekit.YieldBalanceList
import com.tangem.domain.staking.repositories.StakingRepository
@ -45,7 +45,7 @@ abstract class BaseCurrencyStatusOperations(
private val stakingRepository: StakingRepository,
private val multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
private val singleQuoteSupplier: SingleQuoteSupplier,
private val singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
private val singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
private val tokensFeatureToggles: TokensFeatureToggles,
) {
@ -191,7 +191,7 @@ abstract class BaseCurrencyStatusOperations(
}
val quote = cryptoCurrencyId.rawCurrencyId?.let { rawId ->
singleQuoteSupplier(params = SingleQuoteProducer.Params(rawCurrencyId = rawId))
singleQuoteStatusSupplier(params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawId))
.firstOrNull()
}
?.right()
@ -287,7 +287,7 @@ abstract class BaseCurrencyStatusOperations(
)
val quotes = currency.id.rawCurrencyId?.let {
singleQuoteSupplier(params = SingleQuoteProducer.Params(rawCurrencyId = it))
singleQuoteStatusSupplier(params = SingleQuoteStatusProducer.Params(rawCurrencyId = it))
.firstOrNull()
}
?.right()

View file

@ -19,9 +19,9 @@ import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
import com.tangem.domain.networks.single.SingleNetworkStatusProducer
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
import com.tangem.domain.quotes.QuotesRepository
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
import com.tangem.domain.quotes.single.SingleQuoteProducer
import com.tangem.domain.quotes.single.SingleQuoteSupplier
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
import com.tangem.domain.staking.model.stakekit.YieldBalance
import com.tangem.domain.staking.model.stakekit.YieldBalanceList
@ -48,8 +48,8 @@ class CachedCurrenciesStatusesOperations(
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
private val multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
private val multiQuoteFetcher: MultiQuoteFetcher,
private val singleQuoteSupplier: SingleQuoteSupplier,
private val multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
private val singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
private val singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
private val multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
private val tokensFeatureToggles: TokensFeatureToggles,
@ -60,7 +60,7 @@ class CachedCurrenciesStatusesOperations(
stakingRepository = stakingRepository,
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
singleQuoteSupplier = singleQuoteSupplier,
singleQuoteStatusSupplier = singleQuoteStatusSupplier,
singleYieldBalanceSupplier = singleYieldBalanceSupplier,
tokensFeatureToggles = tokensFeatureToggles,
) {
@ -189,8 +189,8 @@ class CachedCurrenciesStatusesOperations(
async {
val rawCurrenciesIds = currenciesIds.mapNotNullTo(mutableSetOf()) { it.rawCurrencyId }
multiQuoteFetcher(
params = MultiQuoteFetcher.Params(currenciesIds = rawCurrenciesIds, appCurrencyId = null),
multiQuoteStatusFetcher(
params = MultiQuoteStatusFetcher.Params(currenciesIds = rawCurrenciesIds, appCurrencyId = null),
)
},
async {
@ -282,8 +282,8 @@ class CachedCurrenciesStatusesOperations(
}
override fun getQuotes(id: CryptoCurrency.RawID): Flow<Either<Error, Set<QuoteStatus>>> {
return singleQuoteSupplier(
params = SingleQuoteProducer.Params(rawCurrencyId = id),
return singleQuoteStatusSupplier(
params = SingleQuoteStatusProducer.Params(rawCurrencyId = id),
)
.map<QuoteStatus, Either<Error, Set<QuoteStatus>>> { setOf(it).right() }
.distinctUntilChanged()
@ -361,8 +361,8 @@ class CachedCurrenciesStatusesOperations(
rawCurrencyIds.onEach {
launch {
singleQuoteSupplier(
params = SingleQuoteProducer.Params(rawCurrencyId = it),
singleQuoteStatusSupplier(
params = SingleQuoteStatusProducer.Params(rawCurrencyId = it),
)
.onEach { quote ->
state.update { loadedStatuses ->