Updated on 2026-08-14
This commit is contained in:
parent
d4b7aa85e1
commit
d84315a40c
4 changed files with 12 additions and 322 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
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<CurrencyStatusError, CryptoCurrencyStatus> {
|
||||
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<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
val networkFlow = if (isSingleWalletWithTokens) {
|
||||
currencyStatusOperations.getNetworkCoinForSingleWalletWithTokenFlow(userWalletId, networkId)
|
||||
} else {
|
||||
currencyStatusOperations.getNetworkCoinFlow(userWalletId, networkId, derivationPath)
|
||||
}
|
||||
return networkFlow.map { maybeCurrency ->
|
||||
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Either<Error, CryptoCurrencyStatus>> {
|
||||
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<Either<Error, CryptoCurrencyStatus>> {
|
||||
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<Either<Error, CryptoCurrencyStatus>> {
|
||||
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<Either<Error, CryptoCurrencyStatus>> {
|
||||
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<Error, CryptoCurrencyStatus> = either {
|
||||
val currency = getNetworkCoinForSingleWalletWithToken(userWalletId, networkId)
|
||||
|
||||
return getCurrencyStatusSync(userWalletId, currency.id)
|
||||
}
|
||||
|
||||
suspend fun getPrimaryCurrencyStatusFlow(
|
||||
userWalletId: UserWalletId,
|
||||
includeQuotes: Boolean = true,
|
||||
): Flow<Either<Error, CryptoCurrencyStatus>> {
|
||||
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<Error, List<CryptoCurrencyStatus>> {
|
||||
return either {
|
||||
catch(
|
||||
|
|
@ -279,35 +141,6 @@ class BaseCurrencyStatusOperations(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun getPrimaryCurrencyStatusSync(userWalletId: UserWalletId): Either<Error, CryptoCurrencyStatus> = 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<Error>.getMultiCurrencyWalletCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
|
|
@ -323,36 +156,6 @@ class BaseCurrencyStatusOperations(
|
|||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.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<Error, StakingBalance> {
|
||||
return singleStakingBalanceSupplier(
|
||||
params = SingleStakingBalanceProducer.Params(
|
||||
userWalletId = userWalletId,
|
||||
stakingId = stakingId,
|
||||
),
|
||||
)
|
||||
.map<StakingBalance, Either<Error, StakingBalance>> { it.right() }
|
||||
.catch { emit(Error.DataError(it).left()) }
|
||||
.onEmpty { emit(Error.EmptyStakingBalances.left()) }
|
||||
}
|
||||
|
||||
private fun getNetworkStatus(userWalletId: UserWalletId, network: Network): EitherFlow<Error, NetworkStatus> {
|
||||
return singleNetworkStatusSupplier(
|
||||
params = SingleNetworkStatusProducer.Params(userWalletId = userWalletId, network = network),
|
||||
)
|
||||
.map<NetworkStatus, Either<Error, NetworkStatus>>(NetworkStatus::right)
|
||||
.distinctUntilChanged()
|
||||
.onEmpty { emit(Error.EmptyNetworksStatuses.left()) }
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getNetworkCoin(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
|
|
@ -370,27 +173,6 @@ class BaseCurrencyStatusOperations(
|
|||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.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<Either<Error, Set<QuoteStatus>>> {
|
||||
return singleQuoteStatusSupplier(
|
||||
params = SingleQuoteStatusProducer.Params(rawCurrencyId = id),
|
||||
)
|
||||
.map<QuoteStatus, Either<Error, Set<QuoteStatus>>> { setOf(it).right() }
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
private suspend fun getStakingBalancesSync(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencies: List<CryptoCurrency>,
|
||||
|
|
@ -434,13 +216,6 @@ class BaseCurrencyStatusOperations(
|
|||
ensureNotNull(yieldBalance) { Error.EmptyStakingBalances }
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency {
|
||||
return catch(
|
||||
block = { currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(userWalletId) },
|
||||
catch = { raise(Error.DataError(it)) },
|
||||
)
|
||||
}
|
||||
|
||||
private fun getIds(currencies: List<CryptoCurrency>): Pair<NonEmptySet<Network>, NonEmptySet<CryptoCurrency.ID>> {
|
||||
val currencyIdToNetworkId = currencies.associate { currency ->
|
||||
currency.id to currency.network
|
||||
|
|
|
|||
|
|
@ -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<CurrencyStatusError, CryptoCurrencyStatus> {
|
||||
return getNetworkCoinUseCase.invokeSync(
|
||||
userWallet = userWallet,
|
||||
networkId = network.id,
|
||||
derivationPath = network.derivationPath,
|
||||
)
|
||||
): Option<CryptoCurrencyStatus> {
|
||||
val accountStatusList = singleAccountStatusListSupplier.getSyncOrNull(userWallet.walletId)
|
||||
?: return none()
|
||||
|
||||
return accountStatusList.getCoinStatus(network)
|
||||
}
|
||||
|
||||
private suspend fun buildUiState(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue