Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-23 14:27:12 +04:00
parent c2a912b456
commit 48f8d2aaaa
4 changed files with 31 additions and 33 deletions

View file

@ -46,7 +46,7 @@ class TokenItemStateConverter(
private val appCurrency: AppCurrency,
private val yieldModuleApyMap: Map<String, BigDecimal> = emptyMap(),
private val stakingApyMap: Map<CryptoCurrency, StakingAvailability> = emptyMap(),
private val yieldSupplyPromoBannerKey: String? = null,
private val promoCryptoCurrencyStatus: CryptoCurrencyStatus? = null,
private val iconStateProvider: (CryptoCurrencyStatus) -> CurrencyIconState = {
CryptoCurrencyToIconStateConverter().convert(it)
},
@ -75,7 +75,7 @@ class TokenItemStateConverter(
createPromoBannerState(
status = status,
yieldModuleApyMap = yieldModuleApyMap,
yieldSupplyPromoBannerKey = yieldSupplyPromoBannerKey,
promoCryptoCurrencyStatus = promoCryptoCurrencyStatus,
onApyLabelClick = onApyLabelClick,
onYieldPromoCloseClick = onYieldPromoCloseClick,
onYieldPromoShown = onYieldPromoShown,
@ -404,7 +404,7 @@ class TokenItemStateConverter(
private fun createPromoBannerState(
status: CryptoCurrencyStatus,
yieldModuleApyMap: Map<String, BigDecimal>,
yieldSupplyPromoBannerKey: String?,
promoCryptoCurrencyStatus: CryptoCurrencyStatus?,
onApyLabelClick: ((CryptoCurrencyStatus, ApySource, String) -> Unit)?,
onYieldPromoCloseClick: (() -> Unit)?,
onYieldPromoShown: ((cryptoCurrency: CryptoCurrency) -> Unit)?,
@ -414,13 +414,14 @@ class TokenItemStateConverter(
if (status.value !is CryptoCurrencyStatus.Loaded) {
return TokenItemState.PromoBannerState.Empty
}
if (yieldSupplyPromoBannerKey == null || yieldSupplyPromoBannerKey != token.yieldSupplyKey() ||
yieldModuleApyMap[token.yieldSupplyKey()] == null
) {
if (promoCryptoCurrencyStatus == null || status.currency.id != promoCryptoCurrencyStatus.currency.id) {
return TokenItemState.PromoBannerState.Empty
}
val yieldSupplyApy =
yieldModuleApyMap[token.yieldSupplyKey()] ?: return TokenItemState.PromoBannerState.Empty
val tokenKey = "${token.network.rawId}_${token.contractAddress}"
val shouldIgnoreCase = BlockchainUtils.isCaseInsensitiveContractAddress(token.network.rawId)
val yieldSupplyApy = yieldModuleApyMap.entries.firstOrNull { (key, _) ->
key.equals(tokenKey, shouldIgnoreCase)
}?.value ?: return TokenItemState.PromoBannerState.Empty
return TokenItemState.PromoBannerState.Content(
title = resourceReference(

View file

@ -43,7 +43,7 @@ internal class TokenListStateConverter(
private val shouldShowMainPromo: Boolean,
) : Converter<WalletTokensListState, WalletTokensListState> {
private val yieldSupplyPromoBannerKeyConverter = YieldSupplyPromoBannerKeyConverter(
private val yieldSupplyPromoBannerConverter = YieldSupplyPromoBannerConverter(
yieldModuleApyMap,
shouldShowMainPromo,
)
@ -72,7 +72,7 @@ internal class TokenListStateConverter(
private fun tokenStatusConverter(accountId: AccountId? = null) = TokenItemStateConverter(
appCurrency = appCurrency,
yieldModuleApyMap = yieldModuleApyMap,
yieldSupplyPromoBannerKey = yieldSupplyPromoBannerKeyConverter.convert(params),
promoCryptoCurrencyStatus = yieldSupplyPromoBannerConverter.convert(params),
stakingApyMap = stakingAvailabilityMap,
onItemClick = { _, status -> onTokenClick(accountId, status) },
onItemLongClick = { _, status -> onTokenLongClick(accountId, status) },

View file

@ -2,18 +2,17 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers.convert
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.currency.yieldSupplyKey
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TokenConverterParams
import com.tangem.lib.crypto.BlockchainUtils
import com.tangem.utils.converter.Converter
import java.math.BigDecimal
internal class YieldSupplyPromoBannerKeyConverter(
internal class YieldSupplyPromoBannerConverter(
private val yieldModuleApyMap: Map<String, BigDecimal>,
private val shouldShowMainPromo: Boolean,
) : Converter<TokenConverterParams, String?> {
) : Converter<TokenConverterParams, CryptoCurrencyStatus?> {
override fun convert(value: TokenConverterParams): String? {
override fun convert(value: TokenConverterParams): CryptoCurrencyStatus? {
if (!shouldShowMainPromo) return null
val currencies = when (value) {
@ -31,8 +30,8 @@ internal class YieldSupplyPromoBannerKeyConverter(
val max = cryptoCurrencyStatuses.asSequence()
.mapNotNull { status ->
val token = status.currency as? CryptoCurrency.Token ?: return@mapNotNull null
val tokenKey = token.yieldSupplyKey()
val shouldIgnoreCase = BlockchainUtils.isCaseInsensitiveContractAddress(token.network.rawId)
val tokenKey = "${token.network.rawId}_${token.contractAddress}"
val matchedKey = yieldModuleApyMap.keys.firstOrNull { mapKey ->
mapKey.equals(tokenKey, shouldIgnoreCase)
@ -42,6 +41,6 @@ internal class YieldSupplyPromoBannerKeyConverter(
}
.maxByOrNull { (status, _) -> status.value.amount ?: BigDecimal.ZERO }
return max?.second
return max?.first
}
}

View file

@ -5,7 +5,6 @@ import com.tangem.domain.models.PortfolioId
import com.tangem.domain.models.StatusSource
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.network.Network
import com.tangem.domain.models.network.NetworkAddress
import com.tangem.domain.models.tokenlist.TokenList
@ -15,7 +14,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.TokenCon
import org.junit.Test
import java.math.BigDecimal
class YieldSupplyPromoBannerKeyConverterTest {
class YieldSupplyPromoBannerConverterTest {
@Test
fun `GIVEN promo disabled WHEN convert THEN return null`() {
@ -26,8 +25,8 @@ class YieldSupplyPromoBannerKeyConverterTest {
portfolioId = PortfolioId.Wallet(UserWalletId("00")),
tokenList = tokenList,
)
val converter = YieldSupplyPromoBannerKeyConverter(
yieldModuleApyMap = mapOf(token.yieldSupplyKey() to BigDecimal("0.10")),
val converter = YieldSupplyPromoBannerConverter(
yieldModuleApyMap = mapOf("${token.network.rawId}_${token.contractAddress}" to BigDecimal("0.10")),
shouldShowMainPromo = false,
)
@ -44,7 +43,7 @@ class YieldSupplyPromoBannerKeyConverterTest {
portfolioId = PortfolioId.Wallet(UserWalletId("00")),
tokenList = ungroupedTokenList(status),
)
val converter = YieldSupplyPromoBannerKeyConverter(
val converter = YieldSupplyPromoBannerConverter(
yieldModuleApyMap = emptyMap(),
shouldShowMainPromo = true,
)
@ -62,8 +61,8 @@ class YieldSupplyPromoBannerKeyConverterTest {
portfolioId = PortfolioId.Wallet(UserWalletId("00")),
tokenList = ungroupedTokenList(statusActive),
)
val converter = YieldSupplyPromoBannerKeyConverter(
yieldModuleApyMap = mapOf(token.yieldSupplyKey() to BigDecimal("0.12")),
val converter = YieldSupplyPromoBannerConverter(
yieldModuleApyMap = mapOf("${token.network.rawId}_${token.contractAddress}" to BigDecimal("0.12")),
shouldShowMainPromo = true,
)
@ -73,7 +72,7 @@ class YieldSupplyPromoBannerKeyConverterTest {
}
@Test
fun `GIVEN multiple candidates EVM case insensitive WHEN convert THEN return key of max amount`() {
fun `GIVEN multiple candidates EVM case insensitive WHEN convert THEN return status of max amount`() {
val evmNetworkId = "ETH"
val tokenSmall = createToken(networkId = evmNetworkId, backendId = evmNetworkId, contract = "0xAbCd")
val tokenBig = createToken(networkId = evmNetworkId, backendId = evmNetworkId, contract = "0xBEEF")
@ -82,23 +81,22 @@ class YieldSupplyPromoBannerKeyConverterTest {
val statusBig = createLoadedStatus(token = tokenBig, amount = BigDecimal("10.00"), isYieldActive = false)
val apyMap = mapOf(
"${tokenSmall.network.backendId}_${tokenSmall.contractAddress.lowercase()}" to BigDecimal("0.05"),
"${tokenBig.network.backendId}_${tokenBig.contractAddress.uppercase()}" to BigDecimal("0.15"),
"${tokenSmall.network.rawId}_${tokenSmall.contractAddress.lowercase()}" to BigDecimal("0.05"),
"${tokenBig.network.rawId}_${tokenBig.contractAddress.uppercase()}" to BigDecimal("0.15"),
)
val params = TokenConverterParams.Wallet(
portfolioId = PortfolioId.Wallet(UserWalletId("00")),
tokenList = ungroupedTokenList(statusSmall, statusBig),
)
val converter = YieldSupplyPromoBannerKeyConverter(
val converter = YieldSupplyPromoBannerConverter(
yieldModuleApyMap = apyMap,
shouldShowMainPromo = true,
)
val result = converter.convert(params)
val expectedKey = "${tokenBig.network.backendId}_${tokenBig.contractAddress.uppercase()}"
assertThat(result).isEqualTo(expectedKey)
assertThat(result).isEqualTo(statusBig)
}
@Test
@ -107,14 +105,14 @@ class YieldSupplyPromoBannerKeyConverterTest {
val token = createToken(networkId = nonEvmId, backendId = nonEvmId, contract = "rAbC123")
val status = createLoadedStatus(token = token, amount = BigDecimal("3"), isYieldActive = false)
val mismatchedKey = "${token.network.backendId}_${token.contractAddress.lowercase()}"
val mismatchedKey = "${token.network.rawId}_${token.contractAddress.lowercase()}"
val apyMap = mapOf(mismatchedKey to BigDecimal("0.07"))
val params = TokenConverterParams.Wallet(
portfolioId = PortfolioId.Wallet(UserWalletId("00")),
tokenList = ungroupedTokenList(status),
)
val converter = YieldSupplyPromoBannerKeyConverter(
val converter = YieldSupplyPromoBannerConverter(
yieldModuleApyMap = apyMap,
shouldShowMainPromo = true,
)
@ -132,8 +130,8 @@ class YieldSupplyPromoBannerKeyConverterTest {
portfolioId = PortfolioId.Wallet(UserWalletId("00")),
tokenList = ungroupedTokenList(status),
)
val converter = YieldSupplyPromoBannerKeyConverter(
yieldModuleApyMap = mapOf(token.yieldSupplyKey() to BigDecimal("0.10")),
val converter = YieldSupplyPromoBannerConverter(
yieldModuleApyMap = mapOf("${token.network.rawId}_${token.contractAddress}" to BigDecimal("0.10")),
shouldShowMainPromo = true,
)