Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-19 12:38:07 +02:00
parent c49b3a9176
commit 8467ada25d
16 changed files with 156 additions and 50 deletions

View file

@ -7,6 +7,7 @@ import com.tangem.core.ui.components.icons.IconTint
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.components.marketprice.utils.PriceChangeConverter
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList
@ -16,15 +17,14 @@ import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.format.bigdecimal.percent
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.StatusSource
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.currency.yieldSupplyKey
import com.tangem.domain.models.currency.yieldSupplyNotAllAmountSupplied
import com.tangem.domain.models.staking.YieldBalance
import com.tangem.domain.staking.utils.getTotalWithRewardsStakingBalance
import com.tangem.utils.StringsSigns.DASH_SIGN
import com.tangem.utils.converter.Converter
import com.tangem.utils.extensions.isZero
import com.tangem.utils.extensions.orZero
import kotlinx.collections.immutable.toImmutableList
import java.math.BigDecimal
@ -40,12 +40,13 @@ import java.math.BigDecimal
*/
class TokenItemStateConverter(
private val appCurrency: AppCurrency,
private val apyMap: Map<String, String> = emptyMap(),
private val yieldModuleApyMap: Map<String, String> = emptyMap(),
private val stakingApyMap: Map<String, BigDecimal> = emptyMap(),
private val iconStateProvider: (CryptoCurrencyStatus) -> CurrencyIconState = {
CryptoCurrencyToIconStateConverter().convert(it)
},
private val titleStateProvider: (CryptoCurrencyStatus) -> TokenItemState.TitleState = {
createTitleState(it, apyMap)
createTitleState(it, yieldModuleApyMap, stakingApyMap)
},
private val subtitleStateProvider: (CryptoCurrencyStatus) -> TokenItemState.SubtitleState? = {
createSubtitleState(it, appCurrency)
@ -154,7 +155,8 @@ class TokenItemStateConverter(
private fun createTitleState(
currencyStatus: CryptoCurrencyStatus,
apyMap: Map<String, String>,
yieldModuleApyMap: Map<String, String>,
stakingApyMap: Map<String, BigDecimal>,
): TokenItemState.TitleState {
return when (val value = currencyStatus.value) {
is CryptoCurrencyStatus.Loading,
@ -169,13 +171,11 @@ class TokenItemStateConverter(
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.NoAccount,
-> {
val earnApyText = resolveEarnApy(currencyStatus, apyMap)?.let { apy ->
resourceReference(
R.string.yield_module_earn_badge,
wrappedList(apy),
)
}
val isActive = currencyStatus.value.yieldSupplyStatus?.isActive ?: false
val (earnApyText, isActive) = resolveEarnApy(
cryptoCurrencyStatus = currencyStatus,
yieldModuleApyMap = yieldModuleApyMap,
stakingApyMap = stakingApyMap,
)
TokenItemState.TitleState.Content(
text = stringReference(currencyStatus.currency.name),
hasPending = value.hasCurrentNetworkTransactions,
@ -186,12 +186,36 @@ class TokenItemStateConverter(
}
}
private fun resolveEarnApy(cryptoCurrencyStatus: CryptoCurrencyStatus, apyMap: Map<String, String>): String? {
if (apyMap.isEmpty()) return null
private fun resolveEarnApy(
cryptoCurrencyStatus: CryptoCurrencyStatus,
yieldModuleApyMap: Map<String, String>,
stakingApyMap: Map<String, BigDecimal>,
): Pair<TextReference?, Boolean> {
val token = cryptoCurrencyStatus.currency as? CryptoCurrency.Token
if (token != null && yieldModuleApyMap.isNotEmpty()) {
val yieldSupplyApy = yieldModuleApyMap[token.yieldSupplyKey()]
if (yieldSupplyApy != null) {
val isActive = cryptoCurrencyStatus.value.yieldSupplyStatus?.isActive ?: false
return resourceReference(
R.string.yield_module_earn_badge,
wrappedList(yieldSupplyApy),
) to isActive
}
}
val token = cryptoCurrencyStatus.currency as? CryptoCurrency.Token ?: return null
if (stakingApyMap.isNotEmpty()) {
val stakingKey = cryptoCurrencyStatus.currency.stakingKey()
val stakingApy = stakingApyMap[stakingKey]?.format { percent(withPercentSign = false) }
if (stakingApy != null) {
val hasStakedBalance = cryptoCurrencyStatus.value.yieldBalance is YieldBalance.Data
return resourceReference(
R.string.yield_module_earn_badge,
wrappedList(stakingApy),
) to hasStakedBalance
}
}
return apyMap[token.yieldSupplyKey()]
return null to false
}
private fun createSubtitleState(
@ -255,14 +279,6 @@ class TokenItemStateConverter(
tint = IconTint.Warning,
).let(::add)
}
if (!status.getStakedBalance().isZero()) {
add(
TokenItemState.FiatAmountState.Content.IconUM(
iconRes = R.drawable.ic_staking_24,
tint = IconTint.Accent,
),
)
}
if (status.value.sources.total == StatusSource.ONLY_CACHE) {
add(
TokenItemState.FiatAmountState.Content.IconUM(
@ -308,5 +324,9 @@ class TokenItemStateConverter(
}
fun CryptoCurrencyStatus.Value.isFlickering(): Boolean = sources.total == StatusSource.CACHE
private fun CryptoCurrency.stakingKey(): String {
return "${network.backendId}_$symbol"
}
}
}