From 1166f7e8bf10e9284840d5d33893478397ccc524 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 1 Oct 2025 12:05:57 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../wallet/child/wallet/WalletComponent.kt | 18 +++ .../WalletCurrencyActionsClickIntents.kt | 141 ++++++++++++++---- .../router/DefaultWalletRouter.kt | 16 ++ .../presentation/router/InnerWalletRouter.kt | 9 ++ .../wallet/state/model/WalletDialogConfig.kt | 9 ++ 5 files changed, 162 insertions(+), 31 deletions(-) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/WalletComponent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/WalletComponent.kt index 3104027a66..acd97c7552 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/WalletComponent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/WalletComponent.kt @@ -15,6 +15,7 @@ import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.decompose.ComposableBottomSheetComponent import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.core.ui.decompose.ComposableDialogComponent +import com.tangem.domain.tokens.model.details.TokenAction import com.tangem.feature.wallet.child.wallet.model.WalletModel import com.tangem.feature.wallet.navigation.WalletRoute import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig @@ -25,6 +26,7 @@ import com.tangem.features.markets.entry.MarketsEntryComponent import com.tangem.features.pushnotifications.api.PushNotificationsBottomSheetComponent import com.tangem.features.pushnotifications.api.PushNotificationsParams import com.tangem.features.tokenreceive.TokenReceiveComponent +import com.tangem.features.yield.supply.api.YieldSupplyDepositedWarningComponent import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -39,6 +41,7 @@ internal class WalletComponent @AssistedInject constructor( private val askBiometryComponentFactory: AskBiometryComponent.Factory, private val pushNotificationsBottomSheetComponent: PushNotificationsBottomSheetComponent.Factory, private val tokenReceiveComponentFactory: TokenReceiveComponent.Factory, + private val yieldSupplyDepositedWarningComponent: YieldSupplyDepositedWarningComponent.Factory, ) : ComposableContentComponent, AppComponentContext by appComponentContext { private val model: WalletModel = getOrCreateModel() @@ -90,6 +93,21 @@ internal class WalletComponent @AssistedInject constructor( ), ) } + is WalletDialogConfig.YieldSupplyWarning -> { + yieldSupplyDepositedWarningComponent.create( + context = childByContext(componentContext), + params = YieldSupplyDepositedWarningComponent.Params( + cryptoCurrency = dialogConfig.cryptoCurrency, + onDismiss = model.innerWalletRouter.dialogNavigation::dismiss, + tokenAction = dialogConfig.tokenAction, + modelCallback = object : YieldSupplyDepositedWarningComponent.ModelCallback { + override fun onYieldSupplyWarningAcknowledged(tokenAction: TokenAction) { + dialogConfig.onWarningAcknowledged(tokenAction) + } + }, + ), + ) + } } }, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt index 887f075f2b..f57694c824 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt @@ -45,6 +45,10 @@ import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.GetViewedTokenReceiveWarningUseCase +import com.tangem.domain.tokens.NeedShowYieldSupplyDepositedWarningUseCase +import com.tangem.domain.tokens.SaveViewedTokenReceiveWarningUseCase +import com.tangem.domain.tokens.SaveViewedYieldSupplyWarningUseCase +import com.tangem.domain.tokens.model.details.TokenAction import com.tangem.domain.tokens.legacy.TradeCryptoAction import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason import com.tangem.domain.tokens.model.analytics.TokenReceiveAnalyticsEvent @@ -68,6 +72,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.CloseBot import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender import com.tangem.feature.wallet.presentation.wallet.utils.WalletFeatureUseCasesFacade import com.tangem.features.tokenreceive.TokenReceiveFeatureToggle +import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.Flow @@ -148,7 +153,11 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( private val rampStateManager: RampStateManager, private val tokenReceiveFeatureToggle: TokenReceiveFeatureToggle, private val getViewedTokenReceiveWarningUseCase: GetViewedTokenReceiveWarningUseCase, + private val saveViewedTokenReceiveWarningUseCase: SaveViewedTokenReceiveWarningUseCase, private val getEnsNameUseCase: GetEnsNameUseCase, + private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles, + private val needShowYieldSupplyDepositedWarningUseCase: NeedShowYieldSupplyDepositedWarningUseCase, + private val saveViewedYieldSupplyWarningUseCase: SaveViewedYieldSupplyWarningUseCase, ) : BaseWalletClickIntents(), WalletCurrencyActionsClickIntents { override fun onSendClick( @@ -166,13 +175,24 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( if (handleUnavailabilityReason(unavailabilityReason)) return - stateHolder.update(CloseBottomSheetTransformer(userWalletId = portfolioId.userWalletId)) - val route = AppRoute.Send( - currency = cryptoCurrencyStatus.currency, - portfolioId = portfolioId, - ) - - appRouter.push(route) + modelScope.launch(dispatchers.main) { + if (needShowYieldSupplyWarning(cryptoCurrencyStatus)) { + stateHolder.hideBottomSheet() + router.openYieldSupplyBottomSheet( + cryptoCurrency = cryptoCurrencyStatus.currency, + tokenAction = TokenAction.Send, + onWarningAcknowledged = { tokenAction -> + modelScope.launch { + saveViewedYieldSupplyWarningUseCase(cryptoCurrencyStatus.currency.name) + stateHolder.hideBottomSheet() + navigateToSend(cryptoCurrencyStatus, portfolioId) + } + }, + ) + } else { + navigateToSend(cryptoCurrencyStatus, portfolioId) + } + } } override fun onReceiveClick( @@ -196,24 +216,24 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( event?.let { analyticsEventHandler.send(it) } - if (tokenReceiveFeatureToggle.isNewTokenReceiveEnabled) { - stateHolder.hideBottomSheet() - modelScope.launch { - configureReceiveAddresses(cryptoCurrencyStatus = cryptoCurrencyStatus)?.let { - router.openTokenReceiveBottomSheet(it) - } + modelScope.launch(dispatchers.main) { + if (needShowYieldSupplyWarning(cryptoCurrencyStatus)) { + stateHolder.hideBottomSheet() + router.openYieldSupplyBottomSheet( + cryptoCurrency = cryptoCurrencyStatus.currency, + tokenAction = TokenAction.Receive, + onWarningAcknowledged = { tokenAction -> + modelScope.launch { + saveViewedTokenReceiveWarningUseCase(cryptoCurrencyStatus.currency.name) + saveViewedYieldSupplyWarningUseCase(cryptoCurrencyStatus.currency.name) + stateHolder.hideBottomSheet() + navigateToReceive(cryptoCurrencyStatus) + } + }, + ) + } else { + navigateToReceive(cryptoCurrencyStatus) } - } else { - analyticsEventHandler.send( - event = TokenReceiveAnalyticsEvent.ReceiveScreenOpened(cryptoCurrencyStatus.currency.symbol), - ) - stateHolder.showBottomSheet( - createReceiveBottomSheetContent( - currency = cryptoCurrencyStatus.currency, - addresses = cryptoCurrencyStatus.value.networkAddress ?: return, - ), - userWalletId, - ) } } @@ -417,13 +437,24 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( if (handleUnavailabilityReason(unavailabilityReason)) return - appRouter.push( - AppRoute.Swap( - currencyFrom = cryptoCurrencyStatus.currency, - portfolioId = portfolioId, - screenSource = AnalyticsParam.ScreensSources.LongTap.value, - ), - ) + modelScope.launch(dispatchers.main) { + if (needShowYieldSupplyWarning(cryptoCurrencyStatus)) { + stateHolder.hideBottomSheet() + router.openYieldSupplyBottomSheet( + cryptoCurrency = cryptoCurrencyStatus.currency, + tokenAction = TokenAction.Swap, + onWarningAcknowledged = { tokenAction -> + modelScope.launch { + saveViewedYieldSupplyWarningUseCase(cryptoCurrencyStatus.currency.name) + stateHolder.hideBottomSheet() + navigateToSwap(cryptoCurrencyStatus, portfolioId) + } + }, + ) + } else { + navigateToSwap(cryptoCurrencyStatus, portfolioId) + } + } } override fun onExploreClick() { @@ -729,4 +760,52 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( receiveAddress = receiveAddresses, ) } + + private suspend fun needShowYieldSupplyWarning(cryptoCurrencyStatus: CryptoCurrencyStatus): Boolean { + return yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled && + needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus) + } + + private fun navigateToSend(cryptoCurrencyStatus: CryptoCurrencyStatus, portfolioId: PortfolioId) { + stateHolder.update(CloseBottomSheetTransformer(userWalletId = portfolioId.userWalletId)) + val route = AppRoute.Send( + currency = cryptoCurrencyStatus.currency, + portfolioId = portfolioId, + ) + + appRouter.push(route) + } + + private fun navigateToSwap(cryptoCurrencyStatus: CryptoCurrencyStatus, portfolioId: PortfolioId) { + appRouter.push( + AppRoute.Swap( + currencyFrom = cryptoCurrencyStatus.currency, + portfolioId = portfolioId, + screenSource = AnalyticsParam.ScreensSources.LongTap.value, + ), + ) + } + + private fun navigateToReceive(cryptoCurrencyStatus: CryptoCurrencyStatus) { + val userWalletId = stateHolder.getSelectedWalletId() + if (tokenReceiveFeatureToggle.isNewTokenReceiveEnabled) { + stateHolder.hideBottomSheet() + modelScope.launch { + configureReceiveAddresses(cryptoCurrencyStatus = cryptoCurrencyStatus)?.let { + router.openTokenReceiveBottomSheet(it) + } + } + } else { + analyticsEventHandler.send( + event = TokenReceiveAnalyticsEvent.ReceiveScreenOpened(cryptoCurrencyStatus.currency.symbol), + ) + stateHolder.showBottomSheet( + createReceiveBottomSheetContent( + currency = cryptoCurrencyStatus.currency, + addresses = cryptoCurrencyStatus.value.networkAddress ?: return, + ), + userWalletId, + ) + } + } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt index 6ecbc8f42f..e8390af20c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt @@ -9,12 +9,14 @@ import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.TokenReceiveConfig +import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.redux.StateDialog +import com.tangem.domain.tokens.model.details.TokenAction import com.tangem.feature.wallet.navigation.WalletRoute import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig import kotlinx.coroutines.channels.BufferOverflow @@ -115,4 +117,18 @@ internal class DefaultWalletRouter @Inject constructor( override fun openTangemPayDetails(custoemrWalletAddress: String) { router.push(AppRoute.TangemPayDetails(custoemrWalletAddress)) } + + override fun openYieldSupplyBottomSheet( + cryptoCurrency: CryptoCurrency, + tokenAction: TokenAction, + onWarningAcknowledged: (TokenAction) -> Unit, + ) { + dialogNavigation.activate( + configuration = WalletDialogConfig.YieldSupplyWarning( + cryptoCurrency = cryptoCurrency, + tokenAction = tokenAction, + onWarningAcknowledged = onWarningAcknowledged, + ), + ) + } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt index 4d5858a5f4..fba901af14 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt @@ -4,10 +4,12 @@ import androidx.compose.runtime.Stable import com.arkivanov.decompose.router.slot.SlotNavigation import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.TokenReceiveConfig +import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.domain.tokens.model.details.TokenAction import com.tangem.feature.wallet.navigation.WalletRoute import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig import kotlinx.coroutines.flow.SharedFlow @@ -62,4 +64,11 @@ internal interface InnerWalletRouter { fun openTangemPayOnboarding() fun openTangemPayDetails(custoemrWalletAddress: String) + + /** Open BS abput yield supply active and all money deposited in AAVE */ + fun openYieldSupplyBottomSheet( + cryptoCurrency: CryptoCurrency, + tokenAction: TokenAction, + onWarningAcknowledged: (TokenAction) -> Unit, + ) } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletDialogConfig.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletDialogConfig.kt index 9bce963c5f..4042c8b37e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletDialogConfig.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletDialogConfig.kt @@ -1,7 +1,9 @@ package com.tangem.feature.wallet.presentation.wallet.state.model import com.tangem.domain.models.TokenReceiveConfig +import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.domain.tokens.model.details.TokenAction import kotlinx.serialization.Serializable /** @@ -23,4 +25,11 @@ internal sealed interface WalletDialogConfig { @Serializable data class TokenReceive(val tokenReceiveConfig: TokenReceiveConfig) : WalletDialogConfig + + @Serializable + data class YieldSupplyWarning( + val cryptoCurrency: CryptoCurrency, + val tokenAction: TokenAction, + val onWarningAcknowledged: (TokenAction) -> Unit, + ) : WalletDialogConfig } \ No newline at end of file