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 62da11c64c..c389af965c 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 @@ -100,18 +100,6 @@ internal object TokensDomainModule { ) } - @Provides - @Singleton - fun provideGetCurrencyStatusByNetworkUseCase( - currencyStatusOperations: BaseCurrencyStatusOperations, - dispatchers: CoroutineDispatcherProvider, - ): GetNetworkCoinStatusUseCase { - return GetNetworkCoinStatusUseCase( - currencyStatusOperations = currencyStatusOperations, - dispatchers = dispatchers, - ) - } - @Provides @Singleton fun provideGetFeePaidCryptoCurrencyStatusSyncUseCase( 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 deleted file mode 100644 index 89a9baade6..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetNetworkCoinStatusUseCase.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import com.tangem.domain.card.common.util.cardTypesResolver -import com.tangem.domain.models.currency.CryptoCurrencyStatus -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.models.wallet.isMultiCurrency -import com.tangem.domain.tokens.error.CurrencyStatusError -import com.tangem.domain.tokens.error.mapper.mapToCurrencyError -import com.tangem.domain.tokens.operations.BaseCurrencyStatusOperations -import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.flow.* - -class GetNetworkCoinStatusUseCase( - private val currencyStatusOperations: BaseCurrencyStatusOperations, - private val dispatchers: CoroutineDispatcherProvider, -) { - - operator fun invoke( - userWalletId: UserWalletId, - networkId: Network.ID, - derivationPath: Network.DerivationPath, - isSingleWalletWithTokens: Boolean, - ): Flow> { - return flow { - emitAll( - flow = getCurrency( - userWalletId = userWalletId, - networkId = networkId, - derivationPath = derivationPath, - isSingleWalletWithTokens = isSingleWalletWithTokens, - ), - ) - } - .flowOn(dispatchers.io) - } - - suspend fun invokeSync( - userWallet: UserWallet, - networkId: Network.ID, - derivationPath: Network.DerivationPath, - ): Either { - val userWalletId = userWallet.walletId - - val maybeCurrency = if (userWallet.isMultiCurrency) { - currencyStatusOperations.getNetworkCoinSync(userWalletId, networkId, derivationPath) - } else if (userWallet is UserWallet.Cold && userWallet.cardTypesResolver.isSingleWalletWithToken()) { - currencyStatusOperations.getNetworkCoinForSingleWalletWithTokenSync(userWalletId, networkId) - } else { - currencyStatusOperations.getPrimaryCurrencyStatusSync(userWalletId) - } - - return maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError) - } - - private suspend fun getCurrency( - userWalletId: UserWalletId, - networkId: Network.ID, - derivationPath: Network.DerivationPath, - isSingleWalletWithTokens: Boolean, - ): Flow> { - val networkFlow = if (isSingleWalletWithTokens) { - currencyStatusOperations.getNetworkCoinForSingleWalletWithTokenFlow(userWalletId, networkId) - } else { - currencyStatusOperations.getNetworkCoinFlow(userWalletId, networkId, derivationPath) - } - return networkFlow.map { maybeCurrency -> - maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError) - } - } -} \ No newline at end of file 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 117b907f78..a443a459eb 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 @@ -2,15 +2,10 @@ package com.tangem.domain.tokens.operations import arrow.core.* import arrow.core.raise.* -import com.tangem.blockchainsdk.utils.toBlockchain -import com.tangem.domain.core.utils.EitherFlow import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.Network -import com.tangem.domain.models.network.NetworkStatus -import com.tangem.domain.models.quote.QuoteStatus import com.tangem.domain.models.staking.StakingBalance -import com.tangem.domain.models.staking.StakingID import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.networks.multi.MultiNetworkStatusProducer import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier @@ -20,7 +15,6 @@ import com.tangem.domain.quotes.QuotesRepository import com.tangem.domain.quotes.single.SingleQuoteStatusProducer import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier import com.tangem.domain.staking.StakingIdFactory -import com.tangem.domain.staking.model.isStakingSupported import com.tangem.domain.staking.multi.MultiStakingBalanceProducer import com.tangem.domain.staking.multi.MultiStakingBalanceSupplier import com.tangem.domain.staking.single.SingleStakingBalanceProducer @@ -30,7 +24,7 @@ import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations.Error import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.utils.CurrencyStatusProxyCreator -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.firstOrNull /** * Base operations for working with currency status @@ -54,112 +48,6 @@ class BaseCurrencyStatusOperations( private val currencyStatusProxyCreator = CurrencyStatusProxyCreator() - suspend fun getCurrencyStatusFlow( - userWalletId: UserWalletId, - currencyId: CryptoCurrency.ID, - isSingleWalletWithTokens: Boolean, - ): Flow> { - val currency = recover( - block = { - if (isSingleWalletWithTokens) { - getSingleCurrencyWalletWithCardTokensCurrency(userWalletId, currencyId) - } else { - getMultiCurrencyWalletCurrency(userWalletId, currencyId) - } - }, - recover = { return flowOf(it.left()) }, - ) - - return getCurrencyStatusFlow(userWalletId = userWalletId, currency = currency) - } - - suspend fun getCurrencyStatusFlow( - userWalletId: UserWalletId, - currency: CryptoCurrency, - includeQuotes: Boolean = true, - subscribeOnStakingBalance: Boolean = true, - ): Flow> { - val rawCurrencyId = currency.id.rawCurrencyId - - val quoteFlow = if (includeQuotes && rawCurrencyId != null) { - getQuotes(rawCurrencyId) - .map { maybeQuotes -> - maybeQuotes.flatMap { quotes -> - quotes.singleOrNull { it.rawCurrencyId == currency.id.rawCurrencyId }?.right() - ?: Error.EmptyQuotes.left() - } - } - } else { - // don't use emptyFlow() - flow { emit(Error.EmptyQuotes.left()) } - } - - val statusFlow = getNetworkStatus(userWalletId = userWalletId, network = currency.network) - - val isStakingSupported = currency.network.toBlockchain().isStakingSupported - - val stakingBalanceFlow = if (isStakingSupported) { - val stakingId = stakingIdFactory.create( - userWalletId = userWalletId, - currencyId = currency.id, - network = currency.network, - ) - .getOrNull() - - stakingId?.let { - getStakingBalance(userWalletId = userWalletId, stakingId = it) - } - } else { - null - } - - return if (subscribeOnStakingBalance && stakingBalanceFlow != null) { - combine(quoteFlow, statusFlow, stakingBalanceFlow) { maybeQuote, maybeNetworkStatus, maybeStakingBalance -> - currencyStatusProxyCreator.createCurrencyStatus( - currency = currency, - maybeQuoteStatus = maybeQuote, - maybeNetworkStatus = maybeNetworkStatus, - maybeStakingBalance = maybeStakingBalance, - ) - } - } else { - combine(quoteFlow, statusFlow) { maybeQuote, maybeNetworkStatus -> - currencyStatusProxyCreator.createCurrencyStatus( - currency = currency, - maybeQuoteStatus = maybeQuote, - maybeNetworkStatus = maybeNetworkStatus, - maybeStakingBalance = null, - ) - } - } - } - - suspend fun getNetworkCoinFlow( - userWalletId: UserWalletId, - networkId: Network.ID, - derivationPath: Network.DerivationPath, - includeQuotes: Boolean = true, - ): Flow> { - val currency = recover( - block = { getNetworkCoin(userWalletId, networkId, derivationPath) }, - recover = { return flowOf(it.left()) }, - ) - - return getCurrencyStatusFlow(userWalletId, currency, includeQuotes) - } - - suspend fun getNetworkCoinForSingleWalletWithTokenFlow( - userWalletId: UserWalletId, - networkId: Network.ID, - ): Flow> { - val currency = recover( - block = { getNetworkCoinForSingleWalletWithToken(userWalletId, networkId) }, - recover = { return flowOf(it.left()) }, - ) - - return getCurrencyStatusFlow(userWalletId, currency) - } - suspend fun getNetworkCoinSync( userWalletId: UserWalletId, networkId: Network.ID, @@ -217,32 +105,6 @@ class BaseCurrencyStatusOperations( } } - suspend fun getNetworkCoinForSingleWalletWithTokenSync( - userWalletId: UserWalletId, - networkId: Network.ID, - ): Either = either { - val currency = getNetworkCoinForSingleWalletWithToken(userWalletId, networkId) - - return getCurrencyStatusSync(userWalletId, currency.id) - } - - suspend fun getPrimaryCurrencyStatusFlow( - userWalletId: UserWalletId, - includeQuotes: Boolean = true, - ): Flow> { - val currency = recover( - block = { getPrimaryCurrency(userWalletId) }, - recover = { return flowOf(it.left()) }, - ) - - return getCurrencyStatusFlow( - userWalletId = userWalletId, - currency = currency, - includeQuotes = includeQuotes, - subscribeOnStakingBalance = false, - ) - } - suspend fun getCurrenciesStatusesSync(userWalletId: UserWalletId): Either> { return either { catch( @@ -279,35 +141,6 @@ class BaseCurrencyStatusOperations( } } - suspend fun getPrimaryCurrencyStatusSync(userWalletId: UserWalletId): Either = either { - val currency = catch( - block = { currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(userWalletId) }, - catch = { raise(Error.DataError(it)) }, - ) - - val quotes = currency.id.rawCurrencyId?.let { - singleQuoteStatusSupplier(params = SingleQuoteStatusProducer.Params(rawCurrencyId = it)) - .firstOrNull() - } - ?.right() - ?: Error.EmptyQuotes.left() - - val networkStatus = singleNetworkStatusSupplier( - params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = currency.network), - ) - .firstOrNull() - .right() - - val stakingBalances = getStakingBalanceSync(userWalletId, currency) - - return currencyStatusProxyCreator.createCurrencyStatus( - currency = currency, - maybeQuoteStatus = quotes, - maybeNetworkStatus = networkStatus, - maybeStakingBalance = stakingBalances, - ) - } - private suspend fun Raise.getMultiCurrencyWalletCurrency( userWalletId: UserWalletId, currencyId: CryptoCurrency.ID, @@ -323,36 +156,6 @@ class BaseCurrencyStatusOperations( .bind() } - private suspend fun Raise.getSingleCurrencyWalletWithCardTokensCurrency( - userWalletId: UserWalletId, - currencyId: CryptoCurrency.ID, - ): CryptoCurrency { - return Either.catch { currenciesRepository.getSingleCurrencyWalletWithCardCurrency(userWalletId, currencyId) } - .mapLeft { Error.DataError(it) } - .bind() - } - - private fun getStakingBalance(userWalletId: UserWalletId, stakingId: StakingID): EitherFlow { - return singleStakingBalanceSupplier( - params = SingleStakingBalanceProducer.Params( - userWalletId = userWalletId, - stakingId = stakingId, - ), - ) - .map> { it.right() } - .catch { emit(Error.DataError(it).left()) } - .onEmpty { emit(Error.EmptyStakingBalances.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, @@ -370,27 +173,6 @@ class BaseCurrencyStatusOperations( .bind() } - private suspend fun Raise.getNetworkCoinForSingleWalletWithToken( - userWalletId: UserWalletId, - networkId: Network.ID, - ): CryptoCurrency { - return Either.catch { - currenciesRepository.getSingleCurrencyWalletWithCardCurrencies(userWalletId) - .find { it.network.id == networkId && it is CryptoCurrency.Coin } - ?: raise(Error.DataError(IllegalStateException("Coin with network $networkId not found for this card"))) - } - .mapLeft { Error.DataError(it) } - .bind() - } - - private fun getQuotes(id: CryptoCurrency.RawID): Flow>> { - return singleQuoteStatusSupplier( - params = SingleQuoteStatusProducer.Params(rawCurrencyId = id), - ) - .map>> { setOf(it).right() } - .distinctUntilChanged() - } - private suspend fun getStakingBalancesSync( userWalletId: UserWalletId, cryptoCurrencies: List, @@ -434,13 +216,6 @@ class BaseCurrencyStatusOperations( ensureNotNull(yieldBalance) { Error.EmptyStakingBalances } } - private suspend fun Raise.getPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency { - return catch( - block = { currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(userWalletId) }, - catch = { raise(Error.DataError(it)) }, - ) - } - private fun getIds(currencies: List): Pair, NonEmptySet> { val currencyIdToNetworkId = currencies.associate { currency -> currency.id to currency.network diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt index 493b5158d4..5153c887a2 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt @@ -2,6 +2,8 @@ package com.tangem.features.walletconnect.transaction.model import androidx.compose.runtime.Stable import arrow.core.Either +import arrow.core.Option +import arrow.core.none import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.pop import com.arkivanov.decompose.router.stack.pushNew @@ -22,12 +24,12 @@ import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2 import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2.Icon.Type import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.wrappedList +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier +import com.tangem.domain.account.status.utils.CryptoCurrencyStatusOperations.getCoinStatus import com.tangem.domain.core.lce.Lce import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.tokens.GetNetworkCoinStatusUseCase -import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.transaction.error.SendTransactionError.UserCancelledError import com.tangem.domain.transaction.usecase.GetFeeUseCase @@ -79,7 +81,7 @@ internal class WcSendTransactionModel @Inject constructor( private val useCaseFactory: WcRequestUseCaseFactory, private val converter: WcSendTransactionUMConverter, private val getFeeUseCase: GetFeeUseCase, - private val getNetworkCoinUseCase: GetNetworkCoinStatusUseCase, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val notificationsFactory: WcNotificationsFactory, private val analytics: AnalyticsEventHandler, private val urlOpener: UrlOpener, @@ -121,7 +123,7 @@ internal class WcSendTransactionModel @Inject constructor( -> { this@WcSendTransactionModel.cryptoCurrencyStatus = getCryptoCurrencyStatus(userWallet = useCase.wallet, network = useCase.network) - .onLeft { unknownMethodRunnable() } + .onNone { unknownMethodRunnable() } .getOrNull() ?: return@launch this@WcSendTransactionModel.useCase = useCase (useCase as? WcMutableFee) @@ -233,12 +235,11 @@ internal class WcSendTransactionModel @Inject constructor( private suspend fun getCryptoCurrencyStatus( userWallet: UserWallet, network: Network, - ): Either { - return getNetworkCoinUseCase.invokeSync( - userWallet = userWallet, - networkId = network.id, - derivationPath = network.derivationPath, - ) + ): Option { + val accountStatusList = singleAccountStatusListSupplier.getSyncOrNull(userWallet.walletId) + ?: return none() + + return accountStatusList.getCoinStatus(network) } private suspend fun buildUiState(