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

@ -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> {