From c28d80cb18ffa4ecb07f3847b458b0cf6d14647a Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 21 Nov 2023 00:32:09 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/tap/common/entities/Button.kt | 1 - .../tap/common/entities/ProgressState.kt | 5 + .../tap/common/extensions/Navigation.kt | 28 +- .../com/tangem/tap/common/extensions/Store.kt | 8 +- .../tap/common/extensions/WalletManager.kt | 22 +- .../com/tangem/tap/common/redux/AppReducer.kt | 2 - .../com/tangem/tap/common/redux/AppState.kt | 4 - .../common/redux/FeatureRepositoryProvider.kt | 4 - .../common/redux/global/GlobalMiddleware.kt | 5 - .../IndeterminateProgressButtonWidget.kt | 2 +- .../toggleWidget/RefreshBalanceWidget.kt | 15 +- .../com/tangem/tap/domain/TapWalletManager.kt | 125 +---- .../model/builders/WalletStoreBuilder.kt | 2 +- .../statePrinter/WalletStateConverter.kt | 68 --- .../viewmodels/AddCustomTokenViewModel.kt | 48 -- .../tangem/tap/features/demo/DemoHelper.kt | 2 - .../demo/DemoOnboardingNoteMiddleware.kt | 2 +- .../details/redux/DetailsMiddleware.kt | 4 - .../walletconnect/WalletConnectMiddleware.kt | 104 ++-- .../ui/appsettings/AppSettingsViewModel.kt | 9 +- .../cardsettings/CardSettingsScreenState.kt | 2 - .../ui/cardsettings/CardSettingsViewModel.kt | 11 +- .../details/ui/details/DetailsViewModel.kt | 14 +- .../disclaimer/redux/DisclaimerAction.kt | 2 +- .../disclaimer/redux/DisclaimerState.kt | 2 +- .../disclaimer/ui/DisclaimerFragment.kt | 2 +- .../disclaimer/ui/DisclaimerWebViewClient.kt | 8 +- .../tap/features/home/redux/HomeState.kt | 2 +- .../handlers/BuyCurrencyIntentHandler.kt | 29 +- .../AddressInfoBottomSheetDialog.kt | 74 --- .../features/onboarding/OnboardingManager.kt | 6 +- .../note/redux/OnboardingNoteMiddleware.kt | 2 +- .../twins/redux/TwinCardsMiddleware.kt | 2 +- .../saveWallet/redux/SaveWalletMiddleware.kt | 9 - .../send/redux/reducers/FeeReducer.kt | 2 +- .../send/redux/reducers/ReceiptReducer.kt | 29 +- .../features/send/redux/states/FeeState.kt | 2 +- .../tap/features/send/ui/SendFragment.kt | 2 +- .../ui/adapters/WarningMessagesAdapter.kt | 11 +- .../stateSubscribers/SendStateSubscriber.kt | 15 +- .../viewmodels/TokensListMigration.kt | 46 -- .../wallet/data/WalletRepositoryImpl.kt | 24 - .../wallet/domain/WalletRepository.kt | 10 - .../features/wallet/models/WalletWarning.kt | 23 - .../tap/features/wallet/redux/WalletAction.kt | 143 ----- .../tap/features/wallet/redux/WalletState.kt | 118 ---- .../middlewares/AppCurrencyMiddleware.kt | 157 ------ .../middlewares/MultiWalletMiddleware.kt | 124 ----- .../middlewares/TradeCryptoMiddleware.kt | 368 ------------- .../middlewares/WalletDialogsMiddleware.kt | 56 -- .../redux/middlewares/WalletMiddleware.kt | 412 -------------- .../redux/middlewares/WarningsMiddleware.kt | 184 ------- .../wallet/redux/models/WalletDialog.kt | 42 -- .../redux/reducers/AppCurrencyReducer.kt | 14 - .../redux/reducers/MultiWalletReducer.kt | 31 -- .../wallet/redux/reducers/WalletReducer.kt | 172 ------ .../features/wallet/redux/utils/Constants.kt | 5 - .../tap/features/wallet/ui/BalanceWidget.kt | 123 ----- .../wallet/ui/MultipleAddressUiHelper.kt | 42 -- .../wallet/ui/WalletDetailsFragment.kt | 509 ------------------ .../tap/features/wallet/ui/WalletFragment.kt | 326 ----------- .../tap/features/wallet/ui/WalletViewModel.kt | 132 ----- .../wallet/ui/WalletWarningConverter.kt | 53 -- .../ui/adapters/PendingTransactionsAdapter.kt | 74 --- .../wallet/ui/adapters/WalletAdapter.kt | 110 ---- .../WalletDetailWarningMessagesAdapter.kt | 52 -- .../analytics/WalletAnalyticsEventsMapper.kt | 22 - .../dialogs/AmountToSendBottomSheetDialog.kt | 88 --- .../ChooseTradeActionBottomSheetDialog.kt | 56 -- ...sianCardholdersWarningBottomSheetDialog.kt | 57 -- .../wallet/ui/dialogs/ScanFailsDialog.kt | 30 -- .../ui/dialogs/SignedHashesWarningDialog.kt | 31 -- .../wallet/ui/dialogs/SimpleOkDialog.kt | 75 --- .../wallet/ui/images/CurrencyIconRequest.kt | 172 ------ .../wallet/ui/images/CurrencyIconView.kt | 74 --- .../tap/features/wallet/ui/test/TestWallet.kt | 160 ------ .../wallet/ui/utils/WalletDataOperations.kt | 164 ------ .../wallet/ui/view/TotalBalanceCard.kt | 355 ------------ .../wallet/ui/view/WalletDetailsButtonsRow.kt | 77 --- .../ui/wallet/CurrencySelectionDialog.kt | 37 -- .../wallet/ui/wallet/MultiWalletView.kt | 191 ------- .../wallet/ui/wallet/SingleWalletView.kt | 235 -------- .../features/wallet/ui/wallet/WalletView.kt | 36 -- .../walletSelector/ui/model/UserWalletItem.kt | 4 +- .../CryptoCurrencyConverter.kt | 2 +- .../exchangeServices/DefaultRampManager.kt | 1 - .../com/tangem/tap/proxy/AppStateHolder.kt | 2 - .../tap/proxy/TransactionManagerImpl.kt | 25 +- .../tangem/tap/proxy/UserWalletManagerImpl.kt | 33 +- .../com/tangem/tap/proxy/di/ProxyModule.kt | 5 - .../tangem/lib/crypto/UserWalletManager.kt | 2 - 91 files changed, 178 insertions(+), 5792 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/entities/ProgressState.kt delete mode 100644 app/src/main/java/com/tangem/tap/domain/statePrinter/WalletStateConverter.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt rename app/src/main/java/com/tangem/tap/features/{wallet => send}/ui/adapters/WarningMessagesAdapter.kt (93%) delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/data/WalletRepositoryImpl.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/domain/WalletRepository.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/AppCurrencyReducer.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/redux/utils/Constants.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/MultipleAddressUiHelper.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/WalletViewModel.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletDetailWarningMessagesAdapter.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/analytics/WalletAnalyticsEventsMapper.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/AmountToSendBottomSheetDialog.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ChooseTradeActionBottomSheetDialog.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SignedHashesWarningDialog.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SimpleOkDialog.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconRequest.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWallet.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/WalletView.kt rename app/src/main/java/com/tangem/tap/{features/wallet/converters => network/exchangeServices}/CryptoCurrencyConverter.kt (98%) diff --git a/app/src/main/java/com/tangem/tap/common/entities/Button.kt b/app/src/main/java/com/tangem/tap/common/entities/Button.kt index b873b7ef3e..b0aca7f994 100644 --- a/app/src/main/java/com/tangem/tap/common/entities/Button.kt +++ b/app/src/main/java/com/tangem/tap/common/entities/Button.kt @@ -1,7 +1,6 @@ package com.tangem.tap.common.entities import com.tangem.tap.features.send.redux.states.ButtonState -import com.tangem.tap.features.wallet.redux.ProgressState open class Button(val enabled: Boolean) diff --git a/app/src/main/java/com/tangem/tap/common/entities/ProgressState.kt b/app/src/main/java/com/tangem/tap/common/entities/ProgressState.kt new file mode 100644 index 0000000000..61adc5cd45 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/entities/ProgressState.kt @@ -0,0 +1,5 @@ +package com.tangem.tap.common.entities + +import com.tangem.tap.common.toggleWidget.WidgetState + +enum class ProgressState : WidgetState { Loading, Done, Error } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt index 51ac9818c4..e95ba41f1f 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt @@ -27,8 +27,6 @@ import com.tangem.tap.features.saveWallet.ui.SaveWalletBottomSheetFragment import com.tangem.tap.features.send.ui.SendFragment import com.tangem.tap.features.shop.ui.ShopFragment import com.tangem.tap.features.tokens.impl.presentation.TokensListFragment -import com.tangem.tap.features.wallet.ui.WalletDetailsFragment -import com.tangem.tap.features.wallet.ui.WalletFragment import com.tangem.tap.features.walletSelector.ui.WalletSelectorBottomSheetFragment import com.tangem.tap.features.welcome.ui.WelcomeFragment import com.tangem.tap.proxy.redux.DaggerGraphState @@ -132,16 +130,9 @@ private fun fragmentFactory(screen: AppScreen): Fragment { AppScreen.OnboardingTwins -> TwinsCardsFragment() AppScreen.OnboardingOther -> OnboardingOtherCardsFragment() AppScreen.Wallet -> { - val featureToggles = store.state.daggerGraphState.get( - getDependency = DaggerGraphState::walletFeatureToggles, - ) - if (featureToggles.isRedesignedScreenEnabled) { - store.state.daggerGraphState - .get(getDependency = DaggerGraphState::walletRouter) - .getEntryFragment() - } else { - WalletFragment() - } + store.state.daggerGraphState + .get(getDependency = DaggerGraphState::walletRouter) + .getEntryFragment() } AppScreen.Send -> { val featureToggles = store.state.daggerGraphState.get( @@ -176,16 +167,9 @@ private fun fragmentFactory(screen: AppScreen): Fragment { } AppScreen.AddCustomToken -> AddCustomTokenFragment() AppScreen.WalletDetails -> { - val featureToggles = store.state.daggerGraphState.get( - getDependency = DaggerGraphState::walletFeatureToggles, - ) - if (featureToggles.isRedesignedScreenEnabled) { - store.state.daggerGraphState - .get(getDependency = DaggerGraphState::tokenDetailsRouter) - .getEntryFragment() - } else { - WalletDetailsFragment() - } + store.state.daggerGraphState + .get(getDependency = DaggerGraphState::tokenDetailsRouter) + .getEntryFragment() } AppScreen.WalletConnectSessions -> WalletConnectFragment() AppScreen.QrScan -> QrScanFragment() 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 bcd2445a5f..61b0ee796b 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 @@ -42,12 +42,8 @@ fun Store<*>.dispatchNotification(resId: Int) { dispatchOnMain(GlobalAction.ShowNotification(resId)) } -suspend fun Store.onUserWalletSelected( - userWallet: UserWallet, - refresh: Boolean = false, - sendAnalyticsEvent: Boolean = false, -) { - state.globalState.tapWalletManager.onWalletSelected(userWallet, refresh, sendAnalyticsEvent) +suspend fun Store.onUserWalletSelected(userWallet: UserWallet, sendAnalyticsEvent: Boolean = false) { + state.globalState.tapWalletManager.onWalletSelected(userWallet, sendAnalyticsEvent) } fun Store<*>.dispatchToastNotification(resId: Int) { diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt index 0427435795..ebf3739714 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt @@ -3,6 +3,7 @@ package com.tangem.tap.common.extensions import com.tangem.blockchain.common.BlockchainSdkError import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.WalletManager +import com.tangem.blockchain.common.address.AddressType import com.tangem.common.services.Result import com.tangem.domain.common.extensions.amountToCreateAccount import com.tangem.tap.common.TestActions @@ -10,8 +11,6 @@ import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder import com.tangem.tap.domain.TapError import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.features.demo.isDemoCard -import com.tangem.tap.features.wallet.redux.reducers.createAddressesData import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.store @@ -78,4 +77,23 @@ fun WalletManager?.getAddressData(): WalletDataModel.AddressData? { val addressDataList = wallet.createAddressesData() return if (addressDataList.isEmpty()) null else addressDataList[0] +} + +fun Wallet.createAddressesData(): List { + val listOfAddressData = mutableListOf() + // put a defaultAddress at the first place + addresses.forEach { + val addressData = WalletDataModel.AddressData( + it.value, + it.type, + getShareUri(it.value), + getExploreUrl(it.value), + ) + if (it.type == AddressType.Default) { + listOfAddressData.add(0, addressData) + } else { + listOfAddressData.add(addressData) + } + } + return listOfAddressData } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt index 8175888c08..1af312eb52 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt @@ -15,7 +15,6 @@ import com.tangem.tap.features.send.redux.reducers.SendScreenReducer import com.tangem.tap.features.shop.redux.ShopReducer import com.tangem.tap.features.signin.redux.SignInReducer import com.tangem.tap.features.tokens.legacy.redux.TokensReducer -import com.tangem.tap.features.wallet.redux.reducers.WalletReducer import com.tangem.tap.features.walletSelector.redux.WalletSelectorReducer import com.tangem.tap.features.welcome.redux.WelcomeReducer import com.tangem.tap.proxy.AppStateHolder @@ -33,7 +32,6 @@ fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder) onboardingNoteState = OnboardingNoteReducer.reduce(action, state), onboardingWalletState = OnboardingWalletReducer.reduce(action, state), onboardingOtherCardsState = OnboardingOtherCardsReducer.reduce(action, state), - walletState = WalletReducer.reduce(action, state, appStateHolder), twinCardsState = TwinCardsReducer.reduce(action, state), sendState = SendScreenReducer.reduce(action, state.sendState), detailsState = DetailsReducer.reduce(action, state), diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt index 7b9b9f2bd4..a152d1c585 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt @@ -35,8 +35,6 @@ import com.tangem.tap.features.signin.redux.SignInMiddleware import com.tangem.tap.features.signin.redux.SignInState import com.tangem.tap.features.tokens.legacy.redux.TokensMiddleware import com.tangem.tap.features.tokens.legacy.redux.TokensState -import com.tangem.tap.features.wallet.redux.WalletState -import com.tangem.tap.features.wallet.redux.middlewares.WalletMiddleware import com.tangem.tap.features.walletSelector.redux.WalletSelectorMiddleware import com.tangem.tap.features.walletSelector.redux.WalletSelectorState import com.tangem.tap.features.welcome.redux.WelcomeMiddleware @@ -54,7 +52,6 @@ data class AppState( val onboardingNoteState: OnboardingNoteState = OnboardingNoteState(), val onboardingWalletState: OnboardingWalletState = OnboardingWalletState(), val onboardingOtherCardsState: OnboardingOtherCardsState = OnboardingOtherCardsState(), - val walletState: WalletState = WalletState(), val twinCardsState: TwinCardsState = TwinCardsState(), val sendState: SendState = SendState(), val detailsState: DetailsState = DetailsState(), @@ -92,7 +89,6 @@ data class AppState( OnboardingNoteMiddleware.handler, OnboardingWalletMiddleware.handler, OnboardingOtherCardsMiddleware.handler, - WalletMiddleware().walletMiddleware, TwinCardsMiddleware.handler, SendMiddleware().sendMiddleware, DetailsMiddleware().detailsMiddleware, diff --git a/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt b/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt index 5794edffb9..55e4c0b653 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt @@ -3,13 +3,9 @@ package com.tangem.tap.common.redux import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.tap.features.home.data.HomeRepositoryImpl import com.tangem.tap.features.home.domain.HomeRepository -import com.tangem.tap.features.wallet.data.WalletRepositoryImpl -import com.tangem.tap.features.wallet.domain.WalletRepository import com.tangem.utils.coroutines.CoroutineDispatcherProvider class FeatureRepositoryProvider(tangemTechApi: TangemTechApi, dispatchers: CoroutineDispatcherProvider) { - val walletRepository: WalletRepository = WalletRepositoryImpl(tangemTechApi, dispatchers) - val homeRepository: HomeRepository = HomeRepositoryImpl(tangemTechApi, dispatchers) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt index d20875298c..49d7841274 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt @@ -18,7 +18,6 @@ import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchWithMain import com.tangem.tap.common.redux.AppState import com.tangem.tap.features.send.redux.SendAction -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.network.exchangeServices.BuyExchangeService import com.tangem.tap.network.exchangeServices.CardExchangeRules import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager @@ -87,7 +86,6 @@ private fun handleAction(action: Action, appState: () -> AppState?) { // store.dispatch(WalletAction.Warnings.CheckHashesCount.SaveCardId) // } - store.dispatch(WalletAction.Warnings.Update) store.dispatch(SendAction.Warnings.Update) } } @@ -115,9 +113,6 @@ private fun handleAction(action: Action, appState: () -> AppState?) { } feedbackManager.openChat(chatConfig, action.feedbackData) } - is GlobalAction.UpdateWalletSignedHashes -> { - store.dispatch(WalletAction.Warnings.CheckRemainingSignatures(action.remainingSignatures)) - } is GlobalAction.UpdateFeedbackInfo -> { store.state.globalState.feedbackManager?.infoHolder ?.setWalletsInfo(action.walletManagers) diff --git a/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt b/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt index 56f80d5d78..22817c3f93 100644 --- a/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt +++ b/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt @@ -3,9 +3,9 @@ package com.tangem.tap.common.toggleWidget import android.graphics.drawable.Drawable import android.view.View import com.google.android.material.button.MaterialButton +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.show -import com.tangem.tap.features.wallet.redux.ProgressState /** [REDACTED_AUTHOR] diff --git a/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt b/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt index 6a5bd17f60..3996e28d5c 100644 --- a/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt +++ b/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt @@ -2,25 +2,16 @@ package com.tangem.tap.common.toggleWidget import android.view.View import android.view.ViewGroup -import android.view.animation.AccelerateInterpolator -import android.view.animation.AlphaAnimation -import android.view.animation.Animation -import android.view.animation.AnimationSet -import android.view.animation.AnticipateOvershootInterpolator -import android.view.animation.LinearInterpolator -import android.view.animation.RotateAnimation -import android.view.animation.ScaleAnimation +import android.view.animation.* import android.widget.ViewSwitcher -import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.common.entities.ProgressState import com.tangem.wallet.R /** [REDACTED_AUTHOR] */ @Suppress("MagicNumber") -class RefreshBalanceWidget( - private val root: ViewGroup, -) : ViewStateWidget { +class RefreshBalanceWidget(root: ViewGroup) : ViewStateWidget { var isShowing: Boolean? = null private set 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 9edc4ee417..6318028eed 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -4,39 +4,27 @@ import com.tangem.blockchain.common.BlockchainSdkConfig import com.tangem.blockchain.common.Token import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.WalletManagerFactory -import com.tangem.common.doOnFailure -import com.tangem.common.doOnSuccess import com.tangem.core.analytics.Analytics import com.tangem.datasource.config.ConfigManager -import com.tangem.domain.common.extensions.toNetworkId import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.wallets.models.UserWallet import com.tangem.operations.attestation.Attestation -import com.tangem.tap.* import com.tangem.tap.common.analytics.events.Basic -import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.common.extensions.dispatchWithMain import com.tangem.tap.common.extensions.setContext -import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.walletStores.WalletStoresError -import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor -import com.tangem.tap.domain.walletconnect2.domain.models.Account 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.redux.WalletAction -import com.tangem.tap.proxy.redux.DaggerGraphState +import com.tangem.tap.store +import com.tangem.tap.tangemSdkManager import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.launch -import org.rekotlin.Store -import timber.log.Timber class TapWalletManager( private val dispatchers: CoroutineDispatcherProvider = AppCoroutineDispatcherProvider(), @@ -55,15 +43,15 @@ class TapWalletManager( val walletManagerFactory: WalletManagerFactory by lazy { WalletManagerFactory(blockchainSdkConfig) } - suspend fun onWalletSelected(userWallet: UserWallet, refresh: Boolean, sendAnalyticsEvent: Boolean) { + suspend fun onWalletSelected(userWallet: UserWallet, sendAnalyticsEvent: Boolean) { // If a previous job was running, it gets cancelled before the new one starts, // ensuring that only one job is active at any given time. loadUserWalletDataJob = CoroutineScope(dispatchers.io) - .launch { loadUserWalletData(userWallet, refresh, sendAnalyticsEvent) } + .launch { loadUserWalletData(userWallet, sendAnalyticsEvent) } .also { it.join() } } - private suspend fun loadUserWalletData(userWallet: UserWallet, refresh: Boolean, sendAnalyticsEvent: Boolean) { + private suspend fun loadUserWalletData(userWallet: UserWallet, sendAnalyticsEvent: Boolean) { Analytics.setContext(userWallet.scanResponse) if (sendAnalyticsEvent) { Analytics.send(Basic.WalletOpened()) @@ -78,114 +66,11 @@ class TapWalletManager( withMainContext { // Order is important store.dispatch(DisclaimerAction.SetDisclaimer(card.createDisclaimer())) - store.dispatchWalletAction(action = WalletAction.UserWalletChanged(userWallet)) - store.dispatchWalletAction( - action = WalletAction.UpdateCanSaveUserWallets( - canSaveUserWallets = store.state.daggerGraphState.get(DaggerGraphState::walletsRepository) - .shouldSaveUserWalletsSync(), - ), - ) store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse)) store.dispatch(WalletConnectAction.ResetState) store.dispatch(GlobalAction.SaveScanResponse(scanResponse)) store.dispatch(WalletConnectAction.RestoreSessions(scanResponse)) store.dispatch(GlobalAction.SetIfCardVerifiedOnline(!attestationFailed)) - store.dispatchWalletAction(action = WalletAction.Warnings.CheckIfNeeded) - } - - val walletFeatureToggles = store.state.daggerGraphState.get(DaggerGraphState::walletFeatureToggles) - if (!walletFeatureToggles.isRedesignedScreenEnabled) { - setupWalletConnectV2(userWallet) - loadData(userWallet = userWallet, refresh = refresh) - } - } - - private fun Store.dispatchWalletAction(action: WalletAction) { - val walletFeatureToggles = state.daggerGraphState.get(DaggerGraphState::walletFeatureToggles) - - if (!walletFeatureToggles.isRedesignedScreenEnabled) { - dispatch(action = action) - } - } - - private fun setupWalletConnectV2(userWallet: UserWallet) { - val cardId = if (userWallet.scanResponse.card.backupStatus?.isActive != true) { - userWallet.cardId - } else { // if wallet has backup, any card from wallet can be used to sign - null - } - scope.launch { - val wcInteractor = store.state.daggerGraphState.walletConnectInteractor ?: return@launch - wcInteractor.startListening( - userWalletId = userWallet.walletId.stringValue, - cardId = cardId, - ) - } - } - - suspend fun loadData(userWallet: UserWallet, refresh: Boolean = false) { - walletStoresManager.fetch(userWallet, refresh) - .doOnSuccess { - Timber.d("Wallet stores fetched for ${userWallet.walletId}") - store.dispatchOnMain(WalletAction.LoadData.Success) - store.state.globalState.topUpController?.loadDataSuccess() - store.dispatchWithMain(WalletAction.Warnings.CheckHashesCount.VerifyOnlineIfNeeded) - - val wcInteractor = store.state.daggerGraphState.walletConnectInteractor - wcInteractor?.setUserChains(getAccountsForWc(wcInteractor)) - } - .doOnFailure { error -> - val errorAction = when (error) { - is WalletStoresError -> when (error) { - is WalletStoresError.FetchFiatRatesError -> WalletAction.LoadData.Failure(error = null) - is WalletStoresError.UpdateWalletManagerTokensError -> WalletAction.LoadData.Failure( - error = TapError.WalletManager.InternalError( - message = error.cause.localizedMessage ?: error.customMessage, - ), - ) - is WalletStoresError.WalletManagerNotCreated -> WalletAction.LoadData.Failure( - error = TapError.WalletManager.CreationError, - ) - is WalletStoresError.UnknownBlockchain -> WalletAction.LoadData.Failure( - error = TapError.UnknownBlockchain, - ) - is WalletStoresError.NoInternetConnection -> WalletAction.LoadData.Failure( - error = TapError.NoInternetConnection, - ) - } - else -> WalletAction.LoadData.Failure(error = null) - } - - Timber.e(error, "Wallet stores fetching failed for ${userWallet.walletId}") - - store.dispatchOnMain(errorAction) - } - } - - private suspend fun getAccountsForWc(wcInteractor: WalletConnectInteractor): List { - val walletManagerToggles = store.state.daggerGraphState - .get(DaggerGraphState::walletFeatureToggles) - val walletManagers = if (walletManagerToggles.isRedesignedScreenEnabled) { - val walletManagerFacade = store.state.daggerGraphState - .get(DaggerGraphState::walletManagersFacade) - val userWallet = userWalletsListManager.selectedUserWalletSync ?: return emptyList() - walletManagerFacade.getStoredWalletManagers(userWallet.walletId) - } else { - store.state.walletState.walletManagers - } - - return walletManagers.mapNotNull { - val wallet = it.wallet - val chainId = wcInteractor.blockchainHelper.networkIdToChainIdOrNull( - wallet.blockchain.toNetworkId(), - ) - chainId?.let { - Account( - chainId, - wallet.address, - wallet.publicKey.derivationPath?.rawPath, - ) - } } } diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt index 7bd2f77fe1..9dfe9c24a9 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/builders/WalletStoreBuilder.kt @@ -11,10 +11,10 @@ import com.tangem.domain.common.BlockchainNetwork import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.wallets.models.UserWallet +import com.tangem.tap.common.extensions.createAddressesData import com.tangem.tap.domain.model.WalletDataModel import com.tangem.tap.domain.model.WalletStoreModel import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.redux.reducers.createAddressesData import java.math.BigDecimal interface WalletStoreBuilder { diff --git a/app/src/main/java/com/tangem/tap/domain/statePrinter/WalletStateConverter.kt b/app/src/main/java/com/tangem/tap/domain/statePrinter/WalletStateConverter.kt deleted file mode 100644 index 57762aaf51..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/statePrinter/WalletStateConverter.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.tangem.tap.domain.statePrinter - -import com.tangem.blockchain.common.Wallet -import com.tangem.common.json.MoshiJsonConverter -import com.tangem.domain.redux.state.StringStateConverter -import com.tangem.tap.common.redux.AppState -import com.tangem.tap.store -import timber.log.Timber - -/** -[REDACTED_AUTHOR] - */ -class WalletStateConverter : StringStateConverter { - private val converter = MoshiJsonConverter.INSTANCE - - override fun convert(stateHolder: AppState): String { - val walletState = stateHolder.walletState - - val walletManagers = mutableListOf>() - walletState.walletManagers.forEach { - val wallet = it.wallet - - val walletManagerMap = mutableMapOf() - walletManagerMap["walletManager"] = mapOf( - "wallet" to convertWallet(it.wallet), - ) - - walletManagers.add(walletManagerMap) - } - val json = converter.prettyPrint(walletManagers) - return json - } - - private fun convertWallet(wallet: Wallet): MutableMap { - val walletMap = mutableMapOf() - val amounts = mutableMapOf() - wallet.amounts.forEach { (type, amount) -> - val amountMap = mapOf( - "value" to amount.value?.toPlainString(), - "currencySymbol" to amount.currencySymbol, - "decimals" to amount.decimals, - "type" to amount.type::class.java.simpleName, - ) - amounts[type::class.java.simpleName] = amountMap - } - - val publicKeyMap = mapOf( - "seedKey" to wallet.publicKey.seedKey, - "derivedKey" to wallet.publicKey.derivedKey, - "derivationPath" to wallet.publicKey.derivationPath?.rawPath, - "blockchainKey" to wallet.publicKey.blockchainKey, - ) - - walletMap["address"] = wallet.address - walletMap["blockchain"] = wallet.blockchain.name - walletMap["curve"] = wallet.blockchain.getSupportedCurves()[0].curve - walletMap["publicKey"] = publicKeyMap - walletMap["amounts"] = amounts - walletMap["addresses"] = wallet.addresses.toString() - - return walletMap - } -} - -fun printWalletState() { - val stringState = WalletStateConverter().convert(store.state) - Timber.d(stringState) -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt index 484026d744..f7b4c3e9b0 100644 --- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt @@ -26,7 +26,6 @@ import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles -import com.tangem.tap.domain.model.WalletDataModel import com.tangem.tap.features.customtoken.impl.domain.CustomTokenInteractor import com.tangem.tap.features.customtoken.impl.domain.models.FoundToken import com.tangem.tap.features.customtoken.impl.presentation.models.* @@ -38,8 +37,6 @@ import com.tangem.tap.features.customtoken.impl.presentation.states.AddCustomTok import com.tangem.tap.features.customtoken.impl.presentation.validators.ContactAddressValidator import com.tangem.tap.features.customtoken.impl.presentation.validators.ContractAddressValidatorResult import com.tangem.tap.features.details.ui.cardsettings.TextReference -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.store import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider import com.tangem.utils.coroutines.runCatching import com.tangem.wallet.BuildConfig @@ -591,14 +588,6 @@ internal class AddCustomTokenViewModel @Inject constructor( } private fun isTokenAlreadyAdded(): Boolean { - return if (walletFeatureToggles.isRedesignedScreenEnabled) { - isTokenAlreadyAddedNew() - } else { - isTokenAlreadyAddedOld() - } - } - - private fun isTokenAlreadyAddedNew(): Boolean { return currentCryptoCurrencies .filterIsInstance() .any { token -> @@ -621,32 +610,7 @@ internal class AddCustomTokenViewModel @Inject constructor( } } - private fun isTokenAlreadyAddedOld(): Boolean { - return store.state.walletState.walletsStores - .map { walletStore -> walletStore.walletsData.map(WalletDataModel::currency) } - .flatten() - .filterIsInstance() - .any { wrappedCurrency -> - val contractAddress = uiState.form.contractAddressInputField.value - val networkSelectorValue = uiState.form.networkSelectorField.selectedItem.blockchain - val sameId = foundToken?.id == wrappedCurrency.token.id - val sameAddress = contractAddress == wrappedCurrency.token.contractAddress - val sameBlockchain = - Blockchain.fromNetworkId(networkSelectorValue.toNetworkId()) == wrappedCurrency.blockchain - val isSameDerivationPath = getDerivationPath().isSameDerivationPath(wrappedCurrency.derivationPath) - sameId && sameAddress && sameBlockchain && isSameDerivationPath - } - } - private fun isBlockchainAlreadyAdded(): Boolean { - return if (walletFeatureToggles.isRedesignedScreenEnabled) { - isBlockchainAlreadyAddedNew() - } else { - isBlockchainAlreadyAddedOld() - } - } - - private fun isBlockchainAlreadyAddedNew(): Boolean { return currentCryptoCurrencies .filterIsInstance() .any { coin -> @@ -655,18 +619,6 @@ internal class AddCustomTokenViewModel @Inject constructor( } } - private fun isBlockchainAlreadyAddedOld(): Boolean { - return store.state.walletState.walletsStores - .map { walletStore -> walletStore.walletsData.map(WalletDataModel::currency) } - .flatten() - .filterIsInstance() - .any { - val networkSelectorValue = uiState.form.networkSelectorField.selectedItem.blockchain - networkSelectorValue == it.blockchain && - getDerivationPath().isSameDerivationPath(it.derivationPath) - } - } - private fun DerivationPath?.isSameDerivationPath(rawDerivationPath: String?): Boolean { return this == rawDerivationPath?.let { DerivationPath(it) } } diff --git a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt index 1de357e9df..d784133e08 100644 --- a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt @@ -8,7 +8,6 @@ import com.tangem.tap.common.redux.AppState import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.store import com.tangem.wallet.R import org.rekotlin.Action @@ -25,7 +24,6 @@ object DemoHelper { TradeCryptoAction.Buy::class.java, TradeCryptoAction.Sell::class.java, BackupAction.StartBackup::class.java, - WalletAction.ExploreAddress::class.java, DetailsAction.ResetToFactory.Start::class.java, ) diff --git a/app/src/main/java/com/tangem/tap/features/demo/DemoOnboardingNoteMiddleware.kt b/app/src/main/java/com/tangem/tap/features/demo/DemoOnboardingNoteMiddleware.kt index ae1cf2fa2a..3dad92d4fc 100644 --- a/app/src/main/java/com/tangem/tap/features/demo/DemoOnboardingNoteMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/demo/DemoOnboardingNoteMiddleware.kt @@ -5,9 +5,9 @@ import com.tangem.domain.common.extensions.makePrimaryWalletManager import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.demo.DemoConfig import com.tangem.domain.models.scan.ScanResponse +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteAction import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.scope import com.tangem.tap.store import kotlinx.coroutines.launch 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 4504a0bb43..dd3a911708 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 @@ -36,7 +36,6 @@ import com.tangem.tap.domain.userWalletList.di.provideRuntimeImplementation import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletMode import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.walletSelector.redux.WalletSelectorAction import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.utils.coroutines.JobHolder @@ -381,8 +380,6 @@ class DetailsMiddleware { preferencesStorage.shouldShowSaveUserWalletScreen = false store.state.daggerGraphState.get(DaggerGraphState::walletsRepository) .saveShouldSaveUserWallets(item = true) - - store.dispatchWithMain(WalletAction.UpdateCanSaveUserWallets(canSaveUserWallets = true)) } .doOnFailure { error -> Timber.e(error, "Unable to save user wallet") @@ -399,7 +396,6 @@ class DetailsMiddleware { store.state.daggerGraphState.get(DaggerGraphState::walletsRepository) .saveShouldSaveUserWallets(item = false) - store.dispatchWithMain(WalletAction.UpdateCanSaveUserWallets(canSaveUserWallets = true)) store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Home)) } .doOnFailure { error -> diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt index 3044d21544..24c41042ba 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt @@ -6,15 +6,16 @@ import com.tangem.blockchain.common.derivation.DerivationStyle import com.tangem.common.extensions.guard import com.tangem.core.navigation.AppScreen import com.tangem.core.navigation.NavigationAction -import com.tangem.domain.common.BlockchainNetwork -import com.tangem.domain.common.DerivationStyleProvider +import com.tangem.domain.common.extensions.fromNetworkId import com.tangem.domain.common.extensions.toNetworkId import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.models.scan.ScanResponse +import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.walletconnect.WalletConnectActions import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction @@ -29,11 +30,11 @@ import com.tangem.tap.domain.walletconnect2.domain.models.Account import com.tangem.tap.domain.walletconnect2.domain.models.BnbData import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectError import com.tangem.tap.features.demo.DemoHelper -import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.userWalletsListManager +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.Middleware @@ -115,7 +116,6 @@ class WalletConnectMiddleware { scope.launch { prepareWalletManager( scanResponse = data.scanResponse, - walletState = store.state.walletState, blockchain = action.blockchain, session = data.session, walletConnectManager = walletConnectManager, @@ -176,8 +176,14 @@ class WalletConnectMiddleware { // ) } is WalletConnectAction.ScanCard -> { - val scanResponse = store.state.globalState.scanResponse ?: return - scanCard(scanResponse, action.session, action.chainId) + val scanResponse = userWalletsListManager.selectedUserWalletSync.guard { + Timber.w("Unable to get selected user wallet for WC session") + return + } + + scope.launch(Dispatchers.Main) { + scanCard(scanResponse, action.session, action.chainId) + } } is WalletConnectAction.ApproveSession -> { walletConnectManager.approve(action.session) @@ -274,7 +280,6 @@ class WalletConnectMiddleware { val walletManager = getWalletManager( wallet = action.session.wallet, blockchain = blockchain, - walletState = store.state.walletState, ).guard { store.dispatchOnMain( GlobalAction.ShowDialog( @@ -372,19 +377,14 @@ class WalletConnectMiddleware { } private suspend fun getWalletManagers(): List { - val walletManagerToggles = store.state.daggerGraphState - .get(DaggerGraphState::walletFeatureToggles) - return if (walletManagerToggles.isRedesignedScreenEnabled) { - val walletManagerFacade = store.state.daggerGraphState - .get(DaggerGraphState::walletManagersFacade) - val userWallet = userWalletsListManager.selectedUserWalletSync ?: return emptyList() - walletManagerFacade.getStoredWalletManagers(userWallet.walletId) - } else { - store.state.walletState.walletManagers - } + val walletManagerFacade = store.state.daggerGraphState + .get(DaggerGraphState::walletManagersFacade) + val userWallet = userWalletsListManager.selectedUserWalletSync ?: return emptyList() + + return walletManagerFacade.getStoredWalletManagers(userWallet.walletId) } - private fun scanCard(scanResponse: ScanResponse, session: WalletConnectSession, chainId: Int?) { + private suspend fun scanCard(userWallet: UserWallet, session: WalletConnectSession, chainId: Int?) { val blockchain = WalletConnectNetworkUtils.parseBlockchain( chainId = chainId, peer = session.peerMeta, @@ -393,27 +393,28 @@ class WalletConnectMiddleware { return } - handleScanResponse(scanResponse = scanResponse, session = session, blockchain = blockchain) + handleScanResponse(userWallet, session, blockchain) } - private fun getAvailableBlockchains( - derivationStyleProvider: DerivationStyleProvider, - walletState: WalletState, - ): List { - return walletState.currencies.filter { - it.isBlockchain() && - !it.isCustomCurrency(derivationStyleProvider.getDerivationStyle()) && it.blockchain.isEvm() - }.map { it.blockchain } + private suspend fun getAvailableEvmBlockchains(userWalletId: UserWalletId): List { + val currenciesRepository = store.state.daggerGraphState.get(DaggerGraphState::currenciesRepository) + + return currenciesRepository.getMultiCurrencyWalletCurrenciesSync(userWalletId) + .asSequence() + .filterIsInstance() + .filterNot { it.isCustom } + .mapNotNull { Blockchain.fromNetworkId(it.network.id.value) } + .filter { it.isEvm() } + .toList() } private suspend fun prepareWalletManager( scanResponse: ScanResponse, - walletState: WalletState, blockchain: Blockchain, session: WalletConnectSession, walletConnectManager: WalletConnectManager, ) { - val walletManager = getWalletManager(session.wallet, blockchain, walletState).guard { + val walletManager = getWalletManager(session.wallet, blockchain).guard { store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(session.session)) store.dispatchOnMain( GlobalAction.ShowDialog( @@ -445,20 +446,25 @@ class WalletConnectMiddleware { } } - private fun handleScanResponse(scanResponse: ScanResponse, session: WalletConnectSession, blockchain: Blockchain) { + private suspend fun handleScanResponse( + userWallet: UserWallet, + session: WalletConnectSession, + blockchain: Blockchain, + ) { + val scanResponse = userWallet.scanResponse + if (!scanResponse.cardTypesResolver.isMultiwalletAllowed()) { store.dispatchOnMain(WalletConnectAction.UnsupportedCard) return } - val walletState = store.state.walletState val updatedSession = session.copy(wallet = session.wallet.copy(blockchain = blockchain)) store.dispatch( WalletConnectAction.SetNewSessionData( - NewWcSessionData(session = updatedSession, scanResponse = scanResponse, blockchain = blockchain), + NewWcSessionData(updatedSession, scanResponse, blockchain), ), ) val blockchains = if (blockchain.isEvm()) { - getAvailableBlockchains(scanResponse.derivationStyleProvider, walletState) + getAvailableEvmBlockchains(userWallet.walletId) } else { emptyList() } @@ -469,11 +475,7 @@ class WalletConnectMiddleware { ) } - private suspend fun getWalletManager( - wallet: WalletForSession, - blockchain: Blockchain, - walletState: WalletState, - ): WalletManager? { + private suspend fun getWalletManager(wallet: WalletForSession, blockchain: Blockchain): WalletManager? { val blockchainToMake = if (blockchain == Blockchain.Ethereum && wallet.isTestNet) { Blockchain.EthereumTestnet } else { @@ -483,25 +485,15 @@ class WalletConnectMiddleware { val derivation = blockchainToMake.derivationPath( style = userWallet.scanResponse.derivationStyleProvider.getDerivationStyle(), )?.rawPath - val walletFeatureToggles = store.state.daggerGraphState - .get(DaggerGraphState::walletFeatureToggles) - return if (walletFeatureToggles.isRedesignedScreenEnabled) { - val walletManagerFacade = store.state.daggerGraphState - .get(DaggerGraphState::walletManagersFacade) - walletManagerFacade.getOrCreateWalletManager( - userWalletId = userWallet.walletId, - blockchain = blockchainToMake, - derivationPath = derivation, - ) - } else { - val blockchainNetwork = BlockchainNetwork( - blockchain = blockchainToMake, - derivationPath = derivation, - tokens = emptyList(), - ) - walletState.getWalletManager(blockchainNetwork) - } + val walletManagerFacade = store.state.daggerGraphState + .get(DaggerGraphState::walletManagersFacade) + + return walletManagerFacade.getOrCreateWalletManager( + userWalletId = userWallet.walletId, + blockchain = blockchainToMake, + derivationPath = derivation, + ) } private fun isWalletConnectUri(uri: String): Boolean { diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt index 3bebecb90a..2384570ce9 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt @@ -20,7 +20,6 @@ import com.tangem.tap.features.details.redux.AppSetting import com.tangem.tap.features.details.redux.AppSettingsState import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.DetailsState -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.scope import com.tangem.utils.coroutines.JobHolder import com.tangem.utils.coroutines.saveIn @@ -109,13 +108,7 @@ internal class AppSettingsViewModel( } private fun showAppCurrencySelector() { - val action = if (detailsFeatureToggles.isRedesignedAppCurrencySelectorEnabled) { - NavigationAction.NavigateTo(AppScreen.AppCurrencySelector) - } else { - WalletAction.AppCurrencyAction.ChooseAppCurrency - } - - store.dispatchOnMain(action) + store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.AppCurrencySelector)) } private fun showThemeModeSelector(selectedMode: AppThemeMode) { diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreenState.kt index 1cf79ec5e4..4cf5e68186 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreenState.kt @@ -4,7 +4,6 @@ import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.ui.res.stringResource -import com.tangem.domain.userwallets.Artwork import com.tangem.tap.features.details.redux.AccessCodeRecoveryState import com.tangem.tap.features.details.redux.SecurityOption import com.tangem.tap.features.details.ui.securitymode.toTitleRes @@ -17,7 +16,6 @@ internal data class CardSettingsScreenState( val accessCodeRecoveryState: AccessCodeRecoveryState? = null, val onScanCardClick: () -> Unit, val onElementClick: (CardInfo) -> Unit, - val cardImage: Artwork? = null, ) internal sealed class CardInfo( diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt index 732f7aa06d..64c00b50f4 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt @@ -12,11 +12,9 @@ import com.tangem.domain.common.getTwinCardIdForUser import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Settings -import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.features.details.redux.CardSettingsState import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.DetailsState -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.store import dagger.hilt.android.lifecycle.HiltViewModel import org.rekotlin.StoreSubscriber @@ -37,15 +35,12 @@ internal class CardSettingsViewModel @Inject constructor( is Either.Left -> { Timber.e(selectedWalletEither.value.toString()) } - is Either.Right -> { - store.dispatchOnMain(WalletAction.UpdateUserWalletArtwork(selectedWalletEither.value.walletId)) - } + is Either.Right -> Unit } store.subscribe(this) { state -> state.skipRepeats { oldState, newState -> - oldState.detailsState == newState.detailsState && - oldState.walletState == newState.walletState + oldState.detailsState == newState.detailsState }.select { it.detailsState } } } @@ -67,7 +62,6 @@ internal class CardSettingsViewModel @Inject constructor( onScanCardClick = { store.dispatch(DetailsAction.ScanCard) }, - cardImage = store.state.walletState.cardImage, ) } else { val cardId = if (state.card.isTangemTwins) { @@ -105,7 +99,6 @@ internal class CardSettingsViewModel @Inject constructor( onElementClick = { handleClickingItem(it) }, - cardImage = store.state.walletState.cardImage, ) } } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt index 5f12982afd..4a39c22d2e 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt @@ -2,6 +2,7 @@ package com.tangem.tap.features.details.ui.details import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf +import com.tangem.common.extensions.guard import com.tangem.core.analytics.Analytics import com.tangem.core.navigation.AppScreen import com.tangem.core.navigation.NavigationAction @@ -12,6 +13,7 @@ import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.wallets.repository.WalletsRepository import com.tangem.tap.common.analytics.events.Settings +import com.tangem.tap.common.extensions.addContext import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchWithMain import com.tangem.tap.common.feedback.FeedbackEmail @@ -24,7 +26,6 @@ import com.tangem.tap.features.details.redux.DetailsState import com.tangem.tap.features.disclaimer.redux.DisclaimerAction import com.tangem.tap.features.home.LocaleRegionProvider import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.scope import com.tangem.tap.userWalletsListManager import com.tangem.wallet.BuildConfig @@ -37,6 +38,7 @@ import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.rekotlin.Store +import timber.log.Timber // TODO: change to Android ViewModel [REDACTED_JIRA] internal class DetailsViewModel( @@ -158,7 +160,15 @@ internal class DetailsViewModel( private fun linkMoreCards() { Analytics.send(Settings.ButtonCreateBackup()) - store.dispatchOnMain(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)) } private fun scanAndSaveUserWallet() { diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerAction.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerAction.kt index ded89f039b..52e3057f46 100644 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerAction.kt +++ b/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerAction.kt @@ -1,8 +1,8 @@ package com.tangem.tap.features.disclaimer.redux import com.tangem.core.navigation.AppScreen +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.features.disclaimer.Disclaimer -import com.tangem.tap.features.wallet.redux.ProgressState import org.rekotlin.Action sealed class DisclaimerAction : Action { diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerState.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerState.kt index ff9ab50f31..8d37c385eb 100644 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerState.kt +++ b/app/src/main/java/com/tangem/tap/features/disclaimer/redux/DisclaimerState.kt @@ -2,9 +2,9 @@ package com.tangem.tap.features.disclaimer.redux import com.tangem.common.extensions.VoidCallback import com.tangem.core.navigation.AppScreen +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.features.disclaimer.Disclaimer import com.tangem.tap.features.disclaimer.DummyDisclaimer -import com.tangem.tap.features.wallet.redux.ProgressState import org.rekotlin.StateType data class DisclaimerState( diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerFragment.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerFragment.kt index e2865c1aee..dc438d1872 100644 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerFragment.kt @@ -8,6 +8,7 @@ import androidx.transition.TransitionInflater import by.kirich1409.viewbindingdelegate.viewBinding import com.tangem.core.navigation.AppScreen import com.tangem.core.ui.extensions.setStatusBarColor +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.common.extensions.beginDelayedTransition import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.show @@ -17,7 +18,6 @@ import com.tangem.tap.features.addBackPressHandler import com.tangem.tap.features.disclaimer.Disclaimer import com.tangem.tap.features.disclaimer.redux.DisclaimerAction import com.tangem.tap.features.disclaimer.redux.DisclaimerState -import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.store import com.tangem.wallet.R import com.tangem.wallet.databinding.FragmentDisclaimerBinding diff --git a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt b/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt index abc9d83f27..c64d0b7543 100644 --- a/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt +++ b/app/src/main/java/com/tangem/tap/features/disclaimer/ui/DisclaimerWebViewClient.kt @@ -1,13 +1,9 @@ package com.tangem.tap.features.disclaimer.ui import android.graphics.Bitmap -import android.webkit.WebResourceError -import android.webkit.WebResourceRequest -import android.webkit.WebResourceResponse -import android.webkit.WebView -import android.webkit.WebViewClient +import android.webkit.* import com.tangem.common.extensions.ifNotNull -import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.common.entities.ProgressState class DisclaimerWebViewClient : WebViewClient() { diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt index d2674c5f2a..30d6372cf7 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt @@ -3,8 +3,8 @@ package com.tangem.tap.features.home.redux import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import com.tangem.tap.common.entities.IndeterminateProgressButton +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.features.send.redux.states.ButtonState -import com.tangem.tap.features.wallet.redux.ProgressState import org.rekotlin.StateType import java.util.Locale diff --git a/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BuyCurrencyIntentHandler.kt b/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BuyCurrencyIntentHandler.kt index e0c509b3ff..f58d3a9e72 100644 --- a/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BuyCurrencyIntentHandler.kt +++ b/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BuyCurrencyIntentHandler.kt @@ -1,13 +1,7 @@ package com.tangem.tap.features.intentHandler.handlers import android.content.Intent -import android.net.Uri -import com.tangem.core.analytics.Analytics -import com.tangem.domain.tokens.models.analytics.TokenScreenAnalyticsEvent -import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.features.intentHandler.IntentHandler -import com.tangem.tap.network.exchangeServices.ExchangeUrlBuilder -import com.tangem.tap.store /** [REDACTED_AUTHOR] @@ -15,16 +9,19 @@ import com.tangem.tap.store class BuyCurrencyIntentHandler : IntentHandler { override fun handleIntent(intent: Intent?): Boolean { - val data = intent?.data ?: return false - val currency = store.state.walletState.selectedCurrency ?: return false + // FIXME: It hasn't worked since the redesign + // val data = intent?.data ?: return false + // val currency = store.state.walletState.selectedCurrency ?: return false + // + // val successUri = Uri.parse(ExchangeUrlBuilder.SUCCESS_URL) + // return if (data.host == successUri.host && data.authority == successUri.authority) { + // val currencyType = AnalyticsParam.CurrencyType.Currency(currency) + // Analytics.send(TokenScreenAnalyticsEvent.Bought(currencyType.value)) + // true + // } else { + // false + // } - val successUri = Uri.parse(ExchangeUrlBuilder.SUCCESS_URL) - return if (data.host == successUri.host && data.authority == successUri.authority) { - val currencyType = AnalyticsParam.CurrencyType.Currency(currency) - Analytics.send(TokenScreenAnalyticsEvent.Bought(currencyType.value)) - true - } else { - false - } + return false } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt deleted file mode 100644 index 280ca66499..0000000000 --- a/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.tangem.tap.features.onboarding - -import android.content.Context -import android.os.Bundle -import android.view.LayoutInflater -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.google.android.material.bottomsheet.BottomSheetDialog -import com.tangem.core.analytics.Analytics -import com.tangem.tap.common.analytics.events.Token -import com.tangem.tap.common.extensions.copyToClipboard -import com.tangem.tap.common.extensions.dispatchDialogHide -import com.tangem.tap.common.extensions.dispatchShare -import com.tangem.tap.common.extensions.dispatchToastNotification -import com.tangem.tap.common.extensions.getString -import com.tangem.tap.common.extensions.toQrCode -import com.tangem.tap.common.redux.AppDialog -import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.store -import com.tangem.wallet.R -import com.tangem.wallet.databinding.DialogOnboardingAddressInfoBinding - -/** -[REDACTED_AUTHOR] - */ -class AddressInfoBottomSheetDialog( - private val stateDialog: AppDialog.AddressInfoDialog, - context: Context, -) : BottomSheetDialog(context) { - - var binding: DialogOnboardingAddressInfoBinding? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = DialogOnboardingAddressInfoBinding - .inflate(LayoutInflater.from(context)) - setContentView(binding!!.root) - behavior.state = BottomSheetBehavior.STATE_EXPANDED - setOnCancelListener { - store.dispatchDialogHide() - binding = null - } - } - - override fun show() { - super.show() - Analytics.send(Token.Receive.ScreenOpened()) - showData(data = stateDialog.addressData) - } - - private fun showData(data: WalletDataModel.AddressData) = with(binding!!) { - pseudoToolbar.imvClose.setOnClickListener { - dismissWithAnimation = true - cancel() - } - imvQrCode.setImageBitmap(data.shareUrl.toQrCode()) - tvAddress.text = data.address - btnFlCopyAddress.setOnClickListener { - Analytics.send(Token.Receive.ButtonCopyAddress()) - context.copyToClipboard(data.address) - store.dispatchToastNotification(R.string.copy_toast_msg) - } - btnFlShare.setOnClickListener { - Analytics.send(Token.Receive.ButtonShareAddress()) - store.dispatchShare(data.shareUrl) - } - val blockchain = stateDialog.currency.blockchain - tvReceiveMessage.text = tvReceiveMessage.getString( - id = R.string.address_qr_code_message_format, - blockchain.fullName, - blockchain.currency, - blockchain.fullName, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingManager.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingManager.kt index c7dfdae94d..e4db13a1d3 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingManager.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingManager.kt @@ -5,18 +5,18 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.WalletManager import com.tangem.common.extensions.isZero import com.tangem.common.services.Result +import com.tangem.data.source.preferences.storage.UsedCardsPrefStorage import com.tangem.domain.models.scan.ScanResponse import com.tangem.operations.attestation.CardVerifyAndGetInfo import com.tangem.operations.attestation.OnlineCardVerifier +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.common.extensions.isPositive import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.getOrLoadCardArtworkUrl +import com.tangem.tap.features.demo.isDemoCard import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.hasPendingTransactions -import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.data.source.preferences.storage.UsedCardsPrefStorage -import com.tangem.tap.features.demo.isDemoCard import timber.log.Timber import java.math.BigDecimal diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt index 266b627b65..4701566599 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt @@ -8,6 +8,7 @@ import com.tangem.domain.common.extensions.makePrimaryWalletManager import com.tangem.domain.common.extensions.withMainContext import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Onboarding +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.common.extensions.* import com.tangem.tap.common.postUi import com.tangem.tap.common.redux.AppDialog @@ -19,7 +20,6 @@ import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE import com.tangem.tap.features.onboarding.OnboardingDialog import com.tangem.tap.features.onboarding.OnboardingHelper import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.scope diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt index 31072fcd23..2467a6c18f 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt @@ -14,6 +14,7 @@ import com.tangem.domain.userwallets.UserWalletIdBuilder import com.tangem.domain.wallets.legacy.isLockedSync import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Onboarding +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.common.extensions.* import com.tangem.tap.common.postUi import com.tangem.tap.common.redux.AppDialog @@ -25,7 +26,6 @@ import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE import com.tangem.tap.features.onboarding.OnboardingDialog import com.tangem.tap.features.onboarding.OnboardingHelper import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.preferencesStorage 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 1a1bdd7dd9..92d7685a73 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 @@ -21,7 +21,6 @@ import com.tangem.tap.common.extensions.dispatchWithMain import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.proxy.redux.DaggerGraphState import kotlinx.coroutines.launch import org.rekotlin.Middleware @@ -119,16 +118,8 @@ internal class SaveWalletMiddleware { ) } - val savedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("User wallet is not saved") - return@launch - } store.dispatchWithMain(SaveWalletAction.Save.Success) store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet)) - store.dispatchWithMain(WalletAction.UpdateCanSaveUserWallets(canSaveUserWallets = true)) - store.dispatchWithMain( - action = WalletAction.MultiWallet.CheckForBackupWarning(savedUserWallet.scanResponse.card), - ) } } } diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt index 7e2e65171e..e4ac2c2376 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt @@ -2,13 +2,13 @@ package com.tangem.tap.features.send.redux.reducers import com.tangem.blockchain.common.transaction.Fee import com.tangem.blockchain.common.transaction.TransactionFee +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.features.send.redux.FeeAction import com.tangem.tap.features.send.redux.FeeActionUi import com.tangem.tap.features.send.redux.SendScreenAction import com.tangem.tap.features.send.redux.states.FeeState import com.tangem.tap.features.send.redux.states.FeeType import com.tangem.tap.features.send.redux.states.SendState -import com.tangem.tap.features.wallet.redux.ProgressState /** [REDACTED_AUTHOR] diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt index ebfa2a391a..7d2d583f2f 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt @@ -2,23 +2,12 @@ package com.tangem.tap.features.send.redux.reducers import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.Wallet +import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.tap.common.extensions.scaleToFiat import com.tangem.tap.common.extensions.stripZeroPlainString import com.tangem.tap.features.send.redux.ReceiptAction.RefreshReceipt import com.tangem.tap.features.send.redux.SendScreenAction -import com.tangem.tap.features.send.redux.states.AmountState -import com.tangem.tap.features.send.redux.states.FeeState -import com.tangem.tap.features.send.redux.states.MainCurrencyType -import com.tangem.tap.features.send.redux.states.ReceiptCrypto -import com.tangem.tap.features.send.redux.states.ReceiptFiat -import com.tangem.tap.features.send.redux.states.ReceiptLayoutType -import com.tangem.tap.features.send.redux.states.ReceiptState -import com.tangem.tap.features.send.redux.states.ReceiptSymbols -import com.tangem.tap.features.send.redux.states.ReceiptTokenCrypto -import com.tangem.tap.features.send.redux.states.ReceiptTokenFiat -import com.tangem.tap.features.send.redux.states.SendState -import com.tangem.tap.features.wallet.redux.utils.CAN_BE_LOWER_SIGN -import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN +import com.tangem.tap.features.send.redux.states.* import com.tangem.tap.store import java.math.BigDecimal @@ -143,9 +132,9 @@ class ReceiptReducer : SendInternalReducer { ) } else { ReceiptTokenFiat( - amountFiat = UNKNOWN_AMOUNT_SIGN, - feeFiat = UNKNOWN_AMOUNT_SIGN, - totalFiat = UNKNOWN_AMOUNT_SIGN, + amountFiat = BigDecimalFormatter.EMPTY_BALANCE_SIGN, + feeFiat = BigDecimalFormatter.EMPTY_BALANCE_SIGN, + totalFiat = BigDecimalFormatter.EMPTY_BALANCE_SIGN, willSentToken = tokensToSend.stripZeroPlainString(), willSentFeeCoin = feeCoin.stripZeroPlainString(), symbols = symbols, @@ -175,7 +164,7 @@ class ReceiptReducer : SendInternalReducer { ReceiptTokenCrypto( amountToken = tokensToSend.stripZeroPlainString(), feeCoin = feeCoin.stripZeroPlainString().addPrecisionSign(), - totalFiat = UNKNOWN_AMOUNT_SIGN, + totalFiat = BigDecimalFormatter.EMPTY_BALANCE_SIGN, symbols = symbols, ) } @@ -216,7 +205,7 @@ class ReceiptReducer : SendInternalReducer { sendState.tokenConverter!!.toFiatWithPrecision(value).stripZeroPlainString() } else -> { - UNKNOWN_AMOUNT_SIGN + BigDecimalFormatter.EMPTY_BALANCE_SIGN } } } @@ -225,4 +214,8 @@ class ReceiptReducer : SendInternalReducer { val result = if (feeState.feeIsApproximate) "$CAN_BE_LOWER_SIGN $this" else this return result.trim() } + + private companion object { + const val CAN_BE_LOWER_SIGN = "<" + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt index f7a3a5e41b..844b7956ab 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt @@ -3,7 +3,7 @@ package com.tangem.tap.features.send.redux.states import com.tangem.blockchain.common.transaction.Fee import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.tap.common.analytics.events.AnalyticsParam -import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.common.entities.ProgressState import java.math.BigDecimal /** diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt b/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt index e115eff66d..f2a6c77ccf 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt @@ -40,8 +40,8 @@ import com.tangem.tap.features.send.redux.AmountActionUi.* import com.tangem.tap.features.send.redux.FeeActionUi.* import com.tangem.tap.features.send.redux.states.FeeType import com.tangem.tap.features.send.redux.states.MainCurrencyType +import com.tangem.tap.features.send.ui.adapters.WarningMessagesAdapter import com.tangem.tap.features.send.ui.stateSubscribers.SendStateSubscriber -import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter import com.tangem.tap.mainScope import com.tangem.tap.store import com.tangem.wallet.R diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt b/app/src/main/java/com/tangem/tap/features/send/ui/adapters/WarningMessagesAdapter.kt similarity index 93% rename from app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt rename to app/src/main/java/com/tangem/tap/features/send/ui/adapters/WarningMessagesAdapter.kt index 1534ef1d17..3620265327 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/adapters/WarningMessagesAdapter.kt @@ -1,4 +1,4 @@ -package com.tangem.tap.features.wallet.ui.adapters +package com.tangem.tap.features.send.ui.adapters import android.view.LayoutInflater import android.view.View @@ -13,14 +13,13 @@ import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.configurable.warningMessage.WarningMessage -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.store import com.tangem.wallet.R import com.tangem.wallet.databinding.LayoutWarningCardActionBinding import timber.log.Timber -// TODO: Delete with WalletFeatureToggles -@Deprecated(message = "Used only in old wallet screen") +// TODO: Delete with SendFeatureToggles +@Deprecated(message = "Used only in old send screen") class WarningMessagesAdapter : ListAdapter(DiffUtilCallback) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WarningMessageVH { @@ -81,11 +80,9 @@ class WarningMessageVH(val binding: LayoutWarningCardActionBinding) : RecyclerVi private fun setupControlButtons(warning: WarningMessage) = when (warning.type) { WarningMessage.Type.Permanent, WarningMessage.Type.TestCard -> { binding.groupControlsTemporary.hide() - binding.groupControlsRating.hide() binding.btnClose.hide() } WarningMessage.Type.Temporary -> { - binding.groupControlsRating.hide() binding.groupControlsTemporary.show() binding.btnClose.hide() @@ -115,7 +112,6 @@ class WarningMessageVH(val binding: LayoutWarningCardActionBinding) : RecyclerVi binding.btnClose.setOnClickListener { Analytics.send(MainScreen.NoticeRateAppButton(AnalyticsParam.RateApp.Closed)) store.dispatch(GlobalAction.HideWarningMessage(warning)) - store.dispatch(WalletAction.Warnings.AppRating.RemindLater) } // binding.btnCanBeBetter.setOnClickListener { // Analytics.send(MainScreen.NoticeRateAppButton(AnalyticsParam.RateApp.Disliked)) @@ -127,7 +123,6 @@ class WarningMessageVH(val binding: LayoutWarningCardActionBinding) : RecyclerVi val activity = binding.root.context.getActivity() ?: return@setOnClickListener Analytics.send(MainScreen.NoticeRateAppButton(AnalyticsParam.RateApp.Liked)) - store.dispatch(WalletAction.Warnings.AppRating.SetNeverToShow) val reviewManager = ReviewManagerFactory.create(activity) val task = reviewManager.requestReviewFlow() task.addOnCompleteListener { diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt index 15044dd26f..0802255fb8 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt @@ -7,6 +7,8 @@ import android.view.View import android.view.ViewGroup import androidx.core.text.bold import com.tangem.common.extensions.remove +import com.tangem.core.ui.utils.BigDecimalFormatter +import com.tangem.tap.common.entities.ProgressState import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.getMessageString import com.tangem.tap.common.text.DecimalDigitsInputFilter @@ -19,11 +21,8 @@ import com.tangem.tap.features.send.redux.states.* import com.tangem.tap.features.send.ui.FeeUiHelper import com.tangem.tap.features.send.ui.SendFragment import com.tangem.tap.features.send.ui.SendViewModel +import com.tangem.tap.features.send.ui.adapters.WarningMessagesAdapter import com.tangem.tap.features.send.ui.dialogs.* -import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.tap.features.wallet.redux.utils.ROUGH_SIGN -import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN -import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter import com.tangem.wallet.R /** @@ -316,7 +315,7 @@ internal class SendStateSubscriber( fun getString(id: Int, vararg formatStrings: String): String = mainLayout.getString(id, *formatStrings) fun roughOrEmpty(value: String): String { - return if (value == UNKNOWN_AMOUNT_SIGN) value else "$ROUGH_SIGN $value" + return if (value == BigDecimalFormatter.EMPTY_BALANCE_SIGN) value else "$ROUGH_SIGN $value" } when (feeProgressState) { @@ -362,7 +361,7 @@ internal class SendStateSubscriber( llTotalContainer.tvTotalValue.update("${receipt.totalCrypto} ${receipt.symbols.crypto}") } - if (receipt.willSentFiat == UNKNOWN_AMOUNT_SIGN) { + if (receipt.willSentFiat == BigDecimalFormatter.EMPTY_BALANCE_SIGN) { llTotalContainer.tvWillBeSentValue.hide() } else { llTotalContainer.tvWillBeSentValue.show() @@ -414,4 +413,8 @@ internal class SendStateSubscriber( else -> {} } } + + private companion object { + const val ROUGH_SIGN = "≈" + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt index d4af20b4ea..6403179428 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt @@ -3,7 +3,6 @@ package com.tangem.tap.features.tokens.impl.presentation.viewmodels import arrow.core.Either import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token -import com.tangem.blockchain.common.derivation.DerivationStyle import com.tangem.data.tokens.utils.CryptoCurrencyFactory import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase @@ -13,8 +12,6 @@ import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles -import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.store import timber.log.Timber import kotlin.properties.Delegates @@ -39,14 +36,6 @@ internal class TokensListMigration( private val cryptoCurrencyFactory by lazy { CryptoCurrencyFactory() } suspend fun getCurrentCryptoCurrencies(): TokensListCryptoCurrencies { - return if (walletFeatureToggles.isRedesignedScreenEnabled) { - getNewCryptoCurrencies() - } else { - getLegacyCryptoCurrencies() - } - } - - private suspend fun getNewCryptoCurrencies(): TokensListCryptoCurrencies { return when (val selectedWalletEither = getSelectedWalletSyncUseCase()) { is Either.Left -> { Timber.e(selectedWalletEither.value.toString()) @@ -90,41 +79,6 @@ internal class TokensListMigration( } } - private fun getLegacyCryptoCurrencies(): TokensListCryptoCurrencies { - val wallets = store.state.walletState.walletsDataFromStores - val derivationStyle = store.state.globalState.scanResponse?.derivationStyleProvider?.getDerivationStyle() - - return TokensListCryptoCurrencies( - coins = wallets.toNonCustomBlockchains(derivationStyle), - tokens = wallets.toNonCustomTokensWithBlockchains(derivationStyle), - ) - } - - private fun List.toNonCustomBlockchains(derivationStyle: DerivationStyle?): List { - return this - .mapNotNull { walletDataModel -> - if (walletDataModel.currency.isCustomCurrency(derivationStyle)) { - null - } else { - (walletDataModel.currency as? Currency.Blockchain)?.blockchain - } - } - .distinct() - } - - private fun List.toNonCustomTokensWithBlockchains( - derivationStyle: DerivationStyle?, - ): List { - return this - .mapNotNull { walletDataModel -> - if (walletDataModel.currency !is Currency.Token) return@mapNotNull null - if (walletDataModel.currency.isCustomCurrency(derivationStyle)) return@mapNotNull null - - TokenWithBlockchain(walletDataModel.currency.token, walletDataModel.currency.blockchain) - } - .distinct() - } - fun onSaveButtonClick( currentTokensList: List, currentBlockchainList: List, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/data/WalletRepositoryImpl.kt b/app/src/main/java/com/tangem/tap/features/wallet/data/WalletRepositoryImpl.kt deleted file mode 100644 index e0b6ce6972..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/data/WalletRepositoryImpl.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.tangem.tap.features.wallet.data - -import com.tangem.datasource.api.common.response.getOrThrow -import com.tangem.datasource.api.tangemTech.TangemTechApi -import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse -import com.tangem.tap.features.wallet.domain.WalletRepository -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.withContext - -/** - * Implementation of repository for Wallet feature - * - * @property tangemTechApi API for server requests - * @property dispatchers coroutine dispatcher provider - */ -class WalletRepositoryImpl( - private val tangemTechApi: TangemTechApi, - private val dispatchers: CoroutineDispatcherProvider, -) : WalletRepository { - - override suspend fun getCurrencyList(): CurrenciesResponse = withContext(dispatchers.io) { - tangemTechApi.getCurrencyList().getOrThrow() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/domain/WalletRepository.kt b/app/src/main/java/com/tangem/tap/features/wallet/domain/WalletRepository.kt deleted file mode 100644 index c3ba927d31..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/domain/WalletRepository.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.tangem.tap.features.wallet.domain - -import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse - -/** Repository for Wallet feature */ -interface WalletRepository { - - /** Get list of currency */ - suspend fun getCurrencyList(): CurrenciesResponse -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt deleted file mode 100644 index ef3c3466c4..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.tangem.tap.features.wallet.models - -import com.tangem.tap.domain.model.WalletStoreModel - -sealed class WalletWarning(val showingPosition: Int) { - - data class ExistentialDeposit( - val currencyName: String, - val edStringValueWithSymbol: String, - ) : WalletWarning(1) - - data class TransactionInProgress(val currencyName: String) : WalletWarning(showingPosition = 10) - - data class BalanceNotEnoughForFee( - val currencyName: String, - val blockchainFullName: String, - val blockchainSymbol: String, - ) : WalletWarning(showingPosition = 30) - - data class Rent(val walletRent: WalletStoreModel.WalletRent) : WalletWarning(showingPosition = 40) -} - -data class WalletWarningDescription(val title: String, val message: String) \ No newline at end of file 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 deleted file mode 100644 index 30b0aaadce..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ /dev/null @@ -1,143 +0,0 @@ -package com.tangem.tap.features.wallet.redux - -import android.content.Context -import androidx.lifecycle.LifecycleCoroutineScope -import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.address.AddressType -import com.tangem.core.analytics.models.AnalyticsEvent -import com.tangem.domain.common.BlockchainNetwork -import com.tangem.domain.models.scan.CardDTO -import com.tangem.domain.wallets.models.UserWallet -import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.tap.common.entities.FiatCurrency -import com.tangem.tap.common.redux.NotificationAction -import com.tangem.tap.domain.TapError -import com.tangem.tap.domain.configurable.warningMessage.WarningMessage -import com.tangem.tap.domain.model.TotalFiatBalance -import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.domain.model.WalletStoreModel -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.redux.models.WalletDialog -import com.tangem.wallet.R -import kotlinx.coroutines.CoroutineScope -import org.rekotlin.Action - -sealed class WalletAction : Action { - - object PopBackToInitialScreen : WalletAction() - - data class UpdateCanSaveUserWallets(val canSaveUserWallets: Boolean) : WalletAction() - - object LoadData : WalletAction() { - object Refresh : WalletAction() - object Success : WalletAction() - data class Failure(val error: TapError?) : WalletAction() - } - - sealed class MultiWallet : WalletAction() { - - data class SelectWallet(val currency: Currency?) : MultiWallet() - - data class TryToRemoveWallet(val currency: Currency) : MultiWallet() - data class RemoveWallet(val currency: Currency) : MultiWallet() - - object BackupWallet : MultiWallet() - data class AddMissingDerivations(val blockchains: List) : MultiWallet() - object ScanToGetDerivations : MultiWallet() - - /** - * Display warning if card has no backup - * - * @param card card to check status - * */ - data class CheckForBackupWarning(val card: CardDTO) : MultiWallet() - } - - sealed class Warnings : WalletAction() { - object CheckHashesCount : Warnings() { - - /** - * Start online verification of signed hashes for single currency wallets if the warning not displayed - * */ - object VerifyOnlineIfNeeded : Warnings() - object SaveCardId : Warnings() - } - - object CheckIfNeeded : Warnings() - object Update : Warnings() - data class Set(val warningList: List) : Warnings() - - object AppRating : Warnings() { - object SetNeverToShow : Warnings() - object RemindLater : Warnings() - } - - class CheckRemainingSignatures(val remainingSignatures: Int?) : Warnings() - } - - data class Scan( - val onScanSuccessEvent: AnalyticsEvent?, - val scope: CoroutineScope, - ) : WalletAction() - - data class Send(val amount: Amount? = null) : WalletAction() - - data class CopyAddress(val address: String, val context: Context) : WalletAction() { - object Success : WalletAction(), NotificationAction { - override val messageResource = R.string.wallet_notification_address_copied - } - } - - data class ShareAddress(val address: String, val context: Context) : WalletAction() - - sealed class DialogAction : WalletAction() { - data class QrCode( - val currency: Currency, - val selectedAddress: WalletDataModel.AddressData, - ) : DialogAction() - - object SignedHashesMultiWalletDialog : DialogAction() - data class ChooseTradeActionDialog( - val buyAllowed: Boolean, - val sellAllowed: Boolean, - val swapAllowed: Boolean, - ) : DialogAction() - - data class ChooseCurrency(val amounts: List) : DialogAction() - data class RussianCardholdersWarningDialog( - val dialogData: WalletDialog.RussianCardholdersWarningDialog.Data? = null, - ) : DialogAction() - - object Hide : DialogAction() - } - - data class ExploreAddress(val exploreUrl: String, val context: Context) : WalletAction() - - object CreateWallet : WalletAction() - data class ChangeWallet(val scope: LifecycleCoroutineScope) : WalletAction() - object ShowSaveWalletIfNeeded : WalletAction() - - sealed class TradeCryptoAction : WalletAction() { - object Sell : TradeCryptoAction() - - data class Buy(val checkUserLocation: Boolean = true) : TradeCryptoAction() - - object Swap : TradeCryptoAction() - } - - data class ChangeSelectedAddress(val type: AddressType) : WalletAction() - - sealed class AppCurrencyAction : WalletAction() { - object ChooseAppCurrency : AppCurrencyAction() - data class SelectAppCurrency(val fiatCurrency: FiatCurrency) : AppCurrencyAction() - } - - data class UserWalletChanged(val userWallet: UserWallet) : WalletAction() - data class WalletStoresChanged(val walletStores: List) : WalletAction() - - data class TotalFiatBalanceChanged(val balance: TotalFiatBalance) : WalletAction() - - data class UpdateUserWalletArtwork(val walletId: UserWalletId) : WalletAction() - - data class SetArtworkUrl(val userWalletId: UserWalletId, val url: String) : WalletAction() -} \ No newline at end of file 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 deleted file mode 100644 index f0bdd8f3f1..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ /dev/null @@ -1,118 +0,0 @@ -package com.tangem.tap.features.wallet.redux - -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.WalletManager -import com.tangem.domain.common.BlockchainNetwork -import com.tangem.domain.common.util.cardTypesResolver -import com.tangem.domain.userwallets.Artwork -import com.tangem.tap.common.entities.Button -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.model.TotalFiatBalance -import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.domain.model.WalletStoreModel -import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.store -import org.rekotlin.StateType -import java.math.BigDecimal -import kotlin.properties.ReadOnlyProperty - -data class WalletState( - val state: ProgressState = ProgressState.Done, - val error: ErrorType? = null, - val cardImage: Artwork? = null, - val mainWarningsList: List = mutableListOf(), - val walletsStores: List = listOf(), - val isMultiwalletAllowed: Boolean = false, - val cardCurrency: CryptoCurrencyName? = null, - val selectedCurrency: Currency? = null, - val isTestnet: Boolean = false, - val totalBalance: TotalFiatBalance? = null, - val showBackupWarning: Boolean = false, - val missingDerivations: List = emptyList(), - val loadingUserTokens: Boolean = false, - val walletCardsCount: Int? = null, - val canSaveUserWallets: Boolean = false, -) : StateType { - - val walletsDataFromStores: List - get() = walletsStores.flatMap { it.walletsData } - - val selectedWalletData: WalletDataModel? - get() = walletsDataFromStores.firstOrNull { it.currency == selectedCurrency } - - // if you do not delegate - the application crashes on startup, - // because twinCardsState has not been created yet - val twinCardsState: TwinCardsState by ReadOnlyProperty { _, _ -> - store.state.twinCardsState - } - - val isTangemTwins: Boolean - get() = store.state.globalState.scanResponse?.cardTypesResolver?.isTangemTwins() == true - - val isExchangeServiceFeatureOn: Boolean - get() = store.state.globalState.exchangeManager.featureIsSwitchedOn() - - val blockchains: List - get() = walletsStores.mapNotNull { it.walletManager?.wallet?.blockchain } - - val currencies: List - get() = walletsStores.flatMap { it.walletsData }.map { it.currency } - - val walletManagers: List - get() = walletsStores.mapNotNull { it.walletManager } - - private val primaryWalletStore: WalletStoreModel? - get() = if (isMultiwalletAllowed || walletsStores.isEmpty() || walletsStores.size > 1) { - null - } else { - walletsStores[0] - } - - val primaryWalletManager: WalletManager? - get() = primaryWalletStore?.walletManager - - val primaryWalletData: WalletDataModel? - get() = primaryWalletStore?.blockchainWalletData - - val primaryTokenData: WalletDataModel? - get() = primaryWalletStore?.walletsData - ?.firstOrNull { it.currency !is Currency.Blockchain } - - fun getWalletManager(currency: Currency?): WalletManager? { - if (currency?.blockchain == null) return null - return getWalletStore(currency)?.walletManager - } - - fun getWalletManager(blockchain: BlockchainNetwork): WalletManager? { - return walletsStores.firstOrNull { - it.blockchain == blockchain.blockchain && - it.derivationPath?.rawPath == blockchain.derivationPath - }?.walletManager - } - - fun getWalletStore(currency: Currency?): WalletStoreModel? { - if (currency == null) return null - return walletsStores.firstOrNull { - it.blockchain == currency.blockchain && - it.derivationPath?.rawPath == currency.derivationPath - } - } - - fun getBlockchainAmount(currency: Currency): BigDecimal = - getWalletManager(currency)?.wallet?.amounts?.get(AmountType.Coin)?.value ?: BigDecimal.ZERO -} - -enum class ProgressState : WidgetState { Loading, Refreshing, Done, Error } - -enum class ErrorType { - NoInternetConnection, - UnknownBlockchain, -} - -sealed class WalletMainButton(enabled: Boolean) : Button(enabled) { - class SendButton(enabled: Boolean) : WalletMainButton(enabled) -} \ No newline at end of file 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 deleted file mode 100644 index 857d649336..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/AppCurrencyMiddleware.kt +++ /dev/null @@ -1,157 +0,0 @@ -package com.tangem.tap.features.wallet.redux.middlewares - -import com.tangem.common.extensions.guard -import com.tangem.core.analytics.Analytics -import com.tangem.data.source.preferences.model.DataSourceCurrency -import com.tangem.data.source.preferences.model.DataSourceFiatCurrency -import com.tangem.data.source.preferences.storage.FiatCurrenciesPrefStorage -import com.tangem.domain.appcurrency.repository.AppCurrencyRepository -import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles -import com.tangem.tap.common.analytics.events.AnalyticsParam -import com.tangem.tap.common.analytics.events.MainScreen -import com.tangem.tap.common.entities.FiatCurrency -import com.tangem.tap.common.extensions.dispatchDialogShow -import com.tangem.tap.common.extensions.dispatchWithMain -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.TapWalletManager -import com.tangem.tap.features.details.redux.DetailsAction -import com.tangem.tap.features.wallet.domain.WalletRepository -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.models.WalletDialog -import com.tangem.tap.features.walletSelector.redux.WalletSelectorAction -import com.tangem.tap.scope -import com.tangem.tap.store -import com.tangem.tap.userWalletsListManager -import com.tangem.utils.coroutines.JobHolder -import com.tangem.utils.coroutines.saveIn -import kotlinx.coroutines.launch -import timber.log.Timber - -class AppCurrencyMiddleware( - private val walletRepository: WalletRepository, - private val tapWalletManager: TapWalletManager, - private val fiatCurrenciesPrefStorage: FiatCurrenciesPrefStorage, - private val featureToggles: WalletFeatureToggles, - private val appCurrencyRepository: AppCurrencyRepository, - private val appCurrencyProvider: () -> FiatCurrency, -) { - private val showSelectorJobHolder = JobHolder() - - fun handle(action: WalletAction.AppCurrencyAction) { - when (action) { - is WalletAction.AppCurrencyAction.ChooseAppCurrency -> showSelector() - is WalletAction.AppCurrencyAction.SelectAppCurrency -> selectCurrency(action) - } - } - - private fun showSelector() { - if (featureToggles.isRedesignedScreenEnabled) { - showSelectorNew() - } else { - showSelectorLegacy() - } - } - - private fun selectCurrency(action: WalletAction.AppCurrencyAction.SelectAppCurrency) { - if (featureToggles.isRedesignedScreenEnabled) { - selectCurrencyNew(action.fiatCurrency) - } else { - selectCurrencyLegacy(action.fiatCurrency) - } - } - - private fun showSelectorNew() { - scope.launch { - val currencies = appCurrencyRepository.getAvailableAppCurrencies() - - store.dispatchDialogShow( - WalletDialog.CurrencySelectionDialog( - currenciesList = currencies.map { appCurrency -> - FiatCurrency( - code = appCurrency.code, - name = appCurrency.name, - symbol = appCurrency.symbol, - ) - }, - currentAppCurrency = appCurrencyProvider.invoke(), - ), - ) - }.saveIn(showSelectorJobHolder) - } - - private fun showSelectorLegacy() { - val storedFiatCurrencies = fiatCurrenciesPrefStorage.restore() - if (storedFiatCurrencies.isNotEmpty()) { - store.dispatchDialogShow( - WalletDialog.CurrencySelectionDialog( - currenciesList = storedFiatCurrencies.mapToUiModel(), - currentAppCurrency = appCurrencyProvider.invoke(), - ), - ) - } - - scope.launch { - runCatching { walletRepository.getCurrencyList() } - .onSuccess { response -> - val currenciesList = response.currencies - .map { with(it) { DataSourceCurrency(id, code, name, rateBTC, unit, type) } } - - if (currenciesList.isNotEmpty() && currenciesList.toSet() != storedFiatCurrencies.toSet()) { - fiatCurrenciesPrefStorage.save(currenciesList) - store.dispatchDialogShow( - WalletDialog.CurrencySelectionDialog( - currenciesList = currenciesList.mapToUiModel(), - currentAppCurrency = appCurrencyProvider.invoke(), - ), - ) - } - } - } - } - - private fun selectCurrencyNew(fiatCurrency: FiatCurrency) { - Analytics.send(MainScreen.MainCurrencyChanged(AnalyticsParam.CurrencyType.FiatCurrency(fiatCurrency))) - - scope.launch { - appCurrencyRepository.changeAppCurrency(fiatCurrency.code) - - store.dispatchWithMain(GlobalAction.ChangeAppCurrency(fiatCurrency)) - store.dispatchWithMain(DetailsAction.ChangeAppCurrency(fiatCurrency)) - store.dispatchWithMain(WalletSelectorAction.ChangeAppCurrency(fiatCurrency)) - - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to select currency, no user wallet selected") - return@launch - } - - tapWalletManager.loadData(selectedUserWallet, refresh = true) - } - } - - private fun selectCurrencyLegacy(fiatCurrency: FiatCurrency) { - Analytics.send(MainScreen.MainCurrencyChanged(AnalyticsParam.CurrencyType.FiatCurrency(fiatCurrency))) - fiatCurrenciesPrefStorage.saveAppCurrency( - with(fiatCurrency) { DataSourceFiatCurrency(code, name, symbol) }, - ) - store.dispatch(GlobalAction.ChangeAppCurrency(fiatCurrency)) - store.dispatch(DetailsAction.ChangeAppCurrency(fiatCurrency)) - store.dispatch(WalletSelectorAction.ChangeAppCurrency(fiatCurrency)) - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to select currency, no user wallet selected") - return - } - scope.launch { - tapWalletManager.loadData(selectedUserWallet, refresh = true) - } - } - - private fun List.mapToUiModel(): List { - return this.map { - FiatCurrency( - code = it.code, - name = it.name, - symbol = it.unit, - ) - } - } -} \ No newline at end of file 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 deleted file mode 100644 index 1b3426fda4..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ /dev/null @@ -1,124 +0,0 @@ -package com.tangem.tap.features.wallet.redux.middlewares - -import com.tangem.common.doOnSuccess -import com.tangem.common.extensions.guard -import com.tangem.common.flatMap -import com.tangem.core.analytics.Analytics -import com.tangem.core.navigation.AppScreen -import com.tangem.core.navigation.NavigationAction -import com.tangem.domain.wallets.models.UserWallet -import com.tangem.tap.common.analytics.events.AnalyticsParam -import com.tangem.tap.common.analytics.events.Token.ButtonRemoveToken -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.dispatchWithMain -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.TapError -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.proxy.redux.DaggerGraphState -import com.tangem.tap.scope -import com.tangem.tap.store -import com.tangem.tap.userWalletsListManager -import com.tangem.tap.walletCurrenciesManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import timber.log.Timber - -class MultiWalletMiddleware { - - @Suppress("LongMethod", "ComplexMethod") - fun handle(action: WalletAction.MultiWallet, walletState: WalletState?) { - when (action) { - is WalletAction.MultiWallet.SelectWallet -> { - if (action.currency != null) { - store.dispatch(NavigationAction.NavigateTo(screen = AppScreen.WalletDetails)) - } - } - is WalletAction.MultiWallet.TryToRemoveWallet -> { - val currency = action.currency - val walletManager = walletState?.getWalletManager(currency).guard { - store.dispatchErrorNotification(TapError.UnsupportedState("walletManager is NULL")) - store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) - return - } - - if (currency.isBlockchain() && walletManager.cardTokens.isNotEmpty()) { - store.dispatchDialogShow( - WalletDialog.TokensAreLinkedDialog( - currencyTitle = currency.currencyName, - currencySymbol = currency.currencySymbol, - ), - ) - } else { - store.dispatchDialogShow( - WalletDialog.RemoveWalletDialog( - currencyTitle = currency.currencyName, - onOk = { - Analytics.send(ButtonRemoveToken(AnalyticsParam.CurrencyType.Currency(currency))) - store.dispatch(WalletAction.MultiWallet.RemoveWallet(currency)) - store.dispatch(NavigationAction.PopBackTo()) - }, - ), - ) - } - } - is WalletAction.MultiWallet.RemoveWallet -> { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to remove wallet, no user wallet selected") - return - } - 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 -> { - store.state.globalState.topUpController?.addMissingDerivations(action.blockchains) - } - is WalletAction.MultiWallet.ScanToGetDerivations -> { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to scan to get derivations, no user wallet selected") - return - } - store.state.globalState.topUpController?.scanToGetDerivations() - scanAndUpdateCard(selectedUserWallet) - } - else -> {} - } - } - - private fun scanAndUpdateCard(selectedUserWallet: UserWallet) = scope.launch(Dispatchers.Default) { - store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor) - .scan(cardId = selectedUserWallet.cardId, allowsRequestAccessCodeFromRepository = true) - .flatMap { scanResponse -> - userWalletsListManager.update( - userWalletId = selectedUserWallet.walletId, - update = { userWallet -> - userWallet.copy( - scanResponse = scanResponse, - ) - }, - ) - } - .doOnSuccess { updatedUserWallet -> - store.dispatchWithMain(WalletAction.MultiWallet.AddMissingDerivations(emptyList())) - store.dispatchWithMain(GlobalAction.SaveScanResponse(updatedUserWallet.scanResponse)) - store.state.globalState.tapWalletManager.loadData(updatedUserWallet, refresh = true) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt deleted file mode 100644 index 3864885ded..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt +++ /dev/null @@ -1,368 +0,0 @@ -package com.tangem.tap.features.wallet.redux.middlewares - -import androidx.core.os.bundleOf -import com.google.firebase.crashlytics.FirebaseCrashlytics -import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Blockchain -import com.tangem.common.extensions.guard -import com.tangem.core.analytics.Analytics -import com.tangem.core.navigation.AppScreen -import com.tangem.core.navigation.NavigationAction -import com.tangem.domain.tokens.legacy.TradeCryptoAction -import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.domain.tokens.model.NetworkAddress -import com.tangem.feature.swap.presentation.SwapFragment -import com.tangem.features.send.api.navigation.SendRouter -import com.tangem.tap.common.analytics.events.AnalyticsParam -import com.tangem.tap.common.analytics.events.Token -import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder -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.redux.AppState -import com.tangem.tap.domain.TapError -import com.tangem.tap.features.demo.DemoHelper -import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE -import com.tangem.tap.features.send.redux.PrepareSendScreen -import com.tangem.tap.features.send.redux.SendAction -import com.tangem.tap.features.wallet.models.Currency -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.network.exchangeServices.CurrencyExchangeManager -import com.tangem.tap.network.exchangeServices.buyErc20TestnetTokens -import com.tangem.tap.proxy.redux.DaggerGraphState -import com.tangem.tap.scope -import com.tangem.tap.store -import kotlinx.coroutines.launch - -@Suppress("LargeClass") -class TradeCryptoMiddleware { - - @Suppress("LongMethod", "CyclomaticComplexMethod") - fun handle(state: () -> AppState?, action: TradeCryptoAction) { - if (DemoHelper.tryHandle(state, action)) return - - when (action) { - is TradeCryptoAction.Buy -> proceedBuyAction(state, action) - is TradeCryptoAction.Sell -> proceedSellAction() - is TradeCryptoAction.SendCrypto -> preconfigureAndOpenSendScreen(action) - is TradeCryptoAction.FinishSelling -> openReceiptUrl(action.transactionId) - is TradeCryptoAction.Swap -> { - // todo remove old flow - } - is TradeCryptoAction.New.Buy -> proceedNewBuyAction(state, action) - is TradeCryptoAction.New.Sell -> proceedNewSellAction(action) - is TradeCryptoAction.New.Swap -> openSwap( - currency = action.cryptoCurrency, - ) - is TradeCryptoAction.New.SendToken -> handleNewSendToken(action = action) - is TradeCryptoAction.New.SendCoin -> handleNewSendCoin(action = action) - } - } - - @Deprecated("Use proceedNewBuyAction instead") - private fun proceedBuyAction(state: () -> AppState?, action: TradeCryptoAction.Buy) { - val selectedWalletData = store.state.walletState.selectedWalletData ?: return - val currency = chooseAppropriateCurrency(store.state.walletState) ?: return - - Analytics.send(Token.ButtonBuy(AnalyticsParam.CurrencyType.Currency(currency))) - if (action.checkUserLocation && state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE) { - store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog()) - return - } - - val card = store.state.globalState.scanResponse?.card ?: return - val addresses = selectedWalletData.walletAddresses?.list.orEmpty() - if (addresses.isEmpty()) return - - val exchangeManager = store.state.globalState.exchangeManager - val appCurrency = store.state.globalState.appCurrency - - if (currency is Currency.Token && currency.blockchain.isTestnet()) { - val walletManager = store.state.walletState.getWalletManager(currency) - if (walletManager !is EthereumWalletManager) { - store.dispatchDebugErrorNotification("Testnet tokens available only for the Ethereum") - return - } - - scope.launch { - buyErc20TestnetTokens( - card = card, - walletManager = walletManager, - destinationAddress = currency.token.contractAddress, - ) - } - return - } - - exchangeManager.getUrl( - action = CurrencyExchangeManager.Action.Buy, - blockchain = currency.blockchain, - cryptoCurrencyName = currency.currencySymbol, - fiatCurrencyName = appCurrency.code, - walletAddress = addresses[0].address, - isDarkTheme = MutableAppThemeModeHolder.isDarkThemeActive, - )?.let { - store.dispatchOpenUrl(it) - Analytics.send(Token.Topup.ScreenOpened()) - } - } - - private fun proceedNewBuyAction(state: () -> AppState?, action: TradeCryptoAction.New.Buy) { - val networkAddress = action.cryptoCurrencyStatus.value.networkAddress - ?.defaultAddress - ?.let(NetworkAddress.Address::value) - ?: return - - val status = action.cryptoCurrencyStatus - val currency = status.currency - val blockchain = Blockchain.fromId(currency.network.id.value) - val exchangeManager = store.state.globalState.exchangeManager - val topUrl = exchangeManager.getUrl( - action = CurrencyExchangeManager.Action.Buy, - blockchain = blockchain, - cryptoCurrencyName = currency.symbol, - fiatCurrencyName = action.appCurrencyCode, - walletAddress = networkAddress, - isDarkTheme = MutableAppThemeModeHolder.isDarkThemeActive, - ) - - if (action.checkUserLocation && state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE) { - val dialogData = topUrl?.let { - WalletDialog.RussianCardholdersWarningDialog.Data( - topUpUrl = it, - ) - } - store.dispatchOnMain( - WalletAction.DialogAction.RussianCardholdersWarningDialog( - dialogData = dialogData, - ), - ) - return - } - - if (currency is CryptoCurrency.Token && currency.network.isTestnet) { - scope.launch { - val walletManager = store.state.daggerGraphState - .get(DaggerGraphState::walletManagersFacade) - .getOrCreateWalletManager( - userWalletId = action.userWallet.walletId, - blockchain = blockchain, - derivationPath = currency.network.derivationPath.value, - ) - - if (walletManager !is EthereumWalletManager) { - store.dispatchDebugErrorNotification("Testnet tokens available only for the Ethereum") - return@launch - } - - buyErc20TestnetTokens( - card = action.userWallet.scanResponse.card, - walletManager = walletManager, - destinationAddress = currency.contractAddress, - ) - } - return - } - - topUrl?.let { - store.dispatchOpenUrl(it) - Analytics.send(Token.Topup.ScreenOpened()) - } - } - - private fun proceedSellAction() { - val selectedWalletData = store.state.walletState.selectedWalletData ?: return - val currency = chooseAppropriateCurrency(store.state.walletState) ?: return - - val appCurrency = store.state.globalState.appCurrency - val addresses = selectedWalletData.walletAddresses?.list.orEmpty() - if (addresses.isEmpty()) return - - Analytics.send(Token.ButtonSell(AnalyticsParam.CurrencyType.Currency(currency))) - - store.state.globalState.exchangeManager.getUrl( - action = CurrencyExchangeManager.Action.Sell, - blockchain = currency.blockchain, - cryptoCurrencyName = currency.currencySymbol, - fiatCurrencyName = appCurrency.code, - walletAddress = addresses[0].address, - isDarkTheme = MutableAppThemeModeHolder.isDarkThemeActive, - )?.let { - store.dispatchOpenUrl(it) - Analytics.send(Token.Withdraw.ScreenOpened()) - } - } - - private fun proceedNewSellAction(action: TradeCryptoAction.New.Sell) { - val networkAddress = action.cryptoCurrencyStatus.value.networkAddress - ?.defaultAddress - ?.let(NetworkAddress.Address::value) - ?: return - val currency = action.cryptoCurrencyStatus.currency - - store.state.globalState.exchangeManager.getUrl( - action = CurrencyExchangeManager.Action.Sell, - blockchain = Blockchain.fromId(currency.network.id.value), - cryptoCurrencyName = currency.symbol, - fiatCurrencyName = action.appCurrencyCode, - walletAddress = networkAddress, - isDarkTheme = MutableAppThemeModeHolder.isDarkThemeActive, - )?.let { - store.dispatchOpenUrl(it) - Analytics.send(Token.Withdraw.ScreenOpened()) - } - } - - private fun chooseAppropriateCurrency(walletState: WalletState): Currency? { - return if (walletState.primaryTokenData == null) { - walletState.selectedWalletData?.currency - } else { - walletState.primaryTokenData?.currency as? Currency.Token - }.guard { - store.dispatchDebugErrorNotification("Can't select an appropriate currency for a Trade action") - return null - } - } - - private fun preconfigureAndOpenSendScreen(action: TradeCryptoAction.SendCrypto) { - val selectedWalletData = store.state.walletState.selectedWalletData ?: return - - Analytics.send(Token.ButtonSend(AnalyticsParam.CurrencyType.Currency(selectedWalletData.currency))) - val walletManager = store.state.walletState.getWalletManager(selectedWalletData.currency).guard { - FirebaseCrashlytics.getInstance().recordException(IllegalStateException("WalletManager is null")) - return - } - - store.dispatchOnMain( - PrepareSendScreen( - walletManager = walletManager, - coinAmount = walletManager.wallet.amounts[AmountType.Coin], - coinRate = selectedWalletData.fiatRate, - ), - ) - store.dispatchOnMain( - SendAction.SendSpecificTransaction( - sendAmount = action.amount, - destinationAddress = action.destinationAddress, - transactionId = action.transactionId, - ), - ) - store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Send)) - } - - private fun openReceiptUrl(transactionId: String) { - store.dispatchOnMain(NavigationAction.PopBackTo()) - store.state.globalState.exchangeManager.getSellCryptoReceiptUrl( - action = CurrencyExchangeManager.Action.Sell, - transactionId = transactionId, - )?.let { store.dispatchOpenUrl(it) } - } - - private fun openSwap(currency: CryptoCurrency) { - val bundle = bundleOf( - SwapFragment.CURRENCY_BUNDLE_KEY to currency, - ) - - store.dispatchOnMain(NavigationAction.NavigateTo(screen = AppScreen.Swap, bundle = bundle)) - } - - private fun handleNewSendToken(action: TradeCryptoAction.New.SendToken) { - val currency = action.tokenCurrency - val blockchain = Blockchain.fromId(currency.network.id.value) - - scope.launch { - val walletManager = store.state.daggerGraphState - .get(DaggerGraphState::walletManagersFacade) - .getOrCreateWalletManager( - userWalletId = action.userWallet.walletId, - blockchain = blockchain, - derivationPath = currency.network.derivationPath.value, - ) - - if (walletManager == null) { - val error = TapError.UnsupportedState(stateError = "WalletManager is null") - FirebaseCrashlytics.getInstance().recordException(IllegalStateException(error.stateError)) - store.dispatchErrorNotification(error) - return@launch - } - - val sendableAmount = walletManager.wallet.amounts.values.firstOrNull { - val amountType = it.type - amountType is AmountType.Token && amountType.token.contractAddress == currency.contractAddress - } - - store.dispatchOnMain( - action = PrepareSendScreen( - walletManager = walletManager, - coinAmount = walletManager.wallet.amounts[AmountType.Coin], - coinRate = action.coinFiatRate, - tokenAmount = sendableAmount, - tokenRate = action.tokenFiatRate, - ), - ) - - val bundle = bundleOf( - SendRouter.CRYPTO_CURRENCY_KEY to currency, - SendRouter.USER_WALLET_ID_KEY to action.userWallet.walletId.stringValue, - ) - store.dispatchOnMain(NavigationAction.NavigateTo(screen = AppScreen.Send, bundle = bundle)) - } - } - - private fun handleNewSendCoin(action: TradeCryptoAction.New.SendCoin) { - val cryptoStatus = action.coinStatus - val currency = cryptoStatus.currency - val blockchain = Blockchain.fromId(currency.network.id.value) - - scope.launch { - val walletManager = store.state.daggerGraphState - .get(DaggerGraphState::walletManagersFacade) - .getOrCreateWalletManager( - userWalletId = action.userWallet.walletId, - blockchain = blockchain, - derivationPath = currency.network.derivationPath.value, - ) - - if (walletManager == null) { - val error = TapError.UnsupportedState(stateError = "WalletManager is null") - FirebaseCrashlytics.getInstance().recordException(IllegalStateException(error.stateError)) - store.dispatchErrorNotification(error) - return@launch - } - - val sendableAmounts = walletManager.wallet.amounts.values.filter { it.type == AmountType.Coin } - when (currency) { - is CryptoCurrency.Coin -> { - val amountToSend = sendableAmounts.find { it.currencySymbol == currency.symbol } - - if (amountToSend == null) { - val error = TapError.UnsupportedState(stateError = "Amount to send is null") - FirebaseCrashlytics.getInstance() - .recordException(IllegalStateException(error.stateError)) - store.dispatchErrorNotification(error) - return@launch - } - - store.dispatchOnMain( - action = PrepareSendScreen( - walletManager = walletManager, - coinAmount = amountToSend, - coinRate = cryptoStatus.value.fiatRate, - ), - ) - } - is CryptoCurrency.Token -> error("Action.tokenStatus.currency is Token") - } - - val bundle = bundleOf( - SendRouter.CRYPTO_CURRENCY_KEY to currency, - SendRouter.USER_WALLET_ID_KEY to action.userWallet.walletId.stringValue, - ) - store.dispatchOnMain(NavigationAction.NavigateTo(screen = AppScreen.Send, bundle = bundle)) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt deleted file mode 100644 index b381ec0365..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.tangem.tap.features.wallet.redux.middlewares - -import com.tangem.core.analytics.Analytics -import com.tangem.tap.common.analytics.events.AnalyticsParam -import com.tangem.tap.common.analytics.events.Token -import com.tangem.tap.common.extensions.dispatchDialogHide -import com.tangem.tap.common.extensions.dispatchDialogShow -import com.tangem.tap.common.redux.AppDialog -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.models.WalletDialog -import com.tangem.tap.store - -class WalletDialogsMiddleware { - fun handle(action: WalletAction.DialogAction) { - when (action) { - is WalletAction.DialogAction.SignedHashesMultiWalletDialog -> { - store.dispatchDialogShow(WalletDialog.SignedHashesMultiWalletDialog) - } - is WalletAction.DialogAction.ChooseTradeActionDialog -> { - store.state.walletState.selectedWalletData?.let { - Analytics.send(Token.ButtonExchange(AnalyticsParam.CurrencyType.Currency(it.currency))) - } - store.dispatchDialogShow( - WalletDialog.ChooseTradeActionDialog( - buyAllowed = action.buyAllowed, - sellAllowed = action.sellAllowed, - swapAllowed = action.swapAllowed, - ), - ) - } - is WalletAction.DialogAction.QrCode -> { - store.dispatchDialogShow( - AppDialog.AddressInfoDialog( - currency = action.currency, - addressData = action.selectedAddress, - ), - ) - } - is WalletAction.DialogAction.ChooseCurrency -> { - if (action.amounts.isEmpty()) return - - store.dispatchDialogShow( - WalletDialog.SelectAmountToSendDialog( - amounts = action.amounts, - ), - ) - } - is WalletAction.DialogAction.RussianCardholdersWarningDialog -> { - store.dispatchDialogShow(WalletDialog.RussianCardholdersWarningDialog(action.dialogData)) - } - is WalletAction.DialogAction.Hide -> { - store.dispatchDialogHide() - } - } - } -} \ 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 deleted file mode 100644 index ce93801220..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ /dev/null @@ -1,412 +0,0 @@ -package com.tangem.tap.features.wallet.redux.middlewares - -import androidx.lifecycle.LifecycleCoroutineScope -import com.google.firebase.crashlytics.FirebaseCrashlytics -import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.WalletManager -import com.tangem.blockchain.common.address.AddressType -import com.tangem.common.CompletionResult -import com.tangem.common.doOnSuccess -import com.tangem.common.extensions.guard -import com.tangem.core.analytics.Analytics -import com.tangem.core.navigation.AppScreen -import com.tangem.core.navigation.NavigationAction -import com.tangem.datasource.connection.NetworkConnectionManager -import com.tangem.domain.tokens.legacy.TradeCryptoAction -import com.tangem.domain.userwallets.GetCardImageUseCase -import com.tangem.domain.wallets.legacy.lockIfLockable -import com.tangem.tap.* -import com.tangem.tap.common.analytics.events.AnalyticsParam -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.* -import com.tangem.tap.common.redux.AppState -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.TapError -import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.domain.model.WalletStoreModel -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.getSendableAmounts -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletState -import com.tangem.tap.proxy.redux.DaggerGraphState -import com.tangem.utils.coroutines.ifActive -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import org.rekotlin.Action -import org.rekotlin.Middleware -import timber.log.Timber -import java.math.BigDecimal - -@Suppress("LargeClass") -class WalletMiddleware { - private val tradeCryptoMiddleware = TradeCryptoMiddleware() - private val warningsMiddleware = WarningsMiddleware() - private val multiWalletMiddleware = MultiWalletMiddleware() - private val walletDialogMiddleware = WalletDialogsMiddleware() - private val appCurrencyMiddleware by lazy(mode = LazyThreadSafetyMode.NONE) { - AppCurrencyMiddleware( - // TODO("After adding DI") get dependencies by DI - walletRepository = store.state.featureRepositoryProvider.walletRepository, - tapWalletManager = store.state.globalState.tapWalletManager, - fiatCurrenciesPrefStorage = preferencesStorage.fiatCurrenciesPrefStorage, - appCurrencyRepository = store.state.daggerGraphState.get(DaggerGraphState::appCurrencyRepository), - featureToggles = store.state.daggerGraphState.get(DaggerGraphState::walletFeatureToggles), - appCurrencyProvider = { store.state.globalState.appCurrency }, - ) - } - - private val networkConnectionManager: NetworkConnectionManager - get() = store.state.daggerGraphState.get(DaggerGraphState::networkConnectionManager) - - private var updateWalletStoresJob: Job? = null - set(value) { - field?.cancel() - field = value - } - - val walletMiddleware: Middleware = { _, state -> - { next -> - { action -> - handleAction(state, action) - next(action) - } - } - } - - @Suppress("LongMethod", "ComplexMethod") - private fun handleAction(state: () -> AppState?, action: Action) { - if (DemoHelper.tryHandle(state, action)) return - - val globalState = store.state.globalState - val walletState = store.state.walletState - - when (action) { - is TradeCryptoAction -> tradeCryptoMiddleware.handle(state, action) - is WalletAction.Warnings -> warningsMiddleware.handle(action, globalState) - is WalletAction.MultiWallet -> multiWalletMiddleware.handle(action, walletState) - is WalletAction.AppCurrencyAction -> appCurrencyMiddleware.handle(action) - is WalletAction.DialogAction -> walletDialogMiddleware.handle(action) - is WalletAction.CreateWallet -> { - scope.launch { - when (val result = tangemSdkManager.createWallet(globalState.scanResponse?.card?.cardId)) { - is CompletionResult.Success -> { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to create wallet, no user wallet selected") - return@launch - } - val updatedScanResponse = selectedUserWallet.scanResponse.copy( - card = result.data, - ) - store.dispatchWithMain(GlobalAction.SaveScanResponse(updatedScanResponse)) - userWalletsListManager.update(selectedUserWallet.walletId) { userWallet -> - userWallet.copy(scanResponse = updatedScanResponse) - } - } - is CompletionResult.Failure -> Unit - } - } - } - is WalletAction.Scan -> { - store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) - action.scope.launch { - delay(timeMillis = 700) - store.dispatchOnMain(HomeAction.ReadCard(action.onScanSuccessEvent, action.scope)) - } - } - is WalletAction.LoadData, - is WalletAction.LoadData.Refresh, - -> { - val selectedWallet = userWalletsListManager.selectedUserWalletSync.guard { - Timber.e("Unable to load/refresh wallets data, no user wallet selected") - return - } - - scope.launch { - globalState.tapWalletManager.loadData( - userWallet = selectedWallet, - refresh = action is WalletAction.LoadData.Refresh, - ) - } - - store.dispatchOnMain(WalletAction.UpdateUserWalletArtwork(selectedWallet.walletId)) - } - is WalletAction.CopyAddress -> { - Analytics.send(Token.Receive.ButtonCopyAddress()) - action.context.copyToClipboard(action.address) - store.dispatch(WalletAction.CopyAddress.Success) - } - is WalletAction.ShareAddress -> { - Analytics.send(Token.Receive.ButtonShareAddress()) - action.context.shareText(action.address) - } - is WalletAction.ExploreAddress -> { - Analytics.send(Token.ButtonExplore()) - store.dispatchOpenUrl(action.exploreUrl) - } - is WalletAction.Send -> { - val walletStore = walletState.getWalletStore(walletState.selectedCurrency) - val selectedWalletData = walletState.selectedWalletData - val walletManager = walletStore?.walletManager - - if (walletStore == null || walletManager == null || selectedWalletData == null) { - val error = TapError.UnsupportedState( - "WalletAction.Send: walletStore or selectedWalletData or walletManager is null", - ) - FirebaseCrashlytics.getInstance().recordException(IllegalStateException(error.stateError)) - store.dispatchErrorNotification(error) - return - } - if (!networkConnectionManager.isOnline) { - store.dispatchErrorNotification(TapError.NoInternetConnection) - return - } - - val currency = selectedWalletData.currency - val initSendStateAction = if (action.amount == null) { - val sendableAmounts = walletManager.wallet.getSendableAmounts() - if (sendableAmounts.isEmpty()) { - val error = TapError.UnsupportedState("WalletAction.Send: Nothing to send") - FirebaseCrashlytics.getInstance().recordException(IllegalStateException(error.stateError)) - store.dispatchErrorNotification(error) - return - } - - if (walletState.isMultiwalletAllowed) { - val amountToSend = findAmountToSend(currency = currency, amounts = sendableAmounts) - if (amountToSend == null) { - val error = TapError.UnsupportedState("WalletAction.Send: Amount to send is null") - FirebaseCrashlytics.getInstance().recordException(IllegalStateException(error.stateError)) - store.dispatchErrorNotification(error) - return - } - - makeInitSendStateActionByCurrency( - currency = currency, - amount = amountToSend, - walletStore = walletStore, - walletManager = walletManager, - selectedWalletData = selectedWalletData, - ) - } else { - val isSingleAmount = sendableAmounts.size == 1 - if (isSingleAmount) { - makeInitSendStateActionByAmount( - amount = sendableAmounts.first(), - walletStore = walletStore, - walletManager = walletManager, - selectedWalletData = selectedWalletData, - ) - } else { - store.dispatch(WalletAction.DialogAction.ChooseCurrency(sendableAmounts)) - return - } - } - } else { - // action.amount received from the ChooseCurrency dialog - makeInitSendStateActionByAmount( - amount = action.amount, - walletManager = walletManager, - walletStore = walletStore, - selectedWalletData = selectedWalletData, - ) - } - - Analytics.send(Token.ButtonSend(AnalyticsParam.CurrencyType.Currency(currency))) - store.dispatch(initSendStateAction) - store.dispatch(NavigationAction.NavigateTo(AppScreen.Send)) - } - is WalletAction.ShowSaveWalletIfNeeded -> { - showSaveWalletIfNeeded() - } - is WalletAction.ChangeWallet -> { - changeWallet(walletState, action.scope) - } - is WalletAction.UserWalletChanged -> Unit - is WalletAction.WalletStoresChanged -> { - // Cancel update job when new wallet stores received - updateWalletStoresJob = scope.launch(Dispatchers.Default) { - ifActive { fetchTotalFiatBalance(action.walletStores) } - ifActive { findMissedDerivations(action.walletStores) } - ifActive { tryToShowAppRatingWarning(action.walletStores) } - ifActive { store.state.globalState.topUpController?.walletStoresChanged(action.walletStores) } - } - } - is WalletAction.TotalFiatBalanceChanged -> Unit - is WalletAction.PopBackToInitialScreen -> { - userWalletsListManager.lockIfLockable() - val screen = if (walletState.canSaveUserWallets) { - AppScreen.Welcome - } else { - AppScreen.Home - } - - store.dispatchOnMain(NavigationAction.PopBackTo(screen)) - } - is WalletAction.ChangeSelectedAddress -> { - changeSelectedWalletAddress(action.type, walletState) - } - is WalletAction.UpdateUserWalletArtwork -> { - scope.launch { - userWalletsListManager - .update( - userWalletId = action.walletId, - update = { userWallet -> - userWallet.copy( - artworkUrl = GetCardImageUseCase().invoke( - cardId = userWallet.cardId, - cardPublicKey = userWallet.scanResponse.card.cardPublicKey, - ), - ) - }, - ) - .doOnSuccess { - store.dispatch( - WalletAction.SetArtworkUrl(userWalletId = action.walletId, url = it.artworkUrl), - ) - } - } - } - } - } - - private fun findAmountToSend(currency: Currency, amounts: List): Amount? { - return amounts.find { amount -> - val amountType = amount.type - if (amountType is AmountType.Token && currency is Currency.Token) { - val token = amountType.token - token.symbol == currency.currencySymbol && token.contractAddress == currency.token.contractAddress - } else { - amount.currencySymbol == currency.currencySymbol - } - } - } - - private fun makeInitSendStateActionByAmount( - amount: Amount, - walletStore: WalletStoreModel, - walletManager: WalletManager, - selectedWalletData: WalletDataModel, - ): PrepareSendScreen = when (amount.type) { - AmountType.Coin -> - PrepareSendScreen( - walletManager = walletManager, - coinAmount = amount, - coinRate = selectedWalletData.fiatRate, - ) - is AmountType.Token -> { - PrepareSendScreen( - walletManager = walletManager, - coinAmount = walletManager.wallet.amounts[AmountType.Coin], - coinRate = walletStore.blockchainWalletData.fiatRate, - tokenAmount = amount, - tokenRate = selectedWalletData.fiatRate, - ) - } - AmountType.Reserve -> { - val exception = IllegalStateException("WalletAction.Send: Reserve can't be sent") - FirebaseCrashlytics.getInstance().recordException(exception) - throw exception - } - } - - private fun makeInitSendStateActionByCurrency( - currency: Currency, - amount: Amount, - walletStore: WalletStoreModel, - walletManager: WalletManager, - selectedWalletData: WalletDataModel, - ): PrepareSendScreen = when (currency) { - is Currency.Blockchain -> { - PrepareSendScreen( - walletManager = walletManager, - coinAmount = amount, - coinRate = selectedWalletData.fiatRate, - ) - } - is Currency.Token -> { - PrepareSendScreen( - walletManager = walletManager, - coinAmount = walletManager.wallet.amounts[AmountType.Coin], - coinRate = walletStore.blockchainWalletData.fiatRate, - tokenAmount = amount, - tokenRate = selectedWalletData.fiatRate, - ) - } - } - - private fun changeSelectedWalletAddress(type: AddressType, state: WalletState) { - val selectedUserWalletId = userWalletsListManager.selectedUserWalletSync?.walletId.guard { - Timber.e("Unable to change selected wallet address, no user wallet selected") - return - } - val selectedCurrency = state.selectedCurrency.guard { - Timber.e("Unable to change selected wallet address, no currency selected") - return - } - - scope.launch(Dispatchers.Default) { - walletStoresManager.updateSelectedAddress(selectedUserWalletId, selectedCurrency, type) - } - } - - private suspend fun fetchTotalFiatBalance(walletStores: List) { - val totalFiatBalance = totalFiatBalanceCalculator.calculateOrNull(walletStores) - - if (totalFiatBalance != null) { - store.dispatchOnMain(WalletAction.TotalFiatBalanceChanged(totalFiatBalance)) - } - } - - private fun findMissedDerivations(wallStores: List) { - val missedDerivations = wallStores - .filter { store -> - store.walletsData.any { it.status is WalletDataModel.MissedDerivation } - } - .map(WalletStoreModel::blockchainNetwork) - - store.dispatchOnMain(WalletAction.MultiWallet.AddMissingDerivations(missedDerivations)) - } - - private fun tryToShowAppRatingWarning(walletStores: List) { - warningsMiddleware.tryToShowAppRatingWarning( - hasNonZeroWallets = walletStores - .flatMap { it.walletsData } - .any { it.status.amount.isGreaterThan(BigDecimal.ZERO) }, - ) - } - - private fun showSaveWalletIfNeeded() { - if (preferencesStorage.shouldShowSaveUserWalletScreen && - tangemSdkManager.canUseBiometry && - store.state.navigationState.backStack.lastOrNull() == AppScreen.Wallet - ) { - store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.SaveWallet)) - } - } - - private fun changeWallet(state: WalletState, lifecycleScope: LifecycleCoroutineScope) { - when { - state.canSaveUserWallets -> { - Analytics.send(MainScreen.ButtonMyWallets()) - store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.WalletSelector)) - } - else -> { - Analytics.send(MainScreen.ButtonScanCard()) - store.dispatch( - WalletAction.Scan( - onScanSuccessEvent = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.Main), - scope = lifecycleScope, - ), - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt deleted file mode 100644 index 39e905255e..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt +++ /dev/null @@ -1,184 +0,0 @@ -package com.tangem.tap.features.wallet.redux.middlewares - -import com.tangem.blockchain.common.BlockchainSdkError -import com.tangem.blockchain.common.SignatureCountValidator -import com.tangem.blockchain.extensions.SimpleResult -import com.tangem.common.card.FirmwareVersion -import com.tangem.domain.common.TapWorkarounds.isTestCard -import com.tangem.domain.common.util.cardTypesResolver -import com.tangem.domain.models.scan.CardDTO -import com.tangem.domain.models.scan.ScanResponse -import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.common.redux.global.GlobalState -import com.tangem.tap.domain.configurable.warningMessage.WarningMessage -import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager -import com.tangem.tap.domain.extensions.hasSignedHashes -import com.tangem.tap.features.demo.isDemoCard -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.preferencesStorage -import com.tangem.tap.proxy.redux.DaggerGraphState -import com.tangem.tap.scope -import com.tangem.tap.store -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -// TODO: Delete with WalletFeatureToggles -@Deprecated(message = "Used only in old wallet screen") -class WarningsMiddleware { - fun handle(action: WalletAction.Warnings, globalState: GlobalState?) { - when (action) { - is WalletAction.Warnings.Update -> setWarningMessages() - is WalletAction.Warnings.CheckIfNeeded -> { - showCardWarningsIfNeeded(globalState) - val readyToShow = preferencesStorage.appRatingLaunchObserver.isReadyToShow() - if (readyToShow) addWarningMessage(warning = WarningMessagesManager.appRatingWarning, autoUpdate = true) - } - - is WalletAction.Warnings.CheckHashesCount.VerifyOnlineIfNeeded -> checkHashesCountOnlineIfNeeded() - is WalletAction.Warnings.CheckHashesCount.SaveCardId -> { - val cardId = globalState?.scanResponse?.card?.cardId - cardId?.let { preferencesStorage.usedCardsPrefStorage.scanned(it) } - } - is WalletAction.Warnings.AppRating.RemindLater -> { - preferencesStorage.appRatingLaunchObserver.applyDelayedShowing() - } - is WalletAction.Warnings.AppRating.SetNeverToShow -> { - preferencesStorage.appRatingLaunchObserver.setNeverToShow() - } - is WalletAction.Warnings.CheckRemainingSignatures -> { - if (action.remainingSignatures != null && - action.remainingSignatures <= WarningMessagesManager.REMAINING_SIGNATURES_WARNING - ) { - // store.state.globalState.warningManager?.removeWarnings(R.string.warning_low_signatures_format) - addWarningMessage( - warning = WarningMessagesManager.remainingSignaturesNotEnough(action.remainingSignatures), - autoUpdate = true, - ) - } - } - is WalletAction.Warnings.AppRating, - is WalletAction.Warnings.CheckHashesCount, - is WalletAction.Warnings.Set, - -> Unit - } - } - - fun tryToShowAppRatingWarning(hasNonZeroWallets: Boolean) { - if (hasNonZeroWallets) { - preferencesStorage.appRatingLaunchObserver.foundWalletWithFunds() - } - if (preferencesStorage.appRatingLaunchObserver.isReadyToShow()) { - addWarningMessage(WarningMessagesManager.appRatingWarning, true) - } - } - - private fun showCardWarningsIfNeeded(globalState: GlobalState?) { - globalState?.scanResponse?.let { scanResponse -> - val card = scanResponse.card - globalState.warningManager?.removeWarnings(WarningMessage.Origin.Local) - if (card.isTestCard) { - addWarningMessage(WarningMessagesManager.testCardWarning, autoUpdate = true) - return@let - } - - showWarningLowRemainingSignaturesIfNeeded(card) - if (card.firmwareVersion.type != FirmwareVersion.FirmwareType.Release) { - addWarningMessage(WarningMessagesManager.devCardWarning) - } else if (!preferencesStorage.usedCardsPrefStorage.wasScanned(card.cardId)) { - checkIfWarningNeeded(scanResponse)?.let { warning -> addWarningMessage(warning) } - } - if (card.firmwareVersion.type == FirmwareVersion.FirmwareType.Release && !globalState.cardVerifiedOnline) { - addWarningMessage(WarningMessagesManager.onlineVerificationFailed) - } - if (scanResponse.isDemoCard()) { - addWarningMessage(WarningMessagesManager.demoCardWarning) - } - setWarningMessages() - } - } - - private fun showWarningLowRemainingSignaturesIfNeeded(card: CardDTO) { - val remainingSignatures = card.wallets.firstOrNull()?.remainingSignatures - if (remainingSignatures != null && - remainingSignatures <= WarningMessagesManager.REMAINING_SIGNATURES_WARNING - ) { - addWarningMessage(WarningMessagesManager.remainingSignaturesNotEnough(remainingSignatures)) - } - } - - private fun checkIfWarningNeeded(scanResponse: ScanResponse): WarningMessage? { - if (scanResponse.cardTypesResolver.isTangemTwins() || scanResponse.isDemoCard()) return null - - if (scanResponse.cardTypesResolver.isMultiwalletAllowed()) { - val isBackupForbidden = with(scanResponse.card.settings) { !(isBackupAllowed || isHDWalletAllowed) } - return if (scanResponse.card.hasSignedHashes() && isBackupForbidden) { - WarningMessagesManager.signedHashesMultiWalletWarning - } else { - store.dispatch(WalletAction.Warnings.CheckHashesCount.SaveCardId) - null - } - } - - return if (scanResponse.card.hasSignedHashes()) { - WarningMessagesManager.alreadySignedHashesWarning - } else { - store.dispatch(WalletAction.Warnings.CheckHashesCount.SaveCardId) - null - } - } - - private fun checkHashesCountOnlineIfNeeded() { - val alreadySignedHashesWarning = WarningMessagesManager.alreadySignedHashesWarning - val manager = store.state.globalState.warningManager ?: return - if (manager.containsWarning(alreadySignedHashesWarning)) return - - val networkConnectionManager = store.state.daggerGraphState.get(DaggerGraphState::networkConnectionManager) - if (!networkConnectionManager.isOnline) return - - val scanResponse = store.state.globalState.scanResponse - val card = scanResponse?.card - if (card == null || preferencesStorage.usedCardsPrefStorage.wasScanned(card.cardId)) return - - if (scanResponse.cardTypesResolver.isTangemTwins() || scanResponse.cardTypesResolver.isMultiwalletAllowed()) { - return - } - - val validator = store.state.walletState.walletManagers.firstOrNull() - as? SignatureCountValidator - scope.launch { - val signedHashes = card.wallets.firstOrNull()?.totalSignedHashes ?: 0 - val result = validator?.validateSignatureCount(signedHashes) - withContext(Dispatchers.Main) { - when (result) { - SimpleResult.Success -> { - store.dispatch(WalletAction.Warnings.CheckHashesCount.SaveCardId) - } - is SimpleResult.Failure -> - if (signedHashes > 0 || result.error is BlockchainSdkError.SignatureCountNotMatched) { - alreadySignedHashesWarning.isHidden = false - addWarningMessage(alreadySignedHashesWarning, true) - } - null -> Unit - } - } - } - } - - private fun addWarningMessage(warning: WarningMessage, autoUpdate: Boolean = false) { - store.state.globalState.warningManager?.addWarning(warning) - if (autoUpdate) setWarningMessages() - } - - private fun setWarningMessages() { - store.dispatchOnMain(WalletAction.Warnings.Set(getWarnings())) - } - - private fun getWarnings(): List { - val warningManager = store.state.globalState.warningManager ?: return emptyList() - return warningManager.getWarnings( - WarningMessage.Location.MainScreen, - store.state.walletState.blockchains, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt deleted file mode 100644 index c8b5747a94..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.tangem.tap.features.wallet.redux.models - -import com.tangem.blockchain.common.Amount -import com.tangem.core.navigation.StateDialog -import com.tangem.tap.common.entities.FiatCurrency -import com.tangem.wallet.R - -sealed interface WalletDialog : StateDialog { - data class SelectAmountToSendDialog(val amounts: List) : WalletDialog - object SignedHashesMultiWalletDialog : WalletDialog - data class ChooseTradeActionDialog( - val buyAllowed: Boolean, - val sellAllowed: Boolean, - val swapAllowed: Boolean, - ) : WalletDialog - - data class CurrencySelectionDialog( - val currenciesList: List, - val currentAppCurrency: FiatCurrency, - ) : WalletDialog - - data class RemoveWalletDialog( - val currencyTitle: String, - val onOk: () -> Unit, - ) : WalletDialog { - val messageRes: Int = R.string.token_details_hide_alert_message - val titleRes: Int = R.string.token_details_hide_alert_title - val primaryButtonRes: Int = R.string.token_details_hide_alert_hide - } - - data class TokensAreLinkedDialog( - val currencyTitle: String, - val currencySymbol: String, - ) : WalletDialog { - val messageRes: Int = R.string.token_details_unable_hide_alert_message - val titleRes: Int = R.string.token_details_unable_hide_alert_title - } - - data class RussianCardholdersWarningDialog(val data: Data?) : WalletDialog { - data class Data(val topUpUrl: String) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/AppCurrencyReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/AppCurrencyReducer.kt deleted file mode 100644 index 49ba3fa007..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/AppCurrencyReducer.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.tangem.tap.features.wallet.redux.reducers - -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletState - -class AppCurrencyReducer { - fun reduce(action: WalletAction.AppCurrencyAction, state: WalletState): WalletState { - return when (action) { - is WalletAction.AppCurrencyAction.SelectAppCurrency, - is WalletAction.AppCurrencyAction.ChooseAppCurrency, - -> state - } - } -} \ No newline at end of file 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 deleted file mode 100644 index a0bc33e948..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.tangem.tap.features.wallet.redux.reducers - -import com.tangem.domain.models.scan.CardDTO -import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletState - -class MultiWalletReducer { - @Suppress("LongMethod", "ComplexMethod") - fun reduce(action: WalletAction.MultiWallet, state: WalletState): WalletState { - return when (action) { - is WalletAction.MultiWallet.SelectWallet -> { - state.copy(selectedCurrency = action.currency) - } - - is WalletAction.MultiWallet.TryToRemoveWallet -> state - is WalletAction.MultiWallet.AddMissingDerivations -> state.copy( - missingDerivations = action.blockchains, - ) - - is WalletAction.MultiWallet.BackupWallet -> state - is WalletAction.MultiWallet.ScanToGetDerivations -> state.copy(state = ProgressState.Loading) - is WalletAction.MultiWallet.CheckForBackupWarning -> state.copy( - showBackupWarning = action.card.settings.isBackupAllowed && - action.card.backupStatus == CardDTO.BackupStatus.NoBackup, - ) - - else -> state - } - } -} \ No newline at end of file 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 deleted file mode 100644 index 3fb8a17540..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ /dev/null @@ -1,172 +0,0 @@ -package com.tangem.tap.features.wallet.redux.reducers - -import com.tangem.blockchain.common.Wallet -import com.tangem.blockchain.common.address.AddressType -import com.tangem.domain.common.TapWorkarounds.isTestCard -import com.tangem.domain.models.scan.CardDTO -import com.tangem.domain.userwallets.Artwork -import com.tangem.tap.common.redux.AppState -import com.tangem.tap.domain.TapError -import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.domain.model.WalletStoreModel -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.redux.ErrorType -import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletState -import com.tangem.tap.proxy.AppStateHolder -import com.tangem.tap.userWalletsListManager -import org.rekotlin.Action - -object WalletReducer { - fun reduce(action: Action, state: AppState, appStateHolder: AppStateHolder): WalletState = - internalReduce(action, state, appStateHolder) -} - -@Suppress("LongMethod", "ComplexMethod") -private fun internalReduce(action: Action, state: AppState, appStateHolder: AppStateHolder): WalletState { - val multiWalletReducer = MultiWalletReducer() - val appCurrencyReducer = AppCurrencyReducer() - - if (action !is WalletAction) return state.walletState - - var newState = state.walletState - - when (action) { - is WalletAction.Warnings -> newState = handleCheckSignedHashesActions(action, newState) - is WalletAction.MultiWallet -> newState = multiWalletReducer.reduce(action, newState) - is WalletAction.LoadData.Failure -> { - when (action.error) { - is TapError.NoInternetConnection -> { - newState = newState.copy( - state = ProgressState.Error, - error = ErrorType.NoInternetConnection, - ) - } - is TapError.UnknownBlockchain -> { - newState = newState.copy( - state = ProgressState.Error, - error = ErrorType.UnknownBlockchain, - ) - } - else -> { - newState = newState.copy( - state = ProgressState.Error, - ) - } - } - } - is WalletAction.LoadData -> { - newState = newState.copy( - state = ProgressState.Loading, - error = null, - ) - } - is WalletAction.LoadData.Refresh -> { - newState = newState.copy( - state = ProgressState.Refreshing, - error = null, - ) - } - is WalletAction.AppCurrencyAction -> { - newState = appCurrencyReducer.reduce(action, newState) - } - is WalletAction.UserWalletChanged -> with(action.userWallet) { - val card = scanResponse.card - newState = WalletState( - isMultiwalletAllowed = isMultiCurrency, - cardImage = Artwork( - artworkId = artworkUrl, - ), - isTestnet = card.isTestCard, - state = ProgressState.Loading, - showBackupWarning = isMultiCurrency && - card.settings.isBackupAllowed && - card.backupStatus == CardDTO.BackupStatus.NoBackup, - walletCardsCount = card.findCardsCount(), - walletsStores = newState.walletsStores, - totalBalance = if (isMultiCurrency) { - newState.totalBalance - } else { - null - }, - ) - } - is WalletAction.WalletStoresChanged -> { - newState = newState.copy( - walletsStores = action.walletStores, - selectedCurrency = findSelectedCurrency( - walletsStores = action.walletStores, - currentSelectedCurrency = newState.selectedCurrency, - isMultiWalletAllowed = newState.isMultiwalletAllowed, - ), - ) - } - is WalletAction.TotalFiatBalanceChanged -> { - newState = newState.copy( - totalBalance = action.balance, - ) - } - is WalletAction.LoadData.Success -> { - newState = newState.copy(state = ProgressState.Done) - } - is WalletAction.UpdateCanSaveUserWallets -> { - newState = newState.copy(canSaveUserWallets = action.canSaveUserWallets) - } - is WalletAction.SetArtworkUrl -> { - val selectedUserWallet = userWalletsListManager.selectedUserWalletSync?.walletId - - if (selectedUserWallet == action.userWalletId) { - newState = newState.copy( - cardImage = Artwork(artworkId = action.url), - ) - } - } - else -> Unit - } - appStateHolder.walletState = newState - return newState -} - -fun findSelectedCurrency( - walletsStores: List, - currentSelectedCurrency: Currency?, - isMultiWalletAllowed: Boolean, -): Currency? = if (isMultiWalletAllowed) { - currentSelectedCurrency -} else { - walletsStores.firstOrNull() - ?.walletsData - ?.firstOrNull() - ?.currency -} - -private fun CardDTO.findCardsCount(): Int? { - return (this.backupStatus as? CardDTO.BackupStatus.Active)?.cardCount?.inc() -} - -fun Wallet.createAddressesData(): List { - val listOfAddressData = mutableListOf() - // put a defaultAddress at the first place - addresses.forEach { - val addressData = WalletDataModel.AddressData( - it.value, - it.type, - getShareUri(it.value), - getExploreUrl(it.value), - ) - if (it.type == AddressType.Default) { - listOfAddressData.add(0, addressData) - } else { - listOfAddressData.add(addressData) - } - } - return listOfAddressData -} - -private fun handleCheckSignedHashesActions(action: WalletAction.Warnings, state: WalletState): WalletState { - return when (action) { - is WalletAction.Warnings.Set -> state.copy(mainWarningsList = action.warningList) - else -> state - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/utils/Constants.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/utils/Constants.kt deleted file mode 100644 index dfab28f18a..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/utils/Constants.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.tangem.tap.features.wallet.redux.utils - -const val UNKNOWN_AMOUNT_SIGN = "—" -const val ROUGH_SIGN = "≈" -const val CAN_BE_LOWER_SIGN = "<" \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt deleted file mode 100644 index eb7dfd7126..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt +++ /dev/null @@ -1,123 +0,0 @@ -package com.tangem.tap.features.wallet.ui - -import androidx.annotation.IdRes -import com.tangem.tap.common.extensions.hide -import com.tangem.tap.common.extensions.show -import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.features.wallet.ui.utils.getFormattedCryptoAmount -import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount -import com.tangem.tap.store -import com.tangem.wallet.R -import com.tangem.wallet.databinding.CardBalanceBinding - -// TODO: Delete with WalletFeatureToggles -@Deprecated(message = "Used only in old wallet screen") -class BalanceWidget( - private val binding: CardBalanceBinding, - private val fragment: WalletFragment, - private val blockchainWalletData: WalletDataModel, - private val tokenWalletData: WalletDataModel?, -) { - - @Suppress("LongMethod", "ComplexMethod") - fun setup() { - when (blockchainWalletData.status) { - is WalletDataModel.Loading -> { - with(binding) { - lBalance.root.show() - lBalanceError.root.hide() - lBalance.tvFiatAmount.hide() - - lBalance.tvCurrency.text = blockchainWalletData.currency.currencyName - lBalance.tvAmount.text = "" - } - - showStatus(R.id.tv_status_loading) - - if (tokenWalletData != null) { - showBalanceWithToken(blockchainWalletData, false) - } else { - showBalanceWithoutToken(blockchainWalletData, false) - } - } - is WalletDataModel.VerifiedOnline, - is WalletDataModel.TransactionInProgress, - -> with(binding.lBalance) { - root.show() - binding.lBalanceError.root.hide() - val statusView = if (blockchainWalletData.status is WalletDataModel.VerifiedOnline) { - R.id.tv_status_verified - } else { - // tvStatusError.text = fragment.getText(R.string.wallet_balance_tx_in_progress) - R.id.group_error - } - showStatus(statusView) - // tvStatusErrorMessage.hide() - - if (tokenWalletData != null) { - showBalanceWithToken(blockchainWalletData, true) - } else { - showBalanceWithoutToken(blockchainWalletData, true) - } - } - is WalletDataModel.Unreachable -> with(binding.lBalance) { - root.show() - binding.lBalanceError.root.hide() - tvFiatAmount.hide() - groupBaseCurrency.hide() - - val currency = tokenWalletData?.currency?.currencySymbol - ?: blockchainWalletData.currency.currencyName - tvCurrency.text = currency - tvAmount.text = "" - - // tvStatusErrorMessage.text = blockchainWalletData.status.errorMessage - // TODO: Delete with WalletFeatureToggles - // tvStatusError.text = fragment.getString(R.string.wallet_balance_blockchain_unreachable) - - showStatus(R.id.group_error) - // tvStatusErrorMessage.show(!blockchainWalletData.status.errorMessage.isNullOrBlank()) - } - is WalletDataModel.NoAccount -> with(binding.lBalanceError) { - binding.lBalance.root.hide() - binding.lBalanceError.root.show() - tvErrorTitle.text = fragment.getText(R.string.wallet_error_no_account) - tvErrorDescriptions.text = - fragment.getString( - R.string.no_account_generic, - blockchainWalletData.status.amountToCreateAccount, - blockchainWalletData.currency.currencySymbol, - ) - } - else -> {} - } - } - - private fun showStatus(@IdRes viewRes: Int) = with(binding.lBalance) { - // groupError.show(viewRes == R.id.group_error) - tvStatusLoading.show(viewRes == R.id.tv_status_loading) - tvStatusVerified.show(viewRes == R.id.tv_status_verified) - } - - private fun showBalanceWithToken(data: WalletDataModel, showAmount: Boolean) = with(binding.lBalance) { - groupBaseCurrency.show() - tvCurrency.text = tokenWalletData?.currency?.currencySymbol - tvBaseCurrency.text = data.currency.currencyName - tvAmount.text = if (showAmount) tokenWalletData?.getFormattedCryptoAmount() else "" - tvBaseAmount.text = if (showAmount) data.getFormattedCryptoAmount() else "" - if (showAmount) { - tvFiatAmount.show() - tvFiatAmount.text = tokenWalletData?.getFormattedFiatAmount(store.state.globalState.appCurrency) - } - } - - private fun showBalanceWithoutToken(data: WalletDataModel, showAmount: Boolean) = with(binding.lBalance) { - groupBaseCurrency.hide() - tvCurrency.text = data.currency.currencyName - tvAmount.text = if (showAmount) data.getFormattedCryptoAmount() else "" - if (showAmount) { - tvFiatAmount.show() - tvFiatAmount.text = data.getFormattedFiatAmount(store.state.globalState.appCurrency) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/MultipleAddressUiHelper.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/MultipleAddressUiHelper.kt deleted file mode 100644 index 9531a726e3..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/MultipleAddressUiHelper.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.tangem.tap.features.wallet.ui - -import android.view.View -import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.address.AddressType -import com.tangem.wallet.R - -object MultipleAddressUiHelper { - - private val blockchainsSupportingSplit = listOf( - Blockchain.Bitcoin, - Blockchain.BitcoinTestnet, - Blockchain.Litecoin, - Blockchain.BitcoinCash, - Blockchain.Cardano, - ) - - fun typeToId(type: AddressType, blockchain: Blockchain): Int { - return if (blockchain in blockchainsSupportingSplit) { - if (type == AddressType.Legacy) { - R.id.chip_legacy - } else { - R.id.chip_default - } - } else { - View.NO_ID - } - } - - fun idToType(id: Int, blockchain: Blockchain): AddressType? { - return when (blockchain) { - in blockchainsSupportingSplit -> { - when (id) { - R.id.chip_default -> AddressType.Default - R.id.chip_legacy -> AddressType.Legacy - else -> null - } - } - else -> null - } - } -} \ 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 deleted file mode 100644 index de08710457..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ /dev/null @@ -1,509 +0,0 @@ -package com.tangem.tap.features.wallet.ui - -import android.os.Bundle -import android.view.* -import android.widget.TextView -import androidx.activity.OnBackPressedCallback -import androidx.annotation.ColorRes -import androidx.annotation.DrawableRes -import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.Fragment -import androidx.lifecycle.lifecycleScope -import androidx.recyclerview.widget.LinearLayoutManager -import by.kirich1409.viewbindingdelegate.viewBinding -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.core.navigation.NavigationAction -import com.tangem.domain.common.extensions.withMainContext -import com.tangem.domain.common.util.derivationStyleProvider -import com.tangem.domain.tokens.legacy.TradeCryptoAction -import com.tangem.feature.swap.api.SwapFeatureToggleManager -import com.tangem.feature.swap.domain.SwapInteractor -import com.tangem.sdk.extensions.dpToPx -import com.tangem.tap.common.SnackbarHandler -import com.tangem.tap.common.TestActions -import com.tangem.tap.common.analytics.events.DetailsScreen -import com.tangem.tap.common.analytics.events.Token -import com.tangem.tap.common.extensions.* -import com.tangem.tap.common.recyclerView.SpaceItemDecoration -import com.tangem.tap.common.redux.AppState -import com.tangem.tap.common.utils.SafeStoreSubscriber -import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.models.PendingTransaction -import com.tangem.tap.features.wallet.models.PendingTransactionType -import com.tangem.tap.features.wallet.models.WalletWarning -import com.tangem.tap.features.wallet.redux.ErrorType -import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletState -import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN -import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter -import com.tangem.tap.features.wallet.ui.adapters.WalletDetailWarningMessagesAdapter -import com.tangem.tap.features.wallet.ui.images.load -import com.tangem.tap.features.wallet.ui.test.TestWallet -import com.tangem.tap.features.wallet.ui.utils.* -import com.tangem.tap.store -import com.tangem.tap.userWalletsListManagerSafe -import com.tangem.tap.walletCurrenciesManager -import com.tangem.wallet.R -import com.tangem.wallet.databinding.FragmentWalletDetailsBinding -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import timber.log.Timber -import java.math.BigDecimal -import javax.inject.Inject - -/** - * Wallet details fragment - use only for MultiWallet - */ -// TODO: Delete with WalletFeatureToggles -@Suppress("LargeClass", "MagicNumber") -@Deprecated(message = "Used only in old wallet screen") -@AndroidEntryPoint -class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), SafeStoreSubscriber { - - @Inject - lateinit var swapInteractor: SwapInteractor - - @Inject - lateinit var swapFeatureToggleManager: SwapFeatureToggleManager - - private lateinit var pendingTransactionAdapter: PendingTransactionsAdapter - private lateinit var warningMessagesAdapter: WalletDetailWarningMessagesAdapter - - private val binding: FragmentWalletDetailsBinding by viewBinding(FragmentWalletDetailsBinding::bind) - - private val walletDataWatcher: ModelWatcher = modelWatcher { - val addressCardStrategy: DiffStrategy = { old, new -> - old.currency != new.currency || old.walletAddresses != new.walletAddresses - } - - WalletDataModel::currency { - handleCurrencyIcon(it) - } - WalletDataModel::walletAddresses { walletAddresses -> - setupCopyAndShareButtons(walletAddresses?.selectedAddress?.address) - } - WalletDataModel::currency { currency -> - setupCurrency(currency) - } - watch({ it }, addressCardStrategy) { walletData -> - setupAddressCard( - shouldShowMultipleAddress = walletData.shouldShowMultipleAddress(), - selectedAddress = walletData.walletAddresses?.selectedAddress, - currency = walletData.currency, - ) - } - } - - private val walletStateWatcher: ModelWatcher = modelWatcher { - val walletDataStrategy: DiffStrategy = { old, new -> - new.walletsStores.isNotEmpty() && - new.selectedCurrency != null && - (old.selectedCurrency != new.selectedCurrency || old.walletsStores != new.walletsStores) - } - - watch({ it }, walletDataStrategy) { state -> - val selectedWallet = state.selectedWalletData - if (selectedWallet != null) { - setupBalanceData(selectedWallet) - setupSwipeRefresh(selectedWallet) - walletDataWatcher.invoke(selectedWallet) - - val walletStore = state.getWalletStore(state.selectedCurrency) - if (walletStore != null) { - handleWarnings( - selectedWallet.assembleWarnings( - blockchainAmount = walletStore.blockchainWalletData.status.amount, - blockchainWalletRent = walletStore.walletRent, - ), - ) - } - } - } - (WalletState::selectedWalletData or WalletState::isExchangeServiceFeatureOn) { state -> - val selectedWallet = state.selectedWalletData - if (selectedWallet != null) { - val blockchainAmount: BigDecimal = state.getBlockchainAmount(selectedWallet.currency) - setupButtonsRow(selectedWallet, state.isExchangeServiceFeatureOn, blockchainAmount) - } - } - (WalletState::state or WalletState::error) { state -> - setupNoInternetHandling(state.state, state.error) - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setHasOptionsMenu(true) - - Analytics.send(DetailsScreen.ScreenOpened()) - activity?.onBackPressedDispatcher?.addCallback( - this, - object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - store.dispatch(WalletAction.MultiWallet.SelectWallet(null)) - store.dispatch(NavigationAction.PopBackTo()) - } - }, - ) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - (activity as? AppCompatActivity)?.setSupportActionBar(binding.toolbar) - binding.toolbar.setNavigationOnClickListener { activity?.onBackPressed() } - - setupTransactionsRecyclerView() - setupButtons() - setupWarningsRecyclerView() - setupTestActionButton() - } - - override fun onStart() { - super.onStart() - store.subscribe(this) { state -> state.select(AppState::walletState) } - } - - override fun onStop() { - super.onStop() - store.unsubscribe(this) - } - - override fun onDestroyView() { - super.onDestroyView() - clearWatchers() - } - - private fun setupTransactionsRecyclerView() = with(binding) { - pendingTransactionAdapter = PendingTransactionsAdapter() - rvPendingTransaction.layoutManager = LinearLayoutManager(requireContext()) - rvPendingTransaction.adapter = pendingTransactionAdapter - } - - private fun setupWarningsRecyclerView() = with(binding) { - warningMessagesAdapter = WalletDetailWarningMessagesAdapter() - rvWarningMessages.layoutManager = LinearLayoutManager(requireContext()) - rvWarningMessages.adapter = warningMessagesAdapter - rvWarningMessages.addItemDecoration(SpaceItemDecoration.vertical(8f)) - } - - private fun setupButtons() { - binding.rowButtons.onSendClick = { store.dispatch(WalletAction.Send()) } - } - - private fun setupTestActionButton() { - view?.findViewById(R.id.l_balance)?.let { view -> - TestActions.initFor(view = view, actions = TestWallet.solanaRentExemptWarning()) - } - } - - override fun newStateOnMain(state: WalletState) { - if (activity == null || view == null) return - if (state.selectedWalletData == null) return - walletStateWatcher.invoke(state) - - updateViewMeasurements() - } - - private fun updateViewMeasurements() { - val tvFiatAmount = binding.lWalletDetails.lBalance.tvFiatAmount - val paddingStart = if (tvFiatAmount.text == UNKNOWN_AMOUNT_SIGN) 16f else 12f - - tvFiatAmount.setPadding( - tvFiatAmount.dpToPx(paddingStart).toInt(), - tvFiatAmount.paddingTop, - tvFiatAmount.paddingEnd, - tvFiatAmount.paddingBottom, - ) - } - - private fun setupCurrency(currency: Currency) = with(binding) { - tvCurrencyTitle.text = currency.currencyName - - if (currency is Currency.Token) { - tvCurrencySubtitle.text = tvCurrencySubtitle.getString( - R.string.wallet_currency_subtitle, - currency.blockchain.fullName, - ) - tvCurrencySubtitle.show() - } else { - tvCurrencySubtitle.hide() - } - } - - private fun setupSwipeRefresh(walletData: WalletDataModel) { - binding.srlWalletDetails.setOnRefreshListener { - if (walletData.status !is WalletDataModel.Loading) { - Analytics.send(Token.Refreshed()) - val selectedUserWallet = userWalletsListManagerSafe?.selectedUserWalletSync.guard { - Timber.e("Unable to refresh wallet details screen, no user wallet selected") - return@setOnRefreshListener - } - binding.srlWalletDetails.isRefreshing = true - lifecycleScope.launch(Dispatchers.Default) { - walletCurrenciesManager.update(selectedUserWallet, walletData.currency).doOnResult { - withMainContext { - binding.srlWalletDetails.isRefreshing = false - } - } - } - } - } - } - - private fun setupCopyAndShareButtons(walletAddress: String?) { - binding.lWalletDetails.btnCopy.setOnClickListener { - if (walletAddress != null) store.dispatch(WalletAction.CopyAddress(walletAddress, requireContext())) - } - - binding.lWalletDetails.btnShare.setOnClickListener { - if (walletAddress != null) store.dispatch(WalletAction.ShareAddress(walletAddress, requireContext())) - } - } - - private fun setupButtonsRow( - selectedWallet: WalletDataModel, - isExchangeServiceFeatureOn: Boolean, - blockchainAmount: BigDecimal, - ) { - val exchangeManager = store.state.globalState.exchangeManager - binding.rowButtons.apply { - onBuyClick = { store.dispatch(TradeCryptoAction.Buy()) } - onSellClick = { store.dispatch(TradeCryptoAction.Sell) } - onSwapClick = { store.dispatch(TradeCryptoAction.Swap) } - onTradeClick = { - store.dispatch( - WalletAction.DialogAction.ChooseTradeActionDialog( - buyAllowed = selectedWallet.isAvailableToBuy(exchangeManager), - sellAllowed = selectedWallet.isAvailableToSell(exchangeManager), - swapAllowed = selectedWallet.isAvailableToSwap( - swapFeatureToggleManager = swapFeatureToggleManager, - swapInteractor = swapInteractor, - isSingleWallet = false, - ), - ), - ) - } - } - val actions = selectedWallet.getAvailableActions( - swapInteractor = swapInteractor, - exchangeManager = exchangeManager, - swapFeatureToggleManager = swapFeatureToggleManager, - isSingleWallet = false, - ) - binding.rowButtons.updateButtonsVisibility( - actions = actions, - exchangeServiceFeatureOn = isExchangeServiceFeatureOn, - sendAllowed = selectedWallet.mainButton(blockchainAmount).enabled, - ) - } - - private fun handleWarnings(warnings: List) = with(binding) { - val converter = WalletWarningConverter(requireContext()) - val warningDetails = warnings.map { converter.convert(it) } - - warningMessagesAdapter.submitList(warningDetails) - rvWarningMessages.show(warningDetails.isNotEmpty()) - } - - private fun handleCurrencyIcon(currency: Currency) = with(binding.lWalletDetails.lBalance) { - ivCurrency.load( - currency = currency, - derivationStyle = store.state.globalState.scanResponse - ?.derivationStyleProvider?.getDerivationStyle(), - ) - } - - private fun showPendingTransactionsIfPresent(pendingTransactions: List) { - val knownTransactions = pendingTransactions.filterNot { it.type == PendingTransactionType.Unknown } - pendingTransactionAdapter.submitList(knownTransactions) - binding.rvPendingTransaction.show(knownTransactions.isNotEmpty()) - } - - private fun setupAddressCard( - shouldShowMultipleAddress: Boolean, - selectedAddress: WalletDataModel.AddressData?, - currency: Currency, - ) = with(binding.lWalletDetails) { - if (selectedAddress == null) return@with - - setupAddressTypeChips(shouldShowMultipleAddress, selectedAddress, currency) - - tvAddress.text = selectedAddress.address - tvExplore.setOnClickListener { - store.dispatch(WalletAction.ExploreAddress(selectedAddress.exploreUrl, requireContext())) - } - ivQrCode.setImageBitmap(selectedAddress.shareUrl.toQrCode()) - - tvReceiveMessage.text = when (currency) { - is Currency.Blockchain -> tvReceiveMessage.getString( - id = R.string.address_qr_code_message_format, - currency.blockchain.fullName, - currency.currencySymbol, - currency.blockchain.fullName, - ) - is Currency.Token -> tvReceiveMessage.getString( - id = R.string.address_qr_code_message_format, - currency.token.name, - currency.currencySymbol, - currency.blockchain.fullName, - ) - } - } - - private fun setupAddressTypeChips( - shouldShowMultipleAddress: Boolean, - selectedAddress: WalletDataModel.AddressData, - currency: Currency, - ) = with(binding.lWalletDetails) { - if (shouldShowMultipleAddress && currency is Currency.Blockchain) { - (cardBalance as? ViewGroup)?.beginDelayedTransition() - chipGroupAddressType.show() - chipGroupAddressType.fitChipsByGroupWidth() - - val checkedId = MultipleAddressUiHelper.typeToId(selectedAddress.type, currency.blockchain) - if (checkedId != View.NO_ID) chipGroupAddressType.check(checkedId) - - chipGroupAddressType.setOnCheckedChangeListener { _, checkedId -> - if (checkedId == -1) return@setOnCheckedChangeListener - val type = - MultipleAddressUiHelper.idToType(checkedId, currency.blockchain) - type?.let { store.dispatch(WalletAction.ChangeSelectedAddress(type)) } - } - } else { - chipGroupAddressType.hide() - } - } - - private fun setupNoInternetHandling(progressState: ProgressState, errorType: ErrorType?) { - if (progressState == ProgressState.Error) { - if (errorType == ErrorType.NoInternetConnection) { - binding.srlWalletDetails.isRefreshing = false - (activity as? SnackbarHandler)?.showSnackbar( - text = R.string.wallet_notification_no_internet, - buttonTitle = R.string.common_retry, - ) { store.dispatch(WalletAction.LoadData) } - } - } else { - (activity as? SnackbarHandler)?.dismissSnackbar() - } - } - - private fun setupBalanceData(walletData: WalletDataModel) = with(binding.lWalletDetails) { - when (val status = walletData.status) { - is WalletDataModel.Loading -> { - lBalanceError.root.hide() - lBalance.root.show() - lBalance.groupBalance.show() - lBalance.tvError.hide() - lBalance.tvAmount.text = walletData.getFormattedCryptoAmount() - lBalance.tvFiatAmount.text = walletData.getFormattedFiatAmount(store.state.globalState.appCurrency) - lBalance.tvStatus.setLoadingStatus(R.string.wallet_balance_loading) - } - is WalletDataModel.VerifiedOnline, - is WalletDataModel.SameCurrencyTransactionInProgress, - is WalletDataModel.TransactionInProgress, - -> { - lBalanceError.root.hide() - lBalance.root.show() - lBalance.groupBalance.show() - lBalance.tvError.hide() - lBalance.tvAmount.text = walletData.getFormattedCryptoAmount() - lBalance.tvFiatAmount.text = walletData.getFormattedFiatAmount(store.state.globalState.appCurrency) - when (status) { - is WalletDataModel.VerifiedOnline, - is WalletDataModel.SameCurrencyTransactionInProgress, - -> { - lBalance.tvStatus.setVerifiedBalanceStatus(R.string.wallet_balance_verified) - showPendingTransactionsIfPresent(status.pendingTransactions) - } - - is WalletDataModel.TransactionInProgress -> { - lBalance.tvStatus.setWarningStatus(R.string.wallet_balance_tx_in_progress) - showPendingTransactionsIfPresent(status.pendingTransactions) - } - - else -> Unit - } - } - is WalletDataModel.Unreachable -> { - lBalanceError.root.hide() - lBalance.root.show() - lBalance.groupBalance.hide() - lBalance.tvError.show() - // TODO: Delete with WalletFeatureToggles - // lBalance.tvError.setWarningStatus( - // R.string.wallet_balance_blockchain_unreachable, - // status.errorMessage, - // ) - } - is WalletDataModel.NoAccount -> { - lBalance.root.hide() - lBalanceError.root.show() - lBalanceError.tvErrorTitle.text = getText(R.string.wallet_error_no_account) - lBalanceError.tvErrorDescriptions.text = - getString( - R.string.no_account_generic, - status.amountToCreateAccount, - walletData.currency.currencySymbol, - ) - } - - else -> Unit - } - } - - @Deprecated("Deprecated in Java") - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { - R.id.menu_remove -> { - store.state.walletState.selectedWalletData?.let { walletData -> - store.dispatch(WalletAction.MultiWallet.TryToRemoveWallet(walletData.currency)) - true - } - false - } - - else -> super.onOptionsItemSelected(item) - } - } - - @Deprecated( - message = "Deprecated in Java", - replaceWith = ReplaceWith("inflater.inflate(R.menu.menu_wallet_details, menu)", "com.tangem.wallet.R"), - ) - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.menu_wallet_details, menu) - } - - private fun clearWatchers() { - walletDataWatcher.clear() - walletStateWatcher.clear() - } - - private fun TextView.setWarningStatus(mainMessage: Int, error: String? = null) { - val text = getString(mainMessage).appendIfNotNull(error, "\nError: ") - setStatus(text, R.color.warning, R.drawable.ic_warning_small) - } - - private fun TextView.setVerifiedBalanceStatus(mainMessage: Int) { - setStatus(getString(mainMessage), R.color.accent, R.drawable.ic_ok) - } - - private fun TextView.setLoadingStatus(mainMessage: Int) { - setStatus(getString(mainMessage), R.color.darkGray4, null) - } - - private fun TextView.setStatus(text: String, @ColorRes color: Int, @DrawableRes drawable: Int?) { - this.text = text - setTextColor(getColor(color)) - setCompoundDrawablesWithIntrinsicBounds(drawable ?: 0, 0, 0, 0) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt deleted file mode 100644 index a02a218d62..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ /dev/null @@ -1,326 +0,0 @@ -package com.tangem.tap.features.wallet.ui - -import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import androidx.activity.OnBackPressedCallback -import androidx.appcompat.app.AppCompatActivity -import androidx.compose.runtime.mutableStateOf -import androidx.fragment.app.Fragment -import androidx.fragment.app.viewModels -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.flowWithLifecycle -import androidx.lifecycle.lifecycleScope -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import androidx.transition.TransitionInflater -import by.kirich1409.viewbindingdelegate.viewBinding -import coil.load -import coil.size.Scale -import com.badoo.mvicore.modelWatcher -import com.tangem.core.analytics.Analytics -import com.tangem.core.navigation.AppScreen -import com.tangem.core.navigation.NavigationAction -import com.tangem.core.ui.extensions.setStatusBarColor -import com.tangem.core.ui.utils.OneTouchClickListener -import com.tangem.datasource.connection.NetworkConnectionManager -import com.tangem.feature.swap.api.SwapFeatureToggleManager -import com.tangem.feature.swap.domain.SwapInteractor -import com.tangem.tap.MainActivity -import com.tangem.tap.common.analytics.events.Portfolio -import com.tangem.tap.common.extensions.show -import com.tangem.tap.common.recyclerView.SpaceItemDecoration -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.common.utils.SafeStoreSubscriber -import com.tangem.tap.domain.configurable.warningMessage.WarningMessage -import com.tangem.tap.domain.statePrinter.printScanResponseState -import com.tangem.tap.domain.statePrinter.printWalletState -import com.tangem.tap.features.wallet.redux.ErrorType -import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletState -import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter -import com.tangem.tap.features.wallet.ui.wallet.MultiWalletView -import com.tangem.tap.features.wallet.ui.wallet.SingleWalletView -import com.tangem.tap.features.wallet.ui.wallet.WalletView -import com.tangem.tap.store -import com.tangem.wallet.BuildConfig -import com.tangem.wallet.R -import com.tangem.wallet.databinding.FragmentWalletBinding -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.launch -import javax.inject.Inject - -@AndroidEntryPoint -class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber { - - @Inject - lateinit var swapInteractor: SwapInteractor - - @Inject - lateinit var swapFeatureToggleManager: SwapFeatureToggleManager - - @Inject - lateinit var networkConnectionManager: NetworkConnectionManager - - private lateinit var warningsAdapter: WarningMessagesAdapter - - private val binding: FragmentWalletBinding by viewBinding(FragmentWalletBinding::bind) - - private var walletView: WalletView = MultiWalletView() - - private val viewModel by viewModels() - - private val totalBalanceWatcher = modelWatcher { - (WalletState::totalBalance) { totalBalance -> - totalBalance?.let { - viewModel.onBalanceLoaded(totalBalance) - store.state.globalState.topUpController?.totalBalanceStateChanged(it) - } - } - } - - private val isNetworkConnectionError = mutableStateOf(false) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setHasOptionsMenu(true) - activity?.lifecycle?.addObserver(viewModel) - - activity?.onBackPressedDispatcher?.addCallback( - this, - object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - store.dispatch(WalletAction.PopBackToInitialScreen) - } - }, - ) - val inflater = TransitionInflater.from(requireContext()) - enterTransition = inflater.inflateTransition(R.transition.fade) - exitTransition = inflater.inflateTransition(R.transition.fade) - } - - override fun onStart() { - super.onStart() - - setStatusBarColor(R.color.background_secondary) - - subscribeOnNetworkStateChanging() - - store.subscribe(this) { state -> - state.select { it.walletState } - } - walletView.setFragment(this, binding) - } - - override fun onStop() { - super.onStop() - store.unsubscribe(this) - walletView.removeFragment() - } - - override fun onDestroy() { - walletView.onDestroyFragment() - super.onDestroy() - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - (activity as? AppCompatActivity)?.setSupportActionBar(binding.toolbar) - - binding.toolbar.setNavigationOnClickListener( - OneTouchClickListener { - store.dispatch(WalletAction.ChangeWallet(scope = requireActivity().lifecycleScope)) - }, - ) - setupWarningsRecyclerView() - walletView.changeWalletView(this, binding) - addCustomActionOnCard() - } - - private fun addCustomActionOnCard() { - if (!BuildConfig.TEST_ACTION_ENABLED) return - - binding.ivCard.setOnClickListener { - printScanResponseState() - printWalletState() - } - } - - @Suppress("MagicNumber") - private fun setupWarningsRecyclerView() { - warningsAdapter = WarningMessagesAdapter() - val layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false) - with(binding) { - rvWarningMessages.layoutManager = layoutManager - rvWarningMessages.addItemDecoration(SpaceItemDecoration.all(16f)) - rvWarningMessages.adapter = warningsAdapter - } - } - - @Suppress("ComplexMethod") - override fun newStateOnMain(state: WalletState) { - if (activity == null || view == null) return - - when { - state.isMultiwalletAllowed && walletView !is MultiWalletView -> { - walletView.onViewDestroy() - walletView = MultiWalletView() - walletView.changeWalletView(this, binding) - } - !state.isMultiwalletAllowed && walletView !is SingleWalletView -> { - walletView.onViewDestroy() - walletView = SingleWalletView() - walletView.changeWalletView(this, binding) - } - else -> {} // we keep the same view unless we scan a card that requires a different view - } - totalBalanceWatcher.invoke(state) - - walletView.swapInteractor = swapInteractor - walletView.swapFeatureToggleManager = swapFeatureToggleManager - - walletView.onNewState(state) - - if (binding.toolbar.menu.findItem(R.id.details_menu) == null) { - binding.toolbar.inflateMenu(R.menu.menu_wallet) - } - - setupCardImage(state) - - showWarningsIfPresent(state.mainWarningsList) - - setupPullToRefreshLayout(state) - - binding.toolbar.setNavigationIcon( - if (state.canSaveUserWallets) R.drawable.ic_wallet_24 else R.drawable.ic_tap_card_24, - ) - - // showLearn2earnView() - } - - // private fun showLearn2earnView() { - // val isShowing = learn2earnViewModel.uiState.mainScreenState.isVisible - // if (!isShowing) return - // - // binding.composeLearnToEarnContainer.show(true) { binding.llWarnings.beginDelayedTransition() } - // binding.composeLearnToEarnContainer.apply { - // setViewCompositionStrategy( - // strategy = ViewCompositionStrategy.DisposeOnLifecycleDestroyed( - // lifecycle = [REDACTED_EMAIL], - // ), - // ) - // setContent { - // TangemTheme { - // Learn2earnMainPageScreen(learn2earnViewModel.uiState) - // } - // } - // } - // } - - private fun setupPullToRefreshLayout(state: WalletState) { - setupErrorPullToRefreshState(state) - - binding.pullToRefreshLayout.isRefreshing = state.state == ProgressState.Refreshing - - binding.pullToRefreshLayout.setOnRefreshListener { - if (state.state != ProgressState.Loading && state.state != ProgressState.Refreshing) { - refreshWalletData() - } - } - } - - private fun setupErrorPullToRefreshState(state: WalletState) { - if (state.state == ProgressState.Error) { - when (state.error) { - ErrorType.NoInternetConnection -> { - isNetworkConnectionError.value = true - binding.pullToRefreshLayout.isRefreshing = false - - (activity as? MainActivity)?.showSnackbar( - text = R.string.wallet_notification_no_internet, - buttonTitle = R.string.common_retry, - ) - // because was added logic of autoupdate mainscreen data, remove retry - // TODO("remove comment after release 4.6") - // { store.dispatch(WalletAction.LoadData) } - } - else -> isNetworkConnectionError.value = false - } - } else { - isNetworkConnectionError.value = false - (activity as? MainActivity)?.dismissSnackbar() - } - } - - private fun refreshWalletData() { - Analytics.send(Portfolio.Refreshed()) - store.dispatch(WalletAction.LoadData.Refresh) - // learn2earnViewModel.onMainScreenRefreshed() - } - - private fun showWarningsIfPresent(warnings: List) { - warningsAdapter.submitList(warnings) - binding.rvWarningMessages.show(warnings.isNotEmpty()) - } - - private fun setupCardImage(state: WalletState) { - binding.ivCard.load(state.cardImage?.artworkId) { - scale(Scale.FIT) - crossfade(enable = true) - placeholder(R.drawable.card_placeholder_black) - error(R.drawable.card_placeholder_black) - fallback(R.drawable.card_placeholder_black) - } - } - - private fun subscribeOnNetworkStateChanging() { - viewLifecycleOwner.lifecycleScope.launch { - networkConnectionManager.isOnlineFlow - .flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED) - .distinctUntilChanged() - .collect { isOnline -> - if (isOnline) { - (activity as? MainActivity)?.dismissSnackbar() - } else { - isNetworkConnectionError.value = true - binding.pullToRefreshLayout.isRefreshing = false - (activity as? MainActivity)?.showSnackbar( - text = R.string.wallet_notification_no_internet, - buttonTitle = R.string.common_retry, - ) - } - if (isOnline && isNetworkConnectionError.value) { - refreshWalletData() - } - } - } - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { - R.id.details_menu -> { - store.dispatch(GlobalAction.UpdateFeedbackInfo(store.state.walletState.walletManagers)) - store.dispatch(NavigationAction.NavigateTo(AppScreen.Details)) - - true - } - else -> super.onOptionsItemSelected(item) - } - } - - @Deprecated( - message = "Deprecated in Java", - replaceWith = ReplaceWith( - "if (store.state.walletState.shouldShowDetails) inflater.inflate(R.menu.menu_wallet, menu)", - "com.tangem.tap.store", - "com.tangem.wallet.R", - ), - ) - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.menu_wallet, menu) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletViewModel.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletViewModel.kt deleted file mode 100644 index 271bc8aaae..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletViewModel.kt +++ /dev/null @@ -1,132 +0,0 @@ -package com.tangem.tap.features.wallet.ui - -import androidx.lifecycle.DefaultLifecycleObserver -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.domain.common.util.cardTypesResolver -import com.tangem.domain.wallets.legacy.UserWalletsListManager -import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter -import com.tangem.tap.common.analytics.events.Basic -import com.tangem.tap.common.analytics.events.MainScreen -import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.domain.model.TotalFiatBalance -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.ui.analytics.WalletAnalyticsEventsMapper -import com.tangem.tap.store -import com.tangem.tap.walletStoresManager -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* -import org.rekotlin.StoreSubscriber -import javax.inject.Inject - -// TODO: Kill me, please -@OptIn(ExperimentalCoroutinesApi::class) -@HiltViewModel -internal class WalletViewModel @Inject constructor( - private val analyticsEventHandler: AnalyticsEventHandler, -) : ViewModel(), StoreSubscriber, DefaultLifecycleObserver { - private var observeWalletStoresUpdatesJob: Job? = null - set(value) { - field?.cancel() - field = value - } - - private val walletAnalyticsEventsMapper = WalletAnalyticsEventsMapper() - - init { - subscribeToUserWalletsListManagerUpdates() - } - - override fun onCleared() { - store.unsubscribe(this) - } - - override fun newState(state: UserWalletsListManager?) { - // Restarting observing of wallet store updates when the manager changes - if (state != null) { - bootstrapSelectedWalletStoresChanges(state) - } - } - - override fun onCreate(owner: LifecycleOwner) { - launch() - val scanResponse = store.state.globalState.scanResponse - if (scanResponse != null) { - val currency = ParamCardCurrencyConverter().convert(scanResponse.cardTypesResolver) - val signInType = store.state.signInState.type - if (currency != null && signInType != null) { - analyticsEventHandler.send( - Basic.SignedIn( - currency = currency, - batch = scanResponse.card.batchId, - signInType = signInType, - walletsCount = store.state.globalState.userWalletsListManager?.walletsCount.toString(), - hasBackup = scanResponse.card.backupStatus?.isActive, - ), - ) - } - } - } - - override fun onStart(owner: LifecycleOwner) { - analyticsEventHandler.send(MainScreen.ScreenOpened()) - } - - fun onBalanceLoaded(totalBalance: TotalFiatBalance?) { - if (totalBalance != null) { - walletAnalyticsEventsMapper.convert(totalBalance)?.let { balanceParam -> - analyticsEventHandler.send( - Basic.BalanceLoaded( - balance = balanceParam, - ), - ) - } - } - } - - private fun launch() { - val manager = store.state.globalState.userWalletsListManager - if (manager != null) { - bootstrapSelectedWalletStoresChanges(manager) - } - bootstrapShowSaveWalletIfNeeded() - } - - @OptIn(FlowPreview::class) - private fun bootstrapSelectedWalletStoresChanges(manager: UserWalletsListManager) { - observeWalletStoresUpdatesJob = manager.selectedUserWallet - .map { it.walletId } - .flatMapLatest(walletStoresManager::get) - .debounce { walletStores -> - if (walletStores.isNotEmpty()) WALLET_STORES_DEBOUNCE_TIMEOUT else 0 - } - .onEach { walletStores -> - store.dispatchOnMain(WalletAction.WalletStoresChanged(walletStores)) - } - .launchIn(viewModelScope) - } - - private fun bootstrapShowSaveWalletIfNeeded() { - viewModelScope.launch { - delay(timeMillis = 1_800) - store.dispatchOnMain(WalletAction.ShowSaveWalletIfNeeded) - } - } - - private fun subscribeToUserWalletsListManagerUpdates() { - store.subscribe(this) { appState -> - appState - .skip { old, new -> - old.globalState.userWalletsListManager == new.globalState.userWalletsListManager - } - .select { it.globalState.userWalletsListManager } - } - } - - companion object { - private const val WALLET_STORES_DEBOUNCE_TIMEOUT = 100L - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt deleted file mode 100644 index 5f98692fca..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.tangem.tap.features.wallet.ui - -import android.content.Context -import com.tangem.common.module.ModuleMessageConverter -import com.tangem.tap.features.wallet.models.WalletWarning -import com.tangem.tap.features.wallet.models.WalletWarningDescription -import com.tangem.wallet.R - -/** -[REDACTED_AUTHOR] - */ -// TODO: Delete with WalletFeatureToggles -@Deprecated(message = "Used only in old wallet screen") -class WalletWarningConverter( - private val context: Context, -) : ModuleMessageConverter { - - override fun convert(message: WalletWarning): WalletWarningDescription { - // val warningMessage = when (message) { - // is WalletWarning.ExistentialDeposit -> { - // context.getString( - // R.string.warning_existential_deposit_message, - // message.currencyName, - // message.edStringValueWithSymbol, - // ) - // } - // is WalletWarning.BalanceNotEnoughForFee -> { - // context.getString( - // R.string.token_details_send_blocked_fee_format, - // message.currencyName, - // message.blockchainFullName, - // message.currencyName, - // message.blockchainFullName, - // message.blockchainSymbol, - // ) - // } - // is WalletWarning.TransactionInProgress -> { - // context.getString( - // R.string.token_details_send_blocked_tx_format, - // message.currencyName, - // ) - // } - // is WalletWarning.Rent -> { - // context.getString( - // R.string.solana_rent_warning, - // message.walletRent.rent, - // message.walletRent.exemptionAmount, - // ) - // } - // } - return WalletWarningDescription(context.getString(R.string.common_warning), "") - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt deleted file mode 100644 index 0a59da666a..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.tangem.tap.features.wallet.ui.adapters - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView -import com.tangem.tap.common.extensions.getDrawableCompat -import com.tangem.tap.common.extensions.getString -import com.tangem.tap.common.extensions.hide -import com.tangem.tap.features.wallet.models.PendingTransaction -import com.tangem.tap.features.wallet.models.PendingTransactionType -import com.tangem.wallet.R -import com.tangem.wallet.databinding.ItemPendingTransactionBinding - -class PendingTransactionsAdapter : - ListAdapter(DiffUtilCallback) { - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionsViewHolder { - val binding = ItemPendingTransactionBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false, - ) - return TransactionsViewHolder(binding) - } - - override fun onBindViewHolder(holder: TransactionsViewHolder, position: Int) { - holder.bind(currentList[position]) - } - - object DiffUtilCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame(oldItem: PendingTransaction, newItem: PendingTransaction) = oldItem == newItem - - override fun areItemsTheSame(oldItem: PendingTransaction, newItem: PendingTransaction) = oldItem == newItem - } - - class TransactionsViewHolder(val binding: ItemPendingTransactionBinding) : - RecyclerView.ViewHolder(binding.root) { - - fun bind(transaction: PendingTransaction) { - if (transaction.type == PendingTransactionType.Unknown) { - binding.root.hide() - } - - val transactionDescriptionRes = when (transaction.type) { - PendingTransactionType.Incoming -> R.string.wallet_pending_tx_receiving - PendingTransactionType.Outgoing -> R.string.wallet_pending_tx_sending - PendingTransactionType.Unknown -> return - } - val transactionAddressRes = when (transaction.type) { - PendingTransactionType.Incoming -> R.string.wallet_pending_tx_receiving_address_format - PendingTransactionType.Outgoing -> R.string.wallet_pending_tx_sending_address_format - PendingTransactionType.Unknown -> return - } - val image = when (transaction.type) { - PendingTransactionType.Incoming -> R.drawable.ic_arrow_left - PendingTransactionType.Outgoing -> R.drawable.ic_arrow_right_20 - PendingTransactionType.Unknown -> return - } - binding.tvPendingTransaction.text = - binding.root.getString(transactionDescriptionRes).let { "$it " } - - transaction.amountValueUi?.let { binding.tvPendingTransactionAmount.text = "$it " } - binding.tvPendingTransactionCurrency.text = transaction.currency - - if (transaction.address != null) { - binding.tvPendingTransactionAddress.text = - binding.root.getString(transactionAddressRes, transaction.address) - } - binding.ivPendingTransaction.setImageDrawable(binding.root.context.getDrawableCompat(image)) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt deleted file mode 100644 index 0b1e671dab..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt +++ /dev/null @@ -1,110 +0,0 @@ -package com.tangem.tap.features.wallet.ui.adapters - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.core.view.isVisible -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView -import com.tangem.core.analytics.Analytics -import com.tangem.domain.common.util.derivationStyleProvider -import com.tangem.tap.common.analytics.events.Portfolio -import com.tangem.tap.common.extensions.getString -import com.tangem.tap.common.extensions.hide -import com.tangem.tap.common.extensions.show -import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.ui.images.load -import com.tangem.tap.features.wallet.ui.utils.getFormattedCryptoAmount -import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount -import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatRate -import com.tangem.tap.store -import com.tangem.wallet.R -import com.tangem.wallet.databinding.ItemCurrencyWalletBinding - -// TODO: Delete with WalletFeatureToggles -@Deprecated(message = "Used only in old wallet screen") -class WalletAdapter : ListAdapter(DiffUtilCallback) { - - override fun getItemId(position: Int): Long { - return currentList[position].currency.currencySymbol.hashCode().toLong() - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WalletsViewHolder { - val layout = ItemCurrencyWalletBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false, - ) - return WalletsViewHolder(layout) - } - - override fun onBindViewHolder(holder: WalletsViewHolder, position: Int) { - holder.bind(currentList[position]) - } - - object DiffUtilCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame(oldItem: WalletDataModel, newItem: WalletDataModel) = oldItem == newItem - - override fun areItemsTheSame(oldItem: WalletDataModel, newItem: WalletDataModel) = oldItem == newItem - } - - class WalletsViewHolder(val binding: ItemCurrencyWalletBinding) : - RecyclerView.ViewHolder(binding.root) { - - fun bind(wallet: WalletDataModel) = with(binding) { - val status = wallet.status - val fiatCurrency = store.state.globalState.appCurrency - - val statusMessage = when (status) { - is WalletDataModel.TransactionInProgress -> { - root.getString(R.string.wallet_balance_tx_in_progress) - } - is WalletDataModel.Unreachable -> { - // TODO: Delete with WalletFeatureToggles - // root.getString(R.string.wallet_balance_blockchain_unreachable) - } - is WalletDataModel.MissedDerivation -> { - root.getString(R.string.wallet_balance_missing_derivation) - } - else -> null - } - - if (status is WalletDataModel.Loading) { - lContent.root.hide() - lShimmer.root.veil() - } else { - lShimmer.root.unVeil() - lContent.root.show() - } - - ivCurrency.load( - currency = wallet.currency, - derivationStyle = store.state.globalState.scanResponse - ?.derivationStyleProvider?.getDerivationStyle(), - ) - - lContent.tvCurrency.text = wallet.currency.currencyName - lContent.tvAmountFiat.text = wallet.getFormattedFiatAmount(fiatCurrency) - lContent.tvAmount.text = wallet.getFormattedCryptoAmount() - - lContent.tvStatus.isVisible = statusMessage != null - // lContent.tvStatus.text = statusMessage - - lContent.tvExchangeRate.isVisible = statusMessage == null - lContent.tvExchangeRate.text = wallet.getFormattedFiatRate( - fiatCurrency = fiatCurrency, - noRateValue = root.getString(id = R.string.token_item_no_rate), - ) - - if (wallet.walletAddresses != null) { - cardWallet.setOnClickListener { - Analytics.send(Portfolio.TokenTapped()) - store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet.currency)) - } - } else { - cardWallet.setOnClickListener(null) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletDetailWarningMessagesAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletDetailWarningMessagesAdapter.kt deleted file mode 100644 index 95be9ce597..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletDetailWarningMessagesAdapter.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.tangem.tap.features.wallet.ui.adapters - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView -import com.tangem.tap.common.extensions.getColor -import com.tangem.tap.features.wallet.models.WalletWarningDescription -import com.tangem.wallet.R -import com.tangem.wallet.databinding.LayoutWarningCardBinding - -/** -[REDACTED_AUTHOR] - */ -class WalletDetailWarningMessagesAdapter : - ListAdapter(DiffUtilCallback()) { - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WalletDetailsWarningMessageVH { - val inflater = LayoutInflater.from(parent.context) - val binding = LayoutWarningCardBinding.inflate(inflater, parent, false) - - return WalletDetailsWarningMessageVH(binding) - } - - override fun onBindViewHolder(holder: WalletDetailsWarningMessageVH, position: Int) { - holder.bind(currentList[position]) - } - - private class DiffUtilCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame(oldItem: WalletWarningDescription, newItem: WalletWarningDescription) = - oldItem == newItem - - override fun areItemsTheSame(oldItem: WalletWarningDescription, newItem: WalletWarningDescription) = - oldItem == newItem - } -} - -class WalletDetailsWarningMessageVH( - val binding: LayoutWarningCardBinding, -) : RecyclerView.ViewHolder(binding.root) { - - fun bind(warning: WalletWarningDescription) { - binding.warningCard.setCardBackgroundColor(binding.root.getColor(R.color.darkGray2)) - setText(warning) - } - - private fun setText(warning: WalletWarningDescription) = with(binding.warningContentContainer) { - tvTitle.text = warning.title - tvMessage.text = warning.message - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/analytics/WalletAnalyticsEventsMapper.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/analytics/WalletAnalyticsEventsMapper.kt deleted file mode 100644 index 184e85983c..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/analytics/WalletAnalyticsEventsMapper.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.tangem.tap.features.wallet.ui.analytics - -import com.tangem.tap.common.analytics.events.AnalyticsParam -import com.tangem.tap.common.extensions.isGreaterThan -import com.tangem.tap.domain.model.TotalFiatBalance -import com.tangem.utils.converter.Converter -import java.math.BigDecimal - -class WalletAnalyticsEventsMapper : Converter { - - override fun convert(value: TotalFiatBalance): AnalyticsParam.CardBalanceState? { - return when (value) { - is TotalFiatBalance.Failed -> AnalyticsParam.CardBalanceState.BlockchainError - is TotalFiatBalance.Loaded -> when { - value.isWarning -> AnalyticsParam.CardBalanceState.CustomToken - value.amount.isGreaterThan(BigDecimal.ZERO) -> AnalyticsParam.CardBalanceState.Full - else -> AnalyticsParam.CardBalanceState.Empty - } - is TotalFiatBalance.Loading -> null - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/AmountToSendBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/AmountToSendBottomSheetDialog.kt deleted file mode 100644 index 75cbe3010a..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/AmountToSendBottomSheetDialog.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.tangem.tap.features.wallet.ui.dialogs - -import android.content.Context -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.appcompat.view.ContextThemeWrapper -import androidx.recyclerview.widget.* -import com.google.android.material.bottomsheet.BottomSheetDialog -import com.tangem.blockchain.common.Amount -import com.tangem.tap.common.extensions.toFormattedString -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.models.WalletDialog -import com.tangem.tap.store -import com.tangem.wallet.R -import com.tangem.wallet.databinding.DialogWalletSendBinding -import com.tangem.wallet.databinding.ItemWalletAmountToSendBinding - -class AmountToSendBottomSheetDialog( - context: Context, - private val dialog: WalletDialog.SelectAmountToSendDialog, -) : BottomSheetDialog(context) { - - var binding: DialogWalletSendBinding? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = DialogWalletSendBinding.inflate(LayoutInflater.from(context)) - setContentView(binding!!.root) - } - - override fun show() { - super.show() - - setOnDismissListener { - binding = null - store.dispatch(WalletAction.DialogAction.Hide) - } - - binding!!.rvAmountsToSend.layoutManager = LinearLayoutManager(context) - val dividerItemDecoration = DividerItemDecoration( - ContextThemeWrapper(binding!!.root.context, R.style.AppTheme), - DividerItemDecoration.VERTICAL, - ) - binding!!.rvAmountsToSend.addItemDecoration(dividerItemDecoration) - - val viewAdapter = ChooseAmountAdapter() - binding!!.rvAmountsToSend.adapter = viewAdapter - - viewAdapter.submitList(dialog.amounts) - } -} - -private class ChooseAmountAdapter : ListAdapter(DiffUtilCallback) { - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AmountViewHolder { - val binding = ItemWalletAmountToSendBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false, - ) - return AmountViewHolder(binding) - } - - override fun onBindViewHolder(holder: AmountViewHolder, position: Int) { - holder.bind(currentList[position]) - } - - object DiffUtilCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame(oldItem: Amount, newItem: Amount) = - oldItem.currencySymbol == newItem.currencySymbol - - override fun areItemsTheSame(oldItem: Amount, newItem: Amount) = oldItem == newItem - } - - class AmountViewHolder(val binding: ItemWalletAmountToSendBinding) : - RecyclerView.ViewHolder(binding.root) { - - fun bind(amount: Amount) = with(binding) { - tvCurrencySymbol.text = amount.currencySymbol - tvAmount.text = amount.value?.toFormattedString(amount.decimals) - root.setOnClickListener { - store.dispatch(WalletAction.DialogAction.Hide) - store.dispatch(WalletAction.Send(amount)) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ChooseTradeActionBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ChooseTradeActionBottomSheetDialog.kt deleted file mode 100644 index 25ce55e44c..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ChooseTradeActionBottomSheetDialog.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.tangem.tap.features.wallet.ui.dialogs - -import android.content.Context -import android.os.Bundle -import android.view.LayoutInflater -import com.google.android.material.bottomsheet.BottomSheetDialog -import com.tangem.domain.tokens.legacy.TradeCryptoAction -import com.tangem.tap.common.extensions.show -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.models.WalletDialog -import com.tangem.tap.store -import com.tangem.wallet.databinding.DialogWalletTradeBinding - -class ChooseTradeActionBottomSheetDialog( - context: Context, - private val dialogData: WalletDialog.ChooseTradeActionDialog, -) : BottomSheetDialog(context) { - - var binding: DialogWalletTradeBinding? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = DialogWalletTradeBinding.inflate(LayoutInflater.from(context)) - setContentView(binding!!.root) - } - - override fun show() { - super.show() - - this.setOnDismissListener { - binding = null - store.dispatch(WalletAction.DialogAction.Hide) - } - - binding?.let { - with(it) { - dialogBtnBuy.show(dialogData.buyAllowed) - dialogBtnSell.show(dialogData.sellAllowed) - dialogBtnSwap.show(dialogData.swapAllowed) - - dialogBtnBuy.setOnClickListener { - dismiss() - store.dispatch(TradeCryptoAction.Buy()) - } - dialogBtnSell.setOnClickListener { - dismiss() - store.dispatch(TradeCryptoAction.Sell) - } - dialogBtnSwap.setOnClickListener { - dismiss() - store.dispatch(TradeCryptoAction.Swap) - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt deleted file mode 100644 index f4f2a4c143..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt +++ /dev/null @@ -1,57 +0,0 @@ -package com.tangem.tap.features.wallet.ui.dialogs - -import android.content.Context -import android.os.Bundle -import android.view.LayoutInflater -import com.google.android.material.bottomsheet.BottomSheetDialog -import com.tangem.core.analytics.Analytics -import com.tangem.core.navigation.NavigationAction -import com.tangem.domain.tokens.legacy.TradeCryptoAction -import com.tangem.tap.common.analytics.events.Token -import com.tangem.tap.common.extensions.dispatchDialogHide -import com.tangem.tap.common.extensions.dispatchOpenUrl -import com.tangem.tap.features.wallet.redux.models.WalletDialog -import com.tangem.tap.store -import com.tangem.wallet.databinding.DialogRussiansCardholdersWarningBinding - -class RussianCardholdersWarningBottomSheetDialog( - context: Context, - private val dialogData: WalletDialog.RussianCardholdersWarningDialog.Data?, -) : BottomSheetDialog(context) { - - private var binding: DialogRussiansCardholdersWarningBinding? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - Analytics.send(Token.Topup.P2PScreenOpened()) - binding = DialogRussiansCardholdersWarningBinding - .inflate(LayoutInflater.from(context)) - .also { setContentView(it.root) } - } - - override fun show() { - super.show() - setOnDismissListener { - binding = null - store.dispatchDialogHide() - } - - binding?.btnYes?.setOnClickListener { - if (dialogData != null) { - store.dispatchOpenUrl(dialogData.topUpUrl) - Analytics.send(Token.Topup.ScreenOpened()) - } else { - store.dispatch(TradeCryptoAction.Buy(checkUserLocation = false)) - } - dismiss() - } - binding?.btnNo?.setOnClickListener { - store.dispatch(NavigationAction.OpenUrl(INSTRUCTION_URL)) - dismiss() - } - } - - companion object { - private const val INSTRUCTION_URL = "https://tangem.com/howtobuy.html" - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt deleted file mode 100644 index 30d7d0b8e4..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.tangem.tap.features.wallet.ui.dialogs - -import android.content.Context -import androidx.appcompat.app.AlertDialog -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.tangem.core.analytics.Analytics -import com.tangem.tap.common.analytics.events.IntroductionProcess -import com.tangem.tap.common.extensions.dispatchDialogHide -import com.tangem.tap.common.feedback.ScanFailsEmail -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.store -import com.tangem.wallet.R - -/** -[REDACTED_AUTHOR] - */ -object ScanFailsDialog { - fun create(context: Context): AlertDialog { - return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply { - setTitle(context.getString(R.string.common_warning)) - setMessage(R.string.alert_troubleshooting_scan_card_title) - setPositiveButton(R.string.alert_button_request_support) { _, _ -> - Analytics.send(IntroductionProcess.ButtonRequestSupport()) - store.dispatch(GlobalAction.SendEmail(ScanFailsEmail())) - } - setNeutralButton(R.string.common_cancel) { _, _ -> } - setOnDismissListener { store.dispatchDialogHide() } - }.create() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SignedHashesWarningDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SignedHashesWarningDialog.kt deleted file mode 100644 index 8ebbffeb54..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SignedHashesWarningDialog.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.tangem.tap.features.wallet.ui.dialogs - -import android.content.Context -import androidx.appcompat.app.AlertDialog -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.store -import com.tangem.wallet.R - -// TODO: Delete with WalletFeatureToggles -@Deprecated(message = "Used only in old wallet screen") -object SignedHashesWarningDialog { - fun create(context: Context): AlertDialog { - return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply { - // setTitle(context.getString(R.string.warning_important_security_info, "\u26A0")) - // setMessage(R.string.alert_signed_hashes_message) - setPositiveButton(R.string.common_understand) { _, _ -> - store.dispatch(WalletAction.Warnings.CheckHashesCount.SaveCardId) - store.dispatch( - GlobalAction.HideWarningMessage(WarningMessagesManager.signedHashesMultiWalletWarning), - ) - } - setNegativeButton(R.string.common_cancel) { _, _ -> } - setOnDismissListener { - store.dispatch(WalletAction.DialogAction.Hide) - } - }.create() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SimpleOkDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SimpleOkDialog.kt deleted file mode 100644 index 9abf465eb0..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SimpleOkDialog.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.tangem.tap.features.wallet.ui.dialogs - -import android.content.Context -import androidx.appcompat.app.AlertDialog -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.tangem.tap.common.extensions.dispatchDialogHide -import com.tangem.tap.common.redux.AppDialog -import com.tangem.tap.store -import com.tangem.wallet.R - -/** -[REDACTED_AUTHOR] - */ -object SimpleOkDialog { - - fun create(dialog: AppDialog.SimpleOkDialog, context: Context): AlertDialog { - return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply { - setTitle(dialog.header) - setMessage(dialog.message) - setPositiveButton(R.string.common_ok) { _, _ -> } - setOnDismissListener { - store.dispatchDialogHide() - dialog.onOk?.invoke() - } - }.create() - } - - fun create(dialog: AppDialog.SimpleOkDialogRes, context: Context): AlertDialog { - val message = if (dialog.args.isEmpty()) { - context.getString(dialog.messageId) - } else { - context.getString(dialog.messageId, *dialog.args.toTypedArray()) - } - return AlertDialog.Builder(context).apply { - setTitle(context.getString(dialog.headerId)) - setMessage(message) - setPositiveButton(R.string.common_ok) { _, _ -> } - setOnDismissListener { - store.dispatchDialogHide() - dialog.onOk?.invoke() - } - }.create() - } - - fun create(dialog: AppDialog.SimpleOkErrorDialog, context: Context): AlertDialog = create( - dialog = AppDialog.SimpleOkDialog( - header = context.getString(R.string.common_error), - message = dialog.message, - onOk = dialog.onOk, - ), - context = context, - ) - - fun create(dialog: AppDialog.SimpleOkWarningDialog, context: Context): AlertDialog = create( - dialog = AppDialog.SimpleOkDialog( - header = context.getString(R.string.common_warning), - message = dialog.message, - onOk = dialog.onOk, - ), - context = context, - ) - - fun create(dialog: AppDialog.OkCancelDialogRes, context: Context): AlertDialog { - return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply { - setTitle(context.getString(dialog.headerId)) - setMessage(dialog.messageId) - setPositiveButton(dialog.okButton.title) { _, _ -> dialog.okButton.action?.invoke() } - setNegativeButton(dialog.cancelButton.title) { _, _ -> dialog.cancelButton.action?.invoke() } - setOnDismissListener { - store.dispatchDialogHide() - dialog.cancelButton.action?.invoke() - } - }.create() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconRequest.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconRequest.kt deleted file mode 100644 index 77ac36e571..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconRequest.kt +++ /dev/null @@ -1,172 +0,0 @@ -package com.tangem.tap.features.wallet.ui.images - -import android.widget.ImageView -import android.widget.TextView -import androidx.constraintlayout.utils.widget.ImageFilterView -import coil.imageLoader -import coil.request.ImageRequest -import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.IconsUtil -import com.tangem.blockchain.common.Token -import com.tangem.core.ui.extensions.getActiveIconRes -import com.tangem.domain.common.extensions.toCoinId -import com.tangem.domain.common.extensions.toNetworkId -import com.tangem.tap.common.extensions.getColor -import com.tangem.tap.common.extensions.getTextColor -import com.tangem.tap.domain.extensions.getCustomIconUrl -import com.tangem.tap.domain.tokens.getIconUrl -import com.tangem.wallet.R - -private const val QCX = "QCX" -private const val VOYR = "VOYRME" - -class CurrencyIconRequest( - private val currencyImageView: ImageFilterView, - private val currencyTextView: TextView?, - private val token: Token?, - private val blockchain: Blockchain, - private val getLocalImage: Boolean = false, -) { - fun load() { - when { - token == null && blockchain.isTestnet() -> loadTestnetBlockchainIcon() - token == null -> loadBlockchainIcon() - blockchain.isTestnet() -> loadTestnetTokenIcon() - else -> loadTokenIcon() - } - } - - private fun loadBlockchainIcon() { - loadBlockchainIconBase( - onStart = { - currencyImageView.colorFilter = null - }, - ) - } - - private fun loadTestnetBlockchainIcon() { - loadBlockchainIconBase( - onStart = { - currencyImageView.saturation = 0f - }, - ) - } - - private fun loadTokenIcon() { - loadTokenIconBase( - onStart = { - currencyImageView.setColorFilter(it.getColor()) - }, - onSuccess = { - currencyImageView.colorFilter = null - }, - onError = { - currencyImageView.setColorFilter(it.getColor()) - currencyTextView?.setTextColor(it.getTextColor()) - }, - ) - } - - private fun loadTestnetTokenIcon() { - loadTokenIconBase( - onStart = { - currencyImageView.saturation = 0f - }, - onError = { - currencyImageView.saturation = 0f - currencyImageView.setColorFilter(it.getColor(true)) - currencyTextView?.setTextColor(it.getTextColor(true)) - }, - ) - } - - private inline fun loadBlockchainIconBase( - crossinline onStart: (Blockchain) -> Unit = {}, - crossinline onSuccess: (Blockchain) -> Unit = {}, - crossinline onError: (Blockchain) -> Unit = {}, - ) { - currencyImageView.loadIcon( - data = getBlockchainIconData(blockchain), - placeholderRes = getActiveIconRes(blockchain.id), - onStart = { onStart(blockchain) }, - onSuccess = { onSuccess(blockchain) }, - onError = { onError(blockchain) }, - ) - } - - private fun getBlockchainIconData(blockchain: Blockchain): Any { - return if (getLocalImage) { - when (blockchain) { - Blockchain.TerraV1, Blockchain.TerraV2 -> getActiveIconRes(blockchain.toCoinId()) - else -> getActiveIconRes(blockchain.id) - } - } else { - when (blockchain) { - Blockchain.TerraV1, Blockchain.TerraV2 -> getIconUrl(blockchain.toCoinId()) - else -> getIconUrl(blockchain.toNetworkId()) - } - } - } - - private inline fun loadTokenIconBase( - crossinline onStart: (Token) -> Unit = {}, - crossinline onSuccess: (Token) -> Unit = {}, - crossinline onError: (Token) -> Unit = {}, - ) { - if (token == null) return - - currencyImageView.loadIcon( - data = getTokenIcon(token, blockchain), - placeholderRes = R.drawable.shape_circle, - onStart = { - currencyTextView?.text = token.name.take(1) - currencyTextView?.setTextColor(token.getTextColor()) - onStart(token) - }, - onSuccess = { - currencyTextView?.text = null - onSuccess(token) - }, - onError = { - // for some reason the onStart doesn't call if an error occurs - currencyTextView?.text = token.name.take(1) - onError(token) - }, - ) - } -} - -private inline fun ImageView.loadIcon( - data: Any?, - placeholderRes: Int, - crossinline onStart: () -> Unit = {}, - crossinline onSuccess: () -> Unit = {}, - crossinline onError: () -> Unit = {}, -) { - ImageRequest.Builder(context) - .data(data) - .placeholder(placeholderRes) - .error(placeholderRes) - .fallback(placeholderRes) - .listener( - onStart = { onStart() }, - onSuccess = { _, _ -> onSuccess() }, - onError = { _, _ -> onError() }, - ) - .target(imageView = this) - .build() - .also(context.imageLoader::enqueue) -} - -private fun getTokenIcon(token: Token, blockchain: Blockchain): Any? { - return when (token.symbol) { - QCX -> R.drawable.ic_qcx - VOYR -> R.drawable.ic_voyr - else -> { - token.id?.let(::getIconUrl) - ?: token.getCustomIconUrl() - ?: IconsUtil.getTokenIconUri(blockchain, token) - ?.toString() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt deleted file mode 100644 index 1eb8c65fd9..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.tangem.tap.features.wallet.ui.images - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.widget.TextView -import androidx.constraintlayout.utils.widget.ImageFilterView -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.core.view.isVisible -import com.tangem.blockchain.common.derivation.DerivationStyle -import com.tangem.sdk.extensions.dpToPx -import com.tangem.tap.features.wallet.models.Currency -import com.tangem.wallet.databinding.ViewCurrencyIconBinding -import kotlin.math.roundToInt - -@Suppress("MagicNumber") -class CurrencyIconView @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, -) : ConstraintLayout(context, attrs, defStyleAttr) { - private val binding = ViewCurrencyIconBinding.inflate( - LayoutInflater.from(context), - this, - ) - - val currencyImageView: ImageFilterView - get() = binding.ivCurrency - - val currencyTextView: TextView - get() = binding.tvTokenLetter - - val blockchainBadge: ImageFilterView - get() = binding.ivBlockchainBadge - - var isBlockchainBadgeVisible: Boolean - get() = binding.ivBlockchainBadge.isVisible - set(value) = binding.ivBlockchainBadge::isVisible.set(value) - - var isCustomCurrencyBadgeVisible: Boolean - get() = binding.customBadge.isVisible - set(value) = binding.customBadge::isVisible.set(value) - - init { - minWidth = dpToPx(48f).roundToInt() - minHeight = dpToPx(48f).roundToInt() - } -} - -fun CurrencyIconView.load(currency: Currency, derivationStyle: DerivationStyle?) { - isCustomCurrencyBadgeVisible = currency.isCustomCurrency(derivationStyle) - - CurrencyIconRequest( - currencyImageView = currencyImageView, - currencyTextView = currencyTextView, - token = (currency as? Currency.Token)?.token, - blockchain = currency.blockchain, - ).load() - - if (currency.isToken()) { - // load a blockchain icon into the blockchain badge - isBlockchainBadgeVisible = true - - CurrencyIconRequest( - currencyImageView = blockchainBadge, - currencyTextView = null, - token = null, - blockchain = currency.blockchain, - getLocalImage = true, - ).load() - } else { - isBlockchainBadgeVisible = false - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWallet.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWallet.kt deleted file mode 100644 index 188cf35d91..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWallet.kt +++ /dev/null @@ -1,160 +0,0 @@ -package com.tangem.tap.features.wallet.ui.test - -import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Token -import com.tangem.blockchain.common.WalletManager -import com.tangem.common.extensions.guard -import com.tangem.domain.common.BlockchainNetwork -import com.tangem.tap.common.TestAction -import com.tangem.tap.common.TestActions -import com.tangem.tap.common.extensions.dispatchDebugErrorNotification -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.store -import java.math.BigDecimal -import kotlin.random.Random - -/** -[REDACTED_AUTHOR] - */ -object TestWallet { - fun solanaRentExemptWarning(): List { - val checker = SolanaRentWarningActionEmitter() - return listOf( - "BALANCE = 0.0" to { checker.setZeroBalance() }, - "BALANCE < 0.00089088" to { checker.setLessThanRentExempt() }, - "BALANCE > 0.00089088" to { checker.setMoreThanRentExempt() }, - "BALANCE = 0.00089087" to { checker.setLessThanRentExemptByOne() }, - "BALANCE = 0.00089088 (rent exempt)" to { checker.setForRentExemptBarrier() }, - "BALANCE = 0.00089089" to { checker.setMoreThanRentExemptByOne() }, - ) - } - - fun getBlockchainBalanceActions(blockchainNetwork: BlockchainNetwork): List { - return getBlockchainBalanceActions( - getWalletManager(blockchainNetwork), - blockchainNetwork.blockchain.decimals(), - ) - } - - fun getTokenBalanceAction(blockchainNetwork: BlockchainNetwork, token: Token): List { - return getTokenBalanceAction(getWalletManager(blockchainNetwork), token) - } - - fun getBlockchainBalanceActions(walletManager: WalletManager?, decimals: Int): List { - val minValue = BigDecimal.ONE.movePointLeft(decimals) - val averageValue = BigDecimal.ONE.movePointRight(decimals) - .divide(BigDecimal(2)).movePointLeft(decimals) - val maxValue = BigDecimal(2).pow(32) - - return listOf( - "0.0" to { setBalance(walletManager, BigDecimal.ZERO) }, - "Min value" to { setBalance(walletManager, minValue) }, - "Average value" to { setBalance(walletManager, averageValue) }, - "Max value" to { setBalance(walletManager, maxValue) }, - "1234567890123.01234567890123" to { setBalance(walletManager, BigDecimal.ZERO) }, - ) - } - - fun getTokenBalanceAction(walletManager: WalletManager?, token: Token): List { - val minValue = BigDecimal.ONE.movePointLeft(token.decimals) - val averageValue = BigDecimal.ONE.movePointRight(token.decimals) - .divide(BigDecimal(2)).movePointLeft(token.decimals) - val maxValue = BigDecimal(2).pow(32) - - return listOf( - "0.0" to { setTokenBalance(walletManager, BigDecimal.ZERO, token) }, - "Min value" to { setTokenBalance(walletManager, minValue, token) }, - "Average value" to { setTokenBalance(walletManager, averageValue, token) }, - "Max value" to { setTokenBalance(walletManager, maxValue, token) }, - "1234567890123.01234567890123" to { setTokenBalance(walletManager, BigDecimal.ZERO, token) }, - ) - } - - fun setBalance(walletManager: WalletManager?, value: BigDecimal) { - val manager = walletManager.guard { - store.dispatchDebugErrorNotification("WalletManager not found") - return - } - val amount = manager.wallet.amounts[AmountType.Coin] ?: Amount(manager.wallet.blockchain) - setBalance(manager, amount, value) - } - - private fun setTokenBalance(walletManager: WalletManager?, value: BigDecimal, token: Token? = null) { - val manager = walletManager.guard { - store.dispatchDebugErrorNotification("WalletManager not found") - return - } - val token = token.guard { - store.dispatchDebugErrorNotification("Token not found") - return - } - - val amount = manager.wallet.amounts[AmountType.Token(token)] ?: Amount(token) - setBalance(manager, amount, value) - } - - private fun setBalance(walletManager: WalletManager, amount: Amount, value: BigDecimal) { - TestActions.testAmountInjectionForWalletManagerEnabled = true - walletManager.wallet.setAmount(amount.copy(value = value)) - store.dispatch(WalletAction.LoadData) - } - - private fun getWalletManager(blockchainNetwork: BlockchainNetwork): WalletManager? { - return store.state.walletState.getWalletManager(blockchainNetwork) - } -} - -private class SolanaRentWarningActionEmitter { - - private val zero = BigDecimal.ZERO - private val one = BigDecimal(0.00000001) - private val rentExemptBarrier = BigDecimal(0.00089088) - private val lessThanRentExemptByOne = rentExemptBarrier.minus(one) - private val moreThanRentExemptByOne = rentExemptBarrier.plus(one) - private val moreThanRentExempt = rentExemptBarrier.plus(Random.nextDouble().toBigDecimal()) - private val lessThanRentExempt = rentExemptBarrier - .minus(Random.nextDouble(0.0, rentExemptBarrier.minus(one).toDouble()).toBigDecimal()) - - fun setZeroBalance() { - setBalance(zero) - } - - fun setForRentExemptBarrier() { - setBalance(rentExemptBarrier) - } - - fun setLessThanRentExemptByOne() { - setBalance(lessThanRentExemptByOne) - } - - fun setMoreThanRentExemptByOne() { - setBalance(moreThanRentExemptByOne) - } - - fun setMoreThanRentExempt() { - setBalance(moreThanRentExempt) - } - - fun setLessThanRentExempt() { - setBalance(lessThanRentExempt) - } - - private fun setBalance(value: BigDecimal) { - val amount = Amount(getBlockchainNetwork().blockchain).copy(value = value) - getWalletManager().apply { - TestActions.testAmountInjectionForWalletManagerEnabled = true - wallet.setAmount(amount) - } - store.dispatch(WalletAction.LoadData) - } - - private fun getWalletManager(): WalletManager { - return store.state.walletState.getWalletManager(getBlockchainNetwork())!! - } - - private fun getBlockchainNetwork(): BlockchainNetwork { - val currency = store.state.walletState.selectedWalletData!!.currency - return BlockchainNetwork(currency.blockchain, currency.derivationPath, listOf()) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt deleted file mode 100644 index 7a43921862..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/utils/WalletDataOperations.kt +++ /dev/null @@ -1,164 +0,0 @@ -package com.tangem.tap.features.wallet.ui.utils - -import com.tangem.blockchain.common.Blockchain -import com.tangem.common.extensions.isZero -import com.tangem.domain.common.extensions.toNetworkId -import com.tangem.feature.swap.api.SwapFeatureToggleManager -import com.tangem.feature.swap.domain.SwapInteractor -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.toFormattedCryptoCurrencyString -import com.tangem.tap.common.extensions.toFormattedFiatValue -import com.tangem.tap.domain.model.WalletDataModel -import com.tangem.tap.domain.model.WalletStoreModel -import com.tangem.tap.features.wallet.models.PendingTransactionType -import com.tangem.tap.features.wallet.models.WalletWarning -import com.tangem.tap.features.wallet.redux.WalletMainButton -import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN -import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager -import java.math.BigDecimal - -internal fun WalletDataModel.mainButton(blockchainAmount: BigDecimal): WalletMainButton = WalletMainButton.SendButton( - enabled = !isEmptyAmount && - hasPendingTransactions() && - !blockchainAmount.isZero(), -) - -internal fun WalletDataModel.hasPendingTransactions(): Boolean { - // for now check pending ongoing only just for BTC, later test and add other utxo networks - val isBitcoinBlockchain = - currency.blockchain == Blockchain.Bitcoin || currency.blockchain == Blockchain.BitcoinTestnet - if (currency.isBlockchain() && isBitcoinBlockchain) { - val outgoingTransactions = status.pendingTransactions.filter { - it.type == PendingTransactionType.Outgoing - } - return outgoingTransactions.isEmpty() - } - return status.pendingTransactions.isEmpty() -} - -internal fun WalletDataModel.getFormattedCryptoAmount(): String { - return status.amount.toFormattedCryptoCurrencyString( - decimals = currency.decimals, - currency = currency.currencySymbol, - ) -} - -internal fun WalletDataModel.getFormattedFiatAmount( - fiatCurrency: FiatCurrency, - unknownAmountSign: String = UNKNOWN_AMOUNT_SIGN, -): String { - return this.fiatRate?.let { status.amount.toFiatValue(it) } - ?.takeIf { !status.isErrorStatus } - ?.toFormattedFiatValue(fiatCurrencyName = fiatCurrency.symbol, fiatCode = fiatCurrency.code) - ?: unknownAmountSign -} - -internal fun WalletDataModel.getFormattedFiatRate(fiatCurrency: FiatCurrency, noRateValue: String): String { - return fiatRate?.toFiatRateString(fiatCurrency.symbol, fiatCurrency.code) - ?: noRateValue -} - -internal fun WalletDataModel.isAvailableToBuy(exchangeManager: CurrencyExchangeManager): Boolean { - return exchangeManager.availableForBuy(currency) -} - -internal fun WalletDataModel.isAvailableToSell(exchangeManager: CurrencyExchangeManager): Boolean { - return exchangeManager.availableForSell(currency) -} - -internal fun WalletDataModel.isAvailableToSwap( - swapFeatureToggleManager: SwapFeatureToggleManager, - swapInteractor: SwapInteractor, - isSingleWallet: Boolean, -): Boolean { - if (isSingleWallet) { - return false - } - if (currency.blockchain.id == Blockchain.Optimism.id && !swapFeatureToggleManager.isOptimismSwapEnabled) { - return false - } - return swapInteractor.isAvailableToSwap(currency.blockchain.toNetworkId()) && - !currency.isCustomCurrency(null) -} - -internal fun WalletDataModel.getAvailableActions( - swapInteractor: SwapInteractor, - exchangeManager: CurrencyExchangeManager, - swapFeatureToggleManager: SwapFeatureToggleManager, - isSingleWallet: Boolean, -): Set { - return setOfNotNull( - if (isAvailableToBuy(exchangeManager)) CurrencyAction.Buy else null, - if (isAvailableToSell(exchangeManager)) CurrencyAction.Sell else null, - if (isAvailableToSwap(swapFeatureToggleManager, swapInteractor, isSingleWallet)) CurrencyAction.Swap else null, - ) -} - -internal fun WalletDataModel.shouldShowMultipleAddress(): Boolean { - val listOfAddresses = walletAddresses?.list.orEmpty() - return listOfAddresses.size > 1 -} - -internal fun WalletDataModel.assembleWarnings( - blockchainAmount: BigDecimal, - blockchainWalletRent: WalletStoreModel.WalletRent?, -): List { - val walletWarnings = mutableListOf() - assembleNonTypedWarnings(walletWarnings, blockchainWalletRent) - assembleBlockchainWarnings(walletWarnings) - assembleTokenWarnings(walletWarnings, blockchainAmount) - - return walletWarnings.sortedBy { it.showingPosition } -} - -private fun WalletDataModel.assembleNonTypedWarnings( - walletWarnings: MutableList, - walletRent: WalletStoreModel.WalletRent?, -) { - if (this.status is WalletDataModel.SameCurrencyTransactionInProgress) { - walletWarnings.add(WalletWarning.TransactionInProgress(currency.currencyName)) - } - if (walletRent != null) { - walletWarnings.add(WalletWarning.Rent(walletRent)) - } -} - -private fun WalletDataModel.assembleBlockchainWarnings(walletWarnings: MutableList) { - with(currency) { - if (!isBlockchain()) return - - if (existentialDeposit != null) { - val warning = WalletWarning.ExistentialDeposit( - currencyName = currencyName, - edStringValueWithSymbol = "${existentialDeposit.toPlainString()} $currencySymbol", - ) - walletWarnings.add(warning) - } - } -} - -private fun WalletDataModel.assembleTokenWarnings( - walletWarnings: MutableList, - blockchainAmount: BigDecimal, -) { - if (!currency.isToken()) return - - if (!this.isEmptyAmount && blockchainAmount.isZero()) { - walletWarnings.add( - WalletWarning.BalanceNotEnoughForFee( - currencyName = currency.currencyName, - blockchainFullName = currency.blockchain.fullName, - blockchainSymbol = currency.blockchain.currency, - ), - ) - } -} - -private val WalletDataModel.isEmptyAmount: Boolean - get() = this.status.amount.isZero() - -enum class CurrencyAction { - Buy, Sell, Swap -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt deleted file mode 100644 index d39bf43e05..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/TotalBalanceCard.kt +++ /dev/null @@ -1,355 +0,0 @@ -package com.tangem.tap.features.wallet.ui.view - -import android.content.Context -import android.util.AttributeSet -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.material.Divider -import androidx.compose.material.Surface -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.AbstractComposeView -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview -import com.tangem.core.ui.components.* -import com.tangem.core.ui.res.TangemTheme -import com.tangem.tap.common.entities.FiatCurrency -import com.tangem.tap.domain.model.TotalFiatBalance -import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN -import com.tangem.wallet.R -import com.valentinilk.shimmer.shimmer -import timber.log.Timber -import java.math.BigDecimal -import java.math.RoundingMode -import java.text.DecimalFormat -import java.text.NumberFormat -import java.util.Currency -import java.util.Locale - -internal class TotalBalanceCard @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, -) : AbstractComposeView(context, attrs, defStyleAttr) { - private var state by mutableStateOf(TotalBalanceCardState.Empty) - - var status: TotalFiatBalance? = null - set(value) { - if (field == value) return - field = value - updateState(value, fiatCurrency, onChangeFiatCurrencyClick) - } - - var onChangeFiatCurrencyClick: () -> Unit = { /* no-op */ } - set(value) { - if (field == value) return - field = value - updateState(status, fiatCurrency, value) - } - - var fiatCurrency: FiatCurrency = FiatCurrency.Default - set(value) { - if (field == value) return - field = value - updateState(status, value, onChangeFiatCurrencyClick) - } - - @Composable - override fun Content() { - TangemTheme { - TotalBalanceCardContent(state = state) - } - } - - override fun getAccessibilityClassName(): CharSequence { - return javaClass.name - } - - private fun updateState(status: TotalFiatBalance?, fiatCurrency: FiatCurrency, onChangeCurrencyClick: () -> Unit) { - state = when (status) { - null -> TotalBalanceCardState.Empty - is TotalFiatBalance.Failed -> TotalBalanceCardState.Failure( - fiatCurrency = fiatCurrency, - onChangeFiatCurrencyClick = onChangeCurrencyClick, - ) - is TotalFiatBalance.Loading -> TotalBalanceCardState.Loading( - fiatCurrency = fiatCurrency, - onChangeFiatCurrencyClick = onChangeCurrencyClick, - ) - is TotalFiatBalance.Loaded -> TotalBalanceCardState.Success( - amount = status.amount, - showWarning = status.isWarning, - onChangeFiatCurrencyClick = onChangeCurrencyClick, - fiatCurrency = fiatCurrency, - ) - } - } -} - -@Composable -private fun TotalBalanceCardContent(state: TotalBalanceCardState, modifier: Modifier = Modifier) { - TotalBalanceCardScaffold( - modifier = modifier, - title = { - Text( - text = stringResource(id = R.string.main_page_balance), - style = TangemTheme.typography.subtitle2, - color = TangemTheme.colors.text.tertiary, - ) - }, - amount = { - when (state) { - is TotalBalanceCardState.Empty, - is TotalBalanceCardState.Loading, - -> LoadingAmount() - is TotalBalanceCardState.Failure, - is TotalBalanceCardState.Success, - -> LoadedAmount( - amount = buildAmountString( - amount = state.amount, - fiatCurrency = state.fiatCurrency, - ), - ) - } - }, - currencySelector = { - if (state !is TotalBalanceCardState.Empty) { - SelectorButton( - text = state.fiatCurrency.code, - onClick = state.onChangeFiatCurrencyClick, - ) - } - }, - warningText = { - AnimatedVisibility(visible = state.showWarning) { - Text( - modifier = Modifier.fillMaxWidth(), - text = stringResource(id = R.string.main_processing_full_amount), - style = TangemTheme.typography.caption2, - color = TangemTheme.colors.text.attention, - ) - } - }, - ) -} - -@Composable -private fun TotalBalanceCardScaffold( - title: @Composable () -> Unit, - amount: @Composable () -> Unit, - currencySelector: @Composable () -> Unit, - warningText: @Composable () -> Unit, - modifier: Modifier = Modifier, - amountWeight: Float = 0.8f, -) { - Surface( - modifier = modifier, - shape = TangemTheme.shapes.roundedCornersMedium, - color = TangemTheme.colors.background.plain, - elevation = TangemTheme.dimens.elevation1, - ) { - Column( - modifier = Modifier.fillMaxWidth(), - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.Top, - ) { - SpacerW16() - Column( - modifier = Modifier.weight(amountWeight), - ) { - SpacerH12() - title() - SpacerH4() - amount() - } - currencySelector() - SpacerW4() - } - SpacerH4() - Box( - modifier = Modifier.padding( - horizontal = TangemTheme.dimens.spacing16, - ), - ) { - warningText() - } - SpacerH12() - } - } -} - -@Composable -private fun LoadingAmount(modifier: Modifier = Modifier) { - Box(modifier = modifier.shimmer()) { - Box( - modifier = Modifier - .width(TangemTheme.dimens.size116) - .height(TangemTheme.dimens.size32) - .background( - color = TangemTheme.colors.stroke.primary, - shape = TangemTheme.shapes.roundedCornersSmall2, - ), - ) - } -} - -@Composable -private fun LoadedAmount(amount: AnnotatedString, modifier: Modifier = Modifier) { - Box(modifier = modifier) { - Text( - text = amount, - style = TangemTheme.typography.h2, - color = TangemTheme.colors.text.primary1, - overflow = TextOverflow.Ellipsis, - maxLines = 1, - ) - } -} - -@Composable -private fun buildAmountString(amount: BigDecimal?, fiatCurrency: FiatCurrency): AnnotatedString { - if (amount == null) return AnnotatedString(text = UNKNOWN_AMOUNT_SIGN) - - val locale = Locale.getDefault() - val fractionDigits = 2 - val formatter = NumberFormat.getCurrencyInstance(locale) as? DecimalFormat - ?: return AnnotatedString("${amount.toPlainString()} ${fiatCurrency.symbol}") - - val currencyToShow = "${fiatCurrency.symbol} " - val scaledAmount = try { - Currency.getInstance(fiatCurrency.code)?.let { currency -> - formatter.currency = currency - formatter.maximumFractionDigits = fractionDigits - formatter.minimumFractionDigits = fractionDigits - formatter.isGroupingUsed = true - formatter.roundingMode = RoundingMode.HALF_UP - formatter.format(amount).replace(currency.symbol, currencyToShow) - } ?: formatter.format(amount) - } catch (e: IllegalArgumentException) { - Timber.e("TotalBalanceCard buildAmountString currencyCode is not a supported ISO 4217 code: $e") - formatter.currency?.let { - formatter.format(amount).replace(it.symbol, currencyToShow) - } ?: formatter.format(amount) - } - - val integer = scaledAmount.substringBefore(formatter.decimalFormatSymbols.decimalSeparator) - var reminder = scaledAmount.substringAfter(formatter.decimalFormatSymbols.decimalSeparator) - - // if locale formatted currency at the end, remember it and place out of AnnotatedString - val currency = if (reminder.endsWith(currencyToShow)) { - reminder = reminder.dropLast(currencyToShow.length) - currencyToShow - } else { - "" - } - - return buildAnnotatedString { - append(integer) - append(formatter.decimalFormatSymbols.decimalSeparator) - append( - AnnotatedString( - text = reminder, - spanStyle = TangemTheme.typography.h3.toSpanStyle(), - ), - ) - append(currency) // it is not empty if was placed at the end after locale formatting - } -} - -private sealed interface TotalBalanceCardState { - val amount: BigDecimal? - val showWarning: Boolean - val fiatCurrency: FiatCurrency - val onChangeFiatCurrencyClick: () -> Unit - - object Empty : TotalBalanceCardState { - override val amount: BigDecimal? = null - override val showWarning: Boolean = false - override val fiatCurrency: FiatCurrency = FiatCurrency.Default - override val onChangeFiatCurrencyClick: () -> Unit = { /* no-op */ } - } - - data class Loading( - override val fiatCurrency: FiatCurrency, - override val onChangeFiatCurrencyClick: () -> Unit, - ) : TotalBalanceCardState { - override val amount: BigDecimal = BigDecimal.ZERO - override val showWarning: Boolean = false - } - - data class Failure( - override val fiatCurrency: FiatCurrency, - override val onChangeFiatCurrencyClick: () -> Unit, - ) : TotalBalanceCardState { - override val amount: BigDecimal? = null - override val showWarning: Boolean = true - } - - data class Success( - override val amount: BigDecimal, - override val showWarning: Boolean, - override val fiatCurrency: FiatCurrency, - override val onChangeFiatCurrencyClick: () -> Unit, - ) : TotalBalanceCardState -} - -// region Preview -@Composable -private fun TotalBalanceCardContentSample(modifier: Modifier = Modifier) { - Column( - modifier = modifier - .background(TangemTheme.colors.background.primary) - .padding(all = TangemTheme.dimens.spacing16), - ) { - TotalBalanceCardContent(state = TotalBalanceCardState.Empty) - Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8)) - TotalBalanceCardContent( - state = TotalBalanceCardState.Loading(FiatCurrency("USD", "USD", "$")) {}, - ) - Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8)) - TotalBalanceCardContent( - state = TotalBalanceCardState.Failure( - onChangeFiatCurrencyClick = {}, - fiatCurrency = FiatCurrency("USD", "USD", "$"), - ), - ) - Divider(modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8)) - TotalBalanceCardContent( - state = TotalBalanceCardState.Success( - amount = BigDecimal("9917.72"), - showWarning = false, - onChangeFiatCurrencyClick = {}, - fiatCurrency = FiatCurrency("USD", "USD", "$"), - ), - ) - } -} - -@Preview(showBackground = true, widthDp = 360) -@Composable -private fun TotalBalanceCardContentPreview_Light() { - TangemTheme { - TotalBalanceCardContentSample() - } -} - -@Preview(showBackground = true, widthDp = 360) -@Composable -private fun TotalBalanceCardContentPreview_Dark() { - TangemTheme(isDark = true) { - TotalBalanceCardContentSample() - } -} -// endregion Preview \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt deleted file mode 100644 index d9bf31f00c..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.tangem.tap.features.wallet.ui.view - -import android.content.Context -import android.util.AttributeSet -import android.view.Gravity -import android.view.LayoutInflater -import android.widget.LinearLayout -import androidx.core.view.isVisible -import com.google.android.material.button.MaterialButton -import com.tangem.tap.common.extensions.hide -import com.tangem.tap.common.extensions.show -import com.tangem.tap.features.wallet.ui.utils.CurrencyAction -import com.tangem.wallet.databinding.ViewWalletDetailsButtonsRowBinding - -internal class WalletDetailsButtonsRow @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, -) : LinearLayout(context, attrs, defStyleAttr) { - private val binding = ViewWalletDetailsButtonsRowBinding.inflate( - LayoutInflater.from(context), - this, - ) - var onBuyClick: (() -> Unit)? = null - var onSellClick: (() -> Unit)? = null - var onTradeClick: (() -> Unit)? = null - var onSwapClick: (() -> Unit)? = null - var onSendClick: (() -> Unit)? = null - - init { - orientation = HORIZONTAL - - with(binding) { - btnBuy.setOnClickListener { onBuyClick?.invoke() } - btnSell.setOnClickListener { onSellClick?.invoke() } - btnSwap.setOnClickListener { onSwapClick?.invoke() } - btnTrade.setOnClickListener { onTradeClick?.invoke() } - btnSend.setOnClickListener { onSendClick?.invoke() } - } - } - - fun updateButtonsVisibility( - actions: Set, - exchangeServiceFeatureOn: Boolean, - sendAllowed: Boolean, - ) = with(binding) { - containerActionButtons.isVisible = exchangeServiceFeatureOn - - when { - actions.isEmpty() -> { - containerActionButtons.hide() - } - actions.size == 1 -> { - val action = actions.first() - btnTrade.hide() - btnBuy.show(action == CurrencyAction.Buy) - btnSell.show(action == CurrencyAction.Sell) - btnSwap.show(action == CurrencyAction.Swap) - } - else -> { - btnBuy.hide() - btnSell.hide() - btnSwap.hide() - btnTrade.show() - } - } - - if (containerActionButtons.isVisible) { - btnSend.gravity = Gravity.START or Gravity.CENTER_VERTICAL - btnSend.iconGravity = MaterialButton.ICON_GRAVITY_END - } else { - btnSend.gravity = Gravity.CENTER - btnSend.iconGravity = MaterialButton.ICON_GRAVITY_TEXT_END - } - btnSend.isEnabled = sendAllowed - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt deleted file mode 100644 index 51a29dfdba..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/CurrencySelectionDialog.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.tangem.tap.features.wallet.ui.wallet - -import android.content.Context -import androidx.appcompat.app.AlertDialog -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.models.WalletDialog -import com.tangem.tap.store -import com.tangem.wallet.R - -object CurrencySelectionDialog { - fun create(dialog: WalletDialog.CurrencySelectionDialog, context: Context): AlertDialog { - val currenciesToShow = dialog.currenciesList - .map { it.displayName } - .toTypedArray() - val currentSelection = dialog.currenciesList - .indexOfFirst { it.code == dialog.currentAppCurrency.code } - - return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog) - .setTitle(context.getString(R.string.details_row_title_currency)) - .setNegativeButton(context.getString(R.string.common_cancel)) { _, _ -> /* no-op */ } - .setOnDismissListener { - store.dispatch(WalletAction.DialogAction.Hide) - } - .setSingleChoiceItems(currenciesToShow, currentSelection) { _, which -> - dialog.currenciesList.getOrNull(which)?.let { selectedCurrency -> - store.dispatch( - WalletAction.AppCurrencyAction.SelectAppCurrency( - fiatCurrency = selectedCurrency, - ), - ) - store.dispatch(WalletAction.DialogAction.Hide) - } - } - .create() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt deleted file mode 100644 index 37789a8792..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt +++ /dev/null @@ -1,191 +0,0 @@ -package com.tangem.tap.features.wallet.ui.wallet - -import androidx.core.view.isVisible -import androidx.recyclerview.widget.LinearLayoutManager -import com.badoo.mvicore.modelWatcher -import com.tangem.core.analytics.Analytics -import com.tangem.core.navigation.AppScreen -import com.tangem.core.navigation.NavigationAction -import com.tangem.domain.tokens.TokensAction -import com.tangem.tap.common.analytics.events.MainScreen -import com.tangem.tap.common.analytics.events.Portfolio -import com.tangem.tap.common.entities.FiatCurrency -import com.tangem.tap.common.extensions.getQuantityString -import com.tangem.tap.common.extensions.hide -import com.tangem.tap.common.extensions.show -import com.tangem.tap.domain.model.TotalFiatBalance -import com.tangem.tap.features.wallet.redux.ErrorType -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletState -import com.tangem.tap.features.wallet.ui.WalletFragment -import com.tangem.tap.features.wallet.ui.adapters.WalletAdapter -import com.tangem.tap.store -import com.tangem.wallet.R -import com.tangem.wallet.databinding.FragmentWalletBinding - -class MultiWalletView : WalletView() { - - private lateinit var walletsAdapter: WalletAdapter - - private val watcher = modelWatcher { - // !!! Workaround !!! - // Checking state properties instead of state params can reduce application performance, - // but here it is necessary because the WalletStore has an unsuitable equals method - WalletState::walletsDataFromStores { - walletsAdapter.submitList(it) - } - WalletState::loadingUserTokens { - binding?.pbLoadingUserTokens?.show(it) - } - WalletState::walletCardsCount { walletCardsCount -> - binding?.let { - setupWalletCardNumber(it, walletCardsCount) - } - } - WalletState::missingDerivations { missingDerivations -> - binding?.let { - handleRescanWarning(it, missingDerivations.isNotEmpty()) - } - } - WalletState::showBackupWarning { showBackupWarnings -> - binding?.let { - handleBackupWarning(it, showBackupWarnings) - } - } - (WalletState::totalBalance or WalletState::walletsDataFromStores) { walletState -> - binding?.let { - handleTotalBalance( - binding = it, - totalBalance = walletState.totalBalance, - walletsCount = walletState.walletsDataFromStores.size, - appFiatCurrency = store.state.globalState.appCurrency, - ) - } - } - } - - override fun changeWalletView(fragment: WalletFragment, binding: FragmentWalletBinding) { - setFragment(fragment, binding) - onViewCreated() - showMultiWalletView(binding) - } - - private fun showMultiWalletView(binding: FragmentWalletBinding) = with(binding) { - watcher.clear() - tvTwinCardNumber.hide() - rvPendingTransaction.hide() - lCardBalance.root.hide() - lAddress.root.hide() - rowButtons.hide() - lSingleWalletBalance.root.hide() - lCardTotalBalance.show() - rvMultiwallet.show() - btnAddToken.show() - } - - override fun onViewCreated() { - setupWalletsRecyclerView() - } - - private fun setupWalletsRecyclerView() { - val fragment = fragment ?: return - walletsAdapter = WalletAdapter() - walletsAdapter.setHasStableIds(true) - binding?.rvMultiwallet?.layoutManager = LinearLayoutManager(fragment.requireContext()) - binding?.rvMultiwallet?.adapter = walletsAdapter - binding?.rvMultiwallet?.itemAnimator = null - } - - override fun onNewState(state: WalletState) { - val fragment = fragment ?: return - val binding = binding ?: return - - watcher.invoke(state) - - binding.btnAddToken.setOnClickListener { - Analytics.send(Portfolio.ButtonManageTokens()) - - store.dispatch(action = TokensAction.SetArgs.ManageAccess) - store.dispatch(action = NavigationAction.NavigateTo(screen = AppScreen.ManageTokens)) - } - handleErrorStates(state = state, binding = binding, fragment = fragment) - } - - private fun setupWalletCardNumber(binding: FragmentWalletBinding, walletCardsCount: Int?) = with(binding) { - if (walletCardsCount != null) { - tvTwinCardNumber.show() - tvTwinCardNumber.text = - tvTwinCardNumber.getQuantityString(R.plurals.card_label_card_count, walletCardsCount) - } else { - tvTwinCardNumber.hide() - } - } - - private fun handleBackupWarning(binding: FragmentWalletBinding, showBackupWarning: Boolean) = - with(binding.lWalletBackupWarning) { - root.isVisible = showBackupWarning - root.setOnClickListener { - Analytics.send(MainScreen.NoticeBackupYourWalletTapped()) - store.dispatch(WalletAction.MultiWallet.BackupWallet) - } - } - - private fun handleRescanWarning(binding: FragmentWalletBinding, showRescanWarning: Boolean) = - with(binding.lWalletRescanWarning) { - root.isVisible = showRescanWarning - root.setOnClickListener { - Analytics.send(MainScreen.NoticeScanYourCardTapped()) - store.dispatch(WalletAction.MultiWallet.ScanToGetDerivations) - } - } - - private fun handleTotalBalance( - binding: FragmentWalletBinding, - totalBalance: TotalFiatBalance?, - walletsCount: Int, - appFiatCurrency: FiatCurrency, - ) = with(binding.lCardTotalBalance) { - isVisible = walletsCount > 0 - - onChangeFiatCurrencyClick = { - store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency) - } - status = totalBalance - fiatCurrency = appFiatCurrency - } - - private fun handleErrorStates(state: WalletState, binding: FragmentWalletBinding, fragment: WalletFragment) { - when (state.error) { - ErrorType.UnknownBlockchain -> { - showErrorState( - binding, - fragment.getText(R.string.wallet_error_unsupported_blockchain), - fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle), - ) - } - - else -> Unit - } - } - - private fun showErrorState( - binding: FragmentWalletBinding, - errorTitle: CharSequence, - errorDescription: CharSequence, - ) = with(binding) { - lCardBalance.root.show() - with(lCardBalance) { - lBalance.root.hide() - lBalanceError.root.show() - rvMultiwallet.show() - btnAddToken.hide() - lBalanceError.tvErrorTitle.text = errorTitle - lBalanceError.tvErrorDescriptions.text = errorDescription - } - } - - override fun onDestroyFragment() { - super.onDestroyFragment() - watcher.clear() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt deleted file mode 100644 index 7ce1a4d49e..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt +++ /dev/null @@ -1,235 +0,0 @@ -package com.tangem.tap.features.wallet.ui.wallet - -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.LinearLayoutManager -import com.tangem.core.analytics.Analytics -import com.tangem.domain.tokens.legacy.TradeCryptoAction -import com.tangem.tap.common.analytics.events.Token -import com.tangem.tap.common.extensions.* -import com.tangem.tap.domain.model.WalletDataModel -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.PendingTransaction -import com.tangem.tap.features.wallet.models.PendingTransactionType -import com.tangem.tap.features.wallet.redux.WalletAction -import com.tangem.tap.features.wallet.redux.WalletState -import com.tangem.tap.features.wallet.ui.BalanceWidget -import com.tangem.tap.features.wallet.ui.MultipleAddressUiHelper -import com.tangem.tap.features.wallet.ui.WalletFragment -import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter -import com.tangem.tap.features.wallet.ui.utils.* -import com.tangem.tap.features.wallet.ui.view.WalletDetailsButtonsRow -import com.tangem.tap.store -import com.tangem.wallet.R -import com.tangem.wallet.databinding.FragmentWalletBinding - -class SingleWalletView : WalletView() { - private lateinit var pendingTransactionAdapter: PendingTransactionsAdapter - - // FIXME: Move to model watcher - private var watchedPrimaryWalletForAddressCard: WalletDataModel? = null - private var watchedPrimaryWalletForBalance: WalletDataModel? = null - - override fun changeWalletView(fragment: WalletFragment, binding: FragmentWalletBinding) { - setFragment(fragment, binding) - onViewCreated() - showSingleWalletView(binding) - } - - private fun showSingleWalletView(binding: FragmentWalletBinding) = with(binding) { - watchedPrimaryWalletForAddressCard = null - watchedPrimaryWalletForBalance = null - tvTwinCardNumber.hide() - rvMultiwallet.hide() - btnAddToken.hide() - rvPendingTransaction.hide() - pbLoadingUserTokens.hide() - lCardTotalBalance.hide() - lSingleWalletBalance.root.hide() - lWalletRescanWarning.root.hide() - lWalletBackupWarning.root.hide() - lCardBalance.root.show() - lAddress.root.show() - rowButtons.show() - } - - override fun onViewCreated() { - setupTransactionsRecyclerView() - } - - override fun onDestroyFragment() { - super.onDestroyFragment() - watchedPrimaryWalletForAddressCard = null - watchedPrimaryWalletForBalance = null - } - - private fun setupTransactionsRecyclerView() { - val fragment = fragment ?: return - pendingTransactionAdapter = PendingTransactionsAdapter() - binding?.rvPendingTransaction?.layoutManager = - LinearLayoutManager(fragment.requireContext()) - binding?.rvPendingTransaction?.adapter = pendingTransactionAdapter - } - - override fun onNewState(state: WalletState) { - val binding = binding ?: return - val primaryWalletData = state.primaryWalletData ?: return - - setupTwinCards(state.twinCardsState, binding) - setupButtons(primaryWalletData, binding, state.isExchangeServiceFeatureOn) - setupAddressCard(state, binding) - showPendingTransactionsIfPresent(primaryWalletData.status.pendingTransactions) - setupBalance(state, primaryWalletData) - } - - private fun showPendingTransactionsIfPresent(pendingTransactions: List) { - val knownTransactions = pendingTransactions.filterNot { - it.type == PendingTransactionType.Unknown - } - pendingTransactionAdapter.submitList(knownTransactions) - binding?.rvPendingTransaction?.show(knownTransactions.isNotEmpty()) - } - - private fun setupBalance(state: WalletState, primaryWallet: WalletDataModel) { - if (watchedPrimaryWalletForBalance == primaryWallet) return - watchedPrimaryWalletForBalance = primaryWallet - - val fragment = fragment ?: return - binding?.apply { - lCardBalance.lBalance.root.show() - BalanceWidget( - binding = this.lCardBalance, - fragment = fragment, - blockchainWalletData = primaryWallet, - tokenWalletData = state.primaryTokenData, - ).setup() - } - } - - private fun setupTwinCards(twinCardsState: TwinCardsState?, binding: FragmentWalletBinding) = with(binding) { - if (twinCardsState?.cardNumber == null) { - tvTwinCardNumber.hide() - } else { - tvTwinCardNumber.show() - tvTwinCardNumber.text = tvTwinCardNumber.getQuantityString(R.plurals.card_label_card_count, 2) - } - } - - private fun setupButtons( - walletData: WalletDataModel, - binding: FragmentWalletBinding, - isExchangeServiceFeatureEnabled: Boolean, - ) = with(binding) { - setupRowButtons(walletData, rowButtons, isExchangeServiceFeatureEnabled) - - lAddress.btnCopy.setOnClickListener { - walletData.walletAddresses?.selectedAddress?.address?.let { addressString -> - store.dispatch(WalletAction.CopyAddress(addressString, fragment!!.requireContext())) - } - } - lAddress.btnShowQr.setOnClickListener { - Analytics.send(Token.ShowWalletAddress) - - walletData.walletAddresses?.selectedAddress?.let { selectedAddress -> - store.dispatch( - WalletAction.DialogAction.QrCode( - currency = walletData.currency, - selectedAddress = selectedAddress, - ), - ) - } - } - } - - private fun setupRowButtons( - walletData: WalletDataModel, - rowButtons: WalletDetailsButtonsRow, - isExchangeServiceFeatureEnabled: Boolean, - ) { - val swapInteractor = this.swapInteractor ?: return - val swapFeatureToggleManager = this.swapFeatureToggleManager ?: return - - val exchangeManager = store.state.globalState.exchangeManager - binding?.rowButtons?.apply { - onBuyClick = { store.dispatch(TradeCryptoAction.Buy()) } - onSellClick = { store.dispatch(TradeCryptoAction.Sell) } - onSwapClick = { store.dispatch(TradeCryptoAction.Swap) } - onTradeClick = { - store.dispatch( - WalletAction.DialogAction.ChooseTradeActionDialog( - buyAllowed = walletData.isAvailableToBuy(exchangeManager), - sellAllowed = walletData.isAvailableToSell(exchangeManager), - swapAllowed = false, // always disable for single wallet - ), - ) - } - } - val actions = walletData.getAvailableActions( - swapInteractor = swapInteractor, - exchangeManager = exchangeManager, - swapFeatureToggleManager = swapFeatureToggleManager, - isSingleWallet = true, - ) - binding?.rowButtons?.updateButtonsVisibility( - actions = actions, - exchangeServiceFeatureOn = isExchangeServiceFeatureEnabled, - sendAllowed = walletData.mainButton(walletData.status.amount).enabled, - ) - - rowButtons.onSendClick = { store.dispatch(WalletAction.Send()) } - } - - private fun setupAddressCard(state: WalletState, binding: FragmentWalletBinding) = with(binding.lAddress) { - val primaryWallet = state.primaryWalletData - if (primaryWallet == watchedPrimaryWalletForAddressCard) return@with - watchedPrimaryWalletForAddressCard = primaryWallet - - if (primaryWallet?.walletAddresses != null && primaryWallet.currency is Currency.Blockchain) { - binding.lAddress.root.show() - if (primaryWallet.shouldShowMultipleAddress()) { - (binding.lAddress.root as? ViewGroup)?.beginDelayedTransition() - chipGroupAddressType.show() - chipGroupAddressType.fitChipsByGroupWidth() - val checkedId = MultipleAddressUiHelper.typeToId( - primaryWallet.walletAddresses.selectedAddress.type, - primaryWallet.currency.blockchain, - ) - if (checkedId != View.NO_ID) chipGroupAddressType.check(checkedId) - - chipGroupAddressType.setOnCheckedChangeListener { group, checkedId -> - if (checkedId == -1) return@setOnCheckedChangeListener - val type = MultipleAddressUiHelper.idToType(checkedId, primaryWallet.currency.blockchain) - type?.let { store.dispatch(WalletAction.ChangeSelectedAddress(type)) } - } - } else { - chipGroupAddressType.hide() - } - tvAddress.text = primaryWallet.walletAddresses.selectedAddress.address - tvExplore.setOnClickListener { - store.dispatch( - WalletAction.ExploreAddress( - primaryWallet.walletAddresses.selectedAddress.exploreUrl, - fragment!!.requireContext(), - ), - ) - } - setupCardInfo(primaryWallet) - } else { - binding.lAddress.root.hide() - } - } - - private fun setupCardInfo(walletData: WalletDataModel) { - val textView = binding?.lAddress?.tvInfo - val blockchain = walletData.currency.blockchain - if (textView != null) { - textView.text = textView.getString( - id = R.string.address_qr_code_message_format, - blockchain.fullName, - blockchain.currency, - blockchain.fullName, - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/WalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/WalletView.kt deleted file mode 100644 index c3cb5a7c74..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/WalletView.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.tangem.tap.features.wallet.ui.wallet - -import com.tangem.feature.swap.api.SwapFeatureToggleManager -import com.tangem.feature.swap.domain.SwapInteractor -import com.tangem.tap.features.wallet.redux.WalletState -import com.tangem.tap.features.wallet.ui.WalletFragment -import com.tangem.wallet.databinding.FragmentWalletBinding - -abstract class WalletView { - - var swapInteractor: SwapInteractor? = null - var swapFeatureToggleManager: SwapFeatureToggleManager? = null - - protected var fragment: WalletFragment? = null - protected var binding: FragmentWalletBinding? = null - - fun setFragment(fragment: WalletFragment, binding: FragmentWalletBinding) { - this.fragment = fragment - this.binding = binding - } - - fun removeFragment() { - fragment = null - binding = null - } - - open fun onViewDestroy() { - removeFragment() - } - - open fun onDestroyFragment() {} - - abstract fun changeWalletView(fragment: WalletFragment, binding: FragmentWalletBinding) - abstract fun onViewCreated() - abstract fun onNewState(state: WalletState) -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/model/UserWalletItem.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/model/UserWalletItem.kt index e5e3033115..546be07f7c 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/model/UserWalletItem.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/model/UserWalletItem.kt @@ -1,7 +1,7 @@ package com.tangem.tap.features.walletSelector.ui.model +import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN internal sealed interface UserWalletItem { val id: UserWalletId @@ -11,7 +11,7 @@ internal sealed interface UserWalletItem { val isLocked: Boolean sealed class Balance { - open val amount: String = UNKNOWN_AMOUNT_SIGN + open val amount: String = BigDecimalFormatter.EMPTY_BALANCE_SIGN open val showWarning: Boolean = false object Loading : Balance() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/converters/CryptoCurrencyConverter.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt similarity index 98% rename from app/src/main/java/com/tangem/tap/features/wallet/converters/CryptoCurrencyConverter.kt rename to app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt index 891841469c..185e765572 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/converters/CryptoCurrencyConverter.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt @@ -1,4 +1,4 @@ -package com.tangem.tap.features.wallet.converters +package com.tangem.tap.network.exchangeServices import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt index b8a3e32d55..76de7375da 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt @@ -2,7 +2,6 @@ package com.tangem.tap.network.exchangeServices import com.tangem.domain.exchange.RampStateManager import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.tap.features.wallet.converters.CryptoCurrencyConverter class DefaultRampManager(private val exchangeService: ExchangeService?) : RampStateManager { diff --git a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt index c1262e0e1f..f5e834bb53 100644 --- a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt +++ b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt @@ -16,7 +16,6 @@ import com.tangem.tap.common.redux.AppState import com.tangem.tap.domain.TangemSdkManager import com.tangem.tap.domain.tokens.UserTokensRepository import com.tangem.tap.domain.walletStores.WalletStoresManager -import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.network.exchangeServices.ExchangeService import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -43,7 +42,6 @@ class AppStateHolder @Inject constructor() : WalletsStateHolder, ReduxNavControl @Deprecated("Use scan response from selected user wallet") var scanResponse: ScanResponse? = null - var walletState: WalletState? = null var userTokensRepository: UserTokensRepository? = null var mainStore: Store? = null var tangemSdkManager: TangemSdkManager? = null diff --git a/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt index 33823b5d36..ac8e2be9ee 100644 --- a/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt @@ -15,10 +15,8 @@ import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.hexToBytes import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.domain.card.repository.CardSdkConfigRepository -import com.tangem.domain.common.BlockchainNetwork import com.tangem.domain.common.extensions.fromNetworkId import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles import com.tangem.lib.crypto.TransactionManager import com.tangem.lib.crypto.models.* import com.tangem.lib.crypto.models.transactions.SendTxResult @@ -39,7 +37,6 @@ class TransactionManagerImpl( private val analytics: AnalyticsEventHandler, private val cardSdkConfigRepository: CardSdkConfigRepository, private val walletManagersFacade: WalletManagersFacade, - private val walletFeatureToggles: WalletFeatureToggles, ) : TransactionManager { override suspend fun sendApproveTransaction( @@ -413,19 +410,15 @@ class TransactionManagerImpl( } private suspend fun getActualWalletManager(blockchain: Blockchain, derivationPath: String?): WalletManager { - val walletManager = if (walletFeatureToggles.isRedesignedScreenEnabled) { - val selectedUserWallet = requireNotNull( - userWalletsListManager.selectedUserWalletSync, - ) { "userWallet or userWalletsListManager is null" } - walletManagersFacade.getOrCreateWalletManager( - selectedUserWallet.walletId, - blockchain, - derivationPath, - ) - } else { - val blockchainNetwork = BlockchainNetwork(blockchain, derivationPath, emptyList()) - appStateHolder.walletState?.getWalletManager(blockchainNetwork) - } + val selectedUserWallet = requireNotNull( + userWalletsListManager.selectedUserWalletSync, + ) { "userWallet or userWalletsListManager is null" } + val walletManager = walletManagersFacade.getOrCreateWalletManager( + selectedUserWallet.walletId, + blockchain, + derivationPath, + ) + return requireNotNull(walletManager) { "no wallet manager found" } } 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 74fce7b587..196bdc51dc 100644 --- a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt @@ -11,15 +11,12 @@ import com.tangem.domain.common.extensions.fromNetworkId import com.tangem.domain.common.extensions.toCoinId import com.tangem.domain.common.extensions.toNetworkId import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles import com.tangem.lib.crypto.UserWalletManager import com.tangem.lib.crypto.models.Currency import com.tangem.lib.crypto.models.Currency.NativeToken import com.tangem.lib.crypto.models.Currency.NonNativeToken import com.tangem.lib.crypto.models.ProxyAmount import com.tangem.lib.crypto.models.ProxyFiatCurrency -import com.tangem.tap.common.extensions.dispatchOnMain -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.userWalletsListManager import com.tangem.tap.walletCurrenciesManager import com.tangem.tap.walletStoresManager @@ -31,7 +28,6 @@ import com.tangem.tap.features.wallet.models.Currency as WalletCurrency class UserWalletManagerImpl( private val appStateHolder: AppStateHolder, private val walletManagersFacade: WalletManagersFacade, - private val walletFeatureToggles: WalletFeatureToggles, ) : UserWalletManager { override suspend fun getUserTokens( @@ -216,28 +212,17 @@ class UserWalletManagerImpl( ) } - override fun refreshWallet() { - // workaround, should update wallet after transaction - appStateHolder.mainStore?.dispatchOnMain(WalletAction.LoadData.Refresh) - } - @Throws(IllegalArgumentException::class) private suspend fun getActualWalletManager(blockchain: Blockchain, derivationPath: String?): WalletManager { - val walletManager = if (walletFeatureToggles.isRedesignedScreenEnabled) { - val selectedUserWallet = requireNotNull( - userWalletsListManager.selectedUserWalletSync, - ) { "userWallet or userWalletsListManager is null" } - walletManagersFacade.getOrCreateWalletManager( - selectedUserWallet.walletId, - blockchain, - derivationPath, - ) - } else { - val blockchainNetwork = BlockchainNetwork(blockchain, derivationPath, emptyList()) - return requireNotNull(appStateHolder.walletState?.getWalletManager(blockchainNetwork)) { - "No wallet manager found" - } - } + val selectedUserWallet = requireNotNull( + userWalletsListManager.selectedUserWalletSync, + ) { "userWallet or userWalletsListManager is null" } + val walletManager = walletManagersFacade.getOrCreateWalletManager( + selectedUserWallet.walletId, + blockchain, + derivationPath, + ) + return requireNotNull(walletManager) { "No wallet manager found" } diff --git a/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt b/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt index b64680c54c..32b8f47384 100644 --- a/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt +++ b/app/src/main/java/com/tangem/tap/proxy/di/ProxyModule.kt @@ -10,7 +10,6 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.tokens.repository.NetworksRepository import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.feature.learn2earn.domain.api.Learn2earnDependencyProvider -import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles import com.tangem.lib.crypto.DerivationManager import com.tangem.lib.crypto.TransactionManager import com.tangem.lib.crypto.UserWalletManager @@ -39,12 +38,10 @@ class ProxyModule { fun provideUserWalletManager( appStateHolder: AppStateHolder, walletManagersFacade: WalletManagersFacade, - walletFeatureToggles: WalletFeatureToggles, ): UserWalletManager { return UserWalletManagerImpl( appStateHolder = appStateHolder, walletManagersFacade = walletManagersFacade, - walletFeatureToggles = walletFeatureToggles, ) } @@ -55,14 +52,12 @@ class ProxyModule { analytics: AnalyticsEventHandler, cardSdkConfigRepository: CardSdkConfigRepository, walletManagersFacade: WalletManagersFacade, - walletFeatureToggles: WalletFeatureToggles, ): TransactionManager { return TransactionManagerImpl( appStateHolder = appStateHolder, analytics = analytics, cardSdkConfigRepository = cardSdkConfigRepository, walletManagersFacade = walletManagersFacade, - walletFeatureToggles = walletFeatureToggles, ) } diff --git a/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt b/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt index 0a489b3498..786c40ac85 100644 --- a/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt +++ b/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt @@ -42,8 +42,6 @@ interface UserWalletManager { suspend fun hideAllTokens() - fun refreshWallet() - /** * Returns wallet public address for token *