diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeStatusResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeStatusResponse.kt
index 94cd9cbf1f..3be2a6ebec 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeStatusResponse.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeStatusResponse.kt
@@ -48,6 +48,9 @@ enum class ExchangeStatus {
@Json(name = "verifying")
VERIFYING,
+
+ @Json(name = "cancelled")
+ CANCELLED,
}
data class ExchangeStatusError(
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index c2434991f2..afc6fda219 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -205,6 +205,7 @@
Операция не выполнена провайдером
Посетите сайт провайдера для проверки
Провайдер запрашивает прохождение верификации
+ Отменен
Подтверждено
Подтверждение
Подтверждение...
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 7998107847..6548a846ee 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -205,7 +205,7 @@
Operation failed by provider
Visit provider’s website for verification
KYC verification required by provider
- Cancelled
+ Canceled
Confirmed
Confirming
Confirming…
diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeStatus.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeStatus.kt
index e412c74751..1e3727b208 100644
--- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeStatus.kt
+++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/domain/ExchangeStatus.kt
@@ -17,4 +17,5 @@ enum class ExchangeStatus {
Sending,
Finished,
Refunded,
+ Cancelled,
}
\ No newline at end of file
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/SwapTransactionsState.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/SwapTransactionsState.kt
index d55821009b..c1e0f67210 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/SwapTransactionsState.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/SwapTransactionsState.kt
@@ -29,6 +29,7 @@ internal data class SwapTransactionsState(
val fromCryptoSymbol: String,
val fromFiatAmount: String,
val fromCurrencyIcon: TokenIconState,
+ val showProviderLink: Boolean,
val onClick: () -> Unit,
val onGoToProviderClick: (String) -> Unit,
)
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt
index 514afc7709..c5069303c7 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt
@@ -62,6 +62,8 @@ internal class TokenDetailsSwapTransactionsStateConverter(
val toFiatAmount = toAmount.multiply(toCurrency.value.fiatRate)
val fromFiatAmount = fromAmount.multiply(fromCurrency.value.fiatRate)
val timestamp = transaction.timestamp
+ val notifications = getNotification(transaction.status?.status, transaction.status?.txExternalUrl)
+ val showProviderLink = getShowProviderLink(notifications, transaction.status)
result.add(
SwapTransactionsState(
txId = transaction.txId,
@@ -92,6 +94,7 @@ internal class TokenDetailsSwapTransactionsStateConverter(
fromCryptoSymbol = fromCurrency.currency.symbol,
fromFiatAmount = getFiatAmount(fromFiatAmount),
fromCurrencyIcon = iconStateConverter.convert(fromCurrency),
+ showProviderLink = showProviderLink,
onClick = { clickIntents.onSwapTransactionClick(transaction.txId) },
onGoToProviderClick = { url ->
analyticsEventsHandlerProvider().send(
@@ -109,12 +112,15 @@ internal class TokenDetailsSwapTransactionsStateConverter(
fun updateTxStatus(tx: SwapTransactionsState, statusModel: ExchangeStatusModel?): SwapTransactionsState {
if (statusModel == null || tx.activeStatus == statusModel.status) return tx
val hasFailed = tx.hasFailed || statusModel.status == ExchangeStatus.Failed
+ val notifications = getNotification(statusModel.status, statusModel.txExternalUrl)
+ val showProviderLink = getShowProviderLink(notifications, statusModel)
return tx.copy(
activeStatus = statusModel.status,
hasFailed = hasFailed,
- notification = getNotification(statusModel.status, statusModel.txExternalUrl),
+ notification = notifications,
statuses = getStatuses(statusModel.status, hasFailed),
txUrl = statusModel.txExternalUrl,
+ showProviderLink = showProviderLink,
)
}
@@ -149,6 +155,9 @@ internal class TokenDetailsSwapTransactionsStateConverter(
}
}
+ private fun getShowProviderLink(notifications: ExchangeStatusNotifications?, status: ExchangeStatusModel?) =
+ notifications == null && status?.txExternalUrl != null && status.status != ExchangeStatus.Cancelled
+
private fun getStatuses(status: ExchangeStatus?, hasFailed: Boolean = false): ImmutableList {
if (status == null) return persistentListOf()
val isWaiting = status == ExchangeStatus.New || status == ExchangeStatus.Waiting
@@ -164,26 +173,37 @@ internal class TokenDetailsSwapTransactionsStateConverter(
val isExchangingDone = !isExchanging && isConfirmingDone
val isSendingDone = !isSending && !isVerifying && !isFailed && isExchangingDone
- return listOf(
- waitStep(isWaiting, isWaitingDone),
- confirmStep(isConfirming, isConfirmingDone),
- exchangeStep(
- isExchanging = isExchanging,
- isExchangingDone = isExchangingDone,
- isRefunded = isRefunded,
- hasFailed = hasFailed,
- isVerifying = isVerifying,
- isFailed = isFailed,
- ),
- sendStep(
- isSending = isSending,
- isSendingDone = isSendingDone,
- isRefunded = isRefunded,
- hasFailed = hasFailed,
- ),
- ).toPersistentList()
+ return if (status == ExchangeStatus.Cancelled) {
+ listOf(cancelledStep())
+ } else {
+ listOf(
+ waitStep(isWaiting, isWaitingDone),
+ confirmStep(isConfirming, isConfirmingDone),
+ exchangeStep(
+ isExchanging = isExchanging,
+ isExchangingDone = isExchangingDone,
+ isRefunded = isRefunded,
+ hasFailed = hasFailed,
+ isVerifying = isVerifying,
+ isFailed = isFailed,
+ ),
+ sendStep(
+ isSending = isSending,
+ isSendingDone = isSendingDone,
+ isRefunded = isRefunded,
+ hasFailed = hasFailed,
+ ),
+ )
+ }.toPersistentList()
}
+ private fun cancelledStep() = ExchangeStatusState(
+ status = ExchangeStatus.Cancelled,
+ text = TextReference.Res(R.string.express_exchange_status_canceled),
+ isActive = true,
+ isDone = true,
+ )
+
private fun waitStep(isNew: Boolean, isNewDone: Boolean) = ExchangeStatusState(
status = ExchangeStatus.New,
text = when {
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBlock.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBlock.kt
index 1574bb2db6..ac5edc4fc4 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBlock.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBlock.kt
@@ -75,11 +75,15 @@ internal fun ExchangeStatusBlock(
}
}
- statuses.forEachIndexed { index, item ->
- ExchangeStatusStep(
- stepStatus = item,
- isLast = index == statuses.lastIndex,
- )
+ AnimatedContent(targetState = statuses.lastIndex, label = "Exchange Status List Change") {
+ Column {
+ statuses.forEachIndexed { index, item ->
+ ExchangeStatusStep(
+ stepStatus = item,
+ isLast = index == it,
+ )
+ }
+ }
}
}
}
@@ -101,6 +105,11 @@ private fun ExchangeStatusStep(
.size(TangemTheme.dimens.size20),
) {
when {
+ it.status == ExchangeStatus.Cancelled -> ExchangeStep(
+ iconRes = R.drawable.ic_close_24,
+ color = TangemTheme.colors.icon.warning,
+ isDone = false,
+ )
it.status == ExchangeStatus.Failed -> ExchangeStep(
iconRes = R.drawable.ic_close_24,
color = TangemTheme.colors.icon.warning,
@@ -131,6 +140,7 @@ private fun ExchangeStatusStep(
@Composable
private fun ExchangeStatusStepText(stepStatus: ExchangeStatusState) {
val textColor = when {
+ stepStatus.status == ExchangeStatus.Cancelled -> TangemTheme.colors.icon.warning
stepStatus.status == ExchangeStatus.Failed && !stepStatus.isDone -> TangemTheme.colors.icon.warning
stepStatus.status == ExchangeStatus.Verifying && !stepStatus.isDone -> TangemTheme.colors.icon.attention
stepStatus.isDone -> TangemTheme.colors.text.primary1
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBottomSheet.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBottomSheet.kt
index ea31904d30..da9113487a 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBottomSheet.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusBottomSheet.kt
@@ -76,7 +76,7 @@ private fun ExchangeStatusBottomSheetContent(content: ExchangeStatusBottomSheetC
SpacerH12()
ExchangeStatusBlock(
statuses = config.statuses,
- showLink = config.notification == null && config.txUrl != null,
+ showLink = config.showProviderLink,
onClick = { config.onGoToProviderClick(config.txUrl.orEmpty()) },
)
AnimatedContent(
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusItems.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusItems.kt
index c32011f436..94c1d12187 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusItems.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/exchange/ExchangeStatusItems.kt
@@ -4,7 +4,9 @@ import androidx.annotation.DrawableRes
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
@@ -42,7 +44,9 @@ internal fun LazyListScope.swapTransactionsItems(
val item = swapTxs[it]
val (iconRes, tint) = when (item.activeStatus) {
ExchangeStatus.Verifying -> R.drawable.ic_alert_triangle_20 to TangemTheme.colors.icon.attention
- ExchangeStatus.Failed -> R.drawable.ic_alert_circle_24 to TangemTheme.colors.icon.warning
+ ExchangeStatus.Failed, ExchangeStatus.Cancelled -> {
+ R.drawable.ic_alert_circle_24 to TangemTheme.colors.icon.warning
+ }
else -> null to null
}
diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt
index 1c3f77a105..fee7ee1a64 100644
--- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt
+++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt
@@ -125,6 +125,7 @@ internal class TokenDetailsViewModel @Inject constructor(
clickIntents = this,
appCurrencyProvider = Provider { selectedAppCurrencyFlow.value },
analyticsEventsHandlerProvider = Provider { analyticsEventsHandler },
+ currentStateProvider = Provider { uiState },
userWalletId = userWalletId,
cryptoCurrency = cryptoCurrency,
)
@@ -229,7 +230,7 @@ internal class TokenDetailsViewModel @Inject constructor(
delay = EXCHANGE_STATUS_UPDATE_DELAY,
task = {
runCatching(dispatchers.io) {
- exchangeStatusFactory.updateSwapTxStatuses(swapTxs)
+ exchangeStatusFactory.updateSwapTxStatuses(uiState.swapTxs)
}
},
onSuccess = ::updateSwapTx,