diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index 5bda69385c..c95c7319f5 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -154,7 +154,7 @@ internal class SwapInteractorImpl @Inject constructor( val amount = SwapAmount(amountDecimal, getTokenDecimals(fromToken)) val fromTokenAddress = getTokenAddress(fromToken) val toTokenAddress = getTokenAddress(toToken) - val isAllowedToSpend = checkAllowance(networkId, fromTokenAddress) + val isAllowedToSpend = isAllowedToSpend(networkId, fromTokenAddress, amount) if (isAllowedToSpend && allowPermissionsHandler.isAddressAllowanceInProgress(fromTokenAddress)) { allowPermissionsHandler.removeAddressFromProgress(fromTokenAddress) transactionManager.updateWalletManager(networkId, derivationPath) @@ -295,13 +295,14 @@ internal class SwapInteractorImpl @Inject constructor( } } - private suspend fun checkAllowance(networkId: String, fromTokenAddress: String): Boolean { + private suspend fun isAllowedToSpend(networkId: String, fromTokenAddress: String, amount: SwapAmount): Boolean { val allowance = repository.checkTokensSpendAllowance( networkId = networkId, tokenAddress = fromTokenAddress, walletAddress = userWalletManager.getWalletAddress(networkId, derivationPath), ) - return allowance.error == DataError.NoError && allowance.dataModel != ZERO_BALANCE + val allowanceAmount = allowance.dataModel?.toBigDecimalOrNull() ?: BigDecimal.ZERO + return allowance.error == DataError.NoError && allowanceAmount >= amount.value.movePointRight(amount.decimals) } private fun createEmptyAmountState(networkId: String, fromToken: Currency, toToken: Currency): SwapState { 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 eb2b1d67e7..88cd6f81f6 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 @@ -103,10 +103,20 @@ internal class StateBuilder(val actions: UiActions) { ) } + /** + * Create quotes loaded state + * + * @param uiStateHolder whole screen state + * @param quoteModel data model + * @param fromToken token data to swap + * @param onFeeSetup callback for reset fee after auto update + * @return updated whole screen state + */ fun createQuotesLoadedState( uiStateHolder: SwapStateHolder, quoteModel: SwapState.QuotesLoadedState, fromToken: Currency, + onFeeSetup: (TxFee) -> Unit, ): SwapStateHolder { val warnings = mutableListOf() if (!quoteModel.preparedSwapConfigState.isAllowedToSpend && @@ -122,7 +132,7 @@ internal class StateBuilder(val actions: UiActions) { if (quoteModel.priceImpact > PRICE_IMPACT_THRESHOLD) { warnings.add(SwapWarning.HighPriceImpact((quoteModel.priceImpact * HUNDRED_PERCENTS).toInt())) } - val feeState = createFeeState(quoteModel, uiStateHolder) + val feeState = createFeeState(quoteModel, uiStateHolder, onFeeSetup) return uiStateHolder.copy( sendCardData = SwapCardData( type = requireNotNull(uiStateHolder.sendCardData.type as? TransactionCardType.SendCard), @@ -282,22 +292,31 @@ internal class StateBuilder(val actions: UiActions) { } } - private fun createFeeState(quoteModel: SwapState.QuotesLoadedState, uiStateHolder: SwapStateHolder): FeeState { + private fun createFeeState( + quoteModel: SwapState.QuotesLoadedState, + uiStateHolder: SwapStateHolder, + onFeeSetup: (TxFee) -> Unit, + ): FeeState { val previousFeeState = when (val stateFee = uiStateHolder.fee) { is FeeState.Loaded -> stateFee.state is FeeState.NotEnoughFundsWarning -> stateFee.state else -> null } + val selectFeeState = createSelectFeeState( + fee = quoteModel.swapDataModel?.fee, + previousState = previousFeeState, + onFeeSetup = onFeeSetup, + ) return if (quoteModel.preparedSwapConfigState.isFeeEnough) { FeeState.Loaded( tangemFee = quoteModel.tangemFee, - state = createSelectFeeState(quoteModel.swapDataModel?.fee, previousFeeState), + state = selectFeeState, onSelectItem = actions.onSelectItemFee, ) } else { FeeState.NotEnoughFundsWarning( tangemFee = quoteModel.tangemFee, - state = createSelectFeeState(quoteModel.swapDataModel?.fee, previousFeeState), + state = selectFeeState, onSelectItem = actions.onSelectItemFee, ) } @@ -422,9 +441,11 @@ internal class StateBuilder(val actions: UiActions) { private fun createSelectFeeState( fee: TxFeeState?, previousState: SelectableItemsState?, + onFeeSetup: (TxFee) -> Unit, ): SelectableItemsState? { if (fee == null) return null if (previousState == null) { + onFeeSetup.invoke(fee.normalFee) // if there is no previous state, setup normal fee by default val selectedItemId = 0 // by default preselect normal val preselectedItem = Item( @@ -469,8 +490,10 @@ internal class StateBuilder(val actions: UiActions) { ), ) val selectedEndText = if (normalFeeItem.isSelected) { + onFeeSetup.invoke(fee.normalFee) normalFeeItem.endText } else { + onFeeSetup.invoke(fee.priorityFee) priorityFeeItem.endText } return previousState.copy( 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 260ebe4623..2376e4c61e 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 @@ -184,7 +184,11 @@ internal class SwapViewModel @Inject constructor( uiStateHolder = uiState, quoteModel = swapState, fromToken = fromToken, - ) + ) { updatedFee -> + dataState = dataState.copy( + selectedFee = updatedFee, + ) + } } is SwapState.EmptyAmountState -> { uiState = stateBuilder.createQuotesEmptyAmountState( @@ -213,6 +217,7 @@ internal class SwapViewModel @Inject constructor( } else { dataState.copy( swapDataModel = swapDataModel, + selectedFee = swapDataModel?.fee?.normalFee, ) } }