diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/di/UserWalletsListManagerProvider.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/di/UserWalletsListManagerProvider.kt index 28475b75fa..3773da7127 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/di/UserWalletsListManagerProvider.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/di/UserWalletsListManagerProvider.kt @@ -14,10 +14,13 @@ import com.tangem.tap.domain.userWalletList.repository.implementation.BiometricU import com.tangem.tap.domain.userWalletList.repository.implementation.DefaultSelectedUserWalletRepository import com.tangem.tap.domain.userWalletList.repository.implementation.DefaultUserWalletsPublicInformationRepository import com.tangem.tap.domain.userWalletList.repository.implementation.DefaultUserWalletsSensitiveInformationRepository -import com.tangem.tap.domain.userWalletList.utils.json.* +import com.tangem.tap.domain.userWalletList.utils.json.ByteArrayKeyAdapter +import com.tangem.tap.domain.userWalletList.utils.json.CardBackupStatusAdapter +import com.tangem.tap.domain.userWalletList.utils.json.ExtendedPublicKeysMapAdapter +import com.tangem.tap.domain.userWalletList.utils.json.ScanResponseDerivedKeysMapAdapter +import com.tangem.tap.domain.userWalletList.utils.json.WalletDerivedKeysMapAdapter -const val USER_WALLETS_STORAGE_NAME = "user_wallets_storage" -const val USER_WALLETS_BIOMETRIC_KEY_NAME = "user_wallets" +private const val USER_WALLETS_STORAGE_NAME = "user_wallets_storage" fun UserWalletsListManager.Companion.provideBiometricImplementation( context: Context, @@ -43,7 +46,6 @@ fun UserWalletsListManager.Companion.provideBiometricImplementation( ) val keysRepository = BiometricUserWalletsKeysRepository( - biometricKeyName = USER_WALLETS_BIOMETRIC_KEY_NAME, moshi = moshi, secureStorage = secureStorage, biometricManager = tangemSdkManager.biometricManager, @@ -61,7 +63,6 @@ fun UserWalletsListManager.Companion.provideBiometricImplementation( ) return BiometricUserWalletsListManager( - tangemSdkManager = tangemSdkManager, keysRepository = keysRepository, publicInformationRepository = publicInformationRepository, sensitiveInformationRepository = sensitiveInformationRepository, 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 2267ab620b..a13cd492d0 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.domain.common.util.encryptionKey -import com.tangem.tap.domain.TangemSdkManager import com.tangem.tap.domain.model.UserWallet import com.tangem.tap.domain.userWalletList.UserWalletListError import com.tangem.tap.domain.userWalletList.UserWalletsListManager @@ -20,7 +19,6 @@ import timber.log.Timber @OptIn(ExperimentalCoroutinesApi::class) internal class BiometricUserWalletsListManager( - private val tangemSdkManager: TangemSdkManager, private val keysRepository: UserWalletsKeysRepository, private val publicInformationRepository: UserWalletsPublicInformationRepository, private val sensitiveInformationRepository: UserWalletsSensitiveInformationRepository, @@ -83,7 +81,6 @@ internal class BiometricUserWalletsListManager( } override fun lock() { - tangemSdkManager.biometricManager.unauthenticate() state.update { prevState -> prevState.copy( encryptionKeys = emptyList(), @@ -122,14 +119,15 @@ internal class BiometricUserWalletsListManager( if (isWalletSaved && !canOverride) { CompletionResult.Failure(UserWalletListError.WalletAlreadySaved) } else { - keysRepository.save( - walletId = userWallet.walletId, - encryptionKey = userWallet.scanResponse.card.encryptionKey, - ) - .doOnSuccess { keys -> + val newEncryptionKeys = state.value.encryptionKeys + .plus(UserWalletEncryptionKey(userWallet.walletId, userWallet.scanResponse.card.encryptionKey)) + .distinctBy { it.walletId } + + keysRepository.store(newEncryptionKeys) + .doOnSuccess { state.update { prevState -> prevState.copy( - encryptionKeys = (keys + prevState.encryptionKeys).distinctBy { it.walletId }, + encryptionKeys = newEncryptionKeys, ) } } @@ -146,21 +144,22 @@ internal class BiometricUserWalletsListManager( val walletIdsToRemove = state.value.wallets .map { it.walletId } .filter { it in walletIds } + val remainingEncryptionKeys = state.value.encryptionKeys + .filter { it.walletId !in walletIdsToRemove } changeSelectedWalletIfNeeded(walletIdsToRemove) return sensitiveInformationRepository.delete(walletIdsToRemove) .flatMap { publicInformationRepository.delete(walletIdsToRemove) } - .flatMap { keysRepository.delete(walletIdsToRemove) } - .map { keys -> + .flatMap { keysRepository.store(remainingEncryptionKeys) } + .map { state.update { prevState -> prevState.copy( - encryptionKeys = keys, + encryptionKeys = remainingEncryptionKeys, wallets = prevState.wallets.filter { it.walletId !in walletIdsToRemove }, ) } } - .flatMap { loadModels() } } override suspend fun clear(): CompletionResult { @@ -171,12 +170,11 @@ internal class BiometricUserWalletsListManager( .flatMap { keysRepository.clear() } .map { selectedUserWalletRepository.set(null) - tangemSdkManager.biometricManager.unauthenticate() state.update { State() } } } - override suspend fun get(walletId: UserWalletId): CompletionResult = withUnlock { + override suspend fun get(walletId: UserWalletId): CompletionResult { return catching { state.value.wallets.first { it.walletId == walletId } } 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 9fc67b367b..974879ca31 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 @@ -1,12 +1,10 @@ package com.tangem.tap.domain.userWalletList.repository import com.tangem.common.CompletionResult -import com.tangem.domain.common.util.UserWalletId import com.tangem.tap.domain.userWalletList.model.UserWalletEncryptionKey internal interface UserWalletsKeysRepository { suspend fun getAll(): CompletionResult> - suspend fun save(walletId: UserWalletId, encryptionKey: ByteArray): CompletionResult> - suspend fun delete(walletIds: List): CompletionResult> + suspend fun store(encryptionKeys: List): CompletionResult suspend fun clear(): CompletionResult } \ 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 e1a2ae7329..cd39605d96 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 @@ -6,24 +6,19 @@ import com.squareup.moshi.Types import com.tangem.common.CompletionResult import com.tangem.common.biometric.BiometricManager import com.tangem.common.biometric.BiometricStorage -import com.tangem.common.flatMap import com.tangem.common.map import com.tangem.common.mapFailure import com.tangem.common.services.secure.SecureStorage -import com.tangem.domain.common.util.UserWalletId -import com.tangem.tap.common.extensions.replaceByOrAdd import com.tangem.tap.domain.userWalletList.UserWalletListError import com.tangem.tap.domain.userWalletList.model.UserWalletEncryptionKey import com.tangem.tap.domain.userWalletList.repository.UserWalletsKeysRepository internal class BiometricUserWalletsKeysRepository( - biometricKeyName: String, moshi: Moshi, secureStorage: SecureStorage, biometricManager: BiometricManager, ) : UserWalletsKeysRepository { private val biometricStorage = BiometricStorage( - biometricKeyName = biometricKeyName, biometricManager = biometricManager, secureStorage = secureStorage, ) @@ -41,50 +36,16 @@ internal class BiometricUserWalletsKeysRepository( } } - override suspend fun save( - walletId: UserWalletId, - encryptionKey: ByteArray, - ): CompletionResult> { - return getAll() - .flatMap { keys -> - if (keys.any { it.walletId == walletId }) { - return@flatMap CompletionResult.Success(Unit) - } - - val encodedKeys = keys.toMutableList() - .apply { - replaceByOrAdd(UserWalletEncryptionKey(walletId, encryptionKey)) { - it.walletId == walletId - } - } - .encode() - - biometricStorage.store( - key = StorageKey.WalletEncryptionKeys.name, - data = encodedKeys, - ) - } - .flatMap { getAll() } + override suspend fun store(encryptionKeys: List): CompletionResult { + return biometricStorage.store( + key = StorageKey.WalletEncryptionKeys.name, + data = encryptionKeys.encode(), + ) .mapFailure { error -> UserWalletListError.SaveEncryptionKeysError(error.cause ?: error) } } - override suspend fun delete(walletIds: List): CompletionResult> { - return getAll() - .map { keys -> - val keysToRemove = keys.filter { it.walletId in walletIds }.toSet() - (keys - keysToRemove).encode() - } - .flatMap { encodedKeys -> - biometricStorage.store( - key = StorageKey.WalletEncryptionKeys.name, - data = encodedKeys, - ) - } - .flatMap { getAll() } - } - override suspend fun clear(): CompletionResult { return biometricStorage.delete(key = StorageKey.WalletEncryptionKeys.name) }