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

@ -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(),
)