Updated on 2026-08-14

This commit is contained in:
Tangem 2024-12-02 13:01:50 +03:00
commit 07e626e124
4 changed files with 44 additions and 24 deletions

View file

@ -217,4 +217,4 @@ DEPENDENCIES
fastlane-plugin-firebase_app_distribution
BUNDLED WITH
1.17.2
2.5.23

View file

@ -17,6 +17,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.isNullOrZero
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.withTimeoutOrNull
/**
* Use case to determine which TokenActions are available for a [CryptoCurrency]
@ -54,9 +55,13 @@ class GetCryptoCurrencyActionsUseCase(
val networkFlow = if (userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
operations.getNetworkCoinForSingleWalletWithTokenFlow(networkId)
} else if (!userWallet.isMultiCurrency) {
operations.getPrimaryCurrencyStatusFlow()
operations.getPrimaryCurrencyStatusFlow(includeQuotes = false)
} else {
operations.getNetworkCoinFlow(networkId, cryptoCurrencyStatus.currency.network.derivationPath)
operations.getNetworkCoinFlow(
networkId = networkId,
derivationPath = cryptoCurrencyStatus.currency.network.derivationPath,
includeQuotes = false,
)
}
val flow = networkFlow.mapLatest { maybeCoinStatus ->
@ -171,10 +176,10 @@ class GetCryptoCurrencyActionsUseCase(
// swap
if (userWallet.isMultiCurrency) {
if (
marketCryptoCurrencyRepository.isExchangeable(userWallet.walletId, cryptoCurrency) &&
cryptoCurrencyStatus.value !is CryptoCurrencyStatus.NoQuote
) {
val isExchangeable = withTimeoutOrNull(REQUEST_EXCHANGE_DATA_TIMEOUT) {
marketCryptoCurrencyRepository.isExchangeable(userWallet.walletId, cryptoCurrency)
} ?: false
if (isExchangeable && cryptoCurrencyStatus.value !is CryptoCurrencyStatus.NoQuote) {
activeList.add(TokenActionsState.ActionState.Swap(ScenarioUnavailabilityReason.None))
} else {
disabledList.add(
@ -312,4 +317,8 @@ class GetCryptoCurrencyActionsUseCase(
cryptoCurrency = cryptoCurrency,
) is StakingAvailability.Available
}
private companion object {
const val REQUEST_EXCHANGE_DATA_TIMEOUT = 1000L
}
}

View file

@ -143,13 +143,14 @@ internal class CurrenciesStatusesOperations(
suspend fun getNetworkCoinFlow(
networkId: Network.ID,
derivationPath: Network.DerivationPath,
includeQuotes: Boolean = true,
): Flow<Either<Error, CryptoCurrencyStatus>> {
val currency = recover(
block = { getNetworkCoin(networkId, derivationPath) },
recover = { return flowOf(it.left()) },
)
return getCurrencyStatusFlow(currency)
return getCurrencyStatusFlow(currency, includeQuotes)
}
suspend fun getNetworkCoinForSingleWalletWithTokenFlow(
@ -163,25 +164,34 @@ internal class CurrenciesStatusesOperations(
return getCurrencyStatusFlow(currency)
}
suspend fun getPrimaryCurrencyStatusFlow(): Flow<Either<Error, CryptoCurrencyStatus>> {
suspend fun getPrimaryCurrencyStatusFlow(includeQuotes: Boolean = true): Flow<Either<Error, CryptoCurrencyStatus>> {
val currency = recover(
block = { getPrimaryCurrency() },
recover = { return flowOf(it.left()) },
)
return getCurrencyStatusFlow(currency)
return getCurrencyStatusFlow(currency, includeQuotes)
}
fun getCurrencyStatusFlow(currency: CryptoCurrency): Flow<Either<Error, CryptoCurrencyStatus>> {
fun getCurrencyStatusFlow(
currency: CryptoCurrency,
includeQuotes: Boolean = true,
): Flow<Either<Error,
CryptoCurrencyStatus,>,> {
val (networks, currenciesIds) = getIds(nonEmptyListOf(currency))
val quoteFlow = getQuotes(currenciesIds)
.map { maybeQuotes ->
maybeQuotes.flatMap { quotes ->
quotes.singleOrNull { it.rawCurrencyId == currency.id.rawCurrencyId }?.right()
?: Error.EmptyQuotes.left()
val quoteFlow = if (includeQuotes) {
getQuotes(currenciesIds)
.map { maybeQuotes ->
maybeQuotes.flatMap { quotes ->
quotes.singleOrNull { it.rawCurrencyId == currency.id.rawCurrencyId }?.right()
?: Error.EmptyQuotes.left()
}
}
}
} else {
// don't use emptyFlow()
flow { emit(Error.EmptyQuotes.left()) }
}
val statusFlow = getNetworksStatuses(networks)
.map { maybeStatuses ->

View file

@ -85,14 +85,8 @@ internal class CurrencyStatusOperations(
} else {
null
}
// order is important for correct total balance calculation
return when {
quote is Quote.Empty || ignoreQuote -> CryptoCurrencyStatus.NoQuote(
amount = amount,
hasCurrentNetworkTransactions = hasCurrentNetworkTransactions,
pendingTransactions = currentTransactions,
networkAddress = status.address,
yieldBalance = currentYieldBalance,
)
currency is CryptoCurrency.Token && currency.isCustom -> CryptoCurrencyStatus.Custom(
amount = amount,
fiatAmount = calculateFiatAmountOrNull(amount, quote?.fiatRate),
@ -103,6 +97,13 @@ internal class CurrencyStatusOperations(
networkAddress = status.address,
yieldBalance = currentYieldBalance,
)
quote is Quote.Empty || ignoreQuote -> CryptoCurrencyStatus.NoQuote(
amount = amount,
hasCurrentNetworkTransactions = hasCurrentNetworkTransactions,
pendingTransactions = currentTransactions,
networkAddress = status.address,
yieldBalance = currentYieldBalance,
)
quote is Quote.Value -> CryptoCurrencyStatus.Loaded(
amount = amount,
fiatAmount = calculateFiatAmount(amount, quote.fiatRate),