Updated on 2026-08-14
This commit is contained in:
parent
c48ddbff25
commit
cf53970ba8
12 changed files with 54 additions and 29 deletions
|
|
@ -12,7 +12,7 @@ data class OnrampCurrencyDTO(
|
|||
val code: String,
|
||||
|
||||
@Json(name = "image")
|
||||
val image: String,
|
||||
val image: String?,
|
||||
|
||||
@Json(name = "precision")
|
||||
val precision: Int,
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ internal class DefaultOnrampRepository(
|
|||
) = if (error is ApiResponseError.HttpException) {
|
||||
val onrampError = onrampErrorConverter.convert(value = error.errorBody.orEmpty())
|
||||
if (onrampError is OnrampError.AmountError) {
|
||||
OnrampQuote.Error(
|
||||
OnrampQuote.AmountError(
|
||||
paymentMethod = paymentMethod,
|
||||
provider = provider,
|
||||
fromAmount = fromOnrampAmount,
|
||||
|
|
@ -473,7 +473,10 @@ internal class DefaultOnrampRepository(
|
|||
)
|
||||
} else {
|
||||
Timber.w(error, "Unable to fetch onramp quotes for ${provider.id}. $error")
|
||||
null
|
||||
OnrampQuote.Error(
|
||||
paymentMethod = paymentMethod,
|
||||
provider = provider,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Timber.w(error, "Unable to fetch onramp quotes for ${provider.id}. $error")
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable
|
|||
data class OnrampCurrency(
|
||||
val name: String,
|
||||
val code: String,
|
||||
val image: String,
|
||||
val image: String?,
|
||||
val precision: Int,
|
||||
val unit: String,
|
||||
)
|
||||
|
|
@ -23,7 +23,7 @@ sealed interface OnrampProviderWithQuote {
|
|||
|
||||
data class Error(
|
||||
override val provider: OnrampProvider,
|
||||
val quoteError: OnrampQuote.Error,
|
||||
val quoteError: OnrampQuote.AmountError,
|
||||
) : Unavailable
|
||||
}
|
||||
}
|
||||
|
|
@ -16,10 +16,15 @@ sealed class OnrampQuote {
|
|||
val maxFromAmount: OnrampAmount,
|
||||
) : OnrampQuote()
|
||||
|
||||
data class Error(
|
||||
data class AmountError(
|
||||
override val paymentMethod: OnrampPaymentMethod,
|
||||
override val provider: OnrampProvider,
|
||||
val fromAmount: OnrampAmount,
|
||||
val error: OnrampError.AmountError,
|
||||
) : OnrampQuote()
|
||||
|
||||
data class Error(
|
||||
override val paymentMethod: OnrampPaymentMethod,
|
||||
override val provider: OnrampProvider,
|
||||
) : OnrampQuote()
|
||||
}
|
||||
|
|
@ -31,8 +31,8 @@ class GetOnrampProviderWithQuoteUseCase(
|
|||
private fun List<OnrampQuote>.quoteWithProvider(
|
||||
provider: OnrampProvider,
|
||||
selectedPaymentMethod: OnrampPaymentMethod,
|
||||
): OnrampProviderWithQuote {
|
||||
val matchedQuote = firstOrNull { it.paymentMethod == selectedPaymentMethod }
|
||||
): OnrampProviderWithQuote? {
|
||||
val matchedQuote = firstOrNull { it.paymentMethod.id == selectedPaymentMethod.id }
|
||||
return when (matchedQuote) {
|
||||
is OnrampQuote.Data -> OnrampProviderWithQuote.Data(
|
||||
provider = matchedQuote.provider,
|
||||
|
|
@ -40,14 +40,23 @@ class GetOnrampProviderWithQuoteUseCase(
|
|||
toAmount = matchedQuote.toAmount,
|
||||
fromAmount = matchedQuote.fromAmount,
|
||||
)
|
||||
is OnrampQuote.Error -> Unavailable.Error(
|
||||
is OnrampQuote.AmountError -> Unavailable.Error(
|
||||
provider = matchedQuote.provider,
|
||||
quoteError = matchedQuote,
|
||||
)
|
||||
null -> Unavailable.NotSupportedPaymentMethod(
|
||||
provider = provider,
|
||||
availablePaymentMethods = provider.paymentMethods,
|
||||
)
|
||||
is OnrampQuote.Error -> null
|
||||
null -> {
|
||||
val availablePaymentMethods = getAvailablePaymentMethods(provider)
|
||||
Unavailable.NotSupportedPaymentMethod(
|
||||
provider = provider,
|
||||
availablePaymentMethods = availablePaymentMethods,
|
||||
).takeIf { availablePaymentMethods.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<OnrampQuote>.getAvailablePaymentMethods(provider: OnrampProvider) = provider.paymentMethods
|
||||
.filter { pm ->
|
||||
filter { it !is OnrampQuote.Error }.any { it.paymentMethod.id == pm.id }
|
||||
}
|
||||
}
|
||||
|
|
@ -47,9 +47,9 @@ class GetOnrampQuotesUseCase(
|
|||
grouped.value.sortedByDescending {
|
||||
when (it) {
|
||||
is OnrampQuote.Data -> it.toAmount.value
|
||||
|
||||
is OnrampQuote.Error -> null
|
||||
// negative difference to sort both when data and unavailable is present
|
||||
is OnrampQuote.Error -> {
|
||||
is OnrampQuote.AmountError -> {
|
||||
when (val error = it.error) {
|
||||
is OnrampError.AmountError.TooSmallError -> it.fromAmount.value - error.requiredAmount
|
||||
is OnrampError.AmountError.TooBigError -> error.requiredAmount - it.fromAmount.value
|
||||
|
|
|
|||
|
|
@ -10,7 +10,12 @@ internal data class OnrampAmountBlockUM(
|
|||
val secondaryFieldModel: OnrampAmountSecondaryFieldUM,
|
||||
)
|
||||
|
||||
internal data class OnrampCurrencyUM(val code: String, val iconUrl: String, val precision: Int, val onClick: () -> Unit)
|
||||
internal data class OnrampCurrencyUM(
|
||||
val code: String,
|
||||
val iconUrl: String?,
|
||||
val precision: Int,
|
||||
val onClick: () -> Unit,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal sealed interface OnrampAmountSecondaryFieldUM {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ internal class OnrampAmountStateFactory(
|
|||
|
||||
return currentState.copy(
|
||||
amountBlockState = amountState.copy(
|
||||
secondaryFieldModel = quote.toSecondaryFieldUiModel(amountState),
|
||||
secondaryFieldModel = quote.toSecondaryFieldUiModel(amountState) ?: amountState.secondaryFieldModel,
|
||||
),
|
||||
providerBlockState = quote.toProviderBlockState(isBestRate),
|
||||
buyButtonConfig = currentState.buyButtonConfig.copy(
|
||||
|
|
@ -175,19 +175,20 @@ internal class OnrampAmountStateFactory(
|
|||
)
|
||||
}
|
||||
|
||||
private fun OnrampQuote.toSecondaryFieldUiModel(amountState: OnrampAmountBlockUM): OnrampAmountSecondaryFieldUM {
|
||||
private fun OnrampQuote.toSecondaryFieldUiModel(amountState: OnrampAmountBlockUM): OnrampAmountSecondaryFieldUM? {
|
||||
return when (this) {
|
||||
is OnrampQuote.Error -> null
|
||||
is OnrampQuote.Data -> {
|
||||
val amount = toAmount.value.format {
|
||||
crypto(symbol = toAmount.symbol, decimals = toAmount.decimals)
|
||||
}
|
||||
OnrampAmountSecondaryFieldUM.Content(stringReference(amount))
|
||||
}
|
||||
is OnrampQuote.Error -> this.toSecondaryFieldUiModel(amountState)
|
||||
is OnrampQuote.AmountError -> this.toSecondaryFieldUiModel(amountState)
|
||||
}
|
||||
}
|
||||
|
||||
private fun OnrampQuote.Error.toSecondaryFieldUiModel(
|
||||
private fun OnrampQuote.AmountError.toSecondaryFieldUiModel(
|
||||
amountState: OnrampAmountBlockUM,
|
||||
): OnrampAmountSecondaryFieldUM.Error {
|
||||
val amount = error.requiredAmount.format {
|
||||
|
|
|
|||
|
|
@ -196,6 +196,8 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
|
||||
private fun subscribeToQuotesUpdate() {
|
||||
getOnrampQuotesUseCase.invoke()
|
||||
.distinctUntilChanged()
|
||||
.conflate()
|
||||
.onEach { maybeQuotes ->
|
||||
maybeQuotes.fold(
|
||||
ifLeft = ::handleOnrampError,
|
||||
|
|
@ -269,7 +271,7 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun handleQuoteResult(quotes: List<OnrampQuote>) {
|
||||
quotes.filterIsInstance<OnrampQuote.Error>().forEach { errorState ->
|
||||
quotes.filterIsInstance<OnrampQuote.AmountError>().forEach { errorState ->
|
||||
sendOnrampErrorAnalytic(errorState.error)
|
||||
}
|
||||
|
||||
|
|
@ -299,12 +301,12 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
paymentMethod = quote.paymentMethod.name,
|
||||
),
|
||||
)
|
||||
}
|
||||
_state.update {
|
||||
amountStateFactory.getAmountSecondaryUpdatedState(
|
||||
quote = quote,
|
||||
isBestRate = isBestProvider,
|
||||
)
|
||||
_state.update {
|
||||
amountStateFactory.getAmountSecondaryUpdatedState(
|
||||
quote = quote,
|
||||
isBestRate = isBestProvider,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,6 @@ sealed class SelectProviderResult {
|
|||
data class ProviderWithError(
|
||||
override val paymentMethod: OnrampPaymentMethod,
|
||||
override val provider: OnrampProvider,
|
||||
val quoteError: OnrampQuote.Error,
|
||||
val quoteError: OnrampQuote.AmountError,
|
||||
) : SelectProviderResult()
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ sealed class OnrampSuccessComponentUM {
|
|||
data class Content(
|
||||
val txId: String,
|
||||
val timestamp: Long,
|
||||
val currencyImageUrl: String,
|
||||
val currencyImageUrl: String?,
|
||||
val fromAmount: TextReference,
|
||||
val toAmount: TextReference,
|
||||
val statusBlock: ExpressStatusUM,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue