diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExpressErrorResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExpressErrorResponse.kt index ea8a552360..d3e2fd0694 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExpressErrorResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExpressErrorResponse.kt @@ -23,6 +23,9 @@ data class ExpressErrorValue( @Json(name = "minAmount") val minAmount: String?, + @Json(name = "maxAmount") + val maxAmount: String?, + @Json(name = "decimals") val decimals: Int?, diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index efdc1b3d26..d5cb28c7c0 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -232,6 +232,7 @@ Провайдер Лучший курс Доступно с %s + Доступно до %s Недоступно для этой пары Требуется разрешение Условиями использования @@ -693,8 +694,9 @@ Чтобы совершить транзакцию, вам необходимо внести немного %1$s %2$s Невозможно покрыть комиссию %s Cервис временно недоступен - Пожалуйста, измените сумму для обмена + Пожалуйста, измените сумму для обмена Сумма для обмена должна быть не менее %s + Сумма для обмена должна быть не более %s Возможно, данная карта - образец или подделка Ошибка проверки подлинности На этой карте осталось всего %s подписей. Вам следует вывести все ваши средства. diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 125fb77911..82870064e4 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -235,6 +235,7 @@ Provider Best rate Available from %s + Available up to %s Unavailable for this pair Permission Required Terms of Use @@ -709,8 +710,9 @@ To make a transaction you need to deposit some %1$s %2$s Unable to cover %s fee Service temporarily unavailable - Please change the amount to swap + Please change the amount to swap The amount to swap must be at least %s + The amount of tokens to be swapped must not exceed %s This card might be a production sample or counterfeit Authenticity check failed Only %s signatures are left on this card. You must withdraw all of your funds. diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt index fa28cf44f2..dca890c55e 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ErrorsDataConverter.kt @@ -11,7 +11,7 @@ internal class ErrorsDataConverter( private val jsonAdapter: JsonAdapter, ) : Converter { - @Suppress("MagicNumber") + @Suppress("MagicNumber", "CyclomaticComplexMethod") override fun convert(value: String): DataError { try { val error = jsonAdapter.fromJson(value)?.error ?: return DataError.UnknownError @@ -23,6 +23,7 @@ internal class ErrorsDataConverter( 2230 -> DataError.ExchangeProviderNotAvailableError(code = error.code) 2240 -> DataError.ExchangeNotPossibleError(code = error.code) 2250 -> tryParseExchangeTooSmallAmountError(error = error) + 2251 -> tryParseExchangeTooBigAmountError(error = error) 2260 -> tryParseExchangeNotEnoughAllowanceError(error = error) 2270 -> DataError.ExchangeNotEnoughBalanceError(code = error.code) 2280 -> DataError.ExchangeInvalidAddressError(code = error.code) @@ -44,6 +45,16 @@ internal class ErrorsDataConverter( ) } + private fun tryParseExchangeTooBigAmountError(error: ExpressError): DataError { + val minAmount = error.value?.maxAmount ?: return DataError.UnknownErrorWithCode(error.code) + val decimals = error.value?.decimals ?: return DataError.UnknownErrorWithCode(error.code) + + return DataError.ExchangeTooBigAmountError( + code = error.code, + amount = createFromAmountWithOffset(minAmount, decimals), + ) + } + private fun tryParseExchangeNotEnoughAllowanceError(error: ExpressError): DataError { val currentAllowance = error.value?.currentAllowance ?: return DataError.UnknownErrorWithCode(error.code) diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt index 0da33b0bcf..21c40c5588 100644 --- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt +++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt @@ -18,6 +18,8 @@ sealed class DataError { data class ExchangeTooSmallAmountError(override val code: Int, val amount: SwapAmount) : DataError() + data class ExchangeTooBigAmountError(override val code: Int, val amount: SwapAmount) : DataError() + data class ExchangeNotEnoughAllowanceError(override val code: Int, val currentAllowance: BigDecimal) : DataError() data class ExchangeNotEnoughBalanceError(override val code: Int) : DataError() diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt index 931563da97..eaddec7e0c 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/ProviderItem.kt @@ -146,7 +146,7 @@ private fun ProviderContentState( } Row( modifier = Modifier.padding( - top = TangemTheme.dimens.spacing8, + top = TangemTheme.dimens.spacing6, end = TangemTheme.dimens.spacing56, ), ) { @@ -238,7 +238,7 @@ private fun ProviderUnavailableState( text = it.resolveReference(), style = TangemTheme.typography.body2, color = TangemTheme.colors.text.tertiary, - modifier = Modifier.padding(top = TangemTheme.dimens.spacing8), + modifier = Modifier.padding(top = TangemTheme.dimens.spacing6), ) } } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index 76f84dc0e2..d6a880f213 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -534,6 +534,16 @@ internal class StateBuilder( onProviderClick = onProviderClick, ) } + is DataError.ExchangeTooBigAmountError -> { + swapProvider.convertToAvailableFromProviderState( + alertText = resourceReference( + R.string.express_provider_max_amount, + wrappedList(dataError.amount.getFormattedCryptoAmount(fromToken)), + ), + selectionType = selectionType, + onProviderClick = onProviderClick, + ) + } else -> { ProviderState.Empty() } @@ -548,7 +558,17 @@ internal class StateBuilder( id = R.string.warning_express_too_minimal_amount_title, formatArgs = wrappedList(dataError.amount.getFormattedCryptoAmount(fromToken)), ), - subtitle = resourceReference(R.string.warning_express_too_minimal_amount_description), + subtitle = resourceReference(R.string.warning_express_wrong_amount_description), + iconResId = R.drawable.ic_alert_circle_24, + ), + ) + is DataError.ExchangeTooBigAmountError -> SwapWarning.GeneralError( + notificationConfig = NotificationConfig( + title = resourceReference( + id = R.string.warning_express_too_maximum_amount_title, + formatArgs = wrappedList(dataError.amount.getFormattedCryptoAmount(fromToken)), + ), + subtitle = resourceReference(R.string.warning_express_wrong_amount_description), iconResId = R.drawable.ic_alert_circle_24, ), ) diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt index c95f3ed693..ace4cb9006 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -99,8 +99,9 @@ internal class SwapViewModel @Inject constructor( private val lastAmount = mutableStateOf(INITIAL_AMOUNT) private var swapRouter: SwapRouter by Delegates.notNull() - private val isExchangeTooSmallAmountError: (SwapState) -> Boolean = { - it is SwapState.SwapError && it.error is DataError.ExchangeTooSmallAmountError + private val isUserResolvableError: (SwapState) -> Boolean = { + it is SwapState.SwapError && + (it.error is DataError.ExchangeTooSmallAmountError || it.error is DataError.ExchangeTooBigAmountError) } val currentScreen: SwapNavScreen @@ -1001,7 +1002,7 @@ internal class SwapViewModel @Inject constructor( private fun Map.consideredProvidersStates(): Map { return this.filter { - it.value is SwapState.QuotesLoadedState || isExchangeTooSmallAmountError(it.value) + it.value is SwapState.QuotesLoadedState || isUserResolvableError(it.value) } }