Updated on 2026-08-14
This commit is contained in:
parent
7d017162cb
commit
642ae56dc7
7 changed files with 98 additions and 20 deletions
|
|
@ -4,8 +4,10 @@ import com.tangem.datasource.exchangeservice.swap.SwapServiceLoader
|
|||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.exchange.RampStateManager
|
||||
import com.tangem.domain.tokens.GetNetworkCoinStatusUseCase
|
||||
import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase
|
||||
import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository
|
||||
|
|
@ -45,6 +47,8 @@ internal object ActivityModule {
|
|||
fun provideDefaultRampManager(
|
||||
appStateHolder: AppStateHolder,
|
||||
swapServiceLoader: SwapServiceLoader,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): RampStateManager {
|
||||
return DefaultRampManager(
|
||||
|
|
@ -52,6 +56,8 @@ internal object ActivityModule {
|
|||
buyService = Provider { requireNotNull(appStateHolder.buyService) },
|
||||
sellService = Provider { requireNotNull(appStateHolder.sellService) },
|
||||
swapServiceLoader = swapServiceLoader,
|
||||
currenciesRepository = currenciesRepository,
|
||||
getNetworkCoinStatusUseCase = getNetworkCoinStatusUseCase,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,23 +4,37 @@ import com.tangem.datasource.api.express.models.TangemExpressValues.EMPTY_CONTRA
|
|||
import com.tangem.datasource.exchangeservice.swap.SwapServiceLoader
|
||||
import com.tangem.domain.exchange.RampStateManager
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.GetNetworkCoinStatusUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
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.UserWalletId
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class DefaultRampManager(
|
||||
private val exchangeService: ExchangeService?,
|
||||
private val buyService: Provider<ExchangeService>,
|
||||
private val sellService: Provider<ExchangeService>,
|
||||
private val swapServiceLoader: SwapServiceLoader,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : RampStateManager {
|
||||
|
||||
private val cryptoCurrencyConverter = CryptoCurrencyConverter()
|
||||
|
||||
override fun isSellSupportedByService(cryptoCurrency: CryptoCurrency): Boolean {
|
||||
return exchangeService?.availableForSell(
|
||||
currency = cryptoCurrencyConverter.convertBack(cryptoCurrency),
|
||||
) ?: false
|
||||
}
|
||||
|
||||
override fun availableForBuy(scanResponse: ScanResponse, cryptoCurrency: CryptoCurrency): Boolean {
|
||||
return exchangeService?.availableForBuy(
|
||||
scanResponse = scanResponse,
|
||||
|
|
@ -28,10 +42,14 @@ internal class DefaultRampManager(
|
|||
) ?: false
|
||||
}
|
||||
|
||||
override fun availableForSell(cryptoCurrency: CryptoCurrency): Boolean {
|
||||
return exchangeService?.availableForSell(
|
||||
currency = cryptoCurrencyConverter.convertBack(cryptoCurrency),
|
||||
) ?: false
|
||||
override suspend fun availableForSell(userWalletId: UserWalletId, status: CryptoCurrencyStatus): Boolean {
|
||||
val sellSupportedByService = isSellSupportedByService(cryptoCurrency = status.currency)
|
||||
|
||||
if (!sellSupportedByService) return false
|
||||
|
||||
val reason = getSendUnavailabilityReason(userWalletId, status)
|
||||
|
||||
return reason == ScenarioUnavailabilityReason.None
|
||||
}
|
||||
|
||||
override suspend fun availableForSwap(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean {
|
||||
|
|
@ -75,4 +93,34 @@ internal class DefaultRampManager(
|
|||
asset?.exchangeAvailable ?: false
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getSendUnavailabilityReason(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
): ScenarioUnavailabilityReason {
|
||||
val coinStatus = getNetworkCoinStatusUseCase.invokeSync(
|
||||
userWalletId = userWalletId,
|
||||
networkId = cryptoCurrencyStatus.currency.network.id,
|
||||
derivationPath = cryptoCurrencyStatus.currency.network.derivationPath,
|
||||
isSingleWalletWithTokens = false,
|
||||
).getOrNull()
|
||||
|
||||
return when {
|
||||
cryptoCurrencyStatus.value.amount.isNullOrZero() -> {
|
||||
ScenarioUnavailabilityReason.EmptyBalance(ScenarioUnavailabilityReason.WithdrawalScenario.SEND)
|
||||
}
|
||||
currenciesRepository.isSendBlockedByPendingTransactions(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
coinStatus = coinStatus,
|
||||
) -> {
|
||||
ScenarioUnavailabilityReason.PendingTransaction(
|
||||
withdrawalScenario = ScenarioUnavailabilityReason.WithdrawalScenario.SEND,
|
||||
networkName = coinStatus?.currency?.network?.name.orEmpty(),
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
ScenarioUnavailabilityReason.None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.domain.exchange
|
|||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
|
|
@ -11,9 +12,18 @@ import kotlinx.coroutines.flow.Flow
|
|||
*/
|
||||
interface RampStateManager {
|
||||
|
||||
/** Check if sell service is supported for given [CryptoCurrency] */
|
||||
fun isSellSupportedByService(cryptoCurrency: CryptoCurrency): Boolean
|
||||
|
||||
fun availableForBuy(scanResponse: ScanResponse, cryptoCurrency: CryptoCurrency): Boolean
|
||||
|
||||
fun availableForSell(cryptoCurrency: CryptoCurrency): Boolean
|
||||
/**
|
||||
* Check if [CryptoCurrency] is available for sell
|
||||
*
|
||||
* @param userWalletId id of multi-currency wallet
|
||||
* @param status crypto currency status
|
||||
*/
|
||||
suspend fun availableForSell(userWalletId: UserWalletId, status: CryptoCurrencyStatus): Boolean
|
||||
|
||||
suspend fun availableForSwap(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean
|
||||
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ class GetCryptoCurrencyActionsUseCase(
|
|||
}
|
||||
|
||||
// sell
|
||||
val sellSupportedByService = rampManager.availableForSell(cryptoCurrency)
|
||||
val sellSupportedByService = rampManager.isSellSupportedByService(cryptoCurrency)
|
||||
val sendAvailable = sendUnavailabilityReason is ScenarioUnavailabilityReason.None
|
||||
|
||||
when {
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ import com.tangem.domain.redux.ReduxStateHolder
|
|||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.onramp.tokenlist.entity.OnrampOperation
|
||||
import com.tangem.features.onramp.impl.R
|
||||
import com.tangem.features.onramp.selecttoken.ui.OnrampSelectToken
|
||||
import com.tangem.features.onramp.tokenlist.OnrampTokenListComponent
|
||||
import com.tangem.features.onramp.tokenlist.entity.OnrampOperation
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -34,7 +34,7 @@ internal class DefaultOnrampOperationComponent @AssistedInject constructor(
|
|||
params = OnrampTokenListComponent.Params(
|
||||
filterOperation = when (params) {
|
||||
is OnrampOperationComponent.Params.Buy -> OnrampOperation.BUY
|
||||
is OnrampOperationComponent.Params.Sell -> OnrampOperation.SWAP
|
||||
is OnrampOperationComponent.Params.Sell -> OnrampOperation.SELL
|
||||
},
|
||||
hasSearchBar = true,
|
||||
userWalletId = params.userWalletId,
|
||||
|
|
|
|||
|
|
@ -124,7 +124,6 @@ internal class UpdateTokenItemsTransformer(
|
|||
-> null
|
||||
}
|
||||
},
|
||||
onItemClick = onItemClick,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.onramp.impl.R
|
||||
import com.tangem.features.onramp.tokenlist.entity.OnrampOperation
|
||||
import com.tangem.features.onramp.tokenlist.OnrampTokenListComponent
|
||||
import com.tangem.features.onramp.tokenlist.entity.OnrampOperation
|
||||
import com.tangem.features.onramp.tokenlist.entity.TokenListUM
|
||||
import com.tangem.features.onramp.tokenlist.entity.TokenListUMController
|
||||
import com.tangem.features.onramp.tokenlist.entity.transformer.UpdateTokenItemsTransformer
|
||||
|
|
@ -124,20 +124,35 @@ internal class OnrampTokenListModel @Inject constructor(
|
|||
|
||||
private suspend fun List<CryptoCurrencyStatus>.filterByAvailability(): Map<Boolean, List<CryptoCurrencyStatus>> {
|
||||
return groupBy { status ->
|
||||
val isAvailable = when (params.filterOperation) {
|
||||
OnrampOperation.BUY -> {
|
||||
rampStateManager.availableForBuy(scanResponse = scanResponse, cryptoCurrency = status.currency)
|
||||
}
|
||||
OnrampOperation.SELL -> rampStateManager.availableForSell(cryptoCurrency = status.currency)
|
||||
OnrampOperation.SWAP -> rampStateManager.availableForSwap(
|
||||
val isAvailable = checkAvailabilityByOperation(status = status)
|
||||
val isNotMissedDerivation = status.value !is CryptoCurrencyStatus.MissedDerivation
|
||||
|
||||
val isNotUnreachable = when (params.filterOperation) {
|
||||
OnrampOperation.BUY -> true // unreachable state is available for Buy operation
|
||||
OnrampOperation.SELL -> status.value !is CryptoCurrencyStatus.Unreachable
|
||||
OnrampOperation.SWAP -> status.value !is CryptoCurrencyStatus.Unreachable
|
||||
}
|
||||
|
||||
isAvailable && isNotMissedDerivation && isNotUnreachable
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun checkAvailabilityByOperation(status: CryptoCurrencyStatus): Boolean {
|
||||
return when (params.filterOperation) {
|
||||
OnrampOperation.BUY -> {
|
||||
rampStateManager.availableForBuy(scanResponse = scanResponse, cryptoCurrency = status.currency)
|
||||
}
|
||||
OnrampOperation.SELL -> {
|
||||
rampStateManager.availableForSell(userWalletId = params.userWalletId, status = status)
|
||||
}
|
||||
OnrampOperation.SWAP -> {
|
||||
val isAvailable = rampStateManager.availableForSwap(
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrency = status.currency,
|
||||
)
|
||||
}
|
||||
|
||||
isAvailable &&
|
||||
status.value !is CryptoCurrencyStatus.MissedDerivation &&
|
||||
status.value !is CryptoCurrencyStatus.Unreachable
|
||||
isAvailable && status.value !is CryptoCurrencyStatus.NoQuote
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue