Updated on 2026-08-14
This commit is contained in:
parent
f39054b5a9
commit
551e2a60bb
22 changed files with 985 additions and 37 deletions
|
|
@ -13,6 +13,7 @@ import com.tangem.domain.onramp.model.error.OnrampError
|
|||
import com.tangem.domain.onramp.repositories.OnrampErrorResolver
|
||||
import com.tangem.domain.onramp.repositories.OnrampRepository
|
||||
import com.tangem.domain.onramp.utils.calculateRateDif
|
||||
import com.tangem.domain.onramp.utils.compareOffersByRateSpeedAndPriority
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
|
@ -38,7 +39,7 @@ class GetOnrampAllOffersUseCase(
|
|||
if (validQuotes.isEmpty()) return emptyList()
|
||||
val isGooglePayAvailable = settingsRepository.isGooglePayAvailability()
|
||||
|
||||
val overallBestRateQuote = validQuotes.maxByOrNull { it.toAmount.value }
|
||||
val overallBestRateQuote = validQuotes.maxWithOrNull(compareOffersByRateSpeedAndPriority(isGooglePayAvailable))
|
||||
val bestRate = overallBestRateQuote?.toAmount?.value
|
||||
|
||||
val offersByPaymentMethod = validQuotes.groupBy { it.paymentMethod }
|
||||
|
|
@ -54,7 +55,8 @@ class GetOnrampAllOffersUseCase(
|
|||
OnrampOffer(quote = quote, rateDif = rateDif, advantages = advantages)
|
||||
}
|
||||
|
||||
val groupBestRateOfferData = methodQuotes.maxByOrNull { it.toAmount.value }
|
||||
val groupBestRateOfferData =
|
||||
methodQuotes.maxWithOrNull(compareOffersByRateSpeedAndPriority(isGooglePayAvailable))
|
||||
val groupBestRateOffer = methodOffers.find {
|
||||
when (val quote = it.quote) {
|
||||
is OnrampQuote.Data -> quote == groupBestRateOfferData
|
||||
|
|
|
|||
|
|
@ -12,15 +12,17 @@ import com.tangem.domain.onramp.repositories.OnrampErrorResolver
|
|||
import com.tangem.domain.onramp.repositories.OnrampRepository
|
||||
import com.tangem.domain.onramp.repositories.OnrampTransactionRepository
|
||||
import com.tangem.domain.onramp.utils.calculateRateDif
|
||||
import com.tangem.domain.onramp.utils.compareOffersByRateSpeedAndPriority
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.map
|
||||
import java.math.BigDecimal
|
||||
|
||||
class GetOnrampOffersUseCase(
|
||||
private val onrampRepository: OnrampRepository,
|
||||
private val onrampTransactionRepository: OnrampTransactionRepository,
|
||||
private val errorResolver: OnrampErrorResolver,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
) {
|
||||
|
||||
operator fun invoke(
|
||||
|
|
@ -37,14 +39,15 @@ class GetOnrampOffersUseCase(
|
|||
.catch { throwable -> errorResolver.resolve(throwable).left() }
|
||||
}
|
||||
|
||||
private fun processOffers(
|
||||
private suspend fun processOffers(
|
||||
quotes: List<OnrampQuote>,
|
||||
transactions: List<OnrampTransaction>,
|
||||
): List<OnrampOffersBlock> {
|
||||
val validQuotes = quotes.filterIsInstance<OnrampQuote.Data>()
|
||||
if (validQuotes.isEmpty()) return emptyList()
|
||||
|
||||
val bestRateQuote = validQuotes.maxByOrNull { it.toAmount.value }
|
||||
val isGooglePayAvailable = settingsRepository.isGooglePayAvailability()
|
||||
val bestRateQuote = validQuotes.maxWithOrNull(compareOffersByRateSpeedAndPriority(isGooglePayAvailable))
|
||||
val bestRate = bestRateQuote?.toAmount?.value
|
||||
|
||||
val offers = validQuotes.map { quote ->
|
||||
|
|
@ -53,8 +56,8 @@ class GetOnrampOffersUseCase(
|
|||
}
|
||||
|
||||
val recentOffer = findRecentOffer(offers, transactions)
|
||||
val bestRateOffer = findBestRateOffer(offers)
|
||||
val fastestOffer = findFastestOffer(offers)
|
||||
val bestRateOffer = findBestRateOffer(offers, isGooglePayAvailable)
|
||||
val fastestOffer = findFastestOffer(offers, isGooglePayAvailable)
|
||||
|
||||
return buildOffersBlocks(
|
||||
recentOffer = recentOffer,
|
||||
|
|
@ -73,36 +76,35 @@ class GetOnrampOffersUseCase(
|
|||
}
|
||||
}
|
||||
|
||||
private fun findBestRateOffer(offers: List<OnrampOffer>): OnrampOffer? {
|
||||
return offers.maxByOrNull { offer ->
|
||||
when (val quote = offer.quote) {
|
||||
is OnrampQuote.Data -> quote.toAmount.value
|
||||
else -> BigDecimal.ZERO
|
||||
}
|
||||
}
|
||||
private fun findBestRateOffer(offers: List<OnrampOffer>, isGooglePayAvailable: Boolean): OnrampOffer? {
|
||||
return offers.maxWithOrNull(offerComparator(isGooglePayAvailable))
|
||||
}
|
||||
|
||||
private fun findFastestOffer(offers: List<OnrampOffer>): OnrampOffer? {
|
||||
private fun findFastestOffer(offers: List<OnrampOffer>, isGooglePayAvailable: Boolean): OnrampOffer? {
|
||||
val instantOffers = offers.filter { it.quote.paymentMethod.type.isInstant() }
|
||||
return if (instantOffers.isNotEmpty()) {
|
||||
instantOffers.maxByOrNull { offer ->
|
||||
when (val quote = offer.quote) {
|
||||
is OnrampQuote.Data -> quote.toAmount.value
|
||||
else -> BigDecimal.ZERO
|
||||
}
|
||||
}
|
||||
instantOffers.maxWithOrNull(offerComparator(isGooglePayAvailable))
|
||||
} else {
|
||||
val offersBySpeed = offers.groupBy { offer ->
|
||||
offer.quote.paymentMethod.type.getProcessingSpeed().speed
|
||||
}
|
||||
val fastestSpeed = offersBySpeed.keys.minOrNull() ?: return null
|
||||
val fastestOffers = offersBySpeed[fastestSpeed] ?: return null
|
||||
fastestOffers.maxByOrNull { offer ->
|
||||
when (val quote = offer.quote) {
|
||||
is OnrampQuote.Data -> quote.toAmount.value
|
||||
else -> BigDecimal.ZERO
|
||||
fastestOffers.maxWithOrNull(offerComparator(isGooglePayAvailable))
|
||||
}
|
||||
}
|
||||
|
||||
private fun offerComparator(isGooglePayAvailable: Boolean): Comparator<OnrampOffer> = Comparator { offer1, offer2 ->
|
||||
when (val quote1 = offer1.quote) {
|
||||
is OnrampQuote.Data -> {
|
||||
when (val quote2 = offer2.quote) {
|
||||
is OnrampQuote.Data -> {
|
||||
compareOffersByRateSpeedAndPriority(isGooglePayAvailable).compare(quote1, quote2)
|
||||
}
|
||||
else -> 1
|
||||
}
|
||||
}
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,34 @@
|
|||
package com.tangem.domain.onramp.utils
|
||||
|
||||
import com.tangem.domain.onramp.model.OnrampQuote
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal fun calculateRateDif(currentTokenRate: BigDecimal, bestRate: BigDecimal?): BigDecimal? {
|
||||
if (bestRate == null) return null
|
||||
return BigDecimal.ONE - currentTokenRate / bestRate
|
||||
}
|
||||
|
||||
internal fun compareOffersByRateSpeedAndPriority(isGooglePayAvailable: Boolean): Comparator<OnrampQuote.Data> {
|
||||
return Comparator { quote1, quote2 ->
|
||||
val rateComparison = quote1
|
||||
.toAmount
|
||||
.value
|
||||
.compareTo(quote2.toAmount.value)
|
||||
if (rateComparison != 0) return@Comparator rateComparison
|
||||
|
||||
val speedComparison =
|
||||
quote2
|
||||
.paymentMethod
|
||||
.type
|
||||
.getProcessingSpeed()
|
||||
.speed
|
||||
.compareTo(quote1.paymentMethod.type.getProcessingSpeed().speed)
|
||||
if (speedComparison != 0) return@Comparator speedComparison
|
||||
|
||||
quote1
|
||||
.paymentMethod
|
||||
.type
|
||||
.getPriority(isGooglePayAvailable)
|
||||
.compareTo(quote2.paymentMethod.type.getPriority(isGooglePayAvailable))
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import com.tangem.domain.onramp.model.cache.OnrampTransaction
|
|||
import com.tangem.domain.onramp.repositories.OnrampErrorResolver
|
||||
import com.tangem.domain.onramp.repositories.OnrampRepository
|
||||
import com.tangem.domain.onramp.repositories.OnrampTransactionRepository
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import io.mockk.*
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
|
|
@ -22,6 +23,7 @@ class GetOnrampOffersUseCaseTest {
|
|||
private val onrampRepository: OnrampRepository = mockk(relaxUnitFun = true)
|
||||
private val onrampTransactionRepository: OnrampTransactionRepository = mockk(relaxUnitFun = true)
|
||||
private val errorResolver: OnrampErrorResolver = mockk(relaxUnitFun = true)
|
||||
private val settingsRepository: SettingsRepository = mockk(relaxUnitFun = true)
|
||||
private val cryptoCurrencyId: CryptoCurrency.ID = mockk(relaxUnitFun = true)
|
||||
private val userWalletId: UserWalletId = mockk(relaxUnitFun = true)
|
||||
|
||||
|
|
@ -34,6 +36,7 @@ class GetOnrampOffersUseCaseTest {
|
|||
onrampRepository = onrampRepository,
|
||||
onrampTransactionRepository = onrampTransactionRepository,
|
||||
errorResolver = errorResolver,
|
||||
settingsRepository = settingsRepository,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -42,6 +45,7 @@ class GetOnrampOffersUseCaseTest {
|
|||
val emptyQuotes = listOf<OnrampQuote>()
|
||||
val emptyTransactions = listOf<OnrampTransaction>()
|
||||
|
||||
coEvery { settingsRepository.isGooglePayAvailability() } returns false
|
||||
coEvery { onrampRepository.getQuotes() } returns flowOf(emptyQuotes)
|
||||
coEvery { onrampTransactionRepository.getTransactions(userWalletId, cryptoCurrencyId) } returns flowOf(
|
||||
emptyTransactions,
|
||||
|
|
@ -77,6 +81,7 @@ class GetOnrampOffersUseCaseTest {
|
|||
createMockTransaction("provider1", "card", 1000L),
|
||||
)
|
||||
|
||||
coEvery { settingsRepository.isGooglePayAvailability() } returns false
|
||||
coEvery { onrampRepository.getQuotes() } returns flowOf(quotes)
|
||||
coEvery { onrampTransactionRepository.getTransactions(userWalletId, cryptoCurrencyId) } returns flowOf(
|
||||
transactions,
|
||||
|
|
@ -121,6 +126,7 @@ class GetOnrampOffersUseCaseTest {
|
|||
|
||||
val transactions = emptyList<OnrampTransaction>()
|
||||
|
||||
coEvery { settingsRepository.isGooglePayAvailability() } returns false
|
||||
coEvery { onrampRepository.getQuotes() } returns flowOf(quotes)
|
||||
coEvery { onrampTransactionRepository.getTransactions(userWalletId, cryptoCurrencyId) } returns flowOf(
|
||||
transactions,
|
||||
|
|
@ -165,6 +171,7 @@ class GetOnrampOffersUseCaseTest {
|
|||
|
||||
val transactions = emptyList<OnrampTransaction>()
|
||||
|
||||
coEvery { settingsRepository.isGooglePayAvailability() } returns false
|
||||
coEvery { onrampRepository.getQuotes() } returns flowOf(quotes)
|
||||
coEvery { onrampTransactionRepository.getTransactions(userWalletId, cryptoCurrencyId) } returns flowOf(
|
||||
transactions,
|
||||
|
|
@ -218,6 +225,7 @@ class GetOnrampOffersUseCaseTest {
|
|||
|
||||
val transactions = emptyList<OnrampTransaction>()
|
||||
|
||||
coEvery { settingsRepository.isGooglePayAvailability() } returns false
|
||||
coEvery { onrampRepository.getQuotes() } returns flowOf(quotes)
|
||||
coEvery { onrampTransactionRepository.getTransactions(userWalletId, cryptoCurrencyId) } returns flowOf(
|
||||
transactions,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue