Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-19 13:58:25 +04:00
parent 032fbe824a
commit afddda1198
4 changed files with 71 additions and 13 deletions

View file

@ -397,6 +397,9 @@ class TokenItemStateConverter(
onYieldPromoCloseClick: (() -> Unit)?,
): TokenItemState.PromoBannerState {
val token = status.currency as? CryptoCurrency.Token ?: return TokenItemState.PromoBannerState.Empty
if (status.value !is CryptoCurrencyStatus.Loaded) {
return TokenItemState.PromoBannerState.Empty
}
if (yieldSupplyPromoBannerKey == null || yieldSupplyPromoBannerKey != token.yieldSupplyKey() ||
yieldModuleApyMap[token.yieldSupplyKey()] == null
) {

View file

@ -44,8 +44,8 @@ internal fun YieldSupplyPromoBanner(state: PromoBannerState.Content, modifier: M
Row(
modifier = Modifier
.background(color = bgColor, shape = TangemTheme.shapes.roundedCornersXMedium)
.padding(horizontal = 12.dp, vertical = 8.dp)
.clickable(onClick = state.onPromoBannerClick)
.padding(horizontal = 12.dp, vertical = 8.dp)
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {

View file

@ -20,16 +20,15 @@ internal class YieldSupplyPromoBannerKeyConverter(
is TokenConverterParams.Wallet -> value.tokenList.flattenCurrencies()
is TokenConverterParams.Account -> value.accountList.flattenCurrencies()
}.filter { status ->
status.value is CryptoCurrencyStatus.Loaded ||
status.value is CryptoCurrencyStatus.Custom
status.value is CryptoCurrencyStatus.Loaded
}
val tokens = currencies.filter { it.currency is CryptoCurrency.Token }
val cryptoCurrencyStatuses = currencies.filter { it.currency is CryptoCurrency.Token }
if (tokens.any { it.value.yieldSupplyStatus?.isActive == true }) return null
if (cryptoCurrencyStatuses.any { it.value.yieldSupplyStatus?.isActive == true }) return null
if (yieldModuleApyMap.isEmpty()) return null
val max = tokens.asSequence()
val max = cryptoCurrencyStatuses.asSequence()
.mapNotNull { status ->
val token = status.currency as? CryptoCurrency.Token ?: return@mapNotNull null
val tokenKey = token.yieldSupplyKey()

View file

@ -20,7 +20,7 @@ class YieldSupplyPromoBannerKeyConverterTest {
@Test
fun `GIVEN promo disabled WHEN convert THEN return null`() {
val token = createToken(networkId = "ethereum", backendId = "ethereum", contract = "0xABCDEF")
val status = createStatus(token = token, amount = BigDecimal.ONE, isYieldActive = false)
val status = createLoadedStatus(token = token, amount = BigDecimal.ONE, isYieldActive = false)
val tokenList = ungroupedTokenList(status)
val params = TokenConverterParams.Wallet(
portfolioId = PortfolioId.Wallet(UserWalletId("00")),
@ -39,7 +39,7 @@ class YieldSupplyPromoBannerKeyConverterTest {
@Test
fun `GIVEN empty apy map WHEN convert THEN return null`() {
val token = createToken(networkId = "ethereum", backendId = "ethereum", contract = "0xA1")
val status = createStatus(token = token, amount = BigDecimal("2.0"), isYieldActive = false)
val status = createLoadedStatus(token = token, amount = BigDecimal("2.0"), isYieldActive = false)
val params = TokenConverterParams.Wallet(
portfolioId = PortfolioId.Wallet(UserWalletId("00")),
tokenList = ungroupedTokenList(status),
@ -57,7 +57,7 @@ class YieldSupplyPromoBannerKeyConverterTest {
@Test
fun `GIVEN active yield token present WHEN convert THEN return null`() {
val token = createToken(networkId = "ethereum", backendId = "ethereum", contract = "0xAA")
val statusActive = createStatus(token = token, amount = BigDecimal("5"), isYieldActive = true)
val statusActive = createLoadedStatus(token = token, amount = BigDecimal("5"), isYieldActive = true)
val params = TokenConverterParams.Wallet(
portfolioId = PortfolioId.Wallet(UserWalletId("00")),
tokenList = ungroupedTokenList(statusActive),
@ -78,8 +78,8 @@ class YieldSupplyPromoBannerKeyConverterTest {
val tokenSmall = createToken(networkId = evmNetworkId, backendId = evmNetworkId, contract = "0xAbCd")
val tokenBig = createToken(networkId = evmNetworkId, backendId = evmNetworkId, contract = "0xBEEF")
val statusSmall = createStatus(token = tokenSmall, amount = BigDecimal("1.00"), isYieldActive = false)
val statusBig = createStatus(token = tokenBig, amount = BigDecimal("10.00"), isYieldActive = false)
val statusSmall = createLoadedStatus(token = tokenSmall, amount = BigDecimal("1.00"), isYieldActive = false)
val statusBig = createLoadedStatus(token = tokenBig, amount = BigDecimal("10.00"), isYieldActive = false)
val apyMap = mapOf(
"${tokenSmall.network.backendId}_${tokenSmall.contractAddress.lowercase()}" to BigDecimal("0.05"),
@ -105,7 +105,7 @@ class YieldSupplyPromoBannerKeyConverterTest {
fun `GIVEN non evm case sensitive mismatch WHEN convert THEN return null`() {
val nonEvmId = "xrp"
val token = createToken(networkId = nonEvmId, backendId = nonEvmId, contract = "rAbC123")
val status = createStatus(token = token, amount = BigDecimal("3"), isYieldActive = false)
val status = createLoadedStatus(token = token, amount = BigDecimal("3"), isYieldActive = false)
val mismatchedKey = "${token.network.backendId}_${token.contractAddress.lowercase()}"
val apyMap = mapOf(mismatchedKey to BigDecimal("0.07"))
@ -124,6 +124,24 @@ class YieldSupplyPromoBannerKeyConverterTest {
assertThat(result).isNull()
}
@Test
fun `GIVEN custom status WHEN convert THEN return null`() {
val token = createToken(networkId = "ethereum", backendId = "ethereum", contract = "0xCUSTOM")
val status = createCustomStatus(token = token, amount = BigDecimal("5.0"), isYieldActive = false)
val params = TokenConverterParams.Wallet(
portfolioId = PortfolioId.Wallet(UserWalletId("00")),
tokenList = ungroupedTokenList(status),
)
val converter = YieldSupplyPromoBannerKeyConverter(
yieldModuleApyMap = mapOf(token.yieldSupplyKey() to BigDecimal("0.10")),
shouldShowMainPromo = true,
)
val result = converter.convert(params)
assertThat(result).isNull()
}
private fun ungroupedTokenList(vararg statuses: CryptoCurrencyStatus): TokenList.Ungrouped {
return TokenList.Ungrouped(
totalFiatBalance = com.tangem.domain.models.TotalFiatBalance.Loaded(
@ -135,7 +153,45 @@ class YieldSupplyPromoBannerKeyConverterTest {
)
}
private fun createStatus(
private fun createLoadedStatus(
token: CryptoCurrency.Token,
amount: BigDecimal,
isYieldActive: Boolean,
): CryptoCurrencyStatus {
val networkAddress = NetworkAddress.Single(
defaultAddress = NetworkAddress.Address(
value = "addr",
type = NetworkAddress.Address.Type.Primary,
),
)
val value = CryptoCurrencyStatus.Loaded(
amount = amount,
fiatAmount = BigDecimal.ZERO,
fiatRate = BigDecimal.ONE,
priceChange = BigDecimal.ZERO,
yieldBalance = null,
yieldSupplyStatus = if (isYieldActive) {
YieldSupplyStatus(
isActive = true,
isInitialized = true,
isAllowedToSpend = true,
effectiveProtocolBalance = null,
)
} else {
null
},
hasCurrentNetworkTransactions = false,
pendingTransactions = emptySet(),
networkAddress = networkAddress,
sources = CryptoCurrencyStatus.Sources(),
)
return CryptoCurrencyStatus(
currency = token,
value = value,
)
}
private fun createCustomStatus(
token: CryptoCurrency.Token,
amount: BigDecimal,
isYieldActive: Boolean,