diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/MoshiModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/MoshiModule.kt
index 53e728d17c..3dd04dc106 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/di/MoshiModule.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/di/MoshiModule.kt
@@ -53,6 +53,7 @@ class MoshiModule {
.withSubtype(PaymentAccountStatusValueDM.UnderReview::class.java, "kyc_status")
.withSubtype(PaymentAccountStatusValueDM.IssuingCard::class.java, "issuing_card")
.withSubtype(PaymentAccountStatusValueDM.ActiveCard::class.java, "active_card")
+ .withSubtype(PaymentAccountStatusValueDM.DeactivatedAccount::class.java, "deactivated_account")
.withSubtype(PaymentAccountStatusValueDM.CardIssueFailed::class.java, "card_issue_failed"),
)
.add(
diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/visa/entity/PaymentAccountStatusValueDM.kt b/core/datasource/src/main/java/com/tangem/datasource/local/visa/entity/PaymentAccountStatusValueDM.kt
index fb91718338..37b8f3cee0 100644
--- a/core/datasource/src/main/java/com/tangem/datasource/local/visa/entity/PaymentAccountStatusValueDM.kt
+++ b/core/datasource/src/main/java/com/tangem/datasource/local/visa/entity/PaymentAccountStatusValueDM.kt
@@ -56,6 +56,12 @@ sealed interface PaymentAccountStatusValueDM {
@Json(name = "customer_id") val customerId: String,
) : PaymentAccountStatusValueDM
+ @NameLabel("deactivated_account")
+ data class DeactivatedAccount(
+ @Json(name = "deactivated_account") val marker: Boolean = true,
+ @Json(name = "fiat_balance") val fiatBalance: FiatBalanceDM,
+ ) : PaymentAccountStatusValueDM
+
@JsonClass(generateAdapter = true)
data class FiatBalanceDM(
@Json(name = "available_balance") val availableBalance: BigDecimal,
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 5b19f4c6fd..1e8b04dd84 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -1568,6 +1568,8 @@
Your card is unfrozen.
Withdrawal
Unable to use on rooted device
+ Your card was deactivated
+ This was done due to regulatory requirements. Anyway withdrawals are still available.
Hide KYC from main screen
Add funds
Top-up options
@@ -1632,6 +1634,7 @@
Unfortunately, we couldn\'t verify your identity
KYC rejected
KYC in progress
+ Card deactivated
View Status
KYC in progress for Tangem Pay
Documents are usually verified automatically within 5 minutes. In rare cases, if manual review is required, it may take up to 48 hours.
diff --git a/data/visa/build.gradle.kts b/data/visa/build.gradle.kts
index 80f1139140..88d718323d 100644
--- a/data/visa/build.gradle.kts
+++ b/data/visa/build.gradle.kts
@@ -12,6 +12,10 @@ android {
namespace = "com.tangem.data.visa"
}
+tasks.withType().configureEach {
+ useJUnitPlatform()
+}
+
dependencies {
/** Project - Data */
@@ -68,4 +72,9 @@ dependencies {
/** DI */
implementation(deps.hilt.android)
kapt(deps.hilt.kapt)
+
+ /** Test */
+ testRuntimeOnly(deps.test.junit5.engine)
+ testImplementation(projects.common.test)
+ testImplementation(projects.test.core)
}
\ No newline at end of file
diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverter.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverter.kt
index 94006aaf9c..92c24a5b12 100644
--- a/data/visa/src/main/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverter.kt
+++ b/data/visa/src/main/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverter.kt
@@ -52,6 +52,9 @@ internal object PaymentAccountStatusValueDMConverter :
customerId = value.customerId,
)
is PaymentAccountStatusValue.Empty -> PaymentAccountStatusValueDM.Empty()
+ is PaymentAccountStatusValue.Deactivated -> PaymentAccountStatusValueDM.DeactivatedAccount(
+ fiatBalance = value.fiatBalance.toDM(),
+ )
// Transient statuses are not persisted
is PaymentAccountStatusValue.Loading,
is PaymentAccountStatusValue.Error.ExposedDevice,
@@ -101,6 +104,10 @@ internal object PaymentAccountStatusValueDMConverter :
kycStatus = value.kycStatus,
customerId = value.customerId,
)
+ is PaymentAccountStatusValueDM.DeactivatedAccount -> PaymentAccountStatusValue.Deactivated(
+ source = StatusSource.CACHE,
+ fiatBalance = value.fiatBalance.toDomain(),
+ )
null -> PaymentAccountStatusValue.Error.Unavailable
}
}
diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/flow/DefaultPaymentAccountStatusFetcher.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/flow/DefaultPaymentAccountStatusFetcher.kt
index 30b61c32ef..c55ac9cb0c 100644
--- a/data/visa/src/main/kotlin/com/tangem/data/pay/flow/DefaultPaymentAccountStatusFetcher.kt
+++ b/data/visa/src/main/kotlin/com/tangem/data/pay/flow/DefaultPaymentAccountStatusFetcher.kt
@@ -48,16 +48,6 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
val account = Account.Payment(userWalletId = params.userWalletId)
logger.i("fetch: ${params.userWalletId.stringValue}")
- if (onboardingRepository.isTangemPayDeactivated(params.userWalletId)) {
- return@catchOn paymentAccountStatusesStore.store(
- userWalletId = params.userWalletId,
- status = AccountStatus.Payment(
- account = account,
- value = PaymentAccountStatusValue.Empty,
- ),
- )
- }
-
if (deviceSecurity.isSecurityExposed()) {
logger.i("fetch security info: rooted: ${deviceSecurity.isRooted}")
logger.i("fetch security info: xposed: ${deviceSecurity.isXposed}")
@@ -254,20 +244,31 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
private fun CustomerInfo.mapToPaymentAccountStatus(): PaymentAccountStatusValue {
val cardInfo = this.cardInfo
val productInstance = this.productInstance
- return if (kycStatus != KycStatus.APPROVED && !customerId.isNullOrEmpty()) {
- PaymentAccountStatusValue.UnderReview(
- source = StatusSource.ACTUAL,
- kycStatus = kycStatus,
- customerId = requireNotNull(customerId) { "CustomerId must not be null" },
- )
- } else if (cardInfo != null && productInstance != null && !customerId.isNullOrEmpty()) {
- convertToContentState(
+
+ val isDeactivated = productInstance?.status == CustomerInfo.ProductInstance.Status.DEACTIVATED
+ val isFormer = state == CustomerInfo.State.FORMER
+ val fiatBalance = fiatBalance
+
+ return when {
+ kycStatus != KycStatus.APPROVED && !customerId.isNullOrEmpty() -> {
+ PaymentAccountStatusValue.UnderReview(
+ source = StatusSource.ACTUAL,
+ kycStatus = kycStatus,
+ customerId = requireNotNull(customerId) { "CustomerId must not be null" },
+ )
+ }
+ fiatBalance != null && (isDeactivated || isFormer) -> {
+ PaymentAccountStatusValue.Deactivated(
+ source = StatusSource.ACTUAL,
+ fiatBalance = fiatBalance,
+ )
+ }
+ cardInfo != null && productInstance != null && !customerId.isNullOrEmpty() -> convertToContentState(
productInstance = productInstance,
cardInfo = cardInfo,
customerId = requireNotNull(customerId) { "CustomerId must not be null" },
)
- } else {
- PaymentAccountStatusValue.IssuingCard(source = StatusSource.ACTUAL)
+ else -> PaymentAccountStatusValue.IssuingCard(source = StatusSource.ACTUAL)
}
}
@@ -306,7 +307,6 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
return when (this) {
is VisaApiError.RefreshTokenExpired -> PaymentAccountStatusValue.Error.NotSynced
is VisaApiError.NotPaeraCustomer -> constructNotCreatedOrEmptyStatus(userWalletId)
- is VisaApiError.Deactivated -> constructNotCreatedOrEmptyStatus(userWalletId)
else -> PaymentAccountStatusValue.Error.Unavailable
}
}
diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultOnboardingRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultOnboardingRepository.kt
index e1f741be61..8eff052a75 100644
--- a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultOnboardingRepository.kt
+++ b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultOnboardingRepository.kt
@@ -2,7 +2,6 @@ package com.tangem.data.pay.repository
import arrow.core.Either
import arrow.core.flatMap
-import arrow.core.left
import arrow.core.right
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.data.pay.store.PaymentAccountStatusesStore
@@ -11,6 +10,7 @@ import com.tangem.datasource.api.pay.models.request.DeeplinkValidityRequest
import com.tangem.datasource.api.pay.models.request.OrderRequest
import com.tangem.datasource.api.pay.models.request.SetTangemPayEnabledRequest
import com.tangem.datasource.api.pay.models.response.CustomerMeResponse
+import com.tangem.datasource.api.pay.models.response.FiatBalance
import com.tangem.datasource.api.pay.models.response.OrderResponse
import com.tangem.datasource.local.visa.TangemPayCardFrozenStateStore
import com.tangem.datasource.local.visa.TangemPayStorage
@@ -101,10 +101,8 @@ internal class DefaultOnboardingRepository @Inject constructor(
val isFormer = result?.state?.let { CustomerInfo.State.fromString(it) } == CustomerInfo.State.FORMER
if (isDeactivated || isFormer) {
tangemPayStorage.storeIsTangemPayDeactivated(userWalletId)
- VisaApiError.Deactivated.left()
- } else {
- getCustomerInfo(userWalletId = userWalletId, response = result).right()
}
+ getCustomerInfo(userWalletId = userWalletId, response = result).right()
}
}
@@ -180,10 +178,7 @@ internal class DefaultOnboardingRepository @Inject constructor(
currencyCode = fiatBalance.currency,
depositAddress = response.depositAddress,
isPinSet = response.card?.isPinSet == true,
- fiatBalance = PaymentAccountStatusValue.FiatBalance(
- availableBalance = fiatBalance.availableBalance,
- currency = fiatBalance.currency,
- ),
+ fiatBalance = fiatBalance.toDomain(),
cryptoBalance = PaymentAccountStatusValue.CryptoBalance(
id = cryptoBalance.id,
chainId = cryptoBalance.chainId.toLong(),
@@ -202,13 +197,20 @@ internal class DefaultOnboardingRepository @Inject constructor(
}
cardFrozenStateStore.store(key = instance.cardId, value = cardFrozenState)
- ProductInstance(id = instance.id, cardId = instance.cardId, frozenState = cardFrozenState)
+ ProductInstance(
+ id = instance.id,
+ cardId = instance.cardId,
+ frozenState = cardFrozenState,
+ status = instance.status.toDomain(),
+ )
}
return CustomerInfo(
customerId = response?.id,
productInstance = productInstance,
kycStatus = kycStatus,
cardInfo = cardInfo,
+ state = response?.state?.let { CustomerInfo.State.fromString(it) } ?: CustomerInfo.State.UNDEFINED,
+ fiatBalance = fiatBalance?.toDomain(),
).also {
lastFetchedCustomerInfoMap[userWalletId] = it
}
@@ -290,4 +292,24 @@ internal class DefaultOnboardingRepository @Inject constructor(
setHideMainOnboardingBanner(userWalletId)
}
}
+}
+
+private fun FiatBalance.toDomain() = PaymentAccountStatusValue.FiatBalance(
+ availableBalance = availableBalance,
+ currency = currency,
+)
+
+private fun CustomerMeResponse.ProductInstance.Status.toDomain() = when (this) {
+ CustomerMeResponse.ProductInstance.Status.NEW -> ProductInstance.Status.NEW
+ CustomerMeResponse.ProductInstance.Status.READY_FOR_MANUFACTURING -> ProductInstance.Status.READY_FOR_MANUFACTURING
+ CustomerMeResponse.ProductInstance.Status.MANUFACTURING -> ProductInstance.Status.MANUFACTURING
+ CustomerMeResponse.ProductInstance.Status.SENT_TO_DELIVERY -> ProductInstance.Status.SENT_TO_DELIVERY
+ CustomerMeResponse.ProductInstance.Status.DELIVERED -> ProductInstance.Status.DELIVERED
+ CustomerMeResponse.ProductInstance.Status.ACTIVATING -> ProductInstance.Status.ACTIVATING
+ CustomerMeResponse.ProductInstance.Status.ACTIVE -> ProductInstance.Status.ACTIVE
+ CustomerMeResponse.ProductInstance.Status.BLOCKED -> ProductInstance.Status.BLOCKED
+ CustomerMeResponse.ProductInstance.Status.DEACTIVATING -> ProductInstance.Status.DEACTIVATING
+ CustomerMeResponse.ProductInstance.Status.DEACTIVATED -> ProductInstance.Status.DEACTIVATED
+ CustomerMeResponse.ProductInstance.Status.CANCELED -> ProductInstance.Status.CANCELED
+ CustomerMeResponse.ProductInstance.Status.UNKNOWN -> ProductInstance.Status.UNKNOWN
}
\ No newline at end of file
diff --git a/data/visa/src/test/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverterTest.kt b/data/visa/src/test/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverterTest.kt
new file mode 100644
index 0000000000..37ac01a0fc
--- /dev/null
+++ b/data/visa/src/test/kotlin/com/tangem/data/pay/converter/PaymentAccountStatusValueDMConverterTest.kt
@@ -0,0 +1,147 @@
+package com.tangem.data.pay.converter
+
+import com.google.common.truth.Truth.assertThat
+import com.tangem.datasource.local.visa.entity.PaymentAccountStatusValueDM
+import com.tangem.domain.models.StatusSource
+import com.tangem.domain.models.account.PaymentAccountStatusValue
+import org.junit.jupiter.api.Nested
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.TestInstance
+import java.math.BigDecimal
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+internal class PaymentAccountStatusValueDMConverterTest {
+
+ @Nested
+ @TestInstance(TestInstance.Lifecycle.PER_CLASS)
+ inner class Convert {
+
+ @Test
+ fun `GIVEN domain Empty WHEN convert THEN returns DM Empty`() {
+ // GIVEN
+ val domain = PaymentAccountStatusValue.Empty
+
+ // WHEN
+ val result = PaymentAccountStatusValueDMConverter.convert(domain)
+
+ // THEN
+ assertThat(result).isInstanceOf(PaymentAccountStatusValueDM.Empty::class.java)
+ }
+
+ @Test
+ fun `GIVEN domain Deactivated with balance WHEN convert THEN returns DM DeactivatedAccount with same balance`() {
+ // GIVEN
+ val domain = PaymentAccountStatusValue.Deactivated(
+ source = StatusSource.ACTUAL,
+ fiatBalance = PaymentAccountStatusValue.FiatBalance(
+ availableBalance = BigDecimal("100"),
+ currency = "USD",
+ )
+ )
+
+ // WHEN
+ val result = PaymentAccountStatusValueDMConverter.convert(domain)
+
+ // THEN
+ assertThat(result).isInstanceOf(PaymentAccountStatusValueDM.DeactivatedAccount::class.java)
+ val dm = result as PaymentAccountStatusValueDM.DeactivatedAccount
+ assertThat(dm.fiatBalance.availableBalance).isEqualTo(BigDecimal("100"))
+ assertThat(dm.fiatBalance.currency).isEqualTo("USD")
+ }
+
+ @Test
+ fun `GIVEN domain Loading WHEN convert THEN returns null (transient, not persisted)`() {
+ // GIVEN
+ val domain = PaymentAccountStatusValue.Loading
+
+ // WHEN
+ val result = PaymentAccountStatusValueDMConverter.convert(domain)
+
+ // THEN
+ assertThat(result).isNull()
+ }
+
+ @Test
+ fun `GIVEN domain Error Unavailable WHEN convert THEN returns null (transient, not persisted)`() {
+ // GIVEN
+ val domain = PaymentAccountStatusValue.Error.Unavailable
+
+ // WHEN
+ val result = PaymentAccountStatusValueDMConverter.convert(domain)
+
+ // THEN
+ assertThat(result).isNull()
+ }
+
+ @Test
+ fun `GIVEN domain NotCreated WHEN convert THEN returns DM NotCreated`() {
+ // GIVEN
+ val domain = PaymentAccountStatusValue.NotCreated
+
+ // WHEN
+ val result = PaymentAccountStatusValueDMConverter.convert(domain)
+
+ // THEN
+ assertThat(result).isInstanceOf(PaymentAccountStatusValueDM.NotCreated::class.java)
+ }
+ }
+
+ @Nested
+ @TestInstance(TestInstance.Lifecycle.PER_CLASS)
+ inner class ConvertBack {
+
+ @Test
+ fun `GIVEN DM Empty WHEN convertBack THEN returns domain Empty`() {
+ // GIVEN
+ val dm = PaymentAccountStatusValueDM.Empty()
+
+ // WHEN
+ val result = PaymentAccountStatusValueDMConverter.convertBack(dm)
+
+ // THEN
+ assertThat(result).isEqualTo(PaymentAccountStatusValue.Empty)
+ }
+
+ @Test
+ fun `GIVEN DM DeactivatedAccount WHEN convertBack THEN returns domain Deactivated with CACHE source`() {
+ // GIVEN
+ val dm = PaymentAccountStatusValueDM.DeactivatedAccount(
+ fiatBalance = PaymentAccountStatusValueDM.FiatBalanceDM(
+ availableBalance = BigDecimal("200"),
+ currency = "EUR",
+ )
+ )
+
+ // WHEN
+ val result = PaymentAccountStatusValueDMConverter.convertBack(dm)
+
+ // THEN
+ assertThat(result).isInstanceOf(PaymentAccountStatusValue.Deactivated::class.java)
+ val deactivated = result as PaymentAccountStatusValue.Deactivated
+ assertThat(deactivated.source).isEqualTo(StatusSource.CACHE)
+ assertThat(deactivated.fiatBalance.availableBalance).isEqualTo(BigDecimal("200"))
+ assertThat(deactivated.fiatBalance.currency).isEqualTo("EUR")
+ }
+
+ @Test
+ fun `GIVEN null DM WHEN convertBack THEN returns Error Unavailable`() {
+ // GIVEN / WHEN
+ val result = PaymentAccountStatusValueDMConverter.convertBack(null)
+
+ // THEN
+ assertThat(result).isEqualTo(PaymentAccountStatusValue.Error.Unavailable)
+ }
+
+ @Test
+ fun `GIVEN DM NotCreated WHEN convertBack THEN returns domain NotCreated`() {
+ // GIVEN
+ val dm = PaymentAccountStatusValueDM.NotCreated()
+
+ // WHEN
+ val result = PaymentAccountStatusValueDMConverter.convertBack(dm)
+
+ // THEN
+ assertThat(result).isEqualTo(PaymentAccountStatusValue.NotCreated)
+ }
+ }
+}
\ No newline at end of file
diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/IsAccountsModeEnabledUseCase.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/IsAccountsModeEnabledUseCase.kt
index ae529e245c..7357b3d7cf 100644
--- a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/IsAccountsModeEnabledUseCase.kt
+++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/IsAccountsModeEnabledUseCase.kt
@@ -56,6 +56,7 @@ class IsAccountsModeEnabledUseCase(
is PaymentAccountStatusValue.Loading,
is PaymentAccountStatusValue.Locked,
is PaymentAccountStatusValue.UnderReview,
+ is PaymentAccountStatusValue.Deactivated,
-> true
}
}
diff --git a/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/IsAccountsModeEnabledUseCaseTest.kt b/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/IsAccountsModeEnabledUseCaseTest.kt
index 02aa942198..0366176714 100644
--- a/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/IsAccountsModeEnabledUseCaseTest.kt
+++ b/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/IsAccountsModeEnabledUseCaseTest.kt
@@ -150,6 +150,21 @@ class IsAccountsModeEnabledUseCaseTest {
Truth.assertThat(actual).isTrue()
}
+ @Test
+ fun `GIVEN payment account is Deactivated WHEN invoke THEN returns true`() = runTest {
+ // GIVEN
+ val statusList = createAccountStatusList(
+ statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk())),
+ )
+ every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
+
+ // WHEN
+ val actual = useCase.invoke().first()
+
+ // THEN
+ Truth.assertThat(actual).isTrue()
+ }
+
@Test
fun `returns true when multiple status lists and one has two crypto portfolios`() = runTest {
val statusList1 = createAccountStatusList(statuses = listOf(mockCryptoPortfolio()))
@@ -270,6 +285,21 @@ class IsAccountsModeEnabledUseCaseTest {
Truth.assertThat(actual).isTrue()
}
+ @Test
+ fun `GIVEN payment account is Deactivated WHEN invokeSync THEN returns true`() = runTest {
+ // GIVEN
+ val statusList = createAccountStatusList(
+ statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk())),
+ )
+ coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns listOf(statusList)
+
+ // WHEN
+ val actual = useCase.invokeSync()
+
+ // THEN
+ Truth.assertThat(actual).isTrue()
+ }
+
@Test
fun `returns true when multiple status lists and one has loaded payment`() = runTest {
val statusList1 = createAccountStatusList(statuses = listOf(mockCryptoPortfolio()))
diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/account/PaymentAccountStatusValue.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/account/PaymentAccountStatusValue.kt
index 542733a235..058d78d061 100644
--- a/domain/models/src/main/kotlin/com/tangem/domain/models/account/PaymentAccountStatusValue.kt
+++ b/domain/models/src/main/kotlin/com/tangem/domain/models/account/PaymentAccountStatusValue.kt
@@ -27,6 +27,7 @@ sealed class PaymentAccountStatusValue {
is Loading -> TotalFiatBalance.Loading
is Locked -> TotalFiatBalance.Loaded(amount = fiatBalance.availableBalance, source = source)
is Loaded -> TotalFiatBalance.Loaded(amount = fiatBalance.availableBalance, source = source)
+ is Deactivated -> TotalFiatBalance.Loaded(amount = fiatBalance.availableBalance, source = source)
}
/**
@@ -40,6 +41,7 @@ sealed class PaymentAccountStatusValue {
is Loaded -> copy(source = source)
is Locked -> copy(source = source)
is UnderReview -> copy(source = source)
+ is Deactivated -> copy(source = source)
is Loading,
is Empty,
is NotCreated,
@@ -88,6 +90,18 @@ sealed class PaymentAccountStatusValue {
@Serializable
data class IssuingCard(override val source: StatusSource) : PaymentAccountStatusValue()
+ /**
+ * Represents a state where the account is deactivated.
+ *
+ * @property source The source of the status information.
+ * @property fiatBalance The fiat balance details.
+ */
+ @Serializable
+ data class Deactivated(
+ override val source: StatusSource,
+ val fiatBalance: FiatBalance,
+ ) : PaymentAccountStatusValue()
+
/**
* Represents a state where the payment account is locked.
*
diff --git a/domain/visa/models/src/main/kotlin/com/tangem/domain/pay/TangemPayDetailsConfig.kt b/domain/visa/models/src/main/kotlin/com/tangem/domain/pay/TangemPayDetailsConfig.kt
index e2424a061a..2906021583 100644
--- a/domain/visa/models/src/main/kotlin/com/tangem/domain/pay/TangemPayDetailsConfig.kt
+++ b/domain/visa/models/src/main/kotlin/com/tangem/domain/pay/TangemPayDetailsConfig.kt
@@ -11,4 +11,5 @@ data class TangemPayDetailsConfig(
val cardFrozenState: TangemPayCardFrozenState,
val cardNumberEnd: String,
val chainId: Int,
+ val isTangemPayDeactivated: Boolean,
)
\ No newline at end of file
diff --git a/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/error/VisaError.kt b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/error/VisaError.kt
index 1ebfcecd9a..be321d6b33 100644
--- a/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/error/VisaError.kt
+++ b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/error/VisaError.kt
@@ -57,7 +57,6 @@ sealed class VisaApiError(
data object CustomerIsBlocked : VisaApiError(104110210)
data object UnknownWithoutCode : VisaApiError(104110999)
data class Unknown(override val errorCode: Int) : VisaApiError(errorCode)
- data object Deactivated : VisaApiError(0)
fun isUnknown() = this is UnknownWithoutCode || this is Unknown
diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/CustomerInfo.kt b/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/CustomerInfo.kt
index a35e9adaea..dac433e459 100644
--- a/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/CustomerInfo.kt
+++ b/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/CustomerInfo.kt
@@ -23,6 +23,8 @@ data class CustomerInfo(
val productInstance: ProductInstance?,
val kycStatus: KycStatus,
val cardInfo: CardInfo?,
+ val state: State,
+ val fiatBalance: PaymentAccountStatusValue.FiatBalance?,
) {
enum class State {
NEW,
@@ -49,7 +51,23 @@ data class CustomerInfo(
val id: String,
val cardId: String,
val frozenState: TangemPayCardFrozenState,
- )
+ val status: Status,
+ ) {
+ enum class Status {
+ NEW,
+ READY_FOR_MANUFACTURING,
+ MANUFACTURING,
+ SENT_TO_DELIVERY,
+ DELIVERED,
+ ACTIVATING,
+ ACTIVE,
+ BLOCKED,
+ DEACTIVATING,
+ DEACTIVATED,
+ CANCELED,
+ UNKNOWN,
+ }
+ }
data class CardInfo(
val lastFourDigits: String,
diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayCustomerInfoError.kt b/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayCustomerInfoError.kt
index 07e4dc7bb8..e2086cfed3 100644
--- a/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayCustomerInfoError.kt
+++ b/domain/visa/src/main/kotlin/com/tangem/domain/pay/model/TangemPayCustomerInfoError.kt
@@ -6,5 +6,4 @@ sealed interface TangemPayCustomerInfoError {
data object RefreshNeededError : TangemPayCustomerInfoError
data object UnknownError : TangemPayCustomerInfoError
data object ExposedDeviceError : TangemPayCustomerInfoError
- data object DeactivatedError : TangemPayCustomerInfoError
}
\ No newline at end of file
diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/pay/usecase/TangemPayMainScreenCustomerInfoUseCase.kt b/domain/visa/src/main/kotlin/com/tangem/domain/pay/usecase/TangemPayMainScreenCustomerInfoUseCase.kt
index 04780f63c1..2e62f7190e 100644
--- a/domain/visa/src/main/kotlin/com/tangem/domain/pay/usecase/TangemPayMainScreenCustomerInfoUseCase.kt
+++ b/domain/visa/src/main/kotlin/com/tangem/domain/pay/usecase/TangemPayMainScreenCustomerInfoUseCase.kt
@@ -62,10 +62,6 @@ class TangemPayMainScreenCustomerInfoUseCase(
}
val result = proceedWithPaeraCustomerResult(userWalletId)
- if (result.leftOrNull() is TangemPayCustomerInfoError.DeactivatedError) {
- updateState(userWalletId, MainCustomerInfoContentState.Empty.right())
- return
- }
updateState(userWalletId, result.map(MainCustomerInfoContentState::Content))
} else {
// if there's no tangem pay, check eligibility and show onboarding banner
@@ -172,7 +168,6 @@ class TangemPayMainScreenCustomerInfoUseCase(
return when (this) {
is VisaApiError.RefreshTokenExpired -> TangemPayCustomerInfoError.RefreshNeededError
is VisaApiError.NotPaeraCustomer -> TangemPayCustomerInfoError.UnknownError
- is VisaApiError.Deactivated -> TangemPayCustomerInfoError.DeactivatedError
else -> TangemPayCustomerInfoError.UnavailableError
}
}
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt
index 8fb38c33bc..eba5584f1c 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsStateFactory.kt
@@ -5,6 +5,7 @@ import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
import com.tangem.core.ui.components.dropdownmenu.TangemDropdownMenuItem
import com.tangem.core.ui.components.notifications.NotificationConfig
+import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.themedColor
import com.tangem.core.ui.res.TangemTheme
@@ -12,6 +13,7 @@ import com.tangem.domain.visa.model.TangemPayCardFrozenState
import com.tangem.features.tangempay.details.impl.R
import com.tangem.features.tangempay.model.transformers.TangemPayCardFrozenStateConverter
import com.tangem.features.tangempay.utils.TangemPayDetailIntents
+import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
@@ -23,51 +25,13 @@ internal class TangemPayDetailsStateFactory(
private val cardFrozenState: TangemPayCardFrozenState,
private val converter: TangemPayCardFrozenStateConverter,
) {
-
@Suppress("LongMethod")
- fun getInitialState(): TangemPayDetailsUM {
- val cardFrozenStateItem = when (cardFrozenState) {
- is TangemPayCardFrozenState.Pending -> null
- is TangemPayCardFrozenState.Frozen -> TangemPayDetailsTopBarMenuItem(
- type = TangemPayDetailsTopBarMenuItemType.UnfreezeCard,
- dropdownItem = TangemDropdownMenuItem(
- title = resourceReference(R.string.tangempay_card_details_unfreeze_card),
- textColor = themedColor { TangemTheme.colors.text.primary1 },
- onClick = intents::onClickUnfreezeCard,
- ),
- )
- is TangemPayCardFrozenState.Unfrozen -> TangemPayDetailsTopBarMenuItem(
- type = TangemPayDetailsTopBarMenuItemType.FreezeCard,
- dropdownItem = TangemDropdownMenuItem(
- title = resourceReference(R.string.tangempay_card_details_freeze_card),
- textColor = themedColor { TangemTheme.colors.text.primary1 },
- onClick = intents::onClickFreezeCard,
- ),
- )
- }
+ fun getInitialState(isTangemPayDeactivated: Boolean): TangemPayDetailsUM {
return TangemPayDetailsUM(
topBarConfig = TangemPayDetailsTopBarConfig(
onBackClick = onBack,
onOpenMenu = onOpenMenu,
- items = listOfNotNull(
- TangemPayDetailsTopBarMenuItem(
- type = TangemPayDetailsTopBarMenuItemType.ChangePin,
- dropdownItem = TangemDropdownMenuItem(
- title = resourceReference(R.string.tangempay_card_details_pin_code),
- textColor = themedColor { TangemTheme.colors.text.primary1 },
- onClick = intents::onClickPinCode,
- ),
- ),
- TangemPayDetailsTopBarMenuItem(
- type = TangemPayDetailsTopBarMenuItemType.TermsAndLimits,
- dropdownItem = TangemDropdownMenuItem(
- title = resourceReference(R.string.tangem_pay_terms_limits),
- textColor = themedColor { TangemTheme.colors.text.primary1 },
- onClick = intents::onClickTermsAndLimits,
- ),
- ),
- cardFrozenStateItem,
- ).toPersistentList(),
+ items = getTopBarMenuItems().takeIf { !isTangemPayDeactivated },
),
pullToRefreshConfig = PullToRefreshConfig(
isRefreshing = false,
@@ -92,17 +56,67 @@ internal class TangemPayDetailsStateFactory(
addToWalletBlockState = null,
isBalanceHidden = false,
addFundsEnabled = true,
- cardFrozenState = converter.convert(cardFrozenState),
- betaNotificationConfig = NotificationConfig(
- title = resourceReference(R.string.tangem_pay_beta_notification_title),
- subtitle = resourceReference(R.string.tangem_pay_beta_notification_subtitle),
- iconResId = R.drawable.img_visa_notification,
- buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
- text = resourceReference(R.string.common_contact_support),
- onClick = intents::onContactSupportClicked,
- ),
- iconSize = 36.dp,
- ),
+ cardFrozenState = getCardFrozenState().takeIf { !isTangemPayDeactivated },
+ betaNotificationConfig = getBetaNotificationConfig().takeIf { !isTangemPayDeactivated },
+ accountDeactivatedNotificationConfig = NotificationConfig(
+ title = TextReference.Res(R.string.tangempay_account_deactivated_message_title),
+ subtitle = TextReference.Res(R.string.tangempay_account_deactivated_message_subtitle),
+ iconResId = R.drawable.img_attention_20,
+ ).takeIf { isTangemPayDeactivated },
)
}
+
+ private fun getCardFrozenState() = converter.convert(cardFrozenState)
+
+ private fun getBetaNotificationConfig() = NotificationConfig(
+ title = resourceReference(R.string.tangem_pay_beta_notification_title),
+ subtitle = resourceReference(R.string.tangem_pay_beta_notification_subtitle),
+ iconResId = R.drawable.img_visa_notification,
+ buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
+ text = resourceReference(R.string.common_contact_support),
+ onClick = intents::onContactSupportClicked,
+ ),
+ iconSize = 36.dp,
+ )
+
+ private fun getTopBarMenuItems(): ImmutableList {
+ val cardFrozenStateItem = when (cardFrozenState) {
+ is TangemPayCardFrozenState.Pending -> null
+ is TangemPayCardFrozenState.Frozen -> TangemPayDetailsTopBarMenuItem(
+ type = TangemPayDetailsTopBarMenuItemType.UnfreezeCard,
+ dropdownItem = TangemDropdownMenuItem(
+ title = resourceReference(R.string.tangempay_card_details_unfreeze_card),
+ textColor = themedColor { TangemTheme.colors.text.primary1 },
+ onClick = intents::onClickUnfreezeCard,
+ ),
+ )
+ is TangemPayCardFrozenState.Unfrozen -> TangemPayDetailsTopBarMenuItem(
+ type = TangemPayDetailsTopBarMenuItemType.FreezeCard,
+ dropdownItem = TangemDropdownMenuItem(
+ title = resourceReference(R.string.tangempay_card_details_freeze_card),
+ textColor = themedColor { TangemTheme.colors.text.primary1 },
+ onClick = intents::onClickFreezeCard,
+ ),
+ )
+ }
+ return listOfNotNull(
+ TangemPayDetailsTopBarMenuItem(
+ type = TangemPayDetailsTopBarMenuItemType.ChangePin,
+ dropdownItem = TangemDropdownMenuItem(
+ title = resourceReference(R.string.tangempay_card_details_pin_code),
+ textColor = themedColor { TangemTheme.colors.text.primary1 },
+ onClick = intents::onClickPinCode,
+ ),
+ ),
+ TangemPayDetailsTopBarMenuItem(
+ type = TangemPayDetailsTopBarMenuItemType.TermsAndLimits,
+ dropdownItem = TangemDropdownMenuItem(
+ title = resourceReference(R.string.tangem_pay_terms_limits),
+ textColor = themedColor { TangemTheme.colors.text.primary1 },
+ onClick = intents::onClickTermsAndLimits,
+ ),
+ ),
+ cardFrozenStateItem,
+ ).toPersistentList()
+ }
}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt
index f67ed6b7b0..000fd9d0b5 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsUM.kt
@@ -15,8 +15,9 @@ internal data class TangemPayDetailsUM(
val addToWalletBlockState: AddToWalletBlockState?,
val isBalanceHidden: Boolean,
val addFundsEnabled: Boolean,
- val cardFrozenState: CardFrozenState,
- val betaNotificationConfig: NotificationConfig,
+ val cardFrozenState: CardFrozenState?,
+ val betaNotificationConfig: NotificationConfig?,
+ val accountDeactivatedNotificationConfig: NotificationConfig?,
)
internal data class TangemPayCardDetailsUM(
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt
index 87c07ef8ba..1afea757d7 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt
@@ -55,14 +55,11 @@ import com.tangem.features.tokendetails.ExpressTransactionsEventListener
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
+import com.tangem.utils.logging.TangemLogger
import com.tangem.utils.transformer.update
import kotlinx.coroutines.Job
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
-import com.tangem.utils.logging.TangemLogger
import javax.inject.Inject
@Suppress("LongParameterList", "LargeClass")
@@ -98,7 +95,7 @@ internal class TangemPayDetailsModel @Inject constructor(
)
val uiState: StateFlow
- field = MutableStateFlow(stateFactory.getInitialState())
+ field = MutableStateFlow(stateFactory.getInitialState(params.config.isTangemPayDeactivated))
private val refreshStateJobHolder = JobHolder()
private val fetchBalanceJobHolder = JobHolder()
@@ -116,9 +113,11 @@ internal class TangemPayDetailsModel @Inject constructor(
init {
analytics.send(TangemPayAnalyticsEvents.MainScreenOpened())
handleBalanceHiding()
- fetchAddToWalletBanner()
fetchBalance()
- subscribeToCardFrozenState()
+ if (!params.config.isTangemPayDeactivated) {
+ fetchAddToWalletBanner()
+ subscribeToCardFrozenState()
+ }
}
fun onResume() {
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt
index 1e3a51c9a4..2ecb3a0fc6 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreen.kt
@@ -25,6 +25,7 @@ import androidx.compose.ui.util.fastForEach
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.RectangleShimmer
+import com.tangem.core.ui.components.SpacerH12
import com.tangem.core.ui.components.buttons.HorizontalActionChips
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
@@ -86,13 +87,16 @@ internal fun TangemPayDetailsScreen(
bottom = TangemTheme.dimens.spacing16 + bottomBarHeight,
),
) {
- item(TangemPayCardDetailsUM::class.java) {
- cardDetailsBlockComponent.CardDetailsBlockContent(
- modifier = Modifier
- .padding(horizontal = 16.dp)
- .padding(top = 8.dp),
- state = cardDetailsState,
- )
+ if (state.accountDeactivatedNotificationConfig == null) {
+ item(TangemPayCardDetailsUM::class.java) {
+ cardDetailsBlockComponent.CardDetailsBlockContent(
+ modifier = Modifier
+ .padding(horizontal = 16.dp)
+ .padding(top = 8.dp),
+ state = cardDetailsState,
+ )
+ SpacerH12()
+ }
}
when (state.cardFrozenState) {
is CardFrozenState.Frozen -> item(CardFrozenState.Frozen::class.java) {
@@ -100,11 +104,11 @@ internal fun TangemPayDetailsScreen(
modifier = Modifier
.animateItem()
.padding(horizontal = 16.dp)
- .padding(top = 12.dp)
.fillMaxWidth(),
text = stringResourceSafe(R.string.tangempay_card_details_unfreeze_card),
onClick = state.cardFrozenState.onUnfreeze,
)
+ SpacerH12()
}
else -> Unit
}
@@ -115,9 +119,9 @@ internal fun TangemPayDetailsScreen(
TangemPayAddToWalletBlock(
state = state.addToWalletBlockState,
modifier = Modifier
- .padding(top = TangemTheme.dimens.spacing12)
.padding(horizontal = TangemTheme.dimens.spacing16),
)
+ SpacerH12()
},
)
}
@@ -127,34 +131,52 @@ internal fun TangemPayDetailsScreen(
TangemPayDetailsBalanceBlock(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing16)
- .padding(top = 12.dp)
.fillMaxWidth(),
state = state.balanceBlockState,
isBalanceHidden = state.isBalanceHidden,
)
+ SpacerH12()
},
)
- item(
- key = "TANGEM_PAY_IS_IN_BETA",
- content = {
- TangemPayBetaBlock(
- modifier = modifier
- .padding(horizontal = TangemTheme.dimens.spacing16)
- .padding(top = 12.dp)
- .fillMaxWidth(),
- config = state.betaNotificationConfig,
- )
- },
- )
- with(expressTransactionsComponent) {
- expressTransactionsContent(
- state = expressState.transactionsToDisplay,
- modifier = modifier
- .padding(start = 16.dp, end = 16.dp, top = 12.dp)
- .fillMaxWidth(),
+ if (state.accountDeactivatedNotificationConfig != null) {
+ item(
+ key = "DEACTIVATION_MESSAGE",
+ content = {
+ Notification(
+ modifier = modifier
+ .padding(horizontal = TangemTheme.dimens.spacing16)
+ .fillMaxWidth(),
+ config = state.accountDeactivatedNotificationConfig,
+ )
+ SpacerH12()
+ },
)
}
- with(txHistoryComponent) { txHistoryContent(listState = listState, state = txHistoryState) }
+ if (state.betaNotificationConfig != null) {
+ item(
+ key = "TANGEM_PAY_IS_IN_BETA",
+ content = {
+ TangemPayBetaBlock(
+ modifier = modifier
+ .padding(horizontal = TangemTheme.dimens.spacing16)
+ .fillMaxWidth(),
+ config = state.betaNotificationConfig,
+ )
+ SpacerH12()
+ },
+ )
+ }
+ if (state.accountDeactivatedNotificationConfig == null) {
+ with(expressTransactionsComponent) {
+ expressTransactionsContent(
+ state = expressState.transactionsToDisplay,
+ modifier = modifier
+ .padding(horizontal = 16.dp)
+ .fillMaxWidth(),
+ )
+ }
+ with(txHistoryComponent) { txHistoryContent(listState = listState, state = txHistoryState) }
+ }
}
}
expressTransactionsBottomSheetState?.content()
@@ -349,6 +371,7 @@ private class TangemPayDetailsUMProvider : CollectionPreviewParameterProvider null
}
notification?.let(::add)
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetWalletNotificationsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetWalletNotificationsFactory.kt
index c119fc6251..931e87bff3 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetWalletNotificationsFactory.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetWalletNotificationsFactory.kt
@@ -240,6 +240,7 @@ internal class GetWalletNotificationsFactory @Inject constructor(
is PaymentAccountStatusValue.Locked,
is PaymentAccountStatusValue.UnderReview,
is PaymentAccountStatusValue.Empty,
+ is PaymentAccountStatusValue.Deactivated,
-> null
}
notification?.let(::add)
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/TangemPayUpdateInfoStateTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/TangemPayUpdateInfoStateTransformer.kt
index 3e1615a6e2..91e7b3a263 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/TangemPayUpdateInfoStateTransformer.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/TangemPayUpdateInfoStateTransformer.kt
@@ -80,6 +80,7 @@ internal class TangemPayUpdateInfoStateTransformer(
cardFrozenState = cardFrozenState,
cardNumberEnd = cardInfo.lastFourDigits,
chainId = POLYGON_CHAIN_ID,
+ isTangemPayDeactivated = false,
),
)
},
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TangemPayMainBlockConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TangemPayMainBlockConverter.kt
index fef7fb08bb..dcad0972b5 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TangemPayMainBlockConverter.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TangemPayMainBlockConverter.kt
@@ -56,6 +56,31 @@ internal class TangemPayMainBlockConverter(
is PaymentAccountStatusValue.Empty -> TangemPayMainUM.Empty
is PaymentAccountStatusValue.NotCreated -> TangemPayMainUM.Empty
is PaymentAccountStatusValue.Loading -> TangemPayMainUM.Loading
+ is PaymentAccountStatusValue.Deactivated -> TangemPayMainUM.Content(
+ subtitle = TextReference.Res(R.string.tangempay_status_deactivated),
+ isBalanceFlickering = statusValue.source == StatusSource.CACHE,
+ balance = getBalanceText(
+ currencyCode = statusValue.fiatBalance.currency,
+ balance = statusValue.fiatBalance.availableBalance,
+ ),
+ balanceSubtitle = stringReference("USDC"), // TODO hardcode for now
+ shouldShowOnlyCacheWarning = statusValue.source == StatusSource.ONLY_CACHE,
+ onClick = {
+ // Dummy config for deactivated account just to open details screen
+ tangemPayClickIntents.openDetails(
+ userWalletId = value.account.userWalletId,
+ config = TangemPayDetailsConfig(
+ customerId = "",
+ cardId = "",
+ isPinSet = false,
+ cardFrozenState = TangemPayCardFrozenState.Unfrozen,
+ cardNumberEnd = "",
+ chainId = POLYGON_CHAIN_ID,
+ isTangemPayDeactivated = true,
+ ),
+ )
+ },
+ )
is PaymentAccountStatusValue.Locked -> TangemPayMainUM.Content(
subtitle = stringReference("*${statusValue.lastFourDigits}"),
isBalanceFlickering = statusValue.source == StatusSource.CACHE,
@@ -75,6 +100,7 @@ internal class TangemPayMainBlockConverter(
cardFrozenState = TangemPayCardFrozenState.Frozen,
cardNumberEnd = statusValue.lastFourDigits,
chainId = POLYGON_CHAIN_ID,
+ isTangemPayDeactivated = false,
),
)
},
@@ -98,6 +124,7 @@ internal class TangemPayMainBlockConverter(
cardFrozenState = TangemPayCardFrozenState.Unfrozen,
cardNumberEnd = statusValue.lastFourDigits,
chainId = POLYGON_CHAIN_ID,
+ isTangemPayDeactivated = false,
),
)
},
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TangemPayMainSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TangemPayMainSubscriber.kt
index a800e1a2a7..cc818aa976 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TangemPayMainSubscriber.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TangemPayMainSubscriber.kt
@@ -65,11 +65,6 @@ internal class TangemPayMainSubscriber @AssistedInject constructor(
TangemPayCustomerInfoError.ExposedDeviceError -> {
stateController.update(TangemPayExposedDeviceTransformer(userWalletId))
}
- TangemPayCustomerInfoError.DeactivatedError -> {
- stateController.update(
- transformer = TangemPayHiddenStateTransformer(userWalletId),
- )
- }
TangemPayCustomerInfoError.UnknownError -> {
// hide TangemPay block
TangemLogger.e("Failed when loading main screen TangemPay info: $tangemPayError")