From 210c83d5d5ef96e399dfd45bff9a079634665e8b Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 26 Dec 2022 14:11:02 +0300 Subject: [PATCH 01/19] Updated on 2026-08-14 --- .../com/tangem/tap/domain/TangemSdkManager.kt | 5 ++ .../redux/WalletSelectorMiddleware.kt | 68 +++++++++++-------- 2 files changed, 43 insertions(+), 30 deletions(-) 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 01350c6c63..be8e4f65b2 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -234,6 +234,11 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co } } + fun useBiometricsForAccessCode(): Boolean { + val policy = tangemSdk.config.userCodeRequestPolicy + return policy is UserCodeRequestPolicy.AlwaysWithBiometrics && policy.codeType == UserCodeType.AccessCode + } + companion object { val config = Config( linkedTerminal = true, diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt index b6b31419de..c7d8495f6a 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt @@ -19,6 +19,7 @@ import com.tangem.tap.domain.model.UserWallet import com.tangem.tap.domain.model.WalletStoreModel import com.tangem.tap.domain.model.builders.UserWalletBuilder import com.tangem.tap.domain.scanCard.ScanCardProcessor +import com.tangem.tap.preferencesStorage import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdkManager @@ -131,21 +132,45 @@ internal class WalletSelectorMiddleware { private fun addWallet() = scope.launch { Analytics.send(MyWallets.Button.ScanNewCard) - scanCardInternal { scanResponse -> - val userWallet = UserWalletBuilder(scanResponse).build() + val prevUseBiometricsForAccessCode = tangemSdkManager.useBiometricsForAccessCode() - userWalletsListManager.save(userWallet) - .doOnFailure { error -> - store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error)) - } - .doOnSuccess { - Analytics.send(MyWallets.CardWasScanned) + // Update access code policy for access code saving when a card was scanned + tangemSdkManager.setAccessCodeRequestPolicy( + useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes, + ) + ScanCardProcessor.scan( + onSuccess = { scanResponse -> + saveUserWalletAndPopBackToWalletScreen(scanResponse) + .doOnFailure { error -> + // Rollback policy if card saving was failed + tangemSdkManager.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode) + store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error)) + } + }, + onFailure = { error -> + // Rollback policy if card scanning was failed + tangemSdkManager.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode) + store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error)) + }, + onWalletNotCreated = { + // No need to rollback policy, continue with the policy set before the card scan + store.dispatchOnMain(WalletSelectorAction.AddWallet.Success) + store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet)) + }, + ) + } - store.dispatchOnMain(WalletSelectorAction.AddWallet.Success) - store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet)) - store.onUserWalletSelected(userWallet) - } - } + private suspend fun saveUserWalletAndPopBackToWalletScreen(scanResponse: ScanResponse): CompletionResult { + val userWallet = UserWalletBuilder(scanResponse).build() + + return userWalletsListManager.save(userWallet) + .doOnSuccess { + Analytics.send(MyWallets.CardWasScanned) + + store.dispatchOnMain(WalletSelectorAction.AddWallet.Success) + store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet)) + store.onUserWalletSelected(userWallet) + } } private fun selectWallet(userWalletId: UserWalletId) { @@ -265,23 +290,6 @@ internal class WalletSelectorMiddleware { } } - private suspend inline fun scanCardInternal( - crossinline onCardScanned: suspend (ScanResponse) -> Unit, - ) { - ScanCardProcessor.scan( - onSuccess = { - onCardScanned(it) - }, - onFailure = { error -> - store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error)) - }, - onWalletNotCreated = { - store.dispatchOnMain(WalletSelectorAction.AddWallet.Success) - store.dispatchOnMain(NavigationAction.PopBackTo()) - }, - ) - } - private suspend fun deleteAccessCodes(userWalletsIds: List): CompletionResult { val cardsIds = userWalletsListManager.userWallets.firstOrNull().orEmpty() .asSequence() From a8776a7cb69c973c62a78d0510a2a42bb3a13b61 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 26 Dec 2022 18:11:01 +0300 Subject: [PATCH 02/19] Updated on 2026-08-14 --- .../tap/features/wallet/ui/WalletFragment.kt | 7 +++--- .../core/ui/utils/OneTouchClickListener.kt | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 core/ui/src/main/java/com/tangem/core/ui/utils/OneTouchClickListener.kt diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index c0bde194bf..8a67196de1 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -16,6 +16,7 @@ import by.kirich1409.viewbindingdelegate.viewBinding import coil.load import coil.size.Scale import com.tangem.core.ui.fragments.setStatusBarColor +import com.tangem.core.ui.utils.OneTouchClickListener import com.tangem.domain.common.TapWorkarounds.isSaltPay import com.tangem.tap.MainActivity import com.tangem.tap.common.analytics.Analytics @@ -110,9 +111,9 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber Unit) : View.OnClickListener { + + private var lastClickTimeMs: Long = 0L + + override fun onClick(v: View?) { + if (SystemClock.elapsedRealtime() - lastClickTimeMs > CLICK_DELAY_MS) { + lastClickTimeMs = SystemClock.elapsedRealtime() + action() + } + } + + companion object { + private const val CLICK_DELAY_MS = 500L + } +} \ No newline at end of file From 8fa38f4a7af06228b621100d42e77ccc3daeea4c Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 27 Dec 2022 11:30:21 +0300 Subject: [PATCH 03/19] Updated on 2026-08-14 --- .../com/tangem/tap/features/onboarding/OnboardingHelper.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt index 9b5c5e9958..775dca1ed3 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt @@ -70,7 +70,10 @@ class OnboardingHelper { // then open save wallet screen tangemSdkManager.canUseBiometry && preferencesStorage.shouldShowSaveUserWalletScreen -> scope.launch { + store.onCardScanned(scanResponse) + delay(timeMillis = 1_200) + store.dispatchOnMain( SaveWalletAction.ProvideBackupInfo( scanResponse = scanResponse, From 6d6fb133cde4752508a7f8f6d0f5adcdbdb25710 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 27 Dec 2022 17:59:57 +0300 Subject: [PATCH 04/19] Updated on 2026-08-14 --- .../DefaultWalletManagersRepository.kt | 6 +---- .../redux/middlewares/WalletMiddleware.kt | 2 +- .../redux/reducers/MultiWalletReducer.kt | 8 +++---- .../wallet/redux/reducers/WalletReducer.kt | 6 ++--- .../tap/features/wallet/ui/WalletViewModel.kt | 8 +++++-- .../redux/WalletSelectorMiddleware.kt | 24 ++++++++++++------- 6 files changed, 30 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletManagersRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletManagersRepository.kt index 3de7a3f6b1..6355f2f6d6 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletManagersRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletManagersRepository.kt @@ -106,11 +106,7 @@ internal class DefaultWalletManagersRepository( override suspend fun delete(userWalletIds: List): CompletionResult = catching { walletManagersStorage.update { prevManagers -> - prevManagers.apply { - userWalletIds.forEach { userWalletId -> - remove(userWalletId) - } - } + prevManagers.filterKeys { it !in userWalletIds } as HashMap> } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 5dcd8b81bd..243ab5eab6 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -305,7 +305,7 @@ class WalletMiddleware { val reduxWalletStores = wallStores.mapToReduxModels(state.isMultiwalletAllowed) store.dispatchOnMain( WalletAction.WalletStoresChanged.UpdateWalletStores( - reduxWalletStores = reduxWalletStores.toList(), + reduxWalletStores = reduxWalletStores, ), ) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt index b1e6cebbac..7cb35da559 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt @@ -31,7 +31,7 @@ class MultiWalletReducer { fun reduce(action: WalletAction.MultiWallet, state: WalletState): WalletState { return when (action) { is WalletAction.MultiWallet.AddBlockchains -> { - val walletStores: List = action.blockchains.mapNotNull { blockchain -> + val walletStores: List = action.blockchains.map { blockchain -> val walletManager = action.walletManagers.firstOrNull { it.wallet.blockchain == blockchain.blockchain && (it.wallet.publicKey.derivationPath?.rawPath == blockchain.derivationPath) @@ -65,10 +65,10 @@ class MultiWalletReducer { ) } - val selectedCurrency = if (!state.isMultiwalletAllowed) { - walletStores.firstOrNull()?.walletsData?.firstOrNull()?.currency + val selectedCurrency = if (state.isMultiwalletAllowed) { + state.selectedCurrency } else { - state.selectedWalletData?.currency + walletStores.firstOrNull()?.walletsData?.firstOrNull()?.currency } state.copy( walletsStores = walletStores, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index 254fe48e3b..d71909cfec 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -362,13 +362,13 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS ) } is WalletAction.LoadData.Success -> { - val selectedCurrency = if (!newState.isMultiwalletAllowed) { + val selectedCurrency = if (newState.isMultiwalletAllowed) { + newState.selectedCurrency + } else { newState.walletsStores.firstOrNull() ?.walletsData ?.firstOrNull() ?.currency - } else { - newState.selectedWalletData?.currency } newState = newState.copy( diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletViewModel.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletViewModel.kt index df0b0537ed..a9fc0ad8cf 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletViewModel.kt @@ -8,8 +8,10 @@ import com.tangem.tap.store import com.tangem.tap.userWalletsListManager import com.tangem.tap.walletStoresManager import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -21,8 +23,10 @@ internal class WalletViewModel : ViewModel() { private fun bootstrapSelectedWalletStoresChanges() { userWalletsListManager.selectedUserWallet - .flatMapLatest { selectedWallet -> - walletStoresManager.get(selectedWallet.walletId) + .map { it.walletId } + .distinctUntilChanged() + .flatMapLatest { selectedUserWalletId -> + walletStoresManager.get(selectedUserWalletId) } .onEach { walletStores -> store.dispatch(WalletAction.WalletStoresChanged(walletStores)) diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt index c7d8495f6a..cc6642743f 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt @@ -277,26 +277,32 @@ internal class WalletSelectorMiddleware { .flatMap { walletStoresManager.delete(userWalletsIds) } .flatMap { deleteAccessCodes(userWalletsIds) } .doOnSuccess { - val selectedWallet = userWalletsListManager.selectedUserWalletSync + val selectedUserWallet = userWalletsListManager.selectedUserWalletSync when { - selectedWallet == null -> { + selectedUserWallet == null -> { store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Welcome)) } - currentSelectedWalletId != selectedWallet.walletId -> { - store.onUserWalletSelected(selectedWallet) + + currentSelectedWalletId != selectedUserWallet.walletId -> { + store.onUserWalletSelected(selectedUserWallet) } } } } private suspend fun deleteAccessCodes(userWalletsIds: List): CompletionResult { - val cardsIds = userWalletsListManager.userWallets.firstOrNull().orEmpty() - .asSequence() - .filter { it.walletId in userWalletsIds } - .flatMap { it.cardsInWallet } + val cardsIds = userWalletsListManager.userWallets.firstOrNull() + ?.asSequence() + ?.filter { it.walletId in userWalletsIds } + ?.flatMap { it.cardsInWallet } + ?.toSet() - return tangemSdkManager.deleteSavedUserCodes(cardsIds.toSet()) + return if (cardsIds.isNullOrEmpty()) { + CompletionResult.Success(Unit) + } else { + tangemSdkManager.deleteSavedUserCodes(cardsIds.toSet()) + } } private suspend fun UserWalletModel.updateWalletStoresAndCalculateFiatBalance( From cc57668491f01d7c28f5cd9e33844daf204b669b Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 27 Dec 2022 19:01:21 +0300 Subject: [PATCH 05/19] Updated on 2026-08-14 --- .../tap/features/wallet/redux/reducers/WalletReducer.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index d71909cfec..2505702c20 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -20,7 +20,6 @@ import com.tangem.tap.domain.extensions.isMultiwalletAllowed import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.wallet.models.Currency -import com.tangem.tap.features.wallet.models.TotalBalance import com.tangem.tap.features.wallet.models.WalletRent import com.tangem.tap.features.wallet.redux.AddressData import com.tangem.tap.features.wallet.redux.Artwork @@ -36,7 +35,6 @@ import com.tangem.tap.features.wallet.redux.replaceSomeWalletsData import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData import com.tangem.tap.proxy.AppStateHolder -import com.tangem.tap.store import org.rekotlin.Action import timber.log.Timber import java.math.BigDecimal @@ -344,8 +342,9 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS card.settings.isBackupAllowed && card.backupStatus == CardDTO.BackupStatus.NoBackup, walletCardsCount = card.findCardsCount(), + walletsStores = newState.walletsStores, totalBalance = if (isMultiCurrency) { - TotalBalance(ProgressState.Loading, BigDecimal.ZERO, store.state.globalState.appCurrency) + newState.totalBalance } else { null }, From de6b0af2281de45df3ac84370d7fdfee4f392768 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 27 Dec 2022 11:10:34 +0300 Subject: [PATCH 06/19] Updated on 2026-08-14 --- .../converters/BasicEventConverter.kt | 8 ++- .../common/feedback/AdditionalFeedbackInfo.kt | 4 +- .../com/tangem/tap/domain/model/UserWallet.kt | 20 ------ .../model/builders/UserWalletBuilder.kt | 23 +++--- .../model/builders/UserWalletIdBuilder.kt | 70 +++++++++++++++++++ .../tap/domain/tokens/UserTokensRepository.kt | 16 +++-- .../BiometricUserWalletsListManager.kt | 4 +- .../model/UserWalletEncryptionKey.kt | 2 +- ...erWalletsSensitiveInformationRepository.kt | 2 +- .../utils/UserWalletEncyptionKeyCalculator.kt | 19 ++--- .../details/redux/DetailsMiddleware.kt | 32 ++++----- .../tap/features/home/redux/HomeMiddleware.kt | 2 +- .../twins/redux/TwinCardsMiddleware.kt | 4 +- .../saveWallet/redux/SaveWalletMiddleware.kt | 2 +- .../redux/WalletSelectorMiddleware.kt | 2 + .../welcome/redux/WelcomeMiddleware.kt | 2 +- .../tangem/tap/proxy/UserWalletManagerImpl.kt | 9 ++- .../tangem/domain/common/util/UserWalletId.kt | 16 +---- 18 files changed, 147 insertions(+), 90 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt rename domain/src/main/java/com/tangem/domain/common/util/CardExtensions.kt => app/src/main/java/com/tangem/tap/domain/userWalletList/utils/UserWalletEncyptionKeyCalculator.kt (55%) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt index 45d55aac2a..52fa450434 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt @@ -3,11 +3,11 @@ package com.tangem.tap.common.analytics.converters import com.tangem.common.Converter import com.tangem.common.extensions.isZero import com.tangem.domain.common.ScanResponse -import com.tangem.domain.common.util.userWalletId import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Basic import com.tangem.tap.common.analytics.filters.BasicTopUpFilter import com.tangem.tap.domain.extensions.isMultiwalletAllowed +import com.tangem.tap.domain.model.builders.UserWalletIdBuilder import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.WalletData import com.tangem.tap.features.wallet.redux.WalletState @@ -29,7 +29,9 @@ class BasicSignInEventConverter( currency = cardCurrency, batch = scanResponse.card.batchId, ).apply { - filterData = scanResponse.card.userWalletId.stringValue + filterData = UserWalletIdBuilder.scanResponse(scanResponse) + .build() + ?.stringValue } } } @@ -43,7 +45,7 @@ class BasicTopUpEventConverter( val cardCurrency = ParamCardCurrencyConverter().convert(scanResponse) ?: return null val data = BasicTopUpFilter.Data( - walletId = scanResponse.card.userWalletId.stringValue, + walletId = UserWalletIdBuilder.scanResponse(scanResponse).build()?.stringValue ?: "", cardBalanceState = AnalyticsParam.CardBalanceState.from(value.walletsDataFromStores), ) diff --git a/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt b/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt index 16e1bb559a..589597238f 100644 --- a/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt +++ b/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt @@ -10,8 +10,8 @@ import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.address.Address import com.tangem.domain.common.CardDTO import com.tangem.domain.common.ScanResponse -import com.tangem.domain.common.util.userWalletId import com.tangem.tap.common.extensions.stripZeroPlainString +import com.tangem.tap.domain.model.builders.UserWalletIdBuilder class AdditionalFeedbackInfo { class EmailWalletInfo( @@ -54,7 +54,7 @@ class AdditionalFeedbackInfo { cardFirmwareVersion = data.card.firmwareVersion.stringValue cardIssuer = data.card.issuer.name signedHashesCount = formatSignedHashes(data.card.wallets) - userWalletId = data.card.userWalletId.stringValue + userWalletId = UserWalletIdBuilder.scanResponse(data).build()?.stringValue ?: "" } fun setWalletsInfo(walletManagers: List) { diff --git a/app/src/main/java/com/tangem/tap/domain/model/UserWallet.kt b/app/src/main/java/com/tangem/tap/domain/model/UserWallet.kt index 4dec0df7d1..a76fbb9d1a 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/UserWallet.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/UserWallet.kt @@ -1,6 +1,5 @@ package com.tangem.tap.domain.model -import com.tangem.common.extensions.toHexString import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.util.UserWalletId @@ -33,23 +32,4 @@ data class UserWallet( val isLocked: Boolean get() = scanResponse.card.wallets.isEmpty() -} - -/** - * !!! Workaround !!! - * - * Calculate same [UserWalletId] for twins instead - * - * TODO: Remove after [REDACTED_JIRA] - * */ -fun UserWallet.isTwinnedWith(other: UserWallet): Boolean { - if (!scanResponse.isTangemTwins() || !other.scanResponse.isTangemTwins()) return false - if (scanResponse.secondTwinPublicKey == null || other.scanResponse.secondTwinPublicKey == null) return false - if (other.scanResponse.secondTwinPublicKey == scanResponse.card.wallets.firstOrNull()?.publicKey?.toHexString()) { - return true - } - if (scanResponse.secondTwinPublicKey == other.scanResponse.card.wallets.firstOrNull()?.publicKey?.toHexString()) { - return true - } - return false } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt index 6e4d834d38..c993194983 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt @@ -8,7 +8,6 @@ import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.TapWorkarounds.isStart2Coin import com.tangem.domain.common.TwinCardNumber import com.tangem.domain.common.TwinsHelper -import com.tangem.domain.common.util.userWalletId import com.tangem.operations.attestation.OnlineCardVerifier import com.tangem.operations.attestation.TangemApi import com.tangem.tap.domain.model.UserWallet @@ -49,16 +48,20 @@ class UserWalletBuilder( } } - suspend fun build(): UserWallet { + suspend fun build(): UserWallet? { return with(scanResponse) { - UserWallet( - walletId = card.userWalletId, - name = userWalletName, - artworkUrl = loadArtworkUrl(card.cardId, card.cardPublicKey), - cardsInWallet = backupCardsIds.plus(card.cardId), - scanResponse = this, - isMultiCurrency = isMultiCurrency, - ) + UserWalletIdBuilder.scanResponse(scanResponse) + .build() + ?.let { + UserWallet( + walletId = it, + name = userWalletName, + artworkUrl = loadArtworkUrl(card.cardId, card.cardPublicKey), + cardsInWallet = backupCardsIds.plus(card.cardId), + scanResponse = this, + isMultiCurrency = isMultiCurrency, + ) + } } } diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt new file mode 100644 index 0000000000..1fdef7c37c --- /dev/null +++ b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletIdBuilder.kt @@ -0,0 +1,70 @@ +package com.tangem.tap.domain.model.builders + +import com.tangem.common.extensions.calculateSha256 +import com.tangem.common.extensions.hexToBytes +import com.tangem.crypto.Secp256k1 +import com.tangem.domain.common.CardDTO +import com.tangem.domain.common.ProductType +import com.tangem.domain.common.ScanResponse +import com.tangem.domain.common.TapWorkarounds.isTangemTwins +import com.tangem.domain.common.extensions.calculateHmacSha256 +import com.tangem.domain.common.util.UserWalletId + +class UserWalletIdBuilder private constructor( + private val publicKey: ByteArray?, + private val pairTwinPublicKey: ByteArray? = null, +) { + fun build(): UserWalletId? { + val seed = if (publicKey != null) { + if (pairTwinPublicKey != null) { + Secp256k1.sum(publicKey, pairTwinPublicKey) + } else { + publicKey + } + } else null + + return seed?.let { + UserWalletId(value = calculateUserWalletId(it)) + } + } + + private fun calculateUserWalletId(seed: ByteArray?): ByteArray? { + val message = MESSAGE_FOR_WALLET_ID.toByteArray() + val keyHash = seed?.calculateSha256() + + return if (keyHash != null) { + message.calculateHmacSha256(keyHash) + } else null + } + + companion object { + private const val MESSAGE_FOR_WALLET_ID = "UserWalletID" + + @Throws(IllegalArgumentException::class) + fun card(card: CardDTO): UserWalletIdBuilder { + require(!card.isTangemTwins) { + "For twin cards use scanResponse to ID calculation" + } + + return UserWalletIdBuilder(findPublicKey(card.wallets)) + } + + fun scanResponse(scanResponse: ScanResponse): UserWalletIdBuilder { + return UserWalletIdBuilder( + publicKey = findPublicKey(scanResponse.card.wallets), + pairTwinPublicKey = when (scanResponse.productType) { + ProductType.Twins -> scanResponse.secondTwinPublicKey?.hexToBytes() + ProductType.Note, + ProductType.Wallet, + ProductType.SaltPay, + -> null + }, + ) + } + + private fun findPublicKey(wallets: List): ByteArray? { + return wallets.firstOrNull() + ?.publicKey + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt index 6fb7de9ad7..b3efb6ce5b 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt @@ -6,9 +6,9 @@ import com.tangem.common.services.Result import com.tangem.datasource.api.tangemTech.TangemTechService import com.tangem.datasource.api.tangemTech.UserTokensResponse import com.tangem.domain.common.CardDTO -import com.tangem.domain.common.util.userWalletId import com.tangem.tap.common.AndroidFileReader import com.tangem.tap.domain.NoDataError +import com.tangem.tap.domain.model.builders.UserWalletIdBuilder import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.wallet.models.Currency @@ -24,7 +24,7 @@ class UserTokensRepository( private val networkService: UserTokensNetworkService, ) { suspend fun getUserTokens(card: CardDTO): List { - val userId = card.userWalletId.stringValue + val userId = getUserWalletId(card) ?: return emptyList() if (DemoHelper.isDemoCardId(card.cardId)) { return loadTokensOffline(card, userId).ifEmpty { loadDemoCurrencies() } } @@ -47,14 +47,14 @@ class UserTokensRepository( } suspend fun saveUserTokens(card: CardDTO, tokens: List) { - val userId = card.userWalletId.stringValue + val userId = getUserWalletId(card) ?: return val userTokens = tokens.toUserTokensResponse() networkService.saveUserTokens(userId, userTokens) storageService.saveUserTokens(userId, userTokens) } suspend fun removeUserTokens(card: CardDTO) { - val userId = card.userWalletId.stringValue + val userId = getUserWalletId(card) ?: return val userTokens = emptyList().toUserTokensResponse() networkService.saveUserTokens(userId, userTokens) storageService.saveUserTokens(userId, userTokens) @@ -70,7 +70,7 @@ class UserTokensRepository( } suspend fun loadBlockchainsToDerive(card: CardDTO): List { - val userId = card.userWalletId.stringValue + val userId = getUserWalletId(card) ?: return emptyList() val blockchainNetworks = loadTokensOffline(card, userId).toBlockchainNetworks() if (DemoHelper.isDemoCardId(card.cardId)) { @@ -103,6 +103,7 @@ class UserTokensRepository( coroutineScope { launch { networkService.saveUserTokens(userId = userId, tokens = userTokens) } } tokens } + else -> { val tokens = storageService.getUserTokens(userId) ?: storageService.getUserTokens(card) tokens.distinct() @@ -114,6 +115,11 @@ class UserTokensRepository( return storageService.getUserTokens(userId) ?: storageService.getUserTokens(card) } + private fun getUserWalletId(card: CardDTO): String? { + return UserWalletIdBuilder.card(card).build() + ?.stringValue + } + companion object { const val SORT_DEFAULT_VALUE = "manual" const val GROUP_DEFAULT_VALUE = "none" diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt index f7781ca770..648323a70c 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt @@ -3,7 +3,6 @@ package com.tangem.tap.domain.userWalletList.implementation import com.tangem.common.* import com.tangem.domain.common.util.UserWalletId import com.tangem.tap.domain.model.UserWallet -import com.tangem.tap.domain.model.isTwinnedWith import com.tangem.tap.domain.userWalletList.UserWalletListError import com.tangem.tap.domain.userWalletList.UserWalletsListManager import com.tangem.tap.domain.userWalletList.model.UserWalletEncryptionKey @@ -89,8 +88,7 @@ internal class BiometricUserWalletsListManager( } else { val isWalletSaved = state.value.userWallets .any { - // Workaround, check [UserWallet.isTwinnedWith] - it.cardsInWallet.contains(userWallet.cardId) || it.isTwinnedWith(userWallet) + it.walletId == userWallet.walletId || it.cardsInWallet.contains(userWallet.cardId) } if (isWalletSaved) { diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletEncryptionKey.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletEncryptionKey.kt index cdf1edbdfb..a5c20a7790 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletEncryptionKey.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletEncryptionKey.kt @@ -2,8 +2,8 @@ package com.tangem.tap.domain.userWalletList.model import com.squareup.moshi.JsonClass import com.tangem.domain.common.util.UserWalletId -import com.tangem.domain.common.util.encryptionKey import com.tangem.tap.domain.model.UserWallet +import com.tangem.tap.domain.userWalletList.utils.encryptionKey @JsonClass(generateAdapter = true) internal data class UserWalletEncryptionKey( diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt index 5918312b6e..158dc0db2b 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt @@ -9,13 +9,13 @@ import com.tangem.common.catching import com.tangem.common.mapFailure import com.tangem.common.services.secure.SecureStorage import com.tangem.domain.common.util.UserWalletId -import com.tangem.domain.common.util.encryptionKey import com.tangem.tap.common.extensions.filterNotNull import com.tangem.tap.domain.model.UserWallet import com.tangem.tap.domain.userWalletList.UserWalletListError import com.tangem.tap.domain.userWalletList.model.UserWalletEncryptionKey import com.tangem.tap.domain.userWalletList.model.UserWalletSensitiveInformation import com.tangem.tap.domain.userWalletList.repository.UserWalletsSensitiveInformationRepository +import com.tangem.tap.domain.userWalletList.utils.encryptionKey import com.tangem.tap.domain.userWalletList.utils.sensitiveInformation import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext diff --git a/domain/src/main/java/com/tangem/domain/common/util/CardExtensions.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/UserWalletEncyptionKeyCalculator.kt similarity index 55% rename from domain/src/main/java/com/tangem/domain/common/util/CardExtensions.kt rename to app/src/main/java/com/tangem/tap/domain/userWalletList/utils/UserWalletEncyptionKeyCalculator.kt index 4dc70fd2bd..3ecfb70521 100644 --- a/domain/src/main/java/com/tangem/domain/common/util/CardExtensions.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/UserWalletEncyptionKeyCalculator.kt @@ -1,24 +1,27 @@ -package com.tangem.domain.common.util +package com.tangem.tap.domain.userWalletList.utils import com.tangem.common.extensions.calculateSha256 import com.tangem.domain.common.CardDTO import com.tangem.domain.common.extensions.calculateHmacSha256 -val CardDTO.userWalletId: UserWalletId - get() = UserWalletId(findWalletPublicKey(wallets)) +internal val CardDTO.encryptionKey: ByteArray + @Throws(IllegalArgumentException::class) + get() { + val walletPublicKey = requireNotNull(findPublicKey(wallets)) { + "Wallet public key must not be null" + } -val CardDTO.encryptionKey: ByteArray - get() = findWalletPublicKey(wallets) - ?.let { calculateEncryptionKey(it) } - ?: error("Wallet ID not found") + return calculateEncryptionKey(walletPublicKey) + } private fun calculateEncryptionKey(publicKey: ByteArray): ByteArray { val message = MESSAGE_FOR_ENCRYPTION_KEY.toByteArray() val keyHash = publicKey.calculateSha256() + return message.calculateHmacSha256(keyHash) } -private fun findWalletPublicKey(wallets: List): ByteArray? { +private fun findPublicKey(wallets: List): ByteArray? { return wallets.firstOrNull() ?.publicKey } diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index 319071642c..2c5df4e058 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -4,10 +4,8 @@ import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess -import com.tangem.common.extensions.toHexString import com.tangem.common.flatMap import com.tangem.domain.common.TapWorkarounds.isTangemTwins -import com.tangem.domain.common.util.userWalletId import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Settings @@ -20,6 +18,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.model.builders.UserWalletBuilder +import com.tangem.tap.domain.model.builders.UserWalletIdBuilder import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletMode import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction @@ -27,6 +26,7 @@ import com.tangem.tap.preferencesStorage import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdkManager +import com.tangem.tap.userTokensRepository import com.tangem.tap.userWalletsListManager import com.tangem.tap.walletStoresManager import com.tangem.wallet.R @@ -79,20 +79,16 @@ class DetailsMiddleware { } DetailsAction.ScanCard -> { scope.launch { - tangemSdkManager.scanCard(allowRequestAccessCodeFromRepository = true) - .doOnSuccess { card -> - val isSameWallet = state.scanResponse?.card?.userWalletId - ?.equals(card.userWalletId) - ?: false + tangemSdkManager.scanProduct(userTokensRepository) + .doOnSuccess { scanResponse -> + val currentUserWalletId = state.scanResponse + ?.let { UserWalletIdBuilder.scanResponse(it).build() } + val scannedUserWalletId = UserWalletIdBuilder.scanResponse(scanResponse) + .build() + val isSameWallet = currentUserWalletId == scannedUserWalletId - // !!! Workaround !!! - // TODO: Remove after [REDACTED_JIRA] - val isTwinned = card.wallets.firstOrNull()?.publicKey?.toHexString() - ?.equals(state.scanResponse?.secondTwinPublicKey) - ?: false - - if (isSameWallet || isTwinned) { - store.dispatchOnMain(DetailsAction.PrepareCardSettingsData(card)) + if (isSameWallet) { + store.dispatchOnMain(DetailsAction.PrepareCardSettingsData(scanResponse.card)) } else { store.dispatchDialogShow( AppDialog.SimpleOkDialogRes( @@ -122,8 +118,10 @@ class DetailsMiddleware { is DetailsAction.ResetToFactory.Proceed -> { val card = store.state.detailsState.cardSettingsState?.card ?: return scope.launch { + val userWalletId = UserWalletIdBuilder.card(card).build() + tangemSdkManager.resetToFactorySettings(card.cardId) - .flatMap { userWalletsListManager.delete(listOf(card.userWalletId)) } + .flatMap { userWalletsListManager.delete(listOfNotNull(userWalletId)) } .flatMap { tangemSdkManager.deleteSavedUserCodes(setOf(card.cardId)) } .doOnSuccess { Analytics.send(Settings.CardSettings.FactoryResetFinished()) @@ -275,7 +273,7 @@ class DetailsMiddleware { private suspend fun saveCurrentWallet(state: DetailsState) { val scanResponse = state.scanResponse ?: return - val userWallet = UserWalletBuilder(scanResponse).build() + val userWallet = UserWalletBuilder(scanResponse).build() ?: return userWalletsListManager.save(userWallet) .doOnFailure { error -> 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 0c5b990b06..fdacaa5bd1 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 @@ -93,7 +93,7 @@ private fun readCard() = scope.launch { onSuccess = { scanResponse -> scope.launch { if (preferencesStorage.shouldSaveUserWallets) { - val userWallet = UserWalletBuilder(scanResponse).build() + val userWallet = UserWalletBuilder(scanResponse).build() ?: return@launch userWalletsListManager.save(userWallet) .doOnFailure { error -> Timber.e(error, "Unable to save user wallet") 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 ae60d9f637..b5bd3c7504 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 @@ -6,7 +6,6 @@ import com.tangem.common.CompletionResult import com.tangem.common.extensions.guard import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.extensions.withMainContext -import com.tangem.domain.common.util.userWalletId import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.events.AnalyticsParam @@ -25,6 +24,7 @@ import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.makePrimaryWalletManager +import com.tangem.tap.domain.model.builders.UserWalletIdBuilder import com.tangem.tap.domain.twins.TwinCardsManager import com.tangem.tap.features.onboarding.OnboardingHelper import com.tangem.tap.features.wallet.models.Currency @@ -156,7 +156,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) { TwinCardsStep.CreateFirstWallet -> { scope.launch { userWalletsListManager.delete( - listOf(getScanResponse().card.userWalletId), + listOfNotNull(UserWalletIdBuilder.scanResponse(getScanResponse()).build()), ) } } diff --git a/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt index 106ebfa9af..60bc2e076e 100644 --- a/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt @@ -88,7 +88,7 @@ internal class SaveWalletMiddleware { scope.launch { val userWallet = UserWalletBuilder(scanResponse) .backupCardsIds(state.backupInfo?.backupCardsIds) - .build() + .build() ?: return@launch val isFirstSavedWallet = !userWalletsListManager.hasSavedUserWallets diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt index cc6642743f..c1f24294f4 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.walletSelector.redux import com.tangem.common.CompletionResult +import com.tangem.common.core.TangemSdkError import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess import com.tangem.common.flatMap @@ -162,6 +163,7 @@ internal class WalletSelectorMiddleware { private suspend fun saveUserWalletAndPopBackToWalletScreen(scanResponse: ScanResponse): CompletionResult { val userWallet = UserWalletBuilder(scanResponse).build() + ?: return CompletionResult.Failure(TangemSdkError.WalletIsNotCreated()) return userWalletsListManager.save(userWallet) .doOnSuccess { diff --git a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt index 7b0f37e36e..e7cb2e01e7 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt @@ -71,7 +71,7 @@ internal class WelcomeMiddleware { private fun proceedWithCard(state: WelcomeState) = scope.launch { scanCardInternal { scanResponse -> - val userWallet = UserWalletBuilder(scanResponse).build() + val userWallet = UserWalletBuilder(scanResponse).build() ?: return@scanCardInternal userWalletsListManager.save(userWallet, canOverride = true) .doOnFailure { error -> diff --git a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt index 8856cdc80d..e12ca9b9be 100644 --- a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt @@ -8,12 +8,12 @@ import com.tangem.domain.common.CardDTO import com.tangem.domain.common.TapWorkarounds.derivationStyle import com.tangem.domain.common.extensions.fromNetworkId import com.tangem.domain.common.extensions.toNetworkId -import com.tangem.domain.common.util.userWalletId import com.tangem.lib.crypto.UserWalletManager import com.tangem.lib.crypto.models.Currency import com.tangem.lib.crypto.models.NativeToken import com.tangem.lib.crypto.models.NonNativeToken import com.tangem.tap.domain.extensions.makeWalletManagerForApp +import com.tangem.tap.domain.model.builders.UserWalletIdBuilder import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.wallet.redux.WalletAction import org.rekotlin.Action @@ -54,7 +54,12 @@ class UserWalletManagerImpl( } override fun getWalletId(): String { - return appStateHolder.getActualCard()?.userWalletId?.stringValue ?: "" + return appStateHolder.getActualCard()?.let { + UserWalletIdBuilder.card(it) + .build() + ?.stringValue + } + ?: "" } override suspend fun isTokenAdded(currency: Currency): Boolean { diff --git a/domain/src/main/java/com/tangem/domain/common/util/UserWalletId.kt b/domain/src/main/java/com/tangem/domain/common/util/UserWalletId.kt index 4e83c913ca..abf878da69 100644 --- a/domain/src/main/java/com/tangem/domain/common/util/UserWalletId.kt +++ b/domain/src/main/java/com/tangem/domain/common/util/UserWalletId.kt @@ -1,17 +1,15 @@ package com.tangem.domain.common.util -import com.tangem.common.extensions.calculateSha256 import com.tangem.common.extensions.hexToBytes import com.tangem.common.extensions.toHexString -import com.tangem.domain.common.extensions.calculateHmacSha256 class UserWalletId( val stringValue: String, ) { val value = stringValue.hexToBytes() - constructor(walletPublicKey: ByteArray?) : this( - stringValue = walletPublicKey?.let { calculateUserWalletId(it).toHexString() } ?: "", + constructor(value: ByteArray?) : this( + stringValue = value?.toHexString() ?: "", ) override fun equals(other: Any?): Boolean { @@ -32,12 +30,4 @@ class UserWalletId( "UserWalletId(${take(3)}...${takeLast(3)})" } } -} - -private fun calculateUserWalletId(publicKey: ByteArray): ByteArray { - val message = MESSAGE_FOR_WALLET_ID.toByteArray() - val keyHash = publicKey.calculateSha256() - return message.calculateHmacSha256(keyHash) -} - -private const val MESSAGE_FOR_WALLET_ID = "UserWalletID" \ No newline at end of file +} \ No newline at end of file From 9ee61f80579f285d5fb683b73c21c7058d878631 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 27 Dec 2022 11:10:51 +0300 Subject: [PATCH 07/19] Updated on 2026-08-14 --- buildSrc/src/main/java/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt index 869eaf8f0b..89471ec92c 100644 --- a/buildSrc/src/main/java/Versions.kt +++ b/buildSrc/src/main/java/Versions.kt @@ -61,7 +61,7 @@ object Versions { // region Tangem const val tangemBlockchainSdk = "develop-141" - const val tangemCardSgk = "develop-178" + const val tangemCardSgk = "develop-179" // endregion Tangem // region Testing From 6b3e84f9c34ee038f5b6e22888dc024374a1bd6a Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 28 Dec 2022 17:15:32 +0300 Subject: [PATCH 08/19] Updated on 2026-08-14 --- .../tangem/tap/features/wallet/ui/WalletDetailsFragment.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index a7f230dc35..f212aac2dd 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -132,12 +132,8 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), override fun onStop() { super.onStop() store.unsubscribe(this) - } - - override fun onDestroy() { walletDataWatcher.clear() walletStateWatcher.clear() - super.onDestroy() } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { From 0c888d210f5274f05dddd3c280173cba8faeace3 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 28 Dec 2022 17:00:44 +0300 Subject: [PATCH 09/19] Updated on 2026-08-14 --- .../tap/domain/model/builders/UserWalletBuilder.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt index 6e4d834d38..ed8eb97623 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt @@ -1,5 +1,7 @@ package com.tangem.tap.domain.model.builders +import com.tangem.common.card.EllipticCurve +import com.tangem.common.card.FirmwareVersion import com.tangem.common.extensions.toHexString import com.tangem.common.services.Result import com.tangem.domain.common.CardDTO @@ -40,7 +42,16 @@ class UserWalletBuilder( ProductType.Note -> false ProductType.Twins -> false ProductType.SaltPay -> false - ProductType.Wallet -> !card.isStart2Coin + ProductType.Wallet -> when { + card.isStart2Coin -> false + card.firmwareVersion >= FirmwareVersion.MultiWalletAvailable -> true + else -> { + val cardWallets = card.wallets + require(cardWallets.isNotEmpty()) { "Card wallets must not be empty" } + + cardWallets.first().curve == EllipticCurve.Secp256k1 + } + } } fun backupCardsIds(backupCardsIds: Set?) = this.apply { From 252df193d2fd0e19f7612ded53d47e99df43be04 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 28 Dec 2022 18:40:03 +0300 Subject: [PATCH 10/19] Updated on 2026-08-14 --- .../AddressInfoBottomSheetDialog.kt | 30 +++++------------ .../wallet/ui/WalletDetailsFragment.kt | 18 +++++++++-- .../wallet/ui/wallet/SingleWalletView.kt | 32 ++++++++++++++----- .../layout/dialog_onboarding_address_info.xml | 2 +- app/src/main/res/layout/layout_address.xml | 11 +++++++ .../main/res/layout/layout_wallet_details.xml | 2 +- .../src/main/res/values-de/strings-app.xml | 3 +- .../src/main/res/values-fr/strings-app.xml | 3 +- .../src/main/res/values-it/strings-app.xml | 3 +- .../src/main/res/values-ru/strings-app.xml | 3 +- core/res/src/main/res/values/strings-app.xml | 3 +- 11 files changed, 65 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt index 4635716436..b56ddaf6cd 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt @@ -11,8 +11,8 @@ import com.tangem.tap.common.extensions.copyToClipboard import com.tangem.tap.common.extensions.dispatchDialogHide import com.tangem.tap.common.extensions.dispatchShare import com.tangem.tap.common.extensions.dispatchToastNotification +import com.tangem.tap.common.extensions.getString import com.tangem.tap.common.redux.AppDialog -import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.AddressData import com.tangem.tap.store import com.tangem.wallet.R @@ -62,26 +62,12 @@ class AddressInfoBottomSheetDialog( Analytics.send(Token.Recieve.ButtonShareAddress()) store.dispatchShare(data.shareUrl) } - tvReceiveMessage.text = getQRReceiveMessage(tvReceiveMessage.context, stateDialog.currency) - } -} - -fun getQRReceiveMessage(context: Context, currency: Currency): String { - return when (currency) { - is Currency.Blockchain -> { - context.getString( - R.string.address_qr_code_message_format, - currency.blockchain.fullName, - currency.currencySymbol, - ) - } - is Currency.Token -> { - context.getString( - R.string.address_qr_code_message_token_format, - currency.token.name, - currency.currencySymbol, - currency.blockchain.fullName, - ) - } + val blockchain = stateDialog.currency.blockchain + tvReceiveMessage.text = tvReceiveMessage.getString( + id = R.string.address_qr_code_message_format, + blockchain.fullName, + blockchain.currency, + blockchain.fullName, + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index f212aac2dd..bd1608e7de 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -36,7 +36,6 @@ import com.tangem.tap.common.extensions.toQrCode import com.tangem.tap.common.recyclerView.SpaceItemDecoration import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.tokens.models.BlockchainNetwork -import com.tangem.tap.features.onboarding.getQRReceiveMessage import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.PendingTransaction import com.tangem.tap.features.wallet.redux.ErrorType @@ -324,8 +323,21 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), ) } ivQrCode.setImageBitmap(state.walletAddresses.selectedAddress.shareUrl.toQrCode()) - tvReceiveMessage.text = - getQRReceiveMessage(tvReceiveMessage.context, state.currency) + + tvReceiveMessage.text = when (val currency = state.currency) { + is Currency.Blockchain -> tvReceiveMessage.getString( + id = R.string.address_qr_code_message_format, + currency.blockchain.fullName, + currency.currencySymbol, + currency.blockchain.fullName, + ) + is Currency.Token -> tvReceiveMessage.getString( + id = R.string.address_qr_code_message_format, + currency.token.name, + currency.currencySymbol, + currency.blockchain.fullName, + ) + } } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt index e8fc90a242..18ebc3dd4b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt @@ -6,6 +6,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.tangem.tap.common.extensions.beginDelayedTransition import com.tangem.tap.common.extensions.fitChipsByGroupWidth import com.tangem.tap.common.extensions.getQuantityString +import com.tangem.tap.common.extensions.getString import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.show import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState @@ -65,7 +66,7 @@ class SingleWalletView : WalletView() { setupTwinCards(state.twinCardsState, binding) setupButtons(state.primaryWallet, binding, state.isExchangeServiceFeatureOn) - setupAddressCard(state.primaryWallet, binding) + setupAddressCard(state, binding) showPendingTransactionsIfPresent(state.primaryWallet.pendingTransactions) setupBalance(state, state.primaryWallet) } @@ -146,35 +147,50 @@ class SingleWalletView : WalletView() { } } - private fun setupAddressCard(state: WalletData, binding: FragmentWalletBinding) = with(binding.lAddress) { - if (state.walletAddresses != null && state.currency is Currency.Blockchain) { + private fun setupAddressCard(state: WalletState, binding: FragmentWalletBinding) = with(binding.lAddress) { + val primaryWallet = state.primaryWallet + if (primaryWallet?.walletAddresses != null && primaryWallet.currency is Currency.Blockchain) { binding.lAddress.root.show() - if (state.shouldShowMultipleAddress()) { + if (primaryWallet.shouldShowMultipleAddress()) { (binding.lAddress.root as? ViewGroup)?.beginDelayedTransition() chipGroupAddressType.show() chipGroupAddressType.fitChipsByGroupWidth() - val checkedId = MultipleAddressUiHelper.typeToId(state.walletAddresses.selectedAddress.type) + val checkedId = MultipleAddressUiHelper.typeToId(primaryWallet.walletAddresses.selectedAddress.type) if (checkedId != View.NO_ID) chipGroupAddressType.check(checkedId) chipGroupAddressType.setOnCheckedChangeListener { group, checkedId -> if (checkedId == -1) return@setOnCheckedChangeListener - val type = MultipleAddressUiHelper.idToType(checkedId, state.currency.blockchain) + val type = MultipleAddressUiHelper.idToType(checkedId, primaryWallet.currency.blockchain) type?.let { store.dispatch(WalletAction.ChangeSelectedAddress(type)) } } } else { chipGroupAddressType.hide() } - tvAddress.text = state.walletAddresses.selectedAddress.address + tvAddress.text = primaryWallet.walletAddresses.selectedAddress.address tvExplore.setOnClickListener { store.dispatch( WalletAction.ExploreAddress( - state.walletAddresses.selectedAddress.exploreUrl, + primaryWallet.walletAddresses.selectedAddress.exploreUrl, fragment!!.requireContext(), ), ) } + setupCardInfo(state) } else { binding.lAddress.root.hide() } } + + private fun setupCardInfo(state: WalletState) { + val textView = binding?.lAddress?.tvInfo + val blockchain = state.primaryWallet?.currency?.blockchain + if (textView != null && blockchain != null) { + textView.text = textView.getString( + id = R.string.address_qr_code_message_format, + blockchain.fullName, + blockchain.currency, + blockchain.fullName, + ) + } + } } \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_onboarding_address_info.xml b/app/src/main/res/layout/dialog_onboarding_address_info.xml index ca04440067..eadb8f7f36 100644 --- a/app/src/main/res/layout/dialog_onboarding_address_info.xml +++ b/app/src/main/res/layout/dialog_onboarding_address_info.xml @@ -36,7 +36,7 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/imv_qr_code" - tools:text="@string/address_qr_code_message_token_format" /> + tools:text="Send only Ethereum (ETH) from Ethereum network to this address. Using other tokens and networks may result in loss of funds." /> + + + tools:text="Send only Ethereum (ETH) from Ethereum network to this address. Using other tokens and networks may result in loss of funds." /> diff --git a/core/res/src/main/res/values-de/strings-app.xml b/core/res/src/main/res/values-de/strings-app.xml index 9b09fb053e..bd2e4888dc 100644 --- a/core/res/src/main/res/values-de/strings-app.xml +++ b/core/res/src/main/res/values-de/strings-app.xml @@ -133,8 +133,7 @@ Success! Your card is activated and ready to be used Balance - Send only %s (%s) to this address. Using other tokens and networks may result in loss of funds. - Send only %s (%s) from %s network to this address. Using other tokens and networks may result in loss of funds. + Send only %s (%s) from %s network to this address. Using other tokens and networks may result in loss of funds. If the process of creating the wallet gets interrupted in any way, you\'ll have to start over. The twinning process is partly complete. You can\'t exit it now. OK, ich hab\'s! diff --git a/core/res/src/main/res/values-fr/strings-app.xml b/core/res/src/main/res/values-fr/strings-app.xml index 8d7d037a69..3d926e7f7b 100644 --- a/core/res/src/main/res/values-fr/strings-app.xml +++ b/core/res/src/main/res/values-fr/strings-app.xml @@ -133,8 +133,7 @@ Success! Your card is activated and ready to be used Balance - Send only %s (%s) to this address. Using other tokens and networks may result in loss of funds. - Send only %s (%s) from %s network to this address. Using other tokens and networks may result in loss of funds. + Send only %s (%s) from %s network to this address. Using other tokens and networks may result in loss of funds. If the process of creating the wallet gets interrupted in any way, you\'ll have to start over. The twinning process is partly complete. You can\'t exit it now. Ok, je l\'ai! diff --git a/core/res/src/main/res/values-it/strings-app.xml b/core/res/src/main/res/values-it/strings-app.xml index c5e3134366..aa4147d4ba 100644 --- a/core/res/src/main/res/values-it/strings-app.xml +++ b/core/res/src/main/res/values-it/strings-app.xml @@ -133,8 +133,7 @@ Success! Your card is activated and ready to be used Balance - Send only %s (%s) to this address. Using other tokens and networks may result in loss of funds. - Send only %s (%s) from %s network to this address. Using other tokens and networks may result in loss of funds. + Send only %s (%s) from %s network to this address. Using other tokens and networks may result in loss of funds. If the process of creating the wallet gets interrupted in any way, you\'ll have to start over. The twinning process is partly complete. You can\'t exit it now. Ok, ho capito! diff --git a/core/res/src/main/res/values-ru/strings-app.xml b/core/res/src/main/res/values-ru/strings-app.xml index 34b9be72db..142d4e305f 100644 --- a/core/res/src/main/res/values-ru/strings-app.xml +++ b/core/res/src/main/res/values-ru/strings-app.xml @@ -133,8 +133,7 @@ Успешно! Ваша карта активирована и готова к использованию Баланс - Отправляйте только %s (%s) на этот адрес. Иначе это может привести к утрате средств. - Отправляйте только %s (%s) из сети %s на этот адрес. Иначе это может привести к утрате средств. + Отправляйте только %s (%s) в сети %s на этот адрес. Использование другой сети может привести к утрате средств. Если процесc создания кошелька каким-либо образом прервется, вам придется начинать сначала. Процесс связывания карт частично завершен. Вы не можете выйти из него сейчас. Понятно! diff --git a/core/res/src/main/res/values/strings-app.xml b/core/res/src/main/res/values/strings-app.xml index 4d8976d15d..80bfd3967b 100644 --- a/core/res/src/main/res/values/strings-app.xml +++ b/core/res/src/main/res/values/strings-app.xml @@ -133,8 +133,7 @@ Success! Your card is activated and ready to be used Balance - Send only %s (%s) to this address. Using other tokens and networks may result in loss of funds. - Send only %s (%s) from %s network to this address. Using other tokens and networks may result in loss of funds. + Send only %s (%s) from %s network to this address. Using other tokens and networks may result in loss of funds. If the process of creating the wallet gets interrupted in any way, you\'ll have to start over. The twinning process is partly complete. You can\'t exit it now. Ok, Got it! From c320f58ded1cbfc5e8ce250457f4011194233790 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 28 Dec 2022 18:25:38 +0300 Subject: [PATCH 11/19] Updated on 2026-08-14 --- .../BiometricUserWalletsListManager.kt | 2 +- .../repository/UserWalletsKeysRepository.kt | 6 ++++++ .../UserWalletsPublicInformationRepository.kt | 2 -- .../BiometricUserWalletsKeysRepository.kt | 7 +++++++ .../DefaultUserWalletsPublicInformationRepository.kt | 4 ---- .../tap/features/details/redux/DetailsMiddleware.kt | 12 +++++++++--- .../tap/features/details/redux/DetailsReducer.kt | 3 +-- 7 files changed, 24 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt index f7781ca770..fdd95f5f63 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt @@ -51,7 +51,7 @@ internal class BiometricUserWalletsListManager( get() = state.value.isLocked override val hasSavedUserWallets: Boolean - get() = publicInformationRepository.isNotEmpty() + get() = keysRepository.hasSavedEncryptionKeys() override suspend fun unlockWithBiometry(): CompletionResult { return unlockWithBiometryInternal() diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsKeysRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsKeysRepository.kt index f10e0beeb5..bf96081cd4 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsKeysRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsKeysRepository.kt @@ -32,4 +32,10 @@ internal interface UserWalletsKeysRepository { * @return [CompletionResult] of operation * */ suspend fun clear(): CompletionResult + + /** + * Determine if the user has saved user wallets + * @return [Boolean] true if user has saved wallets + * */ + fun hasSavedEncryptionKeys(): Boolean } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsPublicInformationRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsPublicInformationRepository.kt index f0387d3f0e..8765a6b804 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsPublicInformationRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsPublicInformationRepository.kt @@ -12,6 +12,4 @@ internal interface UserWalletsPublicInformationRepository { suspend fun delete(walletIds: List): CompletionResult suspend fun clear(): CompletionResult - - fun isNotEmpty(): Boolean } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/BiometricUserWalletsKeysRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/BiometricUserWalletsKeysRepository.kt index 5e57d10474..8de5a59457 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/BiometricUserWalletsKeysRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/BiometricUserWalletsKeysRepository.kt @@ -17,6 +17,7 @@ import com.tangem.tap.domain.userWalletList.UserWalletListError import com.tangem.tap.domain.userWalletList.model.UserWalletEncryptionKey import com.tangem.tap.domain.userWalletList.repository.UserWalletsKeysRepository import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext internal class BiometricUserWalletsKeysRepository( @@ -77,6 +78,12 @@ internal class BiometricUserWalletsKeysRepository( } } + override fun hasSavedEncryptionKeys(): Boolean { + return runBlocking { + getUserWalletsIds().isNotEmpty() + } + } + private suspend fun getAllInternal(): CompletionResult> { return getUserWalletsIds() .map { userWalletId -> diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsPublicInformationRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsPublicInformationRepository.kt index 46a016f8c0..7d1bd9333b 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsPublicInformationRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsPublicInformationRepository.kt @@ -72,10 +72,6 @@ internal class DefaultUserWalletsPublicInformationRepository( } } - override fun isNotEmpty(): Boolean { - return secureStorage.get(StorageKey.UserWalletPublicInformation.name)?.isNotEmpty() == true - } - @JvmName("saveWithPublicInformation") private suspend fun save( publicInformation: List, diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index 319071642c..a170aebdfd 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -278,9 +278,6 @@ class DetailsMiddleware { val userWallet = UserWalletBuilder(scanResponse).build() userWalletsListManager.save(userWallet) - .doOnFailure { error -> - Timber.e(error, "Wallet saving failed") - } .doOnSuccess { Analytics.send(Settings.AppSettings.SaveWalletSwitcherChanged(AnalyticsParam.OnOffState.On)) @@ -296,6 +293,9 @@ class DetailsMiddleware { store.onUserWalletSelected(userWallet) } + .doOnFailure { error -> + Timber.e(error, "Unable to save user wallet") + } } private suspend fun deleteSavedWallets() { @@ -315,6 +315,9 @@ class DetailsMiddleware { store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Home)) } + .doOnFailure { error -> + Timber.e(error, "Unable to delete saved wallets") + } } private fun saveAccessCodes(state: DetailsState) { @@ -353,6 +356,9 @@ class DetailsMiddleware { ) } } + .doOnFailure { error -> + Timber.e(error, "Unable to delete saved access codes") + } } } } \ No newline at end of file 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 f00f0b46b4..11b737097a 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 @@ -11,7 +11,6 @@ import com.tangem.tap.domain.extensions.signedHashesCount import com.tangem.tap.preferencesStorage import com.tangem.tap.store import com.tangem.tap.tangemSdkManager -import com.tangem.tap.userWalletsListManager import org.rekotlin.Action import java.util.* @@ -57,7 +56,7 @@ private fun handlePrepareScreen( createBackupAllowed = action.scanResponse.card.backupStatus == CardDTO.BackupStatus.NoBackup, appCurrency = store.state.globalState.appCurrency, isBiometricsAvailable = tangemSdkManager.canUseBiometry, - saveWallets = userWalletsListManager.hasSavedUserWallets, + saveWallets = preferencesStorage.shouldSaveUserWallets, saveAccessCodes = preferencesStorage.shouldSaveAccessCodes, ) } From c48e7204eb3919864b482c993c2b30eb238f5cfd Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 29 Dec 2022 14:00:54 +0300 Subject: [PATCH 12/19] Updated on 2026-08-14 --- .../userWalletList/UserWalletsListManager.kt | 13 +++- .../BiometricUserWalletsListManager.kt | 71 ++++++++++++++----- .../DummyUserWalletsListManager.kt | 56 --------------- .../model/UserWalletEncryptionKey.kt | 7 -- .../repository/UserWalletsKeysRepository.kt | 6 +- ...erWalletsSensitiveInformationRepository.kt | 2 +- .../BiometricUserWalletsKeysRepository.kt | 5 +- ...erWalletsSensitiveInformationRepository.kt | 5 +- .../utils/UserWalletEncyptionKeyCalculator.kt | 11 +-- .../features/tokens/redux/TokensMiddleware.kt | 15 ++-- .../middlewares/MultiWalletMiddleware.kt | 19 ++--- .../redux/WalletSelectorMiddleware.kt | 4 +- .../ui/WalletSelectorViewModel.kt | 20 ++---- 13 files changed, 104 insertions(+), 130 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/DummyUserWalletsListManager.kt diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManager.kt index dfd62c05f5..9e7619e7c5 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManager.kt @@ -19,7 +19,7 @@ interface UserWalletsListManager { suspend fun selectWallet(userWalletId: UserWalletId): CompletionResult /** - * Save user wallet + * Save provided user wallet and set it as selected * @param userWallet [UserWallet] to save * @param canOverride If false, then terminate with [UserWalletListError.WalletAlreadySaved] when user tries to save an * already saved card @@ -27,6 +27,17 @@ interface UserWalletsListManager { * */ suspend fun save(userWallet: UserWallet, canOverride: Boolean = false): CompletionResult + /** + * Same as [save] but not change selected user wallet ID + * and not terminate with [UserWalletListError.WalletAlreadySaved] if [UserWallet] already saved + * + * Can terminate with [NoSuchElementException] if unable to find [UserWallet] with provided [UserWalletId] + * @param userWalletId update [UserWallet] with that [UserWalletId] + * @param update lambda that receives stored [UserWallet] and returns updated [UserWallet] + * @return [CompletionResult] of operation with updated [UserWallet] + * */ + suspend fun update(userWalletId: UserWalletId, update: (UserWallet) -> UserWallet): CompletionResult + suspend fun delete(userWalletIds: List): CompletionResult suspend fun clear(): CompletionResult diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt index 4eef3db4b7..db1db2ebbd 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt @@ -10,6 +10,7 @@ import com.tangem.tap.domain.userWalletList.repository.SelectedUserWalletReposit import com.tangem.tap.domain.userWalletList.repository.UserWalletsKeysRepository import com.tangem.tap.domain.userWalletList.repository.UserWalletsPublicInformationRepository import com.tangem.tap.domain.userWalletList.repository.UserWalletsSensitiveInformationRepository +import com.tangem.tap.domain.userWalletList.utils.encryptionKey import com.tangem.tap.domain.userWalletList.utils.toUserWallets import com.tangem.tap.domain.userWalletList.utils.updateWith import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -84,7 +85,7 @@ internal class BiometricUserWalletsListManager( override suspend fun save(userWallet: UserWallet, canOverride: Boolean): CompletionResult { return if (canOverride) { - saveInternal(userWallet) + saveInternal(userWallet, changeSelectedUserWallet = true) } else { val isWalletSaved = state.value.userWallets .any { @@ -94,11 +95,25 @@ internal class BiometricUserWalletsListManager( if (isWalletSaved) { CompletionResult.Failure(UserWalletListError.WalletAlreadySaved) } else { - saveInternal(userWallet) + saveInternal(userWallet, changeSelectedUserWallet = true) } } } + override suspend fun update( + userWalletId: UserWalletId, + update: (UserWallet) -> UserWallet, + ): CompletionResult { + return get(userWalletId) + .map { storedUserWallet -> + update(storedUserWallet) + } + .flatMap { updatedUserWallet -> + saveInternal(updatedUserWallet, changeSelectedUserWallet = false) + .map { updatedUserWallet } + } + } + override suspend fun delete(userWalletIds: List): CompletionResult { if (userWalletIds.isEmpty()) { return CompletionResult.Success(Unit) @@ -111,9 +126,12 @@ internal class BiometricUserWalletsListManager( .flatMap { keysRepository.delete(userWalletIds) } .map { state.update { prevState -> + val newUserWallets = prevState.userWallets.filter { it.walletId !in userWalletIds } + prevState.copy( encryptionKeys = prevState.encryptionKeys.filter { it.walletId !in userWalletIds }, - userWallets = prevState.userWallets.filter { it.walletId !in userWalletIds }, + userWallets = newUserWallets, + isLocked = newUserWallets.any { it.isLocked }, ) } } @@ -135,27 +153,23 @@ internal class BiometricUserWalletsListManager( } } - private suspend fun saveInternal(userWallet: UserWallet): CompletionResult { - val newEncryptionKeys = state.value.encryptionKeys - .plus(UserWalletEncryptionKey(userWallet)) - .distinctBy { it.walletId } - - return keysRepository.store(newEncryptionKeys) - .doOnSuccess { - state.update { prevState -> - prevState.copy( - encryptionKeys = newEncryptionKeys, - selectedUserWalletId = userWallet.walletId, - ) - } - } + private suspend fun saveInternal( + userWallet: UserWallet, + changeSelectedUserWallet: Boolean, + ): CompletionResult { + return saveEncryptionKeyIfNotNull(userWallet) + .flatMap { sensitiveInformationRepository.save(userWallet, encryptionKey = it) } .flatMap { publicInformationRepository.save(userWallet) } - .flatMap { sensitiveInformationRepository.save(userWallet) } .map { selectedUserWalletRepository.set(userWallet.walletId) } .flatMap { loadModels() } .doOnSuccess { state.update { prevState -> prevState.copy( + selectedUserWalletId = if (changeSelectedUserWallet) { + userWallet.walletId + } else { + prevState.selectedUserWalletId + }, isLocked = prevState.userWallets.any { it.isLocked }, ) } @@ -181,6 +195,27 @@ internal class BiometricUserWalletsListManager( } } + private suspend fun saveEncryptionKeyIfNotNull(userWallet: UserWallet): CompletionResult { + val encryptionKey = userWallet.scanResponse.card.encryptionKey + ?.let { UserWalletEncryptionKey(userWallet.walletId, it) } + + return if (encryptionKey != null) { + keysRepository.save(encryptionKey) + .doOnSuccess { + state.update { prevState -> + prevState.copy( + encryptionKeys = prevState.encryptionKeys + .plus(encryptionKey) + .distinctBy { it.walletId }, + ) + } + } + .map { encryptionKey.encryptionKey } + } else { + CompletionResult.Success(data = null) + } + } + private suspend fun loadModels(): CompletionResult { return getSavedUserWallets() .map { userWallets -> diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/DummyUserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/DummyUserWalletsListManager.kt deleted file mode 100644 index e616c48758..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/DummyUserWalletsListManager.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.tangem.tap.domain.userWalletList.implementation - -import com.tangem.common.CompletionResult -import com.tangem.common.catching -import com.tangem.domain.common.util.UserWalletId -import com.tangem.tap.domain.model.UserWallet -import com.tangem.tap.domain.userWalletList.UserWalletsListManager -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf - -class DummyUserWalletsListManager : UserWalletsListManager { - override val userWallets: Flow> - get() = flowOf(emptyList()) - override val selectedUserWallet: Flow - get() = flowOf() - override val selectedUserWalletSync: UserWallet? - get() = null - override val isLocked: Flow - get() = flowOf(true) - override val isLockedSync: Boolean - get() = true - override val hasSavedUserWallets: Boolean - get() = false - - override suspend fun unlockWithBiometry(): CompletionResult { - return CompletionResult.Success(null) - } - - override fun lock() { - /* no-op */ - } - - override suspend fun selectWallet(userWalletId: UserWalletId): CompletionResult { - return catching { - error("Not implemented") - } - } - - override suspend fun save(userWallet: UserWallet, canOverride: Boolean): CompletionResult { - return CompletionResult.Success(Unit) - } - - override suspend fun delete(userWalletIds: List): CompletionResult { - return CompletionResult.Success(Unit) - } - - override suspend fun clear(): CompletionResult { - return CompletionResult.Success(Unit) - } - - override suspend fun get(userWalletId: UserWalletId): CompletionResult { - return catching { - error("Not implemented") - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletEncryptionKey.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletEncryptionKey.kt index a5c20a7790..df0f473bae 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletEncryptionKey.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletEncryptionKey.kt @@ -2,19 +2,12 @@ package com.tangem.tap.domain.userWalletList.model import com.squareup.moshi.JsonClass import com.tangem.domain.common.util.UserWalletId -import com.tangem.tap.domain.model.UserWallet -import com.tangem.tap.domain.userWalletList.utils.encryptionKey @JsonClass(generateAdapter = true) internal data class UserWalletEncryptionKey( val walletId: UserWalletId, val encryptionKey: ByteArray, ) { - constructor(userWallet: UserWallet) : this( - walletId = userWallet.walletId, - encryptionKey = userWallet.scanResponse.card.encryptionKey, - ) - override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is UserWalletEncryptionKey) return false diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsKeysRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsKeysRepository.kt index bf96081cd4..99b62dc99d 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsKeysRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsKeysRepository.kt @@ -14,11 +14,11 @@ internal interface UserWalletsKeysRepository { suspend fun getAll(): CompletionResult> /** - * Store the encryption keys for user wallets. Biometric authentication not required - * @param encryptionKeys List of encryption keys for user wallets + * Save the encryption key for user wallet. Biometric authentication not required + * @param encryptionKey [UserWalletEncryptionKey] to save * @return [CompletionResult] of operation * */ - suspend fun store(encryptionKeys: List): CompletionResult + suspend fun save(encryptionKey: UserWalletEncryptionKey): CompletionResult /** * Delete encryption keys for user wallets. Biometric authentication not required diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsSensitiveInformationRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsSensitiveInformationRepository.kt index 7e03055150..fdae3e64a0 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsSensitiveInformationRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/UserWalletsSensitiveInformationRepository.kt @@ -7,7 +7,7 @@ import com.tangem.tap.domain.userWalletList.model.UserWalletEncryptionKey import com.tangem.tap.domain.userWalletList.model.UserWalletSensitiveInformation internal interface UserWalletsSensitiveInformationRepository { - suspend fun save(userWallet: UserWallet): CompletionResult + suspend fun save(userWallet: UserWallet, encryptionKey: ByteArray?): CompletionResult suspend fun getAll( encryptionKeys: List, ): CompletionResult> diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/BiometricUserWalletsKeysRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/BiometricUserWalletsKeysRepository.kt index 8de5a59457..11e558535d 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/BiometricUserWalletsKeysRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/BiometricUserWalletsKeysRepository.kt @@ -45,10 +45,9 @@ internal class BiometricUserWalletsKeysRepository( } } - override suspend fun store(encryptionKeys: List): CompletionResult { + override suspend fun save(encryptionKey: UserWalletEncryptionKey): CompletionResult { return withContext(Dispatchers.IO) { - encryptionKeys.map { storeEncryptionKey(it) } - .fold() + storeEncryptionKey(encryptionKey) .mapFailure { error -> UserWalletListError.SaveEncryptionKeysError(error.cause ?: error) } diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt index 158dc0db2b..673ec51a10 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/repository/implementation/DefaultUserWalletsSensitiveInformationRepository.kt @@ -38,11 +38,12 @@ internal class DefaultUserWalletsSensitiveInformationRepository( Cipher.getInstance("$algorithm/$blockMode/$encryptionPadding") } - override suspend fun save(userWallet: UserWallet): CompletionResult { + override suspend fun save(userWallet: UserWallet, encryptionKey: ByteArray?): CompletionResult { + if (encryptionKey == null) return CompletionResult.Success(Unit) // Encryption key is null, do nothing return catching { val encryptedSensitiveInformation = userWallet.sensitiveInformation .encode() - .encryptAndStoreIv(userWallet.walletId.stringValue, userWallet.scanResponse.card.encryptionKey) + .encryptAndStoreIv(userWallet.walletId.stringValue, encryptionKey) getAllEncrypted().toMutableMap() .apply { set(userWallet.walletId.stringValue, encryptedSensitiveInformation) } diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/UserWalletEncyptionKeyCalculator.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/UserWalletEncyptionKeyCalculator.kt index 3ecfb70521..d97af026cc 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/UserWalletEncyptionKeyCalculator.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/UserWalletEncyptionKeyCalculator.kt @@ -4,15 +4,8 @@ import com.tangem.common.extensions.calculateSha256 import com.tangem.domain.common.CardDTO import com.tangem.domain.common.extensions.calculateHmacSha256 -internal val CardDTO.encryptionKey: ByteArray - @Throws(IllegalArgumentException::class) - get() { - val walletPublicKey = requireNotNull(findPublicKey(wallets)) { - "Wallet public key must not be null" - } - - return calculateEncryptionKey(walletPublicKey) - } +internal val CardDTO.encryptionKey: ByteArray? + get() = findPublicKey(wallets)?.let { calculateEncryptionKey(it) } private fun calculateEncryptionKey(publicKey: ByteArray): ByteArray { val message = MESSAGE_FOR_ENCRYPTION_KEY.toByteArray() 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 b07a4fd3ca..10a7d4e03a 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 @@ -281,13 +281,16 @@ class TokensMiddleware { ) { val selectedUserWallet = userWalletsListManager.selectedUserWalletSync if (selectedUserWallet != null) { - val updatedUserWallet = selectedUserWallet.copy( - scanResponse = scanResponse, - ) - scope.launch { - userWalletsListManager.save(updatedUserWallet, canOverride = true) - .flatMap { + userWalletsListManager.update( + userWalletId = selectedUserWallet.walletId, + update = { userWallet -> + userWallet.copy( + scanResponse = scanResponse, + ) + }, + ) + .flatMap { updatedUserWallet -> walletCurrenciesManager.addCurrencies( userWallet = updatedUserWallet, currenciesToAdd = currencyList, 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 9bba0011a5..821f4971b4 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 @@ -179,21 +179,24 @@ class MultiWalletMiddleware { } private fun scanAndUpdateCard( - selectedWallet: UserWallet, + selectedUserWallet: UserWallet, state: WalletState?, ) = scope.launch { Analytics.send(MainScreen.CardWasScanned()) ScanCardProcessor.scan( - cardId = selectedWallet.cardId, + cardId = selectedUserWallet.cardId, additionalBlockchainsToDerive = state?.missingDerivations?.map { it.blockchain }, ) { scanResponse -> - val userWallet = selectedWallet.copy( - scanResponse = scanResponse, + userWalletsListManager.update( + userWalletId = selectedUserWallet.walletId, + update = { userWallet -> + userWallet.copy( + scanResponse = scanResponse, + ) + }, ) - - userWalletsListManager.save(userWallet, canOverride = true) - .doOnSuccess { - store.state.globalState.tapWalletManager.loadData(userWallet, refresh = true) + .doOnSuccess { updatedUserWallet -> + store.state.globalState.tapWalletManager.loadData(updatedUserWallet, refresh = true) } } } diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt index c1f24294f4..4772b501d7 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt @@ -239,9 +239,7 @@ internal class WalletSelectorMiddleware { Analytics.send(MyWallets.Button.EditWalletTapped) scope.launch { - userWalletsListManager.get(userWalletId) - .map { it.copy(name = newName) } - .flatMap { userWalletsListManager.save(it, canOverride = true) } + userWalletsListManager.update(userWalletId) { it.copy(name = newName) } .doOnFailure { error -> store.dispatchOnMain(WalletSelectorAction.HandleError(error)) } diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt index 1192b37c4a..52a99013e3 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt @@ -38,7 +38,6 @@ internal class WalletSelectorViewModel : ViewModel(), StoreSubscriber Unit editingUserWalletsIds.isNotEmpty() && !editingUserWalletsIds.contains(userWalletId) -> { editWallet(userWalletId) } @@ -52,7 +51,7 @@ internal class WalletSelectorViewModel : ViewModel(), StoreSubscriber - store.dispatch(WalletSelectorAction.RenameWallet(editedWalletId, newName)) + store.dispatch(WalletSelectorAction.RenameWallet(editedUserWalletId, newName)) stateInternal.update { prevState -> prevState.copy( renameWalletDialog = null, @@ -137,11 +136,6 @@ internal class WalletSelectorViewModel : ViewModel(), StoreSubscriber appState.skip { old, new -> old.walletSelectorState == new.walletSelectorState } From 0263ee0a28a71d21f7a3c8d817434560cd15e474 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 28 Dec 2022 21:19:13 +0300 Subject: [PATCH 13/19] Updated on 2026-08-14 --- .../DefaultWalletCurrenciesManager.kt | 11 +- .../repository/WalletAmountsRepository.kt | 6 + .../DefaultWalletAmountsRepository.kt | 165 ++++++++++-------- .../utils/WalletStoreOperations.kt | 6 +- .../middlewares/MultiWalletMiddleware.kt | 4 +- 5 files changed, 117 insertions(+), 75 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt index 5fd2e25234..e000fe1c6d 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt @@ -20,6 +20,7 @@ import com.tangem.tap.domain.walletStores.repository.WalletStoresRepository import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.toBlockchainNetworks import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.withContext internal class DefaultWalletCurrenciesManager( @@ -64,7 +65,15 @@ internal class DefaultWalletCurrenciesManager( saveUserCurrencies(card, newCurrencies) } .flatMap { - walletAmountsRepository.updateAmountsForUserWallet( + val updatedBlockchains = updatedBlockchainNetworks + .map { it.blockchain } + val updatedWalletStores = walletStoresRepository.get(userWallet.walletId) + .firstOrNull() + ?.filter { it.blockchain in updatedBlockchains } + ?: return@flatMap CompletionResult.Success(Unit) + + walletAmountsRepository.updateAmountsForWalletStores( + walletStores = updatedWalletStores, userWallet = userWallet, fiatCurrency = appCurrencyProvider(), ) diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletAmountsRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletAmountsRepository.kt index 0af5b8f85e..a054ed0ff2 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletAmountsRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/WalletAmountsRepository.kt @@ -29,6 +29,12 @@ interface WalletAmountsRepository { fiatCurrency: FiatCurrency, ): CompletionResult + suspend fun updateAmountsForWalletStores( + walletStores: List, + userWallet: UserWallet, + fiatCurrency: FiatCurrency, + ): CompletionResult + /** * Fetch wallet amounts and fiat rates then update [com.tangem.tap.domain.walletStores.storage.WalletStoresStorage] * and [com.tangem.tap.domain.walletStores.storage.WalletManagerStorage] with new data diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt index 640c08fe67..444d6fc480 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/DefaultWalletAmountsRepository.kt @@ -41,7 +41,8 @@ import com.tangem.tap.network.NetworkConnectivity import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.flow.first +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.withContext import timber.log.Timber import java.math.BigDecimal @@ -60,7 +61,7 @@ internal class DefaultWalletAmountsRepository( else withContext(Dispatchers.Default) { awaitAll( async { fetchAmountsForUserWallets(userWallets) }, - async { fetchFiatRates(userWallets, fiatCurrency) }, + async { fetchFiatRates(userWallets, walletStores = null, fiatCurrency) }, ) .fold() } @@ -73,46 +74,40 @@ internal class DefaultWalletAmountsRepository( return updateAmountsForUserWallets(listOf(userWallet), fiatCurrency) } + override suspend fun updateAmountsForWalletStores( + walletStores: List, + userWallet: UserWallet, + fiatCurrency: FiatCurrency, + ): CompletionResult { + return if (walletStores.isEmpty()) CompletionResult.Success(Unit) + else withContext(Dispatchers.Default) { + val userWalletId = userWallet.walletId + val scanResponse = userWallet.scanResponse + + awaitAll( + async { fetchAmountForWalletStores(userWalletId, scanResponse, walletStores) }, + async { fetchFiatRates(listOf(userWallet), walletStores, fiatCurrency) }, + ) + .fold() + } + } + override suspend fun updateAmountsForWalletStore( walletStore: WalletStoreModel, userWallet: UserWallet, fiatCurrency: FiatCurrency, - ): CompletionResult = withContext(Dispatchers.Default) { - val walletId = userWallet.walletId - val scanResponse = userWallet.scanResponse - - awaitAll( - async { - // TODO: Find wallet manager via [com.tangem.tap.domain.walletStores.repository.WalletManagersRepository] - val walletManager = walletStore.walletManager - fetchAmountsForWalletStore(walletId, scanResponse, walletStore, walletManager) - }, - async { fetchFiatRates(listOf(userWallet), fiatCurrency) }, - ) - .fold() - } - - private suspend fun fetchAmountsForUserWallets( - userWallets: List, - ): CompletionResult = withContext(Dispatchers.Default) { - userWallets.map { async { fetchAmountsForUserWallet(it) } } - .awaitAll() - .fold() + ): CompletionResult { + return updateAmountsForWalletStores(listOf(walletStore), userWallet, fiatCurrency) } private suspend fun fetchFiatRates( userWallets: List, + walletStores: List?, fiatCurrency: FiatCurrency, ): CompletionResult { - val walletsIds = userWallets.map { it.walletId } - val walletStores = walletsIds - .flatMap { - walletStoresStorage.getAll() - .first() - .getOrElse(it) { emptyList() } - } + val walletStoresInternal = walletStores ?: getWalletStores(userWallets) - val currencies = walletStores + val currencies = walletStoresInternal .asSequence() .flatMap { it.walletsData } .map { it.currency } @@ -129,7 +124,7 @@ internal class DefaultWalletAmountsRepository( return when (fiatRatesResult) { is Result.Success -> { updateWalletStoresWithFiatRates( - walletStores = walletStores, + walletStores = walletStoresInternal, fiatRates = fiatRatesResult.data.rates, ) @@ -145,7 +140,6 @@ internal class DefaultWalletAmountsRepository( error, """ Unable to fetch fiat rates - |- User wallets ids: $walletsIds |- Coins ids: $coinsIds """.trimIndent(), ) @@ -155,20 +149,34 @@ internal class DefaultWalletAmountsRepository( } } + private suspend fun fetchAmountsForUserWallets( + userWallets: List, + ): CompletionResult = withContext(Dispatchers.Default) { + userWallets.map { async { fetchAmountsForUserWallet(it) } } + .awaitAll() + .fold() + } + private suspend fun fetchAmountsForUserWallet( userWallet: UserWallet, ): CompletionResult = withContext(Dispatchers.Default) { - val walletId = userWallet.walletId + val userWalletId = userWallet.walletId val scanResponse = userWallet.scanResponse - val walletStores = walletStoresStorage.getAll() - .first() - .getOrElse(walletId) { emptyList() } + val walletStores = getWalletStores(listOf(userWallet)) + fetchAmountForWalletStores(userWalletId, scanResponse, walletStores) + } + + private suspend fun fetchAmountForWalletStores( + userWalletId: UserWalletId, + scanResponse: ScanResponse, + walletStores: List, + ): CompletionResult = coroutineScope { walletStores.map { walletStore -> async { // TODO: Find wallet manager via [com.tangem.tap.domain.walletStores.repository.WalletManagersRepository] val walletManager = walletStore.walletManager - fetchAmountsForWalletStore(walletId, scanResponse, walletStore, walletManager) + fetchAmountsForWalletStore(userWalletId, scanResponse, walletStore, walletManager) } } .awaitAll() @@ -176,7 +184,7 @@ internal class DefaultWalletAmountsRepository( } private suspend fun fetchAmountsForWalletStore( - walletId: UserWalletId, + userWalletId: UserWalletId, scanResponse: ScanResponse, walletStore: WalletStoreModel, walletManager: WalletManager?, @@ -186,11 +194,15 @@ internal class DefaultWalletAmountsRepository( } return when { - hasMissedDerivations -> updateWalletStoreWithMissedDerivation(walletStore) - walletManager == null -> updateWalletStoreWithUnreachable(walletStore) + hasMissedDerivations -> { + updateWalletStoreWithMissedDerivation(walletStore) + } + walletManager == null -> { + updateWalletStoreWithUnreachable(walletStore) + } else -> { withInternetConnection { walletManager.update() } - .map { updateWalletManagerWithAmounts(walletId, walletManager) } + .map { updateWalletManagerWithAmounts(userWalletId, walletManager) } .flatMap { updateWalletStoreWithAmounts( walletStore = walletStore, @@ -248,35 +260,6 @@ internal class DefaultWalletAmountsRepository( return CompletionResult.Success(Unit) } - private suspend inline fun withInternetConnection(crossinline block: suspend () -> Unit): CompletionResult { - return if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) { - val error = WalletStoresError.NoInternetConnection - Timber.e(error) - CompletionResult.Failure(error) - } else withContext(Dispatchers.IO) { - catching { block() } - } - } - - private suspend fun updateWalletManagerWithAmounts( - walletId: UserWalletId, - walletManager: WalletManager, - ) = withContext(Dispatchers.Default) { - walletManagersStorage.update { prevManagers -> - val newManagersForUserWallet = prevManagers[walletId].orEmpty() - .toMutableList() - .apply { - replaceByOrAdd(walletManager) { - it.wallet.blockchain == it.wallet.blockchain - } - } - - prevManagers.apply { - set(walletId, newManagersForUserWallet) - } - } - } - private suspend fun updateWalletStoreWithError( walletStore: WalletStoreModel, wallet: Wallet, @@ -425,4 +408,44 @@ internal class DefaultWalletAmountsRepository( } } } + + private suspend inline fun withInternetConnection(crossinline block: suspend () -> Unit): CompletionResult { + return if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) { + val error = WalletStoresError.NoInternetConnection + Timber.e(error) + CompletionResult.Failure(error) + } else withContext(Dispatchers.IO) { + catching { block() } + } + } + + private suspend fun updateWalletManagerWithAmounts( + userWalletId: UserWalletId, + walletManager: WalletManager, + ) = withContext(Dispatchers.Default) { + walletManagersStorage.update { prevManagers -> + val newManagersForUserWallet = prevManagers[userWalletId].orEmpty() + .toMutableList() + .apply { + replaceByOrAdd(walletManager) { + it.wallet.blockchain == it.wallet.blockchain + } + } + + prevManagers.apply { + set(userWalletId, newManagersForUserWallet) + } + } + } + + private suspend fun getWalletStores(userWallets: List): List { + return userWallets + .map { it.walletId } + .flatMap { userWalletId -> + walletStoresStorage.getAll() + .firstOrNull() + ?.get(userWalletId) + .orEmpty() + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt index 445ff655f2..2aa7ffcf2d 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt @@ -62,9 +62,11 @@ internal fun WalletStoreModel.updateWithSelf( ): WalletStoreModel { val oldStore = this return oldStore.copy( - walletManager = newWalletStore.walletManager, - walletRent = newWalletStore.walletRent, + derivationPath = newWalletStore.derivationPath, walletsData = oldStore.walletsData.updateWithSelf(newWalletStore.walletsData), + walletRent = newWalletStore.walletRent, + blockchainNetwork = newWalletStore.blockchainNetwork, + walletManager = newWalletStore.walletManager, ) } 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 821f4971b4..ba82d17ccd 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 @@ -12,6 +12,7 @@ import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.analytics.events.Token.ButtonRemoveToken import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchErrorNotification +import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.global.GlobalState @@ -181,7 +182,7 @@ class MultiWalletMiddleware { private fun scanAndUpdateCard( selectedUserWallet: UserWallet, state: WalletState?, - ) = scope.launch { + ) = scope.launch(Dispatchers.Default) { Analytics.send(MainScreen.CardWasScanned()) ScanCardProcessor.scan( cardId = selectedUserWallet.cardId, @@ -196,6 +197,7 @@ class MultiWalletMiddleware { }, ) .doOnSuccess { updatedUserWallet -> + store.dispatchOnMain(WalletAction.MultiWallet.AddMissingDerivations(emptyList())) store.state.globalState.tapWalletManager.loadData(updatedUserWallet, refresh = true) } } From 0155e3c7420238e4cedd3e440bcd2751a8193fe0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 30 Dec 2022 14:33:08 +0400 Subject: [PATCH 14/19] Updated on 2026-08-14 --- .../com/tangem/tap/features/tokens/redux/TokensMiddleware.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 10a7d4e03a..af6ab1607f 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 @@ -149,7 +149,7 @@ class TokensMiddleware { && blockchainsToAdd.isEmpty() && blockchainsToRemove.isEmpty() ) { store.dispatchDebugErrorNotification("Nothing to save") - store.dispatch(NavigationAction.PopBackTo()) + store.dispatchOnMain(NavigationAction.PopBackTo()) return@launch } From 1f6d1fd2bd70b417ccf5947b078479565842a1b0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 13 Dec 2022 12:28:17 +0300 Subject: [PATCH 15/19] Updated on 2026-08-14 --- .../wallet/ui/dialogs/ScanFailsDialog.kt | 2 +- .../{strings-app.xml => strings.xml} | 229 ++++++++++++++++- .../src/main/res/values-de/strings_final.xml | 233 ------------------ ..._plurals_final.xml => strings_plurals.xml} | 0 .../{strings-app.xml => strings.xml} | 229 ++++++++++++++++- .../src/main/res/values-fr/strings_final.xml | 233 ------------------ ..._plurals_final.xml => strings_plurals.xml} | 0 .../{strings-app.xml => strings.xml} | 229 ++++++++++++++++- .../src/main/res/values-it/strings_final.xml | 233 ------------------ .../{strings-app.xml => strings.xml} | 227 ++++++++++++++++- .../src/main/res/values-ru/strings_final.xml | 233 ------------------ .../values/{strings-app.xml => strings.xml} | 231 ++++++++++++++++- .../res/src/main/res/values/strings_final.xml | 233 ------------------ ..._plurals_final.xml => strings_plurals.xml} | 0 14 files changed, 1131 insertions(+), 1181 deletions(-) rename core/res/src/main/res/values-de/{strings-app.xml => strings.xml} (51%) delete mode 100644 core/res/src/main/res/values-de/strings_final.xml rename core/res/src/main/res/values-de/{strings_plurals_final.xml => strings_plurals.xml} (100%) rename core/res/src/main/res/values-fr/{strings-app.xml => strings.xml} (51%) delete mode 100644 core/res/src/main/res/values-fr/strings_final.xml rename core/res/src/main/res/values-fr/{strings_plurals_final.xml => strings_plurals.xml} (100%) rename core/res/src/main/res/values-it/{strings-app.xml => strings.xml} (51%) delete mode 100644 core/res/src/main/res/values-it/strings_final.xml rename core/res/src/main/res/values-ru/{strings-app.xml => strings.xml} (51%) delete mode 100644 core/res/src/main/res/values-ru/strings_final.xml rename core/res/src/main/res/values/{strings-app.xml => strings.xml} (51%) delete mode 100644 core/res/src/main/res/values/strings_final.xml rename core/res/src/main/res/values/{strings_plurals_final.xml => strings_plurals.xml} (100%) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt index d3bc64fa17..cef955c28e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ScanFailsDialog.kt @@ -24,7 +24,7 @@ class ScanFailsDialog { Analytics.send(IntroductionProcess.ButtonRequestSupport()) store.dispatch(GlobalAction.SendEmail(ScanFailsEmail())) } - setNeutralButton(R.string.alert_troubleshooting_scan_card_ok) { _, _ -> } + setNeutralButton(R.string.common_cancel) { _, _ -> } setOnDismissListener { store.dispatchDialogHide() } }.create() } diff --git a/core/res/src/main/res/values-de/strings-app.xml b/core/res/src/main/res/values-de/strings.xml similarity index 51% rename from core/res/src/main/res/values-de/strings-app.xml rename to core/res/src/main/res/values-de/strings.xml index bd2e4888dc..9f2035db71 100644 --- a/core/res/src/main/res/values-de/strings-app.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -1,5 +1,223 @@ - + + Tangem Wallet + 3 cards + 2 cards + Shipping + Free + I have a promo code… + Total + Other payment methods + Buy now + Meet\nTangem + Buy + Store + Send + Pay + Exchange + Lend + Borrow + Revolutionary Hardware Wallet + Store your crypto assets secure while keeping private keys contained in your card + Ultra Secure Backup + Up to + 3 physical cards + to one wallet + Thousands of Currencies + A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card + DeFi Compatible + Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services + The Wallet for Everyone + Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. + Order + Search tokens + You are currently running in Demo mode. All funds are not real. + This feature is disabled in Demo mode + Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. + Available networks + %s network not found. Please, add it first and try again. + Attention + Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. + Tokens in Solana network are not supported by this card due to firmware limitation. + Contract address copied! + Contract address + Required field + Please select the network + Decimal number must be a valid integer, no higher than %d + Contract address is invalid + Derivation path is invalid + Note that tokens can be created by anyone. Be aware of adding scam tokens, they can cost nothing. + This token/network has already been added to your list + Decimals + Network + Not selected + E.g. USD Coin + Name + E.g. USDC + Token symbol + BIP44 coin type + Default + The server is not available, please try again later + Total balance + The amount does not include some of your funds + Tokens + Manage tokens + No rate + Network is unreachable + Hide token + Hide %s + Hide + You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. + Unable to hide %s + The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. + Your wallet has not been backed up + To protect your assets, we advise you to carry out this procedure + Erneut versuchen + Chat + %s network + I understand + Yes + No + Russian bank cards are not accepted at the moment + Do you have a bank card of another country or a UnionPay card? + This network is not supported. Please select another network. + Card Settings + Security Mode + Change Access Code + Access code will be changed on this card only + Continue + Tangem Bot + Get your card ready! + Scan the card to change its settings. The changes will impact only the card you\'ve scanned and will not affect other cards tied to your wallet. + Scan Card + App Settings + Keep the wallet in the app + Enable to link all the wallets to Tangem app. Biometric authentication will be required for unlocking the app. Transaction signing requires tapping your Tangem card. + Save Access Code + Biometric authentication will be requested instead of the access code for interactions with your card. + Removing the saved card deletes all the saved wallets and their access codes. + This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. + WalletConnect + Connect to Dapps + This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + I understand that after performing this action, I will no longer have access to the current wallet + Reset the Card + Reset to Factory Settings + Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + Select network + Scan your card + To access all the networks you need to scan the card + Connection with this Dapp cannot be established due to its technical implementation. + Welcome back! + Use %s or scan a card to access the app + Log in with %s + Karte scannen + Access the app + Log into the app and check your balance without scanning the card + Access code + Note that making a transaction with your funds will still require your card + My Wallets + Multi-currency + Single-currency + Add new wallet + Rename Wallet + Wallet name + Unlock all with %s + Invalid Tag. It won\'t be added to the transaction. + Invalid Memo. It won\'t be added to the transaction. + Tag + Memo + Attention + Tap the card with the visa logo + No funds for activation + Please contact support + Four identical digits isn\'t safe + Such a PIN can be brute-forced easily + Pin code + Connect + KYC + Verify your identity + Set PIN code + Register + Verify via Utorg + Refresh + Connect your card + Verify your identity + KYC is in progress + Connect your card to the decentralized payment system + To start using your card you have to pass the KYC process + Please wait until the verification is completed. You\'ll be notified via email. Usually it takes up to 1 hour. You can close the app and come back later. + PIN Code + Set PIN code for your SaltPay card + Chat with support + Please hold the card until the operation complete + To start the backup process you have to add Tangem card as your backup + No backup card + Backup card ready + Finalize the backup process by creating an access code + Prepare the SaltPay card + Tap the SaltPay card + Tap the Tangem card + Support + Claim %s + To get started, simply claim wxDAI to your wallet + Claim + Congratulations! Your first payment crypto card has been activated + Claiming + It will take a few seconds + Something went wrong + Please check your email for further instructions + Do you want to exit the activation process? + In this case, you will need to start from the beginning. + You have used a card from another wallet. Tap the card associated with this wallet + Referral program + Refer your friends to Tangem + You + Will get + for each wallet bought by your friend on your %s network address%s + Your friend + Will get a + %s discount + when buying a card on tangem.com + Your friends bought + Your personal code + Participate + terms and conditions + By tapping this button you accept + You\'ve accepted + of the referral program + Internal error: wallet manager not found + Bilanz: %s + Share + Copy + Erfolg + Give Permission + To continue you need to allow 1inch smart contracts to use your %s + Amount %s + Your Wallet + Spender + Approve + Swap of %s to + Swap + Insufficient funds + Give Permission + Permit and Swap + Failed to load the information about the referral program. Please try again later. + Failed to load the information about the referral program. Reason: %s. Please try again later. + Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support. + Personal code copied! + Buy Tangem Wallet with discount!\n%s + %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. + Ungültige Adresse + This wallet has already been saved, you can add another one + Entfernen + Privacy policy + Enable biometric authorization + It looks like you have biometric authentication disabled, it is necessary to save wallets + Enable + %d selected + biometric authentication + biometrics Tangem Änderungen speichern Warnung @@ -97,7 +315,6 @@ Can\'t send a transaction Reason: %s Are you having difficulty scanning your card? - I\'m okay Request support Send feedback Really cool! @@ -216,7 +433,7 @@ Tangem feedback Feedback Tell us what functions you are missing, and we will try to help you. - Please tell us what card do you have? + Please tell us what card do you have Please tell us more about your issue. Every small detail can help. Hi support team, The following information is optional. You can erase it if you don\'t want to share it. @@ -226,6 +443,12 @@ Fehler OK Failed to establish WalletConnect session. Please, try again later. + Would you like to use biometrics? + Biometrics will be requested instead of the access code for interactions with your wallet + Allow to use biometrics + Enable biometric authentication + Go to settings to enable biometric authentication in the Tangem App + Scan the card %s diff --git a/core/res/src/main/res/values-de/strings_final.xml b/core/res/src/main/res/values-de/strings_final.xml deleted file mode 100644 index 046904ddaf..0000000000 --- a/core/res/src/main/res/values-de/strings_final.xml +++ /dev/null @@ -1,233 +0,0 @@ - - - Tangem Wallet - 3 cards - 2 cards - Shipping - Free - I have a promo code… - Total - Other payment methods - Buy now - Meet\nTangem - Buy - Store - Send - Pay - Exchange - Lend - Borrow - Revolutionary Hardware Wallet - Store your crypto assets secure while keeping private keys contained in your card - Ultra Secure Backup - Up to - 3 physical cards - to one wallet - Thousands of Currencies - A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card - DeFi Compatible - Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services - The Wallet for Everyone - Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. - Order - Search tokens - You are currently running in Demo mode. All funds are not real. - This feature is disabled in Demo mode - Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. - Available networks - %s network not found. Please, add it first and try again. - Attention - Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. - Tokens in Solana network are not supported by this card due to firmware limitation. - Contract address copied! - Contract address - Required field - Please select the network - Decimal number must be a valid integer, no higher than %d - Contract address is invalid - Derivation path is invalid - Note that tokens can be created by anyone. Be aware of adding scam tokens, they can cost nothing. - This token/network has already been added to your list - Decimals - Network - Not selected - E.g. USD Coin - Name - E.g. USDC - Token symbol - BIP44 coin type - Default - The server is not available, please try again later - Total balance - The amount does not include some of your funds - Tokens - Manage tokens - No rate - Network is unreachable - Hide token - Hide %s - Hide - You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. - Unable to hide %s - The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. - Your wallet has not been backed up - To protect your assets, we advise you to carry out this procedure - Erneut versuchen - Chat - %s network - I understand - Yes - No - Russian bank cards are not accepted at the moment - Do you have a bank card of another country or a UnionPay card? - This network is not supported. Please select another network. - Card Settings - Security Mode - Change access code - Access code will be changed on this card only - Continue - Tangem Bot - Get your card ready! - Scan the card to change its settings. The changes will impact only the card you\'ve scanned and will not affect other cards tied to your wallet. - Scan Card - App Settings - Keep the wallet in the app - Enable to link all the wallets to Tangem app. Biometric authentication will be required for unlocking the app. Transaction signing requires tapping your Tangem card. - Save Access Code - Biometric authentication will be requested instead of the access code for interactions with your card. - Removing the saved card deletes all the saved wallets and their access codes. - This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. - WalletConnect - Connect to Dapps - This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - I understand that after performing this action, I will no longer have access to the current wallet - Reset the card - Reset to Factory Settings - Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - Select network - Scan your card - To access all the networks you need to scan the card - Connection with this Dapp cannot be established due to its technical implementation. - Welcome back! - Use %s or scan a card to access the app - Log in with %s - Karte scannen - Save your Wallet - Would you like to use %s? - Would you like to use biometrics? - Access the app - Log into the app and check your balance without scanning the card - Access code - %s will be requested instead of the access code for interactions with your wallet - Biometrics will be requested instead of the access code for interactions with your wallet - Note that making a transaction with your funds will still require your card - Allow to use %s - Allow to use biometrics - New feature - My Wallets - Multi-currency - Single-currency - Add new wallet - Rename Wallet - Wallet name - Unlock all with %s - Invalid Tag. It won\'t be added to the transaction. - Invalid Memo. It won\'t be added to the transaction. - Tag - Memo - Attention - Tap the card with the visa logo - No funds for activation - Please contact support - Four identical digits isn\'t safe - Such a PIN can be brute-forced easily - Pin code - Connect - KYC - Verify your identity - Set PIN code - Register - Verify via Utorg - Refresh - Connect your card - Verify your identity - KYC is in progress - Connect your card to the decentralized payment system - To start using your card you have to pass the KYC process - Please wait until the verification is completed. Usually it takes up to 1 hour. You can close the app and come back later. - PIN Code - Set PIN code for your SaltPay card - Chat with support - Please hold the card until the operation complete - To start the backup process you have to add Tangem card as your backup - No backup card - Backup card ready - Finalize the backup process by creating an access code - Prepare the SaltPay card - Tap the SaltPay card - Tap the Tangem card - Support - Claim %s - To get started, simply claim wxDAI to your wallet - Claim - Congratulations! Your first payment crypto card has been activated - Claiming - It will take a few seconds - Something went wrong - Please check you email for further instructions - Do you want to exit the activation process? - In this case, you will need to start from the beginning. - You have used a card from another wallet. Tap the card associated with this wallet - Referral program - Refer your friends to Tangem - You - Will get - for each wallet bought by your friend on your %s network address%s - Your friend - Will get a - %s discount - when buying a card on tangem.com - Your friends bought - Your personal code - Participate - terms and conditions - By tapping this button you accept - You\'ve accepted - of the referral program - Internal error: wallet manager not found - Bilanz: %s - Share - Copy - Erfolg - Give Permission - To continue you need to allow 1inch smart contracts to use your %s - Amount %s - Your Wallet - Spender - Approve - Swap of %s to - Swap - Insufficient funds - Give Permission - Permit and Swap - Failed to load the information about the referral program. Please try again later. - Failed to load the information about the referral program. Reason: %s. Please try again later. - Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support. - Personal code copied! - Buy Tangem Wallet with discount!\n%s - %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. - Ungültige Adresse - This wallet has already been saved, you can add another one - Entfernen - Privacy policy - Enable biometric authorization - It looks like you have biometric authentication disabled, it is necessary to save wallets - Enable - Save your Wallet feature allows you to use your wallet with biometric auth without tapping your card to the phone to gain access. - %d selected - biometric authentication - biometrics - Enable biometric authentication - Go to settings to enable biometric authentication in the Tangem App - Scan the card - diff --git a/core/res/src/main/res/values-de/strings_plurals_final.xml b/core/res/src/main/res/values-de/strings_plurals.xml similarity index 100% rename from core/res/src/main/res/values-de/strings_plurals_final.xml rename to core/res/src/main/res/values-de/strings_plurals.xml diff --git a/core/res/src/main/res/values-fr/strings-app.xml b/core/res/src/main/res/values-fr/strings.xml similarity index 51% rename from core/res/src/main/res/values-fr/strings-app.xml rename to core/res/src/main/res/values-fr/strings.xml index 3d926e7f7b..cf498616e2 100644 --- a/core/res/src/main/res/values-fr/strings-app.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -1,5 +1,223 @@ - + + Tangem Wallet + 3 cards + 2 cards + Shipping + Free + I have a promo code… + Total + Other payment methods + Buy now + Meet\nTangem + Buy + Store + Send + Pay + Exchange + Lend + Borrow + Revolutionary Hardware Wallet + Store your crypto assets secure while keeping private keys contained in your card + Ultra Secure Backup + Up to + 3 physical cards + to one wallet + Thousands of Currencies + A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card + DeFi Compatible + Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services + The Wallet for Everyone + Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. + Order + Search tokens + You are currently running in Demo mode. All funds are not real. + This feature is disabled in Demo mode + Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. + Available networks + %s network not found. Please, add it first and try again. + Attention + Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. + Tokens in Solana network are not supported by this card due to firmware limitation. + Contract address copied! + Contract address + Required field + Please select the network + Decimal number must be a valid integer, no higher than %d + Contract address is invalid + Derivation path is invalid + Note that tokens can be created by anyone. Be aware of adding scam tokens, they can cost nothing. + This token/network has already been added to your list + Decimals + Network + Not selected + E.g. USD Coin + Name + E.g. USDC + Token symbol + BIP44 coin type + Default + The server is not available, please try again later + Total balance + The amount does not include some of your funds + Tokens + Manage tokens + No rate + Network is unreachable + Hide token + Hide %s + Hide + You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. + Unable to hide %s + The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. + Your wallet has not been backed up + To protect your assets, we advise you to carry out this procedure + Réessayer + Chat + %s network + I understand + Yes + No + Russian bank cards are not accepted at the moment + Do you have a bank card of another country or a UnionPay card? + This network is not supported. Please select another network. + Card Settings + Security Mode + Change Access Code + Access code will be changed on this card only + Continue + Tangem Bot + Get your card ready! + Scan the card to change its settings. The changes will impact only the card you\'ve scanned and will not affect other cards tied to your wallet. + Scan Card + App Settings + Keep the wallet in the app + Enable to link all the wallets to Tangem app. Biometric authentication will be required for unlocking the app. Transaction signing requires tapping your Tangem card. + Save Access Code + Biometric authentication will be requested instead of the access code for interactions with your card. + Removing the saved card deletes all the saved wallets and their access codes. + This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. + WalletConnect + Connect to Dapps + This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + I understand that after performing this action, I will no longer have access to the current wallet + Reset the Card + Reset to Factory Settings + Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + Select network + Scan your card + To access all the networks you need to scan the card + Connection with this Dapp cannot be established due to its technical implementation. + Welcome back! + Use %s or scan a card to access the app + Log in with %s + Scannez la carte + Access the app + Log into the app and check your balance without scanning the card + Access code + Note that making a transaction with your funds will still require your card + My Wallets + Multi-currency + Single-currency + Add new wallet + Rename Wallet + Wallet name + Unlock all with %s + Invalid Tag. It won\'t be added to the transaction. + Invalid Memo. It won\'t be added to the transaction. + Tag + Memo + Attention + Tap the card with the visa logo + No funds for activation + Please contact support + Four identical digits isn\'t safe + Such a PIN can be brute-forced easily + Pin code + Connect + KYC + Verify your identity + Set PIN code + Register + Verify via Utorg + Refresh + Connect your card + Verify your identity + KYC is in progress + Connect your card to the decentralized payment system + To start using your card you have to pass the KYC process + Please wait until the verification is completed. You\'ll be notified via email. Usually it takes up to 1 hour. You can close the app and come back later. + PIN Code + Set PIN code for your SaltPay card + Chat with support + Please hold the card until the operation complete + To start the backup process you have to add Tangem card as your backup + No backup card + Backup card ready + Finalize the backup process by creating an access code + Prepare the SaltPay card + Tap the SaltPay card + Tap the Tangem card + Support + Claim %s + To get started, simply claim wxDAI to your wallet + Claim + Congratulations! Your first payment crypto card has been activated + Claiming + It will take a few seconds + Something went wrong + Please check your email for further instructions + Do you want to exit the activation process? + In this case, you will need to start from the beginning. + You have used a card from another wallet. Tap the card associated with this wallet + Referral program + Refer your friends to Tangem + You + Will get + for each wallet bought by your friend on your %s network address%s + Your friend + Will get a + %s discount + when buying a card on tangem.com + Your friends bought + Your personal code + Participate + terms and conditions + By tapping this button you accept + You\'ve accepted + of the referral program + Internal error: wallet manager not found + Solde : %s + Share + Copy + Avec succès + Give Permission + To continue you need to allow 1inch smart contracts to use your %s + Amount %s + Your Wallet + Spender + Approve + Swap of %s to + Swap + Insufficient funds + Give Permission + Permit and Swap + Failed to load the information about the referral program. Please try again later. + Failed to load the information about the referral program. Reason: %s. Please try again later. + Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support. + Personal code copied! + Buy Tangem Wallet with discount!\n%s + %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. + Adresse incorrecte + This wallet has already been saved, you can add another one + Supprimer + Privacy policy + Enable biometric authorization + It looks like you have biometric authentication disabled, it is necessary to save wallets + Enable + %d selected + biometric authentication + biometrics Tangem Sauvegarder les modifications Alerte @@ -97,7 +315,6 @@ Can\'t send a transaction Reason: %s Are you having difficulty scanning your card? - I\'m okay Request support Send feedback Really cool! @@ -216,7 +433,7 @@ Tangem feedback Feedback Tell us what functions you are missing, and we will try to help you. - Please tell us what card do you have? + Please tell us what card do you have Please tell us more about your issue. Every small detail can help. Hi support team, The following information is optional. You can erase it if you don\'t want to share it. @@ -226,6 +443,12 @@ Erreur OK Failed to establish WalletConnect session. Please, try again later. + Would you like to use biometrics? + Biometrics will be requested instead of the access code for interactions with your wallet + Allow to use biometrics + Enable biometric authentication + Go to settings to enable biometric authentication in the Tangem App + Scan the card %s diff --git a/core/res/src/main/res/values-fr/strings_final.xml b/core/res/src/main/res/values-fr/strings_final.xml deleted file mode 100644 index 4b3d386d9b..0000000000 --- a/core/res/src/main/res/values-fr/strings_final.xml +++ /dev/null @@ -1,233 +0,0 @@ - - - Tangem Wallet - 3 cards - 2 cards - Shipping - Free - I have a promo code… - Total - Other payment methods - Buy now - Meet\nTangem - Buy - Store - Send - Pay - Exchange - Lend - Borrow - Revolutionary Hardware Wallet - Store your crypto assets secure while keeping private keys contained in your card - Ultra Secure Backup - Up to - 3 physical cards - to one wallet - Thousands of Currencies - A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card - DeFi Compatible - Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services - The Wallet for Everyone - Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. - Order - Search tokens - You are currently running in Demo mode. All funds are not real. - This feature is disabled in Demo mode - Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. - Available networks - %s network not found. Please, add it first and try again. - Attention - Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. - Tokens in Solana network are not supported by this card due to firmware limitation. - Contract address copied! - Contract address - Required field - Please select the network - Decimal number must be a valid integer, no higher than %d - Contract address is invalid - Derivation path is invalid - Note that tokens can be created by anyone. Be aware of adding scam tokens, they can cost nothing. - This token/network has already been added to your list - Decimals - Network - Not selected - E.g. USD Coin - Name - E.g. USDC - Token symbol - BIP44 coin type - Default - The server is not available, please try again later - Total balance - The amount does not include some of your funds - Tokens - Manage tokens - No rate - Network is unreachable - Hide token - Hide %s - Hide - You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. - Unable to hide %s - The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. - Your wallet has not been backed up - To protect your assets, we advise you to carry out this procedure - Réessayer - Chat - %s network - I understand - Yes - No - Russian bank cards are not accepted at the moment - Do you have a bank card of another country or a UnionPay card? - This network is not supported. Please select another network. - Card Settings - Security Mode - Change access code - Access code will be changed on this card only - Continue - Tangem Bot - Get your card ready! - Scan the card to change its settings. The changes will impact only the card you\'ve scanned and will not affect other cards tied to your wallet. - Scan Card - App Settings - Keep the wallet in the app - Enable to link all the wallets to Tangem app. Biometric authentication will be required for unlocking the app. Transaction signing requires tapping your Tangem card. - Save Access Code - Biometric authentication will be requested instead of the access code for interactions with your card. - Removing the saved card deletes all the saved wallets and their access codes. - This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. - WalletConnect - Connect to Dapps - This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - I understand that after performing this action, I will no longer have access to the current wallet - Reset the card - Reset to Factory Settings - Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - Select network - Scan your card - To access all the networks you need to scan the card - Connection with this Dapp cannot be established due to its technical implementation. - Welcome back! - Use %s or scan a card to access the app - Log in with %s - Scannez la carte - Save your Wallet - Would you like to use %s? - Would you like to use biometrics? - Access the app - Log into the app and check your balance without scanning the card - Access code - %s will be requested instead of the access code for interactions with your wallet - Biometrics will be requested instead of the access code for interactions with your wallet - Note that making a transaction with your funds will still require your card - Allow to use %s - Allow to use biometrics - New feature - My Wallets - Multi-currency - Single-currency - Add new wallet - Rename Wallet - Wallet name - Unlock all with %s - Invalid Tag. It won\'t be added to the transaction. - Invalid Memo. It won\'t be added to the transaction. - Tag - Memo - Attention - Tap the card with the visa logo - No funds for activation - Please contact support - Four identical digits isn\'t safe - Such a PIN can be brute-forced easily - Pin code - Connect - KYC - Verify your identity - Set PIN code - Register - Verify via Utorg - Refresh - Connect your card - Verify your identity - KYC is in progress - Connect your card to the decentralized payment system - To start using your card you have to pass the KYC process - Please wait until the verification is completed. Usually it takes up to 1 hour. You can close the app and come back later. - PIN Code - Set PIN code for your SaltPay card - Chat with support - Please hold the card until the operation complete - To start the backup process you have to add Tangem card as your backup - No backup card - Backup card ready - Finalize the backup process by creating an access code - Prepare the SaltPay card - Tap the SaltPay card - Tap the Tangem card - Support - Claim %s - To get started, simply claim wxDAI to your wallet - Claim - Congratulations! Your first payment crypto card has been activated - Claiming - It will take a few seconds - Something went wrong - Please check you email for further instructions - Do you want to exit the activation process? - In this case, you will need to start from the beginning. - You have used a card from another wallet. Tap the card associated with this wallet - Referral program - Refer your friends to Tangem - You - Will get - for each wallet bought by your friend on your %s network address%s - Your friend - Will get a - %s discount - when buying a card on tangem.com - Your friends bought - Your personal code - Participate - terms and conditions - By tapping this button you accept - You\'ve accepted - of the referral program - Internal error: wallet manager not found - Solde : %s - Share - Copy - Avec succès - Give Permission - To continue you need to allow 1inch smart contracts to use your %s - Amount %s - Your Wallet - Spender - Approve - Swap of %s to - Swap - Insufficient funds - Give Permission - Permit and Swap - Failed to load the information about the referral program. Please try again later. - Failed to load the information about the referral program. Reason: %s. Please try again later. - Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support. - Personal code copied! - Buy Tangem Wallet with discount!\n%s - %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. - Adresse incorrecte - This wallet has already been saved, you can add another one - Supprimer - Privacy policy - Enable biometric authorization - It looks like you have biometric authentication disabled, it is necessary to save wallets - Enable - Save your Wallet feature allows you to use your wallet with biometric auth without tapping your card to the phone to gain access. - %d selected - biometric authentication - biometrics - Enable biometric authentication - Go to settings to enable biometric authentication in the Tangem App - Scan the card - diff --git a/core/res/src/main/res/values-fr/strings_plurals_final.xml b/core/res/src/main/res/values-fr/strings_plurals.xml similarity index 100% rename from core/res/src/main/res/values-fr/strings_plurals_final.xml rename to core/res/src/main/res/values-fr/strings_plurals.xml diff --git a/core/res/src/main/res/values-it/strings-app.xml b/core/res/src/main/res/values-it/strings.xml similarity index 51% rename from core/res/src/main/res/values-it/strings-app.xml rename to core/res/src/main/res/values-it/strings.xml index aa4147d4ba..af7ce360a9 100644 --- a/core/res/src/main/res/values-it/strings-app.xml +++ b/core/res/src/main/res/values-it/strings.xml @@ -1,5 +1,223 @@ - + + Tangem Wallet + 3 cards + 2 cards + Shipping + Free + I have a promo code… + Total + Other payment methods + Buy now + Meet\nTangem + Buy + Store + Send + Pay + Exchange + Lend + Borrow + Revolutionary Hardware Wallet + Store your crypto assets secure while keeping private keys contained in your card + Ultra Secure Backup + Up to + 3 physical cards + to one wallet + Thousands of Currencies + A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card + DeFi Compatible + Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services + The Wallet for Everyone + Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. + Order + Search tokens + You are currently running in Demo mode. All funds are not real. + This feature is disabled in Demo mode + Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. + Available networks + %s network not found. Please, add it first and try again. + Attention + Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. + Tokens in Solana network are not supported by this card due to firmware limitation. + Contract address copied! + Contract address + Required field + Please select the network + Decimal number must be a valid integer, no higher than %d + Contract address is invalid + Derivation path is invalid + Note that tokens can be created by anyone. Be aware of adding scam tokens, they can cost nothing. + This token/network has already been added to your list + Decimals + Network + Not selected + E.g. USD Coin + Name + E.g. USDC + Token symbol + BIP44 coin type + Default + The server is not available, please try again later + Total balance + The amount does not include some of your funds + Tokens + Manage tokens + No rate + Network is unreachable + Hide token + Hide %s + Hide + You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. + Unable to hide %s + The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. + Your wallet has not been backed up + To protect your assets, we advise you to carry out this procedure + Riprova + Chat + %s network + I understand + Yes + No + Russian bank cards are not accepted at the moment + Do you have a bank card of another country or a UnionPay card? + This network is not supported. Please select another network. + Card Settings + Security Mode + Change Access Code + Access code will be changed on this card only + Continue + Tangem Bot + Get your card ready! + Scan the card to change its settings. The changes will impact only the card you\'ve scanned and will not affect other cards tied to your wallet. + Scan Card + App Settings + Keep the wallet in the app + Enable to link all the wallets to Tangem app. Biometric authentication will be required for unlocking the app. Transaction signing requires tapping your Tangem card. + Save Access Code + Biometric authentication will be requested instead of the access code for interactions with your card. + Removing the saved card deletes all the saved wallets and their access codes. + This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. + WalletConnect + Connect to Dapps + This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + I understand that after performing this action, I will no longer have access to the current wallet + Reset the Card + Reset to Factory Settings + Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + Select network + Scan your card + To access all the networks you need to scan the card + Connection with this Dapp cannot be established due to its technical implementation. + Welcome back! + Use %s or scan a card to access the app + Log in with %s + Scansiona carta + Access the app + Log into the app and check your balance without scanning the card + Access code + Note that making a transaction with your funds will still require your card + My Wallets + Multi-currency + Single-currency + Add new wallet + Rename Wallet + Wallet name + Unlock all with %s + Invalid Tag. It won\'t be added to the transaction. + Invalid Memo. It won\'t be added to the transaction. + Tag + Memo + Attention + Tap the card with the visa logo + No funds for activation + Please contact support + Four identical digits isn\'t safe + Such a PIN can be brute-forced easily + Pin code + Connect + KYC + Verify your identity + Set PIN code + Register + Verify via Utorg + Refresh + Connect your card + Verify your identity + KYC is in progress + Connect your card to the decentralized payment system + To start using your card you have to pass the KYC process + Please wait until the verification is completed. You\'ll be notified via email. Usually it takes up to 1 hour. You can close the app and come back later. + PIN Code + Set PIN code for your SaltPay card + Chat with support + Please hold the card until the operation complete + To start the backup process you have to add Tangem card as your backup + No backup card + Backup card ready + Finalize the backup process by creating an access code + Prepare the SaltPay card + Tap the SaltPay card + Tap the Tangem card + Support + Claim %s + To get started, simply claim wxDAI to your wallet + Claim + Congratulations! Your first payment crypto card has been activated + Claiming + It will take a few seconds + Something went wrong + Please check your email for further instructions + Do you want to exit the activation process? + In this case, you will need to start from the beginning. + You have used a card from another wallet. Tap the card associated with this wallet + Referral program + Refer your friends to Tangem + You + Will get + for each wallet bought by your friend on your %s network address%s + Your friend + Will get a + %s discount + when buying a card on tangem.com + Your friends bought + Your personal code + Participate + terms and conditions + By tapping this button you accept + You\'ve accepted + of the referral program + Internal error: wallet manager not found + Saldo: %s + Share + Copy + Con successo + Give Permission + To continue you need to allow 1inch smart contracts to use your %s + Amount %s + Your Wallet + Spender + Approve + Swap of %s to + Swap + Insufficient funds + Give Permission + Permit and Swap + Failed to load the information about the referral program. Please try again later. + Failed to load the information about the referral program. Reason: %s. Please try again later. + Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support. + Personal code copied! + Buy Tangem Wallet with discount!\n%s + %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. + Indirizzo non valido + This wallet has already been saved, you can add another one + Rimuovere + Privacy policy + Enable biometric authorization + It looks like you have biometric authentication disabled, it is necessary to save wallets + Enable + %d selected + biometric authentication + biometrics Tangem Mantieni le modifiche Avviso @@ -97,7 +315,6 @@ Can\'t send a transaction Reason: %s Are you having difficulty scanning your card? - I\'m okay Request support Send feedback Really cool! @@ -216,7 +433,7 @@ Tangem feedback Feedback Tell us what functions you are missing, and we will try to help you. - Please tell us what card do you have? + Please tell us what card do you have Please tell us more about your issue. Every small detail can help. Hi support team, The following information is optional. You can erase it if you don\'t want to share it. @@ -226,6 +443,12 @@ Errore OK Failed to establish WalletConnect session. Please, try again later. + Would you like to use biometrics? + Biometrics will be requested instead of the access code for interactions with your wallet + Allow to use biometrics + Enable biometric authentication + Go to settings to enable biometric authentication in the Tangem App + Scan the card %s diff --git a/core/res/src/main/res/values-it/strings_final.xml b/core/res/src/main/res/values-it/strings_final.xml deleted file mode 100644 index 53bd5f260c..0000000000 --- a/core/res/src/main/res/values-it/strings_final.xml +++ /dev/null @@ -1,233 +0,0 @@ - - - Tangem Wallet - 3 cards - 2 cards - Shipping - Free - I have a promo code… - Total - Other payment methods - Buy now - Meet\nTangem - Buy - Store - Send - Pay - Exchange - Lend - Borrow - Revolutionary Hardware Wallet - Store your crypto assets secure while keeping private keys contained in your card - Ultra Secure Backup - Up to - 3 physical cards - to one wallet - Thousands of Currencies - A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card - DeFi Compatible - Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services - The Wallet for Everyone - Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. - Order - Search tokens - You are currently running in Demo mode. All funds are not real. - This feature is disabled in Demo mode - Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. - Available networks - %s network not found. Please, add it first and try again. - Attention - Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. - Tokens in Solana network are not supported by this card due to firmware limitation. - Contract address copied! - Contract address - Required field - Please select the network - Decimal number must be a valid integer, no higher than %d - Contract address is invalid - Derivation path is invalid - Note that tokens can be created by anyone. Be aware of adding scam tokens, they can cost nothing. - This token/network has already been added to your list - Decimals - Network - Not selected - E.g. USD Coin - Name - E.g. USDC - Token symbol - BIP44 coin type - Default - The server is not available, please try again later - Total balance - The amount does not include some of your funds - Tokens - Manage tokens - No rate - Network is unreachable - Hide token - Hide %s - Hide - You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. - Unable to hide %s - The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. - Your wallet has not been backed up - To protect your assets, we advise you to carry out this procedure - Riprova - Chat - %s network - I understand - Yes - No - Russian bank cards are not accepted at the moment - Do you have a bank card of another country or a UnionPay card? - This network is not supported. Please select another network. - Card Settings - Security Mode - Change access code - Access code will be changed on this card only - Continue - Tangem Bot - Get your card ready! - Scan the card to change its settings. The changes will impact only the card you\'ve scanned and will not affect other cards tied to your wallet. - Scan Card - App Settings - Keep the wallet in the app - Enable to link all the wallets to Tangem app. Biometric authentication will be required for unlocking the app. Transaction signing requires tapping your Tangem card. - Save Access Code - Biometric authentication will be requested instead of the access code for interactions with your card. - Removing the saved card deletes all the saved wallets and their access codes. - This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. - WalletConnect - Connect to Dapps - This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - I understand that after performing this action, I will no longer have access to the current wallet - Reset the card - Reset to Factory Settings - Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - Select network - Scan your card - To access all the networks you need to scan the card - Connection with this Dapp cannot be established due to its technical implementation. - Welcome back! - Use %s or scan a card to access the app - Log in with %s - Scansiona carta - Save your Wallet - Would you like to use %s? - Would you like to use biometrics? - Access the app - Log into the app and check your balance without scanning the card - Access code - %s will be requested instead of the access code for interactions with your wallet - Biometrics will be requested instead of the access code for interactions with your wallet - Note that making a transaction with your funds will still require your card - Allow to use %s - Allow to use biometrics - New feature - My Wallets - Multi-currency - Single-currency - Add new wallet - Rename Wallet - Wallet name - Unlock all with %s - Invalid Tag. It won\'t be added to the transaction. - Invalid Memo. It won\'t be added to the transaction. - Tag - Memo - Attention - Tap the card with the visa logo - No funds for activation - Please contact support - Four identical digits isn\'t safe - Such a PIN can be brute-forced easily - Pin code - Connect - KYC - Verify your identity - Set PIN code - Register - Verify via Utorg - Refresh - Connect your card - Verify your identity - KYC is in progress - Connect your card to the decentralized payment system - To start using your card you have to pass the KYC process - Please wait until the verification is completed. Usually it takes up to 1 hour. You can close the app and come back later. - PIN Code - Set PIN code for your SaltPay card - Chat with support - Please hold the card until the operation complete - To start the backup process you have to add Tangem card as your backup - No backup card - Backup card ready - Finalize the backup process by creating an access code - Prepare the SaltPay card - Tap the SaltPay card - Tap the Tangem card - Support - Claim %s - To get started, simply claim wxDAI to your wallet - Claim - Congratulations! Your first payment crypto card has been activated - Claiming - It will take a few seconds - Something went wrong - Please check you email for further instructions - Do you want to exit the activation process? - In this case, you will need to start from the beginning. - You have used a card from another wallet. Tap the card associated with this wallet - Referral program - Refer your friends to Tangem - You - Will get - for each wallet bought by your friend on your %s network address%s - Your friend - Will get a - %s discount - when buying a card on tangem.com - Your friends bought - Your personal code - Participate - terms and conditions - By tapping this button you accept - You\'ve accepted - of the referral program - Internal error: wallet manager not found - Saldo: %s - Share - Copy - Con successo - Give Permission - To continue you need to allow 1inch smart contracts to use your %s - Amount %s - Your Wallet - Spender - Approve - Swap of %s to - Swap - Insufficient funds - Give Permission - Permit and Swap - Failed to load the information about the referral program. Please try again later. - Failed to load the information about the referral program. Reason: %s. Please try again later. - Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support. - Personal code copied! - Buy Tangem Wallet with discount!\n%s - %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. - Indirizzo non valido - This wallet has already been saved, you can add another one - Rimuovere - Privacy policy - Enable biometric authorization - It looks like you have biometric authentication disabled, it is necessary to save wallets - Enable - Save your Wallet feature allows you to use your wallet with biometric auth without tapping your card to the phone to gain access. - %d selected - biometric authentication - biometrics - Enable biometric authentication - Go to settings to enable biometric authentication in the Tangem App - Scan the card - diff --git a/core/res/src/main/res/values-ru/strings-app.xml b/core/res/src/main/res/values-ru/strings.xml similarity index 51% rename from core/res/src/main/res/values-ru/strings-app.xml rename to core/res/src/main/res/values-ru/strings.xml index 142d4e305f..a715487104 100644 --- a/core/res/src/main/res/values-ru/strings-app.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -1,5 +1,223 @@ - + + Tangem Wallet + 3 карты + 2 карты + Доставка + Бесплатно + У меня есть промо-код… + Итого + Другие способы оплаты + Купить сейчас + Встречайте\nTangem + Покупайте + Храните + Отправляйте + Расплачивайтесь + Обменивайте + Вкладывайте + Занимайте + Революционный аппаратный кошелек + Держите свои криптосбережения в безопасности. Приватные ключи надежно хранятся на карте. + Все ключи в безопасности + До + трех карт + с одним кошельком + Тысячи криптовалют + Аппаратный кошелек для ваших биткоинов, эфира и многих других валют одновременно — все в одной карте + Поддержка DeFi + Обменивайте, покупайте NFT, получайте займы и делайте вклады в более чем 100 различных децентрализованных сервисах + Кошелек для каждого + Используйте его на ходу, в любом месте, в любое время. Без проводов и батареек. Как только понадобится крипта, просто приложите карту к телефону. + Купить + Поиск токенов + Приложение работает в демонстрационном режиме. Средства на всех счетах ненастоящие. + Эта функция недоступна в демонстрационном режиме + Недостаточно средств для комиссии на вашем %s кошельке для отправки транзакции. Сначала пополните свой %s кошелек. + Доступные сети + Сеть %s не найдена. Пожалуйста, добавьте её и попробуйте заново. + Внимание + Внимание! Валюты на разных сетях имеют разные адреса. Убедитесь, что адрес соответствует сети, в которой вы отправляете средства. + Токены в сети Solana не поддерживаются этой картой из-за ограничений прошивки. + Адрес контракта скопирован! + Адрес контракта + Обязательное поле + Пожалуйста, выберите сеть + Количество знаков после запятой должно быть корректным числом не больше %d + Адрес контракта некорректен + Путь деривации некорректен + Токены могут быть созданы кем угодно. Остерегайтесь мошеннических токенов, они могут ничего не стоить + Этот токен/сеть уже находится в вашем списке + Знаков после запятой + Сеть + Не выбрано + Например, USD Coin + Название токена + Например, USDC + Символ токена + Деривация по BIP44 + По-умолчанию + Сервер недоступен, повторите попытку позднее + Баланс + В сумме учтены не все монеты + Токены + Управление токенами + Нет цены + Сеть недоступна + Скрыть токен + Скрыть %s + Скрыть + Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно через страницу управления токенами. + Невозможно скрыть %s + Токен %s является основной валютой в сети %s и не может быть скрыт до тех пор, пока у вас в списке есть другие токены этой сети. + Бэкап кошелька не был произведен + Чтобы защитить свои активы, мы советуем вам выполнить эту процедуру + Повторить + Чат + Сеть %s + Я понял + Да + Нет + Карты банков РФ в данный момент не принимаются + У вас есть карта банка другой страны или платежной системы UnionPay? + Сеть не поддерживается. Пожалуйста, выберите другую сеть. + Настройки карты + Тип безопасности + Смена кода доступа + Код доступа будет изменен только на данной карте + Продолжить + Tangem Bot + Приготовьте свою карту + Отсканируйте карту, чтобы изменить ее настройки. Изменения затронут только ту карту, которую вы отсканировали, и не повлияют на другие карты, привязанные к вашему кошельку. + Сканировать + Настройки приложения + Cохранение кошелька + Подключите функцию привязки карты в приложении, а также возможность биометрической аутентификации. Подпись транзакции все так же потребует карту. + Сохранение кода доступа + Подключите функцию хранения кодов доступа от карт на телефоне в зашифрованном виде, и при работе с картой вместо кода доступа будет запрашиваться биометрическая аутентификация. + При отключении функции сохранения кошелька все ранее сохраненные кошельки будут удалены. + Все сохраненные коды доступа будут удалены. Вам потребуется вводить код доступа при работе с кошельком. + WalletConnect + Подключение к Dapps + Это действие приведет к полному удалению кошелька на этой карте. Кошелек невозможно будет восстановить или использовать данную карту для восстановления кода доступа + Я понимаю, что после выполнения этого действия у меня больше не будет доступа к текущему кошельку + Сбросить карту + Сброс к заводским настройкам + Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты. Вы не сможете восстановить текущий кошелек или использовать эту карту для восстановления кода доступа. + Выберите сеть + Отсканируйте карту + Чтобы получить доступ ко всем сетям, вам необходимо отсканировать карту + Cоединение с этим Dapp сервисом не может быть установлено из-за его технической реализации. + C возвращением! + Используйте %s или код доступа для входа в приложение + Войти с %s + Сканировать карту + Доступ в приложение + Войдите в приложение и следите за своим балансом без сканирования карты + Код доступа + Обратите внимание, что для совершения транзакции с вашими средствами по-прежнему потребуется ваша карта + Мои кошельки + Мультивалютные + Одновалютные + Добавить новый кошелек + Переименование кошелька + Имя кошелька + Разблокировать все с %s + Недопустимый Tag. Он не будет добавлен в транзакцию. + Недопустимый Memo. Он не будет добавлен в транзакцию. + Tag + Memo + Внимание + Приложите карту с логотипом Visa + Недостаточно средств для активации + Пожалуйста обратитесь в службу поддержки + Ввод одинаковых цифр является не безопасным + Данный Код доступа может быть легко взломан + Код доступа + Подключиться + Верификация клиента + Подтвердите свою личность + Установить Код доступа + Зарегистрироваться + Верифицировать (Utorg) + Обновить + Подключите свою карту + Подтвердите свою личность + Подтверждение личности в процессе + Подключите вашу карту к децентрализованной платежной системе + Для начала работы с картой вам необходимо завершить процесс подтверждения личности + Пожалуйста дождитесь завершения процесса подтверждения личности. Вы будете уведомлены через e-mail. Обычно это занимает не более часа. Вы можете закрыть приложение и вернуться позже. + Код доступа + Установите Код доступа для вашей SaltPay карты + Чат поддержки + Пожалуйста, удерживайте карту до завершения операции + Для начала процесса бэкапа вам необходимо добавить Tangem карту + Бэкап карта не добавлена + Бэкап карта создана + Завершите процесс бэкапа создав код доступа + Приготовьте SaltPay карту + Приложите SaltPay карту + Приложите Tangem карту + Чат + Запросить %s + Для начала работы просто запросите начисление wxDai на свой кошелек + Запросить + Поздравляем! Ваша платежная крипто карта теперь активирована! + Запрашивается + Это займет несколько секунд + Что-то пошло не так + Более подробная информация отправлена на ваш адрес электронной почты. + Вы хотите выйти из процесса активации? + В этом случае вам будет необходимо начать процесс заново. + Вы использовали карту от другого кошелька. Приложите карту, связанную с этим кошельком. + Реферальная программа + Приведи друга в Tangem + Вы + Получите + на ваш адрес в сети %s%s за каждый кошелек, который купит ваш друг + Ваш друг + Получит + %s скидку + при покупке карточки на сайте tangem.com + Ваши друзья купили + Ваш персональный код + Участвовать + условия участия + Нажимая на эту кнопку вы принимаете + Вы приняли + в реферальной программе + Внутренняя ошибка: не удается найти менеджер кошельков + Баланс: %s + Поделиться + Копировать + Успешно + Дать разрешение + Чтобы продолжить, вам нужно разрешить смарт-контракту 1inch использовать ваш %s + Количество %s + Ваш кошелек + Отправитель + Подтвердить + Обмен %s на + Обмен + Недостаточно средств + Дать разрешение + Разрешить и обменять + Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже. + Не удалось загрузить информацию по реферальной программе. Причина: %s. Пожалуйста, попробуйте позже. + Не удалось обработать вашу заявку на участие. Причина: %s. Пожалуйста, попробуйте позже. Если проблема сохранится, вы можете обратиться в техподдержку. + Персональный код скопирован! + Купи Tangem Wallet со скидкой!\n%s + Сеть %s использует концепцию экзистенциального депозита. Если баланс вашего счета опустится ниже %s, он будет деактивирован, а все оставшиеся средства будут уничтожены. + Неверный адрес + Этот кошелек уже был сохранен, вы можете добавить другой + Удалить + Privacy policy + Включите биометрическую аутентификацию + Похоже, что у вас отключена биометрическая аутентификация, она необходима для сохранения кошельков + Включить + %d выбрано + биометрическую аутентификацию + биометрией Tangem Сохранить изменения Предупреждение @@ -97,7 +315,6 @@ Не могу отправить транзакцию Причина: %s У вас возникли трудности со сканированием карты? - Отмена Обратиться в поддержку Отправить отзыв Очень круто! @@ -226,6 +443,12 @@ Ошибка Ок Не удалось установить сессию WalletConnect. Пожалуйста, повторите попытку позже. + Вы хотите использовать биометрию? + Для операций с вашим кошельком будет запрашиваться биометрия вместо кода доступа карты + Использовать биометрию + Включите биометрическую аутентификацию + Перейдите в настройки, чтобы включить биометрическую аутентификацию в приложении Tangem App + Отсканируйте карту %s diff --git a/core/res/src/main/res/values-ru/strings_final.xml b/core/res/src/main/res/values-ru/strings_final.xml deleted file mode 100644 index c56fea1dcc..0000000000 --- a/core/res/src/main/res/values-ru/strings_final.xml +++ /dev/null @@ -1,233 +0,0 @@ - - - Tangem Wallet - 3 карты - 2 карты - Доставка - Бесплатно - У меня есть промо-код… - Итого - Другие способы оплаты - Купить сейчас - Встречайте\nTangem - Покупайте - Храните - Отправляйте - Расплачивайтесь - Обменивайте - Вкладывайте - Занимайте - Революционный аппаратный кошелек - Держите свои криптосбережения в безопасности. Приватные ключи надежно хранятся на карте. - Все ключи в безопасности - До - трех карт - с одним кошельком - Тысячи криптовалют - Аппаратный кошелек для ваших биткоинов, эфира и многих других валют одновременно — все в одной карте - Поддержка DeFi - Обменивайте, покупайте NFT, получайте займы и делайте вклады в более чем 100 различных децентрализованных сервисах - Кошелек для каждого - Используйте его на ходу, в любом месте, в любое время. Без проводов и батареек. Как только понадобится крипта, просто приложите карту к телефону. - Купить - Поиск токенов - Приложение работает в демонстрационном режиме. Средства на всех счетах ненастоящие. - Эта функция недоступна в демонстрационном режиме - Недостаточно средств для комиссии на вашем %s кошельке для отправки транзакции. Сначала пополните свой %s кошелек. - Доступные сети - Сеть %s не найдена. Пожалуйста, добавьте её и попробуйте заново. - Внимание - Внимание! Валюты на разных сетях имеют разные адреса. Убедитесь, что адрес соответствует сети, в которой вы отправляете средства. - Токены в сети Solana не поддерживаются этой картой из-за ограничений прошивки. - Адрес контракта скопирован! - Адрес контракта - Обязательное поле - Пожалуйста, выберите сеть - Количество знаков после запятой должно быть корректным числом не больше %d - Адрес контракта некорректен - Путь деривации некорректен - Токены могут быть созданы кем угодно. Остерегайтесь мошеннических токенов, они могут ничего не стоить - Этот токен/сеть уже находится в вашем списке - Знаков после запятой - Сеть - Не выбрано - Например, USD Coin - Название токена - Например, USDC - Символ токена - Деривация по BIP44 - По-умолчанию - Сервер недоступен, повторите попытку позднее - Баланс - В сумме учтены не все монеты - Токены - Управление токенами - Нет цены - Сеть недоступна - Скрыть токен - Скрыть %s - Скрыть - Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно через страницу управления токенами. - Невозможно скрыть %s - Токен %s является основной валютой в сети %s и не может быть скрыт до тех пор, пока у вас в списке есть другие токены этой сети. - Бэкап кошелька не был произведен - Чтобы защитить свои активы, мы советуем вам выполнить эту процедуру - Повторить - Чат - Сеть %s - Я понял - Да - Нет - Карты банков РФ в данный момент не принимаются - У вас есть карта банка другой страны или платежной системы UnionPay? - Сеть не поддерживается. Пожалуйста, выберите другую сеть. - Настройки карты - Тип безопасности - Смена кода доступа - Код доступа будет изменен только на данной карте - Продолжить - Tangem Bot - Приготовьте свою карту - Отсканируйте карту, чтобы изменить ее настройки. Изменения затронут только ту карту, которую вы отсканировали, и не повлияют на другие карты, привязанные к вашему кошельку. - Сканировать - Настройки приложения - Cохранение кошелька - Подключите функцию привязки карты в приложении, а также возможность биометрической аутентификации. Подпись транзакции все так же потребует карту. - Сохранение кода доступа - Подключите функцию хранения кодов доступа от карт на телефоне в зашифрованном виде, и при работе с картой вместо кода доступа будет запрашиваться биометрическая аутентификация. - При отключении функции сохранения кошелька все ранее сохраненные кошельки будут удалены. - Все сохраненные коды доступа будут удалены. Вам потребуется вводить код доступа при работе с кошельком. - WalletConnect - Подключение к Dapps - Это действие приведет к полному удалению кошелька на этой карте. Кошелек невозможно будет восстановить или использовать данную карту для восстановления кода доступа - Я понимаю, что после выполнения этого действия у меня больше не будет доступа к текущему кошельку - Сбросить карту - Сброс к заводским настройкам - Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты. Вы не сможете восстановить текущий кошелек или использовать эту карту для восстановления кода доступа. - Выберите сеть - Отсканируйте карту - Чтобы получить доступ ко всем сетям, вам необходимо отсканировать карту - Cоединение с этим Dapp сервисом не может быть установлено из-за его технической реализации. - C возвращением! - Используйте %s или код доступа для входа в приложение - Войти с %s - Сканировать карту - Сохраните ваш кошелек - Вы хотите использовать %s? - Вы хотите использовать биометрию? - Доступ в приложение - Войдите в приложение и следите за своим балансом без сканирования карты - Код доступа - Для операций с вашим кошельком будет запрашиваться %s вместо кода доступа карты - Для операций с вашим кошельком будет запрашиваться биометрия вместо кода доступа карты - Обратите внимание, что для совершения транзакции с вашими средствами по-прежнему потребуется ваша карта - Использовать %s - Использовать биометрию - Новый функционал - Мои кошельки - Мультивалютные - Одновалютные - Добавить новый кошелек - Переименование кошелька - Имя кошелька - Разблокировать все с %s - Недопустимый Tag. Он не будет добавлен в транзакцию. - Недопустимый Memo. Он не будет добавлен в транзакцию. - Tag - Memo - Внимание - Приложите карту с логотипом Visa - Недостаточно средств для активации - Пожалуйста обратитесь в службу поддержки - Ввод одинаковых цифр является не безопасным - Данный Код доступа может быть легко взломан - Код доступа - Подключиться - Верификация клиента - Подтвердите свою личность - Установить Код доступа - Зарегистрироваться - Верифицировать (Utorg) - Обновить - Подключите свою карту - Подтвердите свою личность - Подтверждение личности в процессе - Подключите вашу карту к децентрализованной платежной системе - Для начала работы с картой вам необходимо завершить процесс подтверждения личности - Пожалуйста дождитесь завершения процесса подтверждения личности. Вы будете уведомлены через e-mail. Обычно это занимает не более часа. Вы можете закрыть приложение и вернуться позже. - Код доступа - Установите Код доступа для вашей SaltPay карты - Чат поддержки - Пожалуйста, удерживайте карту до завершения операции - Для начала процесса бэкапа вам необходимо добавить Tangem карту - Бэкап карта не добавлена - Бэкап карта создана - Завершите процесс бэкапа создав код доступа - Приготовьте SaltPay карту - Приложите SaltPay карту - Приложите Tangem карту - Чат - Запросить %s - Для начала работы просто запросите начисление wxDai на свой кошелек - Запросить - Поздравляем! Ваша платежная крипто карта теперь активирована! - Запрашивается - Это займет несколько секунд - Что-то пошло не так - Более подробная информация отправлена на ваш адрес электронной почты. - Вы хотите выйти из процесса активации? - В этом случае вам будет необходимо начать процесс заново. - Вы использовали карту от другого кошелька. Приложите карту, связанную с этим кошельком. - Реферальная программа - Приведи друга в Tangem - Вы - Получите - на ваш адрес в сети %s%s за каждый кошелек, который купит ваш друг - Ваш друг - Получит - %s скидку - при покупке карточки на сайте tangem.com - Ваши друзья купили - Ваш персональный код - Участвовать - условия участия - Нажимая на эту кнопку вы принимаете - Вы приняли - в реферальной программе - Внутренняя ошибка: не удается найти менеджер кошельков - Баланс: %s - Поделиться - Копировать - Успешно - Дать разрешение - Чтобы продолжить, вам нужно разрешить смарт-контракту 1inch использовать ваш %s - Количество %s - Ваш кошелек - Отправитель - Подтвердить - Обмен %s на - Обмен - Недостаточно средств - Дать разрешение - Разрешить и обменять - Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже. - Не удалось загрузить информацию по реферальной программе. Причина: %s. Пожалуйста, попробуйте позже. - Не удалось обработать вашу заявку на участие. Причина: %s. Пожалуйста, попробуйте позже. Если проблема сохранится, вы можете обратиться в техподдержку. - Персональный код скопирован! - Купи Tangem Wallet со скидкой!\n%s - Сеть %s использует концепцию экзистенциального депозита. Если баланс вашего счета опустится ниже %s, он будет деактивирован, а все оставшиеся средства будут уничтожены. - Неверный адрес - Этот кошелек уже был сохранен, вы можете добавить другой - Удалить - Privacy policy - Включите биометрическую аутентификацию - Похоже, что у вас отключена биометрическая аутентификация, она необходима для сохранения кошельков - Включить - Функция сохранения кошелька позволяет вам использовать свой кошелек с биометрической аутентификацией, не прикладывая карту к телефону для получения доступа. - %d выбрано - биометрическую аутентификацию - биометрией - Включите биометрическую аутентификацию - Перейдите в настройки, чтобы включить биометрическую аутентификацию в приложении Tangem App - Отсканируйте карту - diff --git a/core/res/src/main/res/values/strings-app.xml b/core/res/src/main/res/values/strings.xml similarity index 51% rename from core/res/src/main/res/values/strings-app.xml rename to core/res/src/main/res/values/strings.xml index 80bfd3967b..4027017a83 100644 --- a/core/res/src/main/res/values/strings-app.xml +++ b/core/res/src/main/res/values/strings.xml @@ -1,5 +1,223 @@ - + + Tangem Wallet + 3 cards + 2 cards + Shipping + Free + I have a promo code… + Total + Other payment methods + Buy now + Meet\nTangem + Buy + Store + Send + Pay + Exchange + Lend + Borrow + Revolutionary Hardware Wallet + Store your crypto assets secure while keeping private keys contained in your card + Ultra Secure Backup + Up to + 3 physical cards + to one wallet + Thousands of Currencies + A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card + DeFi Compatible + Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services + The Wallet for Everyone + Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. + Order + Search tokens + You are currently running in Demo mode. All funds are not real. + This feature is disabled in Demo mode + Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. + Available networks + %s network not found. Please, add it first and try again. + Attention + Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. + Tokens in Solana network are not supported by this card due to firmware limitation. + Contract address copied! + Contract address + Required field + Please select the network + Decimal number must be a valid integer, no higher than %d + Contract address is invalid + Derivation path is invalid + Note that tokens can be created by anyone. Be aware of adding scam tokens, they can cost nothing. + This token/network has already been added to your list + Decimals + Network + Not selected + E.g. USD Coin + Name + E.g. USDC + Token symbol + BIP44 coin type + Default + The server is not available, please try again later + Total balance + The amount does not include some of your funds + Tokens + Manage tokens + No rate + Network is unreachable + Hide token + Hide %s + Hide + You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. + Unable to hide %s + The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. + Your wallet has not been backed up + To protect your assets, we advise you to carry out this procedure + Retry + Chat + %s network + I understand + Yes + No + Russian bank cards are not accepted at the moment + Do you have a bank card of another country or a UnionPay card? + This network is not supported. Please select another network. + Card Settings + Security Mode + Change Access Code + Access code will be changed on this card only + Continue + Tangem Bot + Get your card ready! + Scan the card to change its settings. The changes will impact only the card you\'ve scanned and will not affect other cards tied to your wallet. + Scan Card + App Settings + Keep the wallet in the app + Enable to link all the wallets to Tangem app. Biometric authentication will be required for unlocking the app. Transaction signing requires tapping your Tangem card. + Save Access Code + Biometric authentication will be requested instead of the access code for interactions with your card. + Removing the saved card deletes all the saved wallets and their access codes. + This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. + WalletConnect + Connect to Dapps + This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + I understand that after performing this action, I will no longer have access to the current wallet + Reset the Card + Reset to Factory Settings + Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + Select network + Scan your card + To access all the networks you need to scan the card + Connection with this Dapp cannot be established due to its technical implementation. + Welcome back! + Use %s or scan a card to access the app + Log in with %s + Scan card + Access the app + Log into the app and check your balance without scanning the card + Access code + Note that making a transaction with your funds will still require your card + My Wallets + Multi-currency + Single-currency + Add new wallet + Rename Wallet + Wallet name + Unlock all with %s + Invalid Tag. It won\'t be added to the transaction. + Invalid Memo. It won\'t be added to the transaction. + Tag + Memo + Attention + Tap the card with the visa logo + No funds for activation + Please contact support + Four identical digits isn\'t safe + Such a PIN can be brute-forced easily + Pin code + Connect + KYC + Verify your identity + Set PIN code + Register + Verify via Utorg + Refresh + Connect your card + Verify your identity + KYC is in progress + Connect your card to the decentralized payment system + To start using your card you have to pass the KYC process + Please wait until the verification is completed. You\'ll be notified via email. Usually it takes up to 1 hour. You can close the app and come back later. + PIN Code + Set PIN code for your SaltPay card + Chat with support + Please hold the card until the operation complete + To start the backup process you have to add Tangem card as your backup + No backup card + Backup card ready + Finalize the backup process by creating an access code + Prepare the SaltPay card + Tap the SaltPay card + Tap the Tangem card + Support + Claim %s + To get started, simply claim wxDAI to your wallet + Claim + Congratulations! Your first payment crypto card has been activated! + Claiming + It will take a few seconds + Something went wrong + Please check your email for further instructions + Do you want to exit the activation process? + In this case, you will need to start from the beginning. + You have used a card from another wallet. Tap the card associated with this wallet + Referral program + Refer your friends to Tangem + You + Will get + for each wallet bought by your friend on your %s network address%s + Your friend + Will get a + %s discount + when buying a card on tangem.com + Your friends bought + Your personal code + Participate + terms and conditions + By tapping this button you accept + You\'ve accepted + of the referral program + Internal error: wallet manager not found + Balance: %s + Share + Copy + Success + Give Permission + To continue you need to allow 1inch smart contracts to use your %s + Amount %s + Your Wallet + Spender + Approve + Swap of %s to + Swap + Insufficient funds + Give Permission + Permit and Swap + Failed to load the information about the referral program. Please try again later. + Failed to load the information about the referral program. Reason: %s. Please try again later. + Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support. + Personal code copied! + Buy Tangem Wallet with discount!\n%s + %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. + Invalid address + This wallet has already been saved, you can add another one + Delete + Privacy policy + Enable biometric authorization + It looks like you have biometric authentication disabled, it is necessary to save wallets + Enable + %d selected + biometric authentication + biometrics Tangem Save changes Warning @@ -54,7 +272,7 @@ Long Tap This mechanism protects against proximity attacks on a card. It will enforce a delay between reception and execution of a command. Passcode - Before executing any command entailing a change of the card state you will have to enter the passcode. + Before executing any command entailing a change of the card state, you will have to enter the passcode. Access code You will have to submit the correct access code before scanning the card This card has been already topped up and signed transactions in the past. Consider immediate withdrawal of all funds if you have received this card from an untrusted source. If it\'s your card, there is nothing to worry about. @@ -97,7 +315,6 @@ Can\'t send a transaction Reason: %s Are you having difficulty scanning your card? - I\'m okay Request support Send feedback Really cool! @@ -216,7 +433,7 @@ Tangem feedback Feedback Tell us what functions you are missing, and we will try to help you. - Please tell us what card do you have? + Please tell us what card do you have Please tell us more about your issue. Every small detail can help. Hi support team, The following information is optional. You can erase it if you don\'t want to share it. @@ -226,6 +443,12 @@ Error OK Failed to establish WalletConnect session. Please, try again later. + Would you like to use biometrics? + Biometrics will be requested instead of the access code for interactions with your wallet + Allow to use biometrics + Enable biometric authentication + Go to settings to enable biometric authentication in the Tangem App + Scan the card %s diff --git a/core/res/src/main/res/values/strings_final.xml b/core/res/src/main/res/values/strings_final.xml deleted file mode 100644 index 673ced5d90..0000000000 --- a/core/res/src/main/res/values/strings_final.xml +++ /dev/null @@ -1,233 +0,0 @@ - - - Tangem Wallet - 3 cards - 2 cards - Shipping - Free - I have a promo code… - Total - Other payment methods - Buy now - Meet\nTangem - Buy - Store - Send - Pay - Exchange - Lend - Borrow - Revolutionary Hardware Wallet - Store your crypto assets secure while keeping private keys contained in your card - Ultra Secure Backup - Up to - 3 physical cards - to one wallet - Thousands of Currencies - A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card - DeFi Compatible - Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services - The Wallet for Everyone - Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. - Order - Search tokens - You are currently running in Demo mode. All funds are not real. - This feature is disabled in Demo mode - Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. - Available networks - %s network not found. Please, add it first and try again. - Attention - Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. - Tokens in Solana network are not supported by this card due to firmware limitation. - Contract address copied! - Contract address - Required field - Please select the network - Decimal number must be a valid integer, no higher than %d - Contract address is invalid - Derivation path is invalid - Note that tokens can be created by anyone. Be aware of adding scam tokens, they can cost nothing. - This token/network has already been added to your list - Decimals - Network - Not selected - E.g. USD Coin - Name - E.g. USDC - Token symbol - BIP44 coin type - Default - The server is not available, please try again later - Total balance - The amount does not include some of your funds - Tokens - Manage tokens - No rate - Network is unreachable - Hide token - Hide %s - Hide - You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. - Unable to hide %s - The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. - Your wallet has not been backed up - To protect your assets, we advise you to carry out this procedure - Retry - Chat - %s network - I understand - Yes - No - Russian bank cards are not accepted at the moment - Do you have a bank card of another country or a UnionPay card? - This network is not supported. Please select another network. - Card Settings - Security Mode - Change Access Code - Access code will be changed on this card only - Continue - Tangem Bot - Get your card ready! - Scan the card to change its settings. The changes will impact only the card you\'ve scanned and will not affect other cards tied to your wallet. - Scan Card - App Settings - Keep the wallet in the app - Enable to link all the wallets to Tangem app. Biometric authentication will be required for unlocking the app. Transaction signing requires tapping your Tangem card. - Save Access Code - Biometric authentication will be requested instead of the access code for interactions with your card. - Removing the saved card deletes all the saved wallets and their access codes. - This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. - WalletConnect - Connect to Dapps - This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - I understand that after performing this action, I will no longer have access to the current wallet - Reset the Card - Reset to Factory Settings - Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - Select network - Scan your card - To access all the networks you need to scan the card - Connection with this Dapp cannot be established due to its technical implementation. - Welcome back! - Use %s or scan a card to access the app - Log in with %s - Scan card - Save your wallet - Would you like to use %s? - Would you like to use biometrics? - Access the app - Log into the app and check your balance without scanning the card - Access code - %s will be requested instead of the access code for interactions with your wallet - Biometrics will be requested instead of the access code for interactions with your wallet - Note that making a transaction with your funds will still require your card - Allow to use %s - Allow to use biometrics - New feature - My Wallets - Multi-currency - Single-currency - Add new wallet - Rename Wallet - Wallet name - Unlock all with %s - Invalid Tag. It won\'t be added to the transaction. - Invalid Memo. It won\'t be added to the transaction. - Tag - Memo - Attention - Tap the card with the visa logo - No funds for activation - Please contact support - Four identical digits isn\'t safe - Such a PIN can be brute-forced easily - Pin code - Connect - KYC - Verify your identity - Set PIN code - Register - Verify via Utorg - Refresh - Connect your card - Verify your identity - KYC is in progress - Connect your card to the decentralized payment system - To start using your card you have to pass the KYC process - Please wait until the verification is completed. Usually it takes up to 1 hour. You can close the app and come back later. - PIN Code - Set PIN code for your SaltPay card - Chat with support - Please hold the card until the operation complete - To start the backup process you have to add Tangem card as your backup - No backup card - Backup card ready - Finalize the backup process by creating an access code - Prepare the SaltPay card - Tap the SaltPay card - Tap the Tangem card - Support - Claim %s - To get started, simply claim wxDAI to your wallet - Claim - Congratulations! Your first payment crypto card has been activated - Claiming - It will take a few seconds - Something went wrong - Please check your email for further instructions - Do you want to exit the activation process? - In this case, you will need to start from the beginning. - You have used a card from another wallet. Tap the card associated with this wallet - Referral program - Refer your friends to Tangem - You - Will get - for each wallet bought by your friend on your %s network address%s - Your friend - Will get a - %s discount - when buying a card on tangem.com - Your friends bought - Your personal code - Participate - terms and conditions - By tapping this button you accept - You\'ve accepted - of the referral program - Internal error: wallet manager not found - Balance: %s - Share - Copy - Success - Give Permission - To continue you need to allow 1inch smart contracts to use your %s - Amount %s - Your Wallet - Spender - Approve - Swap of %s to - Swap - Insufficient funds - Give Permission - Permit and Swap - Failed to load the information about the referral program. Please try again later. - Failed to load the information about the referral program. Reason: %s. Please try again later. - Your participation request could not be processed. Reason: %s. Please try again later. If the problem persists — feel free to contact our support. - Personal code copied! - Buy Tangem Wallet with discount!\n%s - %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. - Invalid address - This wallet has already been saved, you can add another one - Delete - Privacy policy - Enable biometric authorization - It looks like you have biometric authentication disabled, it is necessary to save wallets - Enable - Save your Wallet feature allows you to use your wallet with biometric auth without tapping your card to the phone to gain access. - %d selected - biometric authentication - biometrics - Enable biometric authentication - Go to settings to enable biometric authentication in the Tangem App - Scan the card - diff --git a/core/res/src/main/res/values/strings_plurals_final.xml b/core/res/src/main/res/values/strings_plurals.xml similarity index 100% rename from core/res/src/main/res/values/strings_plurals_final.xml rename to core/res/src/main/res/values/strings_plurals.xml From a0d7410df266d4da85ed92a64481e3b3bb139d4b Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 20 Dec 2022 11:37:56 +0300 Subject: [PATCH 16/19] Updated on 2026-08-14 --- .../cardsettings/CardSettingsScreenState.kt | 19 ++--- .../ui/cardsettings/CardSettingsViewModel.kt | 13 ++- .../details/ui/resetcard/ResetCardScreen.kt | 79 ++++++++----------- .../ui/resetcard/ResetCardScreenState.kt | 3 + .../ui/resetcard/ResetCardViewModel.kt | 6 ++ core/res/src/main/res/values-de/strings.xml | 6 +- core/res/src/main/res/values-fr/strings.xml | 6 +- core/res/src/main/res/values-it/strings.xml | 6 +- core/res/src/main/res/values-ru/strings.xml | 10 +-- core/res/src/main/res/values/strings.xml | 10 +-- 10 files changed, 83 insertions(+), 75 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreenState.kt index e7354df5c5..927780750e 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreenState.kt @@ -15,18 +15,18 @@ data class CardSettingsScreenState( ) sealed class CardInfo( - val titleRes: TextReference, val subtitle: TextReference, val clickable: Boolean = false, + val titleRes: TextReference, + val subtitle: TextReference, + val clickable: Boolean = false, ) { class CardId(subtitle: String) : CardInfo( titleRes = TextReference.Res(R.string.details_row_title_cid), - subtitle = TextReference - .Str(subtitle), + subtitle = TextReference.Str(subtitle), ) class Issuer(subtitle: String) : CardInfo( titleRes = TextReference.Res(R.string.details_row_title_issuer), - subtitle = TextReference - .Str(subtitle), + subtitle = TextReference.Str(subtitle), ) class SignedHashes(hashes: String) : CardInfo( @@ -34,10 +34,7 @@ sealed class CardInfo( subtitle = TextReference.Res(R.string.details_row_subtitle_signed_hashes_format, hashes), ) - class SecurityMode( - securityOption: SecurityOption, - clickable: Boolean, - ) : CardInfo( + class SecurityMode(securityOption: SecurityOption, clickable: Boolean) : CardInfo( titleRes = TextReference.Res(R.string.card_settings_security_mode), subtitle = TextReference.Res(securityOption.toTitleRes()), clickable = clickable, @@ -49,9 +46,9 @@ sealed class CardInfo( clickable = true, ) - object ResetToFactorySettings : CardInfo( + class ResetToFactorySettings(subtitle: TextReference.Res) : CardInfo( titleRes = TextReference.Res(R.string.card_settings_reset_card_to_factory), - subtitle = TextReference.Res(R.string.card_settings_reset_card_to_factory_footer), + subtitle = subtitle, clickable = true, ) } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt index 44f5cdb8d2..ce9da7f8b0 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt @@ -8,6 +8,7 @@ import com.tangem.tap.common.analytics.events.Settings import com.tangem.tap.common.redux.AppState import com.tangem.tap.features.details.redux.CardSettingsState import com.tangem.tap.features.details.redux.DetailsAction +import com.tangem.wallet.R import org.rekotlin.Store class CardSettingsViewModel(private val store: Store) { @@ -46,7 +47,17 @@ class CardSettingsViewModel(private val store: Store) { cardDetails.add(CardInfo.ChangeAccessCode) } if (state.resetCardAllowed) { - cardDetails.add(CardInfo.ResetToFactorySettings) + cardDetails.add( + CardInfo.ResetToFactorySettings( + subtitle = TextReference.Res( + if (state.card.backupStatus?.isActive == true) { + R.string.reset_card_with_backup_to_factory_message + } else { + R.string.reset_card_without_backup_to_factory_message + }, + ), + ), + ) } CardSettingsScreenState( diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt index 85d53a13eb..944e4c715f 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt @@ -32,77 +32,64 @@ import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold import com.tangem.wallet.R @Composable -fun ResetCardScreen( - state: ResetCardScreenState, - onBackPressed: () -> Unit, - modifier: Modifier = Modifier, -) { - SettingsScreensScaffold( - content = { ResetCardView(state = state, modifier = modifier) }, - onBackClick = onBackPressed, - backgroundColor = Color.Transparent, - ) +fun ResetCardScreen(state: ResetCardScreenState, onBackPressed: () -> Unit) { + SettingsScreensScaffold( + content = { ResetCardView(state = state) }, + onBackClick = onBackPressed, + backgroundColor = Color.Transparent, + ) } @Composable -fun ResetCardView( - state: ResetCardScreenState, - modifier: Modifier = Modifier, -) { +fun ResetCardView(state: ResetCardScreenState) { Column( - modifier = modifier + modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.SpaceBetween, ) { - Box( - modifier = modifier, - ) { + Box { Image( painter = painterResource(id = R.drawable.ic_reset_background), - contentDescription = "", - modifier = modifier.offset(y = (-82).dp), + contentDescription = null, + modifier = Modifier.offset(y = (-82).dp), ) ScreenTitle(titleRes = R.string.card_settings_reset_card_to_factory) } - Spacer( - modifier = modifier.weight(1f), - ) + Spacer(modifier = Modifier.weight(1f)) Column( - modifier = modifier - .offset(y = (-32).dp), + modifier = Modifier.offset(y = (-32).dp), verticalArrangement = Arrangement.Bottom, ) { Text( text = stringResource(id = R.string.common_attention), - modifier = modifier.padding(start = 20.dp, end = 20.dp), + modifier = Modifier.padding(start = 20.dp, end = 20.dp), style = TangemTypography.headline3, color = colorResource(id = R.color.text_primary_1), ) - Spacer(modifier = modifier.size(24.dp)) + Spacer(modifier = Modifier.size(24.dp)) Text( - text = stringResource(id = R.string.reset_card_to_factory_message), - modifier = modifier - .padding(start = 20.dp, end = 20.dp), + text = stringResource(id = state.descriptionResId), + modifier = Modifier.padding(start = 20.dp, end = 20.dp), style = TangemTypography.body1, color = colorResource(id = R.color.text_secondary), ) - Spacer(modifier = modifier.size(28.dp)) + Spacer(modifier = Modifier.size(28.dp)) Row( - modifier = modifier + modifier = Modifier .fillMaxWidth() .clickable( - onClick = { state.onAcceptWarningToggleClick(!state.accepted) }, - ) + onClick = { state.onAcceptWarningToggleClick(!state.accepted) }, + ) .padding(top = 16.dp, bottom = 16.dp), ) { IconToggleButton( checked = state.accepted, onCheckedChange = state.onAcceptWarningToggleClick, - modifier = modifier.padding(start = 20.dp, end = 20.dp), + modifier = Modifier.padding(start = 20.dp, end = 20.dp), ) { Icon( painter = painterResource( @@ -124,15 +111,13 @@ fun ResetCardView( text = stringResource(id = R.string.reset_card_to_factory_warning_message), style = TangemTypography.body2, color = colorResource(id = R.color.text_secondary), - modifier = modifier - .padding(end = 20.dp), + modifier = Modifier.padding(end = 20.dp), ) } - Spacer(modifier = modifier.size(16.dp)) + Spacer(modifier = Modifier.size(16.dp)) Box( - modifier = modifier - .padding(start = 16.dp, end = 16.dp, bottom = 32.dp), + modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 32.dp), ) { DetailsMainButton( title = stringResource(id = R.string.reset_card_to_factory_button_title), @@ -146,8 +131,14 @@ fun ResetCardView( @Composable @Preview -fun ResetCardScreenPreview( - -) { - ResetCardScreen(state = ResetCardScreenState(onAcceptWarningToggleClick = {}, accepted = true) {}, {}) +fun ResetCardScreenPreview() { + ResetCardScreen( + state = ResetCardScreenState( + descriptionResId = R.string.reset_card_without_backup_to_factory_message, + accepted = false, + onAcceptWarningToggleClick = {}, + onResetButtonClick = {}, + ), + onBackPressed = {}, + ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreenState.kt index f658eac463..54693e7557 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreenState.kt @@ -1,6 +1,9 @@ package com.tangem.tap.features.details.ui.resetcard +import androidx.annotation.StringRes + data class ResetCardScreenState( + @StringRes val descriptionResId: Int, val accepted: Boolean = false, val onAcceptWarningToggleClick: (Boolean) -> Unit, val onResetButtonClick: () -> Unit, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardViewModel.kt index 15f891dba3..1606631d68 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardViewModel.kt @@ -3,12 +3,18 @@ package com.tangem.tap.features.details.ui.resetcard import com.tangem.tap.common.redux.AppState import com.tangem.tap.features.details.redux.CardSettingsState import com.tangem.tap.features.details.redux.DetailsAction +import com.tangem.wallet.R import org.rekotlin.Store class ResetCardViewModel(private val store: Store) { fun updateState(state: CardSettingsState?): ResetCardScreenState { return ResetCardScreenState( + descriptionResId = if (state?.card?.backupStatus?.isActive == true) { + R.string.reset_card_with_backup_to_factory_message + } else { + R.string.reset_card_without_backup_to_factory_message + }, accepted = state?.resetConfirmed ?: false, onAcceptWarningToggleClick = { store.dispatch(DetailsAction.ResetToFactory.Confirm(it)) }, onResetButtonClick = { store.dispatch(DetailsAction.ResetToFactory.Proceed) }, diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index 9f2035db71..0bee218f2b 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -99,11 +99,11 @@ This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. WalletConnect Connect to Dapps - This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + Factory Reset will completely delete the wallet from the selected card and remove it from the app. You will not be able to restore the current wallet. + Factory Reset will completely delete the wallet from the selected card and remove it from the app. You will not be able to restore the current wallet or use the card to recover the access code. I understand that after performing this action, I will no longer have access to the current wallet Reset the Card Reset to Factory Settings - Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. Select network Scan your card To access all the networks you need to scan the card @@ -279,7 +279,7 @@ Diese Karte ist für die Zusammenarbeit mit Tangem nicht geeignet Die von Ihnen gescannte Karte ist eine Entwicklungskarte. Akzeptieren Sie sie nicht als Zahlungsmittel. Tippen um zu signieren - To create wallet, connect your phone and the card exactly as it shown above + To create the wallet tap the card as shown above and do not remove until the end of the operation Tippen Sie um den Zugangscode zu ändern Tippen Sie um den Passcode zu ändern Nutzungsbedingungen diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index cf498616e2..237e0965f6 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -99,11 +99,11 @@ This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. WalletConnect Connect to Dapps - This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + Factory Reset will completely delete the wallet from the selected card and remove it from the app. You will not be able to restore the current wallet. + Factory Reset will completely delete the wallet from the selected card and remove it from the app. You will not be able to restore the current wallet or use the card to recover the access code. I understand that after performing this action, I will no longer have access to the current wallet Reset the Card Reset to Factory Settings - Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. Select network Scan your card To access all the networks you need to scan the card @@ -279,7 +279,7 @@ Cette carte n\'est pas conçue pour fonctionner avec Tangem La carte que vous avez scannée est une carte de développement. Ne l\'acceptez pas comme paiement. Touchez pour signer - To create wallet, connect your phone and the card exactly as it shown above + To create the wallet tap the card as shown above and do not remove until the end of the operation Touchez, pour modifier le code d\'accès Touchez, pour modifier le mot de passe Conditions d\'utilisation diff --git a/core/res/src/main/res/values-it/strings.xml b/core/res/src/main/res/values-it/strings.xml index af7ce360a9..d6b0c63ee0 100644 --- a/core/res/src/main/res/values-it/strings.xml +++ b/core/res/src/main/res/values-it/strings.xml @@ -99,11 +99,11 @@ This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. WalletConnect Connect to Dapps - This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + Factory Reset will completely delete the wallet from the selected card and remove it from the app. You will not be able to restore the current wallet. + Factory Reset will completely delete the wallet from the selected card and remove it from the app. You will not be able to restore the current wallet or use the card to recover the access code. I understand that after performing this action, I will no longer have access to the current wallet Reset the Card Reset to Factory Settings - Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. Select network Scan your card To access all the networks you need to scan the card @@ -279,7 +279,7 @@ Questa carta non è progettata per funzionare con Tangem La carta che hai scansionato è una carta di sviluppo. Non utilizzarla come strumento di pagamento. Avvicina per firmare - To create wallet, connect your phone and the card exactly as it shown above + To create the wallet tap the card as shown above and do not remove until the end of the operation Avvicina per modificare il codice di accesso Avvicina per modificare la password Termini del servizio diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index a715487104..177687671b 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -99,11 +99,11 @@ Все сохраненные коды доступа будут удалены. Вам потребуется вводить код доступа при работе с кошельком. WalletConnect Подключение к Dapps - Это действие приведет к полному удалению кошелька на этой карте. Кошелек невозможно будет восстановить или использовать данную карту для восстановления кода доступа + Сброс к заводским настройкам приведет к полному удалению кошелька на этой карте, а также отвязыванию карты из приложения. Кошелек невозможно будет восстановить. + Сброс к заводским настройкам приведет к полному удалению кошелька на этой карте, а также отвязыванию карты из приложения. Кошелек невозможно будет восстановить или использовать данную карту для восстановления кода доступа. Я понимаю, что после выполнения этого действия у меня больше не будет доступа к текущему кошельку Сбросить карту Сброс к заводским настройкам - Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты. Вы не сможете восстановить текущий кошелек или использовать эту карту для восстановления кода доступа. Выберите сеть Отсканируйте карту Чтобы получить доступ ко всем сетям, вам необходимо отсканировать карту @@ -279,9 +279,9 @@ Эта карта не предназначена для работы с этим приложением Карта, которую вы отсканировали, является картой разработчика. Не принимайте её в качестве оплаты. Нажмите, чтобы подписать - Чтобы создать кошелек, соедините телефон и карту в точности, как показано выше. - Чтобы изменить код доступа, соедините телефон и карту в точности, как показано выше. - Чтобы изменить пароль, соедините телефон и карту в точности, как показано выше. + Чтобы создать кошелек, приложите карту как показано выше и не убирайте до окончания операции + Чтобы изменить код доступа, приложите карту как показано выше и не убирайте до окончания операции + Чтобы изменить пароль, приложите карту как показано выше и не убирайте до окончания операции Условия использования Нет соединения с интернетом PayString не поддерживается блокчейном diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 4027017a83..f2d00c18af 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -99,11 +99,11 @@ This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. WalletConnect Connect to Dapps - This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + Factory Reset will completely delete the wallet from the selected card and remove it from the app. You will not be able to restore the current wallet. + Factory Reset will completely delete the wallet from the selected card and remove it from the app. You will not be able to restore the current wallet or use the card to recover the access code. I understand that after performing this action, I will no longer have access to the current wallet Reset the Card Reset to Factory Settings - Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. Select network Scan your card To access all the networks you need to scan the card @@ -279,9 +279,9 @@ This card is not designed to work with this app The card you scanned is a development card. Don\'t accept it as a payment. Tap to sign - To create wallet, connect your phone and the card exactly as it shown above - To change the access code, connect your phone and the card exactly as it shown above - To change the passcode, connect your phone and the card exactly as it shown above + To create the wallet tap the card as shown above and do not remove until the end of the operation + To change the access code tap the card as shown above and do not remove until the end of the operation + To change the passcode tap the card as shown above and do not remove until the end of the operation Terms of Service No internet connection PayString unsupported by blockchain From 3e0385dc7f5977eb2d09c18344e41704e5ce42af Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Dec 2022 10:40:02 +0300 Subject: [PATCH 17/19] Updated on 2026-08-14 --- .../redux/reducers/MultiWalletReducer.kt | 62 +++++++++---------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt index 7cb35da559..afb523a5ca 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt @@ -1,12 +1,15 @@ package com.tangem.tap.features.wallet.redux.reducers +import com.google.firebase.crashlytics.FirebaseCrashlytics import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.Token import com.tangem.blockchain.common.WalletManager -import com.tangem.common.extensions.guard +import com.tangem.tap.common.extensions.dispatchToastNotification import com.tangem.tap.common.extensions.toFiatString import com.tangem.tap.common.extensions.toFormattedCurrencyString +import com.tangem.tap.common.redux.navigation.AppScreen +import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.wallet.models.Currency @@ -25,6 +28,8 @@ import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData import com.tangem.tap.features.wallet.ui.TokenData import com.tangem.tap.store +import com.tangem.tap.userWalletsListManager +import com.tangem.wallet.R import java.math.BigDecimal class MultiWalletReducer { @@ -106,16 +111,22 @@ class MultiWalletReducer { newState } } - is WalletAction.MultiWallet.AddTokens -> { - addTokens(action.tokens, action.blockchain, state) - } - is WalletAction.MultiWallet.AddToken -> { - addTokens(listOf(action.token), action.blockchain, state) - } + is WalletAction.MultiWallet.AddTokens -> addTokens(action.tokens, action.blockchain, state) + is WalletAction.MultiWallet.AddToken -> addTokens(listOf(action.token), action.blockchain, state) is WalletAction.MultiWallet.TokenLoaded -> { val currency = Currency.fromBlockchainNetwork(action.blockchain, action.token) - val walletManager = state.getWalletManager(currency).guard { - throw NullPointerException("MultiWallet.TokenLoaded: WalletManager must be not NULL") + val walletManager = state.getWalletManager(currency) + if (walletManager == null) { + if (userWalletsListManager.hasSavedUserWallets) { + store.dispatch(NavigationAction.PopBackTo(screen = AppScreen.Welcome)) + } else { + store.dispatch(NavigationAction.PopBackTo(screen = AppScreen.Home)) + } + FirebaseCrashlytics.getInstance().recordException( + IllegalStateException("MultiWallet.TokenLoaded: walletManager is null"), + ) + store.dispatchToastNotification(R.string.internal_error_wallet_manager_not_found) + return state } val wallet = walletManager.wallet val pendingTransactions = wallet.getPendingTransactions() @@ -170,41 +181,28 @@ class MultiWalletReducer { action.currencies.forEach { updatedState = updatedState.removeWalletData(state.getWalletData(it)) } updatedState } - is WalletAction.MultiWallet.SetPrimaryBlockchain -> - state.copy(primaryBlockchain = action.blockchain) - - is WalletAction.MultiWallet.SetPrimaryToken -> - state.copy(primaryToken = action.token) + is WalletAction.MultiWallet.SetPrimaryBlockchain -> state.copy(primaryBlockchain = action.blockchain) + is WalletAction.MultiWallet.SetPrimaryToken -> state.copy(primaryToken = action.token) is WalletAction.MultiWallet.SaveCurrencies -> state - is WalletAction.MultiWallet.ShowWalletBackupWarning -> state.copy( - showBackupWarning = action.show, - ) - is WalletAction.MultiWallet.AddMissingDerivations -> state.copy( - missingDerivations = action.blockchains, - ) + is WalletAction.MultiWallet.ShowWalletBackupWarning -> state.copy(showBackupWarning = action.show) + is WalletAction.MultiWallet.AddMissingDerivations -> state.copy(missingDerivations = action.blockchains) is WalletAction.MultiWallet.BackupWallet -> state - is WalletAction.MultiWallet.ScanToGetDerivations -> state.copy( - state = ProgressState.Loading, - ) + is WalletAction.MultiWallet.ScanToGetDerivations -> state.copy(state = ProgressState.Loading) } } private fun findWalletRent(walletStore: WalletStore?): WalletRent? { - return walletStore?.walletsData?.firstOrNull { - it.walletRent != null - }?.walletRent + return walletStore?.walletsData?.firstOrNull { it.walletRent != null }?.walletRent } private fun getExistentialDeposit(walletManager: WalletManager?): String? { return (walletManager as? ExistentialDepositProvider)?.getExistentialDeposit()?.toPlainString() } -} -private fun addTokens( - tokens: List, blockchain: BlockchainNetwork, state: WalletState, -): WalletState { - val wallets = tokens.mapNotNull { token -> token.toWallet(state, blockchain) } - return state.updateWalletsData(wallets) + private fun addTokens(tokens: List, blockchain: BlockchainNetwork, state: WalletState): WalletState { + val wallets = tokens.mapNotNull { token -> token.toWallet(state, blockchain) } + return state.updateWalletsData(wallets) + } } fun Token.toWallet(state: WalletState, blockchain: BlockchainNetwork): WalletData? { From 7d56fc1efa8ccc56ff5c80a049bc975fe1a5702c Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 30 Dec 2022 15:28:55 +0300 Subject: [PATCH 18/19] Updated on 2026-08-14 --- .../tap/common/redux/navigation/NavigationMiddleware.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt index 871ef1ea5c..28357c1efd 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt @@ -57,11 +57,8 @@ val navigationMiddleware: Middleware = { _, state -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> { Settings.ACTION_BIOMETRIC_ENROLL } - Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> { - Settings.ACTION_FINGERPRINT_ENROLL - } else -> { - Settings.ACTION_SETTINGS + Settings.ACTION_SECURITY_SETTINGS } } val intent = Intent(settingsAction).apply { From 92b721ecad128e62d3aa03d35b8e52b3ec4a421e Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 30 Dec 2022 16:29:09 +0400 Subject: [PATCH 19/19] Updated on 2026-08-14 --- .../tangem/tap/features/wallet/ui/WalletFragment.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index 8a67196de1..f01805dd39 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.wallet.ui +import android.content.Context import android.os.Bundle import android.view.Menu import android.view.MenuInflater @@ -9,6 +10,7 @@ import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.transition.TransitionInflater @@ -60,6 +62,13 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber() + override fun onAttach(context: Context) { + super.onAttach(context) + activity?.lifecycleScope?.launchWhenCreated { + viewModel.launch() + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) @@ -82,7 +91,6 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber