Updated on 2026-08-14
This commit is contained in:
parent
c49b3a9176
commit
8467ada25d
16 changed files with 156 additions and 50 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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) },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue