Updated on 2026-08-14
This commit is contained in:
parent
2176c243e0
commit
2ad2edd6c8
3 changed files with 123 additions and 41 deletions
|
|
@ -122,6 +122,16 @@ internal object TokensDomainModule {
|
|||
return FetchCurrencyStatusUseCase(currenciesRepository, networksRepository, quotesRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideFetchCardTokenListUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
): FetchCardTokenListUseCase {
|
||||
return FetchCardTokenListUseCase(currenciesRepository, networksRepository, quotesRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetCryptoCurrencyUseCase(currenciesRepository: CurrenciesRepository): GetCryptoCurrencyUseCase {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
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
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
|
||||
class FetchCardTokenListUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId, refresh: Boolean = false): Either<TokenListError, Unit> {
|
||||
return either {
|
||||
val currencies = fetchCurrencies(userWalletId = userWalletId)
|
||||
|
||||
coroutineScope {
|
||||
val fetchStatuses = async {
|
||||
fetchNetworksStatuses(
|
||||
userWalletId = userWalletId,
|
||||
networks = currencies.mapTo(destination = hashSetOf(), transform = CryptoCurrency::network),
|
||||
refresh = refresh,
|
||||
)
|
||||
}
|
||||
val fetchQuotes = async {
|
||||
fetchQuotes(
|
||||
currenciesIds = currencies.mapTo(destination = hashSetOf(), transform = CryptoCurrency::id),
|
||||
refresh = refresh,
|
||||
)
|
||||
}
|
||||
|
||||
awaitAll(fetchStatuses, fetchQuotes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun Raise<TokenListError>.fetchCurrencies(userWalletId: UserWalletId): List<CryptoCurrency> {
|
||||
return catch(
|
||||
block = { currenciesRepository.getSingleCurrencyWalletWithCardCurrencies(userWalletId = userWalletId) },
|
||||
catch = { raise(TokenListError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun Raise<TokenListError>.fetchNetworksStatuses(
|
||||
userWalletId: UserWalletId,
|
||||
networks: Set<Network>,
|
||||
refresh: Boolean,
|
||||
) {
|
||||
catch(
|
||||
block = { networksRepository.getNetworkStatusesSync(userWalletId, networks, refresh) },
|
||||
catch = { raise(TokenListError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun fetchQuotes(currenciesIds: Set<CryptoCurrency.ID>, refresh: Boolean) {
|
||||
catch(
|
||||
block = { quotesRepository.getQuotesSync(currenciesIds, refresh) },
|
||||
catch = { /* Ignore error */ },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -97,6 +97,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
private val getTokenListUseCase: GetTokenListUseCase,
|
||||
private val getCardTokensListUseCase: GetCardTokensListUseCase,
|
||||
private val fetchTokenListUseCase: FetchTokenListUseCase,
|
||||
private val fetchCardTokenListUseCase: FetchCardTokenListUseCase,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
private val getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase,
|
||||
|
|
@ -544,6 +545,24 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun refreshMultiCurrencyContent(walletIndex: Int) {
|
||||
uiState = stateFactory.getRefreshingState()
|
||||
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
val wallet = getWallet(walletIndex)
|
||||
|
||||
val maybeFetchResult = if (isSingleWalletWithTokens(wallet)) {
|
||||
fetchCardTokenListUseCase(userWalletId = wallet.walletId, refresh = true)
|
||||
} else {
|
||||
fetchTokenListUseCase(userWalletId = wallet.walletId, refresh = true)
|
||||
}
|
||||
|
||||
maybeFetchResult.onLeft { uiState = stateFactory.getStateByTokenListError(it) }
|
||||
|
||||
uiState = stateFactory.getRefreshedState()
|
||||
}.saveIn(refreshContentJobHolder)
|
||||
}
|
||||
|
||||
override fun onOrganizeTokensClick() {
|
||||
analyticsEventsHandler.send(PortfolioEvent.OrganizeTokens)
|
||||
|
||||
|
|
@ -702,6 +721,27 @@ internal class WalletViewModel @Inject constructor(
|
|||
refreshSingleCurrencyContent(selectedWalletIndex)
|
||||
}
|
||||
|
||||
private fun refreshSingleCurrencyContent(walletIndex: Int) {
|
||||
uiState = stateFactory.getRefreshingState()
|
||||
val wallet = getWallet(walletIndex)
|
||||
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
val result = fetchCurrencyStatusUseCase(wallet.walletId, refresh = true)
|
||||
|
||||
uiState = stateFactory.getRefreshedState()
|
||||
uiState = result.fold(stateFactory::getStateByCurrencyStatusError) { uiState }
|
||||
|
||||
singleWalletCryptoCurrencyStatus?.let {
|
||||
val singleCurrencyState = uiState as WalletSingleCurrencyState
|
||||
if (singleCurrencyState.txHistoryState !is TxHistoryState.Content) {
|
||||
// show loading indicator while refreshing in non content state
|
||||
uiState = stateFactory.getLoadingTxHistoryState(1.right())
|
||||
}
|
||||
updateTxHistory(wallet.walletId, it.currency, refresh = true)
|
||||
}
|
||||
}.saveIn(refreshContentJobHolder)
|
||||
}
|
||||
|
||||
override fun onExploreClick() {
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val wallet = getWallet(
|
||||
|
|
@ -924,9 +964,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
uiState = stateFactory.getLockedState()
|
||||
}
|
||||
wallet.isMultiCurrency -> getMultiCurrencyContent(wallet, index)
|
||||
isSingleWalletWithTokens(wallet) -> {
|
||||
getSingleCurrencyWithTokenContent(index)
|
||||
}
|
||||
isSingleWalletWithTokens(wallet) -> getSingleCurrencyWithTokenContent(index)
|
||||
!wallet.isMultiCurrency -> getSingleCurrencyContent(index)
|
||||
}
|
||||
}
|
||||
|
|
@ -1137,44 +1175,6 @@ internal class WalletViewModel @Inject constructor(
|
|||
.saveIn(notificationsJobHolder)
|
||||
}
|
||||
|
||||
private fun refreshMultiCurrencyContent(walletIndex: Int) {
|
||||
uiState = stateFactory.getRefreshingState()
|
||||
val wallet = getWallet(walletIndex)
|
||||
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
if (isSingleWalletWithTokens(wallet)) {
|
||||
// TODO add refresh for nodl cards ([REDACTED_JIRA])
|
||||
delay(timeMillis = 1000)
|
||||
} else {
|
||||
val result = fetchTokenListUseCase(wallet.walletId, refresh = true)
|
||||
uiState = result.fold(stateFactory::getStateByTokenListError) { uiState }
|
||||
}
|
||||
|
||||
uiState = stateFactory.getRefreshedState()
|
||||
}.saveIn(refreshContentJobHolder)
|
||||
}
|
||||
|
||||
private fun refreshSingleCurrencyContent(walletIndex: Int) {
|
||||
uiState = stateFactory.getRefreshingState()
|
||||
val wallet = getWallet(walletIndex)
|
||||
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val result = fetchCurrencyStatusUseCase(wallet.walletId, refresh = true)
|
||||
|
||||
uiState = stateFactory.getRefreshedState()
|
||||
uiState = result.fold(stateFactory::getStateByCurrencyStatusError) { uiState }
|
||||
|
||||
singleWalletCryptoCurrencyStatus?.let {
|
||||
val singleCurrencyState = uiState as WalletSingleCurrencyState
|
||||
if (singleCurrencyState.txHistoryState !is TxHistoryState.Content) {
|
||||
// show loading indicator while refreshing in non content state
|
||||
uiState = stateFactory.getLoadingTxHistoryState(1.right())
|
||||
}
|
||||
updateTxHistory(wallet.walletId, it.currency, refresh = true)
|
||||
}
|
||||
}.saveIn(refreshContentJobHolder)
|
||||
}
|
||||
|
||||
private fun createSelectedAppCurrencyFlow(): StateFlow<AppCurrency> {
|
||||
return getSelectedAppCurrencyUseCase()
|
||||
.map { maybeAppCurrency ->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue