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

@ -6,6 +6,7 @@ import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
import com.tangem.domain.staking.single.SingleYieldBalanceFetcher
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
import com.tangem.domain.walletmanager.WalletManagersFacade
import dagger.Module
import dagger.Provides
@ -216,4 +217,10 @@ internal object StakingDomainModule {
fun provideStakingIdFactory(walletManagersFacade: WalletManagersFacade): StakingIdFactory {
return StakingIdFactory(walletManagersFacade = walletManagersFacade)
}
@Provides
@Singleton
fun provideStakingApyFlowUseCase(stakingRepository: StakingRepository): StakingApyFlowUseCase {
return StakingApyFlowUseCase(stakingRepository)
}
}

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"
}
}
}

View file

@ -3,11 +3,7 @@ package com.tangem.core.ui.components.token.internal
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@ -85,14 +81,14 @@ private fun CurrencyNameText(name: String, isAvailable: Boolean, modifier: Modif
private fun YieldSupplyApyLabel(apy: TextReference?, isActive: Boolean, modifier: Modifier = Modifier) {
AnimatedVisibility(visible = apy != null, modifier = modifier) {
Box(
modifier = if (isActive) {
modifier.background(
color = TangemTheme.colors.text.accent.copy(alpha = 0.1f),
shape = TangemTheme.shapes.roundedCornersSmall2,
)
} else {
modifier
},
modifier = Modifier.background(
color = if (isActive) {
TangemTheme.colors.text.accent.copy(alpha = 0.1f)
} else {
TangemTheme.colors.control.unchecked
},
shape = TangemTheme.shapes.roundedCornersSmall2,
),
) {
Text(
text = apy?.resolveReference().orEmpty(),
@ -100,7 +96,7 @@ private fun YieldSupplyApyLabel(apy: TextReference?, isActive: Boolean, modifier
color = if (isActive) {
TangemTheme.colors.text.accent
} else {
TangemTheme.colors.text.tertiary
TangemTheme.colors.text.secondary
},
modifier = Modifier.padding(horizontal = 4.dp, vertical = 2.dp),
)

View file

@ -7,6 +7,7 @@ import java.util.Locale
class BigDecimalPercentFormat(
val isWithoutSign: Boolean = true,
val withPercentSign: Boolean = true,
val locale: Locale = Locale.getDefault(),
) : BigDecimalFormat {
override fun invoke(value: BigDecimal): String = default()(value)
@ -16,24 +17,30 @@ class BigDecimalPercentFormat(
fun BigDecimalFormatScope.percent(
withoutSign: Boolean = true,
withPercentSign: Boolean = true,
locale: Locale = Locale.getDefault(),
): BigDecimalPercentFormat {
return BigDecimalPercentFormat(
isWithoutSign = withoutSign,
locale = locale,
withPercentSign = withPercentSign,
)
}
// == Formatters ==
private fun BigDecimalPercentFormat.default(): BigDecimalFormat = BigDecimalFormat { value ->
val formatter = NumberFormat.getPercentInstance(locale).apply {
val formatter = if (withPercentSign) {
NumberFormat.getPercentInstance(locale)
} else {
NumberFormat.getNumberInstance(locale)
}.apply {
maximumFractionDigits = 2
minimumFractionDigits = 2
roundingMode = RoundingMode.HALF_UP
}
val valueToFormat = if (isWithoutSign) value.abs() else value
val finalValue = if (withPercentSign) valueToFormat else valueToFormat.movePointRight(2)
formatter.format(valueToFormat)
formatter.format(finalValue)
}

View file

@ -500,7 +500,7 @@ internal class DefaultStakingRepository(
)
}
private fun getEnabledYields(): Flow<List<Yield>> {
override fun getEnabledYields(): Flow<List<Yield>> {
return stakingYieldsStore.get().map {
YieldConverter.convertListIgnoreErrors(
input = it,

View file

@ -22,6 +22,8 @@ interface StakingRepository {
suspend fun fetchEnabledYields()
fun getEnabledYields(): Flow<List<Yield>>
suspend fun getEntryInfo(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): StakingEntryInfo
suspend fun getYield(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): Yield

View file

@ -0,0 +1,37 @@
package com.tangem.domain.staking.usecase
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.
*
* Return map:
* - key: currency staking key (network.backendId + "_" + symbol)
* - value: APY as string
*/
class StakingApyFlowUseCase(private val stakingRepository: StakingRepository) {
operator fun invoke(): Flow<Map<String, BigDecimal>> {
return stakingRepository.getEnabledYields()
.map { yields ->
yields.associate { yield ->
val key = "${yield.token.network.name.lowercase()}_${yield.token.symbol}"
val apy = calculateApy(yield)
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
}
}
}

View file

@ -8,6 +8,7 @@ import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
@ -44,6 +45,7 @@ internal class MultiWalletContentLoader(
private val currenciesRepository: CurrenciesRepository,
private val accountDependencies: AccountDependencies,
private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
private val stakingApyFlowUseCase: StakingApyFlowUseCase,
) : WalletContentLoader(id = userWallet.walletId) {
override fun create(): List<WalletSubscriber> {
@ -60,6 +62,7 @@ internal class MultiWalletContentLoader(
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
accountDependencies = accountDependencies,
yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase,
stakingApyFlowUseCase = stakingApyFlowUseCase,
).let(::add)
WalletNFTListSubscriber(

View file

@ -8,6 +8,7 @@ import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
@ -42,6 +43,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
private val currenciesRepository: CurrenciesRepository,
private val accountDependencies: AccountDependencies,
private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
private val stakingApyFlowUseCase: StakingApyFlowUseCase,
) {
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): WalletContentLoader {
@ -65,6 +67,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
currenciesRepository = currenciesRepository,
accountDependencies = accountDependencies,
yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase,
stakingApyFlowUseCase = stakingApyFlowUseCase,
)
}
}

View file

@ -4,6 +4,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.promo.GetStoryContentUseCase
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
@ -34,6 +35,7 @@ internal class SingleWalletWithTokenContentLoader(
private val getStoryContentUseCase: GetStoryContentUseCase,
private val accountDependencies: AccountDependencies,
private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
private val stakingApyFlowUseCase: StakingApyFlowUseCase,
) : WalletContentLoader(id = userWallet.walletId) {
override fun create(): List<WalletSubscriber> {
@ -49,6 +51,7 @@ internal class SingleWalletWithTokenContentLoader(
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
accountDependencies = accountDependencies,
yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase,
stakingApyFlowUseCase = stakingApyFlowUseCase,
).let(::add)
MultiWalletWarningsSubscriber(
userWallet = userWallet,

View file

@ -5,6 +5,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.promo.GetStoryContentUseCase
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
@ -35,6 +36,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
private val getStoryContentUseCase: GetStoryContentUseCase,
private val accountDependencies: AccountDependencies,
private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
private val stakingApyFlowUseCase: StakingApyFlowUseCase,
) {
fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents): SingleWalletWithTokenContentLoader {
@ -54,6 +56,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
accountDependencies = accountDependencies,
yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase,
stakingApyFlowUseCase = stakingApyFlowUseCase,
)
}
}

View file

@ -10,6 +10,7 @@ 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,
@ -17,6 +18,7 @@ internal class SetTokenListTransformer(
private val appCurrency: AppCurrency,
private val clickIntents: WalletClickIntents,
private val yieldSupplyApyMap: Map<String, String> = emptyMap(),
private val stakingApyMap: Map<String, BigDecimal> = emptyMap(),
) : WalletStateTransformer(userWallet.walletId) {
override fun transform(prevState: WalletState): WalletState {
@ -59,7 +61,8 @@ internal class SetTokenListTransformer(
selectedWallet = userWallet,
appCurrency = appCurrency,
clickIntents = clickIntents,
apyMap = yieldSupplyApyMap,
yieldModuleApyMap = yieldSupplyApyMap,
stakingApyMap = stakingApyMap,
).convert(value = this)
}
}

View file

@ -27,6 +27,7 @@ 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(
@ -34,7 +35,8 @@ internal class TokenListStateConverter(
private val params: TokenConverterParams,
private val selectedWallet: UserWallet,
private val clickIntents: WalletClickIntents,
private val apyMap: Map<String, String>,
private val yieldModuleApyMap: Map<String, String>,
private val stakingApyMap: Map<String, BigDecimal>,
) : Converter<WalletTokensListState, WalletTokensListState> {
private val onTokenClick: (accountId: AccountId?, currencyStatus: CryptoCurrencyStatus) -> Unit =
@ -49,7 +51,8 @@ internal class TokenListStateConverter(
private fun tokenStatusConverter(accountId: AccountId? = null) = TokenItemStateConverter(
appCurrency = appCurrency,
apyMap = apyMap,
yieldModuleApyMap = yieldModuleApyMap,
stakingApyMap = stakingApyMap,
onItemClick = { _, status -> onTokenClick(accountId, status) },
onItemLongClick = { _, status -> onTokenLongClick(accountId, status) },
)

View file

@ -16,6 +16,7 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.account.AccountDependencies
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
@ -25,12 +26,14 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetToken
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenListTransformer
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TokenConverterParams
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.combine6
import com.tangem.utils.coroutines.saveIn
import kotlinx.coroutines.CoroutineScope
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() {
@ -43,6 +46,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
protected abstract val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase
protected abstract val accountDependencies: AccountDependencies
protected abstract val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase
protected abstract val stakingApyFlowUseCase: StakingApyFlowUseCase
private val sendAnalyticsJobHolder = JobHolder()
private val onTokenListReceivedJobHolder = JobHolder()
@ -81,12 +85,14 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
},
flow2 = appCurrencyFlow(),
flow3 = yieldSupplyApyFlow(),
transform = { maybeTokenList, appCurrency, yieldSupplyApyMap ->
flow4 = stakingApyFlow(),
transform = { maybeTokenList, appCurrency, yieldSupplyApyMap, stakingApyMap ->
singleAccountTransform(
maybeTokenList = maybeTokenList,
appCurrency = appCurrency,
portfolioId = PortfolioId(userWallet.walletId),
yieldSupplyApyMap = yieldSupplyApyMap,
stakingApyMap = stakingApyMap,
)
},
)
@ -97,6 +103,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
appCurrency: AppCurrency,
portfolioId: PortfolioId,
yieldSupplyApyMap: Map<String, String>,
stakingApyMap: Map<String, BigDecimal>,
) {
val tokenList = maybeTokenList.getOrElse(
ifLoading = { maybeContent ->
@ -124,6 +131,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
params = TokenConverterParams.Wallet(portfolioId, tokenList),
appCurrency = appCurrency,
yieldSupplyApyMap = yieldSupplyApyMap,
stakingApyMap = stakingApyMap,
)
walletWithFundsChecker.check(tokenList)
@ -143,8 +151,8 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
}
}
private fun createAccountListFlow(coroutineScope: CoroutineScope): Flow<*> = combine(
flow = accountListFlow(coroutineScope)
private fun createAccountListFlow(coroutineScope: CoroutineScope): Flow<*> = combine6(
flow1 = accountListFlow(coroutineScope)
.onEach { accountStatusList ->
coroutineScope.launch {
sendTokenListAnalytics(
@ -165,7 +173,8 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
flow3 = accountDependencies.expandedAccountsHolder.expandedAccounts(userWallet),
flow4 = accountDependencies.isAccountsModeEnabledUseCase(),
flow5 = yieldSupplyApyFlow(),
transform = { accountList, appCurrency, expandedAccounts, isAccountMode, yieldSupplyApyMap ->
flow6 = stakingApyFlow(),
transform = { accountList, appCurrency, expandedAccounts, isAccountMode, yieldSupplyApyMap, stakingApyMap ->
val accountFlattenTokensList = accountList.flattenTokens()
val accountFlattenCurrencies = accountFlattenTokensList
.map { it.flattenCurrencies() }
@ -180,6 +189,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
appCurrency,
PortfolioId(mainAccount.account.accountId),
yieldSupplyApyMap,
stakingApyMap,
)
when {
@ -198,7 +208,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
)
false -> {
val convertParams = TokenConverterParams.Account(accountList, expandedAccounts)
updateContent(convertParams, appCurrency, yieldSupplyApyMap)
updateContent(convertParams, appCurrency, yieldSupplyApyMap, stakingApyMap)
accountFlattenTokensList
.map { tokenList -> coroutineScope.launch { walletWithFundsChecker.check(tokenList) } }
.joinAll()
@ -232,6 +242,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
params: TokenConverterParams,
appCurrency: AppCurrency,
yieldSupplyApyMap: Map<String, String>,
stakingApyMap: Map<String, BigDecimal>,
) {
stateHolder.update(
SetTokenListTransformer(
@ -240,6 +251,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
appCurrency = appCurrency,
clickIntents = clickIntents,
yieldSupplyApyMap = yieldSupplyApyMap,
stakingApyMap = stakingApyMap,
),
)
}
@ -255,4 +267,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() {
private fun yieldSupplyApyFlow(): Flow<Map<String, String>> = yieldSupplyApyFlowUseCase()
.distinctUntilChanged()
private fun stakingApyFlow(): Flow<Map<String, BigDecimal>> = stakingApyFlowUseCase()
.distinctUntilChanged()
}

View file

@ -10,6 +10,7 @@ import com.tangem.domain.models.TotalFiatBalance
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.tokenlist.TokenList
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.tokens.error.TokenListError
@ -36,6 +37,7 @@ internal class MultiWalletTokenListSubscriber(
override val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
override val accountDependencies: AccountDependencies,
override val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
override val stakingApyFlowUseCase: StakingApyFlowUseCase,
) : BasicTokenListSubscriber() {
override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow<TokenListError, TokenList> {

View file

@ -7,6 +7,7 @@ import com.tangem.domain.core.lce.Lce
import com.tangem.domain.core.lce.LceFlow
import com.tangem.domain.models.tokenlist.TokenList
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.staking.usecase.StakingApyFlowUseCase
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
@ -31,6 +32,7 @@ internal class SingleWalletWithTokenListSubscriber(
override val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
override val accountDependencies: AccountDependencies,
override val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
override val stakingApyFlowUseCase: StakingApyFlowUseCase,
) : BasicTokenListSubscriber() {
override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow<TokenListError, TokenList> {