Updated on 2026-08-14

This commit is contained in:
Tangem 2023-05-12 14:56:52 +03:00
commit 3544354a97
9 changed files with 34 additions and 52 deletions

View file

@ -14,6 +14,7 @@ import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.setContext
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.model.UserWallet
import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
import com.tangem.tap.domain.walletStores.WalletStoresError
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
import com.tangem.tap.features.disclaimer.createDisclaimer
@ -36,7 +37,10 @@ class TapWalletManager {
suspend fun onWalletSelected(userWallet: UserWallet, refresh: Boolean, sendAnalyticsEvent: Boolean) {
// do nothing if its the same wallet
if (store.state.globalState.scanResponse == userWallet.scanResponse) return
store.state.globalState.scanResponse?.let {
val userWalletId = UserWalletIdBuilder.scanResponse(it).build()
if (userWalletId == userWallet.walletId) return
}
Analytics.setContext(userWallet.scanResponse)
if (sendAnalyticsEvent) {

View file

@ -54,16 +54,6 @@ internal class BiometricUserWalletsListManager(
get() = keysRepository.hasSavedEncryptionKeys()
override suspend fun unlock(): CompletionResult<UserWallet> {
// Occurs when user has locked user wallets after unlocking with biometry
// e.g. after biometric storage master key invalidation
if (state.value.hasLockedUserWalletsAfterUnlock) {
return CompletionResult.Failure(
error = UserWalletsListError.UnableToUnlockUserWallets(
cause = IllegalStateException("Permanently locked"),
),
)
}
return unlockWithBiometryInternal()
.mapFailure { error ->
if (error is UserWalletsListError) {
@ -216,10 +206,7 @@ internal class BiometricUserWalletsListManager(
.map {
state.update { prevState ->
val hasLockedUserWallets = prevState.userWallets.any { it.isLocked }
prevState.copy(
isLocked = hasLockedUserWallets,
hasLockedUserWalletsAfterUnlock = hasLockedUserWallets,
)
prevState.copy(isLocked = hasLockedUserWallets)
}
}
}
@ -262,15 +249,6 @@ internal class BiometricUserWalletsListManager(
}
}
}
.doOnFailure { error ->
if (error is UserWalletsListError.EncryptionKeyInvalidated) {
state.update { prevState ->
prevState.copy(
hasLockedUserWalletsAfterUnlock = true,
)
}
}
}
}
private suspend fun getSavedUserWallets(): CompletionResult<List<UserWallet>> {
@ -334,6 +312,5 @@ internal class BiometricUserWalletsListManager(
val userWallets: List<UserWallet> = emptyList(),
val selectedUserWalletId: UserWalletId? = null,
val isLocked: Boolean = true,
val hasLockedUserWalletsAfterUnlock: Boolean = false,
)
}

View file

@ -10,6 +10,7 @@ import com.tangem.core.analytics.Analytics
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.tap.*
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.extensions.dispatchDialogShow
@ -31,14 +32,6 @@ 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
import com.tangem.tap.features.wallet.redux.WalletAction
import com.tangem.tap.foregroundActivityObserver
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
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
@ -84,6 +77,8 @@ class DetailsMiddleware {
allowsRequestAccessCodeFromRepository = true,
)
.doOnSuccess { scanResponse ->
// if we use biometric, scanResponse in GlobalState is null, and crashes NPE on twin cards
store.dispatch(GlobalAction.SaveScanResponse(scanResponse))
val currentUserWalletId = state.scanResponse
?.let { UserWalletIdBuilder.scanResponse(it).build() }
val scannedUserWalletId = UserWalletIdBuilder.scanResponse(scanResponse)

View file

@ -1,6 +1,7 @@
package com.tangem.tap.features.wallet.redux
import android.graphics.Bitmap
import com.tangem.blockchain.common.AmountType
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.WalletManager
import com.tangem.domain.common.util.cardTypesResolver
@ -16,6 +17,7 @@ import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.store
import org.rekotlin.StateType
import java.math.BigDecimal
import kotlin.properties.ReadOnlyProperty
data class WalletState(
@ -103,6 +105,9 @@ data class WalletState(
it.derivationPath?.rawPath == currency.derivationPath
}
}
fun getBlockchainAmount(currency: Currency): BigDecimal =
getWalletManager(currency)?.wallet?.amounts?.get(AmountType.Coin)?.value ?: BigDecimal.ZERO
}
enum class ProgressState : WidgetState { Loading, Refreshing, Done, Error }
@ -114,7 +119,6 @@ enum class ErrorType {
sealed class WalletMainButton(enabled: Boolean) : Button(enabled) {
class SendButton(enabled: Boolean) : WalletMainButton(enabled)
class CreateWalletButton(enabled: Boolean) : WalletMainButton(enabled)
}
data class Artwork(

View file

@ -55,6 +55,7 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
import java.math.BigDecimal
import javax.inject.Inject
/**
@ -128,7 +129,8 @@ class WalletDetailsFragment :
(WalletState::selectedWalletData or WalletState::isExchangeServiceFeatureOn) { state ->
val selectedWallet = state.selectedWalletData
if (selectedWallet != null) {
setupButtonsRow(selectedWallet, state.isExchangeServiceFeatureOn)
val blockchainAmount: BigDecimal = state.getBlockchainAmount(selectedWallet.currency)
setupButtonsRow(selectedWallet, state.isExchangeServiceFeatureOn, blockchainAmount)
}
}
(WalletState::state or WalletState::error) { state ->
@ -281,7 +283,11 @@ class WalletDetailsFragment :
}
}
private fun setupButtonsRow(selectedWallet: WalletDataModel, isExchangeServiceFeatureOn: Boolean) {
private fun setupButtonsRow(
selectedWallet: WalletDataModel,
isExchangeServiceFeatureOn: Boolean,
blockchainAmount: BigDecimal,
) {
val exchangeManager = store.state.globalState.exchangeManager
binding.rowButtons.apply {
onBuyClick = { store.dispatch(WalletAction.TradeCryptoAction.Buy()) }
@ -310,7 +316,7 @@ class WalletDetailsFragment :
binding.rowButtons.updateButtonsVisibility(
actions = actions,
exchangeServiceFeatureOn = isExchangeServiceFeatureOn,
sendAllowed = selectedWallet.mainButton.enabled,
sendAllowed = selectedWallet.mainButton(blockchainAmount).enabled,
)
}

View file

@ -239,7 +239,10 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber<W
(activity as? MainActivity)?.showSnackbar(
text = R.string.wallet_notification_no_internet,
buttonTitle = R.string.common_retry,
) { store.dispatch(WalletAction.LoadData) }
)
// because was added logic of autoupdate mainscreen data, remove retry
// TODO("remove comment after release 4.6")
// { store.dispatch(WalletAction.LoadData) }
} else {
isNetworkConnectionError.value = false
}

View file

@ -18,10 +18,9 @@ import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
import java.math.BigDecimal
internal val WalletDataModel.mainButton: WalletMainButton
get() = WalletMainButton.SendButton(
enabled = !status.amount.isZero() && status.pendingTransactions.isEmpty(),
)
internal fun WalletDataModel.mainButton(blockchainAmount: BigDecimal): WalletMainButton = WalletMainButton.SendButton(
enabled = !isEmptyAmount && status.pendingTransactions.isEmpty() && !blockchainAmount.isZero(),
)
internal fun WalletDataModel.getFormattedAmount(): String {
return status.amount.toFormattedCurrencyString(

View file

@ -12,7 +12,6 @@ import com.tangem.tap.features.wallet.models.Currency
import com.tangem.tap.features.wallet.models.PendingTransaction
import com.tangem.tap.features.wallet.models.PendingTransactionType
import com.tangem.tap.features.wallet.redux.WalletAction
import com.tangem.tap.features.wallet.redux.WalletMainButton
import com.tangem.tap.features.wallet.redux.WalletState
import com.tangem.tap.features.wallet.ui.BalanceWidget
import com.tangem.tap.features.wallet.ui.MultipleAddressUiHelper
@ -175,15 +174,10 @@ class SingleWalletView : WalletView() {
binding?.rowButtons?.updateButtonsVisibility(
actions = actions,
exchangeServiceFeatureOn = isExchangeServiceFeatureEnabled,
sendAllowed = walletData.mainButton.enabled,
sendAllowed = walletData.mainButton(walletData.status.amount).enabled,
)
rowButtons.onSendClick = {
when (walletData.mainButton) {
is WalletMainButton.SendButton -> store.dispatch(WalletAction.Send())
is WalletMainButton.CreateWalletButton -> store.dispatch(WalletAction.CreateWallet)
}
}
rowButtons.onSendClick = { store.dispatch(WalletAction.Send()) }
}
private fun setupAddressCard(state: WalletState, binding: FragmentWalletBinding) = with(binding.lAddress) {

View file

@ -72,9 +72,9 @@ arrow = "1.2.0-RC"
# endregion Other libraries
# region Tangem
tangemBlockchainSdk = "develop-209"
tangemBlockchainSdk = "release-app_4.5-215"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "develop-229"
tangemCardSdk = "develop-235"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds
# endregion Tangem