diff --git a/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt b/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt index c2476401e7..157b46fe76 100644 --- a/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt +++ b/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt @@ -36,19 +36,28 @@ class AdditionalFeedbackInfo { var userWalletId: String = "" // wallets - internal val walletsInfo = mutableListOf() - internal var onSendErrorWalletInfo: EmailWalletInfo? = null + var walletsInfo = emptyList() + private set + var onSendErrorWalletInfo: EmailWalletInfo? = null + private set var signedHashesCount: String = "" + private set // device var phoneModel: String = Build.MODEL + private set var osVersion: String = Build.VERSION.SDK_INT.toString() + private set // send error var destinationAddress: String = "" + private set var amount: String = "" + private set var fee: String = "" + private set var token: String = "" + private set private val Address.name: String get() = type.javaClass.simpleName @@ -65,10 +74,7 @@ class AdditionalFeedbackInfo { @Deprecated("Don't use it directly") fun setWalletsInfo(walletManagers: List) { - walletsInfo.clear() - walletManagers.forEach { manager -> - walletsInfo.add(createEmailWalletInfo(manager)) - } + walletsInfo = walletManagers.map(::createEmailWalletInfo) } fun updateOnSendError( diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt index 8785a5395d..2092947970 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt @@ -176,6 +176,8 @@ private fun handleAction(action: Action, appState: () -> AppState?) { walletCurrenciesManager.addListener(action.topUpController) } is GlobalAction.UpdateUserWalletsListManager -> { + val walletManagersFacade = store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade) + /* * If implementation of the UserWalletsListManager is changed, * then all observers of selectedUserWallet become irrelevant. @@ -183,13 +185,13 @@ private fun handleAction(action: Action, appState: () -> AppState?) { action.manager.selectedUserWallet .distinctUntilChanged() .onEach { userWallet -> - Analytics.send(event = Basic.WalletOpened()) + Analytics.send(Basic.WalletOpened()) store.state.globalState.feedbackManager?.infoHolder?.let { infoHolder -> - infoHolder.setCardInfo(data = userWallet.scanResponse) + infoHolder.setCardInfo(userWallet.scanResponse) - store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade) - .getAll(userWalletId = userWallet.walletId) + walletManagersFacade + .getAll(userWallet.walletId) .onEach(infoHolder::setWalletsInfo) .launchIn(scope) } diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index 925a5cf11c..d66c81c65f 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -63,9 +63,9 @@ internal object TokensDomainModule { @ViewModelScoped fun provideRemoveCurrencyUseCase( currenciesRepository: CurrenciesRepository, - dispatchers: CoroutineDispatcherProvider, + walletManagersFacade: WalletManagersFacade, ): RemoveCurrencyUseCase { - return RemoveCurrencyUseCase(currenciesRepository, dispatchers) + return RemoveCurrencyUseCase(currenciesRepository, walletManagersFacade) } @Provides diff --git a/app/src/main/java/com/tangem/tap/features/tokens/legacy/redux/TokensMiddleware.kt b/app/src/main/java/com/tangem/tap/features/tokens/legacy/redux/TokensMiddleware.kt index c108b2602f..d99bb5f13c 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/legacy/redux/TokensMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/legacy/redux/TokensMiddleware.kt @@ -403,7 +403,19 @@ object TokensMiddleware { private suspend fun removeNewCurrenciesIfNeeded(userWalletId: UserWalletId, currencies: List) { if (currencies.isEmpty()) return val currenciesRepository = store.state.daggerGraphState.get(DaggerGraphState::currenciesRepository) + val walletManagersFacade = store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade) currenciesRepository.removeCurrencies(userWalletId = userWalletId, currencies = currencies) + + walletManagersFacade.remove( + userWalletId = userWalletId, + networks = currencies + .filterIsInstance() + .mapTo(hashSetOf(), CryptoCurrency::network), + ) + walletManagersFacade.removeTokens( + userWalletId = userWalletId, + tokens = currencies.filterIsInstance().toSet(), + ) } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/walletmanager/DefaultWalletManagersStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/walletmanager/DefaultWalletManagersStore.kt index f99db26624..c009ade118 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/walletmanager/DefaultWalletManagersStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/walletmanager/DefaultWalletManagersStore.kt @@ -6,6 +6,7 @@ import com.tangem.datasource.local.datastore.core.StringKeyDataStore import com.tangem.datasource.local.datastore.core.StringKeyDataStoreDecorator import com.tangem.domain.wallets.models.UserWalletId import com.tangem.utils.extensions.addOrReplace +import com.tangem.utils.extensions.removeBy import kotlinx.coroutines.flow.Flow internal class DefaultWalletManagersStore( @@ -43,10 +44,18 @@ internal class DefaultWalletManagersStore( val updatedWalletManagers = walletManagers ?.addOrReplace(walletManager) { it.wallet.blockchain == walletManager.wallet.blockchain && - it.wallet.publicKey == walletManager.wallet.publicKey + it.wallet.publicKey.derivationPath == walletManager.wallet.publicKey.derivationPath } ?: listOf(walletManager) store(userWalletId, updatedWalletManagers) } + + override suspend fun remove(userWalletId: UserWalletId, predicate: (WalletManager) -> Boolean) { + val walletManagers = getSyncOrNull(userWalletId)?.toMutableList() ?: return + + walletManagers.removeBy(predicate) + + store(userWalletId, walletManagers) + } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/walletmanager/WalletManagersStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/walletmanager/WalletManagersStore.kt index a820b1d7c9..58ddc2d942 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/walletmanager/WalletManagersStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/walletmanager/WalletManagersStore.kt @@ -19,5 +19,7 @@ interface WalletManagersStore { suspend fun store(userWalletId: UserWalletId, walletManager: WalletManager) + suspend fun remove(userWalletId: UserWalletId, predicate: (WalletManager) -> Boolean) + suspend fun clear() } \ No newline at end of file diff --git a/core/utils/src/main/java/com/tangem/utils/extensions/List.kt b/core/utils/src/main/java/com/tangem/utils/extensions/List.kt index 6ecaef28b8..e0fbdb5d90 100644 --- a/core/utils/src/main/java/com/tangem/utils/extensions/List.kt +++ b/core/utils/src/main/java/com/tangem/utils/extensions/List.kt @@ -1,7 +1,7 @@ package com.tangem.utils.extensions /** - * Removes an element from the collection based on the provided predicate. + * Removes elements from the collection based on the provided predicate. * * !!!This function is not thread-safe!!! * diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt index f8aebc28ec..6bf8b33443 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt @@ -60,6 +60,50 @@ class DefaultWalletManagersFacade( return getAndUpdateWalletManager(userWallet, blockchain, derivationPath, extraTokens) } + override suspend fun remove(userWalletId: UserWalletId, networks: Set) { + if (networks.isEmpty()) return + + val blockchainsToDerivationPaths = networks.map { + Blockchain.fromId(it.id.value) to it.derivationPath.value + } + + walletManagersStore.remove(userWalletId) { walletManager -> + val wallet = walletManager.wallet + val blockchainToDerivationPath = wallet.blockchain to wallet.publicKey.derivationPath?.rawPath + + blockchainToDerivationPath in blockchainsToDerivationPaths + } + } + + override suspend fun removeTokens(userWalletId: UserWalletId, tokens: Set) { + if (tokens.isEmpty()) return + + tokens + .groupBy(CryptoCurrency.Token::network) + .forEach { (network, networkTokens) -> + removeTokens(userWalletId, network, networkTokens) + } + } + + private suspend fun removeTokens( + userWalletId: UserWalletId, + network: Network, + networkTokens: List, + ) { + val walletManager = walletManagersStore.getSyncOrNull( + userWalletId = userWalletId, + blockchain = Blockchain.fromId(network.id.value), + derivationPath = network.derivationPath.value, + ) ?: return + val tokensToRemove = sdkTokenConverter.convertList(networkTokens) + + tokensToRemove.forEach { token -> + walletManager.removeToken(token) + } + + walletManagersStore.store(userWalletId, walletManager) + } + override suspend fun updatePendingTransactions( userWalletId: UserWalletId, network: Network, diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt index 1e33f610e6..8d10b2fa4d 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt @@ -37,6 +37,16 @@ interface WalletManagersFacade { extraTokens: Set, ): UpdateWalletManagerResult + /** + * Removes the wallet managers associated with a user's wallet and networks. + * + * @param userWalletId The ID of the user's wallet. + * @param networks Set of networks + * */ + suspend fun remove(userWalletId: UserWalletId, networks: Set) + + suspend fun removeTokens(userWalletId: UserWalletId, tokens: Set) + /** * Returns [UpdateWalletManagerResult] with last pending transactions * diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/remove/RemoveCurrencyError.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/remove/RemoveCurrencyError.kt index 475a90e2a8..8af9ed12ea 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/remove/RemoveCurrencyError.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/remove/RemoveCurrencyError.kt @@ -2,4 +2,6 @@ package com.tangem.domain.tokens.model.remove sealed class RemoveCurrencyError : Throwable() { data class DataError(override val cause: Throwable) : RemoveCurrencyError() + + object HasLinkedTokens : RemoveCurrencyError() } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RemoveCurrencyUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RemoveCurrencyUseCase.kt index da933c144f..3f05e67341 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RemoveCurrencyUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/RemoveCurrencyUseCase.kt @@ -6,12 +6,12 @@ import arrow.core.raise.either import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.remove.RemoveCurrencyError import com.tangem.domain.tokens.repository.CurrenciesRepository +import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.utils.coroutines.CoroutineDispatcherProvider class RemoveCurrencyUseCase( - internal val currenciesRepository: CurrenciesRepository, - internal val dispatchers: CoroutineDispatcherProvider, + private val currenciesRepository: CurrenciesRepository, + private val walletManagersFacade: WalletManagersFacade, ) { suspend operator fun invoke( @@ -19,8 +19,23 @@ class RemoveCurrencyUseCase( currency: CryptoCurrency, ): Either { return either { + if (hasLinkedTokens(userWalletId, currency)) { + raise(RemoveCurrencyError.HasLinkedTokens) + } + catch( - block = { currenciesRepository.removeCurrency(userWalletId, currency) }, + block = { + currenciesRepository.removeCurrency(userWalletId, currency) + + when (currency) { + is CryptoCurrency.Coin -> { + walletManagersFacade.remove(userWalletId, setOf(currency.network)) + } + is CryptoCurrency.Token -> { + walletManagersFacade.removeTokens(userWalletId, setOf(currency)) + } + } + }, catch = { raise(RemoveCurrencyError.DataError(it)) }, ) }