Updated on 2026-08-14
This commit is contained in:
commit
c50439d698
7 changed files with 52 additions and 35 deletions
|
|
@ -8,11 +8,15 @@ internal class DelegatedKeystoreManager(
|
||||||
private val keystoreManagerProvider: Provider<KeystoreManager>,
|
private val keystoreManagerProvider: Provider<KeystoreManager>,
|
||||||
) : KeystoreManager {
|
) : KeystoreManager {
|
||||||
|
|
||||||
override suspend fun authenticateAndGetKey(keyAlias: String): SecretKey? {
|
override suspend fun get(keyAlias: String): SecretKey? {
|
||||||
return keystoreManagerProvider().authenticateAndGetKey(keyAlias)
|
return keystoreManagerProvider().get(keyAlias)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun storeKey(keyAlias: String, key: SecretKey) {
|
override suspend fun get(keyAliases: Collection<String>): Map<String, SecretKey> {
|
||||||
keystoreManagerProvider().storeKey(keyAlias, key)
|
return keystoreManagerProvider().get(keyAliases)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun store(keyAlias: String, key: SecretKey) {
|
||||||
|
return keystoreManagerProvider().store(keyAlias, key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -81,41 +81,38 @@ internal class BiometricUserWalletsKeysRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getAllInternal(): CompletionResult<List<UserWalletEncryptionKey>> {
|
private suspend fun getAllInternal(): CompletionResult<List<UserWalletEncryptionKey>> {
|
||||||
return getUserWalletsIds()
|
return catching {
|
||||||
.map { userWalletId ->
|
val userWalletIds = getUserWalletsIds()
|
||||||
getEncryptionKey(userWalletId)
|
|
||||||
.doOnFailure { error ->
|
|
||||||
when (error) {
|
|
||||||
is TangemSdkError.UserCanceledAuthentication -> {
|
|
||||||
// If the user cancels biometric authentication, then cancel operation with error
|
|
||||||
return CompletionResult.Failure(error)
|
|
||||||
}
|
|
||||||
is TangemSdkError.KeystoreInvalidated -> {
|
|
||||||
// If the biometric cryptography key was invalidated,
|
|
||||||
// then delete all user wallets encryption keys and cancel operation with error
|
|
||||||
getUserWalletsIds().forEach { userWalletId ->
|
|
||||||
deleteEncryptionKey(userWalletId)
|
|
||||||
}
|
|
||||||
|
|
||||||
return CompletionResult.Failure(error)
|
getEncryptionKeys(userWalletIds)
|
||||||
}
|
}
|
||||||
|
.doOnFailure { error ->
|
||||||
|
when (error) {
|
||||||
|
is TangemSdkError.KeystoreInvalidated -> {
|
||||||
|
// If the biometric cryptography key was invalidated, then delete all encryption keys
|
||||||
|
getUserWalletsIds().forEach { userWalletId ->
|
||||||
|
deleteEncryptionKey(userWalletId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else -> Unit
|
||||||
.fold(listOf()) { acc, data ->
|
}
|
||||||
if (data != null) acc + data else acc
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getEncryptionKey(userWalletId: UserWalletId): CompletionResult<UserWalletEncryptionKey?> {
|
private suspend fun getEncryptionKeys(userWalletsIds: List<UserWalletId>): List<UserWalletEncryptionKey> {
|
||||||
return catching { authenticatedStorage.get(StorageKey.UserWalletEncryptionKey(userWalletId).name) }
|
val keys = userWalletsIds.map { userWalletId ->
|
||||||
.map { it.decodeToKey() }
|
StorageKey.UserWalletEncryptionKey(userWalletId).name
|
||||||
|
}
|
||||||
|
|
||||||
|
return authenticatedStorage.get(keys).mapNotNull { (_, encodedData) ->
|
||||||
|
encodedData.decodeToKey()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun storeEncryptionKey(encryptionKey: UserWalletEncryptionKey): CompletionResult<Unit> {
|
private suspend fun storeEncryptionKey(encryptionKey: UserWalletEncryptionKey): CompletionResult<Unit> {
|
||||||
return catching {
|
return catching {
|
||||||
authenticatedStorage.store(
|
authenticatedStorage.store(
|
||||||
key = StorageKey.UserWalletEncryptionKey(encryptionKey.walletId).name,
|
keyAlias = StorageKey.UserWalletEncryptionKey(encryptionKey.walletId).name,
|
||||||
data = encryptionKey.encode(),
|
data = encryptionKey.encode(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,12 @@ package com.tangem.tap.proxy
|
||||||
import androidx.core.text.isDigitsOnly
|
import androidx.core.text.isDigitsOnly
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import com.tangem.Message
|
import com.tangem.Message
|
||||||
|
import com.tangem.blockchain.blockchains.algorand.AlgorandTransactionExtras
|
||||||
import com.tangem.blockchain.blockchains.binance.BinanceTransactionExtras
|
import com.tangem.blockchain.blockchains.binance.BinanceTransactionExtras
|
||||||
import com.tangem.blockchain.blockchains.cosmos.CosmosTransactionExtras
|
import com.tangem.blockchain.blockchains.cosmos.CosmosTransactionExtras
|
||||||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||||
|
import com.tangem.blockchain.blockchains.hedera.HederaTransactionBuilder
|
||||||
import com.tangem.blockchain.blockchains.optimism.OptimismWalletManager
|
import com.tangem.blockchain.blockchains.optimism.OptimismWalletManager
|
||||||
import com.tangem.blockchain.blockchains.stellar.StellarMemo
|
import com.tangem.blockchain.blockchains.stellar.StellarMemo
|
||||||
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
|
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
|
||||||
|
|
@ -138,6 +140,8 @@ class TransactionManagerImpl(
|
||||||
Blockchain.XRP -> memo.toLongOrNull()?.let { XrpTransactionBuilder.XrpTransactionExtras(it) }
|
Blockchain.XRP -> memo.toLongOrNull()?.let { XrpTransactionBuilder.XrpTransactionExtras(it) }
|
||||||
Blockchain.Cosmos -> CosmosTransactionExtras(memo)
|
Blockchain.Cosmos -> CosmosTransactionExtras(memo)
|
||||||
Blockchain.TON -> TonTransactionExtras(memo)
|
Blockchain.TON -> TonTransactionExtras(memo)
|
||||||
|
Blockchain.Hedera -> HederaTransactionBuilder.HederaTransactionExtras(memo)
|
||||||
|
Blockchain.Algorand -> AlgorandTransactionExtras(memo)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ internal object AccountCreatorModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideAccountCreator(authProvider: AuthProvider, @DevTangemApi tangemTechApi: TangemTechApi): AccountCreator {
|
fun provideAccountCreator(authProvider: AuthProvider, tangemTechApi: TangemTechApi): AccountCreator {
|
||||||
return DefaultAccountCreator(authProvider, tangemTechApi)
|
return DefaultAccountCreator(authProvider, tangemTechApi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -915,10 +915,10 @@ internal class StateBuilder(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addAlert(uiState: SwapStateHolder, onClick: () -> Unit): SwapStateHolder {
|
fun addAlert(uiState: SwapStateHolder, message: TextReference? = null, onClick: () -> Unit): SwapStateHolder {
|
||||||
return uiState.copy(
|
return uiState.copy(
|
||||||
alert = SwapWarning.GenericWarning(
|
alert = SwapWarning.GenericWarning(
|
||||||
message = null,
|
message = message,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import arrow.core.getOrElse
|
||||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||||
import com.tangem.core.analytics.models.AnalyticsParam
|
import com.tangem.core.analytics.models.AnalyticsParam
|
||||||
import com.tangem.core.analytics.models.Basic
|
import com.tangem.core.analytics.models.Basic
|
||||||
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.utils.InputNumberFormatter
|
import com.tangem.core.ui.utils.InputNumberFormatter
|
||||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
|
|
@ -119,7 +120,7 @@ internal class SwapViewModel @Inject constructor(
|
||||||
val cryptoCurrencyStatus =
|
val cryptoCurrencyStatus =
|
||||||
getCryptoCurrencyStatusUseCase(it.walletId, initialCryptoCurrency.id).getOrNull()
|
getCryptoCurrencyStatusUseCase(it.walletId, initialCryptoCurrency.id).getOrNull()
|
||||||
if (cryptoCurrencyStatus == null) {
|
if (cryptoCurrencyStatus == null) {
|
||||||
uiState = stateBuilder.addAlert(uiState, swapRouter::back)
|
uiState = stateBuilder.addAlert(uiState = uiState, onClick = swapRouter::back)
|
||||||
} else {
|
} else {
|
||||||
initialCryptoCurrencyStatus = cryptoCurrencyStatus
|
initialCryptoCurrencyStatus = cryptoCurrencyStatus
|
||||||
initTokens()
|
initTokens()
|
||||||
|
|
@ -482,7 +483,12 @@ internal class SwapViewModel @Inject constructor(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val fromCurrency = requireNotNull(dataState.fromCryptoCurrency)
|
val fromCurrency = requireNotNull(dataState.fromCryptoCurrency)
|
||||||
val fee = requireNotNull(dataState.selectedFee)
|
val fee = dataState.selectedFee
|
||||||
|
// TODO: unexpected crash for some users, this workaround to prevent app crash and follow to support
|
||||||
|
if (fee == null) {
|
||||||
|
makeDefaultAlert(TextReference.Str("Fee estimation error. Please send feedback to support."))
|
||||||
|
return
|
||||||
|
}
|
||||||
viewModelScope.launch(dispatchers.main) {
|
viewModelScope.launch(dispatchers.main) {
|
||||||
runCatching(dispatchers.io) {
|
runCatching(dispatchers.io) {
|
||||||
swapInteractor.onSwap(
|
swapInteractor.onSwap(
|
||||||
|
|
@ -821,6 +827,12 @@ internal class SwapViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun makeDefaultAlert(message: TextReference) {
|
||||||
|
uiState = stateBuilder.addAlert(uiState, message) {
|
||||||
|
uiState = stateBuilder.clearAlert(uiState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||||
private fun createUiActions(): UiActions {
|
private fun createUiActions(): UiActions {
|
||||||
return UiActions(
|
return UiActions(
|
||||||
|
|
|
||||||
|
|
@ -85,9 +85,9 @@ web3j = "4.10.1"
|
||||||
# endregion Other libraries
|
# endregion Other libraries
|
||||||
|
|
||||||
# region Tangem
|
# region Tangem
|
||||||
tangemBlockchainSdk = "develop-510"
|
tangemBlockchainSdk = "develop-514"
|
||||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||||
tangemCardSdk = "develop-331"
|
tangemCardSdk = "develop-332"
|
||||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||||
# endregion Tangem
|
# endregion Tangem
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue