From f18338ff443794f6ce73086d1458bf2c6df850f9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 13 Sep 2024 14:46:32 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../DefaultManageTokensRepository.kt | 16 ++++ .../CheckCurrencyUnsupportedUseCase.kt | 14 +++ .../repository/ManageTokensRepository.kt | 6 ++ features/markets/impl/build.gradle.kts | 1 + .../impl/DefaultMarketsEntryComponent.kt | 7 ++ .../model/AddToPortfolioBSContentUMFactory.kt | 3 +- .../impl/model/MarketsPortfolioModel.kt | 93 ++++++++++++++++++- .../impl/model/SelectNetworkUMConverter.kt | 5 +- 8 files changed, 139 insertions(+), 6 deletions(-) diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt index f1749f04d4..49b58cb102 100644 --- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt @@ -1,6 +1,7 @@ package com.tangem.data.managetokens import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.blockchainsdk.compatibility.l2BlockchainsCoinIds import com.tangem.blockchainsdk.utils.isSupportedInApp import com.tangem.blockchainsdk.utils.toNetworkId @@ -193,6 +194,21 @@ internal class DefaultManageTokensRepository( } } + override suspend fun checkCurrencyUnsupportedState( + userWalletId: UserWalletId, + rawNetworkId: String, + isMainNetwork: Boolean, + ): CurrencyUnsupportedState? { + val userWallet = getUserWallet(userWalletId = userWalletId) + val blockchain = Blockchain.fromNetworkId(networkId = rawNetworkId) + ?: error("Can not create blockchain with given networkId -> $rawNetworkId") + return if (isMainNetwork) { + checkBlockchainUnsupportedState(userWallet, blockchain) + } else { + checkTokenUnsupportedState(userWallet, blockchain) + } + } + private fun checkBlockchainUnsupportedState( userWallet: UserWallet, blockchain: Blockchain, diff --git a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/CheckCurrencyUnsupportedUseCase.kt b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/CheckCurrencyUnsupportedUseCase.kt index 40dbddf6fd..eef9093442 100644 --- a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/CheckCurrencyUnsupportedUseCase.kt +++ b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/CheckCurrencyUnsupportedUseCase.kt @@ -18,4 +18,18 @@ class CheckCurrencyUnsupportedUseCase( repository.checkCurrencyUnsupportedState(userWalletId, sourceNetwork) } } + + suspend operator fun invoke( + userWalletId: UserWalletId, + networkId: String, + isMainNetwork: Boolean, + ): Either { + return Either.catch { + repository.checkCurrencyUnsupportedState( + userWalletId = userWalletId, + rawNetworkId = networkId, + isMainNetwork = isMainNetwork, + ) + } + } } \ No newline at end of file diff --git a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/repository/ManageTokensRepository.kt b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/repository/ManageTokensRepository.kt index cfa44069fe..0d879955e8 100644 --- a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/repository/ManageTokensRepository.kt +++ b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/repository/ManageTokensRepository.kt @@ -22,4 +22,10 @@ interface ManageTokensRepository { userWalletId: UserWalletId, sourceNetwork: ManagedCryptoCurrency.SourceNetwork, ): CurrencyUnsupportedState? + + suspend fun checkCurrencyUnsupportedState( + userWalletId: UserWalletId, + rawNetworkId: String, + isMainNetwork: Boolean, + ): CurrencyUnsupportedState? } \ No newline at end of file diff --git a/features/markets/impl/build.gradle.kts b/features/markets/impl/build.gradle.kts index 3ac39315a8..055d5172a9 100644 --- a/features/markets/impl/build.gradle.kts +++ b/features/markets/impl/build.gradle.kts @@ -22,6 +22,7 @@ dependencies { implementation(projects.domain.balanceHiding) implementation(projects.domain.balanceHiding.models) implementation(projects.domain.card) + implementation(projects.domain.manageTokens) implementation(projects.domain.markets) implementation(projects.domain.staking.models) implementation(projects.domain.tokens) diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt index 7f96268b4c..ad932e8965 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt @@ -10,6 +10,8 @@ import com.arkivanov.decompose.value.Value import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.childByContext import com.tangem.core.decompose.navigation.Router +import com.tangem.core.ui.UiDependencies +import com.tangem.core.ui.message.EventMessageEffect import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.markets.TokenMarket import com.tangem.features.markets.entry.BottomSheetState @@ -26,6 +28,7 @@ import dagger.assisted.AssistedInject internal class DefaultMarketsEntryComponent @AssistedInject constructor( @Assisted context: AppComponentContext, private val marketsEntryChildFactory: MarketsEntryChildFactory, + private val uiDependencies: UiDependencies, ) : MarketsEntryComponent, AppComponentContext by context { private val stackNavigation = StackNavigation() @@ -61,6 +64,10 @@ internal class DefaultMarketsEntryComponent @AssistedInject constructor( stackState = stack.subscribeAsState(), modifier = modifier, ) + EventMessageEffect( + messageHandler = uiDependencies.eventMessageHandler, + snackbarHostState = uiDependencies.globalSnackbarHostState, + ) } @OptIn(ExperimentalDecomposeApi::class) diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/AddToPortfolioBSContentUMFactory.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/AddToPortfolioBSContentUMFactory.kt index c1b58bdbf6..3ce401a818 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/AddToPortfolioBSContentUMFactory.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/AddToPortfolioBSContentUMFactory.kt @@ -3,6 +3,7 @@ package com.tangem.features.markets.portfolio.impl.model import com.tangem.common.ui.userwallet.converter.UserWalletItemUMConverter import com.tangem.common.ui.userwallet.state.UserWalletItemUM import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.components.rows.model.BlockchainRowUM import com.tangem.domain.markets.TokenMarketInfo import com.tangem.domain.markets.TokenMarketParams import com.tangem.domain.wallets.models.UserWallet @@ -28,7 +29,7 @@ internal class AddToPortfolioBSContentUMFactory( private val token: TokenMarketParams, private val onAddToPortfolioVisibilityChange: (Boolean) -> Unit, private val onWalletSelectorVisibilityChange: (Boolean) -> Unit, - private val onNetworkSwitchClick: (String, Boolean) -> Unit, + private val onNetworkSwitchClick: (BlockchainRowUM, Boolean) -> Unit, private val onWalletSelect: (UserWalletId) -> Unit, private val onContinueClick: (selectedWalletId: UserWalletId, addedNetworks: Set) -> Unit, ) { diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt index d3291921c8..59a9e16805 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt @@ -1,18 +1,32 @@ package com.tangem.features.markets.portfolio.impl.model import androidx.compose.runtime.Stable +import androidx.compose.ui.res.stringResource import arrow.core.getOrElse import com.tangem.core.decompose.di.ComponentScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.core.decompose.ui.UiMessageSender +import com.tangem.core.ui.components.BasicDialog +import com.tangem.core.ui.components.DialogButtonUM +import com.tangem.core.ui.components.rows.model.BlockchainRowUM +import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.message.ContentMessage +import com.tangem.core.ui.message.SnackbarMessage import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.card.HasMissedDerivationsUseCase +import com.tangem.domain.managetokens.CheckCurrencyUnsupportedUseCase +import com.tangem.domain.managetokens.model.CurrencyUnsupportedState import com.tangem.domain.markets.SaveMarketTokensUseCase import com.tangem.domain.markets.TokenMarketInfo import com.tangem.domain.tokens.model.Network import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase +import com.tangem.features.markets.impl.R import com.tangem.features.markets.portfolio.api.MarketsPortfolioComponent import com.tangem.features.markets.portfolio.impl.loader.PortfolioDataLoader import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM @@ -31,6 +45,8 @@ internal class MarketsPortfolioModel @Inject constructor( getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, tokenActionsIntentsFactory: TokenActionsHandler.Factory, override val dispatchers: CoroutineDispatcherProvider, + private val messageSender: UiMessageSender, + private val checkCurrencyUnsupportedUseCase: CheckCurrencyUnsupportedUseCase, private val getSelectedWalletUseCase: GetSelectedWalletUseCase, private val portfolioDataLoader: PortfolioDataLoader, private val hasMissedDerivationsUseCase: HasMissedDerivationsUseCase, @@ -150,7 +166,7 @@ internal class MarketsPortfolioModel @Inject constructor( } } - private fun onNetworkSwitchClick(networkId: String, isChecked: Boolean) { + private fun onNetworkSwitchClick(blockchainRowUM: BlockchainRowUM, isChecked: Boolean) { val selectedWalletId = selectedMultiWalletIdFlow.value if (selectedWalletId == null) { @@ -159,12 +175,83 @@ internal class MarketsPortfolioModel @Inject constructor( } if (isChecked) { - addToPortfolioManager.addNetwork(userWalletId = selectedWalletId, networkId = networkId) + modelScope.launch { + val unsupportedState = checkCurrencyUnsupportedState( + userWalletId = selectedWalletId, + rawNetworkId = blockchainRowUM.id, + isMainNetwork = blockchainRowUM.isMainNetwork, + ) + if (unsupportedState != null) { + showUnsupportedWarning(unsupportedState) + } else { + addToPortfolioManager.addNetwork(userWalletId = selectedWalletId, networkId = blockchainRowUM.id) + } + } } else { - addToPortfolioManager.removeNetwork(userWalletId = selectedWalletId, networkId = networkId) + addToPortfolioManager.removeNetwork(userWalletId = selectedWalletId, networkId = blockchainRowUM.id) } } + private suspend fun checkCurrencyUnsupportedState( + userWalletId: UserWalletId, + rawNetworkId: String, + isMainNetwork: Boolean, + ): CurrencyUnsupportedState? { + return checkCurrencyUnsupportedUseCase( + userWalletId = userWalletId, + networkId = rawNetworkId, + isMainNetwork = isMainNetwork, + ).getOrElse { + Timber.e( + it, + """ + Failed to check currency unsupported state + |- User wallet ID: $userWalletId + |- Network ID: $rawNetworkId + |- Is main network: $isMainNetwork + """.trimIndent(), + ) + + val message = SnackbarMessage( + message = it.localizedMessage + ?.let(::stringReference) + ?: resourceReference(R.string.common_error), + ) + messageSender.send(message) + + null + } + } + + private fun showUnsupportedWarning(unsupportedState: CurrencyUnsupportedState) { + val message = ContentMessage { onDismiss -> + BasicDialog( + title = resourceReference(R.string.common_warning).resolveReference(), + message = when (unsupportedState) { + is CurrencyUnsupportedState.Token.NetworkTokensUnsupported -> resourceReference( + id = R.string.alert_manage_tokens_unsupported_message, + formatArgs = wrappedList(unsupportedState.networkName), + ) + is CurrencyUnsupportedState.Token.UnsupportedCurve -> resourceReference( + id = R.string.alert_manage_tokens_unsupported_curve_message, + formatArgs = wrappedList(unsupportedState.networkName), + ) + is CurrencyUnsupportedState.UnsupportedNetwork -> resourceReference( + id = R.string.alert_manage_tokens_unsupported_curve_message, + formatArgs = wrappedList(unsupportedState.networkName), + ) + }.resolveReference(), + confirmButton = DialogButtonUM( + title = stringResource(R.string.common_ok), + onClick = onDismiss, + ), + onDismissDialog = onDismiss, + ) + } + + messageSender.send(message) + } + private fun onWalletSelect(userWalletId: UserWalletId) { selectedMultiWalletIdFlow.update { prevUserWalletId -> prevUserWalletId?.let(addToPortfolioManager::removeAllChanges) diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/SelectNetworkUMConverter.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/SelectNetworkUMConverter.kt index d7d84b6bcb..05b33043d7 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/SelectNetworkUMConverter.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/SelectNetworkUMConverter.kt @@ -1,5 +1,6 @@ package com.tangem.features.markets.portfolio.impl.model +import com.tangem.core.ui.components.rows.model.BlockchainRowUM import com.tangem.domain.markets.TokenMarketInfo import com.tangem.domain.markets.TokenMarketParams import com.tangem.features.markets.portfolio.impl.ui.state.SelectNetworkUM @@ -18,7 +19,7 @@ import kotlinx.collections.immutable.toImmutableList internal class SelectNetworkUMConverter( private val networksWithToggle: Map, private val alreadyAddedNetworks: Set, - private val onNetworkSwitchClick: (String, Boolean) -> Unit, + private val onNetworkSwitchClick: (BlockchainRowUM, Boolean) -> Unit, ) : Converter { override fun convert(value: TokenMarketParams): SelectNetworkUM { @@ -30,7 +31,7 @@ internal class SelectNetworkUMConverter( networks = BlockchainRowUMConverter(alreadyAddedNetworks) .convertList(networksWithToggle.toList()) .toImmutableList(), - onNetworkSwitchClick = { um, isChecked -> onNetworkSwitchClick(um.id, isChecked) }, + onNetworkSwitchClick = { um, isChecked -> onNetworkSwitchClick(um, isChecked) }, ) } } \ No newline at end of file