diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt index 32256ffa87..ce11ee65f0 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt @@ -18,6 +18,7 @@ import com.tangem.domain.tokens.GetNetworkCoinStatusUseCase import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason import com.tangem.domain.tokens.repository.CurrenciesRepository +import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId import com.tangem.features.onramp.OnrampFeatureToggles import com.tangem.utils.Provider @@ -55,7 +56,7 @@ internal class DefaultRampManager( } override suspend fun availableForSell( - userWalletId: UserWalletId, + userWallet: UserWallet, status: CryptoCurrencyStatus, ): Either { return either { @@ -68,7 +69,7 @@ internal class DefaultRampManager( catch = { raise(ScenarioUnavailabilityReason.NotSupportedBySellService(status.currency.name)) }, ) - val reason = getSendUnavailabilityReason(userWalletId, status) + val reason = getSendUnavailabilityReason(userWallet = userWallet, cryptoCurrencyStatus = status) ensure(condition = reason is ScenarioUnavailabilityReason.None) { when (reason) { @@ -205,14 +206,13 @@ internal class DefaultRampManager( } private suspend fun getSendUnavailabilityReason( - userWalletId: UserWalletId, + userWallet: UserWallet, cryptoCurrencyStatus: CryptoCurrencyStatus, ): ScenarioUnavailabilityReason { val coinStatus = getNetworkCoinStatusUseCase.invokeSync( - userWalletId = userWalletId, + userWallet = userWallet, networkId = cryptoCurrencyStatus.currency.network.id, derivationPath = cryptoCurrencyStatus.currency.network.derivationPath, - isSingleWalletWithTokens = false, ).getOrNull() return when { diff --git a/data/networks/src/main/java/com/tangem/data/networks/fetcher/CommonNetworkStatusFetcher.kt b/data/networks/src/main/java/com/tangem/data/networks/fetcher/CommonNetworkStatusFetcher.kt index deb556fc61..59ee027076 100644 --- a/data/networks/src/main/java/com/tangem/data/networks/fetcher/CommonNetworkStatusFetcher.kt +++ b/data/networks/src/main/java/com/tangem/data/networks/fetcher/CommonNetworkStatusFetcher.kt @@ -14,6 +14,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject +import javax.inject.Singleton /** * Common implementation of network status fetcher @@ -24,6 +25,7 @@ import javax.inject.Inject * [REDACTED_AUTHOR] */ +@Singleton internal class CommonNetworkStatusFetcher @Inject constructor( private val walletManagersFacade: WalletManagersFacade, private val networksStatusesStore: NetworksStatusesStore, diff --git a/domain/legacy/src/main/java/com/tangem/domain/exchange/RampStateManager.kt b/domain/legacy/src/main/java/com/tangem/domain/exchange/RampStateManager.kt index 0f10ddbc84..ece1e97c5b 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/exchange/RampStateManager.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/exchange/RampStateManager.kt @@ -6,6 +6,7 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason +import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.flow.Flow @@ -23,11 +24,11 @@ interface RampStateManager { /** * Check if [CryptoCurrency] is available for sell * - * @param userWalletId id of multi-currency wallet - * @param status crypto currency status + * @param userWallet user wallet + * @param status crypto currency status */ suspend fun availableForSell( - userWalletId: UserWalletId, + userWallet: UserWallet, status: CryptoCurrencyStatus, ): Either diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt index 5a6a9fa889..8fea6820d1 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/FetchCurrencyStatusUseCase.kt @@ -4,6 +4,7 @@ import arrow.core.Either import arrow.core.raise.Raise import arrow.core.raise.catch import arrow.core.raise.either +import arrow.core.right import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.domain.networks.single.SingleNetworkStatusFetcher @@ -51,17 +52,18 @@ class FetchCurrencyStatusUseCase( return either { val currency = getCurrency(userWalletId, id) - coroutineScope { + return@either coroutineScope { val fetchStatus = async { - fetchNetworkStatus(userWalletId, currency.network) - } - val fetchQuote = async { - fetchQuote(currency.id) + fetchNetworkStatus(userWalletId = userWalletId, network = currency.network) } + + val fetchQuote = async { fetchQuote(currencyId = currency.id) } + val fetchStakingBalance = async { - fetchStakingBalance(userWalletId, currency, refresh) + fetchStakingBalance(userWalletId = userWalletId, cryptoCurrency = currency, refresh = refresh) } - awaitAll(fetchStatus, fetchQuote, fetchStakingBalance) + + awaitAll(fetchStatus, fetchQuote, fetchStakingBalance).summarizeResult() } } } @@ -80,14 +82,14 @@ class FetchCurrencyStatusUseCase( return either { val currency = getPrimaryCurrency(userWalletId, refresh) - coroutineScope { + return@either coroutineScope { val fetchStatus = async { - fetchNetworkStatus(userWalletId, currency.network) + fetchNetworkStatus(userWalletId = userWalletId, network = currency.network) } - val fetchQuote = async { - fetchQuote(currency.id) - } - awaitAll(fetchStatus, fetchQuote) + + val fetchQuote = async { fetchQuote(currencyId = currency.id) } + + awaitAll(fetchStatus, fetchQuote).summarizeResult() } } } @@ -97,9 +99,7 @@ class FetchCurrencyStatusUseCase( id: CryptoCurrency.ID, ): CryptoCurrency { return catch( - block = { - currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, id) - }, + block = { currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId = userWalletId, id = id) }, ) { raise(CurrencyStatusError.DataError(it)) } @@ -114,31 +114,27 @@ class FetchCurrencyStatusUseCase( } } - private suspend fun Raise.fetchNetworkStatus(userWalletId: UserWalletId, network: Network) { - singleNetworkStatusFetcher( + private suspend fun fetchNetworkStatus(userWalletId: UserWalletId, network: Network): Either { + return singleNetworkStatusFetcher( params = SingleNetworkStatusFetcher.Params(userWalletId = userWalletId, network = network), ) - .mapLeft { CurrencyStatusError.DataError(it) } - .bind() } - private suspend fun Raise.fetchQuote(currencyId: CryptoCurrency.ID) { - multiQuoteFetcher( + private suspend fun fetchQuote(currencyId: CryptoCurrency.ID): Either { + return multiQuoteFetcher( params = MultiQuoteFetcher.Params( currenciesIds = setOfNotNull(currencyId.rawCurrencyId), appCurrencyId = null, ), ) - .mapLeft { CurrencyStatusError.DataError(it) } - .bind() } - private suspend fun Raise.fetchStakingBalance( + private suspend fun fetchStakingBalance( userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency, refresh: Boolean, - ) { - if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) { + ): Either { + return if (tokensFeatureToggles.isStakingLoadingRefactoringEnabled) { singleYieldBalanceFetcher( params = SingleYieldBalanceFetcher.Params( userWalletId = userWalletId, @@ -147,11 +143,11 @@ class FetchCurrencyStatusUseCase( ), ) } else { - catch( - block = { stakingRepository.fetchSingleYieldBalance(userWalletId, cryptoCurrency, refresh) }, - ) { - raise(CurrencyStatusError.DataError(it)) - } + Either.catch { stakingRepository.fetchSingleYieldBalance(userWalletId, cryptoCurrency, refresh) } } } + + private fun List>.summarizeResult(): Either { + return firstOrNull { it.isLeft() } ?: Unit.right() + } } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt index 77f16153ff..a6d2f178bb 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt @@ -194,10 +194,7 @@ class GetCryptoCurrencyActionsUseCase( } // region sell - rampManager.availableForSell( - userWalletId = userWallet.walletId, - status = cryptoCurrencyStatus, - ) + rampManager.availableForSell(userWallet = userWallet, status = cryptoCurrencyStatus) .onRight { activeList.add(TokenActionsState.ActionState.Sell(ScenarioUnavailabilityReason.None)) } diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetNetworkCoinStatusUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetNetworkCoinStatusUseCase.kt index 6a1fab3d6b..4ecbcaebcb 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetNetworkCoinStatusUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetNetworkCoinStatusUseCase.kt @@ -1,13 +1,16 @@ package com.tangem.domain.tokens import arrow.core.Either +import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.models.network.Network import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.error.mapper.mapToCurrencyError import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations +import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.domain.wallets.models.requireColdWallet import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.* @@ -36,16 +39,21 @@ class GetNetworkCoinStatusUseCase( } suspend fun invokeSync( - userWalletId: UserWalletId, + userWallet: UserWallet, networkId: Network.ID, derivationPath: Network.DerivationPath, - isSingleWalletWithTokens: Boolean, ): Either { - val maybeCurrency = if (isSingleWalletWithTokens) { + val userWalletId = userWallet.walletId + val cardTypesResolver = userWallet.requireColdWallet().cardTypesResolver // TODO [REDACTED_TASK_KEY] + + val maybeCurrency = if (userWallet.isMultiCurrency) { + currencyStatusOperations.getNetworkCoinSync(userWalletId, networkId, derivationPath) + } else if (cardTypesResolver.isSingleWalletWithToken()) { currencyStatusOperations.getNetworkCoinForSingleWalletWithTokenSync(userWalletId, networkId) } else { - currencyStatusOperations.getNetworkCoinSync(userWalletId, networkId, derivationPath) + currencyStatusOperations.getPrimaryCurrencyStatusSync(userWalletId) } + return maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError) } diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/BaseCurrencyStatusOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/BaseCurrencyStatusOperations.kt index 6e8d810651..e24d551194 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/BaseCurrencyStatusOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/BaseCurrencyStatusOperations.kt @@ -54,11 +54,6 @@ abstract class BaseCurrencyStatusOperations( protected abstract fun getQuotes(id: CryptoCurrency.RawID): Flow>> - protected abstract fun getNetworksStatuses( - userWalletId: UserWalletId, - network: Network, - ): EitherFlow> - protected abstract suspend fun fetchComponents( userWalletId: UserWalletId, networks: Set, @@ -106,13 +101,7 @@ abstract class BaseCurrencyStatusOperations( flow { emit(Error.EmptyQuotes.left()) } } - val statusFlow = getNetworksStatuses(userWalletId = userWalletId, network = currency.network) - .map { maybeStatuses -> - maybeStatuses.flatMap { statuses -> - statuses.singleOrNull { it.network == currency.network }?.right() - ?: Error.EmptyNetworksStatuses.left() - } - } + val statusFlow = getNetworkStatus(userWalletId = userWalletId, network = currency.network) val yieldBalanceFlow = getYieldBalance(userWalletId = userWalletId, cryptoCurrency = currency) @@ -349,6 +338,15 @@ abstract class BaseCurrencyStatusOperations( .onEmpty { emit(Error.EmptyYieldBalances.left()) } } + private fun getNetworkStatus(userWalletId: UserWalletId, network: Network): EitherFlow { + return singleNetworkStatusSupplier( + params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = network), + ) + .map>(NetworkStatus::right) + .distinctUntilChanged() + .onEmpty { emit(Error.EmptyNetworksStatuses.left()) } + } + private suspend fun Raise.getNetworkCoin( userWalletId: UserWalletId, networkId: Network.ID, diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt index d29b49e8be..bf69424d0c 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt @@ -303,18 +303,6 @@ class CachedCurrenciesStatusesOperations( .distinctUntilChanged() } - override fun getNetworksStatuses( - userWalletId: UserWalletId, - network: Network, - ): EitherFlow> { - return singleNetworkStatusSupplier( - params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = network), - ) - .map>> { setOf(it).right() } - .distinctUntilChanged() - .onEmpty { emit(Error.EmptyNetworksStatuses.left()) } - } - private fun getYieldBalances( userWalletId: UserWalletId, cryptoCurrencies: List, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/model/OnrampTokenListModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/model/OnrampTokenListModel.kt index 7086e3f10c..2fb53e1132 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/model/OnrampTokenListModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/model/OnrampTokenListModel.kt @@ -59,9 +59,9 @@ internal class OnrampTokenListModel @Inject constructor( val state: StateFlow = tokenListUMController.state private val params: OnrampTokenListComponent.Params = paramsContainer.require() - private val scanResponse by lazy { + private val userWallet by lazy { getWalletsUseCase.invokeSync().first { it.walletId == params.userWalletId } - .requireColdWallet().scanResponse // TODO [REDACTED_TASK_KEY] + .requireColdWallet() // TODO [REDACTED_TASK_KEY] } init { @@ -229,16 +229,13 @@ internal class OnrampTokenListModel @Inject constructor( return when (params.filterOperation) { OnrampOperation.BUY -> { rampStateManager.availableForBuy( - scanResponse = scanResponse, + scanResponse = userWallet.scanResponse, userWalletId = params.userWalletId, cryptoCurrency = status.currency, ).isAvailable() } OnrampOperation.SELL -> { - rampStateManager.availableForSell( - userWalletId = params.userWalletId, - status = status, - ).isRight() + rampStateManager.availableForSell(userWallet = userWallet, status = status).isRight() } OnrampOperation.SWAP -> { val isAvailable = rampStateManager.availableForSwap(