From 1037d2ff103a1be2d85413284387bb7596e66c42 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 24 Dec 2025 12:01:22 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/data/DefaultTangemPayStorage.kt | 34 +++++++++++++------ .../local/preferences/PreferencesKeys.kt | 1 + .../datasource/local/visa/TangemPayStorage.kt | 3 ++ .../pay/DefaultTangemPayEligibilityManager.kt | 10 +++++- .../repository/DefaultOnboardingRepository.kt | 10 +++++- .../domain/pay/TangemPayEligibilityManager.kt | 1 + .../pay/repository/OnboardingRepository.kt | 1 + .../features/details/model/DetailsModel.kt | 17 ++++++++-- .../features/details/utils/ItemsBuilder.kt | 24 +++++++++---- 9 files changed, 79 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/data/DefaultTangemPayStorage.kt b/app/src/main/java/com/tangem/tap/data/DefaultTangemPayStorage.kt index a6f6497a39..fb02cff093 100644 --- a/app/src/main/java/com/tangem/tap/data/DefaultTangemPayStorage.kt +++ b/app/src/main/java/com/tangem/tap/data/DefaultTangemPayStorage.kt @@ -6,6 +6,7 @@ import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getObjectMapSync +import com.tangem.datasource.local.preferences.utils.getSyncOrDefault import com.tangem.datasource.local.preferences.utils.getSyncOrNull import com.tangem.datasource.local.preferences.utils.store import com.tangem.datasource.local.visa.TangemPayStorage @@ -21,6 +22,7 @@ import javax.inject.Singleton private const val AUTH_TOKENS_DEFAULT_KEY = "tangem_pay_default_key" private const val WITHDRAW_ORDER_ID_KEY = "tangem_pay_withdraw_order_id_key" +@Suppress("TooManyFunctions") @Singleton internal class DefaultTangemPayStorage @Inject constructor( @ApplicationContext applicationContext: Context, @@ -119,16 +121,6 @@ internal class DefaultTangemPayStorage @Inject constructor( return appPreferencesStore.getSyncOrNull(PreferencesKeys.getTangemPayCheckCustomerByWalletId(userWalletId)) } - override suspend fun clearAll(userWalletId: UserWalletId, customerWalletAddress: String) = - withContext(dispatcherProvider.io) { - secureStorage.delete(createAuthTokensKey(customerWalletAddress)) - appPreferencesStore.store(PreferencesKeys.getTangemPayCheckCustomerByWalletId(userWalletId), false) - appPreferencesStore.store(PreferencesKeys.getTangemPayCustomerWalletAddressKey(userWalletId), "") - appPreferencesStore.store(PreferencesKeys.getTangemPayOrderIdKey(customerWalletAddress), "") - appPreferencesStore.store(PreferencesKeys.getTangemPayAddToWalletKey(customerWalletAddress), false) - appPreferencesStore.store(PreferencesKeys.getTangemPayHideOnboardingKey(userWalletId), false) - } - override suspend fun storeWithdrawOrder(userWalletId: UserWalletId, orderId: String) { appPreferencesStore.editData { mutablePreferences -> val orders = mutablePreferences.getObjectMap(PreferencesKeys.TANGEM_PAY_WITHDRAW_ORDERS_KEY) @@ -170,6 +162,28 @@ internal class DefaultTangemPayStorage @Inject constructor( } } + override suspend fun storeTangemPayEligibility(eligibility: Boolean) { + withContext(dispatcherProvider.io) { + appPreferencesStore.store(key = PreferencesKeys.TANGEM_PAY_ELIGIBILITY_KEY, value = eligibility) + } + } + + override suspend fun getTangemPayEligibility(): Boolean { + return withContext(dispatcherProvider.io) { + appPreferencesStore.getSyncOrDefault(key = PreferencesKeys.TANGEM_PAY_ELIGIBILITY_KEY, default = false) + } + } + + override suspend fun clearAll(userWalletId: UserWalletId, customerWalletAddress: String) = + withContext(dispatcherProvider.io) { + secureStorage.delete(createAuthTokensKey(customerWalletAddress)) + appPreferencesStore.store(PreferencesKeys.getTangemPayCheckCustomerByWalletId(userWalletId), false) + appPreferencesStore.store(PreferencesKeys.getTangemPayCustomerWalletAddressKey(userWalletId), "") + appPreferencesStore.store(PreferencesKeys.getTangemPayOrderIdKey(customerWalletAddress), "") + appPreferencesStore.store(PreferencesKeys.getTangemPayAddToWalletKey(customerWalletAddress), false) + appPreferencesStore.store(PreferencesKeys.getTangemPayHideOnboardingKey(userWalletId), false) + } + private fun createAuthTokensKey(address: String): String = "${AUTH_TOKENS_DEFAULT_KEY}_$address" private fun createWithdrawOrderIdKey(userWalletId: UserWalletId): String = "${WITHDRAW_ORDER_ID_KEY}_$userWalletId" diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt index 78e99e42bd..544a55357f 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt @@ -154,6 +154,7 @@ object PreferencesKeys { } val TANGEM_PAY_WITHDRAW_ORDERS_KEY by lazy { stringPreferencesKey(name = "tangemPayWithdrawOrders") } + val TANGEM_PAY_ELIGIBILITY_KEY by lazy { booleanPreferencesKey(name = "tangemPayEligibility") } fun getShouldShowNotificationKey(key: String) = booleanPreferencesKey("showShowNotificationUM_$key") // endregion diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/visa/TangemPayStorage.kt b/core/datasource/src/main/java/com/tangem/datasource/local/visa/TangemPayStorage.kt index a048c54414..591bc9f6be 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/visa/TangemPayStorage.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/visa/TangemPayStorage.kt @@ -3,6 +3,7 @@ package com.tangem.datasource.local.visa import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.visa.model.TangemPayAuthTokens +@Suppress("TooManyFunctions") interface TangemPayStorage { suspend fun storeCustomerWalletAddress(userWalletId: UserWalletId, customerWalletAddress: String) @@ -36,6 +37,8 @@ interface TangemPayStorage { suspend fun getHideMainOnboardingBanner(userWalletId: UserWalletId): Boolean suspend fun storeHideOnboardingBanner(userWalletId: UserWalletId, hide: Boolean) + suspend fun storeTangemPayEligibility(eligibility: Boolean) + suspend fun getTangemPayEligibility(): Boolean suspend fun clearAll(userWalletId: UserWalletId, customerWalletAddress: String) } \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayEligibilityManager.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayEligibilityManager.kt index f2d850f463..4ab4d074f2 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayEligibilityManager.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/pay/DefaultTangemPayEligibilityManager.kt @@ -45,6 +45,10 @@ internal class DefaultTangemPayEligibilityManager @Inject constructor( } } + override suspend fun getTangemPayAvailability(): Boolean { + return onboardingRepository.checkCustomerEligibility() + } + private suspend fun getUserWalletsData(): List { cachedEligibleWallets?.let { return it } @@ -69,7 +73,7 @@ internal class DefaultTangemPayEligibilityManager @Inject constructor( } private suspend fun getPossibleWalletsForTangemPay(): List { - if (!onboardingRepository.checkCustomerEligibility()) { + if (!checkTangemPayEligibility()) { return emptyList() } @@ -125,6 +129,10 @@ internal class DefaultTangemPayEligibilityManager @Inject constructor( eligibleWalletsDeferred = null } + private suspend fun checkTangemPayEligibility(): Boolean { + return onboardingRepository.getCustomerEligibility() || onboardingRepository.checkCustomerEligibility() + } + private data class UserWalletData( val userWallet: UserWallet, val isPaeraCustomer: Boolean, 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 79fed1dc36..fe06e7b5e3 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 @@ -197,7 +197,15 @@ internal class DefaultOnboardingRepository @Inject constructor( val response = requestHelper.performWithoutToken { tangemPayApi.checkCustomerEligibility() }.getOrNull() - return response?.result?.isTangemPayAvailable == true + + val isAvailable = response?.result?.isTangemPayAvailable == true + tangemPayStorage.storeTangemPayEligibility(eligibility = isAvailable) + + return isAvailable + } + + override suspend fun getCustomerEligibility(): Boolean { + return tangemPayStorage.getTangemPayEligibility() } override suspend fun getHideMainOnboardingBanner(userWalletId: UserWalletId): Boolean { diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPayEligibilityManager.kt b/domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPayEligibilityManager.kt index 5ad9a9d3d9..cc26e4832a 100644 --- a/domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPayEligibilityManager.kt +++ b/domain/visa/src/main/kotlin/com/tangem/domain/pay/TangemPayEligibilityManager.kt @@ -5,4 +5,5 @@ import com.tangem.domain.models.wallet.UserWallet interface TangemPayEligibilityManager { suspend fun getEligibleWallets(shouldExcludePaeraCustomers: Boolean): List + suspend fun getTangemPayAvailability(): Boolean } \ No newline at end of file diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/pay/repository/OnboardingRepository.kt b/domain/visa/src/main/kotlin/com/tangem/domain/pay/repository/OnboardingRepository.kt index 6a304dbfbb..1deca6b43a 100644 --- a/domain/visa/src/main/kotlin/com/tangem/domain/pay/repository/OnboardingRepository.kt +++ b/domain/visa/src/main/kotlin/com/tangem/domain/pay/repository/OnboardingRepository.kt @@ -26,6 +26,7 @@ interface OnboardingRepository { suspend fun checkCustomerWallet(userWalletId: UserWalletId): Either suspend fun checkCustomerEligibility(): Boolean + suspend fun getCustomerEligibility(): Boolean fun getSavedCustomerInfo(userWalletId: UserWalletId): CustomerInfo? diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt index b730125b22..992afae4ac 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt @@ -53,19 +53,19 @@ import javax.inject.Inject @Suppress("LongParameterList") internal class DetailsModel @Inject constructor( socialsBuilder: SocialsBuilder, + paramsContainer: ParamsContainer, + feedbackFeatureToggles: FeedbackFeatureToggles, private val itemsBuilder: ItemsBuilder, private val appVersionProvider: AppVersionProvider, private val checkIsWalletConnectAvailableUseCase: CheckIsWalletConnectAvailableUseCase, private val router: Router, private val urlOpener: UrlOpener, private val appInstanceIdProvider: AppInstanceIdProvider, - paramsContainer: ParamsContainer, private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val appStateHolder: ReduxStateHolder, private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val getWalletsUseCase: GetWalletsUseCase, - private val feedbackFeatureToggles: FeedbackFeatureToggles, override val dispatchers: CoroutineDispatcherProvider, private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase, private val hotWalletFeatureToggles: HotWalletFeatureToggles, @@ -254,7 +254,18 @@ internal class DetailsModel @Inject constructor( .getEligibleWallets(shouldExcludePaeraCustomers = true) .isNotEmpty() if (isEligible) { - items.update { itemsBuilder.addVisaItem(it) } + items.update { itemsBuilder.addTangemPayItem(items = it, onClick = ::onTangemPayItemClicked) } + } + } + } + + private fun onTangemPayItemClicked() { + modelScope.launch { + val isEligible = tangemPayEligibilityManager.getTangemPayAvailability() + if (isEligible) { + router.push(AppRoute.TangemPayOnboarding(AppRoute.TangemPayOnboarding.Mode.FromBannerInSettings)) + } else { + items.update { itemsBuilder.removeTangemPayItem(it) } } } } diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt index 8de88bbb26..c8627bf1ea 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt @@ -14,6 +14,8 @@ import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toPersistentList import javax.inject.Inject +private const val TANGEM_PAY_ITEM_ID = "get_tangem_pay" + @ModelScoped internal class ItemsBuilder @Inject constructor(private val router: Router) { @@ -37,10 +39,13 @@ internal class ItemsBuilder @Inject constructor(private val router: Router) { ).let(::add) }.toImmutableList() - fun addVisaItem(items: ImmutableList): ImmutableList { + fun addTangemPayItem(items: ImmutableList, onClick: () -> Unit): ImmutableList { return items.toMutableList().map { block -> if (block.id == "shop" && block is DetailsItemUM.Basic) { - val newItems = block.items.toMutableList().apply { add(getVisaItem()) } + val newItems = block + .items + .toMutableList() + .apply { add(getTangemPayItem(onClick = onClick)) } block.copy(items = newItems.toImmutableList()) } else { block @@ -48,6 +53,13 @@ internal class ItemsBuilder @Inject constructor(private val router: Router) { }.toImmutableList() } + fun removeTangemPayItem(items: ImmutableList): ImmutableList { + val tangemPayItem = items.find { it.id == TANGEM_PAY_ITEM_ID } ?: return items + return items.toMutableList() + .also { list -> list.remove(tangemPayItem) } + .toImmutableList() + } + private fun buildWalletConnectBlock(isWalletConnectAvailable: Boolean, userWalletId: UserWalletId): DetailsItemUM? { return if (isWalletConnectAvailable) { DetailsItemUM.WalletConnect( @@ -126,14 +138,12 @@ internal class ItemsBuilder @Inject constructor(private val router: Router) { }.toPersistentList(), ) - private fun getVisaItem(): DetailsItemUM.Basic.Item = DetailsItemUM.Basic.Item( - id = "get_tangem_visa", + private fun getTangemPayItem(onClick: () -> Unit): DetailsItemUM.Basic.Item = DetailsItemUM.Basic.Item( + id = TANGEM_PAY_ITEM_ID, block = BlockUM( text = resourceReference(R.string.tangempay_get_tangem_pay), iconRes = R.drawable.ic_tangem_pay_24, - onClick = { - router.push(AppRoute.TangemPayOnboarding(AppRoute.TangemPayOnboarding.Mode.FromBannerInSettings)) - }, + onClick = onClick, ), ) } \ No newline at end of file