From a61cb657893396c1e5cc4d081d95dc381826fd3f Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 6 Mar 2025 21:32:04 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../ui/tokens/TokenItemStateConverter.kt | 12 ++----- .../com/tangem/domain/models/StatusSource.kt | 4 +++ .../tokens/model/CryptoCurrencyStatus.kt | 31 ++++++++++------ .../tokens/GetCryptoCurrencyActionsUseCase.kt | 24 +++++++++++-- .../tokens/GetCurrencyWarningsUseCase.kt | 4 ++- .../operations/CurrencyStatusOperations.kt | 36 ++++++++++--------- .../TokenListFiatBalanceOperations.kt | 6 ++-- ...PrimaryCurrencyStatusUpdatesUseCaseTest.kt | 1 + .../domain/tokens/mock/MockTokensStates.kt | 13 +++---- .../TokenDetailsLoadedBalanceConverter.kt | 14 +++----- .../domain/GetSingleWalletWarningsFactory.kt | 2 +- .../SingleWalletCardStateConverter.kt | 2 +- gradle/tangem_dependencies.toml | 2 +- 13 files changed, 89 insertions(+), 62 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt b/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt index d209e29338..c08a010371 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/tokens/TokenItemStateConverter.kt @@ -231,7 +231,7 @@ class TokenItemStateConverter( useAccentColor = true, ).let(::add) } - if (status.value.getStatusSource() == StatusSource.ONLY_CACHE) { + if (status.value.sources.total == StatusSource.ONLY_CACHE) { TokenItemState.FiatAmountState.Content.IconUM( iconRes = R.drawable.ic_error_sync_24, useAccentColor = false, @@ -274,14 +274,6 @@ class TokenItemStateConverter( return PriceChangeConverter.fromBigDecimal(value = this) } - fun CryptoCurrencyStatus.Value.isFlickering(): Boolean = getStatusSource() == StatusSource.CACHE - - private fun CryptoCurrencyStatus.Value.getStatusSource(): StatusSource? { - return when (this) { - is CryptoCurrencyStatus.Loaded -> source - is CryptoCurrencyStatus.NoAccount -> source - else -> null - } - } + fun CryptoCurrencyStatus.Value.isFlickering(): Boolean = sources.total == StatusSource.CACHE } } \ No newline at end of file diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/StatusSource.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/StatusSource.kt index c316840ea4..73edfce845 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/StatusSource.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/StatusSource.kt @@ -21,6 +21,10 @@ enum class StatusSource { /** Status is loaded from the cache and can't be updated with actual value */ ONLY_CACHE, + + ; + + fun isActual() = this == ACTUAL } /** diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/CryptoCurrencyStatus.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/CryptoCurrencyStatus.kt index 4d32d97ab9..0b5947b065 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/CryptoCurrencyStatus.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/CryptoCurrencyStatus.kt @@ -1,6 +1,7 @@ package com.tangem.domain.tokens.model import com.tangem.domain.models.StatusSource +import com.tangem.domain.models.getResultStatusSource import com.tangem.domain.staking.model.stakekit.YieldBalance import com.tangem.domain.txhistory.models.TxHistoryItem import java.math.BigDecimal @@ -51,7 +52,19 @@ data class CryptoCurrencyStatus( /** Staking yield balance */ open val yieldBalance: YieldBalance? = null - open val source: StatusSource = StatusSource.ACTUAL + /** Sources */ + open val sources: Sources = Sources() + } + + data class Sources( + val networkSource: StatusSource = StatusSource.ACTUAL, + val quoteSource: StatusSource = StatusSource.ACTUAL, + val yieldBalanceSource: StatusSource = StatusSource.ACTUAL, + ) { + + val total: StatusSource by lazy { + listOf(networkSource, quoteSource, yieldBalanceSource).getResultStatusSource() + } } /** Represents the Loading state of a cryptocurrency, typically while fetching its details. */ @@ -86,7 +99,7 @@ data class CryptoCurrencyStatus( * Represents a state where there is no account associated with the cryptocurrency * * @property amountToCreateAccount base reserve amount for account creation - * @property source source of data + * @property sources sources of data */ data class NoAccount( val amountToCreateAccount: BigDecimal, @@ -94,7 +107,7 @@ data class CryptoCurrencyStatus( override val priceChange: BigDecimal?, override val fiatRate: BigDecimal?, override val networkAddress: NetworkAddress, - override val source: StatusSource, + override val sources: Sources, ) : Value(isError = false) { override val amount: BigDecimal = BigDecimal.ZERO @@ -110,7 +123,7 @@ data class CryptoCurrencyStatus( * @property hasCurrentNetworkTransactions Indicates if there are any transactions in progress related to the * cryptocurrency network. * @property pendingTransactions The current cryptocurrency transactions. - * @property source source of data + * @property sources sources of data */ data class Loaded( override val amount: BigDecimal, @@ -121,7 +134,7 @@ data class CryptoCurrencyStatus( override val hasCurrentNetworkTransactions: Boolean, override val pendingTransactions: Set, override val networkAddress: NetworkAddress, - override val source: StatusSource, + override val sources: Sources, ) : Value(isError = false) /** @@ -144,7 +157,7 @@ data class CryptoCurrencyStatus( override val hasCurrentNetworkTransactions: Boolean, override val pendingTransactions: Set, override val networkAddress: NetworkAddress, - override val source: StatusSource, + override val sources: Sources, ) : Value(isError = false) /** @@ -161,8 +174,6 @@ data class CryptoCurrencyStatus( override val hasCurrentNetworkTransactions: Boolean, override val pendingTransactions: Set, override val networkAddress: NetworkAddress, - ) : Value(isError = false) { - - override val source: StatusSource = StatusSource.CACHE - } + override val sources: Sources, + ) : Value(isError = false) } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt index cabe3d43f7..680c0148e3 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt @@ -122,7 +122,7 @@ class GetCryptoCurrencyActionsUseCase( return getActionsForUnreachableCurrency(userWallet, cryptoCurrencyStatus, requirements) } - if (cryptoCurrencyStatus.value.source != StatusSource.ACTUAL) { + if (cryptoCurrencyStatus.value.sources.total != StatusSource.ACTUAL) { return getActionsForOutdatedData(userWallet, cryptoCurrencyStatus, requirements) } @@ -289,9 +289,17 @@ class GetCryptoCurrencyActionsUseCase( } // swap + val isSwapAvailable = with(cryptoCurrencyStatus.value.sources) { + quoteSource.isActual() && networkSource.isActual() + } + activeList.add( TokenActionsState.ActionState.Swap( - unavailabilityReason = ScenarioUnavailabilityReason.UsedOutdatedData, + unavailabilityReason = if (isSwapAvailable) { + ScenarioUnavailabilityReason.None + } else { + ScenarioUnavailabilityReason.UsedOutdatedData + }, showBadge = false, ), ) @@ -313,7 +321,17 @@ class GetCryptoCurrencyActionsUseCase( activeList.add(TokenActionsState.ActionState.Stake(ScenarioUnavailabilityReason.UsedOutdatedData, null)) // send - activeList.add(TokenActionsState.ActionState.Send(ScenarioUnavailabilityReason.UsedOutdatedData)) + val isSendAvailable = cryptoCurrencyStatus.value.sources.networkSource.isActual() + + activeList.add( + TokenActionsState.ActionState.Send( + unavailabilityReason = if (isSendAvailable) { + ScenarioUnavailabilityReason.None + } else { + ScenarioUnavailabilityReason.UsedOutdatedData + }, + ), + ) // region sell activeList.add(TokenActionsState.ActionState.Sell(ScenarioUnavailabilityReason.UsedOutdatedData)) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt index 0368ba6b53..00526a46a7 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyWarningsUseCase.kt @@ -138,7 +138,9 @@ class GetCurrencyWarningsUseCase( } private fun getUsedOutdatedDataWarning(status: CryptoCurrencyStatus): CryptoCurrencyWarning? { - return CryptoCurrencyWarning.UsedOutdatedDataWarning.takeIf { status.value.source == StatusSource.ONLY_CACHE } + return CryptoCurrencyWarning.UsedOutdatedDataWarning.takeIf { + status.value.sources.total == StatusSource.ONLY_CACHE + } } private fun getIsBetaTokensWarning(currency: CryptoCurrency): CryptoCurrencyWarning? { diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt index 831989f95e..0c5abe54ba 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt @@ -1,7 +1,6 @@ package com.tangem.domain.tokens.operations import com.tangem.domain.models.StatusSource -import com.tangem.domain.models.getResultStatusSource import com.tangem.domain.staking.model.stakekit.YieldBalance import com.tangem.domain.tokens.model.* import java.math.BigDecimal @@ -56,14 +55,14 @@ internal class CurrencyStatusOperations( priceChange = quote?.priceChange, fiatRate = quote?.fiatRate, networkAddress = status.address, - source = listOf( - status.source, - (quote as? Quote.Value)?.source ?: StatusSource.ACTUAL, - ).getResultStatusSource(), + sources = CryptoCurrencyStatus.Sources( + networkSource = status.source, + quoteSource = (quote as? Quote.Value)?.source ?: StatusSource.ACTUAL, + ), ) } - @Suppress("CyclomaticComplexMethod") + @Suppress("CyclomaticComplexMethod", "LongMethod") private fun createStatus( networkStatusValue: NetworkStatus.Verified, yieldBalance: YieldBalance?, @@ -105,11 +104,11 @@ internal class CurrencyStatusOperations( pendingTransactions = currentTransactions, networkAddress = networkStatusValue.address, yieldBalance = currentYieldBalance, - source = listOfNotNull( - networkStatusValue.source, - currentYieldBalance?.source ?: StatusSource.ACTUAL, - (quote as? Quote.Value)?.source ?: StatusSource.ACTUAL, - ).getResultStatusSource(), + sources = CryptoCurrencyStatus.Sources( + networkSource = networkStatusValue.source, + quoteSource = (quote as? Quote.Value)?.source ?: StatusSource.ACTUAL, + yieldBalanceSource = currentYieldBalance?.source ?: StatusSource.ACTUAL, + ), ) quote is Quote.Empty || ignoreQuote -> CryptoCurrencyStatus.NoQuote( amount = amount, @@ -117,6 +116,11 @@ internal class CurrencyStatusOperations( pendingTransactions = currentTransactions, networkAddress = networkStatusValue.address, yieldBalance = currentYieldBalance, + sources = CryptoCurrencyStatus.Sources( + networkSource = networkStatusValue.source, + quoteSource = (quote as? Quote.Value)?.source ?: StatusSource.ACTUAL, + yieldBalanceSource = currentYieldBalance?.source ?: StatusSource.ACTUAL, + ), ) quote is Quote.Value -> CryptoCurrencyStatus.Loaded( amount = amount, @@ -127,11 +131,11 @@ internal class CurrencyStatusOperations( pendingTransactions = currentTransactions, networkAddress = networkStatusValue.address, yieldBalance = currentYieldBalance, - source = listOf( - networkStatusValue.source, - currentYieldBalance?.source ?: StatusSource.ACTUAL, - quote.source, - ).getResultStatusSource(), + sources = CryptoCurrencyStatus.Sources( + networkSource = networkStatusValue.source, + quoteSource = quote.source, + yieldBalanceSource = currentYieldBalance?.source ?: StatusSource.ACTUAL, + ), ) else -> CryptoCurrencyStatus.Loading } diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/TokenListFiatBalanceOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/TokenListFiatBalanceOperations.kt index e4d319c4ff..1fc7bfdf64 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/TokenListFiatBalanceOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/TokenListFiatBalanceOperations.kt @@ -55,7 +55,7 @@ internal class TokenListFiatBalanceOperations( } return (fiatBalance as? TotalFiatBalance.Loaded)?.copy( - source = currencies.map { it.value.source }.getResultStatusSource(), + source = currencies.map { it.value.sources.total }.getResultStatusSource(), ) ?: fiatBalance } @@ -67,7 +67,7 @@ internal class TokenListFiatBalanceOperations( ?: TotalFiatBalance.Loaded( amount = BigDecimal.ZERO, isAllAmountsSummarized = false, - source = (status as? CryptoCurrencyStatus.NoAccount)?.source ?: StatusSource.ACTUAL, + source = (status as? CryptoCurrencyStatus.NoAccount)?.sources?.total ?: StatusSource.ACTUAL, ) } @@ -85,7 +85,7 @@ internal class TokenListFiatBalanceOperations( ) ?: TotalFiatBalance.Loaded( amount = status.fiatAmount + fiatStakingBalance, isAllAmountsSummarized = true, - source = status.source, + source = status.sources.total, ) } } diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt index 011dcc2efb..c8879e30a3 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt @@ -124,6 +124,7 @@ internal class GetPrimaryCurrencyStatusUpdatesUseCaseTest { defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), ), yieldBalance = null, + sources = CryptoCurrencyStatus.Sources(), ), ) } diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockTokensStates.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockTokensStates.kt index c5e2c10c31..1d660b3156 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockTokensStates.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockTokensStates.kt @@ -1,7 +1,6 @@ package com.tangem.domain.tokens.mock import arrow.core.nonEmptyListOf -import com.tangem.domain.models.StatusSource import com.tangem.domain.tokens.model.* import java.math.BigDecimal @@ -75,7 +74,7 @@ internal object MockTokensStates { networkAddress = NetworkAddress.Single( defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), ), - source = StatusSource.ACTUAL, + sources = CryptoCurrencyStatus.Sources(), ), ) @@ -89,7 +88,7 @@ internal object MockTokensStates { networkAddress = NetworkAddress.Single( defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), ), - source = StatusSource.ACTUAL, + sources = CryptoCurrencyStatus.Sources(), ), ) @@ -103,7 +102,7 @@ internal object MockTokensStates { networkAddress = NetworkAddress.Single( defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), ), - source = StatusSource.ACTUAL, + sources = CryptoCurrencyStatus.Sources(), ), ) @@ -117,7 +116,7 @@ internal object MockTokensStates { networkAddress = NetworkAddress.Single( defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), ), - source = StatusSource.ACTUAL, + sources = CryptoCurrencyStatus.Sources(), ), ) @@ -152,6 +151,7 @@ internal object MockTokensStates { value = MockNetworks.verifiedNetworksStatuses.first { it.network == status.currency.network }.value as? NetworkStatus.Verified, ).address, yieldBalance = null, + sources = CryptoCurrencyStatus.Sources(), ) is Quote.Value -> CryptoCurrencyStatus.Loaded( amount = amount, @@ -162,7 +162,7 @@ internal object MockTokensStates { hasCurrentNetworkTransactions = false, networkAddress = requireNotNull(networkStatus.value as? NetworkStatus.Verified).address, yieldBalance = null, - source = StatusSource.ACTUAL, + sources = CryptoCurrencyStatus.Sources(), ) } status.copy(value = value) @@ -180,6 +180,7 @@ internal object MockTokensStates { .value as? NetworkStatus.Verified, ).address, yieldBalance = null, + sources = CryptoCurrencyStatus.Sources(), ), ) } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt index 131b0eb114..c5e9df5a98 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt @@ -12,7 +12,9 @@ import com.tangem.domain.models.StatusSource import com.tangem.domain.staking.model.stakekit.YieldBalance import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrencyStatus -import com.tangem.feature.tokendetails.presentation.tokendetails.state.* +import com.tangem.feature.tokendetails.presentation.tokendetails.state.BalanceType +import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsBalanceBlockState +import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsTxHistoryTransactionStateConverter import com.tangem.feature.tokendetails.presentation.tokendetails.state.utils.getBalance @@ -211,13 +213,5 @@ internal class TokenDetailsLoadedBalanceConverter( return totalAmount.format { crypto(status.currency) } } - private fun CryptoCurrencyStatus.Value.isFlickering(): Boolean = getStatusSource() == StatusSource.CACHE - - private fun CryptoCurrencyStatus.Value.getStatusSource(): StatusSource? { - return when (this) { - is CryptoCurrencyStatus.Loaded -> source - is CryptoCurrencyStatus.NoAccount -> source - else -> null - } - } + private fun CryptoCurrencyStatus.Value.isFlickering(): Boolean = sources.total == StatusSource.CACHE } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt index d36afb7f8d..4e1f2ca1f1 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt @@ -78,7 +78,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor( element = WalletNotification.UsedOutdatedData, condition = maybePrimaryCurrencyStatus.fold( ifLeft = { false }, - ifRight = { it.value.source == StatusSource.ONLY_CACHE }, + ifRight = { it.value.sources.total == StatusSource.ONLY_CACHE }, ), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletCardStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletCardStateConverter.kt index 6f850012d0..48aaa65b0e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletCardStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletCardStateConverter.kt @@ -68,7 +68,7 @@ internal class SingleWalletCardStateConverter( balance = formatFiatAmount(status = status, appCurrency = appCurrency), cardCount = selectedWallet.getCardsCount(), isZeroBalance = status.fiatAmount?.isZero(), - isBalanceFlickering = (status as? CryptoCurrencyStatus.Loaded)?.source == StatusSource.CACHE, + isBalanceFlickering = (status as? CryptoCurrencyStatus.Loaded)?.sources?.total == StatusSource.CACHE, ) } diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 86711746f2..9096044540 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -1,5 +1,5 @@ [versions] -tangemBlockchainSdk = "release-app_5.21-969" +tangemBlockchainSdk = "release-app_5.21-976" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.21-435" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^