Updated on 2026-08-14
This commit is contained in:
parent
5620f6afe7
commit
f377a40b36
16 changed files with 583 additions and 31 deletions
|
|
@ -1,11 +1,17 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.domain
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.right
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusProducer
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusSupplier
|
||||
import com.tangem.domain.card.CardTypesResolver
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
|
||||
|
|
@ -22,8 +28,11 @@ import kotlinx.coroutines.flow.*
|
|||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
@Suppress("LongParameterList")
|
||||
internal class GetSingleWalletWarningsFactory @Inject constructor(
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val singleAccountStatusSupplier: SingleAccountStatusSupplier,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase,
|
||||
private val isNeedToBackupUseCase: IsNeedToBackupUseCase,
|
||||
|
|
@ -40,7 +49,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
|
||||
|
||||
return combine(
|
||||
flow = getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId),
|
||||
flow = getPrimaryCurrencyStatusFlow(userWallet),
|
||||
flow2 = isReadyToShowRateAppUseCase().conflate(),
|
||||
flow3 = isNeedToBackupUseCase(userWallet.walletId).conflate(),
|
||||
flow4 = getWalletsUseCase().conflate(),
|
||||
|
|
@ -217,6 +226,29 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getPrimaryCurrencyStatusFlow(
|
||||
userWallet: UserWallet,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountStatusFlow(userWallet).mapNotNull { accountStatus ->
|
||||
accountStatus.flattenCurrencies().firstOrNull()
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.conflate()
|
||||
.map { it.right() }
|
||||
} else {
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAccountStatusFlow(userWallet: UserWallet): Flow<AccountStatus> {
|
||||
val accountId = AccountId.forMainCryptoPortfolio(userWalletId = userWallet.walletId)
|
||||
|
||||
return singleAccountStatusSupplier(SingleAccountStatusProducer.Params(accountId))
|
||||
.distinctUntilChanged()
|
||||
.conflate()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val NOTE_MIGRATION_URL = "https://tangem.com/en/?promocode=Note10"
|
||||
const val MAX_REMAINING_SIGNATURES_COUNT = 10
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders
|
||||
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
|
|
@ -12,7 +13,9 @@ import javax.inject.Inject
|
|||
internal class WalletContentLoaderFactory @Inject constructor(
|
||||
private val multiWalletContentLoaderFactory: MultiWalletContentLoaderFactory,
|
||||
private val singleWalletWithTokenContentLoaderFactory: SingleWalletWithTokenContentLoaderFactory,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val singleWalletContentLoaderFactory: SingleWalletContentLoaderFactory,
|
||||
private val singleWalletContentLoaderV2Factory: SingleWalletContentLoaderV2.Factory,
|
||||
private val visaWalletContentLoaderFactory: VisaWalletContentLoaderFactory,
|
||||
) {
|
||||
|
||||
|
|
@ -32,7 +35,11 @@ internal class WalletContentLoaderFactory @Inject constructor(
|
|||
visaWalletContentLoaderFactory.create(userWallet, clickIntents, isRefresh)
|
||||
}
|
||||
userWallet is UserWallet.Cold && !userWallet.isMultiCurrency -> {
|
||||
singleWalletContentLoaderFactory.create(userWallet, clickIntents, isRefresh)
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
singleWalletContentLoaderV2Factory.create(userWallet, isRefresh)
|
||||
} else {
|
||||
singleWalletContentLoaderFactory.create(userWallet, clickIntents, isRefresh)
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
|||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.onramp.GetOnrampTransactionsUseCase
|
||||
import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase
|
||||
import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase
|
||||
|
|
@ -9,10 +10,8 @@ import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
|||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
|
||||
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.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
|
|
@ -36,7 +35,6 @@ internal class SingleWalletContentLoader(
|
|||
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val accountDependencies: AccountDependencies,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> {
|
||||
|
|
@ -55,7 +53,6 @@ internal class SingleWalletContentLoader(
|
|||
clickIntents = clickIntents,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
getCryptoCurrencyActionsUseCase = getCryptoCurrencyActionsUseCase,
|
||||
accountDependencies = accountDependencies,
|
||||
),
|
||||
SingleWalletNotificationsSubscriber(
|
||||
userWallet = userWallet,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
|||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.onramp.GetOnrampTransactionsUseCase
|
||||
import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase
|
||||
import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase
|
||||
|
|
@ -10,10 +11,8 @@ import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
|||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
|
||||
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.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
|
|
@ -21,6 +20,7 @@ import javax.inject.Inject
|
|||
|
||||
@ModelScoped
|
||||
@Suppress("LongParameterList")
|
||||
@Deprecated("Use SingleWalletContentLoaderV2.Factory instead")
|
||||
internal class SingleWalletContentLoaderFactory @Inject constructor(
|
||||
private val stateHolder: WalletStateController,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
|
|
@ -35,14 +35,12 @@ internal class SingleWalletContentLoaderFactory @Inject constructor(
|
|||
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val accountDependencies: AccountDependencies,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader {
|
||||
return SingleWalletContentLoader(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
accountDependencies = accountDependencies,
|
||||
isRefresh = isRefresh,
|
||||
stateHolder = stateHolder,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.account.status.usecase.GetCryptoCurrencyActionsUseCaseV2
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.onramp.GetOnrampTransactionsUseCase
|
||||
import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase
|
||||
import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
|
||||
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.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletContentLoaderV2 @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet.Cold,
|
||||
@Assisted private val isRefresh: Boolean,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val getCryptoCurrencyActionsUseCaseV2: GetCryptoCurrencyActionsUseCaseV2,
|
||||
private val getSingleWalletWarningsFactory: GetSingleWalletWarningsFactory,
|
||||
private val setWalletWithFundsFoundUseCase: SetWalletWithFundsFoundUseCase,
|
||||
private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase,
|
||||
private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase,
|
||||
private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase,
|
||||
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val accountDependencies: AccountDependencies,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> = listOf(
|
||||
PrimaryCurrencySubscriberV2(
|
||||
userWallet = userWallet,
|
||||
singleAccountStatusListSupplier = accountDependencies.singleAccountStatusListSupplier,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
stateController = stateHolder,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
setWalletWithFundsFoundUseCase = setWalletWithFundsFoundUseCase,
|
||||
),
|
||||
SingleWalletButtonsSubscriberV2(
|
||||
userWallet = userWallet,
|
||||
singleAccountStatusListSupplier = accountDependencies.singleAccountStatusListSupplier,
|
||||
stateController = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getCryptoCurrencyActionsUseCaseV2 = getCryptoCurrencyActionsUseCaseV2,
|
||||
),
|
||||
SingleWalletNotificationsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getSingleWalletWarningsFactory = getSingleWalletWarningsFactory,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
),
|
||||
WalletDropDownItemsSubscriber(
|
||||
stateHolder = stateHolder,
|
||||
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
|
||||
clickIntents = clickIntents,
|
||||
),
|
||||
SingleWalletExpressStatusesSubscriberV2(
|
||||
userWallet = userWallet,
|
||||
singleAccountStatusListSupplier = accountDependencies.singleAccountStatusListSupplier,
|
||||
getOnrampTransactionsUseCase = getOnrampTransactionsUseCase,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
onrampRemoveTransactionUseCase = onrampRemoveTransactionUseCase,
|
||||
stateController = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
),
|
||||
TxHistorySubscriberV2(
|
||||
userWallet = userWallet,
|
||||
singleAccountStatusListSupplier = accountDependencies.singleAccountStatusListSupplier,
|
||||
txHistoryItemsCountUseCase = txHistoryItemsCountUseCase,
|
||||
txHistoryItemsUseCase = txHistoryItemsUseCase,
|
||||
isRefresh = isRefresh,
|
||||
stateController = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
),
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet.Cold, isRefresh: Boolean): SingleWalletContentLoaderV2
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
|
||||
/**
|
||||
* Basic implementation of [WalletSubscriber] for single wallet.
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal abstract class BasicSingleWalletSubscriber : BasicWalletSubscriber() {
|
||||
|
||||
/** Account ID for the main crypto portfolio of the user wallet */
|
||||
val accountId: AccountId
|
||||
get() = AccountId.forMainCryptoPortfolio(userWalletId = userWallet.walletId)
|
||||
|
||||
/**
|
||||
* Provides a flow of the primary [CryptoCurrencyStatus] for the associated user wallet.
|
||||
*
|
||||
* @return A [Flow] emitting the primary [CryptoCurrencyStatus] of the wallet, distinct and conflated.
|
||||
*/
|
||||
protected fun getPrimaryCurrencyStatusFlow(): Flow<CryptoCurrencyStatus> {
|
||||
return getMainAccountStatusFlow()
|
||||
.mapNotNull { accountStatus ->
|
||||
accountStatus.flattenCurrencies().firstOrNull()
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.conflate()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
|
||||
/**
|
||||
* Basic implementation of [WalletSubscriber] for wallet.
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal abstract class BasicWalletSubscriber : WalletSubscriber() {
|
||||
|
||||
/** User wallet associated with this subscriber */
|
||||
abstract val userWallet: UserWallet
|
||||
|
||||
/** Supplier to get the account status for the wallet */
|
||||
abstract val singleAccountStatusListSupplier: SingleAccountStatusListSupplier
|
||||
|
||||
/**
|
||||
* Provides a flow of [AccountStatusList] for the associated user wallet.
|
||||
*
|
||||
* @return A [Flow] emitting the [AccountStatusList] of the wallet, distinct and conflated.
|
||||
*/
|
||||
protected fun getAccountStatusListFlow(): Flow<AccountStatusList> {
|
||||
return singleAccountStatusListSupplier(
|
||||
params = SingleAccountStatusListProducer.Params(userWallet.walletId),
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
.conflate()
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a flow of [AccountStatus] for the associated user wallet.
|
||||
*
|
||||
* @return A [Flow] emitting the [AccountStatus] of the wallet, distinct and conflated.
|
||||
*/
|
||||
protected fun getMainAccountStatusFlow(): Flow<AccountStatus> {
|
||||
return getAccountStatusListFlow()
|
||||
.mapNotNull { accountStatusList ->
|
||||
accountStatusList.accountStatuses.find { accountStatus ->
|
||||
when (accountStatus) {
|
||||
is AccountStatus.CryptoPortfolio -> accountStatus.account.isMainAccount
|
||||
}
|
||||
}
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.conflate()
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.*
|
|||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Deprecated("Use PrimaryCurrencySubscriberV2 instead")
|
||||
internal class PrimaryCurrencySubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val stateHolder: WalletStateController,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetPrimaryCurrencyTransformer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal class PrimaryCurrencySubscriberV2(
|
||||
override val userWallet: UserWallet,
|
||||
override val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val stateController: WalletStateController,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val setWalletWithFundsFoundUseCase: SetWalletWithFundsFoundUseCase,
|
||||
) : BasicSingleWalletSubscriber() {
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<*> {
|
||||
return combine(
|
||||
flow = getPrimaryCurrencyStatusFlow(),
|
||||
flow2 = getSelectedAppCurrencyUseCase.invokeOrDefault(),
|
||||
transform = ::Pair,
|
||||
)
|
||||
.onEach { (status, appCurrency) ->
|
||||
updateContent(status, appCurrency)
|
||||
sendAnalyticsEvent(status)
|
||||
checkWalletWithFunds(status)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateContent(status: CryptoCurrencyStatus, appCurrency: AppCurrency) {
|
||||
stateController.update(
|
||||
SetPrimaryCurrencyTransformer(
|
||||
status = status,
|
||||
userWallet = userWallet,
|
||||
appCurrency = appCurrency,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun sendAnalyticsEvent(status: CryptoCurrencyStatus) {
|
||||
val fiatAmount = status.value.fiatAmount
|
||||
val cardBalanceState = when (status.value) {
|
||||
is CryptoCurrencyStatus.Loaded,
|
||||
is CryptoCurrencyStatus.NoAccount,
|
||||
is CryptoCurrencyStatus.NoAmount,
|
||||
-> createCardBalanceState(fiatAmount)
|
||||
is CryptoCurrencyStatus.NoQuote -> AnalyticsParam.CardBalanceState.NoRate
|
||||
is CryptoCurrencyStatus.Unreachable,
|
||||
-> AnalyticsParam.CardBalanceState.BlockchainError
|
||||
is CryptoCurrencyStatus.MissedDerivation,
|
||||
is CryptoCurrencyStatus.Loading,
|
||||
is CryptoCurrencyStatus.Custom,
|
||||
-> null
|
||||
}
|
||||
|
||||
cardBalanceState?.let {
|
||||
// do not send tokens count for single currency wallet
|
||||
analyticsEventHandler.send(
|
||||
event = WalletScreenAnalyticsEvent.Basic.BalanceLoaded(
|
||||
balance = it,
|
||||
tokensCount = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCardBalanceState(fiatAmount: BigDecimal?): AnalyticsParam.CardBalanceState? {
|
||||
return when {
|
||||
fiatAmount == null -> null
|
||||
fiatAmount.isZero() -> AnalyticsParam.CardBalanceState.Empty
|
||||
else -> AnalyticsParam.CardBalanceState.Full
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun checkWalletWithFunds(status: CryptoCurrencyStatus) {
|
||||
if (status.value.amount?.isZero() == false) setWalletWithFundsFoundUseCase()
|
||||
}
|
||||
}
|
||||
|
|
@ -7,20 +7,19 @@ import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
|||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.model.TokenActionsState
|
||||
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.domain.collectLatest
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetCryptoCurrencyActionsTransformer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
@Deprecated("Use SingleWalletButtonsSubscriberV2 instead")
|
||||
internal class SingleWalletButtonsSubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
private val accountDependencies: AccountDependencies,
|
||||
) : WalletSubscriber() {
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<TokenActionsState> {
|
||||
|
|
@ -31,11 +30,10 @@ internal class SingleWalletButtonsSubscriber(
|
|||
}
|
||||
}
|
||||
.onEach { actions ->
|
||||
val portfolioId = when (accountDependencies.accountsFeatureToggles.isFeatureEnabled) {
|
||||
true -> TODO("account") // get main account id for single wallet
|
||||
false -> PortfolioId(userWallet.walletId)
|
||||
}
|
||||
updateContent(actions, portfolioId)
|
||||
updateContent(
|
||||
tokenActionsState = actions,
|
||||
portfolioId = PortfolioId(userWallet.walletId),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.account.status.usecase.GetCryptoCurrencyActionsUseCaseV2
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.tokens.model.TokenActionsState
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetCryptoCurrencyActionsTransformer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
internal class SingleWalletButtonsSubscriberV2(
|
||||
override val userWallet: UserWallet,
|
||||
override val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
private val stateController: WalletStateController,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val getCryptoCurrencyActionsUseCaseV2: GetCryptoCurrencyActionsUseCaseV2,
|
||||
) : BasicSingleWalletSubscriber() {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<TokenActionsState> {
|
||||
return getPrimaryCurrencyStatusFlow()
|
||||
.flatMapLatest {
|
||||
getCryptoCurrencyActionsUseCaseV2(accountId = accountId, currency = it.currency)
|
||||
}
|
||||
.onEach {
|
||||
updateContent(tokenActionsState = it, portfolioId = PortfolioId(userWallet.walletId))
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateContent(tokenActionsState: TokenActionsState, portfolioId: PortfolioId) {
|
||||
stateController.update(
|
||||
SetCryptoCurrencyActionsTransformer(
|
||||
tokenActionsState = tokenActionsState,
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
portfolioId = portfolioId,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.*
|
|||
import timber.log.Timber
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Deprecated("Use SingleWalletExpressStatusesSubscriberV2 instead")
|
||||
internal class SingleWalletExpressStatusesSubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val stateHolder: WalletStateController,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.onramp.GetOnrampTransactionsUseCase
|
||||
import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase
|
||||
import com.tangem.domain.onramp.model.cache.OnrampTransaction
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetExpressStatusesTransformer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletExpressStatusesSubscriberV2(
|
||||
override val userWallet: UserWallet,
|
||||
override val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase,
|
||||
private val stateController: WalletStateController,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : BasicSingleWalletSubscriber() {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<*> {
|
||||
val getOnrampTransactionsFlow = getPrimaryCurrencyStatusFlow().flatMapLatest { currencyStatus ->
|
||||
getOnrampTransactionsUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
cryptoCurrencyId = currencyStatus.currency.id,
|
||||
)
|
||||
.map { currencyStatus to it }
|
||||
}
|
||||
|
||||
return combine(
|
||||
flow = getOnrampTransactionsFlow,
|
||||
flow2 = getSelectedAppCurrencyUseCase.invokeOrDefault(),
|
||||
transform = ::toTriple,
|
||||
)
|
||||
.onEach { (status, maybeTransaction, appCurrency) ->
|
||||
maybeTransaction.fold(
|
||||
ifRight = { onrampTxs ->
|
||||
onrampTxs.clearHiddenTerminal()
|
||||
stateController.update(
|
||||
SetExpressStatusesTransformer(
|
||||
userWalletId = userWallet.walletId,
|
||||
onrampTxs = onrampTxs,
|
||||
clickIntents = clickIntents,
|
||||
cryptoCurrencyStatus = status,
|
||||
appCurrency = appCurrency,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
),
|
||||
)
|
||||
},
|
||||
ifLeft = {
|
||||
stateController.update(
|
||||
SetExpressStatusesTransformer(
|
||||
userWalletId = userWallet.walletId,
|
||||
onrampTxs = listOf(),
|
||||
clickIntents = clickIntents,
|
||||
cryptoCurrencyStatus = status,
|
||||
appCurrency = appCurrency,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <A, B, C> toTriple(firstPair: Pair<A, B>, second: C): Triple<A, B, C> {
|
||||
return Triple(firstPair.first, firstPair.second, second)
|
||||
}
|
||||
|
||||
private suspend fun List<OnrampTransaction>.clearHiddenTerminal() {
|
||||
this
|
||||
.filter { it.status.isHidden && it.status.isTerminal }
|
||||
.forEach { onrampRemoveTransactionUseCase(txId = it.txId) }
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ typealias MaybeTxHistoryCount = Either<TxHistoryStateError, Int>
|
|||
typealias MaybeTxHistoryItems = Either<TxHistoryListError, Flow<PagingData<TxInfo>>>
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Deprecated("Use TxHistorySubscriberV2 instead")
|
||||
internal class TxHistorySubscriber(
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val isRefresh: Boolean,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.cachedIn
|
||||
import androidx.paging.map
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.TxInfo
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTxHistoryCountErrorTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTxHistoryCountTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTxHistoryItemsErrorTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTxHistoryItemsTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TxHistoryItemStateConverter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class TxHistorySubscriberV2(
|
||||
override val userWallet: UserWallet.Cold,
|
||||
override val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase,
|
||||
private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase,
|
||||
private val isRefresh: Boolean,
|
||||
private val stateController: WalletStateController,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
) : BasicSingleWalletSubscriber() {
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<PagingData<TxInfo>> {
|
||||
return flow {
|
||||
getPrimaryCurrencyStatusFlow().collectLatest { status ->
|
||||
val maybeTxHistoryItemCount = txHistoryItemsCountUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = status.currency,
|
||||
)
|
||||
|
||||
setLoadingTxHistoryState(maybeTxHistoryItemCount, status)
|
||||
|
||||
maybeTxHistoryItemCount.onRight {
|
||||
val maybeTxHistoryItems = txHistoryItemsUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = status.currency,
|
||||
refresh = isRefresh,
|
||||
).map { it.cachedIn(coroutineScope) }
|
||||
|
||||
setLoadedTxHistoryState(maybeTxHistoryItems)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setLoadingTxHistoryState(maybeTxHistoryItemCount: MaybeTxHistoryCount, status: CryptoCurrencyStatus) {
|
||||
stateController.update(
|
||||
maybeTxHistoryItemCount.fold(
|
||||
ifLeft = {
|
||||
SetTxHistoryCountErrorTransformer(
|
||||
userWallet = userWallet,
|
||||
error = it,
|
||||
pendingTransactions = status.value.pendingTransactions,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
},
|
||||
ifRight = {
|
||||
SetTxHistoryCountTransformer(
|
||||
userWalletId = userWallet.walletId,
|
||||
transactionsCount = it,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun setLoadedTxHistoryState(maybeTxHistoryItems: MaybeTxHistoryItems) {
|
||||
stateController.update(
|
||||
maybeTxHistoryItems.fold(
|
||||
ifLeft = {
|
||||
SetTxHistoryItemsErrorTransformer(
|
||||
userWalletId = userWallet.walletId,
|
||||
error = it,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
},
|
||||
ifRight = { itemsFlow ->
|
||||
val blockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain()
|
||||
val itemConverter = TxHistoryItemStateConverter(
|
||||
symbol = blockchain.currency,
|
||||
decimals = blockchain.decimals(),
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
SetTxHistoryItemsTransformer(
|
||||
userWallet = userWallet,
|
||||
flow = itemsFlow.map { items ->
|
||||
items.map(itemConverter::convert)
|
||||
},
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,9 @@ import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetWalletCardDropDownItemsTransformer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
internal class WalletDropDownItemsSubscriber(
|
||||
private val stateHolder: WalletStateController,
|
||||
|
|
@ -13,18 +15,15 @@ internal class WalletDropDownItemsSubscriber(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
) : WalletSubscriber() {
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<*> {
|
||||
return flow<Any> {
|
||||
shouldSaveUserWalletsUseCase.invoke()
|
||||
.distinctUntilChanged()
|
||||
.onEach {
|
||||
stateHolder.update(
|
||||
SetWalletCardDropDownItemsTransformer(
|
||||
dropdownEnabled = it,
|
||||
clickIntents = clickIntents,
|
||||
),
|
||||
)
|
||||
}
|
||||
.launchIn(coroutineScope)
|
||||
}
|
||||
return shouldSaveUserWalletsUseCase.invoke()
|
||||
.distinctUntilChanged()
|
||||
.onEach {
|
||||
stateHolder.update(
|
||||
SetWalletCardDropDownItemsTransformer(
|
||||
dropdownEnabled = it,
|
||||
clickIntents = clickIntents,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue