From bf3a15c114cb263ce94a2375e355f66b1763bb49 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 21 Nov 2023 11:49:12 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../java/com/tangem/tap/TapApplication.kt | 11 - .../WalletCurrenciesManager.kt | 87 ------ .../di/WalletCurrenciesManagerProvider.kt | 25 -- .../DefaultWalletCurrenciesManager.kt | 261 ------------------ .../domain/DefaultCustomTokenInteractor.kt | 95 ++----- .../send/redux/middlewares/SendMiddleware.kt | 37 --- .../viewmodels/TokensListMigration.kt | 37 +-- .../viewmodels/TokensListViewModel.kt | 5 - .../tokens/legacy/redux/TokensMiddleware.kt | 223 +-------------- .../tangem/tap/proxy/UserWalletManagerImpl.kt | 54 +--- .../com/tangem/domain/tokens/TokensAction.kt | 12 +- 11 files changed, 46 insertions(+), 801 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/domain/walletCurrencies/WalletCurrenciesManager.kt delete mode 100644 app/src/main/java/com/tangem/tap/domain/walletCurrencies/di/WalletCurrenciesManagerProvider.kt delete mode 100644 app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index be77267ab0..904ef1dc22 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -62,8 +62,6 @@ import com.tangem.tap.domain.tokens.UserTokensRepository import com.tangem.tap.domain.tokens.UserTokensStorageService import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation import com.tangem.tap.domain.userWalletList.di.provideRuntimeImplementation -import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager -import com.tangem.tap.domain.walletCurrencies.di.provideDefaultImplementation import com.tangem.tap.domain.walletStores.WalletStoresManager import com.tangem.tap.domain.walletStores.di.provideDefaultImplementation import com.tangem.tap.domain.walletStores.repository.WalletAmountsRepository @@ -120,15 +118,6 @@ val walletStoresManager by lazy { appCurrencyProvider = { store.state.globalState.appCurrency }, ) } -val walletCurrenciesManager by lazy { - WalletCurrenciesManager.provideDefaultImplementation( - userTokensRepository = userTokensRepository, - walletStoresRepository = walletStoresRepository, - walletManagersRepository = walletManagersRepository, - walletAmountsRepository = walletAmountsRepository, - appCurrencyProvider = { store.state.globalState.appCurrency }, - ) -} @HiltAndroidApp internal class TapApplication : Application(), ImageLoaderFactory { diff --git a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/WalletCurrenciesManager.kt b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/WalletCurrenciesManager.kt deleted file mode 100644 index 413550b22e..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/WalletCurrenciesManager.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.tangem.tap.domain.walletCurrencies - -import com.tangem.common.CompletionResult -import com.tangem.domain.wallets.models.UserWallet -import com.tangem.tap.features.wallet.models.Currency - -interface WalletCurrenciesManager { - /** - * Update [UserWallet] currencies with same blockchain as provided [Currency] blockchain - * [UserWallet] currencies updates can be observed - * with [com.tangem.tap.domain.walletStores.WalletStoresManager.getAll] - * or [com.tangem.tap.domain.walletStores.WalletStoresManager.get] - * - * @param userWallet [UserWallet] which currencies will be updated - * @param currency [Currency] to find other currencies to update - * - * @return [CompletionResult] of operation - * */ - suspend fun update(userWallet: UserWallet, currency: Currency): CompletionResult - - /** - * Add list of [Currency] to [UserWallet]. - * [UserWallet] currencies updates can be observed - * with [com.tangem.tap.domain.walletStores.WalletStoresManager.getAll] - * or [com.tangem.tap.domain.walletStores.WalletStoresManager.get] - * - * @param userWallet [UserWallet] to add currencies - * @param currenciesToAdd list of [Currency] to add [UserWallet] - * - * @return [CompletionResult] of operation - * */ - suspend fun addCurrencies(userWallet: UserWallet, currenciesToAdd: List): CompletionResult - - /** - * Remove [Currency] from [UserWallet] - * [UserWallet] currencies updates can be observed - * with [com.tangem.tap.domain.walletStores.WalletStoresManager.getAll] - * or [com.tangem.tap.domain.walletStores.WalletStoresManager.get] - * - * @param userWallet [UserWallet] which currency will be removed - * @param currencyToRemove [Currency] to remove from [UserWallet] - * - * @return [CompletionResult] of operation - * */ - suspend fun removeCurrency(userWallet: UserWallet, currencyToRemove: Currency): CompletionResult - - /** - * Remove list of [Currency] from [UserWallet] - * [UserWallet] currencies updates can be observed - * with [com.tangem.tap.domain.walletStores.WalletStoresManager.getAll] - * or [com.tangem.tap.domain.walletStores.WalletStoresManager.get] - * - * @param userWallet [UserWallet] which currency will be removed - * @param currenciesToRemove list of [Currency] to remove from [UserWallet] - * - * @return [CompletionResult] of operation - * */ - suspend fun removeCurrencies(userWallet: UserWallet, currenciesToRemove: List): CompletionResult - - /** - * Add a callback [Listener] - * - * @param listener The callback that will add - */ - fun addListener(listener: Listener) - - /** - * Remove a callback [Listener] - * - * @param listener The callback that will removed - */ - fun removeListener(listener: Listener) - - /** - * Interface definition for a callbacks - */ - interface Listener { - fun willUpdate(userWallet: UserWallet, currency: Currency) {} - fun didUpdate(userWallet: UserWallet, currency: Currency) {} - fun willCurrenciesAdd(userWallet: UserWallet, currenciesToAdd: List) {} - fun willCurrenciesRemove(userWallet: UserWallet, currenciesToRemove: List) {} - fun willCurrencyRemove(userWallet: UserWallet, currencyToRemove: Currency) {} - } - - // For provider - companion object -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/di/WalletCurrenciesManagerProvider.kt b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/di/WalletCurrenciesManagerProvider.kt deleted file mode 100644 index bf2d47611e..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/di/WalletCurrenciesManagerProvider.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.tangem.tap.domain.walletCurrencies.di - -import com.tangem.domain.wallets.legacy.WalletManagersRepository -import com.tangem.tap.common.entities.FiatCurrency -import com.tangem.tap.domain.tokens.UserTokensRepository -import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager -import com.tangem.tap.domain.walletCurrencies.implementation.DefaultWalletCurrenciesManager -import com.tangem.tap.domain.walletStores.repository.WalletAmountsRepository -import com.tangem.tap.domain.walletStores.repository.WalletStoresRepository - -fun WalletCurrenciesManager.Companion.provideDefaultImplementation( - userTokensRepository: UserTokensRepository, - walletStoresRepository: WalletStoresRepository, - walletAmountsRepository: WalletAmountsRepository, - walletManagersRepository: WalletManagersRepository, - appCurrencyProvider: () -> FiatCurrency, -): WalletCurrenciesManager { - return DefaultWalletCurrenciesManager( - userTokensRepository = userTokensRepository, - walletStoresRepository = walletStoresRepository, - walletAmountsRepository = walletAmountsRepository, - walletManagersRepository = walletManagersRepository, - appCurrencyProvider = appCurrencyProvider, - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt deleted file mode 100644 index db1f9347dc..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt +++ /dev/null @@ -1,261 +0,0 @@ -package com.tangem.tap.domain.walletCurrencies.implementation - -import com.tangem.blockchain.common.derivation.DerivationStyle -import com.tangem.common.* -import com.tangem.domain.common.BlockchainNetwork -import com.tangem.domain.common.DerivationStyleProvider -import com.tangem.domain.common.util.derivationStyleProvider -import com.tangem.domain.models.scan.CardDTO -import com.tangem.domain.wallets.legacy.WalletManagersRepository -import com.tangem.domain.wallets.models.UserWallet -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.tap.common.entities.FiatCurrency -import com.tangem.tap.domain.model.builders.WalletStoreBuilder -import com.tangem.tap.domain.tokens.UserTokensRepository -import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager -import com.tangem.tap.domain.walletStores.repository.WalletAmountsRepository -import com.tangem.tap.domain.walletStores.repository.WalletStoresRepository -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.models.toBlockchainNetworks -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.firstOrNull -import kotlinx.coroutines.withContext - -internal class DefaultWalletCurrenciesManager( - private val userTokensRepository: UserTokensRepository, - private val walletStoresRepository: WalletStoresRepository, - private val walletAmountsRepository: WalletAmountsRepository, - private val walletManagersRepository: WalletManagersRepository, - private val appCurrencyProvider: () -> FiatCurrency, -) : WalletCurrenciesManager { - - private val listeners = mutableListOf() - - override suspend fun update(userWallet: UserWallet, currency: Currency): CompletionResult = - withContext(Dispatchers.Default) { - listeners.forEach { it.willUpdate(userWallet, currency) } - val walletStore = walletStoresRepository.getSync(userWallet.walletId) - .find { - it.blockchain == currency.blockchain && - it.derivationPath?.rawPath == currency.derivationPath - } - - val updateResult = if (walletStore == null) { - CompletionResult.Success(Unit) - } else { - walletAmountsRepository.updateAmountsForWalletStore( - walletStore = walletStore, - userWallet = userWallet, - fiatCurrency = appCurrencyProvider(), - ) - } - listeners.forEach { it.didUpdate(userWallet, currency) } - updateResult - } - - override suspend fun addCurrencies( - userWallet: UserWallet, - currenciesToAdd: List, - ): CompletionResult = withContext(Dispatchers.Default) { - if (currenciesToAdd.isEmpty()) { - return@withContext CompletionResult.Success(Unit) - } - - val card = userWallet.scanResponse.card - val currenciesToAddWithMissingBlockchains = currenciesToAdd.addMissingBlockchainsIfNeeded( - userWallet.scanResponse.derivationStyleProvider, - ) - listeners.forEach { it.willCurrenciesAdd(userWallet, currenciesToAddWithMissingBlockchains) } - - updateWalletStores( - userWallet = userWallet, - blockchainNetworks = currenciesToAddWithMissingBlockchains - .toBlockchainNetworks() - .addSameBlockchainTokens(userWallet.walletId), - ) - .map { - saveUserCurrencies(card, getSavedCurrencies(userWallet.walletId)) - } - .flatMap { - updateWalletStoresAmounts( - userWallet = userWallet, - updatedCurrencies = currenciesToAddWithMissingBlockchains, - ) - } - } - - override suspend fun removeCurrencies( - userWallet: UserWallet, - currenciesToRemove: List, - ): CompletionResult = withContext(Dispatchers.Default) { - if (currenciesToRemove.isEmpty()) { - return@withContext CompletionResult.Success(Unit) - } - - listeners.forEach { it.willCurrenciesRemove(userWallet, currenciesToRemove) } - val card = userWallet.scanResponse.card - val remainingCurrencies = getSavedCurrencies(userWallet.walletId) - .filter { it !in currenciesToRemove } - val remainingBlockchains = remainingCurrencies - .filterIsInstance() - - walletStoresRepository.deleteDifference(userWallet.walletId, remainingBlockchains) - .flatMap { - updateWalletStores(userWallet, remainingCurrencies.toBlockchainNetworks()) - } - .doOnResult { - saveUserCurrencies(card, remainingCurrencies) - } - } - - override suspend fun removeCurrency(userWallet: UserWallet, currencyToRemove: Currency): CompletionResult { - listeners.forEach { it.willCurrencyRemove(userWallet, currencyToRemove) } - return removeCurrencies(userWallet, listOf(currencyToRemove)) - } - - override fun addListener(listener: WalletCurrenciesManager.Listener) { - listeners.add(listener) - } - - override fun removeListener(listener: WalletCurrenciesManager.Listener) { - listeners.remove(listener) - } - - private suspend fun getSavedCurrencies(userWalletId: UserWalletId): List { - return withContext(Dispatchers.Default) { - walletStoresRepository.getSync(userWalletId) - .flatMap { walletStore -> - walletStore.walletsData.map { it.currency } - } - } - } - - private suspend fun saveUserCurrencies(card: CardDTO, currencies: List) { - withContext(Dispatchers.IO) { - userTokensRepository.saveUserTokens( - card = card, - tokens = currencies, - ) - } - } - - // TODO: Need refactoring - private suspend fun List.addSameBlockchainTokens( - userWalletId: UserWalletId, - ): List { - val networks = arrayListOf() - val savedWalletStores = withContext(Dispatchers.Default) { - walletStoresRepository.getSync(userWalletId) - } - - this.forEach { network -> - val walletStore = savedWalletStores.firstOrNull { - it.blockchain == network.blockchain && it.derivationPath?.rawPath == network.derivationPath - } - - if (walletStore != null) { - val tokens = walletStore.walletsData - .asSequence() - .map { it.currency } - .filterIsInstance() - .map { it.token } - .toList() - - networks.add(network.copy(tokens = tokens + network.tokens.toSet())) - } else { - networks.add(network) - } - } - - return networks - } - - private fun List.addMissingBlockchainsIfNeeded( - derivationStyleProvider: DerivationStyleProvider, - ): List { - if (this.isEmpty()) return this - val currencies = this.asSequence() - - return currencies - .groupBy { currency -> - findBlockchainCurrency(currency, currencies, derivationStyleProvider.getDerivationStyle()) - } - .mapValues { (blockchainCurrency, blockchainCurrencies) -> - findBlockchainTokens(blockchainCurrency, blockchainCurrencies) - } - .flatMap { (blockchainCurrency, blockchainTokens) -> - arrayListOf(blockchainCurrency) + blockchainTokens - } - } - - private fun findBlockchainCurrency( - currency: Currency, - currencies: Sequence, - cardDerivationStyle: DerivationStyle?, - ): Currency.Blockchain { - return currencies - .filterIsInstance() - .firstOrNull { - it.blockchain == currency.blockchain && - it.derivationPath == currency.derivationPath - } - ?: Currency.Blockchain( - blockchain = currency.blockchain, - derivationPath = currency.derivationPath - ?: currency.blockchain.derivationPath(cardDerivationStyle)?.rawPath, - ) - } - - private fun findBlockchainTokens( - blockchainCurrency: Currency.Blockchain, - blockchainCurrencies: List, - ): List { - return blockchainCurrencies - .filterIsInstance() - .map { token -> - token.copy( - derivationPath = token.derivationPath ?: blockchainCurrency.derivationPath, - ) - } - } - - private suspend fun updateWalletStores( - userWallet: UserWallet, - blockchainNetworks: List, - ): CompletionResult { - return blockchainNetworks - .map { blockchainNetwork -> - walletManagersRepository.findOrMakeMultiCurrencyWalletManager( - userWallet = userWallet, - blockchainNetwork = blockchainNetwork, - ) - .flatMap { walletManager -> - walletStoresRepository.storeOrUpdate( - userWalletId = userWallet.walletId, - walletStore = WalletStoreBuilder(userWallet, blockchainNetwork) - .walletManager(walletManager) - .build(), - ) - } - } - .fold() - } - - private suspend fun updateWalletStoresAmounts( - userWallet: UserWallet, - updatedCurrencies: List, - ): CompletionResult { - val updatedBlockchains = updatedCurrencies - .filterIsInstance() - val updatedWalletStores = walletStoresRepository.get(userWallet.walletId) - .firstOrNull() - ?.filter { it.blockchainWalletData.currency in updatedBlockchains } - ?: return CompletionResult.Success(Unit) - - return walletAmountsRepository.updateAmountsForWalletStores( - walletStores = updatedWalletStores, - userWallet = userWallet, - fiatCurrency = appCurrencyProvider(), - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt index 7de4ee238b..08cb0f8f16 100644 --- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt +++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt @@ -6,9 +6,7 @@ import com.tangem.common.CompletionResult import com.tangem.common.card.EllipticCurve import com.tangem.common.core.TangemError import com.tangem.common.extensions.ByteArrayKey -import com.tangem.common.extensions.guard import com.tangem.common.extensions.toMapKey -import com.tangem.common.flatMap import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.data.tokens.utils.CryptoCurrencyFactory import com.tangem.domain.common.configs.CardConfig @@ -18,12 +16,9 @@ import com.tangem.domain.common.util.hasDerivation import com.tangem.domain.features.addCustomToken.CustomCurrency import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase -import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWallet -import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.operations.derivation.ExtendedPublicKeysMap -import com.tangem.tap.* import com.tangem.tap.common.extensions.dispatchDebugErrorNotification import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.global.GlobalAction @@ -32,10 +27,11 @@ import com.tangem.tap.features.customtoken.impl.domain.models.FoundToken import com.tangem.tap.features.tokens.legacy.redux.TokensMiddleware import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.proxy.redux.DaggerGraphState +import com.tangem.tap.store +import com.tangem.tap.tangemSdkManager +import com.tangem.tap.userWalletsListManager import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import timber.log.Timber /** * Default implementation of custom token interactor @@ -178,70 +174,35 @@ class DefaultCustomTokenInteractor( } private suspend fun submitAdd(userWallet: UserWallet, currency: Currency) { + val cryptoCurrencyFactory = CryptoCurrencyFactory() + val scanResponse = userWallet.scanResponse - val walletFeatureToggles = store.state.daggerGraphState.get(DaggerGraphState::walletFeatureToggles) + val userWalletId = userWallet.walletId - if (walletFeatureToggles.isRedesignedScreenEnabled) { - val cryptoCurrencyFactory = CryptoCurrencyFactory() - - submitNewAdd( - userWalletId = userWallet.walletId, - updatedScanResponse = scanResponse, - currencyList = listOfNotNull( - when (currency) { - is Currency.Blockchain -> { - cryptoCurrencyFactory.createCoin( - blockchain = currency.blockchain, - extraDerivationPath = currency.derivationPath, - derivationStyleProvider = scanResponse.derivationStyleProvider, - ) - } - is Currency.Token -> { - cryptoCurrencyFactory.createToken( - sdkToken = currency.token, - blockchain = currency.blockchain, - extraDerivationPath = currency.derivationPath, - derivationStyleProvider = scanResponse.derivationStyleProvider, - ) - } - }, - ), - ) - } else { - submitLegacyAdd(scanResponse = scanResponse, currency = currency) - } - } - - private suspend fun submitLegacyAdd(scanResponse: ScanResponse, currency: Currency) { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to add currencies, no user wallet selected") - return - } - - userWalletsListManager.update( - userWalletId = selectedUserWallet.walletId, - update = { userWallet -> userWallet.copy(scanResponse = scanResponse) }, + val currencyList = listOfNotNull( + when (currency) { + is Currency.Blockchain -> { + cryptoCurrencyFactory.createCoin( + blockchain = currency.blockchain, + extraDerivationPath = currency.derivationPath, + derivationStyleProvider = scanResponse.derivationStyleProvider, + ) + } + is Currency.Token -> { + cryptoCurrencyFactory.createToken( + sdkToken = currency.token, + blockchain = currency.blockchain, + extraDerivationPath = currency.derivationPath, + derivationStyleProvider = scanResponse.derivationStyleProvider, + ) + } + }, ) - .flatMap { updatedUserWallet -> - walletCurrenciesManager.addCurrencies( - userWallet = updatedUserWallet, - currenciesToAdd = listOf(currency), - ) - } - } - private fun submitNewAdd( - userWalletId: UserWalletId, - updatedScanResponse: ScanResponse, - currencyList: List, - ) { - scope.launch { - userWalletsListManager.update( - userWalletId = userWalletId, - update = { it.copy(scanResponse = updatedScanResponse) }, - ) - - addCryptoCurrenciesUseCase(userWalletId, currencyList) + userWalletsListManager.update(userWalletId) { + it.copy(scanResponse = scanResponse) } + + addCryptoCurrenciesUseCase(userWalletId, currencyList) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt index 0dfd830ce1..2988ed383b 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt @@ -11,7 +11,6 @@ import com.tangem.blockchain.common.* import com.tangem.blockchain.common.transaction.Fee import com.tangem.blockchain.extensions.SimpleResult import com.tangem.common.core.TangemSdkError -import com.tangem.common.extensions.guard import com.tangem.core.analytics.Analytics import com.tangem.core.navigation.NavigationAction import com.tangem.domain.common.TapWorkarounds.isStart2Coin @@ -39,20 +38,15 @@ import com.tangem.tap.features.demo.isDemoCard import com.tangem.tap.features.send.redux.* import com.tangem.tap.features.send.redux.FeeAction.RequestFee import com.tangem.tap.features.send.redux.states.* -import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.scope import com.tangem.tap.store -import com.tangem.tap.userWalletsListManager -import com.tangem.tap.walletCurrenciesManager import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE import com.tangem.wallet.R -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.Middleware -import timber.log.Timber import java.util.EnumSet /** @@ -277,9 +271,6 @@ private fun sendTransaction( Analytics.sendSelectedCurrencyEvent(mainCurrencyType) dispatch(NavigationAction.PopBackTo()) } - scope.launch(Dispatchers.IO) { - updateAfterTransaction(walletManager) - } } is SimpleResult.Failure -> { updateFeedbackManagerInfo( @@ -418,32 +409,4 @@ private fun updateWarnings(dispatch: (Action) -> Unit) { val warnings = warningsManager.getWarnings(WarningMessage.Location.SendScreen, listOf(blockchain)) dispatch(SendAction.Warnings.Set(warnings)) -} - -private suspend fun updateAfterTransaction(walletManager: WalletManager) { - val walletFeatureToggles = store.state.daggerGraphState.get(DaggerGraphState::walletFeatureToggles) - if (!walletFeatureToggles.isRedesignedScreenEnabled) { - updateWalletsLegacy(walletManager) - } -} - -private suspend fun updateWalletsLegacy(walletManager: WalletManager) { - updateWallet(walletManager) - delay(timeMillis = 11000) // more than 10000 to avoid throttling - updateWallet(walletManager) -} - -private suspend fun updateWallet(walletManager: WalletManager) { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to update wallet, no user wallet selected") - return - } - val wallet = walletManager.wallet - walletCurrenciesManager.update( - userWallet = selectedUserWallet, - currency = Currency.Blockchain( - blockchain = wallet.blockchain, - derivationPath = wallet.publicKey.derivationPath?.rawPath, - ), - ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt index 6403179428..7ccf604f5a 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt @@ -11,7 +11,6 @@ import com.tangem.domain.tokens.TokensAction import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase -import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles import com.tangem.tap.store import timber.log.Timber import kotlin.properties.Delegates @@ -19,12 +18,10 @@ import kotlin.properties.Delegates /** * Class that divide a new and legacy logic when user uses tokens list screen * - * @property walletFeatureToggles wallet feature toggles * @property getSelectedWalletSyncUseCase use case that returns selected wallet * @property getCurrenciesUseCase use case that returns crypto currencies of a specified wallet */ internal class TokensListMigration( - private val walletFeatureToggles: WalletFeatureToggles, private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val getCurrenciesUseCase: GetCryptoCurrenciesUseCase, ) { @@ -80,24 +77,11 @@ internal class TokensListMigration( } fun onSaveButtonClick( - currentTokensList: List, - currentBlockchainList: List, - changedTokensList: MutableList, - changedBlockchainList: List, - ) { - if (walletFeatureToggles.isRedesignedScreenEnabled) { - saveByNewWay(changedTokensList = changedTokensList, changedBlockchainList = changedBlockchainList) - } else { - saveByOldWay(currentTokensList, currentBlockchainList, changedTokensList, changedBlockchainList) - } - } - - private fun saveByNewWay( changedTokensList: MutableList, changedBlockchainList: List, ) { store.dispatch( - action = TokensAction.NewSaveChanges( + action = TokensAction.SaveChanges( currentTokens = currentNewTokens, currentCoins = currentNewCoins, changedTokens = changedTokensList.mapNotNull { @@ -119,23 +103,4 @@ internal class TokensListMigration( ), ) } - - private fun saveByOldWay( - currentTokensList: List, - currentBlockchainList: List, - changedTokensList: MutableList, - changedBlockchainList: List, - ) { - val scanResponse = store.state.globalState.scanResponse ?: return - - store.dispatch( - action = TokensAction.LegacySaveChanges( - currentTokens = currentTokensList, - currentBlockchains = currentBlockchainList, - changedTokens = changedTokensList, - changedBlockchains = changedBlockchainList, - scanResponse = scanResponse, - ), - ) - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListViewModel.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListViewModel.kt index f2046c81df..94c4974fc7 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListViewModel.kt @@ -22,7 +22,6 @@ import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase import com.tangem.domain.tokens.TokenWithBlockchain import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase -import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles import com.tangem.tap.common.extensions.fullNameWithoutTestnet import com.tangem.tap.common.extensions.getNetworkName import com.tangem.tap.features.tokens.impl.domain.TokensListInteractor @@ -70,7 +69,6 @@ internal class TokensListViewModel @Inject constructor( private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, analyticsEventHandler: AnalyticsEventHandler, getCurrenciesUseCase: GetCryptoCurrenciesUseCase, - walletFeatureToggles: WalletFeatureToggles, ) : ViewModel(), DefaultLifecycleObserver { private val isManageAccess = store.state.tokensState.isManageAccess @@ -88,7 +86,6 @@ internal class TokensListViewModel @Inject constructor( private var changedBlockchainList: MutableList = mutableListOf() private val tokensListMigration = TokensListMigration( - walletFeatureToggles = walletFeatureToggles, getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase, getCurrenciesUseCase = getCurrenciesUseCase, ) @@ -307,8 +304,6 @@ internal class TokensListViewModel @Inject constructor( fun onSaveButtonClick() { analyticsSender.sendWhenSaveButtonClicked() tokensListMigration.onSaveButtonClick( - currentTokensList = currentTokensList, - currentBlockchainList = currentBlockchainList, changedTokensList = changedTokensList, changedBlockchainList = changedBlockchainList, ) 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 101c7c51e5..ceeefb7c60 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 @@ -2,14 +2,11 @@ package com.tangem.tap.features.tokens.legacy.redux import com.tangem.blockchain.blockchains.cardano.CardanoUtils import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.derivation.DerivationStyle import com.tangem.common.CompletionResult import com.tangem.common.card.EllipticCurve import com.tangem.common.doOnSuccess import com.tangem.common.extensions.ByteArrayKey -import com.tangem.common.extensions.guard import com.tangem.common.extensions.toMapKey -import com.tangem.common.flatMap import com.tangem.core.navigation.NavigationAction import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.domain.common.configs.CardConfig @@ -17,26 +14,24 @@ import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.common.util.supportsHdWallet import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase -import com.tangem.domain.tokens.TokenWithBlockchain import com.tangem.domain.tokens.TokensAction import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.walletconnect.WalletConnectActions import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId import com.tangem.operations.derivation.ExtendedPublicKeysMap -import com.tangem.tap.* import com.tangem.tap.common.extensions.dispatchDebugErrorNotification import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.TapError -import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.proxy.redux.DaggerGraphState -import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE -import kotlinx.coroutines.delay +import com.tangem.tap.scope +import com.tangem.tap.store +import com.tangem.tap.tangemSdkManager +import com.tangem.tap.userWalletsListManager import kotlinx.coroutines.launch import org.rekotlin.Middleware -import timber.log.Timber @Suppress("LargeClass") object TokensMiddleware { @@ -53,15 +48,14 @@ object TokensMiddleware { { next -> { action -> when (action) { - is TokensAction.LegacySaveChanges -> handleLegacySaveChanges(action) - is TokensAction.NewSaveChanges -> handleNewSaveChanges(action) + is TokensAction.SaveChanges -> handleSaveChanges(action) } next(action) } } } - private fun handleNewSaveChanges(action: TokensAction.NewSaveChanges) { + private fun handleSaveChanges(action: TokensAction.SaveChanges) { scope.launch { val scanResponse = action.userWallet.scanResponse @@ -74,7 +68,7 @@ object TokensMiddleware { val tokensToAdd = action.changedTokens.filterNot(currentTokens::contains) val tokensToRemove = currentTokens.filterNot { token -> action.changedTokens.any { it == token } } - removeNewCurrenciesIfNeeded( + removeCurrenciesIfNeeded( userWalletId = action.userWallet.walletId, currencies = blockchainsToRemove + tokensToRemove, ) @@ -91,140 +85,14 @@ object TokensMiddleware { if (scanResponse.supportsHdWallet()) { deriveMissingCoins(scanResponse = scanResponse, currencyList = currencyList) { - submitNewAdd( + submitAdd( userWallet = action.userWallet, updatedScanResponse = it, currencyList = currencyList, ) } } else { - submitNewAdd( - userWallet = action.userWallet, - updatedScanResponse = scanResponse, - currencyList = currencyList, - ) - } - } - } - - private fun handleLegacySaveChanges(action: TokensAction.LegacySaveChanges) { - scope.launch { - val scanResponse = action.scanResponse - - val currentTokens = action.currentTokens - val currentBlockchains = action.currentBlockchains - - val blockchainsToAdd = action.changedBlockchains.filterNot(currentBlockchains::contains) - val blockchainsToRemove = currentBlockchains.filterNot(action.changedBlockchains::contains) - - val tokensToAdd = action.changedTokens.filterNot(currentTokens::contains) - val tokensToRemove = - currentTokens.filterNot { token -> action.changedTokens.any { it.token == token.token } } - - removeLegacyCurrenciesIfNeeded( - currencies = convertToCurrencies( - blockchains = blockchainsToRemove, - tokens = tokensToRemove, - derivationStyle = scanResponse.derivationStyleProvider.getDerivationStyle(), - ), - ) - - val isNothingToDoWithTokens = tokensToAdd.isEmpty() && tokensToRemove.isEmpty() - val isNothingToDoWithBlockchain = blockchainsToAdd.isEmpty() && blockchainsToRemove.isEmpty() - if (isNothingToDoWithTokens && isNothingToDoWithBlockchain) { - store.dispatchDebugErrorNotification(message = "Nothing to save") - store.dispatchOnMain(NavigationAction.PopBackTo()) - return@launch - } - - val currencyList = convertToCurrencies( - blockchains = blockchainsToAdd, - tokens = tokensToAdd, - derivationStyle = scanResponse.derivationStyleProvider.getDerivationStyle(), - ) - - if (scanResponse.supportsHdWallet()) { - deriveMissingBlockchains(scanResponse, currencyList) { - submitLegacyAdd(it, currencyList) - store.dispatchOnMain(NavigationAction.PopBackTo()) - } - } else { - submitLegacyAdd(scanResponse, currencyList) - store.dispatchOnMain(NavigationAction.PopBackTo()) - } - } - } - - private fun convertToCurrencies( - blockchains: List, - tokens: List, - derivationStyle: DerivationStyle?, - ): List { - return blockchains.map { Currency.Blockchain(it, it.derivationPath(derivationStyle)?.rawPath) } + - tokens.map { - Currency.Token( - token = it.token, - blockchain = it.blockchain, - derivationPath = it.blockchain.derivationPath(derivationStyle)?.rawPath, - ) - } - } - - private fun deriveMissingBlockchains( - scanResponse: ScanResponse, - currencyList: List, - onSuccess: (ScanResponse) -> Unit, - ) { - val config = CardConfig.createConfig(scanResponse.card) - val derivationDataList = currencyList.mapNotNull { currency -> - val curve = config.primaryCurve(currency.blockchain) - curve?.let { getLegacyDerivations(curve, scanResponse, currency) } - } - val derivations = buildMap> { - derivationDataList.forEach { - val current = this[it.derivations.first] - if (current != null) { - current.addAll(it.derivations.second) - current.distinct() - } else { - this[it.derivations.first] = it.derivations.second.toMutableList() - } - } - } - - if (derivations.isEmpty()) { - onSuccess(scanResponse) - return - } - - scope.launch { - val result = tangemSdkManager.derivePublicKeys( - cardId = null, - derivations = derivations, - ) - when (result) { - is CompletionResult.Success -> { - val newDerivedKeys = result.data.entries - val oldDerivedKeys = scanResponse.derivedKeys - - val walletKeys = (newDerivedKeys.keys + oldDerivedKeys.keys).toSet() - - val updatedDerivedKeys = walletKeys.associateWith { walletKey -> - val oldDerivations = ExtendedPublicKeysMap(oldDerivedKeys[walletKey] ?: emptyMap()) - val newDerivations = newDerivedKeys[walletKey] ?: ExtendedPublicKeysMap(emptyMap()) - ExtendedPublicKeysMap(oldDerivations + newDerivations) - } - val updatedScanResponse = scanResponse.copy( - derivedKeys = updatedDerivedKeys, - ) - store.dispatchOnMain(GlobalAction.SaveScanResponse(updatedScanResponse)) - delay(DELAY_SDK_DIALOG_CLOSE) - - onSuccess(updatedScanResponse) - } - is CompletionResult.Failure -> { - store.dispatchDebugErrorNotification(TapError.CustomError("Error adding tokens")) - } + submitAdd(action.userWallet, scanResponse, currencyList) } } } @@ -237,7 +105,7 @@ object TokensMiddleware { val config = CardConfig.createConfig(scanResponse.card) val derivationDataList = currencyList.mapNotNull { currency -> val curve = config.primaryCurve(blockchain = Blockchain.fromId(currency.network.id.value)) - curve?.let { getNewDerivations(curve, scanResponse, currency) } + curve?.let { getDerivations(curve, scanResponse, currency) } } val derivations = buildMap> { derivationDataList.forEach { @@ -286,42 +154,7 @@ object TokensMiddleware { } } - private fun getLegacyDerivations( - curve: EllipticCurve, - scanResponse: ScanResponse, - currency: Currency, - ): DerivationData? { - val wallet = scanResponse.card.wallets.firstOrNull { it.curve == curve } ?: return null - - val supportedCurves = currency.blockchain.getSupportedCurves() - val path = currency.blockchain.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) - .takeIf { supportedCurves.contains(curve) } - - val customPath = currency.derivationPath?.let { - DerivationPath(it) - }.takeIf { supportedCurves.contains(curve) } - - val bothCandidates = listOfNotNull(path, customPath).distinct().toMutableList() - if (bothCandidates.isEmpty()) return null - - if (currency is Currency.Blockchain && currency.blockchain == Blockchain.Cardano) { - currency.derivationPath?.let { - bothCandidates.add(CardanoUtils.extendedDerivationPath(DerivationPath(it))) - } - } - - val mapKeyOfWalletPublicKey = wallet.publicKey.toMapKey() - val alreadyDerivedKeys: ExtendedPublicKeysMap = - scanResponse.derivedKeys[mapKeyOfWalletPublicKey] ?: ExtendedPublicKeysMap(emptyMap()) - val alreadyDerivedPaths = alreadyDerivedKeys.keys.toList() - - val toDerive = bothCandidates.filterNot { alreadyDerivedPaths.contains(it) } - if (toDerive.isEmpty()) return null - - return DerivationData(derivations = mapKeyOfWalletPublicKey to toDerive) - } - - private fun getNewDerivations( + private fun getDerivations( curve: EllipticCurve, scanResponse: ScanResponse, currency: CryptoCurrency, @@ -359,28 +192,7 @@ object TokensMiddleware { class DerivationData(val derivations: Pair>) - private fun submitLegacyAdd(scanResponse: ScanResponse, currencyList: List) { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to add currencies, no user wallet selected") - return - } - scope.launch { - userWalletsListManager.update( - userWalletId = selectedUserWallet.walletId, - update = { userWallet -> - userWallet.copy(scanResponse = scanResponse) - }, - ) - .flatMap { updatedUserWallet -> - walletCurrenciesManager.addCurrencies( - userWallet = updatedUserWallet, - currenciesToAdd = currencyList, - ) - } - } - } - - private fun submitNewAdd( + private fun submitAdd( userWallet: UserWallet, updatedScanResponse: ScanResponse, currencyList: List, @@ -398,16 +210,7 @@ object TokensMiddleware { store.dispatchOnMain(NavigationAction.PopBackTo()) } - private suspend fun removeLegacyCurrenciesIfNeeded(currencies: List) { - if (currencies.isEmpty()) return - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to remove currencies, no user wallet selected") - return - } - walletCurrenciesManager.removeCurrencies(selectedUserWallet, currencies) - } - - private suspend fun removeNewCurrenciesIfNeeded(userWalletId: UserWalletId, currencies: List) { + private suspend fun removeCurrenciesIfNeeded(userWalletId: UserWalletId, currencies: List) { if (currencies.isEmpty()) return val currenciesRepository = store.state.daggerGraphState.get(DaggerGraphState::currenciesRepository) val walletManagersFacade = store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade) diff --git a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt index 196bdc51dc..ce951866dd 100644 --- a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt @@ -4,9 +4,6 @@ import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token import com.tangem.blockchain.common.WalletManager -import com.tangem.common.doOnFailure -import com.tangem.common.extensions.guard -import com.tangem.domain.common.BlockchainNetwork import com.tangem.domain.common.extensions.fromNetworkId import com.tangem.domain.common.extensions.toCoinId import com.tangem.domain.common.extensions.toNetworkId @@ -18,12 +15,8 @@ import com.tangem.lib.crypto.models.Currency.NonNativeToken import com.tangem.lib.crypto.models.ProxyAmount import com.tangem.lib.crypto.models.ProxyFiatCurrency import com.tangem.tap.userWalletsListManager -import com.tangem.tap.walletCurrenciesManager -import com.tangem.tap.walletStoresManager -import kotlinx.coroutines.flow.firstOrNull import timber.log.Timber import java.math.BigDecimal -import com.tangem.tap.features.wallet.models.Currency as WalletCurrency class UserWalletManagerImpl( private val appStateHolder: AppStateHolder, @@ -104,39 +97,12 @@ class UserWalletManagerImpl( } override suspend fun addToken(currency: Currency, derivationPath: String?) { - val blockchain = requireNotNull(Blockchain.fromNetworkId(currency.networkId)) { "blockchain not found" } - val blockchainNetwork = BlockchainNetwork(blockchain, derivationPath, emptyList()) - - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to add token, no user wallet selected") - return - } - walletCurrenciesManager.addCurrencies( - userWallet = selectedUserWallet, - currenciesToAdd = listOf(currency.toWalletCurrency(blockchainNetwork)), - ) + // FIXME: Can be removed, used only in learn2earn } override suspend fun hideAllTokens() { - val userWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("No user wallets selected") - return - } - - val currencies = walletStoresManager.get(userWallet.walletId) - .firstOrNull() - ?.flatMap { walletStore -> - walletStore.walletsData.map { it.currency } - } - .guard { - Timber.d("No currencies found") - return - } - - walletCurrenciesManager.removeCurrencies(userWallet, currenciesToRemove = currencies) - .doOnFailure { e -> - Timber.e(e, "Unable to delete all currencies") - } + // FIXME: Used only in Tester Actions + Timber.w("Not implemented") } override suspend fun getWalletAddress(networkId: String, derivationPath: String?): String { @@ -237,18 +203,4 @@ private fun NonNativeToken.toSdkToken(): Token { contractAddress = this.contractAddress, decimals = this.decimalCount, ) -} - -private fun Currency.toWalletCurrency(network: BlockchainNetwork): WalletCurrency { - return when (this) { - is NativeToken -> WalletCurrency.Blockchain( - blockchain = network.blockchain, - derivationPath = network.derivationPath, - ) - is NonNativeToken -> WalletCurrency.Token( - token = this.toSdkToken(), - blockchain = network.blockchain, - derivationPath = network.derivationPath, - ) - } } \ No newline at end of file diff --git a/domain/legacy/src/main/java/com/tangem/domain/tokens/TokensAction.kt b/domain/legacy/src/main/java/com/tangem/domain/tokens/TokensAction.kt index 3cfbe08917..d5a0d8be8e 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/tokens/TokensAction.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/tokens/TokensAction.kt @@ -2,7 +2,6 @@ package com.tangem.domain.tokens import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token -import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWallet import org.rekotlin.Action @@ -15,16 +14,7 @@ sealed interface TokensAction : Action { object ReadAccess : SetArgs } - @Deprecated("Action is used for saving data by old way. It will be removed after deleting of legacy wallet screen") - data class LegacySaveChanges( - val currentTokens: List, - val currentBlockchains: List, - val changedTokens: List, - val changedBlockchains: List, - val scanResponse: ScanResponse, - ) : TokensAction - - data class NewSaveChanges( + data class SaveChanges( val currentTokens: List, val currentCoins: List, val changedTokens: List,