From d28e324cd0d6b146eda8aed1062e032c0f110baa Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 28 Feb 2023 19:41:48 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/tap/common/extensions/Store.kt | 16 +- .../com/tangem/tap/domain/TapWalletManager.kt | 213 --------------- .../UserWalletsListManagerExtensions.kt | 6 + .../details/redux/DetailsMiddleware.kt | 5 +- .../features/onboarding/OnboardingHelper.kt | 21 +- .../redux/OnboardingOtherCardsMiddleware.kt | 12 +- .../redux/OnboardingWalletMiddleware.kt | 13 +- .../saveWallet/redux/SaveWalletMiddleware.kt | 8 +- .../send/redux/middlewares/SendMiddleware.kt | 22 +- .../features/tokens/redux/TokensMiddleware.kt | 41 ++- .../tap/features/wallet/redux/WalletAction.kt | 93 ------- .../tap/features/wallet/redux/WalletState.kt | 105 +------- .../middlewares/AppCurrencyMiddleware.kt | 12 +- .../middlewares/MultiWalletMiddleware.kt | 193 ++----------- .../redux/middlewares/WalletMiddleware.kt | 203 ++------------ .../redux/reducers/MultiWalletReducer.kt | 204 +------------- .../redux/reducers/OnWalletLoadedReducer.kt | 154 ----------- .../redux/reducers/TotalBalanceOperations.kt | 6 - .../wallet/redux/reducers/WalletReducer.kt | 255 ------------------ .../wallet/ui/WalletDetailsFragment.kt | 20 +- .../ui/wallet/saltPay/SaltPayWalletView.kt | 6 - .../tangem/tap/proxy/UserWalletManagerImpl.kt | 16 +- 22 files changed, 151 insertions(+), 1473 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Store.kt b/app/src/main/java/com/tangem/tap/common/extensions/Store.kt index 77ed58315d..bfd3fa99c2 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Store.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Store.kt @@ -1,6 +1,5 @@ package com.tangem.tap.common.extensions -import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.extensions.withMainContext import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.StateDialog @@ -78,21 +77,18 @@ fun Store<*>.dispatchDialogHide() { /** * Dispatch action inside a coroutine with the Main dispatcher */ +@Deprecated( + message = "Use dispatchWithMain instead", + replaceWith = ReplaceWith(expression = "dispatchWithMain"), +) suspend fun dispatchOnMain(vararg actions: Action) { withMainContext { actions.forEach { store.dispatch(it) } } } -/** - * Dispatch action - */ -suspend fun Store<*>.onCardScanned(scanResponse: ScanResponse) { - store.state.globalState.tapWalletManager.onCardScanned(scanResponse) -} - fun Store<*>.dispatchOpenUrl(url: String) { - store.dispatch(NavigationAction.OpenUrl(url)) + dispatch(NavigationAction.OpenUrl(url)) } fun Store<*>.dispatchShare(url: String) { - store.dispatch(NavigationAction.Share(url)) + dispatch(NavigationAction.Share(url)) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index 4b34bbb8e7..aae069fed0 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -1,109 +1,42 @@ package com.tangem.tap.domain -import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.BlockchainSdkConfig import com.tangem.blockchain.common.Token import com.tangem.blockchain.common.Wallet -import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess -import com.tangem.common.services.Result import com.tangem.core.analytics.Analytics import com.tangem.datasource.config.ConfigManager -import com.tangem.domain.common.CardDTO import com.tangem.domain.common.ScanResponse -import com.tangem.domain.common.TapWorkarounds.isTestCard -import com.tangem.domain.common.ThrottlerWithValues import com.tangem.domain.common.extensions.withMainContext import com.tangem.operations.attestation.Attestation import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.common.extensions.setContext import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.extensions.makePrimaryWalletManager -import com.tangem.tap.domain.extensions.makeWalletManagersForApp import com.tangem.tap.domain.model.UserWallet -import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.domain.walletStores.WalletStoresError -import com.tangem.tap.features.demo.isDemoCard import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.disclaimer.createDisclaimer import com.tangem.tap.features.disclaimer.redux.DisclaimerAction import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction -import com.tangem.tap.features.wallet.models.toBlockchainNetworks import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.middlewares.handleBasicAnalyticsEvent -import com.tangem.tap.network.NetworkConnectivity import com.tangem.tap.preferencesStorage import com.tangem.tap.store import com.tangem.tap.tangemSdkManager -import com.tangem.tap.userTokensRepository import com.tangem.tap.walletStoresManager -import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import org.rekotlin.Action import timber.log.Timber class TapWalletManager { val walletManagerFactory: WalletManagerFactory by lazy { WalletManagerFactory(blockchainSdkConfig) } - // TODO("After adding DI") get dependencies by DI - val rates: RatesRepository by lazy { - RatesRepository( - tangemTechApi = store.state.domainNetworks.tangemTechService.api, - dispatchers = AppCoroutineDispatcherProvider(), - ) - } - private val blockchainSdkConfig by lazy { store.state.globalState.configManager?.config?.blockchainSdkConfig ?: BlockchainSdkConfig() } - private val walletManagersThrottler = - ThrottlerWithValues>(10000) - - suspend fun loadWalletData(walletManager: WalletManager) { - val blockchainNetwork = BlockchainNetwork.fromWalletManager(walletManager) - val result = if (walletManagersThrottler.isStillThrottled(blockchainNetwork)) { - walletManagersThrottler.geValue(blockchainNetwork)!! - } else { - val safeUpdateResult = walletManager.safeUpdate() - walletManagersThrottler.updateThrottlingTo(blockchainNetwork) - walletManagersThrottler.setValue(blockchainNetwork, safeUpdateResult) - safeUpdateResult - } - when (result) { - is Result.Success -> { - dispatchOnMain(WalletAction.LoadWallet.Success(result.data, blockchainNetwork)) - } - is Result.Failure -> { - when (result.error) { - is TapError.WalletManager.NoAccountError -> { - dispatchOnMain( - WalletAction.LoadWallet.NoAccount( - walletManager.wallet, - blockchainNetwork, - (result.error as TapError.WalletManager.NoAccountError).customMessage, - ), - ) - } - else -> { - dispatchOnMain( - WalletAction.LoadWallet.Failure( - walletManager.wallet, - result.error.localizedMessage, - ), - ) - } - } - } - } - } - suspend fun onWalletSelected(userWallet: UserWallet, refresh: Boolean) { Analytics.setContext(userWallet.scanResponse) val scanResponse = userWallet.scanResponse @@ -161,32 +94,6 @@ class TapWalletManager { } } - suspend fun onCardScanned(data: ScanResponse) { - walletManagersThrottler.clear() - store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(data) - updateConfigManager(data) - - withMainContext { - store.dispatch(WalletAction.ResetState(data.card)) - store.dispatch(WalletConnectAction.ResetState) - store.dispatch(GlobalAction.SaveScanResponse(data)) - store.dispatch(WalletAction.SetIfTestnetCard(data.card.isTestCard)) - store.dispatch( - WalletAction.MultiWallet.SetIsMultiwalletAllowed( - data.cardTypesResolver.isMultiwalletAllowed(), - ), - ) - store.dispatch(WalletConnectAction.RestoreSessions(data)) - store.dispatch( - WalletAction.MultiWallet.ShowWalletBackupWarning( - show = data.card.settings.isBackupAllowed && - data.card.backupStatus == CardDTO.BackupStatus.NoBackup, - ), - ) - loadData(data) - } - } - fun updateConfigManager(data: ScanResponse) { val configManager = store.state.globalState.configManager val blockchain = data.cardTypesResolver.getBlockchain() @@ -203,126 +110,6 @@ class TapWalletManager { configManager?.resetToDefault(ConfigManager.IS_TOP_UP_ENABLED) } } - - suspend fun loadData(data: ScanResponse) { - dispatchOnMain(WalletAction.LoadCardInfo(data.card)) - getActionIfUnknownBlockchainOrEmptyWallet(data)?.let { - dispatchOnMain(it) - return - } - - if (data.cardTypesResolver.isMultiwalletAllowed()) { - dispatchOnMain(WalletAction.MultiWallet.ScheduleCheckForMissingDerivation) - loadMultiWalletData(data) - } else { - loadSingleWalletData(data) - } - - dispatchOnMain(WalletAction.LoadWallet()) - } - - private suspend fun loadMultiWalletData(scanResponse: ScanResponse) { - loadUserCurrencies(scanResponse, walletManagerFactory) - } - - private fun checkIfDerivationsAreMissing(blockchainNetworks: List, scanResponse: ScanResponse) { - blockchainNetworks.map { - if (it.tokens.isNotEmpty()) { - WalletAction.MultiWallet.AddTokens(it.tokens, it) - } - } - val missingDerivations = blockchainNetworks - .filter { - it.derivationPath != null && !scanResponse.hasDerivation(it.blockchain, it.derivationPath) - } - store.dispatch(WalletAction.MultiWallet.AddMissingDerivations(missingDerivations)) - } - - private suspend fun loadSingleWalletData(data: ScanResponse) { - val blockchain = data.cardTypesResolver.getBlockchain() - val primaryWalletManager = walletManagerFactory.makePrimaryWalletManager(data) - - if (blockchain != Blockchain.Unknown && primaryWalletManager != null) { - val blockchainNetwork = BlockchainNetwork.fromWalletManager(primaryWalletManager) - val actionsList = listOfNotNull( - WalletAction.MultiWallet.AddBlockchains( - blockchains = listOf(BlockchainNetwork.fromWalletManager(primaryWalletManager)), - walletManagers = listOf(primaryWalletManager), - ), - data.cardTypesResolver.getPrimaryToken()?.let { - primaryWalletManager.addToken(it) - primaryWalletManager.wallet.setAmount(Amount(it)) - WalletAction.MultiWallet.AddToken(it, blockchainNetwork, false) - }, - WalletAction.LoadFiatRate(), - ) - dispatchOnMain(*actionsList.toTypedArray()) - } - } - - private suspend fun loadUserCurrencies(scanResponse: ScanResponse, walletManagerFactory: WalletManagerFactory) { - val userTokens = userTokensRepository.getUserTokens(scanResponse.card) - withMainContext { - val blockchainNetworks = userTokens.toBlockchainNetworks() - val walletManagers = walletManagerFactory.makeWalletManagersForApp(scanResponse, userTokens) - store.dispatch( - WalletAction.MultiWallet.AddBlockchains( - blockchains = blockchainNetworks, - walletManagers = walletManagers, - ), - ) - - blockchainNetworks.filter { it.tokens.isNotEmpty() } - .map { - store.dispatch( - WalletAction.MultiWallet.AddTokens( - tokens = it.tokens, - blockchain = it, - ), - ) - } - checkIfDerivationsAreMissing(blockchainNetworks, scanResponse) - store.dispatch(WalletAction.LoadFiatRate(coinsList = userTokens)) - } - } - - suspend fun reloadData(data: ScanResponse) { - if (data.cardTypesResolver.isMultiwalletAllowed()) { - loadUserCurrencies(data, walletManagerFactory) - } - withContext(Dispatchers.Main) { - getActionIfUnknownBlockchainOrEmptyWallet(data)?.let { - store.dispatch(it) - return@withContext - } - if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) { - store.dispatch(WalletAction.LoadData.Failure(TapError.NoInternetConnection)) - return@withContext - } - - store.dispatch(WalletAction.LoadWallet()) - } - } - - private fun getActionIfUnknownBlockchainOrEmptyWallet(data: ScanResponse): WalletAction? { - return when { - // check order is important - data.cardTypesResolver.isTangemTwins() && !data.twinsIsTwinned() -> { - WalletAction.EmptyWallet - } - data.cardTypesResolver.getBlockchain() == Blockchain.Unknown && - !data.cardTypesResolver.isMultiwalletAllowed() -> { - WalletAction.LoadData.Failure(TapError.UnknownBlockchain) - } - data.isDemoCard() -> { - return null - } - data.card.wallets.isEmpty() -> { - WalletAction.EmptyWallet - } - else -> null - } - } } fun Wallet.getFirstToken(): Token? { diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManagerExtensions.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManagerExtensions.kt index 47f8b18a7c..6da40c3b93 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManagerExtensions.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManagerExtensions.kt @@ -5,6 +5,12 @@ import com.tangem.tap.domain.model.UserWallet import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf +/** + * Indicates that the [UserWalletsListManager] implements [UserWalletsListManager.Lockable] + * */ +val UserWalletsListManager.isLockable: Boolean + get() = this is UserWalletsListManager.Lockable + /** * Indicates that the [UserWalletsListManager] is locked * diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index 5609112906..89dc7ed09b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -327,9 +327,10 @@ class DetailsMiddleware { scanResponse: ScanResponse?, enableAccessCodesSaving: Boolean, ): CompletionResult { - val userWallet = scanResponse?.let { UserWalletBuilder(it).build() } + val userWallet = userWalletsListManager.selectedUserWalletSync + ?: scanResponse?.let { UserWalletBuilder(it).build() } ?: return CompletionResult.Failure( - TangemSdkError.ExceptionError(IllegalStateException("scanResponse is null")), + error = TangemSdkError.ExceptionError(IllegalStateException("scanResponse is null")), ) updateUserWalletsListManager(enableUserWalletsSaving = true) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt index 426d274352..fdf3a8b90b 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt @@ -68,6 +68,8 @@ object OnboardingHelper { when { // When should save user wallets, then save card without navigate to save wallet screen preferencesStorage.shouldSaveUserWallets -> scope.launch { + proceedWithScanResponse(scanResponse, backupCardsIds) + store.dispatchOnMain( SaveWalletAction.ProvideBackupInfo( scanResponse = scanResponse, @@ -81,7 +83,7 @@ object OnboardingHelper { // then open save wallet screen tangemSdkManager.canUseBiometry && preferencesStorage.shouldShowSaveUserWalletScreen -> scope.launch { - proceedWithScanResponse(scanResponse) + proceedWithScanResponse(scanResponse, backupCardsIds) delay(timeMillis = 1_200) @@ -96,7 +98,7 @@ object OnboardingHelper { } // If device has no biometry and save wallet screen has been shown, then go through old scenario else -> scope.launch { - proceedWithScanResponse(scanResponse) + proceedWithScanResponse(scanResponse, backupCardsIds) } } @@ -107,13 +109,16 @@ object OnboardingHelper { Analytics.removeContext() } - private suspend fun proceedWithScanResponse(scanResponse: ScanResponse) { - val userWallet = UserWalletBuilder(scanResponse).build().guard { - Timber.e("User wallet not created") - return - } + private suspend fun proceedWithScanResponse(scanResponse: ScanResponse, backupCardsIds: List?) { + val userWallet = UserWalletBuilder(scanResponse) + .backupCardsIds(backupCardsIds?.toSet()) + .build() + .guard { + Timber.e("User wallet not created") + return + } - userWalletsListManager.save(userWallet) + userWalletsListManager.save(userWallet, canOverride = true) .doOnFailure { error -> Timber.e(error, "Unable to save user wallet") } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/redux/OnboardingOtherCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/redux/OnboardingOtherCardsMiddleware.kt index acbe7a146c..faa3dd2441 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/redux/OnboardingOtherCardsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/redux/OnboardingOtherCardsMiddleware.kt @@ -11,10 +11,11 @@ import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.onboarding.OnboardingHelper -import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.models.toCurrencies import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdkManager +import com.tangem.tap.userTokensRepository import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.rekotlin.Action @@ -112,9 +113,12 @@ private fun handleOtherCardsAction(action: Action) { ) } - store.dispatch( - WalletAction.MultiWallet.SaveCurrencies(blockchainNetworks, updatedResponse.card), - ) + scope.launch { + userTokensRepository.saveUserTokens( + card = result.data.card, + tokens = blockchainNetworks.toCurrencies(), + ) + } delay(DELAY_SDK_DIALOG_CLOSE) store.dispatch(OnboardingOtherCardsAction.SetStepOfScreen(OnboardingOtherCardsStep.Done)) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 1ea9f428aa..4226d47b74 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -26,13 +26,14 @@ import com.tangem.tap.features.onboarding.OnboardingDialog import com.tangem.tap.features.onboarding.OnboardingHelper import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManagerFactory import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction +import com.tangem.tap.features.wallet.models.toCurrencies import com.tangem.tap.features.wallet.redux.Artwork -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.preferencesStorage import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdk import com.tangem.tap.tangemSdkManager +import com.tangem.tap.userTokensRepository import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.DispatchFunction @@ -135,12 +136,12 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch: BlockchainNetwork(blockchain, result.data.card) } - store.dispatch( - WalletAction.MultiWallet.SaveCurrencies( - blockchainNetworks = blockchainNetworks, + scope.launch { + userTokensRepository.saveUserTokens( card = result.data.card, - ), - ) + tokens = blockchainNetworks.toCurrencies(), + ) + } startCardActivation(updatedResponse) store.dispatch(OnboardingWalletAction.ResumeBackup) } diff --git a/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt index 921894565b..7c248c0f4f 100644 --- a/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt @@ -19,6 +19,7 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.model.builders.UserWalletBuilder import com.tangem.tap.domain.userWalletList.UserWalletsListManager import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation +import com.tangem.tap.domain.userWalletList.isLockable import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.foregroundActivityObserver import com.tangem.tap.preferencesStorage @@ -97,7 +98,8 @@ internal class SaveWalletMiddleware { val userWallet = userWalletsListManager.selectedUserWalletSync ?: UserWalletBuilder(scanResponse) .backupCardsIds(state.backupInfo?.backupCardsIds) - .build() ?: return@launch + .build() + ?: return@launch provideBiometricUserWalletsListManager() @@ -110,13 +112,11 @@ internal class SaveWalletMiddleware { } .doOnSuccess { preferencesStorage.shouldSaveUserWallets = true - // Enable saving access codes only if this is the first time user save the wallet preferencesStorage.shouldSaveAccessCodes = isFirstSavedWallet || preferencesStorage.shouldSaveAccessCodes store.dispatchWithMain(SaveWalletAction.Save.Success) - store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet)) store.dispatchWithMain(WalletAction.UpdateCanSaveUserWallets(canSaveUserWallets = true)) } @@ -124,6 +124,8 @@ internal class SaveWalletMiddleware { } private suspend fun provideBiometricUserWalletsListManager() { + if (store.state.globalState.userWalletsListManager?.isLockable == true) return + val context = foregroundActivityObserver.foregroundActivity?.applicationContext.guard { val error = IllegalStateException("No activities in foreground") Timber.e(error) 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 d4785af2f5..d86397139b 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 @@ -12,6 +12,7 @@ import com.tangem.blockchain.common.TransactionSender import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.extensions.SimpleResult import com.tangem.common.core.TangemSdkError +import com.tangem.common.extensions.guard import com.tangem.common.services.Result import com.tangem.core.analytics.Analytics import com.tangem.domain.common.CardDTO @@ -333,17 +334,16 @@ private fun updateWarnings(dispatch: (Action) -> Unit) { } private suspend fun updateWallet(walletManager: WalletManager) { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync - if (selectedUserWallet != null) { - val wallet = walletManager.wallet - walletCurrenciesManager.update( - userWallet = selectedUserWallet, - currency = Currency.Blockchain( - blockchain = wallet.blockchain, - derivationPath = wallet.publicKey.derivationPath?.rawPath, - ), - ) - } else { + 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/redux/TokensMiddleware.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt index 7d9b1027ed..0896404d09 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt @@ -5,6 +5,7 @@ import com.tangem.blockchain.common.DerivationStyle import com.tangem.common.CompletionResult import com.tangem.common.card.EllipticCurve 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.common.hdWallet.DerivationPath @@ -273,35 +274,33 @@ class TokensMiddleware { ) private fun submitAdd(scanResponse: ScanResponse, currencyList: List) { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync - if (selectedUserWallet != null) { - scope.launch { - userWalletsListManager.update( - userWalletId = selectedUserWallet.walletId, - update = { userWallet -> - userWallet.copy(scanResponse = scanResponse) - }, - ) - .flatMap { updatedUserWallet -> - walletCurrenciesManager.addCurrencies( - userWallet = updatedUserWallet, - currenciesToAdd = currencyList, - ) - } - } - } else { + 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 suspend fun removeCurrenciesIfNeeded(currencies: List) { if (currencies.isEmpty()) return - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync - if (selectedUserWallet != null) { - walletCurrenciesManager.removeCurrencies(selectedUserWallet, currencies) - } else { + val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { Timber.e("Unable to remove currencies, no user wallet selected") + return } + walletCurrenciesManager.removeCurrencies(selectedUserWallet, currencies) } private fun isNeedToDerive(scanResponse: ScanResponse, currency: Currency): Boolean { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index a305989a17..390b337f30 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -2,12 +2,8 @@ package com.tangem.tap.features.wallet.redux import android.content.Context import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.Token -import com.tangem.blockchain.common.Wallet -import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.address.AddressType import com.tangem.core.analytics.AnalyticsEvent -import com.tangem.domain.common.CardDTO import com.tangem.tap.common.entities.FiatCurrency import com.tangem.tap.common.redux.NotificationAction import com.tangem.tap.domain.TapError @@ -20,7 +16,6 @@ import com.tangem.tap.features.wallet.models.TotalBalance import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.wallet.R import org.rekotlin.Action -import java.math.BigDecimal sealed class WalletAction : Action { @@ -28,81 +23,20 @@ sealed class WalletAction : Action { data class UpdateCanSaveUserWallets(val canSaveUserWallets: Boolean) : WalletAction() - data class ResetState(val newCard: CardDTO) : WalletAction() - - data class SetIfTestnetCard(val isTestnet: Boolean) : WalletAction() - object LoadData : WalletAction() { object Refresh : WalletAction() object Success : WalletAction() data class Failure(val error: TapError?) : WalletAction() } - data class LoadWallet( - val blockchain: BlockchainNetwork? = null, - val walletManager: WalletManager? = null, - ) : WalletAction() { - data class Success(val wallet: Wallet, val blockchain: BlockchainNetwork) : WalletAction() - data class NoAccount( - val wallet: Wallet, - val blockchain: BlockchainNetwork, - val amountToCreateAccount: String, - ) : WalletAction() - - data class Failure(val wallet: Wallet, val errorMessage: String? = null) : WalletAction() - } - - data class SetArtworkId(val artworkId: String?) : WalletAction() - - sealed class UserTokens : WalletAction() { - object Loading : UserTokens() - object Loaded : UserTokens() - } - sealed class MultiWallet : WalletAction() { - data class SetIsMultiwalletAllowed(val isMultiwalletAllowed: Boolean) : MultiWallet() - - data class AddBlockchains( - val blockchains: List, - val walletManagers: List, - ) : MultiWallet() - - data class AddTokens( - val tokens: List, - val blockchain: BlockchainNetwork, - ) : MultiWallet() - - data class AddBlockchain( - val blockchain: BlockchainNetwork, - val walletManager: WalletManager?, - val save: Boolean, - ) : MultiWallet() - - data class AddToken( - val token: Token, - val blockchain: BlockchainNetwork, - val save: Boolean, - ) : MultiWallet() - - data class SaveCurrencies( - val blockchainNetworks: List, - val card: CardDTO? = null, - ) : MultiWallet() - - data class TokenLoaded( - val amount: Amount, - val token: Token, - val blockchain: BlockchainNetwork, - ) : MultiWallet() data class SelectWallet(val currency: Currency?) : MultiWallet() data class SetSingleWalletCurrency(val currency: Currency?) : MultiWallet() data class TryToRemoveWallet(val currency: Currency) : MultiWallet() data class RemoveWallet(val currency: Currency) : MultiWallet() - data class RemoveWallets(val currencies: List) : MultiWallet() - data class ShowWalletBackupWarning(val show: Boolean) : MultiWallet() object BackupWallet : MultiWallet() object ScheduleCheckForMissingDerivation : MultiWallet() data class AddMissingDerivations(val blockchains: List) : MultiWallet() @@ -129,24 +63,6 @@ sealed class WalletAction : Action { class CheckRemainingSignatures(val remainingSignatures: Int?) : Warnings() } - data class LoadFiatRate( - val wallet: Wallet? = null, - val coinsList: List? = null, - ) : WalletAction() { - data class Success( - val fiatRates: Map, - ) : WalletAction() - - object Failure : WalletAction() - } - - class LoadCardInfo(val card: CardDTO) : WalletAction() - - data class LoadArtwork(val card: CardDTO, val artworkId: String?) : WalletAction() { - data class Success(val artwork: Artwork) : WalletAction() - object Failure : WalletAction() - } - data class Scan(val onScanSuccessEvent: AnalyticsEvent?) : WalletAction() data class Send(val amount: Amount? = null) : WalletAction() @@ -183,7 +99,6 @@ sealed class WalletAction : Action { data class ExploreAddress(val exploreUrl: String, val context: Context) : WalletAction() object CreateWallet : WalletAction() - object EmptyWallet : WalletAction() object ChangeWallet : WalletAction() object ShowSaveWalletIfNeeded : WalletAction() @@ -206,14 +121,6 @@ sealed class WalletAction : Action { data class ChangeSelectedAddress(val type: AddressType) : WalletAction() - data class SetWalletRent( - val wallet: Wallet, - val minRent: String, - val rentExempt: String, - ) : WalletAction() - - data class RemoveWalletRent(val wallet: Wallet) : WalletAction() - sealed class AppCurrencyAction : WalletAction() { object ChooseAppCurrency : AppCurrencyAction() data class SelectAppCurrency(val fiatCurrency: FiatCurrency) : AppCurrencyAction() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 23c86b2a7e..81b306448b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -2,8 +2,6 @@ package com.tangem.tap.features.wallet.redux import android.graphics.Bitmap import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.Token -import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.address.AddressType import com.tangem.tap.common.entities.Button @@ -11,16 +9,13 @@ import com.tangem.tap.common.extensions.toQrCode import com.tangem.tap.common.redux.global.CryptoCurrencyName import com.tangem.tap.common.toggleWidget.WidgetState import com.tangem.tap.domain.configurable.warningMessage.WarningMessage -import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.TotalBalance -import com.tangem.tap.features.wallet.redux.reducers.calculateTotalFiatAmount import com.tangem.tap.features.wallet.redux.reducers.findProgressState import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.store -import com.tangem.tap.userWalletsListManager import org.rekotlin.StateType import kotlin.properties.ReadOnlyProperty @@ -88,12 +83,6 @@ data class WalletState( val primaryWalletData: WalletData? get() = primaryWalletStore?.walletsData?.firstOrNull() - val primaryBlockchain: Blockchain? - get() = primaryWalletManager?.wallet?.blockchain - - val primaryToken: Token? - get() = primaryWalletManager?.wallet?.getFirstToken() - val primaryTokenData: WalletData? get() = primaryWalletStore?.walletsData?.toMutableList() ?.apply { remove(primaryWalletData) } @@ -103,9 +92,6 @@ data class WalletState( primaryWalletData?.currencyData?.status != BalanceStatus.EmptyCard && primaryWalletData?.currencyData?.status != BalanceStatus.UnknownBlockchain - val hasSavedWallets: Boolean - get() = userWalletsListManager.hasUserWallets - fun getWalletManager(currency: Currency?): WalletManager? { if (currency?.blockchain == null) return null return getWalletStore(currency)?.walletManager @@ -132,14 +118,7 @@ data class WalletState( } } - fun getWalletStore(wallet: Wallet?): WalletStore? { - if (wallet == null) return null - val currency = - Currency.Blockchain(wallet.blockchain, wallet.publicKey.derivationPath?.rawPath) - return getWalletStore(currency) - } - - fun getWalletStore(blockchainNetwork: BlockchainNetwork?): WalletStore? { + private fun getWalletStore(blockchainNetwork: BlockchainNetwork?): WalletStore? { if (blockchainNetwork == null) return null return walletsStores.firstOrNull { it.blockchainNetwork.derivationPath == blockchainNetwork.derivationPath && @@ -152,26 +131,12 @@ data class WalletState( return getWalletStore(currency)?.walletsData?.firstOrNull { it.currency == currency } } - fun replaceWalletStoreInWalletsStores(wallet: WalletStore?): List { - if (wallet == null) return walletsStores - var changed = false - val updatedWallets = walletsStores.map { - if (it.blockchainNetwork == wallet.blockchainNetwork) { - changed = true - wallet - } else { - it - } - } - return if (changed) updatedWallets else walletsStores + wallet - } - fun updateWalletData(walletData: WalletData?): WalletState { if (walletData == null) return this return updateWalletsData(listOf(walletData)) } - fun updateWalletsData(walletsData: List): WalletState { + private fun updateWalletsData(walletsData: List): WalletState { val walletStores = walletsData .map { BlockchainNetwork(it.currency.blockchain, it.currency.derivationPath, emptyList()) } .distinct().map { getWalletStore(it) }.mapNotNull { it?.updateWallets(walletsData) } @@ -179,12 +144,6 @@ data class WalletState( return updateWalletsStores(walletStores) } - fun updateWalletStore(walletStore: WalletStore?): WalletState { - return copy(walletsStores = replaceWalletStoreInWalletsStores(walletStore)) - .updateTotalBalance() - .updateProgressState() - } - private fun updateWalletsStores(walletStores: List): WalletState { val walletStoresMutable = walletStores.toMutableList() val updatedWallets = walletsStores.map { oldWalletStore -> @@ -199,54 +158,9 @@ data class WalletState( } } return copy(walletsStores = updatedWallets + walletStoresMutable) - .updateTotalBalance() .updateProgressState() } - fun removeWalletData(walletData: WalletData?): WalletState { - if (walletData == null) return this - return when (val currency = walletData.currency) { - is Currency.Blockchain -> { - val walletStores = walletsStores.filterNot { - it.blockchainNetwork.blockchain == currency.blockchain && - it.blockchainNetwork.derivationPath == currency.derivationPath - } - copy(walletsStores = walletStores) - .updateTotalBalance() - .updateProgressState() - } - is Currency.Token -> { - val walletStore = getWalletStore(walletData.currency) - val walletDataList = walletStore?.walletsData - ?.filterNot { it.currency == walletData.currency } - ?: emptyList() - val updatedWalletManager = walletStore?.walletManager?.also { it.removeToken(currency.token) } - val updatedWalletStore = walletStore?.copy( - walletsData = walletDataList, - walletManager = updatedWalletManager, - ) - updateWalletStore(updatedWalletStore) - } - } - } - - private fun updateTotalBalance(): WalletState { - val walletsData = this.walletsStores - .flatMap(WalletStore::walletsData) - - return if (walletsData.isNotEmpty()) { - this.copy( - totalBalance = TotalBalance( - state = walletsData.findProgressState(), - fiatAmount = walletsData.calculateTotalFiatAmount(), - fiatCurrency = store.state.globalState.appCurrency, - ), - ) - } else { - this.copy(totalBalance = null) - } - } - private fun updateProgressState(): WalletState { val walletsData = this.walletsStores .flatMap(WalletStore::walletsData) @@ -268,21 +182,6 @@ data class WalletState( } } -fun List.replaceSomeWalletsData(newWallets: List): List { - val remainingWallets: MutableList = newWallets.toMutableList() - val updatedWallets = this.map { wallet -> - val newWallet = newWallets - .firstOrNull { wallet.currency == it.currency } - if (newWallet == null) { - wallet - } else { - remainingWallets.remove(newWallet) - newWallet - } - } - return updatedWallets + remainingWallets -} - enum class ProgressState : WidgetState { Loading, Refreshing, Done, Error } enum class ErrorType { NoInternetConnection } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt index ad7e1d4914..974ef88df8 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.wallet.redux.middlewares +import com.tangem.common.extensions.guard import com.tangem.core.analytics.Analytics import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse import com.tangem.tap.common.analytics.events.AnalyticsParam @@ -67,13 +68,12 @@ class AppCurrencyMiddleware( store.dispatch(GlobalAction.ChangeAppCurrency(action.fiatCurrency)) store.dispatch(DetailsAction.ChangeAppCurrency(action.fiatCurrency)) store.dispatch(WalletSelectorAction.ChangeAppCurrency(action.fiatCurrency)) - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync - if (selectedUserWallet != null) { - scope.launch { - tapWalletManager.loadData(selectedUserWallet, refresh = true) - } - } else { + val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { Timber.e("Unable to select currency, no user wallet selected") + return + } + scope.launch { + tapWalletManager.loadData(selectedUserWallet, refresh = true) } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index 65a19b3d79..2642cbeb50 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -1,8 +1,5 @@ package com.tangem.tap.features.wallet.redux.middlewares -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Token -import com.tangem.blockchain.common.WalletManager import com.tangem.common.doOnSuccess import com.tangem.common.extensions.guard import com.tangem.common.flatMap @@ -13,23 +10,14 @@ import com.tangem.tap.common.extensions.addContext import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchErrorNotification import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.common.redux.global.GlobalState import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.TapError -import com.tangem.tap.domain.extensions.makeWalletManagerForApp import com.tangem.tap.domain.model.UserWallet -import com.tangem.tap.domain.tokens.models.BlockchainNetwork -import com.tangem.tap.features.demo.DemoHelper -import com.tangem.tap.features.demo.isDemoCard -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.models.toCurrencies import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.models.WalletDialog -import com.tangem.tap.features.wallet.redux.reducers.toWallet import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdkManager @@ -39,69 +27,19 @@ import com.tangem.tap.walletCurrenciesManager import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import timber.log.Timber -import java.math.BigDecimal class MultiWalletMiddleware { @Suppress("LongMethod", "ComplexMethod") fun handle( action: WalletAction.MultiWallet, walletState: WalletState?, - globalState: GlobalState?, ) { - val globalState = globalState ?: return - when (action) { - is WalletAction.MultiWallet.AddBlockchains -> { - handleAddingWalletManagers(globalState, action.walletManagers) - } is WalletAction.MultiWallet.SelectWallet -> { if (action.currency != null) { store.dispatch(NavigationAction.NavigateTo(AppScreen.WalletDetails)) } } - is WalletAction.MultiWallet.AddToken -> { - addTokens(listOf(action.token), action.blockchain, walletState, globalState, action.save) - } - is WalletAction.MultiWallet.AddTokens -> { - addTokens(action.tokens, action.blockchain, walletState, globalState, save = false) - } - is WalletAction.MultiWallet.AddBlockchain -> { - action.walletManager?.let { - handleAddingWalletManagers(globalState, listOf(action.walletManager)) - } - val currencies: List = - (walletState?.currencies ?: emptyList()) + action.blockchain.toCurrencies() - - if (action.save && globalState.scanResponse != null) { - scope.launch { - userTokensRepository.saveUserTokens( - card = globalState.scanResponse.card, - tokens = currencies, - ) - } - } - - store.dispatch( - WalletAction.LoadFiatRate( - coinsList = listOf( - Currency.Blockchain( - action.blockchain.blockchain, - action.blockchain.derivationPath, - ), - ), - ), - ) - store.dispatch( - WalletAction.LoadWallet( - blockchain = action.blockchain, - walletManager = action.walletManager, - ), - ) - } - is WalletAction.MultiWallet.SaveCurrencies -> { - val card = action.card ?: globalState.scanResponse?.card ?: return - scope.launch { userTokensRepository.saveUserTokens(card, action.blockchainNetworks.toCurrencies()) } - } is WalletAction.MultiWallet.TryToRemoveWallet -> { val currency = action.currency val walletManager = walletState?.getWalletManager(currency).guard { @@ -131,47 +69,36 @@ class MultiWalletMiddleware { } } is WalletAction.MultiWallet.RemoveWallet -> { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync - if (selectedUserWallet != null) { - scope.launch { - walletCurrenciesManager.removeCurrency( - userWallet = selectedUserWallet, - currencyToRemove = action.currency, - ) - } - } else { + val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { Timber.e("Unable to remove wallet, no user wallet selected") - } - } - is WalletAction.MultiWallet.RemoveWallets -> { - val card = globalState.scanResponse?.card.guard { - store.dispatchErrorNotification(TapError.UnsupportedState("card is NULL")) - store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) return } - var currencies = walletState?.currencies ?: emptyList() - currencies = currencies.filterNot { action.currencies.contains(it) } - scope.launch { userTokensRepository.saveUserTokens(card, currencies) } - store.dispatch(WalletAction.MultiWallet.SelectWallet(null)) - } - is WalletAction.MultiWallet.ShowWalletBackupWarning -> Unit - is WalletAction.MultiWallet.BackupWallet -> { - store.state.globalState.scanResponse?.let { - Analytics.addContext(it) - store.dispatch(GlobalAction.Onboarding.Start(it, canSkipBackup = false)) - store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet)) + scope.launch { + walletCurrenciesManager.removeCurrency( + userWallet = selectedUserWallet, + currencyToRemove = action.currency, + ) } } + is WalletAction.MultiWallet.BackupWallet -> { + val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { + Timber.e("Unable to backup wallet, no user wallet selected") + return + } + val scanResponse = selectedUserWallet.scanResponse + Analytics.addContext(scanResponse) + store.dispatch(GlobalAction.Onboarding.Start(scanResponse, canSkipBackup = false)) + store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet)) + } is WalletAction.MultiWallet.AddMissingDerivations -> { scope.launch { handleBasicAnalyticsEvent() } } is WalletAction.MultiWallet.ScanToGetDerivations -> { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync - if (selectedUserWallet != null) { - scanAndUpdateCard(selectedUserWallet, walletState) - } else { + val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { Timber.e("Unable to scan to get derivations, no user wallet selected") + return } + scanAndUpdateCard(selectedUserWallet, walletState) } else -> {} } @@ -203,86 +130,4 @@ class MultiWalletMiddleware { store.state.globalState.tapWalletManager.loadData(updatedUserWallet, refresh = true) } } - - private fun addDummyBalances(walletManagers: List) { - walletManagers.forEach { - if (it.wallet.fundsAvailable(AmountType.Coin) == BigDecimal.ZERO) { - DemoHelper.injectDemoBalance(it) - } - } - } - - private fun handleAddingWalletManagers( - globalState: GlobalState, - walletManagers: List, - ) { - globalState.feedbackManager?.infoHolder?.setWalletsInfo(walletManagers) - if (globalState.scanResponse?.isDemoCard() == true) { - addDummyBalances(walletManagers) - } - } - - private fun addTokens( - tokens: List, - blockchainNetwork: BlockchainNetwork, - walletState: WalletState?, - globalState: GlobalState?, - save: Boolean, - ) { - if (tokens.isEmpty()) return - val scanResponse = globalState?.scanResponse ?: return - val wmFactory = globalState.tapWalletManager.walletManagerFactory - val walletState = walletState ?: return - val walletManager = walletState.getWalletManager(blockchainNetwork)?.also { - if (save) { - val wallets = tokens.mapNotNull { token -> token.toWallet(walletState, blockchainNetwork) } - val currencies = walletState.updateWalletsData(wallets).currencies - scope.launch { userTokensRepository.saveUserTokens(scanResponse.card, currencies) } - } - } ?: wmFactory.makeWalletManagerForApp(scanResponse, blockchainNetwork)?.also { - store.dispatchOnMain( - WalletAction.MultiWallet.AddBlockchain( - blockchain = blockchainNetwork.updateTokens(tokens), - walletManager = it, - save = save, - ), - ) - } - - store.dispatchOnMain( - WalletAction.LoadFiatRate( - coinsList = tokens.map { token -> - Currency.Token( - token, - blockchainNetwork.blockchain, - blockchainNetwork.derivationPath, - ) - }, - ), - ) - if (tokens.isNotEmpty()) walletManager?.addTokens(tokens) - - scope.launch { - when (val result = walletManager?.safeUpdate()) { - is com.tangem.common.services.Result.Success -> { - val wallet = result.data - wallet.getTokens() - .filter { tokens.contains(it) } - .mapNotNull { token -> - wallet.getTokenAmount(token)?.let { amount -> Pair(token, amount) } - } - .forEach { (token, tokenAmount) -> - store.dispatchOnMain( - WalletAction.MultiWallet.TokenLoaded( - amount = tokenAmount, - token = token, - blockchain = blockchainNetwork, - ), - ) - } - } - else -> Unit - } - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 0ba437fdb6..276265fa9e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -1,17 +1,11 @@ package com.tangem.tap.features.wallet.redux.middlewares import com.google.firebase.crashlytics.FirebaseCrashlytics -import com.tangem.blockchain.blockchains.solana.RentProvider import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.WalletManager import com.tangem.common.CompletionResult -import com.tangem.common.extensions.isZero -import com.tangem.common.services.Result +import com.tangem.common.extensions.guard import com.tangem.core.analytics.Analytics -import com.tangem.domain.common.extensions.withMainContext -import com.tangem.operations.attestation.Attestation -import com.tangem.operations.attestation.OnlineCardVerifier import com.tangem.tap.common.analytics.converters.BasicEventsPreChecker import com.tangem.tap.common.analytics.converters.BasicEventsSourceData import com.tangem.tap.common.analytics.events.AnalyticsParam @@ -19,22 +13,16 @@ import com.tangem.tap.common.analytics.events.Basic import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.analytics.events.Token import com.tangem.tap.common.extensions.copyToClipboard -import com.tangem.tap.common.extensions.dispatchDebugErrorNotification import com.tangem.tap.common.extensions.dispatchErrorNotification import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchOpenUrl import com.tangem.tap.common.extensions.dispatchToastNotification import com.tangem.tap.common.extensions.isGreaterThan -import com.tangem.tap.common.extensions.onCardScanned import com.tangem.tap.common.extensions.shareText -import com.tangem.tap.common.extensions.stripZeroPlainString import com.tangem.tap.common.redux.AppState -import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.TapError -import com.tangem.tap.domain.failedRates -import com.tangem.tap.domain.loadedRates import com.tangem.tap.domain.model.WalletDataModel import com.tangem.tap.domain.model.WalletStoreModel import com.tangem.tap.domain.model.builders.UserWalletIdBuilder @@ -43,9 +31,6 @@ import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.send.redux.PrepareSendScreen import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.models.PendingTransactionType -import com.tangem.tap.features.wallet.models.filterByCoin -import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.models.getSendableAmounts import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletData @@ -64,8 +49,6 @@ import com.tangem.tap.userWalletsListManagerSafe import com.tangem.tap.walletStoresManager import com.tangem.wallet.R import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.rekotlin.Action @@ -108,97 +91,26 @@ class WalletMiddleware { when (action) { is WalletAction.TradeCryptoAction -> tradeCryptoMiddleware.handle(state, action) is WalletAction.Warnings -> warningsMiddleware.handle(action, globalState) - is WalletAction.MultiWallet -> multiWalletMiddleware.handle(action, walletState, globalState) + is WalletAction.MultiWallet -> multiWalletMiddleware.handle(action, walletState) is WalletAction.AppCurrencyAction -> appCurrencyMiddleware.handle(action) is WalletAction.DialogAction -> walletDialogMiddleware.handle(action) - is WalletAction.LoadWallet -> { - scope.launch { - if (action.blockchain == null) { - walletState.walletManagers.map { walletManager -> - async { globalState.tapWalletManager.loadWalletData(walletManager) } - }.awaitAll() - handleBasicAnalyticsEvent() - } else { - val walletManager = walletState.getWalletManager(action.blockchain) - ?: action.walletManager - walletManager?.let { globalState.tapWalletManager.loadWalletData(it) } - } - } - } - is WalletAction.LoadWallet.Success -> { - checkForRentWarning(walletState.getWalletManager(action.blockchain)) - val coinAmount = action.wallet.amounts[AmountType.Coin]?.value - if (coinAmount?.isZero() == false && walletState.getWalletData(action.blockchain) == null) { - store.dispatch( - WalletAction.MultiWallet.AddBlockchain( - blockchain = action.blockchain, - walletManager = null, - save = true, - ), - ) - store.dispatch(WalletAction.LoadWallet.Success(action.wallet, action.blockchain)) - } - store.dispatch(WalletAction.Warnings.CheckHashesCount.CheckHashesCountOnline) - warningsMiddleware.tryToShowAppRatingWarning(action.wallet) - } - is WalletAction.LoadFiatRate -> { - val appCurrencyId = globalState.appCurrency.code - scope.launch { - val coinsList = when { - action.wallet != null -> { - val wallet = action.wallet - wallet.getTokens() - .map { Currency.Token(it, wallet.blockchain, wallet.publicKey.derivationPath?.rawPath) } - .plus(Currency.Blockchain(wallet.blockchain, wallet.publicKey.derivationPath?.rawPath)) - } - action.coinsList != null -> action.coinsList - else -> { - if (walletState.isMultiwalletAllowed) { - walletState.walletsDataFromStores.map { it.currency } - } else { - val derivationPath = walletState.primaryWalletData?.currency?.derivationPath - val primaryBlockchain = walletState.primaryBlockchain - val primaryToken = walletState.primaryToken - listOfNotNull( - primaryBlockchain?.let { Currency.Blockchain(it, derivationPath) }, - primaryToken?.let { Currency.Token(it, primaryBlockchain!!, derivationPath) }, - ) - } - } - } - val ratesResult = globalState.tapWalletManager.rates.loadFiatRate( - currencyId = appCurrencyId, - coinsList = coinsList, - ) - when (ratesResult) { - is Result.Success -> { - ratesResult.data.loadedRates.let { - dispatchOnMain(WalletAction.LoadFiatRate.Success(it)) - } - ratesResult.data.failedRates.forEach { (currency, throwable) -> - Timber.e( - throwable, - "Loading rates failed for [%s]", - currency.currencySymbol, - ) - } - } - is Result.Failure -> { - store.dispatchDebugErrorNotification("LoadFiatRate.Failure") - dispatchOnMain(WalletAction.LoadFiatRate.Failure) - } - } - } - } is WalletAction.CreateWallet -> { scope.launch { - val result = tangemSdkManager.createWallet(globalState.scanResponse?.card?.cardId) - when (result) { + when (val result = tangemSdkManager.createWallet(globalState.scanResponse?.card?.cardId)) { is CompletionResult.Success -> { - val scanResponse = globalState.scanResponse?.copy(card = result.data) - scanResponse?.let { store.onCardScanned(scanResponse) } + val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { + Timber.e("Unable to create wallet, no user wallet selected") + return@launch + } + userWalletsListManager.update(selectedUserWallet.walletId) { userWallet -> + userWallet.copy( + scanResponse = userWallet.scanResponse.copy( + card = result.data, + ), + ) + } } - is CompletionResult.Failure -> {} + is CompletionResult.Failure -> Unit } } } @@ -209,50 +121,29 @@ class WalletMiddleware { store.dispatchOnMain(HomeAction.ReadCard(action.onScanSuccessEvent)) } } - is WalletAction.LoadCardInfo -> { - val attestationFailed = action.card.attestation.status == Attestation.Status.Failed - store.dispatchOnMain(GlobalAction.SetIfCardVerifiedOnline(!attestationFailed)) - - scope.launch { - val response = OnlineCardVerifier().getCardInfo(action.card.cardId, action.card.cardPublicKey) - when (response) { - is Result.Success -> { - val actionList = listOf( - WalletAction.SetArtworkId(response.data.artwork?.id), - WalletAction.LoadArtwork(action.card, response.data.artwork?.id), - ) - withMainContext { actionList.forEach { store.dispatch(it) } } - } - is Result.Failure -> {} - } - store.dispatchOnMain(WalletAction.Warnings.CheckIfNeeded) - } - } is WalletAction.LoadData, is WalletAction.LoadData.Refresh, -> { - val selectedWallet = userWalletsListManager.selectedUserWalletSync + val selectedWallet = userWalletsListManager.selectedUserWalletSync.guard { + Timber.e("Unable to load/refresh wallets data, no user wallet selected") + return + } scope.launch { - if (selectedWallet != null) { - globalState.tapWalletManager.loadData( - userWallet = selectedWallet, - refresh = action is WalletAction.LoadData.Refresh, - ) - } else { - Timber.e("Unable to load/refresh wallets data, no user wallet selected") - } + globalState.tapWalletManager.loadData( + userWallet = selectedWallet, + refresh = action is WalletAction.LoadData.Refresh, + ) } } is NetworkStateChanged -> { store.dispatch(WalletAction.Warnings.CheckHashesCount.CheckHashesCountOnline) if (!action.isOnline) return - val selectedUserWallet = userWalletsListManagerSafe?.selectedUserWalletSync - if (selectedUserWallet != null) { - scope.launch { globalState.tapWalletManager.loadData(selectedUserWallet) } - } else { + val selectedUserWallet = userWalletsListManagerSafe?.selectedUserWalletSync.guard { Timber.e("Unable to proceed with changed network state, no user wallet selected") + return } + scope.launch { globalState.tapWalletManager.loadData(selectedUserWallet) } } is WalletAction.CopyAddress -> { Analytics.send(Token.Receive.ButtonCopyAddress()) @@ -460,48 +351,6 @@ class WalletMiddleware { tokenRate = tokenRate, ) } - - private fun checkForRentWarning(walletManager: WalletManager?) { - val rentProvider = walletManager as? RentProvider ?: return - - scope.launch { - when (val result = rentProvider.minimalBalanceForRentExemption()) { - is com.tangem.blockchain.extensions.Result.Success -> { - fun isNeedToShowWarning(balance: BigDecimal, rentExempt: BigDecimal): Boolean { - return balance < rentExempt - } - - val balance = walletManager.wallet.fundsAvailable(AmountType.Coin) - val outgoingTxs = walletManager.wallet.getPendingTransactions( - PendingTransactionType.Outgoing, - ).filterByCoin() - - val rentExempt = result.data - val show = if (outgoingTxs.isEmpty()) { - isNeedToShowWarning(balance, rentExempt) - } else { - val outgoingAmount = outgoingTxs.sumOf { it.amountValue ?: BigDecimal.ZERO } - val rest = balance.minus(outgoingAmount) - isNeedToShowWarning(rest, rentExempt) - } - - val currency = walletManager.wallet.blockchain.currency - if (show) { - dispatchOnMain( - WalletAction.SetWalletRent( - wallet = walletManager.wallet, - minRent = "${rentProvider.rentAmount().stripZeroPlainString()} $currency", - rentExempt = "${rentExempt.stripZeroPlainString()} $currency", - ), - ) - } else { - dispatchOnMain(WalletAction.RemoveWalletRent(walletManager.wallet)) - } - } - is com.tangem.blockchain.extensions.Result.Failure -> {} - } - } - } } suspend fun handleBasicAnalyticsEvent() { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt index e415a746a2..2dcfeaf198 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt @@ -1,173 +1,13 @@ package com.tangem.tap.features.wallet.redux.reducers -import com.google.firebase.crashlytics.FirebaseCrashlytics -import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Token -import com.tangem.blockchain.common.WalletManager -import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.common.extensions.dispatchToastNotification -import com.tangem.tap.common.extensions.getBlockchainTxHistory -import com.tangem.tap.common.extensions.getTokenTxHistory -import com.tangem.tap.common.extensions.toFiatString -import com.tangem.tap.common.extensions.toFormattedCurrencyString -import com.tangem.tap.common.redux.navigation.AppScreen -import com.tangem.tap.common.redux.navigation.NavigationAction -import com.tangem.tap.domain.tokens.models.BlockchainNetwork -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.models.WalletRent -import com.tangem.tap.features.wallet.models.filterByToken -import com.tangem.tap.features.wallet.models.getPendingTransactions -import com.tangem.tap.features.wallet.models.removeUnknownTransactions import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletData -import com.tangem.tap.features.wallet.redux.WalletMainButton import com.tangem.tap.features.wallet.redux.WalletState -import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN -import com.tangem.tap.features.wallet.redux.WalletStore -import com.tangem.tap.features.wallet.ui.BalanceStatus -import com.tangem.tap.features.wallet.ui.BalanceWidgetData -import com.tangem.tap.store -import com.tangem.tap.userWalletsListManager -import com.tangem.wallet.R -import java.math.BigDecimal class MultiWalletReducer { @Suppress("LongMethod", "ComplexMethod") fun reduce(action: WalletAction.MultiWallet, state: WalletState): WalletState { return when (action) { - is WalletAction.MultiWallet.AddBlockchains -> { - val walletStores: List = action.blockchains.map { blockchain -> - val walletManager = action.walletManagers.firstOrNull { - it.wallet.blockchain == blockchain.blockchain && - it.wallet.publicKey.derivationPath?.rawPath == blockchain.derivationPath - } - val wallet = walletManager?.wallet - val walletData = WalletData( - currencyData = BalanceWidgetData( - status = BalanceStatus.Loading, - currency = blockchain.blockchain.fullName, - currencySymbol = blockchain.blockchain.currency, - ), - walletAddresses = createAddressList(wallet), - mainButton = WalletMainButton.SendButton(false), - currency = Currency.Blockchain( - blockchain.blockchain, - blockchain.derivationPath, - ), - existentialDepositString = getExistentialDeposit(walletManager), - historyTransactions = walletManager?.getBlockchainTxHistory(), - ) - - WalletStore( - walletManager = walletManager, - blockchainNetwork = blockchain, - walletsData = listOf(walletData), - ) - } - - state.copy( - walletsStores = walletStores, - selectedCurrency = findSelectedCurrency( - walletsStores = walletStores, - currentSelectedCurrency = state.selectedCurrency, - isMultiWalletAllowed = state.isMultiwalletAllowed, - ), - ) - } - is WalletAction.MultiWallet.AddBlockchain -> { - val walletManager = action.walletManager ?: state.getWalletManager(action.blockchain) - val wallet = walletManager?.wallet - - val walletData = WalletData( - currencyData = BalanceWidgetData( - status = BalanceStatus.Loading, - currency = action.blockchain.blockchain.fullName, - currencySymbol = action.blockchain.blockchain.currency, - ), - walletAddresses = createAddressList(wallet), - mainButton = WalletMainButton.SendButton(false), - currency = Currency.Blockchain( - action.blockchain.blockchain, - action.blockchain.derivationPath, - ), - existentialDepositString = getExistentialDeposit(walletManager), - historyTransactions = walletManager?.getBlockchainTxHistory(), - ) - val walletStore = WalletStore( - walletManager = walletManager, - blockchainNetwork = action.blockchain, - walletsData = listOf(walletData), - ) - - val newState = state.updateWalletStore(walletStore) - if (wallet != null && wallet.amounts[AmountType.Coin]?.value != null) { - OnWalletLoadedReducer().reduce(wallet, action.blockchain, newState) - } else { - newState - } - } - is WalletAction.MultiWallet.AddTokens -> addTokens(action.tokens, action.blockchain, state) - is WalletAction.MultiWallet.AddToken -> addTokens(listOf(action.token), action.blockchain, state) - is WalletAction.MultiWallet.TokenLoaded -> { - val currency = Currency.fromBlockchainNetwork(action.blockchain, action.token) - val walletManager = state.getWalletManager(currency) - if (walletManager == null) { - val screen = if (userWalletsListManager.hasUserWallets) { - AppScreen.Welcome - } else { - AppScreen.Home - } - store.dispatchOnMain(NavigationAction.PopBackTo(screen)) - - FirebaseCrashlytics.getInstance().recordException( - IllegalStateException("MultiWallet.TokenLoaded: walletManager is null"), - ) - - store.dispatchToastNotification(R.string.internal_error_wallet_manager_not_found) - return state - } - val wallet = walletManager.wallet - val pendingTransactions = wallet.getPendingTransactions() - val tokenPendingTransactions = pendingTransactions.filterByToken(action.token) - val tokenBalanceStatus = when { - tokenPendingTransactions.isNotEmpty() -> BalanceStatus.TransactionInProgress - pendingTransactions.isNotEmpty() -> BalanceStatus.SameCurrencyTransactionInProgress - else -> BalanceStatus.VerifiedOnline - } - val tokenWalletData = state.getWalletData(currency) - val isTokenSendButtonEnabled = tokenWalletData?.shouldEnableTokenSendButton() == true && - pendingTransactions.isEmpty() - - val newTokenWalletData = tokenWalletData?.copy( - currencyData = tokenWalletData.currencyData.copy( - status = tokenBalanceStatus, - amount = action.amount.value, - amountFormatted = action.amount.value?.toFormattedCurrencyString( - decimals = action.amount.decimals, - currency = action.amount.currencySymbol, - ), - fiatAmountFormatted = tokenWalletData.fiatRate?.let { - action.amount.value?.toFiatString(it, store.state.globalState.appCurrency.symbol) - } ?: UNKNOWN_AMOUNT_SIGN, - blockchainAmount = wallet.amounts[AmountType.Coin]?.value ?: BigDecimal.ZERO, - ), - pendingTransactions = pendingTransactions.removeUnknownTransactions(), - mainButton = WalletMainButton.SendButton(isTokenSendButtonEnabled), - currency = Currency.Token( - token = action.token, - blockchain = action.blockchain.blockchain, - derivationPath = action.blockchain.derivationPath, - ), - walletRent = findWalletRent(state.getWalletStore(walletManager.wallet)), - historyTransactions = walletManager.getTokenTxHistory(action.token), - ) - state.updateWalletData(newTokenWalletData) - } - is WalletAction.MultiWallet.SetIsMultiwalletAllowed -> - state.copy(isMultiwalletAllowed = action.isMultiwalletAllowed) - is WalletAction.MultiWallet.SelectWallet -> { state.copy(selectedCurrency = action.currency) } @@ -175,16 +15,6 @@ class MultiWalletReducer { state.copy(selectedCurrency = action.currency) } is WalletAction.MultiWallet.TryToRemoveWallet -> state - is WalletAction.MultiWallet.RemoveWallet -> { - state.removeWalletData(state.getWalletData(action.currency)) - } - is WalletAction.MultiWallet.RemoveWallets -> { - var updatedState = state - action.currencies.forEach { updatedState = updatedState.removeWalletData(state.getWalletData(it)) } - updatedState - } - is WalletAction.MultiWallet.SaveCurrencies -> state - is WalletAction.MultiWallet.ShowWalletBackupWarning -> state.copy(showBackupWarning = action.show) is WalletAction.MultiWallet.ScheduleCheckForMissingDerivation -> state.copy( derivationsCheckIsScheduled = true, ) @@ -194,39 +24,7 @@ class MultiWalletReducer { ) is WalletAction.MultiWallet.BackupWallet -> state is WalletAction.MultiWallet.ScanToGetDerivations -> state.copy(state = ProgressState.Loading) + else -> state } } - - private fun findWalletRent(walletStore: WalletStore?): WalletRent? { - return walletStore?.walletsData?.firstOrNull { it.walletRent != null }?.walletRent - } - - private fun getExistentialDeposit(walletManager: WalletManager?): String? { - return (walletManager as? ExistentialDepositProvider)?.getExistentialDeposit()?.toPlainString() - } - - private fun addTokens(tokens: List, blockchain: BlockchainNetwork, state: WalletState): WalletState { - val wallets = tokens.mapNotNull { token -> token.toWallet(state, blockchain) } - return state.updateWalletsData(wallets) - } -} - -fun Token.toWallet(state: WalletState, blockchain: BlockchainNetwork): WalletData? { - val currency = Currency.fromBlockchainNetwork(blockchain, this) - if (state.currencies.contains(currency)) return null - - val walletManager = state.getWalletManager(currency) - val walletAddresses = createAddressList(walletManager?.wallet) - - return WalletData( - currencyData = BalanceWidgetData( - status = BalanceStatus.Loading, - currency = this.name, - currencySymbol = this.symbol, - ), - walletAddresses = walletAddresses, - mainButton = WalletMainButton.SendButton(false), - currency = currency, - historyTransactions = walletManager?.getTokenTxHistory(this), - ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt deleted file mode 100644 index 086fe57a83..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt +++ /dev/null @@ -1,154 +0,0 @@ -package com.tangem.tap.features.wallet.redux.reducers - -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Wallet -import com.tangem.common.extensions.isZero -import com.tangem.tap.common.extensions.toFiatValue -import com.tangem.tap.common.extensions.toFormattedCurrencyString -import com.tangem.tap.common.extensions.toFormattedFiatValue -import com.tangem.tap.domain.tokens.models.BlockchainNetwork -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.models.filterByToken -import com.tangem.tap.features.wallet.models.getPendingTransactions -import com.tangem.tap.features.wallet.models.removeUnknownTransactions -import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.tap.features.wallet.redux.WalletMainButton -import com.tangem.tap.features.wallet.redux.WalletState -import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN -import com.tangem.tap.features.wallet.redux.replaceSomeWalletsData -import com.tangem.tap.features.wallet.ui.BalanceStatus -import com.tangem.tap.features.wallet.ui.BalanceWidgetData -import com.tangem.tap.store - -class OnWalletLoadedReducer { - - fun reduce(wallet: Wallet, blockchainNetwork: BlockchainNetwork, walletState: WalletState): WalletState { - return if (!walletState.isMultiwalletAllowed) { - onSingleWalletLoaded(wallet, walletState) - } else { - onMultiWalletLoaded(wallet, blockchainNetwork, walletState) - } - } - - @Suppress("LongMethod") - private fun onMultiWalletLoaded( - wallet: Wallet, - blockchainNetwork: BlockchainNetwork, - walletState: WalletState, - ): WalletState { - val walletData = walletState.getWalletData(blockchainNetwork) ?: return walletState - - val fiatCurrency = store.state.globalState.appCurrency - val coinAmountValue = wallet.amounts[AmountType.Coin]?.value - val formattedAmount = coinAmountValue?.toFormattedCurrencyString( - wallet.blockchain.decimals(), - wallet.blockchain.currency, - ) - - val pendingTransactions = wallet.getPendingTransactions() - val isCoinSendButtonEnabled = coinAmountValue?.isZero() == false && pendingTransactions.isEmpty() - val balanceStatus = if (pendingTransactions.isNotEmpty()) { - BalanceStatus.TransactionInProgress - } else { - BalanceStatus.VerifiedOnline - } - - val fiatAmount = walletData.fiatRate?.let { coinAmountValue?.toFiatValue(it) } - val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrency.symbol) ?: UNKNOWN_AMOUNT_SIGN - - val newWalletData = walletData.copy( - currencyData = walletData.currencyData.copy( - status = balanceStatus, - currency = wallet.blockchain.fullName, - currencySymbol = wallet.blockchain.currency, - blockchainAmount = coinAmountValue, - amount = coinAmountValue, - amountFormatted = formattedAmount, - fiatAmount = fiatAmount, - fiatAmountFormatted = fiatAmountFormatted, - ), - pendingTransactions = pendingTransactions.removeUnknownTransactions(), - mainButton = WalletMainButton.SendButton(isCoinSendButtonEnabled), - currency = Currency.fromBlockchainNetwork(blockchainNetwork), - ) - - val tokens = wallet.getTokens().mapNotNull { token -> - val currency = Currency.fromBlockchainNetwork(blockchainNetwork, token) - val tokenWalletData = walletState.getWalletData(currency) - val tokenPendingTransactions = pendingTransactions.filterByToken(token) - val tokenBalanceStatus = when { - tokenPendingTransactions.isNotEmpty() -> BalanceStatus.TransactionInProgress - pendingTransactions.isNotEmpty() -> BalanceStatus.SameCurrencyTransactionInProgress - else -> BalanceStatus.VerifiedOnline - } - val tokenAmountValue = wallet.getTokenAmount(token)?.value - val tokenFiatAmount = tokenWalletData?.fiatRate?.let { tokenAmountValue?.toFiatValue(it) } - val tokenFiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrency.symbol) - ?: UNKNOWN_AMOUNT_SIGN - - val isTokenSendButtonEnabled = tokenWalletData?.shouldEnableTokenSendButton() == true && - pendingTransactions.isEmpty() - tokenWalletData?.copy( - currencyData = tokenWalletData.currencyData.copy( - status = tokenBalanceStatus, - blockchainAmount = coinAmountValue, - amount = tokenAmountValue, - amountFormatted = tokenAmountValue?.toFormattedCurrencyString( - token.decimals, - token.symbol, - ), - fiatAmount = tokenFiatAmount, - fiatAmountFormatted = tokenFiatAmountFormatted, - ), - pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(), - mainButton = WalletMainButton.SendButton(isTokenSendButtonEnabled), - ) - } - val newWalletsData = tokens + newWalletData - val walletsData = walletState.walletsDataFromStores.replaceSomeWalletsData(newWalletsData) - - return walletState.updateWalletsData(walletsData) - } - - private fun onSingleWalletLoaded(wallet: Wallet, walletState: WalletState): WalletState { - if (wallet.blockchain != walletState.primaryBlockchain) return walletState - - val fiatCurrencyName = store.state.globalState.appCurrency.code - val amount = wallet.amounts[AmountType.Coin]?.value - val formattedAmount = amount?.toFormattedCurrencyString( - wallet.blockchain.decimals(), - wallet.blockchain.currency, - ) - val fiatAmount = walletState.primaryWalletData?.fiatRate?.let { amount?.toFiatValue(it) } - val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrencyName) ?: UNKNOWN_AMOUNT_SIGN - - val pendingTransactions = wallet.getPendingTransactions() - val sendButtonEnabled = amount?.isZero() == false && pendingTransactions.isEmpty() - val balanceStatus = if (pendingTransactions.isNotEmpty()) { - BalanceStatus.TransactionInProgress - } else { - BalanceStatus.VerifiedOnline - } - val walletData = walletState.primaryWalletData?.copy( - currencyData = BalanceWidgetData( - status = balanceStatus, - currency = wallet.blockchain.fullName, - currencySymbol = wallet.blockchain.currency, - blockchainAmount = amount, - amount = amount, - amountFormatted = formattedAmount, - fiatAmount = fiatAmount, - fiatAmountFormatted = fiatAmountFormatted, - ), - pendingTransactions = pendingTransactions.removeUnknownTransactions(), - mainButton = WalletMainButton.SendButton(sendButtonEnabled), - ) - val wallets = listOfNotNull(walletData) - val updatedStore = walletState.getWalletStore(walletData?.currency)?.updateWallets(wallets) - - return walletState.updateWalletStore(updatedStore).copy( - state = ProgressState.Done, - error = null, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TotalBalanceOperations.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TotalBalanceOperations.kt index d5865ab287..ab255c0eb9 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TotalBalanceOperations.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TotalBalanceOperations.kt @@ -13,12 +13,6 @@ fun List.findProgressState(initialState: ProgressState = ProgressSta .reduce(ProgressState::or) } -fun List.calculateTotalFiatAmount(): BigDecimal { - return this - .map { it.currencyData.fiatAmount ?: BigDecimal.ZERO } - .reduce(BigDecimal::plus) -} - fun List.calculateTotalCryptoAmount(): BigDecimal { return this .map { it.currencyData.amount ?: BigDecimal.ZERO } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index d79d7a6339..78e56b7d93 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -1,23 +1,13 @@ package com.tangem.tap.features.wallet.redux.reducers -import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Wallet -import com.tangem.common.extensions.mapNotNullValues import com.tangem.domain.common.CardDTO import com.tangem.domain.common.TapWorkarounds.isTestCard -import com.tangem.domain.common.TwinCardNumber -import com.tangem.tap.common.entities.FiatCurrency -import com.tangem.tap.common.extensions.toFiatRateString -import com.tangem.tap.common.extensions.toFiatValue -import com.tangem.tap.common.extensions.toFormattedCurrencyString -import com.tangem.tap.common.extensions.toFormattedFiatValue import com.tangem.tap.common.redux.AppState import com.tangem.tap.domain.TapError -import com.tangem.tap.domain.extensions.getArtworkUrl import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.models.WalletRent import com.tangem.tap.features.wallet.redux.AddressData import com.tangem.tap.features.wallet.redux.Artwork import com.tangem.tap.features.wallet.redux.ErrorType @@ -25,15 +15,12 @@ import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletAddresses import com.tangem.tap.features.wallet.redux.WalletData -import com.tangem.tap.features.wallet.redux.WalletMainButton import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.WalletStore -import com.tangem.tap.features.wallet.redux.replaceSomeWalletsData import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData import com.tangem.tap.proxy.AppStateHolder import org.rekotlin.Action -import java.math.BigDecimal object WalletReducer { fun reduce(action: Action, state: AppState, appStateHolder: AppStateHolder): WalletState = @@ -43,7 +30,6 @@ object WalletReducer { @Suppress("LongMethod", "ComplexMethod") private fun internalReduce(action: Action, state: AppState, appStateHolder: AppStateHolder): WalletState { val multiWalletReducer = MultiWalletReducer() - val onWalletLoadedReducer = OnWalletLoadedReducer() val appCurrencyReducer = AppCurrencyReducer() if (action !is WalletAction) return state.walletState @@ -53,36 +39,6 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS when (action) { is WalletAction.Warnings -> newState = handleCheckSignedHashesActions(action, newState) is WalletAction.MultiWallet -> newState = multiWalletReducer.reduce(action, newState) - - is WalletAction.ResetState -> { - newState = WalletState( - cardId = action.newCard.cardId, - walletCardsCount = action.newCard.findCardsCount(), - ) - } - is WalletAction.SetIfTestnetCard -> newState = newState.copy(isTestnet = action.isTestnet) - is WalletAction.EmptyWallet -> { - newState = newState.copy( - state = ProgressState.Done, - walletsStores = listOf( - WalletStore( - walletManager = null, - blockchainNetwork = BlockchainNetwork( - Blockchain.Unknown, - null, - emptyList(), - ), - walletsData = listOf( - WalletData( - currencyData = BalanceWidgetData(BalanceStatus.EmptyCard), - mainButton = WalletMainButton.CreateWalletButton(true), - currency = Currency.Blockchain(Blockchain.Unknown, null), - ), - ), - ), - ), - ) - } is WalletAction.LoadData.Failure -> { when (action.error) { is TapError.NoInternetConnection -> { @@ -133,7 +89,6 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS } } } - is WalletAction.LoadData -> { newState = newState.copy( state = ProgressState.Loading, @@ -146,152 +101,6 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS error = null, ) } - is WalletAction.LoadWallet -> { - val balanceStatus = if (newState.state == ProgressState.Refreshing) { - BalanceStatus.Refreshing - } else { - BalanceStatus.Loading - } - if (action.blockchain == null) { - val wallets = newState.walletsStores.map { walletStore -> - walletStore.copy( - walletsData = walletStore.walletsData.map { walletData -> - walletData.copy( - currencyData = walletData.currencyData.copy( - status = - if (walletStore.walletManager != null) balanceStatus else BalanceStatus.Unreachable, - currency = walletData.currencyData.currency, - currencySymbol = walletData.currencyData.currencySymbol, - ), - mainButton = WalletMainButton.SendButton(false), - ) - }, - ) - } - newState = newState.copy( - state = ProgressState.Loading, - walletsStores = wallets, - ) - } else { - val walletManager = newState.getWalletManager(action.blockchain) ?: return newState - val currencies = listOf(Currency.fromBlockchainNetwork(action.blockchain)) + - walletManager.cardTokens.map { - Currency.fromBlockchainNetwork(action.blockchain, it) - } - val newWalletsData = newState.walletsDataFromStores.filter { currencies.contains(it.currency) } - .map { wallet -> - wallet.copy( - currencyData = wallet.currencyData.copy( - status = balanceStatus, - currency = wallet.currencyData.currency, - currencySymbol = wallet.currencyData.currencySymbol, - ), - mainButton = WalletMainButton.SendButton(false), - ) - } - val walletsData = newState.walletsDataFromStores.replaceSomeWalletsData(newWalletsData) - val walletStore = newState.getWalletStore(action.blockchain)?.updateWallets(walletsData) - newState = newState.updateWalletStore(walletStore) - } - } - is WalletAction.LoadWallet.Success -> newState = onWalletLoadedReducer.reduce( - wallet = action.wallet, - blockchainNetwork = action.blockchain, - walletState = newState, - ) - is WalletAction.LoadWallet.NoAccount -> { - val amount = BigDecimal.ZERO - val fiatAmount = BigDecimal.ZERO - val walletData = newState.getWalletData(action.blockchain)?.let { walletData -> - val walletBlockchain = walletData.currency.blockchain - walletData.copy( - currencyData = BalanceWidgetData( - status = BalanceStatus.NoAccount, - currency = action.wallet.blockchain.fullName, - currencySymbol = action.wallet.blockchain.currency, - amount = amount, - amountFormatted = amount.toFormattedCurrencyString( - decimals = walletBlockchain.decimals(), - currency = walletBlockchain.currency, - ), - fiatAmount = fiatAmount, - fiatAmountFormatted = fiatAmount.toFormattedFiatValue( - fiatCurrencyName = state.globalState.appCurrency.symbol, - ), - amountToCreateAccount = action.amountToCreateAccount, - ), - ) - } - val updatedWalletStore = newState.getWalletStore(action.blockchain) - ?.updateWallets(listOfNotNull(walletData)) - - newState = newState.updateWalletStore(updatedWalletStore) - } - - is WalletAction.LoadWallet.Failure -> { - val message = if (newState.error == ErrorType.NoInternetConnection) { - null - } else { - action.errorMessage - } - val walletStore = newState.getWalletStore(action.wallet) - val walletData = walletStore?.walletsData?.first { it.currency is Currency.Blockchain } - val newWalletData = walletData?.copy( - currencyData = walletData.currencyData.copy( - status = BalanceStatus.Unreachable, - errorMessage = message, - ), - ) - val tokenWallets = action.wallet.getTokens() - .mapNotNull { token -> - walletStore?.blockchainNetwork?.let { - newState.getWalletData(Currency.fromBlockchainNetwork(it, token)) - } - } - .map { - it.copy( - currencyData = it.currencyData.copy( - status = BalanceStatus.Unreachable, - errorMessage = message, - ), - ) - } - val updatedWallets = walletStore!!.updateWallets(listOfNotNull(newWalletData) + tokenWallets).walletsData - - newState = newState.updateWalletsData(updatedWallets) - - val progressState = - if (newState.walletsDataFromStores.any { it.currencyData.status == BalanceStatus.Loading }) { - ProgressState.Loading - } else { - ProgressState.Done - } - - newState = newState.copy( - state = progressState, - ) - } - is WalletAction.SetArtworkId -> { - val cardImage = if (newState.cardImage?.artworkId == action.artworkId) { - newState.cardImage - } else { - null - } - newState = newState.copy(cardImage = cardImage) - } - - is WalletAction.LoadFiatRate.Success -> { - newState = setNewFiatRate(action.fiatRates, state.globalState.appCurrency, newState) - } - is WalletAction.LoadArtwork -> { - val artworkUrl = action.card.getArtworkUrl(action.artworkId) - ?: when (state.twinCardsState.cardNumber) { - TwinCardNumber.First -> Artwork.TWIN_CARD_1 - TwinCardNumber.Second -> Artwork.TWIN_CARD_2 - else -> Artwork.DEFAULT_IMG_URL - } - newState = newState.copy(cardImage = Artwork(artworkId = artworkUrl)) - } is WalletAction.TradeCryptoAction -> return newState is WalletAction.ChangeSelectedAddress -> { val walletAddresses = newState.getWalletData(newState.selectedCurrency)?.walletAddresses @@ -308,22 +117,9 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS ), ) } - is WalletAction.SetWalletRent -> { - val walletStore = newState.getWalletStore(action.wallet) ?: return newState - val walletRent = WalletRent(action.minRent, action.rentExempt) - val walletsData = walletStore.walletsData.map { it.copy(walletRent = walletRent) } - newState = newState.updateWalletsData(walletsData) - } - is WalletAction.RemoveWalletRent -> { - val walletStore = newState.getWalletStore(action.wallet) ?: return newState - val walletsData = walletStore.walletsData.map { it.copy(walletRent = null) } - newState = newState.updateWalletsData(walletsData) - } is WalletAction.AppCurrencyAction -> { newState = appCurrencyReducer.reduce(action, newState) } - is WalletAction.UserTokens.Loading -> newState = newState.copy(loadingUserTokens = true) - is WalletAction.UserTokens.Loaded -> newState = newState.copy(loadingUserTokens = false) is WalletAction.UserWalletChanged -> with(action.userWallet) { val card = scanResponse.card newState = WalletState( @@ -395,20 +191,6 @@ private fun CardDTO.findCardsCount(): Int? { return (this.backupStatus as? CardDTO.BackupStatus.Active)?.cardCount?.inc() } -fun createAddressList(wallet: Wallet?, walletAddresses: WalletAddresses? = null): WalletAddresses? { - if (wallet == null) return null - - val listOfAddressData = wallet.createAddressesData() - // restore a selected wallet address - var indexOfSelectedWallet = 0 - walletAddresses?.let { - val index = - listOfAddressData.indexOfFirst { it.address == walletAddresses.selectedAddress.address } - if (index != -1) indexOfSelectedWallet = index - } - return WalletAddresses(listOfAddressData[indexOfSelectedWallet], listOfAddressData) -} - fun Wallet.createAddressesData(): List { val listOfAddressData = mutableListOf() // put a defaultAddress at the first place @@ -440,41 +222,4 @@ private fun handleCheckSignedHashesActions( is WalletAction.Warnings.Set -> state.copy(mainWarningsList = action.warningList) else -> state } -} - -private fun setNewFiatRate( - fiatRates: Map, - appCurrency: FiatCurrency, - state: WalletState, -): WalletState { - val rateFormatter: (BigDecimal) -> String = { rate: BigDecimal -> - rate.toFiatRateString(fiatCurrencyName = appCurrency.symbol) - } - - val newWalletsData = fiatRates.mapNotNullValues { it.value }.mapNotNull { (currency, rate) -> - val walletStore = state.getWalletStore(currency) ?: return@mapNotNull null - val wallet = walletStore.walletManager?.wallet - val walletData = state.getWalletData(currency) ?: return@mapNotNull null - val currencyData = walletData.currencyData - - var fiatAmount = when (currency) { - is Currency.Blockchain -> wallet?.amounts?.get(AmountType.Coin)?.value?.toFiatValue(rate) - is Currency.Token -> wallet?.getTokenAmount(currency.token)?.value?.toFiatValue(rate) - } - if (currencyData.status == BalanceStatus.NoAccount && fiatAmount == null) { - fiatAmount = BigDecimal.ZERO.setScale(2) - } - val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(appCurrency.symbol) - - walletData.copy( - currencyData = currencyData.copy( - fiatAmountFormatted = fiatAmountFormatted, - fiatAmount = fiatAmount, - ), - fiatRate = rate, - fiatRateString = rateFormatter(rate), - ) - } - - return state.updateWalletsData(newWalletsData) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index 3ea64226b5..af465cf7b2 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -20,8 +20,10 @@ import com.badoo.mvicore.DiffStrategy import com.badoo.mvicore.ModelWatcher import com.badoo.mvicore.modelWatcher import com.tangem.common.doOnResult +import com.tangem.common.extensions.guard import com.tangem.core.analytics.Analytics import com.tangem.domain.common.TapWorkarounds.derivationStyle +import com.tangem.domain.common.extensions.withMainContext import com.tangem.feature.swap.domain.SwapInteractor import com.tangem.tangem_sdk_new.extensions.dpToPx import com.tangem.tap.common.SnackbarHandler @@ -61,7 +63,6 @@ import com.tangem.wallet.databinding.FragmentWalletDetailsBinding import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import org.rekotlin.StoreSubscriber import timber.log.Timber import javax.inject.Inject @@ -247,17 +248,16 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), if (currencyData.status != BalanceStatus.Loading && currencyData.status != BalanceStatus.Refreshing) { Analytics.send(Token.Refreshed()) lifecycleScope.launch(Dispatchers.Default) { - val selectedUserWallet = userWalletsListManagerSafe?.selectedUserWalletSync - if (selectedUserWallet != null) { - walletCurrenciesManager.update(selectedUserWallet, currency) - .doOnResult { - withContext(Dispatchers.Main) { - binding.srlWalletDetails.isRefreshing = false - } - } - } else { + val selectedUserWallet = userWalletsListManagerSafe?.selectedUserWalletSync.guard { Timber.e("Unable to refresh wallet details screen, no user wallet selected") + return@launch } + walletCurrenciesManager.update(selectedUserWallet, currency) + .doOnResult { + withMainContext { + binding.srlWalletDetails.isRefreshing = false + } + } } } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt index e73d4ab074..a379f290a8 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt @@ -3,7 +3,6 @@ package com.tangem.tap.features.wallet.ui.wallet.saltPay import android.view.LayoutInflater import android.view.ViewGroup import com.tangem.core.analytics.Analytics -import com.tangem.domain.common.extensions.debounce import com.tangem.domain.common.extensions.withMainContext import com.tangem.tap.common.ShimmerData import com.tangem.tap.common.ShimmerRecyclerAdapter @@ -21,7 +20,6 @@ import com.tangem.tap.features.wallet.ui.wallet.WalletView import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.HistoryItemData import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.HistoryTransactionData import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.TxHistoryAdapter -import com.tangem.tap.mainScope import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager import com.tangem.tap.scope import com.tangem.tap.store @@ -31,7 +29,6 @@ import com.tangem.wallet.databinding.LayoutSaltPayBalanceBinding import com.tangem.wallet.databinding.LayoutSaltPayTxHistoryBinding import com.tangem.wallet.databinding.LayoutSaltPayWalletBinding import kotlinx.coroutines.launch -import org.rekotlin.Action import timber.log.Timber /** @@ -41,8 +38,6 @@ class SaltPayWalletView : WalletView() { private var saltPayBinding: LayoutSaltPayWalletBinding? = null - private val actionDebouncer = debounce(500, mainScope) { store.dispatch(it) } - private val balanceWidget: LayoutSaltPayBalanceBinding? get() = saltPayBinding?.lSaltPayBalance @@ -131,7 +126,6 @@ class SaltPayWalletView : WalletView() { if (tokenData.currencyData.fiatAmount == null) { veilBalance.veil() - actionDebouncer(WalletAction.LoadFiatRate()) } else { veilBalance.unVeil() tvBalance.text = tokenData.currencyData.fiatAmount.formatAmountAsSpannedString( 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 fac9f927b3..c0c0c1ac91 100644 --- a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt @@ -4,6 +4,7 @@ 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.extensions.guard import com.tangem.domain.common.extensions.fromNetworkId import com.tangem.domain.common.extensions.toCoinId import com.tangem.domain.common.extensions.toNetworkId @@ -102,15 +103,14 @@ class UserWalletManagerImpl( val blockchain = requireNotNull(Blockchain.fromNetworkId(currency.networkId)) { "blockchain not found" } val blockchainNetwork = BlockchainNetwork(blockchain, card) - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync - if (selectedUserWallet != null) { - walletCurrenciesManager.addCurrencies( - userWallet = selectedUserWallet, - currenciesToAdd = listOf(currency.toWalletCurrency(blockchainNetwork)), - ) - } else { - Timber.e("Unable to add token, selected user wallet is null") + 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)), + ) } override fun getWalletAddress(networkId: String): String {