Updated on 2026-08-14
This commit is contained in:
parent
bfd371bc33
commit
c9e78f485d
10 changed files with 164 additions and 47 deletions
|
|
@ -8,7 +8,7 @@ import com.tangem.domain.networks.repository.NetworksRepository
|
|||
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.QuotesRepositoryV2
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteFetcher
|
||||
import com.tangem.domain.quotes.single.SingleQuoteSupplier
|
||||
import com.tangem.domain.staking.multi.MultiYieldBalanceFetcher
|
||||
|
|
@ -368,7 +368,7 @@ internal object TokensDomainModule {
|
|||
fun provideBaseCurrenciesStatusesOperations(
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepositoryV2: QuotesRepositoryV2,
|
||||
quotesRepository: QuotesRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
|
|
@ -380,7 +380,7 @@ internal object TokensDomainModule {
|
|||
): BaseCurrenciesStatusesOperations {
|
||||
return CachedCurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepositoryV2 = quotesRepositoryV2,
|
||||
quotesRepository = quotesRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
|
|
@ -398,7 +398,7 @@ internal object TokensDomainModule {
|
|||
fun provideBaseCurrencyStatusOperations(
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepositoryV2: QuotesRepositoryV2,
|
||||
quotesRepository: QuotesRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
|
|
@ -410,7 +410,7 @@ internal object TokensDomainModule {
|
|||
): BaseCurrencyStatusOperations {
|
||||
return CachedCurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepositoryV2 = quotesRepositoryV2,
|
||||
quotesRepository = quotesRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
package com.tangem.data.quotes
|
||||
|
||||
import com.tangem.data.quotes.store.QuotesStatusesStore
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.quotes.QuotesRepositoryV2
|
||||
import com.tangem.domain.tokens.model.QuoteStatus
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Default implementation of [QuotesRepositoryV2]
|
||||
*
|
||||
* @property quotesStore quotes store
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultQuotesRepositoryV2 @Inject constructor(
|
||||
private val quotesStore: QuotesStatusesStore,
|
||||
) : QuotesRepositoryV2 {
|
||||
|
||||
override suspend fun getMultiQuoteSyncOrNull(currenciesIds: Set<CryptoCurrency.RawID>): Set<QuoteStatus>? {
|
||||
return quotesStore.getAllSyncOrNull()?.mapTo(hashSetOf()) {
|
||||
it.takeIf { it.rawCurrencyId in currenciesIds }
|
||||
?: QuoteStatus(rawCurrencyId = it.rawCurrencyId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||
import androidx.datastore.core.DataStoreFactory
|
||||
import androidx.datastore.dataStoreFile
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.data.quotes.DefaultQuotesRepositoryV2
|
||||
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
|
||||
|
|
@ -12,7 +12,7 @@ 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.QuotesRepositoryV2
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -51,5 +51,5 @@ internal object QuotesDataModule {
|
|||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun providesQuotesRepositoryV2(impl: DefaultQuotesRepositoryV2): QuotesRepositoryV2 = impl
|
||||
fun providesQuotesRepository(impl: DefaultQuotesRepository): QuotesRepository = impl
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.data.quotes.repository
|
||||
|
||||
import com.tangem.data.quotes.store.QuotesStatusesStore
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.model.QuoteStatus
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Default implementation of [QuotesRepository]
|
||||
*
|
||||
* @property quotesStatusesStore quotes statuses store
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultQuotesRepository @Inject constructor(
|
||||
private val quotesStatusesStore: QuotesStatusesStore,
|
||||
) : QuotesRepository {
|
||||
|
||||
override suspend fun getMultiQuoteSyncOrNull(currenciesIds: Set<CryptoCurrency.RawID>): Set<QuoteStatus> {
|
||||
if (currenciesIds.isEmpty()) {
|
||||
Timber.e("currenciesIds are empty")
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
val storedQuotes = quotesStatusesStore.getAllSyncOrNull()
|
||||
?.filter { it.rawCurrencyId in currenciesIds }
|
||||
|
||||
return currenciesIds.mapTo(hashSetOf()) { currencyId ->
|
||||
storedQuotes?.firstOrNull { it.rawCurrencyId == currencyId }
|
||||
?: QuoteStatus(rawCurrencyId = currencyId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
package com.tangem.data.quotes.repository
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.test.utils.ProvideTestModels
|
||||
import com.tangem.data.quotes.store.QuotesStatusesStore
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.model.QuoteStatus
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class DefaultQuotesRepositoryTest {
|
||||
|
||||
private val quotesStatusesStore = mockk<QuotesStatusesStore>()
|
||||
private val repository: QuotesRepository = DefaultQuotesRepository(quotesStatusesStore = quotesStatusesStore)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(quotesStatusesStore)
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetMultiQuoteSyncOrNull {
|
||||
|
||||
private val btcRawId = CryptoCurrency.RawID(value = "BTC")
|
||||
private val ethRawId = CryptoCurrency.RawID(value = "ETH")
|
||||
|
||||
private val ethQuote = QuoteStatus(
|
||||
rawCurrencyId = ethRawId,
|
||||
value = QuoteStatus.Data(
|
||||
source = StatusSource.ACTUAL,
|
||||
fiatRate = BigDecimal.ZERO,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
),
|
||||
)
|
||||
|
||||
@ParameterizedTest
|
||||
@ProvideTestModels
|
||||
fun getMultiQuoteSyncOrNull(model: GetMultiQuoteSyncOrNullModel) = runTest {
|
||||
// Arrange
|
||||
coEvery { quotesStatusesStore.getAllSyncOrNull() } returns model.initialStore
|
||||
|
||||
// Act
|
||||
val actual = repository.getMultiQuoteSyncOrNull(currenciesIds = model.currencyIds)
|
||||
|
||||
// Assert
|
||||
val expected = model.expected
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
private fun provideTestModels() = listOf(
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = null,
|
||||
currencyIds = emptySet(),
|
||||
expected = emptySet(),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = null,
|
||||
currencyIds = setOf(ethRawId),
|
||||
expected = setOf(QuoteStatus(rawCurrencyId = ethRawId)),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = emptySet(),
|
||||
currencyIds = emptySet(),
|
||||
expected = emptySet(),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = emptySet(),
|
||||
currencyIds = setOf(ethRawId),
|
||||
expected = setOf(QuoteStatus(rawCurrencyId = ethRawId)),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = setOf(ethQuote),
|
||||
currencyIds = setOf(ethRawId),
|
||||
expected = setOf(ethQuote),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = setOf(QuoteStatus(rawCurrencyId = btcRawId)),
|
||||
currencyIds = setOf(ethRawId),
|
||||
expected = setOf(QuoteStatus(rawCurrencyId = ethRawId)),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = setOf(ethQuote, QuoteStatus(rawCurrencyId = btcRawId)),
|
||||
currencyIds = setOf(ethRawId),
|
||||
expected = setOf(ethQuote),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
data class GetMultiQuoteSyncOrNullModel(
|
||||
val initialStore: Set<QuoteStatus>?,
|
||||
val currencyIds: Set<CryptoCurrency.RawID>,
|
||||
val expected: Set<QuoteStatus>?,
|
||||
)
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import com.tangem.domain.tokens.model.QuoteStatus
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface QuotesRepositoryV2 {
|
||||
interface QuotesRepository {
|
||||
|
||||
/** Get quotes by [currenciesIds] synchronously or null */
|
||||
suspend fun getMultiQuoteSyncOrNull(currenciesIds: Set<CryptoCurrency.RawID>): Set<QuoteStatus>?
|
||||
|
|
@ -13,7 +13,7 @@ import com.tangem.domain.networks.multi.MultiNetworkStatusProducer
|
|||
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.QuotesRepositoryV2
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.quotes.single.SingleQuoteProducer
|
||||
import com.tangem.domain.quotes.single.SingleQuoteSupplier
|
||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||
|
|
@ -41,7 +41,7 @@ import kotlinx.coroutines.flow.*
|
|||
@Suppress("LargeClass", "LongParameterList")
|
||||
abstract class BaseCurrencyStatusOperations(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val quotesRepositoryV2: QuotesRepositoryV2,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
|
|
@ -257,7 +257,7 @@ abstract class BaseCurrencyStatusOperations(
|
|||
val (_, currenciesIds) = getIds(nonEmptyCurrencies)
|
||||
val rawIds = currenciesIds.mapNotNull { it.rawCurrencyId }.toSet()
|
||||
|
||||
val quotes = quotesRepositoryV2.getMultiQuoteSyncOrNull(currenciesIds = rawIds)?.right()
|
||||
val quotes = quotesRepository.getMultiQuoteSyncOrNull(currenciesIds = rawIds)?.right()
|
||||
|
||||
val networkStatuses = multiNetworkStatusSupplier(
|
||||
params = MultiNetworkStatusProducer.Params(userWalletId = userWalletId),
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
|
|||
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.QuotesRepositoryV2
|
||||
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
|
||||
|
|
@ -43,7 +43,7 @@ import kotlinx.coroutines.flow.*
|
|||
@Suppress("LongParameterList", "LargeClass")
|
||||
class CachedCurrenciesStatusesOperations(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
quotesRepositoryV2: QuotesRepositoryV2,
|
||||
quotesRepository: QuotesRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
|
|
@ -56,7 +56,7 @@ class CachedCurrenciesStatusesOperations(
|
|||
) : BaseCurrenciesStatusesOperations,
|
||||
BaseCurrencyStatusOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepositoryV2 = quotesRepositoryV2,
|
||||
quotesRepository = quotesRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
|||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.quotes.QuotesRepositoryV2
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.GetCurrencyCheckUseCase
|
||||
import com.tangem.domain.tokens.GetMultiCryptoCurrencyStatusUseCase
|
||||
|
|
@ -65,7 +65,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
private val createTransactionExtrasUseCase: CreateTransactionDataExtrasUseCase,
|
||||
private val createApprovalTransactionUseCase: CreateApprovalTransactionUseCase,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val quotesRepositoryV2: QuotesRepositoryV2,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val swapTransactionRepository: SwapTransactionRepository,
|
||||
private val currencyChecksRepository: CurrencyChecksRepository,
|
||||
private val appCurrencyRepository: AppCurrencyRepository,
|
||||
|
|
@ -1809,7 +1809,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private suspend fun Set<CryptoCurrency.RawID>.getQuotesOrEmpty(): Set<QuoteStatus> {
|
||||
return runCatching { quotesRepositoryV2.getMultiQuoteSyncOrNull(currenciesIds = this) }
|
||||
return runCatching { quotesRepository.getMultiQuoteSyncOrNull(currenciesIds = this) }
|
||||
.getOrNull()
|
||||
.orEmpty()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.datasource.local.swaptx.ExpressAnalyticsStatus
|
|||
import com.tangem.datasource.local.swaptx.SwapTransactionStatusStore
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.quotes.QuotesRepositoryV2
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.model.QuoteStatus
|
||||
import com.tangem.domain.tokens.model.analytics.TokenExchangeAnalyticsEvent
|
||||
|
|
@ -32,7 +32,7 @@ import kotlinx.coroutines.flow.map
|
|||
internal class ExchangeStatusFactory @AssistedInject constructor(
|
||||
private val swapTransactionRepository: SwapTransactionRepository,
|
||||
private val swapRepository: SwapRepository,
|
||||
private val quotesRepositoryV2: QuotesRepositoryV2,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val swapTransactionStatusStore: SwapTransactionStatusStore,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
|
|
@ -190,7 +190,7 @@ internal class ExchangeStatusFactory @AssistedInject constructor(
|
|||
private suspend fun Set<CryptoCurrency.ID>.getQuotesOrEmpty(): Set<QuoteStatus> {
|
||||
val rawIds = mapNotNull { it.rawCurrencyId }.toSet()
|
||||
|
||||
return runCatching { quotesRepositoryV2.getMultiQuoteSyncOrNull(currenciesIds = rawIds) }
|
||||
return runCatching { quotesRepository.getMultiQuoteSyncOrNull(currenciesIds = rawIds) }
|
||||
.getOrNull()
|
||||
.orEmpty()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue