Updated on 2026-08-14

This commit is contained in:
Tangem 2023-12-15 17:39:46 +03:00
parent 97afda563f
commit 424dd37a23
3 changed files with 105 additions and 53 deletions

View file

@ -1,6 +1,5 @@
package com.tangem.domain.tokens
import arrow.core.Either
import com.tangem.domain.settings.ShouldShowSwapPromoTokenUseCase
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
@ -54,18 +53,16 @@ class GetCurrencyWarningsUseCase(
derivationPath = derivationPath,
isSingleWalletWithTokens = isSingleWalletWithTokens,
),
operations.getCurrenciesStatusesFlow().conflate(),
flowOf(walletManagersFacade.getRentInfo(userWalletId, currency.network)),
flowOf(walletManagersFacade.getExistentialDeposit(userWalletId, currency.network)),
showSwapPromoTokenUseCase(userWalletId.stringValue, currency.id.value).conflate(),
) { coinRelatedWarnings, cryptoStatuses, maybeRentWarning, maybeEdWarning, shouldShowSwapPromo ->
getSwapPromoNotificationWarning(
operations = operations,
userWalletId = userWalletId,
currencyStatus = currencyStatus,
).conflate(),
) { coinRelatedWarnings, maybeRentWarning, maybeEdWarning, maybeSwapPromo ->
setOfNotNull(
getSwapPromoNotificationWarning(
shouldShowSwapPromo = shouldShowSwapPromo,
userWalletId = userWalletId,
currencyStatus = currencyStatus,
cryptoStatuses = cryptoStatuses,
),
maybeSwapPromo,
maybeRentWarning,
maybeEdWarning?.let {
CryptoCurrencyWarning.ExistentialDeposit(
@ -81,54 +78,59 @@ class GetCurrencyWarningsUseCase(
}
private suspend fun getSwapPromoNotificationWarning(
shouldShowSwapPromo: Boolean,
operations: CurrenciesStatusesOperations,
userWalletId: UserWalletId,
currencyStatus: CryptoCurrencyStatus,
cryptoStatuses: Either<CurrenciesStatusesOperations.Error, List<CryptoCurrencyStatus>>,
): CryptoCurrencyWarning? {
): Flow<CryptoCurrencyWarning?> {
val currency = currencyStatus.currency
return if (shouldShowSwapPromo && marketCryptoCurrencyRepository.isExchangeable(userWalletId, currency)) {
cryptoStatuses.fold(
ifLeft = { null },
ifRight = { cryptoCurrencyStatuses ->
val pairs = runCatching(dispatchers.io) {
swapRepository.getPairs(
LeastTokenInfo(
contractAddress = (currency as? CryptoCurrency.Token)?.contractAddress ?: "0",
network = currency.network.backendId,
),
cryptoCurrencyStatuses.map { it.currency },
)
}.getOrNull()?.pairs ?: emptyList()
val cryptoStatuses = operations.getCurrenciesStatusesSync()
return combine(
showSwapPromoTokenUseCase(userWalletId.stringValue, currency.id.value).conflate(),
flowOf(marketCryptoCurrencyRepository.isExchangeable(userWalletId, currency)).conflate(),
) { shouldShowSwapPromo, isExchangeable ->
if (shouldShowSwapPromo && isExchangeable) {
cryptoStatuses.fold(
ifLeft = { null },
ifRight = { cryptoCurrencyStatuses ->
val pairs = runCatching(dispatchers.io) {
swapRepository.getPairsOnly(
LeastTokenInfo(
contractAddress = (currency as? CryptoCurrency.Token)?.contractAddress ?: "0",
network = currency.network.backendId,
),
cryptoCurrencyStatuses.map { it.currency },
)
}.getOrNull()?.pairs ?: emptyList()
val filteredCurrencies = cryptoCurrencyStatuses.filterNot {
it.currency.id == currency.id
}
val currencyPairs = pairs.filter {
it.from.network == currency.network.backendId ||
it.to.network == currency.network.backendId
}
val isExchangeable = currencyPairs.any { pair ->
val availablePair = if (currencyStatus.value.amount.isNullOrZero()) {
filteredCurrencies.filterNot { it.value.amount.isNullOrZero() }
} else {
filteredCurrencies
val filteredCurrencies = cryptoCurrencyStatuses.filterNot {
it.currency.id == currency.id
}
availablePair
.any {
it.currency.network.backendId == pair.to.network ||
it.currency.network.backendId == pair.from.network
val currencyPairs = pairs.filter {
it.from.network == currency.network.backendId ||
it.to.network == currency.network.backendId
}
val showPromo = currencyPairs.any { pair ->
val availablePair = if (currencyStatus.value.amount.isNullOrZero()) {
filteredCurrencies.filterNot { it.value.amount.isNullOrZero() }
} else {
filteredCurrencies
}
}
if (isExchangeable) {
CryptoCurrencyWarning.SwapPromo
} else {
null
}
},
)
} else {
null
availablePair
.any {
it.currency.network.backendId == pair.to.network ||
it.currency.network.backendId == pair.from.network
}
}
if (showPromo) {
CryptoCurrencyWarning.SwapPromo
} else {
null
}
},
)
} else {
null
}
}
}

View file

@ -41,7 +41,7 @@ import java.math.BigDecimal
import javax.inject.Inject
import com.tangem.datasource.api.express.models.request.LeastTokenInfo as NetworkLeastTokenInfo
@Suppress("LongParameterList")
@Suppress("LongParameterList", "LargeClass")
internal class SwapRepositoryImpl @Inject constructor(
private val tangemTechApi: TangemTechApi,
private val tangemExpressApi: TangemExpressApi,
@ -109,6 +109,53 @@ internal class SwapRepositoryImpl @Inject constructor(
}
}
override suspend fun getPairsOnly(
initialCurrency: LeastTokenInfo,
currencyList: List<CryptoCurrency>,
): PairsWithProviders {
return withContext(coroutineDispatcher.io) {
try {
val initial = NetworkLeastTokenInfo(
contractAddress = initialCurrency.contractAddress,
network = initialCurrency.network,
)
val currenciesList = currencyList.map { leastTokenInfoConverter.convert(it) }
val pairsDeferred = async {
getPairsInternal(
from = arrayListOf(initial),
to = currenciesList,
)
}
val reversedPairsDeferred = async {
getPairsInternal(
from = currenciesList,
to = arrayListOf(initial),
)
}
val pairs = pairsDeferred.await().getOrThrow()
val reversedPairs = reversedPairsDeferred.await().getOrThrow()
val allPairs = pairs + reversedPairs
return@withContext swapPairInfoConverter.convert(
SwapPairsWithProviders(
swapPair = allPairs,
providers = emptyList(),
),
)
} catch (exception: Exception) {
if (exception is ApiResponseError.HttpException) {
throw ExpressException(errorsDataConverter.convert(exception.errorBody ?: ""))
} else {
throw exception
}
}
}
}
private suspend fun getPairsInternal(
from: List<NetworkLeastTokenInfo>,
to: List<NetworkLeastTokenInfo>,

View file

@ -11,6 +11,9 @@ interface SwapRepository {
suspend fun getPairs(initialCurrency: LeastTokenInfo, currencyList: List<CryptoCurrency>): PairsWithProviders
/** Express getPairs request variant without providers request */
suspend fun getPairsOnly(initialCurrency: LeastTokenInfo, currencyList: List<CryptoCurrency>): PairsWithProviders
suspend fun getRates(currencyId: String, tokenIds: List<String>): Map<String, Double>
suspend fun getExchangeableTokens(networkId: String): List<Currency>