From 3519edfbfd670da9c85ab706d1672c6420692aaf Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 29 May 2024 15:51:45 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/di/domain/TokensDomainModule.kt | 14 ++++ .../repository/DefaultCurrenciesRepository.kt | 17 ++++ .../tokens/GetWalletTotalBalanceUseCase.kt | 82 +++++++++++++++++++ .../CurrenciesStatusesLceOperations.kt | 28 ++++++- .../tokens/repository/CurrenciesRepository.kt | 11 +++ .../repository/MockCurrenciesRepository.kt | 4 + 6 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetWalletTotalBalanceUseCase.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index 5795acae01..40ba3c5084 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -356,4 +356,18 @@ internal object TokensDomainModule { networksRepository = networksRepository, ) } + + @Provides + @Singleton + fun provideGetWalletTotalBalanceUseCase( + currenciesRepository: CurrenciesRepository, + quotesRepository: QuotesRepository, + networksRepository: NetworksRepository, + ): GetWalletTotalBalanceUseCase { + return GetWalletTotalBalanceUseCase( + currenciesRepository = currenciesRepository, + quotesRepository = quotesRepository, + networksRepository = networksRepository, + ) + } } \ No newline at end of file diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt index 91fbcf1881..cf29c3b4a3 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt @@ -173,6 +173,23 @@ internal class DefaultCurrenciesRepository( } } + override fun getWalletCurrenciesUpdates(userWalletId: UserWalletId): LceFlow> { + return lceFlow { + val userWallet = catch({ getUserWallet(userWalletId) }) { + raise(it) + } + + if (userWallet.isMultiCurrency) { + getMultiCurrencyWalletCurrenciesUpdatesLce(userWalletId).collect(::send) + } else { + val currency = catch({ getSingleCurrencyWalletPrimaryCurrency(userWalletId) }) { + raise(it) + } + send(listOf(currency)) + } + } + } + override suspend fun getSingleCurrencyWalletPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency { return withContext(dispatchers.io) { val userWallet = getUserWallet(userWalletId) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetWalletTotalBalanceUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetWalletTotalBalanceUseCase.kt new file mode 100644 index 0000000000..36da5cae5c --- /dev/null +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetWalletTotalBalanceUseCase.kt @@ -0,0 +1,82 @@ +package com.tangem.domain.tokens + +import arrow.core.raise.ensureNotNull +import arrow.core.toNonEmptyListOrNull +import com.tangem.domain.core.lce.Lce +import com.tangem.domain.core.lce.LceFlow +import com.tangem.domain.core.lce.lce +import com.tangem.domain.core.utils.lceLoading +import com.tangem.domain.tokens.error.TokenListError +import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.tokens.model.TotalFiatBalance +import com.tangem.domain.tokens.operations.CurrenciesStatusesLceOperations +import com.tangem.domain.tokens.operations.TokenListFiatBalanceOperations +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.flow.combine +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.transform + +class GetWalletTotalBalanceUseCase( + private val currenciesRepository: CurrenciesRepository, + private val quotesRepository: QuotesRepository, + private val networksRepository: NetworksRepository, +) { + + suspend operator fun invoke( + userWallestIds: Collection, + ): LceFlow> { + val flows = userWallestIds.distinct() + .map { userWalletId -> + invoke(userWalletId).map { maybeBalance -> + userWalletId to maybeBalance + } + } + + return combine(flows) { balances -> + lce { + balances.associate { (userWalletId, maybeBalance) -> + userWalletId to maybeBalance.bind() + } + } + } + } + + suspend operator fun invoke(userWalletId: UserWalletId): LceFlow { + val currenciesStatuses = getStatuses(userWalletId) + + return currenciesStatuses.transform { maybeStatuses -> + val balance = createBalance(maybeStatuses) + + emit(balance) + } + } + + private fun createBalance( + maybeStatuses: Lce>, + ): Lce = lce { + val statuses = maybeStatuses.bind() + + val operations = TokenListFiatBalanceOperations( + currencies = ensureNotNull(statuses.toNonEmptyListOrNull()) { lceLoading() }, + isAnyTokenLoading = false, + ) + + operations.calculateFiatBalance() + } + + private fun getStatuses(userWalletId: UserWalletId): LceFlow> { + val operations = CurrenciesStatusesLceOperations( + currenciesRepository = currenciesRepository, + quotesRepository = quotesRepository, + networksRepository = networksRepository, + ) + + return operations.getCurrenciesStatuses( + userWalletId = userWalletId, + isSingleCurrencyWalletsAllowed = true, + ) + } +} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesLceOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesLceOperations.kt index c358cd158e..6736ffab28 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesLceOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesLceOperations.kt @@ -21,8 +21,25 @@ internal class CurrenciesStatusesLceOperations( private val networksRepository: NetworksRepository, ) { - fun getCurrenciesStatuses(userWalletId: UserWalletId): LceFlow> { - return getMultiCurrencyWalletCurrencies(userWalletId).transform transform@{ maybeCurrencies -> + fun getCurrenciesStatuses( + userWalletId: UserWalletId, + isSingleCurrencyWalletsAllowed: Boolean = false, + ): LceFlow> { + return transformToCurrenciesStatuses( + userWalletId = userWalletId, + flow = if (isSingleCurrencyWalletsAllowed) { + getWalletCurrenies(userWalletId) + } else { + getMultiCurrencyWalletCurrencies(userWalletId) + }, + ) + } + + private fun transformToCurrenciesStatuses( + userWalletId: UserWalletId, + flow: LceFlow>, + ): LceFlow> { + return flow.transform transform@{ maybeCurrencies -> val nonEmptyCurrencies = maybeCurrencies.fold( ifLoading = { maybeContent -> emit(createLoadingCurrenciesStatuses(maybeContent)) @@ -74,6 +91,13 @@ internal class CurrenciesStatusesLceOperations( return statuses } + private fun getWalletCurrenies(userWalletId: UserWalletId): LceFlow> { + return currenciesRepository.getWalletCurrenciesUpdates(userWalletId) + .map { maybeCurrencies -> + maybeCurrencies.mapError { TokenListError.DataError(it) } + } + } + private fun getMultiCurrencyWalletCurrencies( userWalletId: UserWalletId, ): LceFlow> { diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt index e21dfac83c..5bdf7b4067 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt @@ -62,6 +62,17 @@ interface CurrenciesRepository { */ suspend fun removeCurrencies(userWalletId: UserWalletId, currencies: List) + /** + * Retrieves the list of cryptocurrencies within a user wallet. + * + * This method returns a list of cryptocurrencies associated with the user wallet regardless of whether + * it is a multi-currency or single-currency wallet. + * + * @param userWalletId The unique identifier of the user wallet. + * @return A list of [CryptoCurrency]. + */ + fun getWalletCurrenciesUpdates(userWalletId: UserWalletId): LceFlow> + /** * Retrieves the primary cryptocurrency for a specific single-currency user wallet. * diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockCurrenciesRepository.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockCurrenciesRepository.kt index 30d41cb47e..d4d616d88a 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockCurrenciesRepository.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockCurrenciesRepository.kt @@ -54,6 +54,10 @@ internal class MockCurrenciesRepository( override suspend fun removeCurrencies(userWalletId: UserWalletId, currencies: List) = Unit + override fun getWalletCurrenciesUpdates(userWalletId: UserWalletId): LceFlow> { + return emptyFlow() + } + override suspend fun getMultiCurrencyWalletCurrenciesSync( userWalletId: UserWalletId, refresh: Boolean,