Updated on 2026-08-14
This commit is contained in:
commit
eaf56fc0ae
5 changed files with 71 additions and 36 deletions
|
|
@ -385,6 +385,9 @@ internal class DefaultOnrampRepository(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (onrampProviders.isEmpty()) throw OnrampPairsError.PairsNotFound
|
||||||
|
|
||||||
OnrampPair(onrampProviders)
|
OnrampPair(onrampProviders)
|
||||||
}
|
}
|
||||||
pairsStore.store(PAIRS_KEY, onrampPairs)
|
pairsStore.store(PAIRS_KEY, onrampPairs)
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ internal class OnrampStateFactory(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getErrorState(errorCode: String? = null): OnrampMainComponentUM {
|
fun getErrorState(errorCode: String? = null): OnrampMainComponentUM {
|
||||||
val state = currentStateProvider()
|
val state = currentStateProvider()
|
||||||
val endButton = state.topBarConfig.endButtonUM.copy(enabled = true)
|
val endButton = state.topBarConfig.endButtonUM.copy(enabled = true)
|
||||||
|
|
||||||
|
|
@ -84,6 +84,7 @@ internal class OnrampStateFactory(
|
||||||
buyButtonConfig = state.buyButtonConfig.copy(enabled = false),
|
buyButtonConfig = state.buyButtonConfig.copy(enabled = false),
|
||||||
amountBlockState = state.amountBlockState.copy(
|
amountBlockState = state.amountBlockState.copy(
|
||||||
amountFieldModel = state.amountBlockState.amountFieldModel.copy(isError = true),
|
amountFieldModel = state.amountBlockState.amountFieldModel.copy(isError = true),
|
||||||
|
secondaryFieldModel = OnrampAmountSecondaryFieldUM.Content(TextReference.EMPTY),
|
||||||
),
|
),
|
||||||
providerBlockState = OnrampProviderBlockUM.Empty,
|
providerBlockState = OnrampProviderBlockUM.Empty,
|
||||||
errorNotification = NotificationUM.Warning.OnrampErrorNotification(
|
errorNotification = NotificationUM.Warning.OnrampErrorNotification(
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
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.OnrampAmountSecondaryFieldUM
|
||||||
import com.tangem.features.onramp.main.entity.OnrampMainComponentUM
|
import com.tangem.features.onramp.main.entity.OnrampMainComponentUM
|
||||||
import com.tangem.features.onramp.main.entity.OnrampProviderBlockUM
|
import com.tangem.features.onramp.main.entity.OnrampProviderBlockUM
|
||||||
|
|
@ -24,7 +25,7 @@ internal class OnrampAmountFieldChangeConverter(
|
||||||
|
|
||||||
val amountState = state.amountBlockState
|
val amountState = state.amountBlockState
|
||||||
val amountTextField = amountState.amountFieldModel
|
val amountTextField = amountState.amountFieldModel
|
||||||
val fiatDecimal = value.toBigDecimalOrNull() ?: BigDecimal.ZERO
|
val fiatDecimal = value.parseBigDecimalOrNull() ?: BigDecimal.ZERO
|
||||||
val isDoneActionEnabled = !fiatDecimal.isNullOrZero()
|
val isDoneActionEnabled = !fiatDecimal.isNullOrZero()
|
||||||
val amountFieldModel = amountState.amountFieldModel.copy(
|
val amountFieldModel = amountState.amountFieldModel.copy(
|
||||||
fiatValue = value,
|
fiatValue = value,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.features.onramp.main.entity.factory.amount
|
package com.tangem.features.onramp.main.entity.factory.amount
|
||||||
|
|
||||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
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.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
import com.tangem.core.ui.extensions.wrappedList
|
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 {
|
private fun OnrampQuote.toProviderBlockState(isBestRate: Boolean): OnrampProviderBlockUM {
|
||||||
return OnrampProviderBlockUM.Content(
|
return OnrampProviderBlockUM.Content(
|
||||||
paymentMethod = paymentMethod,
|
paymentMethod = paymentMethod,
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,11 @@ internal class OnrampMainComponentModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun updatePairsAndQuotes() {
|
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()
|
startLoadingQuotes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,39 +199,7 @@ internal class OnrampMainComponentModel @Inject constructor(
|
||||||
.onEach { maybeQuotes ->
|
.onEach { maybeQuotes ->
|
||||||
maybeQuotes.fold(
|
maybeQuotes.fold(
|
||||||
ifLeft = ::handleOnrampError,
|
ifLeft = ::handleOnrampError,
|
||||||
ifRight = { quotes ->
|
ifRight = ::handleQuoteResult,
|
||||||
quotes.filterIsInstance<OnrampQuote.Error>().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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.launchIn(modelScope)
|
.launchIn(modelScope)
|
||||||
|
|
@ -296,6 +268,46 @@ internal class OnrampMainComponentModel @Inject constructor(
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleQuoteResult(quotes: List<OnrampQuote>) {
|
||||||
|
quotes.filterIsInstance<OnrampQuote.Error>().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() {
|
private fun showDemoWarning() {
|
||||||
val alertUM = AlertDemoModeUM(onConfirmClick = {})
|
val alertUM = AlertDemoModeUM(onConfirmClick = {})
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue