diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 6fe946df8b..391fe57950 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -647,6 +647,8 @@
Не для пользователя!
Cеть %1$s использует концепцию экзистенциального депозита. Если баланс вашего счета будет ниже %2$s, то он будет деактивирован, а средства на счете уничтожены.
Для работы с сетью необходим депозит
+ Обмен будет доступен после завершения %s транзакции
+ У вас есть активная транзакция
У вас в списке нет монет доступных для обмена с %s
Нет доступных токенов для обмена
Cервис временно недоступен
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index cbd1bf2dab..340dc79988 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -677,6 +677,8 @@
Not for users!
%1$s network requires an Existential Deposit. If your account drops below %2$s, it will be deactivated, and any remaining funds will be destroyed.
Network requires Existential Deposit
+ Swap will be available after the %s transaction is complete
+ You have active transaction
You do not have any %s exchangeable coins in your list
No available tokens to swap
To make a transaction you need to deposit some %1$s %2$s
diff --git a/features/swap/domain/build.gradle.kts b/features/swap/domain/build.gradle.kts
index f3841b400d..b1a50d2773 100644
--- a/features/swap/domain/build.gradle.kts
+++ b/features/swap/domain/build.gradle.kts
@@ -28,6 +28,7 @@ dependencies {
implementation(projects.domain.demo)
implementation(projects.domain.card)
implementation(projects.domain.appCurrency.models)
+ implementation(projects.domain.txhistory.models)
/** Core modules */
implementation(projects.core.utils)
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 6504c6d53a..f15db9df11 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
@@ -420,7 +420,6 @@ internal class SwapInteractorImpl @Inject constructor(
permissionState = PermissionDataState.Empty,
preparedSwapConfigState = state.preparedSwapConfigState.copy(
isBalanceEnough = includeFeeInAmount !is IncludeFeeInAmount.BalanceNotEnough,
- isFeeEnough = includeFeeInAmount !is IncludeFeeInAmount.BalanceNotEnough,
includeFeeInAmount = includeFeeInAmount,
),
)
@@ -798,6 +797,7 @@ internal class SwapInteractorImpl @Inject constructor(
isFeeEnough = includeFeeInAmount !is IncludeFeeInAmount.BalanceNotEnough,
isAllowedToSpend = isAllowedToSpend,
isBalanceEnough = isBalanceWithoutFeeEnough,
+ hasOutgoingTransaction = hasOutgoingTransaction(fromToken),
includeFeeInAmount = includeFeeInAmount,
),
)
@@ -873,7 +873,7 @@ internal class SwapInteractorImpl @Inject constructor(
/**
* Load swap data calls only if spend is allowed for token contract address
*/
- @Suppress("LongParameterList")
+ @Suppress("LongParameterList", "LongMethod")
private suspend fun loadDexSwapData(
provider: SwapProvider,
networkId: String,
@@ -932,6 +932,7 @@ internal class SwapInteractorImpl @Inject constructor(
isAllowedToSpend = true,
isBalanceEnough = isBalanceIncludeFeeEnough,
isFeeEnough = isFeeEnough,
+ hasOutgoingTransaction = hasOutgoingTransaction(fromToken),
includeFeeInAmount = IncludeFeeInAmount.Excluded, // exclude for dex
),
)
@@ -1226,6 +1227,10 @@ internal class SwapInteractorImpl @Inject constructor(
}
}
+ private fun hasOutgoingTransaction(cryptoCurrencyStatuses: CryptoCurrencyStatus): Boolean {
+ return cryptoCurrencyStatuses.value.pendingTransactions.any { it.isOutgoing }
+ }
+
private fun Fee.getGasLimit(): Int {
return when (this) {
is Fee.Common -> 0
diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/PreparedSwapConfigState.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/PreparedSwapConfigState.kt
index 53cfae4ded..ca44dc046e 100644
--- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/PreparedSwapConfigState.kt
+++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/PreparedSwapConfigState.kt
@@ -14,6 +14,7 @@ data class PreparedSwapConfigState(
val isAllowedToSpend: Boolean,
val isBalanceEnough: Boolean,
val isFeeEnough: Boolean,
+ val hasOutgoingTransaction: Boolean,
val includeFeeInAmount: IncludeFeeInAmount,
)
diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt
index d031891ba3..d2788d35a4 100644
--- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt
+++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt
@@ -19,6 +19,7 @@ sealed interface SwapState {
isAllowedToSpend = false,
isBalanceEnough = false,
isFeeEnough = false,
+ hasOutgoingTransaction = false,
includeFeeInAmount = IncludeFeeInAmount.Excluded,
),
val permissionState: PermissionDataState = PermissionDataState.Empty,
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt
index e30eff225c..ae4d9ba3cf 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt
@@ -6,6 +6,7 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.components.states.Item
import com.tangem.core.ui.components.states.SelectableItemsState
+import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.feature.swap.domain.models.ui.TxFee
import com.tangem.feature.swap.models.states.FeeItemState
@@ -125,6 +126,7 @@ sealed interface SwapWarning {
data class TooSmallAmountWarning(val notificationConfig: NotificationConfig) : SwapWarning
data class UnableToCoverFeeWarning(val notificationConfig: NotificationConfig) : SwapWarning
data class GeneralWarning(val notificationConfig: NotificationConfig) : SwapWarning
+ data class TransactionInProgressWarning(val title: TextReference, val description: TextReference) : SwapWarning
}
enum class GenericWarningType {
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 51f6936885..9c3b990219 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
@@ -261,6 +261,7 @@ private fun ProviderLoadingState(modifier: Modifier = Modifier) {
CircularProgressIndicator(
modifier = Modifier.size(TangemTheme.dimens.size16),
color = TangemTheme.colors.icon.informative,
+ strokeWidth = TangemTheme.dimens.size2,
)
Text(
text = "Fetching best rates ...",
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 6881df60df..7042da2c25 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
@@ -320,6 +320,26 @@ internal class StateBuilder(
),
)
}
+ if (quoteModel.permissionState is PermissionDataState.PermissionLoading) {
+ warnings.add(
+ SwapWarning.TransactionInProgressWarning(
+ title = resourceReference(R.string.swapping_pending_transaction_title),
+ description = resourceReference(R.string.swapping_pending_transaction_subtitle),
+ ),
+ )
+ } else if (quoteModel.preparedSwapConfigState.hasOutgoingTransaction) {
+ warnings.add(
+ SwapWarning.TransactionInProgressWarning(
+ title = resourceReference(R.string.warning_express_active_transaction_title),
+ description = resourceReference(
+ id = R.string.warning_express_active_transaction_message,
+ formatArgs = wrappedList(
+ quoteModel.fromTokenInfo.cryptoCurrencyStatus.currency.network.currencySymbol,
+ ),
+ ),
+ ),
+ )
+ }
return warnings
}
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
index ace1d19a31..8d1fe2e6df 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt
@@ -20,6 +20,7 @@ import com.tangem.core.ui.components.*
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.extensions.getActiveIconResByCoinId
+import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.swap.domain.models.ui.FeeType
@@ -67,20 +68,6 @@ internal fun SwapScreenContent(state: SwapStateHolder, modifier: Modifier = Modi
if (state.warnings.isNotEmpty()) SwapWarnings(warnings = state.warnings)
- AnimatedVisibility(visible = state.permissionState is SwapPermissionState.InProgress) {
- CardWithIcon(
- title = stringResource(id = R.string.swapping_pending_transaction_title),
- description = stringResource(id = R.string.swapping_pending_transaction_subtitle),
- icon = {
- CircularProgressIndicator(
- modifier = Modifier
- .size(TangemTheme.dimens.size16),
- color = TangemTheme.colors.icon.primary1,
- strokeWidth = TangemTheme.dimens.size2,
- )
- },
- )
- }
MainButton(state = state, onPermissionWarningClick = state.onShowPermissionBottomSheet)
}
}
@@ -285,6 +272,20 @@ private fun SwapWarnings(warnings: List) {
config = warning.notificationConfig,
)
}
+ is SwapWarning.TransactionInProgressWarning -> {
+ CardWithIcon(
+ title = warning.title.resolveReference(),
+ description = warning.description.resolveReference(),
+ icon = {
+ CircularProgressIndicator(
+ modifier = Modifier
+ .size(TangemTheme.dimens.size16),
+ color = TangemTheme.colors.icon.primary1,
+ strokeWidth = TangemTheme.dimens.size2,
+ )
+ },
+ )
+ }
else -> {}
}
SpacerH8()