Updated on 2026-08-14
This commit is contained in:
parent
78fafc0ee2
commit
74fa237c0d
8 changed files with 136 additions and 23 deletions
|
|
@ -7,6 +7,7 @@ import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
|||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -67,6 +68,7 @@ internal object ManageTokensDomainModule {
|
|||
networksRepository: NetworksRepository,
|
||||
derivationsRepository: DerivationsRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
): SaveManagedTokensUseCase {
|
||||
return SaveManagedTokensUseCase(
|
||||
customTokensRepository = customTokensRepository,
|
||||
|
|
@ -75,6 +77,7 @@ internal object ManageTokensDomainModule {
|
|||
networksRepository = networksRepository,
|
||||
derivationsRepository = derivationsRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
|||
import com.tangem.domain.card.repository.DerivationsRepository
|
||||
import com.tangem.domain.markets.*
|
||||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
|
|
@ -57,12 +58,16 @@ object MarketsDomainModule {
|
|||
marketsTokenRepository: MarketsTokenRepository,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
): SaveMarketTokensUseCase {
|
||||
return SaveMarketTokensUseCase(
|
||||
derivationsRepository = derivationsRepository,
|
||||
marketsTokenRepository = marketsTokenRepository,
|
||||
currenciesRepository = currenciesRepository,
|
||||
networksRepository = networksRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,10 +27,14 @@ internal object TokensDomainModule {
|
|||
fun provideAddCryptoCurrenciesUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
): AddCryptoCurrenciesUseCase {
|
||||
return AddCryptoCurrenciesUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
networksRepository = networksRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,11 @@ import com.tangem.domain.tokens.model.CryptoCurrency
|
|||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
class SaveManagedTokensUseCase(
|
||||
private val customTokensRepository: CustomTokensRepository,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
|
|
@ -20,6 +22,7 @@ class SaveManagedTokensUseCase(
|
|||
private val networksRepository: NetworksRepository,
|
||||
private val derivationsRepository: DerivationsRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
|
|
@ -54,6 +57,8 @@ class SaveManagedTokensUseCase(
|
|||
)
|
||||
|
||||
refreshUpdatedYieldBalances(userWalletId, existingCurrencies)
|
||||
|
||||
refreshUpdatedQuotes(addingCurrencies)
|
||||
}
|
||||
|
||||
private suspend fun removeCurrenciesFromWalletManager(
|
||||
|
|
@ -105,6 +110,13 @@ class SaveManagedTokensUseCase(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedQuotes(addedCurrencies: List<CryptoCurrency>) {
|
||||
quotesRepository.fetchQuotes(
|
||||
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the [existingCurrencies] list contains a coin that corresponds
|
||||
* to the given [network].
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ dependencies {
|
|||
api(projects.domain.models)
|
||||
api(projects.domain.legacy)
|
||||
api(projects.domain.wallets)
|
||||
api(projects.domain.staking)
|
||||
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.tokens)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@ package com.tangem.domain.markets
|
|||
import arrow.core.Either
|
||||
import com.tangem.domain.card.repository.DerivationsRepository
|
||||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
/**
|
||||
|
|
@ -23,6 +25,8 @@ class SaveMarketTokensUseCase(
|
|||
private val marketsTokenRepository: MarketsTokenRepository,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
|
|
@ -60,11 +64,37 @@ class SaveMarketTokensUseCase(
|
|||
|
||||
currenciesRepository.addCurrencies(userWalletId = userWalletId, currencies = addedCurrencies)
|
||||
|
||||
networksRepository.getNetworkStatusesSync(
|
||||
userWalletId = userWalletId,
|
||||
networks = addedCurrencies.map(CryptoCurrency::network).toSet(),
|
||||
refresh = true,
|
||||
)
|
||||
refreshUpdatedNetworks(userWalletId, addedCurrencies)
|
||||
|
||||
refreshUpdatedYieldBalances(userWalletId, addedCurrencies)
|
||||
|
||||
refreshUpdatedQuotes(addedCurrencies)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedNetworks(userWalletId: UserWalletId, addedCurrencies: List<CryptoCurrency>) {
|
||||
networksRepository.getNetworkStatusesSync(
|
||||
userWalletId = userWalletId,
|
||||
networks = addedCurrencies.map(CryptoCurrency::network).toSet(),
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedYieldBalances(
|
||||
userWalletId: UserWalletId,
|
||||
existingCurrencies: List<CryptoCurrency>,
|
||||
) {
|
||||
stakingRepository.fetchMultiYieldBalance(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = existingCurrencies,
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedQuotes(addedCurrencies: List<CryptoCurrency>) {
|
||||
quotesRepository.fetchQuotes(
|
||||
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,10 +5,12 @@ import arrow.core.raise.Raise
|
|||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.toNonEmptyListOrNull
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
/**
|
||||
|
|
@ -21,6 +23,8 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
class AddCryptoCurrenciesUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val stakingRepository: StakingRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
) {
|
||||
|
||||
/**
|
||||
|
|
@ -105,6 +109,8 @@ class AddCryptoCurrenciesUseCase(
|
|||
val tokenToAdd = createTokenCurrency(userWalletId, contractAddress, networkId)
|
||||
addCurrencies(userWalletId, listOf(tokenToAdd))
|
||||
refreshUpdatedNetworks(userWalletId, listOf(tokenToAdd), existingCurrencies)
|
||||
refreshUpdatedYieldBalances(userWalletId, existingCurrencies)
|
||||
refreshUpdatedQuotes(existingCurrencies)
|
||||
tokenToAdd
|
||||
}
|
||||
|
||||
|
|
@ -139,6 +145,24 @@ class AddCryptoCurrenciesUseCase(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedYieldBalances(
|
||||
userWalletId: UserWalletId,
|
||||
existingCurrencies: List<CryptoCurrency>,
|
||||
) {
|
||||
stakingRepository.fetchMultiYieldBalance(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencies = existingCurrencies,
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun refreshUpdatedQuotes(addedCurrencies: List<CryptoCurrency>) {
|
||||
quotesRepository.fetchQuotes(
|
||||
currenciesIds = addedCurrencies.mapNotNullTo(hashSetOf()) { it.id.rawCurrencyId },
|
||||
refresh = true,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun Raise<Throwable>.createTokenCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
contractAddress: String,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.domain.core.lce.LceFlow
|
|||
import com.tangem.domain.core.lce.lce
|
||||
import com.tangem.domain.core.lce.lceFlow
|
||||
import com.tangem.domain.core.utils.EitherFlow
|
||||
import com.tangem.domain.core.utils.lceContent
|
||||
import com.tangem.domain.core.utils.lceError
|
||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||
import com.tangem.domain.staking.model.stakekit.YieldBalanceList
|
||||
|
|
@ -44,30 +45,49 @@ class CachedCurrenciesStatusesOperations(
|
|||
userWalletId: UserWalletId,
|
||||
currenciesFlow: EitherFlow<TokenListError, List<CryptoCurrency>>,
|
||||
): LceFlow<TokenListError, List<CryptoCurrencyStatus>> = lceFlow {
|
||||
currenciesFlow.flatMapLatest { maybeCurrencies ->
|
||||
val isUpdating = MutableStateFlow(value = true)
|
||||
val prevStatuses = MutableStateFlow(value = emptyList<CryptoCurrencyStatus>())
|
||||
|
||||
val nonEmptyCurrencies = maybeCurrencies
|
||||
val isUpdating = MutableStateFlow(value = true)
|
||||
val isFetchingStarted = MutableStateFlow(value = false)
|
||||
|
||||
val nonEmptyCurrencies = currenciesFlow.mapNotNull { it.getOrNull() }.firstOrNull()?.toNonEmptyListOrNull()
|
||||
|
||||
if (nonEmptyCurrencies != null) {
|
||||
launch {
|
||||
isFetchingStarted.value = true
|
||||
|
||||
val (networks, currenciesIds) = getIds(nonEmptyCurrencies)
|
||||
fetchComponents(userWalletId, networks, currenciesIds, nonEmptyCurrencies)
|
||||
}
|
||||
.invokeOnCompletion { isUpdating.value = false }
|
||||
}
|
||||
|
||||
currenciesFlow.flatMapLatest { maybeCurrencies ->
|
||||
val currencies = maybeCurrencies
|
||||
.getOrElse { return@flatMapLatest flowOf(it.lceError()) }
|
||||
.toNonEmptyListOrNull()
|
||||
|
||||
if (nonEmptyCurrencies.isNullOrEmpty()) {
|
||||
if (currencies.isNullOrEmpty()) {
|
||||
prevStatuses.value = emptyList()
|
||||
return@flatMapLatest flowOf(TokenListError.EmptyTokens.lceError())
|
||||
}
|
||||
|
||||
// This is only 'true' when the flow here is empty, such as during initial loading
|
||||
if (isLoading.get()) {
|
||||
val loadingCurrencies = createCurrenciesStatuses(
|
||||
currencies = nonEmptyCurrencies,
|
||||
currencies = currencies,
|
||||
maybeNetworkStatuses = null,
|
||||
maybeQuotes = null,
|
||||
maybeYieldBalances = null,
|
||||
isUpdating = true,
|
||||
)
|
||||
|
||||
loadingCurrencies.getOrNull()?.let { prevStatuses.value = it }
|
||||
|
||||
send(loadingCurrencies)
|
||||
}
|
||||
|
||||
val (networks, currenciesIds) = getIds(nonEmptyCurrencies)
|
||||
val (networks, currenciesIds) = getIds(currencies)
|
||||
|
||||
fun createCurrenciesStatuses(
|
||||
maybeQuotes: Either<TokenListError, Set<Quote>>?,
|
||||
|
|
@ -75,26 +95,46 @@ class CachedCurrenciesStatusesOperations(
|
|||
maybeYieldBalances: Either<TokenListError, YieldBalanceList>?,
|
||||
isUpdating: Boolean,
|
||||
) = createCurrenciesStatuses(
|
||||
currencies = nonEmptyCurrencies,
|
||||
currencies = currencies,
|
||||
maybeQuotes = maybeQuotes,
|
||||
maybeNetworkStatuses = maybeNetworkStatuses,
|
||||
maybeYieldBalances = maybeYieldBalances,
|
||||
isUpdating = isUpdating,
|
||||
)
|
||||
|
||||
launch { fetchComponents(userWalletId, networks, currenciesIds, nonEmptyCurrencies) }
|
||||
.invokeOnCompletion { isUpdating.value = false }
|
||||
// removing token
|
||||
val prevStatusesValue = prevStatuses.value
|
||||
if (prevStatusesValue.size - currencies.size == 1) {
|
||||
val removed = prevStatusesValue.map { it.currency } - currencies
|
||||
|
||||
return@flatMapLatest flowOf(
|
||||
prevStatusesValue.filter { it.currency !in removed }.lceContent(),
|
||||
)
|
||||
}
|
||||
|
||||
if (!isFetchingStarted.value) {
|
||||
launch {
|
||||
isFetchingStarted.value = true
|
||||
|
||||
fetchComponents(userWalletId, networks, currenciesIds, currencies)
|
||||
}
|
||||
.invokeOnCompletion { isUpdating.value = false }
|
||||
}
|
||||
|
||||
combine(
|
||||
flow = getQuotes(currenciesIds),
|
||||
flow2 = getNetworksStatuses(userWalletId, networks),
|
||||
flow3 = getYieldBalances(userWalletId, nonEmptyCurrencies),
|
||||
flow3 = getYieldBalances(userWalletId, currencies),
|
||||
flow4 = isUpdating,
|
||||
transform = ::createCurrenciesStatuses,
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
.onEach(::send)
|
||||
.onEach { statusesLce ->
|
||||
statusesLce.getOrNull()?.let { prevStatuses.value = it }
|
||||
|
||||
send(statusesLce)
|
||||
}
|
||||
.launchIn(scope = this)
|
||||
}
|
||||
|
||||
|
|
@ -112,13 +152,7 @@ class CachedCurrenciesStatusesOperations(
|
|||
val rawCurrenciesIds = currenciesIds.mapNotNullTo(mutableSetOf()) { it.rawCurrencyId }
|
||||
quotesRepository.fetchQuotes(rawCurrenciesIds)
|
||||
},
|
||||
async {
|
||||
if (currencies.size == 1) {
|
||||
stakingRepository.fetchSingleYieldBalance(userWalletId, currencies.first())
|
||||
} else {
|
||||
stakingRepository.fetchMultiYieldBalance(userWalletId, currencies)
|
||||
}
|
||||
},
|
||||
async { stakingRepository.fetchMultiYieldBalance(userWalletId, currencies) },
|
||||
)
|
||||
}
|
||||
.map { }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue