From 6a04ccb2850c727eb2ad2b660efe76599cfa9f0b Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 1 Mar 2026 13:55:27 +0400 Subject: [PATCH 1/4] Updated on 2026-08-14 --- .../core/ui/security/DisableAutofill.kt | 31 +++++++++++++++++++ .../ui/MultiWalletSeedPhraseImport.kt | 3 ++ 2 files changed, 34 insertions(+) create mode 100644 core/ui/src/main/java/com/tangem/core/ui/security/DisableAutofill.kt diff --git a/core/ui/src/main/java/com/tangem/core/ui/security/DisableAutofill.kt b/core/ui/src/main/java/com/tangem/core/ui/security/DisableAutofill.kt new file mode 100644 index 0000000000..8693a0ea3e --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/security/DisableAutofill.kt @@ -0,0 +1,31 @@ +package com.tangem.core.ui.security + +import android.os.Build +import android.view.View +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.ui.platform.LocalView + +/** + * Disables autofill for the current Compose view hierarchy. + * + * This prevents password managers and other autofill services from accessing + * sensitive content (e.g., seed phrases, private keys) entered in text fields. + * + * Must be called within a Composable scope before the text fields that need protection. + * + * The original autofill setting is restored when this composable leaves the composition. + */ +@Composable +fun DisableAutofillEffect() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val view = LocalView.current + DisposableEffect(view) { + val previousValue = view.importantForAutofill + view.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS + onDispose { + view.importantForAutofill = previousValue + } + } + } +} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/ui/MultiWalletSeedPhraseImport.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/ui/MultiWalletSeedPhraseImport.kt index 8779ab378a..a5fda3ab83 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/ui/MultiWalletSeedPhraseImport.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/ui/MultiWalletSeedPhraseImport.kt @@ -28,6 +28,7 @@ import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.security.DisableAutofillEffect import com.tangem.features.onboarding.v2.impl.R import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.ui.state.MultiWalletSeedPhraseUM import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.ui.utils.InvalidWordsColorTransformation @@ -53,6 +54,8 @@ internal fun MultiWalletSeedPhraseImport(state: MultiWalletSeedPhraseUM.Import, ) } + DisableAutofillEffect() + Box(modifier.fillMaxSize()) { Column( modifier = Modifier From cf94c1f82622a60d68b3933edd47b55baf77ac1e Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 3 Mar 2026 19:15:58 +0500 Subject: [PATCH 2/4] Updated on 2026-08-14 --- .../usecase/ManageCryptoCurrenciesUseCase.kt | 17 ++++++-- .../model/CustomTokenFormModel.kt | 41 +++++++++++-------- .../list/CustomTokenFormUseCasesFacade.kt | 6 ++- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ManageCryptoCurrenciesUseCase.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ManageCryptoCurrenciesUseCase.kt index 2bef64e9b1..2774fa49fe 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ManageCryptoCurrenciesUseCase.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ManageCryptoCurrenciesUseCase.kt @@ -84,7 +84,7 @@ class ManageCryptoCurrenciesUseCase( withContext(NonCancellable) { val accountStatus = getAccountStatus(accountId = accountId) - val modifiedCurrencyList = accountStatus.tokenList.flattenCurrencies() + var modifiedCurrencyList = accountStatus.tokenList.flattenCurrencies() .modify(add = add, remove = remove) if (!modifiedCurrencyList.hasChanges) { @@ -92,12 +92,21 @@ class ManageCryptoCurrenciesUseCase( return@withContext } + val derivingResult = derivePublicKeys(userWalletId = userWalletId, currencies = modifiedCurrencyList.added) + + if (!skipDerivationErrors && derivingResult.isLeft()) { + modifiedCurrencyList = accountStatus.tokenList.flattenCurrencies() + .modify(add = emptyList(), remove = remove) + + if (!modifiedCurrencyList.hasChanges) { + derivingResult.bind() + } + } + saveAccount( account = accountStatus.account.copy(cryptoCurrencies = modifiedCurrencyList.total), ) - val result = derivePublicKeys(userWalletId = userWalletId, currencies = modifiedCurrencyList.added) - parallelUpdatingScope.launch { syncTokens(userWalletId, modifiedCurrencyList) @@ -107,7 +116,7 @@ class ManageCryptoCurrenciesUseCase( } if (!skipDerivationErrors) { - result.bind() + derivingResult.bind() } } } diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt index 1ce00a7b83..d741fc5ed0 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt @@ -1,6 +1,7 @@ package com.tangem.features.managetokens.model import arrow.core.getOrElse +import com.tangem.common.core.TangemSdkError import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model @@ -8,6 +9,7 @@ import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.message.DialogMessage import com.tangem.domain.managetokens.CreateCryptoCurrencyUseCase import com.tangem.domain.managetokens.FindTokenUseCase @@ -146,7 +148,7 @@ internal class CustomTokenFormModel @Inject constructor( is CustomCurrencyValidator.Status.Validating, -> Unit is CustomCurrencyValidator.Status.SearchingToken -> updateStateWithProgress() - is CustomCurrencyValidator.Status.UnexpectedException -> showErrorDialog() + is CustomCurrencyValidator.Status.UnexpectedException -> showErrorDialog(validatorState.cause) is CustomCurrencyValidator.Status.FormValidationException -> updateStateWithExceptions( exceptions = validatorState.exceptions, ) @@ -236,9 +238,17 @@ internal class CustomTokenFormModel @Inject constructor( } } - private fun showErrorDialog() { + private fun showErrorDialog(throwable: Throwable) { + Timber.e(throwable) + val message = when (throwable) { + is TangemSdkError -> resourceReference( + R.string.generic_error_code, + wrappedList(throwable.code.toString()), + ) + else -> resourceReference(R.string.common_unknown_error) + } val dialog = DialogMessage( - message = resourceReference(R.string.common_unknown_error), + message = message, ) messageSender.send(dialog) @@ -341,8 +351,17 @@ internal class CustomTokenFormModel @Inject constructor( ) { val currency = createdCurrency if (currency == null) { - Timber.e("Trying to add currency without validation") - showErrorDialog() + showErrorDialog(IllegalStateException("Trying to add currency without validation")) + return@resource + } + + useCasesFacade.derivePublicKeysUseCase(listOf(currency)).getOrElse { + showErrorDialog(IllegalStateException("Failed to derive public keys")) + return@resource + } + + useCasesFacade.addCryptoCurrenciesUseCase(currency).getOrElse { throwable -> + showErrorDialog(throwable) return@resource } @@ -353,18 +372,6 @@ internal class CustomTokenFormModel @Inject constructor( ) analyticsEventHandler.send(event) - useCasesFacade.derivePublicKeysUseCase(listOf(currency)).getOrElse { - Timber.e(it, "Failed to derive public keys") - showErrorDialog() - return@resource - } - - useCasesFacade.addCryptoCurrenciesUseCase(currency).getOrElse { - Timber.e(it, "Failed to add currency") - showErrorDialog() - return@resource - } - params.onCurrencyAdded(currency) } diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/CustomTokenFormUseCasesFacade.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/CustomTokenFormUseCasesFacade.kt index 51a46bd0e0..d446dd0141 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/CustomTokenFormUseCasesFacade.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/CustomTokenFormUseCasesFacade.kt @@ -44,7 +44,11 @@ internal class CustomTokenFormUseCasesFacade @AssistedInject constructor( either { val accountId = getAccountId(currency) - manageCryptoCurrenciesUseCase(accountId = accountId, add = currency).bind() + manageCryptoCurrenciesUseCase( + accountId = accountId, + add = currency, + skipDerivationErrors = false, + ).bind() } } else { addCryptoCurrenciesUseCase.invoke(userWalletId = userWalletId, currency = currency) From 6f1c50c2a538133d40356fd4db1af25fd483fefd Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 3 Mar 2026 18:29:38 +0200 Subject: [PATCH 3/4] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index e4fac168bd..b693d601d9 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit e4fac168bd941fe90b0f081dfa70ea1b4148b49f +Subproject commit b693d601d9dc3de27f0536574bce59a6aa5e2e89 From dff0539d13039a8b771fab2e9c8d3f2cab04e6b7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 3 Mar 2026 16:38:56 +0000 Subject: [PATCH 4/4] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index a3bc5cab8e..6934faad61 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,9 +5,9 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.34-1430" +tangemBlockchainSdk = "develop-1437" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "releases-5.34-587" +tangemCardSdk = "develop-582" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem12" #tangemVico = "0.0.1" # Keep it! - used for local builds ^