Updated on 2026-08-14

This commit is contained in:
Tangem 2024-09-13 14:46:32 +05:00
parent 06d139362e
commit f18338ff44
8 changed files with 139 additions and 6 deletions

View file

@ -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,

View file

@ -18,4 +18,18 @@ class CheckCurrencyUnsupportedUseCase(
repository.checkCurrencyUnsupportedState(userWalletId, sourceNetwork)
}
}
suspend operator fun invoke(
userWalletId: UserWalletId,
networkId: String,
isMainNetwork: Boolean,
): Either<Throwable, CurrencyUnsupportedState?> {
return Either.catch {
repository.checkCurrencyUnsupportedState(
userWalletId = userWalletId,
rawNetworkId = networkId,
isMainNetwork = isMainNetwork,
)
}
}
}

View file

@ -22,4 +22,10 @@ interface ManageTokensRepository {
userWalletId: UserWalletId,
sourceNetwork: ManagedCryptoCurrency.SourceNetwork,
): CurrencyUnsupportedState?
suspend fun checkCurrencyUnsupportedState(
userWalletId: UserWalletId,
rawNetworkId: String,
isMainNetwork: Boolean,
): CurrencyUnsupportedState?
}

View file

@ -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)

View file

@ -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<Child>()
@ -61,6 +64,10 @@ internal class DefaultMarketsEntryComponent @AssistedInject constructor(
stackState = stack.subscribeAsState(),
modifier = modifier,
)
EventMessageEffect(
messageHandler = uiDependencies.eventMessageHandler,
snackbarHostState = uiDependencies.globalSnackbarHostState,
)
}
@OptIn(ExperimentalDecomposeApi::class)

View file

@ -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<TokenMarketInfo.Network>) -> Unit,
) {

View file

@ -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)

View file

@ -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<TokenMarketInfo.Network, Boolean>,
private val alreadyAddedNetworks: Set<String>,
private val onNetworkSwitchClick: (String, Boolean) -> Unit,
private val onNetworkSwitchClick: (BlockchainRowUM, Boolean) -> Unit,
) : Converter<TokenMarketParams, SelectNetworkUM> {
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) },
)
}
}