Updated on 2026-08-14

This commit is contained in:
Tangem 2025-07-11 22:34:54 +04:00
parent 309c9aad6c
commit 0e1e5e3a67
20 changed files with 834 additions and 484 deletions

View file

@ -14,11 +14,9 @@ import com.tangem.domain.exchange.ExpressAvailabilityState
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.scan.ScanResponse
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
@ -35,7 +33,6 @@ internal class DefaultRampManager(
private val sellService: Provider<ExchangeService>,
private val expressServiceLoader: ExpressServiceLoader,
private val currenciesRepository: CurrenciesRepository,
private val getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase,
private val dispatchers: CoroutineDispatcherProvider,
private val onrampFeatureToggles: OnrampFeatureToggles,
excludedBlockchains: ExcludedBlockchains,
@ -56,20 +53,22 @@ internal class DefaultRampManager(
}
override suspend fun availableForSell(
userWallet: UserWallet,
userWalletId: UserWalletId,
status: CryptoCurrencyStatus,
sendUnavailabilityReason: ScenarioUnavailabilityReason?,
): Either<ScenarioUnavailabilityReason, Unit> {
return either {
val sellSupportedByService = catch(
block = {
val serviceCurrency = cryptoCurrencyConverter.convertBack(status.currency)
exchangeService?.availableForSell(currency = serviceCurrency) ?: false
exchangeService?.availableForSell(currency = serviceCurrency) == true
},
catch = { raise(ScenarioUnavailabilityReason.NotSupportedBySellService(status.currency.name)) },
)
val reason = getSendUnavailabilityReason(userWallet = userWallet, cryptoCurrencyStatus = status)
val reason = sendUnavailabilityReason
?: getSendUnavailabilityReason(userWalletId = userWalletId, cryptoCurrencyStatus = status)
ensure(condition = reason is ScenarioUnavailabilityReason.None) {
when (reason) {
@ -125,6 +124,27 @@ internal class DefaultRampManager(
return expressServiceLoader.getInitializationStatus(userWalletId)
}
override suspend fun getSendUnavailabilityReason(
userWalletId: UserWalletId,
cryptoCurrencyStatus: CryptoCurrencyStatus,
): ScenarioUnavailabilityReason {
return when {
cryptoCurrencyStatus.value.amount.isNullOrZero() -> {
ScenarioUnavailabilityReason.EmptyBalance(ScenarioUnavailabilityReason.WithdrawalScenario.SEND)
}
currenciesRepository.isSendBlockedByPendingTransactions(
userWalletId = userWalletId,
cryptoCurrencyStatus = cryptoCurrencyStatus,
) -> {
ScenarioUnavailabilityReason.PendingTransaction(
withdrawalScenario = ScenarioUnavailabilityReason.WithdrawalScenario.SEND,
networkName = cryptoCurrencyStatus.currency.network.name,
)
}
else -> ScenarioUnavailabilityReason.None
}
}
private suspend fun getExchangeableState(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
@ -204,33 +224,4 @@ internal class DefaultRampManager(
val contractAddress = (this as? CryptoCurrency.Token)?.contractAddress ?: EMPTY_CONTRACT_ADDRESS_VALUE
return asset.network == network.backendId && asset.contractAddress.equals(contractAddress, ignoreCase = true)
}
private suspend fun getSendUnavailabilityReason(
userWallet: UserWallet,
cryptoCurrencyStatus: CryptoCurrencyStatus,
): ScenarioUnavailabilityReason {
val coinStatus = getNetworkCoinStatusUseCase.invokeSync(
userWallet = userWallet,
networkId = cryptoCurrencyStatus.currency.network.id,
derivationPath = cryptoCurrencyStatus.currency.network.derivationPath,
).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
}
}
}
}