Updated on 2026-08-14

This commit is contained in:
Tangem 2024-12-02 13:34:17 +04:00
parent eaa676e9f5
commit 4812e53ba2
2 changed files with 113 additions and 47 deletions

View file

@ -7,9 +7,9 @@ import com.tangem.core.ui.components.marketprice.utils.PriceChangeConverter
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.format.bigdecimal.percent
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.staking.model.stakekit.YieldBalance
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
@ -37,8 +37,11 @@ class TokenItemStateConverter(
private val subtitleStateProvider: (CryptoCurrencyStatus) -> TokenItemState.SubtitleState? = {
createSubtitleState(it, appCurrency)
},
private val subtitle2StateProvider: (CryptoCurrencyStatus) -> TokenItemState.Subtitle2State? = {
createSubtitle2State(currencyStatus = it)
},
private val fiatAmountStateProvider: (CryptoCurrencyStatus) -> TokenItemState.FiatAmountState? = {
createFiatAmountState(it, appCurrency)
createFiatAmountState(status = it, appCurrency = appCurrency)
},
private val onItemClick: ((TokenItemState, CryptoCurrencyStatus) -> Unit)? = null,
private val onItemLongClick: ((TokenItemState, CryptoCurrencyStatus) -> Unit)? = null,
@ -75,7 +78,7 @@ class TokenItemStateConverter(
titleState = titleStateProvider(this),
subtitleState = requireNotNull(subtitleStateProvider(this)),
fiatAmountState = requireNotNull(fiatAmountStateProvider(this)),
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = getFormattedAmount()),
subtitle2State = requireNotNull(subtitle2StateProvider(this)),
onItemClick = onItemClick?.let { onItemClick ->
{ onItemClick(it, this) }
},
@ -85,12 +88,6 @@ class TokenItemStateConverter(
)
}
private fun CryptoCurrencyStatus.getFormattedAmount(): String {
val amount = value.amount?.plus(getStakedBalance()) ?: return DASH_SIGN
return amount.format { crypto(currency) }
}
private fun CryptoCurrencyStatus.mapToUnreachableTokenItemState(): TokenItemState.Unreachable {
return TokenItemState.Unreachable(
id = currency.id.value,
@ -120,6 +117,37 @@ class TokenItemStateConverter(
companion object {
fun CryptoCurrencyStatus.getFormattedFiatAmount(appCurrency: AppCurrency, includeStaking: Boolean): String {
val fiatAmount = value.fiatAmount ?: return DASH_SIGN
val totalAmount = if (includeStaking) {
val fiatYieldBalance = value.fiatRate?.times(getStakedBalance()).orZero()
fiatAmount.plus(fiatYieldBalance)
} else {
fiatAmount
}
return totalAmount.format {
fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol)
}
}
fun CryptoCurrencyStatus.getFormattedCryptoAmount(includeStaking: Boolean): String {
val cryptoAmount = value.amount ?: return DASH_SIGN
val totalAmount = if (includeStaking) {
cryptoAmount.plus(getStakedBalance())
} else {
cryptoAmount
}
return totalAmount.format { crypto(currency) }
}
fun CryptoCurrencyStatus.getStakedBalance() =
(value.yieldBalance as? YieldBalance.Data)?.getTotalWithRewardsStakingBalance().orZero()
private fun createTitleState(currencyStatus: CryptoCurrencyStatus): TokenItemState.TitleState {
return when (val value = currencyStatus.value) {
is CryptoCurrencyStatus.Loading,
@ -160,6 +188,25 @@ class TokenItemStateConverter(
}
}
private fun createSubtitle2State(currencyStatus: CryptoCurrencyStatus): TokenItemState.Subtitle2State? {
return when (currencyStatus.value) {
is CryptoCurrencyStatus.Loaded,
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.NoAccount,
-> {
TokenItemState.Subtitle2State.TextContent(
text = currencyStatus.getFormattedCryptoAmount(includeStaking = true),
)
}
is CryptoCurrencyStatus.Loading,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.NoAmount,
-> null
}
}
private fun createFiatAmountState(
status: CryptoCurrencyStatus,
appCurrency: AppCurrency,
@ -171,7 +218,7 @@ class TokenItemStateConverter(
is CryptoCurrencyStatus.NoAccount,
-> {
TokenItemState.FiatAmountState.Content(
text = status.getFormattedFiatAmount(appCurrency),
text = status.getFormattedFiatAmount(appCurrency = appCurrency, includeStaking = true),
hasStaked = !status.getStakedBalance().isZero(),
)
}
@ -199,25 +246,13 @@ class TokenItemStateConverter(
}
private fun BigDecimal.getFormattedCryptoPrice(appCurrency: AppCurrency): String {
return BigDecimalFormatter.formatFiatAmountUncapped(
fiatAmount = this,
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
)
return format {
fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol)
}
}
private fun BigDecimal.getPriceChangeType(): PriceChangeType {
return PriceChangeConverter.fromBigDecimal(value = this)
}
fun CryptoCurrencyStatus.getFormattedFiatAmount(appCurrency: AppCurrency): String {
val fiatYieldBalance = value.fiatRate?.times(getStakedBalance()).orZero()
val fiatAmount = value.fiatAmount?.plus(fiatYieldBalance) ?: return DASH_SIGN
return BigDecimalFormatter.formatFiatAmount(fiatAmount, appCurrency.code, appCurrency.symbol)
}
private fun CryptoCurrencyStatus.getStakedBalance() =
(value.yieldBalance as? YieldBalance.Data)?.getTotalWithRewardsStakingBalance().orZero()
}
}

View file

@ -1,6 +1,7 @@
package com.tangem.features.onramp.tokenlist.entity.transformer
import com.tangem.common.ui.tokens.TokenItemStateConverter
import com.tangem.common.ui.tokens.TokenItemStateConverter.Companion.getFormattedCryptoAmount
import com.tangem.common.ui.tokens.TokenItemStateConverter.Companion.getFormattedFiatAmount
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
import com.tangem.core.ui.components.fields.entity.SearchBarUM
@ -30,7 +31,7 @@ internal class UpdateTokenItemsTransformer(
override fun transform(prevState: TokenListUM): TokenListUM {
val availableItems = convertStatuses(
converter = createDefaultTokenItemStateConverter(),
converter = createAvailableTokenItemStateConverter(),
statuses = statuses[true].orEmpty(),
)
@ -80,8 +81,13 @@ internal class UpdateTokenItemsTransformer(
.map(TokensListItemUM::Token)
}
private fun createDefaultTokenItemStateConverter(): TokenItemStateConverter {
return TokenItemStateConverter(appCurrency = appCurrency, onItemClick = onItemClick)
private fun createAvailableTokenItemStateConverter(): TokenItemStateConverter {
return TokenItemStateConverter(
appCurrency = appCurrency,
subtitle2StateProvider = ::createSubtitle2State,
fiatAmountStateProvider = { createFiatAmountStateProvider(status = it, isAvailable = true) },
onItemClick = onItemClick,
)
}
private fun createUnavailableTokenItemStateConverter(): TokenItemStateConverter {
@ -105,28 +111,53 @@ internal class UpdateTokenItemsTransformer(
}
}
},
fiatAmountStateProvider = {
when (it.value) {
is CryptoCurrencyStatus.Loaded,
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.NoAccount,
-> {
TokenItemState.FiatAmountState.TextContent(
text = it.getFormattedFiatAmount(appCurrency),
isAvailable = false,
)
}
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.NoAmount,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Loading,
-> null
}
},
subtitle2StateProvider = ::createSubtitle2State,
fiatAmountStateProvider = { createFiatAmountStateProvider(status = it, isAvailable = false) },
)
}
private fun createSubtitle2State(status: CryptoCurrencyStatus): TokenItemState.Subtitle2State? {
return when (status.value) {
is CryptoCurrencyStatus.Loaded,
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.NoAccount,
-> {
TokenItemState.Subtitle2State.TextContent(
text = status.getFormattedCryptoAmount(includeStaking = false),
)
}
is CryptoCurrencyStatus.Loading,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.NoAmount,
-> null
}
}
private fun createFiatAmountStateProvider(
status: CryptoCurrencyStatus,
isAvailable: Boolean,
): TokenItemState.FiatAmountState? {
return when (status.value) {
is CryptoCurrencyStatus.Loaded,
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.NoAccount,
-> {
TokenItemState.FiatAmountState.TextContent(
text = status.getFormattedFiatAmount(appCurrency = appCurrency, includeStaking = false),
isAvailable = isAvailable,
)
}
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.NoAmount,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Loading,
-> null
}
}
private fun createSearchBarItem(): TokensListItemUM.SearchBar {
return TokensListItemUM.SearchBar(
searchBarUM = SearchBarUM(