From a10c1a850552842c0dbf528d61c440da96cb799c Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 7 Feb 2024 14:44:58 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../java/com/tangem/tap/TapApplication.kt | 14 - .../com/tangem/tap/common/redux/AppState.kt | 2 - .../tangem/tap/di/domain/CardDomainModule.kt | 12 +- .../card/DefaultDerivePublicKeysUseCase.kt | 41 --- .../impl/di/CustomTokenInteractorModule.kt | 3 - .../domain/DefaultCustomTokenInteractor.kt | 156 +-------- .../viewmodels/TokensListMigration.kt | 95 ++++-- .../viewmodels/TokensListViewModel.kt | 17 +- .../tokens/legacy/redux/TokensMiddleware.kt | 250 --------------- .../tangem/tap/proxy/DerivationManagerImpl.kt | 298 ------------------ .../com/tangem/tap/proxy/di/ProxyModule.kt | 16 - .../tap/proxy/redux/DaggerGraphState.kt | 6 - .../configs/feature_toggles_config.json | 4 - .../domain/card/DerivePublicKeysUseCase.kt | 22 +- .../com/tangem/domain/tokens/TokensAction.kt | 10 - .../referral/domain/ReferralInteractorImpl.kt | 35 +- .../domain/converter/TokensConverter.kt | 34 -- .../domain/di/ReferralDomainModule.kt | 9 - .../tester/api/TesterFeatureToggles.kt | 11 - .../tester/di/TesterFeatureTogglesModule.kt | 21 -- .../DefaultTesterFeatureToggles.kt | 19 -- .../wallet/viewmodels/WalletViewModel.kt | 138 ++------ .../intents/WalletWarningsClickIntents.kt | 122 +------ .../tangem/lib/crypto/DerivationManager.kt | 12 - 24 files changed, 132 insertions(+), 1215 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/domain/card/DefaultDerivePublicKeysUseCase.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/tokens/legacy/redux/TokensMiddleware.kt delete mode 100644 app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt delete mode 100644 features/referral/domain/src/main/java/com/tangem/feature/referral/domain/converter/TokensConverter.kt delete mode 100644 features/tester/api/src/main/java/com/tangem/features/tester/api/TesterFeatureToggles.kt delete mode 100644 features/tester/impl/src/main/java/com/tangem/feature/tester/di/TesterFeatureTogglesModule.kt delete mode 100644 features/tester/impl/src/main/java/com/tangem/feature/tester/featuretoggles/DefaultTesterFeatureToggles.kt delete mode 100644 libs/crypto/src/main/java/com/tangem/lib/crypto/DerivationManager.kt diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 955106f3dc..11145469dc 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -29,7 +29,6 @@ import com.tangem.domain.apptheme.GetAppThemeModeUseCase import com.tangem.domain.apptheme.repository.AppThemeModeRepository import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository import com.tangem.domain.card.ScanCardProcessor -import com.tangem.domain.card.repository.DerivationsRepository import com.tangem.domain.common.LogConfig import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.NetworksRepository @@ -38,10 +37,8 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.domain.wallets.repository.WalletsRepository import com.tangem.features.managetokens.featuretoggles.ManageTokensFeatureToggles import com.tangem.features.send.api.featuretoggles.SendFeatureToggles -import com.tangem.features.tester.api.TesterFeatureToggles import com.tangem.tap.common.analytics.AnalyticsFactory import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder -import com.tangem.tap.common.analytics.handlers.BlockchainExceptionHandler import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHandler import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler @@ -119,9 +116,6 @@ internal class TapApplication : Application(), ImageLoaderFactory { @Inject lateinit var scanCardProcessor: ScanCardProcessor - @Inject - lateinit var blockchainExceptionHandler: BlockchainExceptionHandler - @Inject lateinit var appCurrencyRepository: AppCurrencyRepository @@ -155,12 +149,6 @@ internal class TapApplication : Application(), ImageLoaderFactory { @Inject lateinit var oneTimeEventFilter: OneTimeEventFilter - @Inject - lateinit var derivationsRepository: DerivationsRepository - - @Inject - lateinit var testerFeatureToggles: TesterFeatureToggles - @Inject lateinit var blockchainDataStorage: BlockchainDataStorage // endregion Injected @@ -238,8 +226,6 @@ internal class TapApplication : Application(), ImageLoaderFactory { balanceHidingRepository = balanceHidingRepository, walletsRepository = walletsRepository, sendFeatureToggles = sendFeatureToggles, - derivationsRepository = derivationsRepository, - testerFeatureToggles = testerFeatureToggles, blockchainDataStorage = blockchainDataStorage, ), ), diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt index e312758a52..892271058e 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt @@ -33,7 +33,6 @@ import com.tangem.tap.features.shop.redux.ShopMiddleware import com.tangem.tap.features.shop.redux.ShopState import com.tangem.tap.features.signin.redux.SignInMiddleware import com.tangem.tap.features.signin.redux.SignInState -import com.tangem.tap.features.tokens.legacy.redux.TokensMiddleware import com.tangem.tap.features.tokens.legacy.redux.TokensState import com.tangem.tap.features.wallet.redux.middlewares.TradeCryptoMiddleware import com.tangem.tap.features.welcome.redux.WelcomeMiddleware @@ -91,7 +90,6 @@ data class AppState( SendMiddleware().sendMiddleware, DetailsMiddleware().detailsMiddleware, DisclaimerMiddleware().disclaimerMiddleware, - TokensMiddleware.tokensMiddleware, WalletConnectMiddleware().walletConnectMiddleware, BackupMiddleware().backupMiddleware, ShopMiddleware().shopMiddleware, diff --git a/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt index 0d32faca9a..76aa092682 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt @@ -8,8 +8,6 @@ import com.tangem.domain.demo.DemoConfig import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.wallets.legacy.WalletsStateHolder import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase -import com.tangem.tap.domain.TangemSdkManager -import com.tangem.tap.domain.card.DefaultDerivePublicKeysUseCase import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -62,14 +60,8 @@ internal object CardDomainModule { @Provides @ViewModelScoped - fun provideDerivePublicKeysUseCase( - tangemSdkManager: TangemSdkManager, - derivationsRepository: DerivationsRepository, - ): DerivePublicKeysUseCase { - return DefaultDerivePublicKeysUseCase( - tangemSdkManager = tangemSdkManager, - derivationsRepository = derivationsRepository, - ) + fun provideDerivePublicKeysUseCase(derivationsRepository: DerivationsRepository): DerivePublicKeysUseCase { + return DerivePublicKeysUseCase(derivationsRepository = derivationsRepository) } @Provides diff --git a/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivePublicKeysUseCase.kt b/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivePublicKeysUseCase.kt deleted file mode 100644 index a09df2969a..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/card/DefaultDerivePublicKeysUseCase.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.tangem.tap.domain.card - -import arrow.core.Either -import arrow.core.left -import arrow.core.right -import com.tangem.common.doOnFailure -import com.tangem.common.doOnSuccess -import com.tangem.common.extensions.ByteArrayKey -import com.tangem.crypto.hdWallet.DerivationPath -import com.tangem.domain.card.DerivePublicKeysUseCase -import com.tangem.domain.card.repository.DerivationsRepository -import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.operations.derivation.DerivationTaskResponse -import com.tangem.tap.domain.TangemSdkManager - -internal class DefaultDerivePublicKeysUseCase( - private val tangemSdkManager: TangemSdkManager, - private val derivationsRepository: DerivationsRepository, -) : DerivePublicKeysUseCase { - - override suspend fun invoke( - cardId: String?, - derivations: Map>, - ): Either { - tangemSdkManager.derivePublicKeys(cardId = cardId, derivations = derivations) - .doOnSuccess { return it.right() } - .doOnFailure { return Unit.left() } - - return Unit.left() - } - - override suspend fun invoke( - userWalletId: UserWalletId, - currencies: List, - ): Either { - return Either.catch { - derivationsRepository.derivePublicKeys(userWalletId, currencies) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/di/CustomTokenInteractorModule.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/di/CustomTokenInteractorModule.kt index 44d4a98284..61dc90c2dc 100644 --- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/di/CustomTokenInteractorModule.kt +++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/di/CustomTokenInteractorModule.kt @@ -3,7 +3,6 @@ package com.tangem.tap.features.customtoken.impl.di import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase -import com.tangem.features.tester.api.TesterFeatureToggles import com.tangem.tap.features.customtoken.impl.data.DefaultCustomTokenRepository import com.tangem.tap.features.customtoken.impl.domain.CustomTokenInteractor import com.tangem.tap.features.customtoken.impl.domain.DefaultCustomTokenInteractor @@ -30,7 +29,6 @@ internal object CustomTokenInteractorModule { reduxStateHolder: AppStateHolder, getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, derivePublicKeysUseCase: DerivePublicKeysUseCase, - testerFeatureToggles: TesterFeatureToggles, ): CustomTokenInteractor { return DefaultCustomTokenInteractor( featureRepository = DefaultCustomTokenRepository( @@ -40,7 +38,6 @@ internal object CustomTokenInteractorModule { ), getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase, derivePublicKeysUseCase = derivePublicKeysUseCase, - testerFeatureToggles = testerFeatureToggles, ) } } \ 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 2d6ad2aebf..f3f73a98d3 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 @@ -1,40 +1,19 @@ package com.tangem.tap.features.customtoken.impl.domain -import com.tangem.blockchain.blockchains.cardano.CardanoUtils import com.tangem.blockchain.common.Blockchain -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.toMapKey -import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.data.tokens.utils.CryptoCurrencyFactory import com.tangem.domain.card.DerivePublicKeysUseCase -import com.tangem.domain.common.configs.CardConfig import com.tangem.domain.common.extensions.toNetworkId import com.tangem.domain.common.util.derivationStyleProvider -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.usecase.GetSelectedWalletSyncUseCase -import com.tangem.features.tester.api.TesterFeatureToggles -import com.tangem.operations.derivation.ExtendedPublicKeysMap -import com.tangem.tap.common.extensions.dispatchDebugErrorNotification -import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.TapError import com.tangem.tap.domain.model.Currency import com.tangem.tap.features.customtoken.impl.domain.models.FoundToken -import com.tangem.tap.features.tokens.legacy.redux.TokensMiddleware 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 timber.log.Timber /** @@ -48,7 +27,6 @@ class DefaultCustomTokenInteractor( private val featureRepository: CustomTokenRepository, private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val derivePublicKeysUseCase: DerivePublicKeysUseCase, - private val testerFeatureToggles: TesterFeatureToggles, ) : CustomTokenInteractor { // TODO: Move to DI @@ -70,136 +48,12 @@ class DefaultCustomTokenInteractor( val userWallet = getSelectedWalletSyncUseCase().fold(ifLeft = { return }, ifRight = { it }) val currency = Currency.fromCustomCurrency(customCurrency) - if (testerFeatureToggles.isDerivePublicKeysRefactoringEnabled) { - val currencies = listOfNotNull(element = currency.toCryptoCurrency(userWallet.scanResponse)) - derivePublicKeysUseCase(userWalletId = userWallet.walletId, currencies = currencies) - .onRight { - addCryptoCurrenciesUseCase(userWalletId = userWallet.walletId, currencies = currencies) - } - .onLeft { Timber.e("Failed to derive public keys: $it") } - } else { - // TODO: delete [REDACTED_JIRA] - val isNeedToDerive = isNeedToDerive(userWallet, currency) - if (isNeedToDerive) { - deriveMissingBlockchains( - userWallet = userWallet, - currencyList = listOf(currency), - onSuccess = { submitAdd(userWallet = userWallet.copy(scanResponse = it), currency = currency) }, - ) { - throw it - } - } else { - submitAdd(userWallet, currency) + val currencies = listOfNotNull(element = currency.toCryptoCurrency(userWallet.scanResponse)) + derivePublicKeysUseCase(userWalletId = userWallet.walletId, currencies = currencies) + .onRight { + addCryptoCurrenciesUseCase(userWalletId = userWallet.walletId, currencies = currencies) } - } - } - - private fun isNeedToDerive(userWallet: UserWallet, currency: Currency): Boolean { - val scanResponse = userWallet.scanResponse - return currency.derivationPath?.let { !scanResponse.hasDerivation(currency.blockchain, it) } ?: false - } - - private suspend fun deriveMissingBlockchains( - userWallet: UserWallet, - currencyList: List, - onSuccess: suspend (ScanResponse) -> Unit, - onFailure: suspend (TangemError) -> Unit, - ) { - val scanResponse = userWallet.scanResponse - val config = CardConfig.createConfig(scanResponse.card) - val derivationDataList = currencyList.mapNotNull { currency -> - val curve = config.primaryCurve(currency.blockchain) - curve?.let { getDerivations(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 - } - - when (val result = tangemSdkManager.derivePublicKeys(cardId = null, derivations = derivations)) { - 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 -> { - onFailure.invoke(result.error) - store.dispatchDebugErrorNotification(TapError.CustomError("Error adding tokens")) - } - } - } - - private fun getDerivations( - curve: EllipticCurve, - scanResponse: ScanResponse, - currency: Currency, - ): TokensMiddleware.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 TokensMiddleware.DerivationData(derivations = mapKeyOfWalletPublicKey to toDerive) - } - - private suspend fun submitAdd(userWallet: UserWallet, currency: Currency) { - val scanResponse = userWallet.scanResponse - val userWalletId = userWallet.walletId - - val currencyList = listOfNotNull(element = currency.toCryptoCurrency(scanResponse)) - - userWalletsListManager.update(userWalletId) { - it.copy(scanResponse = scanResponse) - } - - addCryptoCurrenciesUseCase(userWalletId, currencyList) + .onLeft { Timber.e("Failed to derive public keys: $it") } } private fun Currency.toCryptoCurrency(scanResponse: ScanResponse): CryptoCurrency? { 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 7ccf604f5a..f4f5e5e72d 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 @@ -3,14 +3,20 @@ package com.tangem.tap.features.tokens.impl.presentation.viewmodels import arrow.core.Either import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token +import com.tangem.core.navigation.NavigationAction import com.tangem.data.tokens.utils.CryptoCurrencyFactory +import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.common.util.derivationStyleProvider +import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase import com.tangem.domain.tokens.TokenWithBlockchain -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.models.UserWalletId import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase +import com.tangem.tap.common.extensions.dispatchDebugErrorNotification +import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.store import timber.log.Timber import kotlin.properties.Delegates @@ -24,6 +30,8 @@ import kotlin.properties.Delegates internal class TokensListMigration( private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val getCurrenciesUseCase: GetCryptoCurrenciesUseCase, + private val derivePublicKeysUseCase: DerivePublicKeysUseCase, + private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, ) { private var currentNewCoins: List by Delegates.notNull() @@ -76,31 +84,72 @@ internal class TokensListMigration( } } - fun onSaveButtonClick( + suspend fun onSaveButtonClick( changedTokensList: MutableList, changedBlockchainList: List, ) { - store.dispatch( - action = TokensAction.SaveChanges( - currentTokens = currentNewTokens, - currentCoins = currentNewCoins, - changedTokens = changedTokensList.mapNotNull { - cryptoCurrencyFactory.createToken( - sdkToken = it.token, - blockchain = it.blockchain, - extraDerivationPath = null, - derivationStyleProvider = currentUserWallet.scanResponse.derivationStyleProvider, - ) - }, - changedCoins = changedBlockchainList.mapNotNull { - cryptoCurrencyFactory.createCoin( - blockchain = it, - extraDerivationPath = null, - derivationStyleProvider = currentUserWallet.scanResponse.derivationStyleProvider, - ) - }, - userWallet = currentUserWallet, - ), + val changedTokens = changedTokensList.mapNotNull { + cryptoCurrencyFactory.createToken( + sdkToken = it.token, + blockchain = it.blockchain, + extraDerivationPath = null, + derivationStyleProvider = currentUserWallet.scanResponse.derivationStyleProvider, + ) + } + + val changedCoins = changedBlockchainList.mapNotNull { + cryptoCurrencyFactory.createCoin( + blockchain = it, + extraDerivationPath = null, + derivationStyleProvider = currentUserWallet.scanResponse.derivationStyleProvider, + ) + } + + val blockchainsToAdd = changedCoins.filterNot(currentNewCoins::contains) + val blockchainsToRemove = currentNewCoins.filterNot(changedCoins::contains) + + val tokensToAdd = changedTokens.filterNot(currentNewTokens::contains) + val tokensToRemove = currentNewTokens.filterNot { token -> changedTokens.any { it == token } } + + removeCurrenciesIfNeeded( + userWalletId = currentUserWallet.walletId, + currencies = blockchainsToRemove + tokensToRemove, + ) + + 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 + } + + val currencyList = blockchainsToAdd + tokensToAdd + + derivePublicKeysUseCase(userWalletId = currentUserWallet.walletId, currencies = currencyList) + .onRight { + addCryptoCurrenciesUseCase(userWalletId = currentUserWallet.walletId, currencies = currencyList) + store.dispatchOnMain(NavigationAction.PopBackTo()) + } + .onLeft { Timber.e("Failed to derive public keys: $it") } + } + + 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) + + 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/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 94c4974fc7..337e8f24ec 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 @@ -13,12 +13,14 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.ui.extensions.getActiveIconRes import com.tangem.core.ui.extensions.getGreyedOutIconRes +import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation import com.tangem.domain.common.extensions.canHandleBlockchain import com.tangem.domain.common.extensions.canHandleToken import com.tangem.domain.common.extensions.fromNetworkId import com.tangem.domain.common.extensions.supportedTokens import com.tangem.domain.common.util.cardTypesResolver +import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase import com.tangem.domain.tokens.TokenWithBlockchain import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase @@ -67,6 +69,8 @@ internal class TokensListViewModel @Inject constructor( private val router: TokensListRouter, private val dispatchers: AppCoroutineDispatcherProvider, private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, + derivePublicKeysUseCase: DerivePublicKeysUseCase, + addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, analyticsEventHandler: AnalyticsEventHandler, getCurrenciesUseCase: GetCryptoCurrenciesUseCase, ) : ViewModel(), DefaultLifecycleObserver { @@ -88,6 +92,8 @@ internal class TokensListViewModel @Inject constructor( private val tokensListMigration = TokensListMigration( getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase, getCurrenciesUseCase = getCurrenciesUseCase, + derivePublicKeysUseCase = derivePublicKeysUseCase, + addCryptoCurrenciesUseCase = addCryptoCurrenciesUseCase, ) init { @@ -303,10 +309,13 @@ internal class TokensListViewModel @Inject constructor( fun onSaveButtonClick() { analyticsSender.sendWhenSaveButtonClicked() - tokensListMigration.onSaveButtonClick( - changedTokensList = changedTokensList, - changedBlockchainList = changedBlockchainList, - ) + + viewModelScope.launch(dispatchers.main) { + tokensListMigration.onSaveButtonClick( + changedTokensList = changedTokensList, + changedBlockchainList = changedBlockchainList, + ) + } } private fun onSearchValueChange(newValue: String) { 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 deleted file mode 100644 index eb39d0d64b..0000000000 --- a/app/src/main/java/com/tangem/tap/features/tokens/legacy/redux/TokensMiddleware.kt +++ /dev/null @@ -1,250 +0,0 @@ -package com.tangem.tap.features.tokens.legacy.redux - -import com.tangem.blockchain.blockchains.cardano.CardanoUtils -import com.tangem.blockchain.common.Blockchain -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.toMapKey -import com.tangem.core.navigation.NavigationAction -import com.tangem.crypto.hdWallet.DerivationPath -import com.tangem.domain.common.configs.CardConfig -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.TokensAction -import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.domain.wallets.models.UserWallet -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.operations.derivation.ExtendedPublicKeysMap -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.domain.card.DefaultDerivePublicKeysUseCase -import com.tangem.tap.proxy.redux.DaggerGraphState -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 { - - // TODO: Move to DI - private val addCryptoCurrenciesUseCase by lazy(LazyThreadSafetyMode.NONE) { - val currenciesRepository = store.state.daggerGraphState.get(DaggerGraphState::currenciesRepository) - val networksRepository = store.state.daggerGraphState.get(DaggerGraphState::networksRepository) - - AddCryptoCurrenciesUseCase(currenciesRepository, networksRepository) - } - - val tokensMiddleware: Middleware = { _, _ -> - { next -> - { action -> - when (action) { - is TokensAction.SaveChanges -> handleSaveChanges(action) - } - next(action) - } - } - } - - private fun handleSaveChanges(action: TokensAction.SaveChanges) { - scope.launch { - val scanResponse = action.userWallet.scanResponse - - val currentTokens = action.currentTokens - val currentBlockchains = action.currentCoins - - val blockchainsToAdd = action.changedCoins.filterNot(currentBlockchains::contains) - val blockchainsToRemove = currentBlockchains.filterNot(action.changedCoins::contains) - - val tokensToAdd = action.changedTokens.filterNot(currentTokens::contains) - val tokensToRemove = currentTokens.filterNot { token -> action.changedTokens.any { it == token } } - - removeCurrenciesIfNeeded( - userWalletId = action.userWallet.walletId, - currencies = blockchainsToRemove + tokensToRemove, - ) - - 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 = blockchainsToAdd + tokensToAdd - - val featureToggles = store.state.daggerGraphState.get(DaggerGraphState::testerFeatureToggles) - if (featureToggles.isDerivePublicKeysRefactoringEnabled) { - val derivePublicKeys = DefaultDerivePublicKeysUseCase( - tangemSdkManager = tangemSdkManager, - derivationsRepository = store.state.daggerGraphState.get(DaggerGraphState::derivationsRepository), - ) - - derivePublicKeys(userWalletId = action.userWallet.walletId, currencies = currencyList) - .onRight { - addCryptoCurrenciesUseCase( - userWalletId = action.userWallet.walletId, - currencies = currencyList, - ) - store.dispatchOnMain(NavigationAction.PopBackTo()) - } - .onLeft { Timber.e("Failed to derive public keys: $it") } - } else { - // TODO: delete [REDACTED_JIRA] - if (scanResponse.supportsHdWallet()) { - deriveMissingCoins(scanResponse = scanResponse, currencyList = currencyList) { - submitAdd( - userWallet = action.userWallet, - updatedScanResponse = it, - currencyList = currencyList, - ) - } - } else { - submitAdd(action.userWallet, scanResponse, currencyList) - } - } - } - } - - @Deprecated(message = "Use DerivePublicKeysUseCase instead") - private fun deriveMissingCoins( - scanResponse: ScanResponse, - currencyList: List, - onSuccess: (ScanResponse) -> Unit, - ) { - val config = CardConfig.createConfig(scanResponse.card) - val derivationDataList = currencyList.mapNotNull { currency -> - val curve = config.primaryCurve(blockchain = Blockchain.fromId(currency.network.id.value)) - curve?.let { getDerivations(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)) - - onSuccess(updatedScanResponse) - } - is CompletionResult.Failure -> { - store.dispatchDebugErrorNotification(TapError.CustomError("Error adding tokens")) - } - } - } - } - - private fun getDerivations( - curve: EllipticCurve, - scanResponse: ScanResponse, - currency: CryptoCurrency, - ): DerivationData? { - val wallet = scanResponse.card.wallets.firstOrNull { it.curve == curve } ?: return null - - val blockchain = Blockchain.fromId(currency.network.id.value) - val supportedCurves = blockchain.getSupportedCurves() - val path = blockchain.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) - .takeIf { supportedCurves.contains(curve) } - - val customPath = currency.network.derivationPath.value?.let { - DerivationPath(it) - }.takeIf { supportedCurves.contains(curve) } - - val bothCandidates = listOfNotNull(path, customPath).distinct().toMutableList() - if (bothCandidates.isEmpty()) return null - - if (currency is CryptoCurrency.Coin && blockchain == Blockchain.Cardano) { - currency.network.derivationPath.value?.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) - } - - class DerivationData(val derivations: Pair>) - - private fun submitAdd( - userWallet: UserWallet, - updatedScanResponse: ScanResponse, - currencyList: List, - ) { - scope.launch { - userWalletsListManager.update( - userWalletId = userWallet.walletId, - update = { it.copy(scanResponse = updatedScanResponse) }, - ).doOnSuccess { - addCryptoCurrenciesUseCase(userWallet.walletId, currencyList) - } - } - store.dispatchOnMain(NavigationAction.PopBackTo()) - } - - 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) - - 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/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt deleted file mode 100644 index 63b07213d1..0000000000 --- a/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt +++ /dev/null @@ -1,298 +0,0 @@ -package com.tangem.tap.proxy - -import com.tangem.blockchain.blockchains.cardano.CardanoUtils -import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.Token -import com.tangem.common.CompletionResult -import com.tangem.common.card.EllipticCurve -import com.tangem.common.core.TangemError -import com.tangem.common.core.TangemSdkError -import com.tangem.common.extensions.ByteArrayKey -import com.tangem.common.extensions.toMapKey -import com.tangem.crypto.hdWallet.DerivationPath -import com.tangem.data.tokens.utils.CryptoCurrencyFactory -import com.tangem.domain.common.BlockchainNetwork -import com.tangem.domain.common.DerivationStyleProvider -import com.tangem.domain.common.configs.CardConfig -import com.tangem.domain.common.extensions.fromNetworkId -import com.tangem.domain.common.util.derivationStyleProvider -import com.tangem.domain.common.util.hasDerivation -import com.tangem.domain.models.scan.ScanResponse -import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase -import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.lib.crypto.DerivationManager -import com.tangem.lib.crypto.models.Currency -import com.tangem.lib.crypto.models.Currency.NonNativeToken -import com.tangem.lib.crypto.models.errors.UserCancelledException -import com.tangem.operations.derivation.ExtendedPublicKeysMap -import com.tangem.tap.common.extensions.dispatchDebugErrorNotification -import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.TapError -import com.tangem.tap.features.tokens.legacy.redux.TokensMiddleware -import com.tangem.tap.scope -import com.tangem.tap.userWalletsListManager -import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlin.coroutines.suspendCoroutine -import com.tangem.tap.domain.model.Currency as WalletModelCurrency - -class DerivationManagerImpl( - private val appStateHolder: AppStateHolder, - private val currenciesRepository: CurrenciesRepository, - private val networksRepository: NetworksRepository, -) : DerivationManager { - - // TODO: Move to DI - private val addCryptoCurrenciesUseCase by lazy(LazyThreadSafetyMode.NONE) { - AddCryptoCurrenciesUseCase(currenciesRepository, networksRepository) - } - - override suspend fun deriveAndAddTokens(currency: Currency) = suspendCoroutine { continuation -> - val selectedUserWallet = requireNotNull( - userWalletsListManager.selectedUserWalletSync, - ) { "selectedUserWallet shouldn't be null" } - val scanResponse = selectedUserWallet.scanResponse - val blockchain = requireNotNull( - Blockchain.fromNetworkId(currency.networkId), - ) { "unsupported blockchain" } - val derivationStyleProvider = scanResponse.derivationStyleProvider - val derivationPath = requireNotNull( - blockchain.derivationPath(derivationStyleProvider.getDerivationStyle())?.rawPath, - ) { "derivationPath shouldn't be null" } - val hasDerivation = scanResponse.hasDerivation( - blockchain, - derivationPath, - ) - if (hasDerivation) { - scope.launch { - addToken( - userWalletId = selectedUserWallet.walletId, - blockchain = blockchain, - currency = currency, - derivationPath = derivationPath, - derivationStyleProvider = derivationStyleProvider, - ) - continuation.resumeWith(Result.success(derivationPath)) - } - } else { - val blockchainNetwork = BlockchainNetwork(blockchain, scanResponse.derivationStyleProvider) - val appCurrency = com.tangem.tap.domain.model.Currency.fromBlockchainNetwork( - blockchainNetwork, - getAppToken(currency), - ) - deriveMissingBlockchains( - scanResponse = scanResponse, - currencyList = listOf(appCurrency), - onSuccess = { updatedScanResponse -> - scope.launch { - userWalletsListManager.update( - userWalletId = selectedUserWallet.walletId, - update = { it.copy(scanResponse = updatedScanResponse) }, - ) - addToken( - userWalletId = selectedUserWallet.walletId, - blockchain = blockchain, - currency = currency, - derivationPath = derivationPath, - derivationStyleProvider = derivationStyleProvider, - ) - continuation.resumeWith(Result.success(derivationPath)) - } - }, - onFailure = { - continuation.resumeWith(Result.failure(it)) - }, - ) - } - } - - private suspend fun addToken( - userWalletId: UserWalletId, - blockchain: Blockchain, - currency: Currency, - derivationPath: String, - derivationStyleProvider: DerivationStyleProvider, - ) { - val cryptoCurrency = convertCurrency( - blockchain = blockchain, - currency = currency, - derivationPath = derivationPath, - derivationStyleProvider = derivationStyleProvider, - ) - - addCryptoCurrenciesUseCase(userWalletId, cryptoCurrency) - } - - private fun convertCurrency( - blockchain: Blockchain, - currency: Currency, - derivationPath: String, - derivationStyleProvider: DerivationStyleProvider, - ): CryptoCurrency { - val cryptoCurrencyFactory = CryptoCurrencyFactory() - return when (currency) { - is Currency.NativeToken -> { - cryptoCurrencyFactory.createCoin( - blockchain = blockchain, - extraDerivationPath = derivationPath, - derivationStyleProvider = derivationStyleProvider, - ) - } - is NonNativeToken -> { - val sdkToken = Token( - name = currency.name, - symbol = currency.symbol, - contractAddress = currency.contractAddress, - decimals = currency.decimalCount, - id = currency.id, - ) - cryptoCurrencyFactory.createToken( - sdkToken = sdkToken, - blockchain = blockchain, - extraDerivationPath = derivationPath, - derivationStyleProvider = derivationStyleProvider, - ) - } - } as CryptoCurrency - } - - private fun deriveMissingBlockchains( - scanResponse: ScanResponse, - currencyList: List, - onSuccess: (ScanResponse) -> Unit, - onFailure: (Exception) -> Unit, - ) { - val config = CardConfig.createConfig(scanResponse.card) - val derivationDataList = currencyList.mapNotNull { currency -> - val curve = config.primaryCurve(currency.blockchain) - curve?.let { getDerivations(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 selectedUserWallet = userWalletsListManager.selectedUserWalletSync - - val result = appStateHolder.tangemSdkManager?.derivePublicKeys( - cardId = null, // always ignore cardId in derive task - 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, - ) - if (selectedUserWallet != null) { - userWalletsListManager.update( - userWalletId = selectedUserWallet.walletId, - update = { it.copy(scanResponse = updatedScanResponse) }, - ) - } - appStateHolder.mainStore?.dispatchOnMain(GlobalAction.SaveScanResponse(updatedScanResponse)) - delay(DELAY_SDK_DIALOG_CLOSE) - onSuccess(updatedScanResponse) - } - is CompletionResult.Failure -> { - appStateHolder.mainStore?.dispatchDebugErrorNotification( - TapError.CustomError( - "Error derivation", - ), - ) - onFailure.invoke(handleTangemError(result.error)) - } - else -> { - error("result result is null") - } - } - } - } - - private fun getDerivations( - curve: EllipticCurve, - scanResponse: ScanResponse, - currency: com.tangem.tap.domain.model.Currency, - ): TokensMiddleware.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 WalletModelCurrency.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 TokensMiddleware.DerivationData(derivations = mapKeyOfWalletPublicKey to toDerive) - } - - private fun getAppToken(currency: Currency): Token? { - return if (currency is NonNativeToken) { - Token( - symbol = currency.symbol, - contractAddress = currency.contractAddress, - decimals = currency.decimalCount, - ) - } else { - null - } - } - /** - * Simple error handler - * for now specifically handle only UserCancelled - * - * @param error [TangemError] - */ - private fun handleTangemError(error: TangemError): Exception { - if (error is TangemSdkError.UserCancelled) { - return UserCancelledException() - } - return IllegalStateException(error.customMessage) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt b/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt index 8c0c4eda47..d72bae0238 100644 --- a/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt +++ b/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt @@ -4,9 +4,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.tokens.repository.CurrenciesRepository -import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.lib.crypto.DerivationManager import com.tangem.lib.crypto.TransactionManager import com.tangem.lib.crypto.UserWalletManager import com.tangem.tap.proxy.* @@ -56,18 +54,4 @@ internal object ProxyModule { walletManagersFacade = walletManagersFacade, ) } - - @Provides - @Singleton - fun provideDerivationManager( - appStateHolder: AppStateHolder, - currenciesRepository: CurrenciesRepository, - networksRepository: NetworksRepository, - ): DerivationManager { - return DerivationManagerImpl( - appStateHolder = appStateHolder, - currenciesRepository = currenciesRepository, - networksRepository = networksRepository, - ) - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt index d10051fa08..3bfa07a2ce 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt @@ -8,7 +8,6 @@ import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository import com.tangem.domain.card.ScanCardProcessor import com.tangem.domain.card.ScanCardUseCase import com.tangem.domain.card.repository.CardSdkConfigRepository -import com.tangem.domain.card.repository.DerivationsRepository import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.walletmanager.WalletManagersFacade @@ -18,7 +17,6 @@ import com.tangem.features.managetokens.featuretoggles.ManageTokensFeatureToggle import com.tangem.features.managetokens.navigation.ManageTokensRouter import com.tangem.features.send.api.featuretoggles.SendFeatureToggles import com.tangem.features.send.api.navigation.SendRouter -import com.tangem.features.tester.api.TesterFeatureToggles import com.tangem.features.tester.api.TesterRouter import com.tangem.features.tokendetails.navigation.TokenDetailsRouter import com.tangem.features.wallet.navigation.WalletRouter @@ -53,11 +51,7 @@ data class DaggerGraphState( val sendFeatureToggles: SendFeatureToggles? = null, val sendRouter: SendRouter? = null, val qrScanningRouter: QrScanningRouter? = null, - - // FIXME: It is used only for TokensList screen. Remove after refactoring of TokensList val currenciesRepository: CurrenciesRepository? = null, - val derivationsRepository: DerivationsRepository? = null, - val testerFeatureToggles: TesterFeatureToggles? = null, val blockchainDataStorage: BlockchainDataStorage? = null, ) : StateType { diff --git a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json index e91e7f03e8..13b20fb797 100644 --- a/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/featuretoggles/src/main/assets/configs/feature_toggles_config.json @@ -18,9 +18,5 @@ { "name": "WALLETS_SCROLLING_PREVIEW_ENABLED", "version": "5.5.0" - }, - { - "name": "DERIVE_PUBLIC_KEYS_REFACTORING_ENABLED", - "version": "5.5.0" } ] diff --git a/domain/card/src/main/kotlin/com/tangem/domain/card/DerivePublicKeysUseCase.kt b/domain/card/src/main/kotlin/com/tangem/domain/card/DerivePublicKeysUseCase.kt index 8aad6ceb32..3061e99534 100644 --- a/domain/card/src/main/kotlin/com/tangem/domain/card/DerivePublicKeysUseCase.kt +++ b/domain/card/src/main/kotlin/com/tangem/domain/card/DerivePublicKeysUseCase.kt @@ -1,21 +1,17 @@ package com.tangem.domain.card import arrow.core.Either -import com.tangem.common.extensions.ByteArrayKey -import com.tangem.crypto.hdWallet.DerivationPath +import com.tangem.domain.card.repository.DerivationsRepository import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.operations.derivation.DerivationTaskResponse -// TODO: Convert to class [REDACTED_JIRA] -interface DerivePublicKeysUseCase { +class DerivePublicKeysUseCase( + private val derivationsRepository: DerivationsRepository, +) { - // TODO: delete [REDACTED_JIRA] - @Deprecated(message = "Use invoke(cardId: String?, derivations: Map>) instead") - suspend operator fun invoke( - cardId: String? = null, - derivations: Map>, - ): Either - - suspend operator fun invoke(userWalletId: UserWalletId, currencies: List): Either + suspend operator fun invoke(userWalletId: UserWalletId, currencies: List): Either { + return Either.catch { + derivationsRepository.derivePublicKeys(userWalletId, currencies) + } + } } \ 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 d5a0d8be8e..90378e19c2 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,8 +2,6 @@ package com.tangem.domain.tokens import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token -import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.domain.wallets.models.UserWallet import org.rekotlin.Action sealed interface TokensAction : Action { @@ -13,14 +11,6 @@ sealed interface TokensAction : Action { object ManageAccess : SetArgs object ReadAccess : SetArgs } - - data class SaveChanges( - val currentTokens: List, - val currentCoins: List, - val changedTokens: List, - val changedCoins: List, - val userWallet: UserWallet, - ) : TokensAction } data class TokenWithBlockchain(val token: Token, val blockchain: Blockchain) \ No newline at end of file diff --git a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt index 379d153a48..154764b162 100644 --- a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt +++ b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt @@ -4,30 +4,23 @@ import arrow.core.getOrElse import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase -import com.tangem.feature.referral.domain.converter.TokensConverter import com.tangem.feature.referral.domain.models.ReferralData import com.tangem.feature.referral.domain.models.TokenData -import com.tangem.features.tester.api.TesterFeatureToggles -import com.tangem.lib.crypto.DerivationManager import com.tangem.lib.crypto.UserWalletManager import timber.log.Timber @Suppress("LongParameterList") internal class ReferralInteractorImpl( private val repository: ReferralRepository, - private val derivationManager: DerivationManager, private val userWalletManager: UserWalletManager, - private val tokensConverter: TokensConverter, private val derivePublicKeysUseCase: DerivePublicKeysUseCase, private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, - private val testerFeatureToggles: TesterFeatureToggles, ) : ReferralInteractor { private val tokensForReferral = mutableListOf() - override val isDemoMode: Boolean - get() = repository.isDemoMode + override val isDemoMode: Boolean get() = repository.isDemoMode override suspend fun getReferralStatus(): ReferralData { val referralData = repository.getReferralData(userWalletManager.getWalletId()) @@ -38,19 +31,9 @@ internal class ReferralInteractorImpl( } override suspend fun startReferral(): ReferralData { - return if (tokensForReferral.isNotEmpty()) { - if (testerFeatureToggles.isDerivePublicKeysRefactoringEnabled) { - startReferralNew(tokenData = tokensForReferral.first()) - } else { - // TODO: delete [REDACTED_JIRA] - startReferralLegacy(tokenData = tokensForReferral.first()) - } - } else { - error("Tokens for ref is empty") - } - } + if (tokensForReferral.isEmpty()) error("Tokens for ref is empty") - private suspend fun startReferralNew(tokenData: TokenData): ReferralData { + val tokenData = tokensForReferral.first() val userWallet = getSelectedWalletSyncUseCase().getOrElse { error("Failed to get selected wallet: $it") } @@ -79,18 +62,6 @@ internal class ReferralInteractorImpl( ) } - private suspend fun startReferralLegacy(tokenData: TokenData): ReferralData { - val currency = tokensConverter.convert(tokenData) - val derivationPath = derivationManager.deriveAndAddTokens(currency) - val publicAddress = userWalletManager.getWalletAddress(currency.networkId, derivationPath) - return repository.startReferral( - walletId = userWalletManager.getWalletId(), - networkId = currency.networkId, - tokenId = currency.id, - address = publicAddress, - ) - } - private fun saveReferralTokens(tokens: List) { tokensForReferral.clear() tokensForReferral.addAll(tokens) diff --git a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/converter/TokensConverter.kt b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/converter/TokensConverter.kt deleted file mode 100644 index a477782d9f..0000000000 --- a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/converter/TokensConverter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.tangem.feature.referral.domain.converter - -import com.tangem.feature.referral.domain.models.TokenData -import com.tangem.lib.crypto.models.Currency -import com.tangem.lib.crypto.models.Currency.NativeToken -import com.tangem.lib.crypto.models.Currency.NonNativeToken -import com.tangem.utils.converter.Converter - -import javax.inject.Inject - -class TokensConverter @Inject constructor() : Converter { - - override fun convert(value: TokenData): Currency { - return if (value.decimalCount != null && - value.contractAddress != null - ) { - NonNativeToken( - id = value.id, - name = value.name, - symbol = value.symbol, - networkId = value.networkId, - contractAddress = value.contractAddress, - decimalCount = value.decimalCount, - ) - } else { - NativeToken( - id = value.id, - name = value.name, - symbol = value.symbol, - networkId = value.networkId, - ) - } - } -} \ No newline at end of file diff --git a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt index 9b90eb5b0a..0cd466fed7 100644 --- a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt +++ b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt @@ -6,9 +6,6 @@ import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.feature.referral.domain.ReferralInteractor import com.tangem.feature.referral.domain.ReferralInteractorImpl import com.tangem.feature.referral.domain.ReferralRepository -import com.tangem.feature.referral.domain.converter.TokensConverter -import com.tangem.features.tester.api.TesterFeatureToggles -import com.tangem.lib.crypto.DerivationManager import com.tangem.lib.crypto.UserWalletManager import dagger.Module import dagger.Provides @@ -24,23 +21,17 @@ class ReferralDomainModule { @ViewModelScoped fun provideReferralInteractor( referralRepository: ReferralRepository, - derivationManager: DerivationManager, userWalletManager: UserWalletManager, - tokensConverter: TokensConverter, derivePublicKeysUseCase: DerivePublicKeysUseCase, getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase, - testerFeatureToggles: TesterFeatureToggles, ): ReferralInteractor { return ReferralInteractorImpl( repository = referralRepository, - derivationManager = derivationManager, userWalletManager = userWalletManager, - tokensConverter = tokensConverter, derivePublicKeysUseCase = derivePublicKeysUseCase, getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase, addCryptoCurrenciesUseCase = addCryptoCurrenciesUseCase, - testerFeatureToggles = testerFeatureToggles, ) } } \ No newline at end of file diff --git a/features/tester/api/src/main/java/com/tangem/features/tester/api/TesterFeatureToggles.kt b/features/tester/api/src/main/java/com/tangem/features/tester/api/TesterFeatureToggles.kt deleted file mode 100644 index 84a02490cc..0000000000 --- a/features/tester/api/src/main/java/com/tangem/features/tester/api/TesterFeatureToggles.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.tangem.features.tester.api - -/** - * Tester feature toggles - * -[REDACTED_AUTHOR] - */ -interface TesterFeatureToggles { - - val isDerivePublicKeysRefactoringEnabled: Boolean -} \ No newline at end of file diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/di/TesterFeatureTogglesModule.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/di/TesterFeatureTogglesModule.kt deleted file mode 100644 index ee49bf39b7..0000000000 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/di/TesterFeatureTogglesModule.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.tangem.feature.tester.di - -import com.tangem.core.featuretoggle.manager.FeatureTogglesManager -import com.tangem.feature.tester.featuretoggles.DefaultTesterFeatureToggles -import com.tangem.features.tester.api.TesterFeatureToggles -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -internal object TesterFeatureTogglesModule { - - @Provides - @Singleton - fun provideTesterFeatureToggles(featureTogglesManager: FeatureTogglesManager): TesterFeatureToggles { - return DefaultTesterFeatureToggles(featureTogglesManager = featureTogglesManager) - } -} \ No newline at end of file diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/featuretoggles/DefaultTesterFeatureToggles.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/featuretoggles/DefaultTesterFeatureToggles.kt deleted file mode 100644 index 77e2de389a..0000000000 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/featuretoggles/DefaultTesterFeatureToggles.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.tangem.feature.tester.featuretoggles - -import com.tangem.core.featuretoggle.manager.FeatureTogglesManager -import com.tangem.features.tester.api.TesterFeatureToggles - -/** - * Default implementation of Tester feature toggles - * - * @property featureTogglesManager manager for getting information about the availability of feature toggles - * -[REDACTED_AUTHOR] - */ -internal class DefaultTesterFeatureToggles( - private val featureTogglesManager: FeatureTogglesManager, -) : TesterFeatureToggles { - - override val isDerivePublicKeysRefactoringEnabled: Boolean - get() = featureTogglesManager.isFeatureEnabled(name = "DERIVE_PUBLIC_KEYS_REFACTORING_ENABLED") -} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt index 8adfe05590..71d9d95d97 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt @@ -5,13 +5,8 @@ import androidx.paging.cachedIn import arrow.core.Either import arrow.core.getOrElse import arrow.core.right -import com.tangem.blockchain.blockchains.cardano.CardanoUtils -import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.address.AddressType -import com.tangem.common.card.EllipticCurve -import com.tangem.common.extensions.ByteArrayKey import com.tangem.common.extensions.isZero -import com.tangem.common.extensions.toMapKey import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.navigation.AppScreen @@ -23,19 +18,14 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.WrappedList import com.tangem.core.ui.extensions.resourceReference -import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.domain.analytics.ChangeCardAnalyticsContextUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase -import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.card.SetCardWasScannedUseCase import com.tangem.domain.common.CardTypesResolver -import com.tangem.domain.common.configs.CardConfig import com.tangem.domain.common.util.cardTypesResolver -import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.demo.IsDemoCardUseCase -import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.redux.LegacyAction import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.settings.* @@ -66,7 +56,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCard import com.tangem.feature.wallet.presentation.wallet.state.factory.TokenListWithWallet import com.tangem.feature.wallet.presentation.wallet.state.factory.WalletStateFactory import com.tangem.feature.wallet.presentation.wallet.subscribers.MaybeTokenListFlow -import com.tangem.operations.derivation.ExtendedPublicKeysMap import com.tangem.utils.Provider import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.JobHolder @@ -103,7 +92,6 @@ internal class WalletViewModel @Inject constructor( private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, private val getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase, - private val derivePublicKeysUseCase: DerivePublicKeysUseCase, private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase, private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase, private val getExploreUrlUseCase: GetExploreUrlUseCase, @@ -295,112 +283,30 @@ internal class WalletViewModel @Inject constructor( } override fun onGenerateMissedAddressesClick(missedAddressCurrencies: List) { - val state = uiState as? WalletState.ContentState ?: return - - analyticsEventsHandler.send(WalletScreenAnalyticsEvent.Basic.CardWasScanned(AnalyticsParam.ScannedFrom.Main)) - analyticsEventsHandler.send(WalletScreenAnalyticsEvent.MainScreen.NoticeScanYourCardTapped) - - viewModelScope.launch(dispatchers.io) { - val userWallet = getWallet(index = state.walletsListConfig.selectedWalletIndex) - - deriveMissingCurrencies( - scanResponse = userWallet.scanResponse, - currencyList = missedAddressCurrencies, - ) { scannedCardResponse -> - updateWalletUseCase( - userWalletId = userWallet.walletId, - update = { it.copy(scanResponse = scannedCardResponse) }, - ) - .onRight { - fetchTokenListUseCase(userWalletId = it.walletId) - } - } - } + // TODO: delete [REDACTED_JIRA] + // val state = uiState as? WalletState.ContentState ?: return + // + // analyticsEventsHandler.send(WalletScreenAnalyticsEvent.Basic.CardWasScanned(AnalyticsParam.ScannedFrom.Main)) + // analyticsEventsHandler.send(WalletScreenAnalyticsEvent.MainScreen.NoticeScanYourCardTapped) + // + // viewModelScope.launch(dispatchers.io) { + // val userWallet = getWallet(index = state.walletsListConfig.selectedWalletIndex) + // + // deriveMissingCurrencies( + // scanResponse = userWallet.scanResponse, + // currencyList = missedAddressCurrencies, + // ) { scannedCardResponse -> + // updateWalletUseCase( + // userWalletId = userWallet.walletId, + // update = { it.copy(scanResponse = scannedCardResponse) }, + // ) + // .onRight { + // fetchTokenListUseCase(userWalletId = it.walletId) + // } + // } + // } } - @Deprecated("Use DerivePublicKeysUseCase instead") - private fun deriveMissingCurrencies( - scanResponse: ScanResponse, - currencyList: List, - onSuccess: suspend (ScanResponse) -> Unit, - ) { - val config = CardConfig.createConfig(scanResponse.card) - val derivationDataList = currencyList.mapNotNull { - config.primaryCurve(blockchain = Blockchain.fromId(it.network.id.value))?.let { curve -> - getNewDerivations(curve, scanResponse, it) - } - } - - 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() - } - } - }.ifEmpty { return } - - viewModelScope.launch(dispatchers.io) { - derivePublicKeysUseCase(cardId = null, derivations = derivations) - .onRight { - val newDerivedKeys = it.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) - - onSuccess(updatedScanResponse) - } - } - } - - private fun getNewDerivations( - curve: EllipticCurve, - scanResponse: ScanResponse, - currency: CryptoCurrency, - ): DerivationData? { - val wallet = scanResponse.card.wallets.firstOrNull { it.curve == curve } ?: return null - - val blockchain = Blockchain.fromId(currency.network.id.value) - val supportedCurves = blockchain.getSupportedCurves() - val path = blockchain.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) - .takeIf { supportedCurves.contains(curve) } - - val customPath = currency.network.derivationPath.value?.let { - DerivationPath(it) - }.takeIf { supportedCurves.contains(curve) } - - val bothCandidates = listOfNotNull(path, customPath).distinct().toMutableList() - if (bothCandidates.isEmpty()) return null - - if (currency is CryptoCurrency.Coin && blockchain == Blockchain.Cardano) { - currency.network.derivationPath.value?.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) - } - - class DerivationData(val derivations: Pair>) - override fun onScanToUnlockWalletClick() { val state = uiState as? WalletState.ContentState ?: return diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt index ae87db6d02..0a09fcf2c4 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt @@ -1,19 +1,10 @@ package com.tangem.feature.wallet.presentation.wallet.viewmodels.intents -import com.tangem.blockchain.blockchains.cardano.CardanoUtils -import com.tangem.blockchain.common.Blockchain -import com.tangem.common.card.EllipticCurve -import com.tangem.common.extensions.ByteArrayKey -import com.tangem.common.extensions.toMapKey import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.ui.extensions.resourceReference -import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.card.SetCardWasScannedUseCase -import com.tangem.domain.common.configs.CardConfig -import com.tangem.domain.common.util.derivationStyleProvider -import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.redux.LegacyAction import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.settings.NeverToSuggestRateAppUseCase @@ -23,7 +14,6 @@ import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UnlockWalletsError import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.domain.wallets.usecase.UnlockWalletsUseCase -import com.tangem.domain.wallets.usecase.UpdateWalletUseCase import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.Basic import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen @@ -35,8 +25,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletEvent import com.tangem.feature.wallet.presentation.wallet.state2.WalletStateController import com.tangem.feature.wallet.presentation.wallet.state2.transformers.CloseBottomSheetTransformer import com.tangem.feature.wallet.presentation.wallet.state2.utils.WalletEventSender -import com.tangem.features.tester.api.TesterFeatureToggles -import com.tangem.operations.derivation.ExtendedPublicKeysMap import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.hilt.android.scopes.ViewModelScoped import kotlinx.coroutines.launch @@ -70,7 +58,6 @@ internal class WalletWarningsClickIntentsImplementer @Inject constructor( private val stateHolder: WalletStateController, private val walletEventSender: WalletEventSender, private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, - private val updateWalletUseCase: UpdateWalletUseCase, private val unlockWalletsUseCase: UnlockWalletsUseCase, private val derivePublicKeysUseCase: DerivePublicKeysUseCase, private val scanCardToUnlockWalletClickHandler: ScanCardToUnlockWalletClickHandler, @@ -80,7 +67,6 @@ internal class WalletWarningsClickIntentsImplementer @Inject constructor( private val remindToRateAppLaterUseCase: RemindToRateAppLaterUseCase, private val analyticsEventHandler: AnalyticsEventHandler, private val reduxStateHolder: ReduxStateHolder, - private val testerFeatureToggles: TesterFeatureToggles, private val dispatchers: CoroutineDispatcherProvider, ) : BaseWalletClickIntents(), WalletWarningsClickIntents { @@ -117,111 +103,15 @@ internal class WalletWarningsClickIntentsImplementer @Inject constructor( analyticsEventHandler.send(MainScreen.NoticeScanYourCardTapped) viewModelScope.launch(dispatchers.main) { - if (testerFeatureToggles.isDerivePublicKeysRefactoringEnabled) { - derivePublicKeysUseCase( - userWalletId = userWallet.walletId, - currencies = missedAddressCurrencies, - ) - .onRight { fetchTokenListUseCase(userWalletId = userWallet.walletId) } - .onLeft { Timber.e("Failed to derive public keys: $it") } - } else { - // TODO: delete [REDACTED_JIRA] - deriveMissingCurrencies( - scanResponse = userWallet.scanResponse, - currencyList = missedAddressCurrencies, - ) { scannedCardResponse -> - updateWalletUseCase( - userWalletId = userWallet.walletId, - update = { it.copy(scanResponse = scannedCardResponse) }, - ) - .onRight { fetchTokenListUseCase(userWalletId = it.walletId) } - } - } + derivePublicKeysUseCase( + userWalletId = userWallet.walletId, + currencies = missedAddressCurrencies, + ) + .onRight { fetchTokenListUseCase(userWalletId = userWallet.walletId) } + .onLeft { Timber.e("Failed to derive public keys: $it") } } } - private fun deriveMissingCurrencies( - scanResponse: ScanResponse, - currencyList: List, - onSuccess: suspend (ScanResponse) -> Unit, - ) { - val config = CardConfig.createConfig(scanResponse.card) - val derivationDataList = currencyList.mapNotNull { - config.primaryCurve(blockchain = Blockchain.fromId(it.network.id.value))?.let { curve -> - getNewDerivations(curve, scanResponse, it) - } - } - - 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() - } - } - }.ifEmpty { return } - - viewModelScope.launch(dispatchers.io) { - derivePublicKeysUseCase(cardId = null, derivations = derivations) - .onRight { - val newDerivedKeys = it.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) - - onSuccess(updatedScanResponse) - } - } - } - - private fun getNewDerivations( - curve: EllipticCurve, - scanResponse: ScanResponse, - currency: CryptoCurrency, - ): DerivationData? { - val wallet = scanResponse.card.wallets.firstOrNull { it.curve == curve } ?: return null - - val blockchain = Blockchain.fromId(currency.network.id.value) - val supportedCurves = blockchain.getSupportedCurves() - val path = blockchain.derivationPath(scanResponse.derivationStyleProvider.getDerivationStyle()) - .takeIf { supportedCurves.contains(curve) } - - val customPath = currency.network.derivationPath.value?.let { - DerivationPath(it) - }.takeIf { supportedCurves.contains(curve) } - - val bothCandidates = listOfNotNull(path, customPath).distinct().toMutableList() - if (bothCandidates.isEmpty()) return null - - if (currency is CryptoCurrency.Coin && blockchain == Blockchain.Cardano) { - currency.network.derivationPath.value?.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) - } - - class DerivationData(val derivations: Pair>) - override fun onOpenUnlockWalletsBottomSheetClick() { val config = requireNotNull(stateHolder.getSelectedWallet().bottomSheetConfig) { "Impossible to open unlock wallet bottom sheet if it's null" diff --git a/libs/crypto/src/main/java/com/tangem/lib/crypto/DerivationManager.kt b/libs/crypto/src/main/java/com/tangem/lib/crypto/DerivationManager.kt deleted file mode 100644 index e3f12c83f6..0000000000 --- a/libs/crypto/src/main/java/com/tangem/lib/crypto/DerivationManager.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.lib.crypto - -import com.tangem.lib.crypto.models.Currency - -@Deprecated(message = "Use DerivePublicKeysUseCase instead") -interface DerivationManager { - - /** - * Makes derivation for [Currency] if it is missing and adds token to wallet - */ - suspend fun deriveAndAddTokens(currency: Currency): String -} \ No newline at end of file