diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 51d8c6a65b..6591e77f82 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -947,6 +947,7 @@ %s min Available from + Available up to You get Service is provided by an external provider. \nTangem is not responsible. You can close this screen and check the transaction status on the token details screen. diff --git a/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampPaymentMethodGroup.kt b/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampPaymentMethodGroup.kt index 68d0fd7c24..14173b152f 100644 --- a/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampPaymentMethodGroup.kt +++ b/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampPaymentMethodGroup.kt @@ -13,5 +13,10 @@ data class OnrampPaymentMethodGroup( sealed interface PaymentMethodStatus { data object Available : PaymentMethodStatus - data class Unavailable(val availableFrom: BigDecimal) : PaymentMethodStatus + sealed interface Unavailable : PaymentMethodStatus { + val requiredAmount: BigDecimal + + data class MinAmount(override val requiredAmount: BigDecimal) : Unavailable + data class MaxAmount(override val requiredAmount: BigDecimal) : Unavailable + } } \ No newline at end of file diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampAllOffersUseCase.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampAllOffersUseCase.kt index 148202162c..970018eeee 100644 --- a/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampAllOffersUseCase.kt +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampAllOffersUseCase.kt @@ -167,10 +167,16 @@ class GetOnrampAllOffersUseCase( return if (hasAtLeastOneValidQuote) { PaymentMethodStatus.Available } else { - val minSum = methodQuotes - .filterIsInstance() - .minOfOrNull { it.error.requiredAmount } ?: BigDecimal.ZERO - PaymentMethodStatus.Unavailable(minSum) + val amountErrorQuotes = methodQuotes.filterIsInstance() + val minAmountErrors = amountErrorQuotes.filter { it.error is OnrampError.AmountError.TooSmallError } + + if (minAmountErrors.isNotEmpty()) { + val minRequiredAmount = minAmountErrors.minOf { it.error.requiredAmount } + PaymentMethodStatus.Unavailable.MinAmount(minRequiredAmount) + } else { + val maxAmount = amountErrorQuotes.maxOfOrNull { it.error.requiredAmount } ?: BigDecimal.ZERO + PaymentMethodStatus.Unavailable.MaxAmount(maxAmount) + } } } } \ No newline at end of file diff --git a/domain/onramp/src/test/kotlin/com/tangem/domain/onramp/GetOnrampAllOffersUseCaseTest.kt b/domain/onramp/src/test/kotlin/com/tangem/domain/onramp/GetOnrampAllOffersUseCaseTest.kt index 6158e843b4..c6b773442b 100644 --- a/domain/onramp/src/test/kotlin/com/tangem/domain/onramp/GetOnrampAllOffersUseCaseTest.kt +++ b/domain/onramp/src/test/kotlin/com/tangem/domain/onramp/GetOnrampAllOffersUseCaseTest.kt @@ -240,7 +240,7 @@ class GetOnrampAllOffersUseCaseTest { val cardGroup = offers.first() Truth.assertThat( cardGroup.methodStatus, - ).isEqualTo(PaymentMethodStatus.Unavailable(BigDecimal("50.0"))) + ).isEqualTo(PaymentMethodStatus.Unavailable.MinAmount(BigDecimal("50.0"))) Truth.assertThat(cardGroup.offers).hasSize(2) Truth.assertThat(cardGroup.bestRateOffer).isNotNull() @@ -446,14 +446,17 @@ class GetOnrampAllOffersUseCaseTest { paymentMethod: OnrampPaymentMethod, provider: OnrampProvider, requiredAmount: BigDecimal = BigDecimal("50.0"), + isMinAmountError: Boolean = true, ): OnrampQuote.AmountError { return mockk { every { this@mockk.paymentMethod } returns paymentMethod every { this@mockk.provider } returns provider every { this@mockk.fromAmount } returns createMockAmount(BigDecimal("10.0")) every { this@mockk.countryCode } returns "US" - every { this@mockk.error } returns mockk { - every { this@mockk.requiredAmount } returns requiredAmount + every { this@mockk.error } returns if (isMinAmountError) { + OnrampError.AmountError.TooSmallError(requiredAmount = requiredAmount) + } else { + OnrampError.AmountError.TooBigError(requiredAmount = requiredAmount) } } } diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/alloffers/entity/AllOffersStateFactory.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/alloffers/entity/AllOffersStateFactory.kt index 6692632302..6035f80287 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/alloffers/entity/AllOffersStateFactory.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/alloffers/entity/AllOffersStateFactory.kt @@ -175,9 +175,14 @@ internal class AllOffersStateFactory( offer: OnrampOffer, currencyCode: String, ): OnrampOfferUM { + val advantages = when (quote.error) { + is OnrampError.AmountError.TooSmallError -> OnrampOfferAdvantagesUM.Unavailable.MinAmount + is OnrampError.AmountError.TooBigError -> OnrampOfferAdvantagesUM.Unavailable.MaxAmount + } + return OnrampOfferUM( category = OnrampOfferCategoryUM.Recommended, - advantages = OnrampOfferAdvantagesUM.Unavailable, + advantages = advantages, paymentMethod = quote.paymentMethod, providerName = quote.provider.info.name, rate = formatRequiredAmount(quote, currencyCode), diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/alloffers/ui/PaymentMethodsContent.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/alloffers/ui/PaymentMethodsContent.kt index 928989b690..46ca3d4017 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/alloffers/ui/PaymentMethodsContent.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/alloffers/ui/PaymentMethodsContent.kt @@ -108,6 +108,7 @@ private fun PaymentMethod(methodUM: AllOffersPaymentMethodUM, modifier: Modifier UnavailablePaymentMethodInfoBlock( paymentMethodName = methodUM.methodConfig.method.name, errorAmount = methodUM.rate, + unavailableStatus = methodUM.paymentMethodStatus, ) } } @@ -116,7 +117,11 @@ private fun PaymentMethod(methodUM: AllOffersPaymentMethodUM, modifier: Modifier } @Composable -private fun UnavailablePaymentMethodInfoBlock(paymentMethodName: String, errorAmount: String) { +private fun UnavailablePaymentMethodInfoBlock( + paymentMethodName: String, + errorAmount: String, + unavailableStatus: PaymentMethodStatus.Unavailable, +) { Column(modifier = Modifier.padding(bottom = 14.dp)) { Text( text = paymentMethodName, @@ -125,8 +130,12 @@ private fun UnavailablePaymentMethodInfoBlock(paymentMethodName: String, errorAm modifier = Modifier.testTag(SelectPaymentMethodBottomSheetTestTags.PAYMENT_METHOD_NAME), ) SpacerH(2.dp) + val messageResId = when (unavailableStatus) { + is PaymentMethodStatus.Unavailable.MinAmount -> R.string.onramp_provider_min_amount + is PaymentMethodStatus.Unavailable.MaxAmount -> R.string.onramp_provider_max_amount + } Text( - text = stringResourceSafe(R.string.onramp_provider_min_amount, errorAmount), + text = stringResourceSafe(messageResId, errorAmount), style = TangemTheme.typography.caption2, color = TangemTheme.colors.text.tertiary, modifier = Modifier.testTag(SelectPaymentMethodBottomSheetTestTags.UP_TO_TEXT), diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/OnrampOfferBlockUM.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/OnrampOfferBlockUM.kt index 89e414f3d5..f731c6e29c 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/OnrampOfferBlockUM.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/entity/OnrampOfferBlockUM.kt @@ -34,8 +34,16 @@ internal enum class OnrampOfferCategoryUM { RecentlyUsed, Recommended } -internal enum class OnrampOfferAdvantagesUM { - Default, BestRate, GreatRate, Fastest, Unavailable; +internal sealed interface OnrampOfferAdvantagesUM { + data object Default : OnrampOfferAdvantagesUM + data object BestRate : OnrampOfferAdvantagesUM + data object GreatRate : OnrampOfferAdvantagesUM + data object Fastest : OnrampOfferAdvantagesUM + + sealed interface Unavailable : OnrampOfferAdvantagesUM { + data object MinAmount : Unavailable + data object MaxAmount : Unavailable + } fun toAnalyticsEvent( cryptoCurrencySymbol: String, @@ -55,7 +63,7 @@ internal enum class OnrampOfferAdvantagesUM { ) Default, BestRate, - Unavailable, + is Unavailable, -> null } } diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/ui/OnrampOffersContent.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/ui/OnrampOffersContent.kt index 0eaace88c0..eeb6351799 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/ui/OnrampOffersContent.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/mainv2/ui/OnrampOffersContent.kt @@ -119,7 +119,7 @@ internal fun Offer(onrampOfferUM: OnrampOfferUM, modifier: Modifier = Modifier) RateBlock( rate = onrampOfferUM.rate, diff = onrampOfferUM.diff, - isOfferUnavailable = onrampOfferUM.advantages == OnrampOfferAdvantagesUM.Unavailable, + isOfferUnavailable = onrampOfferUM.advantages is OnrampOfferAdvantagesUM.Unavailable, ) } SpacerWMax() @@ -127,7 +127,7 @@ internal fun Offer(onrampOfferUM: OnrampOfferUM, modifier: Modifier = Modifier) size = TangemButtonSize.RoundedAction, text = stringResourceSafe(R.string.common_buy), onClick = onrampOfferUM.onBuyClicked, - enabled = onrampOfferUM.advantages != OnrampOfferAdvantagesUM.Unavailable, + enabled = onrampOfferUM.advantages !is OnrampOfferAdvantagesUM.Unavailable, ) } SpacerH(10.dp) @@ -184,9 +184,13 @@ private fun OfferHeader(advantage: OnrampOfferAdvantagesUM) { color = TangemTheme.colors.icon.attention, ) } - OnrampOfferAdvantagesUM.Unavailable -> { + is OnrampOfferAdvantagesUM.Unavailable -> { + val textResId = when (advantage) { + OnrampOfferAdvantagesUM.Unavailable.MinAmount -> R.string.onramp_title_available_from + OnrampOfferAdvantagesUM.Unavailable.MaxAmount -> R.string.onramp_title_available_up_to + } Text( - text = stringResourceSafe(R.string.onramp_title_available_from), + text = stringResourceSafe(textResId), style = TangemTheme.typography.caption1, color = TangemTheme.colors.text.tertiary, )