From 72f108b2f9c6ad49f114a5a67e4c020a46578813 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 3 Dec 2021 14:37:36 +0300 Subject: [PATCH 01/37] Updated on 2026-08-14 --- .../java/com/tangem/tap/persistence/UsedCardsPrefStorage.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/persistence/UsedCardsPrefStorage.kt b/app/src/main/java/com/tangem/tap/persistence/UsedCardsPrefStorage.kt index a016e233f3..17238689f5 100644 --- a/app/src/main/java/com/tangem/tap/persistence/UsedCardsPrefStorage.kt +++ b/app/src/main/java/com/tangem/tap/persistence/UsedCardsPrefStorage.kt @@ -45,7 +45,7 @@ class UsedCardsPrefStorage( } fun activationIsStarted(cardId: String): Boolean { - return findCardInfo(cardId)?.isActivationStarted ?: true + return findCardInfo(cardId)?.isActivationStarted ?: false } fun activationFinished(cardId: String) { From bbd81c7c856740868745fcb1f1c96e7a8c4f9c97 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 3 Dec 2021 14:54:27 +0300 Subject: [PATCH 02/37] Updated on 2026-08-14 --- .../product/ResetToFactorySettingsTask.kt | 2 +- .../redux/OnboardingWalletMiddleware.kt | 23 ++++++++++++------- .../wallet/redux/OnboardingWalletReducer.kt | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt index f475ef12ef..444a7b3971 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt @@ -40,7 +40,7 @@ class ResetToFactorySettingsTask() : CardSessionRunnable { ) { val backupStatus = session.environment.card?.backupStatus - if (backupStatus == null && backupStatus == Card.BackupStatus.NoBackup) { + if (backupStatus == null || backupStatus == Card.BackupStatus.NoBackup) { callback(CompletionResult.Success(session.environment.card!!)) return } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index f0c695ebd0..c4ecaf3a6d 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -112,11 +112,18 @@ private fun handleWalletAction(action: Action) { store.dispatch(newAction) } OnboardingWalletAction.OnBackPressed -> { - if (walletState.backupState.backupStep is BackupStep.WriteBackupCard || - walletState.backupState.backupStep is BackupStep.WritePrimaryCard) { - store.dispatch(GlobalAction.ShowDialog(BackupDialog.BackupInProgress)) - } else { - store.dispatch(NavigationAction.PopBackTo()) + when (walletState.backupState.backupStep) { + BackupStep.InitBackup, BackupStep.Finished -> store.dispatch(NavigationAction.PopBackTo()) + BackupStep.ScanOriginCard, BackupStep.AddBackupCards, BackupStep.EnterAccessCode, + BackupStep.ReenterAccessCode, BackupStep.SetAccessCode, + -> { + store.dispatch(BackupAction.DiscardBackup) + store.dispatch(NavigationAction.PopBackTo()) + } + is BackupStep.WriteBackupCard, BackupStep.WritePrimaryCard -> + store.dispatch(GlobalAction.ShowDialog(BackupDialog.BackupInProgress)) + + } } } @@ -188,9 +195,9 @@ class BackupMiddleware { backupService.proceedBackup { result -> when (result) { is CompletionResult.Success -> { - store.dispatchOnMain( - BackupAction.PrepareToWriteBackupCard(1) - ) + store.dispatchOnMain( + BackupAction.PrepareToWriteBackupCard(1) + ) } is CompletionResult.Failure -> { } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt index 4069f04a22..982d4e127b 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt @@ -39,7 +39,7 @@ class BackupReducer { ): BackupState { return when (action) { - BackupAction.IntroduceBackup -> state.copy(backupStep = BackupStep.InitBackup) + BackupAction.IntroduceBackup -> BackupState(backupStep = BackupStep.InitBackup) BackupAction.StartBackup -> state.copy(backupStep = BackupStep.ScanOriginCard) From 5f9579c63eb503899f9760630a88904e65d994de Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 6 Dec 2021 14:52:40 +0300 Subject: [PATCH 03/37] Updated on 2026-08-14 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8a098dc5a8..0e5a1cae34 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -78,8 +78,8 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' implementation 'com.tangem:blockchain:develop-48' - implementation 'com.tangem.tangem-sdk-kotlin:core:develop-99' - implementation 'com.tangem.tangem-sdk-kotlin:android:develop-99' + implementation 'com.tangem.tangem-sdk-kotlin:core:develop-100' + implementation 'com.tangem.tangem-sdk-kotlin:android:develop-100' // WebView implementation "androidx.browser:browser:1.3.0" From 767a7f9400919ceb93729b5f1622f58dee3d66e9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 6 Dec 2021 15:04:48 +0300 Subject: [PATCH 04/37] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/common/analytics/TangemSdkError.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt b/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt index 5ef395e4ad..0880e773be 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt @@ -103,6 +103,7 @@ object TangemSdk { is TangemSdkError.FilesDisabled -> TangemSdkError.FilesDisabled() is TangemSdkError.HDWalletDisabled -> TangemSdkError.HDWalletDisabled() is TangemSdkError.WrongInteractionMode -> TangemSdkError.WrongInteractionMode() + is TangemSdkError.IssuerSignatureLoadingFailed -> TangemSdkError.IssuerSignatureLoadingFailed() } } From 8f66155ee14bb6c4ff5623e4b23640650d3d3e85 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 6 Dec 2021 15:37:17 +0300 Subject: [PATCH 05/37] Updated on 2026-08-14 --- .../java/com/tangem/tap/features/details/redux/DetailsReducer.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index cdbde3bb92..dfd5599b6a 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt @@ -190,6 +190,7 @@ private fun prepareAllowedSecurityOptions( if (card?.isTangemTwin() == true) { allowedSecurityOptions.add(SecurityOption.PassCode) + allowedSecurityOptions.add(SecurityOption.LongTap) } if ((currentSecurityOption == SecurityOption.LongTap) || !prohibitDefaultPin) { allowedSecurityOptions.add(SecurityOption.LongTap) From d88410bd03b67f43c459bb0ba59df24b4a6e6b8e Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 6 Dec 2021 15:49:19 +0300 Subject: [PATCH 06/37] Updated on 2026-08-14 --- .../res/layout/fragment_onboarding_wallet.xml | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/app/src/main/res/layout/fragment_onboarding_wallet.xml b/app/src/main/res/layout/fragment_onboarding_wallet.xml index 00ff82b671..7197ed1eab 100644 --- a/app/src/main/res/layout/fragment_onboarding_wallet.xml +++ b/app/src/main/res/layout/fragment_onboarding_wallet.xml @@ -78,30 +78,27 @@ From e039c889e28233dddc70a34d88dcacc0f964ad26 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 6 Dec 2021 16:00:47 +0300 Subject: [PATCH 07/37] Updated on 2026-08-14 --- .../onboarding/products/wallet/ui/dialogs/AccessCodeDialog.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AccessCodeDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AccessCodeDialog.kt index afd4521ac1..9433d4e274 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AccessCodeDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AccessCodeDialog.kt @@ -33,6 +33,7 @@ class AccessCodeDialog(context: Context) : BottomSheetDialog(context) { fun showInfoScreen() { behavior.state = BottomSheetBehavior.STATE_EXPANDED + access_code_title.text = context.getText(R.string.onboarding_access_code_intro_title) layout_backup_access_code_info.show() layout_backup_access_code_submit.hide() btn_access_code_create.setOnClickListener { @@ -43,6 +44,7 @@ class AccessCodeDialog(context: Context) : BottomSheetDialog(context) { fun showEnterAccessCode() { layout_backup_access_code_info.hide() layout_backup_access_code_submit.show() + access_code_title.text = context.getText(R.string.onboarding_access_code_intro_title) btn_access_code_submit.text = context.getText(R.string.common_continue) btn_access_code_submit.setOnClickListener { store.dispatch(BackupAction.CheckAccessCode(et_access_code.text.toString())) @@ -52,6 +54,7 @@ class AccessCodeDialog(context: Context) : BottomSheetDialog(context) { fun showReenterAccessCode() { layout_backup_access_code_info.hide() layout_backup_access_code_submit.show() + access_code_title.text = context.getText(R.string.onboarding_access_code_repeat_code_title) et_access_code.setText("") btn_access_code_submit.text = context.getText(R.string.common_submit) btn_access_code_submit.setOnClickListener { From ac9618a1f2a4f6b2954b27e93b4b7a68142e6730 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 6 Dec 2021 21:42:07 +0300 Subject: [PATCH 08/37] Updated on 2026-08-14 --- .../tangem/tap/common/extensions/Navigation.kt | 1 - .../wallet/redux/OnboardingWalletMiddleware.kt | 6 ++---- .../wallet/ui/OnboardingWalletFragment.kt | 18 ++++++++---------- 3 files changed, 10 insertions(+), 15 deletions(-) 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 36723da434..30d8e1b18a 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 @@ -68,7 +68,6 @@ fun FragmentActivity.addOnBackPressedDispatcher( private fun fragmentFactory(screen: AppScreen): Fragment { return when (screen) { -// AppScreen.Home -> TestLeapfrogFragment() AppScreen.Home -> HomeFragment() AppScreen.OnboardingNote -> OnboardingNoteFragment() AppScreen.OnboardingWallet -> OnboardingWalletFragment() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index c4ecaf3a6d..15e1c65c17 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -115,15 +115,13 @@ private fun handleWalletAction(action: Action) { when (walletState.backupState.backupStep) { BackupStep.InitBackup, BackupStep.Finished -> store.dispatch(NavigationAction.PopBackTo()) BackupStep.ScanOriginCard, BackupStep.AddBackupCards, BackupStep.EnterAccessCode, - BackupStep.ReenterAccessCode, BackupStep.SetAccessCode, + BackupStep.ReenterAccessCode, BackupStep.SetAccessCode, BackupStep.WritePrimaryCard -> { store.dispatch(BackupAction.DiscardBackup) store.dispatch(NavigationAction.PopBackTo()) } - is BackupStep.WriteBackupCard, BackupStep.WritePrimaryCard -> + is BackupStep.WriteBackupCard -> store.dispatch(GlobalAction.ShowDialog(BackupDialog.BackupInProgress)) - - } } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index 52adf8a47d..c0cee1429d 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -10,20 +10,19 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.tabs.TabLayoutMediator import com.tangem.common.CardIdFormatter import com.tangem.common.core.CardIdDisplayFormat -import com.tangem.tap.common.extensions.addOnBackPressedDispatcher import com.tangem.tap.common.extensions.dispatchOpenUrl import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.show import com.tangem.tap.common.leapfrogWidget.LeapfrogWidget import com.tangem.tap.common.postUi +import com.tangem.tap.features.FragmentOnBackPressedHandler +import com.tangem.tap.features.addBackPressHandler import com.tangem.tap.features.home.redux.HomeMiddleware import com.tangem.tap.features.onboarding.products.wallet.redux.* import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AccessCodeDialog import com.tangem.tap.store import com.tangem.wallet.R import kotlinx.android.synthetic.main.fragment_onboarding_wallet.* -import kotlinx.android.synthetic.main.fragment_onboarding_wallet.toolbar -import kotlinx.android.synthetic.main.fragment_wallet_details.* import kotlinx.android.synthetic.main.layout_onboarding_buttons_add_cards.* import kotlinx.android.synthetic.main.layout_onboarding_buttons_common.* import kotlinx.android.synthetic.main.view_confetti.* @@ -31,7 +30,7 @@ import kotlinx.android.synthetic.main.view_onboarding_progress.* import org.rekotlin.StoreSubscriber class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), - StoreSubscriber { + StoreSubscriber, FragmentOnBackPressedHandler { private var accessCodeDialog: AccessCodeDialog? = null private lateinit var cardsWidget: BackupCardsWidget @@ -41,11 +40,6 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), postponeEnterTransition() setHasOptionsMenu(true) - - activity?.addOnBackPressedDispatcher { - store.dispatch(OnboardingWalletAction.OnBackPressed) - } - val inflater = TransitionInflater.from(requireContext()) enterTransition = inflater.inflateTransition(R.transition.fade) exitTransition = inflater.inflateTransition(R.transition.fade) @@ -68,7 +62,7 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), store.dispatch(OnboardingWalletAction.Init) toolbar.setNavigationOnClickListener { activity?.onBackPressed() } -// store.dispatch(OnboardingWalletAction.LoadArtwork) + addBackPressHandler(this) } override fun onStart() { @@ -381,4 +375,8 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), backupStep == BackupStep.ScanOriginCard || backupStep == BackupStep.AddBackupCards menu.getItem(0).isVisible = shopMenuShouldBeVisible } + + override fun handleOnBackPressed() { + store.dispatch(OnboardingWalletAction.OnBackPressed) + } } \ No newline at end of file From 83ec2441f2109c7df5eaf8247943792045da0502 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 6 Dec 2021 21:59:07 +0300 Subject: [PATCH 09/37] Updated on 2026-08-14 --- .../products/wallet/redux/OnboardingWalletMiddleware.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 15e1c65c17..84979eafda 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -103,11 +103,10 @@ private fun handleWalletAction(action: Action) { } OnboardingWalletAction.ProceedBackup -> { val newAction = when (val backupState = backupService.currentState) { - BackupService.State.Preparing -> BackupAction.IntroduceBackup BackupService.State.FinalizingPrimaryCard -> BackupAction.PrepareToWritePrimaryCard is BackupService.State.FinalizingBackupCard -> BackupAction.PrepareToWriteBackupCard(backupState.index) - BackupService.State.Finished -> BackupAction.FinishBackup + else -> BackupAction.IntroduceBackup } store.dispatch(newAction) } From 4228536a51a77f4d71657fcd0121f315bf081413 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 6 Dec 2021 22:41:18 +0300 Subject: [PATCH 10/37] Updated on 2026-08-14 --- .../tangem/tap/features/details/redux/DetailsReducer.kt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index dfd5599b6a..71f4bd5fd7 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt @@ -184,16 +184,10 @@ private fun handleSecurityAction( private fun prepareAllowedSecurityOptions( card: Card?, currentSecurityOption: SecurityOption?, ): EnumSet { - val prohibitDefaultPin = card?.settings?.isResettingUserCodesAllowed != true - - val allowedSecurityOptions = EnumSet.noneOf(SecurityOption::class.java) + val allowedSecurityOptions = EnumSet.of(SecurityOption.LongTap) if (card?.isTangemTwin() == true) { allowedSecurityOptions.add(SecurityOption.PassCode) - allowedSecurityOptions.add(SecurityOption.LongTap) - } - if ((currentSecurityOption == SecurityOption.LongTap) || !prohibitDefaultPin) { - allowedSecurityOptions.add(SecurityOption.LongTap) } if (currentSecurityOption == SecurityOption.AccessCode) { allowedSecurityOptions.add(SecurityOption.AccessCode) From 00cf8c5b0cedca43fb7fd974a93f381736594cc5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 15:14:06 +0300 Subject: [PATCH 11/37] Updated on 2026-08-14 --- app/build.gradle | 6 +- .../tangem/tap/common/extensions/ByteArray.kt | 17 +++ .../tap/common/redux/global/GlobalAction.kt | 1 + .../common/redux/global/GlobalMidlleware.kt | 12 +- .../com/tangem/tap/domain/TangemSdkManager.kt | 32 +++-- .../com/tangem/tap/domain/TangemSigner.kt | 24 ++-- .../com/tangem/tap/domain/TapWalletManager.kt | 17 ++- .../domain/extensions/WalletManagerFactory.kt | 96 ++++++++------- .../tap/domain/tasks/CreateWalletsTask.kt | 2 +- ...scanTask.kt => CreateProductWalletTask.kt} | 71 +++++++----- ...uctWalletsTask.kt => CreateWalletsTask.kt} | 12 +- .../domain/tasks/product/ScanProductTask.kt | 70 ++++++++++- .../tangem/tap/domain/topup/TopUpManager.kt | 2 +- .../tap/domain/twins/FinalizeTwinTask.kt | 2 +- .../walletconnect/WalletConnectManager.kt | 6 +- .../walletconnect/WalletConnectSdkHelper.kt | 16 +-- .../walletconnect/WalletConnectMiddleware.kt | 31 +++-- .../redux/walletconnect/WalletConnectState.kt | 7 +- .../tap/features/home/redux/HomeMiddleware.kt | 4 +- .../redux/OnboardingWalletMiddleware.kt | 3 +- .../send/redux/middlewares/SendMiddleware.kt | 2 +- .../features/tokens/redux/CurrencyListItem.kt | 4 + .../tap/features/tokens/redux/TokensAction.kt | 7 ++ .../features/tokens/redux/TokensMiddleware.kt | 109 +++++++++++++++--- .../features/tokens/redux/TokensReducer.kt | 15 ++- .../tap/features/tokens/redux/TokensState.kt | 1 + .../features/tokens/ui/AddTokensFragment.kt | 17 ++- .../tokens/ui/adapters/CurrenciesAdapter.kt | 46 ++++---- .../tap/features/wallet/redux/WalletAction.kt | 3 +- .../middlewares/MultiWalletMiddleware.kt | 69 +++++------ .../java/com/tangem/tap/network/Retrofit.kt | 6 +- .../main/res/layout/fragment_add_tokens.xml | 25 +++- .../main/res/layout/item_popular_token.xml | 33 ++---- app/src/main/res/values/colors.xml | 2 +- 34 files changed, 502 insertions(+), 268 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/extensions/ByteArray.kt rename app/src/main/java/com/tangem/tap/domain/tasks/product/{CreateProductWalletAndRescanTask.kt => CreateProductWalletTask.kt} (66%) rename app/src/main/java/com/tangem/tap/domain/tasks/product/{CreateProductWalletsTask.kt => CreateWalletsTask.kt} (82%) diff --git a/app/build.gradle b/app/build.gradle index 0e5a1cae34..11fe6e6a2e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,9 +77,9 @@ dependencies { implementation 'com.google.android.play:core-ktx:1.8.1' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' - implementation 'com.tangem:blockchain:develop-48' - implementation 'com.tangem.tangem-sdk-kotlin:core:develop-100' - implementation 'com.tangem.tangem-sdk-kotlin:android:develop-100' + implementation 'com.tangem:blockchain:develop-50' + implementation 'com.tangem.tangem-sdk-kotlin:core:develop-102' + implementation 'com.tangem.tangem-sdk-kotlin:android:develop-102' // WebView implementation "androidx.browser:browser:1.3.0" diff --git a/app/src/main/java/com/tangem/tap/common/extensions/ByteArray.kt b/app/src/main/java/com/tangem/tap/common/extensions/ByteArray.kt new file mode 100644 index 0000000000..376b56f399 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/extensions/ByteArray.kt @@ -0,0 +1,17 @@ +package com.tangem.tap.common.extensions + +/** +[REDACTED_AUTHOR] + */ + +data class ByteArrayKey(val bytes: ByteArray) { + override fun equals(other: Any?): Boolean { + return this === other || other is ByteArrayKey && this.bytes.contentEquals(other.bytes) + } + + override fun hashCode(): Int = bytes.contentHashCode() +} + +fun ByteArray.toMapKey(): ByteArrayKey = ByteArrayKey(this) + +fun ByteArrayKey.bytes(): ByteArray = this.bytes \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt index af62d98fff..f448916049 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt @@ -36,6 +36,7 @@ sealed class GlobalAction : Action { } data class ScanCard( + val shouldDeriveWC: Boolean, val onSuccess: ((ScanResponse) -> Unit)? = null, val onFailure: ((TangemError) -> Unit)? = null, val messageResId: Int? = null, diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt index 06cc349269..258131199b 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt @@ -3,6 +3,7 @@ package com.tangem.tap.common.redux.global import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError import com.tangem.common.services.Result +import com.tangem.tap.* import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchOnMain @@ -13,10 +14,6 @@ import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager import com.tangem.tap.features.send.redux.SendAction import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.network.moonpay.MoonpayService -import com.tangem.tap.preferencesStorage -import com.tangem.tap.scope -import com.tangem.tap.store -import com.tangem.tap.tangemSdkManager import kotlinx.coroutines.launch import org.rekotlin.Middleware import timber.log.Timber @@ -91,7 +88,12 @@ private val globalMiddlewareHandler: Middleware = { dispatch, appState } is GlobalAction.ScanCard -> { scope.launch { - val result = tangemSdkManager.scanProduct(FirebaseAnalyticsHandler, action.messageResId) + val result = tangemSdkManager.scanProduct( + FirebaseAnalyticsHandler, + currenciesRepository, + action.shouldDeriveWC, + action.messageResId + ) store.dispatch(GlobalAction.ScanFailsCounter.ChooseBehavior(result)) withMainContext { when (result) { diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt index 695f3b83f0..7131feb7b7 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -1,6 +1,6 @@ package com.tangem.tap.domain -import CreateProductWalletAndRescanTask +import CreateProductWalletTask import android.content.Context import com.tangem.Message import com.tangem.TangemSdk @@ -12,7 +12,10 @@ import com.tangem.common.card.FirmwareVersion import com.tangem.common.core.CardSessionRunnable import com.tangem.common.core.Config import com.tangem.common.core.TangemSdkError +import com.tangem.common.hdWallet.DerivationPath import com.tangem.operations.CommandResponse +import com.tangem.operations.derivation.DeriveWalletPublicKeysTask +import com.tangem.operations.derivation.ExtendedPublicKeyList import com.tangem.operations.pins.CheckUserCodesCommand import com.tangem.operations.pins.CheckUserCodesResponse import com.tangem.operations.pins.SetUserCodeCommand @@ -23,6 +26,7 @@ import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask import com.tangem.tap.domain.tasks.product.ResetToFactorySettingsTask import com.tangem.tap.domain.tasks.product.ScanProductTask import com.tangem.tap.domain.tasks.product.ScanResponse +import com.tangem.tap.domain.tokens.CurrenciesRepository import com.tangem.wallet.R import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -33,18 +37,20 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co suspend fun scanProduct( analyticsHandler: AnalyticsHandler, + currenciesRepository: CurrenciesRepository, + shouldDeriveWC: Boolean, messageRes: Int? = null, ): CompletionResult { analyticsHandler.triggerEvent(AnalyticsEvent.READY_TO_SCAN, null) val message = Message(context.getString(messageRes ?: R.string.initial_message_scan_header)) - return runTaskAsyncReturnOnMain(ScanProductTask(), null, message) - .also { sendScanFailuresToAnalytics(analyticsHandler, it) } + return runTaskAsyncReturnOnMain(ScanProductTask(null, currenciesRepository, shouldDeriveWC), null, message) + .also { sendScanFailuresToAnalytics(analyticsHandler, it) } } suspend fun createProductWallet(scanResponse: ScanResponse): CompletionResult { return runTaskAsync( - CreateProductWalletAndRescanTask(scanResponse.productType), + CreateProductWalletTask(scanResponse.productType), scanResponse.card.cardId, Message(context.getString(R.string.initial_message_create_wallet_body)) ) @@ -66,6 +72,14 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co initialMessage = Message(context.getString(R.string.initial_message_create_wallet_body))) } + suspend fun derivePublicKeys( + cardId: String, + walletPublicKey: ByteArray, + derivationPaths: List + ): CompletionResult { + return runTaskAsyncReturnOnMain(DeriveWalletPublicKeysTask(walletPublicKey, derivationPaths), cardId) + } + suspend fun resetToFactorySettings(card: Card): CompletionResult { return runTaskAsyncReturnOnMain( ResetToFactorySettingsTask(), @@ -104,13 +118,13 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co suspend fun runTaskAsync( runnable: CardSessionRunnable, cardId: String? = null, initialMessage: Message? = null, ): CompletionResult = - withContext(Dispatchers.Main) { - suspendCoroutine { continuation -> - tangemSdk.startSessionWithRunnable(runnable, cardId, initialMessage) { result -> - continuation.resume(result) - } + withContext(Dispatchers.Main) { + suspendCoroutine { continuation -> + tangemSdk.startSessionWithRunnable(runnable, cardId, initialMessage) { result -> + continuation.resume(result) } } + } private suspend fun runTaskAsyncReturnOnMain( runnable: CardSessionRunnable, cardId: String? = null, initialMessage: Message? = null, diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt b/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt index 978ca5288f..1042913d5d 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt @@ -3,6 +3,7 @@ package com.tangem.tap.domain import com.tangem.Message import com.tangem.TangemSdk import com.tangem.blockchain.common.TransactionSigner +import com.tangem.blockchain.common.Wallet import com.tangem.common.CompletionResult import com.tangem.tap.domain.tasks.SignHashTask import com.tangem.tap.domain.tasks.SignHashesTask @@ -15,13 +16,9 @@ class TangemSigner( private val signerCallback: (TangemSignerResponse) -> Unit, ) : TransactionSigner { - override suspend fun sign( - hash: ByteArray, - cardId: String, - walletPublicKey: ByteArray, - ): CompletionResult = - suspendCoroutine { continuation -> - val command = SignHashTask(hash, walletPublicKey) + override suspend fun sign(hash: ByteArray, cardId: String, publicKey: Wallet.PublicKey): CompletionResult { + return suspendCoroutine { continuation -> + val command = SignHashTask(hash, publicKey.seedKey) tangemSdk.startSessionWithRunnable( runnable = command, cardId = cardId, @@ -42,15 +39,11 @@ class TangemSigner( } } } + } - - override suspend fun sign( - hashes: List, - cardId: String, - walletPublicKey: ByteArray, - ): CompletionResult> = - suspendCoroutine { continuation -> - val task = SignHashesTask(hashes, walletPublicKey) + override suspend fun sign(hashes: List, cardId: String, publicKey: Wallet.PublicKey): CompletionResult> { + return suspendCoroutine { continuation -> + val task = SignHashesTask(hashes, publicKey.seedKey) tangemSdk.startSessionWithRunnable( runnable = task, cardId = cardId, @@ -71,6 +64,7 @@ class TangemSigner( } } } + } } data class TangemSignerResponse( 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 10f1a76a87..844eeb0bfa 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -1,7 +1,6 @@ package com.tangem.tap.domain import com.tangem.blockchain.common.* -import com.tangem.common.card.Card import com.tangem.common.services.Result import com.tangem.tap.common.analytics.AnalyticsEvent import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler @@ -131,7 +130,7 @@ class TapWalletManager { store.dispatch(WalletAction.MultiWallet.SetPrimaryToken(primaryToken)) } if (data.card.isMultiwalletAllowed) { - loadMultiWalletData(data.card, blockchain, primaryWalletManager) + loadMultiWalletData(data, blockchain, primaryWalletManager) } else { store.dispatch(WalletAction.MultiWallet.AddWalletManagers(primaryWalletManager)) store.dispatch(WalletAction.MultiWallet.AddBlockchains(listOf(blockchain))) @@ -139,7 +138,7 @@ class TapWalletManager { } else { if (data.card.isMultiwalletAllowed) { - loadMultiWalletData(data.card, blockchain, null) + loadMultiWalletData(data, blockchain, null) } } val moonPayStatus = store.state.globalState.moonpayStatus @@ -149,10 +148,10 @@ class TapWalletManager { } private fun loadMultiWalletData( - card: Card, primaryBlockchain: Blockchain?, primaryWalletManager: WalletManager? + scanResponse: ScanResponse, primaryBlockchain: Blockchain?, primaryWalletManager: WalletManager? ) { val primaryTokens = primaryWalletManager?.cardTokens?.toList() ?: emptyList() - val savedCurrencies = currenciesRepository.loadCardCurrencies(card.cardId) + val savedCurrencies = currenciesRepository.loadCardCurrencies(scanResponse.card.cardId) if (savedCurrencies == null) { if (primaryBlockchain != null && primaryWalletManager != null) { @@ -169,11 +168,11 @@ class TapWalletManager { CardCurrencies(blockchains = blockchains, tokens = emptyList()) )) val walletManagers = - walletManagerFactory.makeWalletManagersForApp(card, blockchains.toList()) + walletManagerFactory.makeWalletManagersForApp(scanResponse, blockchains.toList()) store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManagers)) store.dispatch(WalletAction.MultiWallet.AddBlockchains(blockchains.toList())) } - store.dispatch(WalletAction.MultiWallet.FindBlockchainsInUse(card, walletManagerFactory)) + store.dispatch(WalletAction.MultiWallet.FindBlockchainsInUse) store.dispatch(WalletAction.MultiWallet.FindTokensInUse) } else { val blockchains = savedCurrencies.blockchains.toList() @@ -182,10 +181,10 @@ class TapWalletManager { primaryWalletManager != null && primaryBlockchain != null ) { val blockchainsWithoutPrimary = blockchains.filterNot { it == primaryBlockchain } - walletManagerFactory.makeWalletManagersForApp(card, blockchainsWithoutPrimary) + walletManagerFactory.makeWalletManagersForApp(scanResponse, blockchainsWithoutPrimary) .plus(primaryWalletManager) } else { - walletManagerFactory.makeWalletManagersForApp(card, blockchains) + walletManagerFactory.makeWalletManagersForApp(scanResponse, blockchains) } store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManagers)) diff --git a/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt b/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt index aa85331ab2..b505619739 100644 --- a/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt +++ b/app/src/main/java/com/tangem/tap/domain/extensions/WalletManagerFactory.kt @@ -3,74 +3,70 @@ package com.tangem.tap.domain.extensions import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.WalletManagerFactory -import com.tangem.common.card.Card import com.tangem.common.card.CardWallet import com.tangem.common.card.EllipticCurve import com.tangem.common.extensions.hexToBytes +import com.tangem.tap.common.extensions.toMapKey import com.tangem.tap.domain.TapWorkarounds.isTestCard import com.tangem.tap.domain.tasks.product.ScanResponse fun WalletManagerFactory.makeWalletManagerForApp( - card: Card, - blockchain: Blockchain, + scanResponse: ScanResponse, blockchain: Blockchain ): WalletManager? { + val card = scanResponse.card + if (card.isTestCard && blockchain.getTestnetVersion() == null) return null val supportedCurves = blockchain.getSupportedCurves() ?: return null + val wallets = card.wallets.filter { wallet -> supportedCurves.contains(wallet.curve) } - val wallet = selectWallet(wallets) - val publicKey = wallet?.publicKey ?: return null - val curveToUse = wallet.curve ?: return null - return if (card.isTestCard) { - blockchain.getTestnetVersion()?.let { - makeWalletManager(card.cardId, publicKey, it, curveToUse) + val wallet = selectWallet(wallets) ?: return null + + val environmentBlockchain = if (card.isTestCard) blockchain.getTestnetVersion()!! else blockchain + + val seedKey = wallet.extendedPublicKey + return when { + scanResponse.isTangemTwins() && scanResponse.secondTwinPublicKey != null -> { + makeTwinWalletManager( + card.cardId, + wallet.publicKey, scanResponse.secondTwinPublicKey.hexToBytes(), + environmentBlockchain, wallet.curve + ) + } + seedKey != null -> { + val derivedKeys = scanResponse.derivedKeys[wallet.publicKey.toMapKey()] + val derivedKey = derivedKeys?.firstOrNull { it.derivationPath == blockchain.derivationPath() } + ?: return null + + makeWalletManager(card.cardId, environmentBlockchain, seedKey, derivedKey) + } + else -> { + makeWalletManager(card.cardId, environmentBlockchain, wallet.publicKey, wallet.curve) } - } else { - makeWalletManager(card.cardId, publicKey, blockchain, curveToUse) } } +fun WalletManagerFactory.makeWalletManagersForApp( + scanResponse: ScanResponse, blockchains: List, +): List { + val isTestCard = scanResponse.card.isTestCard + val filteredBlockchains = blockchains.mapNotNull { if (isTestCard) it.getTestnetVersion() else it } + return filteredBlockchains.mapNotNull { makeWalletManagerForApp(scanResponse, it) } +} + +fun WalletManagerFactory.makePrimaryWalletManager( + scanResponse: ScanResponse, +): WalletManager? { + val blockchain = if (scanResponse.card.isTestCard) { + scanResponse.getBlockchain().getTestnetVersion() ?: return null + } else { + scanResponse.getBlockchain() + } + return makeWalletManagerForApp(scanResponse, blockchain) +} + private fun selectWallet(wallets: List): CardWallet? { return when (wallets.size) { 0 -> null 1 -> wallets[0] else -> wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: wallets[0] } -} - -fun WalletManagerFactory.makeWalletManagersForApp( - card: Card, blockchains: List, -): List { - return if (card.isTestCard) { - blockchains.mapNotNull { blockchain -> - blockchain.getTestnetVersion()?.let { makeWalletManagerForApp(card, it) } - } - } else { - blockchains.mapNotNull { blockchain -> makeWalletManagerForApp(card, blockchain) } - } -} - -fun WalletManagerFactory.makePrimaryWalletManager( - data: ScanResponse, -): WalletManager? { - val card = data.card - val blockchain = if (card.isTestCard) { - data.getBlockchain().getTestnetVersion() - } else { - data.getBlockchain() - } - val supportedCurves = blockchain?.getSupportedCurves() ?: return null - - val wallets = card.wallets.filter { wallet -> supportedCurves.contains(wallet.curve) } - val wallet = selectWallet(wallets) - val publicKey = wallet?.publicKey ?: return null - val curveToUse = wallet.curve - - return if (data.isTangemTwins() && data.secondTwinPublicKey != null) { - makeMultisigWalletManager( - cardId = card.cardId, - walletPublicKey = publicKey, pairPublicKey = data.secondTwinPublicKey.hexToBytes(), - blockchain = blockchain, curve = curveToUse - ) - } else { - makeWalletManager(card.cardId, publicKey, blockchain, curveToUse) - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt index 6de34f651a..c580b5389a 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt @@ -9,7 +9,7 @@ import com.tangem.operations.PreflightReadMode import com.tangem.operations.PreflightReadTask import com.tangem.operations.wallet.CreateWalletCommand -@Deprecated("Use CreateProductWalletsResponse instead") +@Deprecated("Use CreateProductWalletTask instead") class CreateWalletsTask(curves: List? = null) : CardSessionRunnable { private val curves = curves ?: listOf( diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletAndRescanTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt similarity index 66% rename from app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletAndRescanTask.kt rename to app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt index 12ce0fdb66..347965e1f5 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletAndRescanTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt @@ -1,25 +1,29 @@ +import com.tangem.blockchain.common.Blockchain import com.tangem.common.CompletionResult import com.tangem.common.card.Card +import com.tangem.common.card.CardWallet import com.tangem.common.card.EllipticCurve import com.tangem.common.card.FirmwareVersion import com.tangem.common.core.CardSession import com.tangem.common.core.CardSessionRunnable import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.guard -import com.tangem.operations.PreflightReadMode -import com.tangem.operations.PreflightReadTask +import com.tangem.operations.derivation.DeriveWalletPublicKeysTask +import com.tangem.operations.derivation.ExtendedPublicKeyList import com.tangem.operations.wallet.CreateWalletCommand import com.tangem.operations.wallet.CreateWalletResponse +import com.tangem.tap.common.extensions.toMapKey import com.tangem.tap.domain.ProductType import com.tangem.tap.domain.TapWorkarounds.getTangemNoteBlockchain -import com.tangem.tap.domain.tasks.product.CreateProductWalletsTask +import com.tangem.tap.domain.tasks.product.CreateWalletsTask import com.tangem.tap.domain.tasks.product.ProductCommandProcessor import com.tangem.tap.domain.tasks.product.getCurvesForNonCreatedWallets +import com.tangem.tap.store /** [REDACTED_AUTHOR] */ -class CreateProductWalletAndRescanTask( +class CreateProductWalletTask( private val type: ProductType, ) : CardSessionRunnable { @@ -28,33 +32,19 @@ class CreateProductWalletAndRescanTask( callback(CompletionResult.Failure(TangemSdkError.CardError())) return } - CreateProductWalletTask(card, type).run(session) { result -> - when (result) { - is CompletionResult.Success -> PreflightReadTask(PreflightReadMode.FullCardRead).run( - session, - callback) - is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) - } - } - } -} -private class CreateProductWalletTask( - private val card: Card, - private val type: ProductType, -) : CardSessionRunnable { - - override fun run( - session: CardSession, - callback: (result: CompletionResult) -> Unit, - ) { val commandProcessor = when (type) { ProductType.Note -> CreateWalletTangemNote() ProductType.Twins -> throw UnsupportedOperationException("Use the TwinCardsManager to create a wallet") ProductType.Wallet -> CreateWalletTangemWallet() else -> CreateWalletOtherCards() } - commandProcessor.proceed(card, session, callback) + commandProcessor.proceed(card, session) { + when (it) { + is CompletionResult.Success -> callback(CompletionResult.Success(session.environment.card!!)) + is CompletionResult.Failure -> callback(CompletionResult.Failure(it.error)) + } + } } } @@ -85,12 +75,12 @@ private class CreateWalletTangemNote : ProductCommandProcessor { + override fun proceed( card: Card, session: CardSession, @@ -98,16 +88,37 @@ private class CreateWalletTangemWallet : ProductCommandProcessor + CreateWalletsTask(curves).run(session) { result -> when (result) { - is CompletionResult.Success -> - callback(CompletionResult.Success(result.data.createWalletResponses[0])) + is CompletionResult.Success -> { + val response = result.data.createWalletResponses[0] + val derivationPaths = listOf(Blockchain.Bitcoin, Blockchain.Ethereum) + .mapNotNull { it.derivationPath() } + + DeriveWalletPublicKeysTask(response.wallet.publicKey, derivationPaths).run(session) { + when (it) { + is CompletionResult.Success -> { + updateDerivedKeys(response.wallet, it.data) + callback(CompletionResult.Success(response)) + } + is CompletionResult.Failure -> callback(CompletionResult.Failure(it.error)) + } + } + } is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) } } } } +//TODO: updating derived wallet public keys - make it better later +private fun updateDerivedKeys(wallet: CardWallet, derivedKeys: ExtendedPublicKeyList) { + val onboardingManager = store.state.globalState.onboardingManager ?: return + onboardingManager.scanResponse = onboardingManager.scanResponse.copy( + derivedKeys = mapOf(wallet.publicKey.toMapKey() to derivedKeys) + ) +} + private class CreateWalletOtherCards : ProductCommandProcessor { override fun proceed( @@ -117,9 +128,9 @@ private class CreateWalletOtherCards : ProductCommandProcessor diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletsTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateWalletsTask.kt similarity index 82% rename from app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletsTask.kt rename to app/src/main/java/com/tangem/tap/domain/tasks/product/CreateWalletsTask.kt index fc00138a57..4eb426dc26 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletsTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateWalletsTask.kt @@ -11,17 +11,17 @@ import com.tangem.operations.wallet.CreateWalletResponse /** [REDACTED_AUTHOR] */ -class CreateProductWalletsResponse( +class CreateWalletsResponse( val createWalletResponses: List ) : CommandResponse -class CreateProductWalletsTask( +class CreateWalletsTask( private val curves: List, -) : CardSessionRunnable { +) : CardSessionRunnable { private val createdWalletsResponses = mutableListOf() - override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { + override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { val curve = curves[createdWalletsResponses.size] createWallet(curve, session, callback) } @@ -29,7 +29,7 @@ class CreateProductWalletsTask( private fun createWallet( curve: EllipticCurve, session: CardSession, - callback: (result: CompletionResult) -> Unit + callback: (result: CompletionResult) -> Unit ) { CreateWalletCommand(curve).run(session) { result -> @@ -37,7 +37,7 @@ class CreateProductWalletsTask( is CompletionResult.Success -> { createdWalletsResponses.add(result.data) if (createdWalletsResponses.size == curves.size) { - callback(CompletionResult.Success(CreateProductWalletsResponse(createdWalletsResponses))) + callback(CompletionResult.Success(CreateWalletsResponse(createdWalletsResponses))) return@run } createWallet(curves[createdWalletsResponses.size], session, callback) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt index 14f454c6b5..6a82fd222f 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt @@ -14,11 +14,16 @@ import com.tangem.common.core.TangemError import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.guard import com.tangem.common.extensions.toHexString +import com.tangem.common.hdWallet.DerivationPath +import com.tangem.common.hdWallet.ExtendedPublicKey import com.tangem.operations.CommandResponse import com.tangem.operations.PreflightReadMode import com.tangem.operations.PreflightReadTask import com.tangem.operations.ScanTask +import com.tangem.operations.derivation.DeriveWalletPublicKeysTask import com.tangem.operations.issuerAndUserData.ReadIssuerDataCommand +import com.tangem.tap.common.extensions.ByteArrayKey +import com.tangem.tap.common.extensions.toMapKey import com.tangem.tap.domain.ProductType import com.tangem.tap.domain.TapSdkError import com.tangem.tap.domain.TapWorkarounds @@ -26,6 +31,7 @@ import com.tangem.tap.domain.TapWorkarounds.getTangemNoteBlockchain import com.tangem.tap.domain.TapWorkarounds.isExcluded import com.tangem.tap.domain.TapWorkarounds.isNotSupportedInThatRelease import com.tangem.tap.domain.extensions.getSingleWallet +import com.tangem.tap.domain.tokens.CurrenciesRepository import com.tangem.tap.domain.twins.TwinsHelper data class ScanResponse( @@ -33,6 +39,7 @@ data class ScanResponse( val productType: ProductType, val walletData: WalletData?, val secondTwinPublicKey: String? = null, + val derivedKeys: Map> = mapOf() ) : CommandResponse { fun getBlockchain(): Blockchain { @@ -60,7 +67,13 @@ data class ScanResponse( fun twinsIsTwinned(): Boolean = card.isTangemTwins() && walletData != null && secondTwinPublicKey != null } -class ScanProductTask(val card: Card? = null) : CardSessionRunnable { +typealias KeyWalletPublicKey = ByteArrayKey + +class ScanProductTask( + val card: Card? = null, + private val currenciesRepository: CurrenciesRepository?, + private val shouldDeriveWC: Boolean +) : CardSessionRunnable { override fun run( session: CardSession, @@ -80,7 +93,7 @@ class ScanProductTask(val card: Card? = null) : CardSessionRunnable ScanNoteProcessor() card.isTangemTwins() -> ScanTwinProcessor() - TapWorkarounds.isTangemWallet(card) -> ScanWalletProcessor() + TapWorkarounds.isTangemWallet(card) -> ScanWalletProcessor(currenciesRepository, shouldDeriveWC) else -> ScanOtherCardsProcessor() } commandProcessor.proceed(card, session) { processorResult -> @@ -116,13 +129,60 @@ private class ScanNoteProcessor : ProductCommandProcessor { } } -private class ScanWalletProcessor : ProductCommandProcessor { +private class ScanWalletProcessor( + private val currenciesRepository: CurrenciesRepository?, + private val shouldDeriveWC: Boolean +) : ProductCommandProcessor { + override fun proceed( card: Card, session: CardSession, callback: (result: CompletionResult) -> Unit ) { - callback(CompletionResult.Success(ScanResponse(card, ProductType.Wallet, session.environment.walletData))) + val derivationPaths = collectDerivationPaths(card) + val wallet = card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } + + if (derivationPaths.isNullOrEmpty() || wallet == null || wallet.chainCode == null) { + callback(CompletionResult.Success(ScanResponse(card, ProductType.Wallet, session.environment.walletData))) + return + } + + DeriveWalletPublicKeysTask(wallet.publicKey, derivationPaths).run(session) { result -> + when (result) { + is CompletionResult.Success -> { + val derivedKeys = mapOf(wallet.publicKey.toMapKey() to result.data) + val response = ScanResponse( + card, + ProductType.Wallet, + session.environment.walletData, + derivedKeys = derivedKeys + ) + callback(CompletionResult.Success(response)) + + } + is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) + } + } + } + + private fun collectDerivationPaths(card: Card): List? { + val currenciesRepository = currenciesRepository ?: return null + val cardCurrencies = currenciesRepository.loadCardCurrencies(card.cardId) + + val blockchainsToDerive = if (cardCurrencies == null) { + mutableListOf(Blockchain.Bitcoin, Blockchain.Ethereum) + } else { + val tokenBlockchains = cardCurrencies.tokens.map { it.blockchain } + (cardCurrencies.blockchains + tokenBlockchains).toMutableList() + } + + if (shouldDeriveWC) { + blockchainsToDerive.addAll(listOf(Blockchain.Ethereum, Blockchain.Binance, Blockchain.EthereumTestnet)) + } + + return blockchainsToDerive.toSet() + .filter { it.getSupportedCurves()?.contains(EllipticCurve.Secp256k1) == true } + .mapNotNull { it.derivationPath() } } } @@ -174,7 +234,7 @@ private class ScanOtherCardsProcessor : ProductCommandProcessor { return } - CreateProductWalletsTask(curvesToCreate).run(session) { result -> + CreateWalletsTask(curvesToCreate).run(session) { result -> when (result) { is CompletionResult.Success -> { PreflightReadTask(PreflightReadMode.FullCardRead, card.cardId).run(session) { readResult -> diff --git a/app/src/main/java/com/tangem/tap/domain/topup/TopUpManager.kt b/app/src/main/java/com/tangem/tap/domain/topup/TopUpManager.kt index 775d3748a7..9dd6e91960 100644 --- a/app/src/main/java/com/tangem/tap/domain/topup/TopUpManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/topup/TopUpManager.kt @@ -35,7 +35,7 @@ class TopUpManager { store.dispatch( GlobalAction.UpdateWalletSignedHashes( walletSignedHashes = signResponse.totalSignedHashes, - walletPublicKey = walletManager.wallet.publicKey, + walletPublicKey = walletManager.wallet.publicKey.seedKey, remainingSignatures = signResponse.remainingSignatures ) ) diff --git a/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt index c035973ac7..6fb4bb28c6 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt @@ -23,7 +23,7 @@ class FinalizeTwinTask( PreflightReadTask(PreflightReadMode.FullCardRead).run(session) { readResult -> when (readResult) { is CompletionResult.Success -> - ScanProductTask(readResult.data).run(session, callback) + ScanProductTask(readResult.data, null, false).run(session, callback) is CompletionResult.Failure -> callback(CompletionResult.Failure(readResult.error)) } diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt index f93217e447..e7b23953b5 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt @@ -2,7 +2,6 @@ package com.tangem.tap.domain.walletconnect import com.tangem.blockchain.common.Blockchain import com.tangem.common.extensions.guard -import com.tangem.common.extensions.hexToBytes import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.global.GlobalAction @@ -97,10 +96,9 @@ class WalletConnectManager { val activeData = sessions[session] ?: return removeSimilarSessions(activeData) + val accounts = listOf(Blockchain.Ethereum.makeAddresses(activeData.wallet.walletPublicKey).first().value) val approved = activeData.client.approveSession( - accounts = listOf(Blockchain.Ethereum.makeAddresses( - activeData.wallet.walletPublicKey.hexToBytes()).first().value - ), + accounts = accounts, chainId = activeData.wallet.chainId ) if (approved) { diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt index e2ac447999..739a1c621d 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt @@ -5,10 +5,7 @@ import com.tangem.blockchain.blockchains.ethereum.EthereumGasLoader import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras import com.tangem.blockchain.blockchains.ethereum.EthereumUtils import com.tangem.blockchain.blockchains.ethereum.EthereumUtils.Companion.toKeccak -import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.TransactionData -import com.tangem.blockchain.common.TransactionSender +import com.tangem.blockchain.common.* import com.tangem.blockchain.extensions.* import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError @@ -36,9 +33,14 @@ class WalletConnectSdkHelper { type: WcTransactionType, ): WcTransactionData? { val factory = store.state.globalState.tapWalletManager.walletManagerFactory + val publicKey = Wallet.PublicKey( + session.wallet.walletPublicKey, + session.wallet.derivedPublicKey, + session.wallet.derivationPath, + ) val walletManager = factory.makeEthereumWalletManager( session.wallet.cardId, - session.wallet.walletPublicKey.hexToBytes(), + publicKey, emptyList(), isTestNet = session.wallet.isTestNet ) ?: return null @@ -151,7 +153,7 @@ class WalletConnectSdkHelper { val command = SignHashCommand( hash = dataToSign.hash, - walletPublicKey = data.walletManager.wallet.publicKey + walletPublicKey = data.walletManager.wallet.publicKey.seedKey ) val result = tangemSdkManager.runTaskAsync(command, initialMessage = Message()) return when (result) { @@ -208,7 +210,7 @@ class WalletConnectSdkHelper { } suspend fun signPersonalMessage(hashToSign: ByteArray, wallet: WalletForSession): String? { - val publicKey = wallet.walletPublicKey.hexToBytes() + val publicKey = wallet.walletPublicKey val command = SignHashCommand(hashToSign, publicKey) return when (val result = tangemSdkManager.runTaskAsync(command, wallet.cardId)) { is CompletionResult.Success -> { 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 dff6c35c72..cca999bf87 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 @@ -1,9 +1,7 @@ package com.tangem.tap.features.details.redux.walletconnect import com.tangem.blockchain.common.* -import com.tangem.common.card.Card import com.tangem.common.extensions.guard -import com.tangem.common.extensions.toHexString import com.tangem.tap.* import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.getFromClipboard @@ -14,6 +12,7 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.TapWorkarounds.isTestCard import com.tangem.tap.domain.extensions.makeWalletManagerForApp import com.tangem.tap.domain.isMultiwalletAllowed +import com.tangem.tap.domain.tasks.product.ScanResponse import com.tangem.tap.domain.walletconnect.WalletConnectManager import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.wallet.R @@ -128,24 +127,32 @@ class WalletConnectMiddleware { } private fun handleScanCard(wcUri: String) { - store.dispatch(GlobalAction.ScanCard({ scanResponse -> + store.dispatch(GlobalAction.ScanCard(true, { scanResponse -> val card = scanResponse.card if (!card.isMultiwalletAllowed) { store.dispatchOnMain(WalletConnectAction.UnsupportedCard) return@ScanCard } - val walletManager = getWalletManager(card).guard { + val walletManager = getWalletManager(scanResponse).guard { store.dispatchOnMain(WalletConnectAction.UnsupportedCard) return@ScanCard } - val key = walletManager.wallet.publicKey + val wallet = walletManager.wallet + val derivedKey = if (wallet.publicKey.blockchainKey.contentEquals(wallet.publicKey.seedKey)) { + null + } else { + walletManager.wallet.publicKey.blockchainKey + } store.dispatchOnMain(WalletConnectAction.OpenSession( wcUri = wcUri, wallet = WalletForSession( - card.cardId, key.toHexString(), - isTestNet = card.isTestCard + card.cardId, + wallet.publicKey.seedKey, + derivedKey, + wallet.publicKey.derivationPath, + card.isTestCard ), )) }, { @@ -153,12 +160,13 @@ class WalletConnectMiddleware { }, R.string.wallet_connect_scan_card_message)) } - private fun getWalletManager(card: Card): WalletManager? { + private fun getWalletManager(scanResponse: ScanResponse): WalletManager? { + val card = scanResponse.card val factory = store.state.globalState.tapWalletManager.walletManagerFactory return if (store.state.globalState.scanResponse?.card?.cardId == card.cardId) { store.state.walletState.getWalletManager(Blockchain.Ethereum) - ?: factory.makeWalletManagerForApp(card, Blockchain.Ethereum) + ?: factory.makeWalletManagerForApp(scanResponse, Blockchain.Ethereum) ?.also { walletManager -> store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManager)) store.dispatch(WalletAction.MultiWallet.AddBlockchain(walletManager.wallet.blockchain)) @@ -167,10 +175,9 @@ class WalletConnectMiddleware { if (currenciesRepository.loadCardCurrencies(card.cardId)?.blockchains?.contains( Blockchain.Ethereum) == true ) { - factory.makeWalletManagerForApp(card, Blockchain.Ethereum) + factory.makeWalletManagerForApp(scanResponse, Blockchain.Ethereum) } else { - factory.makeWalletManagerForApp(card, - Blockchain.Ethereum) + factory.makeWalletManagerForApp(scanResponse, Blockchain.Ethereum) ?.also { currenciesRepository.saveAddedBlockchain(card.cardId, Blockchain.Ethereum) } diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt index 38aeaabc84..2757d8cea9 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt @@ -1,7 +1,9 @@ package com.tangem.tap.features.details.redux.walletconnect +import com.squareup.moshi.JsonClass import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.WalletManager +import com.tangem.common.hdWallet.DerivationPath import com.tangem.tap.common.redux.StateDialog import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialogData import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionRequestDialogData @@ -21,9 +23,12 @@ data class WalletConnectSession( val peerMeta: WCPeerMeta, ) +@JsonClass(generateAdapter = true) data class WalletForSession( val cardId: String, - val walletPublicKey: String, + val walletPublicKey: ByteArray, + val derivedPublicKey: ByteArray?, + val derivationPath: DerivationPath?, val isTestNet: Boolean = false, ) { val chainId diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index 0dc437eb3c..0ad3f5d218 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -28,7 +28,7 @@ class HomeMiddleware { val handler = homeMiddleware const val CARD_SHOP_URI = - "https://shop.tangem.com/?afmc=1i&utm_campaign=1i&utm_source=leaddyno&utm_medium=affiliate" + "https://shop.tangem.com/?afmc=1i&utm_campaign=1i&utm_source=leaddyno&utm_medium=affiliate" } } @@ -61,7 +61,7 @@ private fun handleReadCard() { store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer)) } else { changeButtonState(ButtonState.PROGRESS) - store.dispatch(GlobalAction.ScanCard({ scanResponse -> + store.dispatch(GlobalAction.ScanCard(false, { scanResponse -> store.state.globalState.tapWalletManager.updateConfigManager(scanResponse) store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse)) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 84979eafda..d2c733e206 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -71,7 +71,8 @@ private fun handleWalletAction(action: Action) { withMainContext { when (result) { is CompletionResult.Success -> { - val updatedResponse = scanResponse.copy(card = result.data) + //here we must use updated scanResponse after createWallet & derivation + val updatedResponse = globalState.onboardingManager.scanResponse.copy(card = result.data) onboardingManager.scanResponse = updatedResponse onboardingManager.activationStarted(updatedResponse.card.cardId) store.dispatch(OnboardingWalletAction.ProceedBackup) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt index 6701ac636d..ac8bfea3dd 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt @@ -158,7 +158,7 @@ private fun sendTransaction( store.dispatch( GlobalAction.UpdateWalletSignedHashes( walletSignedHashes = signResponse.totalSignedHashes, - walletPublicKey = walletManager.wallet.publicKey, + walletPublicKey = walletManager.wallet.publicKey.seedKey, remainingSignatures = signResponse.remainingSignatures ) ) diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/CurrencyListItem.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/CurrencyListItem.kt index 98efd84540..bcf0bf5644 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/CurrencyListItem.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/CurrencyListItem.kt @@ -6,8 +6,12 @@ import com.tangem.blockchain.common.Token import com.tangem.wallet.R sealed class CurrencyListItem { + var isAdded: Boolean = false + var isLock: Boolean = false + data class TokenListItem(val token: Token) : CurrencyListItem() data class BlockchainListItem(val blockchain: Blockchain) : CurrencyListItem() + data class TitleListItem( @StringRes val titleResId: Int, var isContentShown: Boolean = true, diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt index 1be9e7c701..27db550708 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt @@ -7,6 +7,8 @@ import org.rekotlin.Action sealed class TokensAction : Action { + object ResetState : TokensAction() + object LoadCurrencies : TokensAction() { data class Success(val currencies: List) : TokensAction() } @@ -19,4 +21,9 @@ sealed class TokensAction : Action { data class ToggleShowTokensForBlockchain(val isShown: Boolean, val blockchain: Blockchain) : TokensAction() + sealed class TokensList : TokensAction() { + data class AddBlockchain(val blockchain: Blockchain) : TokensList() + data class AddToken(val token: Token) : TokensList() + object SaveChanges : TokensList() + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt index 6ecff3f595..42311b8b1a 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt @@ -1,9 +1,22 @@ package com.tangem.tap.features.tokens.redux +import com.tangem.common.CompletionResult +import com.tangem.common.card.EllipticCurve +import com.tangem.tap.common.extensions.dispatchErrorNotification +import com.tangem.tap.common.extensions.toMapKey import com.tangem.tap.common.redux.AppState +import com.tangem.tap.common.redux.global.GlobalAction +import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.currenciesRepository +import com.tangem.tap.domain.DELAY_SDK_DIALOG_CLOSE +import com.tangem.tap.domain.TapError import com.tangem.tap.domain.TapWorkarounds.isTestCard +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.scope import com.tangem.tap.store +import com.tangem.tap.tangemSdkManager +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import org.rekotlin.Middleware class TokensMiddleware { @@ -12,22 +25,92 @@ class TokensMiddleware { { next -> { action -> when (action) { - is TokensAction.LoadCurrencies -> { - val card = state()?.globalState?.scanResponse?.card - val isTestcard = card?.isTestCard ?: false - val tokens = currenciesRepository.getPopularTokens(isTestcard) - val blockchains = currenciesRepository.getBlockchains( - cardFirmware = card?.firmwareVersion, - isTestNet = isTestcard - ) - val currencies = CurrencyListItem.createListOfCurrencies( - blockchains, tokens - ) - store.dispatch(TokensAction.LoadCurrencies.Success(currencies)) - } + is TokensAction.LoadCurrencies -> handleLoadCurrencies(action) + is TokensAction.TokensList.SaveChanges -> handleSaveChanges(action) } next(action) } } } + + private fun handleLoadCurrencies(action: TokensAction.LoadCurrencies) { + val scanResponse = store.state.globalState.scanResponse ?: return + val isTestcard = scanResponse.card.isTestCard + + val tokens = currenciesRepository.getPopularTokens(isTestcard) + val blockchains = currenciesRepository.getBlockchains( + cardFirmware = scanResponse.card.firmwareVersion, + isTestNet = isTestcard + ) + val currencies = CurrencyListItem.createListOfCurrencies(blockchains, tokens).toMutableList() + if (scanResponse.isTangemWallet()) { + currencies.forEach { + when (it) { + is CurrencyListItem.TitleListItem -> { + } + is CurrencyListItem.BlockchainListItem -> { + val firstCurve = it.blockchain.getSupportedCurves()?.firstOrNull() + if (firstCurve == EllipticCurve.Ed25519) { + it.isLock = true + } + } + is CurrencyListItem.TokenListItem -> { + val firstCurve = it.token.blockchain.getSupportedCurves()?.firstOrNull() + if (firstCurve == EllipticCurve.Ed25519) { + it.isLock = true + } + } + } + } + } + store.dispatch(TokensAction.LoadCurrencies.Success(currencies)) + } + + private fun handleSaveChanges(action: TokensAction.TokensList.SaveChanges) { + val scanResponse = store.state.globalState.scanResponse ?: return + val wallet = scanResponse.card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: return + + val candidatesToAdd = store.state.tokensState.candidateToAdd + if (candidatesToAdd.isEmpty()) return + + val blockchains = candidatesToAdd.filterIsInstance() + .map { it.blockchain } + val tokens = candidatesToAdd.filterIsInstance() + .map { it.token } + if (blockchains.isEmpty() && tokens.isEmpty()) return + + val derivationPathsCandidates = (blockchains + tokens.map { it.blockchain }) + .distinct().mapNotNull { it.derivationPath() } + + val mapKeyOfWalletPublicKey = wallet.publicKey.toMapKey() + val alreadyDerivedKeys = scanResponse.derivedKeys[mapKeyOfWalletPublicKey]?.toMutableList() ?: mutableListOf() + val alreadyDerivedPaths = alreadyDerivedKeys.map { it.derivationPath } + + val toDerive = derivationPathsCandidates.filterNot { alreadyDerivedPaths.contains(it) } + + scope.launch { + val result = tangemSdkManager.derivePublicKeys(scanResponse.card.cardId, wallet.publicKey, toDerive) + when (result) { + is CompletionResult.Success -> { + val newDerivedKeys = result.data + alreadyDerivedKeys.addAll(newDerivedKeys) + val updatedScanResponse = scanResponse.copy( + derivedKeys = mapOf(mapKeyOfWalletPublicKey to alreadyDerivedKeys.toList()) + ) + + store.dispatch(GlobalAction.SaveScanNoteResponse(updatedScanResponse)) + + val actions = blockchains.map { WalletAction.MultiWallet.AddBlockchain(it) } + tokens.map { + WalletAction.MultiWallet.AddToken(it) + } + actions.forEach { store.dispatch(it) } + delay(DELAY_SDK_DIALOG_CLOSE) + store.dispatch(NavigationAction.PopBackTo()) + } + is CompletionResult.Failure -> { + store.dispatchErrorNotification(TapError.CustomError("Error adding tokens")) + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt index f221424d67..f6ba05bc49 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt @@ -17,6 +17,7 @@ private fun internalReduce(action: Action, state: AppState): TokensState { val tokensState = state.tokensState return when (action) { + is TokensAction.ResetState -> TokensState() is TokensAction.LoadCurrencies.Success -> { tokensState.copy(currencies = action.currencies, shownCurrencies = action.currencies) } @@ -33,15 +34,25 @@ private fun internalReduce(action: Action, state: AppState): TokensState { if (action.isShown) { val shownCurrencies = tokensState.shownCurrencies .removeTokensForBlockchain(action.blockchain) - shownCurrencies.toggleHeaderContentShownValue(action.blockchain) + shownCurrencies.toggleHeaderContentShownValue(action.blockchain) tokensState.copy(shownCurrencies = shownCurrencies) } else { val shownCurrencies = tokensState.shownCurrencies .addTokensForBlockchain(action.blockchain, tokensState.currencies) - shownCurrencies.toggleHeaderContentShownValue(action.blockchain) + shownCurrencies.toggleHeaderContentShownValue(action.blockchain) tokensState.copy(shownCurrencies = shownCurrencies) } } + is TokensAction.TokensList.AddBlockchain -> { + val candidates = tokensState.candidateToAdd.toMutableSet() + candidates.add(CurrencyListItem.BlockchainListItem(action.blockchain)) + tokensState.copy(candidateToAdd = candidates.toList()) + } + is TokensAction.TokensList.AddToken -> { + val candidates = tokensState.candidateToAdd.toMutableSet() + candidates.add(CurrencyListItem.TokenListItem(action.token)) + tokensState.copy(candidateToAdd = candidates.toList()) + } else -> tokensState } } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt index ef30a92229..d0c204ee45 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt @@ -10,6 +10,7 @@ data class TokensState( val addedCurrencies: CardCurrencies? = null, val currencies: List = emptyList(), val shownCurrencies: List = emptyList(), + val candidateToAdd: List = emptyList(), ) : StateType data class TokenWithAmount( diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt index b5d09b7074..e29365e728 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt @@ -12,6 +12,7 @@ import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.transition.TransitionInflater import com.tangem.tap.common.redux.navigation.NavigationAction +import com.tangem.tap.features.tokens.redux.TokensAction import com.tangem.tap.features.tokens.redux.TokensState import com.tangem.tap.features.tokens.ui.adapters.CurrenciesAdapter import com.tangem.tap.mainScope @@ -57,30 +58,31 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens), override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + (activity as? AppCompatActivity)?.setSupportActionBar(toolbar) toolbar.setNavigationOnClickListener { activity?.onBackPressed() } + btn_tokens_save_changes.setOnClickListener { store.dispatch(TokensAction.TokensList.SaveChanges)} setupPopularTokensRecyclerView() } - private fun setupPopularTokensRecyclerView() { viewAdapter = CurrenciesAdapter() rv_popular_tokens.layoutManager = LinearLayoutManager(context) rv_popular_tokens.adapter = viewAdapter } - override fun newState(state: TokensState) { if (activity == null) return + + btn_tokens_save_changes.isEnabled = state.candidateToAdd.isNotEmpty() + viewAdapter.addedCurrencies = state.addedCurrencies viewAdapter.submitUnfilteredList(state.shownCurrencies) } override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { - R.id.menu_search -> { - true - } + R.id.menu_search -> true else -> super.onOptionsItemSelected(item) } } @@ -101,6 +103,11 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens), .launchIn(mainScope) return super.onCreateOptionsMenu(menu, inflater); } + + override fun onDestroy() { + store.dispatch(TokensAction.ResetState) + super.onDestroy() + } } fun SearchView.inputtedTextAsFlow(): Flow = callbackFlow { diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt index 85a8462b81..5935014bf4 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt @@ -14,7 +14,6 @@ import com.tangem.tap.common.extensions.show import com.tangem.tap.domain.tokens.CardCurrencies import com.tangem.tap.features.tokens.redux.CurrencyListItem import com.tangem.tap.features.tokens.redux.TokensAction -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.store import com.tangem.wallet.R import kotlinx.android.synthetic.main.item_currency_subtitle.view.* @@ -86,15 +85,15 @@ class CurrenciesAdapter : ListAdapter is CurrencyListItem.BlockchainListItem -> { element.blockchain.currency.toLowerCase(Locale.US) .contains(queryNormalized) || - element.blockchain.fullName.toLowerCase(Locale.US) - .contains(queryNormalized) + element.blockchain.fullName.toLowerCase(Locale.US) + .contains(queryNormalized) } is CurrencyListItem.TokenListItem -> { element.token.name.toLowerCase(Locale.US) .contains(queryNormalized) || - element.token.symbol.toLowerCase(Locale.US) - .contains(queryNormalized) + element.token.symbol.toLowerCase(Locale.US) + .contains(queryNormalized) } is CurrencyListItem.TitleListItem -> true } @@ -105,17 +104,16 @@ class CurrenciesAdapter : ListAdapter submitList(list) } - class CurrenciesViewHolder(val view: View) : - RecyclerView.ViewHolder(view) { + class CurrenciesViewHolder(val view: View) : RecyclerView.ViewHolder(view) { + fun bind(currency: CurrencyListItem, addedCurrencies: CardCurrencies?) { when (currency) { is CurrencyListItem.BlockchainListItem -> { val blockchain = currency.blockchain view.tv_currency_name.text = blockchain.fullName view.tv_currency_symbol.text = blockchain.currency - val isAdded = addedCurrencies?.blockchains?.contains(blockchain) == true - view.btn_add_token.show(!isAdded) - view.btn_token_added.show(isAdded) + currency.isAdded = addedCurrencies?.blockchains?.contains(blockchain) == true + modifyAddTokenButton(currency) Picasso.get().loadCurrenciesIcon( imageView = view.iv_currency, @@ -124,9 +122,9 @@ class CurrenciesAdapter : ListAdapter ) view.btn_add_token.setOnClickListener { - store.dispatch(WalletAction.MultiWallet.AddBlockchain(blockchain)) - view.btn_add_token.hide() - view.btn_token_added.show() + store.dispatch(TokensAction.TokensList.AddBlockchain(blockchain)) + currency.isAdded = !currency.isAdded + modifyAddTokenButton(currency) } } is CurrencyListItem.TokenListItem -> { @@ -134,13 +132,11 @@ class CurrenciesAdapter : ListAdapter view.tv_currency_name.text = token.name view.tv_currency_symbol.text = token.symbol - val isAdded = addedCurrencies?.tokens + currency.isAdded = addedCurrencies?.tokens ?.any { it.symbol == token.symbol && it.contractAddress == token.contractAddress } == true - - view.btn_add_token.show(!isAdded) - view.btn_token_added.show(isAdded) + modifyAddTokenButton(currency) Picasso.get().loadCurrenciesIcon( imageView = view.iv_currency, @@ -148,13 +144,23 @@ class CurrenciesAdapter : ListAdapter token = token, blockchain = token.blockchain ) view.btn_add_token.setOnClickListener { - store.dispatch(WalletAction.MultiWallet.AddToken(token)) - view.btn_add_token.hide() - view.btn_token_added.show() + store.dispatch(TokensAction.TokensList.AddToken(token)) + currency.isAdded = !currency.isAdded + modifyAddTokenButton(currency) } } } } + + private fun modifyAddTokenButton(currency: CurrencyListItem) { + if (currency.isLock) { + view.btn_add_token.isEnabled = false + } else { + val text = if (currency.isAdded) R.string.add_token_added else R.string.common_add + view.btn_add_token.setText(text) + view.btn_add_token.isEnabled = !currency.isAdded + } + } } class TitleViewHolder(val view: View) : diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index 149550727b..1081a3303c 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -50,8 +50,7 @@ sealed class WalletAction : Action { data class AddToken(val token: Token) : MultiWallet() data class SaveCurrencies(val cardCurrencies: CardCurrencies) : MultiWallet() object FindTokensInUse : MultiWallet() - data class FindBlockchainsInUse(val card: Card, val factory: WalletManagerFactory) : - MultiWallet() + object FindBlockchainsInUse : MultiWallet() data class TokenLoaded(val amount: Amount, val token: Token) : MultiWallet() data class SelectWallet(val walletData: WalletData?) : MultiWallet() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index 8397f148e0..7d93d65312 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -24,10 +24,12 @@ class MultiWalletMiddleware { fun handle( action: WalletAction.MultiWallet, walletState: WalletState?, globalState: GlobalState?, ) { + val globalState = globalState ?: return + val tapWalletManager = globalState.tapWalletManager + when (action) { is WalletAction.MultiWallet.AddWalletManagers -> { - store.state.globalState.feedbackManager?.infoHolder - ?.setWalletsInfo(action.walletManagers) + globalState.feedbackManager?.infoHolder?.setWalletsInfo(action.walletManagers) } is WalletAction.MultiWallet.SelectWallet -> { if (action.walletData != null) { @@ -35,7 +37,7 @@ class MultiWalletMiddleware { } } is WalletAction.MultiWallet.AddToken -> { - globalState?.scanResponse?.card?.cardId?.let { + globalState.scanResponse?.card?.cardId?.let { currenciesRepository.saveAddedToken(it, action.token) } addToken(action.token, walletState, globalState) @@ -44,35 +46,33 @@ class MultiWalletMiddleware { addTokens(action.tokens, walletState, globalState) } is WalletAction.MultiWallet.AddBlockchain -> { - globalState?.scanResponse?.card?.let { card -> - currenciesRepository.saveAddedBlockchain(card.cardId, action.blockchain) + globalState.scanResponse?.let { + currenciesRepository.saveAddedBlockchain(it.card.cardId, action.blockchain) if (walletState?.blockchains?.contains(action.blockchain) != true) { - globalState.tapWalletManager.walletManagerFactory - .makeWalletManagerForApp(card, action.blockchain)?.let { - store.dispatch(WalletAction.MultiWallet.AddWalletManagers(it)) + tapWalletManager.walletManagerFactory + .makeWalletManagerForApp(it, action.blockchain)?.let { walletManager -> + store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManager)) } } } store.dispatch(WalletAction.LoadFiatRate(currency = Currency.Blockchain(action.blockchain))) store.dispatch(WalletAction.LoadWallet( - moonpayStatus = globalState?.moonpayStatus, + moonpayStatus = globalState.moonpayStatus, blockchain = action.blockchain - ) + ) ) } is WalletAction.MultiWallet.SaveCurrencies -> { - val cardId = globalState?.scanResponse?.card?.cardId - cardId?.let { currenciesRepository.saveCardCurrencies(it, action.cardCurrencies) } + globalState.scanResponse?.card?.cardId?.let { + currenciesRepository.saveCardCurrencies(it, action.cardCurrencies) + } } is WalletAction.MultiWallet.RemoveWallet -> { - val cardId = globalState?.scanResponse?.card?.cardId + val cardId = globalState.scanResponse?.card?.cardId when (val currency = action.walletData.currency) { is Currency.Blockchain -> { cardId?.let { - currenciesRepository.removeBlockchain( - it, - currency.blockchain - ) + currenciesRepository.removeBlockchain(it, currency.blockchain) } } is Currency.Token -> { @@ -83,11 +83,13 @@ class MultiWalletMiddleware { } } is WalletAction.MultiWallet.FindBlockchainsInUse -> { - val cardFirmware = globalState?.scanResponse?.card?.firmwareVersion + val scanResponse = globalState.scanResponse ?: return + + val cardFirmware = scanResponse.card.firmwareVersion val blockchains = currenciesRepository.getBlockchains(cardFirmware) .filterNot { walletState?.blockchains?.contains(it) == true } val walletManagers = - action.factory.makeWalletManagersForApp(action.card, blockchains) + tapWalletManager.walletManagerFactory.makeWalletManagersForApp(scanResponse, blockchains) scope.launch { walletManagers.map { walletManager -> @@ -120,12 +122,13 @@ class MultiWalletMiddleware { } } is WalletAction.MultiWallet.FindTokensInUse -> { - val card = globalState?.scanResponse?.card ?: return + val scanResponse = globalState.scanResponse ?: return + + val walletFactory = tapWalletManager.walletManagerFactory + val card = scanResponse.card val walletManager = walletState?.getWalletManager(Blockchain.Ethereum) - ?: globalState.tapWalletManager.walletManagerFactory.makeWalletManagerForApp( - card = card, - blockchain = Blockchain.Ethereum - ) + ?: walletFactory.makeWalletManagerForApp(scanResponse, Blockchain.Ethereum) + val tokenFinder = walletManager as TokenFinder scope.launch { val result = tokenFinder.findTokens() @@ -159,19 +162,18 @@ class MultiWalletMiddleware { } private fun addToken(token: Token, walletState: WalletState?, globalState: GlobalState?) { - val card = globalState?.scanResponse?.card ?: return + val scanResponse = globalState?.scanResponse ?: return + val walletManager = walletState?.getWalletManager(token) ?: globalState.tapWalletManager.walletManagerFactory.makeWalletManagerForApp( - card = card, - blockchain = token.blockchain + scanResponse, + token.blockchain )?.also { walletManager -> store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManager)) store.dispatch(WalletAction.MultiWallet.AddBlockchain(walletManager.wallet.blockchain)) } - store.dispatch( - WalletAction.LoadFiatRate(currency = Currency.Token(token)) - ) + store.dispatch(WalletAction.LoadFiatRate(currency = Currency.Token(token))) scope.launch { when (val result = walletManager?.addToken(token)) { @@ -189,12 +191,13 @@ class MultiWalletMiddleware { walletState: WalletState?, globalState: GlobalState?, ) { - val card = globalState?.scanResponse?.card ?: return + val scanResponse = globalState?.scanResponse ?: return + val tokensWithManagers = tokens.map { token -> val walletManager = walletState?.getWalletManager(token) ?: globalState.tapWalletManager.walletManagerFactory.makeWalletManagerForApp( - card = card, - blockchain = token.blockchain + scanResponse, + token.blockchain )?.also { walletManager -> store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManager)) store.dispatch(WalletAction.MultiWallet.AddBlockchain(walletManager.wallet.blockchain)) diff --git a/app/src/main/java/com/tangem/tap/network/Retrofit.kt b/app/src/main/java/com/tangem/tap/network/Retrofit.kt index dd16923173..a2188e6d64 100644 --- a/app/src/main/java/com/tangem/tap/network/Retrofit.kt +++ b/app/src/main/java/com/tangem/tap/network/Retrofit.kt @@ -4,6 +4,7 @@ import com.squareup.moshi.FromJson import com.squareup.moshi.Moshi import com.squareup.moshi.ToJson import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import com.tangem.common.json.TangemSdkAdapter import com.tangem.wallet.BuildConfig import okhttp3.Interceptor import okhttp3.OkHttpClient @@ -41,7 +42,10 @@ fun createMoshiConverterFactory(): Converter.Factory = MoshiConverterFactory.cre fun createMoshi(): Moshi = Moshi.Builder() .add(BigDecimalAdapter) - .add(KotlinJsonAdapterFactory()).build() + .add(KotlinJsonAdapterFactory()) + .add(TangemSdkAdapter.DerivationPathAdapter()) + .add(TangemSdkAdapter.DerivationNodeAdapter()) + .build() private fun createHttpLoggingInterceptor(): HttpLoggingInterceptor { val logging = HttpLoggingInterceptor() diff --git a/app/src/main/res/layout/fragment_add_tokens.xml b/app/src/main/res/layout/fragment_add_tokens.xml index 792f48fc05..4d25c3cf14 100644 --- a/app/src/main/res/layout/fragment_add_tokens.xml +++ b/app/src/main/res/layout/fragment_add_tokens.xml @@ -13,8 +13,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/backgroundLightGray" - android:fitsSystemWindows="true" - > + android:fitsSystemWindows="true"> + + + diff --git a/app/src/main/res/layout/item_popular_token.xml b/app/src/main/res/layout/item_popular_token.xml index 976047b14b..dc388c1dfa 100644 --- a/app/src/main/res/layout/item_popular_token.xml +++ b/app/src/main/res/layout/item_popular_token.xml @@ -74,33 +74,17 @@ app:layout_constraintVertical_bias="0" tools:text="NODLE" /> - - - @@ -110,7 +94,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" app:barrierDirection="start" - app:constraint_referenced_ids="btn_add_token, btn_token_added" /> - + app:constraint_referenced_ids="btn_add_token" /> \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 3bf6353760..93cbbcca62 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -10,7 +10,7 @@ @color/accent #661ACE80 @color/darkGray6 - #661C1C1E + #6A6A6A #5AC461 #C4291C From 8b36ed7a9ba721a67b4a631f7e30fe8c77d48f99 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 15:57:44 +0300 Subject: [PATCH 12/37] Updated on 2026-08-14 --- .../features/tokens/redux/TokensMiddleware.kt | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt index 42311b8b1a..4e1d90b2e4 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt @@ -1,5 +1,7 @@ package com.tangem.tap.features.tokens.redux +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.Token import com.tangem.common.CompletionResult import com.tangem.common.card.EllipticCurve import com.tangem.tap.common.extensions.dispatchErrorNotification @@ -11,6 +13,7 @@ import com.tangem.tap.currenciesRepository import com.tangem.tap.domain.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.domain.TapError import com.tangem.tap.domain.TapWorkarounds.isTestCard +import com.tangem.tap.domain.tasks.product.ScanResponse import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.scope import com.tangem.tap.store @@ -68,7 +71,6 @@ class TokensMiddleware { private fun handleSaveChanges(action: TokensAction.TokensList.SaveChanges) { val scanResponse = store.state.globalState.scanResponse ?: return - val wallet = scanResponse.card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: return val candidatesToAdd = store.state.tokensState.candidateToAdd if (candidatesToAdd.isEmpty()) return @@ -79,8 +81,24 @@ class TokensMiddleware { .map { it.token } if (blockchains.isEmpty() && tokens.isEmpty()) return - val derivationPathsCandidates = (blockchains + tokens.map { it.blockchain }) - .distinct().mapNotNull { it.derivationPath() } + if (scanResponse.isTangemWallet()) { + deriveMissingBlockchains(scanResponse, blockchains, tokens) + } else { + submitAdd(blockchains, tokens) + store.dispatch(NavigationAction.PopBackTo()) + } + } + + private fun deriveMissingBlockchains( + scanResponse: ScanResponse, + blockchains: List, + tokens: List + ) { + val wallet = scanResponse.card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } ?: return + + val tokenBlockchains = tokens.map { it.blockchain } + val derivationPathsCandidates = (blockchains + tokenBlockchains).distinct() + .mapNotNull { it.derivationPath() } val mapKeyOfWalletPublicKey = wallet.publicKey.toMapKey() val alreadyDerivedKeys = scanResponse.derivedKeys[mapKeyOfWalletPublicKey]?.toMutableList() ?: mutableListOf() @@ -97,13 +115,9 @@ class TokensMiddleware { val updatedScanResponse = scanResponse.copy( derivedKeys = mapOf(mapKeyOfWalletPublicKey to alreadyDerivedKeys.toList()) ) - store.dispatch(GlobalAction.SaveScanNoteResponse(updatedScanResponse)) + submitAdd(blockchains, tokens) - val actions = blockchains.map { WalletAction.MultiWallet.AddBlockchain(it) } + tokens.map { - WalletAction.MultiWallet.AddToken(it) - } - actions.forEach { store.dispatch(it) } delay(DELAY_SDK_DIALOG_CLOSE) store.dispatch(NavigationAction.PopBackTo()) } @@ -113,4 +127,12 @@ class TokensMiddleware { } } } + + private fun submitAdd(blockchains: List, tokens: List) { + (blockchains.map { + WalletAction.MultiWallet.AddBlockchain(it) + } + tokens.map { + WalletAction.MultiWallet.AddToken(it) + }).forEach { store.dispatch(it) } + } } \ No newline at end of file From 9c5d35adbeaa9c8a3f57f9e82bb764a71ca975c7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 16:28:46 +0300 Subject: [PATCH 13/37] Updated on 2026-08-14 --- .../walletconnect/WalletConnectSdkHelper.kt | 3 ++- .../walletconnect/WalletConnectMiddleware.kt | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt index 739a1c621d..152bdd04d7 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt @@ -10,6 +10,7 @@ import com.tangem.blockchain.extensions.* import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.hexToBytes +import com.tangem.crypto.CryptoUtils import com.tangem.operations.sign.SignHashCommand import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler import com.tangem.tap.common.extensions.toFormattedString @@ -216,7 +217,7 @@ class WalletConnectSdkHelper { is CompletionResult.Success -> { val hash = result.data.signature return EthereumUtils.prepareSignedMessageData( - hash, hashToSign, publicKey + hash, hashToSign, CryptoUtils.decompressPublicKey(wallet.walletPublicKey) ) } is CompletionResult.Failure -> { 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 cca999bf87..2c1aab1596 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 @@ -164,22 +164,28 @@ class WalletConnectMiddleware { val card = scanResponse.card val factory = store.state.globalState.tapWalletManager.walletManagerFactory + val wcBlockchain = if (scanResponse.card.isTestCard) { + Blockchain.EthereumTestnet + } else { + Blockchain.Ethereum + } + return if (store.state.globalState.scanResponse?.card?.cardId == card.cardId) { - store.state.walletState.getWalletManager(Blockchain.Ethereum) - ?: factory.makeWalletManagerForApp(scanResponse, Blockchain.Ethereum) + store.state.walletState.getWalletManager(wcBlockchain) + ?: factory.makeWalletManagerForApp(scanResponse, wcBlockchain) ?.also { walletManager -> store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManager)) store.dispatch(WalletAction.MultiWallet.AddBlockchain(walletManager.wallet.blockchain)) } } else { if (currenciesRepository.loadCardCurrencies(card.cardId)?.blockchains?.contains( - Blockchain.Ethereum) == true + wcBlockchain) == true ) { - factory.makeWalletManagerForApp(scanResponse, Blockchain.Ethereum) + factory.makeWalletManagerForApp(scanResponse, wcBlockchain) } else { - factory.makeWalletManagerForApp(scanResponse, Blockchain.Ethereum) + factory.makeWalletManagerForApp(scanResponse, wcBlockchain) ?.also { - currenciesRepository.saveAddedBlockchain(card.cardId, Blockchain.Ethereum) + currenciesRepository.saveAddedBlockchain(card.cardId, wcBlockchain) } } } From f2a3b35fe98273233af8568ae95bf3d201d7565e Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 16:31:25 +0300 Subject: [PATCH 14/37] Updated on 2026-08-14 --- .../send/redux/middlewares/SendMiddleware.kt | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt index ac8bfea3dd..ff45a74e19 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt @@ -15,6 +15,7 @@ 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.common.redux.navigation.NavigationAction +import com.tangem.tap.domain.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.domain.TangemSigner import com.tangem.tap.domain.TapError import com.tangem.tap.domain.TapWorkarounds.isStart2Coin @@ -152,9 +153,8 @@ private fun sendTransaction( if (card.isStart2Coin) { tangemSdk.config.linkedTerminal = false } - val signer = TangemSigner( - tangemSdk = tangemSdk, initialMessage = action.messageForSigner - ) { signResponse -> + + val signer = TangemSigner(tangemSdk, action.messageForSigner) { signResponse -> store.dispatch( GlobalAction.UpdateWalletSignedHashes( walletSignedHashes = signResponse.totalSignedHashes, @@ -163,10 +163,22 @@ private fun sendTransaction( ) ) } - val result = (walletManager as TransactionSender).send(txData, signer) + + val sendResult = try { + (walletManager as TransactionSender).send(txData, signer) + } catch (ex: Exception) { + FirebaseCrashlytics.getInstance().recordException(ex) + delay(DELAY_SDK_DIALOG_CLOSE) + withMainContext { + dispatch(SendAction.ChangeSendButtonState(ButtonState.ENABLED)) + store.dispatchErrorNotification(TapError.CustomError(ex.localizedMessage ?: "Unknown error")) + } + return@launch + } + withContext(Dispatchers.Main) { tangemSdk.config.linkedTerminal = isLinkedTerminal - when (result) { + when (sendResult) { is SimpleResult.Success -> { FirebaseAnalyticsHandler.triggerEvent( event = AnalyticsEvent.TRANSACTION_IS_SENT, @@ -191,20 +203,18 @@ private fun sendTransaction( } } is SimpleResult.Failure -> { - when (result.error) { + when (sendResult.error) { is CreateAccountUnderfunded -> { - val error = result.error as CreateAccountUnderfunded + val error = sendResult.error as CreateAccountUnderfunded val reserve = error.minReserve.value?.stripZeroPlainString() ?: "0" val symbol = error.minReserve.currencySymbol dispatch(SendAction.SendError(TapError.CreateAccountUnderfunded(listOf(reserve, symbol)))) } is SendException -> { - result.error?.let { - FirebaseCrashlytics.getInstance().recordException(it) - } + sendResult.error?.let { FirebaseCrashlytics.getInstance().recordException(it) } } is Throwable -> { - val throwable = result.error as Throwable + val throwable = sendResult.error as Throwable val message = throwable.message val infoHolder = store.state.globalState.feedbackManager?.infoHolder when { @@ -228,13 +238,13 @@ private fun sendTransaction( dispatch(SendAction.SendError(TapError.XmlError.AssetAccountNotCreated)) } else -> { - (result.error as? TangemSdkError)?.let { error -> + (sendResult.error as? TangemSdkError)?.let { error -> FirebaseAnalyticsHandler.logCardSdkError( error, FirebaseAnalyticsHandler.ActionToLog.SendTransaction, mapOf( FirebaseAnalyticsHandler.AnalyticsParam.BLOCKCHAIN - to walletManager.wallet.blockchain.currency), + to walletManager.wallet.blockchain.currency), card = card, ) } @@ -303,7 +313,7 @@ fun createValidateTransactionError(errorList: EnumSet, walletM private fun setIfSendingToPayIdEnabled(appState: AppState?, dispatch: (Action) -> Unit) { val isSendingToPayIdEnabled = - appState?.globalState?.configManager?.config?.isSendingToPayIdEnabled ?: false + appState?.globalState?.configManager?.config?.isSendingToPayIdEnabled ?: false dispatch(AddressPayIdActionUi.ChangePayIdState(isSendingToPayIdEnabled)) } From 4b4c3c79028b77a02e69bf714ab4a293c54dc0c4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 16:39:57 +0300 Subject: [PATCH 15/37] Updated on 2026-08-14 --- .../products/wallet/redux/OnboardingWalletReducer.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt index 982d4e127b..8e0c5daac7 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt @@ -39,7 +39,10 @@ class BackupReducer { ): BackupState { return when (action) { - BackupAction.IntroduceBackup -> BackupState(backupStep = BackupStep.InitBackup) + BackupAction.IntroduceBackup -> BackupState( + backupStep = BackupStep.InitBackup, + canSkipBackup = state.canSkipBackup + ) BackupAction.StartBackup -> state.copy(backupStep = BackupStep.ScanOriginCard) From 1608e759ee458ed026bfedbfe9f9c830ab2efb21 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 16:49:20 +0300 Subject: [PATCH 16/37] Updated on 2026-08-14 --- app/src/main/res/layout/fragment_onboarding_wallet.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/fragment_onboarding_wallet.xml b/app/src/main/res/layout/fragment_onboarding_wallet.xml index 7197ed1eab..56427dc352 100644 --- a/app/src/main/res/layout/fragment_onboarding_wallet.xml +++ b/app/src/main/res/layout/fragment_onboarding_wallet.xml @@ -168,7 +168,7 @@ app:layout_constraintBottom_toTopOf="@id/layout_buttons_common" app:flow_verticalBias="0" app:layout_constraintTop_toTopOf="@+id/guideline2" - android:layout_marginBottom="12dp"/> + android:layout_marginBottom="8dp"/> From 88adeea535f8d2086bc9c90c12f7167cd9e3de88 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 17:23:16 +0300 Subject: [PATCH 17/37] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/domain/TangemSigner.kt | 4 ++-- .../main/java/com/tangem/tap/domain/tasks/SignHashTask.kt | 7 ++++--- .../java/com/tangem/tap/domain/tasks/SignHashesTask.kt | 7 ++++--- .../com/tangem/tap/domain/tasks/product/ScanProductTask.kt | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt b/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt index 1042913d5d..20d1eda08c 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt @@ -18,7 +18,7 @@ class TangemSigner( override suspend fun sign(hash: ByteArray, cardId: String, publicKey: Wallet.PublicKey): CompletionResult { return suspendCoroutine { continuation -> - val command = SignHashTask(hash, publicKey.seedKey) + val command = SignHashTask(hash, publicKey) tangemSdk.startSessionWithRunnable( runnable = command, cardId = cardId, @@ -43,7 +43,7 @@ class TangemSigner( override suspend fun sign(hashes: List, cardId: String, publicKey: Wallet.PublicKey): CompletionResult> { return suspendCoroutine { continuation -> - val task = SignHashesTask(hashes, publicKey.seedKey) + val task = SignHashesTask(hashes, publicKey) tangemSdk.startSessionWithRunnable( runnable = task, cardId = cardId, diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/SignHashTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/SignHashTask.kt index 3c24418b42..58520125ce 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/SignHashTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/SignHashTask.kt @@ -1,5 +1,6 @@ package com.tangem.tap.domain.tasks +import com.tangem.blockchain.common.Wallet import com.tangem.common.CompletionResult import com.tangem.common.core.CardSession import com.tangem.common.core.CardSessionRunnable @@ -15,17 +16,17 @@ class TangemSignHashResponse( class SignHashTask( private val hash: ByteArray, - private val walletPublicKey: ByteArray, + private val publicKey: Wallet.PublicKey, ) : CardSessionRunnable { override fun run(session: CardSession, callback: CompletionCallback) { - SignHashCommand(hash, walletPublicKey).run(session) { response -> + SignHashCommand(hash, publicKey.seedKey, publicKey.derivationPath).run(session) { response -> when (response) { is CompletionResult.Success -> { callback(CompletionResult.Success(TangemSignHashResponse( response.data.signature, response.data.totalSignedHashes, - session.environment.card?.wallet(walletPublicKey)?.remainingSignatures + session.environment.card?.wallet(publicKey.seedKey)?.remainingSignatures ))) } is CompletionResult.Failure -> diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt index 2755d9aa82..4d25a1de56 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt @@ -1,5 +1,6 @@ package com.tangem.tap.domain.tasks +import com.tangem.blockchain.common.Wallet import com.tangem.common.CompletionResult import com.tangem.common.core.CardSession import com.tangem.common.core.CardSessionRunnable @@ -15,16 +16,16 @@ class TangemSignHashesResponse( class SignHashesTask( private val hashes: Collection, - private val walletPublicKey: ByteArray, + private val publicKey: Wallet.PublicKey, ) : CardSessionRunnable { override fun run(session: CardSession, callback: CompletionCallback) { - SignHashesCommand(hashes.toTypedArray(), walletPublicKey).run(session) { response -> + SignHashesCommand(hashes.toTypedArray(), publicKey.seedKey, publicKey.derivationPath).run(session) { response -> when (response) { is CompletionResult.Success -> { callback(CompletionResult.Success(TangemSignHashesResponse( response.data.signatures, response.data.totalSignedHashes, - session.environment.card?.wallet(walletPublicKey)?.remainingSignatures + session.environment.card?.wallet(publicKey.seedKey)?.remainingSignatures ))) } is CompletionResult.Failure -> diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt index 6a82fd222f..4aa99403d2 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt @@ -139,7 +139,7 @@ private class ScanWalletProcessor( session: CardSession, callback: (result: CompletionResult) -> Unit ) { - val derivationPaths = collectDerivationPaths(card) + val derivationPaths = collectDerivationPaths(card)?.distinct() val wallet = card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } if (derivationPaths.isNullOrEmpty() || wallet == null || wallet.chainCode == null) { From 87d4b2277e24ee7066d71a3874cfac9b6dcfa30b Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 19:12:28 +0300 Subject: [PATCH 18/37] Updated on 2026-08-14 --- app/build.gradle | 4 ++-- .../tangem/tap/domain/tasks/CreateWalletAndRescanTask.kt | 4 ++-- .../java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt | 4 ++-- .../tap/domain/tasks/product/CreateProductWalletTask.kt | 4 ++-- .../tangem/tap/domain/tasks/product/CreateWalletsTask.kt | 5 ++--- .../tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt | 8 +++----- .../tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt | 4 ++-- 7 files changed, 15 insertions(+), 18 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 11fe6e6a2e..682d6d359e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -78,8 +78,8 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' implementation 'com.tangem:blockchain:develop-50' - implementation 'com.tangem.tangem-sdk-kotlin:core:develop-102' - implementation 'com.tangem.tangem-sdk-kotlin:android:develop-102' + implementation 'com.tangem.tangem-sdk-kotlin:core:develop-103' + implementation 'com.tangem.tangem-sdk-kotlin:android:develop-103' // WebView implementation "androidx.browser:browser:1.3.0" diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletAndRescanTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletAndRescanTask.kt index 1487f07e37..81a967c20b 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletAndRescanTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletAndRescanTask.kt @@ -9,7 +9,7 @@ import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.guard import com.tangem.operations.PreflightReadMode import com.tangem.operations.PreflightReadTask -import com.tangem.operations.wallet.CreateWalletCommand +import com.tangem.operations.wallet.CreateWalletTask @Deprecated("Use CreateProductWalletAndRescanTask instead") class CreateWalletAndRescanTask : CardSessionRunnable { @@ -22,7 +22,7 @@ class CreateWalletAndRescanTask : CardSessionRunnable { val firmwareVersion = card.firmwareVersion val task = if (firmwareVersion < FirmwareVersion.MultiWalletAvailable) { - CreateWalletCommand(card.supportedCurves.first()) + CreateWalletTask(card.supportedCurves.first()) } else { CreateWalletsTask() } diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt index c580b5389a..140a0ef72d 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/CreateWalletsTask.kt @@ -7,7 +7,7 @@ import com.tangem.common.core.CardSession import com.tangem.common.core.CardSessionRunnable import com.tangem.operations.PreflightReadMode import com.tangem.operations.PreflightReadTask -import com.tangem.operations.wallet.CreateWalletCommand +import com.tangem.operations.wallet.CreateWalletTask @Deprecated("Use CreateProductWalletTask instead") class CreateWalletsTask(curves: List? = null) : CardSessionRunnable { @@ -30,7 +30,7 @@ class CreateWalletsTask(curves: List? = null) : CardSessionRunnab callback: (result: CompletionResult) -> Unit ) { - CreateWalletCommand(curve).run(session) { result -> + CreateWalletTask(curve).run(session) { result -> when (result) { is CompletionResult.Success -> { if (index == curves.lastIndex) { diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt index 347965e1f5..8818309e08 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt @@ -10,8 +10,8 @@ import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.guard import com.tangem.operations.derivation.DeriveWalletPublicKeysTask import com.tangem.operations.derivation.ExtendedPublicKeyList -import com.tangem.operations.wallet.CreateWalletCommand import com.tangem.operations.wallet.CreateWalletResponse +import com.tangem.operations.wallet.CreateWalletTask import com.tangem.tap.common.extensions.toMapKey import com.tangem.tap.domain.ProductType import com.tangem.tap.domain.TapWorkarounds.getTangemNoteBlockchain @@ -74,7 +74,7 @@ private class CreateWalletTangemNote : ProductCommandProcessor) -> Unit ) { - - CreateWalletCommand(curve).run(session) { result -> + CreateWalletTask(curve).run(session) { result -> when (result) { is CompletionResult.Success -> { createdWalletsResponses.add(result.data) diff --git a/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt index 400ee19ae3..872c130c30 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/CreateFirstTwinWalletTask.kt @@ -4,8 +4,8 @@ import com.tangem.common.CompletionResult import com.tangem.common.card.EllipticCurve import com.tangem.common.core.CardSession import com.tangem.common.core.CardSessionRunnable -import com.tangem.operations.wallet.CreateWalletCommand import com.tangem.operations.wallet.CreateWalletResponse +import com.tangem.operations.wallet.CreateWalletTask import com.tangem.operations.wallet.PurgeWalletCommand import com.tangem.tap.domain.extensions.getSingleWallet @@ -20,15 +20,13 @@ class CreateFirstTwinWalletTask : CardSessionRunnable { when (response) { is CompletionResult.Success -> { session.environment.card = session.environment.card?.setWallets(emptyList()) - CreateWalletCommand(EllipticCurve.Secp256k1) - .run(session) { callback(it) } + CreateWalletTask(EllipticCurve.Secp256k1).run(session) { callback(it) } } is CompletionResult.Failure -> callback(CompletionResult.Failure(response.error)) } } } else { - CreateWalletCommand(EllipticCurve.Secp256k1) - .run(session) { callback(it) } + CreateWalletTask(EllipticCurve.Secp256k1).run(session) { callback(it) } } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt index 24b908cb0a..f7ef809d38 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt @@ -8,8 +8,8 @@ import com.tangem.common.core.CardSession import com.tangem.common.core.CardSessionRunnable import com.tangem.common.core.TangemError import com.tangem.common.extensions.hexToBytes -import com.tangem.operations.wallet.CreateWalletCommand import com.tangem.operations.wallet.CreateWalletResponse +import com.tangem.operations.wallet.CreateWalletTask import com.tangem.operations.wallet.PurgeWalletCommand import com.tangem.tap.domain.extensions.getSingleWallet import com.tangem.wallet.R @@ -47,7 +47,7 @@ class CreateSecondTwinWalletTask( private fun finishTask(session: CardSession, callback: (result: CompletionResult) -> Unit) { session.setMessage(creatingWalletMessage) - CreateWalletCommand(EllipticCurve.Secp256k1).run(session) { result -> + CreateWalletTask(EllipticCurve.Secp256k1).run(session) { result -> when (result) { is CompletionResult.Success -> { session.environment.card = session.environment.card?.updateWallet(result.data.wallet) From 2c25a256a7ed61268298bf77cce9c1ea10f9652f Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 22:11:50 +0300 Subject: [PATCH 19/37] Updated on 2026-08-14 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 682d6d359e..0d1c8f68ca 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -78,8 +78,8 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' implementation 'com.tangem:blockchain:develop-50' - implementation 'com.tangem.tangem-sdk-kotlin:core:develop-103' - implementation 'com.tangem.tangem-sdk-kotlin:android:develop-103' + implementation 'com.tangem.tangem-sdk-kotlin:core:develop-104' + implementation 'com.tangem.tangem-sdk-kotlin:android:develop-104' // WebView implementation "androidx.browser:browser:1.3.0" From a16701f7bd052406d8a51e3f6a4dbb2da3fcdfa2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 22:19:12 +0300 Subject: [PATCH 20/37] Updated on 2026-08-14 --- .../products/wallet/redux/OnboardingWalletAction.kt | 1 + .../products/wallet/redux/OnboardingWalletReducer.kt | 4 ++++ .../products/wallet/ui/OnboardingWalletFragment.kt | 5 ++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt index 364f97ce71..f00b5c5273 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt @@ -51,6 +51,7 @@ sealed class BackupAction : Action { data class SaveFirstAccessCode(val accessCode: String) : BackupAction() object ShowReenterAccessCodeScreen : BackupAction() data class SaveAccessCodeConfirmation(val accessCodeConfirmation: String) : BackupAction() + object OnAccessCodeDialogClosed : BackupAction() data class PrepareToWriteBackupCard(val cardNumber: Int) : BackupAction() data class WriteBackupCard(val cardNumber: Int) : BackupAction() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt index 8e0c5daac7..1d48365843 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt @@ -107,6 +107,10 @@ class BackupReducer { ) } + BackupAction.OnAccessCodeDialogClosed -> { + state.copy(backupStep = BackupStep.AddBackupCards) + } + BackupAction.WritePrimaryCard -> state is BackupAction.WriteBackupCard -> state is BackupAction.SaveAccessCodeConfirmation -> state diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index c0cee1429d..dd517f6e3b 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -175,6 +175,9 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), imv_first_backup_card.show() imv_second_backup_card.show() + accessCodeDialog?.dismiss() + accessCodeDialog = null + layout_buttons_add_cards.show() layout_buttons_common.hide() if (state.backupCardsNumber < state.maxBackupCards) { @@ -218,7 +221,7 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), dismissWithAnimation = true create() setOnCancelListener { - + store.dispatch(BackupAction.OnAccessCodeDialogClosed) } show() showInfoScreen() From 39c5e5da34ca6eb9d103bfeae4cb1156915d647f Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 22:41:49 +0300 Subject: [PATCH 21/37] Updated on 2026-08-14 --- .../redux/OnboardingWalletMiddleware.kt | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index d2c733e206..cecbb010c6 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -12,6 +12,7 @@ import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.extensions.hasWallets +import com.tangem.tap.domain.tasks.product.ScanResponse import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.home.redux.HomeMiddleware import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteAction @@ -98,7 +99,9 @@ private fun handleWalletAction(action: Action) { store.dispatch(NavigationAction.PopBackTo()) store.dispatch(HomeAction.ReadCard) } else { - scope.launch { globalState.tapWalletManager.onCardScanned(scanResponse) } + val backupState = store.state.onboardingWalletState.backupState + val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState) + scope.launch { globalState.tapWalletManager.onCardScanned(updatedScanResponse) } store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet)) } } @@ -127,6 +130,21 @@ private fun handleWalletAction(action: Action) { } } +private fun updateScanResponseAfterBackup( + scanResponse: ScanResponse, backupState: BackupState +): ScanResponse { + val card = if (backupState.backupStep == BackupStep.Finished) { + val cardsCount = backupState.backupCardsNumber + 1 + scanResponse.card.copy( + backupStatus = Card.BackupStatus.Active(cardCount = cardsCount), + isAccessCodeSet = true + ) + } else { + scanResponse.card + } + return scanResponse.copy(card = card) +} + class BackupMiddleware { val backupMiddleware: Middleware = { dispatch, state -> { next -> @@ -239,7 +257,6 @@ class BackupMiddleware { store.dispatch(BackupAction.FinishBackup) } } - next(action) } } From 6d95dfe1fdae924f935536a85142b61caa505cd9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 23:32:06 +0300 Subject: [PATCH 22/37] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/MainActivity.kt | 4 ++-- .../tangem/tap/common/redux/global/GlobalAction.kt | 2 +- .../tangem/tap/common/redux/global/GlobalReducer.kt | 12 ++++++++---- .../tangem/tap/common/redux/global/GlobalState.kt | 13 +++++++++---- .../domain/tasks/product/CreateProductWalletTask.kt | 2 +- .../products/note/redux/OnboardingNoteMiddleware.kt | 2 +- .../redux/OnboardingOtherCardsMiddleware.kt | 2 +- .../products/twins/redux/TwinCardsMiddleware.kt | 2 +- .../wallet/redux/OnboardingWalletMiddleware.kt | 8 +++++--- app/src/main/res/drawable/shape_chip.xml | 2 +- 10 files changed, 30 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 43eaa90ca3..0c9f4a0bbf 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -96,8 +96,8 @@ class MainActivity : AppCompatActivity(), SnackbarHandler { val backStackIsEmpty = supportFragmentManager.backStackEntryCount == 0 val isScannedBefore = store.state.globalState.scanResponse != null - val isOnboardingServiceActive = store.state.globalState.onboardingManager != null - if (backStackIsEmpty && (!isOnboardingServiceActive && !isScannedBefore)) { + val isOnboardingServiceActive = store.state.globalState.onboardingState.onboardingStarted + if (backStackIsEmpty || (!isOnboardingServiceActive && !isScannedBefore)) { store.dispatch(NavigationAction.NavigateTo(AppScreen.Home)) } intentHandler.handleIntent(intent) diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt index f448916049..bbea6e43f9 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt @@ -31,7 +31,7 @@ sealed class GlobalAction : Action { object HideDialog : GlobalAction() sealed class Onboarding { - data class Start(val scanResponse: ScanResponse, val fromHomeScreen: Boolean = true) : GlobalAction() + data class Start(val scanResponse: ScanResponse?, val fromHomeScreen: Boolean = true) : GlobalAction() object Stop : GlobalAction() } diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt index 993830329a..e549a2f386 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt @@ -17,12 +17,16 @@ fun globalReducer(action: Action, state: AppState): GlobalState { globalState.copy(resources = action.resources) } is GlobalAction.Onboarding.Start -> { - val usedCardsPrefStorage = preferencesStorage.usedCardsPrefStorage - val onboardingState = OnboardingManager(action.scanResponse, usedCardsPrefStorage) - globalState.copy(onboardingManager = onboardingState) + val onboardingManager = if (action.scanResponse != null) { + val usedCardsPrefStorage = preferencesStorage.usedCardsPrefStorage + OnboardingManager(action.scanResponse, usedCardsPrefStorage) + } else { + null + } + globalState.copy(onboardingState = OnboardingState(true, onboardingManager)) } is GlobalAction.Onboarding.Stop -> { - globalState.copy(onboardingManager = null) + globalState.copy(onboardingState = OnboardingState(false)) } is GlobalAction.ScanFailsCounter.Increment -> { globalState.copy(scanCardFailsCounter = globalState.scanCardFailsCounter + 1) diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt index 484142c611..f634a6a0ff 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt @@ -15,7 +15,7 @@ import org.rekotlin.StateType data class GlobalState( val scanResponse: ScanResponse? = null, - val onboardingManager: OnboardingManager? = null, + val onboardingState: OnboardingState = OnboardingState(), val cardVerifiedOnline: Boolean = false, val tapWalletManager: TapWalletManager = TapWalletManager(), val payIdManager: PayIdManager = PayIdManager(), @@ -32,12 +32,17 @@ data class GlobalState( data class AndroidResources( - val strings: RString = RString() + val strings: RString = RString(), ) { data class RString( val addressWasCopied: Int = -1, - val walletIsNotEmpty: Int = -1 + val walletIsNotEmpty: Int = -1, ) } typealias CryptoCurrencyName = String -typealias FiatCurrencyName = String \ No newline at end of file +typealias FiatCurrencyName = String + +data class OnboardingState( + val onboardingStarted: Boolean = false, + val onboardingManager: OnboardingManager? = null, +) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt index 8818309e08..530b53ac4c 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt @@ -113,7 +113,7 @@ private class CreateWalletTangemWallet : ProductCommandProcessor = { dispatch, state - private fun handleNoteAction(action: Action, dispatch: DispatchFunction) { if (action !is OnboardingNoteAction) return val globalState = store.state.globalState - val onboardingManager = globalState.onboardingManager ?: return + val onboardingManager = globalState.onboardingState.onboardingManager ?: return val scanResponse = onboardingManager.scanResponse val card = onboardingManager.scanResponse.card diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/redux/OnboardingOtherCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/redux/OnboardingOtherCardsMiddleware.kt index 4606c539ae..f3419e67fa 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/redux/OnboardingOtherCardsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/otherCards/redux/OnboardingOtherCardsMiddleware.kt @@ -37,7 +37,7 @@ private val onboardingOtherCardsMiddleware: Middleware = { dispatch, s private fun handleOtherCardsAction(action: Action, dispatch: DispatchFunction) { if (action !is OnboardingOtherCardsAction) return val globalState = store.state.globalState - val onboardingManager = globalState.onboardingManager ?: return + val onboardingManager = globalState.onboardingState.onboardingManager ?: return val card = onboardingManager.scanResponse.card 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 818b1974aa..f69e59381f 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 @@ -45,7 +45,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) { val action = action as? TwinCardsAction ?: return val globalState = store.state.globalState - val onboardingManager = globalState.onboardingManager + val onboardingManager = globalState.onboardingState.onboardingManager val twinCardsState = store.state.twinCardsState fun getScanResponse(): ScanResponse { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index cecbb010c6..4e8cc263ab 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -38,7 +38,7 @@ private val onboardingWalletMiddleware: Middleware = { dispatch, state private fun handleWalletAction(action: Action) { if (action !is OnboardingWalletAction) return val globalState = store.state.globalState - val onboardingManager = globalState.onboardingManager + val onboardingManager = globalState.onboardingState.onboardingManager val scanResponse = onboardingManager?.scanResponse val card = scanResponse?.card @@ -73,7 +73,8 @@ private fun handleWalletAction(action: Action) { when (result) { is CompletionResult.Success -> { //here we must use updated scanResponse after createWallet & derivation - val updatedResponse = globalState.onboardingManager.scanResponse.copy(card = result.data) + val updatedResponse = + globalState.onboardingState.onboardingManager.scanResponse.copy(card = result.data) onboardingManager.scanResponse = updatedResponse onboardingManager.activationStarted(updatedResponse.card.cardId) store.dispatch(OnboardingWalletAction.ProceedBackup) @@ -134,7 +135,7 @@ private fun updateScanResponseAfterBackup( scanResponse: ScanResponse, backupState: BackupState ): ScanResponse { val card = if (backupState.backupStep == BackupStep.Finished) { - val cardsCount = backupState.backupCardsNumber + 1 + val cardsCount = backupState.backupCardsNumber scanResponse.card.copy( backupStatus = Card.BackupStatus.Active(cardCount = cardsCount), isAccessCodeSet = true @@ -250,6 +251,7 @@ class BackupMiddleware { } } is BackupAction.ResumeBackup -> { + store.dispatch(GlobalAction.Onboarding.Start(null, true)) store.dispatch(OnboardingWalletAction.ProceedBackup) store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet)) } diff --git a/app/src/main/res/drawable/shape_chip.xml b/app/src/main/res/drawable/shape_chip.xml index 9544d9916d..658e94c9a7 100644 --- a/app/src/main/res/drawable/shape_chip.xml +++ b/app/src/main/res/drawable/shape_chip.xml @@ -1,7 +1,7 @@ - + Date: Tue, 7 Dec 2021 23:48:15 +0300 Subject: [PATCH 23/37] Updated on 2026-08-14 --- app/src/main/res/layout/fragment_onboarding_wallet.xml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/layout/fragment_onboarding_wallet.xml b/app/src/main/res/layout/fragment_onboarding_wallet.xml index 56427dc352..7f004c814d 100644 --- a/app/src/main/res/layout/fragment_onboarding_wallet.xml +++ b/app/src/main/res/layout/fragment_onboarding_wallet.xml @@ -165,7 +165,6 @@ android:layout_height="wrap_content" android:visibility="gone" app:layout_constraintHorizontal_bias="0.504" - app:layout_constraintBottom_toTopOf="@id/layout_buttons_common" app:flow_verticalBias="0" app:layout_constraintTop_toTopOf="@+id/guideline2" android:layout_marginBottom="8dp"/> @@ -173,7 +172,7 @@ From 4239b2aa25755855f7a41348c5c159f1aec7a728 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 7 Dec 2021 23:57:35 +0300 Subject: [PATCH 24/37] Updated on 2026-08-14 --- .../products/wallet/redux/OnboardingWalletMiddleware.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 4e8cc263ab..8b248a9422 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -134,7 +134,7 @@ private fun handleWalletAction(action: Action) { private fun updateScanResponseAfterBackup( scanResponse: ScanResponse, backupState: BackupState ): ScanResponse { - val card = if (backupState.backupStep == BackupStep.Finished) { + val card = if (backupState.backupCardsNumber > 0) { val cardsCount = backupState.backupCardsNumber scanResponse.card.copy( backupStatus = Card.BackupStatus.Active(cardCount = cardsCount), From f80e12e9ca0f0001bdf0878faa24490ac1336d95 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 10:45:33 +0300 Subject: [PATCH 25/37] Updated on 2026-08-14 --- .../wallet/redux/OnboardingWalletAction.kt | 1 + .../redux/OnboardingWalletMiddleware.kt | 25 +++++++++++-------- .../wallet/redux/OnboardingWalletReducer.kt | 1 + .../dialogs/ConfirmDiscardingBackupDialog.kt | 2 +- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt index f00b5c5273..b3056d7bdd 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt @@ -61,6 +61,7 @@ sealed class BackupAction : Action { object FinishBackup : BackupAction() object DiscardBackup : BackupAction() + object DiscardSavedBackup : BackupAction() object ResumeBackup : BackupAction() } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 8b248a9422..dd9ea5cd54 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -89,13 +89,6 @@ private fun handleWalletAction(action: Action) { OnboardingWalletAction.FinishOnboarding -> { store.dispatch(GlobalAction.Onboarding.Stop) - (listOf(walletState.backupState.primaryCardId) + - walletState.backupState.backupCardIds + scanResponse?.card?.cardId) - .distinct().filterNotNull() - .forEach { cardId -> - preferencesStorage.usedCardsPrefStorage.activationFinished(cardId) - } - if (scanResponse == null) { store.dispatch(NavigationAction.PopBackTo()) store.dispatch(HomeAction.ReadCard) @@ -119,7 +112,7 @@ private fun handleWalletAction(action: Action) { when (walletState.backupState.backupStep) { BackupStep.InitBackup, BackupStep.Finished -> store.dispatch(NavigationAction.PopBackTo()) BackupStep.ScanOriginCard, BackupStep.AddBackupCards, BackupStep.EnterAccessCode, - BackupStep.ReenterAccessCode, BackupStep.SetAccessCode, BackupStep.WritePrimaryCard + BackupStep.ReenterAccessCode, BackupStep.SetAccessCode, BackupStep.WritePrimaryCard, -> { store.dispatch(BackupAction.DiscardBackup) store.dispatch(NavigationAction.PopBackTo()) @@ -132,7 +125,7 @@ private fun handleWalletAction(action: Action) { } private fun updateScanResponseAfterBackup( - scanResponse: ScanResponse, backupState: BackupState + scanResponse: ScanResponse, backupState: BackupState, ): ScanResponse { val card = if (backupState.backupCardsNumber > 0) { val cardsCount = backupState.backupCardsNumber @@ -240,11 +233,23 @@ class BackupMiddleware { } } is BackupAction.FinishBackup -> { -// store.dispatch(OnboardingWalletAction.Done) + (listOf(backupState?.primaryCardId, + store.state.globalState.onboardingState.onboardingManager?.scanResponse?.card?.cardId) + + backupState?.backupCardIds as List) + .distinct().filterNotNull() + .forEach { cardId -> + preferencesStorage.usedCardsPrefStorage.activationFinished(cardId) + } } is BackupAction.DiscardBackup -> { backupService.discardSavedBackup() } + is BackupAction.DiscardSavedBackup -> { + backupService.primaryCardId?.let { + preferencesStorage.usedCardsPrefStorage.activationFinished(it) + } + backupService.discardSavedBackup() + } is BackupAction.CheckForUnfinishedBackup -> { if (backupService.hasIncompletedBackup) { store.dispatch(GlobalAction.ShowDialog(BackupDialog.UnfinishedBackupFound)) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt index 1d48365843..3947cd5d3f 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt @@ -126,6 +126,7 @@ class BackupReducer { BackupAction.CheckForUnfinishedBackup -> state BackupAction.DiscardBackup -> state BackupAction.ResumeBackup -> state + BackupAction.DiscardSavedBackup -> state } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt index 07900822ba..8b88890be8 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt @@ -17,7 +17,7 @@ class ConfirmDiscardingBackupDialog { store.dispatch(BackupAction.ResumeBackup) } setNegativeButton(R.string.welcome_interrupted_backup_discard_discard) { _, _ -> - store.dispatch(BackupAction.DiscardBackup) + store.dispatch(BackupAction.DiscardSavedBackup) } setOnDismissListener { store.dispatch(GlobalAction.HideDialog) From aa50fa63ba6c382b28ac4a75337069be74db560a Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 14:16:36 +0300 Subject: [PATCH 26/37] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/common/DialogManager.kt | 4 ++-- .../products/wallet/redux/OnboardingWalletMiddleware.kt | 2 +- .../products/wallet/redux/OnboardingWalletState.kt | 2 +- ...MoreBackupCardsDialog.kt => AddMoreBackupCardsDialog.kt} | 6 +++--- app/src/main/res/values/strings_untranslated.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) rename app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/{BuyMoreBackupCardsDialog.kt => AddMoreBackupCardsDialog.kt} (89%) diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt index 6533bab1a3..8f1491368c 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -10,8 +10,8 @@ import com.tangem.tap.features.onboarding.AddressInfoBottomSheetDialog import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.features.onboarding.products.twins.ui.dialog.CreateWalletInterruptDialog import com.tangem.tap.features.onboarding.products.wallet.redux.BackupDialog +import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AddMoreBackupCardsDialog import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.BackupInProgressDialog -import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.BuyMoreBackupCardsDialog import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.ConfirmDiscardingBackupDialog import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.UnfinishedBackupFoundDialog import com.tangem.tap.features.wallet.ui.dialogs.ScanFailsDialog @@ -79,7 +79,7 @@ class DialogManager : StoreSubscriber { TransactionDialog.create(state.dialog.dialogData, context) is WalletConnectDialog.PersonalSign -> PersonalSignDialog.create(state.dialog.data, context) - is BackupDialog.BuyMoreBackupCards -> BuyMoreBackupCardsDialog.create(context) + is BackupDialog.AddMoreBackupCards -> AddMoreBackupCardsDialog.create(context) is BackupDialog.BackupInProgress -> BackupInProgressDialog.create(context) is BackupDialog.UnfinishedBackupFound -> UnfinishedBackupFoundDialog.create(context) is BackupDialog.ConfirmDiscardingBackup -> ConfirmDiscardingBackupDialog.create(context) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index dd9ea5cd54..95e7b3e0a5 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -176,7 +176,7 @@ class BackupMiddleware { } is BackupAction.FinishAddingBackupCards -> { if (backupService.addedBackupCardsCount == 1) { - store.dispatchOnMain(GlobalAction.ShowDialog(BackupDialog.BuyMoreBackupCards)) + store.dispatchOnMain(GlobalAction.ShowDialog(BackupDialog.AddMoreBackupCards)) } if (backupService.addedBackupCardsCount == 2) { store.dispatchOnMain(BackupAction.ShowAccessCodeInfoScreen) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt index 6c6ff6d1f7..d8d0c687b7 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt @@ -74,7 +74,7 @@ sealed class BackupStep { } sealed class BackupDialog: StateDialog { - object BuyMoreBackupCards : StateDialog + object AddMoreBackupCards : StateDialog object BackupInProgress : StateDialog object UnfinishedBackupFound : StateDialog object ConfirmDiscardingBackup : StateDialog diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BuyMoreBackupCardsDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt similarity index 89% rename from app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BuyMoreBackupCardsDialog.kt rename to app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt index 06f4c1565d..883ce390dc 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BuyMoreBackupCardsDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt @@ -7,7 +7,7 @@ import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction import com.tangem.tap.store import com.tangem.wallet.R -class BuyMoreBackupCardsDialog { +class AddMoreBackupCardsDialog { companion object { fun create(context: Context): AlertDialog { return AlertDialog.Builder(context).apply { @@ -16,8 +16,8 @@ class BuyMoreBackupCardsDialog { setPositiveButton(R.string.common_continue) { _, _ -> store.dispatch(BackupAction.ShowAccessCodeInfoScreen) } - setNegativeButton(R.string.onboarding_button_buy_more_cards) { _, _ -> - store.dispatch(BackupAction.GoToShop) + setNegativeButton(R.string.onboarding_button_add_more_cards) { _, _ -> + } setOnDismissListener { store.dispatch(GlobalAction.HideDialog) diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml index 3a6508fd00..e81e6a07bf 100644 --- a/app/src/main/res/values/strings_untranslated.xml +++ b/app/src/main/res/values/strings_untranslated.xml @@ -218,7 +218,7 @@ + Add backup card Scan the card #%d Scan primary card - Buy more cards + Add more cards Backup your wallet No backup cards From 03a73dfa78e308b60700e8287184b7772b59df1c Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 14:27:38 +0300 Subject: [PATCH 27/37] Updated on 2026-08-14 --- .../com/tangem/tap/features/home/redux/HomeMiddleware.kt | 3 +-- .../products/wallet/redux/OnboardingWalletMiddleware.kt | 6 ++++-- .../products/wallet/ui/OnboardingWalletFragment.kt | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index 0ad3f5d218..b93b3a2e7e 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -27,8 +27,7 @@ class HomeMiddleware { companion object { val handler = homeMiddleware - const val CARD_SHOP_URI = - "https://shop.tangem.com/?afmc=1i&utm_campaign=1i&utm_source=leaddyno&utm_medium=affiliate" + const val CARD_SHOP_URI = "http://cards.tangem.com/" } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 95e7b3e0a5..b4e4fa28f8 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -14,8 +14,8 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.extensions.hasWallets import com.tangem.tap.domain.tasks.product.ScanResponse import com.tangem.tap.features.home.redux.HomeAction -import com.tangem.tap.features.home.redux.HomeMiddleware import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteAction +import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletMiddleware.Companion.BUY_WALLET_URL import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.Middleware @@ -23,6 +23,8 @@ import org.rekotlin.Middleware class OnboardingWalletMiddleware { companion object { val handler = onboardingWalletMiddleware + + const val BUY_WALLET_URL = "https://wallet.tangem.com/" } } @@ -172,7 +174,7 @@ class BackupMiddleware { } } is BackupAction.GoToShop -> { - store.dispatchOpenUrl(HomeMiddleware.CARD_SHOP_URI) + store.dispatchOpenUrl(BUY_WALLET_URL) } is BackupAction.FinishAddingBackupCards -> { if (backupService.addedBackupCardsCount == 1) { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index dd517f6e3b..f415e176b9 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -17,8 +17,8 @@ import com.tangem.tap.common.leapfrogWidget.LeapfrogWidget import com.tangem.tap.common.postUi import com.tangem.tap.features.FragmentOnBackPressedHandler import com.tangem.tap.features.addBackPressHandler -import com.tangem.tap.features.home.redux.HomeMiddleware import com.tangem.tap.features.onboarding.products.wallet.redux.* +import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletMiddleware.Companion.BUY_WALLET_URL import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AccessCodeDialog import com.tangem.tap.store import com.tangem.wallet.R @@ -363,7 +363,7 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.shop_menu -> { - store.dispatchOpenUrl(HomeMiddleware.CARD_SHOP_URI) + store.dispatchOpenUrl(BUY_WALLET_URL) true } else -> super.onOptionsItemSelected(item) From 05f9be0331ef817cf5cd749c7b99757e49798de7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 14:39:26 +0300 Subject: [PATCH 28/37] Updated on 2026-08-14 --- .../redux/OnboardingWalletMiddleware.kt | 251 +++++++++--------- 1 file changed, 130 insertions(+), 121 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index b4e4fa28f8..f9465751c3 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -145,129 +145,138 @@ class BackupMiddleware { val backupMiddleware: Middleware = { dispatch, state -> { next -> { action -> - val backupState = state()?.onboardingWalletState?.backupState - when (action) { - is BackupAction.StartBackup -> { - backupService.discardSavedBackup() - } - is BackupAction.ScanPrimaryCard -> { - backupService.readPrimaryCard { result -> - when (result) { - is CompletionResult.Success -> { - store.dispatchOnMain(BackupAction.StartAddingBackupCards) - } - is CompletionResult.Failure -> { - } - } - } - } - is BackupAction.AddBackupCard -> { - backupService.addBackupCard { result -> - when (result) { - is CompletionResult.Success -> { - store.dispatchOnMain(BackupAction.AddBackupCard.Success) - } - is CompletionResult.Failure -> { - - } - } - } - } - is BackupAction.GoToShop -> { - store.dispatchOpenUrl(BUY_WALLET_URL) - } - is BackupAction.FinishAddingBackupCards -> { - if (backupService.addedBackupCardsCount == 1) { - store.dispatchOnMain(GlobalAction.ShowDialog(BackupDialog.AddMoreBackupCards)) - } - if (backupService.addedBackupCardsCount == 2) { - store.dispatchOnMain(BackupAction.ShowAccessCodeInfoScreen) - } - } - is BackupAction.CheckAccessCode -> { - if (action.accessCode.length < 4) { - store.dispatch(BackupAction.SetAccessCodeError( - AccessCodeError.CodeTooShort - )) - } else { - store.dispatch(BackupAction.SaveFirstAccessCode(action.accessCode)) - } - } - is BackupAction.SaveAccessCodeConfirmation -> { - if (action.accessCodeConfirmation == backupState?.accessCode) { - backupService.setAccessCode(action.accessCodeConfirmation) - store.dispatch(BackupAction.PrepareToWritePrimaryCard) - } else { - store.dispatch(BackupAction.SetAccessCodeError( - AccessCodeError.CodesDoNotMatch - )) - } - } - is BackupAction.WritePrimaryCard -> { - backupService.proceedBackup { result -> - when (result) { - is CompletionResult.Success -> { - store.dispatchOnMain( - BackupAction.PrepareToWriteBackupCard(1) - ) - } - is CompletionResult.Failure -> { - } - } - } - } - is BackupAction.WriteBackupCard -> { - backupService.proceedBackup { result -> - when (result) { - is CompletionResult.Success -> { - if (backupService.currentState == BackupService.State.Finished) { - store.dispatchOnMain(BackupAction.FinishBackup) - } else { - store.dispatchOnMain( - BackupAction.PrepareToWriteBackupCard(action.cardNumber + 1) - ) - } - } - is CompletionResult.Failure -> { - - } - } - } - } - is BackupAction.FinishBackup -> { - (listOf(backupState?.primaryCardId, - store.state.globalState.onboardingState.onboardingManager?.scanResponse?.card?.cardId) + - backupState?.backupCardIds as List) - .distinct().filterNotNull() - .forEach { cardId -> - preferencesStorage.usedCardsPrefStorage.activationFinished(cardId) - } - } - is BackupAction.DiscardBackup -> { - backupService.discardSavedBackup() - } - is BackupAction.DiscardSavedBackup -> { - backupService.primaryCardId?.let { - preferencesStorage.usedCardsPrefStorage.activationFinished(it) - } - backupService.discardSavedBackup() - } - is BackupAction.CheckForUnfinishedBackup -> { - if (backupService.hasIncompletedBackup) { - store.dispatch(GlobalAction.ShowDialog(BackupDialog.UnfinishedBackupFound)) - } - } - is BackupAction.ResumeBackup -> { - store.dispatch(GlobalAction.Onboarding.Start(null, true)) - store.dispatch(OnboardingWalletAction.ProceedBackup) - store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet)) - } - is BackupAction.DismissBackup -> { - store.dispatch(BackupAction.FinishBackup) - } - } + if (action is BackupAction) handleBackupAction(action) next(action) } } } +} + +private fun handleBackupAction(action: BackupAction) { + val backupState = store.state.onboardingWalletState.backupState + + val globalState = store.state.globalState + val onboardingManager = globalState.onboardingState.onboardingManager + + val scanResponse = onboardingManager?.scanResponse + val card = scanResponse?.card + + when (action) { + is BackupAction.StartBackup -> { + backupService.discardSavedBackup() + } + is BackupAction.ScanPrimaryCard -> { + backupService.readPrimaryCard(cardId = card?.cardId) { result -> + when (result) { + is CompletionResult.Success -> { + store.dispatchOnMain(BackupAction.StartAddingBackupCards) + } + is CompletionResult.Failure -> { + } + } + } + } + is BackupAction.AddBackupCard -> { + backupService.addBackupCard { result -> + when (result) { + is CompletionResult.Success -> { + store.dispatchOnMain(BackupAction.AddBackupCard.Success) + } + is CompletionResult.Failure -> { + + } + } + } + } + is BackupAction.GoToShop -> { + store.dispatchOpenUrl(BUY_WALLET_URL) + } + is BackupAction.FinishAddingBackupCards -> { + if (backupService.addedBackupCardsCount == 1) { + store.dispatchOnMain(GlobalAction.ShowDialog(BackupDialog.AddMoreBackupCards)) + } + if (backupService.addedBackupCardsCount == 2) { + store.dispatchOnMain(BackupAction.ShowAccessCodeInfoScreen) + } + } + is BackupAction.CheckAccessCode -> { + if (action.accessCode.length < 4) { + store.dispatch(BackupAction.SetAccessCodeError( + AccessCodeError.CodeTooShort + )) + } else { + store.dispatch(BackupAction.SaveFirstAccessCode(action.accessCode)) + } + } + is BackupAction.SaveAccessCodeConfirmation -> { + if (action.accessCodeConfirmation == backupState.accessCode) { + backupService.setAccessCode(action.accessCodeConfirmation) + store.dispatch(BackupAction.PrepareToWritePrimaryCard) + } else { + store.dispatch(BackupAction.SetAccessCodeError( + AccessCodeError.CodesDoNotMatch + )) + } + } + is BackupAction.WritePrimaryCard -> { + backupService.proceedBackup { result -> + when (result) { + is CompletionResult.Success -> { + store.dispatchOnMain( + BackupAction.PrepareToWriteBackupCard(1) + ) + } + is CompletionResult.Failure -> { + } + } + } + } + is BackupAction.WriteBackupCard -> { + backupService.proceedBackup { result -> + when (result) { + is CompletionResult.Success -> { + if (backupService.currentState == BackupService.State.Finished) { + store.dispatchOnMain(BackupAction.FinishBackup) + } else { + store.dispatchOnMain( + BackupAction.PrepareToWriteBackupCard(action.cardNumber + 1) + ) + } + } + is CompletionResult.Failure -> { + + } + } + } + } + is BackupAction.FinishBackup -> { + (listOf(backupState.primaryCardId, card?.cardId) + backupState.backupCardIds) + .distinct().filterNotNull() + .forEach { cardId -> + preferencesStorage.usedCardsPrefStorage.activationFinished(cardId) + } + } + is BackupAction.DiscardBackup -> { + backupService.discardSavedBackup() + } + is BackupAction.DiscardSavedBackup -> { + backupService.primaryCardId?.let { + preferencesStorage.usedCardsPrefStorage.activationFinished(it) + } + backupService.discardSavedBackup() + } + is BackupAction.CheckForUnfinishedBackup -> { + if (backupService.hasIncompletedBackup) { + store.dispatch(GlobalAction.ShowDialog(BackupDialog.UnfinishedBackupFound)) + } + } + is BackupAction.ResumeBackup -> { + store.dispatch(GlobalAction.Onboarding.Start(null, true)) + store.dispatch(OnboardingWalletAction.ProceedBackup) + store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet)) + } + is BackupAction.DismissBackup -> { + store.dispatch(BackupAction.FinishBackup) + } + } } \ No newline at end of file From a6a59e086342a53a6af875a90e1c4fd928aefcc6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 15:08:04 +0300 Subject: [PATCH 29/37] Updated on 2026-08-14 --- .../tap/features/tokens/redux/TokensAction.kt | 6 +- .../features/tokens/redux/TokensMiddleware.kt | 6 +- .../features/tokens/redux/TokensReducer.kt | 10 -- .../tap/features/tokens/redux/TokensState.kt | 1 - .../features/tokens/ui/AddTokensFragment.kt | 10 +- .../tokens/ui/adapters/CurrenciesAdapter.kt | 128 ++++++++++++------ 6 files changed, 97 insertions(+), 64 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt index 27db550708..0a27c90233 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt @@ -21,9 +21,5 @@ sealed class TokensAction : Action { data class ToggleShowTokensForBlockchain(val isShown: Boolean, val blockchain: Blockchain) : TokensAction() - sealed class TokensList : TokensAction() { - data class AddBlockchain(val blockchain: Blockchain) : TokensList() - data class AddToken(val token: Token) : TokensList() - object SaveChanges : TokensList() - } + data class SaveChanges(val addedItems: List) : TokensAction() } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt index 4e1d90b2e4..2176e4ea51 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt @@ -29,7 +29,7 @@ class TokensMiddleware { { action -> when (action) { is TokensAction.LoadCurrencies -> handleLoadCurrencies(action) - is TokensAction.TokensList.SaveChanges -> handleSaveChanges(action) + is TokensAction.SaveChanges -> handleSaveChanges(action) } next(action) } @@ -69,10 +69,10 @@ class TokensMiddleware { store.dispatch(TokensAction.LoadCurrencies.Success(currencies)) } - private fun handleSaveChanges(action: TokensAction.TokensList.SaveChanges) { + private fun handleSaveChanges(action: TokensAction.SaveChanges) { val scanResponse = store.state.globalState.scanResponse ?: return - val candidatesToAdd = store.state.tokensState.candidateToAdd + val candidatesToAdd = action.addedItems if (candidatesToAdd.isEmpty()) return val blockchains = candidatesToAdd.filterIsInstance() diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt index f6ba05bc49..8496a9c7fb 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt @@ -43,16 +43,6 @@ private fun internalReduce(action: Action, state: AppState): TokensState { tokensState.copy(shownCurrencies = shownCurrencies) } } - is TokensAction.TokensList.AddBlockchain -> { - val candidates = tokensState.candidateToAdd.toMutableSet() - candidates.add(CurrencyListItem.BlockchainListItem(action.blockchain)) - tokensState.copy(candidateToAdd = candidates.toList()) - } - is TokensAction.TokensList.AddToken -> { - val candidates = tokensState.candidateToAdd.toMutableSet() - candidates.add(CurrencyListItem.TokenListItem(action.token)) - tokensState.copy(candidateToAdd = candidates.toList()) - } else -> tokensState } } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt index d0c204ee45..ef30a92229 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensState.kt @@ -10,7 +10,6 @@ data class TokensState( val addedCurrencies: CardCurrencies? = null, val currencies: List = emptyList(), val shownCurrencies: List = emptyList(), - val candidateToAdd: List = emptyList(), ) : StateType data class TokenWithAmount( diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt index e29365e728..38de45981b 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt @@ -61,12 +61,18 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens), (activity as? AppCompatActivity)?.setSupportActionBar(toolbar) toolbar.setNavigationOnClickListener { activity?.onBackPressed() } - btn_tokens_save_changes.setOnClickListener { store.dispatch(TokensAction.TokensList.SaveChanges)} setupPopularTokensRecyclerView() + btn_tokens_save_changes.setOnClickListener { + store.dispatch(TokensAction.SaveChanges(viewAdapter.getAddedItems())) + } } private fun setupPopularTokensRecyclerView() { viewAdapter = CurrenciesAdapter() + viewAdapter.setOnItemAddListener { + btn_tokens_save_changes.isEnabled = viewAdapter.getAddedItems().isNotEmpty() + } + rv_popular_tokens.layoutManager = LinearLayoutManager(context) rv_popular_tokens.adapter = viewAdapter } @@ -74,8 +80,6 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens), override fun newState(state: TokensState) { if (activity == null) return - btn_tokens_save_changes.isEnabled = state.candidateToAdd.isNotEmpty() - viewAdapter.addedCurrencies = state.addedCurrencies viewAdapter.submitUnfilteredList(state.shownCurrencies) } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt index 5935014bf4..b3d0ecdc04 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/adapters/CurrenciesAdapter.kt @@ -7,6 +7,9 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.squareup.picasso.Picasso +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.Token +import com.tangem.common.extensions.VoidCallback import com.tangem.tap.common.extensions.getString import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.loadCurrenciesIcon @@ -26,11 +29,28 @@ class CurrenciesAdapter : ListAdapter private var unfilteredList = listOf() + private val currentlyAddedItems = mutableListOf() + + private var vhOnItemAddListener: ((CurrencyListItem) -> Unit) = { + currentlyAddedItems.add(it) + onItemAddListener?.invoke() + } + private var onItemAddListener: VoidCallback? = null + fun submitUnfilteredList(list: List) { unfilteredList = list submitList(list) } + fun setOnItemAddListener(itemAddListener: VoidCallback) { + onItemAddListener = itemAddListener + if (currentlyAddedItems.isNotEmpty()) itemAddListener() + } + + fun getAddedItems(): List { + return currentlyAddedItems.toList() + } + override fun getItemViewType(position: Int): Int { return when (currentList[position]) { is CurrencyListItem.TitleListItem -> 0 @@ -46,11 +66,13 @@ class CurrenciesAdapter : ListAdapter ) 1 -> CurrenciesViewHolder( LayoutInflater.from(parent.context) - .inflate(R.layout.item_popular_token, parent, false) + .inflate(R.layout.item_popular_token, parent, false), + vhOnItemAddListener ) else -> CurrenciesViewHolder( LayoutInflater.from(parent.context) - .inflate(R.layout.item_popular_token, parent, false) + .inflate(R.layout.item_popular_token, parent, false), + vhOnItemAddListener ) } } @@ -60,7 +82,7 @@ class CurrenciesAdapter : ListAdapter if (holder is TitleViewHolder && listItem is CurrencyListItem.TitleListItem) { holder.bind(listItem) } else if (holder is CurrenciesViewHolder) { - holder.bind(listItem, addedCurrencies) + holder.bind(listItem, addedCurrencies, currentlyAddedItems) } } @@ -104,56 +126,78 @@ class CurrenciesAdapter : ListAdapter submitList(list) } - class CurrenciesViewHolder(val view: View) : RecyclerView.ViewHolder(view) { + class CurrenciesViewHolder( + private val view: View, + private val onItemAddListener: ((CurrencyListItem) -> Unit), + ) : RecyclerView.ViewHolder(view) { - fun bind(currency: CurrencyListItem, addedCurrencies: CardCurrencies?) { + fun bind( + currency: CurrencyListItem, + addedCurrencies: CardCurrencies?, + currentlyAddedItems: MutableList + ) { when (currency) { is CurrencyListItem.BlockchainListItem -> { - val blockchain = currency.blockchain - view.tv_currency_name.text = blockchain.fullName - view.tv_currency_symbol.text = blockchain.currency - currency.isAdded = addedCurrencies?.blockchains?.contains(blockchain) == true - modifyAddTokenButton(currency) - - Picasso.get().loadCurrenciesIcon( - imageView = view.iv_currency, - textView = view.tv_token_letter, - blockchain = blockchain, token = null - ) - - view.btn_add_token.setOnClickListener { - store.dispatch(TokensAction.TokensList.AddBlockchain(blockchain)) - currency.isAdded = !currency.isAdded - modifyAddTokenButton(currency) - } + val addedBlockchains = addedCurrencies?.blockchains ?: listOf() + val currentlyAdded = currentlyAddedItems.filterIsInstance() + bindBlockchain(currency, addedBlockchains, currentlyAdded) } is CurrencyListItem.TokenListItem -> { - val token = currency.token - view.tv_currency_name.text = token.name - view.tv_currency_symbol.text = token.symbol - - currency.isAdded = addedCurrencies?.tokens - ?.any { - it.symbol == token.symbol && it.contractAddress == token.contractAddress - } == true - modifyAddTokenButton(currency) - - Picasso.get().loadCurrenciesIcon( - imageView = view.iv_currency, - textView = view.tv_token_letter, - token = token, blockchain = token.blockchain - ) - view.btn_add_token.setOnClickListener { - store.dispatch(TokensAction.TokensList.AddToken(token)) - currency.isAdded = !currency.isAdded - modifyAddTokenButton(currency) - } + val addedTokens = addedCurrencies?.tokens ?: listOf() + val currentlyAdded = currentlyAddedItems.filterIsInstance() + bindToken(currency, addedTokens, currentlyAdded) } } } + private fun bindBlockchain( + currency: CurrencyListItem.BlockchainListItem, + addedBlockchains: List, + currentlyAdded: List + ) { + val blockchain = currency.blockchain + Picasso.get().loadCurrenciesIcon(view.iv_currency, view.tv_token_letter, null, blockchain) + + view.tv_currency_name.text = blockchain.fullName + view.tv_currency_symbol.text = blockchain.currency + view.btn_add_token.setOnClickListener { + onItemAddListener.invoke(currency) + currency.isAdded = true + modifyAddTokenButton(currency) + } + + val isAddedBefore = addedBlockchains.contains(blockchain) + val isCurrentlyAdded = currentlyAdded.any { it.blockchain == blockchain } + currency.isAdded = isAddedBefore || isCurrentlyAdded + modifyAddTokenButton(currency) + } + + private fun bindToken( + currency: CurrencyListItem.TokenListItem, + addedTokens: List, + currentlyAdded: List + ) { + val token = currency.token + Picasso.get().loadCurrenciesIcon(view.iv_currency, view.tv_token_letter, token, token.blockchain) + + view.tv_currency_name.text = token.name + view.tv_currency_symbol.text = token.symbol + view.btn_add_token.setOnClickListener { + onItemAddListener.invoke(currency) + currency.isAdded = true + modifyAddTokenButton(currency) + } + + val isAddedBefore = addedTokens.any { it == token } + val isCurrentlyAdded = currentlyAdded.any { it.token == token } + currency.isAdded = isAddedBefore || isCurrentlyAdded + + modifyAddTokenButton(currency) + } + private fun modifyAddTokenButton(currency: CurrencyListItem) { if (currency.isLock) { + view.btn_add_token.setText(R.string.common_add) view.btn_add_token.isEnabled = false } else { val text = if (currency.isAdded) R.string.add_token_added else R.string.common_add From 850beb1ec10f908de8e49d51b6970d88565495e8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 16:30:02 +0300 Subject: [PATCH 30/37] Updated on 2026-08-14 --- .../features/wallet/redux/middlewares/MultiWalletMiddleware.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index 7d93d65312..2906fca76b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -84,6 +84,7 @@ class MultiWalletMiddleware { } is WalletAction.MultiWallet.FindBlockchainsInUse -> { val scanResponse = globalState.scanResponse ?: return + if (scanResponse.isTangemWallet()) return val cardFirmware = scanResponse.card.firmwareVersion val blockchains = currenciesRepository.getBlockchains(cardFirmware) @@ -123,6 +124,7 @@ class MultiWalletMiddleware { } is WalletAction.MultiWallet.FindTokensInUse -> { val scanResponse = globalState.scanResponse ?: return + if (scanResponse.isTangemWallet()) return val walletFactory = tapWalletManager.walletManagerFactory val card = scanResponse.card From eead85f6efe0e1e8d27ccc95c7609db9d9c8f6b1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 18:02:39 +0300 Subject: [PATCH 31/37] Updated on 2026-08-14 --- app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0d1c8f68ca..058f6937ca 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,9 +77,9 @@ dependencies { implementation 'com.google.android.play:core-ktx:1.8.1' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' - implementation 'com.tangem:blockchain:develop-50' - implementation 'com.tangem.tangem-sdk-kotlin:core:develop-104' - implementation 'com.tangem.tangem-sdk-kotlin:android:develop-104' + implementation 'com.tangem:blockchain:develop-51' + implementation 'com.tangem.tangem-sdk-kotlin:core:develop-105' + implementation 'com.tangem.tangem-sdk-kotlin:android:develop-105' // WebView implementation "androidx.browser:browser:1.3.0" From b832254229f1396fa78087f4505b72cdbbe2af23 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 19:41:44 +0300 Subject: [PATCH 32/37] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/domain/TapWalletManager.kt | 9 ++------- .../com/tangem/tap/features/tokens/redux/TokensAction.kt | 5 ----- .../tangem/tap/features/tokens/redux/TokensReducer.kt | 6 ------ 3 files changed, 2 insertions(+), 18 deletions(-) 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 844eeb0bfa..d2bb6e06c2 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -15,7 +15,6 @@ import com.tangem.tap.domain.configurable.config.ConfigManager import com.tangem.tap.domain.extensions.* import com.tangem.tap.domain.tasks.product.ScanResponse import com.tangem.tap.domain.tokens.CardCurrencies -import com.tangem.tap.features.tokens.redux.TokensAction import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.network.NetworkConnectivity @@ -84,12 +83,6 @@ class TapWalletManager { store.dispatch(GlobalAction.SaveScanNoteResponse(data)) store.dispatch(WalletAction.SetIfTestnetCard(data.card.isTestCard)) store.dispatch(WalletAction.MultiWallet.SetIsMultiwalletAllowed(data.card.isMultiwalletAllowed)) - - val blockchain = data.getBlockchain() - if (blockchain == Blockchain.Ethereum || - blockchain == Blockchain.EthereumTestnet) { - store.dispatch(TokensAction.LoadCardTokens) - } loadData(data) } } @@ -110,6 +103,7 @@ class TapWalletManager { } } + suspend fun loadData(data: ScanResponse) { withContext(Dispatchers.Main) { store.dispatch(WalletAction.LoadCardInfo(data.card)) @@ -147,6 +141,7 @@ class TapWalletManager { } } + @Deprecated("") private fun loadMultiWalletData( scanResponse: ScanResponse, primaryBlockchain: Blockchain?, primaryWalletManager: WalletManager? ) { diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt index 0a27c90233..d2b911d8b7 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensAction.kt @@ -1,7 +1,6 @@ package com.tangem.tap.features.tokens.redux import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.Token import com.tangem.tap.features.wallet.redux.WalletData import org.rekotlin.Action @@ -13,10 +12,6 @@ sealed class TokensAction : Action { data class Success(val currencies: List) : TokensAction() } - object LoadCardTokens : TokensAction() { - data class Success(val tokens: List) : TokensAction() - } - data class SetAddedCurrencies(val wallets: List) : TokensAction() data class ToggleShowTokensForBlockchain(val isShown: Boolean, val blockchain: Blockchain) : TokensAction() diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt index 8496a9c7fb..2fb4c5dec8 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensReducer.kt @@ -24,12 +24,6 @@ private fun internalReduce(action: Action, state: AppState): TokensState { is TokensAction.SetAddedCurrencies -> { tokensState.copy(addedCurrencies = action.wallets.toCardCurrencies()) } - is TokensAction.LoadCardTokens.Success -> { - tokensState.copy(addedTokens = LinkedHashSet( - action.tokens.map { TokenWithAmount(it, null) } - )) - } - is TokensAction.ToggleShowTokensForBlockchain -> { if (action.isShown) { val shownCurrencies = tokensState.shownCurrencies From 7b266abf2aff725b7b6ea2cf5676acdc1d7c08aa Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 20:03:18 +0300 Subject: [PATCH 33/37] Updated on 2026-08-14 --- .../middlewares/MultiWalletMiddleware.kt | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index 2906fca76b..11d7232cd3 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -4,6 +4,7 @@ import com.tangem.blockchain.common.* import com.tangem.blockchain.extensions.Result import com.tangem.common.extensions.isZero import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.common.redux.global.GlobalState import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction @@ -180,9 +181,17 @@ class MultiWalletMiddleware { scope.launch { when (val result = walletManager?.addToken(token)) { is Result.Success -> { - store.dispatchOnMain( - WalletAction.MultiWallet.TokenLoaded(amount = result.data, token = token) - ) + store.dispatchOnMain(WalletAction.MultiWallet.TokenLoaded(result.data, token)) + } + is Result.Failure -> { + when (val result = walletManager.safeUpdate()) { + is com.tangem.common.services.Result.Success -> { + val tokenAmount = result.data.getTokenAmount(token) ?: return@launch + store.dispatchOnMain(WalletAction.MultiWallet.TokenLoaded(tokenAmount, token)) + } + is com.tangem.common.services.Result.Failure -> { + } + } } } } @@ -213,11 +222,17 @@ class MultiWalletMiddleware { tokensWithManagers.forEach { when (val result = it.walletManager?.addToken(it.token)) { is Result.Success -> { - store.dispatchOnMain( - WalletAction.MultiWallet.TokenLoaded( - amount = result.data, token = it.token - ) - ) + store.dispatchOnMain(WalletAction.MultiWallet.TokenLoaded(result.data, it.token)) + } + is Result.Failure -> { + when (val result = it.walletManager.safeUpdate()) { + is com.tangem.common.services.Result.Success -> { + val tokenAmount = result.data.getTokenAmount(it.token) ?: return@launch + store.dispatchOnMain(WalletAction.MultiWallet.TokenLoaded(tokenAmount, it.token)) + } + is com.tangem.common.services.Result.Failure -> { + } + } } } } From e9b0d9cad89e4df25584aff842bfeea79cb6ef60 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 20:10:47 +0300 Subject: [PATCH 34/37] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt | 1 - 1 file changed, 1 deletion(-) 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 d2bb6e06c2..ddfcad7e23 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -103,7 +103,6 @@ class TapWalletManager { } } - suspend fun loadData(data: ScanResponse) { withContext(Dispatchers.Main) { store.dispatch(WalletAction.LoadCardInfo(data.card)) From 2adb00d3bd686e358597987b8827bacce933f3f2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 20:11:48 +0300 Subject: [PATCH 35/37] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt | 1 - 1 file changed, 1 deletion(-) 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 ddfcad7e23..9f6d0f13e1 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -140,7 +140,6 @@ class TapWalletManager { } } - @Deprecated("") private fun loadMultiWalletData( scanResponse: ScanResponse, primaryBlockchain: Blockchain?, primaryWalletManager: WalletManager? ) { From c80dcd69cc0e4d01594da3805b0b2ddb4e35cb09 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 8 Dec 2021 23:34:30 +0300 Subject: [PATCH 36/37] Updated on 2026-08-14 --- .../tap/domain/walletconnect/WalletConnectManager.kt | 3 ++- .../tap/domain/walletconnect/WalletConnectSdkHelper.kt | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt index e7b23953b5..7c74264429 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt @@ -96,7 +96,8 @@ class WalletConnectManager { val activeData = sessions[session] ?: return removeSimilarSessions(activeData) - val accounts = listOf(Blockchain.Ethereum.makeAddresses(activeData.wallet.walletPublicKey).first().value) + val key = activeData.wallet.derivedPublicKey ?: activeData.wallet.walletPublicKey + val accounts = listOf(Blockchain.Ethereum.makeAddresses(key).first().value) val approved = activeData.client.approveSession( accounts = accounts, chainId = activeData.wallet.chainId diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt index 152bdd04d7..85ef0eaac6 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt @@ -154,7 +154,8 @@ class WalletConnectSdkHelper { val command = SignHashCommand( hash = dataToSign.hash, - walletPublicKey = data.walletManager.wallet.publicKey.seedKey + walletPublicKey = data.walletManager.wallet.publicKey.seedKey, + derivationPath = data.walletManager.wallet.publicKey.derivationPath ) val result = tangemSdkManager.runTaskAsync(command, initialMessage = Message()) return when (result) { @@ -211,13 +212,13 @@ class WalletConnectSdkHelper { } suspend fun signPersonalMessage(hashToSign: ByteArray, wallet: WalletForSession): String? { - val publicKey = wallet.walletPublicKey - val command = SignHashCommand(hashToSign, publicKey) + val key = wallet.derivedPublicKey ?: wallet.walletPublicKey + val command = SignHashCommand(hashToSign, wallet.walletPublicKey, wallet.derivationPath) return when (val result = tangemSdkManager.runTaskAsync(command, wallet.cardId)) { is CompletionResult.Success -> { val hash = result.data.signature return EthereumUtils.prepareSignedMessageData( - hash, hashToSign, CryptoUtils.decompressPublicKey(wallet.walletPublicKey) + hash, hashToSign, CryptoUtils.decompressPublicKey(key) ) } is CompletionResult.Failure -> { From 08708a2ba77e1c9623fd3e38d4e3b52ab847effc Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 9 Dec 2021 13:24:47 +0300 Subject: [PATCH 37/37] Updated on 2026-08-14 --- app/build.gradle | 4 ++-- .../java/com/tangem/tap/common/analytics/TangemSdkError.kt | 1 + .../tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 058f6937ca..c8e2711c22 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -78,8 +78,8 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' implementation 'com.tangem:blockchain:develop-51' - implementation 'com.tangem.tangem-sdk-kotlin:core:develop-105' - implementation 'com.tangem.tangem-sdk-kotlin:android:develop-105' + implementation 'com.tangem.tangem-sdk-kotlin:core:develop-106' + implementation 'com.tangem.tangem-sdk-kotlin:android:develop-106' // WebView implementation "androidx.browser:browser:1.3.0" diff --git a/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt b/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt index 0880e773be..233fa3702d 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt @@ -104,6 +104,7 @@ object TangemSdk { is TangemSdkError.HDWalletDisabled -> TangemSdkError.HDWalletDisabled() is TangemSdkError.WrongInteractionMode -> TangemSdkError.WrongInteractionMode() is TangemSdkError.IssuerSignatureLoadingFailed -> TangemSdkError.IssuerSignatureLoadingFailed() + is TangemSdkError.BackupFailedFirmware -> TangemSdkError.BackupFailedFirmware() } } 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 index 6fc58ea550..8eeef0afdc 100644 --- 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 @@ -55,7 +55,7 @@ class MultiWalletView : WalletView { private fun setupWalletCardNumber(fragment: WalletFragment) = with(fragment) { val card = store.state.globalState.scanResponse?.card - if (card?.backupStatus?.isActive == true) { + if (card?.backupStatus is Card.BackupStatus.Active) { val cardCount = (card.backupStatus as Card.BackupStatus.Active).cardCount + 1 tv_twin_card_number.show() tv_twin_card_number.text =