From 3ca8a415cd5b85346937c3717b8211825fc08c76 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 27 Oct 2025 12:15:41 +0100 Subject: [PATCH] Updated on 2026-08-14 --- .../ui/tokens/TokenItemStateConverter.kt | 40 ++++++++++++++----- .../staking/usecase/StakingApyFlowUseCase.kt | 18 ++------- .../transformers/SetTokenListTransformer.kt | 4 +- .../converter/TokenListStateConverter.kt | 4 +- .../subscribers/BasicTokenListSubscriber.kt | 8 ++-- 5 files changed, 43 insertions(+), 31 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 31d7fecf65..273839cc0e 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 @@ -21,6 +21,7 @@ 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.staking.YieldBalance +import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.staking.utils.getTotalWithRewardsStakingBalance import com.tangem.lib.crypto.BlockchainUtils import com.tangem.utils.StringsSigns.DASH_SIGN @@ -41,7 +42,7 @@ import java.math.BigDecimal class TokenItemStateConverter( private val appCurrency: AppCurrency, private val yieldModuleApyMap: Map = emptyMap(), - private val stakingApyMap: Map = emptyMap(), + private val stakingApyMap: Map> = emptyMap(), private val iconStateProvider: (CryptoCurrencyStatus) -> CurrencyIconState = { CryptoCurrencyToIconStateConverter().convert(it) }, @@ -156,7 +157,7 @@ class TokenItemStateConverter( private fun createTitleState( currencyStatus: CryptoCurrencyStatus, yieldModuleApyMap: Map, - stakingApyMap: Map, + stakingApyMap: Map>, ): TokenItemState.TitleState { return when (val value = currencyStatus.value) { is CryptoCurrencyStatus.Loading, @@ -190,7 +191,7 @@ class TokenItemStateConverter( private fun resolveEarnApy( cryptoCurrencyStatus: CryptoCurrencyStatus, yieldModuleApyMap: Map, - stakingApyMap: Map, + stakingApyMap: Map>, ): Pair { val token = cryptoCurrencyStatus.currency as? CryptoCurrency.Token if (token != null && yieldModuleApyMap.isNotEmpty()) { @@ -210,20 +211,41 @@ class TokenItemStateConverter( } 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 + val (stakingRate, hasStaked) = findStakingRate( + currencyStatus = cryptoCurrencyStatus, + stakingApyMap = stakingApyMap, + ) + if (stakingRate != null) { return resourceReference( R.string.yield_module_earn_badge, - wrappedList(stakingApy), - ) to hasStakedBalance + wrappedList(stakingRate.format { percent(withPercentSign = false) }), + ) to hasStaked } } return null to false } + private fun findStakingRate( + currencyStatus: CryptoCurrencyStatus, + stakingApyMap: Map>, + ): Pair { + val stakingKey = currencyStatus.currency.stakingKey() + val validators = stakingApyMap[stakingKey] ?: return null to false + val yieldBalance = currencyStatus.value.yieldBalance + val hasStakedBalance = yieldBalance is YieldBalance.Data + val rate = if (hasStakedBalance) { + val validatorsByAddress = validators.associateBy { it.address } + yieldBalance.balance.items + .mapNotNull { it.validatorAddress } + .firstNotNullOfOrNull { address -> validatorsByAddress[address]?.rewardInfo?.rate } + ?: validators.mapNotNull { it.rewardInfo?.rate }.maxOrNull() + } else { + validators.mapNotNull { it.rewardInfo?.rate }.maxOrNull() + } + return rate to hasStakedBalance + } + private fun createSubtitleState( currencyStatus: CryptoCurrencyStatus, appCurrency: AppCurrency, diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt index e709bd63de..3b50f3a63c 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/usecase/StakingApyFlowUseCase.kt @@ -4,34 +4,24 @@ import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.staking.repositories.StakingRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -import java.math.BigDecimal /** - * Emits a map of APY values per currency for staking. + * Emits a map of Validators values per currency for staking. * * Return map: * - key: currency staking key (network.backendId + "_" + symbol) - * - value: APY as string + * - value: validators */ class StakingApyFlowUseCase(private val stakingRepository: StakingRepository) { - operator fun invoke(): Flow> { + operator fun invoke(): Flow>> { return stakingRepository.getEnabledYields() .map { yields -> yields.associate { yield -> val key = "${yield.token.coinGeckoId}_${yield.token.symbol}" - val apy = calculateApy(yield) + val apy = yield.validators key to apy } } } - - private fun calculateApy(yield: Yield): BigDecimal { - val rates = yield.validators.mapNotNull { it.rewardInfo?.rate } - return if (rates.isNotEmpty()) { - rates.maxOf { it } - } else { - yield.apy - } - } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt index 5255206967..4d102bb5d8 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListTransformer.kt @@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState @@ -10,7 +11,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.converte import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TokenListStateConverter import com.tangem.feature.wallet.presentation.wallet.state.utils.enableButtons import timber.log.Timber -import java.math.BigDecimal internal class SetTokenListTransformer( private val params: TokenConverterParams, @@ -18,7 +18,7 @@ internal class SetTokenListTransformer( private val appCurrency: AppCurrency, private val clickIntents: WalletClickIntents, private val yieldSupplyApyMap: Map = emptyMap(), - private val stakingApyMap: Map = emptyMap(), + private val stakingApyMap: Map> = emptyMap(), ) : WalletStateTransformer(userWallet.walletId) { override fun transform(prevState: WalletState): WalletState { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt index 9134b2295d..34ade399d3 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt @@ -17,6 +17,7 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.tokenlist.TokenList import com.tangem.domain.models.tokenlist.TokenList.GroupedByNetwork.NetworkGroup import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState @@ -27,7 +28,6 @@ import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.mutate import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList -import java.math.BigDecimal import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState.OrganizeTokensButtonConfig as WalletOrganizeTokensButtonConfig internal class TokenListStateConverter( @@ -36,7 +36,7 @@ internal class TokenListStateConverter( private val selectedWallet: UserWallet, private val clickIntents: WalletClickIntents, private val yieldModuleApyMap: Map, - private val stakingApyMap: Map, + private val stakingApyMap: Map>, ) : Converter { private val onTokenClick: (accountId: AccountId?, currencyStatus: CryptoCurrencyStatus) -> Unit = diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt index 328d3a5cbe..8fbd5a1d74 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt @@ -13,6 +13,7 @@ import com.tangem.domain.models.account.AccountStatus import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.tokenlist.TokenList import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase @@ -33,7 +34,6 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch import timber.log.Timber -import java.math.BigDecimal @Suppress("LongParameterList") internal abstract class BasicTokenListSubscriber : WalletSubscriber() { @@ -103,7 +103,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { appCurrency: AppCurrency, portfolioId: PortfolioId, yieldSupplyApyMap: Map, - stakingApyMap: Map, + stakingApyMap: Map>, ) { val tokenList = maybeTokenList.getOrElse( ifLoading = { maybeContent -> @@ -242,7 +242,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { params: TokenConverterParams, appCurrency: AppCurrency, yieldSupplyApyMap: Map, - stakingApyMap: Map, + stakingApyMap: Map>, ) { stateHolder.update( SetTokenListTransformer( @@ -268,6 +268,6 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { private fun yieldSupplyApyFlow(): Flow> = yieldSupplyApyFlowUseCase() .distinctUntilChanged() - private fun stakingApyFlow(): Flow> = stakingApyFlowUseCase() + private fun stakingApyFlow(): Flow>> = stakingApyFlowUseCase() .distinctUntilChanged() } \ No newline at end of file