diff --git a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt index d8222cc618..ca78dbeca6 100644 --- a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt +++ b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt @@ -385,6 +385,9 @@ internal class DefaultOnrampRepository( }, ) } + + if (onrampProviders.isEmpty()) throw OnrampPairsError.PairsNotFound + OnrampPair(onrampProviders) } pairsStore.store(PAIRS_KEY, onrampPairs) diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/OnrampStateFactory.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/OnrampStateFactory.kt index 8cd1890fbb..136405af33 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/OnrampStateFactory.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/OnrampStateFactory.kt @@ -74,7 +74,7 @@ internal class OnrampStateFactory( ) } - private fun getErrorState(errorCode: String? = null): OnrampMainComponentUM { + fun getErrorState(errorCode: String? = null): OnrampMainComponentUM { val state = currentStateProvider() val endButton = state.topBarConfig.endButtonUM.copy(enabled = true) @@ -84,6 +84,7 @@ internal class OnrampStateFactory( buyButtonConfig = state.buyButtonConfig.copy(enabled = false), amountBlockState = state.amountBlockState.copy( amountFieldModel = state.amountBlockState.amountFieldModel.copy(isError = true), + secondaryFieldModel = OnrampAmountSecondaryFieldUM.Content(TextReference.EMPTY), ), providerBlockState = OnrampProviderBlockUM.Empty, errorNotification = NotificationUM.Warning.OnrampErrorNotification( diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountFieldChangeConverter.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountFieldChangeConverter.kt index cb2186a058..576bbe719e 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountFieldChangeConverter.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountFieldChangeConverter.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.utils.parseBigDecimalOrNull import com.tangem.features.onramp.main.entity.OnrampAmountSecondaryFieldUM import com.tangem.features.onramp.main.entity.OnrampMainComponentUM import com.tangem.features.onramp.main.entity.OnrampProviderBlockUM @@ -24,7 +25,7 @@ internal class OnrampAmountFieldChangeConverter( val amountState = state.amountBlockState val amountTextField = amountState.amountFieldModel - val fiatDecimal = value.toBigDecimalOrNull() ?: BigDecimal.ZERO + val fiatDecimal = value.parseBigDecimalOrNull() ?: BigDecimal.ZERO val isDoneActionEnabled = !fiatDecimal.isNullOrZero() val amountFieldModel = amountState.amountFieldModel.copy( fiatValue = value, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountStateFactory.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountStateFactory.kt index cb9d102bc6..5d85cb0561 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountStateFactory.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/entity/factory/amount/OnrampAmountStateFactory.kt @@ -1,6 +1,7 @@ package com.tangem.features.onramp.main.entity.factory.amount import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList @@ -144,6 +145,23 @@ internal class OnrampAmountStateFactory( ) } + fun getAmountSecondaryResetState(): OnrampMainComponentUM { + val currentState = currentStateProvider() + if (currentState !is OnrampMainComponentUM.Content) return currentState + + val amountState = currentState.amountBlockState + + if (amountState.secondaryFieldModel is OnrampAmountSecondaryFieldUM.Content) return currentState + + return currentState.copy( + amountBlockState = amountState.copy( + secondaryFieldModel = OnrampAmountSecondaryFieldUM.Content( + amount = TextReference.EMPTY, + ), + ), + ) + } + private fun OnrampQuote.toProviderBlockState(isBestRate: Boolean): OnrampProviderBlockUM { return OnrampProviderBlockUM.Content( paymentMethod = paymentMethod, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt index c85fe513cc..366e4ba313 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt @@ -157,7 +157,11 @@ internal class OnrampMainComponentModel @Inject constructor( } private suspend fun updatePairsAndQuotes() { - fetchPairsUseCase.invoke(params.cryptoCurrency).onLeft(::handleOnrampError) + _state.update { amountStateFactory.getAmountSecondaryLoadingState() } + fetchPairsUseCase.invoke(params.cryptoCurrency).fold( + ifLeft = ::handleOnrampError, + ifRight = { _state.update { amountStateFactory.getAmountSecondaryResetState() } }, + ) startLoadingQuotes() } @@ -195,39 +199,7 @@ internal class OnrampMainComponentModel @Inject constructor( .onEach { maybeQuotes -> maybeQuotes.fold( ifLeft = ::handleOnrampError, - ifRight = { quotes -> - quotes.filterIsInstance().forEach { errorState -> - sendOnrampErrorAnalytic(errorState.error) - } - val quote = quotes.firstOrNull() ?: return@onEach - - val bestProvider = quote as? OnrampQuote.Data - val isMultipleQuotes = !quotes.isSingleItem() - val isOtherQuotesHasData = quotes - .filter { it.paymentMethod == quote.paymentMethod } - .filterNot { it == bestProvider } - .any { it is OnrampQuote.Data } - val hasBestProvider = isMultipleQuotes && isOtherQuotesHasData - - val isBestProvider = quote == bestProvider && hasBestProvider - - if (quote is OnrampQuote.Data && lastAmount.value != quote.fromAmount.value) { - lastAmount.value = quote.fromAmount.value - analyticsEventHandler.send( - OnrampAnalyticsEvent.ProviderCalculated( - providerName = quote.provider.info.name, - tokenSymbol = params.cryptoCurrency.symbol, - paymentMethod = quote.paymentMethod.name, - ), - ) - } - _state.update { - amountStateFactory.getAmountSecondaryUpdatedState( - quote = quote, - isBestRate = isBestProvider, - ) - } - }, + ifRight = ::handleQuoteResult, ) } .launchIn(modelScope) @@ -296,6 +268,46 @@ internal class OnrampMainComponentModel @Inject constructor( super.onDestroy() } + private fun handleQuoteResult(quotes: List) { + quotes.filterIsInstance().forEach { errorState -> + sendOnrampErrorAnalytic(errorState.error) + } + + val quote = quotes.firstOrNull() + + if (quote == null) { + _state.update { stateFactory.getErrorState() } + return + } + + val bestProvider = quote as? OnrampQuote.Data + val isMultipleQuotes = !quotes.isSingleItem() + val isOtherQuotesHasData = quotes + .filter { it.paymentMethod == quote.paymentMethod } + .filterNot { it == bestProvider } + .any { it is OnrampQuote.Data } + val hasBestProvider = isMultipleQuotes && isOtherQuotesHasData + + val isBestProvider = quote == bestProvider && hasBestProvider + + if (quote is OnrampQuote.Data && lastAmount.value != quote.fromAmount.value) { + lastAmount.value = quote.fromAmount.value + analyticsEventHandler.send( + OnrampAnalyticsEvent.ProviderCalculated( + providerName = quote.provider.info.name, + tokenSymbol = params.cryptoCurrency.symbol, + paymentMethod = quote.paymentMethod.name, + ), + ) + } + _state.update { + amountStateFactory.getAmountSecondaryUpdatedState( + quote = quote, + isBestRate = isBestProvider, + ) + } + } + private fun showDemoWarning() { val alertUM = AlertDemoModeUM(onConfirmClick = {})